diff --git a/.jshintignore b/.jshintignore index 9881bb30b..848a3a19d 100644 --- a/.jshintignore +++ b/.jshintignore @@ -1,6 +1,8 @@ node_modules libs lib-jitsi-meet.js +lib-jitsi-meet.min.js +lib-jitsi-meet.js.map doc diff --git a/Makefile b/Makefile index 241725f0c..314a8405c 100644 --- a/Makefile +++ b/Makefile @@ -1,14 +1,16 @@ BROWSERIFY = ./node_modules/.bin/browserify +UGLIFYJS = ./node_modules/.bin/uglifyjs +EXORCIST = ./node_modules/.bin/exorcist GLOBAL_FLAGS = OUTPUT_DIR = . DEPLOY_DIR = ../../jitsi-meet -all: compile deploy +all: compile uglify deploy compile:FLAGS = $(GLOBAL_FLAGS) compile: app -debug: compile-debug deploy +debug: compile-debug source-maps uglify-debug deploy compile-debug:FLAGS = -d $(GLOBAL_FLAGS) compile-debug: app @@ -16,6 +18,16 @@ compile-debug: app app: $(BROWSERIFY) $(FLAGS) JitsiMeetJS.js -s JitsiMeetJS -o $(OUTPUT_DIR)/lib-jitsi-meet.js +source-maps: + cat $(OUTPUT_DIR)/lib-jitsi-meet.js | $(EXORCIST) $(OUTPUT_DIR)/lib-jitsi-meet.js.map + +uglify:SOURCE_MAPS= +uglify: + $(UGLIFYJS) -p relative $(OUTPUT_DIR)/lib-jitsi-meet.js -o $(OUTPUT_DIR)/lib-jitsi-meet.min.js $(SOURCE_MAPS) + +uglify-debug:SOURCE_MAPS=--source-map $(OUTPUT_DIR)/lib-jitsi-meet.min.map --in-source-map $(OUTPUT_DIR)/lib-jitsi-meet.js.map +uglify-debug: uglify + clean: rm -f $(OUTPUT_DIR)/lib-jitsi-meet.js diff --git a/lib-jitsi-meet.js b/lib-jitsi-meet.js index 11b7dc39e..bdd05e922 100644 --- a/lib-jitsi-meet.js +++ b/lib-jitsi-meet.js @@ -768,6 +768,7 @@ function setupListeners(conference) { module.exports = JitsiConference; }).call(this,"/JitsiConference.js") + },{"./JitsiConferenceErrors":2,"./JitsiConferenceEvents":3,"./JitsiParticipant":8,"./JitsiTrackEvents":10,"./modules/DTMF/JitsiDTMFManager":11,"./modules/RTC/RTC":16,"./modules/statistics/statistics":24,"./service/RTC/RTCEvents":80,"./service/authentication/AuthenticationEvents":83,"./service/xmpp/XMPPEvents":87,"events":44,"jitsi-meet-logger":48}],2:[function(require,module,exports){ /** * Enumeration with the errors for the conference. @@ -1360,6 +1361,7 @@ JitsiDTMFManager.prototype.sendTones = function (tones, duration, pause) { }; }).call(this,"/modules/DTMF/JitsiDTMFManager.js") + },{"jitsi-meet-logger":48}],12:[function(require,module,exports){ (function (__filename){ /* global config, APP, Strophe */ @@ -1576,6 +1578,7 @@ module.exports = DataChannels; }).call(this,"/modules/RTC/DataChannels.js") + },{"../../service/RTC/RTCEvents":80,"jitsi-meet-logger":48}],13:[function(require,module,exports){ var JitsiTrack = require("./JitsiTrack"); var RTCBrowserType = require("./RTCBrowserType"); @@ -3258,6 +3261,7 @@ var RTCUtils = { module.exports = RTCUtils; }).call(this,"/modules/RTC/RTCUtils.js") + },{"../../JitsiTrackErrors":9,"../../service/RTC/RTCEvents":80,"../../service/RTC/Resolutions":81,"../xmpp/SDPUtil":32,"./RTCBrowserType":17,"./ScreenObtainer":19,"./adapter.screenshare":20,"events":44,"jitsi-meet-logger":48}],19:[function(require,module,exports){ (function (__filename){ /* global chrome, $, alert */ @@ -3680,6 +3684,7 @@ function initFirefoxExtensionDetection(options) { module.exports = ScreenObtainer; }).call(this,"/modules/RTC/ScreenObtainer.js") + },{"../../service/desktopsharing/DesktopSharingEventTypes":84,"./RTCBrowserType":17,"./adapter.screenshare":20,"jitsi-meet-logger":48}],20:[function(require,module,exports){ (function (__filename){ /*! adapterjs - v0.12.3 - 2015-11-16 */ @@ -4864,6 +4869,7 @@ if (navigator.mozGetUserMedia) { } }).call(this,"/modules/RTC/adapter.screenshare.js") + },{"jitsi-meet-logger":48}],21:[function(require,module,exports){ (function (__filename){ @@ -4950,6 +4956,7 @@ Settings.prototype.setLanguage = function (lang) { module.exports = Settings; }).call(this,"/modules/settings/Settings.js") + },{"jitsi-meet-logger":48}],22:[function(require,module,exports){ /* global config */ /** @@ -5802,6 +5809,7 @@ StatsCollector.prototype.processAudioLevelReport = function () { }; }).call(this,"/modules/statistics/RTPStatsCollector.js") + },{"../../service/statistics/Events":85,"../RTC/RTCBrowserType":17,"jitsi-meet-logger":48}],24:[function(require,module,exports){ /* global require, APP */ var LocalStats = require("./LocalStatsCollector.js"); @@ -6814,6 +6822,7 @@ ChatRoom.prototype.getConnectionState = function () { module.exports = ChatRoom; }).call(this,"/modules/xmpp/ChatRoom.js") + },{"../../service/xmpp/XMPPEvents":87,"./moderator":34,"./recording":35,"events":44,"jitsi-meet-logger":48}],27:[function(require,module,exports){ (function (__filename){ /* @@ -6950,6 +6959,7 @@ JingleSession.prototype.setAnswer = function(jingle) {}; module.exports = JingleSession; }).call(this,"/modules/xmpp/JingleSession.js") + },{"jitsi-meet-logger":48}],28:[function(require,module,exports){ (function (__filename){ /* jshint -W117 */ @@ -8591,6 +8601,7 @@ JingleSessionPC.prototype.getIceConnectionState = function () { module.exports = JingleSessionPC; }).call(this,"/modules/xmpp/JingleSessionPC.js") + },{"../../service/xmpp/XMPPEvents":87,"../RTC/RTC":16,"../RTC/RTCBrowserType":17,"./JingleSession":27,"./LocalSSRCReplacement":29,"./SDP":30,"./SDPDiffer":31,"./SDPUtil":32,"./TraceablePeerConnection":33,"async":43,"jitsi-meet-logger":48,"sdp-transform":76}],29:[function(require,module,exports){ (function (__filename){ /* global $ */ @@ -8887,6 +8898,7 @@ var LocalSSRCReplacement = { module.exports = LocalSSRCReplacement; }).call(this,"/modules/xmpp/LocalSSRCReplacement.js") + },{"../RTC/RTCBrowserType":17,"../util/RandomUtil":25,"./SDP":30,"jitsi-meet-logger":48}],30:[function(require,module,exports){ (function (__filename){ /* jshint -W117 */ @@ -9538,6 +9550,7 @@ SDP.prototype.jingle2media = function (content) { module.exports = SDP; }).call(this,"/modules/xmpp/SDP.js") + },{"./SDPUtil":32,"jitsi-meet-logger":48}],31:[function(require,module,exports){ var SDPUtil = require("./SDPUtil"); @@ -10075,6 +10088,7 @@ SDPUtil = { module.exports = SDPUtil; }).call(this,"/modules/xmpp/SDPUtil.js") + },{"../RTC/RTCBrowserType":17,"jitsi-meet-logger":48}],33:[function(require,module,exports){ (function (__filename){ /* global $ */ @@ -10528,7 +10542,8 @@ TraceablePeerConnection.prototype.getStats = function(callback, errback) { module.exports = TraceablePeerConnection; }).call(this,"/modules/xmpp/TraceablePeerConnection.js") -},{"../../service/xmpp/XMPPEvents":87,"../RTC/RTC":16,"../RTC/RTCBrowserType.js":17,"./LocalSSRCReplacement":29,"jitsi-meet-logger":48,"sdp-interop":66,"sdp-simulcast":69,"sdp-transform":76}],34:[function(require,module,exports){ + +},{"../../service/xmpp/XMPPEvents":87,"../RTC/RTC":16,"../RTC/RTCBrowserType.js":17,"./LocalSSRCReplacement":29,"jitsi-meet-logger":48,"sdp-interop":66,"sdp-simulcast":73,"sdp-transform":76}],34:[function(require,module,exports){ (function (__filename){ /* global $, $iq, Promise, Strophe */ @@ -10989,6 +11004,7 @@ Moderator.prototype.logout = function (callback) { module.exports = Moderator; }).call(this,"/modules/xmpp/moderator.js") + },{"../../service/authentication/AuthenticationEvents":83,"../../service/xmpp/XMPPEvents":87,"../settings/Settings":21,"jitsi-meet-logger":48}],35:[function(require,module,exports){ (function (__filename){ /* global $, $iq, config, connection, focusMucJid, messageHandler, @@ -11110,6 +11126,7 @@ Recording.prototype.getURL = function () { module.exports = Recording; }).call(this,"/modules/xmpp/recording.js") + },{"../../service/XMPP/XMPPEvents":82,"jitsi-meet-logger":48}],36:[function(require,module,exports){ (function (__filename){ /* jshint -W117 */ @@ -11207,6 +11224,7 @@ module.exports = function(XMPP) { }).call(this,"/modules/xmpp/strophe.emuc.js") + },{"./ChatRoom":26,"jitsi-meet-logger":48}],37:[function(require,module,exports){ (function (__filename){ /* jshint -W117 */ @@ -11504,6 +11522,7 @@ module.exports = function(XMPP, eventEmitter) { }).call(this,"/modules/xmpp/strophe.jingle.js") + },{"../../service/xmpp/XMPPEvents":87,"../RTC/RTCBrowserType":17,"./JingleSessionPC":28,"jitsi-meet-logger":48}],38:[function(require,module,exports){ /* global Strophe */ module.exports = function () { @@ -11652,6 +11671,7 @@ module.exports = function (XMPP, eventEmitter) { }; }).call(this,"/modules/xmpp/strophe.ping.js") + },{"../../service/xmpp/XMPPEvents":87,"jitsi-meet-logger":48}],40:[function(require,module,exports){ (function (__filename){ /* jshint -W117 */ @@ -11769,6 +11789,7 @@ module.exports = function() { }; }).call(this,"/modules/xmpp/strophe.rayo.js") + },{"jitsi-meet-logger":48}],41:[function(require,module,exports){ (function (__filename){ /* global Strophe */ @@ -11818,6 +11839,7 @@ module.exports = function () { }; }).call(this,"/modules/xmpp/strophe.util.js") + },{"jitsi-meet-logger":48}],42:[function(require,module,exports){ (function (__filename){ /* global $, APP, config, Strophe*/ @@ -12146,6 +12168,7 @@ XMPP.prototype.getLocalSSRC = function (mediaType) { module.exports = XMPP; }).call(this,"/modules/xmpp/xmpp.js") + },{"../../JitsiConnectionErrors":5,"../../JitsiConnectionEvents":6,"../../service/RTC/RTCEvents":80,"../../service/xmpp/XMPPEvents":87,"../RTC/RTC":16,"./strophe.emuc":36,"./strophe.jingle":37,"./strophe.logger":38,"./strophe.ping":39,"./strophe.rayo":40,"./strophe.util":41,"events":44,"jitsi-meet-logger":48,"pako":49}],43:[function(require,module,exports){ (function (process){ /*! @@ -13273,6 +13296,7 @@ module.exports = XMPP; }()); }).call(this,require('_process')) + },{"_process":45}],44:[function(require,module,exports){ // Copyright Joyent, Inc. and other Node contributors. // @@ -14640,6 +14664,7 @@ process.umask = function() { return 0; }; }).call(this,require('_process'),typeof global !== "undefined" ? global : typeof self !== "undefined" ? self : typeof window !== "undefined" ? window : {}) + },{"_process":45}],47:[function(require,module,exports){ /* Copyright @ 2015 Atlassian Pty Ltd * @@ -22196,7 +22221,487 @@ exports.parse = function(sdp) { }; -},{"sdp-transform":76}],69:[function(require,module,exports){ +},{"sdp-transform":70}],69:[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:([\w_\/]*) (\S*)(?: (\S*))?/, + names: ['value', 'uri', 'config'], // value may include "/direction" suffix + format: function (o) { + return (o.config != null) ? + "extmap:%s %s %s": + "extmap:%s %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 + //a=candidate:3289912957 2 udp 1845501695 193.84.77.194 60017 typ srflx raddr 192.168.34.75 rport 60017 generation 0 + //a=candidate:229815620 1 tcp 1518280447 192.168.150.19 60017 typ host tcptype active generation 0 + //a=candidate:3289912957 2 tcp 1845501695 193.84.77.194 60017 typ srflx raddr 192.168.34.75 rport 60017 tcptype passive generation 0 + push:'candidates', + reg: /^candidate:(\S*) (\d*) (\S*) (\d*) (\S*) (\d*) typ (\S*)(?: raddr (\S*) rport (\d*))?(?: tcptype (\S*))?(?: generation (\d*))?/, + names: ['foundation', 'component', 'transport', 'priority', 'ip', 'port', 'type', 'raddr', 'rport', 'tcptype', 'generation'], + 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"; + } + 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: "ssrc:%d %s:%s" + }, + { //a=ssrc-group:FEC 1 2 + push: "ssrcGroups", + reg: /^ssrc-group:(\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)/ + }, + { // 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"; + } + }); +}); + +},{}],70:[function(require,module,exports){ +var parser = require('./parser'); +var writer = require('./writer'); + +exports.write = writer; +exports.parse = parser.parse; +exports.parseFmtpConfig = parser.parseFmtpConfig; +exports.parsePayloads = parser.parsePayloads; +exports.parseRemoteCandidates = parser.parseRemoteCandidates; + +},{"./parser":71,"./writer":72}],71:[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 fmtpReducer = function (acc, expr) { + var s = expr.split('='); + if (s.length === 2) { + acc[s[0]] = toIntIfInt(s[1]); + } + return acc; +}; + +exports.parseFmtpConfig = function (str) { + return str.split(/\;\s?/).reduce(fmtpReducer, {}); +}; + +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; +}; + +},{"./grammar":69}],72:[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":69}],73:[function(require,module,exports){ /* Copyright @ 2015 Atlassian Pty Ltd * * Licensed under the Apache License, Version 2.0 (the "License"); @@ -22329,7 +22834,7 @@ function explodeRemoteSimulcast(mLine) { function implodeRemoteSimulcast(mLine) { if (!mLine || !Array.isArray(mLine.ssrcGroups)) { - console.debug('Halt: There are no SSRC groups in the remote ' + + console.info('Halt: There are no SSRC groups in the remote ' + 'description.'); return; } @@ -22342,7 +22847,7 @@ function implodeRemoteSimulcast(mLine) { return; } - console.debug("Imploding SIM group: " + simulcastGroup.ssrcs); + console.info("Imploding SIM group: " + simulcastGroup.ssrcs); // Schedule the SIM group for nuking. simulcastGroup.nuke = true; @@ -22616,7 +23121,7 @@ Simulcast.prototype.mungeLocalDescription = function (desc) { module.exports = Simulcast; -},{"./transform-utils":70,"sdp-transform":72}],70:[function(require,module,exports){ +},{"./transform-utils":74,"sdp-transform":76}],74:[function(require,module,exports){ /* Copyright @ 2015 Atlassian Pty Ltd * * Licensed under the Apache License, Version 2.0 (the "License"); @@ -22682,827 +23187,15 @@ exports.parseSsrcs = function (mLine) { }; -},{}],71:[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\-]*)\/(\d*)(?:\s*\/(\S*))?/, - names: ['payload', 'codec', 'rate', 'encoding'], - format: function (o) { - return (o.encoding) ? - "rtpmap:%d %s/%s/%s": - "rtpmap:%d %s/%s"; - } - }, - { //a=fmtp:108 profile-level-id=24;object=23;bitrate=64000 - 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:([\w_\/]*) (\S*)(?: (\S*))?/, - names: ['value', 'uri', 'config'], // value may include "/direction" suffix - format: function (o) { - return (o.config != null) ? - "extmap:%s %s %s": - "extmap:%s %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 - //a=candidate:3289912957 2 udp 1845501695 193.84.77.194 60017 typ srflx raddr 192.168.34.75 rport 60017 generation 0 - push:'candidates', - reg: /^candidate:(\S*) (\d*) (\S*) (\d*) (\S*) (\d*) typ (\S*)(?: raddr (\S*) rport (\d*))?(?: generation (\d*))?/, - names: ['foundation', 'component', 'transport', 'priority', 'ip', 'port', 'type', 'raddr', 'rport', 'generation'], - format: function (o) { - var str = "candidate:%s %d %s %d %s %d typ %s"; - // NB: candidate has two optional chunks, so %void middle one if it's missing - str += (o.raddr != null) ? " raddr %s rport %d" : "%v%v"; - if (o.generation != null) { - str += " generation %d"; - } - 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: "ssrc:%d %s:%s" - }, - { //a=ssrc-group:FEC 1 2 - push: "ssrcGroups", - reg: /^ssrc-group:(\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)/ - }, - { // 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"; - } - }); -}); - -},{}],72:[function(require,module,exports){ -var parser = require('./parser'); -var writer = require('./writer'); - -exports.write = writer; -exports.parse = parser.parse; -exports.parseFmtpConfig = parser.parseFmtpConfig; -exports.parsePayloads = parser.parsePayloads; -exports.parseRemoteCandidates = parser.parseRemoteCandidates; - -},{"./parser":73,"./writer":74}],73:[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 fmtpReducer = function (acc, expr) { - var s = expr.split('='); - if (s.length === 2) { - acc[s[0]] = toIntIfInt(s[1]); - } - return acc; -}; - -exports.parseFmtpConfig = function (str) { - return str.split(';').reduce(fmtpReducer, {}); -}; - -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; -}; - -},{"./grammar":71}],74:[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":71}],75:[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\-]*)\/(\d*)(?:\s*\/(\S*))?/, - names: ['payload', 'codec', 'rate', 'encoding'], - format: function (o) { - return (o.encoding) ? - "rtpmap:%d %s/%s/%s": - "rtpmap:%d %s/%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:([\w_\/]*) (\S*)(?: (\S*))?/, - names: ['value', 'uri', 'config'], // value may include "/direction" suffix - format: function (o) { - return (o.config != null) ? - "extmap:%s %s %s": - "extmap:%s %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 - //a=candidate:3289912957 2 udp 1845501695 193.84.77.194 60017 typ srflx raddr 192.168.34.75 rport 60017 generation 0 - push:'candidates', - reg: /^candidate:(\S*) (\d*) (\S*) (\d*) (\S*) (\d*) typ (\S*)(?: raddr (\S*) rport (\d*))?(?: generation (\d*))?/, - names: ['foundation', 'component', 'transport', 'priority', 'ip', 'port', 'type', 'raddr', 'rport', 'generation'], - format: function (o) { - var str = "candidate:%s %d %s %d %s %d typ %s"; - // NB: candidate has two optional chunks, so %void middle one if it's missing - str += (o.raddr != null) ? " raddr %s rport %d" : "%v%v"; - if (o.generation != null) { - str += " generation %d"; - } - 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: "ssrc:%d %s:%s" - }, - { //a=ssrc-group:FEC 1 2 - push: "ssrcGroups", - reg: /^ssrc-group:(\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)/ - }, - { // 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"; - } - }); -}); - -},{}],76:[function(require,module,exports){ +},{}],75:[function(require,module,exports){ +arguments[4][69][0].apply(exports,arguments) +},{"dup":69}],76:[function(require,module,exports){ +arguments[4][70][0].apply(exports,arguments) +},{"./parser":77,"./writer":78,"dup":70}],77:[function(require,module,exports){ +arguments[4][71][0].apply(exports,arguments) +},{"./grammar":75,"dup":71}],78:[function(require,module,exports){ arguments[4][72][0].apply(exports,arguments) -},{"./parser":77,"./writer":78,"dup":72}],77:[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 fmtpReducer = function (acc, expr) { - var s = expr.split('='); - if (s.length === 2) { - acc[s[0]] = toIntIfInt(s[1]); - } - return acc; -}; - -exports.parseFmtpConfig = function (str) { - return str.split(/\;\s?/).reduce(fmtpReducer, {}); -}; - -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; -}; - -},{"./grammar":75}],78:[function(require,module,exports){ -arguments[4][74][0].apply(exports,arguments) -},{"./grammar":75,"dup":74}],79:[function(require,module,exports){ +},{"./grammar":75,"dup":72}],79:[function(require,module,exports){ var MediaStreamType = { VIDEO_TYPE: "Video", @@ -23740,4 +23433,5 @@ module.exports = Constants; },{}],87:[function(require,module,exports){ arguments[4][82][0].apply(exports,arguments) },{"dup":82}]},{},[7])(7) -}); \ No newline at end of file +}); +//# sourceMappingURL=data:application/json;charset:utf-8;base64,eyJ2ZXJzaW9uIjozLCJzb3VyY2VzIjpbIm5vZGVfbW9kdWxlcy9icm93c2VyaWZ5L25vZGVfbW9kdWxlcy9icm93c2VyLXBhY2svX3ByZWx1ZGUuanMiLCJKaXRzaUNvbmZlcmVuY2UuanMiLCJKaXRzaUNvbmZlcmVuY2VFcnJvcnMuanMiLCJKaXRzaUNvbmZlcmVuY2VFdmVudHMuanMiLCJKaXRzaUNvbm5lY3Rpb24uanMiLCJKaXRzaUNvbm5lY3Rpb25FcnJvcnMuanMiLCJKaXRzaUNvbm5lY3Rpb25FdmVudHMuanMiLCJKaXRzaU1lZXRKUy5qcyIsIkppdHNpUGFydGljaXBhbnQuanMiLCJKaXRzaVRyYWNrRXJyb3JzLmpzIiwiSml0c2lUcmFja0V2ZW50cy5qcyIsIm1vZHVsZXMvRFRNRi9KaXRzaURUTUZNYW5hZ2VyLmpzIiwibW9kdWxlcy9SVEMvRGF0YUNoYW5uZWxzLmpzIiwibW9kdWxlcy9SVEMvSml0c2lMb2NhbFRyYWNrLmpzIiwibW9kdWxlcy9SVEMvSml0c2lSZW1vdGVUcmFjay5qcyIsIm1vZHVsZXMvUlRDL0ppdHNpVHJhY2suanMiLCJtb2R1bGVzL1JUQy9SVEMuanMiLCJtb2R1bGVzL1JUQy9SVENCcm93c2VyVHlwZS5qcyIsIm1vZHVsZXMvUlRDL1JUQ1V0aWxzLmpzIiwibW9kdWxlcy9SVEMvU2NyZWVuT2J0YWluZXIuanMiLCJtb2R1bGVzL1JUQy9hZGFwdGVyLnNjcmVlbnNoYXJlLmpzIiwibW9kdWxlcy9zZXR0aW5ncy9TZXR0aW5ncy5qcyIsIm1vZHVsZXMvc3RhdGlzdGljcy9Mb2NhbFN0YXRzQ29sbGVjdG9yLmpzIiwibW9kdWxlcy9zdGF0aXN0aWNzL1JUUFN0YXRzQ29sbGVjdG9yLmpzIiwibW9kdWxlcy9zdGF0aXN0aWNzL3N0YXRpc3RpY3MuanMiLCJtb2R1bGVzL3V0aWwvUmFuZG9tVXRpbC5qcyIsIm1vZHVsZXMveG1wcC9DaGF0Um9vbS5qcyIsIm1vZHVsZXMveG1wcC9KaW5nbGVTZXNzaW9uLmpzIiwibW9kdWxlcy94bXBwL0ppbmdsZVNlc3Npb25QQy5qcyIsIm1vZHVsZXMveG1wcC9Mb2NhbFNTUkNSZXBsYWNlbWVudC5qcyIsIm1vZHVsZXMveG1wcC9TRFAuanMiLCJtb2R1bGVzL3htcHAvU0RQRGlmZmVyLmpzIiwibW9kdWxlcy94bXBwL1NEUFV0aWwuanMiLCJtb2R1bGVzL3htcHAvVHJhY2VhYmxlUGVlckNvbm5lY3Rpb24uanMiLCJtb2R1bGVzL3htcHAvbW9kZXJhdG9yLmpzIiwibW9kdWxlcy94bXBwL3JlY29yZGluZy5qcyIsIm1vZHVsZXMveG1wcC9zdHJvcGhlLmVtdWMuanMiLCJtb2R1bGVzL3htcHAvc3Ryb3BoZS5qaW5nbGUuanMiLCJtb2R1bGVzL3htcHAvc3Ryb3BoZS5sb2dnZXIuanMiLCJtb2R1bGVzL3htcHAvc3Ryb3BoZS5waW5nLmpzIiwibW9kdWxlcy94bXBwL3N0cm9waGUucmF5by5qcyIsIm1vZHVsZXMveG1wcC9zdHJvcGhlLnV0aWwuanMiLCJtb2R1bGVzL3htcHAveG1wcC5qcyIsIm5vZGVfbW9kdWxlcy9hc3luYy9saWIvYXN5bmMuanMiLCJub2RlX21vZHVsZXMvYnJvd3NlcmlmeS9ub2RlX21vZHVsZXMvZXZlbnRzL2V2ZW50cy5qcyIsIm5vZGVfbW9kdWxlcy9icm93c2VyaWZ5L25vZGVfbW9kdWxlcy9wcm9jZXNzL2Jyb3dzZXIuanMiLCJub2RlX21vZHVsZXMvZXM2LXByb21pc2UvZGlzdC9lczYtcHJvbWlzZS5qcyIsIm5vZGVfbW9kdWxlcy9qaXRzaS1tZWV0LWxvZ2dlci9saWIvTG9nZ2VyLmpzIiwibm9kZV9tb2R1bGVzL2ppdHNpLW1lZXQtbG9nZ2VyL2xpYi9pbmRleC5qcyIsIm5vZGVfbW9kdWxlcy9wYWtvL2luZGV4LmpzIiwibm9kZV9tb2R1bGVzL3Bha28vbGliL2RlZmxhdGUuanMiLCJub2RlX21vZHVsZXMvcGFrby9saWIvaW5mbGF0ZS5qcyIsIm5vZGVfbW9kdWxlcy9wYWtvL2xpYi91dGlscy9jb21tb24uanMiLCJub2RlX21vZHVsZXMvcGFrby9saWIvdXRpbHMvc3RyaW5ncy5qcyIsIm5vZGVfbW9kdWxlcy9wYWtvL2xpYi96bGliL2FkbGVyMzIuanMiLCJub2RlX21vZHVsZXMvcGFrby9saWIvemxpYi9jb25zdGFudHMuanMiLCJub2RlX21vZHVsZXMvcGFrby9saWIvemxpYi9jcmMzMi5qcyIsIm5vZGVfbW9kdWxlcy9wYWtvL2xpYi96bGliL2RlZmxhdGUuanMiLCJub2RlX21vZHVsZXMvcGFrby9saWIvemxpYi9nemhlYWRlci5qcyIsIm5vZGVfbW9kdWxlcy9wYWtvL2xpYi96bGliL2luZmZhc3QuanMiLCJub2RlX21vZHVsZXMvcGFrby9saWIvemxpYi9pbmZsYXRlLmpzIiwibm9kZV9tb2R1bGVzL3Bha28vbGliL3psaWIvaW5mdHJlZXMuanMiLCJub2RlX21vZHVsZXMvcGFrby9saWIvemxpYi9tZXNzYWdlcy5qcyIsIm5vZGVfbW9kdWxlcy9wYWtvL2xpYi96bGliL3RyZWVzLmpzIiwibm9kZV9tb2R1bGVzL3Bha28vbGliL3psaWIvenN0cmVhbS5qcyIsIm5vZGVfbW9kdWxlcy9zZHAtaW50ZXJvcC9saWIvYXJyYXktZXF1YWxzLmpzIiwibm9kZV9tb2R1bGVzL3NkcC1pbnRlcm9wL2xpYi9pbmRleC5qcyIsIm5vZGVfbW9kdWxlcy9zZHAtaW50ZXJvcC9saWIvaW50ZXJvcC5qcyIsIm5vZGVfbW9kdWxlcy9zZHAtaW50ZXJvcC9saWIvdHJhbnNmb3JtLmpzIiwibm9kZV9tb2R1bGVzL3NkcC1pbnRlcm9wL25vZGVfbW9kdWxlcy9zZHAtdHJhbnNmb3JtL2xpYi9ncmFtbWFyLmpzIiwibm9kZV9tb2R1bGVzL3NkcC1pbnRlcm9wL25vZGVfbW9kdWxlcy9zZHAtdHJhbnNmb3JtL2xpYi9pbmRleC5qcyIsIm5vZGVfbW9kdWxlcy9zZHAtaW50ZXJvcC9ub2RlX21vZHVsZXMvc2RwLXRyYW5zZm9ybS9saWIvcGFyc2VyLmpzIiwibm9kZV9tb2R1bGVzL3NkcC1pbnRlcm9wL25vZGVfbW9kdWxlcy9zZHAtdHJhbnNmb3JtL2xpYi93cml0ZXIuanMiLCJub2RlX21vZHVsZXMvc2RwLXNpbXVsY2FzdC9saWIvaW5kZXguanMiLCJub2RlX21vZHVsZXMvc2RwLXNpbXVsY2FzdC9saWIvdHJhbnNmb3JtLXV0aWxzLmpzIiwic2VydmljZS9SVEMvTWVkaWFTdHJlYW1UeXBlcy5qcyIsInNlcnZpY2UvUlRDL1JUQ0V2ZW50cy5qcyIsInNlcnZpY2UvUlRDL1Jlc29sdXRpb25zLmpzIiwic2VydmljZS9YTVBQL1hNUFBFdmVudHMuanMiLCJzZXJ2aWNlL2F1dGhlbnRpY2F0aW9uL0F1dGhlbnRpY2F0aW9uRXZlbnRzLmpzIiwic2VydmljZS9kZXNrdG9wc2hhcmluZy9EZXNrdG9wU2hhcmluZ0V2ZW50VHlwZXMuanMiLCJzZXJ2aWNlL3N0YXRpc3RpY3MvRXZlbnRzLmpzIiwic2VydmljZS9zdGF0aXN0aWNzL2NvbnN0YW50cy5qcyJdLCJuYW1lcyI6W10sIm1hcHBpbmdzIjoiQUFBQTs7QUNBQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOzs7O0FDOXZCQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUNwQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQ3JHQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUMzRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FDckJBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FDekJBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUNyR0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FDNUpBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQ3hCQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOzs7QUNoQkE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7Ozs7O0FDZkE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOzs7O0FDcE5BO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FDaEtBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUN2RUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FDclFBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQ3BPQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7O0FDM0tBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOzs7OztBQ3p3QkE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7Ozs7QUNsYUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7Ozs7QUM1cENBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7Ozs7QUNsRkE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7OztBQzNIQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7OztBQ250QkE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQzdLQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOzs7QUN6RUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOzs7OztBQ3R2QkE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7Ozs7O0FDcElBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7Ozs7QUNybURBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7Ozs7O0FDcFNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7OztBQ3ZvQkE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOzs7QUN2S0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7Ozs7QUM1V0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOzs7OztBQ2pjQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOzs7OztBQ3pjQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7Ozs7QUNySEE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7Ozs7O0FDN0ZBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7OztBQ3JTQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOzs7QUNuQkE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7Ozs7O0FDM0hBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7Ozs7QUNqSEE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7Ozs7O0FDN0NBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOzs7OztBQ3BVQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOzs7O0FDbm1DQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQzdTQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOzs7QUMzRkE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7OztBQ3Y4QkE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUM5SUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQ25GQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FDZEE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUN4WEE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUNoWkE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FDdEdBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUN6TEE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQ2hDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FDL0NBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUN6Q0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUNydURBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FDeENBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUN0VUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FDLzlDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUN2VUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUNiQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FDL3FDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FDN0JBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQ3ZDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQ2hCQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQ2p0QkE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUNoSEE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQ2pRQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FDUkE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FDN0ZBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQ2xIQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQ2xhQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOzs7Ozs7Ozs7O0FDaEVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUNMQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUNUQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQ3BEQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FDOUdBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQ1pBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUNkQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FDZEE7QUFDQTtBQUNBO0FBQ0EiLCJmaWxlIjoiZ2VuZXJhdGVkLmpzIiwic291cmNlUm9vdCI6IiIsInNvdXJjZXNDb250ZW50IjpbIihmdW5jdGlvbiBlKHQsbixyKXtmdW5jdGlvbiBzKG8sdSl7aWYoIW5bb10pe2lmKCF0W29dKXt2YXIgYT10eXBlb2YgcmVxdWlyZT09XCJmdW5jdGlvblwiJiZyZXF1aXJlO2lmKCF1JiZhKXJldHVybiBhKG8sITApO2lmKGkpcmV0dXJuIGkobywhMCk7dmFyIGY9bmV3IEVycm9yKFwiQ2Fubm90IGZpbmQgbW9kdWxlICdcIitvK1wiJ1wiKTt0aHJvdyBmLmNvZGU9XCJNT0RVTEVfTk9UX0ZPVU5EXCIsZn12YXIgbD1uW29dPXtleHBvcnRzOnt9fTt0W29dWzBdLmNhbGwobC5leHBvcnRzLGZ1bmN0aW9uKGUpe3ZhciBuPXRbb11bMV1bZV07cmV0dXJuIHMobj9uOmUpfSxsLGwuZXhwb3J0cyxlLHQsbixyKX1yZXR1cm4gbltvXS5leHBvcnRzfXZhciBpPXR5cGVvZiByZXF1aXJlPT1cImZ1bmN0aW9uXCImJnJlcXVpcmU7Zm9yKHZhciBvPTA7bzxyLmxlbmd0aDtvKyspcyhyW29dKTtyZXR1cm4gc30pIiwiLyogZ2xvYmFsIFN0cm9waGUsICQsIFByb21pc2UgKi9cbi8qIGpzaGludCAtVzEwMSAqL1xudmFyIGxvZ2dlciA9IHJlcXVpcmUoXCJqaXRzaS1tZWV0LWxvZ2dlclwiKS5nZXRMb2dnZXIoX19maWxlbmFtZSk7XG52YXIgUlRDID0gcmVxdWlyZShcIi4vbW9kdWxlcy9SVEMvUlRDXCIpO1xudmFyIFhNUFBFdmVudHMgPSByZXF1aXJlKFwiLi9zZXJ2aWNlL3htcHAvWE1QUEV2ZW50c1wiKTtcbnZhciBBdXRoZW50aWNhdGlvbkV2ZW50cyA9IHJlcXVpcmUoXCIuL3NlcnZpY2UvYXV0aGVudGljYXRpb24vQXV0aGVudGljYXRpb25FdmVudHNcIik7XG52YXIgUlRDRXZlbnRzID0gcmVxdWlyZShcIi4vc2VydmljZS9SVEMvUlRDRXZlbnRzXCIpO1xudmFyIEV2ZW50RW1pdHRlciA9IHJlcXVpcmUoXCJldmVudHNcIik7XG52YXIgSml0c2lDb25mZXJlbmNlRXZlbnRzID0gcmVxdWlyZShcIi4vSml0c2lDb25mZXJlbmNlRXZlbnRzXCIpO1xudmFyIEppdHNpQ29uZmVyZW5jZUVycm9ycyA9IHJlcXVpcmUoXCIuL0ppdHNpQ29uZmVyZW5jZUVycm9yc1wiKTtcbnZhciBKaXRzaVBhcnRpY2lwYW50ID0gcmVxdWlyZShcIi4vSml0c2lQYXJ0aWNpcGFudFwiKTtcbnZhciBTdGF0aXN0aWNzID0gcmVxdWlyZShcIi4vbW9kdWxlcy9zdGF0aXN0aWNzL3N0YXRpc3RpY3NcIik7XG52YXIgSml0c2lEVE1GTWFuYWdlciA9IHJlcXVpcmUoJy4vbW9kdWxlcy9EVE1GL0ppdHNpRFRNRk1hbmFnZXInKTtcbnZhciBKaXRzaVRyYWNrRXZlbnRzID0gcmVxdWlyZShcIi4vSml0c2lUcmFja0V2ZW50c1wiKTtcblxuLyoqXG4gKiBDcmVhdGVzIGEgSml0c2lDb25mZXJlbmNlIG9iamVjdCB3aXRoIHRoZSBnaXZlbiBuYW1lIGFuZCBwcm9wZXJ0aWVzLlxuICogTm90ZTogdGhpcyBjb25zdHJ1Y3RvciBpcyBub3QgYSBwYXJ0IG9mIHRoZSBwdWJsaWMgQVBJIChvYmplY3RzIHNob3VsZCBiZVxuICogY3JlYXRlZCB1c2luZyBKaXRzaUNvbm5lY3Rpb24uY3JlYXRlQ29uZmVyZW5jZSkuXG4gKiBAcGFyYW0gb3B0aW9ucy5jb25maWcgcHJvcGVydGllcyAvIHNldHRpbmdzIHJlbGF0ZWQgdG8gdGhlIGNvbmZlcmVuY2UgdGhhdCB3aWxsIGJlIGNyZWF0ZWQuXG4gKiBAcGFyYW0gb3B0aW9ucy5uYW1lIHRoZSBuYW1lIG9mIHRoZSBjb25mZXJlbmNlXG4gKiBAcGFyYW0gb3B0aW9ucy5jb25uZWN0aW9uIHRoZSBKaXRzaUNvbm5lY3Rpb24gb2JqZWN0IGZvciB0aGlzIEppdHNpQ29uZmVyZW5jZS5cbiAqIEBjb25zdHJ1Y3RvclxuICovXG5mdW5jdGlvbiBKaXRzaUNvbmZlcmVuY2Uob3B0aW9ucykge1xuICAgIGlmKCFvcHRpb25zLm5hbWUgfHwgb3B0aW9ucy5uYW1lLnRvTG93ZXJDYXNlKCkgIT09IG9wdGlvbnMubmFtZSkge1xuICAgICAgICBsb2dnZXIuZXJyb3IoXCJJbnZhbGlkIGNvbmZlcmVuY2UgbmFtZSAobm8gY29uZmVyZW5jZSBuYW1lIHBhc3NlZCBvciBpdFwiXG4gICAgICAgICAgICArIFwiY29udGFpbnMgaW52YWxpZCBjaGFyYWN0ZXJzIGxpa2UgY2FwaXRhbCBsZXR0ZXJzKSFcIik7XG4gICAgICAgICByZXR1cm47XG4gICAgfVxuICAgIHRoaXMub3B0aW9ucyA9IG9wdGlvbnM7XG4gICAgdGhpcy5jb25uZWN0aW9uID0gdGhpcy5vcHRpb25zLmNvbm5lY3Rpb247XG4gICAgdGhpcy54bXBwID0gdGhpcy5jb25uZWN0aW9uLnhtcHA7XG4gICAgdGhpcy5ldmVudEVtaXR0ZXIgPSBuZXcgRXZlbnRFbWl0dGVyKCk7XG4gICAgdGhpcy5yb29tID0gdGhpcy54bXBwLmNyZWF0ZVJvb20odGhpcy5vcHRpb25zLm5hbWUsIHRoaXMub3B0aW9ucy5jb25maWcpO1xuICAgIHRoaXMucm9vbS51cGRhdGVEZXZpY2VBdmFpbGFiaWxpdHkoUlRDLmdldERldmljZUF2YWlsYWJpbGl0eSgpKTtcbiAgICB0aGlzLnJ0YyA9IG5ldyBSVEModGhpcy5yb29tLCBvcHRpb25zKTtcbiAgICBpZighUlRDLm9wdGlvbnMuZGlzYWJsZUF1ZGlvTGV2ZWxzKVxuICAgICAgICB0aGlzLnN0YXRpc3RpY3MgPSBuZXcgU3RhdGlzdGljcygpO1xuICAgIHNldHVwTGlzdGVuZXJzKHRoaXMpO1xuICAgIHRoaXMucGFydGljaXBhbnRzID0ge307XG4gICAgdGhpcy5sYXN0QWN0aXZlU3BlYWtlciA9IG51bGw7XG4gICAgdGhpcy5kdG1mTWFuYWdlciA9IG51bGw7XG4gICAgdGhpcy5zb21lYm9keVN1cHBvcnRzRFRNRiA9IGZhbHNlO1xuICAgIHRoaXMuYXV0aEVuYWJsZWQgPSBmYWxzZTtcbiAgICB0aGlzLmF1dGhJZGVudGl0eTtcbn1cblxuLyoqXG4gKiBKb2lucyB0aGUgY29uZmVyZW5jZS5cbiAqIEBwYXJhbSBwYXNzd29yZCB7c3RyaW5nfSB0aGUgcGFzc3dvcmRcbiAqL1xuSml0c2lDb25mZXJlbmNlLnByb3RvdHlwZS5qb2luID0gZnVuY3Rpb24gKHBhc3N3b3JkKSB7XG4gICAgaWYodGhpcy5yb29tKVxuICAgICAgICB0aGlzLnJvb20uam9pbihwYXNzd29yZCk7XG59O1xuXG4vKipcbiAqIENoZWNrIGlmIGpvaW5lZCB0byB0aGUgY29uZmVyZW5jZS5cbiAqL1xuSml0c2lDb25mZXJlbmNlLnByb3RvdHlwZS5pc0pvaW5lZCA9IGZ1bmN0aW9uICgpIHtcbiAgICByZXR1cm4gdGhpcy5yb29tICYmIHRoaXMucm9vbS5qb2luZWQ7XG59O1xuXG4vKipcbiAqIExlYXZlcyB0aGUgY29uZmVyZW5jZS5cbiAqL1xuSml0c2lDb25mZXJlbmNlLnByb3RvdHlwZS5sZWF2ZSA9IGZ1bmN0aW9uICgpIHtcbiAgICBpZih0aGlzLnhtcHAgJiYgdGhpcy5yb29tKVxuICAgICAgICB0aGlzLnhtcHAubGVhdmVSb29tKHRoaXMucm9vbS5yb29tamlkKTtcbiAgICB0aGlzLnJvb20gPSBudWxsO1xufTtcblxuLyoqXG4gKiBSZXR1cm5zIG5hbWUgb2YgdGhpcyBjb25mZXJlbmNlLlxuICovXG5KaXRzaUNvbmZlcmVuY2UucHJvdG90eXBlLmdldE5hbWUgPSBmdW5jdGlvbiAoKSB7XG4gICAgcmV0dXJuIHRoaXMub3B0aW9ucy5uYW1lO1xufTtcblxuLyoqXG4gKiBDaGVjayBpZiBhdXRoZW50aWNhdGlvbiBpcyBlbmFibGVkIGZvciB0aGlzIGNvbmZlcmVuY2UuXG4gKi9cbkppdHNpQ29uZmVyZW5jZS5wcm90b3R5cGUuaXNBdXRoRW5hYmxlZCA9IGZ1bmN0aW9uICgpIHtcbiAgICByZXR1cm4gdGhpcy5hdXRoRW5hYmxlZDtcbn07XG5cbi8qKlxuICogQ2hlY2sgaWYgdXNlciBpcyBsb2dnZWQgaW4uXG4gKi9cbkppdHNpQ29uZmVyZW5jZS5wcm90b3R5cGUuaXNMb2dnZWRJbiA9IGZ1bmN0aW9uICgpIHtcbiAgICByZXR1cm4gISF0aGlzLmF1dGhJZGVudGl0eTtcbn07XG5cbi8qKlxuICogR2V0IGF1dGhvcml6ZWQgbG9naW4uXG4gKi9cbkppdHNpQ29uZmVyZW5jZS5wcm90b3R5cGUuZ2V0QXV0aExvZ2luID0gZnVuY3Rpb24gKCkge1xuICAgIHJldHVybiB0aGlzLmF1dGhJZGVudGl0eTtcbn07XG5cbi8qKlxuICogQ2hlY2sgaWYgZXh0ZXJuYWwgYXV0aGVudGljYXRpb24gaXMgZW5hYmxlZCBmb3IgdGhpcyBjb25mZXJlbmNlLlxuICovXG5KaXRzaUNvbmZlcmVuY2UucHJvdG90eXBlLmlzRXh0ZXJuYWxBdXRoRW5hYmxlZCA9IGZ1bmN0aW9uICgpIHtcbiAgICByZXR1cm4gdGhpcy5yb29tICYmIHRoaXMucm9vbS5tb2RlcmF0b3IuaXNFeHRlcm5hbEF1dGhFbmFibGVkKCk7XG59O1xuXG4vKipcbiAqIEdldCB1cmwgZm9yIGV4dGVybmFsIGF1dGhlbnRpY2F0aW9uLlxuICogQHBhcmFtIHtib29sZWFufSBbdXJsRm9yUG9wdXBdIGlmIHRydWUgdGhlbiByZXR1cm4gdXJsIGZvciBsb2dpbiBwb3B1cCxcbiAqICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBlbHNlIHVybCBvZiBsb2dpbiBwYWdlLlxuICogQHJldHVybnMge1Byb21pc2V9XG4gKi9cbkppdHNpQ29uZmVyZW5jZS5wcm90b3R5cGUuZ2V0RXh0ZXJuYWxBdXRoVXJsID0gZnVuY3Rpb24gKHVybEZvclBvcHVwKSB7XG4gICAgcmV0dXJuIG5ldyBQcm9taXNlKGZ1bmN0aW9uIChyZXNvbHZlLCByZWplY3QpIHtcbiAgICAgICAgaWYgKCF0aGlzLmlzRXh0ZXJuYWxBdXRoRW5hYmxlZCgpKSB7XG4gICAgICAgICAgICByZWplY3QoKTtcbiAgICAgICAgICAgIHJldHVybjtcbiAgICAgICAgfVxuICAgICAgICBpZiAodXJsRm9yUG9wdXApIHtcbiAgICAgICAgICAgIHRoaXMucm9vbS5tb2RlcmF0b3IuZ2V0UG9wdXBMb2dpblVybChyZXNvbHZlLCByZWplY3QpO1xuICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgdGhpcy5yb29tLm1vZGVyYXRvci5nZXRMb2dpblVybChyZXNvbHZlLCByZWplY3QpO1xuICAgICAgICB9XG4gICAgfS5iaW5kKHRoaXMpKTtcbn07XG5cbi8qKlxuICogUmV0dXJucyB0aGUgbG9jYWwgdHJhY2tzLlxuICovXG5KaXRzaUNvbmZlcmVuY2UucHJvdG90eXBlLmdldExvY2FsVHJhY2tzID0gZnVuY3Rpb24gKCkge1xuICAgIGlmICh0aGlzLnJ0Yykge1xuICAgICAgICByZXR1cm4gdGhpcy5ydGMubG9jYWxTdHJlYW1zO1xuICAgIH0gZWxzZSB7XG4gICAgICAgIHJldHVybiBbXTtcbiAgICB9XG59O1xuXG5cbi8qKlxuICogQXR0YWNoZXMgYSBoYW5kbGVyIGZvciBldmVudHMoRm9yIGV4YW1wbGUgLSBcInBhcnRpY2lwYW50IGpvaW5lZFwiLikgaW4gdGhlIGNvbmZlcmVuY2UuIEFsbCBwb3NzaWJsZSBldmVudCBhcmUgZGVmaW5lZFxuICogaW4gSml0c2lDb25mZXJlbmNlRXZlbnRzLlxuICogQHBhcmFtIGV2ZW50SWQgdGhlIGV2ZW50IElELlxuICogQHBhcmFtIGhhbmRsZXIgaGFuZGxlciBmb3IgdGhlIGV2ZW50LlxuICpcbiAqIE5vdGU6IGNvbnNpZGVyIGFkZGluZyBldmVudGluZyBmdW5jdGlvbmFsaXR5IGJ5IGV4dGVuZGluZyBhbiBFdmVudEVtaXR0ZXIgaW1wbCwgaW5zdGVhZCBvZiByb2xsaW5nIG91cnNlbHZlc1xuICovXG5KaXRzaUNvbmZlcmVuY2UucHJvdG90eXBlLm9uID0gZnVuY3Rpb24gKGV2ZW50SWQsIGhhbmRsZXIpIHtcbiAgICBpZih0aGlzLmV2ZW50RW1pdHRlcilcbiAgICAgICAgdGhpcy5ldmVudEVtaXR0ZXIub24oZXZlbnRJZCwgaGFuZGxlcik7XG59O1xuXG4vKipcbiAqIFJlbW92ZXMgZXZlbnQgbGlzdGVuZXJcbiAqIEBwYXJhbSBldmVudElkIHRoZSBldmVudCBJRC5cbiAqIEBwYXJhbSBbaGFuZGxlcl0gb3B0aW9uYWwsIHRoZSBzcGVjaWZpYyBoYW5kbGVyIHRvIHVuYmluZFxuICpcbiAqIE5vdGU6IGNvbnNpZGVyIGFkZGluZyBldmVudGluZyBmdW5jdGlvbmFsaXR5IGJ5IGV4dGVuZGluZyBhbiBFdmVudEVtaXR0ZXIgaW1wbCwgaW5zdGVhZCBvZiByb2xsaW5nIG91cnNlbHZlc1xuICovXG5KaXRzaUNvbmZlcmVuY2UucHJvdG90eXBlLm9mZiA9IGZ1bmN0aW9uIChldmVudElkLCBoYW5kbGVyKSB7XG4gICAgaWYodGhpcy5ldmVudEVtaXR0ZXIpXG4gICAgICAgIHRoaXMuZXZlbnRFbWl0dGVyLnJlbW92ZUxpc3RlbmVyKGV2ZW50SWQsIGhhbmRsZXIpO1xufTtcblxuLy8gQ29tbW9uIGFsaWFzZXMgZm9yIGV2ZW50IGVtaXR0ZXJcbkppdHNpQ29uZmVyZW5jZS5wcm90b3R5cGUuYWRkRXZlbnRMaXN0ZW5lciA9IEppdHNpQ29uZmVyZW5jZS5wcm90b3R5cGUub247XG5KaXRzaUNvbmZlcmVuY2UucHJvdG90eXBlLnJlbW92ZUV2ZW50TGlzdGVuZXIgPSBKaXRzaUNvbmZlcmVuY2UucHJvdG90eXBlLm9mZjtcblxuLyoqXG4gKiBSZWNlaXZlcyBub3RpZmljYXRpb25zIGZyb20gYW5vdGhlciBwYXJ0aWNpcGFudHMgZm9yIGNvbW1hbmRzIC8gY3VzdG9tIGV2ZW50c1xuICogKHNlbmQgYnkgc2VuZFByZXNlbmNlQ29tbWFuZCBtZXRob2QpLlxuICogQHBhcmFtIGNvbW1hbmQge1N0cmluZ30gdGhlIG5hbWUgb2YgdGhlIGNvbW1hbmRcbiAqIEBwYXJhbSBoYW5kbGVyIHtGdW5jdGlvbn0gaGFuZGxlciBmb3IgdGhlIGNvbW1hbmRcbiAqL1xuIEppdHNpQ29uZmVyZW5jZS5wcm90b3R5cGUuYWRkQ29tbWFuZExpc3RlbmVyID0gZnVuY3Rpb24gKGNvbW1hbmQsIGhhbmRsZXIpIHtcbiAgICBpZih0aGlzLnJvb20pXG4gICAgICAgIHRoaXMucm9vbS5hZGRQcmVzZW5jZUxpc3RlbmVyKGNvbW1hbmQsIGhhbmRsZXIpO1xuIH07XG5cbi8qKlxuICAqIFJlbW92ZXMgY29tbWFuZCAgbGlzdGVuZXJcbiAgKiBAcGFyYW0gY29tbWFuZCB7U3RyaW5nfSAgdGhlIG5hbWUgb2YgdGhlIGNvbW1hbmRcbiAgKi9cbiBKaXRzaUNvbmZlcmVuY2UucHJvdG90eXBlLnJlbW92ZUNvbW1hbmRMaXN0ZW5lciA9IGZ1bmN0aW9uIChjb21tYW5kKSB7XG4gICAgaWYodGhpcy5yb29tKVxuICAgICAgICB0aGlzLnJvb20ucmVtb3ZlUHJlc2VuY2VMaXN0ZW5lcihjb21tYW5kKTtcbiB9O1xuXG4vKipcbiAqIFNlbmRzIHRleHQgbWVzc2FnZSB0byB0aGUgb3RoZXIgcGFydGljaXBhbnRzIGluIHRoZSBjb25mZXJlbmNlXG4gKiBAcGFyYW0gbWVzc2FnZSB0aGUgdGV4dCBtZXNzYWdlLlxuICovXG5KaXRzaUNvbmZlcmVuY2UucHJvdG90eXBlLnNlbmRUZXh0TWVzc2FnZSA9IGZ1bmN0aW9uIChtZXNzYWdlKSB7XG4gICAgaWYodGhpcy5yb29tKVxuICAgICAgICB0aGlzLnJvb20uc2VuZE1lc3NhZ2UobWVzc2FnZSk7XG59O1xuXG4vKipcbiAqIFNlbmQgcHJlc2VuY2UgY29tbWFuZC5cbiAqIEBwYXJhbSBuYW1lIHRoZSBuYW1lIG9mIHRoZSBjb21tYW5kLlxuICogQHBhcmFtIHZhbHVlcyBPYmplY3Qgd2l0aCBrZXlzIGFuZCB2YWx1ZXMgdGhhdCB3aWxsIGJlIHNlbmQuXG4gKiovXG5KaXRzaUNvbmZlcmVuY2UucHJvdG90eXBlLnNlbmRDb21tYW5kID0gZnVuY3Rpb24gKG5hbWUsIHZhbHVlcykge1xuICAgIGlmKHRoaXMucm9vbSkge1xuICAgICAgICB0aGlzLnJvb20uYWRkVG9QcmVzZW5jZShuYW1lLCB2YWx1ZXMpO1xuICAgICAgICB0aGlzLnJvb20uc2VuZFByZXNlbmNlKCk7XG4gICAgfVxufTtcblxuLyoqXG4gKiBTZW5kIHByZXNlbmNlIGNvbW1hbmQgb25lIHRpbWUuXG4gKiBAcGFyYW0gbmFtZSB0aGUgbmFtZSBvZiB0aGUgY29tbWFuZC5cbiAqIEBwYXJhbSB2YWx1ZXMgT2JqZWN0IHdpdGgga2V5cyBhbmQgdmFsdWVzIHRoYXQgd2lsbCBiZSBzZW5kLlxuICoqL1xuSml0c2lDb25mZXJlbmNlLnByb3RvdHlwZS5zZW5kQ29tbWFuZE9uY2UgPSBmdW5jdGlvbiAobmFtZSwgdmFsdWVzKSB7XG4gICAgdGhpcy5zZW5kQ29tbWFuZChuYW1lLCB2YWx1ZXMpO1xuICAgIHRoaXMucmVtb3ZlQ29tbWFuZChuYW1lKTtcbn07XG5cbi8qKlxuICogU2VuZCBwcmVzZW5jZSBjb21tYW5kLlxuICogQHBhcmFtIG5hbWUgdGhlIG5hbWUgb2YgdGhlIGNvbW1hbmQuXG4gKiBAcGFyYW0gdmFsdWVzIE9iamVjdCB3aXRoIGtleXMgYW5kIHZhbHVlcyB0aGF0IHdpbGwgYmUgc2VuZC5cbiAqIEBwYXJhbSBwZXJzaXN0ZW50IGlmIGZhbHNlIHRoZSBjb21tYW5kIHdpbGwgYmUgc2VudCBvbmx5IG9uZSB0aW1lXG4gKiovXG5KaXRzaUNvbmZlcmVuY2UucHJvdG90eXBlLnJlbW92ZUNvbW1hbmQgPSBmdW5jdGlvbiAobmFtZSkge1xuICAgIGlmKHRoaXMucm9vbSlcbiAgICAgICAgdGhpcy5yb29tLnJlbW92ZUZyb21QcmVzZW5jZShuYW1lKTtcbn07XG5cbi8qKlxuICogU2V0cyB0aGUgZGlzcGxheSBuYW1lIGZvciB0aGlzIGNvbmZlcmVuY2UuXG4gKiBAcGFyYW0gbmFtZSB0aGUgZGlzcGxheSBuYW1lIHRvIHNldFxuICovXG5KaXRzaUNvbmZlcmVuY2UucHJvdG90eXBlLnNldERpc3BsYXlOYW1lID0gZnVuY3Rpb24obmFtZSkge1xuICAgIGlmKHRoaXMucm9vbSl7XG4gICAgICAgIC8vIHJlbW92ZSBwcmV2aW91c2x5IHNldCBuaWNrbmFtZVxuICAgICAgICB0aGlzLnJvb20ucmVtb3ZlRnJvbVByZXNlbmNlKFwibmlja1wiKTtcblxuICAgICAgICB0aGlzLnJvb20uYWRkVG9QcmVzZW5jZShcIm5pY2tcIiwge2F0dHJpYnV0ZXM6IHt4bWxuczogJ2h0dHA6Ly9qYWJiZXIub3JnL3Byb3RvY29sL25pY2snfSwgdmFsdWU6IG5hbWV9KTtcbiAgICAgICAgdGhpcy5yb29tLnNlbmRQcmVzZW5jZSgpO1xuICAgIH1cbn07XG5cbi8qKlxuICogQWRkcyBKaXRzaUxvY2FsVHJhY2sgb2JqZWN0IHRvIHRoZSBjb25mZXJlbmNlLlxuICogQHBhcmFtIHRyYWNrIHRoZSBKaXRzaUxvY2FsVHJhY2sgb2JqZWN0LlxuICovXG5KaXRzaUNvbmZlcmVuY2UucHJvdG90eXBlLmFkZFRyYWNrID0gZnVuY3Rpb24gKHRyYWNrKSB7XG4gICAgdGhpcy5yb29tLmFkZFN0cmVhbSh0cmFjay5nZXRPcmlnaW5hbFN0cmVhbSgpLCBmdW5jdGlvbiAoKSB7XG4gICAgICAgIHRoaXMucnRjLmFkZExvY2FsU3RyZWFtKHRyYWNrKTtcbiAgICAgICAgdmFyIG11dGVIYW5kbGVyID0gdGhpcy5fZmlyZU11dGVDaGFuZ2VFdmVudC5iaW5kKHRoaXMsIHRyYWNrKTtcbiAgICAgICAgdmFyIHN0b3BIYW5kbGVyID0gdGhpcy5yZW1vdmVUcmFjay5iaW5kKHRoaXMsIHRyYWNrKTtcbiAgICAgICAgdmFyIGF1ZGlvTGV2ZWxIYW5kbGVyID0gdGhpcy5fZmlyZUF1ZGlvTGV2ZWxDaGFuZ2VFdmVudC5iaW5kKHRoaXMpO1xuICAgICAgICB0cmFjay5hZGRFdmVudExpc3RlbmVyKEppdHNpVHJhY2tFdmVudHMuVFJBQ0tfTVVURV9DSEFOR0VELCBtdXRlSGFuZGxlcik7XG4gICAgICAgIHRyYWNrLmFkZEV2ZW50TGlzdGVuZXIoSml0c2lUcmFja0V2ZW50cy5UUkFDS19TVE9QUEVELCBzdG9wSGFuZGxlcik7XG4gICAgICAgIHRyYWNrLmFkZEV2ZW50TGlzdGVuZXIoSml0c2lUcmFja0V2ZW50cy5UUkFDS19BVURJT19MRVZFTF9DSEFOR0VELCBhdWRpb0xldmVsSGFuZGxlcik7XG4gICAgICAgIHRoaXMuYWRkRXZlbnRMaXN0ZW5lcihKaXRzaUNvbmZlcmVuY2VFdmVudHMuVFJBQ0tfUkVNT1ZFRCwgZnVuY3Rpb24gKHNvbWVUcmFjaykge1xuICAgICAgICAgICAgaWYgKHNvbWVUcmFjayAhPT0gdHJhY2spIHtcbiAgICAgICAgICAgICAgICByZXR1cm47XG4gICAgICAgICAgICB9XG4gICAgICAgICAgICB0cmFjay5yZW1vdmVFdmVudExpc3RlbmVyKEppdHNpVHJhY2tFdmVudHMuVFJBQ0tfTVVURV9DSEFOR0VELCBtdXRlSGFuZGxlcik7XG4gICAgICAgICAgICB0cmFjay5yZW1vdmVFdmVudExpc3RlbmVyKEppdHNpVHJhY2tFdmVudHMuVFJBQ0tfU1RPUFBFRCwgc3RvcEhhbmRsZXIpO1xuICAgICAgICAgICAgdHJhY2sucmVtb3ZlRXZlbnRMaXN0ZW5lcihKaXRzaVRyYWNrRXZlbnRzLlRSQUNLX0FVRElPX0xFVkVMX0NIQU5HRUQsIGF1ZGlvTGV2ZWxIYW5kbGVyKTtcbiAgICAgICAgfSk7XG4gICAgICAgIHRoaXMuZXZlbnRFbWl0dGVyLmVtaXQoSml0c2lDb25mZXJlbmNlRXZlbnRzLlRSQUNLX0FEREVELCB0cmFjayk7XG4gICAgfS5iaW5kKHRoaXMpKTtcbn07XG5cbi8qKlxuICogRmlyZXMgVFJBQ0tfQVVESU9fTEVWRUxfQ0hBTkdFRCBjaGFuZ2UgY29uZmVyZW5jZSBldmVudC5cbiAqIEBwYXJhbSBhdWRpb0xldmVsIHRoZSBhdWRpbyBsZXZlbFxuICovXG5KaXRzaUNvbmZlcmVuY2UucHJvdG90eXBlLl9maXJlQXVkaW9MZXZlbENoYW5nZUV2ZW50ID0gZnVuY3Rpb24gKGF1ZGlvTGV2ZWwpIHtcbiAgICB0aGlzLmV2ZW50RW1pdHRlci5lbWl0KFxuICAgICAgICBKaXRzaUNvbmZlcmVuY2VFdmVudHMuVFJBQ0tfQVVESU9fTEVWRUxfQ0hBTkdFRCxcbiAgICAgICAgdGhpcy5teVVzZXJJZCgpLCBhdWRpb0xldmVsKTtcbn07XG5cbi8qKlxuICogRmlyZXMgVFJBQ0tfTVVURV9DSEFOR0VEIGNoYW5nZSBjb25mZXJlbmNlIGV2ZW50LlxuICogQHBhcmFtIHRyYWNrIHRoZSBKaXRzaVRyYWNrIG9iamVjdCByZWxhdGVkIHRvIHRoZSBldmVudC5cbiAqL1xuSml0c2lDb25mZXJlbmNlLnByb3RvdHlwZS5fZmlyZU11dGVDaGFuZ2VFdmVudCA9IGZ1bmN0aW9uICh0cmFjaykge1xuICAgIHRoaXMuZXZlbnRFbWl0dGVyLmVtaXQoSml0c2lDb25mZXJlbmNlRXZlbnRzLlRSQUNLX01VVEVfQ0hBTkdFRCwgdHJhY2spO1xufTtcblxuLyoqXG4gKiBSZW1vdmVzIEppdHNpTG9jYWxUcmFjayBvYmplY3QgdG8gdGhlIGNvbmZlcmVuY2UuXG4gKiBAcGFyYW0gdHJhY2sgdGhlIEppdHNpTG9jYWxUcmFjayBvYmplY3QuXG4gKi9cbkppdHNpQ29uZmVyZW5jZS5wcm90b3R5cGUucmVtb3ZlVHJhY2sgPSBmdW5jdGlvbiAodHJhY2spIHtcbiAgICBpZighdGhpcy5yb29tKXtcbiAgICAgICAgaWYodGhpcy5ydGMpXG4gICAgICAgICAgICB0aGlzLnJ0Yy5yZW1vdmVMb2NhbFN0cmVhbSh0cmFjayk7XG4gICAgICAgIHJldHVybjtcbiAgICB9XG4gICAgdGhpcy5yb29tLnJlbW92ZVN0cmVhbSh0cmFjay5nZXRPcmlnaW5hbFN0cmVhbSgpLCBmdW5jdGlvbigpe1xuICAgICAgICB0aGlzLnJ0Yy5yZW1vdmVMb2NhbFN0cmVhbSh0cmFjayk7XG4gICAgICAgIHRoaXMuZXZlbnRFbWl0dGVyLmVtaXQoSml0c2lDb25mZXJlbmNlRXZlbnRzLlRSQUNLX1JFTU9WRUQsIHRyYWNrKTtcbiAgICB9LmJpbmQodGhpcykpO1xufTtcblxuLyoqXG4gKiBHZXQgcm9sZSBvZiB0aGUgbG9jYWwgdXNlci5cbiAqIEByZXR1cm5zIHtzdHJpbmd9IHVzZXIgcm9sZTogJ21vZGVyYXRvcicgb3IgJ25vbmUnXG4gKi9cbkppdHNpQ29uZmVyZW5jZS5wcm90b3R5cGUuZ2V0Um9sZSA9IGZ1bmN0aW9uICgpIHtcbiAgICByZXR1cm4gdGhpcy5yb29tLnJvbGU7XG59O1xuXG4vKipcbiAqIENoZWNrIGlmIGxvY2FsIHVzZXIgaXMgbW9kZXJhdG9yLlxuICogQHJldHVybnMge2Jvb2xlYW59IHRydWUgaWYgbG9jYWwgdXNlciBpcyBtb2RlcmF0b3IsIGZhbHNlIG90aGVyd2lzZS5cbiAqL1xuSml0c2lDb25mZXJlbmNlLnByb3RvdHlwZS5pc01vZGVyYXRvciA9IGZ1bmN0aW9uICgpIHtcbiAgICByZXR1cm4gdGhpcy5yb29tLmlzTW9kZXJhdG9yKCk7XG59O1xuXG4vKipcbiAqIFNldCBwYXNzd29yZCBmb3IgdGhlIHJvb20uXG4gKiBAcGFyYW0ge3N0cmluZ30gcGFzc3dvcmQgbmV3IHBhc3N3b3JkIGZvciB0aGUgcm9vbS5cbiAqIEByZXR1cm5zIHtQcm9taXNlfVxuICovXG5KaXRzaUNvbmZlcmVuY2UucHJvdG90eXBlLmxvY2sgPSBmdW5jdGlvbiAocGFzc3dvcmQpIHtcbiAgaWYgKCF0aGlzLmlzTW9kZXJhdG9yKCkpIHtcbiAgICByZXR1cm4gUHJvbWlzZS5yZWplY3QoKTtcbiAgfVxuXG4gIHZhciBjb25mZXJlbmNlID0gdGhpcztcbiAgcmV0dXJuIG5ldyBQcm9taXNlKGZ1bmN0aW9uIChyZXNvbHZlLCByZWplY3QpIHtcbiAgICBjb25mZXJlbmNlLnJvb20ubG9ja1Jvb20ocGFzc3dvcmQgfHwgXCJcIiwgZnVuY3Rpb24gKCkge1xuICAgICAgcmVzb2x2ZSgpO1xuICAgIH0sIGZ1bmN0aW9uIChlcnIpIHtcbiAgICAgIHJlamVjdChlcnIpO1xuICAgIH0sIGZ1bmN0aW9uICgpIHtcbiAgICAgIHJlamVjdChKaXRzaUNvbmZlcmVuY2VFcnJvcnMuUEFTU1dPUkRfTk9UX1NVUFBPUlRFRCk7XG4gICAgfSk7XG4gIH0pO1xufTtcblxuLyoqXG4gKiBSZW1vdmUgcGFzc3dvcmQgZnJvbSB0aGUgcm9vbS5cbiAqIEByZXR1cm5zIHtQcm9taXNlfVxuICovXG5KaXRzaUNvbmZlcmVuY2UucHJvdG90eXBlLnVubG9jayA9IGZ1bmN0aW9uICgpIHtcbiAgcmV0dXJuIHRoaXMubG9jaygpO1xufTtcblxuLyoqXG4gKiBFbGVjdHMgdGhlIHBhcnRpY2lwYW50IHdpdGggdGhlIGdpdmVuIGlkIHRvIGJlIHRoZSBzZWxlY3RlZCBwYXJ0aWNpcGFudCBvciB0aGUgc3BlYWtlci5cbiAqIEBwYXJhbSBpZCB0aGUgaWRlbnRpZmllciBvZiB0aGUgcGFydGljaXBhbnRcbiAqL1xuSml0c2lDb25mZXJlbmNlLnByb3RvdHlwZS5zZWxlY3RQYXJ0aWNpcGFudCA9IGZ1bmN0aW9uKHBhcnRpY2lwYW50SWQpIHtcbiAgICBpZiAodGhpcy5ydGMpIHtcbiAgICAgICAgdGhpcy5ydGMuc2VsZWN0ZWRFbmRwb2ludChwYXJ0aWNpcGFudElkKTtcbiAgICB9XG59O1xuXG4vKipcbiAqXG4gKiBAcGFyYW0gaWQgdGhlIGlkZW50aWZpZXIgb2YgdGhlIHBhcnRpY2lwYW50XG4gKi9cbkppdHNpQ29uZmVyZW5jZS5wcm90b3R5cGUucGluUGFydGljaXBhbnQgPSBmdW5jdGlvbihwYXJ0aWNpcGFudElkKSB7XG4gICAgaWYgKHRoaXMucnRjKSB7XG4gICAgICAgIHRoaXMucnRjLnBpbkVuZHBvaW50KHBhcnRpY2lwYW50SWQpO1xuICAgIH1cbn07XG5cbi8qKlxuICogUmV0dXJucyB0aGUgbGlzdCBvZiBwYXJ0aWNpcGFudHMgZm9yIHRoaXMgY29uZmVyZW5jZS5cbiAqIEByZXR1cm4gQXJyYXk8Sml0c2lQYXJ0aWNpcGFudD4gYSBsaXN0IG9mIHBhcnRpY2lwYW50IGlkZW50aWZpZXJzIGNvbnRhaW5pbmcgYWxsIGNvbmZlcmVuY2UgcGFydGljaXBhbnRzLlxuICovXG5KaXRzaUNvbmZlcmVuY2UucHJvdG90eXBlLmdldFBhcnRpY2lwYW50cyA9IGZ1bmN0aW9uKCkge1xuICAgIHJldHVybiBPYmplY3Qua2V5cyh0aGlzLnBhcnRpY2lwYW50cykubWFwKGZ1bmN0aW9uIChrZXkpIHtcbiAgICAgICAgcmV0dXJuIHRoaXMucGFydGljaXBhbnRzW2tleV07XG4gICAgfSwgdGhpcyk7XG59O1xuXG4vKipcbiAqIEByZXR1cm5zIHtKaXRzaVBhcnRpY2lwYW50fSB0aGUgcGFydGljaXBhbnQgaW4gdGhpcyBjb25mZXJlbmNlIHdpdGggdGhlIHNwZWNpZmllZCBpZCAob3JcbiAqIHVuZGVmaW5lZCBpZiB0aGVyZSBpc24ndCBvbmUpLlxuICogQHBhcmFtIGlkIHRoZSBpZCBvZiB0aGUgcGFydGljaXBhbnQuXG4gKi9cbkppdHNpQ29uZmVyZW5jZS5wcm90b3R5cGUuZ2V0UGFydGljaXBhbnRCeUlkID0gZnVuY3Rpb24oaWQpIHtcbiAgICByZXR1cm4gdGhpcy5wYXJ0aWNpcGFudHNbaWRdO1xufTtcblxuLyoqXG4gKiBLaWNrIHBhcnRpY2lwYW50IGZyb20gdGhpcyBjb25mZXJlbmNlLlxuICogQHBhcmFtIHtzdHJpbmd9IGlkIGlkIG9mIHRoZSBwYXJ0aWNpcGFudCB0byBraWNrXG4gKi9cbkppdHNpQ29uZmVyZW5jZS5wcm90b3R5cGUua2lja1BhcnRpY2lwYW50ID0gZnVuY3Rpb24gKGlkKSB7XG4gICAgdmFyIHBhcnRpY2lwYW50ID0gdGhpcy5nZXRQYXJ0aWNpcGFudEJ5SWQoaWQpO1xuICAgIGlmICghcGFydGljaXBhbnQpIHtcbiAgICAgICAgcmV0dXJuO1xuICAgIH1cbiAgICB0aGlzLnJvb20ua2ljayhwYXJ0aWNpcGFudC5nZXRKaWQoKSk7XG59O1xuXG5KaXRzaUNvbmZlcmVuY2UucHJvdG90eXBlLm9uTWVtYmVySm9pbmVkID0gZnVuY3Rpb24gKGppZCwgZW1haWwsIG5pY2spIHtcbiAgICB2YXIgaWQgPSBTdHJvcGhlLmdldFJlc291cmNlRnJvbUppZChqaWQpO1xuICAgIGlmIChpZCA9PT0gJ2ZvY3VzJyB8fCB0aGlzLm15VXNlcklkKCkgPT09IGlkKSB7XG4gICAgICAgcmV0dXJuO1xuICAgIH1cbiAgICB2YXIgcGFydGljaXBhbnQgPSBuZXcgSml0c2lQYXJ0aWNpcGFudChqaWQsIHRoaXMsIG5pY2spO1xuICAgIHRoaXMucGFydGljaXBhbnRzW2lkXSA9IHBhcnRpY2lwYW50O1xuICAgIHRoaXMuZXZlbnRFbWl0dGVyLmVtaXQoSml0c2lDb25mZXJlbmNlRXZlbnRzLlVTRVJfSk9JTkVELCBpZCwgcGFydGljaXBhbnQpO1xuICAgIHRoaXMueG1wcC5jb25uZWN0aW9uLmRpc2NvLmluZm8oXG4gICAgICAgIGppZCwgXCJub2RlXCIsIGZ1bmN0aW9uKGlxKSB7XG4gICAgICAgICAgICBwYXJ0aWNpcGFudC5fc3VwcG9ydHNEVE1GID0gJChpcSkuZmluZChcbiAgICAgICAgICAgICAgICAnPnF1ZXJ5PmZlYXR1cmVbdmFyPVwidXJuOnhtcHA6amluZ2xlOmR0bWY6MFwiXScpLmxlbmd0aCA+IDA7XG4gICAgICAgICAgICB0aGlzLnVwZGF0ZURUTUZTdXBwb3J0KCk7XG4gICAgICAgIH0uYmluZCh0aGlzKVxuICAgICk7XG59O1xuXG5KaXRzaUNvbmZlcmVuY2UucHJvdG90eXBlLm9uTWVtYmVyTGVmdCA9IGZ1bmN0aW9uIChqaWQpIHtcbiAgICB2YXIgaWQgPSBTdHJvcGhlLmdldFJlc291cmNlRnJvbUppZChqaWQpO1xuICAgIGlmIChpZCA9PT0gJ2ZvY3VzJyB8fCB0aGlzLm15VXNlcklkKCkgPT09IGlkKSB7XG4gICAgICAgcmV0dXJuO1xuICAgIH1cbiAgICB2YXIgcGFydGljaXBhbnQgPSB0aGlzLnBhcnRpY2lwYW50c1tpZF07XG4gICAgZGVsZXRlIHRoaXMucGFydGljaXBhbnRzW2lkXTtcbiAgICB0aGlzLmV2ZW50RW1pdHRlci5lbWl0KEppdHNpQ29uZmVyZW5jZUV2ZW50cy5VU0VSX0xFRlQsIGlkLCBwYXJ0aWNpcGFudCk7XG59O1xuXG5KaXRzaUNvbmZlcmVuY2UucHJvdG90eXBlLm9uVXNlclJvbGVDaGFuZ2VkID0gZnVuY3Rpb24gKGppZCwgcm9sZSkge1xuICAgIHZhciBpZCA9IFN0cm9waGUuZ2V0UmVzb3VyY2VGcm9tSmlkKGppZCk7XG4gICAgdmFyIHBhcnRpY2lwYW50ID0gdGhpcy5nZXRQYXJ0aWNpcGFudEJ5SWQoaWQpO1xuICAgIGlmICghcGFydGljaXBhbnQpIHtcbiAgICAgICAgcmV0dXJuO1xuICAgIH1cbiAgICBwYXJ0aWNpcGFudC5fcm9sZSA9IHJvbGU7XG4gICAgdGhpcy5ldmVudEVtaXR0ZXIuZW1pdChKaXRzaUNvbmZlcmVuY2VFdmVudHMuVVNFUl9ST0xFX0NIQU5HRUQsIGlkLCByb2xlKTtcbn07XG5cbkppdHNpQ29uZmVyZW5jZS5wcm90b3R5cGUub25EaXNwbGF5TmFtZUNoYW5nZWQgPSBmdW5jdGlvbiAoamlkLCBkaXNwbGF5TmFtZSkge1xuICAgIHZhciBpZCA9IFN0cm9waGUuZ2V0UmVzb3VyY2VGcm9tSmlkKGppZCk7XG4gICAgdmFyIHBhcnRpY2lwYW50ID0gdGhpcy5nZXRQYXJ0aWNpcGFudEJ5SWQoaWQpO1xuICAgIGlmICghcGFydGljaXBhbnQpIHtcbiAgICAgICAgcmV0dXJuO1xuICAgIH1cbiAgICBwYXJ0aWNpcGFudC5fZGlzcGxheU5hbWUgPSBkaXNwbGF5TmFtZTtcbiAgICB0aGlzLmV2ZW50RW1pdHRlci5lbWl0KEppdHNpQ29uZmVyZW5jZUV2ZW50cy5ESVNQTEFZX05BTUVfQ0hBTkdFRCwgaWQsIGRpc3BsYXlOYW1lKTtcbn07XG5cbkppdHNpQ29uZmVyZW5jZS5wcm90b3R5cGUub25UcmFja0FkZGVkID0gZnVuY3Rpb24gKHRyYWNrKSB7XG4gICAgdmFyIGlkID0gdHJhY2suZ2V0UGFydGljaXBhbnRJZCgpO1xuICAgIHZhciBwYXJ0aWNpcGFudCA9IHRoaXMuZ2V0UGFydGljaXBhbnRCeUlkKGlkKTtcbiAgICBpZiAoIXBhcnRpY2lwYW50KSB7XG4gICAgICAgIHJldHVybjtcbiAgICB9XG4gICAgLy8gYWRkIHRyYWNrIHRvIEppdHNpUGFydGljaXBhbnRcbiAgICBwYXJ0aWNpcGFudC5fdHJhY2tzLnB1c2godHJhY2spO1xuXG4gICAgdmFyIGVtaXR0ZXIgPSB0aGlzLmV2ZW50RW1pdHRlcjtcbiAgICB0cmFjay5hZGRFdmVudExpc3RlbmVyKFxuICAgICAgICBKaXRzaVRyYWNrRXZlbnRzLlRSQUNLX1NUT1BQRUQsXG4gICAgICAgIGZ1bmN0aW9uICgpIHtcbiAgICAgICAgICAgIC8vIHJlbW92ZSB0cmFjayBmcm9tIEppdHNpUGFydGljaXBhbnRcbiAgICAgICAgICAgIHZhciBwb3MgPSBwYXJ0aWNpcGFudC5fdHJhY2tzLmluZGV4T2YodHJhY2spO1xuICAgICAgICAgICAgaWYgKHBvcyA+IC0xKSB7XG4gICAgICAgICAgICAgICAgcGFydGljaXBhbnQuX3RyYWNrcy5zcGxpY2UocG9zLCAxKTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgICAgIGVtaXR0ZXIuZW1pdChKaXRzaUNvbmZlcmVuY2VFdmVudHMuVFJBQ0tfUkVNT1ZFRCwgdHJhY2spO1xuICAgICAgICB9XG4gICAgKTtcbiAgICB0cmFjay5hZGRFdmVudExpc3RlbmVyKFxuICAgICAgICBKaXRzaVRyYWNrRXZlbnRzLlRSQUNLX01VVEVfQ0hBTkdFRCxcbiAgICAgICAgZnVuY3Rpb24gKCkge1xuICAgICAgICAgICAgZW1pdHRlci5lbWl0KEppdHNpQ29uZmVyZW5jZUV2ZW50cy5UUkFDS19NVVRFX0NIQU5HRUQsIHRyYWNrKTtcbiAgICAgICAgfVxuICAgICk7XG4gICAgdHJhY2suYWRkRXZlbnRMaXN0ZW5lcihcbiAgICAgICAgSml0c2lUcmFja0V2ZW50cy5UUkFDS19BVURJT19MRVZFTF9DSEFOR0VELFxuICAgICAgICBmdW5jdGlvbiAoYXVkaW9MZXZlbCkge1xuICAgICAgICAgICAgZW1pdHRlci5lbWl0KEppdHNpQ29uZmVyZW5jZUV2ZW50cy5UUkFDS19BVURJT19MRVZFTF9DSEFOR0VELCBpZCwgYXVkaW9MZXZlbCk7XG4gICAgICAgIH1cbiAgICApO1xuXG4gICAgdGhpcy5ldmVudEVtaXR0ZXIuZW1pdChKaXRzaUNvbmZlcmVuY2VFdmVudHMuVFJBQ0tfQURERUQsIHRyYWNrKTtcbn07XG5cbkppdHNpQ29uZmVyZW5jZS5wcm90b3R5cGUudXBkYXRlRFRNRlN1cHBvcnQgPSBmdW5jdGlvbiAoKSB7XG4gICAgdmFyIHNvbWVib2R5U3VwcG9ydHNEVE1GID0gZmFsc2U7XG4gICAgdmFyIHBhcnRpY2lwYW50cyA9IHRoaXMuZ2V0UGFydGljaXBhbnRzKCk7XG5cbiAgICAvLyBjaGVjayBpZiBhdCBsZWFzdCAxIHBhcnRpY2lwYW50IHN1cHBvcnRzIERUTUZcbiAgICBmb3IgKHZhciBpID0gMDsgaSA8IHBhcnRpY2lwYW50cy5sZW5ndGg7IGkgKz0gMSkge1xuICAgICAgICBpZiAocGFydGljaXBhbnRzW2ldLnN1cHBvcnRzRFRNRigpKSB7XG4gICAgICAgICAgICBzb21lYm9keVN1cHBvcnRzRFRNRiA9IHRydWU7XG4gICAgICAgICAgICBicmVhaztcbiAgICAgICAgfVxuICAgIH1cbiAgICBpZiAoc29tZWJvZHlTdXBwb3J0c0RUTUYgIT09IHRoaXMuc29tZWJvZHlTdXBwb3J0c0RUTUYpIHtcbiAgICAgICAgdGhpcy5zb21lYm9keVN1cHBvcnRzRFRNRiA9IHNvbWVib2R5U3VwcG9ydHNEVE1GO1xuICAgICAgICB0aGlzLmV2ZW50RW1pdHRlci5lbWl0KEppdHNpQ29uZmVyZW5jZUV2ZW50cy5EVE1GX1NVUFBPUlRfQ0hBTkdFRCwgc29tZWJvZHlTdXBwb3J0c0RUTUYpO1xuICAgIH1cbn07XG5cbi8qKlxuICogQWxsb3dzIHRvIGNoZWNrIGlmIHRoZXJlIGlzIGF0IGxlYXN0IG9uZSB1c2VyIGluIHRoZSBjb25mZXJlbmNlXG4gKiB0aGF0IHN1cHBvcnRzIERUTUYuXG4gKiBAcmV0dXJucyB7Ym9vbGVhbn0gdHJ1ZSBpZiBzb21lYm9keSBzdXBwb3J0cyBEVE1GLCBmYWxzZSBvdGhlcndpc2VcbiAqL1xuSml0c2lDb25mZXJlbmNlLnByb3RvdHlwZS5pc0RUTUZTdXBwb3J0ZWQgPSBmdW5jdGlvbiAoKSB7XG4gICAgcmV0dXJuIHRoaXMuc29tZWJvZHlTdXBwb3J0c0RUTUY7XG59O1xuXG4vKipcbiAqIFJldHVybnMgdGhlIGxvY2FsIHVzZXIncyBJRFxuICogQHJldHVybiB7c3RyaW5nfSBsb2NhbCB1c2VyJ3MgSURcbiAqL1xuSml0c2lDb25mZXJlbmNlLnByb3RvdHlwZS5teVVzZXJJZCA9IGZ1bmN0aW9uICgpIHtcbiAgICByZXR1cm4gKHRoaXMucm9vbSAmJiB0aGlzLnJvb20ubXlyb29tamlkKT8gU3Ryb3BoZS5nZXRSZXNvdXJjZUZyb21KaWQodGhpcy5yb29tLm15cm9vbWppZCkgOiBudWxsO1xufTtcblxuSml0c2lDb25mZXJlbmNlLnByb3RvdHlwZS5zZW5kVG9uZXMgPSBmdW5jdGlvbiAodG9uZXMsIGR1cmF0aW9uLCBwYXVzZSkge1xuICAgIGlmICghdGhpcy5kdG1mTWFuYWdlcikge1xuICAgICAgICB2YXIgY29ubmVjdGlvbiA9IHRoaXMueG1wcC5jb25uZWN0aW9uLmppbmdsZS5hY3RpdmVjYWxsLnBlZXJjb25uZWN0aW9uO1xuICAgICAgICBpZiAoIWNvbm5lY3Rpb24pIHtcbiAgICAgICAgICAgIGxvZ2dlci53YXJuKFwiY2Fubm90IHNlbmRUb25lczogbm8gY29ubmVjaXRvblwiKTtcbiAgICAgICAgICAgIHJldHVybjtcbiAgICAgICAgfVxuXG4gICAgICAgIHZhciB0cmFja3MgPSB0aGlzLmdldExvY2FsVHJhY2tzKCkuZmlsdGVyKGZ1bmN0aW9uICh0cmFjaykge1xuICAgICAgICAgICAgcmV0dXJuIHRyYWNrLmlzQXVkaW9UcmFjaygpO1xuICAgICAgICB9KTtcbiAgICAgICAgaWYgKCF0cmFja3MubGVuZ3RoKSB7XG4gICAgICAgICAgICBsb2dnZXIud2FybihcImNhbm5vdCBzZW5kVG9uZXM6IG5vIGxvY2FsIGF1ZGlvIHN0cmVhbVwiKTtcbiAgICAgICAgICAgIHJldHVybjtcbiAgICAgICAgfVxuICAgICAgICB0aGlzLmR0bWZNYW5hZ2VyID0gbmV3IEppdHNpRFRNRk1hbmFnZXIodHJhY2tzWzBdLCBjb25uZWN0aW9uKTtcbiAgICB9XG5cbiAgICB0aGlzLmR0bWZNYW5hZ2VyLnNlbmRUb25lcyh0b25lcywgZHVyYXRpb24sIHBhdXNlKTtcbn07XG5cbi8qKlxuICogUmV0dXJucyB0cnVlIGlmIHRoZSByZWNvcmRpbmcgaXMgc3VwcHJvdGVkIGFuZCBmYWxzZSBpZiBub3QuXG4gKi9cbkppdHNpQ29uZmVyZW5jZS5wcm90b3R5cGUuaXNSZWNvcmRpbmdTdXBwb3J0ZWQgPSBmdW5jdGlvbiAoKSB7XG4gICAgaWYodGhpcy5yb29tKVxuICAgICAgICByZXR1cm4gdGhpcy5yb29tLmlzUmVjb3JkaW5nU3VwcG9ydGVkKCk7XG4gICAgcmV0dXJuIGZhbHNlO1xufTtcblxuLyoqXG4gKiBSZXR1cm5zIG51bGwgaWYgdGhlIHJlY29yZGluZyBpcyBub3Qgc3VwcG9ydGVkLCBcIm9uXCIgaWYgdGhlIHJlY29yZGluZyBzdGFydGVkXG4gKiBhbmQgXCJvZmZcIiBpZiB0aGUgcmVjb3JkaW5nIGlzIG5vdCBzdGFydGVkLlxuICovXG5KaXRzaUNvbmZlcmVuY2UucHJvdG90eXBlLmdldFJlY29yZGluZ1N0YXRlID0gZnVuY3Rpb24gKCkge1xuICAgIGlmKHRoaXMucm9vbSlcbiAgICAgICAgcmV0dXJuIHRoaXMucm9vbS5nZXRSZWNvcmRpbmdTdGF0ZSgpO1xuICAgIHJldHVybiBcIm9mZlwiO1xufVxuXG4vKipcbiAqIFJldHVybnMgdGhlIHVybCBvZiB0aGUgcmVjb3JkZWQgdmlkZW8uXG4gKi9cbkppdHNpQ29uZmVyZW5jZS5wcm90b3R5cGUuZ2V0UmVjb3JkaW5nVVJMID0gZnVuY3Rpb24gKCkge1xuICAgIGlmKHRoaXMucm9vbSlcbiAgICAgICAgcmV0dXJuIHRoaXMucm9vbS5nZXRSZWNvcmRpbmdVUkwoKTtcbiAgICByZXR1cm4gbnVsbDtcbn1cblxuLyoqXG4gKiBTdGFydHMvc3RvcHMgdGhlIHJlY29yZGluZ1xuICogQHBhcmFtIHRva2VuIGEgdG9rZW4gZm9yIGF1dGhlbnRpY2F0aW9uLlxuICovXG5KaXRzaUNvbmZlcmVuY2UucHJvdG90eXBlLnRvZ2dsZVJlY29yZGluZyA9IGZ1bmN0aW9uICh0b2tlbiwgZm9sbG93RW50aXR5KSB7XG4gICAgaWYodGhpcy5yb29tKVxuICAgICAgICByZXR1cm4gdGhpcy5yb29tLnRvZ2dsZVJlY29yZGluZyh0b2tlbiwgZm9sbG93RW50aXR5KTtcbiAgICByZXR1cm4gbmV3IFByb21pc2UoZnVuY3Rpb24ocmVzb2x2ZSwgcmVqZWN0KXtcbiAgICAgICAgcmVqZWN0KG5ldyBFcnJvcihcIlRoZSBjb25mZXJlbmNlIGlzIG5vdCBjcmVhdGVkIHlldCFcIikpfSk7XG59XG5cbi8qKlxuICogUmV0dXJucyB0cnVlIGlmIHRoZSBTSVAgY2FsbHMgYXJlIHN1cHBvcnRlZCBhbmQgZmFsc2Ugb3RoZXJ3aXNlXG4gKi9cbkppdHNpQ29uZmVyZW5jZS5wcm90b3R5cGUuaXNTSVBDYWxsaW5nU3VwcG9ydGVkID0gZnVuY3Rpb24gKCkge1xuICAgIGlmKHRoaXMucm9vbSlcbiAgICAgICAgcmV0dXJuIHRoaXMucm9vbS5pc1NJUENhbGxpbmdTdXBwb3J0ZWQoKTtcbiAgICByZXR1cm4gZmFsc2U7XG59XG5cbi8qKlxuICogRGlhbHMgYSBudW1iZXIuXG4gKiBAcGFyYW0gbnVtYmVyIHRoZSBudW1iZXJcbiAqL1xuSml0c2lDb25mZXJlbmNlLnByb3RvdHlwZS5kaWFsID0gZnVuY3Rpb24gKG51bWJlcikge1xuICAgIGlmKHRoaXMucm9vbSlcbiAgICAgICAgcmV0dXJuIHRoaXMucm9vbS5kaWFsKG51bWJlcik7XG4gICAgcmV0dXJuIG5ldyBQcm9taXNlKGZ1bmN0aW9uKHJlc29sdmUsIHJlamVjdCl7XG4gICAgICAgIHJlamVjdChuZXcgRXJyb3IoXCJUaGUgY29uZmVyZW5jZSBpcyBub3QgY3JlYXRlZCB5ZXQhXCIpKX0pO1xufVxuXG4vKipcbiAqIEhhbmd1cCBhbiBleGlzdGluZyBjYWxsXG4gKi9cbkppdHNpQ29uZmVyZW5jZS5wcm90b3R5cGUuaGFuZ3VwID0gZnVuY3Rpb24gKCkge1xuICAgIGlmKHRoaXMucm9vbSlcbiAgICAgICAgcmV0dXJuIHRoaXMucm9vbS5oYW5ndXAoKTtcbiAgICByZXR1cm4gbmV3IFByb21pc2UoZnVuY3Rpb24ocmVzb2x2ZSwgcmVqZWN0KXtcbiAgICAgICAgcmVqZWN0KG5ldyBFcnJvcihcIlRoZSBjb25mZXJlbmNlIGlzIG5vdCBjcmVhdGVkIHlldCFcIikpfSk7XG59XG5cbi8qKlxuICogUmV0dXJucyB0aGUgcGhvbmUgbnVtYmVyIGZvciBqb2luaW5nIHRoZSBjb25mZXJlbmNlLlxuICovXG5KaXRzaUNvbmZlcmVuY2UucHJvdG90eXBlLmdldFBob25lTnVtYmVyID0gZnVuY3Rpb24gKCkge1xuICAgIGlmKHRoaXMucm9vbSlcbiAgICAgICAgcmV0dXJuIHRoaXMucm9vbS5nZXRQaG9uZU51bWJlcigpO1xuICAgIHJldHVybiBudWxsO1xufVxuXG4vKipcbiAqIFJldHVybnMgdGhlIHBpbiBmb3Igam9pbmluZyB0aGUgY29uZmVyZW5jZSB3aXRoIHBob25lLlxuICovXG5KaXRzaUNvbmZlcmVuY2UucHJvdG90eXBlLmdldFBob25lUGluID0gZnVuY3Rpb24gKCkge1xuICAgIGlmKHRoaXMucm9vbSlcbiAgICAgICAgcmV0dXJuIHRoaXMucm9vbS5nZXRQaG9uZVBpbigpO1xuICAgIHJldHVybiBudWxsO1xufVxuXG4vKipcbiAqIFJldHVybnMgdGhlIGNvbm5lY3Rpb24gc3RhdGUgZm9yIHRoZSBjdXJyZW50IHJvb20uIEl0cyBpY2UgY29ubmVjdGlvbiBzdGF0ZVxuICogZm9yIGl0cyBzZXNzaW9uLlxuICovXG5KaXRzaUNvbmZlcmVuY2UucHJvdG90eXBlLmdldENvbm5lY3Rpb25TdGF0ZSA9IGZ1bmN0aW9uICgpIHtcbiAgICBpZih0aGlzLnJvb20pXG4gICAgICAgIHJldHVybiB0aGlzLnJvb20uZ2V0Q29ubmVjdGlvblN0YXRlKCk7XG4gICAgcmV0dXJuIG51bGw7XG59XG5cbi8qKlxuICogU2V0dXBzIHRoZSBsaXN0ZW5lcnMgbmVlZGVkIGZvciB0aGUgY29uZmVyZW5jZS5cbiAqIEBwYXJhbSBjb25mZXJlbmNlIHRoZSBjb25mZXJlbmNlXG4gKi9cbmZ1bmN0aW9uIHNldHVwTGlzdGVuZXJzKGNvbmZlcmVuY2UpIHtcbiAgICBjb25mZXJlbmNlLnhtcHAuYWRkTGlzdGVuZXIoWE1QUEV2ZW50cy5DQUxMX0lOQ09NSU5HLCBmdW5jdGlvbiAoZXZlbnQpIHtcbiAgICAgICAgY29uZmVyZW5jZS5ydGMub25JbmNvbW1pbmdDYWxsKGV2ZW50KTtcbiAgICAgICAgaWYoY29uZmVyZW5jZS5zdGF0aXN0aWNzKVxuICAgICAgICAgICAgY29uZmVyZW5jZS5zdGF0aXN0aWNzLnN0YXJ0UmVtb3RlU3RhdHMoZXZlbnQucGVlcmNvbm5lY3Rpb24pO1xuICAgIH0pO1xuXG4gICAgY29uZmVyZW5jZS5yb29tLmFkZExpc3RlbmVyKFhNUFBFdmVudHMuUkVNT1RFX1NUUkVBTV9SRUNFSVZFRCxcbiAgICAgICAgZnVuY3Rpb24gKGRhdGEsIHNpZCwgdGhlc3NyYykge1xuICAgICAgICAgICAgdmFyIHRyYWNrID0gY29uZmVyZW5jZS5ydGMuY3JlYXRlUmVtb3RlU3RyZWFtKGRhdGEsIHNpZCwgdGhlc3NyYyk7XG4gICAgICAgICAgICBpZiAodHJhY2spIHtcbiAgICAgICAgICAgICAgICBjb25mZXJlbmNlLm9uVHJhY2tBZGRlZCh0cmFjayk7XG4gICAgICAgICAgICB9XG4gICAgICAgIH1cbiAgICApO1xuXG4gICAgY29uZmVyZW5jZS5yb29tLmFkZExpc3RlbmVyKFhNUFBFdmVudHMuTVVDX0pPSU5FRCwgZnVuY3Rpb24gKCkge1xuICAgICAgICBjb25mZXJlbmNlLmV2ZW50RW1pdHRlci5lbWl0KEppdHNpQ29uZmVyZW5jZUV2ZW50cy5DT05GRVJFTkNFX0pPSU5FRCk7XG4gICAgfSk7XG4gICAgY29uZmVyZW5jZS5yb29tLmFkZExpc3RlbmVyKFhNUFBFdmVudHMuUk9PTV9KT0lOX0VSUk9SLCBmdW5jdGlvbiAocHJlcykge1xuICAgICAgICBjb25mZXJlbmNlLmV2ZW50RW1pdHRlci5lbWl0KEppdHNpQ29uZmVyZW5jZUV2ZW50cy5DT05GRVJFTkNFX0ZBSUxFRCwgSml0c2lDb25mZXJlbmNlRXJyb3JzLkNPTk5FQ1RJT05fRVJST1IsIHByZXMpO1xuICAgIH0pO1xuICAgIGNvbmZlcmVuY2Uucm9vbS5hZGRMaXN0ZW5lcihYTVBQRXZlbnRzLlJPT01fQ09OTkVDVF9FUlJPUiwgZnVuY3Rpb24gKHByZXMpIHtcbiAgICAgICAgY29uZmVyZW5jZS5ldmVudEVtaXR0ZXIuZW1pdChKaXRzaUNvbmZlcmVuY2VFdmVudHMuQ09ORkVSRU5DRV9GQUlMRUQsIEppdHNpQ29uZmVyZW5jZUVycm9ycy5DT05ORUNUSU9OX0VSUk9SLCBwcmVzKTtcbiAgICB9KTtcbiAgICBjb25mZXJlbmNlLnJvb20uYWRkTGlzdGVuZXIoWE1QUEV2ZW50cy5QQVNTV09SRF9SRVFVSVJFRCwgZnVuY3Rpb24gKHByZXMpIHtcbiAgICAgICAgY29uZmVyZW5jZS5ldmVudEVtaXR0ZXIuZW1pdChKaXRzaUNvbmZlcmVuY2VFdmVudHMuQ09ORkVSRU5DRV9GQUlMRUQsIEppdHNpQ29uZmVyZW5jZUVycm9ycy5QQVNTV09SRF9SRVFVSVJFRCwgcHJlcyk7XG4gICAgfSk7XG4gICAgY29uZmVyZW5jZS5yb29tLmFkZExpc3RlbmVyKFhNUFBFdmVudHMuQVVUSEVOVElDQVRJT05fUkVRVUlSRUQsIGZ1bmN0aW9uICgpIHtcbiAgICAgICAgY29uZmVyZW5jZS5ldmVudEVtaXR0ZXIuZW1pdChKaXRzaUNvbmZlcmVuY2VFdmVudHMuQ09ORkVSRU5DRV9GQUlMRUQsIEppdHNpQ29uZmVyZW5jZUVycm9ycy5BVVRIRU5USUNBVElPTl9SRVFVSVJFRCk7XG4gICAgfSk7XG4vLyAgICBGSVhNRVxuLy8gICAgY29uZmVyZW5jZS5yb29tLmFkZExpc3RlbmVyKFhNUFBFdmVudHMuTVVDX0pPSU5FRCwgZnVuY3Rpb24gKCkge1xuLy8gICAgICAgIGNvbmZlcmVuY2UuZXZlbnRFbWl0dGVyLmVtaXQoSml0c2lDb25mZXJlbmNlRXZlbnRzLkNPTkZFUkVOQ0VfTEVGVCk7XG4vLyAgICB9KTtcblxuICAgIGNvbmZlcmVuY2Uucm9vbS5hZGRMaXN0ZW5lcihYTVBQRXZlbnRzLktJQ0tFRCwgZnVuY3Rpb24gKCkge1xuICAgICAgICBjb25mZXJlbmNlLmV2ZW50RW1pdHRlci5lbWl0KEppdHNpQ29uZmVyZW5jZUV2ZW50cy5LSUNLRUQpO1xuICAgIH0pO1xuXG4gICAgY29uZmVyZW5jZS5yb29tLmFkZExpc3RlbmVyKFhNUFBFdmVudHMuTVVDX01FTUJFUl9KT0lORUQsIGNvbmZlcmVuY2Uub25NZW1iZXJKb2luZWQuYmluZChjb25mZXJlbmNlKSk7XG4gICAgY29uZmVyZW5jZS5yb29tLmFkZExpc3RlbmVyKFhNUFBFdmVudHMuTVVDX01FTUJFUl9MRUZULCBjb25mZXJlbmNlLm9uTWVtYmVyTGVmdC5iaW5kKGNvbmZlcmVuY2UpKTtcblxuICAgIGNvbmZlcmVuY2Uucm9vbS5hZGRMaXN0ZW5lcihYTVBQRXZlbnRzLkRJU1BMQVlfTkFNRV9DSEFOR0VELCBjb25mZXJlbmNlLm9uRGlzcGxheU5hbWVDaGFuZ2VkLmJpbmQoY29uZmVyZW5jZSkpO1xuXG4gICAgY29uZmVyZW5jZS5yb29tLmFkZExpc3RlbmVyKFhNUFBFdmVudHMuTE9DQUxfUk9MRV9DSEFOR0VELCBmdW5jdGlvbiAocm9sZSkge1xuICAgICAgICBjb25mZXJlbmNlLmV2ZW50RW1pdHRlci5lbWl0KEppdHNpQ29uZmVyZW5jZUV2ZW50cy5VU0VSX1JPTEVfQ0hBTkdFRCwgY29uZmVyZW5jZS5teVVzZXJJZCgpLCByb2xlKTtcbiAgICB9KTtcbiAgICBjb25mZXJlbmNlLnJvb20uYWRkTGlzdGVuZXIoWE1QUEV2ZW50cy5NVUNfUk9MRV9DSEFOR0VELCBjb25mZXJlbmNlLm9uVXNlclJvbGVDaGFuZ2VkLmJpbmQoY29uZmVyZW5jZSkpO1xuXG4gICAgY29uZmVyZW5jZS5yb29tLmFkZExpc3RlbmVyKFhNUFBFdmVudHMuQ09OTkVDVElPTl9JTlRFUlJVUFRFRCwgZnVuY3Rpb24gKCkge1xuICAgICAgICBjb25mZXJlbmNlLmV2ZW50RW1pdHRlci5lbWl0KEppdHNpQ29uZmVyZW5jZUV2ZW50cy5DT05ORUNUSU9OX0lOVEVSUlVQVEVEKTtcbiAgICB9KTtcblxuICAgIGNvbmZlcmVuY2Uucm9vbS5hZGRMaXN0ZW5lcihYTVBQRXZlbnRzLlJFQ09SRElOR19TVEFURV9DSEFOR0VELFxuICAgICAgICBmdW5jdGlvbiAoKSB7XG4gICAgICAgICAgICBjb25mZXJlbmNlLmV2ZW50RW1pdHRlci5lbWl0KFxuICAgICAgICAgICAgICAgIEppdHNpQ29uZmVyZW5jZUV2ZW50cy5SRUNPUkRJTkdfU1RBVEVfQ0hBTkdFRCk7XG4gICAgICAgIH0pO1xuXG4gICAgY29uZmVyZW5jZS5yb29tLmFkZExpc3RlbmVyKFhNUFBFdmVudHMuUEhPTkVfTlVNQkVSX0NIQU5HRUQsIGZ1bmN0aW9uICgpIHtcbiAgICAgICAgY29uZmVyZW5jZS5ldmVudEVtaXR0ZXIuZW1pdChcbiAgICAgICAgICAgIEppdHNpQ29uZmVyZW5jZUV2ZW50cy5QSE9ORV9OVU1CRVJfQ0hBTkdFRCk7XG4gICAgfSk7XG5cbiAgICBjb25mZXJlbmNlLnJvb20uYWRkTGlzdGVuZXIoWE1QUEV2ZW50cy5DT05ORUNUSU9OX1JFU1RPUkVELCBmdW5jdGlvbiAoKSB7XG4gICAgICAgIGNvbmZlcmVuY2UuZXZlbnRFbWl0dGVyLmVtaXQoSml0c2lDb25mZXJlbmNlRXZlbnRzLkNPTk5FQ1RJT05fUkVTVE9SRUQpO1xuICAgIH0pO1xuICAgIGNvbmZlcmVuY2Uucm9vbS5hZGRMaXN0ZW5lcihYTVBQRXZlbnRzLkNPTkZFUkVOQ0VfU0VUVVBfRkFJTEVELCBmdW5jdGlvbiAoKSB7XG4gICAgICAgIGNvbmZlcmVuY2UuZXZlbnRFbWl0dGVyLmVtaXQoSml0c2lDb25mZXJlbmNlRXZlbnRzLkNPTkZFUkVOQ0VfRkFJTEVELCBKaXRzaUNvbmZlcmVuY2VFcnJvcnMuU0VUVVBfRkFJTEVEKTtcbiAgICB9KTtcblxuICAgIGNvbmZlcmVuY2Uucm9vbS5hZGRMaXN0ZW5lcihBdXRoZW50aWNhdGlvbkV2ZW50cy5JREVOVElUWV9VUERBVEVELCBmdW5jdGlvbiAoYXV0aEVuYWJsZWQsIGF1dGhJZGVudGl0eSkge1xuICAgICAgICBjb25mZXJlbmNlLmF1dGhFbmFibGVkID0gYXV0aEVuYWJsZWQ7XG4gICAgICAgIGNvbmZlcmVuY2UuYXV0aElkZW50aXR5ID0gYXV0aElkZW50aXR5O1xuICAgIH0pO1xuXG4gICAgY29uZmVyZW5jZS5yb29tLmFkZExpc3RlbmVyKFhNUFBFdmVudHMuTUVTU0FHRV9SRUNFSVZFRCwgZnVuY3Rpb24gKGppZCwgZGlzcGxheU5hbWUsIHR4dCwgbXlKaWQsIHRzKSB7XG4gICAgICAgIHZhciBpZCA9IFN0cm9waGUuZ2V0UmVzb3VyY2VGcm9tSmlkKGppZCk7XG4gICAgICAgIGNvbmZlcmVuY2UuZXZlbnRFbWl0dGVyLmVtaXQoSml0c2lDb25mZXJlbmNlRXZlbnRzLk1FU1NBR0VfUkVDRUlWRUQsIGlkLCB0eHQsIHRzKTtcbiAgICB9KTtcblxuICAgIGNvbmZlcmVuY2UucnRjLmFkZExpc3RlbmVyKFJUQ0V2ZW50cy5ET01JTkFOVFNQRUFLRVJfQ0hBTkdFRCwgZnVuY3Rpb24gKGlkKSB7XG4gICAgICAgIGlmKGNvbmZlcmVuY2UubGFzdEFjdGl2ZVNwZWFrZXIgIT09IGlkICYmIGNvbmZlcmVuY2Uucm9vbSkge1xuICAgICAgICAgICAgY29uZmVyZW5jZS5sYXN0QWN0aXZlU3BlYWtlciA9IGlkO1xuICAgICAgICAgICAgY29uZmVyZW5jZS5ldmVudEVtaXR0ZXIuZW1pdChKaXRzaUNvbmZlcmVuY2VFdmVudHMuQUNUSVZFX1NQRUFLRVJfQ0hBTkdFRCwgaWQpO1xuICAgICAgICB9XG4gICAgfSk7XG5cbiAgICBjb25mZXJlbmNlLnJ0Yy5hZGRMaXN0ZW5lcihSVENFdmVudHMuTEFTVE5fQ0hBTkdFRCwgZnVuY3Rpb24gKG9sZFZhbHVlLCBuZXdWYWx1ZSkge1xuICAgICAgICBjb25mZXJlbmNlLmV2ZW50RW1pdHRlci5lbWl0KEppdHNpQ29uZmVyZW5jZUV2ZW50cy5JTl9MQVNUX05fQ0hBTkdFRCwgb2xkVmFsdWUsIG5ld1ZhbHVlKTtcbiAgICB9KTtcblxuICAgIGNvbmZlcmVuY2UucnRjLmFkZExpc3RlbmVyKFJUQ0V2ZW50cy5MQVNUTl9FTkRQT0lOVF9DSEFOR0VELFxuICAgICAgICBmdW5jdGlvbiAobGFzdE5FbmRwb2ludHMsIGVuZHBvaW50c0VudGVyaW5nTGFzdE4pIHtcbiAgICAgICAgICAgIGNvbmZlcmVuY2UuZXZlbnRFbWl0dGVyLmVtaXQoSml0c2lDb25mZXJlbmNlRXZlbnRzLkxBU1RfTl9FTkRQT0lOVFNfQ0hBTkdFRCxcbiAgICAgICAgICAgICAgICBsYXN0TkVuZHBvaW50cywgZW5kcG9pbnRzRW50ZXJpbmdMYXN0Tik7XG4gICAgICAgIH0pO1xuICAgIGNvbmZlcmVuY2UueG1wcC5hZGRMaXN0ZW5lcihYTVBQRXZlbnRzLlBBU1NXT1JEX1JFUVVJUkVELCBmdW5jdGlvbiAoKSB7XG4gICAgICAgIGNvbmZlcmVuY2UuZXZlbnRFbWl0dGVyLmVtaXQoSml0c2lDb25mZXJlbmNlRXJyb3JzLlBBU1NXT1JEX1JFUVVJUkVEKTtcbiAgICB9KTtcblxuICAgIGlmKGNvbmZlcmVuY2Uuc3RhdGlzdGljcykge1xuICAgICAgICAvL0ZJWE1FOiBNYXliZSByZW1vdmUgZXZlbnQgc2hvdWxkIG5vdCBiZSBhc3NvY2lhdGVkIHdpdGggdGhlIGNvbmZlcmVuY2UuXG4gICAgICAgIGNvbmZlcmVuY2Uuc3RhdGlzdGljcy5hZGRBdWRpb0xldmVsTGlzdGVuZXIoZnVuY3Rpb24gKHNzcmMsIGxldmVsKSB7XG4gICAgICAgICAgICB2YXIgdXNlcklkID0gbnVsbDtcbiAgICAgICAgICAgIHZhciBqaWQgPSBjb25mZXJlbmNlLnJvb20uZ2V0SmlkQnlTU1JDKHNzcmMpO1xuICAgICAgICAgICAgaWYgKCFqaWQpXG4gICAgICAgICAgICAgICAgcmV0dXJuO1xuXG4gICAgICAgICAgICBjb25mZXJlbmNlLnJ0Yy5zZXRBdWRpb0xldmVsKGppZCwgbGV2ZWwpO1xuICAgICAgICB9KTtcbiAgICAgICAgY29uZmVyZW5jZS54bXBwLmFkZExpc3RlbmVyKFhNUFBFdmVudHMuRElTUE9TRV9DT05GRVJFTkNFLFxuICAgICAgICAgICAgZnVuY3Rpb24gKCkge1xuICAgICAgICAgICAgICAgIGNvbmZlcmVuY2Uuc3RhdGlzdGljcy5kaXNwb3NlKCk7XG4gICAgICAgICAgICB9KTtcbiAgICAgICAgLy8gRklYTUU6IE1heWJlIHdlIHNob3VsZCBtb3ZlIHRoaXMuXG4gICAgICAgIC8vIFJUQy5hZGRMaXN0ZW5lcihSVENFdmVudHMuQVZBSUxBQkxFX0RFVklDRVNfQ0hBTkdFRCwgZnVuY3Rpb24gKGRldmljZXMpIHtcbiAgICAgICAgLy8gICAgIGNvbmZlcmVuY2Uucm9vbS51cGRhdGVEZXZpY2VBdmFpbGFiaWxpdHkoZGV2aWNlcyk7XG4gICAgICAgIC8vIH0pO1xuICAgIH1cbn1cblxuXG5tb2R1bGUuZXhwb3J0cyA9IEppdHNpQ29uZmVyZW5jZTtcbiIsIi8qKlxuICogRW51bWVyYXRpb24gd2l0aCB0aGUgZXJyb3JzIGZvciB0aGUgY29uZmVyZW5jZS5cbiAqIEB0eXBlIHt7c3RyaW5nOiBzdHJpbmd9fVxuICovXG52YXIgSml0c2lDb25mZXJlbmNlRXJyb3JzID0ge1xuICAgIC8qKlxuICAgICAqIEluZGljYXRlcyB0aGF0IGEgcGFzc3dvcmQgaXMgcmVxdWlyZWQgaW4gb3JkZXIgdG8gam9pbiB0aGUgY29uZmVyZW5jZS5cbiAgICAgKi9cbiAgICBQQVNTV09SRF9SRVFVSVJFRDogXCJjb25mZXJlbmNlLnBhc3N3b3JkUmVxdWlyZWRcIixcbiAgICAvKipcbiAgICAgKiBJbmRpY2F0ZXMgdGhhdCBjbGllbnQgbXVzdCBiZSBhdXRoZW50aWNhdGVkIHRvIGNyZWF0ZSB0aGUgY29uZmVyZW5jZS5cbiAgICAgKi9cbiAgICBBVVRIRU5USUNBVElPTl9SRVFVSVJFRDogXCJjb25mZXJlbmNlLmF1dGhlbnRpY2F0aW9uUmVxdWlyZWRcIixcbiAgICAvKipcbiAgICAgKiBJbmRpY2F0ZXMgdGhhdCBwYXNzd29yZCBjYW5ub3QgYmUgc2V0IGZvciB0aGlzIGNvbmZlcmVuY2UuXG4gICAgICovXG4gICAgUEFTU1dPUkRfTk9UX1NVUFBPUlRFRDogXCJjb25mZXJlbmNlLnBhc3N3b3JkTm90U3VwcG9ydGVkXCIsXG4gICAgLyoqXG4gICAgICogSW5kaWNhdGVzIHRoYXQgYSBjb25uZWN0aW9uIGVycm9yIG9jY3VycmVkIHdoZW4gdHJ5aW5nIHRvIGpvaW4gYVxuICAgICAqIGNvbmZlcmVuY2UuXG4gICAgICovXG4gICAgQ09OTkVDVElPTl9FUlJPUjogXCJjb25mZXJlbmNlLmNvbm5lY3Rpb25FcnJvclwiLFxuICAgIC8qKlxuICAgICAqIEluZGljYXRlcyB0aGF0IHRoZSBjb25mZXJlbmNlIHNldHVwIGZhaWxlZC5cbiAgICAgKi9cbiAgICBTRVRVUF9GQUlMRUQ6IFwiY29uZmVyZW5jZS5zZXR1cF9mYWlsZWRcIixcbiAgICAvKipcbiAgICAgKiBJbmRpY2F0ZXMgdGhhdCB0aGVyZSBpcyBubyBhdmFpbGFibGUgdmlkZW9icmlkZ2UuXG4gICAgICovXG4gICAgVklERU9CUklER0VfTk9UX0FWQUlMQUJMRTogXCJjb25mZXJlbmNlLnZpZGVvYnJpZGdlTm90QXZhaWxhYmxlXCJcbiAgICAvKipcbiAgICAgKiBNYW55IG1vcmUgZXJyb3JzIFRCRCBoZXJlLlxuICAgICAqL1xufTtcblxubW9kdWxlLmV4cG9ydHMgPSBKaXRzaUNvbmZlcmVuY2VFcnJvcnM7XG4iLCIvKipcbiAqIEVudW1lcmF0aW9uIHdpdGggdGhlIGV2ZW50cyBmb3IgdGhlIGNvbmZlcmVuY2UuXG4gKiBAdHlwZSB7e3N0cmluZzogc3RyaW5nfX1cbiAqL1xudmFyIEppdHNpQ29uZmVyZW5jZUV2ZW50cyA9IHtcbiAgICAvKipcbiAgICAgKiBBIG5ldyBtZWRpYSB0cmFjayB3YXMgYWRkZWQgdG8gdGhlIGNvbmZlcmVuY2UuXG4gICAgICovXG4gICAgVFJBQ0tfQURERUQ6IFwiY29uZmVyZW5jZS50cmFja0FkZGVkXCIsXG4gICAgLyoqXG4gICAgICogVGhlIG1lZGlhIHRyYWNrIHdhcyByZW1vdmVkIGZyb20gdGhlIGNvbmZlcmVuY2UuXG4gICAgICovXG4gICAgVFJBQ0tfUkVNT1ZFRDogXCJjb25mZXJlbmNlLnRyYWNrUmVtb3ZlZFwiLFxuICAgIC8qKlxuICAgICAqIFRoZSBhY3RpdmUgc3BlYWtlciB3YXMgY2hhbmdlZC5cbiAgICAgKi9cbiAgICBBQ1RJVkVfU1BFQUtFUl9DSEFOR0VEOiBcImNvbmZlcmVuY2UuYWN0aXZlU3BlYWtlclwiLFxuICAgIC8qKlxuICAgICAqIEEgbmV3IHVzZXIgam9pbm5lZCB0aGUgY29uZmVyZW5jZS5cbiAgICAgKi9cbiAgICBVU0VSX0pPSU5FRDogXCJjb25mZXJlbmNlLnVzZXJKb2luZWRcIixcbiAgICAvKipcbiAgICAgKiBBIHVzZXIgaGFzIGxlZnQgdGhlIGNvbmZlcmVuY2UuXG4gICAgICovXG4gICAgVVNFUl9MRUZUOiBcImNvbmZlcmVuY2UudXNlckxlZnRcIixcbiAgICAvKipcbiAgICAgKiBVc2VyIHJvbGUgY2hhbmdlZC5cbiAgICAgKi9cbiAgICBVU0VSX1JPTEVfQ0hBTkdFRDogXCJjb25mZXJlbmNlLnJvbGVDaGFuZ2VkXCIsXG4gICAgLyoqXG4gICAgICogTmV3IHRleHQgbWVzc2FnZSB3YXMgcmVjZWl2ZWQuXG4gICAgICovXG4gICAgTUVTU0FHRV9SRUNFSVZFRDogXCJjb25mZXJlbmNlLm1lc3NhZ2VSZWNlaXZlZFwiLFxuICAgIC8qKlxuICAgICAqIEEgdXNlciBoYXMgY2hhbmdlZCBpdCBkaXNwbGF5IG5hbWVcbiAgICAgKi9cbiAgICBESVNQTEFZX05BTUVfQ0hBTkdFRDogXCJjb25mZXJlbmNlLmRpc3BsYXlOYW1lQ2hhbmdlZFwiLFxuICAgIC8qKlxuICAgICAqIEEgcGFydGljaXBhbnQgYXZhdGFyIGhhcyBjaGFuZ2VkLlxuICAgICAqL1xuICAgIEFWQVRBUl9DSEFOR0VEOiBcImNvbmZlcmVuY2UuYXZhdGFyQ2hhbmdlZFwiLFxuICAgIC8qKlxuICAgICAqIE5ldyBjb25uZWN0aW9uIHN0YXRpc3RpY3MgYXJlIHJlY2VpdmVkLlxuICAgICAqL1xuICAgIENPTk5FQ1RJT05fU1RBVFNfUkVDRUlWRUQ6IFwiY29uZmVyZW5jZS5jb25uZWN0aW9uU3RhdHNSZWNlaXZlZFwiLFxuICAgIC8qKlxuICAgICAqIFRoZSBMYXN0IE4gc2V0IGlzIGNoYW5nZWQuXG4gICAgICovXG4gICAgTEFTVF9OX0VORFBPSU5UU19DSEFOR0VEOiBcImNvbmZlcmVuY2UubGFzdE5FbmRwb2ludHNDaGFuZ2VkXCIsXG4gICAgLyoqXG4gICAgICogWW91IGFyZSBpbmNsdWRlZCAvIGV4Y2x1ZGVkIGluIHNvbWVib2R5J3MgbGFzdCBOIHNldFxuICAgICAqL1xuICAgIElOX0xBU1RfTl9DSEFOR0VEOiBcImNvbmZlcmVuY2UubGFzdE5FbmRwb2ludHNDaGFuZ2VkXCIsXG4gICAgLyoqXG4gICAgICogQSBtZWRpYSB0cmFjayAoIGF0dGFjaGVkIHRvIHRoZSBjb25mZXJlbmNlKSBtdXRlIHN0YXR1cyB3YXMgY2hhbmdlZC5cbiAgICAgKi9cbiAgICBUUkFDS19NVVRFX0NIQU5HRUQ6IFwiY29uZmVyZW5jZS50cmFja011dGVDaGFuZ2VkXCIsXG4gICAgLyoqXG4gICAgICogQXVkaW8gbGV2ZWxzIG9mIGEgbWVkaWEgdHJhY2sgKCBhdHRhY2hlZCB0byB0aGUgY29uZmVyZW5jZSkgd2FzIGNoYW5nZWQuXG4gICAgICovXG4gICAgVFJBQ0tfQVVESU9fTEVWRUxfQ0hBTkdFRDogXCJjb25mZXJlbmNlLmF1ZGlvTGV2ZWxzQ2hhbmdlZFwiLFxuICAgIC8qKlxuICAgICAqIEluZGljYXRlcyB0aGF0IHRoZSBjb25uZWN0aW9uIHRvIHRoZSBjb25mZXJlbmNlIGhhcyBiZWVuIGludGVycnVwdGVkXG4gICAgICogZm9yIHNvbWUgcmVhc29uLlxuICAgICAqL1xuICAgIENPTk5FQ1RJT05fSU5URVJSVVBURUQ6IFwiY29uZmVyZW5jZS5jb25uZWN0aW9uSW50ZXJydXB0ZWRcIixcbiAgICAvKipcbiAgICAgKiBJbmRpY2F0ZXMgdGhhdCB0aGUgY29ubmVjdGlvbiB0byB0aGUgY29uZmVyZW5jZSBoYXMgYmVlbiByZXN0b3JlZC5cbiAgICAgKi9cbiAgICBDT05ORUNUSU9OX1JFU1RPUkVEOiBcImNvbmZlcmVuY2UuY29ubmVjdGlvblJlc3RvcmVkXCIsXG4gICAgLyoqXG4gICAgICogSW5kaWNhdGVzIHRoYXQgY29uZmVyZW5jZSBmYWlsZWQuXG4gICAgICovXG4gICAgQ09ORkVSRU5DRV9GQUlMRUQ6IFwiY29uZmVyZW5jZS5mYWlsZWRcIixcbiAgICAvKipcbiAgICAgKiBJbmRpY2F0ZXMgdGhhdCBjb25mZXJlbmNlIGhhcyBiZWVuIGpvaW5lZC5cbiAgICAgKi9cbiAgICBDT05GRVJFTkNFX0pPSU5FRDogXCJjb25mZXJlbmNlLmpvaW5lZFwiLFxuICAgIC8qKlxuICAgICAqIEluZGljYXRlcyB0aGF0IGNvbmZlcmVuY2UgaGFzIGJlZW4gbGVmdC5cbiAgICAgKi9cbiAgICBDT05GRVJFTkNFX0xFRlQ6IFwiY29uZmVyZW5jZS5sZWZ0XCIsXG4gICAgLyoqXG4gICAgICogWW91IGFyZSBraWNrZWQgZnJvbSB0aGUgY29uZmVyZW5jZS5cbiAgICAgKi9cbiAgICBLSUNLRUQ6IFwiY29uZmVyZW5lY2Uua2lja2VkXCIsXG4gICAgLyoqXG4gICAgICogSW5kaWNhdGVzIHRoYXQgRFRNRiBzdXBwb3J0IGNoYW5nZWQuXG4gICAgICovXG4gICAgRFRNRl9TVVBQT1JUX0NIQU5HRUQ6IFwiY29uZmVyZW5jZS5kdG1mU3VwcG9ydENoYW5nZWRcIixcbiAgICAvKipcbiAgICAgKiBJbmRpY2F0ZXMgdGhhdCByZWNvcmRpbmcgc3RhdGUgY2hhbmdlZC5cbiAgICAgKi9cbiAgICBSRUNPUkRJTkdfU1RBVEVfQ0hBTkdFRDogXCJjb25mZXJlbmNlLnJlY29yZGluZ1N0YXRlQ2hhbmdlZFwiLFxuICAgIC8qKlxuICAgICAqIEluZGljYXRlcyB0aGF0IHBob25lIG51bWJlciBjaGFuZ2VkLlxuICAgICAqL1xuICAgIFBIT05FX05VTUJFUl9DSEFOR0VEOiBcImNvbmZlcmVuY2UucGhvbmVOdW1iZXJDaGFuZ2VkXCJcbn07XG5cbm1vZHVsZS5leHBvcnRzID0gSml0c2lDb25mZXJlbmNlRXZlbnRzO1xuIiwidmFyIEppdHNpQ29uZmVyZW5jZSA9IHJlcXVpcmUoXCIuL0ppdHNpQ29uZmVyZW5jZVwiKTtcbnZhciBYTVBQID0gcmVxdWlyZShcIi4vbW9kdWxlcy94bXBwL3htcHBcIik7XG5cbi8qKlxuICogQ3JlYXRlcyBuZXcgY29ubmVjdGlvbiBvYmplY3QgZm9yIHRoZSBKaXRzaSBNZWV0IHNlcnZlciBzaWRlIHZpZGVvIGNvbmZlcmVuY2luZyBzZXJ2aWNlLiBQcm92aWRlcyBhY2Nlc3MgdG8gdGhlXG4gKiBKaXRzaUNvbmZlcmVuY2UgaW50ZXJmYWNlLlxuICogQHBhcmFtIGFwcElEIGlkZW50aWZpY2F0aW9uIGZvciB0aGUgcHJvdmlkZXIgb2YgSml0c2kgTWVldCB2aWRlbyBjb25mZXJlbmNpbmcgc2VydmljZXMuXG4gKiBAcGFyYW0gdG9rZW4gdGhlIEpXVCB0b2tlbiB1c2VkIHRvIGF1dGhlbnRpY2F0ZSB3aXRoIHRoZSBzZXJ2ZXIob3B0aW9uYWwpXG4gKiBAcGFyYW0gb3B0aW9ucyBPYmplY3Qgd2l0aCBwcm9wZXJ0aWVzIC8gc2V0dGluZ3MgcmVsYXRlZCB0byBjb25uZWN0aW9uIHdpdGggdGhlIHNlcnZlci5cbiAqIEBjb25zdHJ1Y3RvclxuICovXG5mdW5jdGlvbiBKaXRzaUNvbm5lY3Rpb24oYXBwSUQsIHRva2VuLCBvcHRpb25zKSB7XG4gICAgdGhpcy5hcHBJRCA9IGFwcElEO1xuICAgIHRoaXMudG9rZW4gPSB0b2tlbjtcbiAgICB0aGlzLm9wdGlvbnMgPSBvcHRpb25zO1xuICAgIHRoaXMueG1wcCA9IG5ldyBYTVBQKG9wdGlvbnMpO1xuICAgIHRoaXMuY29uZmVyZW5jZXMgPSB7fTtcbn1cblxuLyoqXG4gKiBDb25uZWN0IHRoZSBjbGllbnQgd2l0aCB0aGUgc2VydmVyLlxuICogQHBhcmFtIG9wdGlvbnMge29iamVjdH0gY29ubmVjdGluZyBvcHRpb25zIChmb3IgZXhhbXBsZSBhdXRoZW50aWNhdGlvbnMgcGFyYW1ldGVycykuXG4gKi9cbkppdHNpQ29ubmVjdGlvbi5wcm90b3R5cGUuY29ubmVjdCA9IGZ1bmN0aW9uIChvcHRpb25zKSB7XG4gICAgaWYoIW9wdGlvbnMpXG4gICAgICAgIG9wdGlvbnMgPSB7fTtcblxuICAgIHRoaXMueG1wcC5jb25uZWN0KG9wdGlvbnMuaWQsIG9wdGlvbnMucGFzc3dvcmQpO1xufVxuXG4vKipcbiAqIERpc2Nvbm5lY3QgdGhlIGNsaWVudCBmcm9tIHRoZSBzZXJ2ZXIuXG4gKi9cbkppdHNpQ29ubmVjdGlvbi5wcm90b3R5cGUuZGlzY29ubmVjdCA9IGZ1bmN0aW9uICgpIHtcbiAgICB0aGlzLnhtcHAuZGlzY29ubmVjdCgpO1xufVxuXG4vKipcbiAqIFRoaXMgbWV0aG9kIGFsbG93cyByZW5ld2FsIG9mIHRoZSB0b2tlbnMgaWYgdGhleSBhcmUgZXhwaXJpbmcuXG4gKiBAcGFyYW0gdG9rZW4gdGhlIG5ldyB0b2tlbi5cbiAqL1xuSml0c2lDb25uZWN0aW9uLnByb3RvdHlwZS5zZXRUb2tlbiA9IGZ1bmN0aW9uICh0b2tlbikge1xuICAgIHRoaXMudG9rZW4gPSB0b2tlbjtcbn1cblxuLyoqXG4gKiBDcmVhdGVzIGFuZCBqb2lucyBuZXcgY29uZmVyZW5jZS5cbiAqIEBwYXJhbSBuYW1lIHRoZSBuYW1lIG9mIHRoZSBjb25mZXJlbmNlOyBpZiBudWxsIC0gYSBnZW5lcmF0ZWQgbmFtZSB3aWxsIGJlIHByb3ZpZGVkIGZyb20gdGhlIGFwaVxuICogQHBhcmFtIG9wdGlvbnMgT2JqZWN0IHdpdGggcHJvcGVydGllcyAvIHNldHRpbmdzIHJlbGF0ZWQgdG8gdGhlIGNvbmZlcmVuY2UgdGhhdCB3aWxsIGJlIGNyZWF0ZWQuXG4gKiBAcmV0dXJucyB7Sml0c2lDb25mZXJlbmNlfSByZXR1cm5zIHRoZSBuZXcgY29uZmVyZW5jZSBvYmplY3QuXG4gKi9cbkppdHNpQ29ubmVjdGlvbi5wcm90b3R5cGUuaW5pdEppdHNpQ29uZmVyZW5jZSA9IGZ1bmN0aW9uIChuYW1lLCBvcHRpb25zKSB7XG4gICAgdGhpcy5jb25mZXJlbmNlc1tuYW1lXSA9IG5ldyBKaXRzaUNvbmZlcmVuY2Uoe25hbWU6IG5hbWUsIGNvbmZpZzogb3B0aW9ucywgY29ubmVjdGlvbjogdGhpc30pO1xuICAgIHJldHVybiB0aGlzLmNvbmZlcmVuY2VzW25hbWVdO1xufVxuXG4vKipcbiAqIFN1YnNjcmliZXMgdGhlIHBhc3NlZCBsaXN0ZW5lciB0byB0aGUgZXZlbnQuXG4gKiBAcGFyYW0gZXZlbnQge0ppdHNpQ29ubmVjdGlvbkV2ZW50c30gdGhlIGNvbm5lY3Rpb24gZXZlbnQuXG4gKiBAcGFyYW0gbGlzdGVuZXIge0Z1bmN0aW9ufSB0aGUgZnVuY3Rpb24gdGhhdCB3aWxsIHJlY2VpdmUgdGhlIGV2ZW50XG4gKi9cbkppdHNpQ29ubmVjdGlvbi5wcm90b3R5cGUuYWRkRXZlbnRMaXN0ZW5lciA9IGZ1bmN0aW9uIChldmVudCwgbGlzdGVuZXIpIHtcbiAgICB0aGlzLnhtcHAuYWRkTGlzdGVuZXIoZXZlbnQsIGxpc3RlbmVyKTtcbn1cblxuLyoqXG4gKiBVbnN1YnNjcmliZXMgdGhlIHBhc3NlZCBoYW5kbGVyLlxuICogQHBhcmFtIGV2ZW50IHtKaXRzaUNvbm5lY3Rpb25FdmVudHN9IHRoZSBjb25uZWN0aW9uIGV2ZW50LlxuICogQHBhcmFtIGxpc3RlbmVyIHtGdW5jdGlvbn0gdGhlIGZ1bmN0aW9uIHRoYXQgd2lsbCByZWNlaXZlIHRoZSBldmVudFxuICovXG5KaXRzaUNvbm5lY3Rpb24ucHJvdG90eXBlLnJlbW92ZUV2ZW50TGlzdGVuZXIgPSBmdW5jdGlvbiAoZXZlbnQsIGxpc3RlbmVyKSB7XG4gICAgdGhpcy54bXBwLnJlbW92ZUxpc3RlbmVyKGV2ZW50LCBsaXN0ZW5lcik7XG59XG5cbm1vZHVsZS5leHBvcnRzID0gSml0c2lDb25uZWN0aW9uO1xuIiwiLyoqXG4gKiBFbnVtZXJhdGlvbiB3aXRoIHRoZSBlcnJvcnMgZm9yIHRoZSBjb25uZWN0aW9uLlxuICogQHR5cGUge3tzdHJpbmc6IHN0cmluZ319XG4gKi9cbnZhciBKaXRzaUNvbm5lY3Rpb25FcnJvcnMgPSB7XG4gICAgLyoqXG4gICAgICogSW5kaWNhdGVzIHRoYXQgYSBwYXNzd29yZCBpcyByZXF1aXJlZCBpbiBvcmRlciB0byBqb2luIHRoZSBjb25mZXJlbmNlLlxuICAgICAqL1xuICAgIFBBU1NXT1JEX1JFUVVJUkVEOiBcImNvbm5lY3Rpb24ucGFzc3dvcmRSZXF1aXJlZFwiLFxuICAgIC8qKlxuICAgICAqIEluZGljYXRlcyB0aGF0IGEgY29ubmVjdGlvbiBlcnJvciBvY2N1cnJlZCB3aGVuIHRyeWluZyB0byBqb2luIGFcbiAgICAgKiBjb25mZXJlbmNlLlxuICAgICAqL1xuICAgIENPTk5FQ1RJT05fRVJST1I6IFwiY29ubmVjdGlvbi5jb25uZWN0aW9uRXJyb3JcIixcbiAgICAvKipcbiAgICAgKiBOb3Qgc3BlY2lmaWVkIGVycm9ycy5cbiAgICAgKi9cbiAgICBPVEhFUl9FUlJPUjogXCJjb25uZWN0aW9uLm90aGVyRXJyb3JcIlxufTtcblxubW9kdWxlLmV4cG9ydHMgPSBKaXRzaUNvbm5lY3Rpb25FcnJvcnM7XG4iLCIvKipcbiAqIEVudW1lcmF0aW9uIHdpdGggdGhlIGV2ZW50cyBmb3IgdGhlIGNvbm5lY3Rpb24uXG4gKiBAdHlwZSB7e3N0cmluZzogc3RyaW5nfX1cbiAqL1xudmFyIEppdHNpQ29ubm5lY3Rpb25FdmVudHMgPSB7XG4gICAgLyoqXG4gICAgICogSW5kaWNhdGVzIHRoYXQgdGhlIGNvbm5lY3Rpb24gaGFzIGJlZW4gZmFpbGVkIGZvciBzb21lIHJlYXNvbi5cbiAgICAgKi9cbiAgICBDT05ORUNUSU9OX0ZBSUxFRDogXCJjb25uZWN0aW9uLmNvbm5lY3Rpb25GYWlsZWRcIixcbiAgICAvKipcbiAgICAgKiBJbmRpY2F0ZXMgdGhhdCB0aGUgY29ubmVjdGlvbiBoYXMgYmVlbiBlc3RhYmxpc2hlZC5cbiAgICAgKi9cbiAgICBDT05ORUNUSU9OX0VTVEFCTElTSEVEOiBcImNvbm5lY3Rpb24uY29ubmVjdGlvbkVzdGFibGlzaGVkXCIsXG4gICAgLyoqXG4gICAgICogSW5kaWNhdGVzIHRoYXQgdGhlIGNvbm5lY3Rpb24gaGFzIGJlZW4gZGlzY29ubmVjdGVkLlxuICAgICAqL1xuICAgIENPTk5FQ1RJT05fRElTQ09OTkVDVEVEOiBcImNvbm5lY3Rpb24uY29ubmVjdGlvbkRpc2Nvbm5lY3RlZFwiLFxuICAgIC8qKlxuICAgICAqIEluZGljYXRlcyB0aGF0IHRoZSBwZXJmb21lZCBhY3Rpb24gY2Fubm90IGJlIGV4ZWN1dGVkIGJlY2F1c2UgdGhlXG4gICAgICogY29ubmVjdGlvbiBpcyBub3QgaW4gdGhlIGNvcnJlY3Qgc3RhdGUoY29ubmVjdGVkLCBkaXNjb25uZWN0ZWQsIGV0Yy4pXG4gICAgICovXG4gICAgV1JPTkdfU1RBVEU6IFwiY29ubmVjdGlvbi53cm9uZ1N0YXRlXCJcbn07XG5cbm1vZHVsZS5leHBvcnRzID0gSml0c2lDb25ubmVjdGlvbkV2ZW50cztcbiIsInZhciBKaXRzaUNvbm5lY3Rpb24gPSByZXF1aXJlKFwiLi9KaXRzaUNvbm5lY3Rpb25cIik7XG52YXIgSml0c2lDb25mZXJlbmNlRXZlbnRzID0gcmVxdWlyZShcIi4vSml0c2lDb25mZXJlbmNlRXZlbnRzXCIpO1xudmFyIEppdHNpQ29ubmVjdGlvbkV2ZW50cyA9IHJlcXVpcmUoXCIuL0ppdHNpQ29ubmVjdGlvbkV2ZW50c1wiKTtcbnZhciBKaXRzaUNvbm5lY3Rpb25FcnJvcnMgPSByZXF1aXJlKFwiLi9KaXRzaUNvbm5lY3Rpb25FcnJvcnNcIik7XG52YXIgSml0c2lDb25mZXJlbmNlRXJyb3JzID0gcmVxdWlyZShcIi4vSml0c2lDb25mZXJlbmNlRXJyb3JzXCIpO1xudmFyIEppdHNpVHJhY2tFdmVudHMgPSByZXF1aXJlKFwiLi9KaXRzaVRyYWNrRXZlbnRzXCIpO1xudmFyIEppdHNpVHJhY2tFcnJvcnMgPSByZXF1aXJlKFwiLi9KaXRzaVRyYWNrRXJyb3JzXCIpO1xudmFyIExvZ2dlciA9IHJlcXVpcmUoXCJqaXRzaS1tZWV0LWxvZ2dlclwiKTtcbnZhciBSVEMgPSByZXF1aXJlKFwiLi9tb2R1bGVzL1JUQy9SVENcIik7XG52YXIgU3RhdGlzdGljcyA9IHJlcXVpcmUoXCIuL21vZHVsZXMvc3RhdGlzdGljcy9zdGF0aXN0aWNzXCIpO1xuXG4vKipcbiAqIE5hbWVzcGFjZSBmb3IgdGhlIGludGVyZmFjZSBvZiBKaXRzaSBNZWV0IExpYnJhcnkuXG4gKi9cbnZhciBMaWJKaXRzaU1lZXQgPSB7XG5cbiAgICBKaXRzaUNvbm5lY3Rpb246IEppdHNpQ29ubmVjdGlvbixcbiAgICBldmVudHM6IHtcbiAgICAgICAgY29uZmVyZW5jZTogSml0c2lDb25mZXJlbmNlRXZlbnRzLFxuICAgICAgICBjb25uZWN0aW9uOiBKaXRzaUNvbm5lY3Rpb25FdmVudHMsXG4gICAgICAgIHRyYWNrOiBKaXRzaVRyYWNrRXZlbnRzXG4gICAgfSxcbiAgICBlcnJvcnM6IHtcbiAgICAgICAgY29uZmVyZW5jZTogSml0c2lDb25mZXJlbmNlRXJyb3JzLFxuICAgICAgICBjb25uZWN0aW9uOiBKaXRzaUNvbm5lY3Rpb25FcnJvcnMsXG4gICAgICAgIHRyYWNrOiBKaXRzaVRyYWNrRXJyb3JzXG4gICAgfSxcbiAgICBsb2dMZXZlbHM6IExvZ2dlci5sZXZlbHMsXG4gICAgaW5pdDogZnVuY3Rpb24gKG9wdGlvbnMpIHtcbiAgICAgICAgcmV0dXJuIFJUQy5pbml0KG9wdGlvbnMgfHwge30pO1xuICAgIH0sXG4gICAgLyoqXG4gICAgICogUmV0dXJucyB3aGV0aGVyIHRoZSBkZXNrdG9wIHNoYXJpbmcgaXMgZW5hYmxlZCBvciBub3QuXG4gICAgICogQHJldHVybnMge2Jvb2xlYW59XG4gICAgICovXG4gICAgaXNEZXNrdG9wU2hhcmluZ0VuYWJsZWQ6IGZ1bmN0aW9uICgpIHtcbiAgICAgICAgcmV0dXJuIFJUQy5pc0Rlc2t0b3BTaGFyaW5nRW5hYmxlZCgpO1xuICAgIH0sXG4gICAgc2V0TG9nTGV2ZWw6IGZ1bmN0aW9uIChsZXZlbCkge1xuICAgICAgICBMb2dnZXIuc2V0TG9nTGV2ZWwobGV2ZWwpO1xuICAgIH0sXG4gICAgLyoqXG4gICAgICogQ3JlYXRlcyB0aGUgbWVkaWEgdHJhY2tzIGFuZCByZXR1cm5zIHRoZW0gdHJvdWdoIHRoZSBjYWxsYmFjay5cbiAgICAgKiBAcGFyYW0gb3B0aW9ucyBPYmplY3Qgd2l0aCBwcm9wZXJ0aWVzIC8gc2V0dGluZ3Mgc3BlY2lmeWluZyB0aGUgdHJhY2tzIHdoaWNoIHNob3VsZCBiZSBjcmVhdGVkLlxuICAgICAqIHNob3VsZCBiZSBjcmVhdGVkIG9yIHNvbWUgYWRkaXRpb25hbCBjb25maWd1cmF0aW9ucyBhYm91dCByZXNvbHV0aW9uIGZvciBleGFtcGxlLlxuICAgICAqIEBwYXJhbSB7QXJyYXl9IG9wdGlvbnMuZGV2aWNlcyB0aGUgZGV2aWNlcyB0aGF0IHdpbGwgYmUgcmVxdWVzdGVkXG4gICAgICogQHBhcmFtIHtzdHJpbmd9IG9wdGlvbnMucmVzb2x1dGlvbiByZXNvbHV0aW9uIGNvbnN0cmFpbnRzXG4gICAgICogQHBhcmFtIHtib29sfSBvcHRpb25zLmRvbnRDcmVhdGVKaXRzaVRyYWNrIGlmIDx0dD50cnVlPC90dD4gb2JqZWN0cyB3aXRoIHRoZSBmb2xsb3dpbmcgc3RydWN0dXJlIHtzdHJlYW06IHRoZSBNZWRpYSBTdHJlYW0sXG4gICAgICogdHlwZTogXCJhdWRpb1wiIG9yIFwidmlkZW9cIiwgdmlkZW9UeXBlOiBcImNhbWVyYVwiIG9yIFwiZGVza3RvcFwifVxuICAgICAqIHdpbGwgYmUgcmV0dXJuZWQgdHJvdWdoIHRoZSBQcm9taXNlLCBvdGhlcndpc2UgSml0c2lUcmFjayBvYmplY3RzIHdpbGwgYmUgcmV0dXJuZWQuXG4gICAgICogQHBhcmFtIHtzdHJpbmd9IG9wdGlvbnMuY2FtZXJhRGV2aWNlSWRcbiAgICAgKiBAcGFyYW0ge3N0cmluZ30gb3B0aW9ucy5taWNEZXZpY2VJZFxuICAgICAqIEByZXR1cm5zIHtQcm9taXNlLjx7QXJyYXkuPEppdHNpVHJhY2s+fSwgSml0c2lDb25mZXJlbmNlRXJyb3I+fVxuICAgICAqICAgICBBIHByb21pc2UgdGhhdCByZXR1cm5zIGFuIGFycmF5IG9mIGNyZWF0ZWQgSml0c2lUcmFja3MgaWYgcmVzb2x2ZWQsXG4gICAgICogICAgIG9yIGEgSml0c2lDb25mZXJlbmNlRXJyb3IgaWYgcmVqZWN0ZWQuXG4gICAgICovXG4gICAgY3JlYXRlTG9jYWxUcmFja3M6IGZ1bmN0aW9uIChvcHRpb25zKSB7XG4gICAgICAgIHJldHVybiBSVEMub2J0YWluQXVkaW9BbmRWaWRlb1Blcm1pc3Npb25zKG9wdGlvbnMgfHwge30pLnRoZW4oXG4gICAgICAgICAgICBmdW5jdGlvbih0cmFja3MpIHtcbiAgICAgICAgICAgICAgICBpZighUlRDLm9wdGlvbnMuZGlzYWJsZUF1ZGlvTGV2ZWxzKVxuICAgICAgICAgICAgICAgICAgICBmb3IodmFyIGkgPSAwOyBpIDwgdHJhY2tzLmxlbmd0aDsgaSsrKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICB2YXIgdHJhY2sgPSB0cmFja3NbaV07XG4gICAgICAgICAgICAgICAgICAgICAgICB2YXIgbVN0cmVhbSA9IHRyYWNrLmdldE9yaWdpbmFsU3RyZWFtKCk7XG4gICAgICAgICAgICAgICAgICAgICAgICBpZih0cmFjay5nZXRUeXBlKCkgPT09IFwiYXVkaW9cIil7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgU3RhdGlzdGljcy5zdGFydExvY2FsU3RhdHMobVN0cmVhbSxcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgdHJhY2suc2V0QXVkaW9MZXZlbC5iaW5kKHRyYWNrKSk7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgdHJhY2suYWRkRXZlbnRMaXN0ZW5lcihcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgSml0c2lUcmFja0V2ZW50cy5UUkFDS19TVE9QUEVELFxuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBmdW5jdGlvbigpe1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgU3RhdGlzdGljcy5zdG9wTG9jYWxTdGF0cyhtU3RyZWFtKTtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgfSk7XG4gICAgICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICByZXR1cm4gdHJhY2tzO1xuICAgICAgICAgICAgfSk7XG4gICAgfSxcbiAgICAvKipcbiAgICAgKiBDaGVja3MgaWYgaXRzIHBvc3NpYmxlIHRvIGVudW1lcmF0ZSBhdmFpbGFibGUgY2FtZXJhcy9taWNyb3BvbmVzLlxuICAgICAqIEByZXR1cm5zIHtib29sZWFufSB0cnVlIGlmIGF2YWlsYWJsZSwgZmFsc2Ugb3RoZXJ3aXNlLlxuICAgICAqL1xuICAgIGlzRGV2aWNlTGlzdEF2YWlsYWJsZTogZnVuY3Rpb24gKCkge1xuICAgICAgICByZXR1cm4gUlRDLmlzRGV2aWNlTGlzdEF2YWlsYWJsZSgpO1xuICAgIH0sXG4gICAgLyoqXG4gICAgICogUmV0dXJucyB0cnVlIGlmIGNoYW5naW5nIHRoZSBjYW1lcmEgLyBtaWNyb3Bob25lIGRldmljZSBpcyBzdXBwb3J0ZWQgYW5kXG4gICAgICogZmFsc2UgaWYgbm90LlxuICAgICAqIEByZXR1cm5zIHtib29sZWFufSB0cnVlIGlmIGF2YWlsYWJsZSwgZmFsc2Ugb3RoZXJ3aXNlLlxuICAgICAqL1xuICAgIGlzRGV2aWNlQ2hhbmdlQXZhaWxhYmxlOiBmdW5jdGlvbiAoKSB7XG4gICAgICAgIHJldHVybiBSVEMuaXNEZXZpY2VDaGFuZ2VBdmFpbGFibGUoKTtcbiAgICB9LFxuICAgIGVudW1lcmF0ZURldmljZXM6IGZ1bmN0aW9uIChjYWxsYmFjaykge1xuICAgICAgICBSVEMuZW51bWVyYXRlRGV2aWNlcyhjYWxsYmFjayk7XG4gICAgfVxufTtcblxucmVxdWlyZShcImVzNi1wcm9taXNlXCIpLnBvbHlmaWxsKClcbi8vU2V0dXBzIHRoZSBwcm9taXNlIG9iamVjdC5cbndpbmRvdy5Qcm9taXNlID0gd2luZG93LlByb21pc2UgfHwgcmVxdWlyZShcImVzNi1wcm9taXNlXCIpLlByb21pc2U7XG5cbm1vZHVsZS5leHBvcnRzID0gTGliSml0c2lNZWV0O1xuIiwiLyogZ2xvYmFsIFN0cm9waGUgKi9cblxuLyoqXG4gKiBSZXByZXNlbnRzIGEgcGFydGljaXBhbnQgaW4gKGEgbWVtYmVyIG9mKSBhIGNvbmZlcmVuY2UuXG4gKi9cbmZ1bmN0aW9uIEppdHNpUGFydGljaXBhbnQoamlkLCBjb25mZXJlbmNlLCBkaXNwbGF5TmFtZSl7XG4gICAgdGhpcy5famlkID0gamlkO1xuICAgIHRoaXMuX2lkID0gU3Ryb3BoZS5nZXRSZXNvdXJjZUZyb21KaWQoamlkKTtcbiAgICB0aGlzLl9jb25mZXJlbmNlID0gY29uZmVyZW5jZTtcbiAgICB0aGlzLl9kaXNwbGF5TmFtZSA9IGRpc3BsYXlOYW1lO1xuICAgIHRoaXMuX3N1cHBvcnRzRFRNRiA9IGZhbHNlO1xuICAgIHRoaXMuX3RyYWNrcyA9IFtdO1xuICAgIHRoaXMuX3JvbGUgPSAnbm9uZSc7XG59XG5cbi8qKlxuICogQHJldHVybnMge0ppdHNpQ29uZmVyZW5jZX0gVGhlIGNvbmZlcmVuY2UgdGhhdCB0aGlzIHBhcnRpY2lwYW50IGJlbG9uZ3MgdG8uXG4gKi9cbkppdHNpUGFydGljaXBhbnQucHJvdG90eXBlLmdldENvbmZlcmVuY2UgPSBmdW5jdGlvbigpIHtcbiAgICByZXR1cm4gdGhpcy5fY29uZmVyZW5jZTtcbn07XG5cbi8qKlxuICogQHJldHVybnMge0FycmF5LjxKaXRzaVRyYWNrPn0gVGhlIGxpc3Qgb2YgbWVkaWEgdHJhY2tzIGZvciB0aGlzIHBhcnRpY2lwYW50LlxuICovXG5KaXRzaVBhcnRpY2lwYW50LnByb3RvdHlwZS5nZXRUcmFja3MgPSBmdW5jdGlvbigpIHtcbiAgICByZXR1cm4gdGhpcy5fdHJhY2tzO1xufTtcblxuLyoqXG4gKiBAcmV0dXJucyB7U3RyaW5nfSBUaGUgSUQgb2YgdGhpcyBwYXJ0aWNpcGFudC5cbiAqL1xuSml0c2lQYXJ0aWNpcGFudC5wcm90b3R5cGUuZ2V0SWQgPSBmdW5jdGlvbigpIHtcbiAgICByZXR1cm4gdGhpcy5faWQ7XG59O1xuXG4vKipcbiAqIEByZXR1cm5zIHtTdHJpbmd9IFRoZSBKSUQgb2YgdGhpcyBwYXJ0aWNpcGFudC5cbiAqL1xuSml0c2lQYXJ0aWNpcGFudC5wcm90b3R5cGUuZ2V0SmlkID0gZnVuY3Rpb24oKSB7XG4gICAgcmV0dXJuIHRoaXMuX2ppZDtcbn07XG5cbi8qKlxuICogQHJldHVybnMge1N0cmluZ30gVGhlIGh1bWFuLXJlYWRhYmxlIGRpc3BsYXkgbmFtZSBvZiB0aGlzIHBhcnRpY2lwYW50LlxuICovXG5KaXRzaVBhcnRpY2lwYW50LnByb3RvdHlwZS5nZXREaXNwbGF5TmFtZSA9IGZ1bmN0aW9uKCkge1xuICAgIHJldHVybiB0aGlzLl9kaXNwbGF5TmFtZTtcbn07XG5cbi8qKlxuICogQHJldHVybnMge0Jvb2xlYW59IFdoZXRoZXIgdGhpcyBwYXJ0aWNpcGFudCBpcyBhIG1vZGVyYXRvciBvciBub3QuXG4gKi9cbkppdHNpUGFydGljaXBhbnQucHJvdG90eXBlLmlzTW9kZXJhdG9yID0gZnVuY3Rpb24oKSB7XG4gICAgcmV0dXJuIHRoaXMuX3JvbGUgPT09ICdtb2RlcmF0b3InO1xufTtcblxuLy8gR2V0cyBhIGxpbmsgdG8gYW4gZXRoZXJwYWQgaW5zdGFuY2UgYWR2ZXJ0aXNlZCBieSB0aGUgcGFydGljaXBhbnQ/XG4vL0ppdHNpUGFydGljaXBhbnQucHJvdG90eXBlLmdldEV0aGVycGFkID0gZnVuY3Rpb24oKSB7XG4vL1xuLy99XG5cblxuLypcbiAqIEByZXR1cm5zIHtCb29sZWFufSBXaGV0aGVyIHRoaXMgcGFydGljaXBhbnQgaGFzIG11dGVkIHRoZWlyIGF1ZGlvLlxuICovXG5KaXRzaVBhcnRpY2lwYW50LnByb3RvdHlwZS5pc0F1ZGlvTXV0ZWQgPSBmdW5jdGlvbigpIHtcbiAgICByZXR1cm4gdGhpcy5nZXRUcmFja3MoKS5yZWR1Y2UoZnVuY3Rpb24gKHRyYWNrLCBpc0F1ZGlvTXV0ZWQpIHtcbiAgICAgICAgcmV0dXJuIGlzQXVkaW9NdXRlZCAmJiAodHJhY2suaXNWaWRlb1RyYWNrKCkgfHwgdHJhY2suaXNNdXRlZCgpKTtcbiAgICB9LCB0cnVlKTtcbn07XG5cbi8qXG4gKiBAcmV0dXJucyB7Qm9vbGVhbn0gV2hldGhlciB0aGlzIHBhcnRpY2lwYW50IGhhcyBtdXRlZCB0aGVpciB2aWRlby5cbiAqL1xuSml0c2lQYXJ0aWNpcGFudC5wcm90b3R5cGUuaXNWaWRlb011dGVkID0gZnVuY3Rpb24oKSB7XG4gICAgcmV0dXJuIHRoaXMuZ2V0VHJhY2tzKCkucmVkdWNlKGZ1bmN0aW9uICh0cmFjaywgaXNWaWRlb011dGVkKSB7XG4gICAgICAgIHJldHVybiBpc1ZpZGVvTXV0ZWQgJiYgKHRyYWNrLmlzQXVkaW9UcmFjaygpIHx8IHRyYWNrLmlzTXV0ZWQoKSk7XG4gICAgfSwgdHJ1ZSk7XG59O1xuXG4vKlxuICogQHJldHVybnMgez8/P30gVGhlIGxhdGVzdCBzdGF0aXN0aWNzIHJlcG9ydGVkIGJ5IHRoaXMgcGFydGljaXBhbnRcbiAqIChpLmUuIGluZm8gdXNlZCB0byBwb3B1bGF0ZSB0aGUgR1NNIGJhcnMpXG4gKiBUT0RPOiBkbyB3ZSBleHBvc2UgdGhpcyBvciBoYW5kbGUgaXQgaW50ZXJuYWxseT9cbiAqL1xuSml0c2lQYXJ0aWNpcGFudC5wcm90b3R5cGUuZ2V0TGF0ZXN0U3RhdHMgPSBmdW5jdGlvbigpIHtcblxufTtcblxuLyoqXG4gKiBAcmV0dXJucyB7U3RyaW5nfSBUaGUgcm9sZSBvZiB0aGlzIHBhcnRpY2lwYW50LlxuICovXG5KaXRzaVBhcnRpY2lwYW50LnByb3RvdHlwZS5nZXRSb2xlID0gZnVuY3Rpb24oKSB7XG4gICAgcmV0dXJuIHRoaXMuX3JvbGU7XG59O1xuXG4vKlxuICogQHJldHVybnMge0Jvb2xlYW59IFdoZXRoZXIgdGhpcyBwYXJ0aWNpcGFudCBpc1xuICogdGhlIGNvbmZlcmVuY2UgZm9jdXMgKGkuZS4gamljb2ZvKS5cbiAqL1xuSml0c2lQYXJ0aWNpcGFudC5wcm90b3R5cGUuaXNGb2N1cyA9IGZ1bmN0aW9uKCkge1xuXG59O1xuXG4vKlxuICogQHJldHVybnMge0Jvb2xlYW59IFdoZXRoZXIgdGhpcyBwYXJ0aWNpcGFudCBpc1xuICogYSBjb25mZXJlbmNlIHJlY29yZGVyIChpLmUuIGppcmVjb24pLlxuICovXG5KaXRzaVBhcnRpY2lwYW50LnByb3RvdHlwZS5pc1JlY29yZGVyID0gZnVuY3Rpb24oKSB7XG5cbn07XG5cbi8qXG4gKiBAcmV0dXJucyB7Qm9vbGVhbn0gV2hldGhlciB0aGlzIHBhcnRpY2lwYW50IGlzIGEgU0lQIGdhdGV3YXkgKGkuZS4gamlnYXNpKS5cbiAqL1xuSml0c2lQYXJ0aWNpcGFudC5wcm90b3R5cGUuaXNTaXBHYXRld2F5ID0gZnVuY3Rpb24oKSB7XG5cbn07XG5cbi8qKlxuICogQHJldHVybnMge0Jvb2xlYW59IFdoZXRoZXIgdGhpcyBwYXJ0aWNpcGFudFxuICogaXMgY3VycmVudGx5IHNoYXJpbmcgdGhlaXIgc2NyZWVuLlxuICovXG5KaXRzaVBhcnRpY2lwYW50LnByb3RvdHlwZS5pc1NjcmVlblNoYXJpbmcgPSBmdW5jdGlvbigpIHtcblxufTtcblxuLyoqXG4gKiBAcmV0dXJucyB7U3RyaW5nfSBUaGUgdXNlciBhZ2VudCBvZiB0aGlzIHBhcnRpY2lwYW50XG4gKiAoaS5lLiBicm93c2VyIHVzZXJBZ2VudCBzdHJpbmcpLlxuICovXG5KaXRzaVBhcnRpY2lwYW50LnByb3RvdHlwZS5nZXRVc2VyQWdlbnQgPSBmdW5jdGlvbigpIHtcblxufTtcblxuLyoqXG4gKiBLaWNrcyB0aGUgcGFydGljaXBhbnQgZnJvbSB0aGUgY29uZmVyZW5jZSAocmVxdWlyZXMgY2VydGFpbiBwcml2aWxlZ2VzKS5cbiAqL1xuSml0c2lQYXJ0aWNpcGFudC5wcm90b3R5cGUua2ljayA9IGZ1bmN0aW9uKCkge1xuXG59O1xuXG4vKipcbiAqIEFza3MgdGhpcyBwYXJ0aWNpcGFudCB0byBtdXRlIHRoZW1zZWx2ZXMuXG4gKi9cbkppdHNpUGFydGljaXBhbnQucHJvdG90eXBlLmFza1RvTXV0ZSA9IGZ1bmN0aW9uKCkge1xuXG59O1xuXG5KaXRzaVBhcnRpY2lwYW50LnByb3RvdHlwZS5zdXBwb3J0c0RUTUYgPSBmdW5jdGlvbiAoKSB7XG4gICAgcmV0dXJuIHRoaXMuX3N1cHBvcnRzRFRNRjtcbn07XG5cblxubW9kdWxlLmV4cG9ydHMgPSBKaXRzaVBhcnRpY2lwYW50O1xuIiwibW9kdWxlLmV4cG9ydHMgPSB7XG4gICAgLyoqXG4gICAgICogUmV0dXJucyBKaXRzaVRyYWNrRXJyb3JzIGJhc2VkIG9uIHRoZSBlcnJvciBvYmplY3QgcGFzc2VkIGJ5IEdVTVxuICAgICAqIEBwYXJhbSBlcnJvciB0aGUgZXJyb3JcbiAgICAgKiBAcGFyYW0ge09iamVjdH0gb3B0aW9ucyB0aGUgb3B0aW9ucyBvYmplY3QgZ2l2ZW4gdG8gR1VNLlxuICAgICAqL1xuICAgIHBhcnNlRXJyb3I6IGZ1bmN0aW9uIChlcnJvciwgb3B0aW9ucykge1xuICAgICAgICBvcHRpb25zID0gb3B0aW9ucyB8fCB7fTtcbiAgICAgICAgaWYgKHR5cGVvZiBlcnJvciA9PSBcIm9iamVjdFwiICYmIGVycm9yLmNvbnN0cmFpbnROYW1lICYmIGVycm9yLm5hbWVcbiAgICAgICAgICAgICYmIChlcnJvci5uYW1lID09IFwiQ29uc3RyYWludE5vdFNhdGlzZmllZEVycm9yXCIgfHxcbiAgICAgICAgICAgIGVycm9yLm5hbWUgPT0gXCJPdmVyY29uc3RyYWluZWRFcnJvclwiKSAmJlxuICAgICAgICAgICAgKGVycm9yLmNvbnN0cmFpbnROYW1lID09IFwibWluV2lkdGhcIiB8fFxuICAgICAgICAgICAgZXJyb3IuY29uc3RyYWludE5hbWUgPT0gXCJtYXhXaWR0aFwiIHx8XG4gICAgICAgICAgICBlcnJvci5jb25zdHJhaW50TmFtZSA9PSBcIm1pbkhlaWdodFwiIHx8XG4gICAgICAgICAgICBlcnJvci5jb25zdHJhaW50TmFtZSA9PSBcIm1heEhlaWdodFwiKSAmJlxuICAgICAgICAgICAgb3B0aW9ucy5kZXZpY2VzLmluZGV4T2YoXCJ2aWRlb1wiKSAhPT0gLTEpIHtcbiAgICAgICAgICAgICAgICByZXR1cm4gdGhpcy5VTlNVUFBPUlRFRF9SRVNPTFVUSU9OO1xuICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgcmV0dXJuIHRoaXMuR0VORVJBTDtcbiAgICAgICAgfVxuICAgIH0sXG4gICAgVU5TVVBQT1JURURfUkVTT0xVVElPTjogXCJndW0udW5zdXBwb3J0ZWRfcmVzb2x1dGlvblwiLFxuICAgIEdFTkVSQUw6IFwiZ3VtLmdlbmVyYWxcIlxufTtcbiIsInZhciBKaXRzaVRyYWNrRXZlbnRzID0ge1xuICAgIC8qKlxuICAgICAqIEEgbWVkaWEgdHJhY2sgbXV0ZSBzdGF0dXMgd2FzIGNoYW5nZWQuXG4gICAgICovXG4gICAgVFJBQ0tfTVVURV9DSEFOR0VEOiBcInRyYWNrLnRyYWNrTXV0ZUNoYW5nZWRcIixcbiAgICAvKipcbiAgICAgKiBBdWRpbyBsZXZlbHMgb2YgYSB0aGlzIHRyYWNrIHdhcyBjaGFuZ2VkLlxuICAgICAqL1xuICAgIFRSQUNLX0FVRElPX0xFVkVMX0NIQU5HRUQ6IFwidHJhY2suYXVkaW9MZXZlbHNDaGFuZ2VkXCIsXG4gICAgLyoqXG4gICAgICogVGhlIG1lZGlhIHRyYWNrIHdhcyByZW1vdmVkIHRvIHRoZSBjb25mZXJlbmNlLlxuICAgICAqL1xuICAgIFRSQUNLX1NUT1BQRUQ6IFwidHJhY2suc3RvcHBlZFwiXG59O1xuXG5tb2R1bGUuZXhwb3J0cyA9IEppdHNpVHJhY2tFdmVudHM7XG4iLCJ2YXIgbG9nZ2VyID0gcmVxdWlyZShcImppdHNpLW1lZXQtbG9nZ2VyXCIpLmdldExvZ2dlcihfX2ZpbGVuYW1lKTtcblxuZnVuY3Rpb24gSml0c2lEVE1GTWFuYWdlciAobG9jYWxBdWRpbywgcGVlckNvbm5lY3Rpb24pIHtcbiAgICB2YXIgdHJhY2tzID0gbG9jYWxBdWRpby5fZ2V0VHJhY2tzKCk7XG4gICAgaWYgKCF0cmFja3MubGVuZ3RoKSB7XG4gICAgICAgIHRocm93IG5ldyBFcnJvcihcIkZhaWxlZCB0byBpbml0aWFsaXplIERUTUZTZW5kZXI6IG5vIGF1ZGlvIHRyYWNrLlwiKTtcbiAgICB9XG4gICAgdGhpcy5kdG1mU2VuZGVyID0gcGVlckNvbm5lY3Rpb24ucGVlcmNvbm5lY3Rpb24uY3JlYXRlRFRNRlNlbmRlcih0cmFja3NbMF0pO1xuICAgIGxvZ2dlci5kZWJ1ZyhcIkluaXRpYWxpemVkIERUTUZTZW5kZXJcIik7XG59XG5cblxuSml0c2lEVE1GTWFuYWdlci5wcm90b3R5cGUuc2VuZFRvbmVzID0gZnVuY3Rpb24gKHRvbmVzLCBkdXJhdGlvbiwgcGF1c2UpIHtcbiAgICB0aGlzLmR0bWZTZW5kZXIuaW5zZXJ0RFRNRih0b25lcywgKGR1cmF0aW9uIHx8IDIwMCksIChwYXVzZSB8fCAyMDApKTtcbn07XG4iLCIvKiBnbG9iYWwgY29uZmlnLCBBUFAsIFN0cm9waGUgKi9cblxuLy8gY2FjaGUgZGF0YWNoYW5uZWxzIHRvIGF2b2lkIGdhcmJhZ2UgY29sbGVjdGlvblxuLy8gaHR0cHM6Ly9jb2RlLmdvb2dsZS5jb20vcC9jaHJvbWl1bS9pc3N1ZXMvZGV0YWlsP2lkPTQwNTU0NVxuXG52YXIgbG9nZ2VyID0gcmVxdWlyZShcImppdHNpLW1lZXQtbG9nZ2VyXCIpLmdldExvZ2dlcihfX2ZpbGVuYW1lKTtcbnZhciBSVENFdmVudHMgPSByZXF1aXJlKFwiLi4vLi4vc2VydmljZS9SVEMvUlRDRXZlbnRzXCIpO1xuXG5cbi8qKlxuICogQmluZHMgXCJvbmRhdGFjaGFubmVsXCIgZXZlbnQgbGlzdGVuZXIgdG8gZ2l2ZW4gUGVlckNvbm5lY3Rpb24gaW5zdGFuY2UuXG4gKiBAcGFyYW0gcGVlckNvbm5lY3Rpb24gV2ViUlRDIHBlZXIgY29ubmVjdGlvbiBpbnN0YW5jZS5cbiAqL1xuZnVuY3Rpb24gRGF0YUNoYW5uZWxzKHBlZXJDb25uZWN0aW9uLCBlbWl0dGVyKSB7XG4gICAgcGVlckNvbm5lY3Rpb24ub25kYXRhY2hhbm5lbCA9IHRoaXMub25EYXRhQ2hhbm5lbC5iaW5kKHRoaXMpO1xuICAgIHRoaXMuZXZlbnRFbWl0dGVyID0gZW1pdHRlcjtcblxuICAgIHRoaXMuX2RhdGFDaGFubmVscyA9IFtdO1xuXG4gICAgLy8gU2FtcGxlIGNvZGUgZm9yIG9wZW5pbmcgbmV3IGRhdGEgY2hhbm5lbCBmcm9tIEppdHNpIE1lZXQgdG8gdGhlIGJyaWRnZS5cbiAgICAvLyBBbHRob3VnaCBpdCdzIG5vdCBhIHJlcXVpcmVtZW50IHRvIG9wZW4gc2VwYXJhdGUgY2hhbm5lbHMgZnJvbSBib3RoIGJyaWRnZVxuICAgIC8vIGFuZCBwZWVyIGFzIHNpbmdsZSBjaGFubmVsIGNhbiBiZSB1c2VkIGZvciBzZW5kaW5nIGFuZCByZWNlaXZpbmcgZGF0YS5cbiAgICAvLyBTbyBlaXRoZXIgY2hhbm5lbCBvcGVuZWQgYnkgdGhlIGJyaWRnZSBvciB0aGUgb25lIG9wZW5lZCBoZXJlIGlzIGVub3VnaFxuICAgIC8vIGZvciBjb21tdW5pY2F0aW9uIHdpdGggdGhlIGJyaWRnZS5cbiAgICAvKnZhciBkYXRhQ2hhbm5lbE9wdGlvbnMgPVxuICAgICB7XG4gICAgIHJlbGlhYmxlOiB0cnVlXG4gICAgIH07XG4gICAgIHZhciBkYXRhQ2hhbm5lbFxuICAgICA9IHBlZXJDb25uZWN0aW9uLmNyZWF0ZURhdGFDaGFubmVsKFwibXlDaGFubmVsXCIsIGRhdGFDaGFubmVsT3B0aW9ucyk7XG5cbiAgICAgLy8gQ2FuIGJlIHVzZWQgb25seSB3aGVuIGlzIGluIG9wZW4gc3RhdGVcbiAgICAgZGF0YUNoYW5uZWwub25vcGVuID0gZnVuY3Rpb24gKClcbiAgICAge1xuICAgICBkYXRhQ2hhbm5lbC5zZW5kKFwiTXkgY2hhbm5lbCAhISFcIik7XG4gICAgIH07XG4gICAgIGRhdGFDaGFubmVsLm9ubWVzc2FnZSA9IGZ1bmN0aW9uIChldmVudClcbiAgICAge1xuICAgICB2YXIgbXNnRGF0YSA9IGV2ZW50LmRhdGE7XG4gICAgIGxvZ2dlci5pbmZvKFwiR290IE15IERhdGEgQ2hhbm5lbCBNZXNzYWdlOlwiLCBtc2dEYXRhLCBkYXRhQ2hhbm5lbCk7XG4gICAgIH07Ki9cbn07XG5cblxuLyoqXG4gKiBDYWxsYmFjayB0cmlnZ2VyZWQgYnkgUGVlckNvbm5lY3Rpb24gd2hlbiBuZXcgZGF0YSBjaGFubmVsIGlzIG9wZW5lZFxuICogb24gdGhlIGJyaWRnZS5cbiAqIEBwYXJhbSBldmVudCB0aGUgZXZlbnQgaW5mbyBvYmplY3QuXG4gKi9cbkRhdGFDaGFubmVscy5wcm90b3R5cGUub25EYXRhQ2hhbm5lbCA9IGZ1bmN0aW9uIChldmVudCkge1xuICAgIHZhciBkYXRhQ2hhbm5lbCA9IGV2ZW50LmNoYW5uZWw7XG4gICAgdmFyIHNlbGYgPSB0aGlzO1xuXG4gICAgZGF0YUNoYW5uZWwub25vcGVuID0gZnVuY3Rpb24gKCkge1xuICAgICAgICBsb2dnZXIuaW5mbyhcIkRhdGEgY2hhbm5lbCBvcGVuZWQgYnkgdGhlIFZpZGVvYnJpZGdlIVwiLCBkYXRhQ2hhbm5lbCk7XG5cbiAgICAgICAgLy8gQ29kZSBzYW1wbGUgZm9yIHNlbmRpbmcgc3RyaW5nIGFuZC9vciBiaW5hcnkgZGF0YVxuICAgICAgICAvLyBTZW5kcyBTdHJpbmcgbWVzc2FnZSB0byB0aGUgYnJpZGdlXG4gICAgICAgIC8vZGF0YUNoYW5uZWwuc2VuZChcIkhlbGxvIGJyaWRnZSFcIik7XG4gICAgICAgIC8vIFNlbmRzIDEyIGJ5dGVzIGJpbmFyeSBtZXNzYWdlIHRvIHRoZSBicmlkZ2VcbiAgICAgICAgLy9kYXRhQ2hhbm5lbC5zZW5kKG5ldyBBcnJheUJ1ZmZlcigxMikpO1xuXG4gICAgICAgIHNlbGYuZXZlbnRFbWl0dGVyLmVtaXQoUlRDRXZlbnRzLkRBVEFfQ0hBTk5FTF9PUEVOKTtcbiAgICB9O1xuXG4gICAgZGF0YUNoYW5uZWwub25lcnJvciA9IGZ1bmN0aW9uIChlcnJvcikge1xuICAgICAgICBsb2dnZXIuZXJyb3IoXCJEYXRhIENoYW5uZWwgRXJyb3I6XCIsIGVycm9yLCBkYXRhQ2hhbm5lbCk7XG4gICAgfTtcblxuICAgIGRhdGFDaGFubmVsLm9ubWVzc2FnZSA9IGZ1bmN0aW9uIChldmVudCkge1xuICAgICAgICB2YXIgZGF0YSA9IGV2ZW50LmRhdGE7XG4gICAgICAgIC8vIEpTT05cbiAgICAgICAgdmFyIG9iajtcblxuICAgICAgICB0cnkge1xuICAgICAgICAgICAgb2JqID0gSlNPTi5wYXJzZShkYXRhKTtcbiAgICAgICAgfVxuICAgICAgICBjYXRjaCAoZSkge1xuICAgICAgICAgICAgbG9nZ2VyLmVycm9yKFxuICAgICAgICAgICAgICAgIFwiRmFpbGVkIHRvIHBhcnNlIGRhdGEgY2hhbm5lbCBtZXNzYWdlIGFzIEpTT046IFwiLFxuICAgICAgICAgICAgICAgIGRhdGEsXG4gICAgICAgICAgICAgICAgZGF0YUNoYW5uZWwpO1xuICAgICAgICB9XG4gICAgICAgIGlmICgoJ3VuZGVmaW5lZCcgIT09IHR5cGVvZihvYmopKSAmJiAobnVsbCAhPT0gb2JqKSkge1xuICAgICAgICAgICAgdmFyIGNvbGlicmlDbGFzcyA9IG9iai5jb2xpYnJpQ2xhc3M7XG5cbiAgICAgICAgICAgIGlmIChcIkRvbWluYW50U3BlYWtlckVuZHBvaW50Q2hhbmdlRXZlbnRcIiA9PT0gY29saWJyaUNsYXNzKSB7XG4gICAgICAgICAgICAgICAgLy8gRW5kcG9pbnQgSUQgZnJvbSB0aGUgVmlkZW9icmlkZ2UuXG4gICAgICAgICAgICAgICAgdmFyIGRvbWluYW50U3BlYWtlckVuZHBvaW50ID0gb2JqLmRvbWluYW50U3BlYWtlckVuZHBvaW50O1xuXG4gICAgICAgICAgICAgICAgbG9nZ2VyLmluZm8oXG4gICAgICAgICAgICAgICAgICAgIFwiRGF0YSBjaGFubmVsIG5ldyBkb21pbmFudCBzcGVha2VyIGV2ZW50OiBcIixcbiAgICAgICAgICAgICAgICAgICAgZG9taW5hbnRTcGVha2VyRW5kcG9pbnQpO1xuICAgICAgICAgICAgICAgIHNlbGYuZXZlbnRFbWl0dGVyLmVtaXQoUlRDRXZlbnRzLkRPTUlOQU5UU1BFQUtFUl9DSEFOR0VELCBkb21pbmFudFNwZWFrZXJFbmRwb2ludCk7XG4gICAgICAgICAgICB9XG4gICAgICAgICAgICBlbHNlIGlmIChcIkluTGFzdE5DaGFuZ2VFdmVudFwiID09PSBjb2xpYnJpQ2xhc3MpIHtcbiAgICAgICAgICAgICAgICB2YXIgb2xkVmFsdWUgPSBvYmoub2xkVmFsdWU7XG4gICAgICAgICAgICAgICAgdmFyIG5ld1ZhbHVlID0gb2JqLm5ld1ZhbHVlO1xuICAgICAgICAgICAgICAgIC8vIE1ha2Ugc3VyZSB0aGF0IG9sZFZhbHVlIGFuZCBuZXdWYWx1ZSBhcmUgb2YgdHlwZSBib29sZWFuLlxuICAgICAgICAgICAgICAgIHZhciB0eXBlO1xuXG4gICAgICAgICAgICAgICAgaWYgKCh0eXBlID0gdHlwZW9mIG9sZFZhbHVlKSAhPT0gJ2Jvb2xlYW4nKSB7XG4gICAgICAgICAgICAgICAgICAgIGlmICh0eXBlID09PSAnc3RyaW5nJykge1xuICAgICAgICAgICAgICAgICAgICAgICAgb2xkVmFsdWUgPSAob2xkVmFsdWUgPT0gXCJ0cnVlXCIpO1xuICAgICAgICAgICAgICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgICAgICAgICAgICAgb2xkVmFsdWUgPSBuZXcgQm9vbGVhbihvbGRWYWx1ZSkudmFsdWVPZigpO1xuICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgIGlmICgodHlwZSA9IHR5cGVvZiBuZXdWYWx1ZSkgIT09ICdib29sZWFuJykge1xuICAgICAgICAgICAgICAgICAgICBpZiAodHlwZSA9PT0gJ3N0cmluZycpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgIG5ld1ZhbHVlID0gKG5ld1ZhbHVlID09IFwidHJ1ZVwiKTtcbiAgICAgICAgICAgICAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgICAgICAgICAgICAgIG5ld1ZhbHVlID0gbmV3IEJvb2xlYW4obmV3VmFsdWUpLnZhbHVlT2YoKTtcbiAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgICAgIHNlbGYuZXZlbnRFbWl0dGVyLmVtaXQoUlRDRXZlbnRzLkxBU1ROX0NIQU5HRUQsIG9sZFZhbHVlLCBuZXdWYWx1ZSk7XG4gICAgICAgICAgICB9XG4gICAgICAgICAgICBlbHNlIGlmIChcIkxhc3RORW5kcG9pbnRzQ2hhbmdlRXZlbnRcIiA9PT0gY29saWJyaUNsYXNzKSB7XG4gICAgICAgICAgICAgICAgLy8gVGhlIG5ldy9sYXRlc3QgbGlzdCBvZiBsYXN0LW4gZW5kcG9pbnQgSURzLlxuICAgICAgICAgICAgICAgIHZhciBsYXN0TkVuZHBvaW50cyA9IG9iai5sYXN0TkVuZHBvaW50cztcbiAgICAgICAgICAgICAgICAvLyBUaGUgbGlzdCBvZiBlbmRwb2ludCBJRHMgd2hpY2ggYXJlIGVudGVyaW5nIHRoZSBsaXN0IG9mXG4gICAgICAgICAgICAgICAgLy8gbGFzdC1uIGF0IHRoaXMgdGltZSBpLmUuIHdlcmUgbm90IGluIHRoZSBvbGQgbGlzdCBvZiBsYXN0LW5cbiAgICAgICAgICAgICAgICAvLyBlbmRwb2ludCBJRHMuXG4gICAgICAgICAgICAgICAgdmFyIGVuZHBvaW50c0VudGVyaW5nTGFzdE4gPSBvYmouZW5kcG9pbnRzRW50ZXJpbmdMYXN0TjtcblxuICAgICAgICAgICAgICAgIGxvZ2dlci5pbmZvKFxuICAgICAgICAgICAgICAgICAgICBcIkRhdGEgY2hhbm5lbCBuZXcgbGFzdC1uIGV2ZW50OiBcIixcbiAgICAgICAgICAgICAgICAgICAgbGFzdE5FbmRwb2ludHMsIGVuZHBvaW50c0VudGVyaW5nTGFzdE4sIG9iaik7XG4gICAgICAgICAgICAgICAgc2VsZi5ldmVudEVtaXR0ZXIuZW1pdChSVENFdmVudHMuTEFTVE5fRU5EUE9JTlRfQ0hBTkdFRCxcbiAgICAgICAgICAgICAgICAgICAgbGFzdE5FbmRwb2ludHMsIGVuZHBvaW50c0VudGVyaW5nTGFzdE4sIG9iaik7XG4gICAgICAgICAgICB9XG4gICAgICAgICAgICBlbHNlIHtcbiAgICAgICAgICAgICAgICBsb2dnZXIuZGVidWcoXCJEYXRhIGNoYW5uZWwgSlNPTi1mb3JtYXR0ZWQgbWVzc2FnZTogXCIsIG9iaik7XG4gICAgICAgICAgICAgICAgLy8gVGhlIHJlY2VpdmVkIG1lc3NhZ2UgYXBwZWFycyB0byBiZSBhcHByb3ByaWF0ZWx5IGZvcm1hdHRlZFxuICAgICAgICAgICAgICAgIC8vIChpLmUuIGlzIGEgSlNPTiBvYmplY3Qgd2hpY2ggYXNzaWducyBhIHZhbHVlIHRvIHRoZSBtYW5kYXRvcnlcbiAgICAgICAgICAgICAgICAvLyBwcm9wZXJ0eSBjb2xpYnJpQ2xhc3MpIHNvIGRvbid0IGp1c3Qgc3dhbGxvdyBpdCwgZXhwb3NlIGl0IHRvXG4gICAgICAgICAgICAgICAgLy8gcHVibGljIGNvbnN1bXB0aW9uLlxuICAgICAgICAgICAgICAgIHNlbGYuZXZlbnRFbWl0dGVyLmVtaXQoXCJydGMuZGF0YWNoYW5uZWwuXCIgKyBjb2xpYnJpQ2xhc3MsIG9iaik7XG4gICAgICAgICAgICB9XG4gICAgICAgIH1cbiAgICB9O1xuXG4gICAgZGF0YUNoYW5uZWwub25jbG9zZSA9IGZ1bmN0aW9uICgpIHtcbiAgICAgICAgbG9nZ2VyLmluZm8oXCJUaGUgRGF0YSBDaGFubmVsIGNsb3NlZFwiLCBkYXRhQ2hhbm5lbCk7XG4gICAgICAgIHZhciBpZHggPSBzZWxmLl9kYXRhQ2hhbm5lbHMuaW5kZXhPZihkYXRhQ2hhbm5lbCk7XG4gICAgICAgIGlmIChpZHggPiAtMSlcbiAgICAgICAgICAgIHNlbGYuX2RhdGFDaGFubmVscyA9IHNlbGYuX2RhdGFDaGFubmVscy5zcGxpY2UoaWR4LCAxKTtcbiAgICB9O1xuICAgIHRoaXMuX2RhdGFDaGFubmVscy5wdXNoKGRhdGFDaGFubmVsKTtcbn07XG5cbkRhdGFDaGFubmVscy5wcm90b3R5cGUuaGFuZGxlU2VsZWN0ZWRFbmRwb2ludEV2ZW50ID0gZnVuY3Rpb24gKHVzZXJSZXNvdXJjZSkge1xuICAgIHRoaXMuX29uWFhYRW5kcG9pbnRDaGFuZ2VkKFwic2VsZWN0ZWRcIiwgdXNlclJlc291cmNlKTtcbn1cblxuRGF0YUNoYW5uZWxzLnByb3RvdHlwZS5oYW5kbGVQaW5uZWRFbmRwb2ludEV2ZW50ID0gZnVuY3Rpb24gKHVzZXJSZXNvdXJjZSkge1xuICAgIHRoaXMuX29uWFhYRW5kcG9pbnRDaGFuZ2VkKFwicGlubm5lZFwiLCB1c2VyUmVzb3VyY2UpO1xufVxuXG4vKipcbiAqIE5vdGlmaWVzIFZpZGVvYnJpZGdlIGFib3V0IGEgY2hhbmdlIGluIHRoZSB2YWx1ZSBvZiBhIHNwZWNpZmljXG4gKiBlbmRwb2ludC1yZWxhdGVkIHByb3BlcnR5IHN1Y2ggYXMgc2VsZWN0ZWQgZW5kcG9pbnQgYW5kIHBpbm5uZWQgZW5kcG9pbnQuXG4gKlxuICogQHBhcmFtIHh4eCB0aGUgbmFtZSBvZiB0aGUgZW5kcG9pbnQtcmVsYXRlZCBwcm9wZXJ0eSB3aG9zZSB2YWx1ZSBjaGFuZ2VkXG4gKiBAcGFyYW0gdXNlclJlc291cmNlIHRoZSBuZXcgdmFsdWUgb2YgdGhlIGVuZHBvaW50LXJlbGF0ZWQgcHJvcGVydHkgYWZ0ZXIgdGhlXG4gKiBjaGFuZ2VcbiAqL1xuRGF0YUNoYW5uZWxzLnByb3RvdHlwZS5fb25YWFhFbmRwb2ludENoYW5nZWQgPSBmdW5jdGlvbiAoeHh4LCB1c2VyUmVzb3VyY2UpIHtcbiAgICAvLyBEZXJpdmUgdGhlIGNvcnJlY3Qgd29yZHMgZnJvbSB4eHggc3VjaCBhcyBzZWxlY3RlZCBhbmQgU2VsZWN0ZWQsIHBpbm5lZFxuICAgIC8vIGFuZCBQaW5uZWQuXG4gICAgdmFyIGhlYWQgPSB4eHguY2hhckF0KDApO1xuICAgIHZhciB0YWlsID0geHh4LnN1YnN0cmluZygxKTtcbiAgICB2YXIgbG93ZXIgPSBoZWFkLnRvTG93ZXJDYXNlKCkgKyB0YWlsO1xuICAgIHZhciB1cHBlciA9IGhlYWQudG9VcHBlckNhc2UoKSArIHRhaWw7XG5cbiAgICAvLyBOb3RpZnkgVmlkZW9icmlkZ2UgYWJvdXQgdGhlIHNwZWNpZmllZCBlbmRwb2ludCBjaGFuZ2UuXG4gICAgY29uc29sZS5sb2cobG93ZXIgKyAnIGVuZHBvaW50IGNoYW5nZWQ6ICcsIHVzZXJSZXNvdXJjZSk7XG4gICAgdGhpcy5fc29tZShmdW5jdGlvbiAoZGF0YUNoYW5uZWwpIHtcbiAgICAgICAgaWYgKGRhdGFDaGFubmVsLnJlYWR5U3RhdGUgPT0gJ29wZW4nKSB7XG4gICAgICAgICAgICBjb25zb2xlLmxvZyhcbiAgICAgICAgICAgICAgICAgICAgJ3NlbmRpbmcgJyArIGxvd2VyXG4gICAgICAgICAgICAgICAgICAgICAgICArICcgZW5kcG9pbnQgY2hhbmdlZCBub3RpZmljYXRpb24gdG8gdGhlIGJyaWRnZTogJyxcbiAgICAgICAgICAgICAgICAgICAgdXNlclJlc291cmNlKTtcblxuICAgICAgICAgICAgdmFyIGpzb25PYmplY3QgPSB7fTtcblxuICAgICAgICAgICAganNvbk9iamVjdC5jb2xpYnJpQ2xhc3MgPSAodXBwZXIgKyAnRW5kcG9pbnRDaGFuZ2VkRXZlbnQnKTtcbiAgICAgICAgICAgIGpzb25PYmplY3RbbG93ZXIgKyBcIkVuZHBvaW50XCJdXG4gICAgICAgICAgICAgICAgPSAodXNlclJlc291cmNlID8gdXNlclJlc291cmNlIDogbnVsbCk7XG4gICAgICAgICAgICBkYXRhQ2hhbm5lbC5zZW5kKEpTT04uc3RyaW5naWZ5KGpzb25PYmplY3QpKTtcblxuICAgICAgICAgICAgcmV0dXJuIHRydWU7XG4gICAgICAgIH1cbiAgICB9KTtcbn1cblxuRGF0YUNoYW5uZWxzLnByb3RvdHlwZS5fc29tZSA9IGZ1bmN0aW9uIChjYWxsYmFjaywgdGhpc0FyZykge1xuICAgIHZhciBkYXRhQ2hhbm5lbHMgPSB0aGlzLl9kYXRhQ2hhbm5lbHM7XG5cbiAgICBpZiAoZGF0YUNoYW5uZWxzICYmIGRhdGFDaGFubmVscy5sZW5ndGggIT09IDApIHtcbiAgICAgICAgaWYgKHRoaXNBcmcpXG4gICAgICAgICAgICByZXR1cm4gZGF0YUNoYW5uZWxzLnNvbWUoY2FsbGJhY2ssIHRoaXNBcmcpO1xuICAgICAgICBlbHNlXG4gICAgICAgICAgICByZXR1cm4gZGF0YUNoYW5uZWxzLnNvbWUoY2FsbGJhY2spO1xuICAgIH0gZWxzZSB7XG4gICAgICAgIHJldHVybiBmYWxzZTtcbiAgICB9XG59XG5cbm1vZHVsZS5leHBvcnRzID0gRGF0YUNoYW5uZWxzO1xuXG4iLCJ2YXIgSml0c2lUcmFjayA9IHJlcXVpcmUoXCIuL0ppdHNpVHJhY2tcIik7XG52YXIgUlRDQnJvd3NlclR5cGUgPSByZXF1aXJlKFwiLi9SVENCcm93c2VyVHlwZVwiKTtcbnZhciBKaXRzaVRyYWNrRXZlbnRzID0gcmVxdWlyZSgnLi4vLi4vSml0c2lUcmFja0V2ZW50cycpO1xudmFyIFJUQyA9IHJlcXVpcmUoXCIuL1JUQ1V0aWxzXCIpO1xuXG4vKipcbiAqIFJlcHJlc2VudHMgYSBzaW5nbGUgbWVkaWEgdHJhY2sgKGVpdGhlciBhdWRpbyBvciB2aWRlbykuXG4gKiBAY29uc3RydWN0b3JcbiAqL1xuZnVuY3Rpb24gSml0c2lMb2NhbFRyYWNrKHN0cmVhbSwgdmlkZW9UeXBlLFxuICByZXNvbHV0aW9uKVxue1xuICAgIHRoaXMudmlkZW9UeXBlID0gdmlkZW9UeXBlO1xuICAgIHRoaXMuZG9udEZpcmVSZW1vdmVFdmVudCA9IGZhbHNlO1xuICAgIHRoaXMucmVzb2x1dGlvbiA9IHJlc29sdXRpb247XG4gICAgdGhpcy5zdGFydE11dGVkID0gZmFsc2U7XG4gICAgdmFyIHNlbGYgPSB0aGlzO1xuICAgIEppdHNpVHJhY2suY2FsbCh0aGlzLCBudWxsLCBzdHJlYW0sXG4gICAgICAgIGZ1bmN0aW9uICgpIHtcbiAgICAgICAgICAgIGlmKCF0aGlzLmRvbnRGaXJlUmVtb3ZlRXZlbnQpXG4gICAgICAgICAgICAgICAgdGhpcy5ldmVudEVtaXR0ZXIuZW1pdChcbiAgICAgICAgICAgICAgICAgICAgSml0c2lUcmFja0V2ZW50cy5UUkFDS19TVE9QUEVEKTtcbiAgICAgICAgICAgIHRoaXMuZG9udEZpcmVSZW1vdmVFdmVudCA9IGZhbHNlO1xuICAgICAgICB9LmJpbmQodGhpcykpO1xuXG59XG5cbkppdHNpTG9jYWxUcmFjay5wcm90b3R5cGUgPSBPYmplY3QuY3JlYXRlKEppdHNpVHJhY2sucHJvdG90eXBlKTtcbkppdHNpTG9jYWxUcmFjay5wcm90b3R5cGUuY29uc3RydWN0b3IgPSBKaXRzaUxvY2FsVHJhY2s7XG5cbi8qKlxuICogTXV0ZXMgLyB1bm11dGVzIHRoZSB0cmFjay5cbiAqIEBwYXJhbSBtdXRlIHtib29sZWFufSBpZiB0cnVlIHRoZSB0cmFjayB3aWxsIGJlIG11dGVkLiBPdGhlcndpc2UgdGhlIHRyYWNrIHdpbGwgYmUgdW5tdXRlZC5cbiAqL1xuSml0c2lMb2NhbFRyYWNrLnByb3RvdHlwZS5fc2V0TXV0ZSA9IGZ1bmN0aW9uIChtdXRlKSB7XG4gICAgaWYoIXRoaXMucnRjKSB7XG4gICAgICAgIHRoaXMuc3RhcnRNdXRlZCA9IG11dGU7XG4gICAgICAgIHJldHVybjtcbiAgICB9XG4gICAgdmFyIGlzQXVkaW8gPSB0aGlzLnR5cGUgPT09IEppdHNpVHJhY2suQVVESU87XG4gICAgdGhpcy5kb250RmlyZVJlbW92ZUV2ZW50ID0gZmFsc2U7XG5cbiAgICBpZiAoKHdpbmRvdy5sb2NhdGlvbi5wcm90b2NvbCAhPSBcImh0dHBzOlwiKSB8fFxuICAgICAgICAoaXNBdWRpbykgfHwgdGhpcy52aWRlb1R5cGUgPT09IFwiZGVza3RvcFwiIHx8XG4gICAgICAgIC8vIEZJWE1FIEZGIGRvZXMgbm90IHN1cHBvcnQgJ3JlbW92ZVN0cmVhbScgbWV0aG9kIHVzZWQgdG8gbXV0ZVxuICAgICAgICBSVENCcm93c2VyVHlwZS5pc0ZpcmVmb3goKSkge1xuXG4gICAgICAgIHZhciB0cmFja3MgPSB0aGlzLl9nZXRUcmFja3MoKTtcbiAgICAgICAgZm9yICh2YXIgaWR4ID0gMDsgaWR4IDwgdHJhY2tzLmxlbmd0aDsgaWR4KyspIHtcbiAgICAgICAgICAgIHRyYWNrc1tpZHhdLmVuYWJsZWQgPSAhbXV0ZTtcbiAgICAgICAgfVxuICAgICAgICBpZihpc0F1ZGlvKVxuICAgICAgICAgICAgdGhpcy5ydGMucm9vbS5zZXRBdWRpb011dGUobXV0ZSk7XG4gICAgICAgIGVsc2VcbiAgICAgICAgICAgIHRoaXMucnRjLnJvb20uc2V0VmlkZW9NdXRlKG11dGUpO1xuICAgICAgICB0aGlzLmV2ZW50RW1pdHRlci5lbWl0KEppdHNpVHJhY2tFdmVudHMuVFJBQ0tfTVVURV9DSEFOR0VEKTtcbiAgICB9IGVsc2Uge1xuICAgICAgICBpZiAobXV0ZSkge1xuICAgICAgICAgICAgdGhpcy5kb250RmlyZVJlbW92ZUV2ZW50ID0gdHJ1ZTtcbiAgICAgICAgICAgIHRoaXMucnRjLnJvb20ucmVtb3ZlU3RyZWFtKHRoaXMuc3RyZWFtLCBmdW5jdGlvbiAoKSB7fSk7XG4gICAgICAgICAgICBSVEMuc3RvcE1lZGlhU3RyZWFtKHRoaXMuc3RyZWFtKTtcbiAgICAgICAgICAgIGlmKGlzQXVkaW8pXG4gICAgICAgICAgICAgICAgdGhpcy5ydGMucm9vbS5zZXRBdWRpb011dGUobXV0ZSk7XG4gICAgICAgICAgICBlbHNlXG4gICAgICAgICAgICAgICAgdGhpcy5ydGMucm9vbS5zZXRWaWRlb011dGUobXV0ZSk7XG4gICAgICAgICAgICB0aGlzLnN0cmVhbSA9IG51bGw7XG4gICAgICAgICAgICB0aGlzLmV2ZW50RW1pdHRlci5lbWl0KEppdHNpVHJhY2tFdmVudHMuVFJBQ0tfTVVURV9DSEFOR0VEKTtcbiAgICAgICAgICAgIC8vRklYTUU6IE1heWJlIGhlcmUgd2Ugc2hvdWxkIHNldCB0aGUgU1JDIGZvciB0aGUgY29udGFpbmVycyB0byBzb21ldGhpbmdcbiAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgIHZhciBzZWxmID0gdGhpcztcbiAgICAgICAgICAgIFJUQy5vYnRhaW5BdWRpb0FuZFZpZGVvUGVybWlzc2lvbnMoe1xuICAgICAgICAgICAgICAgIGRldmljZXM6IChpc0F1ZGlvID8gW1wiYXVkaW9cIl0gOiBbXCJ2aWRlb1wiXSksXG4gICAgICAgICAgICAgICAgcmVzb2x1dGlvbjogc2VsZi5yZXNvbHV0aW9ufSlcbiAgICAgICAgICAgICAgICAudGhlbihmdW5jdGlvbiAoc3RyZWFtcykge1xuICAgICAgICAgICAgICAgICAgICB2YXIgc3RyZWFtID0gbnVsbDtcbiAgICAgICAgICAgICAgICAgICAgZm9yKHZhciBpID0gMDsgaSA8IHN0cmVhbXMubGVuZ3RoOyBpKyspIHtcbiAgICAgICAgICAgICAgICAgICAgICAgIHN0cmVhbSA9IHN0cmVhbXNbaV07XG4gICAgICAgICAgICAgICAgICAgICAgICBpZihzdHJlYW0udHlwZSA9PT0gc2VsZi50eXBlKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgc2VsZi5zdHJlYW0gPSBzdHJlYW0uc3RyZWFtO1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgIHNlbGYudmlkZW9UeXBlID0gc3RyZWFtLnZpZGVvVHlwZTtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICBicmVhaztcbiAgICAgICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICAgICAgICAgIGlmKCFzdHJlYW0pXG4gICAgICAgICAgICAgICAgICAgICAgICByZXR1cm47XG5cbiAgICAgICAgICAgICAgICAgICAgZm9yKHZhciBpID0gMDsgaSA8IHNlbGYuY29udGFpbmVycy5sZW5ndGg7IGkrKylcbiAgICAgICAgICAgICAgICAgICAge1xuICAgICAgICAgICAgICAgICAgICAgICAgUlRDLmF0dGFjaE1lZGlhU3RyZWFtKHNlbGYuY29udGFpbmVyc1tpXSwgc2VsZi5zdHJlYW0pO1xuICAgICAgICAgICAgICAgICAgICB9XG5cbiAgICAgICAgICAgICAgICAgICAgc2VsZi5ydGMucm9vbS5hZGRTdHJlYW0oc3RyZWFtLnN0cmVhbSxcbiAgICAgICAgICAgICAgICAgICAgICAgIGZ1bmN0aW9uICgpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICBpZihpc0F1ZGlvKVxuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBzZWxmLnJ0Yy5yb29tLnNldEF1ZGlvTXV0ZShtdXRlKTtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICBlbHNlXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIHNlbGYucnRjLnJvb20uc2V0VmlkZW9NdXRlKG11dGUpO1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgIHNlbGYuZXZlbnRFbWl0dGVyLmVtaXQoXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIEppdHNpVHJhY2tFdmVudHMuVFJBQ0tfTVVURV9DSEFOR0VEKTtcbiAgICAgICAgICAgICAgICAgICAgICAgIH0pO1xuICAgICAgICAgICAgICAgIH0pO1xuICAgICAgICB9XG4gICAgfVxufVxuXG4vKipcbiAqIFN0b3BzIHNlbmRpbmcgdGhlIG1lZGlhIHRyYWNrLiBBbmQgcmVtb3ZlcyBpdCBmcm9tIHRoZSBIVE1MLlxuICogTk9URTogV29ya3MgZm9yIGxvY2FsIHRyYWNrcyBvbmx5LlxuICovXG5KaXRzaUxvY2FsVHJhY2sucHJvdG90eXBlLnN0b3AgPSBmdW5jdGlvbiAoKSB7XG4gICAgaWYoIXRoaXMuc3RyZWFtKVxuICAgICAgICByZXR1cm47XG4gICAgaWYodGhpcy5ydGMpXG4gICAgICAgIHRoaXMucnRjLnJvb20ucmVtb3ZlU3RyZWFtKHRoaXMuc3RyZWFtLCBmdW5jdGlvbiAoKSB7fSk7XG4gICAgUlRDLnN0b3BNZWRpYVN0cmVhbSh0aGlzLnN0cmVhbSk7XG4gICAgdGhpcy5kZXRhY2goKTtcbn1cblxuLyoqXG4gKiBSZXR1cm5zIDx0dD50cnVlPC90dD4gLSBpZiB0aGUgc3RyZWFtIGlzIG11dGVkXG4gKiBhbmQgPHR0PmZhbHNlPC90dD4gb3RoZXJ3aXNlLlxuICogQHJldHVybnMge2Jvb2xlYW59IDx0dD50cnVlPC90dD4gLSBpZiB0aGUgc3RyZWFtIGlzIG11dGVkXG4gKiBhbmQgPHR0PmZhbHNlPC90dD4gb3RoZXJ3aXNlLlxuICovXG5KaXRzaUxvY2FsVHJhY2sucHJvdG90eXBlLmlzTXV0ZWQgPSBmdW5jdGlvbiAoKSB7XG4gICAgaWYgKCF0aGlzLnN0cmVhbSlcbiAgICAgICAgcmV0dXJuIHRydWU7XG4gICAgdmFyIHRyYWNrcyA9IFtdO1xuICAgIHZhciBpc0F1ZGlvID0gdGhpcy50eXBlID09PSBKaXRzaVRyYWNrLkFVRElPO1xuICAgIGlmIChpc0F1ZGlvKSB7XG4gICAgICAgIHRyYWNrcyA9IHRoaXMuc3RyZWFtLmdldEF1ZGlvVHJhY2tzKCk7XG4gICAgfSBlbHNlIHtcbiAgICAgICAgaWYgKCF0aGlzLmlzQWN0aXZlKCkpXG4gICAgICAgICAgICByZXR1cm4gdHJ1ZTtcbiAgICAgICAgdHJhY2tzID0gdGhpcy5zdHJlYW0uZ2V0VmlkZW9UcmFja3MoKTtcbiAgICB9XG4gICAgZm9yICh2YXIgaWR4ID0gMDsgaWR4IDwgdHJhY2tzLmxlbmd0aDsgaWR4KyspIHtcbiAgICAgICAgaWYodHJhY2tzW2lkeF0uZW5hYmxlZClcbiAgICAgICAgICAgIHJldHVybiBmYWxzZTtcbiAgICB9XG4gICAgcmV0dXJuIHRydWU7XG59O1xuXG4vKipcbiAqIFByaXZhdGUgbWV0aG9kLiBVcGRhdGVzIHJ0YyBwcm9wZXJ0eSBvZiB0aGUgdHJhY2suXG4gKiBAcGFyYW0gcnRjIHRoZSBydGMgaW5zdGFuY2UuXG4gKi9cbkppdHNpTG9jYWxUcmFjay5wcm90b3R5cGUuX3NldFJUQyA9IGZ1bmN0aW9uIChydGMpIHtcbiAgICB0aGlzLnJ0YyA9IHJ0Yztcbn07XG5cbi8qKlxuICogUmV0dXJuIHRydWU7XG4gKi9cbkppdHNpTG9jYWxUcmFjay5wcm90b3R5cGUuaXNMb2NhbCA9IGZ1bmN0aW9uICgpIHtcbiAgICByZXR1cm4gdHJ1ZTtcbn1cblxubW9kdWxlLmV4cG9ydHMgPSBKaXRzaUxvY2FsVHJhY2s7XG4iLCJ2YXIgSml0c2lUcmFjayA9IHJlcXVpcmUoXCIuL0ppdHNpVHJhY2tcIik7XG52YXIgSml0c2lUcmFja0V2ZW50cyA9IHJlcXVpcmUoXCIuLi8uLi9KaXRzaVRyYWNrRXZlbnRzXCIpO1xuXG4vKipcbiAqIFJlcHJlc2VudHMgYSBzaW5nbGUgbWVkaWEgdHJhY2sgKGVpdGhlciBhdWRpbyBvciB2aWRlbykuXG4gKiBAcGFyYW0gUlRDIHRoZSBydGMgaW5zdGFuY2UuXG4gKiBAcGFyYW0gZGF0YSBvYmplY3Qgd2l0aCB0aGUgc3RyZWFtIGFuZCBzb21lIGRldGFpbHMgYWJvdXQgaXQocGFydGljaXBhbnQgaWQsIHZpZGVvIHR5cGUsIGV0Yy4pXG4gKiBAcGFyYW0gc2lkIHNpZCBmb3IgdGhlIE1lZGlhIFN0cmVhbVxuICogQHBhcmFtIHNzcmMgc3NyYyBmb3IgdGhlIE1lZGlhIFN0cmVhbVxuICogQHBhcmFtIGV2ZW50RW1pdHRlciB0aGUgZXZlbnQgZW1pdHRlclxuICogQGNvbnN0cnVjdG9yXG4gKi9cbmZ1bmN0aW9uIEppdHNpUmVtb3RlVHJhY2soUlRDLCBkYXRhLCBzaWQsIHNzcmMpIHtcbiAgICBKaXRzaVRyYWNrLmNhbGwodGhpcywgUlRDLCBkYXRhLnN0cmVhbSxcbiAgICAgICAgZnVuY3Rpb24gKCkge1xuICAgICAgICAgICAgdGhpcy5ldmVudEVtaXR0ZXIuZW1pdChKaXRzaVRyYWNrRXZlbnRzLlRSQUNLX1NUT1BQRUQpO1xuICAgICAgICB9LmJpbmQodGhpcykpO1xuICAgIHRoaXMucnRjID0gUlRDO1xuICAgIHRoaXMuc2lkID0gc2lkO1xuICAgIHRoaXMuc3RyZWFtID0gZGF0YS5zdHJlYW07XG4gICAgdGhpcy5wZWVyamlkID0gZGF0YS5wZWVyamlkO1xuICAgIHRoaXMudmlkZW9UeXBlID0gZGF0YS52aWRlb1R5cGU7XG4gICAgdGhpcy5zc3JjID0gc3NyYztcbiAgICB0aGlzLm11dGVkID0gZmFsc2U7XG4gICAgaWYoKHRoaXMudHlwZSA9PT0gSml0c2lUcmFjay5BVURJTyAmJiBkYXRhLmF1ZGlvbXV0ZWQpXG4gICAgICB8fCAodGhpcy50eXBlID09PSBKaXRzaVRyYWNrLlZJREVPICYmIGRhdGEudmlkZW9tdXRlZCkpIHtcbiAgICAgICAgdGhpcy5tdXRlZCA9IHRydWU7XG4gICAgfVxufVxuXG5KaXRzaVJlbW90ZVRyYWNrLnByb3RvdHlwZSA9IE9iamVjdC5jcmVhdGUoSml0c2lUcmFjay5wcm90b3R5cGUpO1xuSml0c2lSZW1vdGVUcmFjay5wcm90b3R5cGUuY29uc3RydWN0b3IgPSBKaXRzaVJlbW90ZVRyYWNrO1xuXG4vKipcbiAqIFNldHMgY3VycmVudCBtdXRlZCBzdGF0dXMgYW5kIGZpcmVzIGFuIGV2ZW50cyBmb3IgdGhlIGNoYW5nZS5cbiAqIEBwYXJhbSB2YWx1ZSB0aGUgbXV0ZWQgc3RhdHVzLlxuICovXG5KaXRzaVJlbW90ZVRyYWNrLnByb3RvdHlwZS5zZXRNdXRlID0gZnVuY3Rpb24gKHZhbHVlKSB7XG4gICAgdGhpcy5zdHJlYW0ubXV0ZWQgPSB2YWx1ZTtcbiAgICB0aGlzLm11dGVkID0gdmFsdWU7XG4gICAgdGhpcy5ldmVudEVtaXR0ZXIuZW1pdChKaXRzaVRyYWNrRXZlbnRzLlRSQUNLX01VVEVfQ0hBTkdFRCk7XG59O1xuXG4vKipcbiAqIFJldHVybnMgdGhlIGN1cnJlbnQgbXV0ZWQgc3RhdHVzIG9mIHRoZSB0cmFjay5cbiAqIEByZXR1cm5zIHtib29sZWFufCp8Sml0c2lSZW1vdGVUcmFjay5tdXRlZH0gPHR0PnRydWU8L3R0PiBpZiB0aGUgdHJhY2sgaXMgbXV0ZWQgYW5kIDx0dD5mYWxzZTwvdHQ+IG90aGVyd2lzZS5cbiAqL1xuSml0c2lSZW1vdGVUcmFjay5wcm90b3R5cGUuaXNNdXRlZCA9IGZ1bmN0aW9uICgpIHtcbiAgICByZXR1cm4gdGhpcy5tdXRlZDtcbn07XG5cbi8qKlxuICogUmV0dXJucyB0aGUgcGFydGljaXBhbnQgaWQgd2hpY2ggb3ducyB0aGUgdHJhY2suXG4gKiBAcmV0dXJucyB7c3RyaW5nfSB0aGUgaWQgb2YgdGhlIHBhcnRpY2lwYW50cy5cbiAqL1xuSml0c2lSZW1vdGVUcmFjay5wcm90b3R5cGUuZ2V0UGFydGljaXBhbnRJZCA9IGZ1bmN0aW9uKCkge1xuICAgIHJldHVybiBTdHJvcGhlLmdldFJlc291cmNlRnJvbUppZCh0aGlzLnBlZXJqaWQpO1xufTtcblxuLyoqXG4gKiBSZXR1cm4gZmFsc2U7XG4gKi9cbkppdHNpUmVtb3RlVHJhY2sucHJvdG90eXBlLmlzTG9jYWwgPSBmdW5jdGlvbiAoKSB7XG4gICAgcmV0dXJuIGZhbHNlO1xufTtcblxuZGVsZXRlIEppdHNpUmVtb3RlVHJhY2sucHJvdG90eXBlLnN0b3A7XG5cbmRlbGV0ZSBKaXRzaVJlbW90ZVRyYWNrLnByb3RvdHlwZS5zdGFydDtcblxubW9kdWxlLmV4cG9ydHMgPSBKaXRzaVJlbW90ZVRyYWNrO1xuIiwidmFyIFJUQ0Jyb3dzZXJUeXBlID0gcmVxdWlyZShcIi4vUlRDQnJvd3NlclR5cGVcIik7XG52YXIgSml0c2lUcmFja0V2ZW50cyA9IHJlcXVpcmUoXCIuLi8uLi9KaXRzaVRyYWNrRXZlbnRzXCIpO1xudmFyIEV2ZW50RW1pdHRlciA9IHJlcXVpcmUoXCJldmVudHNcIik7XG52YXIgUlRDID0gcmVxdWlyZShcIi4vUlRDVXRpbHNcIik7XG5cbi8qKlxuICogVGhpcyBpbXBsZW1lbnRzICdvbmVuZGVkJyBjYWxsYmFjayBub3JtYWxseSBmaXJlZCBieSBXZWJSVEMgYWZ0ZXIgdGhlIHN0cmVhbVxuICogaXMgc3RvcHBlZC4gVGhlcmUgaXMgbm8gc3VjaCBiZWhhdmlvdXIgeWV0IGluIEZGLCBzbyB3ZSBoYXZlIHRvIGFkZCBpdC5cbiAqIEBwYXJhbSBqaXRzaVRyYWNrIG91ciB0cmFjayBvYmplY3QgaG9sZGluZyB0aGUgb3JpZ2luYWwgV2ViUlRDIHN0cmVhbSBvYmplY3RcbiAqIHRvIHdoaWNoICdvbmVuZGVkJyBoYW5kbGluZyB3aWxsIGJlIGFkZGVkLlxuICovXG5mdW5jdGlvbiBpbXBsZW1lbnRPbkVuZGVkSGFuZGxpbmcoaml0c2lUcmFjaykge1xuICAgIHZhciBzdHJlYW0gPSBqaXRzaVRyYWNrLmdldE9yaWdpbmFsU3RyZWFtKCk7XG4gICAgdmFyIG9yaWdpbmFsU3RvcCA9IHN0cmVhbS5zdG9wO1xuICAgIHN0cmVhbS5zdG9wID0gZnVuY3Rpb24gKCkge1xuICAgICAgICBvcmlnaW5hbFN0b3AuYXBwbHkoc3RyZWFtKTtcbiAgICAgICAgaWYgKGppdHNpVHJhY2suaXNBY3RpdmUoKSkge1xuICAgICAgICAgICAgc3RyZWFtLm9uZW5kZWQoKTtcbiAgICAgICAgfVxuICAgIH07XG59XG5cbi8qKlxuICogQWRkcyBvbmVuZGVkL29uaW5hY3RpdmUgaGFuZGxlciB0byBhIE1lZGlhU3RyZWFtLlxuICogQHBhcmFtIG1lZGlhU3RyZWFtIGEgTWVkaWFTdHJlYW0gdG8gYXR0YWNoIG9uZW5kZWQvb25pbmFjdGl2ZSBoYW5kbGVyXG4gKiBAcGFyYW0gaGFuZGxlciB0aGUgaGFuZGxlclxuICovXG5mdW5jdGlvbiBhZGRNZWRpYVN0cmVhbUluYWN0aXZlSGFuZGxlcihtZWRpYVN0cmVhbSwgaGFuZGxlcikge1xuICAgIGlmKFJUQ0Jyb3dzZXJUeXBlLmlzVGVtYXN5c1BsdWdpblVzZWQoKSkge1xuICAgICAgICAvLyB0aGVtYXN5c1xuICAgICAgICAvL0ZJWE1FOiBTZWVtcyB0aGF0IG5vdCB3b3JraW5nIHByb3Blcmx5LlxuICAgICAgICBpZihtZWRpYVN0cmVhbS5vbmVuZGVkKSB7XG4gICAgICAgICAgICBtZWRpYVN0cmVhbS5vbmVuZGVkID0gaGFuZGxlcjtcbiAgICAgICAgfSBlbHNlIGlmKG1lZGlhU3RyZWFtLmFkZEV2ZW50TGlzdGVuZXIpIHtcbiAgICAgICAgICAgIG1lZGlhU3RyZWFtLmFkZEV2ZW50TGlzdGVuZXIoJ2VuZGVkJywgZnVuY3Rpb24gKCkge1xuICAgICAgICAgICAgICAgIGhhbmRsZXIobWVkaWFTdHJlYW0pO1xuICAgICAgICAgICAgfSk7XG4gICAgICAgIH0gZWxzZSBpZihtZWRpYVN0cmVhbS5hdHRhY2hFdmVudCkge1xuICAgICAgICAgICAgbWVkaWFTdHJlYW0uYXR0YWNoRXZlbnQoJ2VuZGVkJywgZnVuY3Rpb24gKCkge1xuICAgICAgICAgICAgICAgIGhhbmRsZXIobWVkaWFTdHJlYW0pO1xuICAgICAgICAgICAgfSk7XG4gICAgICAgIH1cbiAgICB9XG4gICAgZWxzZSB7XG4gICAgICAgIGlmKHR5cGVvZiBtZWRpYVN0cmVhbS5hY3RpdmUgIT09IFwidW5kZWZpbmVkXCIpXG4gICAgICAgICAgICBtZWRpYVN0cmVhbS5vbmluYWN0aXZlID0gaGFuZGxlcjtcbiAgICAgICAgZWxzZVxuICAgICAgICAgICAgbWVkaWFTdHJlYW0ub25lbmRlZCA9IGhhbmRsZXI7XG4gICAgfVxufVxuXG4vKipcbiAqIFJlcHJlc2VudHMgYSBzaW5nbGUgbWVkaWEgdHJhY2sgKGVpdGhlciBhdWRpbyBvciB2aWRlbykuXG4gKiBAY29uc3RydWN0b3JcbiAqIEBwYXJhbSBydGMgdGhlIHJ0YyBpbnN0YW5jZVxuICogQHBhcmFtIHN0cmVhbSB0aGUgc3RyZWFtXG4gKiBAcGFyYW0gc3RyZWFtSW5hY3RpdmVIYW5kbGVyIHRoZSBmdW5jdGlvbiB0aGF0IHdpbGwgaGFuZGxlXG4gKiAgICAgICAgb25lbmRlZC9vbmluYWN0aXZlIGV2ZW50cyBvZiB0aGUgc3RyZWFtLlxuICovXG5mdW5jdGlvbiBKaXRzaVRyYWNrKHJ0Yywgc3RyZWFtLCBzdHJlYW1JbmFjdGl2ZUhhbmRsZXIpXG57XG4gICAgLyoqXG4gICAgICogQXJyYXkgd2l0aCB0aGUgSFRNTCBlbGVtZW50cyB0aGF0IGFyZSBkaXNwbGF5aW5nIHRoZSBzdHJlYW1zLlxuICAgICAqIEB0eXBlIHtBcnJheX1cbiAgICAgKi9cbiAgICB0aGlzLmNvbnRhaW5lcnMgPSBbXTtcbiAgICB0aGlzLnJ0YyA9IHJ0YztcbiAgICB0aGlzLnN0cmVhbSA9IHN0cmVhbTtcbiAgICB0aGlzLmV2ZW50RW1pdHRlciA9IG5ldyBFdmVudEVtaXR0ZXIoKTtcbiAgICB0aGlzLmF1ZGlvTGV2ZWwgPSAtMTtcbiAgICB0aGlzLnR5cGUgPSAodGhpcy5zdHJlYW0uZ2V0VmlkZW9UcmFja3MoKS5sZW5ndGggPiAwKT9cbiAgICAgICAgSml0c2lUcmFjay5WSURFTyA6IEppdHNpVHJhY2suQVVESU87XG4gICAgaWYodGhpcy50eXBlID09IFwiYXVkaW9cIikge1xuICAgICAgICB0aGlzLl9nZXRUcmFja3MgPSBmdW5jdGlvbiAoKSB7XG4gICAgICAgICAgICByZXR1cm4gdGhpcy5zdHJlYW0uZ2V0QXVkaW9UcmFja3MoKTtcbiAgICAgICAgfS5iaW5kKHRoaXMpO1xuICAgIH0gZWxzZSB7XG4gICAgICAgIHRoaXMuX2dldFRyYWNrcyA9IGZ1bmN0aW9uICgpIHtcbiAgICAgICAgICAgIHJldHVybiB0aGlzLnN0cmVhbS5nZXRWaWRlb1RyYWNrcygpO1xuICAgICAgICB9LmJpbmQodGhpcyk7XG4gICAgfVxuICAgIGlmIChSVENCcm93c2VyVHlwZS5pc0ZpcmVmb3goKSAmJiB0aGlzLnN0cmVhbSkge1xuICAgICAgICBpbXBsZW1lbnRPbkVuZGVkSGFuZGxpbmcodGhpcyk7XG4gICAgfVxuXG4gICAgaWYoc3RyZWFtKVxuICAgICAgICBhZGRNZWRpYVN0cmVhbUluYWN0aXZlSGFuZGxlcihzdHJlYW0sIHN0cmVhbUluYWN0aXZlSGFuZGxlcik7XG59XG5cbi8qKlxuICogSml0c2lUcmFjayB2aWRlbyB0eXBlLlxuICogQHR5cGUge3N0cmluZ31cbiAqL1xuSml0c2lUcmFjay5WSURFTyA9IFwidmlkZW9cIjtcblxuLyoqXG4gKiBKaXRzaVRyYWNrIGF1ZGlvIHR5cGUuXG4gKiBAdHlwZSB7c3RyaW5nfVxuICovXG5KaXRzaVRyYWNrLkFVRElPID0gXCJhdWRpb1wiO1xuXG4vKipcbiAqIFJldHVybnMgdGhlIHR5cGUgKGF1ZGlvIG9yIHZpZGVvKSBvZiB0aGlzIHRyYWNrLlxuICovXG5KaXRzaVRyYWNrLnByb3RvdHlwZS5nZXRUeXBlID0gZnVuY3Rpb24oKSB7XG4gICAgcmV0dXJuIHRoaXMudHlwZTtcbn07XG5cbi8qKlxuICogQ2hlY2sgaWYgdGhpcyBpcyBhdWRpb3RyYWNrLlxuICovXG5KaXRzaVRyYWNrLnByb3RvdHlwZS5pc0F1ZGlvVHJhY2sgPSBmdW5jdGlvbiAoKSB7XG4gICAgcmV0dXJuIHRoaXMuZ2V0VHlwZSgpID09PSBKaXRzaVRyYWNrLkFVRElPO1xufTtcblxuLyoqXG4gKiBDaGVjayBpZiB0aGlzIGlzIHZpZGVvdHJhY2suXG4gKi9cbkppdHNpVHJhY2sucHJvdG90eXBlLmlzVmlkZW9UcmFjayA9IGZ1bmN0aW9uICgpIHtcbiAgICByZXR1cm4gdGhpcy5nZXRUeXBlKCkgPT09IEppdHNpVHJhY2suVklERU87XG59O1xuXG4vKipcbiAqIFJldHVybnMgdGhlIFJUQ01lZGlhU3RyZWFtIGZyb20gdGhlIGJyb3dzZXIgKD8pLlxuICovXG5KaXRzaVRyYWNrLnByb3RvdHlwZS5nZXRPcmlnaW5hbFN0cmVhbSA9IGZ1bmN0aW9uKCkge1xuICAgIHJldHVybiB0aGlzLnN0cmVhbTtcbn1cblxuLyoqXG4gKiBNdXRlcyB0aGUgdHJhY2suXG4gKi9cbkppdHNpVHJhY2sucHJvdG90eXBlLm11dGUgPSBmdW5jdGlvbiAoKSB7XG4gICAgdGhpcy5fc2V0TXV0ZSh0cnVlKTtcbn1cblxuLyoqXG4gKiBVbm11dGVzIHRoZSBzdHJlYW0uXG4gKi9cbkppdHNpVHJhY2sucHJvdG90eXBlLnVubXV0ZSA9IGZ1bmN0aW9uICgpIHtcbiAgICB0aGlzLl9zZXRNdXRlKGZhbHNlKTtcbn1cblxuLyoqXG4gKiBBdHRhY2hlcyB0aGUgTWVkaWFTdHJlYW0gb2YgdGhpcyB0cmFjayB0byBhbiBIVE1MIGNvbnRhaW5lciAoPykuXG4gKiBBZGRzIHRoZSBjb250YWluZXIgdG8gdGhlIGxpc3Qgb2YgY29udGFpbmVycyB0aGF0IGFyZSBkaXNwbGF5aW5nIHRoZSB0cmFjay5cbiAqIEBwYXJhbSBjb250YWluZXIgdGhlIEhUTUwgY29udGFpbmVyXG4gKi9cbkppdHNpVHJhY2sucHJvdG90eXBlLmF0dGFjaCA9IGZ1bmN0aW9uIChjb250YWluZXIpIHtcbiAgICBpZih0aGlzLnN0cmVhbSlcbiAgICAgICAgcmVxdWlyZShcIi4vUlRDVXRpbHNcIikuYXR0YWNoTWVkaWFTdHJlYW0oY29udGFpbmVyLCB0aGlzLnN0cmVhbSk7XG4gICAgdGhpcy5jb250YWluZXJzLnB1c2goY29udGFpbmVyKTtcbn1cblxuLyoqXG4gKiBSZW1vdmVzIHRoZSB0cmFjayBmcm9tIHRoZSBwYXNzZWQgSFRNTCBjb250YWluZXIuXG4gKiBAcGFyYW0gY29udGFpbmVyIHRoZSBIVE1MIGNvbnRhaW5lci4gSWYgPHR0Pm51bGw8L3R0PiBhbGwgY29udGFpbmVycyBhcmUgcmVtb3ZlZC5cbiAqL1xuSml0c2lUcmFjay5wcm90b3R5cGUuZGV0YWNoID0gZnVuY3Rpb24gKGNvbnRhaW5lcikge1xuICAgIGZvcih2YXIgaSA9IDA7IGkgPCB0aGlzLmNvbnRhaW5lcnMubGVuZ3RoOyBpKyspXG4gICAge1xuICAgICAgICBpZih0aGlzLmNvbnRhaW5lcnNbaV0uaXMoY29udGFpbmVyKSlcbiAgICAgICAge1xuICAgICAgICAgICAgdGhpcy5jb250YWluZXJzLnNwbGljZShpLDEpO1xuICAgICAgICB9XG4gICAgICAgIGlmKCFjb250YWluZXIpXG4gICAgICAgIHtcbiAgICAgICAgICAgIHRoaXMuY29udGFpbmVyc1tpXS5maW5kKFwiPnZpZGVvXCIpLnJlbW92ZSgpO1xuICAgICAgICB9XG4gICAgfVxuICAgIGlmKGNvbnRhaW5lcilcbiAgICAgICAgJChjb250YWluZXIpLmZpbmQoXCI+dmlkZW9cIikucmVtb3ZlKCk7XG5cbn1cblxuLyoqXG4gKiBTdG9wcyBzZW5kaW5nIHRoZSBtZWRpYSB0cmFjay4gQW5kIHJlbW92ZXMgaXQgZnJvbSB0aGUgSFRNTC5cbiAqIE5PVEU6IFdvcmtzIGZvciBsb2NhbCB0cmFja3Mgb25seS5cbiAqL1xuSml0c2lUcmFjay5wcm90b3R5cGUuc3RvcCA9IGZ1bmN0aW9uICgpIHtcbn1cblxuLyoqXG4gKiBSZXR1cm5zIHRydWUgaWYgdGhpcyBpcyBhIHZpZGVvIHRyYWNrIGFuZCB0aGUgc291cmNlIG9mIHRoZSB2aWRlbyBpcyBhXG4gKiBzY3JlZW4gY2FwdHVyZSBhcyBvcHBvc2VkIHRvIGEgY2FtZXJhLlxuICovXG5KaXRzaVRyYWNrLnByb3RvdHlwZS5pc1NjcmVlblNoYXJpbmcgPSBmdW5jdGlvbigpe1xuXG59XG5cbi8qKlxuICogUmV0dXJucyBpZCBvZiB0aGUgdHJhY2suXG4gKiBAcmV0dXJucyB7c3RyaW5nfSBpZCBvZiB0aGUgdHJhY2sgb3IgbnVsbCBpZiB0aGlzIGlzIGZha2UgdHJhY2suXG4gKi9cbkppdHNpVHJhY2sucHJvdG90eXBlLl9nZXRJZCA9IGZ1bmN0aW9uICgpIHtcbiAgICB2YXIgdHJhY2tzID0gdGhpcy5zdHJlYW0uZ2V0VHJhY2tzKCk7XG4gICAgaWYoIXRyYWNrcyB8fCB0cmFja3MubGVuZ3RoID09PSAwKVxuICAgICAgICByZXR1cm4gbnVsbDtcbiAgICByZXR1cm4gdHJhY2tzWzBdLmlkO1xufTtcblxuLyoqXG4gKiBSZXR1cm5zIGlkIG9mIHRoZSB0cmFjay5cbiAqIEByZXR1cm5zIHtzdHJpbmd9IGlkIG9mIHRoZSB0cmFjayBvciBudWxsIGlmIHRoaXMgaXMgZmFrZSB0cmFjay5cbiAqL1xuSml0c2lUcmFjay5wcm90b3R5cGUuZ2V0SWQgPSBmdW5jdGlvbiAoKSB7XG4gICAgcmV0dXJuIFJUQy5nZXRTdHJlYW1JRCh0aGlzLnN0cmVhbSk7XG59O1xuXG4vKipcbiAqIENoZWNrcyB3aGV0aGVyIHRoZSBNZWRpYVN0cmVhbSBpcyBhdnRpdmUvbm90IGVuZGVkLlxuICogV2hlbiB0aGVyZSBpcyBubyBjaGVjayBmb3IgYWN0aXZlIHdlIGRvbid0IGhhdmUgaW5mb3JtYXRpb24gYW5kIHNvXG4gKiB3aWxsIHJldHVybiB0aGF0IHN0cmVhbSBpcyBhY3RpdmUgKGluIGNhc2Ugb2YgRkYpLlxuICogQHJldHVybnMge2Jvb2xlYW59IHdoZXRoZXIgTWVkaWFTdHJlYW0gaXMgYWN0aXZlLlxuICovXG5KaXRzaVRyYWNrLnByb3RvdHlwZS5pc0FjdGl2ZSA9IGZ1bmN0aW9uICgpIHtcbiAgICBpZigodHlwZW9mIHRoaXMuc3RyZWFtLmFjdGl2ZSAhPT0gXCJ1bmRlZmluZWRcIikpXG4gICAgICAgIHJldHVybiB0aGlzLnN0cmVhbS5hY3RpdmU7XG4gICAgZWxzZVxuICAgICAgICByZXR1cm4gdHJ1ZTtcbn07XG5cbi8qKlxuICogQXR0YWNoZXMgYSBoYW5kbGVyIGZvciBldmVudHMoRm9yIGV4YW1wbGUgLSBcImF1ZGlvIGxldmVsIGNoYW5nZWRcIi4pLlxuICogQWxsIHBvc3NpYmxlIGV2ZW50IGFyZSBkZWZpbmVkIGluIEppdHNpVHJhY2tFdmVudHMuXG4gKiBAcGFyYW0gZXZlbnRJZCB0aGUgZXZlbnQgSUQuXG4gKiBAcGFyYW0gaGFuZGxlciBoYW5kbGVyIGZvciB0aGUgZXZlbnQuXG4gKi9cbkppdHNpVHJhY2sucHJvdG90eXBlLm9uID0gZnVuY3Rpb24gKGV2ZW50SWQsIGhhbmRsZXIpIHtcbiAgICBpZih0aGlzLmV2ZW50RW1pdHRlcilcbiAgICAgICAgdGhpcy5ldmVudEVtaXR0ZXIub24oZXZlbnRJZCwgaGFuZGxlcik7XG59XG5cbi8qKlxuICogUmVtb3ZlcyBldmVudCBsaXN0ZW5lclxuICogQHBhcmFtIGV2ZW50SWQgdGhlIGV2ZW50IElELlxuICogQHBhcmFtIFtoYW5kbGVyXSBvcHRpb25hbCwgdGhlIHNwZWNpZmljIGhhbmRsZXIgdG8gdW5iaW5kXG4gKi9cbkppdHNpVHJhY2sucHJvdG90eXBlLm9mZiA9IGZ1bmN0aW9uIChldmVudElkLCBoYW5kbGVyKSB7XG4gICAgaWYodGhpcy5ldmVudEVtaXR0ZXIpXG4gICAgICAgIHRoaXMuZXZlbnRFbWl0dGVyLnJlbW92ZUxpc3RlbmVyKGV2ZW50SWQsIGhhbmRsZXIpO1xufVxuXG4vLyBDb21tb24gYWxpYXNlcyBmb3IgZXZlbnQgZW1pdHRlclxuSml0c2lUcmFjay5wcm90b3R5cGUuYWRkRXZlbnRMaXN0ZW5lciA9IEppdHNpVHJhY2sucHJvdG90eXBlLm9uO1xuSml0c2lUcmFjay5wcm90b3R5cGUucmVtb3ZlRXZlbnRMaXN0ZW5lciA9IEppdHNpVHJhY2sucHJvdG90eXBlLm9mZjtcblxuXG4vKipcbiAqIFNldHMgdGhlIGF1ZGlvIGxldmVsIGZvciB0aGUgc3RyZWFtXG4gKiBAcGFyYW0gYXVkaW9MZXZlbCB0aGUgbmV3IGF1ZGlvIGxldmVsXG4gKi9cbkppdHNpVHJhY2sucHJvdG90eXBlLnNldEF1ZGlvTGV2ZWwgPSBmdW5jdGlvbiAoYXVkaW9MZXZlbCkge1xuICAgIGlmKHRoaXMuYXVkaW9MZXZlbCAhPT0gYXVkaW9MZXZlbCkge1xuICAgICAgICB0aGlzLmV2ZW50RW1pdHRlci5lbWl0KEppdHNpVHJhY2tFdmVudHMuVFJBQ0tfQVVESU9fTEVWRUxfQ0hBTkdFRCxcbiAgICAgICAgICAgIGF1ZGlvTGV2ZWwpO1xuICAgICAgICB0aGlzLmF1ZGlvTGV2ZWwgPSBhdWRpb0xldmVsO1xuICAgIH1cbiB9XG5cbm1vZHVsZS5leHBvcnRzID0gSml0c2lUcmFjaztcbiIsIi8qIGdsb2JhbCBBUFAgKi9cbnZhciBFdmVudEVtaXR0ZXIgPSByZXF1aXJlKFwiZXZlbnRzXCIpO1xudmFyIFJUQ0Jyb3dzZXJUeXBlID0gcmVxdWlyZShcIi4vUlRDQnJvd3NlclR5cGVcIik7XG52YXIgUlRDVXRpbHMgPSByZXF1aXJlKFwiLi9SVENVdGlscy5qc1wiKTtcbnZhciBKaXRzaVRyYWNrID0gcmVxdWlyZShcIi4vSml0c2lUcmFja1wiKTtcbnZhciBKaXRzaUxvY2FsVHJhY2sgPSByZXF1aXJlKFwiLi9KaXRzaUxvY2FsVHJhY2suanNcIik7XG52YXIgRGF0YUNoYW5uZWxzID0gcmVxdWlyZShcIi4vRGF0YUNoYW5uZWxzXCIpO1xudmFyIEppdHNpUmVtb3RlVHJhY2sgPSByZXF1aXJlKFwiLi9KaXRzaVJlbW90ZVRyYWNrLmpzXCIpO1xudmFyIERlc2t0b3BTaGFyaW5nRXZlbnRUeXBlc1xuICAgID0gcmVxdWlyZShcIi4uLy4uL3NlcnZpY2UvZGVza3RvcHNoYXJpbmcvRGVza3RvcFNoYXJpbmdFdmVudFR5cGVzXCIpO1xudmFyIE1lZGlhU3RyZWFtVHlwZSA9IHJlcXVpcmUoXCIuLi8uLi9zZXJ2aWNlL1JUQy9NZWRpYVN0cmVhbVR5cGVzXCIpO1xudmFyIFJUQ0V2ZW50cyA9IHJlcXVpcmUoXCIuLi8uLi9zZXJ2aWNlL1JUQy9SVENFdmVudHMuanNcIik7XG5cbmZ1bmN0aW9uIGNyZWF0ZUxvY2FsVHJhY2tzKHN0cmVhbXMpIHtcbiAgICB2YXIgbmV3U3RyZWFtcyA9IFtdXG4gICAgZm9yICh2YXIgaSA9IDA7IGkgPCBzdHJlYW1zLmxlbmd0aDsgaSsrKSB7XG4gICAgICAgIHZhciBsb2NhbFN0cmVhbSA9IG5ldyBKaXRzaUxvY2FsVHJhY2soc3RyZWFtc1tpXS5zdHJlYW0sXG4gICAgICAgICAgICBzdHJlYW1zW2ldLnZpZGVvVHlwZSwgc3RyZWFtc1tpXS5yZXNvbHV0aW9uKTtcbiAgICAgICAgbmV3U3RyZWFtcy5wdXNoKGxvY2FsU3RyZWFtKTtcbiAgICAgICAgaWYgKHN0cmVhbXNbaV0uaXNNdXRlZCA9PT0gdHJ1ZSlcbiAgICAgICAgICAgIGxvY2FsU3RyZWFtLnNldE11dGUodHJ1ZSk7XG4gICAgfVxuICAgIHJldHVybiBuZXdTdHJlYW1zO1xufVxuXG5mdW5jdGlvbiBSVEMocm9vbSwgb3B0aW9ucykge1xuICAgIHRoaXMucm9vbSA9IHJvb207XG4gICAgdGhpcy5sb2NhbFN0cmVhbXMgPSBbXTtcbiAgICAvL0ZJWE1FOiB3ZSBzaG91bGQgc3RhcnQgcmVtb3ZpbmcgdGhvc2Ugc3RyZWFtcy5cbiAgICAvL0ZJWE1FOiBXZSBzaG91bGQgc3VwcG9ydCBtdWx0aXBsZSBzdHJlYW1zIHBlciBqaWQuXG4gICAgdGhpcy5yZW1vdGVTdHJlYW1zID0ge307XG4gICAgdGhpcy5sb2NhbEF1ZGlvID0gbnVsbDtcbiAgICB0aGlzLmxvY2FsVmlkZW8gPSBudWxsO1xuICAgIHRoaXMuZXZlbnRFbWl0dGVyID0gbmV3IEV2ZW50RW1pdHRlcigpO1xuICAgIHZhciBzZWxmID0gdGhpcztcbiAgICB0aGlzLm9wdGlvbnMgPSBvcHRpb25zIHx8IHt9O1xuICAgIHJvb20uYWRkUHJlc2VuY2VMaXN0ZW5lcihcInZpZGVvbXV0ZWRcIiwgZnVuY3Rpb24gKHZhbHVlcywgZnJvbSkge1xuICAgICAgICBpZihzZWxmLnJlbW90ZVN0cmVhbXNbZnJvbV0pIHtcbiAgICAgICAgICAgIHNlbGYucmVtb3RlU3RyZWFtc1tmcm9tXVtKaXRzaVRyYWNrLlZJREVPXS5zZXRNdXRlKHZhbHVlcy52YWx1ZSA9PSBcInRydWVcIik7XG4gICAgICAgIH1cbiAgICB9KTtcbiAgICByb29tLmFkZFByZXNlbmNlTGlzdGVuZXIoXCJhdWRpb211dGVkXCIsIGZ1bmN0aW9uICh2YWx1ZXMsIGZyb20pIHtcbiAgICAgICAgaWYoc2VsZi5yZW1vdGVTdHJlYW1zW2Zyb21dKSB7XG4gICAgICAgICAgICBzZWxmLnJlbW90ZVN0cmVhbXNbZnJvbV1bSml0c2lUcmFjay5BVURJT10uc2V0TXV0ZSh2YWx1ZXMudmFsdWUgPT0gXCJ0cnVlXCIpO1xuICAgICAgICB9XG4gICAgfSk7XG59XG5cbi8qKlxuICogQ3JlYXRlcyB0aGUgbG9jYWwgTWVkaWFTdHJlYW1zLlxuICogQHBhcmFtIHtPYmplY3R9IFtvcHRpb25zXSBvcHRpb25hbCBwYXJhbWV0ZXJzXG4gKiBAcGFyYW0ge0FycmF5fSBvcHRpb25zLmRldmljZXMgdGhlIGRldmljZXMgdGhhdCB3aWxsIGJlIHJlcXVlc3RlZFxuICogQHBhcmFtIHtzdHJpbmd9IG9wdGlvbnMucmVzb2x1dGlvbiByZXNvbHV0aW9uIGNvbnN0cmFpbnRzXG4gKiBAcGFyYW0ge2Jvb2x9IG9wdGlvbnMuZG9udENyZWF0ZUppdHNpVHJhY2sgaWYgPHR0PnRydWU8L3R0PiBvYmplY3RzIHdpdGggdGhlIGZvbGxvd2luZyBzdHJ1Y3R1cmUge3N0cmVhbTogdGhlIE1lZGlhIFN0cmVhbSxcbiAqIHR5cGU6IFwiYXVkaW9cIiBvciBcInZpZGVvXCIsIHZpZGVvVHlwZTogXCJjYW1lcmFcIiBvciBcImRlc2t0b3BcIn1cbiAqIHdpbGwgYmUgcmV0dXJuZWQgdHJvdWdoIHRoZSBQcm9taXNlLCBvdGhlcndpc2UgSml0c2lUcmFjayBvYmplY3RzIHdpbGwgYmUgcmV0dXJuZWQuXG4gKiBAcGFyYW0ge3N0cmluZ30gb3B0aW9ucy5jYW1lcmFEZXZpY2VJZFxuICogQHBhcmFtIHtzdHJpbmd9IG9wdGlvbnMubWljRGV2aWNlSWRcbiAqIEByZXR1cm5zIHsqfSBQcm9taXNlIG9iamVjdCB0aGF0IHdpbGwgcmVjZWl2ZSB0aGUgbmV3IEppdHNpVHJhY2tzXG4gKi9cblJUQy5vYnRhaW5BdWRpb0FuZFZpZGVvUGVybWlzc2lvbnMgPSBmdW5jdGlvbiAob3B0aW9ucykge1xuICAgIHJldHVybiBSVENVdGlscy5vYnRhaW5BdWRpb0FuZFZpZGVvUGVybWlzc2lvbnMob3B0aW9ucykudGhlbihjcmVhdGVMb2NhbFRyYWNrcyk7XG59XG5cblJUQy5wcm90b3R5cGUub25JbmNvbW1pbmdDYWxsID0gZnVuY3Rpb24oZXZlbnQpIHtcbiAgICBpZih0aGlzLm9wdGlvbnMuY29uZmlnLm9wZW5TY3RwKVxuICAgICAgICB0aGlzLmRhdGFDaGFubmVscyA9IG5ldyBEYXRhQ2hhbm5lbHMoZXZlbnQucGVlcmNvbm5lY3Rpb24sIHRoaXMuZXZlbnRFbWl0dGVyKTtcbiAgICBmb3IodmFyIGkgPSAwOyBpIDwgdGhpcy5sb2NhbFN0cmVhbXMubGVuZ3RoOyBpKyspXG4gICAgICAgIGlmKHRoaXMubG9jYWxTdHJlYW1zW2ldKVxuICAgICAgICB7XG4gICAgICAgICAgICB0aGlzLnJvb20uYWRkU3RyZWFtKHRoaXMubG9jYWxTdHJlYW1zW2ldLmdldE9yaWdpbmFsU3RyZWFtKCksIGZ1bmN0aW9uICgpIHt9KTtcbiAgICAgICAgfVxufVxuXG5SVEMucHJvdG90eXBlLnNlbGVjdGVkRW5kcG9pbnQgPSBmdW5jdGlvbiAoaWQpIHtcbiAgICBpZih0aGlzLmRhdGFDaGFubmVscylcbiAgICAgICAgdGhpcy5kYXRhQ2hhbm5lbHMuaGFuZGxlU2VsZWN0ZWRFbmRwb2ludEV2ZW50KGlkKTtcbn1cblxuUlRDLnByb3RvdHlwZS5waW5FbmRwb2ludCA9IGZ1bmN0aW9uIChpZCkge1xuICAgIGlmKHRoaXMuZGF0YUNoYW5uZWxzKVxuICAgICAgICB0aGlzLmRhdGFDaGFubmVscy5oYW5kbGVQaW5uZWRFbmRwb2ludEV2ZW50KGlkKTtcbn1cblxuUlRDLnByb3RvdHlwZS5hZGRMaXN0ZW5lciA9IGZ1bmN0aW9uICh0eXBlLCBsaXN0ZW5lcikge1xuICAgIHRoaXMuZXZlbnRFbWl0dGVyLm9uKHR5cGUsIGxpc3RlbmVyKTtcbn07XG5cblJUQy5wcm90b3R5cGUucmVtb3ZlTGlzdGVuZXIgPSBmdW5jdGlvbiAoZXZlbnRUeXBlLCBsaXN0ZW5lcikge1xuICAgIHRoaXMuZXZlbnRFbWl0dGVyLnJlbW92ZUxpc3RlbmVyKGV2ZW50VHlwZSwgbGlzdGVuZXIpO1xufTtcblxuUlRDLmFkZExpc3RlbmVyID0gZnVuY3Rpb24gKGV2ZW50VHlwZSwgbGlzdGVuZXIpIHtcbiAgICBSVENVdGlscy5hZGRMaXN0ZW5lcihldmVudFR5cGUsIGxpc3RlbmVyKTtcbn1cblxuUlRDLnJlbW92ZUxpc3RlbmVyID0gZnVuY3Rpb24gKGV2ZW50VHlwZSwgbGlzdGVuZXIpIHtcbiAgICBSVENVdGlscy5yZW1vdmVMaXN0ZW5lcihldmVudFR5cGUsIGxpc3RlbmVyKVxufVxuXG5SVEMuaXNSVENSZWFkeSA9IGZ1bmN0aW9uICgpIHtcbiAgICByZXR1cm4gUlRDVXRpbHMuaXNSVENSZWFkeSgpO1xufVxuXG5SVEMuaW5pdCA9IGZ1bmN0aW9uIChvcHRpb25zKSB7XG4gICAgdGhpcy5vcHRpb25zID0gb3B0aW9ucyB8fCB7fTtcbiAgICByZXR1cm4gUlRDVXRpbHMuaW5pdCh0aGlzLm9wdGlvbnMpO1xufVxuXG5SVEMuZ2V0RGV2aWNlQXZhaWxhYmlsaXR5ID0gZnVuY3Rpb24gKCkge1xuICAgIHJldHVybiBSVENVdGlscy5nZXREZXZpY2VBdmFpbGFiaWxpdHkoKTtcbn1cblxuUlRDLnByb3RvdHlwZS5hZGRMb2NhbFN0cmVhbSA9IGZ1bmN0aW9uIChzdHJlYW0pIHtcbiAgICB0aGlzLmxvY2FsU3RyZWFtcy5wdXNoKHN0cmVhbSk7XG4gICAgc3RyZWFtLl9zZXRSVEModGhpcyk7XG5cbiAgICBpZiAoc3RyZWFtLnR5cGUgPT0gXCJhdWRpb1wiKSB7XG4gICAgICAgIHRoaXMubG9jYWxBdWRpbyA9IHN0cmVhbTtcbiAgICB9IGVsc2Uge1xuICAgICAgICB0aGlzLmxvY2FsVmlkZW8gPSBzdHJlYW07XG4gICAgfVxufTtcblxuUlRDLnByb3RvdHlwZS5yZW1vdmVMb2NhbFN0cmVhbSA9IGZ1bmN0aW9uIChzdHJlYW0pIHtcbiAgICBmb3IodmFyIGkgPSAwOyBpIDwgdGhpcy5sb2NhbFN0cmVhbXMubGVuZ3RoOyBpKyspIHtcbiAgICAgICAgaWYodGhpcy5sb2NhbFN0cmVhbXNbaV0uZ2V0T3JpZ2luYWxTdHJlYW0oKSA9PT0gc3RyZWFtKSB7XG4gICAgICAgICAgICBkZWxldGUgdGhpcy5sb2NhbFN0cmVhbXNbaV07XG4gICAgICAgICAgICByZXR1cm47XG4gICAgICAgIH1cbiAgICB9XG59O1xuXG5SVEMucHJvdG90eXBlLmNyZWF0ZVJlbW90ZVN0cmVhbSA9IGZ1bmN0aW9uIChkYXRhLCBzaWQsIHRoZXNzcmMpIHtcbiAgICB2YXIgcmVtb3RlU3RyZWFtID0gbmV3IEppdHNpUmVtb3RlVHJhY2sodGhpcywgZGF0YSwgc2lkLCB0aGVzc3JjKTtcbiAgICBpZighZGF0YS5wZWVyamlkKVxuICAgICAgICByZXR1cm47XG4gICAgdmFyIGppZCA9IGRhdGEucGVlcmppZDtcbiAgICBpZighdGhpcy5yZW1vdGVTdHJlYW1zW2ppZF0pIHtcbiAgICAgICAgdGhpcy5yZW1vdGVTdHJlYW1zW2ppZF0gPSB7fTtcbiAgICB9XG4gICAgdGhpcy5yZW1vdGVTdHJlYW1zW2ppZF1bcmVtb3RlU3RyZWFtLnR5cGVdPSByZW1vdGVTdHJlYW07XG4gICAgcmV0dXJuIHJlbW90ZVN0cmVhbTtcbn07XG5cblJUQy5nZXRQQ0NvbnN0cmFpbnRzID0gZnVuY3Rpb24gKCkge1xuICAgIHJldHVybiBSVENVdGlscy5wY19jb25zdHJhaW50cztcbn07XG5cblJUQy5hdHRhY2hNZWRpYVN0cmVhbSA9ICBmdW5jdGlvbiAoZWxTZWxlY3Rvciwgc3RyZWFtKSB7XG4gICAgUlRDVXRpbHMuYXR0YWNoTWVkaWFTdHJlYW0oZWxTZWxlY3Rvciwgc3RyZWFtKTtcbn07XG5cblJUQy5nZXRTdHJlYW1JRCA9IGZ1bmN0aW9uIChzdHJlYW0pIHtcbiAgICByZXR1cm4gUlRDVXRpbHMuZ2V0U3RyZWFtSUQoc3RyZWFtKTtcbn07XG5cblJUQy5nZXRWaWRlb1NyYyA9IGZ1bmN0aW9uIChlbGVtZW50KSB7XG4gICAgcmV0dXJuIFJUQ1V0aWxzLmdldFZpZGVvU3JjKGVsZW1lbnQpO1xufTtcblxuLyoqXG4gKiBSZXR1cm5zIHRydWUgaWYgcmV0cmlldmluZyB0aGUgdGhlIGxpc3Qgb2YgaW5wdXQgZGV2aWNlcyBpcyBzdXBwb3J0ZWQgYW5kXG4gKiBmYWxzZSBpZiBub3QuXG4gKi9cblJUQy5pc0RldmljZUxpc3RBdmFpbGFibGUgPSBmdW5jdGlvbiAoKSB7XG4gICAgcmV0dXJuIFJUQ1V0aWxzLmlzRGV2aWNlTGlzdEF2YWlsYWJsZSgpO1xufTtcblxuLyoqXG4gKiBSZXR1cm5zIHRydWUgaWYgY2hhbmdpbmcgdGhlIGNhbWVyYSAvIG1pY3JvcGhvbmUgZGV2aWNlIGlzIHN1cHBvcnRlZCBhbmRcbiAqIGZhbHNlIGlmIG5vdC5cbiAqL1xuUlRDLmlzRGV2aWNlQ2hhbmdlQXZhaWxhYmxlID0gZnVuY3Rpb24gKCkge1xuICAgIHJldHVybiBSVENVdGlscy5pc0RldmljZUNoYW5nZUF2YWlsYWJsZSgpO1xufVxuLyoqXG4gKiBBbGxvd3MgdG8gcmVjZWl2ZSBsaXN0IG9mIGF2YWlsYWJsZSBjYW1lcmFzL21pY3JvcGhvbmVzLlxuICogQHBhcmFtIHtmdW5jdGlvbn0gY2FsbGJhY2sgd291bGQgcmVjZWl2ZSBhcnJheSBvZiBkZXZpY2VzIGFzIGFuIGFyZ3VtZW50XG4gKi9cblJUQy5lbnVtZXJhdGVEZXZpY2VzID0gZnVuY3Rpb24gKGNhbGxiYWNrKSB7XG4gICAgUlRDVXRpbHMuZW51bWVyYXRlRGV2aWNlcyhjYWxsYmFjayk7XG59O1xuXG5SVEMuc2V0VmlkZW9TcmMgPSBmdW5jdGlvbiAoZWxlbWVudCwgc3JjKSB7XG4gICAgUlRDVXRpbHMuc2V0VmlkZW9TcmMoZWxlbWVudCwgc3JjKTtcbn07XG5cbi8qKlxuICogQSBtZXRob2QgdG8gaGFuZGxlIHN0b3BwaW5nIG9mIHRoZSBzdHJlYW0uXG4gKiBPbmUgcG9pbnQgdG8gaGFuZGxlIHRoZSBkaWZmZXJlbmNlcyBpbiB2YXJpb3VzIGltcGxlbWVudGF0aW9ucy5cbiAqIEBwYXJhbSBtZWRpYVN0cmVhbSBNZWRpYVN0cmVhbSBvYmplY3QgdG8gc3RvcC5cbiAqL1xuUlRDLnN0b3BNZWRpYVN0cmVhbSA9IGZ1bmN0aW9uIChtZWRpYVN0cmVhbSkge1xuICAgIFJUQ1V0aWxzLnN0b3BNZWRpYVN0cmVhbShtZWRpYVN0cmVhbSk7XG59O1xuXG4vKipcbiAqIFJldHVybnMgd2hldGhlciB0aGUgZGVza3RvcCBzaGFyaW5nIGlzIGVuYWJsZWQgb3Igbm90LlxuICogQHJldHVybnMge2Jvb2xlYW59XG4gKi9cblJUQy5pc0Rlc2t0b3BTaGFyaW5nRW5hYmxlZCA9IGZ1bmN0aW9uICgpIHtcbiAgICByZXR1cm4gUlRDVXRpbHMuaXNEZXNrdG9wU2hhcmluZ0VuYWJsZWQoKTtcbn1cblxuUlRDLnByb3RvdHlwZS5nZXRWaWRlb0VsZW1lbnROYW1lID0gZnVuY3Rpb24gKCkge1xuICAgIHJldHVybiBSVENCcm93c2VyVHlwZS5pc1RlbWFzeXNQbHVnaW5Vc2VkKCkgPyAnb2JqZWN0JyA6ICd2aWRlbyc7XG59O1xuXG5SVEMucHJvdG90eXBlLmRpc3Bvc2UgPSBmdW5jdGlvbigpIHtcbn07XG5cblJUQy5wcm90b3R5cGUuc3dpdGNoVmlkZW9TdHJlYW1zID0gZnVuY3Rpb24gKG5ld1N0cmVhbSkge1xuICAgIHRoaXMubG9jYWxWaWRlby5zdHJlYW0gPSBuZXdTdHJlYW07XG5cbiAgICB0aGlzLmxvY2FsU3RyZWFtcyA9IFtdO1xuXG4gICAgLy9pbiBmaXJlZm94IHdlIGhhdmUgb25seSBvbmUgc3RyZWFtIG9iamVjdFxuICAgIGlmICh0aGlzLmxvY2FsQXVkaW8uZ2V0T3JpZ2luYWxTdHJlYW0oKSAhPSBuZXdTdHJlYW0pXG4gICAgICAgIHRoaXMubG9jYWxTdHJlYW1zLnB1c2godGhpcy5sb2NhbEF1ZGlvKTtcbiAgICB0aGlzLmxvY2FsU3RyZWFtcy5wdXNoKHRoaXMubG9jYWxWaWRlbyk7XG59O1xuXG5SVEMucHJvdG90eXBlLnNldEF1ZGlvTGV2ZWwgPSBmdW5jdGlvbiAoamlkLCBhdWRpb0xldmVsKSB7XG4gICAgaWYodGhpcy5yZW1vdGVTdHJlYW1zW2ppZF0gJiYgdGhpcy5yZW1vdGVTdHJlYW1zW2ppZF1bSml0c2lUcmFjay5BVURJT10pXG4gICAgICAgIHRoaXMucmVtb3RlU3RyZWFtc1tqaWRdW0ppdHNpVHJhY2suQVVESU9dLnNldEF1ZGlvTGV2ZWwoYXVkaW9MZXZlbCk7XG59XG5tb2R1bGUuZXhwb3J0cyA9IFJUQztcbiIsIlxudmFyIGN1cnJlbnRCcm93c2VyO1xuXG52YXIgYnJvd3NlclZlcnNpb247XG5cbnZhciBpc0FuZHJvaWQ7XG5cbnZhciBSVENCcm93c2VyVHlwZSA9IHtcblxuICAgIFJUQ19CUk9XU0VSX0NIUk9NRTogXCJydGNfYnJvd3Nlci5jaHJvbWVcIixcblxuICAgIFJUQ19CUk9XU0VSX09QRVJBOiBcInJ0Y19icm93c2VyLm9wZXJhXCIsXG5cbiAgICBSVENfQlJPV1NFUl9GSVJFRk9YOiBcInJ0Y19icm93c2VyLmZpcmVmb3hcIixcblxuICAgIFJUQ19CUk9XU0VSX0lFWFBMT1JFUjogXCJydGNfYnJvd3Nlci5pZXhwbG9yZXJcIixcblxuICAgIFJUQ19CUk9XU0VSX1NBRkFSSTogXCJydGNfYnJvd3Nlci5zYWZhcmlcIixcblxuICAgIGdldEJyb3dzZXJUeXBlOiBmdW5jdGlvbiAoKSB7XG4gICAgICAgIHJldHVybiBjdXJyZW50QnJvd3NlcjtcbiAgICB9LFxuXG4gICAgaXNDaHJvbWU6IGZ1bmN0aW9uICgpIHtcbiAgICAgICAgcmV0dXJuIGN1cnJlbnRCcm93c2VyID09PSBSVENCcm93c2VyVHlwZS5SVENfQlJPV1NFUl9DSFJPTUU7XG4gICAgfSxcblxuICAgIGlzT3BlcmE6IGZ1bmN0aW9uICgpIHtcbiAgICAgICAgcmV0dXJuIGN1cnJlbnRCcm93c2VyID09PSBSVENCcm93c2VyVHlwZS5SVENfQlJPV1NFUl9PUEVSQTtcbiAgICB9LFxuICAgIGlzRmlyZWZveDogZnVuY3Rpb24gKCkge1xuICAgICAgICByZXR1cm4gY3VycmVudEJyb3dzZXIgPT09IFJUQ0Jyb3dzZXJUeXBlLlJUQ19CUk9XU0VSX0ZJUkVGT1g7XG4gICAgfSxcblxuICAgIGlzSUV4cGxvcmVyOiBmdW5jdGlvbiAoKSB7XG4gICAgICAgIHJldHVybiBjdXJyZW50QnJvd3NlciA9PT0gUlRDQnJvd3NlclR5cGUuUlRDX0JST1dTRVJfSUVYUExPUkVSO1xuICAgIH0sXG5cbiAgICBpc1NhZmFyaTogZnVuY3Rpb24gKCkge1xuICAgICAgICByZXR1cm4gY3VycmVudEJyb3dzZXIgPT09IFJUQ0Jyb3dzZXJUeXBlLlJUQ19CUk9XU0VSX1NBRkFSSTtcbiAgICB9LFxuICAgIGlzVGVtYXN5c1BsdWdpblVzZWQ6IGZ1bmN0aW9uICgpIHtcbiAgICAgICAgcmV0dXJuIFJUQ0Jyb3dzZXJUeXBlLmlzSUV4cGxvcmVyKCkgfHwgUlRDQnJvd3NlclR5cGUuaXNTYWZhcmkoKTtcbiAgICB9LFxuICAgIGdldEZpcmVmb3hWZXJzaW9uOiBmdW5jdGlvbiAoKSB7XG4gICAgICAgIHJldHVybiBSVENCcm93c2VyVHlwZS5pc0ZpcmVmb3goKSA/IGJyb3dzZXJWZXJzaW9uIDogbnVsbDtcbiAgICB9LFxuXG4gICAgZ2V0Q2hyb21lVmVyc2lvbjogZnVuY3Rpb24gKCkge1xuICAgICAgICByZXR1cm4gUlRDQnJvd3NlclR5cGUuaXNDaHJvbWUoKSA/IGJyb3dzZXJWZXJzaW9uIDogbnVsbDtcbiAgICB9LFxuXG4gICAgdXNlc1BsYW5COiBmdW5jdGlvbigpIHtcbiAgICAgICAgcmV0dXJuIFJUQ0Jyb3dzZXJUeXBlLmlzQ2hyb21lKCkgfHwgUlRDQnJvd3NlclR5cGUuaXNPcGVyYSgpIHx8XG4gICAgICAgICAgICBSVENCcm93c2VyVHlwZS5pc1RlbWFzeXNQbHVnaW5Vc2VkKCk7XG4gICAgfSxcblxuICAgIHVzZXNVbmlmaWVkUGxhbjogZnVuY3Rpb24oKSB7XG4gICAgICAgIHJldHVybiBSVENCcm93c2VyVHlwZS5pc0ZpcmVmb3goKTtcbiAgICB9LFxuXG4gICAgLyoqXG4gICAgICogV2hldGhlciB0aGUgYnJvd3NlciBpcyBydW5uaW5nIG9uIGFuIGFuZHJvaWQgZGV2aWNlLlxuICAgICAqL1xuICAgIGlzQW5kcm9pZDogZnVuY3Rpb24oKSB7XG4gICAgICAgIHJldHVybiBpc0FuZHJvaWQ7XG4gICAgfVxuXG4gICAgLy8gQWRkIHZlcnNpb24gZ2V0dGVycyBmb3Igb3RoZXIgYnJvd3NlcnMgd2hlbiBuZWVkZWRcbn07XG5cbi8vIGRldGVjdE9wZXJhKCkgbXVzdCBiZSBjYWxsZWQgYmVmb3JlIGRldGVjdENocm9tZSgpICEhIVxuLy8gb3RoZXJ3aXNlIE9wZXJhIHdpbCBiZSBkZXRlY3RlZCBhcyBDaHJvbWVcbmZ1bmN0aW9uIGRldGVjdENocm9tZSgpIHtcbiAgICBpZiAobmF2aWdhdG9yLndlYmtpdEdldFVzZXJNZWRpYSkge1xuICAgICAgICBjdXJyZW50QnJvd3NlciA9IFJUQ0Jyb3dzZXJUeXBlLlJUQ19CUk9XU0VSX0NIUk9NRTtcbiAgICAgICAgdmFyIHVzZXJBZ2VudCA9IG5hdmlnYXRvci51c2VyQWdlbnQudG9Mb3dlckNhc2UoKTtcbiAgICAgICAgLy8gV2UgY2FuIGFzc3VtZSB0aGF0IHVzZXIgYWdlbnQgaXMgY2hyb21lLCBiZWNhdXNlIGl0J3NcbiAgICAgICAgLy8gZW5mb3JjZWQgd2hlbiAnZXh0JyBzdHJlYW1pbmcgbWV0aG9kIGlzIHNldFxuICAgICAgICB2YXIgdmVyID0gcGFyc2VJbnQodXNlckFnZW50Lm1hdGNoKC9jaHJvbWVcXC8oXFxkKylcXC4vKVsxXSwgMTApO1xuICAgICAgICBjb25zb2xlLmxvZyhcIlRoaXMgYXBwZWFycyB0byBiZSBDaHJvbWUsIHZlcjogXCIgKyB2ZXIpO1xuICAgICAgICByZXR1cm4gdmVyO1xuICAgIH1cbiAgICByZXR1cm4gbnVsbDtcbn1cblxuZnVuY3Rpb24gZGV0ZWN0T3BlcmEoKSB7XG4gICAgdmFyIHVzZXJBZ2VudCA9IG5hdmlnYXRvci51c2VyQWdlbnQ7XG4gICAgaWYgKHVzZXJBZ2VudC5tYXRjaCgvT3BlcmF8T1BSLykpIHtcbiAgICAgICAgY3VycmVudEJyb3dzZXIgPSBSVENCcm93c2VyVHlwZS5SVENfQlJPV1NFUl9PUEVSQTtcbiAgICAgICAgdmFyIHZlcnNpb24gPSB1c2VyQWdlbnQubWF0Y2goLyhPcGVyYXxPUFIpID9cXC8/KFxcZCspXFwuPy8pWzJdO1xuICAgICAgICBjb25zb2xlLmluZm8oXCJUaGlzIGFwcGVhcnMgdG8gYmUgT3BlcmEsIHZlcjogXCIgKyB2ZXJzaW9uKTtcbiAgICAgICAgcmV0dXJuIHZlcnNpb247XG4gICAgfVxuICAgIHJldHVybiBudWxsO1xufVxuXG5mdW5jdGlvbiBkZXRlY3RGaXJlZm94KCkge1xuICAgIGlmIChuYXZpZ2F0b3IubW96R2V0VXNlck1lZGlhKSB7XG4gICAgICAgIGN1cnJlbnRCcm93c2VyID0gUlRDQnJvd3NlclR5cGUuUlRDX0JST1dTRVJfRklSRUZPWDtcbiAgICAgICAgdmFyIHZlcnNpb24gPSBwYXJzZUludChcbiAgICAgICAgICAgIG5hdmlnYXRvci51c2VyQWdlbnQubWF0Y2goL0ZpcmVmb3hcXC8oWzAtOV0rKVxcLi8pWzFdLCAxMCk7XG4gICAgICAgIGNvbnNvbGUubG9nKCdUaGlzIGFwcGVhcnMgdG8gYmUgRmlyZWZveCwgdmVyOiAnICsgdmVyc2lvbik7XG4gICAgICAgIHJldHVybiB2ZXJzaW9uO1xuICAgIH1cbiAgICByZXR1cm4gbnVsbDtcbn1cblxuZnVuY3Rpb24gZGV0ZWN0U2FmYXJpKCkge1xuICAgIGlmICgoL14oKD8hY2hyb21lKS4pKnNhZmFyaS9pLnRlc3QobmF2aWdhdG9yLnVzZXJBZ2VudCkpKSB7XG4gICAgICAgIGN1cnJlbnRCcm93c2VyID0gUlRDQnJvd3NlclR5cGUuUlRDX0JST1dTRVJfU0FGQVJJO1xuICAgICAgICBjb25zb2xlLmluZm8oXCJUaGlzIGFwcGVhcnMgdG8gYmUgU2FmYXJpXCIpO1xuICAgICAgICAvLyBGSVhNRSBkZXRlY3QgU2FmYXJpIHZlcnNpb24gd2hlbiBuZWVkZWRcbiAgICAgICAgcmV0dXJuIDE7XG4gICAgfVxuICAgIHJldHVybiBudWxsO1xufVxuXG5mdW5jdGlvbiBkZXRlY3RJRSgpIHtcbiAgICB2YXIgdmVyc2lvbjtcbiAgICB2YXIgdWEgPSB3aW5kb3cubmF2aWdhdG9yLnVzZXJBZ2VudDtcblxuICAgIHZhciBtc2llID0gdWEuaW5kZXhPZignTVNJRSAnKTtcbiAgICBpZiAobXNpZSA+IDApIHtcbiAgICAgICAgLy8gSUUgMTAgb3Igb2xkZXIgPT4gcmV0dXJuIHZlcnNpb24gbnVtYmVyXG4gICAgICAgIHZlcnNpb24gPSBwYXJzZUludCh1YS5zdWJzdHJpbmcobXNpZSArIDUsIHVhLmluZGV4T2YoJy4nLCBtc2llKSksIDEwKTtcbiAgICB9XG5cbiAgICB2YXIgdHJpZGVudCA9IHVhLmluZGV4T2YoJ1RyaWRlbnQvJyk7XG4gICAgaWYgKCF2ZXJzaW9uICYmIHRyaWRlbnQgPiAwKSB7XG4gICAgICAgIC8vIElFIDExID0+IHJldHVybiB2ZXJzaW9uIG51bWJlclxuICAgICAgICB2YXIgcnYgPSB1YS5pbmRleE9mKCdydjonKTtcbiAgICAgICAgdmVyc2lvbiA9IHBhcnNlSW50KHVhLnN1YnN0cmluZyhydiArIDMsIHVhLmluZGV4T2YoJy4nLCBydikpLCAxMCk7XG4gICAgfVxuXG4gICAgdmFyIGVkZ2UgPSB1YS5pbmRleE9mKCdFZGdlLycpO1xuICAgIGlmICghdmVyc2lvbiAmJiBlZGdlID4gMCkge1xuICAgICAgICAvLyBJRSAxMiA9PiByZXR1cm4gdmVyc2lvbiBudW1iZXJcbiAgICAgICAgdmVyc2lvbiA9IHBhcnNlSW50KHVhLnN1YnN0cmluZyhlZGdlICsgNSwgdWEuaW5kZXhPZignLicsIGVkZ2UpKSwgMTApO1xuICAgIH1cblxuICAgIGlmICh2ZXJzaW9uKSB7XG4gICAgICAgIGN1cnJlbnRCcm93c2VyID0gUlRDQnJvd3NlclR5cGUuUlRDX0JST1dTRVJfSUVYUExPUkVSO1xuICAgICAgICBjb25zb2xlLmluZm8oXCJUaGlzIGFwcGVhcnMgdG8gYmUgSUV4cGxvcmVyLCB2ZXI6IFwiICsgdmVyc2lvbik7XG4gICAgfVxuICAgIHJldHVybiB2ZXJzaW9uO1xufVxuXG5mdW5jdGlvbiBkZXRlY3RCcm93c2VyKCkge1xuICAgIHZhciB2ZXJzaW9uO1xuICAgIHZhciBkZXRlY3RvcnMgPSBbXG4gICAgICAgIGRldGVjdE9wZXJhLFxuICAgICAgICBkZXRlY3RDaHJvbWUsXG4gICAgICAgIGRldGVjdEZpcmVmb3gsXG4gICAgICAgIGRldGVjdElFLFxuICAgICAgICBkZXRlY3RTYWZhcmlcbiAgICBdO1xuICAgIC8vIFRyeSBhbGwgYnJvd3NlciBkZXRlY3RvcnNcbiAgICBmb3IgKHZhciBpID0gMDsgaSA8IGRldGVjdG9ycy5sZW5ndGg7IGkrKykge1xuICAgICAgICB2ZXJzaW9uID0gZGV0ZWN0b3JzW2ldKCk7XG4gICAgICAgIGlmICh2ZXJzaW9uKVxuICAgICAgICAgICAgcmV0dXJuIHZlcnNpb247XG4gICAgfVxuICAgIGNvbnNvbGUud2FybihcIkJyb3dzZXIgdHlwZSBkZWZhdWx0cyB0byBTYWZhcmkgdmVyIDFcIik7XG4gICAgY3VycmVudEJyb3dzZXIgPSBSVENCcm93c2VyVHlwZS5SVENfQlJPV1NFUl9TQUZBUkk7XG4gICAgcmV0dXJuIDE7XG59XG5cbmJyb3dzZXJWZXJzaW9uID0gZGV0ZWN0QnJvd3NlcigpO1xuaXNBbmRyb2lkID0gbmF2aWdhdG9yLnVzZXJBZ2VudC5pbmRleE9mKCdBbmRyb2lkJykgIT0gLTE7XG5cbm1vZHVsZS5leHBvcnRzID0gUlRDQnJvd3NlclR5cGU7IiwiLyogZ2xvYmFsIGNvbmZpZywgcmVxdWlyZSwgYXR0YWNoTWVkaWFTdHJlYW0sIGdldFVzZXJNZWRpYSxcbiAgIFJUQ1BlZXJDb25uZWN0aW9uLCBSVENTZXNzaW9uRGVzY3JpcHRpb24sIFJUQ0ljZUNhbmRpZGF0ZSwgTWVkaWFTdHJlYW1UcmFjayxcbiAgIG1velJUQ1BlZXJDb25uZWN0aW9uLCBtb3pSVENTZXNzaW9uRGVzY3JpcHRpb24sIG1velJUQ0ljZUNhbmRpZGF0ZSxcbiAgIHdlYmtpdFJUQ1BlZXJDb25uZWN0aW9uLCB3ZWJraXRNZWRpYVN0cmVhbSwgd2Via2l0VVJMXG4qL1xuLyoganNoaW50IC1XMTAxICovXG5cbnZhciBsb2dnZXIgPSByZXF1aXJlKFwiaml0c2ktbWVldC1sb2dnZXJcIikuZ2V0TG9nZ2VyKF9fZmlsZW5hbWUpO1xudmFyIFJUQ0Jyb3dzZXJUeXBlID0gcmVxdWlyZShcIi4vUlRDQnJvd3NlclR5cGVcIik7XG52YXIgUmVzb2x1dGlvbnMgPSByZXF1aXJlKFwiLi4vLi4vc2VydmljZS9SVEMvUmVzb2x1dGlvbnNcIik7XG52YXIgUlRDRXZlbnRzID0gcmVxdWlyZShcIi4uLy4uL3NlcnZpY2UvUlRDL1JUQ0V2ZW50c1wiKTtcbnZhciBBZGFwdGVySlMgPSByZXF1aXJlKFwiLi9hZGFwdGVyLnNjcmVlbnNoYXJlXCIpO1xudmFyIFNEUFV0aWwgPSByZXF1aXJlKFwiLi4veG1wcC9TRFBVdGlsXCIpO1xudmFyIEV2ZW50RW1pdHRlciA9IHJlcXVpcmUoXCJldmVudHNcIik7XG52YXIgc2NyZWVuT2J0YWluZXIgPSByZXF1aXJlKFwiLi9TY3JlZW5PYnRhaW5lclwiKTtcbnZhciBKaXRzaVRyYWNrRXJyb3JzID0gcmVxdWlyZShcIi4uLy4uL0ppdHNpVHJhY2tFcnJvcnNcIik7XG5cbnZhciBldmVudEVtaXR0ZXIgPSBuZXcgRXZlbnRFbWl0dGVyKCk7XG5cbnZhciBkZXZpY2VzID0ge1xuICAgIGF1ZGlvOiB0cnVlLFxuICAgIHZpZGVvOiB0cnVlXG59O1xuXG52YXIgcnRjUmVhZHkgPSBmYWxzZTtcblxuZnVuY3Rpb24gc2V0UmVzb2x1dGlvbkNvbnN0cmFpbnRzKGNvbnN0cmFpbnRzLCByZXNvbHV0aW9uKSB7XG4gICAgdmFyIGlzQW5kcm9pZCA9IFJUQ0Jyb3dzZXJUeXBlLmlzQW5kcm9pZCgpO1xuXG4gICAgaWYgKFJlc29sdXRpb25zW3Jlc29sdXRpb25dKSB7XG4gICAgICAgIGNvbnN0cmFpbnRzLnZpZGVvLm1hbmRhdG9yeS5taW5XaWR0aCA9IFJlc29sdXRpb25zW3Jlc29sdXRpb25dLndpZHRoO1xuICAgICAgICBjb25zdHJhaW50cy52aWRlby5tYW5kYXRvcnkubWluSGVpZ2h0ID0gUmVzb2x1dGlvbnNbcmVzb2x1dGlvbl0uaGVpZ2h0O1xuICAgIH1cbiAgICBlbHNlIGlmIChpc0FuZHJvaWQpIHtcbiAgICAgICAgLy8gRklYTUUgY2FuJ3QgcmVtZW1iZXIgaWYgdGhlIHB1cnBvc2Ugb2YgdGhpcyB3YXMgdG8gYWx3YXlzIHJlcXVlc3RcbiAgICAgICAgLy8gICAgICAgbG93IHJlc29sdXRpb24gb24gQW5kcm9pZCA/IGlmIHllcyBpdCBzaG91bGQgYmUgbW92ZWQgdXAgZnJvbnRcbiAgICAgICAgY29uc3RyYWludHMudmlkZW8ubWFuZGF0b3J5Lm1pbldpZHRoID0gMzIwO1xuICAgICAgICBjb25zdHJhaW50cy52aWRlby5tYW5kYXRvcnkubWluSGVpZ2h0ID0gMjQwO1xuICAgICAgICBjb25zdHJhaW50cy52aWRlby5tYW5kYXRvcnkubWF4RnJhbWVSYXRlID0gMTU7XG4gICAgfVxuXG4gICAgaWYgKGNvbnN0cmFpbnRzLnZpZGVvLm1hbmRhdG9yeS5taW5XaWR0aClcbiAgICAgICAgY29uc3RyYWludHMudmlkZW8ubWFuZGF0b3J5Lm1heFdpZHRoID1cbiAgICAgICAgICAgIGNvbnN0cmFpbnRzLnZpZGVvLm1hbmRhdG9yeS5taW5XaWR0aDtcbiAgICBpZiAoY29uc3RyYWludHMudmlkZW8ubWFuZGF0b3J5Lm1pbkhlaWdodClcbiAgICAgICAgY29uc3RyYWludHMudmlkZW8ubWFuZGF0b3J5Lm1heEhlaWdodCA9XG4gICAgICAgICAgICBjb25zdHJhaW50cy52aWRlby5tYW5kYXRvcnkubWluSGVpZ2h0O1xufVxuXG4vKipcbiAqIEBwYXJhbSB7c3RyaW5nW119IHVtIHJlcXVpcmVkIHVzZXIgbWVkaWEgdHlwZXNcbiAqXG4gKiBAcGFyYW0ge09iamVjdH0gW29wdGlvbnM9e31dIG9wdGlvbmFsIHBhcmFtZXRlcnNcbiAqIEBwYXJhbSB7c3RyaW5nfSBvcHRpb25zLnJlc29sdXRpb25cbiAqIEBwYXJhbSB7bnVtYmVyfSBvcHRpb25zLmJhbmR3aWR0aFxuICogQHBhcmFtIHtudW1iZXJ9IG9wdGlvbnMuZnBzXG4gKiBAcGFyYW0ge3N0cmluZ30gb3B0aW9ucy5kZXNrdG9wU3RyZWFtXG4gKiBAcGFyYW0ge3N0cmluZ30gb3B0aW9ucy5jYW1lcmFEZXZpY2VJZFxuICogQHBhcmFtIHtzdHJpbmd9IG9wdGlvbnMubWljRGV2aWNlSWRcbiAqIEBwYXJhbSB7Ym9vbH0gZmlyZWZveF9mYWtlX2RldmljZVxuICovXG5mdW5jdGlvbiBnZXRDb25zdHJhaW50cyh1bSwgb3B0aW9ucykge1xuICAgIHZhciBjb25zdHJhaW50cyA9IHthdWRpbzogZmFsc2UsIHZpZGVvOiBmYWxzZX07XG5cbiAgICBpZiAodW0uaW5kZXhPZigndmlkZW8nKSA+PSAwKSB7XG4gICAgICAgIC8vIHNhbWUgYmVoYXZpb3VyIGFzIHRydWVcbiAgICAgICAgY29uc3RyYWludHMudmlkZW8gPSB7IG1hbmRhdG9yeToge30sIG9wdGlvbmFsOiBbXSB9O1xuXG4gICAgICAgIGlmIChvcHRpb25zLmNhbWVyYURldmljZUlkKSB7XG4gICAgICAgICAgICBjb25zdHJhaW50cy52aWRlby5vcHRpb25hbC5wdXNoKHtcbiAgICAgICAgICAgICAgICBzb3VyY2VJZDogb3B0aW9ucy5jYW1lcmFEZXZpY2VJZFxuICAgICAgICAgICAgfSk7XG4gICAgICAgIH1cblxuICAgICAgICBjb25zdHJhaW50cy52aWRlby5vcHRpb25hbC5wdXNoKHsgZ29vZ0xlYWt5QnVja2V0OiB0cnVlIH0pO1xuXG4gICAgICAgIHNldFJlc29sdXRpb25Db25zdHJhaW50cyhjb25zdHJhaW50cywgb3B0aW9ucy5yZXNvbHV0aW9uKTtcbiAgICB9XG4gICAgaWYgKHVtLmluZGV4T2YoJ2F1ZGlvJykgPj0gMCkge1xuICAgICAgICBpZiAoIVJUQ0Jyb3dzZXJUeXBlLmlzRmlyZWZveCgpKSB7XG4gICAgICAgICAgICAvLyBzYW1lIGJlaGF2aW91ciBhcyB0cnVlXG4gICAgICAgICAgICBjb25zdHJhaW50cy5hdWRpbyA9IHsgbWFuZGF0b3J5OiB7fSwgb3B0aW9uYWw6IFtdfTtcbiAgICAgICAgICAgIGlmIChvcHRpb25zLm1pY0RldmljZUlkKSB7XG4gICAgICAgICAgICAgICAgY29uc3RyYWludHMuYXVkaW8ub3B0aW9uYWwucHVzaCh7XG4gICAgICAgICAgICAgICAgICAgIHNvdXJjZUlkOiBvcHRpb25zLm1pY0RldmljZUlkXG4gICAgICAgICAgICAgICAgfSk7XG4gICAgICAgICAgICB9XG4gICAgICAgICAgICAvLyBpZiBpdCBpcyBnb29kIGVub3VnaCBmb3IgaGFuZ291dHMuLi5cbiAgICAgICAgICAgIGNvbnN0cmFpbnRzLmF1ZGlvLm9wdGlvbmFsLnB1c2goXG4gICAgICAgICAgICAgICAge2dvb2dFY2hvQ2FuY2VsbGF0aW9uOiB0cnVlfSxcbiAgICAgICAgICAgICAgICB7Z29vZ0F1dG9HYWluQ29udHJvbDogdHJ1ZX0sXG4gICAgICAgICAgICAgICAge2dvb2dOb2lzZVN1cHJlc3Npb246IHRydWV9LFxuICAgICAgICAgICAgICAgIHtnb29nSGlnaHBhc3NGaWx0ZXI6IHRydWV9LFxuICAgICAgICAgICAgICAgIHtnb29nTm9pc2VzdXBwcmVzc2lvbjI6IHRydWV9LFxuICAgICAgICAgICAgICAgIHtnb29nRWNob0NhbmNlbGxhdGlvbjI6IHRydWV9LFxuICAgICAgICAgICAgICAgIHtnb29nQXV0b0dhaW5Db250cm9sMjogdHJ1ZX1cbiAgICAgICAgICAgICk7XG4gICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICBpZiAob3B0aW9ucy5taWNEZXZpY2VJZCkge1xuICAgICAgICAgICAgICAgIGNvbnN0cmFpbnRzLmF1ZGlvID0ge1xuICAgICAgICAgICAgICAgICAgICBtYW5kYXRvcnk6IHt9LFxuICAgICAgICAgICAgICAgICAgICBvcHRpb25hbDogW3tcbiAgICAgICAgICAgICAgICAgICAgICAgIHNvdXJjZUlkOiBvcHRpb25zLm1pY0RldmljZUlkXG4gICAgICAgICAgICAgICAgICAgIH1dfTtcbiAgICAgICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICAgICAgY29uc3RyYWludHMuYXVkaW8gPSB0cnVlO1xuICAgICAgICAgICAgfVxuICAgICAgICB9XG4gICAgfVxuICAgIGlmICh1bS5pbmRleE9mKCdzY3JlZW4nKSA+PSAwKSB7XG4gICAgICAgIGlmIChSVENCcm93c2VyVHlwZS5pc0Nocm9tZSgpKSB7XG4gICAgICAgICAgICBjb25zdHJhaW50cy52aWRlbyA9IHtcbiAgICAgICAgICAgICAgICBtYW5kYXRvcnk6IHtcbiAgICAgICAgICAgICAgICAgICAgY2hyb21lTWVkaWFTb3VyY2U6IFwic2NyZWVuXCIsXG4gICAgICAgICAgICAgICAgICAgIGdvb2dMZWFreUJ1Y2tldDogdHJ1ZSxcbiAgICAgICAgICAgICAgICAgICAgbWF4V2lkdGg6IHdpbmRvdy5zY3JlZW4ud2lkdGgsXG4gICAgICAgICAgICAgICAgICAgIG1heEhlaWdodDogd2luZG93LnNjcmVlbi5oZWlnaHQsXG4gICAgICAgICAgICAgICAgICAgIG1heEZyYW1lUmF0ZTogM1xuICAgICAgICAgICAgICAgIH0sXG4gICAgICAgICAgICAgICAgb3B0aW9uYWw6IFtdXG4gICAgICAgICAgICB9O1xuICAgICAgICB9IGVsc2UgaWYgKFJUQ0Jyb3dzZXJUeXBlLmlzVGVtYXN5c1BsdWdpblVzZWQoKSkge1xuICAgICAgICAgICAgY29uc3RyYWludHMudmlkZW8gPSB7XG4gICAgICAgICAgICAgICAgb3B0aW9uYWw6IFtcbiAgICAgICAgICAgICAgICAgICAge1xuICAgICAgICAgICAgICAgICAgICAgICAgc291cmNlSWQ6IEFkYXB0ZXJKUy5XZWJSVENQbHVnaW4ucGx1Z2luLnNjcmVlbnNoYXJpbmdLZXlcbiAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgIF1cbiAgICAgICAgICAgIH07XG4gICAgICAgIH0gZWxzZSBpZiAoUlRDQnJvd3NlclR5cGUuaXNGaXJlZm94KCkpIHtcbiAgICAgICAgICAgIGNvbnN0cmFpbnRzLnZpZGVvID0ge1xuICAgICAgICAgICAgICAgIG1vek1lZGlhU291cmNlOiBcIndpbmRvd1wiLFxuICAgICAgICAgICAgICAgIG1lZGlhU291cmNlOiBcIndpbmRvd1wiXG4gICAgICAgICAgICB9O1xuXG4gICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICBsb2dnZXIuZXJyb3IoXG4gICAgICAgICAgICAgICAgXCInc2NyZWVuJyBXZWJSVEMgbWVkaWEgc291cmNlIGlzIHN1cHBvcnRlZCBvbmx5IGluIENocm9tZVwiICtcbiAgICAgICAgICAgICAgICBcIiBhbmQgd2l0aCBUZW1hc3lzIHBsdWdpblwiKTtcbiAgICAgICAgfVxuICAgIH1cbiAgICBpZiAodW0uaW5kZXhPZignZGVza3RvcCcpID49IDApIHtcbiAgICAgICAgY29uc3RyYWludHMudmlkZW8gPSB7XG4gICAgICAgICAgICBtYW5kYXRvcnk6IHtcbiAgICAgICAgICAgICAgICBjaHJvbWVNZWRpYVNvdXJjZTogXCJkZXNrdG9wXCIsXG4gICAgICAgICAgICAgICAgY2hyb21lTWVkaWFTb3VyY2VJZDogb3B0aW9ucy5kZXNrdG9wU3RyZWFtLFxuICAgICAgICAgICAgICAgIGdvb2dMZWFreUJ1Y2tldDogdHJ1ZSxcbiAgICAgICAgICAgICAgICBtYXhXaWR0aDogd2luZG93LnNjcmVlbi53aWR0aCxcbiAgICAgICAgICAgICAgICBtYXhIZWlnaHQ6IHdpbmRvdy5zY3JlZW4uaGVpZ2h0LFxuICAgICAgICAgICAgICAgIG1heEZyYW1lUmF0ZTogM1xuICAgICAgICAgICAgfSxcbiAgICAgICAgICAgIG9wdGlvbmFsOiBbXVxuICAgICAgICB9O1xuICAgIH1cblxuICAgIGlmIChvcHRpb25zLmJhbmR3aWR0aCkge1xuICAgICAgICBpZiAoIWNvbnN0cmFpbnRzLnZpZGVvKSB7XG4gICAgICAgICAgICAvL3NhbWUgYmVoYXZpb3VyIGFzIHRydWVcbiAgICAgICAgICAgIGNvbnN0cmFpbnRzLnZpZGVvID0ge21hbmRhdG9yeToge30sIG9wdGlvbmFsOiBbXX07XG4gICAgICAgIH1cbiAgICAgICAgY29uc3RyYWludHMudmlkZW8ub3B0aW9uYWwucHVzaCh7YmFuZHdpZHRoOiBvcHRpb25zLmJhbmR3aWR0aH0pO1xuICAgIH1cbiAgICBpZiAob3B0aW9ucy5mcHMpIHtcbiAgICAgICAgLy8gZm9yIHNvbWUgY2FtZXJhcyBpdCBtaWdodCBiZSBuZWNlc3NhcnkgdG8gcmVxdWVzdCAzMGZwc1xuICAgICAgICAvLyBzbyB0aGV5IGNob29zZSAzMGZwcyBtanBnIG92ZXIgMTBmcHMgeXV5MlxuICAgICAgICBpZiAoIWNvbnN0cmFpbnRzLnZpZGVvKSB7XG4gICAgICAgICAgICAvLyBzYW1lIGJlaGF2aW91ciBhcyB0cnVlO1xuICAgICAgICAgICAgY29uc3RyYWludHMudmlkZW8gPSB7bWFuZGF0b3J5OiB7fSwgb3B0aW9uYWw6IFtdfTtcbiAgICAgICAgfVxuICAgICAgICBjb25zdHJhaW50cy52aWRlby5tYW5kYXRvcnkubWluRnJhbWVSYXRlID0gb3B0aW9ucy5mcHM7XG4gICAgfVxuXG4gICAgLy8gd2UgdHVybiBhdWRpbyBmb3IgYm90aCBhdWRpbyBhbmQgdmlkZW8gdHJhY2tzLCB0aGUgZmFrZSBhdWRpbyAmIHZpZGVvIHNlZW1zIHRvIHdvcmtcbiAgICAvLyBvbmx5IHdoZW4gZW5hYmxlZCBpbiBvbmUgZ2V0VXNlck1lZGlhIGNhbGwsIHdlIGNhbm5vdCBnZXQgZmFrZSBhdWRpbyBzZXBhcmF0ZSBieSBmYWtlIHZpZGVvXG4gICAgLy8gdGhpcyBsYXRlciBjYW4gYmUgYSBwcm9ibGVtIHdpdGggc29tZSBvZiB0aGUgdGVzdHNcbiAgICBpZihSVENCcm93c2VyVHlwZS5pc0ZpcmVmb3goKSAmJiBvcHRpb25zLmZpcmVmb3hfZmFrZV9kZXZpY2UpXG4gICAge1xuICAgICAgICAvLyBzZWVtcyB0byBiZSBmaXhlZCBub3csIHJlbW92aW5nIHRoaXMgZXhwZXJpbWVudGFsIGZpeCwgYXMgaGF2aW5nXG4gICAgICAgIC8vIG11bHRpcGxlIGF1ZGlvIHRyYWNrcyBicmFrZSB0aGUgdGVzdHNcbiAgICAgICAgLy9jb25zdHJhaW50cy5hdWRpbyA9IHRydWU7XG4gICAgICAgIGNvbnN0cmFpbnRzLmZha2UgPSB0cnVlO1xuICAgIH1cblxuICAgIHJldHVybiBjb25zdHJhaW50cztcbn1cblxuZnVuY3Rpb24gc2V0QXZhaWxhYmxlRGV2aWNlcyh1bSwgYXZhaWxhYmxlKSB7XG4gICAgaWYgKHVtLmluZGV4T2YoXCJ2aWRlb1wiKSAhPSAtMSkge1xuICAgICAgICBkZXZpY2VzLnZpZGVvID0gYXZhaWxhYmxlO1xuICAgIH1cbiAgICBpZiAodW0uaW5kZXhPZihcImF1ZGlvXCIpICE9IC0xKSB7XG4gICAgICAgIGRldmljZXMuYXVkaW8gPSBhdmFpbGFibGU7XG4gICAgfVxuXG4gICAgZXZlbnRFbWl0dGVyLmVtaXQoUlRDRXZlbnRzLkFWQUlMQUJMRV9ERVZJQ0VTX0NIQU5HRUQsIGRldmljZXMpO1xufVxuXG4vLyBJbiBjYXNlIG9mIElFIHdlIGNvbnRpbnVlIGZyb20gJ29uUmVhZHknIGNhbGxiYWNrXG4vLyBwYXNzZWQgdG8gUlRDVXRpbHMgY29uc3RydWN0b3IuIEl0IHdpbGwgYmUgaW52b2tlZCBieSBUZW1hc3lzIHBsdWdpblxuLy8gb25jZSBpdCBpcyBpbml0aWFsaXplZC5cbmZ1bmN0aW9uIG9uUmVhZHkgKG9wdGlvbnMsIEdVTSkge1xuICAgIHJ0Y1JlYWR5ID0gdHJ1ZTtcbiAgICBldmVudEVtaXR0ZXIuZW1pdChSVENFdmVudHMuUlRDX1JFQURZLCB0cnVlKTtcbiAgICBzY3JlZW5PYnRhaW5lci5pbml0KGV2ZW50RW1pdHRlciwgb3B0aW9ucywgR1VNKTtcbn1cblxuLyoqXG4gKiBBcHBseSBmdW5jdGlvbiB3aXRoIGFyZ3VtZW50cyBpZiBmdW5jdGlvbiBleGlzdHMuXG4gKiBEbyBub3RoaW5nIGlmIGZ1bmN0aW9uIG5vdCBwcm92aWRlZC5cbiAqIEBwYXJhbSB7ZnVuY3Rpb259IFtmbl0gZnVuY3Rpb24gdG8gYXBwbHlcbiAqIEBwYXJhbSB7QXJyYXl9IFthcmdzPVtdXSBhcmd1bWVudHMgZm9yIGZ1bmN0aW9uXG4gKi9cbmZ1bmN0aW9uIG1heWJlQXBwbHkoZm4sIGFyZ3MpIHtcbiAgaWYgKGZuKSB7XG4gICAgZm4uYXBwbHkobnVsbCwgYXJncyB8fCBbXSk7XG4gIH1cbn1cblxudmFyIGdldFVzZXJNZWRpYVN0YXR1cyA9IHtcbiAgaW5pdGlhbGl6ZWQ6IGZhbHNlLFxuICBjYWxsYmFja3M6IFtdXG59O1xuXG4vKipcbiAqIFdyYXAgYGdldFVzZXJNZWRpYWAgdG8gYWxsb3cgb3RoZXJzIHRvIGtub3cgaWYgaXQgd2FzIGV4ZWN1dGVkIGF0IGxlYXN0XG4gKiBvbmNlIG9yIG5vdC4gV3JhcHBlciBmdW5jdGlvbiB1c2VzIGBnZXRVc2VyTWVkaWFTdGF0dXNgIG9iamVjdC5cbiAqIEBwYXJhbSB7RnVuY3Rpb259IGdldFVzZXJNZWRpYSBuYXRpdmUgZnVuY3Rpb25cbiAqIEByZXR1cm5zIHtGdW5jdGlvbn0gd3JhcHBlZCBmdW5jdGlvblxuICovXG5mdW5jdGlvbiB3cmFwR2V0VXNlck1lZGlhKGdldFVzZXJNZWRpYSkge1xuICByZXR1cm4gZnVuY3Rpb24gKGNvbnN0cmFpbnRzLCBzdWNjZXNzQ2FsbGJhY2ssIGVycm9yQ2FsbGJhY2spIHtcbiAgICBnZXRVc2VyTWVkaWEoY29uc3RyYWludHMsIGZ1bmN0aW9uIChzdHJlYW0pIHtcbiAgICAgIG1heWJlQXBwbHkoc3VjY2Vzc0NhbGxiYWNrLCBbc3RyZWFtXSk7XG4gICAgICBpZiAoIWdldFVzZXJNZWRpYVN0YXR1cy5pbml0aWFsaXplZCkge1xuICAgICAgICBnZXRVc2VyTWVkaWFTdGF0dXMuaW5pdGlhbGl6ZWQgPSB0cnVlO1xuICAgICAgICBnZXRVc2VyTWVkaWFTdGF0dXMuY2FsbGJhY2tzLmZvckVhY2goZnVuY3Rpb24gKGNhbGxiYWNrKSB7XG4gICAgICAgICAgY2FsbGJhY2soKTtcbiAgICAgICAgfSk7XG4gICAgICAgIGdldFVzZXJNZWRpYVN0YXR1cy5jYWxsYmFja3MubGVuZ3RoID0gMDtcbiAgICAgIH1cbiAgICB9LCBmdW5jdGlvbiAoZXJyb3IpIHtcbiAgICAgIG1heWJlQXBwbHkoZXJyb3JDYWxsYmFjaywgW2Vycm9yXSk7XG4gICAgfSk7XG4gIH07XG59XG5cbi8qKlxuICogQ3JlYXRlIHN0dWIgZGV2aWNlIHdoaWNoIGVxdWFscyB0byBhdXRvIHNlbGVjdGVkIGRldmljZS5cbiAqIEBwYXJhbSB7c3RyaW5nfSBraW5kIGlmIHRoYXQgc2hvdWxkIGJlIGBhdWRpb2Agb3IgYHZpZGVvYCBkZXZpY2VcbiAqIEByZXR1cm5zIHtPYmplY3R9IHN0dWIgZGV2aWNlIGRlc2NyaXB0aW9uIGluIGBlbnVtZXJhdGVEZXZpY2VzYCBmb3JtYXRcbiAqL1xuZnVuY3Rpb24gY3JlYXRlQXV0b0RldmljZUluZm8oa2luZCkge1xuICAgIHJldHVybiB7XG4gICAgICAgIGZhY2luZzogbnVsbCxcbiAgICAgICAgbGFiZWw6ICdBdXRvJyxcbiAgICAgICAga2luZDoga2luZCxcbiAgICAgICAgZGV2aWNlSWQ6ICcnLFxuICAgICAgICBncm91cElkOiBudWxsXG4gICAgfTtcbn1cblxuXG4vKipcbiAqIEV4ZWN1dGUgZnVuY3Rpb24gYWZ0ZXIgZ2V0VXNlck1lZGlhIHdhcyBleGVjdXRlZCBhdCBsZWFzdCBvbmNlLlxuICogQHBhcmFtIHtGdW5jdGlvbn0gY2FsbGJhY2sgZnVuY3Rpb24gdG8gZXhlY3V0ZSBhZnRlciBnZXRVc2VyTWVkaWFcbiAqL1xuZnVuY3Rpb24gYWZ0ZXJVc2VyTWVkaWFJbml0aWFsaXplZChjYWxsYmFjaykge1xuICAgIGlmIChnZXRVc2VyTWVkaWFTdGF0dXMuaW5pdGlhbGl6ZWQpIHtcbiAgICAgICAgY2FsbGJhY2soKTtcbiAgICB9IGVsc2Uge1xuICAgICAgICBnZXRVc2VyTWVkaWFTdGF0dXMuY2FsbGJhY2tzLnB1c2goY2FsbGJhY2spO1xuICAgIH1cbn1cblxuLyoqXG4gKiBXcmFwcGVyIGZ1bmN0aW9uIHdoaWNoIG1ha2VzIGVudW1lcmF0ZURldmljZXMgdG8gd2FpdFxuICogdW50aWwgc29tZW9uZSBleGVjdXRlcyBnZXRVc2VyTWVkaWEgZmlyc3QgdGltZS5cbiAqIEBwYXJhbSB7RnVuY3Rpb259IGVudW1lcmF0ZURldmljZXMgbmF0aXZlIGZ1bmN0aW9uXG4gKiBAcmV0dXJucyB7RnVudGlvbn0gd3JhcHBlZCBmdW5jdGlvblxuICovXG5mdW5jdGlvbiB3cmFwRW51bWVyYXRlRGV2aWNlcyhlbnVtZXJhdGVEZXZpY2VzKSB7XG4gICAgcmV0dXJuIGZ1bmN0aW9uIChjYWxsYmFjaykge1xuICAgICAgICAvLyBlbnVtZXJhdGUgZGV2aWNlcyBvbmx5IGFmdGVyIGluaXRpYWwgZ2V0VXNlck1lZGlhXG4gICAgICAgIGFmdGVyVXNlck1lZGlhSW5pdGlhbGl6ZWQoZnVuY3Rpb24gKCkge1xuXG4gICAgICAgICAgICBlbnVtZXJhdGVEZXZpY2VzKCkudGhlbihmdW5jdGlvbiAoZGV2aWNlcykge1xuICAgICAgICAgICAgICAgIC8vYWRkIGF1dG8gZGV2aWNlc1xuICAgICAgICAgICAgICAgIGRldmljZXMudW5zaGlmdChcbiAgICAgICAgICAgICAgICAgICAgY3JlYXRlQXV0b0RldmljZUluZm8oJ2F1ZGlvaW5wdXQnKSxcbiAgICAgICAgICAgICAgICAgICAgY3JlYXRlQXV0b0RldmljZUluZm8oJ3ZpZGVvaW5wdXQnKVxuICAgICAgICAgICAgICAgICk7XG5cbiAgICAgICAgICAgICAgICBjYWxsYmFjayhkZXZpY2VzKTtcbiAgICAgICAgICAgIH0sIGZ1bmN0aW9uIChlcnIpIHtcbiAgICAgICAgICAgICAgICBjb25zb2xlLmVycm9yKCdjYW5ub3QgZW51bWVyYXRlIGRldmljZXM6ICcsIGVycik7XG5cbiAgICAgICAgICAgICAgICAvLyByZXR1cm4gb25seSBhdXRvIGRldmljZXNcbiAgICAgICAgICAgICAgICBjYWxsYmFjayhbY3JlYXRlQXV0b0RldmljZUluZm8oJ2F1ZGlvSW5wdXQnKSxcbiAgICAgICAgICAgICAgICAgICAgICAgICAgY3JlYXRlQXV0b0RldmljZUluZm8oJ3ZpZGVvaW5wdXQnKV0pO1xuICAgICAgICAgICAgfSk7XG4gICAgICAgIH0pO1xuICAgIH07XG59XG5cbi8qKlxuICogVXNlIG9sZCBNZWRpYVN0cmVhbVRyYWNrIHRvIGdldCBkZXZpY2VzIGxpc3QgYW5kXG4gKiBjb252ZXJ0IGl0IHRvIGVudW1lcmF0ZURldmljZXMgZm9ybWF0LlxuICogQHBhcmFtIHtGdW5jdGlvbn0gY2FsbGJhY2sgZnVuY3Rpb24gdG8gY2FsbCB3aGVuIHJlY2VpdmVkIGRldmljZXMgbGlzdC5cbiAqL1xuZnVuY3Rpb24gZW51bWVyYXRlRGV2aWNlc1Rocm91Z2hNZWRpYVN0cmVhbVRyYWNrIChjYWxsYmFjaykge1xuICAgIE1lZGlhU3RyZWFtVHJhY2suZ2V0U291cmNlcyhmdW5jdGlvbiAoc291cmNlcykge1xuICAgICAgICB2YXIgZGV2aWNlcyA9IHNvdXJjZXMubWFwKGZ1bmN0aW9uIChzb3VyY2UpIHtcbiAgICAgICAgICAgIHZhciBraW5kID0gKHNvdXJjZS5raW5kIHx8ICcnKS50b0xvd2VyQ2FzZSgpO1xuICAgICAgICAgICAgcmV0dXJuIHtcbiAgICAgICAgICAgICAgICBmYWNpbmc6IHNvdXJjZS5mYWNpbmcgfHwgbnVsbCxcbiAgICAgICAgICAgICAgICBsYWJlbDogc291cmNlLmxhYmVsLFxuICAgICAgICAgICAgICAgIGtpbmQ6IGtpbmQgPyBraW5kICsgJ2lucHV0JzogbnVsbCxcbiAgICAgICAgICAgICAgICBkZXZpY2VJZDogc291cmNlLmlkLFxuICAgICAgICAgICAgICAgIGdyb3VwSWQ6IHNvdXJjZS5ncm91cElkIHx8IG51bGxcbiAgICAgICAgICAgIH07XG4gICAgICAgIH0pO1xuXG4gICAgICAgIC8vYWRkIGF1dG8gZGV2aWNlc1xuICAgICAgICBkZXZpY2VzLnVuc2hpZnQoXG4gICAgICAgICAgICBjcmVhdGVBdXRvRGV2aWNlSW5mbygnYXVkaW9pbnB1dCcpLFxuICAgICAgICAgICAgY3JlYXRlQXV0b0RldmljZUluZm8oJ3ZpZGVvaW5wdXQnKVxuICAgICAgICApO1xuICAgICAgICBjYWxsYmFjayhkZXZpY2VzKTtcbiAgICB9KTtcbn1cblxuZnVuY3Rpb24gb2J0YWluRGV2aWNlcyhvcHRpb25zKSB7XG4gICAgaWYoIW9wdGlvbnMuZGV2aWNlcyB8fCBvcHRpb25zLmRldmljZXMubGVuZ3RoID09PSAwKSB7XG4gICAgICAgIHJldHVybiBvcHRpb25zLnN1Y2Nlc3NDYWxsYmFjayhvcHRpb25zLnN0cmVhbXMgfHwge30pO1xuICAgIH1cblxuICAgIHZhciBkZXZpY2UgPSBvcHRpb25zLmRldmljZXMuc3BsaWNlKDAsIDEpO1xuICAgIG9wdGlvbnMuZGV2aWNlR1VNW2RldmljZV0oZnVuY3Rpb24gKHN0cmVhbSkge1xuICAgICAgICAgICAgb3B0aW9ucy5zdHJlYW1zID0gb3B0aW9ucy5zdHJlYW1zIHx8IHt9O1xuICAgICAgICAgICAgb3B0aW9ucy5zdHJlYW1zW2RldmljZV0gPSBzdHJlYW07XG4gICAgICAgICAgICBvYnRhaW5EZXZpY2VzKG9wdGlvbnMpO1xuICAgICAgICB9LFxuICAgICAgICBmdW5jdGlvbiAoZXJyb3IpIHtcbiAgICAgICAgICAgIGxvZ2dlci5lcnJvcihcbiAgICAgICAgICAgICAgICBcImZhaWxlZCB0byBvYnRhaW4gXCIgKyBkZXZpY2UgKyBcIiBzdHJlYW0gLSBzdG9wXCIsIGVycm9yKTtcbiAgICAgICAgICAgIG9wdGlvbnMuZXJyb3JDYWxsYmFjayhKaXRzaVRyYWNrRXJyb3JzLnBhcnNlRXJyb3IoZXJyb3IpKTtcbiAgICAgICAgfSk7XG59XG5cblxuLyoqXG4gKiBIYW5kbGVzIHRoZSBuZXdseSBjcmVhdGVkIE1lZGlhIFN0cmVhbXMuXG4gKiBAcGFyYW0gc3RyZWFtcyB0aGUgbmV3IE1lZGlhIFN0cmVhbXNcbiAqIEBwYXJhbSByZXNvbHV0aW9uIHRoZSByZXNvbHV0aW9uIG9mIHRoZSB2aWRlbyBzdHJlYW1zXG4gKiBAcmV0dXJucyB7KltdfSBvYmplY3QgdGhhdCBkZXNjcmliZXMgdGhlIG5ldyBzdHJlYW1zXG4gKi9cbmZ1bmN0aW9uIGhhbmRsZUxvY2FsU3RyZWFtKHN0cmVhbXMsIHJlc29sdXRpb24pIHtcbiAgICB2YXIgYXVkaW9TdHJlYW0sIHZpZGVvU3RyZWFtLCBkZXNrdG9wU3RyZWFtLCByZXMgPSBbXTtcbiAgICAvLyBJZiB0aGlzIGlzIEZGLCB0aGUgc3RyZWFtIHBhcmFtZXRlciBpcyAqbm90KiBhIE1lZGlhU3RyZWFtIG9iamVjdCwgaXQnc1xuICAgIC8vIGFuIG9iamVjdCB3aXRoIHR3byBwcm9wZXJ0aWVzOiBhdWRpb1N0cmVhbSwgdmlkZW9TdHJlYW0uXG4gICAgaWYgKHdpbmRvdy53ZWJraXRNZWRpYVN0cmVhbSkge1xuICAgICAgICB2YXIgYXVkaW9WaWRlbyA9IHN0cmVhbXMuYXVkaW9WaWRlbztcbiAgICAgICAgaWYgKGF1ZGlvVmlkZW8pIHtcbiAgICAgICAgICAgIHZhciBhdWRpb1RyYWNrcyA9IGF1ZGlvVmlkZW8uZ2V0QXVkaW9UcmFja3MoKTtcbiAgICAgICAgICAgIGlmKGF1ZGlvVHJhY2tzLmxlbmd0aCkge1xuICAgICAgICAgICAgICAgIGF1ZGlvU3RyZWFtID0gbmV3IHdlYmtpdE1lZGlhU3RyZWFtKCk7XG4gICAgICAgICAgICAgICAgZm9yICh2YXIgaSA9IDA7IGkgPCBhdWRpb1RyYWNrcy5sZW5ndGg7IGkrKykge1xuICAgICAgICAgICAgICAgICAgICBhdWRpb1N0cmVhbS5hZGRUcmFjayhhdWRpb1RyYWNrc1tpXSk7XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICB2YXIgdmlkZW9UcmFja3MgPSBhdWRpb1ZpZGVvLmdldFZpZGVvVHJhY2tzKCk7XG4gICAgICAgICAgICBpZih2aWRlb1RyYWNrcy5sZW5ndGgpIHtcbiAgICAgICAgICAgICAgICB2aWRlb1N0cmVhbSA9IG5ldyB3ZWJraXRNZWRpYVN0cmVhbSgpO1xuICAgICAgICAgICAgICAgIGZvciAodmFyIGogPSAwOyBqIDwgdmlkZW9UcmFja3MubGVuZ3RoOyBqKyspIHtcbiAgICAgICAgICAgICAgICAgICAgdmlkZW9TdHJlYW0uYWRkVHJhY2sodmlkZW9UcmFja3Nbal0pO1xuICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgIH1cbiAgICAgICAgfVxuXG4gICAgICAgIGlmIChzdHJlYW1zICYmIHN0cmVhbXMuZGVza3RvcFN0cmVhbSlcbiAgICAgICAgICAgIGRlc2t0b3BTdHJlYW0gPSBzdHJlYW1zLmRlc2t0b3BTdHJlYW07XG5cbiAgICB9XG4gICAgZWxzZSBpZiAoUlRDQnJvd3NlclR5cGUuaXNGaXJlZm94KCkgfHwgUlRDQnJvd3NlclR5cGUuaXNUZW1hc3lzUGx1Z2luVXNlZCgpKSB7ICAgLy8gRmlyZWZveCBhbmQgVGVtYXN5cyBwbHVnaW5cbiAgICAgICAgaWYgKHN0cmVhbXMgJiYgc3RyZWFtcy5hdWRpbylcbiAgICAgICAgICAgIGF1ZGlvU3RyZWFtID0gc3RyZWFtcy5hdWRpbztcblxuICAgICAgICBpZiAoc3RyZWFtcyAmJiBzdHJlYW1zLnZpZGVvKVxuICAgICAgICAgICAgdmlkZW9TdHJlYW0gPSBzdHJlYW1zLnZpZGVvO1xuXG4gICAgICAgIGlmKHN0cmVhbXMgJiYgc3RyZWFtcy5kZXNrdG9wKVxuICAgICAgICAgICAgZGVza3RvcFN0cmVhbSA9IHN0cmVhbXMuZGVza3RvcDtcbiAgICB9XG5cbiAgICBpZiAoZGVza3RvcFN0cmVhbSlcbiAgICAgICAgcmVzLnB1c2goe3N0cmVhbTogZGVza3RvcFN0cmVhbSxcbiAgICAgICAgICAgIHR5cGU6IFwidmlkZW9cIiwgdmlkZW9UeXBlOiBcImRlc2t0b3BcIn0pO1xuXG4gICAgaWYoYXVkaW9TdHJlYW0pXG4gICAgICAgIHJlcy5wdXNoKHtzdHJlYW06IGF1ZGlvU3RyZWFtLCB0eXBlOiBcImF1ZGlvXCIsIHZpZGVvVHlwZTogbnVsbH0pO1xuXG4gICAgaWYodmlkZW9TdHJlYW0pXG4gICAgICAgIHJlcy5wdXNoKHtzdHJlYW06IHZpZGVvU3RyZWFtLCB0eXBlOiBcInZpZGVvXCIsIHZpZGVvVHlwZTogXCJjYW1lcmFcIixcbiAgICAgICAgICAgIHJlc29sdXRpb246IHJlc29sdXRpb259KTtcblxuICAgIHJldHVybiByZXM7XG59XG5cbi8vT3B0aW9ucyBwYXJhbWV0ZXIgaXMgdG8gcGFzcyBjb25maWcgb3B0aW9ucy4gQ3VycmVudGx5IHVzZXMgb25seSBcInVzZUlQdjZcIi5cbnZhciBSVENVdGlscyA9IHtcbiAgICBpbml0OiBmdW5jdGlvbiAob3B0aW9ucykge1xuICAgICAgICByZXR1cm4gbmV3IFByb21pc2UoZnVuY3Rpb24ocmVzb2x2ZSwgcmVqZWN0KSB7XG4gICAgICAgICAgICBpZiAoUlRDQnJvd3NlclR5cGUuaXNGaXJlZm94KCkpIHtcbiAgICAgICAgICAgICAgICB2YXIgRkZ2ZXJzaW9uID0gUlRDQnJvd3NlclR5cGUuZ2V0RmlyZWZveFZlcnNpb24oKTtcbiAgICAgICAgICAgICAgICBpZiAoRkZ2ZXJzaW9uIDwgNDApIHtcbiAgICAgICAgICAgICAgICAgICAgbG9nZ2VyLmVycm9yKFxuICAgICAgICAgICAgICAgICAgICAgICAgICAgIFwiRmlyZWZveCB2ZXJzaW9uIHRvbyBvbGQ6IFwiICsgRkZ2ZXJzaW9uICtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICBcIi4gUmVxdWlyZWQgPj0gNDAuXCIpO1xuICAgICAgICAgICAgICAgICAgICByZWplY3QobmV3IEVycm9yKFwiRmlyZWZveCB2ZXJzaW9uIHRvbyBvbGQ6IFwiICsgRkZ2ZXJzaW9uICtcbiAgICAgICAgICAgICAgICAgICAgXCIuIFJlcXVpcmVkID49IDQwLlwiKSk7XG4gICAgICAgICAgICAgICAgICAgIHJldHVybjtcbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgdGhpcy5wZWVyY29ubmVjdGlvbiA9IG1velJUQ1BlZXJDb25uZWN0aW9uO1xuICAgICAgICAgICAgICAgIHRoaXMuZ2V0VXNlck1lZGlhID0gd3JhcEdldFVzZXJNZWRpYShuYXZpZ2F0b3IubW96R2V0VXNlck1lZGlhLmJpbmQobmF2aWdhdG9yKSk7XG4gICAgICAgICAgICAgICAgdGhpcy5lbnVtZXJhdGVEZXZpY2VzID0gd3JhcEVudW1lcmF0ZURldmljZXMoXG4gICAgICAgICAgICAgICAgICAgIG5hdmlnYXRvci5tZWRpYURldmljZXMuZW51bWVyYXRlRGV2aWNlcy5iaW5kKG5hdmlnYXRvci5tZWRpYURldmljZXMpXG4gICAgICAgICAgICAgICAgKTtcbiAgICAgICAgICAgICAgICB0aGlzLnBjX2NvbnN0cmFpbnRzID0ge307XG4gICAgICAgICAgICAgICAgdGhpcy5hdHRhY2hNZWRpYVN0cmVhbSA9IGZ1bmN0aW9uIChlbGVtZW50LCBzdHJlYW0pIHtcbiAgICAgICAgICAgICAgICAgICAgLy8gIHNyY09iamVjdCBpcyBiZWluZyBzdGFuZGFyZGl6ZWQgYW5kIEZGIHdpbGwgZXZlbnR1YWxseVxuICAgICAgICAgICAgICAgICAgICAvLyAgc3VwcG9ydCB0aGF0IHVucHJlZml4ZWQuIEZGIGFsc28gc3VwcG9ydHMgdGhlXG4gICAgICAgICAgICAgICAgICAgIC8vICBcImVsZW1lbnQuc3JjID0gVVJMLmNyZWF0ZU9iamVjdFVSTCguLi4pXCIgY29tYm8sIGJ1dCB0aGF0XG4gICAgICAgICAgICAgICAgICAgIC8vICB3aWxsIGJlIGRlcHJlY2F0ZWQgaW4gZmF2b3VyIG9mIHNyY09iamVjdC5cbiAgICAgICAgICAgICAgICAgICAgLy9cbiAgICAgICAgICAgICAgICAgICAgLy8gaHR0cHM6Ly9ncm91cHMuZ29vZ2xlLmNvbS9mb3J1bS8jIXRvcGljL21vemlsbGEuZGV2Lm1lZGlhL3BLT2lpb1hvbkpnXG4gICAgICAgICAgICAgICAgICAgIC8vIGh0dHBzOi8vZ2l0aHViLmNvbS93ZWJydGMvc2FtcGxlcy9pc3N1ZXMvMzAyXG4gICAgICAgICAgICAgICAgICAgIGlmICghZWxlbWVudFswXSlcbiAgICAgICAgICAgICAgICAgICAgICAgIHJldHVybjtcbiAgICAgICAgICAgICAgICAgICAgZWxlbWVudFswXS5tb3pTcmNPYmplY3QgPSBzdHJlYW07XG4gICAgICAgICAgICAgICAgICAgIGVsZW1lbnRbMF0ucGxheSgpO1xuICAgICAgICAgICAgICAgIH07XG4gICAgICAgICAgICAgICAgdGhpcy5nZXRTdHJlYW1JRCA9IGZ1bmN0aW9uIChzdHJlYW0pIHtcbiAgICAgICAgICAgICAgICAgICAgdmFyIGlkID0gc3RyZWFtLmlkO1xuICAgICAgICAgICAgICAgICAgICBpZiAoIWlkKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICB2YXIgdHJhY2tzID0gc3RyZWFtLmdldFZpZGVvVHJhY2tzKCk7XG4gICAgICAgICAgICAgICAgICAgICAgICBpZiAoIXRyYWNrcyB8fCB0cmFja3MubGVuZ3RoID09PSAwKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgdHJhY2tzID0gc3RyZWFtLmdldEF1ZGlvVHJhY2tzKCk7XG4gICAgICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgICAgICAgICBpZCA9IHRyYWNrc1swXS5pZDtcbiAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgICAgICByZXR1cm4gU0RQVXRpbC5maWx0ZXJfc3BlY2lhbF9jaGFycyhpZCk7XG4gICAgICAgICAgICAgICAgfTtcbiAgICAgICAgICAgICAgICB0aGlzLmdldFZpZGVvU3JjID0gZnVuY3Rpb24gKGVsZW1lbnQpIHtcbiAgICAgICAgICAgICAgICAgICAgaWYgKCFlbGVtZW50KVxuICAgICAgICAgICAgICAgICAgICAgICAgcmV0dXJuIG51bGw7XG4gICAgICAgICAgICAgICAgICAgIHJldHVybiBlbGVtZW50Lm1velNyY09iamVjdDtcbiAgICAgICAgICAgICAgICB9O1xuICAgICAgICAgICAgICAgIHRoaXMuc2V0VmlkZW9TcmMgPSBmdW5jdGlvbiAoZWxlbWVudCwgc3JjKSB7XG4gICAgICAgICAgICAgICAgICAgIGlmIChlbGVtZW50KVxuICAgICAgICAgICAgICAgICAgICAgICAgZWxlbWVudC5tb3pTcmNPYmplY3QgPSBzcmM7XG4gICAgICAgICAgICAgICAgfTtcbiAgICAgICAgICAgICAgICBSVENTZXNzaW9uRGVzY3JpcHRpb24gPSBtb3pSVENTZXNzaW9uRGVzY3JpcHRpb247XG4gICAgICAgICAgICAgICAgUlRDSWNlQ2FuZGlkYXRlID0gbW96UlRDSWNlQ2FuZGlkYXRlO1xuICAgICAgICAgICAgfSBlbHNlIGlmIChSVENCcm93c2VyVHlwZS5pc0Nocm9tZSgpIHx8IFJUQ0Jyb3dzZXJUeXBlLmlzT3BlcmEoKSkge1xuICAgICAgICAgICAgICAgIHRoaXMucGVlcmNvbm5lY3Rpb24gPSB3ZWJraXRSVENQZWVyQ29ubmVjdGlvbjtcbiAgICAgICAgICAgICAgICB2YXIgZ2V0VXNlck1lZGlhID0gbmF2aWdhdG9yLndlYmtpdEdldFVzZXJNZWRpYS5iaW5kKG5hdmlnYXRvcik7XG4gICAgICAgICAgICAgICAgaWYgKG5hdmlnYXRvci5tZWRpYURldmljZXMpIHtcbiAgICAgICAgICAgICAgICAgICAgdGhpcy5nZXRVc2VyTWVkaWEgPSB3cmFwR2V0VXNlck1lZGlhKGdldFVzZXJNZWRpYSk7XG4gICAgICAgICAgICAgICAgICAgIHRoaXMuZW51bWVyYXRlRGV2aWNlcyA9IHdyYXBFbnVtZXJhdGVEZXZpY2VzKFxuICAgICAgICAgICAgICAgICAgICAgICAgbmF2aWdhdG9yLm1lZGlhRGV2aWNlcy5lbnVtZXJhdGVEZXZpY2VzLmJpbmQobmF2aWdhdG9yLm1lZGlhRGV2aWNlcylcbiAgICAgICAgICAgICAgICAgICAgKTtcbiAgICAgICAgICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgICAgICAgICB0aGlzLmdldFVzZXJNZWRpYSA9IGdldFVzZXJNZWRpYTtcbiAgICAgICAgICAgICAgICAgICAgdGhpcy5lbnVtZXJhdGVEZXZpY2VzID0gZW51bWVyYXRlRGV2aWNlc1Rocm91Z2hNZWRpYVN0cmVhbVRyYWNrO1xuICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICB0aGlzLmF0dGFjaE1lZGlhU3RyZWFtID0gZnVuY3Rpb24gKGVsZW1lbnQsIHN0cmVhbSkge1xuICAgICAgICAgICAgICAgICAgICBlbGVtZW50LmF0dHIoJ3NyYycsIHdlYmtpdFVSTC5jcmVhdGVPYmplY3RVUkwoc3RyZWFtKSk7XG4gICAgICAgICAgICAgICAgfTtcbiAgICAgICAgICAgICAgICB0aGlzLmdldFN0cmVhbUlEID0gZnVuY3Rpb24gKHN0cmVhbSkge1xuICAgICAgICAgICAgICAgICAgICAvLyBzdHJlYW1zIGZyb20gRkYgZW5kcG9pbnRzIGhhdmUgdGhlIGNoYXJhY3RlcnMgJ3snIGFuZCAnfSdcbiAgICAgICAgICAgICAgICAgICAgLy8gdGhhdCBtYWtlIGpRdWVyeSBjaG9rZS5cbiAgICAgICAgICAgICAgICAgICAgcmV0dXJuIFNEUFV0aWwuZmlsdGVyX3NwZWNpYWxfY2hhcnMoc3RyZWFtLmlkKTtcbiAgICAgICAgICAgICAgICB9O1xuICAgICAgICAgICAgICAgIHRoaXMuZ2V0VmlkZW9TcmMgPSBmdW5jdGlvbiAoZWxlbWVudCkge1xuICAgICAgICAgICAgICAgICAgICBpZiAoIWVsZW1lbnQpXG4gICAgICAgICAgICAgICAgICAgICAgICByZXR1cm4gbnVsbDtcbiAgICAgICAgICAgICAgICAgICAgcmV0dXJuIGVsZW1lbnQuZ2V0QXR0cmlidXRlKFwic3JjXCIpO1xuICAgICAgICAgICAgICAgIH07XG4gICAgICAgICAgICAgICAgdGhpcy5zZXRWaWRlb1NyYyA9IGZ1bmN0aW9uIChlbGVtZW50LCBzcmMpIHtcbiAgICAgICAgICAgICAgICAgICAgaWYgKGVsZW1lbnQpXG4gICAgICAgICAgICAgICAgICAgICAgICBlbGVtZW50LnNldEF0dHJpYnV0ZShcInNyY1wiLCBzcmMpO1xuICAgICAgICAgICAgICAgIH07XG4gICAgICAgICAgICAgICAgLy8gRFRMUyBzaG91bGQgbm93IGJlIGVuYWJsZWQgYnkgZGVmYXVsdCBidXQuLlxuICAgICAgICAgICAgICAgIHRoaXMucGNfY29uc3RyYWludHMgPSB7J29wdGlvbmFsJzogW1xuICAgICAgICAgICAgICAgICAgICB7J0R0bHNTcnRwS2V5QWdyZWVtZW50JzogJ3RydWUnfVxuICAgICAgICAgICAgICAgIF19O1xuICAgICAgICAgICAgICAgIGlmIChvcHRpb25zLnVzZUlQdjYpIHtcbiAgICAgICAgICAgICAgICAgICAgLy8gaHR0cHM6Ly9jb2RlLmdvb2dsZS5jb20vcC93ZWJydGMvaXNzdWVzL2RldGFpbD9pZD0yODI4XG4gICAgICAgICAgICAgICAgICAgIHRoaXMucGNfY29uc3RyYWludHMub3B0aW9uYWwucHVzaCh7Z29vZ0lQdjY6IHRydWV9KTtcbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgaWYgKFJUQ0Jyb3dzZXJUeXBlLmlzQW5kcm9pZCgpKSB7XG4gICAgICAgICAgICAgICAgICAgIHRoaXMucGNfY29uc3RyYWludHMgPSB7fTsgLy8gZGlzYWJsZSBEVExTIG9uIEFuZHJvaWRcbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgaWYgKCF3ZWJraXRNZWRpYVN0cmVhbS5wcm90b3R5cGUuZ2V0VmlkZW9UcmFja3MpIHtcbiAgICAgICAgICAgICAgICAgICAgd2Via2l0TWVkaWFTdHJlYW0ucHJvdG90eXBlLmdldFZpZGVvVHJhY2tzID0gZnVuY3Rpb24gKCkge1xuICAgICAgICAgICAgICAgICAgICAgICAgcmV0dXJuIHRoaXMudmlkZW9UcmFja3M7XG4gICAgICAgICAgICAgICAgICAgIH07XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgIGlmICghd2Via2l0TWVkaWFTdHJlYW0ucHJvdG90eXBlLmdldEF1ZGlvVHJhY2tzKSB7XG4gICAgICAgICAgICAgICAgICAgIHdlYmtpdE1lZGlhU3RyZWFtLnByb3RvdHlwZS5nZXRBdWRpb1RyYWNrcyA9IGZ1bmN0aW9uICgpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgIHJldHVybiB0aGlzLmF1ZGlvVHJhY2tzO1xuICAgICAgICAgICAgICAgICAgICB9O1xuICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgIH1cbiAgICAgICAgICAgIC8vIERldGVjdCBJRS9TYWZhcmlcbiAgICAgICAgICAgIGVsc2UgaWYgKFJUQ0Jyb3dzZXJUeXBlLmlzVGVtYXN5c1BsdWdpblVzZWQoKSkge1xuXG4gICAgICAgICAgICAgICAgLy9BZGFwdGVySlMuV2ViUlRDUGx1Z2luLnNldExvZ0xldmVsKFxuICAgICAgICAgICAgICAgIC8vICAgIEFkYXB0ZXJKUy5XZWJSVENQbHVnaW4uUExVR0lOX0xPR19MRVZFTFMuVkVSQk9TRSk7XG4gICAgICAgICAgICAgICAgdmFyIHNlbGYgPSB0aGlzO1xuICAgICAgICAgICAgICAgIEFkYXB0ZXJKUy53ZWJSVENSZWFkeShmdW5jdGlvbiAoaXNQbHVnaW4pIHtcblxuICAgICAgICAgICAgICAgICAgICBzZWxmLnBlZXJjb25uZWN0aW9uID0gUlRDUGVlckNvbm5lY3Rpb247XG4gICAgICAgICAgICAgICAgICAgIHNlbGYuZ2V0VXNlck1lZGlhID0gd2luZG93LmdldFVzZXJNZWRpYTtcbiAgICAgICAgICAgICAgICAgICAgc2VsZi5lbnVtZXJhdGVEZXZpY2VzID0gZW51bWVyYXRlRGV2aWNlc1Rocm91Z2hNZWRpYVN0cmVhbVRyYWNrO1xuICAgICAgICAgICAgICAgICAgICBzZWxmLmF0dGFjaE1lZGlhU3RyZWFtID0gZnVuY3Rpb24gKGVsU2VsLCBzdHJlYW0pIHtcblxuICAgICAgICAgICAgICAgICAgICAgICAgaWYgKHN0cmVhbS5pZCA9PT0gXCJkdW1teUF1ZGlvXCIgfHwgc3RyZWFtLmlkID09PSBcImR1bW15VmlkZW9cIikge1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgIHJldHVybjtcbiAgICAgICAgICAgICAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgICAgICAgICAgICAgYXR0YWNoTWVkaWFTdHJlYW0oZWxTZWxbMF0sIHN0cmVhbSk7XG4gICAgICAgICAgICAgICAgICAgIH07XG4gICAgICAgICAgICAgICAgICAgIHNlbGYuZ2V0U3RyZWFtSUQgPSBmdW5jdGlvbiAoc3RyZWFtKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICB2YXIgaWQgPSBTRFBVdGlsLmZpbHRlcl9zcGVjaWFsX2NoYXJzKHN0cmVhbS5sYWJlbCk7XG4gICAgICAgICAgICAgICAgICAgICAgICByZXR1cm4gaWQ7XG4gICAgICAgICAgICAgICAgICAgIH07XG4gICAgICAgICAgICAgICAgICAgIHNlbGYuZ2V0VmlkZW9TcmMgPSBmdW5jdGlvbiAoZWxlbWVudCkge1xuICAgICAgICAgICAgICAgICAgICAgICAgaWYgKCFlbGVtZW50KSB7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgbG9nZ2VyLndhcm4oXCJBdHRlbXB0IHRvIGdldCB2aWRlbyBTUkMgb2YgbnVsbCBlbGVtZW50XCIpO1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgIHJldHVybiBudWxsO1xuICAgICAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgICAgICAgICAgdmFyIGNoaWxkcmVuID0gZWxlbWVudC5jaGlsZHJlbjtcbiAgICAgICAgICAgICAgICAgICAgICAgIGZvciAodmFyIGkgPSAwOyBpICE9PSBjaGlsZHJlbi5sZW5ndGg7ICsraSkge1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgIGlmIChjaGlsZHJlbltpXS5uYW1lID09PSAnc3RyZWFtSWQnKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIHJldHVybiBjaGlsZHJlbltpXS52YWx1ZTtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgICAgICAgICAvL2xvZ2dlci5pbmZvKGVsZW1lbnQuaWQgKyBcIiBTUkM6IFwiICsgc3JjKTtcbiAgICAgICAgICAgICAgICAgICAgICAgIHJldHVybiBudWxsO1xuICAgICAgICAgICAgICAgICAgICB9O1xuICAgICAgICAgICAgICAgICAgICBzZWxmLnNldFZpZGVvU3JjID0gZnVuY3Rpb24gKGVsZW1lbnQsIHNyYykge1xuICAgICAgICAgICAgICAgICAgICAgICAgLy9sb2dnZXIuaW5mbyhcIlNldCB2aWRlbyBzcmM6IFwiLCBlbGVtZW50LCBzcmMpO1xuICAgICAgICAgICAgICAgICAgICAgICAgaWYgKCFzcmMpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICBsb2dnZXIud2FybihcIk5vdCBhdHRhY2hpbmcgdmlkZW8gc3RyZWFtLCAnc3JjJyBpcyBudWxsXCIpO1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgIHJldHVybjtcbiAgICAgICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICAgICAgICAgIEFkYXB0ZXJKUy5XZWJSVENQbHVnaW4uV2FpdEZvclBsdWdpblJlYWR5KCk7XG4gICAgICAgICAgICAgICAgICAgICAgICB2YXIgc3RyZWFtID0gQWRhcHRlckpTLldlYlJUQ1BsdWdpbi5wbHVnaW5cbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAuZ2V0U3RyZWFtV2l0aElkKEFkYXB0ZXJKUy5XZWJSVENQbHVnaW4ucGFnZUlkLCBzcmMpO1xuICAgICAgICAgICAgICAgICAgICAgICAgYXR0YWNoTWVkaWFTdHJlYW0oZWxlbWVudCwgc3RyZWFtKTtcbiAgICAgICAgICAgICAgICAgICAgfTtcblxuICAgICAgICAgICAgICAgICAgICBvblJlYWR5KG9wdGlvbnMsIHNlbGYuZ2V0VXNlck1lZGlhV2l0aENvbnN0cmFpbnRzKTtcbiAgICAgICAgICAgICAgICAgICAgcmVzb2x2ZSgpO1xuICAgICAgICAgICAgICAgIH0pO1xuICAgICAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgICAgICB0cnkge1xuICAgICAgICAgICAgICAgICAgICBsb2dnZXIuZXJyb3IoJ0Jyb3dzZXIgZG9lcyBub3QgYXBwZWFyIHRvIGJlIFdlYlJUQy1jYXBhYmxlJyk7XG4gICAgICAgICAgICAgICAgfSBjYXRjaCAoZSkge1xuICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICByZWplY3QoJ0Jyb3dzZXIgZG9lcyBub3QgYXBwZWFyIHRvIGJlIFdlYlJUQy1jYXBhYmxlJyk7XG4gICAgICAgICAgICAgICAgcmV0dXJuO1xuICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICAvLyBDYWxsIG9uUmVhZHkoKSBpZiBUZW1hc3lzIHBsdWdpbiBpcyBub3QgdXNlZFxuICAgICAgICAgICAgaWYgKCFSVENCcm93c2VyVHlwZS5pc1RlbWFzeXNQbHVnaW5Vc2VkKCkpIHtcbiAgICAgICAgICAgICAgICBvblJlYWR5KG9wdGlvbnMsIHRoaXMuZ2V0VXNlck1lZGlhV2l0aENvbnN0cmFpbnRzKTtcbiAgICAgICAgICAgICAgICByZXNvbHZlKCk7XG4gICAgICAgICAgICB9XG4gICAgICAgIH0uYmluZCh0aGlzKSk7XG4gICAgfSxcbiAgICAvKipcbiAgICAqIEBwYXJhbSB7c3RyaW5nW119IHVtIHJlcXVpcmVkIHVzZXIgbWVkaWEgdHlwZXNcbiAgICAqIEBwYXJhbSB7ZnVuY3Rpb259IHN1Y2Nlc3NfY2FsbGJhY2tcbiAgICAqIEBwYXJhbSB7RnVuY3Rpb259IGZhaWx1cmVfY2FsbGJhY2tcbiAgICAqIEBwYXJhbSB7T2JqZWN0fSBbb3B0aW9uc10gb3B0aW9uYWwgcGFyYW1ldGVyc1xuICAgICogQHBhcmFtIHtzdHJpbmd9IG9wdGlvbnMucmVzb2x1dGlvblxuICAgICogQHBhcmFtIHtudW1iZXJ9IG9wdGlvbnMuYmFuZHdpZHRoXG4gICAgKiBAcGFyYW0ge251bWJlcn0gb3B0aW9ucy5mcHNcbiAgICAqIEBwYXJhbSB7c3RyaW5nfSBvcHRpb25zLmRlc2t0b3BTdHJlYW1cbiAgICAqIEBwYXJhbSB7c3RyaW5nfSBvcHRpb25zLmNhbWVyYURldmljZUlkXG4gICAgKiBAcGFyYW0ge3N0cmluZ30gb3B0aW9ucy5taWNEZXZpY2VJZFxuICAgICoqL1xuICAgIGdldFVzZXJNZWRpYVdpdGhDb25zdHJhaW50czogZnVuY3Rpb24gKCB1bSwgc3VjY2Vzc19jYWxsYmFjaywgZmFpbHVyZV9jYWxsYmFjaywgb3B0aW9ucykge1xuICAgICAgICBvcHRpb25zID0gb3B0aW9ucyB8fCB7fTtcbiAgICAgICAgdmFyIHJlc29sdXRpb24gPSBvcHRpb25zLnJlc29sdXRpb247XG4gICAgICAgIHZhciBjb25zdHJhaW50cyA9IGdldENvbnN0cmFpbnRzKHVtLCBvcHRpb25zKTtcblxuICAgICAgICBsb2dnZXIuaW5mbyhcIkdldCBtZWRpYSBjb25zdHJhaW50c1wiLCBjb25zdHJhaW50cyk7XG5cbiAgICAgICAgdHJ5IHtcbiAgICAgICAgICAgIHRoaXMuZ2V0VXNlck1lZGlhKGNvbnN0cmFpbnRzLFxuICAgICAgICAgICAgICAgIGZ1bmN0aW9uIChzdHJlYW0pIHtcbiAgICAgICAgICAgICAgICAgICAgbG9nZ2VyLmxvZygnb25Vc2VyTWVkaWFTdWNjZXNzJyk7XG4gICAgICAgICAgICAgICAgICAgIHNldEF2YWlsYWJsZURldmljZXModW0sIHRydWUpO1xuICAgICAgICAgICAgICAgICAgICBzdWNjZXNzX2NhbGxiYWNrKHN0cmVhbSk7XG4gICAgICAgICAgICAgICAgfSxcbiAgICAgICAgICAgICAgICBmdW5jdGlvbiAoZXJyb3IpIHtcbiAgICAgICAgICAgICAgICAgICAgc2V0QXZhaWxhYmxlRGV2aWNlcyh1bSwgZmFsc2UpO1xuICAgICAgICAgICAgICAgICAgICBsb2dnZXIud2FybignRmFpbGVkIHRvIGdldCBhY2Nlc3MgdG8gbG9jYWwgbWVkaWEuIEVycm9yICcsXG4gICAgICAgICAgICAgICAgICAgICAgICBlcnJvciwgY29uc3RyYWludHMpO1xuICAgICAgICAgICAgICAgICAgICBpZiAoZmFpbHVyZV9jYWxsYmFjaykge1xuICAgICAgICAgICAgICAgICAgICAgICAgZmFpbHVyZV9jYWxsYmFjayhlcnJvciwgcmVzb2x1dGlvbik7XG4gICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICB9KTtcbiAgICAgICAgfSBjYXRjaCAoZSkge1xuICAgICAgICAgICAgbG9nZ2VyLmVycm9yKCdHVU0gZmFpbGVkOiAnLCBlKTtcbiAgICAgICAgICAgIGlmIChmYWlsdXJlX2NhbGxiYWNrKSB7XG4gICAgICAgICAgICAgICAgZmFpbHVyZV9jYWxsYmFjayhlKTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgfVxuICAgIH0sXG5cbiAgICAvKipcbiAgICAgKiBDcmVhdGVzIHRoZSBsb2NhbCBNZWRpYVN0cmVhbXMuXG4gICAgICogQHBhcmFtIHtPYmplY3R9IFtvcHRpb25zXSBvcHRpb25hbCBwYXJhbWV0ZXJzXG4gICAgICogQHBhcmFtIHtBcnJheX0gb3B0aW9ucy5kZXZpY2VzIHRoZSBkZXZpY2VzIHRoYXQgd2lsbCBiZSByZXF1ZXN0ZWRcbiAgICAgKiBAcGFyYW0ge3N0cmluZ30gb3B0aW9ucy5yZXNvbHV0aW9uIHJlc29sdXRpb24gY29uc3RyYWludHNcbiAgICAgKiBAcGFyYW0ge2Jvb2x9IG9wdGlvbnMuZG9udENyZWF0ZUppdHNpVHJhY2sgaWYgPHR0PnRydWU8L3R0PiBvYmplY3RzIHdpdGggdGhlIGZvbGxvd2luZyBzdHJ1Y3R1cmUge3N0cmVhbTogdGhlIE1lZGlhIFN0cmVhbSxcbiAgICAgKiB0eXBlOiBcImF1ZGlvXCIgb3IgXCJ2aWRlb1wiLCB2aWRlb1R5cGU6IFwiY2FtZXJhXCIgb3IgXCJkZXNrdG9wXCJ9XG4gICAgICogd2lsbCBiZSByZXR1cm5lZCB0cm91Z2ggdGhlIFByb21pc2UsIG90aGVyd2lzZSBKaXRzaVRyYWNrIG9iamVjdHMgd2lsbCBiZSByZXR1cm5lZC5cbiAgICAgKiBAcGFyYW0ge3N0cmluZ30gb3B0aW9ucy5jYW1lcmFEZXZpY2VJZFxuICAgICAqIEBwYXJhbSB7c3RyaW5nfSBvcHRpb25zLm1pY0RldmljZUlkXG4gICAgICogQHJldHVybnMgeyp9IFByb21pc2Ugb2JqZWN0IHRoYXQgd2lsbCByZWNlaXZlIHRoZSBuZXcgSml0c2lUcmFja3NcbiAgICAgKi9cbiAgICBvYnRhaW5BdWRpb0FuZFZpZGVvUGVybWlzc2lvbnM6IGZ1bmN0aW9uIChvcHRpb25zKSB7XG4gICAgICAgIHZhciBzZWxmID0gdGhpcztcblxuICAgICAgICBvcHRpb25zID0gb3B0aW9ucyB8fCB7fTtcbiAgICAgICAgcmV0dXJuIG5ldyBQcm9taXNlKGZ1bmN0aW9uIChyZXNvbHZlLCByZWplY3QpIHtcbiAgICAgICAgICAgIHZhciBzdWNjZXNzQ2FsbGJhY2sgPSBmdW5jdGlvbiAoc3RyZWFtKSB7XG4gICAgICAgICAgICAgICAgcmVzb2x2ZShoYW5kbGVMb2NhbFN0cmVhbShzdHJlYW0sIG9wdGlvbnMucmVzb2x1dGlvbikpO1xuICAgICAgICAgICAgfTtcblxuICAgICAgICAgICAgb3B0aW9ucy5kZXZpY2VzID0gb3B0aW9ucy5kZXZpY2VzIHx8IFsnYXVkaW8nLCAndmlkZW8nXTtcbiAgICAgICAgICAgIGlmKCFzY3JlZW5PYnRhaW5lci5pc1N1cHBvcnRlZCgpXG4gICAgICAgICAgICAgICAgJiYgb3B0aW9ucy5kZXZpY2VzLmluZGV4T2YoXCJkZXNrdG9wXCIpICE9PSAtMSl7XG4gICAgICAgICAgICAgICAgcmVqZWN0KG5ldyBFcnJvcihcIkRlc2t0b3Agc2hhcmluZyBpcyBub3Qgc3VwcG9ydGVkIVwiKSk7XG4gICAgICAgICAgICB9XG4gICAgICAgICAgICBpZiAoUlRDQnJvd3NlclR5cGUuaXNGaXJlZm94KCkgfHxcbiAgICAgICAgICAgICAgICBSVENCcm93c2VyVHlwZS5pc1RlbWFzeXNQbHVnaW5Vc2VkKCkpIHtcbiAgICAgICAgICAgICAgICB2YXIgR1VNID0gZnVuY3Rpb24gKGRldmljZSwgcywgZSkge1xuICAgICAgICAgICAgICAgICAgICB0aGlzLmdldFVzZXJNZWRpYVdpdGhDb25zdHJhaW50cyhkZXZpY2UsIHMsIGUsIG9wdGlvbnMpO1xuICAgICAgICAgICAgICAgIH07XG4gICAgICAgICAgICAgICAgdmFyIGRldmljZUdVTSA9IHtcbiAgICAgICAgICAgICAgICAgICAgXCJhdWRpb1wiOiBHVU0uYmluZChzZWxmLCBbXCJhdWRpb1wiXSksXG4gICAgICAgICAgICAgICAgICAgIFwidmlkZW9cIjogR1VNLmJpbmQoc2VsZiwgW1widmlkZW9cIl0pLFxuICAgICAgICAgICAgICAgICAgICBcImRlc2t0b3BcIjogc2NyZWVuT2J0YWluZXIub2J0YWluU3RyZWFtLmJpbmQoc2NyZWVuT2J0YWluZXIpXG4gICAgICAgICAgICAgICAgfTtcbiAgICAgICAgICAgICAgICAvLyBXaXRoIEZGL0lFIHdlIGNhbid0IHNwbGl0IHRoZSBzdHJlYW0gaW50byBhdWRpbyBhbmQgdmlkZW8gYmVjYXVzZSBGRlxuICAgICAgICAgICAgICAgIC8vIGRvZXNuJ3Qgc3VwcG9ydCBtZWRpYSBzdHJlYW0gY29uc3RydWN0b3JzLiBTbywgd2UgbmVlZCB0byBnZXQgdGhlXG4gICAgICAgICAgICAgICAgLy8gYXVkaW8gc3RyZWFtIHNlcGFyYXRlbHkgZnJvbSB0aGUgdmlkZW8gc3RyZWFtIHVzaW5nIHR3byBkaXN0aW5jdCBHVU1cbiAgICAgICAgICAgICAgICAvLyBjYWxscy4gTm90IHZlcnkgdXNlciBmcmllbmRseSA6LSggYnV0IHdlIGRvbid0IGhhdmUgbWFueSBvdGhlclxuICAgICAgICAgICAgICAgIC8vIG9wdGlvbnMgbmVpdGhlci5cbiAgICAgICAgICAgICAgICAvL1xuICAgICAgICAgICAgICAgIC8vIE5vdGUgdGhhdCB3ZSBwYWNrIHRob3NlIDIgc3RyZWFtcyBpbiBhIHNpbmdsZSBvYmplY3QgYW5kIHBhc3MgaXQgdG9cbiAgICAgICAgICAgICAgICAvLyB0aGUgc3VjY2Vzc0NhbGxiYWNrIG1ldGhvZC5cbiAgICAgICAgICAgICAgICBvYnRhaW5EZXZpY2VzKHtcbiAgICAgICAgICAgICAgICAgICAgZGV2aWNlczogb3B0aW9ucy5kZXZpY2VzLFxuICAgICAgICAgICAgICAgICAgICBzdHJlYW1zOiBbXSxcbiAgICAgICAgICAgICAgICAgICAgc3VjY2Vzc0NhbGxiYWNrOiBzdWNjZXNzQ2FsbGJhY2ssXG4gICAgICAgICAgICAgICAgICAgIGVycm9yQ2FsbGJhY2s6IHJlamVjdCxcbiAgICAgICAgICAgICAgICAgICAgZGV2aWNlR1VNOiBkZXZpY2VHVU1cbiAgICAgICAgICAgICAgICB9KTtcbiAgICAgICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICAgICAgdmFyIGhhc0Rlc2t0b3AgPSBvcHRpb25zLmRldmljZXMuaW5kZXhPZignZGVza3RvcCcpID4gLTE7XG4gICAgICAgICAgICAgICAgaWYgKGhhc0Rlc2t0b3ApIHtcbiAgICAgICAgICAgICAgICAgICAgb3B0aW9ucy5kZXZpY2VzLnNwbGljZShvcHRpb25zLmRldmljZXMuaW5kZXhPZihcImRlc2t0b3BcIiksIDEpO1xuICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICBvcHRpb25zLnJlc29sdXRpb24gPSBvcHRpb25zLnJlc29sdXRpb24gfHwgJzM2MCc7XG4gICAgICAgICAgICAgICAgaWYob3B0aW9ucy5kZXZpY2VzLmxlbmd0aCkge1xuICAgICAgICAgICAgICAgICAgICB0aGlzLmdldFVzZXJNZWRpYVdpdGhDb25zdHJhaW50cyhcbiAgICAgICAgICAgICAgICAgICAgICAgIG9wdGlvbnMuZGV2aWNlcyxcbiAgICAgICAgICAgICAgICAgICAgICAgIGZ1bmN0aW9uIChzdHJlYW0pIHtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICBpZihoYXNEZXNrdG9wKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIHNjcmVlbk9idGFpbmVyLm9idGFpblN0cmVhbShcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGZ1bmN0aW9uIChkZXNrdG9wU3RyZWFtKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgc3VjY2Vzc0NhbGxiYWNrKHthdWRpb1ZpZGVvOiBzdHJlYW0sXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGRlc2t0b3BTdHJlYW06IGRlc2t0b3BTdHJlYW19KTtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIH0sIGZ1bmN0aW9uIChlcnJvcikge1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIHJlamVjdChcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgSml0c2lUcmFja0Vycm9ycy5wYXJzZUVycm9yKGVycm9yKSk7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICB9KTtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBzdWNjZXNzQ2FsbGJhY2soe2F1ZGlvVmlkZW86IHN0cmVhbX0pO1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICAgICAgICAgIH0sXG4gICAgICAgICAgICAgICAgICAgICAgICBmdW5jdGlvbiAoZXJyb3IpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICByZWplY3QoSml0c2lUcmFja0Vycm9ycy5wYXJzZUVycm9yKGVycm9yKSk7XG4gICAgICAgICAgICAgICAgICAgICAgICB9LFxuICAgICAgICAgICAgICAgICAgICAgICAgb3B0aW9ucyk7XG4gICAgICAgICAgICAgICAgfSBlbHNlIGlmIChoYXNEZXNrdG9wKSB7XG4gICAgICAgICAgICAgICAgICAgIHNjcmVlbk9idGFpbmVyLm9idGFpblN0cmVhbShcbiAgICAgICAgICAgICAgICAgICAgICAgIGZ1bmN0aW9uIChzdHJlYW0pIHtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICBzdWNjZXNzQ2FsbGJhY2soe2Rlc2t0b3BTdHJlYW06IHN0cmVhbX0pO1xuICAgICAgICAgICAgICAgICAgICAgICAgfSwgZnVuY3Rpb24gKGVycm9yKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgcmVqZWN0KFxuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBKaXRzaVRyYWNrRXJyb3JzLnBhcnNlRXJyb3IoZXJyb3IpKTtcbiAgICAgICAgICAgICAgICAgICAgICAgIH0pO1xuICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgIH1cbiAgICAgICAgfS5iaW5kKHRoaXMpKTtcbiAgICB9LFxuICAgIGFkZExpc3RlbmVyOiBmdW5jdGlvbiAoZXZlbnRUeXBlLCBsaXN0ZW5lcikge1xuICAgICAgICBldmVudEVtaXR0ZXIub24oZXZlbnRUeXBlLCBsaXN0ZW5lcik7XG4gICAgfSxcbiAgICByZW1vdmVMaXN0ZW5lcjogZnVuY3Rpb24gKGV2ZW50VHlwZSwgbGlzdGVuZXIpIHtcbiAgICAgICAgZXZlbnRFbWl0dGVyLnJlbW92ZUxpc3RlbmVyKGV2ZW50VHlwZSwgbGlzdGVuZXIpO1xuICAgIH0sXG4gICAgZ2V0RGV2aWNlQXZhaWxhYmlsaXR5OiBmdW5jdGlvbiAoKSB7XG4gICAgICAgIHJldHVybiBkZXZpY2VzO1xuICAgIH0sXG4gICAgaXNSVENSZWFkeTogZnVuY3Rpb24gKCkge1xuICAgICAgICByZXR1cm4gcnRjUmVhZHk7XG4gICAgfSxcbiAgICAvKipcbiAgICAgKiBDaGVja3MgaWYgaXRzIHBvc3NpYmxlIHRvIGVudW1lcmF0ZSBhdmFpbGFibGUgY2FtZXJhcy9taWNyb3BvbmVzLlxuICAgICAqIEByZXR1cm5zIHtib29sZWFufSB0cnVlIGlmIGF2YWlsYWJsZSwgZmFsc2Ugb3RoZXJ3aXNlLlxuICAgICAqL1xuICAgIGlzRGV2aWNlTGlzdEF2YWlsYWJsZTogZnVuY3Rpb24gKCkge1xuICAgICAgICB2YXIgaXNFbnVtZXJhdGVEZXZpY2VzQXZhaWxhYmxlID0gbmF2aWdhdG9yLm1lZGlhRGV2aWNlcyAmJiBuYXZpZ2F0b3IubWVkaWFEZXZpY2VzLmVudW1lcmF0ZURldmljZXM7XG4gICAgICAgIGlmIChpc0VudW1lcmF0ZURldmljZXNBdmFpbGFibGUpIHtcbiAgICAgICAgICAgIHJldHVybiB0cnVlO1xuICAgICAgICB9XG4gICAgICAgIHJldHVybiAoTWVkaWFTdHJlYW1UcmFjayAmJiBNZWRpYVN0cmVhbVRyYWNrLmdldFNvdXJjZXMpPyB0cnVlIDogZmFsc2U7XG4gICAgfSxcbiAgICAvKipcbiAgICAgKiBSZXR1cm5zIHRydWUgaWYgY2hhbmdpbmcgdGhlIGNhbWVyYSAvIG1pY3JvcGhvbmUgZGV2aWNlIGlzIHN1cHBvcnRlZCBhbmRcbiAgICAgKiBmYWxzZSBpZiBub3QuXG4gICAgICovXG4gICAgaXNEZXZpY2VDaGFuZ2VBdmFpbGFibGU6IGZ1bmN0aW9uICgpIHtcbiAgICAgICAgaWYoUlRDQnJvd3NlclR5cGUuaXNDaHJvbWUoKSB8fCBSVENCcm93c2VyVHlwZS5pc09wZXJhKCkgfHxcbiAgICAgICAgICAgIFJUQ0Jyb3dzZXJUeXBlLmlzVGVtYXN5c1BsdWdpblVzZWQoKSlcbiAgICAgICAgICAgIHJldHVybiB0cnVlO1xuICAgICAgICByZXR1cm4gZmFsc2U7XG4gICAgfSxcbiAgICAvKipcbiAgICAgKiBBIG1ldGhvZCB0byBoYW5kbGUgc3RvcHBpbmcgb2YgdGhlIHN0cmVhbS5cbiAgICAgKiBPbmUgcG9pbnQgdG8gaGFuZGxlIHRoZSBkaWZmZXJlbmNlcyBpbiB2YXJpb3VzIGltcGxlbWVudGF0aW9ucy5cbiAgICAgKiBAcGFyYW0gbWVkaWFTdHJlYW0gTWVkaWFTdHJlYW0gb2JqZWN0IHRvIHN0b3AuXG4gICAgICovXG4gICAgc3RvcE1lZGlhU3RyZWFtOiBmdW5jdGlvbiAobWVkaWFTdHJlYW0pIHtcbiAgICAgICAgbWVkaWFTdHJlYW0uZ2V0VHJhY2tzKCkuZm9yRWFjaChmdW5jdGlvbiAodHJhY2spIHtcbiAgICAgICAgICAgIC8vIHN0b3AoKSBub3Qgc3VwcG9ydGVkIHdpdGggSUVcbiAgICAgICAgICAgIGlmICh0cmFjay5zdG9wKSB7XG4gICAgICAgICAgICAgICAgdHJhY2suc3RvcCgpO1xuICAgICAgICAgICAgfVxuICAgICAgICB9KTtcblxuICAgICAgICAvLyBsZWF2ZSBzdG9wIGZvciBpbXBsZW1lbnRhdGlvbiBzdGlsbCB1c2luZyBpdFxuICAgICAgICBpZiAobWVkaWFTdHJlYW0uc3RvcCkge1xuICAgICAgICAgICAgbWVkaWFTdHJlYW0uc3RvcCgpO1xuICAgICAgICB9XG4gICAgfSxcbiAgICAvKipcbiAgICAgKiBSZXR1cm5zIHdoZXRoZXIgdGhlIGRlc2t0b3Agc2hhcmluZyBpcyBlbmFibGVkIG9yIG5vdC5cbiAgICAgKiBAcmV0dXJucyB7Ym9vbGVhbn1cbiAgICAgKi9cbiAgICBpc0Rlc2t0b3BTaGFyaW5nRW5hYmxlZDogZnVuY3Rpb24gKCkge1xuICAgICAgICByZXR1cm4gc2NyZWVuT2J0YWluZXIuaXNTdXBwb3J0ZWQoKTtcbiAgICB9XG5cbn07XG5cbm1vZHVsZS5leHBvcnRzID0gUlRDVXRpbHM7XG4iLCIvKiBnbG9iYWwgY2hyb21lLCAkLCBhbGVydCAqL1xuLyoganNoaW50IC1XMDAzICovXG52YXIgbG9nZ2VyID0gcmVxdWlyZShcImppdHNpLW1lZXQtbG9nZ2VyXCIpLmdldExvZ2dlcihfX2ZpbGVuYW1lKTtcbnZhciBSVENCcm93c2VyVHlwZSA9IHJlcXVpcmUoXCIuL1JUQ0Jyb3dzZXJUeXBlXCIpO1xudmFyIEFkYXB0ZXJKUyA9IHJlcXVpcmUoXCIuL2FkYXB0ZXIuc2NyZWVuc2hhcmVcIik7XG52YXIgRGVza3RvcFNoYXJpbmdFdmVudFR5cGVzXG4gICAgPSByZXF1aXJlKFwiLi4vLi4vc2VydmljZS9kZXNrdG9wc2hhcmluZy9EZXNrdG9wU2hhcmluZ0V2ZW50VHlwZXNcIik7XG5cbi8qKlxuICogSW5kaWNhdGVzIHdoZXRoZXIgdGhlIENocm9tZSBkZXNrdG9wIHNoYXJpbmcgZXh0ZW5zaW9uIGlzIGluc3RhbGxlZC5cbiAqIEB0eXBlIHtib29sZWFufVxuICovXG52YXIgY2hyb21lRXh0SW5zdGFsbGVkID0gZmFsc2U7XG5cbi8qKlxuICogSW5kaWNhdGVzIHdoZXRoZXIgYW4gdXBkYXRlIG9mIHRoZSBDaHJvbWUgZGVza3RvcCBzaGFyaW5nIGV4dGVuc2lvbiBpc1xuICogcmVxdWlyZWQuXG4gKiBAdHlwZSB7Ym9vbGVhbn1cbiAqL1xudmFyIGNocm9tZUV4dFVwZGF0ZVJlcXVpcmVkID0gZmFsc2U7XG5cbi8qKlxuICogV2hldGhlciB0aGUgamlkZXNoYSBleHRlbnNpb24gZm9yIGZpcmVmb3ggaXMgaW5zdGFsbGVkIGZvciB0aGUgZG9tYWluIG9uXG4gKiB3aGljaCB3ZSBhcmUgcnVubmluZy4gTnVsbCBkZXNpZ25hdGVzIGFuIHVua25vd24gdmFsdWUuXG4gKiBAdHlwZSB7bnVsbH1cbiAqL1xudmFyIGZpcmVmb3hFeHRJbnN0YWxsZWQgPSBudWxsO1xuXG4vKipcbiAqIElmIHNldCB0byB0cnVlLCBkZXRlY3Rpb24gb2YgYW4gaW5zdGFsbGVkIGZpcmVmb3ggZXh0ZW5zaW9uIHdpbGwgYmUgc3RhcnRlZFxuICogYWdhaW4gdGhlIG5leHQgdGltZSBvYnRhaW5TY3JlZW5PbkZpcmVmb3ggaXMgY2FsbGVkIChlLmcuIG5leHQgdGltZSB0aGVcbiAqIHVzZXIgdHJpZXMgdG8gZW5hYmxlIHNjcmVlbiBzaGFyaW5nKS5cbiAqL1xudmFyIHJlRGV0ZWN0RmlyZWZveEV4dGVuc2lvbiA9IGZhbHNlO1xuXG52YXIgR1VNID0gbnVsbDtcblxuLyoqXG4gKiBIYW5kbGVzIG9idGFpbmluZyBhIHN0cmVhbSBmcm9tIGEgc2NyZWVuIGNhcHR1cmUgb24gZGlmZmVyZW50IGJyb3dzZXJzLlxuICovXG52YXIgU2NyZWVuT2J0YWluZXIgPSB7XG4gICAgLyoqXG4gICAgICogVGhlIEV2ZW50RW1pdHRlciB0byB1c2UgdG8gZW1pdCBldmVudHMuXG4gICAgICogQHR5cGUge251bGx9XG4gICAgICovXG4gICAgZXZlbnRFbWl0dGVyOiBudWxsLFxuICAgIG9idGFpblN0cmVhbTogbnVsbCxcbiAgICAvKipcbiAgICAgKiBJbml0aWFsaXplcyB0aGUgZnVuY3Rpb24gdXNlZCB0byBvYnRhaW4gYSBzY3JlZW4gY2FwdHVyZVxuICAgICAqICh0aGlzLm9idGFpblN0cmVhbSkuXG4gICAgICogXG4gICAgICogSWYgdGhlIGJyb3dzZXIgaXMgQ2hyb21lLCBpdCB1c2VzIHRoZSB2YWx1ZSBvZlxuICAgICAqICdvcHRpb25zLmRlc2t0b3BTaGFyaW5nQ2hyb21lTWV0aG9kJyAob3IgJ29wdGlvbnMuZGVza3RvcFNoYXJpbmcnKSB0b1xuICAgICAqIGRlY2lkZSB3aGV0aGVyIHRvIHVzZSB0aGUgYSBDaHJvbWUgZXh0ZW5zaW9uIChpZiB0aGUgdmFsdWUgaXMgJ2V4dCcpLFxuICAgICAqIHVzZSB0aGUgXCJzY3JlZW5cIiBtZWRpYSBzb3VyY2UgKGlmIHRoZSB2YWx1ZSBpcyAnd2VicnRjJyksXG4gICAgICogb3IgZGlzYWJsZSBzY3JlZW4gY2FwdHVyZSAoaWYgdGhlIHZhbHVlIGlzIG90aGVyKS5cbiAgICAgKiBOb3RlIHRoYXQgZm9yIHRoZSBcInNjcmVlblwiIG1lZGlhIHNvdXJjZSB0byB3b3JrIHRoZVxuICAgICAqICdjaHJvbWU6Ly9mbGFncy8jZW5hYmxlLXVzZXJtZWRpYS1zY3JlZW4tY2FwdHVyZScgZmxhZyBtdXN0IGJlIHNldC5cbiAgICAgKi9cbiAgICBpbml0OiBmdW5jdGlvbihldmVudEVtaXR0ZXIsIG9wdGlvbnMsIGd1bSkge1xuICAgICAgICB0aGlzLmV2ZW50RW1pdHRlciA9IGV2ZW50RW1pdHRlcjtcbiAgICAgICAgdmFyIG9idGFpbkRlc2t0b3BTdHJlYW0gPSBudWxsO1xuICAgICAgICB0aGlzLm9wdGlvbnMgPSBvcHRpb25zID0gb3B0aW9ucyB8fCB7fTtcbiAgICAgICAgR1VNID0gZ3VtO1xuXG4gICAgICAgIGlmIChSVENCcm93c2VyVHlwZS5pc0ZpcmVmb3goKSlcbiAgICAgICAgICAgIGluaXRGaXJlZm94RXh0ZW5zaW9uRGV0ZWN0aW9uKG9wdGlvbnMpO1xuXG4gICAgICAgIC8vIFRPRE8gcmVtb3ZlIHRoaXMsIG9wdGlvbnMuZGVza3RvcFNoYXJpbmcgaXMgZGVwcmVjYXRlZC5cbiAgICAgICAgdmFyIGNocm9tZU1ldGhvZCA9XG4gICAgICAgICAgICAob3B0aW9ucy5kZXNrdG9wU2hhcmluZ0Nocm9tZU1ldGhvZCB8fCBvcHRpb25zLmRlc2t0b3BTaGFyaW5nKTtcblxuICAgICAgICBpZiAoUlRDQnJvd3NlclR5cGUuaXNUZW1hc3lzUGx1Z2luVXNlZCgpKSB7XG4gICAgICAgICAgICBpZiAoIUFkYXB0ZXJKUy5XZWJSVENQbHVnaW4ucGx1Z2luLkhhc1NjcmVlbnNoYXJpbmdGZWF0dXJlKSB7XG4gICAgICAgICAgICAgICAgbG9nZ2VyLmluZm8oXCJTY3JlZW5zaGFyaW5nIG5vdCBzdXBwb3J0ZWQgYnkgdGhpcyBwbHVnaW4gXCIgK1xuICAgICAgICAgICAgICAgICAgICBcInZlcnNpb25cIik7XG4gICAgICAgICAgICB9IGVsc2UgaWYoIUFkYXB0ZXJKUy5XZWJSVENQbHVnaW4ucGx1Z2luLmlzU2NyZWVuc2hhcmluZ0F2YWlsYWJsZSkge1xuICAgICAgICAgICAgICAgIGxvZ2dlci5pbmZvKFxuICAgICAgICAgICAgICAgICAgICBcIlNjcmVlbnNoYXJpbmcgbm90IGF2YWlsYWJsZSB3aXRoIFRlbWFzeXMgcGx1Z2luIG9uXCIgK1xuICAgICAgICAgICAgICAgICAgICBcIiB0aGlzIHNpdGVcIik7XG4gICAgICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgICAgIG9idGFpbkRlc2t0b3BTdHJlYW0gPSBvYnRhaW5XZWJSVENTY3JlZW47XG4gICAgICAgICAgICAgICAgbG9nZ2VyLmluZm8oXCJVc2luZyBUZW1hc3lzIHBsdWdpbiBmb3IgZGVza3RvcCBzaGFyaW5nXCIpO1xuICAgICAgICAgICAgfVxuICAgICAgICB9IGVsc2UgaWYgKFJUQ0Jyb3dzZXJUeXBlLmlzQ2hyb21lKCkpIHtcbiAgICAgICAgICAgIGlmIChjaHJvbWVNZXRob2QgPT0gXCJleHRcIikge1xuICAgICAgICAgICAgICAgIGlmIChSVENCcm93c2VyVHlwZS5nZXRDaHJvbWVWZXJzaW9uKCkgPj0gMzQpIHtcbiAgICAgICAgICAgICAgICAgICAgb2J0YWluRGVza3RvcFN0cmVhbSA9XG4gICAgICAgICAgICAgICAgICAgICAgICB0aGlzLm9idGFpblNjcmVlbkZyb21FeHRlbnNpb247XG4gICAgICAgICAgICAgICAgICAgIGxvZ2dlci5pbmZvKFwiVXNpbmcgQ2hyb21lIGV4dGVuc2lvbiBmb3IgZGVza3RvcCBzaGFyaW5nXCIpO1xuICAgICAgICAgICAgICAgICAgICBpbml0Q2hyb21lRXh0ZW5zaW9uKG9wdGlvbnMpO1xuICAgICAgICAgICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICAgICAgICAgIGxvZ2dlci5pbmZvKFwiQ2hyb21lIGV4dGVuc2lvbiBub3Qgc3VwcG9ydGVkIHVudGlsIHZlciAzNFwiKTtcbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICB9IGVsc2UgaWYgKGNocm9tZU1ldGhvZCA9PSBcIndlYnJ0Y1wiKSB7XG4gICAgICAgICAgICAgICAgb2J0YWluRGVza3RvcFN0cmVhbSA9IG9idGFpbldlYlJUQ1NjcmVlbjtcbiAgICAgICAgICAgICAgICBsb2dnZXIuaW5mbyhcIlVzaW5nIENocm9tZSBXZWJSVEMgZm9yIGRlc2t0b3Agc2hhcmluZ1wiKTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgfSBlbHNlIGlmIChSVENCcm93c2VyVHlwZS5pc0ZpcmVmb3goKSkge1xuICAgICAgICAgICAgaWYgKG9wdGlvbnMuZGVza3RvcFNoYXJpbmdGaXJlZm94RGlzYWJsZWQpIHtcbiAgICAgICAgICAgICAgICBvYnRhaW5EZXNrdG9wU3RyZWFtID0gbnVsbDtcbiAgICAgICAgICAgIH0gZWxzZSBpZiAod2luZG93LmxvY2F0aW9uLnByb3RvY29sID09PSBcImh0dHA6XCIpe1xuICAgICAgICAgICAgICAgIGxvZ2dlci5sb2coXCJTY3JlZW4gc2hhcmluZyBpcyBub3Qgc3VwcG9ydGVkIG92ZXIgSFRUUC4gXCIgK1xuICAgICAgICAgICAgICAgICAgICBcIlVzZSBvZiBIVFRQUyBpcyByZXF1aXJlZC5cIik7XG4gICAgICAgICAgICAgICAgb2J0YWluRGVza3RvcFN0cmVhbSA9IG51bGw7XG4gICAgICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgICAgIG9idGFpbkRlc2t0b3BTdHJlYW0gPSB0aGlzLm9idGFpblNjcmVlbk9uRmlyZWZveDtcbiAgICAgICAgICAgIH1cblxuICAgICAgICB9XG5cbiAgICAgICAgaWYgKCFvYnRhaW5EZXNrdG9wU3RyZWFtKSB7XG4gICAgICAgICAgICBsb2dnZXIuaW5mbyhcIkRlc2t0b3Agc2hhcmluZyBkaXNhYmxlZFwiKTtcbiAgICAgICAgfVxuXG4gICAgICAgIHRoaXMub2J0YWluU3RyZWFtID0gb2J0YWluRGVza3RvcFN0cmVhbTtcbiAgICB9LFxuXG4gICAgLyoqXG4gICAgICogQ2hlY2tzIHdoZXRoZXIgb2J0YWluaW5nIGEgc2NyZWVuIGNhcHR1cmUgaXMgc3VwcG9ydGVkIGluIHRoZSBjdXJyZW50XG4gICAgICogZW52aXJvbm1lbnQuXG4gICAgICogQHJldHVybnMge2Jvb2xlYW59XG4gICAgICovXG4gICAgaXNTdXBwb3J0ZWQ6IGZ1bmN0aW9uKCkge1xuICAgICAgICByZXR1cm4gISF0aGlzLm9idGFpblN0cmVhbTtcbiAgICB9LFxuICAgIC8qKlxuICAgICAqIE9idGFpbnMgYSBzY3JlZW4gY2FwdHVyZSBzdHJlYW0gb24gRmlyZWZveC5cbiAgICAgKiBAcGFyYW0gY2FsbGJhY2tcbiAgICAgKiBAcGFyYW0gZXJyb3JDYWxsYmFja1xuICAgICAqL1xuICAgIG9idGFpblNjcmVlbk9uRmlyZWZveDpcbiAgICAgICAgICAgZnVuY3Rpb24gKGNhbGxiYWNrLCBlcnJvckNhbGxiYWNrKSB7XG4gICAgICAgIHZhciBzZWxmID0gdGhpcztcbiAgICAgICAgdmFyIGV4dGVuc2lvblJlcXVpcmVkID0gZmFsc2U7XG4gICAgICAgIGlmICh0aGlzLm9wdGlvbnMuZGVza3RvcFNoYXJpbmdGaXJlZm94TWF4VmVyc2lvbkV4dFJlcXVpcmVkID09PSAtMSB8fFxuICAgICAgICAgICAgKHRoaXMub3B0aW9ucy5kZXNrdG9wU2hhcmluZ0ZpcmVmb3hNYXhWZXJzaW9uRXh0UmVxdWlyZWQgPj0gMCAmJlxuICAgICAgICAgICAgICAgIFJUQ0Jyb3dzZXJUeXBlLmdldEZpcmVmb3hWZXJzaW9uKCkgPD1cbiAgICAgICAgICAgICAgICAgICAgdGhpcy5vcHRpb25zLmRlc2t0b3BTaGFyaW5nRmlyZWZveE1heFZlcnNpb25FeHRSZXF1aXJlZCkpIHtcbiAgICAgICAgICAgIGV4dGVuc2lvblJlcXVpcmVkID0gdHJ1ZTtcbiAgICAgICAgICAgIGxvZ2dlci5sb2coXCJKaWRlc2hhIGV4dGVuc2lvbiByZXF1aXJlZCBvbiBmaXJlZm94IHZlcnNpb24gXCIgK1xuICAgICAgICAgICAgICAgIFJUQ0Jyb3dzZXJUeXBlLmdldEZpcmVmb3hWZXJzaW9uKCkpO1xuICAgICAgICB9XG5cbiAgICAgICAgaWYgKCFleHRlbnNpb25SZXF1aXJlZCB8fCBmaXJlZm94RXh0SW5zdGFsbGVkID09PSB0cnVlKSB7XG4gICAgICAgICAgICBvYnRhaW5XZWJSVENTY3JlZW4oY2FsbGJhY2ssIGVycm9yQ2FsbGJhY2spO1xuICAgICAgICAgICAgcmV0dXJuO1xuICAgICAgICB9XG5cbiAgICAgICAgaWYgKHJlRGV0ZWN0RmlyZWZveEV4dGVuc2lvbikge1xuICAgICAgICAgICAgcmVEZXRlY3RGaXJlZm94RXh0ZW5zaW9uID0gZmFsc2U7XG4gICAgICAgICAgICBpbml0RmlyZWZveEV4dGVuc2lvbkRldGVjdGlvbih0aGlzLm9wdGlvbnMpO1xuICAgICAgICB9XG5cbiAgICAgICAgLy8gR2l2ZSBpdCBzb21lIChtb3JlKSB0aW1lIHRvIGluaXRpYWxpemUsIGFuZCBhc3N1bWUgbGFjayBvZlxuICAgICAgICAvLyBleHRlbnNpb24gaWYgaXQgaGFzbid0LlxuICAgICAgICBpZiAoZmlyZWZveEV4dEluc3RhbGxlZCA9PT0gbnVsbCkge1xuICAgICAgICAgICAgd2luZG93LnNldFRpbWVvdXQoXG4gICAgICAgICAgICAgICAgZnVuY3Rpb24oKSB7XG4gICAgICAgICAgICAgICAgICAgIGlmIChmaXJlZm94RXh0SW5zdGFsbGVkID09PSBudWxsKVxuICAgICAgICAgICAgICAgICAgICAgICAgZmlyZWZveEV4dEluc3RhbGxlZCA9IGZhbHNlO1xuICAgICAgICAgICAgICAgICAgICBzZWxmLm9idGFpblNjcmVlbk9uRmlyZWZveChjYWxsYmFjaywgZXJyb3JDYWxsYmFjayk7XG4gICAgICAgICAgICAgICAgfSxcbiAgICAgICAgICAgICAgICAzMDBcbiAgICAgICAgICAgICk7XG4gICAgICAgICAgICBsb2dnZXIubG9nKFwiV2FpdGluZyBmb3IgZGV0ZWN0aW9uIG9mIGppZGVzaGEgb24gZmlyZWZveCB0byBcIiArXG4gICAgICAgICAgICAgICAgXCJmaW5pc2guXCIpO1xuICAgICAgICAgICAgcmV0dXJuO1xuICAgICAgICB9XG5cbiAgICAgICAgLy8gV2UgbmVlZCBhbiBleHRlbnNpb24gYW5kIGl0IGlzbid0IGluc3RhbGxlZC5cblxuICAgICAgICAvLyBNYWtlIHN1cmUgd2UgY2hlY2sgZm9yIHRoZSBleHRlbnNpb24gd2hlbiB0aGUgdXNlciBjbGlja3MgYWdhaW4uXG4gICAgICAgIGZpcmVmb3hFeHRJbnN0YWxsZWQgPSBudWxsO1xuICAgICAgICByZURldGVjdEZpcmVmb3hFeHRlbnNpb24gPSB0cnVlO1xuXG4gICAgICAgIC8vIFByb21wdCB0aGUgdXNlciB0byBpbnN0YWxsIHRoZSBleHRlbnNpb25cbiAgICAgICAgdGhpcy5ldmVudEVtaXR0ZXIuZW1pdChcbiAgICAgICAgICAgIERlc2t0b3BTaGFyaW5nRXZlbnRUeXBlcy5GSVJFRk9YX0VYVEVOU0lPTl9ORUVERUQsXG4gICAgICAgICAgICB0aGlzLm9wdGlvbnMuZGVza3RvcFNoYXJpbmdGaXJlZm94RXh0ZW5zaW9uVVJMKTtcblxuICAgICAgICAvLyBNYWtlIHN1cmUgZGVza3RvcHNoYXJpbmcga25vd3MgdGhhdCB3ZSBmYWlsZWQsIHNvIHRoYXQgaXQgZG9lc24ndCBnZXRcbiAgICAgICAgLy8gc3R1Y2sgaW4gJ3N3aXRjaGluZycgbW9kZS5cbiAgICAgICAgZXJyb3JDYWxsYmFjaygnRmlyZWZveCBleHRlbnNpb24gcmVxdWlyZWQuJyk7XG4gICAgfSxcbiAgICAvKipcbiAgICAgKiBBc2tzIENocm9tZSBleHRlbnNpb24gdG8gY2FsbCBjaG9vc2VEZXNrdG9wTWVkaWEgYW5kIGdldHMgY2hyb21lXG4gICAgICogJ2Rlc2t0b3AnIHN0cmVhbSBmb3IgcmV0dXJuZWQgc3RyZWFtIHRva2VuLlxuICAgICAqL1xuICAgIG9idGFpblNjcmVlbkZyb21FeHRlbnNpb246IGZ1bmN0aW9uIChzdHJlYW1DYWxsYmFjaywgZmFpbENhbGxiYWNrKSB7XG4gICAgICAgIGlmIChjaHJvbWVFeHRJbnN0YWxsZWQpIHtcbiAgICAgICAgICAgIGRvR2V0U3RyZWFtRnJvbUV4dGVuc2lvbih0aGlzLm9wdGlvbnMsIHN0cmVhbUNhbGxiYWNrLFxuICAgICAgICAgICAgICAgIGZhaWxDYWxsYmFjayk7XG4gICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICBpZiAoY2hyb21lRXh0VXBkYXRlUmVxdWlyZWQpIHtcbiAgICAgICAgICAgICAgICBhbGVydChcbiAgICAgICAgICAgICAgICAgICAgJ0ppdHNpIERlc2t0b3AgU3RyZWFtZXIgcmVxdWlyZXMgdXBkYXRlLiAnICtcbiAgICAgICAgICAgICAgICAgICAgJ0NoYW5nZXMgd2lsbCB0YWtlIGVmZmVjdCBhZnRlciBuZXh0IENocm9tZSByZXN0YXJ0LicpO1xuICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICBjaHJvbWUud2Vic3RvcmUuaW5zdGFsbChcbiAgICAgICAgICAgICAgICBnZXRXZWJTdG9yZUluc3RhbGxVcmwodGhpcy5vcHRpb25zKSxcbiAgICAgICAgICAgICAgICBmdW5jdGlvbiAoYXJnKSB7XG4gICAgICAgICAgICAgICAgICAgIGxvZ2dlci5sb2coXCJFeHRlbnNpb24gaW5zdGFsbGVkIHN1Y2Nlc3NmdWxseVwiLCBhcmcpO1xuICAgICAgICAgICAgICAgICAgICBjaHJvbWVFeHRJbnN0YWxsZWQgPSB0cnVlO1xuICAgICAgICAgICAgICAgICAgICAvLyBXZSBuZWVkIHRvIGdpdmUgYSBtb21lbnQgZm9yIHRoZSBlbmRwb2ludCB0byBiZWNvbWVcbiAgICAgICAgICAgICAgICAgICAgLy8gYXZhaWxhYmxlXG4gICAgICAgICAgICAgICAgICAgIHdpbmRvdy5zZXRUaW1lb3V0KGZ1bmN0aW9uICgpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgIGRvR2V0U3RyZWFtRnJvbUV4dGVuc2lvbih0aGlzLm9wdGlvbnMsIHN0cmVhbUNhbGxiYWNrLFxuICAgICAgICAgICAgICAgICAgICAgICAgICAgIGZhaWxDYWxsYmFjayk7XG4gICAgICAgICAgICAgICAgICAgIH0sIDUwMCk7XG4gICAgICAgICAgICAgICAgfSxcbiAgICAgICAgICAgICAgICBmdW5jdGlvbiAoYXJnKSB7XG4gICAgICAgICAgICAgICAgICAgIGxvZ2dlci5sb2coXCJGYWlsZWQgdG8gaW5zdGFsbCB0aGUgZXh0ZW5zaW9uXCIsIGFyZyk7XG4gICAgICAgICAgICAgICAgICAgIGZhaWxDYWxsYmFjayhhcmcpO1xuICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICk7XG4gICAgICAgIH1cbiAgICB9XG59O1xuXG5cblxuLyoqXG4gKiBPYnRhaW5zIGEgZGVza3RvcCBzdHJlYW0gdXNpbmcgZ2V0VXNlck1lZGlhLlxuICogRm9yIHRoaXMgdG8gd29yayBvbiBDaHJvbWUsIHRoZVxuICogJ2Nocm9tZTovL2ZsYWdzLyNlbmFibGUtdXNlcm1lZGlhLXNjcmVlbi1jYXB0dXJlJyBmbGFnIG11c3QgYmUgZW5hYmxlZC5cbiAqXG4gKiBPbiBmaXJlZm94LCB0aGUgZG9jdW1lbnQncyBkb21haW4gbXVzdCBiZSB3aGl0ZS1saXN0ZWQgaW4gdGhlXG4gKiAnbWVkaWEuZ2V0dXNlcm1lZGlhLnNjcmVlbnNoYXJpbmcuYWxsb3dlZF9kb21haW5zJyBwcmVmZXJlbmNlIGluXG4gKiAnYWJvdXQ6Y29uZmlnJy5cbiAqL1xuZnVuY3Rpb24gb2J0YWluV2ViUlRDU2NyZWVuKHN0cmVhbUNhbGxiYWNrLCBmYWlsQ2FsbGJhY2spIHtcbiAgICBHVU0oXG4gICAgICAgIFsnc2NyZWVuJ10sXG4gICAgICAgIHN0cmVhbUNhbGxiYWNrLFxuICAgICAgICBmYWlsQ2FsbGJhY2tcbiAgICApO1xufVxuXG4vKipcbiAqIENvbnN0cnVjdHMgaW5saW5lIGluc3RhbGwgVVJMIGZvciBDaHJvbWUgZGVza3RvcCBzdHJlYW1pbmcgZXh0ZW5zaW9uLlxuICogVGhlICdjaHJvbWVFeHRlbnNpb25JZCcgbXVzdCBiZSBkZWZpbmVkIGluIG9wdGlvbnMgcGFyYW1ldGVyLlxuICogQHBhcmFtIG9wdGlvbnMgc3VwcG9ydHMgXCJkZXNrdG9wU2hhcmluZ0Nocm9tZUV4dElkXCIgYW5kIFwiY2hyb21lRXh0ZW5zaW9uSWRcIlxuICogQHJldHVybnMge3N0cmluZ31cbiAqL1xuZnVuY3Rpb24gZ2V0V2ViU3RvcmVJbnN0YWxsVXJsKG9wdGlvbnMpXG57XG4gICAgLy9UT0RPIHJlbW92ZSBjaHJvbWVFeHRlbnNpb25JZCAoZGVwcmVjYXRlZClcbiAgICByZXR1cm4gXCJodHRwczovL2Nocm9tZS5nb29nbGUuY29tL3dlYnN0b3JlL2RldGFpbC9cIiArXG4gICAgICAgIChvcHRpb25zLmRlc2t0b3BTaGFyaW5nQ2hyb21lRXh0SWQgfHwgb3B0aW9ucy5jaHJvbWVFeHRlbnNpb25JZCk7XG59XG5cbi8qKlxuICogQ2hlY2tzIHdoZXRoZXIgYW4gdXBkYXRlIG9mIHRoZSBDaHJvbWUgZXh0ZW5zaW9uIGlzIHJlcXVpcmVkLlxuICogQHBhcmFtIG1pblZlcnNpb24gbWluaW1hbCByZXF1aXJlZCB2ZXJzaW9uXG4gKiBAcGFyYW0gZXh0VmVyc2lvbiBjdXJyZW50IGV4dGVuc2lvbiB2ZXJzaW9uXG4gKiBAcmV0dXJucyB7Ym9vbGVhbn1cbiAqL1xuZnVuY3Rpb24gaXNVcGRhdGVSZXF1aXJlZChtaW5WZXJzaW9uLCBleHRWZXJzaW9uKSB7XG4gICAgdHJ5IHtcbiAgICAgICAgdmFyIHMxID0gbWluVmVyc2lvbi5zcGxpdCgnLicpO1xuICAgICAgICB2YXIgczIgPSBleHRWZXJzaW9uLnNwbGl0KCcuJyk7XG5cbiAgICAgICAgdmFyIGxlbiA9IE1hdGgubWF4KHMxLmxlbmd0aCwgczIubGVuZ3RoKTtcbiAgICAgICAgZm9yICh2YXIgaSA9IDA7IGkgPCBsZW47IGkrKykge1xuICAgICAgICAgICAgdmFyIG4xID0gMCxcbiAgICAgICAgICAgICAgICBuMiA9IDA7XG5cbiAgICAgICAgICAgIGlmIChpIDwgczEubGVuZ3RoKVxuICAgICAgICAgICAgICAgIG4xID0gcGFyc2VJbnQoczFbaV0pO1xuICAgICAgICAgICAgaWYgKGkgPCBzMi5sZW5ndGgpXG4gICAgICAgICAgICAgICAgbjIgPSBwYXJzZUludChzMltpXSk7XG5cbiAgICAgICAgICAgIGlmIChpc05hTihuMSkgfHwgaXNOYU4objIpKSB7XG4gICAgICAgICAgICAgICAgcmV0dXJuIHRydWU7XG4gICAgICAgICAgICB9IGVsc2UgaWYgKG4xICE9PSBuMikge1xuICAgICAgICAgICAgICAgIHJldHVybiBuMSA+IG4yO1xuICAgICAgICAgICAgfVxuICAgICAgICB9XG5cbiAgICAgICAgLy8gd2lsbCBoYXBwZW4gaWYgYm90aCB2ZXJzaW9ucyBoYXZlIGlkZW50aWNhbCBudW1iZXJzIGluXG4gICAgICAgIC8vIHRoZWlyIGNvbXBvbmVudHMgKGV2ZW4gaWYgb25lIG9mIHRoZW0gaXMgbG9uZ2VyLCBoYXMgbW9yZSBjb21wb25lbnRzKVxuICAgICAgICByZXR1cm4gZmFsc2U7XG4gICAgfVxuICAgIGNhdGNoIChlKSB7XG4gICAgICAgIGxvZ2dlci5lcnJvcihcIkZhaWxlZCB0byBwYXJzZSBleHRlbnNpb24gdmVyc2lvblwiLCBlKTtcbiAgICAgICAgcmV0dXJuIHRydWU7XG4gICAgfVxufVxuXG5mdW5jdGlvbiBjaGVja0Nocm9tZUV4dEluc3RhbGxlZChjYWxsYmFjaywgb3B0aW9ucykge1xuICAgIGlmICghY2hyb21lIHx8ICFjaHJvbWUucnVudGltZSkge1xuICAgICAgICAvLyBObyBBUEksIHNvIG5vIGV4dGVuc2lvbiBmb3Igc3VyZVxuICAgICAgICBjYWxsYmFjayhmYWxzZSwgZmFsc2UpO1xuICAgICAgICByZXR1cm47XG4gICAgfVxuICAgIGNocm9tZS5ydW50aW1lLnNlbmRNZXNzYWdlKFxuICAgICAgICAvL1RPRE86IHJlbW92ZSBjaHJvbWVFeHRlbnNpb25JZCAoZGVwcmVjYXRlZClcbiAgICAgICAgKG9wdGlvbnMuZGVza3RvcFNoYXJpbmdDaHJvbWVFeHRJZCB8fCBvcHRpb25zLmNocm9tZUV4dGVuc2lvbklkKSxcbiAgICAgICAgeyBnZXRWZXJzaW9uOiB0cnVlIH0sXG4gICAgICAgIGZ1bmN0aW9uIChyZXNwb25zZSkge1xuICAgICAgICAgICAgaWYgKCFyZXNwb25zZSB8fCAhcmVzcG9uc2UudmVyc2lvbikge1xuICAgICAgICAgICAgICAgIC8vIENvbW11bmljYXRpb24gZmFpbHVyZSAtIGFzc3VtZSB0aGF0IG5vIGVuZHBvaW50IGV4aXN0c1xuICAgICAgICAgICAgICAgIGxvZ2dlci53YXJuKFxuICAgICAgICAgICAgICAgICAgICBcIkV4dGVuc2lvbiBub3QgaW5zdGFsbGVkPzogXCIsIGNocm9tZS5ydW50aW1lLmxhc3RFcnJvcik7XG4gICAgICAgICAgICAgICAgY2FsbGJhY2soZmFsc2UsIGZhbHNlKTtcbiAgICAgICAgICAgICAgICByZXR1cm47XG4gICAgICAgICAgICB9XG4gICAgICAgICAgICAvLyBDaGVjayBpbnN0YWxsZWQgZXh0ZW5zaW9uIHZlcnNpb25cbiAgICAgICAgICAgIHZhciBleHRWZXJzaW9uID0gcmVzcG9uc2UudmVyc2lvbjtcbiAgICAgICAgICAgIGxvZ2dlci5sb2coJ0V4dGVuc2lvbiB2ZXJzaW9uIGlzOiAnICsgZXh0VmVyc2lvbik7XG4gICAgICAgICAgICAvL1RPRE86IHJlbW92ZSBtaW5DaHJvbWVFeHRWZXJzaW9uIChkZXByZWNhdGVkKVxuICAgICAgICAgICAgdmFyIHVwZGF0ZVJlcXVpcmVkXG4gICAgICAgICAgICAgICAgPSBpc1VwZGF0ZVJlcXVpcmVkKFxuICAgICAgICAgICAgICAgICAgICAob3B0aW9ucy5kZXNrdG9wU2hhcmluZ0Nocm9tZU1pbkV4dFZlcnNpb24gfHxcbiAgICAgICAgICAgICAgICAgICAgICAgIG9wdGlvbnMubWluQ2hyb21lRXh0VmVyc2lvbiksXG4gICAgICAgICAgICAgICAgICAgIGV4dFZlcnNpb24pO1xuICAgICAgICAgICAgY2FsbGJhY2soIXVwZGF0ZVJlcXVpcmVkLCB1cGRhdGVSZXF1aXJlZCk7XG4gICAgICAgIH1cbiAgICApO1xufVxuXG5mdW5jdGlvbiBkb0dldFN0cmVhbUZyb21FeHRlbnNpb24ob3B0aW9ucywgc3RyZWFtQ2FsbGJhY2ssIGZhaWxDYWxsYmFjaykge1xuICAgIC8vIFNlbmRzICdnZXRTdHJlYW0nIG1zZyB0byB0aGUgZXh0ZW5zaW9uLlxuICAgIC8vIEV4dGVuc2lvbiBpZCBtdXN0IGJlIGRlZmluZWQgaW4gdGhlIGNvbmZpZy5cbiAgICBjaHJvbWUucnVudGltZS5zZW5kTWVzc2FnZShcbiAgICAgICAgLy9UT0RPOiByZW1vdmUgY2hyb21lRXh0ZW5zaW9uSWQgKGRlcHJlY2F0ZWQpXG4gICAgICAgIChvcHRpb25zLmRlc2t0b3BTaGFyaW5nQ2hyb21lRXh0SWQgfHwgb3B0aW9ucy5jaHJvbWVFeHRlbnNpb25JZCksXG4gICAgICAgIHtcbiAgICAgICAgICAgIGdldFN0cmVhbTogdHJ1ZSxcbiAgICAgICAgICAgIC8vVE9ETzogcmVtb3ZlIGRlc2t0b3BTaGFyaW5nU291cmNlcyAoZGVwcmVjYXRlZCkuXG4gICAgICAgICAgICBzb3VyY2VzOiAob3B0aW9ucy5kZXNrdG9wU2hhcmluZ0Nocm9tZVNvdXJjZXMgfHxcbiAgICAgICAgICAgICAgICBvcHRpb25zLmRlc2t0b3BTaGFyaW5nU291cmNlcylcbiAgICAgICAgfSxcbiAgICAgICAgZnVuY3Rpb24gKHJlc3BvbnNlKSB7XG4gICAgICAgICAgICBpZiAoIXJlc3BvbnNlKSB7XG4gICAgICAgICAgICAgICAgZmFpbENhbGxiYWNrKGNocm9tZS5ydW50aW1lLmxhc3RFcnJvcik7XG4gICAgICAgICAgICAgICAgcmV0dXJuO1xuICAgICAgICAgICAgfVxuICAgICAgICAgICAgbG9nZ2VyLmxvZyhcIlJlc3BvbnNlIGZyb20gZXh0ZW5zaW9uOiBcIiArIHJlc3BvbnNlKTtcbiAgICAgICAgICAgIGlmIChyZXNwb25zZS5zdHJlYW1JZCkge1xuICAgICAgICAgICAgICAgIEdVTShcbiAgICAgICAgICAgICAgICAgICAgWydkZXNrdG9wJ10sXG4gICAgICAgICAgICAgICAgICAgIGZ1bmN0aW9uIChzdHJlYW0pIHtcbiAgICAgICAgICAgICAgICAgICAgICAgIHN0cmVhbUNhbGxiYWNrKHN0cmVhbSk7XG4gICAgICAgICAgICAgICAgICAgIH0sXG4gICAgICAgICAgICAgICAgICAgIGZhaWxDYWxsYmFjayxcbiAgICAgICAgICAgICAgICAgICAge2Rlc2t0b3BTdHJlYW06IHJlc3BvbnNlLnN0cmVhbUlkfSk7XG4gICAgICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgICAgIGZhaWxDYWxsYmFjayhcIkV4dGVuc2lvbiBmYWlsZWQgdG8gZ2V0IHRoZSBzdHJlYW1cIik7XG4gICAgICAgICAgICB9XG4gICAgICAgIH1cbiAgICApO1xufVxuXG4vKipcbiAqIEluaXRpYWxpemVzIDxsaW5rIHJlbD1jaHJvbWUtd2Vic3RvcmUtaXRlbSAvPiB3aXRoIGV4dGVuc2lvbiBpZCBzZXQgaW5cbiAqIGNvbmZpZy5qcyB0byBzdXBwb3J0IGlubGluZSBpbnN0YWxscy4gSG9zdCBzaXRlIG11c3QgYmUgc2VsZWN0ZWQgYXMgbWFpblxuICogd2Vic2l0ZSBvZiBwdWJsaXNoZWQgZXh0ZW5zaW9uLlxuICogQHBhcmFtIG9wdGlvbnMgc3VwcG9ydHMgXCJkZXNrdG9wU2hhcmluZ0Nocm9tZUV4dElkXCIgYW5kIFwiY2hyb21lRXh0ZW5zaW9uSWRcIlxuICovXG5mdW5jdGlvbiBpbml0SW5saW5lSW5zdGFsbHMob3B0aW9ucylcbntcbiAgICAkKFwibGlua1tyZWw9Y2hyb21lLXdlYnN0b3JlLWl0ZW1dXCIpLmF0dHIoXCJocmVmXCIsXG4gICAgICAgIGdldFdlYlN0b3JlSW5zdGFsbFVybChvcHRpb25zKSk7XG59XG5cbmZ1bmN0aW9uIGluaXRDaHJvbWVFeHRlbnNpb24ob3B0aW9ucykge1xuICAgIC8vIEluaXRpYWxpemUgQ2hyb21lIGV4dGVuc2lvbiBpbmxpbmUgaW5zdGFsbHNcbiAgICBpbml0SW5saW5lSW5zdGFsbHMob3B0aW9ucyk7XG4gICAgLy8gQ2hlY2sgaWYgZXh0ZW5zaW9uIGlzIGluc3RhbGxlZFxuICAgIGNoZWNrQ2hyb21lRXh0SW5zdGFsbGVkKGZ1bmN0aW9uIChpbnN0YWxsZWQsIHVwZGF0ZVJlcXVpcmVkKSB7XG4gICAgICAgIGNocm9tZUV4dEluc3RhbGxlZCA9IGluc3RhbGxlZDtcbiAgICAgICAgY2hyb21lRXh0VXBkYXRlUmVxdWlyZWQgPSB1cGRhdGVSZXF1aXJlZDtcbiAgICAgICAgbG9nZ2VyLmluZm8oXG4gICAgICAgICAgICBcIkNocm9tZSBleHRlbnNpb24gaW5zdGFsbGVkOiBcIiArIGNocm9tZUV4dEluc3RhbGxlZCArXG4gICAgICAgICAgICBcIiB1cGRhdGVSZXF1aXJlZDogXCIgKyBjaHJvbWVFeHRVcGRhdGVSZXF1aXJlZCk7XG4gICAgfSwgb3B0aW9ucyk7XG59XG5cbi8qKlxuICogU3RhcnRzIHRoZSBkZXRlY3Rpb24gb2YgYW4gaW5zdGFsbGVkIGppZGVzaGEgZXh0ZW5zaW9uIGZvciBmaXJlZm94LlxuICogQHBhcmFtIG9wdGlvbnMgc3VwcG9ydHMgXCJkZXNrdG9wU2hhcmluZ0ZpcmVmb3hEaXNhYmxlZFwiLFxuICogXCJkZXNrdG9wU2hhcmluZ0ZpcmVmb3hFeHRJZFwiIGFuZCBcImNocm9tZUV4dGVuc2lvbklkXCJcbiAqL1xuZnVuY3Rpb24gaW5pdEZpcmVmb3hFeHRlbnNpb25EZXRlY3Rpb24ob3B0aW9ucykge1xuICAgIGlmIChvcHRpb25zLmRlc2t0b3BTaGFyaW5nRmlyZWZveERpc2FibGVkKSB7XG4gICAgICAgIHJldHVybjtcbiAgICB9XG4gICAgaWYgKGZpcmVmb3hFeHRJbnN0YWxsZWQgPT09IGZhbHNlIHx8IGZpcmVmb3hFeHRJbnN0YWxsZWQgPT09IHRydWUpXG4gICAgICAgIHJldHVybjtcbiAgICBpZiAoIW9wdGlvbnMuZGVza3RvcFNoYXJpbmdGaXJlZm94RXh0SWQpIHtcbiAgICAgICAgZmlyZWZveEV4dEluc3RhbGxlZCA9IGZhbHNlO1xuICAgICAgICByZXR1cm47XG4gICAgfVxuXG4gICAgdmFyIGltZyA9IGRvY3VtZW50LmNyZWF0ZUVsZW1lbnQoJ2ltZycpO1xuICAgIGltZy5vbmxvYWQgPSBmdW5jdGlvbigpe1xuICAgICAgICBsb2dnZXIubG9nKFwiRGV0ZWN0ZWQgZmlyZWZveCBzY3JlZW4gc2hhcmluZyBleHRlbnNpb24uXCIpO1xuICAgICAgICBmaXJlZm94RXh0SW5zdGFsbGVkID0gdHJ1ZTtcbiAgICB9O1xuICAgIGltZy5vbmVycm9yID0gZnVuY3Rpb24oKXtcbiAgICAgICAgbG9nZ2VyLmxvZyhcIkRldGVjdGVkIGxhY2sgb2YgZmlyZWZveCBzY3JlZW4gc2hhcmluZyBleHRlbnNpb24uXCIpO1xuICAgICAgICBmaXJlZm94RXh0SW5zdGFsbGVkID0gZmFsc2U7XG4gICAgfTtcblxuICAgIC8vIFRoZSBqaWRlc2hhIGV4dGVuc2lvbiBleHBvc2VzIGFuIGVtcHR5IGltYWdlIGZpbGUgdW5kZXIgdGhlIHVybDpcbiAgICAvLyBcImNocm9tZTovL0VYVF9JRC9jb250ZW50L0RPTUFJTi5wbmdcIlxuICAgIC8vIFdoZXJlIEVYVF9JRCBpcyB0aGUgSUQgb2YgdGhlIGV4dGVuc2lvbiB3aXRoIFwiQFwiIHJlcGxhY2VkIGJ5IFwiLlwiLCBhbmRcbiAgICAvLyBET01BSU4gaXMgYSBkb21haW4gd2hpdGVsaXN0ZWQgYnkgdGhlIGV4dGVuc2lvbi5cbiAgICB2YXIgc3JjID0gXCJjaHJvbWU6Ly9cIiArXG4gICAgICAgIChvcHRpb25zLmRlc2t0b3BTaGFyaW5nRmlyZWZveEV4dElkLnJlcGxhY2UoJ0AnLCAnLicpKSArXG4gICAgICAgIFwiL2NvbnRlbnQvXCIgKyBkb2N1bWVudC5sb2NhdGlvbi5ob3N0bmFtZSArIFwiLnBuZ1wiO1xuICAgIGltZy5zZXRBdHRyaWJ1dGUoJ3NyYycsIHNyYyk7XG59XG5cbm1vZHVsZS5leHBvcnRzID0gU2NyZWVuT2J0YWluZXI7XG4iLCIvKiEgYWRhcHRlcmpzIC0gdjAuMTIuMyAtIDIwMTUtMTEtMTYgKi9cbnZhciBjb25zb2xlID0gcmVxdWlyZShcImppdHNpLW1lZXQtbG9nZ2VyXCIpLmdldExvZ2dlcihfX2ZpbGVuYW1lKTtcbi8vIEFkYXB0ZXIncyBpbnRlcmZhY2UuXG52YXIgQWRhcHRlckpTID0gQWRhcHRlckpTIHx8IHt9O1xuXG4vLyBCcm93c2VyaWZ5IGNvbXBhdGliaWxpdHlcbmlmKHR5cGVvZiBleHBvcnRzICE9PSAndW5kZWZpbmVkJykge1xuICBtb2R1bGUuZXhwb3J0cyA9IEFkYXB0ZXJKUztcbn1cblxuQWRhcHRlckpTLm9wdGlvbnMgPSBBZGFwdGVySlMub3B0aW9ucyB8fCB7fTtcblxuLy8gdW5jb21tZW50IHRvIGdldCB2aXJ0dWFsIHdlYmNhbXNcbi8vIEFkYXB0ZXJKUy5vcHRpb25zLmdldEFsbENhbXMgPSB0cnVlO1xuXG4vLyB1bmNvbW1lbnQgdG8gcHJldmVudCB0aGUgaW5zdGFsbCBwcm9tcHQgd2hlbiB0aGUgcGx1Z2luIGluIG5vdCB5ZXQgaW5zdGFsbGVkXG4vLyBBZGFwdGVySlMub3B0aW9ucy5oaWRlUGx1Z2luSW5zdGFsbFByb21wdCA9IHRydWU7XG5cbi8vIEFkYXB0ZXJKUyB2ZXJzaW9uXG5BZGFwdGVySlMuVkVSU0lPTiA9ICcwLjEyLjMnO1xuXG4vLyBUaGlzIGZ1bmN0aW9uIHdpbGwgYmUgY2FsbGVkIHdoZW4gdGhlIFdlYlJUQyBBUEkgaXMgcmVhZHkgdG8gYmUgdXNlZFxuLy8gV2hldGhlciBpdCBpcyB0aGUgbmF0aXZlIGltcGxlbWVudGF0aW9uIChDaHJvbWUsIEZpcmVmb3gsIE9wZXJhKSBvclxuLy8gdGhlIHBsdWdpblxuLy8gWW91IG1heSBPdmVycmlkZSB0aGlzIGZ1bmN0aW9uIHRvIHN5bmNocm9uaXNlIHRoZSBzdGFydCBvZiB5b3VyIGFwcGxpY2F0aW9uXG4vLyB3aXRoIHRoZSBXZWJSVEMgQVBJIGJlaW5nIHJlYWR5LlxuLy8gSWYgeW91IGRlY2lkZSBub3QgdG8gb3ZlcnJpZGUgdXNlIHRoaXMgc3luY2hyb25pc2F0aW9uLCBpdCBtYXkgcmVzdWx0IGluXG4vLyBhbiBleHRlbnNpdmUgQ1BVIHVzYWdlIG9uIHRoZSBwbHVnaW4gc3RhcnQgKG9uY2UgcGVyIHRhYiBsb2FkZWQpXG4vLyBQYXJhbXM6XG4vLyAgICAtIGlzVXNpbmdQbHVnaW46IHRydWUgaXMgdGhlIFdlYlJUQyBwbHVnaW4gaXMgYmVpbmcgdXNlZCwgZmFsc2Ugb3RoZXJ3aXNlXG4vL1xuQWRhcHRlckpTLm9ud2VicnRjcmVhZHkgPSBBZGFwdGVySlMub253ZWJydGNyZWFkeSB8fCBmdW5jdGlvbihpc1VzaW5nUGx1Z2luKSB7XG4gIC8vIFRoZSBXZWJSVEMgQVBJIGlzIHJlYWR5LlxuICAvLyBPdmVycmlkZSBtZSBhbmQgZG8gd2hhdGV2ZXIgeW91IHdhbnQgaGVyZVxufTtcblxuLy8gU2V0cyBhIGNhbGxiYWNrIGZ1bmN0aW9uIHRvIGJlIGNhbGxlZCB3aGVuIHRoZSBXZWJSVEMgaW50ZXJmYWNlIGlzIHJlYWR5LlxuLy8gVGhlIGZpcnN0IGFyZ3VtZW50IGlzIHRoZSBmdW5jdGlvbiB0byBjYWxsYmFjay5cXFxuLy8gVGhyb3dzIGFuIGVycm9yIGlmIHRoZSBmaXJzdCBhcmd1bWVudCBpcyBub3QgYSBmdW5jdGlvblxuQWRhcHRlckpTLndlYlJUQ1JlYWR5ID0gZnVuY3Rpb24gKGNhbGxiYWNrKSB7XG4gIGlmICh0eXBlb2YgY2FsbGJhY2sgIT09ICdmdW5jdGlvbicpIHtcbiAgICB0aHJvdyBuZXcgRXJyb3IoJ0NhbGxiYWNrIHByb3ZpZGVkIGlzIG5vdCBhIGZ1bmN0aW9uJyk7XG4gIH1cblxuICBpZiAodHJ1ZSA9PT0gQWRhcHRlckpTLm9ud2VicnRjcmVhZHlEb25lKSB7XG4gICAgLy8gQWxsIFdlYlJUQyBpbnRlcmZhY2VzIGFyZSByZWFkeSwganVzdCBjYWxsIHRoZSBjYWxsYmFja1xuICAgIGNhbGxiYWNrKG51bGwgIT09IEFkYXB0ZXJKUy5XZWJSVENQbHVnaW4ucGx1Z2luKTtcbiAgfSBlbHNlIHtcbiAgICAvLyB3aWxsIGJlIHRyaWdnZXJlZCBhdXRvbWF0aWNhbGx5IHdoZW4geW91ciBicm93c2VyL3BsdWdpbiBpcyByZWFkeS5cbiAgICBBZGFwdGVySlMub253ZWJydGNyZWFkeSA9IGNhbGxiYWNrO1xuICB9XG59O1xuXG4vLyBQbHVnaW4gbmFtZXNwYWNlXG5BZGFwdGVySlMuV2ViUlRDUGx1Z2luID0gQWRhcHRlckpTLldlYlJUQ1BsdWdpbiB8fCB7fTtcblxuLy8gVGhlIG9iamVjdCB0byBzdG9yZSBwbHVnaW4gaW5mb3JtYXRpb25cbkFkYXB0ZXJKUy5XZWJSVENQbHVnaW4ucGx1Z2luSW5mbyA9IHtcbiAgcHJlZml4IDogJ1RlbScsXG4gIHBsdWdOYW1lIDogJ1RlbVdlYlJUQ1BsdWdpbicsXG4gIHBsdWdpbklkIDogJ3BsdWdpbjAnLFxuICB0eXBlIDogJ2FwcGxpY2F0aW9uL3gtdGVtd2VicnRjcGx1Z2luJyxcbiAgb25sb2FkIDogJ19fVGVtV2ViUlRDUmVhZHkwJyxcbiAgcG9ydGFsTGluayA6ICdodHRwOi8vc2t5bGluay5pby9wbHVnaW4vJyxcbiAgZG93bmxvYWRMaW5rIDogbnVsbCwgLy9zZXQgYmVsb3dcbiAgY29tcGFueU5hbWU6ICdUZW1hc3lzJ1xufTtcbmlmKCEhbmF2aWdhdG9yLnBsYXRmb3JtLm1hdGNoKC9eTWFjL2kpKSB7XG4gIEFkYXB0ZXJKUy5XZWJSVENQbHVnaW4ucGx1Z2luSW5mby5kb3dubG9hZExpbmsgPSAnaHR0cDovL2JpdC5seS8xbjc3aGNvJztcbn1cbmVsc2UgaWYoISFuYXZpZ2F0b3IucGxhdGZvcm0ubWF0Y2goL15XaW4vaSkpIHtcbiAgQWRhcHRlckpTLldlYlJUQ1BsdWdpbi5wbHVnaW5JbmZvLmRvd25sb2FkTGluayA9ICdodHRwOi8vYml0Lmx5LzFra1M0Rk4nO1xufVxuXG5BZGFwdGVySlMuV2ViUlRDUGx1Z2luLlRBR1MgPSB7XG4gIE5PTkUgIDogJ25vbmUnLFxuICBBVURJTyA6ICdhdWRpbycsXG4gIFZJREVPIDogJ3ZpZGVvJ1xufTtcblxuLy8gVW5pcXVlIGlkZW50aWZpZXIgb2YgZWFjaCBvcGVuZWQgcGFnZVxuQWRhcHRlckpTLldlYlJUQ1BsdWdpbi5wYWdlSWQgPSBNYXRoLnJhbmRvbSgpLnRvU3RyaW5nKDM2KS5zbGljZSgyKTtcblxuLy8gVXNlIHRoaXMgd2hlbmV2ZXIgeW91IHdhbnQgdG8gY2FsbCB0aGUgcGx1Z2luLlxuQWRhcHRlckpTLldlYlJUQ1BsdWdpbi5wbHVnaW4gPSBudWxsO1xuXG4vLyBTZXQgbG9nIGxldmVsIGZvciB0aGUgcGx1Z2luIG9uY2UgaXQgaXMgcmVhZHkuXG4vLyBUaGUgZGlmZmVyZW50IHZhbHVlcyBhcmVcbi8vIFRoaXMgaXMgYW4gYXN5bmNocm9ub3VzIGZ1bmN0aW9uIHRoYXQgd2lsbCBydW4gd2hlbiB0aGUgcGx1Z2luIGlzIHJlYWR5XG5BZGFwdGVySlMuV2ViUlRDUGx1Z2luLnNldExvZ0xldmVsID0gbnVsbDtcblxuLy8gRGVmaW5lcyB3ZWJydGMncyBKUyBpbnRlcmZhY2UgYWNjb3JkaW5nIHRvIHRoZSBwbHVnaW4ncyBpbXBsZW1lbnRhdGlvbi5cbi8vIERlZmluZSBwbHVnaW4gQnJvd3NlcnMgYXMgV2ViUlRDIEludGVyZmFjZS5cbkFkYXB0ZXJKUy5XZWJSVENQbHVnaW4uZGVmaW5lV2ViUlRDSW50ZXJmYWNlID0gbnVsbDtcblxuLy8gVGhpcyBmdW5jdGlvbiBkZXRlY3RzIHdoZXRoZXIgb3Igbm90IGEgcGx1Z2luIGlzIGluc3RhbGxlZC5cbi8vIENoZWNrcyBpZiBOb3QgSUUgKGZpcmVmb3gsIGZvciBleGFtcGxlKSwgZWxzZSBpZiBpdCdzIElFLFxuLy8gd2UncmUgcnVubmluZyBJRSBhbmQgZG8gc29tZXRoaW5nLiBJZiBub3QgaXQgaXMgbm90IHN1cHBvcnRlZC5cbkFkYXB0ZXJKUy5XZWJSVENQbHVnaW4uaXNQbHVnaW5JbnN0YWxsZWQgPSBudWxsO1xuXG4gLy8gTGV0cyBhZGFwdGVyLmpzIHdhaXQgdW50aWwgdGhlIHRoZSBkb2N1bWVudCBpcyByZWFkeSBiZWZvcmUgaW5qZWN0aW5nIHRoZSBwbHVnaW5cbkFkYXB0ZXJKUy5XZWJSVENQbHVnaW4ucGx1Z2luSW5qZWN0aW9uSW50ZXJ2YWwgPSBudWxsO1xuXG4vLyBJbmplY3QgdGhlIEhUTUwgRE9NIG9iamVjdCBlbGVtZW50IGludG8gdGhlIHBhZ2UuXG5BZGFwdGVySlMuV2ViUlRDUGx1Z2luLmluamVjdFBsdWdpbiA9IG51bGw7XG5cbi8vIFN0YXRlcyBvZiByZWFkaW5lc3MgdGhhdCB0aGUgcGx1Z2luIGdvZXMgdGhyb3VnaCB3aGVuXG4vLyBiZWluZyBpbmplY3RlZCBhbmQgc3RhdGVkXG5BZGFwdGVySlMuV2ViUlRDUGx1Z2luLlBMVUdJTl9TVEFURVMgPSB7XG4gIE5PTkUgOiAwLCAgICAgICAgICAgLy8gbm8gcGx1Z2luIHVzZVxuICBJTklUSUFMSVpJTkcgOiAxLCAgIC8vIERldGVjdGVkIG5lZWQgZm9yIHBsdWdpblxuICBJTkpFQ1RJTkcgOiAyLCAgICAgIC8vIEluamVjdGluZyBwbHVnaW5cbiAgSU5KRUNURUQ6IDMsICAgICAgICAvLyBQbHVnaW4gZWxlbWVudCBpbmplY3RlZCBidXQgbm90IHVzYWJsZSB5ZXRcbiAgUkVBRFk6IDQgICAgICAgICAgICAvLyBQbHVnaW4gcmVhZHkgdG8gYmUgdXNlZFxufTtcblxuLy8gQ3VycmVudCBzdGF0ZSBvZiB0aGUgcGx1Z2luLiBZb3UgY2Fubm90IHVzZSB0aGUgcGx1Z2luIGJlZm9yZSB0aGlzIGlzXG4vLyBlcXVhbCB0byBBZGFwdGVySlMuV2ViUlRDUGx1Z2luLlBMVUdJTl9TVEFURVMuUkVBRFlcbkFkYXB0ZXJKUy5XZWJSVENQbHVnaW4ucGx1Z2luU3RhdGUgPSBBZGFwdGVySlMuV2ViUlRDUGx1Z2luLlBMVUdJTl9TVEFURVMuTk9ORTtcblxuLy8gVHJ1ZSBpcyBBZGFwdGVySlMub253ZWJydGNyZWFkeSB3YXMgYWxyZWFkeSBjYWxsZWQsIGZhbHNlIG90aGVyd2lzZVxuLy8gVXNlZCB0byBtYWtlIHN1cmUgQWRhcHRlckpTLm9ud2VicnRjcmVhZHkgaXMgb25seSBjYWxsZWQgb25jZVxuQWRhcHRlckpTLm9ud2VicnRjcmVhZHlEb25lID0gZmFsc2U7XG5cbi8vIExvZyBsZXZlbHMgZm9yIHRoZSBwbHVnaW4uXG4vLyBUbyBiZSBzZXQgYnkgY2FsbGluZyBBZGFwdGVySlMuV2ViUlRDUGx1Z2luLnNldExvZ0xldmVsXG4vKlxuTG9nIG91dHB1dHMgYXJlIHByZWZpeGVkIGluIHNvbWUgY2FzZXMuXG4gIElORk86IEluZm9ybWF0aW9uIHJlcG9ydGVkIGJ5IHRoZSBwbHVnaW4uXG4gIEVSUk9SOiBFcnJvcnMgb3JpZ2luYXRpbmcgZnJvbSB3aXRoaW4gdGhlIHBsdWdpbi5cbiAgV0VCUlRDOiBFcnJvciBvcmlnaW5hdGluZyBmcm9tIHdpdGhpbiB0aGUgbGliV2ViUlRDIGxpYnJhcnlcbiovXG4vLyBGcm9tIHRoZSBsZWFzdCB2ZXJib3NlIHRvIHRoZSBtb3N0IHZlcmJvc2VcbkFkYXB0ZXJKUy5XZWJSVENQbHVnaW4uUExVR0lOX0xPR19MRVZFTFMgPSB7XG4gIE5PTkUgOiAnTk9ORScsXG4gIEVSUk9SIDogJ0VSUk9SJyxcbiAgV0FSTklORyA6ICdXQVJOSU5HJyxcbiAgSU5GTzogJ0lORk8nLFxuICBWRVJCT1NFOiAnVkVSQk9TRScsXG4gIFNFTlNJVElWRTogJ1NFTlNJVElWRSdcbn07XG5cbi8vIERvZXMgYSB3YWl0aW5nIGNoZWNrIGJlZm9yZSBwcm9jZWVkaW5nIHRvIGxvYWQgdGhlIHBsdWdpbi5cbkFkYXB0ZXJKUy5XZWJSVENQbHVnaW4uV2FpdEZvclBsdWdpblJlYWR5ID0gbnVsbDtcblxuLy8gVGhpcyBtZXRoaWQgd2lsbCB1c2UgYW4gaW50ZXJ2YWwgdG8gd2FpdCBmb3IgdGhlIHBsdWdpbiB0byBiZSByZWFkeS5cbkFkYXB0ZXJKUy5XZWJSVENQbHVnaW4uY2FsbFdoZW5QbHVnaW5SZWFkeSA9IG51bGw7XG5cbi8vICEhISEgV0FSTklORzogRE8gTk9UIE9WRVJSSURFIFRISVMgRlVOQ1RJT04uICEhIVxuLy8gVGhpcyBmdW5jdGlvbiB3aWxsIGJlIGNhbGxlZCB3aGVuIHBsdWdpbiBpcyByZWFkeS4gSXQgc2VuZHMgbmVjZXNzYXJ5XG4vLyBkZXRhaWxzIHRvIHRoZSBwbHVnaW4uXG4vLyBUaGUgZnVuY3Rpb24gd2lsbCB3YWl0IGZvciB0aGUgZG9jdW1lbnQgdG8gYmUgcmVhZHkgYW5kIHRoZSBzZXQgdGhlXG4vLyBwbHVnaW4gc3RhdGUgdG8gQWRhcHRlckpTLldlYlJUQ1BsdWdpbi5QTFVHSU5fU1RBVEVTLlJFQURZLFxuLy8gaW5kaWNhdGluZyB0aGF0IGl0IGNhbiBzdGFydCBiZWluZyByZXF1ZXN0ZWQuXG4vLyBUaGlzIGZ1bmN0aW9uIGlzIG5vdCBpbiB0aGUgSUUvU2FmYXJpIGNvbmRpdGlvbiBicmFja2V0cyBzbyB0aGF0XG4vLyBUZW1QbHVnaW5Mb2FkZWQgZnVuY3Rpb24gbWlnaHQgYmUgY2FsbGVkIG9uIENocm9tZS9GaXJlZm94LlxuLy8gVGhpcyBmdW5jdGlvbiBpcyB0aGUgb25seSBwcml2YXRlIGZ1bmN0aW9uIHRoYXQgaXMgbm90IGVuY2Fwc3VsYXRlZCB0b1xuLy8gYWxsb3cgdGhlIHBsdWdpbiBtZXRob2QgdG8gYmUgY2FsbGVkLlxuX19UZW1XZWJSVENSZWFkeTAgPSBmdW5jdGlvbiAoKSB7XG4gIGlmIChkb2N1bWVudC5yZWFkeVN0YXRlID09PSAnY29tcGxldGUnKSB7XG4gICAgQWRhcHRlckpTLldlYlJUQ1BsdWdpbi5wbHVnaW5TdGF0ZSA9IEFkYXB0ZXJKUy5XZWJSVENQbHVnaW4uUExVR0lOX1NUQVRFUy5SRUFEWTtcblxuICAgIEFkYXB0ZXJKUy5tYXliZVRocm91Z2hXZWJSVENSZWFkeSgpO1xuICB9IGVsc2Uge1xuICAgIEFkYXB0ZXJKUy5XZWJSVENQbHVnaW4uZG9jdW1lbnRSZWFkeUludGVydmFsID0gc2V0SW50ZXJ2YWwoZnVuY3Rpb24gKCkge1xuICAgICAgaWYgKGRvY3VtZW50LnJlYWR5U3RhdGUgPT09ICdjb21wbGV0ZScpIHtcbiAgICAgICAgLy8gVE9ETzogdXBkYXRlIGNvbW1lbnRzLCB3ZSB3YWl0IGZvciB0aGUgZG9jdW1lbnQgdG8gYmUgcmVhZHlcbiAgICAgICAgY2xlYXJJbnRlcnZhbChBZGFwdGVySlMuV2ViUlRDUGx1Z2luLmRvY3VtZW50UmVhZHlJbnRlcnZhbCk7XG4gICAgICAgIEFkYXB0ZXJKUy5XZWJSVENQbHVnaW4ucGx1Z2luU3RhdGUgPSBBZGFwdGVySlMuV2ViUlRDUGx1Z2luLlBMVUdJTl9TVEFURVMuUkVBRFk7XG5cbiAgICAgICAgQWRhcHRlckpTLm1heWJlVGhyb3VnaFdlYlJUQ1JlYWR5KCk7XG4gICAgICB9XG4gICAgfSwgMTAwKTtcbiAgfVxufTtcblxuQWRhcHRlckpTLm1heWJlVGhyb3VnaFdlYlJUQ1JlYWR5ID0gZnVuY3Rpb24oKSB7XG4gIGlmICghQWRhcHRlckpTLm9ud2VicnRjcmVhZHlEb25lKSB7XG4gICAgQWRhcHRlckpTLm9ud2VicnRjcmVhZHlEb25lID0gdHJ1ZTtcblxuICAgIGlmICh0eXBlb2YoQWRhcHRlckpTLm9ud2VicnRjcmVhZHkpID09PSAnZnVuY3Rpb24nKSB7XG4gICAgICBBZGFwdGVySlMub253ZWJydGNyZWFkeShBZGFwdGVySlMuV2ViUlRDUGx1Z2luLnBsdWdpbiAhPT0gbnVsbCk7XG4gICAgfVxuICB9XG59O1xuXG4vLyBUZXh0IG5hbWVzcGFjZVxuQWRhcHRlckpTLlRFWFQgPSB7XG4gIFBMVUdJTjoge1xuICAgIFJFUVVJUkVfSU5TVEFMTEFUSU9OOiAnVGhpcyB3ZWJzaXRlIHJlcXVpcmVzIHlvdSB0byBpbnN0YWxsIGEgV2ViUlRDLWVuYWJsaW5nIHBsdWdpbiAnICtcbiAgICAgICd0byB3b3JrIG9uIHRoaXMgYnJvd3Nlci4nLFxuICAgIE5PVF9TVVBQT1JURUQ6ICdZb3VyIGJyb3dzZXIgZG9lcyBub3Qgc3VwcG9ydCBXZWJSVEMuJyxcbiAgICBCVVRUT046ICdJbnN0YWxsIE5vdydcbiAgfSxcbiAgUkVGUkVTSDoge1xuICAgIFJFUVVJUkVfUkVGUkVTSDogJ1BsZWFzZSByZWZyZXNoIHBhZ2UnLFxuICAgIEJVVFRPTjogJ1JlZnJlc2ggUGFnZSdcbiAgfVxufTtcblxuLy8gVGhlIHJlc3VsdCBvZiBpY2UgY29ubmVjdGlvbiBzdGF0ZXMuXG4vLyAtIHN0YXJ0aW5nOiBJY2UgY29ubmVjdGlvbiBpcyBzdGFydGluZy5cbi8vIC0gY2hlY2tpbmc6IEljZSBjb25uZWN0aW9uIGlzIGNoZWNraW5nLlxuLy8gLSBjb25uZWN0ZWQgSWNlIGNvbm5lY3Rpb24gaXMgY29ubmVjdGVkLlxuLy8gLSBjb21wbGV0ZWQgSWNlIGNvbm5lY3Rpb24gaXMgY29ubmVjdGVkLlxuLy8gLSBkb25lIEljZSBjb25uZWN0aW9uIGhhcyBiZWVuIGNvbXBsZXRlZC5cbi8vIC0gZGlzY29ubmVjdGVkIEljZSBjb25uZWN0aW9uIGhhcyBiZWVuIGRpc2Nvbm5lY3RlZC5cbi8vIC0gZmFpbGVkIEljZSBjb25uZWN0aW9uIGhhcyBmYWlsZWQuXG4vLyAtIGNsb3NlZCBJY2UgY29ubmVjdGlvbiBpcyBjbG9zZWQuXG5BZGFwdGVySlMuX2ljZUNvbm5lY3Rpb25TdGF0ZXMgPSB7XG4gIHN0YXJ0aW5nIDogJ3N0YXJ0aW5nJyxcbiAgY2hlY2tpbmcgOiAnY2hlY2tpbmcnLFxuICBjb25uZWN0ZWQgOiAnY29ubmVjdGVkJyxcbiAgY29tcGxldGVkIDogJ2Nvbm5lY3RlZCcsXG4gIGRvbmUgOiAnY29tcGxldGVkJyxcbiAgZGlzY29ubmVjdGVkIDogJ2Rpc2Nvbm5lY3RlZCcsXG4gIGZhaWxlZCA6ICdmYWlsZWQnLFxuICBjbG9zZWQgOiAnY2xvc2VkJ1xufTtcblxuLy9UaGUgSWNlQ29ubmVjdGlvbiBzdGF0ZXMgdGhhdCBoYXMgYmVlbiBmaXJlZCBmb3IgZWFjaCBwZWVyLlxuQWRhcHRlckpTLl9pY2VDb25uZWN0aW9uRmlyZWRTdGF0ZXMgPSBbXTtcblxuXG4vLyBDaGVjayBpZiBXZWJSVEMgSW50ZXJmYWNlIGlzIGRlZmluZWQuXG5BZGFwdGVySlMuaXNEZWZpbmVkID0gbnVsbDtcblxuLy8gVGhpcyBmdW5jdGlvbiBoZWxwcyB0byByZXRyaWV2ZSB0aGUgd2VicnRjIGRldGVjdGVkIGJyb3dzZXIgaW5mb3JtYXRpb24uXG4vLyBUaGlzIHNldHM6XG4vLyAtIHdlYnJ0Y0RldGVjdGVkQnJvd3NlcjogVGhlIGJyb3dzZXIgYWdlbnQgbmFtZS5cbi8vIC0gd2VicnRjRGV0ZWN0ZWRWZXJzaW9uOiBUaGUgYnJvd3NlciB2ZXJzaW9uLlxuLy8gLSB3ZWJydGNEZXRlY3RlZFR5cGU6IFRoZSB0eXBlcyBvZiB3ZWJSVEMgc3VwcG9ydC5cbi8vICAgLSAnbW96JzogTW96aWxsYSBpbXBsZW1lbnRhdGlvbiBvZiB3ZWJSVEMuXG4vLyAgIC0gJ3dlYmtpdCc6IFdlYktpdCBpbXBsZW1lbnRhdGlvbiBvZiB3ZWJSVEMuXG4vLyAgIC0gJ3BsdWdpbic6IFVzaW5nIHRoZSBwbHVnaW4gaW1wbGVtZW50YXRpb24uXG5BZGFwdGVySlMucGFyc2VXZWJydGNEZXRlY3RlZEJyb3dzZXIgPSBmdW5jdGlvbiAoKSB7XG4gIHZhciBoYXNNYXRjaCwgY2hlY2tNYXRjaCA9IG5hdmlnYXRvci51c2VyQWdlbnQubWF0Y2goXG4gICAgLyhvcGVyYXxjaHJvbWV8c2FmYXJpfGZpcmVmb3h8bXNpZXx0cmlkZW50KD89XFwvKSlcXC8/XFxzKihcXGQrKS9pKSB8fCBbXTtcbiAgaWYgKC90cmlkZW50L2kudGVzdChjaGVja01hdGNoWzFdKSkge1xuICAgIGhhc01hdGNoID0gL1xcYnJ2WyA6XSsoXFxkKykvZy5leGVjKG5hdmlnYXRvci51c2VyQWdlbnQpIHx8IFtdO1xuICAgIHdlYnJ0Y0RldGVjdGVkQnJvd3NlciA9ICdJRSc7XG4gICAgd2VicnRjRGV0ZWN0ZWRWZXJzaW9uID0gcGFyc2VJbnQoaGFzTWF0Y2hbMV0gfHwgJzAnLCAxMCk7XG4gIH0gZWxzZSBpZiAoY2hlY2tNYXRjaFsxXSA9PT0gJ0Nocm9tZScpIHtcbiAgICBoYXNNYXRjaCA9IG5hdmlnYXRvci51c2VyQWdlbnQubWF0Y2goL1xcYk9QUlxcLyhcXGQrKS8pO1xuICAgIGlmIChoYXNNYXRjaCAhPT0gbnVsbCkge1xuICAgICAgd2VicnRjRGV0ZWN0ZWRCcm93c2VyID0gJ29wZXJhJztcbiAgICAgIHdlYnJ0Y0RldGVjdGVkVmVyc2lvbiA9IHBhcnNlSW50KGhhc01hdGNoWzFdLCAxMCk7XG4gICAgfVxuICB9XG4gIGlmIChuYXZpZ2F0b3IudXNlckFnZW50LmluZGV4T2YoJ1NhZmFyaScpKSB7XG4gICAgaWYgKHR5cGVvZiBJbnN0YWxsVHJpZ2dlciAhPT0gJ3VuZGVmaW5lZCcpIHtcbiAgICAgIHdlYnJ0Y0RldGVjdGVkQnJvd3NlciA9ICdmaXJlZm94JztcbiAgICB9IGVsc2UgaWYgKC8qQGNjX29uIUAqLyBmYWxzZSB8fCAhIWRvY3VtZW50LmRvY3VtZW50TW9kZSkge1xuICAgICAgd2VicnRjRGV0ZWN0ZWRCcm93c2VyID0gJ0lFJztcbiAgICB9IGVsc2UgaWYgKFxuICAgICAgT2JqZWN0LnByb3RvdHlwZS50b1N0cmluZy5jYWxsKHdpbmRvdy5IVE1MRWxlbWVudCkuaW5kZXhPZignQ29uc3RydWN0b3InKSA+IDApIHtcbiAgICAgIHdlYnJ0Y0RldGVjdGVkQnJvd3NlciA9ICdzYWZhcmknO1xuICAgIH0gZWxzZSBpZiAoISF3aW5kb3cub3BlcmEgfHwgbmF2aWdhdG9yLnVzZXJBZ2VudC5pbmRleE9mKCcgT1BSLycpID49IDApIHtcbiAgICAgIHdlYnJ0Y0RldGVjdGVkQnJvd3NlciA9ICdvcGVyYSc7XG4gICAgfSBlbHNlIGlmICghIXdpbmRvdy5jaHJvbWUpIHtcbiAgICAgIHdlYnJ0Y0RldGVjdGVkQnJvd3NlciA9ICdjaHJvbWUnO1xuICAgIH1cbiAgfVxuICBpZiAoIXdlYnJ0Y0RldGVjdGVkQnJvd3Nlcikge1xuICAgIHdlYnJ0Y0RldGVjdGVkVmVyc2lvbiA9IGNoZWNrTWF0Y2hbMV07XG4gIH1cbiAgaWYgKCF3ZWJydGNEZXRlY3RlZFZlcnNpb24pIHtcbiAgICB0cnkge1xuICAgICAgY2hlY2tNYXRjaCA9IChjaGVja01hdGNoWzJdKSA/IFtjaGVja01hdGNoWzFdLCBjaGVja01hdGNoWzJdXSA6XG4gICAgICAgIFtuYXZpZ2F0b3IuYXBwTmFtZSwgbmF2aWdhdG9yLmFwcFZlcnNpb24sICctPyddO1xuICAgICAgaWYgKChoYXNNYXRjaCA9IG5hdmlnYXRvci51c2VyQWdlbnQubWF0Y2goL3ZlcnNpb25cXC8oXFxkKykvaSkpICE9PSBudWxsKSB7XG4gICAgICAgIGNoZWNrTWF0Y2guc3BsaWNlKDEsIDEsIGhhc01hdGNoWzFdKTtcbiAgICAgIH1cbiAgICAgIHdlYnJ0Y0RldGVjdGVkVmVyc2lvbiA9IHBhcnNlSW50KGNoZWNrTWF0Y2hbMV0sIDEwKTtcbiAgICB9IGNhdGNoIChlcnJvcikgeyB9XG4gIH1cbn07XG5cbi8vIFRvIGZpeCBjb25maWd1cmF0aW9uIGFzIHNvbWUgYnJvd3NlcnMgZG9lcyBub3Qgc3VwcG9ydFxuLy8gdGhlICd1cmxzJyBhdHRyaWJ1dGUuXG5BZGFwdGVySlMubWF5YmVGaXhDb25maWd1cmF0aW9uID0gZnVuY3Rpb24gKHBjQ29uZmlnKSB7XG4gIGlmIChwY0NvbmZpZyA9PT0gbnVsbCkge1xuICAgIHJldHVybjtcbiAgfVxuICBmb3IgKHZhciBpID0gMDsgaSA8IHBjQ29uZmlnLmljZVNlcnZlcnMubGVuZ3RoOyBpKyspIHtcbiAgICBpZiAocGNDb25maWcuaWNlU2VydmVyc1tpXS5oYXNPd25Qcm9wZXJ0eSgndXJscycpKSB7XG4gICAgICBwY0NvbmZpZy5pY2VTZXJ2ZXJzW2ldLnVybCA9IHBjQ29uZmlnLmljZVNlcnZlcnNbaV0udXJscztcbiAgICAgIGRlbGV0ZSBwY0NvbmZpZy5pY2VTZXJ2ZXJzW2ldLnVybHM7XG4gICAgfVxuICB9XG59O1xuXG5BZGFwdGVySlMuYWRkRXZlbnQgPSBmdW5jdGlvbihlbGVtLCBldm50LCBmdW5jKSB7XG4gIGlmIChlbGVtLmFkZEV2ZW50TGlzdGVuZXIpIHsgLy8gVzNDIERPTVxuICAgIGVsZW0uYWRkRXZlbnRMaXN0ZW5lcihldm50LCBmdW5jLCBmYWxzZSk7XG4gIH0gZWxzZSBpZiAoZWxlbS5hdHRhY2hFdmVudCkgey8vIE9MRCBJRSBET01cbiAgICBlbGVtLmF0dGFjaEV2ZW50KCdvbicrZXZudCwgZnVuYyk7XG4gIH0gZWxzZSB7IC8vIE5vIG11Y2ggdG8gZG9cbiAgICBlbGVtW2V2bnRdID0gZnVuYztcbiAgfVxufTtcblxuQWRhcHRlckpTLnJlbmRlck5vdGlmaWNhdGlvbkJhciA9IGZ1bmN0aW9uICh0ZXh0LCBidXR0b25UZXh0LCBidXR0b25MaW5rLCBvcGVuTmV3VGFiLCBkaXNwbGF5UmVmcmVzaEJhcikge1xuICAvLyBvbmx5IGluamVjdCBvbmNlIHRoZSBwYWdlIGlzIHJlYWR5XG4gIGlmIChkb2N1bWVudC5yZWFkeVN0YXRlICE9PSAnY29tcGxldGUnKSB7XG4gICAgcmV0dXJuO1xuICB9XG5cbiAgdmFyIHcgPSB3aW5kb3c7XG4gIHZhciBpID0gZG9jdW1lbnQuY3JlYXRlRWxlbWVudCgnaWZyYW1lJyk7XG4gIGkuc3R5bGUucG9zaXRpb24gPSAnZml4ZWQnO1xuICBpLnN0eWxlLnRvcCA9ICctNDFweCc7XG4gIGkuc3R5bGUubGVmdCA9IDA7XG4gIGkuc3R5bGUucmlnaHQgPSAwO1xuICBpLnN0eWxlLndpZHRoID0gJzEwMCUnO1xuICBpLnN0eWxlLmhlaWdodCA9ICc0MHB4JztcbiAgaS5zdHlsZS5iYWNrZ3JvdW5kQ29sb3IgPSAnI2ZmZmZlMSc7XG4gIGkuc3R5bGUuYm9yZGVyID0gJ25vbmUnO1xuICBpLnN0eWxlLmJvcmRlckJvdHRvbSA9ICcxcHggc29saWQgIzg4ODg4OCc7XG4gIGkuc3R5bGUuekluZGV4ID0gJzk5OTk5OTknO1xuICBpZih0eXBlb2YgaS5zdHlsZS53ZWJraXRUcmFuc2l0aW9uID09PSAnc3RyaW5nJykge1xuICAgIGkuc3R5bGUud2Via2l0VHJhbnNpdGlvbiA9ICdhbGwgLjVzIGVhc2Utb3V0JztcbiAgfSBlbHNlIGlmKHR5cGVvZiBpLnN0eWxlLnRyYW5zaXRpb24gPT09ICdzdHJpbmcnKSB7XG4gICAgaS5zdHlsZS50cmFuc2l0aW9uID0gJ2FsbCAuNXMgZWFzZS1vdXQnO1xuICB9XG4gIGRvY3VtZW50LmJvZHkuYXBwZW5kQ2hpbGQoaSk7XG4gIGMgPSAoaS5jb250ZW50V2luZG93KSA/IGkuY29udGVudFdpbmRvdyA6XG4gICAgKGkuY29udGVudERvY3VtZW50LmRvY3VtZW50KSA/IGkuY29udGVudERvY3VtZW50LmRvY3VtZW50IDogaS5jb250ZW50RG9jdW1lbnQ7XG4gIGMuZG9jdW1lbnQub3BlbigpO1xuICBjLmRvY3VtZW50LndyaXRlKCc8c3BhbiBzdHlsZT1cImRpc3BsYXk6IGlubGluZS1ibG9jazsgZm9udC1mYW1pbHk6IEhlbHZldGljYSwgQXJpYWwsJyArXG4gICAgJ3NhbnMtc2VyaWY7IGZvbnQtc2l6ZTogLjlyZW07IHBhZGRpbmc6IDRweDsgdmVydGljYWwtYWxpZ246ICcgK1xuICAgICdtaWRkbGU7IGN1cnNvcjogZGVmYXVsdDtcIj4nICsgdGV4dCArICc8L3NwYW4+Jyk7XG4gIGlmKGJ1dHRvblRleHQgJiYgYnV0dG9uTGluaykge1xuICAgIGMuZG9jdW1lbnQud3JpdGUoJzxidXR0b24gaWQ9XCJva2F5XCI+JyArIGJ1dHRvblRleHQgKyAnPC9idXR0b24+PGJ1dHRvbiBpZD1cImNhbmNlbFwiPkNhbmNlbDwvYnV0dG9uPicpO1xuICAgIGMuZG9jdW1lbnQuY2xvc2UoKTtcblxuICAgIC8vIE9uIGNsaWNrIG9uIG9rYXlcbiAgICBBZGFwdGVySlMuYWRkRXZlbnQoYy5kb2N1bWVudC5nZXRFbGVtZW50QnlJZCgnb2theScpLCAnY2xpY2snLCBmdW5jdGlvbihlKSB7XG4gICAgICBpZiAoISFkaXNwbGF5UmVmcmVzaEJhcikge1xuICAgICAgICBBZGFwdGVySlMucmVuZGVyTm90aWZpY2F0aW9uQmFyKEFkYXB0ZXJKUy5URVhULkVYVEVOU0lPTiA/XG4gICAgICAgICAgQWRhcHRlckpTLlRFWFQuRVhURU5TSU9OLlJFUVVJUkVfUkVGUkVTSCA6IEFkYXB0ZXJKUy5URVhULlJFRlJFU0guUkVRVUlSRV9SRUZSRVNILFxuICAgICAgICAgIEFkYXB0ZXJKUy5URVhULlJFRlJFU0guQlVUVE9OLCAnamF2YXNjcmlwdDpsb2NhdGlvbi5yZWxvYWQoKScpO1xuICAgICAgfVxuICAgICAgd2luZG93Lm9wZW4oYnV0dG9uTGluaywgISFvcGVuTmV3VGFiID8gJ19ibGFuaycgOiAnX3RvcCcpO1xuXG4gICAgICBlLnByZXZlbnREZWZhdWx0KCk7XG4gICAgICB0cnkge1xuICAgICAgICBldmVudC5jYW5jZWxCdWJibGUgPSB0cnVlO1xuICAgICAgfSBjYXRjaChlcnJvcikgeyB9XG5cbiAgICAgIHZhciBwbHVnaW5JbnN0YWxsSW50ZXJ2YWwgPSBzZXRJbnRlcnZhbChmdW5jdGlvbigpe1xuICAgICAgICBpZighIGlzSUUpIHtcbiAgICAgICAgICBuYXZpZ2F0b3IucGx1Z2lucy5yZWZyZXNoKGZhbHNlKTtcbiAgICAgICAgfVxuICAgICAgICBBZGFwdGVySlMuV2ViUlRDUGx1Z2luLmlzUGx1Z2luSW5zdGFsbGVkKFxuICAgICAgICAgIEFkYXB0ZXJKUy5XZWJSVENQbHVnaW4ucGx1Z2luSW5mby5wcmVmaXgsXG4gICAgICAgICAgQWRhcHRlckpTLldlYlJUQ1BsdWdpbi5wbHVnaW5JbmZvLnBsdWdOYW1lLFxuICAgICAgICAgIGZ1bmN0aW9uKCkgeyAvLyBwbHVnaW4gbm93IGluc3RhbGxlZFxuICAgICAgICAgICAgY2xlYXJJbnRlcnZhbChwbHVnaW5JbnN0YWxsSW50ZXJ2YWwpO1xuICAgICAgICAgICAgQWRhcHRlckpTLldlYlJUQ1BsdWdpbi5kZWZpbmVXZWJSVENJbnRlcmZhY2UoKTtcbiAgICAgICAgICB9LFxuICAgICAgICAgIGZ1bmN0aW9uKCkge1xuICAgICAgICAgICAgLy8gc3RpbGwgbm8gcGx1Z2luIGRldGVjdGVkLCBub3RoaW5nIHRvIGRvXG4gICAgICAgICAgfSk7XG4gICAgICB9ICwgNTAwKTtcbiAgICB9KTtcblxuICAgIC8vIE9uIGNsaWNrIG9uIENhbmNlbFxuICAgIEFkYXB0ZXJKUy5hZGRFdmVudChjLmRvY3VtZW50LmdldEVsZW1lbnRCeUlkKCdjYW5jZWwnKSwgJ2NsaWNrJywgZnVuY3Rpb24oZSkge1xuICAgICAgdy5kb2N1bWVudC5ib2R5LnJlbW92ZUNoaWxkKGkpO1xuICAgIH0pO1xuICB9IGVsc2Uge1xuICAgIGMuZG9jdW1lbnQuY2xvc2UoKTtcbiAgfVxuICBzZXRUaW1lb3V0KGZ1bmN0aW9uKCkge1xuICAgIGlmKHR5cGVvZiBpLnN0eWxlLndlYmtpdFRyYW5zZm9ybSA9PT0gJ3N0cmluZycpIHtcbiAgICAgIGkuc3R5bGUud2Via2l0VHJhbnNmb3JtID0gJ3RyYW5zbGF0ZVkoNDBweCknO1xuICAgIH0gZWxzZSBpZih0eXBlb2YgaS5zdHlsZS50cmFuc2Zvcm0gPT09ICdzdHJpbmcnKSB7XG4gICAgICBpLnN0eWxlLnRyYW5zZm9ybSA9ICd0cmFuc2xhdGVZKDQwcHgpJztcbiAgICB9IGVsc2Uge1xuICAgICAgaS5zdHlsZS50b3AgPSAnMHB4JztcbiAgICB9XG4gIH0sIDMwMCk7XG59O1xuXG4vLyAtLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLVxuLy8gRGV0ZWN0ZWQgd2VicnRjIGltcGxlbWVudGF0aW9uLiBUeXBlcyBhcmU6XG4vLyAtICdtb3onOiBNb3ppbGxhIGltcGxlbWVudGF0aW9uIG9mIHdlYlJUQy5cbi8vIC0gJ3dlYmtpdCc6IFdlYktpdCBpbXBsZW1lbnRhdGlvbiBvZiB3ZWJSVEMuXG4vLyAtICdwbHVnaW4nOiBVc2luZyB0aGUgcGx1Z2luIGltcGxlbWVudGF0aW9uLlxud2VicnRjRGV0ZWN0ZWRUeXBlID0gbnVsbDtcblxuLy8gRGV0ZWN0ZWQgd2VicnRjIGRhdGFjaGFubmVsIHN1cHBvcnQuIFR5cGVzIGFyZTpcbi8vIC0gJ1NDVFAnOiBTQ1RQIGRhdGFjaGFubmVsIHN1cHBvcnQuXG4vLyAtICdSVFAnOiBSVFAgZGF0YWNoYW5uZWwgc3VwcG9ydC5cbndlYnJ0Y0RldGVjdGVkRENTdXBwb3J0ID0gbnVsbDtcblxuLy8gU2V0IHRoZSBzZXR0aW5ncyBmb3IgY3JlYXRpbmcgRGF0YUNoYW5uZWxzLCBNZWRpYVN0cmVhbSBmb3Jcbi8vIENyb3NzLWJyb3dzZXIgY29tcGFiaWxpdHkuXG4vLyAtIFRoaXMgaXMgb25seSBmb3IgU0NUUCBiYXNlZCBzdXBwb3J0IGJyb3dzZXJzLlxuLy8gdGhlICd1cmxzJyBhdHRyaWJ1dGUuXG5jaGVja01lZGlhRGF0YUNoYW5uZWxTZXR0aW5ncyA9XG4gIGZ1bmN0aW9uIChwZWVyQnJvd3NlckFnZW50LCBwZWVyQnJvd3NlclZlcnNpb24sIGNhbGxiYWNrLCBjb25zdHJhaW50cykge1xuICBpZiAodHlwZW9mIGNhbGxiYWNrICE9PSAnZnVuY3Rpb24nKSB7XG4gICAgcmV0dXJuO1xuICB9XG4gIHZhciBiZU9mZmVyZXIgPSB0cnVlO1xuICB2YXIgaXNMb2NhbEZpcmVmb3ggPSB3ZWJydGNEZXRlY3RlZEJyb3dzZXIgPT09ICdmaXJlZm94JztcbiAgLy8gTmlnaHRseSB2ZXJzaW9uIGRvZXMgbm90IHJlcXVpcmUgTW96RG9udE9mZmVyRGF0YUNoYW5uZWwgZm9yIGludGVyb3BcbiAgdmFyIGlzTG9jYWxGaXJlZm94SW50ZXJvcCA9IHdlYnJ0Y0RldGVjdGVkVHlwZSA9PT0gJ21veicgJiYgd2VicnRjRGV0ZWN0ZWRWZXJzaW9uID4gMzA7XG4gIHZhciBpc1BlZXJGaXJlZm94ID0gcGVlckJyb3dzZXJBZ2VudCA9PT0gJ2ZpcmVmb3gnO1xuICB2YXIgaXNQZWVyRmlyZWZveEludGVyb3AgPSBwZWVyQnJvd3NlckFnZW50ID09PSAnZmlyZWZveCcgJiZcbiAgICAoKHBlZXJCcm93c2VyVmVyc2lvbikgPyAocGVlckJyb3dzZXJWZXJzaW9uID4gMzApIDogZmFsc2UpO1xuXG4gIC8vIFJlc2VuZHMgYW4gdXBkYXRlZCB2ZXJzaW9uIG9mIGNvbnN0cmFpbnRzIGZvciBNb3pEYXRhQ2hhbm5lbCB0byB3b3JrXG4gIC8vIElmIG90aGVyIHVzZXJBZ2VudCBpcyBmaXJlZm94IGFuZCB1c2VyIGlzIGZpcmVmb3gsIHJlbW92ZSBNb3pEYXRhQ2hhbm5lbFxuICBpZiAoKGlzTG9jYWxGaXJlZm94ICYmIGlzUGVlckZpcmVmb3gpIHx8IChpc0xvY2FsRmlyZWZveEludGVyb3ApKSB7XG4gICAgdHJ5IHtcbiAgICAgIGRlbGV0ZSBjb25zdHJhaW50cy5tYW5kYXRvcnkuTW96RG9udE9mZmVyRGF0YUNoYW5uZWw7XG4gICAgfSBjYXRjaCAoZXJyb3IpIHtcbiAgICAgIGNvbnNvbGUuZXJyb3IoJ0ZhaWxlZCBkZWxldGluZyBNb3pEb250T2ZmZXJEYXRhQ2hhbm5lbCcpO1xuICAgICAgY29uc29sZS5lcnJvcihlcnJvcik7XG4gICAgfVxuICB9IGVsc2UgaWYgKChpc0xvY2FsRmlyZWZveCAmJiAhaXNQZWVyRmlyZWZveCkpIHtcbiAgICBjb25zdHJhaW50cy5tYW5kYXRvcnkuTW96RG9udE9mZmVyRGF0YUNoYW5uZWwgPSB0cnVlO1xuICB9XG4gIGlmICghaXNMb2NhbEZpcmVmb3gpIHtcbiAgICAvLyB0ZW1wb3JhcnkgbWVhc3VyZSB0byByZW1vdmUgTW96KiBjb25zdHJhaW50cyBpbiBub24gRmlyZWZveCBicm93c2Vyc1xuICAgIGZvciAodmFyIHByb3AgaW4gY29uc3RyYWludHMubWFuZGF0b3J5KSB7XG4gICAgICBpZiAoY29uc3RyYWludHMubWFuZGF0b3J5Lmhhc093blByb3BlcnR5KHByb3ApKSB7XG4gICAgICAgIGlmIChwcm9wLmluZGV4T2YoJ01veicpICE9PSAtMSkge1xuICAgICAgICAgIGRlbGV0ZSBjb25zdHJhaW50cy5tYW5kYXRvcnlbcHJvcF07XG4gICAgICAgIH1cbiAgICAgIH1cbiAgICB9XG4gIH1cbiAgLy8gRmlyZWZveCAobm90IGludGVyb3BhYmxlKSBjYW5ub3Qgb2ZmZXIgRGF0YUNoYW5uZWwgYXMgaXQgd2lsbCBjYXVzZSBwcm9ibGVtcyB0byB0aGVcbiAgLy8gaW50ZXJvcGFiaWxpdHkgb2YgdGhlIG1lZGlhIHN0cmVhbVxuICBpZiAoaXNMb2NhbEZpcmVmb3ggJiYgIWlzUGVlckZpcmVmb3ggJiYgIWlzTG9jYWxGaXJlZm94SW50ZXJvcCkge1xuICAgIGJlT2ZmZXJlciA9IGZhbHNlO1xuICB9XG4gIGNhbGxiYWNrKGJlT2ZmZXJlciwgY29uc3RyYWludHMpO1xufTtcblxuLy8gSGFuZGxlcyB0aGUgZGlmZmVyZW5jZXMgZm9yIGFsbCBicm93c2VycyBpY2UgY29ubmVjdGlvbiBzdGF0ZSBvdXRwdXQuXG4vLyAtIFRlc3RlZCBvdXRjb21lcyBhcmU6XG4vLyAgIC0gQ2hyb21lIChvZmZlcmVyKSAgOiAnY2hlY2tpbmcnID4gJ2NvbXBsZXRlZCcgPiAnY29tcGxldGVkJ1xuLy8gICAtIENocm9tZSAoYW5zd2VyZXIpIDogJ2NoZWNraW5nJyA+ICdjb25uZWN0ZWQnXG4vLyAgIC0gRmlyZWZveCAob2ZmZXJlcikgOiAnY2hlY2tpbmcnID4gJ2Nvbm5lY3RlZCdcbi8vICAgLSBGaXJlZm94IChhbnN3ZXJlcik6ICdjaGVja2luZycgPiAnY29ubmVjdGVkJ1xuY2hlY2tJY2VDb25uZWN0aW9uU3RhdGUgPSBmdW5jdGlvbiAocGVlcklkLCBpY2VDb25uZWN0aW9uU3RhdGUsIGNhbGxiYWNrKSB7XG4gIGlmICh0eXBlb2YgY2FsbGJhY2sgIT09ICdmdW5jdGlvbicpIHtcbiAgICBjb25zb2xlLndhcm4oJ05vIGNhbGxiYWNrIHNwZWNpZmllZCBpbiBjaGVja0ljZUNvbm5lY3Rpb25TdGF0ZS4gQWJvcnRlZC4nKTtcbiAgICByZXR1cm47XG4gIH1cbiAgcGVlcklkID0gKHBlZXJJZCkgPyBwZWVySWQgOiAncGVlcic7XG5cbiAgaWYgKCFBZGFwdGVySlMuX2ljZUNvbm5lY3Rpb25GaXJlZFN0YXRlc1twZWVySWRdIHx8XG4gICAgaWNlQ29ubmVjdGlvblN0YXRlID09PSBBZGFwdGVySlMuX2ljZUNvbm5lY3Rpb25TdGF0ZXMuZGlzY29ubmVjdGVkIHx8XG4gICAgaWNlQ29ubmVjdGlvblN0YXRlID09PSBBZGFwdGVySlMuX2ljZUNvbm5lY3Rpb25TdGF0ZXMuZmFpbGVkIHx8XG4gICAgaWNlQ29ubmVjdGlvblN0YXRlID09PSBBZGFwdGVySlMuX2ljZUNvbm5lY3Rpb25TdGF0ZXMuY2xvc2VkKSB7XG4gICAgQWRhcHRlckpTLl9pY2VDb25uZWN0aW9uRmlyZWRTdGF0ZXNbcGVlcklkXSA9IFtdO1xuICB9XG4gIGljZUNvbm5lY3Rpb25TdGF0ZSA9IEFkYXB0ZXJKUy5faWNlQ29ubmVjdGlvblN0YXRlc1tpY2VDb25uZWN0aW9uU3RhdGVdO1xuICBpZiAoQWRhcHRlckpTLl9pY2VDb25uZWN0aW9uRmlyZWRTdGF0ZXNbcGVlcklkXS5pbmRleE9mKGljZUNvbm5lY3Rpb25TdGF0ZSkgPCAwKSB7XG4gICAgQWRhcHRlckpTLl9pY2VDb25uZWN0aW9uRmlyZWRTdGF0ZXNbcGVlcklkXS5wdXNoKGljZUNvbm5lY3Rpb25TdGF0ZSk7XG4gICAgaWYgKGljZUNvbm5lY3Rpb25TdGF0ZSA9PT0gQWRhcHRlckpTLl9pY2VDb25uZWN0aW9uU3RhdGVzLmNvbm5lY3RlZCkge1xuICAgICAgc2V0VGltZW91dChmdW5jdGlvbiAoKSB7XG4gICAgICAgIEFkYXB0ZXJKUy5faWNlQ29ubmVjdGlvbkZpcmVkU3RhdGVzW3BlZXJJZF1cbiAgICAgICAgICAucHVzaChBZGFwdGVySlMuX2ljZUNvbm5lY3Rpb25TdGF0ZXMuZG9uZSk7XG4gICAgICAgIGNhbGxiYWNrKEFkYXB0ZXJKUy5faWNlQ29ubmVjdGlvblN0YXRlcy5kb25lKTtcbiAgICAgIH0sIDEwMDApO1xuICAgIH1cbiAgICBjYWxsYmFjayhpY2VDb25uZWN0aW9uU3RhdGUpO1xuICB9XG4gIHJldHVybjtcbn07XG5cbi8vIEZpcmVmb3g6XG4vLyAtIENyZWF0ZXMgaWNlU2VydmVyIGZyb20gdGhlIHVybCBmb3IgRmlyZWZveC5cbi8vIC0gQ3JlYXRlIGljZVNlcnZlciB3aXRoIHN0dW4gdXJsLlxuLy8gLSBDcmVhdGUgaWNlU2VydmVyIHdpdGggdHVybiB1cmwuXG4vLyAgIC0gSWdub3JlIHRoZSB0cmFuc3BvcnQgcGFyYW1ldGVyIGZyb20gVFVSTiB1cmwgZm9yIEZGIHZlcnNpb24gPD0yNy5cbi8vICAgLSBSZXR1cm4gbnVsbCBmb3IgY3JlYXRlSWNlU2VydmVyIGlmIHRyYW5zcG9ydD10Y3AuXG4vLyAtIEZGIDI3IGFuZCBhYm92ZSBzdXBwb3J0cyB0cmFuc3BvcnQgcGFyYW1ldGVycyBpbiBUVVJOIHVybCxcbi8vIC0gU28gcGFzc2luZyBpbiB0aGUgZnVsbCB1cmwgdG8gY3JlYXRlIGljZVNlcnZlci5cbi8vIENocm9tZTpcbi8vIC0gQ3JlYXRlcyBpY2VTZXJ2ZXIgZnJvbSB0aGUgdXJsIGZvciBDaHJvbWUgTTMzIGFuZCBlYXJsaWVyLlxuLy8gICAtIENyZWF0ZSBpY2VTZXJ2ZXIgd2l0aCBzdHVuIHVybC5cbi8vICAgLSBDaHJvbWUgTTI4ICYgYWJvdmUgdXNlcyBiZWxvdyBUVVJOIGZvcm1hdC5cbi8vIFBsdWdpbjpcbi8vIC0gQ3JlYXRlcyBJY2UgU2VydmVyIGZvciBQbHVnaW4gQnJvd3NlcnNcbi8vICAgLSBJZiBTdHVuIC0gQ3JlYXRlIGljZVNlcnZlciB3aXRoIHN0dW4gdXJsLlxuLy8gICAtIEVsc2UgLSBDcmVhdGUgaWNlU2VydmVyIHdpdGggdHVybiB1cmxcbi8vICAgLSBUaGlzIGlzIGEgV2ViUlRDIEZ1bmN0aW9uXG5jcmVhdGVJY2VTZXJ2ZXIgPSBudWxsO1xuXG4vLyBGaXJlZm94OlxuLy8gLSBDcmVhdGVzIEljZVNlcnZlcnMgZm9yIEZpcmVmb3hcbi8vICAgLSBVc2UgLnVybCBmb3IgRmlyZUZveC5cbi8vICAgLSBNdWx0aXBsZSBVcmxzIHN1cHBvcnRcbi8vIENocm9tZTpcbi8vIC0gQ3JlYXRlcyBpY2VTZXJ2ZXJzIGZyb20gdGhlIHVybHMgZm9yIENocm9tZSBNMzQgYW5kIGFib3ZlLlxuLy8gICAtIC51cmxzIGlzIHN1cHBvcnRlZCBzaW5jZSBDaHJvbWUgTTM0LlxuLy8gICAtIE11bHRpcGxlIFVybHMgc3VwcG9ydFxuLy8gUGx1Z2luOlxuLy8gLSBDcmVhdGVzIEljZSBTZXJ2ZXJzIGZvciBQbHVnaW4gQnJvd3NlcnNcbi8vICAgLSBNdWx0aXBsZSBVcmxzIHN1cHBvcnRcbi8vICAgLSBUaGlzIGlzIGEgV2ViUlRDIEZ1bmN0aW9uXG5jcmVhdGVJY2VTZXJ2ZXJzID0gbnVsbDtcbi8vLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tXG5cbi8vVGhlIFJUQ1BlZXJDb25uZWN0aW9uIG9iamVjdC5cblJUQ1BlZXJDb25uZWN0aW9uID0gbnVsbDtcblxuLy8gQ3JlYXRlcyBSVENTZXNzaW9uRGVzY3JpcHRpb24gb2JqZWN0IGZvciBQbHVnaW4gQnJvd3NlcnNcblJUQ1Nlc3Npb25EZXNjcmlwdGlvbiA9ICh0eXBlb2YgUlRDU2Vzc2lvbkRlc2NyaXB0aW9uID09PSAnZnVuY3Rpb24nKSA/XG4gIFJUQ1Nlc3Npb25EZXNjcmlwdGlvbiA6IG51bGw7XG5cbi8vIENyZWF0ZXMgUlRDSWNlQ2FuZGlkYXRlIG9iamVjdCBmb3IgUGx1Z2luIEJyb3dzZXJzXG5SVENJY2VDYW5kaWRhdGUgPSAodHlwZW9mIFJUQ0ljZUNhbmRpZGF0ZSA9PT0gJ2Z1bmN0aW9uJykgP1xuICBSVENJY2VDYW5kaWRhdGUgOiBudWxsO1xuXG4vLyBHZXQgVXNlck1lZGlhIChvbmx5IGRpZmZlcmVuY2UgaXMgdGhlIHByZWZpeCkuXG4vLyBDb2RlIGZyb20gQWRhbSBCYXJ0aC5cbmdldFVzZXJNZWRpYSA9IG51bGw7XG5cbi8vIEF0dGFjaCBhIG1lZGlhIHN0cmVhbSB0byBhbiBlbGVtZW50LlxuYXR0YWNoTWVkaWFTdHJlYW0gPSBudWxsO1xuXG4vLyBSZS1hdHRhY2ggYSBtZWRpYSBzdHJlYW0gdG8gYW4gZWxlbWVudC5cbnJlYXR0YWNoTWVkaWFTdHJlYW0gPSBudWxsO1xuXG5cbi8vIERldGVjdGVkIGJyb3dzZXIgYWdlbnQgbmFtZS4gVHlwZXMgYXJlOlxuLy8gLSAnZmlyZWZveCc6IEZpcmVmb3ggYnJvd3Nlci5cbi8vIC0gJ2Nocm9tZSc6IENocm9tZSBicm93c2VyLlxuLy8gLSAnb3BlcmEnOiBPcGVyYSBicm93c2VyLlxuLy8gLSAnc2FmYXJpJzogU2FmYXJpIGJyb3dzZXIuXG4vLyAtICdJRScgLSBJbnRlcm5ldCBFeHBsb3JlciBicm93c2VyLlxud2VicnRjRGV0ZWN0ZWRCcm93c2VyID0gbnVsbDtcblxuLy8gRGV0ZWN0ZWQgYnJvd3NlciB2ZXJzaW9uLlxud2VicnRjRGV0ZWN0ZWRWZXJzaW9uID0gbnVsbDtcblxuLy8gQ2hlY2sgZm9yIGJyb3dzZXIgdHlwZXMgYW5kIHJlYWN0IGFjY29yZGluZ2x5XG5pZiAobmF2aWdhdG9yLm1vekdldFVzZXJNZWRpYSkge1xuICB3ZWJydGNEZXRlY3RlZEJyb3dzZXIgPSAnZmlyZWZveCc7XG4gIHdlYnJ0Y0RldGVjdGVkVmVyc2lvbiA9IHBhcnNlSW50KG5hdmlnYXRvclxuICAgIC51c2VyQWdlbnQubWF0Y2goL0ZpcmVmb3hcXC8oWzAtOV0rKVxcLi8pWzFdLCAxMCk7XG4gIHdlYnJ0Y0RldGVjdGVkVHlwZSA9ICdtb3onO1xuICB3ZWJydGNEZXRlY3RlZERDU3VwcG9ydCA9ICdTQ1RQJztcblxuICBSVENQZWVyQ29ubmVjdGlvbiA9IGZ1bmN0aW9uIChwY0NvbmZpZywgcGNDb25zdHJhaW50cykge1xuICAgIEFkYXB0ZXJKUy5tYXliZUZpeENvbmZpZ3VyYXRpb24ocGNDb25maWcpO1xuICAgIHJldHVybiBuZXcgbW96UlRDUGVlckNvbm5lY3Rpb24ocGNDb25maWcsIHBjQ29uc3RyYWludHMpO1xuICB9O1xuXG4gLy8gVGhlIFJUQ1Nlc3Npb25EZXNjcmlwdGlvbiBvYmplY3QuXG4gIFJUQ1Nlc3Npb25EZXNjcmlwdGlvbiA9IG1velJUQ1Nlc3Npb25EZXNjcmlwdGlvbjtcbiAgd2luZG93LlJUQ1Nlc3Npb25EZXNjcmlwdGlvbiA9IFJUQ1Nlc3Npb25EZXNjcmlwdGlvbjtcblxuICAvLyBUaGUgUlRDSWNlQ2FuZGlkYXRlIG9iamVjdC5cbiAgUlRDSWNlQ2FuZGlkYXRlID0gbW96UlRDSWNlQ2FuZGlkYXRlO1xuICB3aW5kb3cuUlRDSWNlQ2FuZGlkYXRlID0gUlRDSWNlQ2FuZGlkYXRlO1xuXG4gIHdpbmRvdy5nZXRVc2VyTWVkaWEgPSBuYXZpZ2F0b3IubW96R2V0VXNlck1lZGlhLmJpbmQobmF2aWdhdG9yKTtcbiAgbmF2aWdhdG9yLmdldFVzZXJNZWRpYSA9IHdpbmRvdy5nZXRVc2VyTWVkaWE7XG5cbiAgLy8gU2hpbSBmb3IgTWVkaWFTdHJlYW1UcmFjay5nZXRTb3VyY2VzLlxuICBNZWRpYVN0cmVhbVRyYWNrLmdldFNvdXJjZXMgPSBmdW5jdGlvbihzdWNjZXNzQ2IpIHtcbiAgICBzZXRUaW1lb3V0KGZ1bmN0aW9uKCkge1xuICAgICAgdmFyIGluZm9zID0gW1xuICAgICAgICB7IGtpbmQ6ICdhdWRpbycsIGlkOiAnZGVmYXVsdCcsIGxhYmVsOicnLCBmYWNpbmc6JycgfSxcbiAgICAgICAgeyBraW5kOiAndmlkZW8nLCBpZDogJ2RlZmF1bHQnLCBsYWJlbDonJywgZmFjaW5nOicnIH1cbiAgICAgIF07XG4gICAgICBzdWNjZXNzQ2IoaW5mb3MpO1xuICAgIH0sIDApO1xuICB9O1xuXG4gIGNyZWF0ZUljZVNlcnZlciA9IGZ1bmN0aW9uICh1cmwsIHVzZXJuYW1lLCBwYXNzd29yZCkge1xuICAgIHZhciBpY2VTZXJ2ZXIgPSBudWxsO1xuICAgIHZhciB1cmxfcGFydHMgPSB1cmwuc3BsaXQoJzonKTtcbiAgICBpZiAodXJsX3BhcnRzWzBdLmluZGV4T2YoJ3N0dW4nKSA9PT0gMCkge1xuICAgICAgaWNlU2VydmVyID0geyB1cmwgOiB1cmwgfTtcbiAgICB9IGVsc2UgaWYgKHVybF9wYXJ0c1swXS5pbmRleE9mKCd0dXJuJykgPT09IDApIHtcbiAgICAgIGlmICh3ZWJydGNEZXRlY3RlZFZlcnNpb24gPCAyNykge1xuICAgICAgICB2YXIgdHVybl91cmxfcGFydHMgPSB1cmwuc3BsaXQoJz8nKTtcbiAgICAgICAgaWYgKHR1cm5fdXJsX3BhcnRzLmxlbmd0aCA9PT0gMSB8fFxuICAgICAgICAgIHR1cm5fdXJsX3BhcnRzWzFdLmluZGV4T2YoJ3RyYW5zcG9ydD11ZHAnKSA9PT0gMCkge1xuICAgICAgICAgIGljZVNlcnZlciA9IHtcbiAgICAgICAgICAgIHVybCA6IHR1cm5fdXJsX3BhcnRzWzBdLFxuICAgICAgICAgICAgY3JlZGVudGlhbCA6IHBhc3N3b3JkLFxuICAgICAgICAgICAgdXNlcm5hbWUgOiB1c2VybmFtZVxuICAgICAgICAgIH07XG4gICAgICAgIH1cbiAgICAgIH0gZWxzZSB7XG4gICAgICAgIGljZVNlcnZlciA9IHtcbiAgICAgICAgICB1cmwgOiB1cmwsXG4gICAgICAgICAgY3JlZGVudGlhbCA6IHBhc3N3b3JkLFxuICAgICAgICAgIHVzZXJuYW1lIDogdXNlcm5hbWVcbiAgICAgICAgfTtcbiAgICAgIH1cbiAgICB9XG4gICAgcmV0dXJuIGljZVNlcnZlcjtcbiAgfTtcblxuICBjcmVhdGVJY2VTZXJ2ZXJzID0gZnVuY3Rpb24gKHVybHMsIHVzZXJuYW1lLCBwYXNzd29yZCkge1xuICAgIHZhciBpY2VTZXJ2ZXJzID0gW107XG4gICAgZm9yICh2YXIgaSA9IDA7IGkgPCB1cmxzLmxlbmd0aDsgaSsrKSB7XG4gICAgICB2YXIgaWNlU2VydmVyID0gY3JlYXRlSWNlU2VydmVyKHVybHNbaV0sIHVzZXJuYW1lLCBwYXNzd29yZCk7XG4gICAgICBpZiAoaWNlU2VydmVyICE9PSBudWxsKSB7XG4gICAgICAgIGljZVNlcnZlcnMucHVzaChpY2VTZXJ2ZXIpO1xuICAgICAgfVxuICAgIH1cbiAgICByZXR1cm4gaWNlU2VydmVycztcbiAgfTtcblxuICBhdHRhY2hNZWRpYVN0cmVhbSA9IGZ1bmN0aW9uIChlbGVtZW50LCBzdHJlYW0pIHtcbiAgICBlbGVtZW50Lm1velNyY09iamVjdCA9IHN0cmVhbTtcbiAgICBpZiAoc3RyZWFtICE9PSBudWxsKVxuICAgICAgZWxlbWVudC5wbGF5KCk7XG5cbiAgICByZXR1cm4gZWxlbWVudDtcbiAgfTtcblxuICByZWF0dGFjaE1lZGlhU3RyZWFtID0gZnVuY3Rpb24gKHRvLCBmcm9tKSB7XG4gICAgdG8ubW96U3JjT2JqZWN0ID0gZnJvbS5tb3pTcmNPYmplY3Q7XG4gICAgdG8ucGxheSgpO1xuICAgIHJldHVybiB0bztcbiAgfTtcblxuICBNZWRpYVN0cmVhbVRyYWNrLmdldFNvdXJjZXMgPSBNZWRpYVN0cmVhbVRyYWNrLmdldFNvdXJjZXMgfHwgZnVuY3Rpb24gKGNhbGxiYWNrKSB7XG4gICAgaWYgKCFjYWxsYmFjaykge1xuICAgICAgdGhyb3cgbmV3IFR5cGVFcnJvcignRmFpbGVkIHRvIGV4ZWN1dGUgXFwnZ2V0U291cmNlc1xcJyBvbiBcXCdNZWRpYVN0cmVhbVRyYWNrXFwnJyArXG4gICAgICAgICc6IDEgYXJndW1lbnQgcmVxdWlyZWQsIGJ1dCBvbmx5IDAgcHJlc2VudC4nKTtcbiAgICB9XG4gICAgcmV0dXJuIGNhbGxiYWNrKFtdKTtcbiAgfTtcblxuICAvLyBGYWtlIGdldHtWaWRlbyxBdWRpb31UcmFja3NcbiAgaWYgKCFNZWRpYVN0cmVhbS5wcm90b3R5cGUuZ2V0VmlkZW9UcmFja3MpIHtcbiAgICBNZWRpYVN0cmVhbS5wcm90b3R5cGUuZ2V0VmlkZW9UcmFja3MgPSBmdW5jdGlvbiAoKSB7XG4gICAgICByZXR1cm4gW107XG4gICAgfTtcbiAgfVxuICBpZiAoIU1lZGlhU3RyZWFtLnByb3RvdHlwZS5nZXRBdWRpb1RyYWNrcykge1xuICAgIE1lZGlhU3RyZWFtLnByb3RvdHlwZS5nZXRBdWRpb1RyYWNrcyA9IGZ1bmN0aW9uICgpIHtcbiAgICAgIHJldHVybiBbXTtcbiAgICB9O1xuICB9XG5cbiAgQWRhcHRlckpTLm1heWJlVGhyb3VnaFdlYlJUQ1JlYWR5KCk7XG59IGVsc2UgaWYgKG5hdmlnYXRvci53ZWJraXRHZXRVc2VyTWVkaWEpIHtcbiAgd2VicnRjRGV0ZWN0ZWRCcm93c2VyID0gJ2Nocm9tZSc7XG4gIHdlYnJ0Y0RldGVjdGVkVHlwZSA9ICd3ZWJraXQnO1xuICB3ZWJydGNEZXRlY3RlZFZlcnNpb24gPSBwYXJzZUludChuYXZpZ2F0b3JcbiAgICAudXNlckFnZW50Lm1hdGNoKC9DaHJvbShlfGl1bSlcXC8oWzAtOV0rKVxcLi8pWzJdLCAxMCk7XG4gIC8vIGNoZWNrIGlmIGJyb3dzZXIgaXMgb3BlcmEgMjArXG4gIHZhciBjaGVja0lmT3BlcmEgPSBuYXZpZ2F0b3IudXNlckFnZW50Lm1hdGNoKC9cXGJPUFJcXC8oXFxkKykvKTtcbiAgaWYgKGNoZWNrSWZPcGVyYSAhPT0gbnVsbCkge1xuICAgIHdlYnJ0Y0RldGVjdGVkQnJvd3NlciA9ICdvcGVyYSc7XG4gICAgd2VicnRjRGV0ZWN0ZWRWZXJzaW9uID0gcGFyc2VJbnQoY2hlY2tJZk9wZXJhWzFdLCAxMCk7XG4gIH1cbiAgLy8gY2hlY2sgYnJvd3NlciBkYXRhY2hhbm5lbCBzdXBwb3J0XG4gIGlmICgod2VicnRjRGV0ZWN0ZWRCcm93c2VyID09PSAnY2hyb21lJyAmJiB3ZWJydGNEZXRlY3RlZFZlcnNpb24gPj0gMzEpIHx8XG4gICAgKHdlYnJ0Y0RldGVjdGVkQnJvd3NlciA9PT0gJ29wZXJhJyAmJiB3ZWJydGNEZXRlY3RlZFZlcnNpb24gPj0gMjApKSB7XG4gICAgd2VicnRjRGV0ZWN0ZWREQ1N1cHBvcnQgPSAnU0NUUCc7XG4gIH0gZWxzZSBpZiAod2VicnRjRGV0ZWN0ZWRCcm93c2VyID09PSAnY2hyb21lJyAmJiB3ZWJydGNEZXRlY3RlZFZlcnNpb24gPCAzMCAmJlxuICAgIHdlYnJ0Y0RldGVjdGVkVmVyc2lvbiA+IDI0KSB7XG4gICAgd2VicnRjRGV0ZWN0ZWREQ1N1cHBvcnQgPSAnUlRQJztcbiAgfSBlbHNlIHtcbiAgICB3ZWJydGNEZXRlY3RlZERDU3VwcG9ydCA9ICcnO1xuICB9XG5cbiAgY3JlYXRlSWNlU2VydmVyID0gZnVuY3Rpb24gKHVybCwgdXNlcm5hbWUsIHBhc3N3b3JkKSB7XG4gICAgdmFyIGljZVNlcnZlciA9IG51bGw7XG4gICAgdmFyIHVybF9wYXJ0cyA9IHVybC5zcGxpdCgnOicpO1xuICAgIGlmICh1cmxfcGFydHNbMF0uaW5kZXhPZignc3R1bicpID09PSAwKSB7XG4gICAgICBpY2VTZXJ2ZXIgPSB7ICd1cmwnIDogdXJsIH07XG4gICAgfSBlbHNlIGlmICh1cmxfcGFydHNbMF0uaW5kZXhPZigndHVybicpID09PSAwKSB7XG4gICAgICBpY2VTZXJ2ZXIgPSB7XG4gICAgICAgICd1cmwnIDogdXJsLFxuICAgICAgICAnY3JlZGVudGlhbCcgOiBwYXNzd29yZCxcbiAgICAgICAgJ3VzZXJuYW1lJyA6IHVzZXJuYW1lXG4gICAgICB9O1xuICAgIH1cbiAgICByZXR1cm4gaWNlU2VydmVyO1xuICB9O1xuXG4gIGNyZWF0ZUljZVNlcnZlcnMgPSBmdW5jdGlvbiAodXJscywgdXNlcm5hbWUsIHBhc3N3b3JkKSB7XG4gICAgdmFyIGljZVNlcnZlcnMgPSBbXTtcbiAgICBpZiAod2VicnRjRGV0ZWN0ZWRWZXJzaW9uID49IDM0KSB7XG4gICAgICBpY2VTZXJ2ZXJzID0ge1xuICAgICAgICAndXJscycgOiB1cmxzLFxuICAgICAgICAnY3JlZGVudGlhbCcgOiBwYXNzd29yZCxcbiAgICAgICAgJ3VzZXJuYW1lJyA6IHVzZXJuYW1lXG4gICAgICB9O1xuICAgIH0gZWxzZSB7XG4gICAgICBmb3IgKHZhciBpID0gMDsgaSA8IHVybHMubGVuZ3RoOyBpKyspIHtcbiAgICAgICAgdmFyIGljZVNlcnZlciA9IGNyZWF0ZUljZVNlcnZlcih1cmxzW2ldLCB1c2VybmFtZSwgcGFzc3dvcmQpO1xuICAgICAgICBpZiAoaWNlU2VydmVyICE9PSBudWxsKSB7XG4gICAgICAgICAgaWNlU2VydmVycy5wdXNoKGljZVNlcnZlcik7XG4gICAgICAgIH1cbiAgICAgIH1cbiAgICB9XG4gICAgcmV0dXJuIGljZVNlcnZlcnM7XG4gIH07XG5cbiAgUlRDUGVlckNvbm5lY3Rpb24gPSBmdW5jdGlvbiAocGNDb25maWcsIHBjQ29uc3RyYWludHMpIHtcbiAgICBpZiAod2VicnRjRGV0ZWN0ZWRWZXJzaW9uIDwgMzQpIHtcbiAgICAgIEFkYXB0ZXJKUy5tYXliZUZpeENvbmZpZ3VyYXRpb24ocGNDb25maWcpO1xuICAgIH1cbiAgICByZXR1cm4gbmV3IHdlYmtpdFJUQ1BlZXJDb25uZWN0aW9uKHBjQ29uZmlnLCBwY0NvbnN0cmFpbnRzKTtcbiAgfTtcblxuICB3aW5kb3cuZ2V0VXNlck1lZGlhID0gbmF2aWdhdG9yLndlYmtpdEdldFVzZXJNZWRpYS5iaW5kKG5hdmlnYXRvcik7XG4gIG5hdmlnYXRvci5nZXRVc2VyTWVkaWEgPSB3aW5kb3cuZ2V0VXNlck1lZGlhO1xuXG4gIGF0dGFjaE1lZGlhU3RyZWFtID0gZnVuY3Rpb24gKGVsZW1lbnQsIHN0cmVhbSkge1xuICAgIGlmICh0eXBlb2YgZWxlbWVudC5zcmNPYmplY3QgIT09ICd1bmRlZmluZWQnKSB7XG4gICAgICBlbGVtZW50LnNyY09iamVjdCA9IHN0cmVhbTtcbiAgICB9IGVsc2UgaWYgKHR5cGVvZiBlbGVtZW50Lm1velNyY09iamVjdCAhPT0gJ3VuZGVmaW5lZCcpIHtcbiAgICAgIGVsZW1lbnQubW96U3JjT2JqZWN0ID0gc3RyZWFtO1xuICAgIH0gZWxzZSBpZiAodHlwZW9mIGVsZW1lbnQuc3JjICE9PSAndW5kZWZpbmVkJykge1xuICAgICAgZWxlbWVudC5zcmMgPSAoc3RyZWFtID09PSBudWxsID8gJycgOiBVUkwuY3JlYXRlT2JqZWN0VVJMKHN0cmVhbSkpO1xuICAgIH0gZWxzZSB7XG4gICAgICBjb25zb2xlLmxvZygnRXJyb3IgYXR0YWNoaW5nIHN0cmVhbSB0byBlbGVtZW50LicpO1xuICAgIH1cbiAgICByZXR1cm4gZWxlbWVudDtcbiAgfTtcblxuICByZWF0dGFjaE1lZGlhU3RyZWFtID0gZnVuY3Rpb24gKHRvLCBmcm9tKSB7XG4gICAgdG8uc3JjID0gZnJvbS5zcmM7XG4gICAgcmV0dXJuIHRvO1xuICB9O1xuXG4gIEFkYXB0ZXJKUy5tYXliZVRocm91Z2hXZWJSVENSZWFkeSgpO1xufSBlbHNlIGlmIChuYXZpZ2F0b3IubWVkaWFEZXZpY2VzICYmIG5hdmlnYXRvci51c2VyQWdlbnQubWF0Y2goXG4gICAgL0VkZ2VcXC8oXFxkKykuKFxcZCspJC8pKSB7XG4gIHdlYnJ0Y0RldGVjdGVkQnJvd3NlciA9ICdlZGdlJztcblxuICB3ZWJydGNEZXRlY3RlZFZlcnNpb24gPVxuICAgIHBhcnNlSW50KG5hdmlnYXRvci51c2VyQWdlbnQubWF0Y2goL0VkZ2VcXC8oXFxkKykuKFxcZCspJC8pWzJdLCAxMCk7XG5cbiAgLy8gdGhlIG1pbmltdW0gdmVyc2lvbiBzdGlsbCBzdXBwb3J0ZWQgYnkgYWRhcHRlci5cbiAgd2VicnRjTWluaW11bVZlcnNpb24gPSAxMjtcblxuICB3aW5kb3cuZ2V0VXNlck1lZGlhID0gbmF2aWdhdG9yLmdldFVzZXJNZWRpYS5iaW5kKG5hdmlnYXRvcik7XG5cbiAgYXR0YWNoTWVkaWFTdHJlYW0gPSBmdW5jdGlvbihlbGVtZW50LCBzdHJlYW0pIHtcbiAgICBlbGVtZW50LnNyY09iamVjdCA9IHN0cmVhbTtcbiAgICByZXR1cm4gZWxlbWVudDtcbiAgfTtcbiAgcmVhdHRhY2hNZWRpYVN0cmVhbSA9IGZ1bmN0aW9uKHRvLCBmcm9tKSB7XG4gICAgdG8uc3JjT2JqZWN0ID0gZnJvbS5zcmNPYmplY3Q7XG4gICAgcmV0dXJuIHRvO1xuICB9O1xuXG4gIEFkYXB0ZXJKUy5tYXliZVRocm91Z2hXZWJSVENSZWFkeSgpO1xufSBlbHNlIHsgLy8gVFJZIFRPIFVTRSBQTFVHSU5cbiAgLy8gSUUgOSBpcyBub3Qgb2ZmZXJpbmcgYW4gaW1wbGVtZW50YXRpb24gb2YgY29uc29sZS5sb2cgdW50aWwgeW91IG9wZW4gYSBjb25zb2xlXG4gIGlmICh0eXBlb2YgY29uc29sZSAhPT0gJ29iamVjdCcgfHwgdHlwZW9mIGNvbnNvbGUubG9nICE9PSAnZnVuY3Rpb24nKSB7XG4gICAgLyoganNoaW50IC1XMDIwICovXG4gICAgY29uc29sZSA9IHt9IHx8IGNvbnNvbGU7XG4gICAgLy8gSW1wbGVtZW50ZWQgYmFzZWQgb24gY29uc29sZSBzcGVjcyBmcm9tIE1ETlxuICAgIC8vIFlvdSBtYXkgb3ZlcnJpZGUgdGhlc2UgZnVuY3Rpb25zXG4gICAgY29uc29sZS5sb2cgPSBmdW5jdGlvbiAoYXJnKSB7fTtcbiAgICBjb25zb2xlLmluZm8gPSBmdW5jdGlvbiAoYXJnKSB7fTtcbiAgICBjb25zb2xlLmVycm9yID0gZnVuY3Rpb24gKGFyZykge307XG4gICAgY29uc29sZS5kaXIgPSBmdW5jdGlvbiAoYXJnKSB7fTtcbiAgICBjb25zb2xlLmV4Y2VwdGlvbiA9IGZ1bmN0aW9uIChhcmcpIHt9O1xuICAgIGNvbnNvbGUudHJhY2UgPSBmdW5jdGlvbiAoYXJnKSB7fTtcbiAgICBjb25zb2xlLndhcm4gPSBmdW5jdGlvbiAoYXJnKSB7fTtcbiAgICBjb25zb2xlLmNvdW50ID0gZnVuY3Rpb24gKGFyZykge307XG4gICAgY29uc29sZS5kZWJ1ZyA9IGZ1bmN0aW9uIChhcmcpIHt9O1xuICAgIGNvbnNvbGUuY291bnQgPSBmdW5jdGlvbiAoYXJnKSB7fTtcbiAgICBjb25zb2xlLnRpbWUgPSBmdW5jdGlvbiAoYXJnKSB7fTtcbiAgICBjb25zb2xlLnRpbWVFbmQgPSBmdW5jdGlvbiAoYXJnKSB7fTtcbiAgICBjb25zb2xlLmdyb3VwID0gZnVuY3Rpb24gKGFyZykge307XG4gICAgY29uc29sZS5ncm91cENvbGxhcHNlZCA9IGZ1bmN0aW9uIChhcmcpIHt9O1xuICAgIGNvbnNvbGUuZ3JvdXBFbmQgPSBmdW5jdGlvbiAoYXJnKSB7fTtcbiAgICAvKiBqc2hpbnQgK1cwMjAgKi9cbiAgfVxuICB3ZWJydGNEZXRlY3RlZFR5cGUgPSAncGx1Z2luJztcbiAgd2VicnRjRGV0ZWN0ZWREQ1N1cHBvcnQgPSAncGx1Z2luJztcbiAgQWRhcHRlckpTLnBhcnNlV2VicnRjRGV0ZWN0ZWRCcm93c2VyKCk7XG4gIGlzSUUgPSB3ZWJydGNEZXRlY3RlZEJyb3dzZXIgPT09ICdJRSc7XG5cbiAgLyoganNoaW50IC1XMDM1ICovXG4gIEFkYXB0ZXJKUy5XZWJSVENQbHVnaW4uV2FpdEZvclBsdWdpblJlYWR5ID0gZnVuY3Rpb24oKSB7XG4gICAgd2hpbGUgKEFkYXB0ZXJKUy5XZWJSVENQbHVnaW4ucGx1Z2luU3RhdGUgIT09IEFkYXB0ZXJKUy5XZWJSVENQbHVnaW4uUExVR0lOX1NUQVRFUy5SRUFEWSkge1xuICAgICAgLyogZW1wdHkgYmVjYXVzZSBpdCBuZWVkcyB0byBwcmV2ZW50IHRoZSBmdW5jdGlvbiBmcm9tIHJ1bm5pbmcuICovXG4gICAgfVxuICB9O1xuICAvKiBqc2hpbnQgK1cwMzUgKi9cblxuICBBZGFwdGVySlMuV2ViUlRDUGx1Z2luLmNhbGxXaGVuUGx1Z2luUmVhZHkgPSBmdW5jdGlvbiAoY2FsbGJhY2spIHtcbiAgICBpZiAoQWRhcHRlckpTLldlYlJUQ1BsdWdpbi5wbHVnaW5TdGF0ZSA9PT0gQWRhcHRlckpTLldlYlJUQ1BsdWdpbi5QTFVHSU5fU1RBVEVTLlJFQURZKSB7XG4gICAgICAvLyBDYWxsIGltbWVkaWF0ZWx5IGlmIHBvc3NpYmxlXG4gICAgICAvLyBPbmNlIHRoZSBwbHVnaW4gaXMgc2V0LCB0aGUgY29kZSB3aWxsIGFsd2F5cyB0YWtlIHRoaXMgcGF0aFxuICAgICAgY2FsbGJhY2soKTtcbiAgICB9IGVsc2Uge1xuICAgICAgLy8gb3RoZXJ3aXNlIHN0YXJ0IGEgMTAwbXMgaW50ZXJ2YWxcbiAgICAgIHZhciBjaGVja1BsdWdpblJlYWR5U3RhdGUgPSBzZXRJbnRlcnZhbChmdW5jdGlvbiAoKSB7XG4gICAgICAgIGlmIChBZGFwdGVySlMuV2ViUlRDUGx1Z2luLnBsdWdpblN0YXRlID09PSBBZGFwdGVySlMuV2ViUlRDUGx1Z2luLlBMVUdJTl9TVEFURVMuUkVBRFkpIHtcbiAgICAgICAgICBjbGVhckludGVydmFsKGNoZWNrUGx1Z2luUmVhZHlTdGF0ZSk7XG4gICAgICAgICAgY2FsbGJhY2soKTtcbiAgICAgICAgfVxuICAgICAgfSwgMTAwKTtcbiAgICB9XG4gIH07XG5cbiAgQWRhcHRlckpTLldlYlJUQ1BsdWdpbi5zZXRMb2dMZXZlbCA9IGZ1bmN0aW9uKGxvZ0xldmVsKSB7XG4gICAgQWRhcHRlckpTLldlYlJUQ1BsdWdpbi5jYWxsV2hlblBsdWdpblJlYWR5KGZ1bmN0aW9uKCkge1xuICAgICAgQWRhcHRlckpTLldlYlJUQ1BsdWdpbi5wbHVnaW4uc2V0TG9nTGV2ZWwobG9nTGV2ZWwpO1xuICAgIH0pO1xuICB9O1xuXG4gIEFkYXB0ZXJKUy5XZWJSVENQbHVnaW4uaW5qZWN0UGx1Z2luID0gZnVuY3Rpb24gKCkge1xuICAgIC8vIG9ubHkgaW5qZWN0IG9uY2UgdGhlIHBhZ2UgaXMgcmVhZHlcbiAgICBpZiAoZG9jdW1lbnQucmVhZHlTdGF0ZSAhPT0gJ2NvbXBsZXRlJykge1xuICAgICAgcmV0dXJuO1xuICAgIH1cblxuICAgIC8vIFByZXZlbnQgbXVsdGlwbGUgaW5qZWN0aW9uc1xuICAgIGlmIChBZGFwdGVySlMuV2ViUlRDUGx1Z2luLnBsdWdpblN0YXRlICE9PSBBZGFwdGVySlMuV2ViUlRDUGx1Z2luLlBMVUdJTl9TVEFURVMuSU5JVElBTElaSU5HKSB7XG4gICAgICByZXR1cm47XG4gICAgfVxuXG4gICAgQWRhcHRlckpTLldlYlJUQ1BsdWdpbi5wbHVnaW5TdGF0ZSA9IEFkYXB0ZXJKUy5XZWJSVENQbHVnaW4uUExVR0lOX1NUQVRFUy5JTkpFQ1RJTkc7XG5cbiAgICBpZiAod2VicnRjRGV0ZWN0ZWRCcm93c2VyID09PSAnSUUnICYmIHdlYnJ0Y0RldGVjdGVkVmVyc2lvbiA8PSAxMCkge1xuICAgICAgdmFyIGZyYWcgPSBkb2N1bWVudC5jcmVhdGVEb2N1bWVudEZyYWdtZW50KCk7XG4gICAgICBBZGFwdGVySlMuV2ViUlRDUGx1Z2luLnBsdWdpbiA9IGRvY3VtZW50LmNyZWF0ZUVsZW1lbnQoJ2RpdicpO1xuICAgICAgQWRhcHRlckpTLldlYlJUQ1BsdWdpbi5wbHVnaW4uaW5uZXJIVE1MID0gJzxvYmplY3QgaWQ9XCInICtcbiAgICAgICAgQWRhcHRlckpTLldlYlJUQ1BsdWdpbi5wbHVnaW5JbmZvLnBsdWdpbklkICsgJ1wiIHR5cGU9XCInICtcbiAgICAgICAgQWRhcHRlckpTLldlYlJUQ1BsdWdpbi5wbHVnaW5JbmZvLnR5cGUgKyAnXCIgJyArICd3aWR0aD1cIjFcIiBoZWlnaHQ9XCIxXCI+JyArXG4gICAgICAgICc8cGFyYW0gbmFtZT1cInBsdWdpbklkXCIgdmFsdWU9XCInICtcbiAgICAgICAgQWRhcHRlckpTLldlYlJUQ1BsdWdpbi5wbHVnaW5JbmZvLnBsdWdpbklkICsgJ1wiIC8+ICcgK1xuICAgICAgICAnPHBhcmFtIG5hbWU9XCJ3aW5kb3dsZXNzXCIgdmFsdWU9XCJmYWxzZVwiIC8+ICcgK1xuICAgICAgICAnPHBhcmFtIG5hbWU9XCJwYWdlSWRcIiB2YWx1ZT1cIicgKyBBZGFwdGVySlMuV2ViUlRDUGx1Z2luLnBhZ2VJZCArICdcIiAvPiAnICtcbiAgICAgICAgJzxwYXJhbSBuYW1lPVwib25sb2FkXCIgdmFsdWU9XCInICsgQWRhcHRlckpTLldlYlJUQ1BsdWdpbi5wbHVnaW5JbmZvLm9ubG9hZCArICdcIiAvPicgK1xuICAgICAgICAnPHBhcmFtIG5hbWU9XCJ0YWdcIiB2YWx1ZT1cIicgKyBBZGFwdGVySlMuV2ViUlRDUGx1Z2luLlRBR1MuTk9ORSArICdcIiAvPicgK1xuICAgICAgICAvLyB1bmNvbW1lbnQgdG8gYmUgYWJsZSB0byB1c2UgdmlydHVhbCBjYW1zXG4gICAgICAgIChBZGFwdGVySlMub3B0aW9ucy5nZXRBbGxDYW1zID8gJzxwYXJhbSBuYW1lPVwiZm9yY2VHZXRBbGxDYW1zXCIgdmFsdWU9XCJUcnVlXCIgLz4nOicnKSArXG5cbiAgICAgICAgJzwvb2JqZWN0Pic7XG4gICAgICB3aGlsZSAoQWRhcHRlckpTLldlYlJUQ1BsdWdpbi5wbHVnaW4uZmlyc3RDaGlsZCkge1xuICAgICAgICBmcmFnLmFwcGVuZENoaWxkKEFkYXB0ZXJKUy5XZWJSVENQbHVnaW4ucGx1Z2luLmZpcnN0Q2hpbGQpO1xuICAgICAgfVxuICAgICAgZG9jdW1lbnQuYm9keS5hcHBlbmRDaGlsZChmcmFnKTtcblxuICAgICAgLy8gTmVlZCB0byByZS1mZXRjaCB0aGUgcGx1Z2luXG4gICAgICBBZGFwdGVySlMuV2ViUlRDUGx1Z2luLnBsdWdpbiA9XG4gICAgICAgIGRvY3VtZW50LmdldEVsZW1lbnRCeUlkKEFkYXB0ZXJKUy5XZWJSVENQbHVnaW4ucGx1Z2luSW5mby5wbHVnaW5JZCk7XG4gICAgfSBlbHNlIHtcbiAgICAgIC8vIExvYWQgUGx1Z2luXG4gICAgICBBZGFwdGVySlMuV2ViUlRDUGx1Z2luLnBsdWdpbiA9IGRvY3VtZW50LmNyZWF0ZUVsZW1lbnQoJ29iamVjdCcpO1xuICAgICAgQWRhcHRlckpTLldlYlJUQ1BsdWdpbi5wbHVnaW4uaWQgPVxuICAgICAgICBBZGFwdGVySlMuV2ViUlRDUGx1Z2luLnBsdWdpbkluZm8ucGx1Z2luSWQ7XG4gICAgICAvLyBJRSB3aWxsIG9ubHkgc3RhcnQgdGhlIHBsdWdpbiBpZiBpdCdzIEFDVFVBTExZIHZpc2libGVcbiAgICAgIGlmIChpc0lFKSB7XG4gICAgICAgIEFkYXB0ZXJKUy5XZWJSVENQbHVnaW4ucGx1Z2luLndpZHRoID0gJzFweCc7XG4gICAgICAgIEFkYXB0ZXJKUy5XZWJSVENQbHVnaW4ucGx1Z2luLmhlaWdodCA9ICcxcHgnO1xuICAgICAgfSBlbHNlIHsgLy8gVGhlIHNpemUgb2YgdGhlIHBsdWdpbiBvbiBTYWZhcmkgc2hvdWxkIGJlIDB4MHB4XG4gICAgICAgICAgICAgIC8vIHNvIHRoYXQgdGhlIGF1dG9yaXNhdGlvbiBwcm9tcHQgaXMgYXQgdGhlIHRvcFxuICAgICAgICBBZGFwdGVySlMuV2ViUlRDUGx1Z2luLnBsdWdpbi53aWR0aCA9ICcwcHgnO1xuICAgICAgICBBZGFwdGVySlMuV2ViUlRDUGx1Z2luLnBsdWdpbi5oZWlnaHQgPSAnMHB4JztcbiAgICAgIH1cbiAgICAgIEFkYXB0ZXJKUy5XZWJSVENQbHVnaW4ucGx1Z2luLnR5cGUgPSBBZGFwdGVySlMuV2ViUlRDUGx1Z2luLnBsdWdpbkluZm8udHlwZTtcbiAgICAgIEFkYXB0ZXJKUy5XZWJSVENQbHVnaW4ucGx1Z2luLmlubmVySFRNTCA9ICc8cGFyYW0gbmFtZT1cIm9ubG9hZFwiIHZhbHVlPVwiJyArXG4gICAgICAgIEFkYXB0ZXJKUy5XZWJSVENQbHVnaW4ucGx1Z2luSW5mby5vbmxvYWQgKyAnXCI+JyArXG4gICAgICAgICc8cGFyYW0gbmFtZT1cInBsdWdpbklkXCIgdmFsdWU9XCInICtcbiAgICAgICAgQWRhcHRlckpTLldlYlJUQ1BsdWdpbi5wbHVnaW5JbmZvLnBsdWdpbklkICsgJ1wiPicgK1xuICAgICAgICAnPHBhcmFtIG5hbWU9XCJ3aW5kb3dsZXNzXCIgdmFsdWU9XCJmYWxzZVwiIC8+ICcgK1xuICAgICAgICAoQWRhcHRlckpTLm9wdGlvbnMuZ2V0QWxsQ2FtcyA/ICc8cGFyYW0gbmFtZT1cImZvcmNlR2V0QWxsQ2Ftc1wiIHZhbHVlPVwiVHJ1ZVwiIC8+JzonJykgK1xuICAgICAgICAnPHBhcmFtIG5hbWU9XCJwYWdlSWRcIiB2YWx1ZT1cIicgKyBBZGFwdGVySlMuV2ViUlRDUGx1Z2luLnBhZ2VJZCArICdcIj4nICtcbiAgICAgICAgJzxwYXJhbSBuYW1lPVwidGFnXCIgdmFsdWU9XCInICsgQWRhcHRlckpTLldlYlJUQ1BsdWdpbi5UQUdTLk5PTkUgKyAnXCIgLz4nO1xuICAgICAgZG9jdW1lbnQuYm9keS5hcHBlbmRDaGlsZChBZGFwdGVySlMuV2ViUlRDUGx1Z2luLnBsdWdpbik7XG4gICAgfVxuXG5cbiAgICBBZGFwdGVySlMuV2ViUlRDUGx1Z2luLnBsdWdpblN0YXRlID0gQWRhcHRlckpTLldlYlJUQ1BsdWdpbi5QTFVHSU5fU1RBVEVTLklOSkVDVEVEO1xuICB9O1xuXG4gIEFkYXB0ZXJKUy5XZWJSVENQbHVnaW4uaXNQbHVnaW5JbnN0YWxsZWQgPVxuICAgIGZ1bmN0aW9uIChjb21OYW1lLCBwbHVnTmFtZSwgaW5zdGFsbGVkQ2IsIG5vdEluc3RhbGxlZENiKSB7XG4gICAgaWYgKCFpc0lFKSB7XG4gICAgICB2YXIgcGx1Z2luQXJyYXkgPSBuYXZpZ2F0b3IucGx1Z2lucztcbiAgICAgIGZvciAodmFyIGkgPSAwOyBpIDwgcGx1Z2luQXJyYXkubGVuZ3RoOyBpKyspIHtcbiAgICAgICAgaWYgKHBsdWdpbkFycmF5W2ldLm5hbWUuaW5kZXhPZihwbHVnTmFtZSkgPj0gMCkge1xuICAgICAgICAgIGluc3RhbGxlZENiKCk7XG4gICAgICAgICAgcmV0dXJuO1xuICAgICAgICB9XG4gICAgICB9XG4gICAgICBub3RJbnN0YWxsZWRDYigpO1xuICAgIH0gZWxzZSB7XG4gICAgICB0cnkge1xuICAgICAgICB2YXIgYXhvID0gbmV3IEFjdGl2ZVhPYmplY3QoY29tTmFtZSArICcuJyArIHBsdWdOYW1lKTtcbiAgICAgIH0gY2F0Y2ggKGUpIHtcbiAgICAgICAgbm90SW5zdGFsbGVkQ2IoKTtcbiAgICAgICAgcmV0dXJuO1xuICAgICAgfVxuICAgICAgaW5zdGFsbGVkQ2IoKTtcbiAgICB9XG4gIH07XG5cbiAgQWRhcHRlckpTLldlYlJUQ1BsdWdpbi5kZWZpbmVXZWJSVENJbnRlcmZhY2UgPSBmdW5jdGlvbiAoKSB7XG4gICAgaWYgKEFkYXB0ZXJKUy5XZWJSVENQbHVnaW4ucGx1Z2luU3RhdGUgPT09XG4gICAgICAgIEFkYXB0ZXJKUy5XZWJSVENQbHVnaW4uUExVR0lOX1NUQVRFUy5SRUFEWSkge1xuICAgICAgY29uc29sZS5lcnJvcihcIkFkYXB0ZXJKUyAtIFdlYlJUQyBpbnRlcmZhY2UgaGFzIGFscmVhZHkgYmVlbiBkZWZpbmVkXCIpO1xuICAgICAgcmV0dXJuO1xuICAgIH1cblxuICAgIEFkYXB0ZXJKUy5XZWJSVENQbHVnaW4ucGx1Z2luU3RhdGUgPSBBZGFwdGVySlMuV2ViUlRDUGx1Z2luLlBMVUdJTl9TVEFURVMuSU5JVElBTElaSU5HO1xuXG4gICAgQWRhcHRlckpTLmlzRGVmaW5lZCA9IGZ1bmN0aW9uICh2YXJpYWJsZSkge1xuICAgICAgcmV0dXJuIHZhcmlhYmxlICE9PSBudWxsICYmIHZhcmlhYmxlICE9PSB1bmRlZmluZWQ7XG4gICAgfTtcblxuICAgIGNyZWF0ZUljZVNlcnZlciA9IGZ1bmN0aW9uICh1cmwsIHVzZXJuYW1lLCBwYXNzd29yZCkge1xuICAgICAgdmFyIGljZVNlcnZlciA9IG51bGw7XG4gICAgICB2YXIgdXJsX3BhcnRzID0gdXJsLnNwbGl0KCc6Jyk7XG4gICAgICBpZiAodXJsX3BhcnRzWzBdLmluZGV4T2YoJ3N0dW4nKSA9PT0gMCkge1xuICAgICAgICBpY2VTZXJ2ZXIgPSB7XG4gICAgICAgICAgJ3VybCcgOiB1cmwsXG4gICAgICAgICAgJ2hhc0NyZWRlbnRpYWxzJyA6IGZhbHNlXG4gICAgICAgIH07XG4gICAgICB9IGVsc2UgaWYgKHVybF9wYXJ0c1swXS5pbmRleE9mKCd0dXJuJykgPT09IDApIHtcbiAgICAgICAgaWNlU2VydmVyID0ge1xuICAgICAgICAgICd1cmwnIDogdXJsLFxuICAgICAgICAgICdoYXNDcmVkZW50aWFscycgOiB0cnVlLFxuICAgICAgICAgICdjcmVkZW50aWFsJyA6IHBhc3N3b3JkLFxuICAgICAgICAgICd1c2VybmFtZScgOiB1c2VybmFtZVxuICAgICAgICB9O1xuICAgICAgfVxuICAgICAgcmV0dXJuIGljZVNlcnZlcjtcbiAgICB9O1xuXG4gICAgY3JlYXRlSWNlU2VydmVycyA9IGZ1bmN0aW9uICh1cmxzLCB1c2VybmFtZSwgcGFzc3dvcmQpIHtcbiAgICAgIHZhciBpY2VTZXJ2ZXJzID0gW107XG4gICAgICBmb3IgKHZhciBpID0gMDsgaSA8IHVybHMubGVuZ3RoOyArK2kpIHtcbiAgICAgICAgaWNlU2VydmVycy5wdXNoKGNyZWF0ZUljZVNlcnZlcih1cmxzW2ldLCB1c2VybmFtZSwgcGFzc3dvcmQpKTtcbiAgICAgIH1cbiAgICAgIHJldHVybiBpY2VTZXJ2ZXJzO1xuICAgIH07XG5cbiAgICBSVENTZXNzaW9uRGVzY3JpcHRpb24gPSBmdW5jdGlvbiAoaW5mbykge1xuICAgICAgQWRhcHRlckpTLldlYlJUQ1BsdWdpbi5XYWl0Rm9yUGx1Z2luUmVhZHkoKTtcbiAgICAgIHJldHVybiBBZGFwdGVySlMuV2ViUlRDUGx1Z2luLnBsdWdpbi5cbiAgICAgICAgQ29uc3RydWN0U2Vzc2lvbkRlc2NyaXB0aW9uKGluZm8udHlwZSwgaW5mby5zZHApO1xuICAgIH07XG5cbiAgICBSVENQZWVyQ29ubmVjdGlvbiA9IGZ1bmN0aW9uIChzZXJ2ZXJzLCBjb25zdHJhaW50cykge1xuICAgICAgdmFyIGljZVNlcnZlcnMgPSBudWxsO1xuICAgICAgaWYgKHNlcnZlcnMpIHtcbiAgICAgICAgaWNlU2VydmVycyA9IHNlcnZlcnMuaWNlU2VydmVycztcbiAgICAgICAgZm9yICh2YXIgaSA9IDA7IGkgPCBpY2VTZXJ2ZXJzLmxlbmd0aDsgaSsrKSB7XG4gICAgICAgICAgaWYgKGljZVNlcnZlcnNbaV0udXJscyAmJiAhaWNlU2VydmVyc1tpXS51cmwpIHtcbiAgICAgICAgICAgIGljZVNlcnZlcnNbaV0udXJsID0gaWNlU2VydmVyc1tpXS51cmxzO1xuICAgICAgICAgIH1cbiAgICAgICAgICBpY2VTZXJ2ZXJzW2ldLmhhc0NyZWRlbnRpYWxzID0gQWRhcHRlckpTLlxuICAgICAgICAgICAgaXNEZWZpbmVkKGljZVNlcnZlcnNbaV0udXNlcm5hbWUpICYmXG4gICAgICAgICAgICBBZGFwdGVySlMuaXNEZWZpbmVkKGljZVNlcnZlcnNbaV0uY3JlZGVudGlhbCk7XG4gICAgICAgIH1cbiAgICAgIH1cbiAgICAgIHZhciBtYW5kYXRvcnkgPSAoY29uc3RyYWludHMgJiYgY29uc3RyYWludHMubWFuZGF0b3J5KSA/XG4gICAgICAgIGNvbnN0cmFpbnRzLm1hbmRhdG9yeSA6IG51bGw7XG4gICAgICB2YXIgb3B0aW9uYWwgPSAoY29uc3RyYWludHMgJiYgY29uc3RyYWludHMub3B0aW9uYWwpID9cbiAgICAgICAgY29uc3RyYWludHMub3B0aW9uYWwgOiBudWxsO1xuXG4gICAgICBBZGFwdGVySlMuV2ViUlRDUGx1Z2luLldhaXRGb3JQbHVnaW5SZWFkeSgpO1xuICAgICAgcmV0dXJuIEFkYXB0ZXJKUy5XZWJSVENQbHVnaW4ucGx1Z2luLlxuICAgICAgICBQZWVyQ29ubmVjdGlvbihBZGFwdGVySlMuV2ViUlRDUGx1Z2luLnBhZ2VJZCxcbiAgICAgICAgaWNlU2VydmVycywgbWFuZGF0b3J5LCBvcHRpb25hbCk7XG4gICAgfTtcblxuICAgIE1lZGlhU3RyZWFtVHJhY2sgPSB7fTtcbiAgICBNZWRpYVN0cmVhbVRyYWNrLmdldFNvdXJjZXMgPSBmdW5jdGlvbiAoY2FsbGJhY2spIHtcbiAgICAgIEFkYXB0ZXJKUy5XZWJSVENQbHVnaW4uY2FsbFdoZW5QbHVnaW5SZWFkeShmdW5jdGlvbigpIHtcbiAgICAgICAgQWRhcHRlckpTLldlYlJUQ1BsdWdpbi5wbHVnaW4uR2V0U291cmNlcyhjYWxsYmFjayk7XG4gICAgICB9KTtcbiAgICB9O1xuXG4gICAgd2luZG93LmdldFVzZXJNZWRpYSA9IGZ1bmN0aW9uIChjb25zdHJhaW50cywgc3VjY2Vzc0NhbGxiYWNrLCBmYWlsdXJlQ2FsbGJhY2spIHtcbiAgICAgIGNvbnN0cmFpbnRzLmF1ZGlvID0gY29uc3RyYWludHMuYXVkaW8gfHwgZmFsc2U7XG4gICAgICBjb25zdHJhaW50cy52aWRlbyA9IGNvbnN0cmFpbnRzLnZpZGVvIHx8IGZhbHNlO1xuXG4gICAgICBBZGFwdGVySlMuV2ViUlRDUGx1Z2luLmNhbGxXaGVuUGx1Z2luUmVhZHkoZnVuY3Rpb24oKSB7XG4gICAgICAgIEFkYXB0ZXJKUy5XZWJSVENQbHVnaW4ucGx1Z2luLlxuICAgICAgICAgIGdldFVzZXJNZWRpYShjb25zdHJhaW50cywgc3VjY2Vzc0NhbGxiYWNrLCBmYWlsdXJlQ2FsbGJhY2spO1xuICAgICAgfSk7XG4gICAgfTtcbiAgICB3aW5kb3cubmF2aWdhdG9yLmdldFVzZXJNZWRpYSA9IHdpbmRvdy5nZXRVc2VyTWVkaWE7XG5cbiAgICBhdHRhY2hNZWRpYVN0cmVhbSA9IGZ1bmN0aW9uIChlbGVtZW50LCBzdHJlYW0pIHtcbiAgICAgIGlmICghZWxlbWVudCB8fCAhZWxlbWVudC5wYXJlbnROb2RlKSB7XG4gICAgICAgIHJldHVybjtcbiAgICAgIH1cblxuICAgICAgdmFyIHN0cmVhbUlkO1xuICAgICAgaWYgKHN0cmVhbSA9PT0gbnVsbCkge1xuICAgICAgICBzdHJlYW1JZCA9ICcnO1xuICAgICAgfSBlbHNlIHtcbiAgICAgICAgaWYgKHR5cGVvZiBzdHJlYW0uZW5hYmxlU291bmRUcmFja3MgIT09ICd1bmRlZmluZWQnKSB7XG4gICAgICAgICAgc3RyZWFtLmVuYWJsZVNvdW5kVHJhY2tzKHRydWUpO1xuICAgICAgICB9XG4gICAgICAgIHN0cmVhbUlkID0gc3RyZWFtLmlkO1xuICAgICAgfVxuXG4gICAgICB2YXIgZWxlbWVudElkID0gZWxlbWVudC5pZC5sZW5ndGggPT09IDAgPyBNYXRoLnJhbmRvbSgpLnRvU3RyaW5nKDM2KS5zbGljZSgyKSA6IGVsZW1lbnQuaWQ7XG4gICAgICB2YXIgbm9kZU5hbWUgPSBlbGVtZW50Lm5vZGVOYW1lLnRvTG93ZXJDYXNlKCk7XG4gICAgICBpZiAobm9kZU5hbWUgIT09ICdvYmplY3QnKSB7IC8vIG5vdCBhIHBsdWdpbiA8b2JqZWN0PiB0YWcgeWV0XG4gICAgICAgIHZhciB0YWc7XG4gICAgICAgIHN3aXRjaChub2RlTmFtZSkge1xuICAgICAgICAgIGNhc2UgJ2F1ZGlvJzpcbiAgICAgICAgICAgIHRhZyA9IEFkYXB0ZXJKUy5XZWJSVENQbHVnaW4uVEFHUy5BVURJTztcbiAgICAgICAgICAgIGJyZWFrO1xuICAgICAgICAgIGNhc2UgJ3ZpZGVvJzpcbiAgICAgICAgICAgIHRhZyA9IEFkYXB0ZXJKUy5XZWJSVENQbHVnaW4uVEFHUy5WSURFTztcbiAgICAgICAgICAgIGJyZWFrO1xuICAgICAgICAgIGRlZmF1bHQ6XG4gICAgICAgICAgICB0YWcgPSBBZGFwdGVySlMuV2ViUlRDUGx1Z2luLlRBR1MuTk9ORTtcbiAgICAgICAgICB9XG5cbiAgICAgICAgdmFyIGZyYWcgPSBkb2N1bWVudC5jcmVhdGVEb2N1bWVudEZyYWdtZW50KCk7XG4gICAgICAgIHZhciB0ZW1wID0gZG9jdW1lbnQuY3JlYXRlRWxlbWVudCgnZGl2Jyk7XG4gICAgICAgIHZhciBjbGFzc0hUTUwgPSAnJztcbiAgICAgICAgaWYgKGVsZW1lbnQuY2xhc3NOYW1lKSB7XG4gICAgICAgICAgY2xhc3NIVE1MID0gJ2NsYXNzPVwiJyArIGVsZW1lbnQuY2xhc3NOYW1lICsgJ1wiICc7XG4gICAgICAgIH0gZWxzZSBpZiAoZWxlbWVudC5hdHRyaWJ1dGVzICYmIGVsZW1lbnQuYXR0cmlidXRlc1snY2xhc3MnXSkge1xuICAgICAgICAgIGNsYXNzSFRNTCA9ICdjbGFzcz1cIicgKyBlbGVtZW50LmF0dHJpYnV0ZXNbJ2NsYXNzJ10udmFsdWUgKyAnXCIgJztcbiAgICAgICAgfVxuXG4gICAgICAgIHRlbXAuaW5uZXJIVE1MID0gJzxvYmplY3QgaWQ9XCInICsgZWxlbWVudElkICsgJ1wiICcgKyBjbGFzc0hUTUwgK1xuICAgICAgICAgICd0eXBlPVwiJyArIEFkYXB0ZXJKUy5XZWJSVENQbHVnaW4ucGx1Z2luSW5mby50eXBlICsgJ1wiPicgK1xuICAgICAgICAgICc8cGFyYW0gbmFtZT1cInBsdWdpbklkXCIgdmFsdWU9XCInICsgZWxlbWVudElkICsgJ1wiIC8+ICcgK1xuICAgICAgICAgICc8cGFyYW0gbmFtZT1cInBhZ2VJZFwiIHZhbHVlPVwiJyArIEFkYXB0ZXJKUy5XZWJSVENQbHVnaW4ucGFnZUlkICsgJ1wiIC8+ICcgK1xuICAgICAgICAgICc8cGFyYW0gbmFtZT1cIndpbmRvd2xlc3NcIiB2YWx1ZT1cInRydWVcIiAvPiAnICtcbiAgICAgICAgICAnPHBhcmFtIG5hbWU9XCJzdHJlYW1JZFwiIHZhbHVlPVwiJyArIHN0cmVhbUlkICsgJ1wiIC8+ICcgK1xuICAgICAgICAgICc8cGFyYW0gbmFtZT1cInRhZ1wiIHZhbHVlPVwiJyArIHRhZyArICdcIiAvPiAnICtcbiAgICAgICAgICAnPC9vYmplY3Q+JztcbiAgICAgICAgd2hpbGUgKHRlbXAuZmlyc3RDaGlsZCkge1xuICAgICAgICAgIGZyYWcuYXBwZW5kQ2hpbGQodGVtcC5maXJzdENoaWxkKTtcbiAgICAgICAgfVxuXG4gICAgICAgIHZhciBoZWlnaHQgPSAnJztcbiAgICAgICAgdmFyIHdpZHRoID0gJyc7XG4gICAgICAgIGlmIChlbGVtZW50LmNsaWVudFdpZHRoIHx8IGVsZW1lbnQuY2xpZW50SGVpZ2h0KSB7XG4gICAgICAgICAgd2lkdGggPSBlbGVtZW50LmNsaWVudFdpZHRoO1xuICAgICAgICAgIGhlaWdodCA9IGVsZW1lbnQuY2xpZW50SGVpZ2h0O1xuICAgICAgICB9XG4gICAgICAgIGVsc2UgaWYgKGVsZW1lbnQud2lkdGggfHwgZWxlbWVudC5oZWlnaHQpIHtcbiAgICAgICAgICB3aWR0aCA9IGVsZW1lbnQud2lkdGg7XG4gICAgICAgICAgaGVpZ2h0ID0gZWxlbWVudC5oZWlnaHQ7XG4gICAgICAgIH1cblxuICAgICAgICBlbGVtZW50LnBhcmVudE5vZGUuaW5zZXJ0QmVmb3JlKGZyYWcsIGVsZW1lbnQpO1xuICAgICAgICBmcmFnID0gZG9jdW1lbnQuZ2V0RWxlbWVudEJ5SWQoZWxlbWVudElkKTtcbiAgICAgICAgZnJhZy53aWR0aCA9IHdpZHRoO1xuICAgICAgICBmcmFnLmhlaWdodCA9IGhlaWdodDtcbiAgICAgICAgZWxlbWVudC5wYXJlbnROb2RlLnJlbW92ZUNoaWxkKGVsZW1lbnQpO1xuICAgICAgfSBlbHNlIHsgLy8gYWxyZWFkeSBhbiA8b2JqZWN0PiB0YWcsIGp1c3QgY2hhbmdlIHRoZSBzdHJlYW0gaWRcbiAgICAgICAgdmFyIGNoaWxkcmVuID0gZWxlbWVudC5jaGlsZHJlbjtcbiAgICAgICAgZm9yICh2YXIgaSA9IDA7IGkgIT09IGNoaWxkcmVuLmxlbmd0aDsgKytpKSB7XG4gICAgICAgICAgaWYgKGNoaWxkcmVuW2ldLm5hbWUgPT09ICdzdHJlYW1JZCcpIHtcbiAgICAgICAgICAgIGNoaWxkcmVuW2ldLnZhbHVlID0gc3RyZWFtSWQ7XG4gICAgICAgICAgICBicmVhaztcbiAgICAgICAgICB9XG4gICAgICAgIH1cbiAgICAgICAgZWxlbWVudC5zZXRTdHJlYW1JZChzdHJlYW1JZCk7XG4gICAgICB9XG4gICAgICB2YXIgbmV3RWxlbWVudCA9IGRvY3VtZW50LmdldEVsZW1lbnRCeUlkKGVsZW1lbnRJZCk7XG4gICAgICBBZGFwdGVySlMuZm9yd2FyZEV2ZW50SGFuZGxlcnMobmV3RWxlbWVudCwgZWxlbWVudCwgT2JqZWN0LmdldFByb3RvdHlwZU9mKGVsZW1lbnQpKTtcblxuICAgICAgcmV0dXJuIG5ld0VsZW1lbnQ7XG4gICAgfTtcblxuICAgIHJlYXR0YWNoTWVkaWFTdHJlYW0gPSBmdW5jdGlvbiAodG8sIGZyb20pIHtcbiAgICAgIHZhciBzdHJlYW0gPSBudWxsO1xuICAgICAgdmFyIGNoaWxkcmVuID0gZnJvbS5jaGlsZHJlbjtcbiAgICAgIGZvciAodmFyIGkgPSAwOyBpICE9PSBjaGlsZHJlbi5sZW5ndGg7ICsraSkge1xuICAgICAgICBpZiAoY2hpbGRyZW5baV0ubmFtZSA9PT0gJ3N0cmVhbUlkJykge1xuICAgICAgICAgIEFkYXB0ZXJKUy5XZWJSVENQbHVnaW4uV2FpdEZvclBsdWdpblJlYWR5KCk7XG4gICAgICAgICAgc3RyZWFtID0gQWRhcHRlckpTLldlYlJUQ1BsdWdpbi5wbHVnaW5cbiAgICAgICAgICAgIC5nZXRTdHJlYW1XaXRoSWQoQWRhcHRlckpTLldlYlJUQ1BsdWdpbi5wYWdlSWQsIGNoaWxkcmVuW2ldLnZhbHVlKTtcbiAgICAgICAgICBicmVhaztcbiAgICAgICAgfVxuICAgICAgfVxuICAgICAgaWYgKHN0cmVhbSAhPT0gbnVsbCkge1xuICAgICAgICByZXR1cm4gYXR0YWNoTWVkaWFTdHJlYW0odG8sIHN0cmVhbSk7XG4gICAgICB9IGVsc2Uge1xuICAgICAgICBjb25zb2xlLmxvZygnQ291bGQgbm90IGZpbmQgdGhlIHN0cmVhbSBhc3NvY2lhdGVkIHdpdGggdGhpcyBlbGVtZW50Jyk7XG4gICAgICB9XG4gICAgfTtcblxuICAgIEFkYXB0ZXJKUy5mb3J3YXJkRXZlbnRIYW5kbGVycyA9IGZ1bmN0aW9uIChkZXN0RWxlbSwgc3JjRWxlbSwgcHJvdG90eXBlKSB7XG5cbiAgICAgIHByb3BlcnRpZXMgPSBPYmplY3QuZ2V0T3duUHJvcGVydHlOYW1lcyggcHJvdG90eXBlICk7XG5cbiAgICAgIGZvcihwcm9wIGluIHByb3BlcnRpZXMpIHtcbiAgICAgICAgcHJvcE5hbWUgPSBwcm9wZXJ0aWVzW3Byb3BdO1xuXG4gICAgICAgIGlmICh0eXBlb2YocHJvcE5hbWUuc2xpY2UpID09PSAnZnVuY3Rpb24nKSB7XG4gICAgICAgICAgaWYgKHByb3BOYW1lLnNsaWNlKDAsMikgPT0gJ29uJyAmJiBzcmNFbGVtW3Byb3BOYW1lXSAhPSBudWxsKSB7XG4gICAgICAgICAgICBpZiAoaXNJRSkge1xuICAgICAgICAgICAgICBkZXN0RWxlbS5hdHRhY2hFdmVudChwcm9wTmFtZSxzcmNFbGVtW3Byb3BOYW1lXSk7XG4gICAgICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgICBkZXN0RWxlbS5hZGRFdmVudExpc3RlbmVyKHByb3BOYW1lLnNsaWNlKDIpLCBzcmNFbGVtW3Byb3BOYW1lXSwgZmFsc2UpXG4gICAgICAgICAgICB9XG4gICAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgIC8vVE9ETyAoaHR0cDovL2ppcmEudGVtYXN5cy5jb20uc2cvYnJvd3NlL1RXUC0zMjgpIEZvcndhcmQgbm9uLWV2ZW50IHByb3BlcnRpZXMgP1xuICAgICAgICAgIH1cbiAgICAgICAgfVxuICAgICAgfVxuXG4gICAgICB2YXIgc3ViUHJvdG90eXBlID0gT2JqZWN0LmdldFByb3RvdHlwZU9mKHByb3RvdHlwZSlcbiAgICAgIGlmKHN1YlByb3RvdHlwZSAhPSBudWxsKSB7XG4gICAgICAgIEFkYXB0ZXJKUy5mb3J3YXJkRXZlbnRIYW5kbGVycyhkZXN0RWxlbSwgc3JjRWxlbSwgc3ViUHJvdG90eXBlKTtcbiAgICAgIH1cbiAgICB9XG5cbiAgICBSVENJY2VDYW5kaWRhdGUgPSBmdW5jdGlvbiAoY2FuZGlkYXRlKSB7XG4gICAgICBpZiAoIWNhbmRpZGF0ZS5zZHBNaWQpIHtcbiAgICAgICAgY2FuZGlkYXRlLnNkcE1pZCA9ICcnO1xuICAgICAgfVxuXG4gICAgICBBZGFwdGVySlMuV2ViUlRDUGx1Z2luLldhaXRGb3JQbHVnaW5SZWFkeSgpO1xuICAgICAgcmV0dXJuIEFkYXB0ZXJKUy5XZWJSVENQbHVnaW4ucGx1Z2luLkNvbnN0cnVjdEljZUNhbmRpZGF0ZShcbiAgICAgICAgY2FuZGlkYXRlLnNkcE1pZCwgY2FuZGlkYXRlLnNkcE1MaW5lSW5kZXgsIGNhbmRpZGF0ZS5jYW5kaWRhdGVcbiAgICAgICk7XG4gICAgfTtcblxuICAgIC8vIGluamVjdCBwbHVnaW5cbiAgICBBZGFwdGVySlMuYWRkRXZlbnQoZG9jdW1lbnQsICdyZWFkeXN0YXRlY2hhbmdlJywgQWRhcHRlckpTLldlYlJUQ1BsdWdpbi5pbmplY3RQbHVnaW4pO1xuICAgIEFkYXB0ZXJKUy5XZWJSVENQbHVnaW4uaW5qZWN0UGx1Z2luKCk7XG4gIH07XG5cbiAgLy8gVGhpcyBmdW5jdGlvbiB3aWxsIGJlIGNhbGxlZCBpZiB0aGUgcGx1Z2luIGlzIG5lZWRlZCAoYnJvd3NlciBkaWZmZXJlbnRcbiAgLy8gZnJvbSBDaHJvbWUgb3IgRmlyZWZveCksIGJ1dCB0aGUgcGx1Z2luIGlzIG5vdCBpbnN0YWxsZWQuXG4gIEFkYXB0ZXJKUy5XZWJSVENQbHVnaW4ucGx1Z2luTmVlZGVkQnV0Tm90SW5zdGFsbGVkQ2IgPSBBZGFwdGVySlMuV2ViUlRDUGx1Z2luLnBsdWdpbk5lZWRlZEJ1dE5vdEluc3RhbGxlZENiIHx8XG4gICAgZnVuY3Rpb24oKSB7XG4gICAgICBBZGFwdGVySlMuYWRkRXZlbnQoZG9jdW1lbnQsXG4gICAgICAgICAgICAgICAgICAgICAgICAncmVhZHlzdGF0ZWNoYW5nZScsXG4gICAgICAgICAgICAgICAgICAgICAgICAgQWRhcHRlckpTLldlYlJUQ1BsdWdpbi5wbHVnaW5OZWVkZWRCdXROb3RJbnN0YWxsZWRDYlByaXYpO1xuICAgICAgQWRhcHRlckpTLldlYlJUQ1BsdWdpbi5wbHVnaW5OZWVkZWRCdXROb3RJbnN0YWxsZWRDYlByaXYoKTtcbiAgICB9O1xuXG4gIEFkYXB0ZXJKUy5XZWJSVENQbHVnaW4ucGx1Z2luTmVlZGVkQnV0Tm90SW5zdGFsbGVkQ2JQcml2ID0gZnVuY3Rpb24gKCkge1xuICAgIGlmIChBZGFwdGVySlMub3B0aW9ucy5oaWRlUGx1Z2luSW5zdGFsbFByb21wdCkge1xuICAgICAgcmV0dXJuO1xuICAgIH1cblxuICAgIHZhciBkb3dubG9hZExpbmsgPSBBZGFwdGVySlMuV2ViUlRDUGx1Z2luLnBsdWdpbkluZm8uZG93bmxvYWRMaW5rO1xuICAgIGlmKGRvd25sb2FkTGluaykgeyAvLyBpZiBkb3dubG9hZCBsaW5rXG4gICAgICB2YXIgcG9wdXBTdHJpbmc7XG4gICAgICBpZiAoQWRhcHRlckpTLldlYlJUQ1BsdWdpbi5wbHVnaW5JbmZvLnBvcnRhbExpbmspIHsgLy8gaXMgcG9ydGFsIGxpbmtcbiAgICAgICBwb3B1cFN0cmluZyA9ICdUaGlzIHdlYnNpdGUgcmVxdWlyZXMgeW91IHRvIGluc3RhbGwgdGhlICcgK1xuICAgICAgICAnIDxhIGhyZWY9XCInICsgQWRhcHRlckpTLldlYlJUQ1BsdWdpbi5wbHVnaW5JbmZvLnBvcnRhbExpbmsgK1xuICAgICAgICAnXCIgdGFyZ2V0PVwiX2JsYW5rXCI+JyArIEFkYXB0ZXJKUy5XZWJSVENQbHVnaW4ucGx1Z2luSW5mby5jb21wYW55TmFtZSArXG4gICAgICAgICcgV2ViUlRDIFBsdWdpbjwvYT4nICtcbiAgICAgICAgJyB0byB3b3JrIG9uIHRoaXMgYnJvd3Nlci4nO1xuICAgICAgfSBlbHNlIHsgLy8gbm8gcG9ydGFsIGxpbmssIGp1c3QgcHJpbnQgYSBnZW5lcmljIGV4cGxhbmF0aW9uXG4gICAgICAgcG9wdXBTdHJpbmcgPSBBZGFwdGVySlMuVEVYVC5QTFVHSU4uUkVRVUlSRV9JTlNUQUxMQVRJT047XG4gICAgICB9XG5cbiAgICAgIEFkYXB0ZXJKUy5yZW5kZXJOb3RpZmljYXRpb25CYXIocG9wdXBTdHJpbmcsIEFkYXB0ZXJKUy5URVhULlBMVUdJTi5CVVRUT04sIGRvd25sb2FkTGluayk7XG4gICAgfSBlbHNlIHsgLy8gbm8gZG93bmxvYWQgbGluaywganVzdCBwcmludCBhIGdlbmVyaWMgZXhwbGFuYXRpb25cbiAgICAgIEFkYXB0ZXJKUy5yZW5kZXJOb3RpZmljYXRpb25CYXIoQWRhcHRlckpTLlRFWFQuUExVR0lOLk5PVF9TVVBQT1JURUQpO1xuICAgIH1cbiAgfTtcblxuICAvLyBUcnkgdG8gZGV0ZWN0IHRoZSBwbHVnaW4gYW5kIGFjdCBhY2NvcmRpbmdseVxuICBBZGFwdGVySlMuV2ViUlRDUGx1Z2luLmlzUGx1Z2luSW5zdGFsbGVkKFxuICAgIEFkYXB0ZXJKUy5XZWJSVENQbHVnaW4ucGx1Z2luSW5mby5wcmVmaXgsXG4gICAgQWRhcHRlckpTLldlYlJUQ1BsdWdpbi5wbHVnaW5JbmZvLnBsdWdOYW1lLFxuICAgIEFkYXB0ZXJKUy5XZWJSVENQbHVnaW4uZGVmaW5lV2ViUlRDSW50ZXJmYWNlLFxuICAgIEFkYXB0ZXJKUy5XZWJSVENQbHVnaW4ucGx1Z2luTmVlZGVkQnV0Tm90SW5zdGFsbGVkQ2IpO1xufVxuIiwiXG52YXIgbG9nZ2VyID0gcmVxdWlyZShcImppdHNpLW1lZXQtbG9nZ2VyXCIpLmdldExvZ2dlcihfX2ZpbGVuYW1lKTtcbmZ1bmN0aW9uIHN1cHBvcnRzTG9jYWxTdG9yYWdlKCkge1xuICAgIHRyeSB7XG4gICAgICAgIHJldHVybiAnbG9jYWxTdG9yYWdlJyBpbiB3aW5kb3cgJiYgd2luZG93LmxvY2FsU3RvcmFnZSAhPT0gbnVsbDtcbiAgICB9IGNhdGNoIChlKSB7XG4gICAgICAgIGxvZ2dlci5sb2coXCJsb2NhbHN0b3JhZ2UgaXMgbm90IHN1cHBvcnRlZFwiKTtcbiAgICAgICAgcmV0dXJuIGZhbHNlO1xuICAgIH1cbn1cblxuXG5mdW5jdGlvbiBnZW5lcmF0ZVVuaXF1ZUlkKCkge1xuICAgIGZ1bmN0aW9uIF9wOCgpIHtcbiAgICAgICAgcmV0dXJuIChNYXRoLnJhbmRvbSgpLnRvU3RyaW5nKDE2KSArIFwiMDAwMDAwMDAwXCIpLnN1YnN0cigyLCA4KTtcbiAgICB9XG4gICAgcmV0dXJuIF9wOCgpICsgX3A4KCkgKyBfcDgoKSArIF9wOCgpO1xufVxuXG5mdW5jdGlvbiBTZXR0aW5ncyhjb25mZXJlbmNlSUQpIHtcbiAgICB0aGlzLmVtYWlsID0gJyc7XG4gICAgdGhpcy5kaXNwbGF5TmFtZSA9ICcnO1xuICAgIHRoaXMudXNlcklkO1xuICAgIHRoaXMubGFuZ3VhZ2UgPSBudWxsO1xuICAgIHRoaXMuY29uZlNldHRpbmdzID0gbnVsbDtcbiAgICB0aGlzLmNvbmZlcmVuY2VJRCA9IGNvbmZlcmVuY2VJRDtcbiAgICBpZiAoc3VwcG9ydHNMb2NhbFN0b3JhZ2UoKSkge1xuICAgICAgICBpZighd2luZG93LmxvY2FsU3RvcmFnZS5nZXRJdGVtKGNvbmZlcmVuY2VJRCkpXG4gICAgICAgICAgICB0aGlzLmNvbmZTZXR0aW5ncyA9IHt9O1xuICAgICAgICBlbHNlXG4gICAgICAgICAgICB0aGlzLmNvbmZTZXR0aW5ncyA9IEpTT04ucGFyc2Uod2luZG93LmxvY2FsU3RvcmFnZS5nZXRJdGVtKGNvbmZlcmVuY2VJRCkpO1xuICAgICAgICBpZighdGhpcy5jb25mU2V0dGluZ3Muaml0c2lNZWV0SWQpIHtcbiAgICAgICAgICAgIHRoaXMuY29uZlNldHRpbmdzLmppdHNpTWVldElkID0gZ2VuZXJhdGVVbmlxdWVJZCgpO1xuICAgICAgICAgICAgbG9nZ2VyLmxvZyhcImdlbmVyYXRlZCBpZFwiLFxuICAgICAgICAgICAgICAgIHRoaXMuY29uZlNldHRpbmdzLmppdHNpTWVldElkKTtcbiAgICAgICAgICAgIHRoaXMuc2F2ZSgpO1xuICAgICAgICB9XG4gICAgICAgIHRoaXMudXNlcklkID0gdGhpcy5jb25mU2V0dGluZ3Muaml0c2lNZWV0SWQgfHwgJyc7XG4gICAgICAgIHRoaXMuZW1haWwgPSB0aGlzLmNvbmZTZXR0aW5ncy5lbWFpbCB8fCAnJztcbiAgICAgICAgdGhpcy5kaXNwbGF5TmFtZSA9IHRoaXMuY29uZlNldHRpbmdzLmRpc3BsYXluYW1lIHx8ICcnO1xuICAgICAgICB0aGlzLmxhbmd1YWdlID0gdGhpcy5jb25mU2V0dGluZ3MubGFuZ3VhZ2U7XG4gICAgfSBlbHNlIHtcbiAgICAgICAgbG9nZ2VyLmxvZyhcImxvY2FsIHN0b3JhZ2UgaXMgbm90IHN1cHBvcnRlZFwiKTtcbiAgICAgICAgdGhpcy51c2VySWQgPSBnZW5lcmF0ZVVuaXF1ZUlkKCk7XG4gICAgfVxufVxuXG5TZXR0aW5ncy5wcm90b3R5cGUuc2F2ZSA9IGZ1bmN0aW9uICgpIHtcbiAgICBpZighc3VwcG9ydHNMb2NhbFN0b3JhZ2UoKSlcbiAgICAgICAgd2luZG93LmxvY2FsU3RvcmFnZS5zZXRJdGVtKHRoaXMuY29uZmVyZW5jZUlELCBKU09OLnN0cmluZ2lmeSh0aGlzLmNvbmZTZXR0aW5ncykpO1xufVxuXG5TZXR0aW5ncy5wcm90b3R5cGUuc2V0RGlzcGxheU5hbWUgPSBmdW5jdGlvbiAobmV3RGlzcGxheU5hbWUpIHtcbiAgICB0aGlzLmRpc3BsYXlOYW1lID0gbmV3RGlzcGxheU5hbWU7XG4gICAgaWYodGhpcy5jb25mU2V0dGluZ3MgIT0gbnVsbClcbiAgICAgICAgdGhpcy5jb25mU2V0dGluZ3MuZGlzcGxheW5hbWUgPSBkaXNwbGF5TmFtZTtcbiAgICB0aGlzLnNhdmUoKTtcbiAgICByZXR1cm4gdGhpcy5kaXNwbGF5TmFtZTtcbn0sXG5TZXR0aW5ncy5wcm90b3R5cGUuc2V0RW1haWwgPSBmdW5jdGlvbiAobmV3RW1haWwpIHtcbiAgICB0aGlzLmVtYWlsID0gbmV3RW1haWw7XG4gICAgaWYodGhpcy5jb25mU2V0dGluZ3MgIT0gbnVsbClcbiAgICAgICAgdGhpcy5jb25mU2V0dGluZ3MuZW1haWwgPSBuZXdFbWFpbDtcbiAgICB0aGlzLnNhdmUoKTtcbiAgICByZXR1cm4gdGhpcy5lbWFpbDtcbn0sXG5TZXR0aW5ncy5wcm90b3R5cGUuZ2V0U2V0dGluZ3MgPSBmdW5jdGlvbiAoKSB7XG4gICAgcmV0dXJuIHtcbiAgICAgICAgZW1haWw6IHRoaXMuZW1haWwsXG4gICAgICAgIGRpc3BsYXlOYW1lOiB0aGlzLmRpc3BsYXlOYW1lLFxuICAgICAgICB1aWQ6IHRoaXMudXNlcklkLFxuICAgICAgICBsYW5ndWFnZTogdGhpcy5sYW5ndWFnZVxuICAgIH07XG59LFxuU2V0dGluZ3MucHJvdG90eXBlLnNldExhbmd1YWdlID0gZnVuY3Rpb24gKGxhbmcpIHtcbiAgICB0aGlzLmxhbmd1YWdlID0gbGFuZztcbiAgICBpZih0aGlzLmNvbmZTZXR0aW5ncyAhPSBudWxsKVxuICAgICAgICB0aGlzLmNvbmZTZXR0aW5ncy5sYW5ndWFnZSA9IGxhbmc7XG4gICAgdGhpcy5zYXZlKCk7XG59XG5cbm1vZHVsZS5leHBvcnRzID0gU2V0dGluZ3M7XG4iLCIvKiBnbG9iYWwgY29uZmlnICovXG4vKipcbiAqIFByb3ZpZGVzIHN0YXRpc3RpY3MgZm9yIHRoZSBsb2NhbCBzdHJlYW0uXG4gKi9cblxudmFyIFJUQ0Jyb3dzZXJUeXBlID0gcmVxdWlyZSgnLi4vUlRDL1JUQ0Jyb3dzZXJUeXBlJyk7XG5cbi8qKlxuICogU2l6ZSBvZiB0aGUgd2ViYXVkaW8gYW5hbHl6ZXIgYnVmZmVyLlxuICogQHR5cGUge251bWJlcn1cbiAqL1xudmFyIFdFQkFVRElPX0FOQUxZWkVSX0ZGVF9TSVpFID0gMjA0ODtcblxuLyoqXG4gKiBWYWx1ZSBvZiB0aGUgd2ViYXVkaW8gYW5hbHl6ZXIgc21vb3RoaW5nIHRpbWUgcGFyYW1ldGVyLlxuICogQHR5cGUge251bWJlcn1cbiAqL1xudmFyIFdFQkFVRElPX0FOQUxZWkVSX1NNT09USU5HX1RJTUUgPSAwLjg7XG5cbi8qKlxuICogQ29udmVydHMgdGltZSBkb21haW4gZGF0YSBhcnJheSB0byBhdWRpbyBsZXZlbC5cbiAqIEBwYXJhbSBzYW1wbGVzIHRoZSB0aW1lIGRvbWFpbiBkYXRhIGFycmF5LlxuICogQHJldHVybnMge251bWJlcn0gdGhlIGF1ZGlvIGxldmVsXG4gKi9cbmZ1bmN0aW9uIHRpbWVEb21haW5EYXRhVG9BdWRpb0xldmVsKHNhbXBsZXMpIHtcblxuICAgIHZhciBtYXhWb2x1bWUgPSAwO1xuXG4gICAgdmFyIGxlbmd0aCA9IHNhbXBsZXMubGVuZ3RoO1xuXG4gICAgZm9yICh2YXIgaSA9IDA7IGkgPCBsZW5ndGg7IGkrKykge1xuICAgICAgICBpZiAobWF4Vm9sdW1lIDwgc2FtcGxlc1tpXSlcbiAgICAgICAgICAgIG1heFZvbHVtZSA9IHNhbXBsZXNbaV07XG4gICAgfVxuXG4gICAgcmV0dXJuIHBhcnNlRmxvYXQoKChtYXhWb2x1bWUgLSAxMjcpIC8gMTI4KS50b0ZpeGVkKDMpKTtcbn1cblxuLyoqXG4gKiBBbmltYXRlcyBhdWRpbyBsZXZlbCBjaGFuZ2VcbiAqIEBwYXJhbSBuZXdMZXZlbCB0aGUgbmV3IGF1ZGlvIGxldmVsXG4gKiBAcGFyYW0gbGFzdExldmVsIHRoZSBsYXN0IGF1ZGlvIGxldmVsXG4gKiBAcmV0dXJucyB7TnVtYmVyfSB0aGUgYXVkaW8gbGV2ZWwgdG8gYmUgc2V0XG4gKi9cbmZ1bmN0aW9uIGFuaW1hdGVMZXZlbChuZXdMZXZlbCwgbGFzdExldmVsKSB7XG4gICAgdmFyIHZhbHVlID0gMDtcbiAgICB2YXIgZGlmZiA9IGxhc3RMZXZlbCAtIG5ld0xldmVsO1xuICAgIGlmKGRpZmYgPiAwLjIpIHtcbiAgICAgICAgdmFsdWUgPSBsYXN0TGV2ZWwgLSAwLjI7XG4gICAgfVxuICAgIGVsc2UgaWYoZGlmZiA8IC0wLjQpIHtcbiAgICAgICAgdmFsdWUgPSBsYXN0TGV2ZWwgKyAwLjQ7XG4gICAgfVxuICAgIGVsc2Uge1xuICAgICAgICB2YWx1ZSA9IG5ld0xldmVsO1xuICAgIH1cblxuICAgIHJldHVybiBwYXJzZUZsb2F0KHZhbHVlLnRvRml4ZWQoMykpO1xufVxuXG5cbi8qKlxuICogPHR0PkxvY2FsU3RhdHNDb2xsZWN0b3I8L3R0PiBjYWxjdWxhdGVzIHN0YXRpc3RpY3MgZm9yIHRoZSBsb2NhbCBzdHJlYW0uXG4gKlxuICogQHBhcmFtIHN0cmVhbSB0aGUgbG9jYWwgc3RyZWFtXG4gKiBAcGFyYW0gaW50ZXJ2YWwgc3RhdHMgcmVmcmVzaCBpbnRlcnZhbCBnaXZlbiBpbiBtcy5cbiAqIEBwYXJhbSBjYWxsYmFjayBmdW5jdGlvbiB0aGF0IHJlY2VpdmVzIHRoZSBhdWRpbyBsZXZlbHMuXG4gKiBAY29uc3RydWN0b3JcbiAqL1xuZnVuY3Rpb24gTG9jYWxTdGF0c0NvbGxlY3RvcihzdHJlYW0sIGludGVydmFsLCBjYWxsYmFjaykge1xuICAgIHdpbmRvdy5BdWRpb0NvbnRleHQgPSB3aW5kb3cuQXVkaW9Db250ZXh0IHx8IHdpbmRvdy53ZWJraXRBdWRpb0NvbnRleHQ7XG4gICAgdGhpcy5zdHJlYW0gPSBzdHJlYW07XG4gICAgdGhpcy5pbnRlcnZhbElkID0gbnVsbDtcbiAgICB0aGlzLmludGVydmFsTWlsaXMgPSBpbnRlcnZhbDtcbiAgICB0aGlzLmF1ZGlvTGV2ZWwgPSAwO1xuICAgIHRoaXMuY2FsbGJhY2sgPSBjYWxsYmFjaztcbn1cblxuLyoqXG4gKiBTdGFydHMgdGhlIGNvbGxlY3RpbmcgdGhlIHN0YXRpc3RpY3MuXG4gKi9cbkxvY2FsU3RhdHNDb2xsZWN0b3IucHJvdG90eXBlLnN0YXJ0ID0gZnVuY3Rpb24gKCkge1xuICAgIGlmICghd2luZG93LkF1ZGlvQ29udGV4dCB8fFxuICAgICAgICBSVENCcm93c2VyVHlwZS5pc1RlbWFzeXNQbHVnaW5Vc2VkKCkpXG4gICAgICAgIHJldHVybjtcblxuICAgIHZhciBjb250ZXh0ID0gbmV3IEF1ZGlvQ29udGV4dCgpO1xuICAgIHZhciBhbmFseXNlciA9IGNvbnRleHQuY3JlYXRlQW5hbHlzZXIoKTtcbiAgICBhbmFseXNlci5zbW9vdGhpbmdUaW1lQ29uc3RhbnQgPSBXRUJBVURJT19BTkFMWVpFUl9TTU9PVElOR19USU1FO1xuICAgIGFuYWx5c2VyLmZmdFNpemUgPSBXRUJBVURJT19BTkFMWVpFUl9GRlRfU0laRTtcblxuXG4gICAgdmFyIHNvdXJjZSA9IGNvbnRleHQuY3JlYXRlTWVkaWFTdHJlYW1Tb3VyY2UodGhpcy5zdHJlYW0pO1xuICAgIHNvdXJjZS5jb25uZWN0KGFuYWx5c2VyKTtcblxuXG4gICAgdmFyIHNlbGYgPSB0aGlzO1xuXG4gICAgdGhpcy5pbnRlcnZhbElkID0gc2V0SW50ZXJ2YWwoXG4gICAgICAgIGZ1bmN0aW9uICgpIHtcbiAgICAgICAgICAgIHZhciBhcnJheSA9IG5ldyBVaW50OEFycmF5KGFuYWx5c2VyLmZyZXF1ZW5jeUJpbkNvdW50KTtcbiAgICAgICAgICAgIGFuYWx5c2VyLmdldEJ5dGVUaW1lRG9tYWluRGF0YShhcnJheSk7XG4gICAgICAgICAgICB2YXIgYXVkaW9MZXZlbCA9IHRpbWVEb21haW5EYXRhVG9BdWRpb0xldmVsKGFycmF5KTtcbiAgICAgICAgICAgIGlmIChhdWRpb0xldmVsICE9IHNlbGYuYXVkaW9MZXZlbCkge1xuICAgICAgICAgICAgICAgIHNlbGYuYXVkaW9MZXZlbCA9IGFuaW1hdGVMZXZlbChhdWRpb0xldmVsLCBzZWxmLmF1ZGlvTGV2ZWwpO1xuICAgICAgICAgICAgICAgIHNlbGYuY2FsbGJhY2soc2VsZi5hdWRpb0xldmVsKTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgfSxcbiAgICAgICAgdGhpcy5pbnRlcnZhbE1pbGlzXG4gICAgKTtcbn07XG5cbi8qKlxuICogU3RvcHMgY29sbGVjdGluZyB0aGUgc3RhdGlzdGljcy5cbiAqL1xuTG9jYWxTdGF0c0NvbGxlY3Rvci5wcm90b3R5cGUuc3RvcCA9IGZ1bmN0aW9uICgpIHtcbiAgICBpZiAodGhpcy5pbnRlcnZhbElkKSB7XG4gICAgICAgIGNsZWFySW50ZXJ2YWwodGhpcy5pbnRlcnZhbElkKTtcbiAgICAgICAgdGhpcy5pbnRlcnZhbElkID0gbnVsbDtcbiAgICB9XG59O1xuXG5tb2R1bGUuZXhwb3J0cyA9IExvY2FsU3RhdHNDb2xsZWN0b3I7XG4iLCIvKiBnbG9iYWwgcmVxdWlyZSwgc3NyYzJqaWQgKi9cbi8qIGpzaGludCAtVzExNyAqL1xuXG52YXIgbG9nZ2VyID0gcmVxdWlyZShcImppdHNpLW1lZXQtbG9nZ2VyXCIpLmdldExvZ2dlcihfX2ZpbGVuYW1lKTtcbnZhciBSVENCcm93c2VyVHlwZSA9IHJlcXVpcmUoXCIuLi9SVEMvUlRDQnJvd3NlclR5cGVcIik7XG52YXIgU3RhdGlzdGljc0V2ZW50cyA9IHJlcXVpcmUoXCIuLi8uLi9zZXJ2aWNlL3N0YXRpc3RpY3MvRXZlbnRzXCIpO1xuXG4vKiBXaGV0aGVyIHdlIHN1cHBvcnQgdGhlIGJyb3dzZXIgd2UgYXJlIHJ1bm5pbmcgaW50byBmb3IgbG9nZ2luZyBzdGF0aXN0aWNzICovXG52YXIgYnJvd3NlclN1cHBvcnRlZCA9IFJUQ0Jyb3dzZXJUeXBlLmlzQ2hyb21lKCkgfHxcbiAgICBSVENCcm93c2VyVHlwZS5pc09wZXJhKCk7XG5cbnZhciBrZXlNYXAgPSB7fTtcbmtleU1hcFtSVENCcm93c2VyVHlwZS5SVENfQlJPV1NFUl9GSVJFRk9YXSA9IHtcbiAgICBcInNzcmNcIjogXCJzc3JjXCIsXG4gICAgXCJwYWNrZXRzUmVjZWl2ZWRcIjogXCJwYWNrZXRzUmVjZWl2ZWRcIixcbiAgICBcInBhY2tldHNMb3N0XCI6IFwicGFja2V0c0xvc3RcIixcbiAgICBcInBhY2tldHNTZW50XCI6IFwicGFja2V0c1NlbnRcIixcbiAgICBcImJ5dGVzUmVjZWl2ZWRcIjogXCJieXRlc1JlY2VpdmVkXCIsXG4gICAgXCJieXRlc1NlbnRcIjogXCJieXRlc1NlbnRcIlxufTtcbmtleU1hcFtSVENCcm93c2VyVHlwZS5SVENfQlJPV1NFUl9DSFJPTUVdID0ge1xuICAgIFwicmVjZWl2ZUJhbmR3aWR0aFwiOiBcImdvb2dBdmFpbGFibGVSZWNlaXZlQmFuZHdpZHRoXCIsXG4gICAgXCJzZW5kQmFuZHdpZHRoXCI6IFwiZ29vZ0F2YWlsYWJsZVNlbmRCYW5kd2lkdGhcIixcbiAgICBcInJlbW90ZUFkZHJlc3NcIjogXCJnb29nUmVtb3RlQWRkcmVzc1wiLFxuICAgIFwidHJhbnNwb3J0VHlwZVwiOiBcImdvb2dUcmFuc3BvcnRUeXBlXCIsXG4gICAgXCJsb2NhbEFkZHJlc3NcIjogXCJnb29nTG9jYWxBZGRyZXNzXCIsXG4gICAgXCJhY3RpdmVDb25uZWN0aW9uXCI6IFwiZ29vZ0FjdGl2ZUNvbm5lY3Rpb25cIixcbiAgICBcInNzcmNcIjogXCJzc3JjXCIsXG4gICAgXCJwYWNrZXRzUmVjZWl2ZWRcIjogXCJwYWNrZXRzUmVjZWl2ZWRcIixcbiAgICBcInBhY2tldHNTZW50XCI6IFwicGFja2V0c1NlbnRcIixcbiAgICBcInBhY2tldHNMb3N0XCI6IFwicGFja2V0c0xvc3RcIixcbiAgICBcImJ5dGVzUmVjZWl2ZWRcIjogXCJieXRlc1JlY2VpdmVkXCIsXG4gICAgXCJieXRlc1NlbnRcIjogXCJieXRlc1NlbnRcIixcbiAgICBcImdvb2dGcmFtZUhlaWdodFJlY2VpdmVkXCI6IFwiZ29vZ0ZyYW1lSGVpZ2h0UmVjZWl2ZWRcIixcbiAgICBcImdvb2dGcmFtZVdpZHRoUmVjZWl2ZWRcIjogXCJnb29nRnJhbWVXaWR0aFJlY2VpdmVkXCIsXG4gICAgXCJnb29nRnJhbWVIZWlnaHRTZW50XCI6IFwiZ29vZ0ZyYW1lSGVpZ2h0U2VudFwiLFxuICAgIFwiZ29vZ0ZyYW1lV2lkdGhTZW50XCI6IFwiZ29vZ0ZyYW1lV2lkdGhTZW50XCIsXG4gICAgXCJhdWRpb0lucHV0TGV2ZWxcIjogXCJhdWRpb0lucHV0TGV2ZWxcIixcbiAgICBcImF1ZGlvT3V0cHV0TGV2ZWxcIjogXCJhdWRpb091dHB1dExldmVsXCJcbn07XG5rZXlNYXBbUlRDQnJvd3NlclR5cGUuUlRDX0JST1dTRVJfT1BFUkFdID1cbiAgICBrZXlNYXBbUlRDQnJvd3NlclR5cGUuUlRDX0JST1dTRVJfQ0hST01FXTtcblxuLyoqXG4gKiBDYWxjdWxhdGVzIHBhY2tldCBsb3N0IHBlcmNlbnQgdXNpbmcgdGhlIG51bWJlciBvZiBsb3N0IHBhY2tldHMgYW5kIHRoZVxuICogbnVtYmVyIG9mIGFsbCBwYWNrZXQuXG4gKiBAcGFyYW0gbG9zdFBhY2tldHMgdGhlIG51bWJlciBvZiBsb3N0IHBhY2tldHNcbiAqIEBwYXJhbSB0b3RhbFBhY2tldHMgdGhlIG51bWJlciBvZiBhbGwgcGFja2V0cy5cbiAqIEByZXR1cm5zIHtudW1iZXJ9IHBhY2tldCBsb3NzIHBlcmNlbnRcbiAqL1xuZnVuY3Rpb24gY2FsY3VsYXRlUGFja2V0TG9zcyhsb3N0UGFja2V0cywgdG90YWxQYWNrZXRzKSB7XG4gICAgaWYoIXRvdGFsUGFja2V0cyB8fCB0b3RhbFBhY2tldHMgPD0gMCB8fCAhbG9zdFBhY2tldHMgfHwgbG9zdFBhY2tldHMgPD0gMClcbiAgICAgICAgcmV0dXJuIDA7XG4gICAgcmV0dXJuIE1hdGgucm91bmQoKGxvc3RQYWNrZXRzL3RvdGFsUGFja2V0cykqMTAwKTtcbn1cblxuZnVuY3Rpb24gZ2V0U3RhdFZhbHVlKGl0ZW0sIG5hbWUpIHtcbiAgICB2YXIgYnJvd3NlclR5cGUgPSBSVENCcm93c2VyVHlwZS5nZXRCcm93c2VyVHlwZSgpO1xuICAgIGlmICgha2V5TWFwW2Jyb3dzZXJUeXBlXVtuYW1lXSlcbiAgICAgICAgdGhyb3cgXCJUaGUgcHJvcGVydHkgaXNuJ3Qgc3VwcG9ydGVkIVwiO1xuICAgIHZhciBrZXkgPSBrZXlNYXBbYnJvd3NlclR5cGVdW25hbWVdO1xuICAgIHJldHVybiAoUlRDQnJvd3NlclR5cGUuaXNDaHJvbWUoKSB8fCBSVENCcm93c2VyVHlwZS5pc09wZXJhKCkpID9cbiAgICAgICAgaXRlbS5zdGF0KGtleSkgOiBpdGVtW2tleV07XG59XG5cbmZ1bmN0aW9uIGZvcm1hdEF1ZGlvTGV2ZWwoYXVkaW9MZXZlbCkge1xuICAgIHJldHVybiBNYXRoLm1pbihNYXRoLm1heChhdWRpb0xldmVsLCAwKSwgMSk7XG59XG5cbi8qKlxuICogQ2hlY2tzIHdoZXRoZXIgYSBjZXJ0YWluIHJlY29yZCBzaG91bGQgYmUgaW5jbHVkZWQgaW4gdGhlIGxvZ2dlZCBzdGF0aXN0aWNzLlxuICovXG5mdW5jdGlvbiBhY2NlcHRTdGF0KHJlcG9ydElkLCByZXBvcnRUeXBlLCBzdGF0TmFtZSkge1xuICAgIGlmIChyZXBvcnRUeXBlID09IFwiZ29vZ0NhbmRpZGF0ZVBhaXJcIiAmJiBzdGF0TmFtZSA9PSBcImdvb2dDaGFubmVsSWRcIilcbiAgICAgICAgcmV0dXJuIGZhbHNlO1xuXG4gICAgaWYgKHJlcG9ydFR5cGUgPT0gXCJzc3JjXCIpIHtcbiAgICAgICAgaWYgKHN0YXROYW1lID09IFwiZ29vZ1RyYWNrSWRcIiB8fFxuICAgICAgICAgICAgc3RhdE5hbWUgPT0gXCJ0cmFuc3BvcnRJZFwiIHx8XG4gICAgICAgICAgICBzdGF0TmFtZSA9PSBcInNzcmNcIilcbiAgICAgICAgICAgIHJldHVybiBmYWxzZTtcbiAgICB9XG5cbiAgICByZXR1cm4gdHJ1ZTtcbn1cblxuLyoqXG4gKiBDaGVja3Mgd2hldGhlciBhIGNlcnRhaW4gcmVjb3JkIHNob3VsZCBiZSBpbmNsdWRlZCBpbiB0aGUgbG9nZ2VkIHN0YXRpc3RpY3MuXG4gKi9cbmZ1bmN0aW9uIGFjY2VwdFJlcG9ydChpZCwgdHlwZSkge1xuICAgIGlmIChpZC5zdWJzdHJpbmcoMCwgMTUpID09IFwiZ29vZ0NlcnRpZmljYXRlXCIgfHxcbiAgICAgICAgaWQuc3Vic3RyaW5nKDAsIDkpID09IFwiZ29vZ1RyYWNrXCIgfHxcbiAgICAgICAgaWQuc3Vic3RyaW5nKDAsIDIwKSA9PSBcImdvb2dMaWJqaW5nbGVTZXNzaW9uXCIpXG4gICAgICAgIHJldHVybiBmYWxzZTtcblxuICAgIGlmICh0eXBlID09IFwiZ29vZ0NvbXBvbmVudFwiKVxuICAgICAgICByZXR1cm4gZmFsc2U7XG5cbiAgICByZXR1cm4gdHJ1ZTtcbn1cblxuLyoqXG4gKiBQZWVyIHN0YXRpc3RpY3MgZGF0YSBob2xkZXIuXG4gKiBAY29uc3RydWN0b3JcbiAqL1xuZnVuY3Rpb24gUGVlclN0YXRzKClcbntcbiAgICB0aGlzLnNzcmMyTG9zcyA9IHt9O1xuICAgIHRoaXMuc3NyYzJBdWRpb0xldmVsID0ge307XG4gICAgdGhpcy5zc3JjMmJpdHJhdGUgPSB7fTtcbiAgICB0aGlzLnNzcmMycmVzb2x1dGlvbiA9IHt9O1xufVxuXG4vKipcbiAqIFNldHMgcGFja2V0cyBsb3NzIHJhdGUgZm9yIGdpdmVuIDx0dD5zc3JjPC90dD4gdGhhdCBibG9uZyB0byB0aGUgcGVlclxuICogcmVwcmVzZW50ZWQgYnkgdGhpcyBpbnN0YW5jZS5cbiAqIEBwYXJhbSBsb3NzUmF0ZSBuZXcgcGFja2V0IGxvc3MgcmF0ZSB2YWx1ZSB0byBiZSBzZXQuXG4gKi9cblBlZXJTdGF0cy5wcm90b3R5cGUuc2V0U3NyY0xvc3MgPSBmdW5jdGlvbiAobG9zc1JhdGUpXG57XG4gICAgdGhpcy5zc3JjMkxvc3MgPSBsb3NzUmF0ZTtcbn07XG5cbi8qKlxuICogU2V0cyByZXNvbHV0aW9uIHRoYXQgYmVsb25nIHRvIHRoZSBzc3JjXG4gKiByZXByZXNlbnRlZCBieSB0aGlzIGluc3RhbmNlLlxuICogQHBhcmFtIHJlc29sdXRpb24gbmV3IHJlc29sdXRpb24gdmFsdWUgdG8gYmUgc2V0LlxuICovXG5QZWVyU3RhdHMucHJvdG90eXBlLnNldFNzcmNSZXNvbHV0aW9uID0gZnVuY3Rpb24gKHJlc29sdXRpb24pXG57XG4gICAgaWYocmVzb2x1dGlvbiA9PT0gbnVsbCAmJiB0aGlzLnNzcmMycmVzb2x1dGlvbltzc3JjXSlcbiAgICB7XG4gICAgICAgIGRlbGV0ZSB0aGlzLnNzcmMycmVzb2x1dGlvbltzc3JjXTtcbiAgICB9XG4gICAgZWxzZSBpZihyZXNvbHV0aW9uICE9PSBudWxsKVxuICAgICAgICB0aGlzLnNzcmMycmVzb2x1dGlvbltzc3JjXSA9IHJlc29sdXRpb247XG59O1xuXG4vKipcbiAqIFNldHMgdGhlIGJpdCByYXRlIGZvciBnaXZlbiA8dHQ+c3NyYzwvdHQ+IHRoYXQgYmxvbmcgdG8gdGhlIHBlZXJcbiAqIHJlcHJlc2VudGVkIGJ5IHRoaXMgaW5zdGFuY2UuXG4gKiBAcGFyYW0gc3NyYyBhdWRpbyBvciB2aWRlbyBSVFAgc3RyZWFtIFNTUkMuXG4gKiBAcGFyYW0gYml0cmF0ZSBuZXcgYml0cmF0ZSB2YWx1ZSB0byBiZSBzZXQuXG4gKi9cblBlZXJTdGF0cy5wcm90b3R5cGUuc2V0U3NyY0JpdHJhdGUgPSBmdW5jdGlvbiAoc3NyYywgYml0cmF0ZSlcbntcbiAgICBpZih0aGlzLnNzcmMyYml0cmF0ZVtzc3JjXSlcbiAgICB7XG4gICAgICAgIHRoaXMuc3NyYzJiaXRyYXRlW3NzcmNdLmRvd25sb2FkICs9IGJpdHJhdGUuZG93bmxvYWQ7XG4gICAgICAgIHRoaXMuc3NyYzJiaXRyYXRlW3NzcmNdLnVwbG9hZCArPSBiaXRyYXRlLnVwbG9hZDtcbiAgICB9XG4gICAgZWxzZSB7XG4gICAgICAgIHRoaXMuc3NyYzJiaXRyYXRlW3NzcmNdID0gYml0cmF0ZTtcbiAgICB9XG59O1xuXG4vKipcbiAqIFNldHMgbmV3IGF1ZGlvIGxldmVsKGlucHV0IG9yIG91dHB1dCkgZm9yIGdpdmVuIDx0dD5zc3JjPC90dD4gdGhhdCBpZGVudGlmaWVzXG4gKiB0aGUgc3RyZWFtIHdoaWNoIGJlbG9uZ3MgdG8gdGhlIHBlZXIgcmVwcmVzZW50ZWQgYnkgdGhpcyBpbnN0YW5jZS5cbiAqIEBwYXJhbSBzc3JjIFJUUCBzdHJlYW0gU1NSQyBmb3Igd2hpY2ggY3VycmVudCBhdWRpbyBsZXZlbCB2YWx1ZSB3aWxsIGJlXG4gKiAgICAgICAgdXBkYXRlZC5cbiAqIEBwYXJhbSBhdWRpb0xldmVsIHRoZSBuZXcgYXVkaW8gbGV2ZWwgdmFsdWUgdG8gYmUgc2V0LiBWYWx1ZSBpcyB0cnVuY2F0ZWQgdG9cbiAqICAgICAgICBmaXQgdGhlIHJhbmdlIGZyb20gMCB0byAxLlxuICovXG5QZWVyU3RhdHMucHJvdG90eXBlLnNldFNzcmNBdWRpb0xldmVsID0gZnVuY3Rpb24gKHNzcmMsIGF1ZGlvTGV2ZWwpXG57XG4gICAgLy8gUmFuZ2UgbGltaXQgMCAtIDFcbiAgICB0aGlzLnNzcmMyQXVkaW9MZXZlbFtzc3JjXSA9IGZvcm1hdEF1ZGlvTGV2ZWwoYXVkaW9MZXZlbCk7XG59O1xuXG5mdW5jdGlvbiBDb25mZXJlbmNlU3RhdHMoKSB7XG5cblxuICAgIC8qKlxuICAgICAqIFRoZSBiYW5kd2lkdGhcbiAgICAgKiBAdHlwZSB7e319XG4gICAgICovXG4gICAgdGhpcy5iYW5kd2lkdGggPSB7fTtcblxuICAgIC8qKlxuICAgICAqIFRoZSBiaXQgcmF0ZVxuICAgICAqIEB0eXBlIHt7fX1cbiAgICAgKi9cbiAgICB0aGlzLmJpdHJhdGUgPSB7fTtcblxuICAgIC8qKlxuICAgICAqIFRoZSBwYWNrZXQgbG9zcyByYXRlXG4gICAgICogQHR5cGUge3t9fVxuICAgICAqL1xuICAgIHRoaXMucGFja2V0TG9zcyA9IG51bGw7XG5cblxuICAgIC8qKlxuICAgICAqIEFycmF5IHdpdGggdGhlIHRyYW5zcG9ydCBpbmZvcm1hdGlvbi5cbiAgICAgKiBAdHlwZSB7QXJyYXl9XG4gICAgICovXG4gICAgdGhpcy50cmFuc3BvcnQgPSBbXTtcbn1cblxuLyoqXG4gKiA8dHQ+U3RhdHNDb2xsZWN0b3I8L3R0PiByZWdpc3RlcnMgZm9yIHN0YXRzIHVwZGF0ZXMgb2YgZ2l2ZW5cbiAqIDx0dD5wZWVyY29ubmVjdGlvbjwvdHQ+IGluIGdpdmVuIDx0dD5pbnRlcnZhbDwvdHQ+LiBPbiBlYWNoIHVwZGF0ZSBwYXJ0aWN1bGFyXG4gKiBzdGF0cyBhcmUgZXh0cmFjdGVkIGFuZCBwdXQgaW4ge0BsaW5rIFBlZXJTdGF0c30gb2JqZWN0cy4gT25jZSB0aGUgcHJvY2Vzc2luZ1xuICogaXMgZG9uZSA8dHQ+YXVkaW9MZXZlbHNVcGRhdGVDYWxsYmFjazwvdHQ+IGlzIGNhbGxlZCB3aXRoIDx0dD50aGlzPC90dD5cbiAqIGluc3RhbmNlIGFzIGFuIGV2ZW50IHNvdXJjZS5cbiAqXG4gKiBAcGFyYW0gcGVlcmNvbm5lY3Rpb24gd2ViUlRDIHBlZXIgY29ubmVjdGlvbiBvYmplY3QuXG4gKiBAcGFyYW0gaW50ZXJ2YWwgc3RhdHMgcmVmcmVzaCBpbnRlcnZhbCBnaXZlbiBpbiBtcy5cbiAqIEBwYXJhbSB7ZnVuY3Rpb24oU3RhdHNDb2xsZWN0b3IpfSBhdWRpb0xldmVsc1VwZGF0ZUNhbGxiYWNrIHRoZSBjYWxsYmFja1xuICogY2FsbGVkIG9uIHN0YXRzIHVwZGF0ZS5cbiAqIEBwYXJhbSBjb25maWcge29iamVjdH0gc3VwcG9ydHMgdGhlIGZvbGxvd2luZyBwcm9wZXJ0aWVzIC0gZGlzYWJsZUF1ZGlvTGV2ZWxzLCBkaXNhYmxlU3RhdHMsIGxvZ1N0YXRzXG4gKiBAY29uc3RydWN0b3JcbiAqL1xuZnVuY3Rpb24gU3RhdHNDb2xsZWN0b3IocGVlcmNvbm5lY3Rpb24sIGF1ZGlvTGV2ZWxzSW50ZXJ2YWwsIHN0YXRzSW50ZXJ2YWwsIGV2ZW50RW1pdHRlciwgY29uZmlnKVxue1xuICAgIHRoaXMucGVlcmNvbm5lY3Rpb24gPSBwZWVyY29ubmVjdGlvbjtcbiAgICB0aGlzLmJhc2VsaW5lQXVkaW9MZXZlbHNSZXBvcnQgPSBudWxsO1xuICAgIHRoaXMuY3VycmVudEF1ZGlvTGV2ZWxzUmVwb3J0ID0gbnVsbDtcbiAgICB0aGlzLmN1cnJlbnRTdGF0c1JlcG9ydCA9IG51bGw7XG4gICAgdGhpcy5iYXNlbGluZVN0YXRzUmVwb3J0ID0gbnVsbDtcbiAgICB0aGlzLmF1ZGlvTGV2ZWxzSW50ZXJ2YWxJZCA9IG51bGw7XG4gICAgdGhpcy5ldmVudEVtaXR0ZXIgPSBldmVudEVtaXR0ZXI7XG4gICAgdGhpcy5jb25maWcgPSBjb25maWcgfHwge307XG4gICAgdGhpcy5jb25mZXJlbmNlU3RhdHMgPSBuZXcgQ29uZmVyZW5jZVN0YXRzKCk7XG5cbiAgICAvKipcbiAgICAgKiBHYXRoZXIgUGVlckNvbm5lY3Rpb24gc3RhdHMgb25jZSBldmVyeSB0aGlzIG1hbnkgbWlsbGlzZWNvbmRzLlxuICAgICAqL1xuICAgIHRoaXMuR0FUSEVSX0lOVEVSVkFMID0gMTUwMDA7XG5cbiAgICAvKipcbiAgICAgKiBMb2cgc3RhdHMgdmlhIHRoZSBmb2N1cyBvbmNlIGV2ZXJ5IHRoaXMgbWFueSBtaWxsaXNlY29uZHMuXG4gICAgICovXG4gICAgdGhpcy5MT0dfSU5URVJWQUwgPSA2MDAwMDtcblxuICAgIC8qKlxuICAgICAqIEdhdGhlciBzdGF0cyBhbmQgc3RvcmUgdGhlbSBpbiB0aGlzLnN0YXRzVG9CZUxvZ2dlZC5cbiAgICAgKi9cbiAgICB0aGlzLmdhdGhlclN0YXRzSW50ZXJ2YWxJZCA9IG51bGw7XG5cbiAgICAvKipcbiAgICAgKiBTZW5kIHRoZSBzdGF0cyBhbHJlYWR5IHNhdmVkIGluIHRoaXMuc3RhdHNUb0JlTG9nZ2VkIHRvIGJlIGxvZ2dlZCB2aWFcbiAgICAgKiB0aGUgZm9jdXMuXG4gICAgICovXG4gICAgdGhpcy5sb2dTdGF0c0ludGVydmFsSWQgPSBudWxsO1xuXG4gICAgLyoqXG4gICAgICogU3RvcmVzIHRoZSBzdGF0aXN0aWNzIHdoaWNoIHdpbGwgYmUgc2VuZCB0byB0aGUgZm9jdXMgdG8gYmUgbG9nZ2VkLlxuICAgICAqL1xuICAgIHRoaXMuc3RhdHNUb0JlTG9nZ2VkID1cbiAgICB7XG4gICAgICAgIHRpbWVzdGFtcHM6IFtdLFxuICAgICAgICBzdGF0czoge31cbiAgICB9O1xuXG4gICAgLy8gVXBkYXRlcyBzdGF0cyBpbnRlcnZhbFxuICAgIHRoaXMuYXVkaW9MZXZlbHNJbnRlcnZhbE1pbGlzID0gYXVkaW9MZXZlbHNJbnRlcnZhbDtcblxuICAgIHRoaXMuc3RhdHNJbnRlcnZhbElkID0gbnVsbDtcbiAgICB0aGlzLnN0YXRzSW50ZXJ2YWxNaWxpcyA9IHN0YXRzSW50ZXJ2YWw7XG4gICAgLy8gTWFwIG9mIHNzcmNzIHRvIFBlZXJTdGF0c1xuICAgIHRoaXMuc3NyYzJzdGF0cyA9IHt9O1xufVxuXG5tb2R1bGUuZXhwb3J0cyA9IFN0YXRzQ29sbGVjdG9yO1xuXG4vKipcbiAqIFN0b3BzIHN0YXRzIHVwZGF0ZXMuXG4gKi9cblN0YXRzQ29sbGVjdG9yLnByb3RvdHlwZS5zdG9wID0gZnVuY3Rpb24gKCkge1xuICAgIGlmICh0aGlzLmF1ZGlvTGV2ZWxzSW50ZXJ2YWxJZCkge1xuICAgICAgICBjbGVhckludGVydmFsKHRoaXMuYXVkaW9MZXZlbHNJbnRlcnZhbElkKTtcbiAgICAgICAgdGhpcy5hdWRpb0xldmVsc0ludGVydmFsSWQgPSBudWxsO1xuICAgIH1cblxuICAgIGlmICh0aGlzLnN0YXRzSW50ZXJ2YWxJZClcbiAgICB7XG4gICAgICAgIGNsZWFySW50ZXJ2YWwodGhpcy5zdGF0c0ludGVydmFsSWQpO1xuICAgICAgICB0aGlzLnN0YXRzSW50ZXJ2YWxJZCA9IG51bGw7XG4gICAgfVxuXG4gICAgaWYodGhpcy5sb2dTdGF0c0ludGVydmFsSWQpXG4gICAge1xuICAgICAgICBjbGVhckludGVydmFsKHRoaXMubG9nU3RhdHNJbnRlcnZhbElkKTtcbiAgICAgICAgdGhpcy5sb2dTdGF0c0ludGVydmFsSWQgPSBudWxsO1xuICAgIH1cblxuICAgIGlmKHRoaXMuZ2F0aGVyU3RhdHNJbnRlcnZhbElkKVxuICAgIHtcbiAgICAgICAgY2xlYXJJbnRlcnZhbCh0aGlzLmdhdGhlclN0YXRzSW50ZXJ2YWxJZCk7XG4gICAgICAgIHRoaXMuZ2F0aGVyU3RhdHNJbnRlcnZhbElkID0gbnVsbDtcbiAgICB9XG59O1xuXG4vKipcbiAqIENhbGxiYWNrIHBhc3NlZCB0byA8dHQ+Z2V0U3RhdHM8L3R0PiBtZXRob2QuXG4gKiBAcGFyYW0gZXJyb3IgYW4gZXJyb3IgdGhhdCBvY2N1cnJlZCBvbiA8dHQ+Z2V0U3RhdHM8L3R0PiBjYWxsLlxuICovXG5TdGF0c0NvbGxlY3Rvci5wcm90b3R5cGUuZXJyb3JDYWxsYmFjayA9IGZ1bmN0aW9uIChlcnJvcilcbntcbiAgICBsb2dnZXIuZXJyb3IoXCJHZXQgc3RhdHMgZXJyb3JcIiwgZXJyb3IpO1xuICAgIHRoaXMuc3RvcCgpO1xufTtcblxuLyoqXG4gKiBTdGFydHMgc3RhdHMgdXBkYXRlcy5cbiAqL1xuU3RhdHNDb2xsZWN0b3IucHJvdG90eXBlLnN0YXJ0ID0gZnVuY3Rpb24gKClcbntcbiAgICB2YXIgc2VsZiA9IHRoaXM7XG4gICAgdGhpcy5hdWRpb0xldmVsc0ludGVydmFsSWQgPSBzZXRJbnRlcnZhbChcbiAgICAgICAgZnVuY3Rpb24gKCkge1xuICAgICAgICAgICAgLy8gSW50ZXJ2YWwgdXBkYXRlc1xuICAgICAgICAgICAgc2VsZi5wZWVyY29ubmVjdGlvbi5nZXRTdGF0cyhcbiAgICAgICAgICAgICAgICBmdW5jdGlvbiAocmVwb3J0KSB7XG4gICAgICAgICAgICAgICAgICAgIHZhciByZXN1bHRzID0gbnVsbDtcbiAgICAgICAgICAgICAgICAgICAgaWYgKCFyZXBvcnQgfHwgIXJlcG9ydC5yZXN1bHQgfHxcbiAgICAgICAgICAgICAgICAgICAgICAgIHR5cGVvZiByZXBvcnQucmVzdWx0ICE9ICdmdW5jdGlvbicpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgIHJlc3VsdHMgPSByZXBvcnQ7XG4gICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICAgICAgZWxzZSB7XG4gICAgICAgICAgICAgICAgICAgICAgICByZXN1bHRzID0gcmVwb3J0LnJlc3VsdCgpO1xuICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgICAgIC8vbG9nZ2VyLmVycm9yKFwiR290IGludGVydmFsIHJlcG9ydFwiLCByZXN1bHRzKTtcbiAgICAgICAgICAgICAgICAgICAgc2VsZi5jdXJyZW50QXVkaW9MZXZlbHNSZXBvcnQgPSByZXN1bHRzO1xuICAgICAgICAgICAgICAgICAgICBzZWxmLnByb2Nlc3NBdWRpb0xldmVsUmVwb3J0KCk7XG4gICAgICAgICAgICAgICAgICAgIHNlbGYuYmFzZWxpbmVBdWRpb0xldmVsc1JlcG9ydCA9XG4gICAgICAgICAgICAgICAgICAgICAgICBzZWxmLmN1cnJlbnRBdWRpb0xldmVsc1JlcG9ydDtcbiAgICAgICAgICAgICAgICB9LFxuICAgICAgICAgICAgICAgIHNlbGYuZXJyb3JDYWxsYmFja1xuICAgICAgICAgICAgKTtcbiAgICAgICAgfSxcbiAgICAgICAgc2VsZi5hdWRpb0xldmVsc0ludGVydmFsTWlsaXNcbiAgICApO1xuXG4vLyAgICBpZiAoIXRoaXMuY29uZmlnLmRpc2FibGVTdGF0cyAmJiBicm93c2VyU3VwcG9ydGVkKSB7XG4vLyAgICAgICAgdGhpcy5zdGF0c0ludGVydmFsSWQgPSBzZXRJbnRlcnZhbChcbi8vICAgICAgICAgICAgZnVuY3Rpb24gKCkge1xuLy8gICAgICAgICAgICAgICAgLy8gSW50ZXJ2YWwgdXBkYXRlc1xuLy8gICAgICAgICAgICAgICAgc2VsZi5wZWVyY29ubmVjdGlvbi5nZXRTdGF0cyhcbi8vICAgICAgICAgICAgICAgICAgICBmdW5jdGlvbiAocmVwb3J0KSB7XG4vLyAgICAgICAgICAgICAgICAgICAgICAgIHZhciByZXN1bHRzID0gbnVsbDtcbi8vICAgICAgICAgICAgICAgICAgICAgICAgaWYgKCFyZXBvcnQgfHwgIXJlcG9ydC5yZXN1bHQgfHxcbi8vICAgICAgICAgICAgICAgICAgICAgICAgICAgIHR5cGVvZiByZXBvcnQucmVzdWx0ICE9ICdmdW5jdGlvbicpIHtcbi8vICAgICAgICAgICAgICAgICAgICAgICAgICAgIC8vZmlyZWZveFxuLy8gICAgICAgICAgICAgICAgICAgICAgICAgICAgcmVzdWx0cyA9IHJlcG9ydDtcbi8vICAgICAgICAgICAgICAgICAgICAgICAgfVxuLy8gICAgICAgICAgICAgICAgICAgICAgICBlbHNlIHtcbi8vICAgICAgICAgICAgICAgICAgICAgICAgICAgIC8vY2hyb21lXG4vLyAgICAgICAgICAgICAgICAgICAgICAgICAgICByZXN1bHRzID0gcmVwb3J0LnJlc3VsdCgpO1xuLy8gICAgICAgICAgICAgICAgICAgICAgICB9XG4vLyAgICAgICAgICAgICAgICAgICAgICAgIC8vbG9nZ2VyLmVycm9yKFwiR290IGludGVydmFsIHJlcG9ydFwiLCByZXN1bHRzKTtcbi8vICAgICAgICAgICAgICAgICAgICAgICAgc2VsZi5jdXJyZW50U3RhdHNSZXBvcnQgPSByZXN1bHRzO1xuLy8gICAgICAgICAgICAgICAgICAgICAgICB0cnkge1xuLy8gICAgICAgICAgICAgICAgICAgICAgICAgICAgc2VsZi5wcm9jZXNzU3RhdHNSZXBvcnQoKTtcbi8vICAgICAgICAgICAgICAgICAgICAgICAgfVxuLy8gICAgICAgICAgICAgICAgICAgICAgICBjYXRjaCAoZSkge1xuLy8gICAgICAgICAgICAgICAgICAgICAgICAgICAgbG9nZ2VyLmVycm9yKFwiVW5zdXBwb3J0ZWQga2V5OlwiICsgZSwgZSk7XG4vLyAgICAgICAgICAgICAgICAgICAgICAgIH1cbi8vXG4vLyAgICAgICAgICAgICAgICAgICAgICAgIHNlbGYuYmFzZWxpbmVTdGF0c1JlcG9ydCA9IHNlbGYuY3VycmVudFN0YXRzUmVwb3J0O1xuLy8gICAgICAgICAgICAgICAgICAgIH0sXG4vLyAgICAgICAgICAgICAgICAgICAgc2VsZi5lcnJvckNhbGxiYWNrXG4vLyAgICAgICAgICAgICAgICApO1xuLy8gICAgICAgICAgICB9LFxuLy8gICAgICAgICAgICBzZWxmLnN0YXRzSW50ZXJ2YWxNaWxpc1xuLy8gICAgICAgICk7XG4vLyAgICB9XG4vL1xuLy8gICAgaWYgKHRoaXMuY29uZmlnLmxvZ1N0YXRzICYmIGJyb3dzZXJTdXBwb3J0ZWQpIHtcbi8vICAgICAgICB0aGlzLmdhdGhlclN0YXRzSW50ZXJ2YWxJZCA9IHNldEludGVydmFsKFxuLy8gICAgICAgICAgICBmdW5jdGlvbiAoKSB7XG4vLyAgICAgICAgICAgICAgICBzZWxmLnBlZXJjb25uZWN0aW9uLmdldFN0YXRzKFxuLy8gICAgICAgICAgICAgICAgICAgIGZ1bmN0aW9uIChyZXBvcnQpIHtcbi8vICAgICAgICAgICAgICAgICAgICAgICAgc2VsZi5hZGRTdGF0c1RvQmVMb2dnZWQocmVwb3J0LnJlc3VsdCgpKTtcbi8vICAgICAgICAgICAgICAgICAgICB9LFxuLy8gICAgICAgICAgICAgICAgICAgIGZ1bmN0aW9uICgpIHtcbi8vICAgICAgICAgICAgICAgICAgICB9XG4vLyAgICAgICAgICAgICAgICApO1xuLy8gICAgICAgICAgICB9LFxuLy8gICAgICAgICAgICB0aGlzLkdBVEhFUl9JTlRFUlZBTFxuLy8gICAgICAgICk7XG4vL1xuLy8gICAgICAgIHRoaXMubG9nU3RhdHNJbnRlcnZhbElkID0gc2V0SW50ZXJ2YWwoXG4vLyAgICAgICAgICAgIGZ1bmN0aW9uKCkgeyBzZWxmLmxvZ1N0YXRzKCk7IH0sXG4vLyAgICAgICAgICAgIHRoaXMuTE9HX0lOVEVSVkFMKTtcbi8vICAgIH1cbn07XG5cbi8qKlxuICogQ29udmVydHMgdGhlIHN0YXRzIHRvIHRoZSBmb3JtYXQgdXNlZCBmb3IgbG9nZ2luZywgYW5kIHNhdmVzIHRoZSBkYXRhIGluXG4gKiB0aGlzLnN0YXRzVG9CZUxvZ2dlZC5cbiAqIEBwYXJhbSByZXBvcnRzIFJlcG9ydHMgYXMgZ2l2ZW4gYnkgd2Via2l0UlRDUGVyQ29ubmVjdGlvbi5nZXRTdGF0cy5cbiAqL1xuU3RhdHNDb2xsZWN0b3IucHJvdG90eXBlLmFkZFN0YXRzVG9CZUxvZ2dlZCA9IGZ1bmN0aW9uIChyZXBvcnRzKSB7XG4gICAgdmFyIHNlbGYgPSB0aGlzO1xuICAgIHZhciBudW1fcmVjb3JkcyA9IHRoaXMuc3RhdHNUb0JlTG9nZ2VkLnRpbWVzdGFtcHMubGVuZ3RoO1xuICAgIHRoaXMuc3RhdHNUb0JlTG9nZ2VkLnRpbWVzdGFtcHMucHVzaChuZXcgRGF0ZSgpLmdldFRpbWUoKSk7XG4gICAgcmVwb3J0cy5tYXAoZnVuY3Rpb24gKHJlcG9ydCkge1xuICAgICAgICBpZiAoIWFjY2VwdFJlcG9ydChyZXBvcnQuaWQsIHJlcG9ydC50eXBlKSlcbiAgICAgICAgICAgIHJldHVybjtcbiAgICAgICAgdmFyIHN0YXQgPSBzZWxmLnN0YXRzVG9CZUxvZ2dlZC5zdGF0c1tyZXBvcnQuaWRdO1xuICAgICAgICBpZiAoIXN0YXQpIHtcbiAgICAgICAgICAgIHN0YXQgPSBzZWxmLnN0YXRzVG9CZUxvZ2dlZC5zdGF0c1tyZXBvcnQuaWRdID0ge307XG4gICAgICAgIH1cbiAgICAgICAgc3RhdC50eXBlID0gcmVwb3J0LnR5cGU7XG4gICAgICAgIHJlcG9ydC5uYW1lcygpLm1hcChmdW5jdGlvbiAobmFtZSkge1xuICAgICAgICAgICAgaWYgKCFhY2NlcHRTdGF0KHJlcG9ydC5pZCwgcmVwb3J0LnR5cGUsIG5hbWUpKVxuICAgICAgICAgICAgICAgIHJldHVybjtcbiAgICAgICAgICAgIHZhciB2YWx1ZXMgPSBzdGF0W25hbWVdO1xuICAgICAgICAgICAgaWYgKCF2YWx1ZXMpIHtcbiAgICAgICAgICAgICAgICB2YWx1ZXMgPSBzdGF0W25hbWVdID0gW107XG4gICAgICAgICAgICB9XG4gICAgICAgICAgICB3aGlsZSAodmFsdWVzLmxlbmd0aCA8IG51bV9yZWNvcmRzKSB7XG4gICAgICAgICAgICAgICAgdmFsdWVzLnB1c2gobnVsbCk7XG4gICAgICAgICAgICB9XG4gICAgICAgICAgICB2YWx1ZXMucHVzaChyZXBvcnQuc3RhdChuYW1lKSk7XG4gICAgICAgIH0pO1xuICAgIH0pO1xufTtcblxuXG4vL0ZJWE1FOlxuLy9TdGF0c0NvbGxlY3Rvci5wcm90b3R5cGUubG9nU3RhdHMgPSBmdW5jdGlvbiAoKSB7XG4vL1xuLy8gICAgaWYoIUFQUC54bXBwLnNlbmRMb2dzKHRoaXMuc3RhdHNUb0JlTG9nZ2VkKSlcbi8vICAgICAgICByZXR1cm47XG4vLyAgICAvLyBSZXNldCB0aGUgc3RhdHNcbi8vICAgIHRoaXMuc3RhdHNUb0JlTG9nZ2VkLnN0YXRzID0ge307XG4vLyAgICB0aGlzLnN0YXRzVG9CZUxvZ2dlZC50aW1lc3RhbXBzID0gW107XG4vL307XG5cblxuLyoqXG4gKiBTdGF0cyBwcm9jZXNzaW5nIGxvZ2ljLlxuICovXG5TdGF0c0NvbGxlY3Rvci5wcm90b3R5cGUucHJvY2Vzc1N0YXRzUmVwb3J0ID0gZnVuY3Rpb24gKCkge1xuICAgIGlmICghdGhpcy5iYXNlbGluZVN0YXRzUmVwb3J0KSB7XG4gICAgICAgIHJldHVybjtcbiAgICB9XG5cbiAgICBmb3IgKHZhciBpZHggaW4gdGhpcy5jdXJyZW50U3RhdHNSZXBvcnQpIHtcbiAgICAgICAgdmFyIG5vdyA9IHRoaXMuY3VycmVudFN0YXRzUmVwb3J0W2lkeF07XG4gICAgICAgIHRyeSB7XG4gICAgICAgICAgICBpZiAoZ2V0U3RhdFZhbHVlKG5vdywgJ3JlY2VpdmVCYW5kd2lkdGgnKSB8fFxuICAgICAgICAgICAgICAgIGdldFN0YXRWYWx1ZShub3csICdzZW5kQmFuZHdpZHRoJykpIHtcbiAgICAgICAgICAgICAgICB0aGlzLmNvbmZlcmVuY2VTdGF0cy5iYW5kd2lkdGggPSB7XG4gICAgICAgICAgICAgICAgICAgIFwiZG93bmxvYWRcIjogTWF0aC5yb3VuZChcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAoZ2V0U3RhdFZhbHVlKG5vdywgJ3JlY2VpdmVCYW5kd2lkdGgnKSkgLyAxMDAwKSxcbiAgICAgICAgICAgICAgICAgICAgXCJ1cGxvYWRcIjogTWF0aC5yb3VuZChcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAoZ2V0U3RhdFZhbHVlKG5vdywgJ3NlbmRCYW5kd2lkdGgnKSkgLyAxMDAwKVxuICAgICAgICAgICAgICAgIH07XG4gICAgICAgICAgICB9XG4gICAgICAgIH1cbiAgICAgICAgY2F0Y2goZSl7Lypub3Qgc3VwcG9ydGVkKi99XG5cbiAgICAgICAgaWYobm93LnR5cGUgPT0gJ2dvb2dDYW5kaWRhdGVQYWlyJylcbiAgICAgICAge1xuICAgICAgICAgICAgdmFyIGlwLCB0eXBlLCBsb2NhbElQLCBhY3RpdmU7XG4gICAgICAgICAgICB0cnkge1xuICAgICAgICAgICAgICAgIGlwID0gZ2V0U3RhdFZhbHVlKG5vdywgJ3JlbW90ZUFkZHJlc3MnKTtcbiAgICAgICAgICAgICAgICB0eXBlID0gZ2V0U3RhdFZhbHVlKG5vdywgXCJ0cmFuc3BvcnRUeXBlXCIpO1xuICAgICAgICAgICAgICAgIGxvY2FsSVAgPSBnZXRTdGF0VmFsdWUobm93LCBcImxvY2FsQWRkcmVzc1wiKTtcbiAgICAgICAgICAgICAgICBhY3RpdmUgPSBnZXRTdGF0VmFsdWUobm93LCBcImFjdGl2ZUNvbm5lY3Rpb25cIik7XG4gICAgICAgICAgICB9XG4gICAgICAgICAgICBjYXRjaChlKXsvKm5vdCBzdXBwb3J0ZWQqL31cbiAgICAgICAgICAgIGlmKCFpcCB8fCAhdHlwZSB8fCAhbG9jYWxJUCB8fCBhY3RpdmUgIT0gXCJ0cnVlXCIpXG4gICAgICAgICAgICAgICAgY29udGludWU7XG4gICAgICAgICAgICB2YXIgYWRkcmVzc1NhdmVkID0gZmFsc2U7XG4gICAgICAgICAgICBmb3IodmFyIGkgPSAwOyBpIDwgdGhpcy5jb25mZXJlbmNlU3RhdHMudHJhbnNwb3J0Lmxlbmd0aDsgaSsrKVxuICAgICAgICAgICAge1xuICAgICAgICAgICAgICAgIGlmKHRoaXMuY29uZmVyZW5jZVN0YXRzLnRyYW5zcG9ydFtpXS5pcCA9PSBpcCAmJlxuICAgICAgICAgICAgICAgICAgICB0aGlzLmNvbmZlcmVuY2VTdGF0cy50cmFuc3BvcnRbaV0udHlwZSA9PSB0eXBlICYmXG4gICAgICAgICAgICAgICAgICAgIHRoaXMuY29uZmVyZW5jZVN0YXRzLnRyYW5zcG9ydFtpXS5sb2NhbGlwID09IGxvY2FsSVApXG4gICAgICAgICAgICAgICAge1xuICAgICAgICAgICAgICAgICAgICBhZGRyZXNzU2F2ZWQgPSB0cnVlO1xuICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgIH1cbiAgICAgICAgICAgIGlmKGFkZHJlc3NTYXZlZClcbiAgICAgICAgICAgICAgICBjb250aW51ZTtcbiAgICAgICAgICAgIHRoaXMuY29uZmVyZW5jZVN0YXRzLnRyYW5zcG9ydC5wdXNoKHtsb2NhbGlwOiBsb2NhbElQLCBpcDogaXAsIHR5cGU6IHR5cGV9KTtcbiAgICAgICAgICAgIGNvbnRpbnVlO1xuICAgICAgICB9XG5cbiAgICAgICAgaWYobm93LnR5cGUgPT0gXCJjYW5kaWRhdGVwYWlyXCIpXG4gICAgICAgIHtcbiAgICAgICAgICAgIGlmKG5vdy5zdGF0ZSA9PSBcInN1Y2NlZWRlZFwiKVxuICAgICAgICAgICAgICAgIGNvbnRpbnVlO1xuXG4gICAgICAgICAgICB2YXIgbG9jYWwgPSB0aGlzLmN1cnJlbnRTdGF0c1JlcG9ydFtub3cubG9jYWxDYW5kaWRhdGVJZF07XG4gICAgICAgICAgICB2YXIgcmVtb3RlID0gdGhpcy5jdXJyZW50U3RhdHNSZXBvcnRbbm93LnJlbW90ZUNhbmRpZGF0ZUlkXTtcbiAgICAgICAgICAgIHRoaXMuY29uZmVyZW5jZVN0YXRzLnRyYW5zcG9ydC5wdXNoKHtsb2NhbGlwOiBsb2NhbC5pcEFkZHJlc3MgKyBcIjpcIiArIGxvY2FsLnBvcnROdW1iZXIsXG4gICAgICAgICAgICAgICAgaXA6IHJlbW90ZS5pcEFkZHJlc3MgKyBcIjpcIiArIHJlbW90ZS5wb3J0TnVtYmVyLCB0eXBlOiBsb2NhbC50cmFuc3BvcnR9KTtcblxuICAgICAgICB9XG5cbiAgICAgICAgaWYgKG5vdy50eXBlICE9ICdzc3JjJyAmJiBub3cudHlwZSAhPSBcIm91dGJvdW5kcnRwXCIgJiZcbiAgICAgICAgICAgIG5vdy50eXBlICE9IFwiaW5ib3VuZHJ0cFwiKSB7XG4gICAgICAgICAgICBjb250aW51ZTtcbiAgICAgICAgfVxuXG4gICAgICAgIHZhciBiZWZvcmUgPSB0aGlzLmJhc2VsaW5lU3RhdHNSZXBvcnRbaWR4XTtcbiAgICAgICAgaWYgKCFiZWZvcmUpIHtcbiAgICAgICAgICAgIGxvZ2dlci53YXJuKGdldFN0YXRWYWx1ZShub3csICdzc3JjJykgKyAnIG5vdCBlbm91Z2ggZGF0YScpO1xuICAgICAgICAgICAgY29udGludWU7XG4gICAgICAgIH1cblxuICAgICAgICB2YXIgc3NyYyA9IGdldFN0YXRWYWx1ZShub3csICdzc3JjJyk7XG4gICAgICAgIGlmKCFzc3JjKVxuICAgICAgICAgICAgY29udGludWU7XG5cbiAgICAgICAgdmFyIHNzcmNTdGF0cyA9IHRoaXMuc3NyYzJzdGF0c1tzc3JjXTtcbiAgICAgICAgaWYgKCFzc3JjU3RhdHMpIHtcbiAgICAgICAgICAgIHNzcmNTdGF0cyA9IG5ldyBQZWVyU3RhdHMoKTtcbiAgICAgICAgICAgIHRoaXMuc3NyYzJzdGF0c1tzc3JjXSA9IHNzcmNTdGF0cztcbiAgICAgICAgfVxuXG5cbiAgICAgICAgdmFyIGlzRG93bmxvYWRTdHJlYW0gPSB0cnVlO1xuICAgICAgICB2YXIga2V5ID0gJ3BhY2tldHNSZWNlaXZlZCc7XG4gICAgICAgIHZhciBwYWNrZXRzTm93ID0gZ2V0U3RhdFZhbHVlKG5vdywga2V5KTtcbiAgICAgICAgaWYgKHR5cGVvZiBwYWNrZXRzTm93ID09PSAndW5kZWZpbmVkJyB8fCBwYWNrZXRzTm93ID09PSBudWxsKSB7XG4gICAgICAgICAgICBpc0Rvd25sb2FkU3RyZWFtID0gZmFsc2U7XG4gICAgICAgICAgICBrZXkgPSAncGFja2V0c1NlbnQnO1xuICAgICAgICAgICAgcGFja2V0c05vdyA9IGdldFN0YXRWYWx1ZShub3csIGtleSk7XG4gICAgICAgICAgICBpZiAodHlwZW9mIHBhY2tldHNOb3cgPT09ICd1bmRlZmluZWQnIHx8IHBhY2tldHNOb3cgPT09IG51bGwpIHtcbiAgICAgICAgICAgICAgICBjb25zb2xlLndhcm4oXCJObyBwYWNrZXRzUmVjZWl2ZWQgbm9yIHBhY2tldHNTZW50IHN0YXQgZm91bmRcIik7XG4gICAgICAgICAgICAgICAgY29udGludWU7XG4gICAgICAgICAgICB9XG4gICAgICAgIH1cbiAgICAgICAgaWYgKCFwYWNrZXRzTm93IHx8IHBhY2tldHNOb3cgPCAwKVxuICAgICAgICAgICAgcGFja2V0c05vdyA9IDA7XG5cbiAgICAgICAgdmFyIHBhY2tldHNCZWZvcmUgPSBnZXRTdGF0VmFsdWUoYmVmb3JlLCBrZXkpO1xuICAgICAgICBpZiAoIXBhY2tldHNCZWZvcmUgfHwgcGFja2V0c0JlZm9yZSA8IDApXG4gICAgICAgICAgICBwYWNrZXRzQmVmb3JlID0gMDtcbiAgICAgICAgdmFyIHBhY2tldFJhdGUgPSBwYWNrZXRzTm93IC0gcGFja2V0c0JlZm9yZTtcbiAgICAgICAgaWYgKCFwYWNrZXRSYXRlIHx8IHBhY2tldFJhdGUgPCAwKVxuICAgICAgICAgICAgcGFja2V0UmF0ZSA9IDA7XG4gICAgICAgIHZhciBjdXJyZW50TG9zcyA9IGdldFN0YXRWYWx1ZShub3csICdwYWNrZXRzTG9zdCcpO1xuICAgICAgICBpZiAoIWN1cnJlbnRMb3NzIHx8IGN1cnJlbnRMb3NzIDwgMClcbiAgICAgICAgICAgIGN1cnJlbnRMb3NzID0gMDtcbiAgICAgICAgdmFyIHByZXZpb3VzTG9zcyA9IGdldFN0YXRWYWx1ZShiZWZvcmUsICdwYWNrZXRzTG9zdCcpO1xuICAgICAgICBpZiAoIXByZXZpb3VzTG9zcyB8fCBwcmV2aW91c0xvc3MgPCAwKVxuICAgICAgICAgICAgcHJldmlvdXNMb3NzID0gMDtcbiAgICAgICAgdmFyIGxvc3NSYXRlID0gY3VycmVudExvc3MgLSBwcmV2aW91c0xvc3M7XG4gICAgICAgIGlmICghbG9zc1JhdGUgfHwgbG9zc1JhdGUgPCAwKVxuICAgICAgICAgICAgbG9zc1JhdGUgPSAwO1xuICAgICAgICB2YXIgcGFja2V0c1RvdGFsID0gKHBhY2tldFJhdGUgKyBsb3NzUmF0ZSk7XG5cbiAgICAgICAgc3NyY1N0YXRzLnNldFNzcmNMb3NzKHNzcmMsXG4gICAgICAgICAgICB7XCJwYWNrZXRzVG90YWxcIjogcGFja2V0c1RvdGFsLFxuICAgICAgICAgICAgICAgIFwicGFja2V0c0xvc3RcIjogbG9zc1JhdGUsXG4gICAgICAgICAgICAgICAgXCJpc0Rvd25sb2FkU3RyZWFtXCI6IGlzRG93bmxvYWRTdHJlYW19KTtcblxuXG4gICAgICAgIHZhciBieXRlc1JlY2VpdmVkID0gMCwgYnl0ZXNTZW50ID0gMDtcbiAgICAgICAgaWYoZ2V0U3RhdFZhbHVlKG5vdywgXCJieXRlc1JlY2VpdmVkXCIpKSB7XG4gICAgICAgICAgICBieXRlc1JlY2VpdmVkID0gZ2V0U3RhdFZhbHVlKG5vdywgXCJieXRlc1JlY2VpdmVkXCIpIC1cbiAgICAgICAgICAgICAgICBnZXRTdGF0VmFsdWUoYmVmb3JlLCBcImJ5dGVzUmVjZWl2ZWRcIik7XG4gICAgICAgIH1cblxuICAgICAgICBpZiAoZ2V0U3RhdFZhbHVlKG5vdywgXCJieXRlc1NlbnRcIikpIHtcbiAgICAgICAgICAgIGJ5dGVzU2VudCA9IGdldFN0YXRWYWx1ZShub3csIFwiYnl0ZXNTZW50XCIpIC1cbiAgICAgICAgICAgICAgICBnZXRTdGF0VmFsdWUoYmVmb3JlLCBcImJ5dGVzU2VudFwiKTtcbiAgICAgICAgfVxuXG4gICAgICAgIHZhciB0aW1lID0gTWF0aC5yb3VuZCgobm93LnRpbWVzdGFtcCAtIGJlZm9yZS50aW1lc3RhbXApIC8gMTAwMCk7XG4gICAgICAgIGlmIChieXRlc1JlY2VpdmVkIDw9IDAgfHwgdGltZSA8PSAwKSB7XG4gICAgICAgICAgICBieXRlc1JlY2VpdmVkID0gMDtcbiAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgIGJ5dGVzUmVjZWl2ZWQgPSBNYXRoLnJvdW5kKCgoYnl0ZXNSZWNlaXZlZCAqIDgpIC8gdGltZSkgLyAxMDAwKTtcbiAgICAgICAgfVxuXG4gICAgICAgIGlmIChieXRlc1NlbnQgPD0gMCB8fCB0aW1lIDw9IDApIHtcbiAgICAgICAgICAgIGJ5dGVzU2VudCA9IDA7XG4gICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICBieXRlc1NlbnQgPSBNYXRoLnJvdW5kKCgoYnl0ZXNTZW50ICogOCkgLyB0aW1lKSAvIDEwMDApO1xuICAgICAgICB9XG5cbiAgICAgICAgc3NyY1N0YXRzLnNldFNzcmNCaXRyYXRlKHNzcmMsIHtcbiAgICAgICAgICAgIFwiZG93bmxvYWRcIjogYnl0ZXNSZWNlaXZlZCxcbiAgICAgICAgICAgIFwidXBsb2FkXCI6IGJ5dGVzU2VudH0pO1xuXG4gICAgICAgIHZhciByZXNvbHV0aW9uID0ge2hlaWdodDogbnVsbCwgd2lkdGg6IG51bGx9O1xuICAgICAgICB0cnkge1xuICAgICAgICAgICAgaWYgKGdldFN0YXRWYWx1ZShub3csIFwiZ29vZ0ZyYW1lSGVpZ2h0UmVjZWl2ZWRcIikgJiZcbiAgICAgICAgICAgICAgICBnZXRTdGF0VmFsdWUobm93LCBcImdvb2dGcmFtZVdpZHRoUmVjZWl2ZWRcIikpIHtcbiAgICAgICAgICAgICAgICByZXNvbHV0aW9uLmhlaWdodCA9XG4gICAgICAgICAgICAgICAgICAgIGdldFN0YXRWYWx1ZShub3csIFwiZ29vZ0ZyYW1lSGVpZ2h0UmVjZWl2ZWRcIik7XG4gICAgICAgICAgICAgICAgcmVzb2x1dGlvbi53aWR0aCA9IGdldFN0YXRWYWx1ZShub3csIFwiZ29vZ0ZyYW1lV2lkdGhSZWNlaXZlZFwiKTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgICAgIGVsc2UgaWYgKGdldFN0YXRWYWx1ZShub3csIFwiZ29vZ0ZyYW1lSGVpZ2h0U2VudFwiKSAmJlxuICAgICAgICAgICAgICAgIGdldFN0YXRWYWx1ZShub3csIFwiZ29vZ0ZyYW1lV2lkdGhTZW50XCIpKSB7XG4gICAgICAgICAgICAgICAgcmVzb2x1dGlvbi5oZWlnaHQgPSBnZXRTdGF0VmFsdWUobm93LCBcImdvb2dGcmFtZUhlaWdodFNlbnRcIik7XG4gICAgICAgICAgICAgICAgcmVzb2x1dGlvbi53aWR0aCA9IGdldFN0YXRWYWx1ZShub3csIFwiZ29vZ0ZyYW1lV2lkdGhTZW50XCIpO1xuICAgICAgICAgICAgfVxuICAgICAgICB9XG4gICAgICAgIGNhdGNoKGUpey8qbm90IHN1cHBvcnRlZCovfVxuXG4gICAgICAgIGlmIChyZXNvbHV0aW9uLmhlaWdodCAmJiByZXNvbHV0aW9uLndpZHRoKSB7XG4gICAgICAgICAgICBzc3JjU3RhdHMuc2V0U3NyY1Jlc29sdXRpb24oc3NyYywgcmVzb2x1dGlvbik7XG4gICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICBzc3JjU3RhdHMuc2V0U3NyY1Jlc29sdXRpb24oc3NyYywgbnVsbCk7XG4gICAgICAgIH1cbiAgICB9XG5cbiAgICB2YXIgc2VsZiA9IHRoaXM7XG4gICAgLy8gSmlkIHN0YXRzXG4gICAgdmFyIHRvdGFsUGFja2V0cyA9IHtkb3dubG9hZDogMCwgdXBsb2FkOiAwfTtcbiAgICB2YXIgbG9zdFBhY2tldHMgPSB7ZG93bmxvYWQ6IDAsIHVwbG9hZDogMH07XG4gICAgdmFyIGJpdHJhdGVEb3dubG9hZCA9IDA7XG4gICAgdmFyIGJpdHJhdGVVcGxvYWQgPSAwO1xuICAgIHZhciByZXNvbHV0aW9ucyA9IHt9O1xuICAgIE9iamVjdC5rZXlzKHRoaXMuc3NyYzJzdGF0cykuZm9yRWFjaChcbiAgICAgICAgZnVuY3Rpb24gKGppZCkge1xuICAgICAgICAgICAgT2JqZWN0LmtleXMoc2VsZi5zc3JjMnN0YXRzW2ppZF0uc3NyYzJMb3NzKS5mb3JFYWNoKFxuICAgICAgICAgICAgICAgIGZ1bmN0aW9uIChzc3JjKSB7XG4gICAgICAgICAgICAgICAgICAgIHZhciB0eXBlID0gXCJ1cGxvYWRcIjtcbiAgICAgICAgICAgICAgICAgICAgaWYoc2VsZi5zc3JjMnN0YXRzW2ppZF0uc3NyYzJMb3NzW3NzcmNdLmlzRG93bmxvYWRTdHJlYW0pXG4gICAgICAgICAgICAgICAgICAgICAgICB0eXBlID0gXCJkb3dubG9hZFwiO1xuICAgICAgICAgICAgICAgICAgICB0b3RhbFBhY2tldHNbdHlwZV0gKz1cbiAgICAgICAgICAgICAgICAgICAgICAgIHNlbGYuc3NyYzJzdGF0c1tqaWRdLnNzcmMyTG9zc1tzc3JjXS5wYWNrZXRzVG90YWw7XG4gICAgICAgICAgICAgICAgICAgIGxvc3RQYWNrZXRzW3R5cGVdICs9XG4gICAgICAgICAgICAgICAgICAgICAgICBzZWxmLnNzcmMyc3RhdHNbamlkXS5zc3JjMkxvc3Nbc3NyY10ucGFja2V0c0xvc3Q7XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgKTtcbiAgICAgICAgICAgIE9iamVjdC5rZXlzKHNlbGYuc3NyYzJzdGF0c1tqaWRdLnNzcmMyYml0cmF0ZSkuZm9yRWFjaChcbiAgICAgICAgICAgICAgICBmdW5jdGlvbiAoc3NyYykge1xuICAgICAgICAgICAgICAgICAgICBiaXRyYXRlRG93bmxvYWQgKz1cbiAgICAgICAgICAgICAgICAgICAgICAgIHNlbGYuc3NyYzJzdGF0c1tqaWRdLnNzcmMyYml0cmF0ZVtzc3JjXS5kb3dubG9hZDtcbiAgICAgICAgICAgICAgICAgICAgYml0cmF0ZVVwbG9hZCArPVxuICAgICAgICAgICAgICAgICAgICAgICAgc2VsZi5zc3JjMnN0YXRzW2ppZF0uc3NyYzJiaXRyYXRlW3NzcmNdLnVwbG9hZDtcblxuICAgICAgICAgICAgICAgICAgICBkZWxldGUgc2VsZi5zc3JjMnN0YXRzW2ppZF0uc3NyYzJiaXRyYXRlW3NzcmNdO1xuICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICk7XG4gICAgICAgICAgICByZXNvbHV0aW9uc1tqaWRdID0gc2VsZi5zc3JjMnN0YXRzW2ppZF0uc3NyYzJyZXNvbHV0aW9uO1xuICAgICAgICB9XG4gICAgKTtcblxuICAgIHRoaXMuY29uZmVyZW5jZVN0YXRzLmJpdHJhdGUgPSB7XCJ1cGxvYWRcIjogYml0cmF0ZVVwbG9hZCwgXCJkb3dubG9hZFwiOiBiaXRyYXRlRG93bmxvYWR9O1xuXG4gICAgdGhpcy5jb25mZXJlbmNlU3RhdHMucGFja2V0TG9zcyA9IHtcbiAgICAgICAgdG90YWw6XG4gICAgICAgICAgICBjYWxjdWxhdGVQYWNrZXRMb3NzKGxvc3RQYWNrZXRzLmRvd25sb2FkICsgbG9zdFBhY2tldHMudXBsb2FkLFxuICAgICAgICAgICAgICAgICAgICB0b3RhbFBhY2tldHMuZG93bmxvYWQgKyB0b3RhbFBhY2tldHMudXBsb2FkKSxcbiAgICAgICAgZG93bmxvYWQ6XG4gICAgICAgICAgICBjYWxjdWxhdGVQYWNrZXRMb3NzKGxvc3RQYWNrZXRzLmRvd25sb2FkLCB0b3RhbFBhY2tldHMuZG93bmxvYWQpLFxuICAgICAgICB1cGxvYWQ6XG4gICAgICAgICAgICBjYWxjdWxhdGVQYWNrZXRMb3NzKGxvc3RQYWNrZXRzLnVwbG9hZCwgdG90YWxQYWNrZXRzLnVwbG9hZClcbiAgICB9O1xuICAgIHRoaXMuZXZlbnRFbWl0dGVyLmVtaXQoU3RhdGlzdGljc0V2ZW50cy5DT05ORUNUSU9OX1NUQVRTLFxuICAgICAgICB7XG4gICAgICAgICAgICBcImJpdHJhdGVcIjogdGhpcy5jb25mZXJlbmNlU3RhdHMuYml0cmF0ZSxcbiAgICAgICAgICAgIFwicGFja2V0TG9zc1wiOiB0aGlzLmNvbmZlcmVuY2VTdGF0cy5wYWNrZXRMb3NzLFxuICAgICAgICAgICAgXCJiYW5kd2lkdGhcIjogdGhpcy5jb25mZXJlbmNlU3RhdHMuYmFuZHdpZHRoLFxuICAgICAgICAgICAgXCJyZXNvbHV0aW9uXCI6IHJlc29sdXRpb25zLFxuICAgICAgICAgICAgXCJ0cmFuc3BvcnRcIjogdGhpcy5jb25mZXJlbmNlU3RhdHMudHJhbnNwb3J0XG4gICAgICAgIH0pO1xuICAgIHRoaXMuY29uZmVyZW5jZVN0YXRzLnRyYW5zcG9ydCA9IFtdO1xuXG59O1xuXG4vKipcbiAqIFN0YXRzIHByb2Nlc3NpbmcgbG9naWMuXG4gKi9cblN0YXRzQ29sbGVjdG9yLnByb3RvdHlwZS5wcm9jZXNzQXVkaW9MZXZlbFJlcG9ydCA9IGZ1bmN0aW9uICgpIHtcbiAgICBpZiAoIXRoaXMuYmFzZWxpbmVBdWRpb0xldmVsc1JlcG9ydCkge1xuICAgICAgICByZXR1cm47XG4gICAgfVxuXG4gICAgZm9yICh2YXIgaWR4IGluIHRoaXMuY3VycmVudEF1ZGlvTGV2ZWxzUmVwb3J0KSB7XG4gICAgICAgIHZhciBub3cgPSB0aGlzLmN1cnJlbnRBdWRpb0xldmVsc1JlcG9ydFtpZHhdO1xuXG4gICAgICAgIC8vaWYgd2UgZG9uJ3QgaGF2ZSBcInBhY2tldHNSZWNlaXZlZFwiIHRoaXMgaXMgbG9jYWwgc3RyZWFtXG4gICAgICAgIGlmIChub3cudHlwZSAhPSAnc3NyYycgfHwgIWdldFN0YXRWYWx1ZShub3csICdwYWNrZXRzUmVjZWl2ZWQnKSkge1xuICAgICAgICAgICAgY29udGludWU7XG4gICAgICAgIH1cblxuICAgICAgICB2YXIgYmVmb3JlID0gdGhpcy5iYXNlbGluZUF1ZGlvTGV2ZWxzUmVwb3J0W2lkeF07XG4gICAgICAgIGlmICghYmVmb3JlKSB7XG4gICAgICAgICAgICBsb2dnZXIud2FybihnZXRTdGF0VmFsdWUobm93LCAnc3NyYycpICsgJyBub3QgZW5vdWdoIGRhdGEnKTtcbiAgICAgICAgICAgIGNvbnRpbnVlO1xuICAgICAgICB9XG5cbiAgICAgICAgdmFyIHNzcmMgPSBnZXRTdGF0VmFsdWUobm93LCAnc3NyYycpO1xuICAgICAgICBpZiAoIXNzcmMpIHtcbiAgICAgICAgICAgIGlmKChEYXRlLm5vdygpIC0gbm93LnRpbWVzdGFtcCkgPCAzMDAwKVxuICAgICAgICAgICAgICAgIGxvZ2dlci53YXJuKFwiTm8gc3NyYzogXCIpO1xuICAgICAgICAgICAgY29udGludWU7XG4gICAgICAgIH1cblxuICAgICAgICB2YXIgc3NyY1N0YXRzID0gdGhpcy5zc3JjMnN0YXRzW3NzcmNdO1xuICAgICAgICBpZiAoIXNzcmNTdGF0cykge1xuICAgICAgICAgICAgc3NyY1N0YXRzID0gbmV3IFBlZXJTdGF0cygpO1xuICAgICAgICAgICAgdGhpcy5zc3JjMnN0YXRzW3NzcmNdID0gc3NyY1N0YXRzO1xuICAgICAgICB9XG5cbiAgICAgICAgLy8gQXVkaW8gbGV2ZWxcbiAgICAgICAgdmFyIGF1ZGlvTGV2ZWwgPSBudWxsO1xuXG4gICAgICAgIHRyeSB7XG4gICAgICAgICAgICBhdWRpb0xldmVsID0gZ2V0U3RhdFZhbHVlKG5vdywgJ2F1ZGlvSW5wdXRMZXZlbCcpO1xuICAgICAgICAgICAgaWYgKCFhdWRpb0xldmVsKVxuICAgICAgICAgICAgICAgIGF1ZGlvTGV2ZWwgPSBnZXRTdGF0VmFsdWUobm93LCAnYXVkaW9PdXRwdXRMZXZlbCcpO1xuICAgICAgICB9XG4gICAgICAgIGNhdGNoKGUpIHsvKm5vdCBzdXBwb3J0ZWQqL1xuICAgICAgICAgICAgbG9nZ2VyLndhcm4oXCJBdWRpbyBMZXZlbHMgYXJlIG5vdCBhdmFpbGFibGUgaW4gdGhlIHN0YXRpc3RpY3MuXCIpO1xuICAgICAgICAgICAgY2xlYXJJbnRlcnZhbCh0aGlzLmF1ZGlvTGV2ZWxzSW50ZXJ2YWxJZCk7XG4gICAgICAgICAgICByZXR1cm47XG4gICAgICAgIH1cblxuICAgICAgICBpZiAoYXVkaW9MZXZlbCkge1xuICAgICAgICAgICAgLy8gVE9ETzogY2FuJ3QgZmluZCBzcGVjcyBhYm91dCB3aGF0IHRoaXMgdmFsdWUgcmVhbGx5IGlzLFxuICAgICAgICAgICAgLy8gYnV0IGl0IHNlZW1zIHRvIHZhcnkgYmV0d2VlbiAwIGFuZCBhcm91bmQgMzJrLlxuICAgICAgICAgICAgYXVkaW9MZXZlbCA9IGF1ZGlvTGV2ZWwgLyAzMjc2NztcbiAgICAgICAgICAgIHNzcmNTdGF0cy5zZXRTc3JjQXVkaW9MZXZlbChzc3JjLCBhdWRpb0xldmVsKTtcbiAgICAgICAgICAgIHRoaXMuZXZlbnRFbWl0dGVyLmVtaXQoXG4gICAgICAgICAgICAgICAgU3RhdGlzdGljc0V2ZW50cy5BVURJT19MRVZFTCwgc3NyYywgYXVkaW9MZXZlbCk7XG4gICAgICAgIH1cbiAgICB9XG59O1xuIiwiLyogZ2xvYmFsIHJlcXVpcmUsIEFQUCAqL1xudmFyIExvY2FsU3RhdHMgPSByZXF1aXJlKFwiLi9Mb2NhbFN0YXRzQ29sbGVjdG9yLmpzXCIpO1xudmFyIFJUUFN0YXRzID0gcmVxdWlyZShcIi4vUlRQU3RhdHNDb2xsZWN0b3IuanNcIik7XG52YXIgRXZlbnRFbWl0dGVyID0gcmVxdWlyZShcImV2ZW50c1wiKTtcbnZhciBTdGF0aXN0aWNzRXZlbnRzID0gcmVxdWlyZShcIi4uLy4uL3NlcnZpY2Uvc3RhdGlzdGljcy9FdmVudHNcIik7XG4vL3ZhciBTdHJlYW1FdmVudFR5cGVzID0gcmVxdWlyZShcIi4uLy4uL3NlcnZpY2UvUlRDL1N0cmVhbUV2ZW50VHlwZXMuanNcIik7XG4vL3ZhciBYTVBQRXZlbnRzID0gcmVxdWlyZShcIi4uLy4uL3NlcnZpY2UveG1wcC9YTVBQRXZlbnRzXCIpO1xuLy92YXIgQ2FsbFN0YXRzID0gcmVxdWlyZShcIi4vQ2FsbFN0YXRzXCIpO1xuLy92YXIgUlRDRXZlbnRzID0gcmVxdWlyZShcIi4uLy4uL3NlcnZpY2UvUlRDL1JUQ0V2ZW50c1wiKTtcblxuLy9cbi8vZnVuY3Rpb24gb25EaXNwb3NlQ29uZmVyZW5jZShvblVubG9hZCkge1xuLy8gICAgQ2FsbFN0YXRzLnNlbmRUZXJtaW5hdGVFdmVudCgpO1xuLy8gICAgc3RvcFJlbW90ZSgpO1xuLy8gICAgaWYob25VbmxvYWQpIHtcbi8vICAgICAgICBzdG9wTG9jYWwoKTtcbi8vICAgICAgICBldmVudEVtaXR0ZXIucmVtb3ZlQWxsTGlzdGVuZXJzKCk7XG4vLyAgICB9XG4vL31cblxudmFyIGV2ZW50RW1pdHRlciA9IG5ldyBFdmVudEVtaXR0ZXIoKTtcblxuZnVuY3Rpb24gU3RhdGlzdGljcygpIHtcbiAgICB0aGlzLnJ0cFN0YXRzID0gbnVsbDtcbiAgICB0aGlzLmV2ZW50RW1pdHRlciA9IG5ldyBFdmVudEVtaXR0ZXIoKTtcbn1cblxuU3RhdGlzdGljcy5wcm90b3R5cGUuc3RhcnRSZW1vdGVTdGF0cyA9IGZ1bmN0aW9uIChwZWVyY29ubmVjdGlvbikge1xuICAgIGlmICh0aGlzLnJ0cFN0YXRzKSB7XG4gICAgICAgIHRoaXMucnRwU3RhdHMuc3RvcCgpO1xuICAgIH1cblxuICAgIHRoaXMucnRwU3RhdHMgPSBuZXcgUlRQU3RhdHMocGVlcmNvbm5lY3Rpb24sIDIwMCwgMjAwMCwgdGhpcy5ldmVudEVtaXR0ZXIpO1xuICAgIHRoaXMucnRwU3RhdHMuc3RhcnQoKTtcbn1cblxuU3RhdGlzdGljcy5sb2NhbFN0YXRzID0gW107XG5cblN0YXRpc3RpY3Muc3RhcnRMb2NhbFN0YXRzID0gZnVuY3Rpb24gKHN0cmVhbSwgY2FsbGJhY2spIHtcbiAgICB2YXIgbG9jYWxTdGF0cyA9IG5ldyBMb2NhbFN0YXRzKHN0cmVhbSwgMjAwLCBjYWxsYmFjayk7XG4gICAgdGhpcy5sb2NhbFN0YXRzLnB1c2gobG9jYWxTdGF0cyk7XG4gICAgbG9jYWxTdGF0cy5zdGFydCgpO1xufVxuXG5TdGF0aXN0aWNzLnByb3RvdHlwZS5hZGRBdWRpb0xldmVsTGlzdGVuZXIgPSBmdW5jdGlvbihsaXN0ZW5lcilcbntcbiAgICB0aGlzLmV2ZW50RW1pdHRlci5vbihTdGF0aXN0aWNzRXZlbnRzLkFVRElPX0xFVkVMLCBsaXN0ZW5lcik7XG59XG5cblN0YXRpc3RpY3MucHJvdG90eXBlLnJlbW92ZUF1ZGlvTGV2ZWxMaXN0ZW5lciA9IGZ1bmN0aW9uKGxpc3RlbmVyKVxue1xuICAgIHRoaXMuZXZlbnRFbWl0dGVyLnJlbW92ZUxpc3RlbmVyKFN0YXRpc3RpY3NFdmVudHMuQVVESU9fTEVWRUwsIGxpc3RlbmVyKTtcbn1cblxuU3RhdGlzdGljcy5wcm90b3R5cGUuZGlzcG9zZSA9IGZ1bmN0aW9uICgpIHtcbiAgICBTdGF0aXN0aWNzLnN0b3BBbGxMb2NhbFN0YXRzKCk7XG4gICAgdGhpcy5zdG9wUmVtb3RlKCk7XG4gICAgaWYodGhpcy5ldmVudEVtaXR0ZXIpXG4gICAgICAgIHRoaXMuZXZlbnRFbWl0dGVyLnJlbW92ZUFsbExpc3RlbmVycygpO1xuXG4gICAgaWYoZXZlbnRFbWl0dGVyKVxuICAgICAgICBldmVudEVtaXR0ZXIucmVtb3ZlQWxsTGlzdGVuZXJzKCk7XG59XG5cblxuU3RhdGlzdGljcy5zdG9wQWxsTG9jYWxTdGF0cyA9IGZ1bmN0aW9uICgpIHtcbiAgICBmb3IodmFyIGkgPSAwOyBpIDwgdGhpcy5sb2NhbFN0YXRzLmxlbmd0aDsgaSsrKVxuICAgICAgICB0aGlzLmxvY2FsU3RhdHNbaV0uc3RvcCgpO1xuICAgIHRoaXMubG9jYWxTdGF0cyA9IFtdO1xufVxuXG5TdGF0aXN0aWNzLnN0b3BMb2NhbFN0YXRzID0gZnVuY3Rpb24gKHN0cmVhbSkge1xuICAgIGZvcih2YXIgaSA9IDA7IGkgPCBTdGF0aXN0aWNzLmxvY2FsU3RhdHMubGVuZ3RoOyBpKyspXG4gICAgICAgIGlmKFN0YXRpc3RpY3MubG9jYWxTdGF0c1tpXS5zdHJlYW0gPT09IHN0cmVhbSl7XG4gICAgICAgICAgICB2YXIgbG9jYWxTdGF0cyA9IFN0YXRpc3RpY3MubG9jYWxTdGF0cy5zcGxpY2UoaSwgMSk7XG4gICAgICAgICAgICBsb2NhbFN0YXRzLnN0b3AoKTtcbiAgICAgICAgICAgIGJyZWFrO1xuICAgICAgICB9XG59XG5cblN0YXRpc3RpY3MucHJvdG90eXBlLnN0b3BSZW1vdGUgPSBmdW5jdGlvbiAoKSB7XG4gICAgaWYgKHRoaXMucnRwU3RhdHMpIHtcbiAgICAgICAgdGhpcy5ydHBTdGF0cy5zdG9wKCk7XG4gICAgICAgIHRoaXMuZXZlbnRFbWl0dGVyLmVtaXQoU3RhdGlzdGljc0V2ZW50cy5TVE9QKTtcbiAgICAgICAgdGhpcy5ydHBTdGF0cyA9IG51bGw7XG4gICAgfVxufTtcblxuLyoqXG4gKiBPYnRhaW5zIGF1ZGlvIGxldmVsIHJlcG9ydGVkIGluIHRoZSBzdGF0cyBmb3Igc3BlY2lmaWVkIHBlZXIuXG4gKiBAcGFyYW0gcGVlckppZCBmdWxsIE1VQyBqaWQgb2YgdGhlIHVzZXIgZm9yIHdob20gd2Ugd2FudCB0byBvYnRhaW4gbGFzdFxuICogICAgICAgIGF1ZGlvIGxldmVsLlxuICogQHBhcmFtIHNzcmMgdGhlIFNTUkMgb2YgYXVkaW8gc3RyZWFtIGZvciB3aGljaCB3ZSB3YW50IHRvIG9idGFpbiBhdWRpb1xuICogICAgICAgIGxldmVsLlxuICogQHJldHVybnMgeyp9IGEgZmxvYXQgZm9ybSAwIHRvIDEgdGhhdCByZXByZXNlbnRzIGN1cnJlbnQgYXVkaW8gbGV2ZWwgb3JcbiAqICAgICAgICAgICAgICA8dHQ+bnVsbDwvdHQ+IGlmIGZvciBhbnkgcmVhc29uIHRoZSB2YWx1ZSBpcyBub3QgYXZhaWxhYmxlXG4gKiAgICAgICAgICAgICAgYXQgdGhpcyB0aW1lLlxuICovXG5TdGF0aXN0aWNzLnByb3RvdHlwZS5nZXRQZWVyU1NSQ0F1ZGlvTGV2ZWwgPSBmdW5jdGlvbiAocGVlckppZCwgc3NyYykge1xuXG4gICAgdmFyIHBlZXJTdGF0cyA9IHRoaXMucnRwU3RhdHMuamlkMnN0YXRzW3BlZXJKaWRdO1xuXG4gICAgcmV0dXJuIHBlZXJTdGF0cyA/IHBlZXJTdGF0cy5zc3JjMkF1ZGlvTGV2ZWxbc3NyY10gOiBudWxsO1xufTtcblxuU3RhdGlzdGljcy5MT0NBTF9KSUQgPSByZXF1aXJlKFwiLi4vLi4vc2VydmljZS9zdGF0aXN0aWNzL2NvbnN0YW50c1wiKS5MT0NBTF9KSUQ7XG5cbi8vXG4vL3ZhciBzdGF0aXN0aWNzID0ge1xuLy8gICAgLyoqXG4vLyAgICAgKiBJbmRpY2F0ZXMgdGhhdCB0aGlzIGF1ZGlvIGxldmVsIGlzIGZvciBsb2NhbCBqaWQuXG4vLyAgICAgKiBAdHlwZSB7c3RyaW5nfVxuLy8gICAgICovXG4vLyAgICBMT0NBTF9KSUQ6ICdsb2NhbCcsXG4vL1xuLy8gICAgYWRkQ29ubmVjdGlvblN0YXRzTGlzdGVuZXI6IGZ1bmN0aW9uKGxpc3RlbmVyKVxuLy8gICAge1xuLy8gICAgICAgIGV2ZW50RW1pdHRlci5vbihcInN0YXRpc3RpY3MuY29ubmVjdGlvbnN0YXRzXCIsIGxpc3RlbmVyKTtcbi8vICAgIH0sXG4vL1xuLy8gICAgcmVtb3ZlQ29ubmVjdGlvblN0YXRzTGlzdGVuZXI6IGZ1bmN0aW9uKGxpc3RlbmVyKVxuLy8gICAge1xuLy8gICAgICAgIGV2ZW50RW1pdHRlci5yZW1vdmVMaXN0ZW5lcihcInN0YXRpc3RpY3MuY29ubmVjdGlvbnN0YXRzXCIsIGxpc3RlbmVyKTtcbi8vICAgIH0sXG4vL1xuLy9cbi8vICAgIGFkZFJlbW90ZVN0YXRzU3RvcExpc3RlbmVyOiBmdW5jdGlvbihsaXN0ZW5lcilcbi8vICAgIHtcbi8vICAgICAgICBldmVudEVtaXR0ZXIub24oXCJzdGF0aXN0aWNzLnN0b3BcIiwgbGlzdGVuZXIpO1xuLy8gICAgfSxcbi8vXG4vLyAgICByZW1vdmVSZW1vdGVTdGF0c1N0b3BMaXN0ZW5lcjogZnVuY3Rpb24obGlzdGVuZXIpXG4vLyAgICB7XG4vLyAgICAgICAgZXZlbnRFbWl0dGVyLnJlbW92ZUxpc3RlbmVyKFwic3RhdGlzdGljcy5zdG9wXCIsIGxpc3RlbmVyKTtcbi8vICAgIH0sXG4vL1xuLy9cbi8vICAgIHN0b3BSZW1vdGVTdGF0aXN0aWNzOiBmdW5jdGlvbigpXG4vLyAgICB7XG4vLyAgICAgICAgc3RvcFJlbW90ZSgpO1xuLy8gICAgfSxcbi8vXG4vLy8vICAgIEFscmVhZHkgaW1wbGVtZW50ZWQgd2l0aCB0aGUgY29uc3RydWN0b3Jcbi8vICAgIHN0YXJ0OiBmdW5jdGlvbiAoKSB7XG4vLyAgICAgICAgQVBQLlJUQy5hZGRTdHJlYW1MaXN0ZW5lcihvblN0cmVhbUNyZWF0ZWQsXG4vLyAgICAgICAgICAgIFN0cmVhbUV2ZW50VHlwZXMuRVZFTlRfVFlQRV9MT0NBTF9DUkVBVEVEKTtcbi8vICAgICAgICBBUFAueG1wcC5hZGRMaXN0ZW5lcihYTVBQRXZlbnRzLkRJU1BPU0VfQ09ORkVSRU5DRSwgb25EaXNwb3NlQ29uZmVyZW5jZSk7XG4vLyAgICAgICAgLy9GSVhNRTogd2UgbWF5IHdhbnQgdG8gY2hhbmdlIENBTEwgSU5DT01JTkcgZXZlbnQgdG8gb25uZWdvdGlhdGlvbm5lZWRlZFxuLy8gICAgICAgIEFQUC54bXBwLmFkZExpc3RlbmVyKFhNUFBFdmVudHMuQ0FMTF9JTkNPTUlORywgZnVuY3Rpb24gKGV2ZW50KSB7XG4vLyAgICAgICAgICAgIHN0YXJ0UmVtb3RlU3RhdHMoZXZlbnQucGVlcmNvbm5lY3Rpb24pO1xuLy8vLyAgICAgICAgICAgIENhbGxTdGF0cy5pbml0KGV2ZW50KTtcbi8vICAgICAgICB9KTtcbi8vLy8gICAgICAgIEFQUC54bXBwLmFkZExpc3RlbmVyKFhNUFBFdmVudHMuUEVFUkNPTk5FQ1RJT05fUkVBRFksIGZ1bmN0aW9uIChzZXNzaW9uKSB7XG4vLy8vICAgICAgICAgICAgQ2FsbFN0YXRzLmluaXQoc2Vzc2lvbik7XG4vLy8vICAgICAgICB9KTtcbi8vICAgICAgICAvL0ZJWE1FOiB0aGF0IGV2ZW50IGlzIGNoYW5nZWQgdG8gVFJBQ0tfTVVURV9DSEFOR0VEXG4vLy8vICAgICAgICBBUFAuUlRDLmFkZExpc3RlbmVyKFJUQ0V2ZW50cy5BVURJT19NVVRFLCBmdW5jdGlvbiAobXV0ZSkge1xuLy8vLyAgICAgICAgICAgIENhbGxTdGF0cy5zZW5kTXV0ZUV2ZW50KG11dGUsIFwiYXVkaW9cIik7XG4vLy8vICAgICAgICB9KTtcbi8vLy8gICAgICAgIEFQUC54bXBwLmFkZExpc3RlbmVyKFhNUFBFdmVudHMuQ09ORkVSRU5DRV9TRVRVUF9GQUlMRUQsIGZ1bmN0aW9uICgpIHtcbi8vLy8gICAgICAgICAgICBDYWxsU3RhdHMuc2VuZFNldHVwRmFpbGVkRXZlbnQoKTtcbi8vLy8gICAgICAgIH0pO1xuLy8gICAgICAgIC8vRklYTUU6IHRoYXQgZXZlbnQgaXMgY2hhbmdlZCB0byBUUkFDS19NVVRFX0NIQU5HRURcbi8vLy8gICAgICAgIEFQUC5SVEMuYWRkTGlzdGVuZXIoUlRDRXZlbnRzLlZJREVPX01VVEUsIGZ1bmN0aW9uIChtdXRlKSB7XG4vLy8vICAgICAgICAgICAgQ2FsbFN0YXRzLnNlbmRNdXRlRXZlbnQobXV0ZSwgXCJ2aWRlb1wiKTtcbi8vLy8gICAgICAgIH0pO1xuLy8gICAgfVxuLy99O1xuXG5cblxuXG5tb2R1bGUuZXhwb3J0cyA9IFN0YXRpc3RpY3M7XG4iLCIvKipcbi8qKlxuICogQGNvbnN0XG4gKi9cbnZhciBBTFBIQU5VTSA9ICcwMTIzNDU2Nzg5YWJjZGVmZ2hpamtsbW5vcHFyc3R1dnd4eXpBQkNERUZHSElKS0xNTk9QUVJTVFVWV1hZWic7XG5cbi8qKlxuICogSGV4YWRlY2ltYWwgZGlnaXRzLlxuICogQGNvbnN0XG4gKi9cbnZhciBIRVhfRElHSVRTID0gJzAxMjM0NTY3ODlhYmNkZWYnO1xuXG4vKipcbiAqIEdlbmVyYXRlcyByYW5kb20gaW50IHdpdGhpbiB0aGUgcmFuZ2UgW21pbiwgbWF4XVxuICogQHBhcmFtIG1pbiB0aGUgbWluaW11bSB2YWx1ZSBmb3IgdGhlIGdlbmVyYXRlZCBudW1iZXJcbiAqIEBwYXJhbSBtYXggdGhlIG1heGltdW0gdmFsdWUgZm9yIHRoZSBnZW5lcmF0ZWQgbnVtYmVyXG4gKiBAcmV0dXJucyByYW5kb20gaW50IG51bWJlclxuICovXG5mdW5jdGlvbiByYW5kb21JbnQobWluLCBtYXgpIHtcbiAgICByZXR1cm4gTWF0aC5mbG9vcihNYXRoLnJhbmRvbSgpICogKG1heCAtIG1pbiArIDEpKSArIG1pbjtcbn1cblxuLyoqXG4gKiBHZXQgcmFuZG9tIGVsZW1lbnQgZnJvbSBhcnJheSBvciBzdHJpbmcuXG4gKiBAcGFyYW0ge0FycmF5fHN0cmluZ30gYXJyIHNvdXJjZVxuICogQHJldHVybnMgYXJyYXkgZWxlbWVudCBvciBzdHJpbmcgY2hhcmFjdGVyXG4gKi9cbmZ1bmN0aW9uIHJhbmRvbUVsZW1lbnQoYXJyKSB7XG4gICAgcmV0dXJuIGFycltyYW5kb21JbnQoMCwgYXJyLmxlbmd0aCAtIDEpXTtcbn1cblxuLyoqXG4gKiBHZW5lcmF0ZSByYW5kb20gYWxwaGFudW1lcmljIHN0cmluZy5cbiAqIEBwYXJhbSB7bnVtYmVyfSBsZW5ndGggZXhwZWN0ZWQgc3RyaW5nIGxlbmd0aFxuICogQHJldHVybnMge3N0cmluZ30gcmFuZG9tIHN0cmluZyBvZiBzcGVjaWZpZWQgbGVuZ3RoXG4gKi9cbmZ1bmN0aW9uIHJhbmRvbUFscGhhbnVtU3RyKGxlbmd0aCkge1xuICAgIHZhciByZXN1bHQgPSAnJztcblxuICAgIGZvciAodmFyIGkgPSAwOyBpIDwgbGVuZ3RoOyBpICs9IDEpIHtcbiAgICAgICAgcmVzdWx0ICs9IHJhbmRvbUVsZW1lbnQoQUxQSEFOVU0pO1xuICAgIH1cblxuICAgIHJldHVybiByZXN1bHQ7XG59XG5cbi8qKlxuICogRXhwb3J0ZWQgaW50ZXJmYWNlLlxuICovXG52YXIgUmFuZG9tVXRpbCA9IHtcbiAgICAvKipcbiAgICAgKiBSZXR1cm5zIGEgcmFuZG9tIGhleCBkaWdpdC5cbiAgICAgKiBAcmV0dXJucyB7Kn1cbiAgICAgKi9cbiAgICByYW5kb21IZXhEaWdpdDogZnVuY3Rpb24oKSB7XG4gICAgICAgIHJldHVybiByYW5kb21FbGVtZW50KEhFWF9ESUdJVFMpO1xuICAgIH0sXG4gICAgLyoqXG4gICAgICogUmV0dXJucyBhIHJhbmRvbSBzdHJpbmcgb2YgaGV4IGRpZ2l0cyB3aXRoIGxlbmd0aCAnbGVuJy5cbiAgICAgKiBAcGFyYW0gbGVuIHRoZSBsZW5ndGguXG4gICAgICovXG4gICAgcmFuZG9tSGV4U3RyaW5nOiBmdW5jdGlvbiAobGVuKSB7XG4gICAgICAgIHZhciByZXQgPSAnJztcbiAgICAgICAgd2hpbGUgKGxlbi0tKSB7XG4gICAgICAgICAgICByZXQgKz0gdGhpcy5yYW5kb21IZXhEaWdpdCgpO1xuICAgICAgICB9XG4gICAgICAgIHJldHVybiByZXQ7XG4gICAgfSxcbiAgICByYW5kb21FbGVtZW50OiByYW5kb21FbGVtZW50LFxuICAgIHJhbmRvbUFscGhhbnVtU3RyOiByYW5kb21BbHBoYW51bVN0clxufTtcblxubW9kdWxlLmV4cG9ydHMgPSBSYW5kb21VdGlsO1xuIiwiLyogZ2xvYmFsIFN0cm9waGUsICQsICRwcmVzLCAkaXEsICRtc2cgKi9cbi8qIGpzaGludCAtVzEwMSwtVzA2OSAqL1xudmFyIGxvZ2dlciA9IHJlcXVpcmUoXCJqaXRzaS1tZWV0LWxvZ2dlclwiKS5nZXRMb2dnZXIoX19maWxlbmFtZSk7XG52YXIgWE1QUEV2ZW50cyA9IHJlcXVpcmUoXCIuLi8uLi9zZXJ2aWNlL3htcHAvWE1QUEV2ZW50c1wiKTtcbnZhciBNb2RlcmF0b3IgPSByZXF1aXJlKFwiLi9tb2RlcmF0b3JcIik7XG52YXIgRXZlbnRFbWl0dGVyID0gcmVxdWlyZShcImV2ZW50c1wiKTtcbnZhciBSZWNvcmRlciA9IHJlcXVpcmUoXCIuL3JlY29yZGluZ1wiKTtcbnZhciBKSUJSSV9YTUxOUyA9ICdodHRwOi8vaml0c2kub3JnL3Byb3RvY29sL2ppYnJpJztcblxudmFyIHBhcnNlciA9IHtcbiAgICBwYWNrZXQySlNPTjogZnVuY3Rpb24gKHBhY2tldCwgbm9kZXMpIHtcbiAgICAgICAgdmFyIHNlbGYgPSB0aGlzO1xuICAgICAgICAkKHBhY2tldCkuY2hpbGRyZW4oKS5lYWNoKGZ1bmN0aW9uIChpbmRleCkge1xuICAgICAgICAgICAgdmFyIHRhZ05hbWUgPSAkKHRoaXMpLnByb3AoXCJ0YWdOYW1lXCIpO1xuICAgICAgICAgICAgdmFyIG5vZGUgPSB7XG4gICAgICAgICAgICAgICAgdGFnTmFtZTogdGFnTmFtZVxuICAgICAgICAgICAgfTtcbiAgICAgICAgICAgIG5vZGUuYXR0cmlidXRlcyA9IHt9O1xuICAgICAgICAgICAgJCgkKHRoaXMpWzBdLmF0dHJpYnV0ZXMpLmVhY2goZnVuY3Rpb24oIGluZGV4LCBhdHRyICkge1xuICAgICAgICAgICAgICAgIG5vZGUuYXR0cmlidXRlc1sgYXR0ci5uYW1lIF0gPSBhdHRyLnZhbHVlO1xuICAgICAgICAgICAgfSk7XG4gICAgICAgICAgICB2YXIgdGV4dCA9IFN0cm9waGUuZ2V0VGV4dCgkKHRoaXMpWzBdKTtcbiAgICAgICAgICAgIGlmICh0ZXh0KSB7XG4gICAgICAgICAgICAgICAgbm9kZS52YWx1ZSA9IHRleHQ7XG4gICAgICAgICAgICB9XG4gICAgICAgICAgICBub2RlLmNoaWxkcmVuID0gW107XG4gICAgICAgICAgICBub2Rlcy5wdXNoKG5vZGUpO1xuICAgICAgICAgICAgc2VsZi5wYWNrZXQySlNPTigkKHRoaXMpLCBub2RlLmNoaWxkcmVuKTtcbiAgICAgICAgfSk7XG4gICAgfSxcbiAgICBKU09OMnBhY2tldDogZnVuY3Rpb24gKG5vZGVzLCBwYWNrZXQpIHtcbiAgICAgICAgZm9yKHZhciBpID0gMDsgaSA8IG5vZGVzLmxlbmd0aDsgaSsrKSB7XG4gICAgICAgICAgICB2YXIgbm9kZSA9IG5vZGVzW2ldO1xuICAgICAgICAgICAgaWYoIW5vZGUgfHwgbm9kZSA9PT0gbnVsbCl7XG4gICAgICAgICAgICAgICAgY29udGludWU7XG4gICAgICAgICAgICB9XG4gICAgICAgICAgICBwYWNrZXQuYyhub2RlLnRhZ05hbWUsIG5vZGUuYXR0cmlidXRlcyk7XG4gICAgICAgICAgICBpZihub2RlLnZhbHVlKVxuICAgICAgICAgICAgICAgIHBhY2tldC50KG5vZGUudmFsdWUpO1xuICAgICAgICAgICAgaWYobm9kZS5jaGlsZHJlbilcbiAgICAgICAgICAgICAgICB0aGlzLkpTT04ycGFja2V0KG5vZGUuY2hpbGRyZW4sIHBhY2tldCk7XG4gICAgICAgICAgICBwYWNrZXQudXAoKTtcbiAgICAgICAgfVxuICAgICAgICAvLyBwYWNrZXQudXAoKTtcbiAgICB9XG59O1xuXG4vKipcbiAqIFJldHVybnMgYXJyYXkgb2YgSlMgb2JqZWN0cyBmcm9tIHRoZSBwcmVzZW5jZSBKU09OIGFzc29jaWF0ZWQgd2l0aCB0aGUgcGFzc2VkIG5vZGVOYW1lXG4gKiBAcGFyYW0gcHJlcyB0aGUgcHJlc2VuY2UgSlNPTlxuICogQHBhcmFtIG5vZGVOYW1lIHRoZSBuYW1lIG9mIHRoZSBub2RlICh2aWRlb211dGVkLCBhdWRpb211dGVkLCBldGMpXG4gKi9cbmZ1bmN0aW9uIGZpbHRlck5vZGVGcm9tUHJlc2VuY2VKU09OKHByZXMsIG5vZGVOYW1lKXtcbiAgICB2YXIgcmVzID0gW107XG4gICAgZm9yKHZhciBpID0gMDsgaSA8IHByZXMubGVuZ3RoOyBpKyspXG4gICAgICAgIGlmKHByZXNbaV0udGFnTmFtZSA9PT0gbm9kZU5hbWUpXG4gICAgICAgICAgICByZXMucHVzaChwcmVzW2ldKTtcblxuICAgIHJldHVybiByZXM7XG59XG5cbmZ1bmN0aW9uIENoYXRSb29tKGNvbm5lY3Rpb24sIGppZCwgcGFzc3dvcmQsIFhNUFAsIG9wdGlvbnMpIHtcbiAgICB0aGlzLmV2ZW50RW1pdHRlciA9IG5ldyBFdmVudEVtaXR0ZXIoKTtcbiAgICB0aGlzLnhtcHAgPSBYTVBQO1xuICAgIHRoaXMuY29ubmVjdGlvbiA9IGNvbm5lY3Rpb247XG4gICAgdGhpcy5yb29tamlkID0gU3Ryb3BoZS5nZXRCYXJlSmlkRnJvbUppZChqaWQpO1xuICAgIHRoaXMubXlyb29tamlkID0gamlkO1xuICAgIHRoaXMucGFzc3dvcmQgPSBwYXNzd29yZDtcbiAgICBsb2dnZXIuaW5mbyhcIkpvaW5lZCBNVUMgYXMgXCIgKyB0aGlzLm15cm9vbWppZCk7XG4gICAgdGhpcy5tZW1iZXJzID0ge307XG4gICAgdGhpcy5wcmVzTWFwID0ge307XG4gICAgdGhpcy5wcmVzSGFuZGxlcnMgPSB7fTtcbiAgICB0aGlzLmpvaW5lZCA9IGZhbHNlO1xuICAgIHRoaXMucm9sZSA9ICdub25lJztcbiAgICB0aGlzLmZvY3VzTXVjSmlkID0gbnVsbDtcbiAgICB0aGlzLmJyaWRnZUlzRG93biA9IGZhbHNlO1xuICAgIHRoaXMub3B0aW9ucyA9IG9wdGlvbnMgfHwge307XG4gICAgdGhpcy5tb2RlcmF0b3IgPSBuZXcgTW9kZXJhdG9yKHRoaXMucm9vbWppZCwgdGhpcy54bXBwLCB0aGlzLmV2ZW50RW1pdHRlcik7XG4gICAgdGhpcy5pbml0UHJlc2VuY2VNYXAoKTtcbiAgICB0aGlzLnNlc3Npb24gPSBudWxsO1xuICAgIHZhciBzZWxmID0gdGhpcztcbiAgICB0aGlzLmxhc3RQcmVzZW5jZXMgPSB7fTtcbiAgICB0aGlzLnBob25lTnVtYmVyID0gbnVsbDtcbiAgICB0aGlzLnBob25lUGluID0gbnVsbDtcbn1cblxuQ2hhdFJvb20ucHJvdG90eXBlLmluaXRQcmVzZW5jZU1hcCA9IGZ1bmN0aW9uICgpIHtcbiAgICB0aGlzLnByZXNNYXBbJ3RvJ10gPSB0aGlzLm15cm9vbWppZDtcbiAgICB0aGlzLnByZXNNYXBbJ3hucyddID0gJ2h0dHA6Ly9qYWJiZXIub3JnL3Byb3RvY29sL211Yyc7XG4gICAgdGhpcy5wcmVzTWFwW1wibm9kZXNcIl0gPSBbXTtcbiAgICB0aGlzLnByZXNNYXBbXCJub2Rlc1wiXS5wdXNoKCB7XG4gICAgICAgIFwidGFnTmFtZVwiOiBcInVzZXItYWdlbnRcIixcbiAgICAgICAgXCJ2YWx1ZVwiOiBuYXZpZ2F0b3IudXNlckFnZW50LFxuICAgICAgICBcImF0dHJpYnV0ZXNcIjoge3htbG5zOiAnaHR0cDovL2ppdHNpLm9yZy9qaXRtZWV0L3VzZXItYWdlbnQnfVxuICAgIH0pO1xuXG59O1xuXG5DaGF0Um9vbS5wcm90b3R5cGUudXBkYXRlRGV2aWNlQXZhaWxhYmlsaXR5ID0gZnVuY3Rpb24gKGRldmljZXMpIHtcbiAgICB0aGlzLnByZXNNYXBbXCJub2Rlc1wiXS5wdXNoKCB7XG4gICAgICAgIFwidGFnTmFtZVwiOiBcImRldmljZXNcIixcbiAgICAgICAgXCJjaGlsZHJlblwiOiBbXG4gICAgICAgICAgICB7XG4gICAgICAgICAgICAgICAgXCJ0YWdOYW1lXCI6IFwiYXVkaW9cIixcbiAgICAgICAgICAgICAgICBcInZhbHVlXCI6IGRldmljZXMuYXVkaW8sXG4gICAgICAgICAgICB9LFxuICAgICAgICAgICAge1xuICAgICAgICAgICAgICAgIFwidGFnTmFtZVwiOiBcInZpZGVvXCIsXG4gICAgICAgICAgICAgICAgXCJ2YWx1ZVwiOiBkZXZpY2VzLnZpZGVvLFxuICAgICAgICAgICAgfVxuICAgICAgICBdXG4gICAgfSk7XG59O1xuXG5DaGF0Um9vbS5wcm90b3R5cGUuam9pbiA9IGZ1bmN0aW9uIChwYXNzd29yZCkge1xuICAgIGlmKHBhc3N3b3JkKVxuICAgICAgICB0aGlzLnBhc3N3b3JkID0gcGFzc3dvcmQ7XG4gICAgdmFyIHNlbGYgPSB0aGlzO1xuICAgIHRoaXMubW9kZXJhdG9yLmFsbG9jYXRlQ29uZmVyZW5jZUZvY3VzKGZ1bmN0aW9uKClcbiAgICB7XG4gICAgICAgIHNlbGYuc2VuZFByZXNlbmNlKCk7XG4gICAgfS5iaW5kKHRoaXMpKTtcbn07XG5cbkNoYXRSb29tLnByb3RvdHlwZS5zZW5kUHJlc2VuY2UgPSBmdW5jdGlvbiAoKSB7XG4gICAgaWYgKCF0aGlzLnByZXNNYXBbJ3RvJ10pIHtcbiAgICAgICAgLy8gVG9vIGVhcmx5IHRvIHNlbmQgcHJlc2VuY2UgLSBub3QgaW5pdGlhbGl6ZWRcbiAgICAgICAgcmV0dXJuO1xuICAgIH1cbiAgICB2YXIgcHJlcyA9ICRwcmVzKHt0bzogdGhpcy5wcmVzTWFwWyd0byddIH0pO1xuICAgIHByZXMuYygneCcsIHt4bWxuczogdGhpcy5wcmVzTWFwWyd4bnMnXX0pO1xuXG4gICAgaWYgKHRoaXMucGFzc3dvcmQpIHtcbiAgICAgICAgcHJlcy5jKCdwYXNzd29yZCcpLnQodGhpcy5wYXNzd29yZCkudXAoKTtcbiAgICB9XG5cbiAgICBwcmVzLnVwKCk7XG5cbiAgICAvLyBTZW5kIFhFUC0wMTE1ICdjJyBzdGFuemEgdGhhdCBjb250YWlucyBvdXIgY2FwYWJpbGl0aWVzIGluZm9cbiAgICBpZiAodGhpcy5jb25uZWN0aW9uLmNhcHMpIHtcbiAgICAgICAgdGhpcy5jb25uZWN0aW9uLmNhcHMubm9kZSA9IHRoaXMueG1wcC5vcHRpb25zLmNsaWVudE5vZGU7XG4gICAgICAgIHByZXMuYygnYycsIHRoaXMuY29ubmVjdGlvbi5jYXBzLmdlbmVyYXRlQ2Fwc0F0dHJzKCkpLnVwKCk7XG4gICAgfVxuXG4gICAgcGFyc2VyLkpTT04ycGFja2V0KHRoaXMucHJlc01hcC5ub2RlcywgcHJlcyk7XG4gICAgdGhpcy5jb25uZWN0aW9uLnNlbmQocHJlcyk7XG59O1xuXG5cbkNoYXRSb29tLnByb3RvdHlwZS5kb0xlYXZlID0gZnVuY3Rpb24gKCkge1xuICAgIGxvZ2dlci5sb2coXCJkbyBsZWF2ZVwiLCB0aGlzLm15cm9vbWppZCk7XG4gICAgdmFyIHByZXMgPSAkcHJlcyh7dG86IHRoaXMubXlyb29tamlkLCB0eXBlOiAndW5hdmFpbGFibGUnIH0pO1xuICAgIHRoaXMucHJlc01hcC5sZW5ndGggPSAwO1xuICAgIHRoaXMuY29ubmVjdGlvbi5zZW5kKHByZXMpO1xufTtcblxuXG5DaGF0Um9vbS5wcm90b3R5cGUuY3JlYXRlTm9uQW5vbnltb3VzUm9vbSA9IGZ1bmN0aW9uICgpIHtcbiAgICAvLyBodHRwOi8veG1wcC5vcmcvZXh0ZW5zaW9ucy94ZXAtMDA0NS5odG1sI2NyZWF0ZXJvb20tcmVzZXJ2ZWRcblxuICAgIHZhciBnZXRGb3JtID0gJGlxKHt0eXBlOiAnZ2V0JywgdG86IHRoaXMucm9vbWppZH0pXG4gICAgICAgIC5jKCdxdWVyeScsIHt4bWxuczogJ2h0dHA6Ly9qYWJiZXIub3JnL3Byb3RvY29sL211YyNvd25lcid9KVxuICAgICAgICAuYygneCcsIHt4bWxuczogJ2phYmJlcjp4OmRhdGEnLCB0eXBlOiAnc3VibWl0J30pO1xuXG4gICAgdmFyIHNlbGYgPSB0aGlzO1xuXG4gICAgdGhpcy5jb25uZWN0aW9uLnNlbmRJUShnZXRGb3JtLCBmdW5jdGlvbiAoZm9ybSkge1xuXG4gICAgICAgIGlmICghJChmb3JtKS5maW5kKFxuICAgICAgICAgICAgICAgICc+cXVlcnk+eFt4bWxucz1cImphYmJlcjp4OmRhdGFcIl0nICtcbiAgICAgICAgICAgICAgICAnPmZpZWxkW3Zhcj1cIm11YyNyb29tY29uZmlnX3dob2lzXCJdJykubGVuZ3RoKSB7XG5cbiAgICAgICAgICAgIGxvZ2dlci5lcnJvcignbm9uLWFub255bW91cyByb29tcyBub3Qgc3VwcG9ydGVkJyk7XG4gICAgICAgICAgICByZXR1cm47XG4gICAgICAgIH1cblxuICAgICAgICB2YXIgZm9ybVN1Ym1pdCA9ICRpcSh7dG86IHRoaXMucm9vbWppZCwgdHlwZTogJ3NldCd9KVxuICAgICAgICAgICAgLmMoJ3F1ZXJ5Jywge3htbG5zOiAnaHR0cDovL2phYmJlci5vcmcvcHJvdG9jb2wvbXVjI293bmVyJ30pO1xuXG4gICAgICAgIGZvcm1TdWJtaXQuYygneCcsIHt4bWxuczogJ2phYmJlcjp4OmRhdGEnLCB0eXBlOiAnc3VibWl0J30pO1xuXG4gICAgICAgIGZvcm1TdWJtaXQuYygnZmllbGQnLCB7J3Zhcic6ICdGT1JNX1RZUEUnfSlcbiAgICAgICAgICAgIC5jKCd2YWx1ZScpXG4gICAgICAgICAgICAudCgnaHR0cDovL2phYmJlci5vcmcvcHJvdG9jb2wvbXVjI3Jvb21jb25maWcnKS51cCgpLnVwKCk7XG5cbiAgICAgICAgZm9ybVN1Ym1pdC5jKCdmaWVsZCcsIHsndmFyJzogJ211YyNyb29tY29uZmlnX3dob2lzJ30pXG4gICAgICAgICAgICAuYygndmFsdWUnKS50KCdhbnlvbmUnKS51cCgpLnVwKCk7XG5cbiAgICAgICAgc2VsZi5jb25uZWN0aW9uLnNlbmRJUShmb3JtU3VibWl0KTtcblxuICAgIH0sIGZ1bmN0aW9uIChlcnJvcikge1xuICAgICAgICBsb2dnZXIuZXJyb3IoXCJFcnJvciBnZXR0aW5nIHJvb20gY29uZmlndXJhdGlvbiBmb3JtXCIpO1xuICAgIH0pO1xufTtcblxuQ2hhdFJvb20ucHJvdG90eXBlLm9uUHJlc2VuY2UgPSBmdW5jdGlvbiAocHJlcykge1xuICAgIGNvbnNvbGUubG9nKHByZXMpO1xuICAgIHZhciBmcm9tID0gcHJlcy5nZXRBdHRyaWJ1dGUoJ2Zyb20nKTtcbiAgICAvLyBQYXJzZSByb2xlcy5cbiAgICB2YXIgbWVtYmVyID0ge307XG4gICAgbWVtYmVyLnNob3cgPSAkKHByZXMpLmZpbmQoJz5zaG93JykudGV4dCgpO1xuICAgIG1lbWJlci5zdGF0dXMgPSAkKHByZXMpLmZpbmQoJz5zdGF0dXMnKS50ZXh0KCk7XG4gICAgdmFyIHRtcCA9ICQocHJlcykuZmluZCgnPnhbeG1sbnM9XCJodHRwOi8vamFiYmVyLm9yZy9wcm90b2NvbC9tdWMjdXNlclwiXT5pdGVtJyk7XG4gICAgbWVtYmVyLmFmZmlsaWF0aW9uID0gdG1wLmF0dHIoJ2FmZmlsaWF0aW9uJyk7XG4gICAgbWVtYmVyLnJvbGUgPSB0bXAuYXR0cigncm9sZScpO1xuXG4gICAgLy8gRm9jdXMgcmVjb2duaXRpb25cbiAgICBtZW1iZXIuamlkID0gdG1wLmF0dHIoJ2ppZCcpO1xuICAgIG1lbWJlci5pc0ZvY3VzID0gZmFsc2U7XG4gICAgaWYgKG1lbWJlci5qaWRcbiAgICAgICAgJiYgbWVtYmVyLmppZC5pbmRleE9mKHRoaXMubW9kZXJhdG9yLmdldEZvY3VzVXNlckppZCgpICsgXCIvXCIpID09PSAwKSB7XG4gICAgICAgIG1lbWJlci5pc0ZvY3VzID0gdHJ1ZTtcbiAgICB9XG5cbiAgICAkKHByZXMpLmZpbmQoXCI+eFwiKS5yZW1vdmUoKTtcbiAgICB2YXIgbm9kZXMgPSBbXTtcbiAgICBwYXJzZXIucGFja2V0MkpTT04ocHJlcywgbm9kZXMpO1xuICAgIHRoaXMubGFzdFByZXNlbmNlc1tmcm9tXSA9IG5vZGVzO1xuICAgIHZhciBqaWJyaSA9IG51bGw7XG4gICAgZm9yKHZhciBpID0gMDsgaSA8IG5vZGVzLmxlbmd0aDsgaSsrKVxuICAgIHtcbiAgICAgICAgdmFyIG5vZGUgPSBub2Rlc1tpXTtcbiAgICAgICAgc3dpdGNoKG5vZGUudGFnTmFtZSlcbiAgICAgICAge1xuICAgICAgICAgICAgY2FzZSBcIm5pY2tcIjpcbiAgICAgICAgICAgICAgICBtZW1iZXIubmljayA9IG5vZGUudmFsdWU7XG4gICAgICAgICAgICAgICAgaWYoIW1lbWJlci5pc0ZvY3VzKSB7XG4gICAgICAgICAgICAgICAgICAgIHZhciBkaXNwbGF5TmFtZSA9ICF0aGlzLnhtcHAub3B0aW9ucy5kaXNwbGF5Smlkc1xuICAgICAgICAgICAgICAgICAgICAgICAgPyBtZW1iZXIubmljayA6IFN0cm9waGUuZ2V0UmVzb3VyY2VGcm9tSmlkKGZyb20pO1xuXG4gICAgICAgICAgICAgICAgICAgIGlmIChkaXNwbGF5TmFtZSAmJiBkaXNwbGF5TmFtZS5sZW5ndGggPiAwKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICB0aGlzLmV2ZW50RW1pdHRlci5lbWl0KFhNUFBFdmVudHMuRElTUExBWV9OQU1FX0NIQU5HRUQsIGZyb20sIGRpc3BsYXlOYW1lKTtcbiAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgICAgICBsb2dnZXIuaW5mbyhcIkRpc3BsYXkgbmFtZTogXCIgKyBkaXNwbGF5TmFtZSwgcHJlcyk7XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgIGJyZWFrO1xuICAgICAgICAgICAgY2FzZSBcInVzZXJJZFwiOlxuICAgICAgICAgICAgICAgIG1lbWJlci5pZCA9IG5vZGUudmFsdWU7XG4gICAgICAgICAgICAgICAgYnJlYWs7XG4gICAgICAgICAgICBjYXNlIFwiZW1haWxcIjpcbiAgICAgICAgICAgICAgICBtZW1iZXIuZW1haWwgPSBub2RlLnZhbHVlO1xuICAgICAgICAgICAgICAgIGJyZWFrO1xuICAgICAgICAgICAgY2FzZSBcImJyaWRnZUlzRG93blwiOlxuICAgICAgICAgICAgICAgIGlmKCF0aGlzLmJyaWRnZUlzRG93bikge1xuICAgICAgICAgICAgICAgICAgICB0aGlzLmJyaWRnZUlzRG93biA9IHRydWU7XG4gICAgICAgICAgICAgICAgICAgIHRoaXMuZXZlbnRFbWl0dGVyLmVtaXQoWE1QUEV2ZW50cy5CUklER0VfRE9XTik7XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgIGJyZWFrO1xuICAgICAgICAgICAgY2FzZSBcImppYnJpLXJlY29yZGluZy1zdGF0dXNcIjpcbiAgICAgICAgICAgICAgICB2YXIgamlicmkgPSBub2RlO1xuICAgICAgICAgICAgICAgIGJyZWFrO1xuICAgICAgICAgICAgY2FzZSBcImNhbGwtY29udHJvbFwiOlxuICAgICAgICAgICAgICAgIGNvbnNvbGUubG9nKHByZXMpO1xuICAgICAgICAgICAgICAgIHZhciBhdHQgPSBub2RlLmF0dHJpYnV0ZXM7XG4gICAgICAgICAgICAgICAgaWYoIWF0dClcbiAgICAgICAgICAgICAgICAgICAgYnJlYWs7XG4gICAgICAgICAgICAgICAgdGhpcy5waG9uZU51bWJlciA9IGF0dC5waG9uZSB8fCBudWxsO1xuICAgICAgICAgICAgICAgIHRoaXMucGhvbmVQaW4gPSBhdHQucGluIHx8IG51bGw7XG4gICAgICAgICAgICAgICAgdGhpcy5ldmVudEVtaXR0ZXIuZW1pdChYTVBQRXZlbnRzLlBIT05FX05VTUJFUl9DSEFOR0VEKTtcbiAgICAgICAgICAgICAgICBicmVhaztcbiAgICAgICAgICAgIGRlZmF1bHQgOlxuICAgICAgICAgICAgICAgIHRoaXMucHJvY2Vzc05vZGUobm9kZSwgZnJvbSk7XG4gICAgICAgIH1cblxuICAgIH1cblxuICAgIGlmIChmcm9tID09IHRoaXMubXlyb29tamlkKSB7XG4gICAgICAgIGlmIChtZW1iZXIuYWZmaWxpYXRpb24gPT0gJ293bmVyJylcblxuICAgICAgICAgICAgaWYgKHRoaXMucm9sZSAhPT0gbWVtYmVyLnJvbGUpIHtcbiAgICAgICAgICAgICAgICB0aGlzLnJvbGUgPSBtZW1iZXIucm9sZTtcblxuICAgICAgICAgICAgICAgIHRoaXMuZXZlbnRFbWl0dGVyLmVtaXQoWE1QUEV2ZW50cy5MT0NBTF9ST0xFX0NIQU5HRUQsIHRoaXMucm9sZSk7XG4gICAgICAgICAgICB9XG4gICAgICAgIGlmICghdGhpcy5qb2luZWQpIHtcbiAgICAgICAgICAgIHRoaXMuam9pbmVkID0gdHJ1ZTtcbiAgICAgICAgICAgIGNvbnNvbGUubG9nKFwiKFRJTUUpIE1VQyBqb2luZWQ6XFx0XCIsIHdpbmRvdy5wZXJmb3JtYW5jZS5ub3coKSk7XG4gICAgICAgICAgICB0aGlzLmV2ZW50RW1pdHRlci5lbWl0KFhNUFBFdmVudHMuTVVDX0pPSU5FRCwgZnJvbSwgbWVtYmVyKTtcbiAgICAgICAgfVxuICAgIH0gZWxzZSBpZiAodGhpcy5tZW1iZXJzW2Zyb21dID09PSB1bmRlZmluZWQpIHtcbiAgICAgICAgLy8gbmV3IHBhcnRpY2lwYW50XG4gICAgICAgIHRoaXMubWVtYmVyc1tmcm9tXSA9IG1lbWJlcjtcbiAgICAgICAgbG9nZ2VyLmxvZygnZW50ZXJlZCcsIGZyb20sIG1lbWJlcik7XG4gICAgICAgIGlmIChtZW1iZXIuaXNGb2N1cykge1xuICAgICAgICAgICAgdGhpcy5mb2N1c011Y0ppZCA9IGZyb207XG4gICAgICAgICAgICBpZighdGhpcy5yZWNvcmRpbmcpIHtcbiAgICAgICAgICAgICAgICB0aGlzLnJlY29yZGluZyA9IG5ldyBSZWNvcmRlcih0aGlzLmV2ZW50RW1pdHRlciwgdGhpcy5jb25uZWN0aW9uLFxuICAgICAgICAgICAgICAgICAgICB0aGlzLmZvY3VzTXVjSmlkKTtcbiAgICAgICAgICAgICAgICBpZih0aGlzLmxhc3RKaWJyaSlcbiAgICAgICAgICAgICAgICAgICAgdGhpcy5yZWNvcmRpbmcuaGFuZGxlSmlicmlQcmVzZW5jZSh0aGlzLmxhc3RKaWJyaSk7XG4gICAgICAgICAgICB9XG4gICAgICAgICAgICBsb2dnZXIuaW5mbyhcIklnbm9yZSBmb2N1czogXCIgKyBmcm9tICsgXCIsIHJlYWwgSklEOiBcIiArIG1lbWJlci5qaWQpO1xuICAgICAgICB9XG4gICAgICAgIGVsc2Uge1xuICAgICAgICAgICAgdGhpcy5ldmVudEVtaXR0ZXIuZW1pdChYTVBQRXZlbnRzLk1VQ19NRU1CRVJfSk9JTkVELCBmcm9tLCBtZW1iZXIuaWQgfHwgbWVtYmVyLmVtYWlsLCBtZW1iZXIubmljayk7XG4gICAgICAgIH1cbiAgICB9IGVsc2Uge1xuICAgICAgICAvLyBQcmVzZW5jZSB1cGRhdGUgZm9yIGV4aXN0aW5nIHBhcnRpY2lwYW50XG4gICAgICAgIC8vIFdhdGNoIHJvbGUgY2hhbmdlOlxuICAgICAgICBpZiAodGhpcy5tZW1iZXJzW2Zyb21dLnJvbGUgIT0gbWVtYmVyLnJvbGUpIHtcbiAgICAgICAgICAgIHRoaXMubWVtYmVyc1tmcm9tXS5yb2xlID0gbWVtYmVyLnJvbGU7XG4gICAgICAgICAgICB0aGlzLmV2ZW50RW1pdHRlci5lbWl0KFhNUFBFdmVudHMuTVVDX1JPTEVfQ0hBTkdFRCwgZnJvbSwgbWVtYmVyLnJvbGUpO1xuICAgICAgICB9XG5cbiAgICAgICAgLy8gc3RvcmUgdGhlIG5ldyBkaXNwbGF5IG5hbWVcbiAgICAgICAgaWYobWVtYmVyLmRpc3BsYXlOYW1lKVxuICAgICAgICAgICAgdGhpcy5tZW1iZXJzW2Zyb21dLmRpc3BsYXlOYW1lID0gbWVtYmVyLmRpc3BsYXlOYW1lO1xuICAgIH1cblxuXG5cbiAgICBpZighbWVtYmVyLmlzRm9jdXMpXG4gICAgICAgIHRoaXMuZXZlbnRFbWl0dGVyLmVtaXQoWE1QUEV2ZW50cy5VU0VSX0lEX0NIQU5HRUQsIGZyb20sIG1lbWJlci5pZCB8fCBtZW1iZXIuZW1haWwpO1xuXG4gICAgLy8gVHJpZ2dlciBzdGF0dXMgbWVzc2FnZSB1cGRhdGVcbiAgICBpZiAobWVtYmVyLnN0YXR1cykge1xuICAgICAgICB0aGlzLmV2ZW50RW1pdHRlci5lbWl0KFhNUFBFdmVudHMuUFJFU0VOQ0VfU1RBVFVTLCBmcm9tLCBtZW1iZXIpO1xuICAgIH1cblxuICAgIGlmKGppYnJpKVxuICAgIHtcbiAgICAgICAgdGhpcy5sYXN0SmlicmkgPSBqaWJyaTtcbiAgICAgICAgaWYodGhpcy5yZWNvcmRpbmcpXG4gICAgICAgICAgICB0aGlzLnJlY29yZGluZy5oYW5kbGVKaWJyaVByZXNlbmNlKGppYnJpKTtcbiAgICB9XG5cbn07XG5cbkNoYXRSb29tLnByb3RvdHlwZS5wcm9jZXNzTm9kZSA9IGZ1bmN0aW9uIChub2RlLCBmcm9tKSB7XG4gICAgaWYodGhpcy5wcmVzSGFuZGxlcnNbbm9kZS50YWdOYW1lXSlcbiAgICAgICAgdGhpcy5wcmVzSGFuZGxlcnNbbm9kZS50YWdOYW1lXShub2RlLCBTdHJvcGhlLmdldFJlc291cmNlRnJvbUppZChmcm9tKSk7XG59O1xuXG5DaGF0Um9vbS5wcm90b3R5cGUuc2VuZE1lc3NhZ2UgPSBmdW5jdGlvbiAoYm9keSwgbmlja25hbWUpIHtcbiAgICB2YXIgbXNnID0gJG1zZyh7dG86IHRoaXMucm9vbWppZCwgdHlwZTogJ2dyb3VwY2hhdCd9KTtcbiAgICBtc2cuYygnYm9keScsIGJvZHkpLnVwKCk7XG4gICAgaWYgKG5pY2tuYW1lKSB7XG4gICAgICAgIG1zZy5jKCduaWNrJywge3htbG5zOiAnaHR0cDovL2phYmJlci5vcmcvcHJvdG9jb2wvbmljayd9KS50KG5pY2tuYW1lKS51cCgpLnVwKCk7XG4gICAgfVxuICAgIHRoaXMuY29ubmVjdGlvbi5zZW5kKG1zZyk7XG4gICAgdGhpcy5ldmVudEVtaXR0ZXIuZW1pdChYTVBQRXZlbnRzLlNFTkRJTkdfQ0hBVF9NRVNTQUdFLCBib2R5KTtcbn07XG5cbkNoYXRSb29tLnByb3RvdHlwZS5zZXRTdWJqZWN0ID0gZnVuY3Rpb24gKHN1YmplY3QpIHtcbiAgICB2YXIgbXNnID0gJG1zZyh7dG86IHRoaXMucm9vbWppZCwgdHlwZTogJ2dyb3VwY2hhdCd9KTtcbiAgICBtc2cuYygnc3ViamVjdCcsIHN1YmplY3QpO1xuICAgIHRoaXMuY29ubmVjdGlvbi5zZW5kKG1zZyk7XG4gICAgbG9nZ2VyLmxvZyhcInRvcGljIGNoYW5nZWQgdG8gXCIgKyBzdWJqZWN0KTtcbn07XG5cblxuQ2hhdFJvb20ucHJvdG90eXBlLm9uUGFydGljaXBhbnRMZWZ0ID0gZnVuY3Rpb24gKGppZCkge1xuXG4gICAgZGVsZXRlIHRoaXMubGFzdFByZXNlbmNlc1tqaWRdO1xuICAgIHRoaXMuZXZlbnRFbWl0dGVyLmVtaXQoWE1QUEV2ZW50cy5NVUNfTUVNQkVSX0xFRlQsIGppZCk7XG5cbiAgICB0aGlzLm1vZGVyYXRvci5vbk11Y01lbWJlckxlZnQoamlkKTtcbn07XG5cbkNoYXRSb29tLnByb3RvdHlwZS5vblByZXNlbmNlVW5hdmFpbGFibGUgPSBmdW5jdGlvbiAocHJlcywgZnJvbSkge1xuICAgIC8vIHJvb20gZGVzdHJveWVkID9cbiAgICBpZiAoJChwcmVzKS5maW5kKCc+eFt4bWxucz1cImh0dHA6Ly9qYWJiZXIub3JnL3Byb3RvY29sL211YyN1c2VyXCJdJyArXG4gICAgICAgICc+ZGVzdHJveScpLmxlbmd0aCkge1xuICAgICAgICB2YXIgcmVhc29uO1xuICAgICAgICB2YXIgcmVhc29uU2VsZWN0ID0gJChwcmVzKS5maW5kKFxuICAgICAgICAgICAgICAgICc+eFt4bWxucz1cImh0dHA6Ly9qYWJiZXIub3JnL3Byb3RvY29sL211YyN1c2VyXCJdJyArXG4gICAgICAgICAgICAgICAgJz5kZXN0cm95PnJlYXNvbicpO1xuICAgICAgICBpZiAocmVhc29uU2VsZWN0Lmxlbmd0aCkge1xuICAgICAgICAgICAgcmVhc29uID0gcmVhc29uU2VsZWN0LnRleHQoKTtcbiAgICAgICAgfVxuXG4gICAgICAgIHRoaXMueG1wcC5sZWF2ZVJvb20odGhpcy5yb29tamlkKTtcblxuICAgICAgICB0aGlzLmV2ZW50RW1pdHRlci5lbWl0KFhNUFBFdmVudHMuTVVDX0RFU1RST1lFRCwgcmVhc29uKTtcbiAgICAgICAgZGVsZXRlIHRoaXMuY29ubmVjdGlvbi5lbXVjLnJvb21zW1N0cm9waGUuZ2V0QmFyZUppZEZyb21KaWQoZnJvbSldO1xuICAgICAgICByZXR1cm4gdHJ1ZTtcbiAgICB9XG5cbiAgICAvLyBTdGF0dXMgY29kZSAxMTAgaW5kaWNhdGVzIHRoYXQgdGhpcyBub3RpZmljYXRpb24gaXMgXCJzZWxmLXByZXNlbmNlXCIuXG4gICAgaWYgKCEkKHByZXMpLmZpbmQoJz54W3htbG5zPVwiaHR0cDovL2phYmJlci5vcmcvcHJvdG9jb2wvbXVjI3VzZXJcIl0+c3RhdHVzW2NvZGU9XCIxMTBcIl0nKS5sZW5ndGgpIHtcbiAgICAgICAgZGVsZXRlIHRoaXMubWVtYmVyc1tmcm9tXTtcbiAgICAgICAgdGhpcy5vblBhcnRpY2lwYW50TGVmdChmcm9tKTtcbiAgICB9XG4gICAgLy8gSWYgdGhlIHN0YXR1cyBjb2RlIGlzIDExMCB0aGlzIG1lYW5zIHdlJ3JlIGxlYXZpbmcgYW5kIHdlIHdvdWxkIGxpa2VcbiAgICAvLyB0byByZW1vdmUgZXZlcnlvbmUgZWxzZSBmcm9tIG91ciB2aWV3LCBzbyB3ZSB0cmlnZ2VyIHRoZSBldmVudC5cbiAgICBlbHNlIGlmIChPYmplY3Qua2V5cyh0aGlzLm1lbWJlcnMpLmxlbmd0aCA+IDEpIHtcbiAgICAgICAgZm9yICh2YXIgaSBpbiB0aGlzLm1lbWJlcnMpIHtcbiAgICAgICAgICAgIHZhciBtZW1iZXIgPSB0aGlzLm1lbWJlcnNbaV07XG4gICAgICAgICAgICBkZWxldGUgdGhpcy5tZW1iZXJzW2ldO1xuICAgICAgICAgICAgdGhpcy5vblBhcnRpY2lwYW50TGVmdChtZW1iZXIpO1xuICAgICAgICB9XG4gICAgfVxuICAgIGlmICgkKHByZXMpLmZpbmQoJz54W3htbG5zPVwiaHR0cDovL2phYmJlci5vcmcvcHJvdG9jb2wvbXVjI3VzZXJcIl0+c3RhdHVzW2NvZGU9XCIzMDdcIl0nKS5sZW5ndGgpIHtcbiAgICAgICAgaWYgKHRoaXMubXlyb29tamlkID09PSBmcm9tKSB7XG4gICAgICAgICAgICB0aGlzLnhtcHAubGVhdmVSb29tKHRoaXMucm9vbWppZCk7XG4gICAgICAgICAgICB0aGlzLmV2ZW50RW1pdHRlci5lbWl0KFhNUFBFdmVudHMuS0lDS0VEKTtcbiAgICAgICAgfVxuICAgIH1cbn07XG5cbkNoYXRSb29tLnByb3RvdHlwZS5vbk1lc3NhZ2UgPSBmdW5jdGlvbiAobXNnLCBmcm9tKSB7XG4gICAgdmFyIG5pY2sgPVxuICAgICAgICAkKG1zZykuZmluZCgnPm5pY2tbeG1sbnM9XCJodHRwOi8vamFiYmVyLm9yZy9wcm90b2NvbC9uaWNrXCJdJylcbiAgICAgICAgICAgIC50ZXh0KCkgfHxcbiAgICAgICAgU3Ryb3BoZS5nZXRSZXNvdXJjZUZyb21KaWQoZnJvbSk7XG5cbiAgICB2YXIgdHh0ID0gJChtc2cpLmZpbmQoJz5ib2R5JykudGV4dCgpO1xuICAgIHZhciB0eXBlID0gbXNnLmdldEF0dHJpYnV0ZShcInR5cGVcIik7XG4gICAgaWYgKHR5cGUgPT0gXCJlcnJvclwiKSB7XG4gICAgICAgIHRoaXMuZXZlbnRFbWl0dGVyLmVtaXQoWE1QUEV2ZW50cy5DSEFUX0VSUk9SX1JFQ0VJVkVELFxuICAgICAgICAgICAgJChtc2cpLmZpbmQoJz50ZXh0JykudGV4dCgpLCB0eHQpO1xuICAgICAgICByZXR1cm4gdHJ1ZTtcbiAgICB9XG5cbiAgICB2YXIgc3ViamVjdCA9ICQobXNnKS5maW5kKCc+c3ViamVjdCcpO1xuICAgIGlmIChzdWJqZWN0Lmxlbmd0aCkge1xuICAgICAgICB2YXIgc3ViamVjdFRleHQgPSBzdWJqZWN0LnRleHQoKTtcbiAgICAgICAgaWYgKHN1YmplY3RUZXh0IHx8IHN1YmplY3RUZXh0ID09PSBcIlwiKSB7XG4gICAgICAgICAgICB0aGlzLmV2ZW50RW1pdHRlci5lbWl0KFhNUFBFdmVudHMuU1VCSkVDVF9DSEFOR0VELCBzdWJqZWN0VGV4dCk7XG4gICAgICAgICAgICBsb2dnZXIubG9nKFwiU3ViamVjdCBpcyBjaGFuZ2VkIHRvIFwiICsgc3ViamVjdFRleHQpO1xuICAgICAgICB9XG4gICAgfVxuXG4gICAgLy8geGVwLTAyMDMgZGVsYXlcbiAgICB2YXIgc3RhbXAgPSAkKG1zZykuZmluZCgnPmRlbGF5JykuYXR0cignc3RhbXAnKTtcblxuICAgIGlmICghc3RhbXApIHtcbiAgICAgICAgLy8gb3IgeGVwLTAwOTEgZGVsYXksIFVUQyB0aW1lc3RhbXBcbiAgICAgICAgc3RhbXAgPSAkKG1zZykuZmluZCgnPlt4bWxucz1cImphYmJlcjp4OmRlbGF5XCJdJykuYXR0cignc3RhbXAnKTtcblxuICAgICAgICBpZiAoc3RhbXApIHtcbiAgICAgICAgICAgIC8vIHRoZSBmb3JtYXQgaXMgQ0NZWU1NRERUaGg6bW06c3NcbiAgICAgICAgICAgIHZhciBkYXRlUGFydHMgPSBzdGFtcC5tYXRjaCgvKFxcZHs0fSkoXFxkezJ9KShcXGR7Mn1UXFxkezJ9OlxcZHsyfTpcXGR7Mn0pLyk7XG4gICAgICAgICAgICBzdGFtcCA9IGRhdGVQYXJ0c1sxXSArIFwiLVwiICsgZGF0ZVBhcnRzWzJdICsgXCItXCIgKyBkYXRlUGFydHNbM10gKyBcIlpcIjtcbiAgICAgICAgfVxuICAgIH1cblxuICAgIGlmICh0eHQpIHtcbiAgICAgICAgbG9nZ2VyLmxvZygnY2hhdCcsIG5pY2ssIHR4dCk7XG4gICAgICAgIHRoaXMuZXZlbnRFbWl0dGVyLmVtaXQoWE1QUEV2ZW50cy5NRVNTQUdFX1JFQ0VJVkVELFxuICAgICAgICAgICAgZnJvbSwgbmljaywgdHh0LCB0aGlzLm15cm9vbWppZCwgc3RhbXApO1xuICAgIH1cbn07XG5cbkNoYXRSb29tLnByb3RvdHlwZS5vblByZXNlbmNlRXJyb3IgPSBmdW5jdGlvbiAocHJlcywgZnJvbSkge1xuICAgIGlmICgkKHByZXMpLmZpbmQoJz5lcnJvclt0eXBlPVwiYXV0aFwiXT5ub3QtYXV0aG9yaXplZFt4bWxucz1cInVybjppZXRmOnBhcmFtczp4bWw6bnM6eG1wcC1zdGFuemFzXCJdJykubGVuZ3RoKSB7XG4gICAgICAgIGxvZ2dlci5sb2coJ29uIHBhc3N3b3JkIHJlcXVpcmVkJywgZnJvbSk7XG4gICAgICAgIHRoaXMuZXZlbnRFbWl0dGVyLmVtaXQoWE1QUEV2ZW50cy5QQVNTV09SRF9SRVFVSVJFRCk7XG4gICAgfSBlbHNlIGlmICgkKHByZXMpLmZpbmQoXG4gICAgICAgICc+ZXJyb3JbdHlwZT1cImNhbmNlbFwiXT5ub3QtYWxsb3dlZFt4bWxucz1cInVybjppZXRmOnBhcmFtczp4bWw6bnM6eG1wcC1zdGFuemFzXCJdJykubGVuZ3RoKSB7XG4gICAgICAgIHZhciB0b0RvbWFpbiA9IFN0cm9waGUuZ2V0RG9tYWluRnJvbUppZChwcmVzLmdldEF0dHJpYnV0ZSgndG8nKSk7XG4gICAgICAgIGlmICh0b0RvbWFpbiA9PT0gdGhpcy54bXBwLm9wdGlvbnMuaG9zdHMuYW5vbnltb3VzZG9tYWluKSB7XG4gICAgICAgICAgICAvLyBlbnRlciB0aGUgcm9vbSBieSByZXBseWluZyB3aXRoICdub3QtYXV0aG9yaXplZCcuIFRoaXMgd291bGRcbiAgICAgICAgICAgIC8vIHJlc3VsdCBpbiByZWNvbm5lY3Rpb24gZnJvbSBhdXRob3JpemVkIGRvbWFpbi5cbiAgICAgICAgICAgIC8vIFdlJ3JlIGVpdGhlciBtaXNzaW5nIEppY29mby9Qcm9zb2R5IGNvbmZpZyBmb3IgYW5vbnltb3VzXG4gICAgICAgICAgICAvLyBkb21haW5zIG9yIHNvbWV0aGluZyBpcyB3cm9uZy5cbiAgICAgICAgICAgIHRoaXMuZXZlbnRFbWl0dGVyLmVtaXQoWE1QUEV2ZW50cy5ST09NX0pPSU5fRVJST1IsIHByZXMpO1xuXG4gICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICBsb2dnZXIud2Fybignb25QcmVzRXJyb3IgJywgcHJlcyk7XG4gICAgICAgICAgICB0aGlzLmV2ZW50RW1pdHRlci5lbWl0KFhNUFBFdmVudHMuUk9PTV9DT05ORUNUX0VSUk9SLCBwcmVzKTtcbiAgICAgICAgfVxuICAgIH0gZWxzZSB7XG4gICAgICAgIGxvZ2dlci53YXJuKCdvblByZXNFcnJvciAnLCBwcmVzKTtcbiAgICAgICAgdGhpcy5ldmVudEVtaXR0ZXIuZW1pdChYTVBQRXZlbnRzLlJPT01fQ09OTkVDVF9FUlJPUiwgcHJlcyk7XG4gICAgfVxufTtcblxuQ2hhdFJvb20ucHJvdG90eXBlLmtpY2sgPSBmdW5jdGlvbiAoamlkKSB7XG4gICAgdmFyIGtpY2tJUSA9ICRpcSh7dG86IHRoaXMucm9vbWppZCwgdHlwZTogJ3NldCd9KVxuICAgICAgICAuYygncXVlcnknLCB7eG1sbnM6ICdodHRwOi8vamFiYmVyLm9yZy9wcm90b2NvbC9tdWMjYWRtaW4nfSlcbiAgICAgICAgLmMoJ2l0ZW0nLCB7bmljazogU3Ryb3BoZS5nZXRSZXNvdXJjZUZyb21KaWQoamlkKSwgcm9sZTogJ25vbmUnfSlcbiAgICAgICAgLmMoJ3JlYXNvbicpLnQoJ1lvdSBoYXZlIGJlZW4ga2lja2VkLicpLnVwKCkudXAoKS51cCgpO1xuXG4gICAgdGhpcy5jb25uZWN0aW9uLnNlbmRJUShcbiAgICAgICAga2lja0lRLFxuICAgICAgICBmdW5jdGlvbiAocmVzdWx0KSB7XG4gICAgICAgICAgICBsb2dnZXIubG9nKCdLaWNrIHBhcnRpY2lwYW50IHdpdGggamlkOiAnLCBqaWQsIHJlc3VsdCk7XG4gICAgICAgIH0sXG4gICAgICAgIGZ1bmN0aW9uIChlcnJvcikge1xuICAgICAgICAgICAgbG9nZ2VyLmxvZygnS2ljayBwYXJ0aWNpcGFudCBlcnJvcjogJywgZXJyb3IpO1xuICAgICAgICB9KTtcbn07XG5cbkNoYXRSb29tLnByb3RvdHlwZS5sb2NrUm9vbSA9IGZ1bmN0aW9uIChrZXksIG9uU3VjY2Vzcywgb25FcnJvciwgb25Ob3RTdXBwb3J0ZWQpIHtcbiAgICAvL2h0dHA6Ly94bXBwLm9yZy9leHRlbnNpb25zL3hlcC0wMDQ1Lmh0bWwjcm9vbWNvbmZpZ1xuICAgIHZhciBvYiA9IHRoaXM7XG4gICAgdGhpcy5jb25uZWN0aW9uLnNlbmRJUSgkaXEoe3RvOiB0aGlzLnJvb21qaWQsIHR5cGU6ICdnZXQnfSkuYygncXVlcnknLCB7eG1sbnM6ICdodHRwOi8vamFiYmVyLm9yZy9wcm90b2NvbC9tdWMjb3duZXInfSksXG4gICAgICAgIGZ1bmN0aW9uIChyZXMpIHtcbiAgICAgICAgICAgIGlmICgkKHJlcykuZmluZCgnPnF1ZXJ5PnhbeG1sbnM9XCJqYWJiZXI6eDpkYXRhXCJdPmZpZWxkW3Zhcj1cIm11YyNyb29tY29uZmlnX3Jvb21zZWNyZXRcIl0nKS5sZW5ndGgpIHtcbiAgICAgICAgICAgICAgICB2YXIgZm9ybXN1Ym1pdCA9ICRpcSh7dG86IG9iLnJvb21qaWQsIHR5cGU6ICdzZXQnfSkuYygncXVlcnknLCB7eG1sbnM6ICdodHRwOi8vamFiYmVyLm9yZy9wcm90b2NvbC9tdWMjb3duZXInfSk7XG4gICAgICAgICAgICAgICAgZm9ybXN1Ym1pdC5jKCd4Jywge3htbG5zOiAnamFiYmVyOng6ZGF0YScsIHR5cGU6ICdzdWJtaXQnfSk7XG4gICAgICAgICAgICAgICAgZm9ybXN1Ym1pdC5jKCdmaWVsZCcsIHsndmFyJzogJ0ZPUk1fVFlQRSd9KS5jKCd2YWx1ZScpLnQoJ2h0dHA6Ly9qYWJiZXIub3JnL3Byb3RvY29sL211YyNyb29tY29uZmlnJykudXAoKS51cCgpO1xuICAgICAgICAgICAgICAgIGZvcm1zdWJtaXQuYygnZmllbGQnLCB7J3Zhcic6ICdtdWMjcm9vbWNvbmZpZ19yb29tc2VjcmV0J30pLmMoJ3ZhbHVlJykudChrZXkpLnVwKCkudXAoKTtcbiAgICAgICAgICAgICAgICAvLyBGaXhlcyBhIGJ1ZyBpbiBwcm9zb2R5IDAuOS4rIGh0dHBzOi8vY29kZS5nb29nbGUuY29tL3AvbHhtcHBkL2lzc3Vlcy9kZXRhaWw/aWQ9MzczXG4gICAgICAgICAgICAgICAgZm9ybXN1Ym1pdC5jKCdmaWVsZCcsIHsndmFyJzogJ211YyNyb29tY29uZmlnX3dob2lzJ30pLmMoJ3ZhbHVlJykudCgnYW55b25lJykudXAoKS51cCgpO1xuICAgICAgICAgICAgICAgIC8vIEZJWE1FOiBpcyBtdWMjcm9vbWNvbmZpZ19wYXNzd29yZHByb3RlY3RlZHJvb20gcmVxdWlyZWQ/XG4gICAgICAgICAgICAgICAgb2IuY29ubmVjdGlvbi5zZW5kSVEoZm9ybXN1Ym1pdCxcbiAgICAgICAgICAgICAgICAgICAgb25TdWNjZXNzLFxuICAgICAgICAgICAgICAgICAgICBvbkVycm9yKTtcbiAgICAgICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICAgICAgb25Ob3RTdXBwb3J0ZWQoKTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgfSwgb25FcnJvcik7XG59O1xuXG5DaGF0Um9vbS5wcm90b3R5cGUuYWRkVG9QcmVzZW5jZSA9IGZ1bmN0aW9uIChrZXksIHZhbHVlcykge1xuICAgIHZhbHVlcy50YWdOYW1lID0ga2V5O1xuICAgIHRoaXMucHJlc01hcFtcIm5vZGVzXCJdLnB1c2godmFsdWVzKTtcbn07XG5cbkNoYXRSb29tLnByb3RvdHlwZS5yZW1vdmVGcm9tUHJlc2VuY2UgPSBmdW5jdGlvbiAoa2V5KSB7XG4gICAgZm9yKHZhciBpID0gMDsgaSA8IHRoaXMucHJlc01hcC5ub2Rlcy5sZW5ndGg7IGkrKylcbiAgICB7XG4gICAgICAgIGlmKGtleSA9PT0gdGhpcy5wcmVzTWFwLm5vZGVzW2ldLnRhZ05hbWUpXG4gICAgICAgICAgICB0aGlzLnByZXNNYXAubm9kZXMuc3BsaWNlKGksIDEpO1xuICAgIH1cbn07XG5cbkNoYXRSb29tLnByb3RvdHlwZS5hZGRQcmVzZW5jZUxpc3RlbmVyID0gZnVuY3Rpb24gKG5hbWUsIGhhbmRsZXIpIHtcbiAgICB0aGlzLnByZXNIYW5kbGVyc1tuYW1lXSA9IGhhbmRsZXI7XG59O1xuXG5DaGF0Um9vbS5wcm90b3R5cGUucmVtb3ZlUHJlc2VuY2VMaXN0ZW5lciA9IGZ1bmN0aW9uIChuYW1lKSB7XG4gICAgZGVsZXRlIHRoaXMucHJlc0hhbmRsZXJzW25hbWVdO1xufTtcblxuQ2hhdFJvb20ucHJvdG90eXBlLmlzTW9kZXJhdG9yID0gZnVuY3Rpb24gKCkge1xuICAgIHJldHVybiB0aGlzLnJvbGUgPT09ICdtb2RlcmF0b3InO1xufTtcblxuQ2hhdFJvb20ucHJvdG90eXBlLmdldE1lbWJlclJvbGUgPSBmdW5jdGlvbiAocGVlckppZCkge1xuICAgIGlmICh0aGlzLm1lbWJlcnNbcGVlckppZF0pIHtcbiAgICAgICAgcmV0dXJuIHRoaXMubWVtYmVyc1twZWVySmlkXS5yb2xlO1xuICAgIH1cbiAgICByZXR1cm4gbnVsbDtcbn07XG5cbkNoYXRSb29tLnByb3RvdHlwZS5zZXRKaW5nbGVTZXNzaW9uID0gZnVuY3Rpb24oc2Vzc2lvbil7XG4gICAgdGhpcy5zZXNzaW9uID0gc2Vzc2lvbjtcbiAgICB0aGlzLnNlc3Npb24ucm9vbSA9IHRoaXM7XG59O1xuXG5cbkNoYXRSb29tLnByb3RvdHlwZS5yZW1vdmVTdHJlYW0gPSBmdW5jdGlvbiAoc3RyZWFtLCBjYWxsYmFjaykge1xuICAgIGlmKCF0aGlzLnNlc3Npb24pXG4gICAgICAgIHJldHVybjtcbiAgICB0aGlzLnNlc3Npb24ucmVtb3ZlU3RyZWFtKHN0cmVhbSwgY2FsbGJhY2spO1xufTtcblxuQ2hhdFJvb20ucHJvdG90eXBlLnN3aXRjaFN0cmVhbXMgPSBmdW5jdGlvbiAoc3RyZWFtLCBvbGRTdHJlYW0sIGNhbGxiYWNrLCBpc0F1ZGlvKSB7XG4gICAgaWYodGhpcy5zZXNzaW9uKSB7XG4gICAgICAgIC8vIEZJWE1FOiB3aWxsIGJsb2NrIHN3aXRjaEluUHJvZ3Jlc3Mgb24gdHJ1ZSB2YWx1ZSBpbiBjYXNlIG9mIGV4Y2VwdGlvblxuICAgICAgICB0aGlzLnNlc3Npb24uc3dpdGNoU3RyZWFtcyhzdHJlYW0sIG9sZFN0cmVhbSwgY2FsbGJhY2ssIGlzQXVkaW8pO1xuICAgIH0gZWxzZSB7XG4gICAgICAgIC8vIFdlIGFyZSBkb25lIGltbWVkaWF0ZWx5XG4gICAgICAgIGxvZ2dlci53YXJuKFwiTm8gY29uZmVyZW5jZSBoYW5kbGVyIG9yIGNvbmZlcmVuY2Ugbm90IHN0YXJ0ZWQgeWV0XCIpO1xuICAgICAgICBjYWxsYmFjaygpO1xuICAgIH1cbn07XG5cbkNoYXRSb29tLnByb3RvdHlwZS5hZGRTdHJlYW0gPSBmdW5jdGlvbiAoc3RyZWFtLCBjYWxsYmFjaykge1xuICAgIGlmKHRoaXMuc2Vzc2lvbikge1xuICAgICAgICAvLyBGSVhNRTogd2lsbCBibG9jayBzd2l0Y2hJblByb2dyZXNzIG9uIHRydWUgdmFsdWUgaW4gY2FzZSBvZiBleGNlcHRpb25cbiAgICAgICAgdGhpcy5zZXNzaW9uLmFkZFN0cmVhbShzdHJlYW0sIGNhbGxiYWNrKTtcbiAgICB9IGVsc2Uge1xuICAgICAgICAvLyBXZSBhcmUgZG9uZSBpbW1lZGlhdGVseVxuICAgICAgICBsb2dnZXIud2FybihcIk5vIGNvbmZlcmVuY2UgaGFuZGxlciBvciBjb25mZXJlbmNlIG5vdCBzdGFydGVkIHlldFwiKTtcbiAgICAgICAgY2FsbGJhY2soKTtcbiAgICB9XG59O1xuXG5DaGF0Um9vbS5wcm90b3R5cGUuc2V0VmlkZW9NdXRlID0gZnVuY3Rpb24gKG11dGUsIGNhbGxiYWNrLCBvcHRpb25zKSB7XG4gICAgdmFyIHNlbGYgPSB0aGlzO1xuICAgIHZhciBsb2NhbENhbGxiYWNrID0gZnVuY3Rpb24gKG11dGUpIHtcbiAgICAgICAgc2VsZi5zZW5kVmlkZW9JbmZvUHJlc2VuY2UobXV0ZSk7XG4gICAgICAgIGlmKGNhbGxiYWNrKVxuICAgICAgICAgICAgY2FsbGJhY2sobXV0ZSk7XG4gICAgfTtcblxuICAgIGlmKHRoaXMuc2Vzc2lvbilcbiAgICB7XG4gICAgICAgIHRoaXMuc2Vzc2lvbi5zZXRWaWRlb011dGUoXG4gICAgICAgICAgICBtdXRlLCBsb2NhbENhbGxiYWNrLCBvcHRpb25zKTtcbiAgICB9XG4gICAgZWxzZSB7XG4gICAgICAgIGxvY2FsQ2FsbGJhY2sobXV0ZSk7XG4gICAgfVxuXG59O1xuXG5DaGF0Um9vbS5wcm90b3R5cGUuc2V0QXVkaW9NdXRlID0gZnVuY3Rpb24gKG11dGUsIGNhbGxiYWNrKSB7XG4gICAgLy9UaGlzIHdpbGwgYmUgZm9yIHJlbW90ZSBzdHJlYW1zIG9ubHlcbi8vICAgIGlmICh0aGlzLmZvcmNlTXV0ZWQgJiYgIW11dGUpIHtcbi8vICAgICAgICBsb2dnZXIuaW5mbyhcIkFza2luZyBmb2N1cyBmb3IgdW5tdXRlXCIpO1xuLy8gICAgICAgIHRoaXMuY29ubmVjdGlvbi5tb2RlcmF0ZS5zZXRNdXRlKHRoaXMuY29ubmVjdGlvbi5lbXVjLm15cm9vbWppZCwgbXV0ZSk7XG4vLyAgICAgICAgLy8gRklYTUU6IHdhaXQgZm9yIHJlc3VsdCBiZWZvcmUgcmVzZXR0aW5nIG11dGVkIHN0YXR1c1xuLy8gICAgICAgIHRoaXMuZm9yY2VNdXRlZCA9IGZhbHNlO1xuLy8gICAgfVxuXG5cbiAgICByZXR1cm4gdGhpcy5zZW5kQXVkaW9JbmZvUHJlc2VuY2UobXV0ZSwgY2FsbGJhY2spO1xufTtcblxuQ2hhdFJvb20ucHJvdG90eXBlLmFkZEF1ZGlvSW5mb1RvUHJlc2VuY2UgPSBmdW5jdGlvbiAobXV0ZSkge1xuICAgIHRoaXMucmVtb3ZlRnJvbVByZXNlbmNlKFwiYXVkaW9tdXRlZFwiKTtcbiAgICB0aGlzLmFkZFRvUHJlc2VuY2UoXCJhdWRpb211dGVkXCIsXG4gICAgICAgIHthdHRyaWJ1dGVzOlxuICAgICAgICB7XCJhdWRpb25zXCI6IFwiaHR0cDovL2ppdHNpLm9yZy9qaXRtZWV0L2F1ZGlvXCJ9LFxuICAgICAgICAgICAgdmFsdWU6IG11dGUudG9TdHJpbmcoKX0pO1xufTtcblxuQ2hhdFJvb20ucHJvdG90eXBlLnNlbmRBdWRpb0luZm9QcmVzZW5jZSA9IGZ1bmN0aW9uKG11dGUsIGNhbGxiYWNrKSB7XG4gICAgdGhpcy5hZGRBdWRpb0luZm9Ub1ByZXNlbmNlKG11dGUpO1xuICAgIGlmKHRoaXMuY29ubmVjdGlvbikge1xuICAgICAgICB0aGlzLnNlbmRQcmVzZW5jZSgpO1xuICAgIH1cbiAgICBpZihjYWxsYmFjaylcbiAgICAgICAgY2FsbGJhY2soKTtcbn07XG5cbkNoYXRSb29tLnByb3RvdHlwZS5hZGRWaWRlb0luZm9Ub1ByZXNlbmNlID0gZnVuY3Rpb24gKG11dGUpIHtcbiAgICB0aGlzLnJlbW92ZUZyb21QcmVzZW5jZShcInZpZGVvbXV0ZWRcIik7XG4gICAgdGhpcy5hZGRUb1ByZXNlbmNlKFwidmlkZW9tdXRlZFwiLFxuICAgICAgICB7YXR0cmlidXRlczpcbiAgICAgICAge1widmlkZW9uc1wiOiBcImh0dHA6Ly9qaXRzaS5vcmcvaml0bWVldC92aWRlb1wifSxcbiAgICAgICAgICAgIHZhbHVlOiBtdXRlLnRvU3RyaW5nKCl9KTtcbn07XG5cblxuQ2hhdFJvb20ucHJvdG90eXBlLnNlbmRWaWRlb0luZm9QcmVzZW5jZSA9IGZ1bmN0aW9uIChtdXRlKSB7XG4gICAgdGhpcy5hZGRWaWRlb0luZm9Ub1ByZXNlbmNlKG11dGUpO1xuICAgIGlmKCF0aGlzLmNvbm5lY3Rpb24pXG4gICAgICAgIHJldHVybjtcbiAgICB0aGlzLnNlbmRQcmVzZW5jZSgpO1xufTtcblxuQ2hhdFJvb20ucHJvdG90eXBlLmFkZExpc3RlbmVyID0gZnVuY3Rpb24odHlwZSwgbGlzdGVuZXIpIHtcbiAgICB0aGlzLmV2ZW50RW1pdHRlci5vbih0eXBlLCBsaXN0ZW5lcik7XG59O1xuXG5DaGF0Um9vbS5wcm90b3R5cGUucmVtb3ZlTGlzdGVuZXIgPSBmdW5jdGlvbiAodHlwZSwgbGlzdGVuZXIpIHtcbiAgICB0aGlzLmV2ZW50RW1pdHRlci5yZW1vdmVMaXN0ZW5lcih0eXBlLCBsaXN0ZW5lcik7XG59O1xuXG5DaGF0Um9vbS5wcm90b3R5cGUucmVtb3RlU3RyZWFtQWRkZWQgPSBmdW5jdGlvbihkYXRhLCBzaWQsIHRoZXNzcmMpIHtcbiAgICBpZih0aGlzLmxhc3RQcmVzZW5jZXNbZGF0YS5wZWVyamlkXSlcbiAgICB7XG4gICAgICAgIHZhciBwcmVzID0gdGhpcy5sYXN0UHJlc2VuY2VzW2RhdGEucGVlcmppZF07XG4gICAgICAgIHZhciBhdWRpb211dGVkID0gZmlsdGVyTm9kZUZyb21QcmVzZW5jZUpTT04ocHJlcywgXCJhdWRpb211dGVkXCIpO1xuICAgICAgICB2YXIgdmlkZW9tdXRlZCA9IGZpbHRlck5vZGVGcm9tUHJlc2VuY2VKU09OKHByZXMsIFwidmlkZW9tdXRlZFwiKTtcbiAgICAgICAgZGF0YS52aWRlb211dGVkID0gKCh2aWRlb211dGVkLmxlbmd0aCA+IDBcbiAgICAgICAgICAgICYmIHZpZGVvbXV0ZWRbMF1cbiAgICAgICAgICAgICYmIHZpZGVvbXV0ZWRbMF1bXCJ2YWx1ZVwiXSA9PT0gXCJ0cnVlXCIpPyB0cnVlIDogZmFsc2UpO1xuICAgICAgICBkYXRhLmF1ZGlvbXV0ZWQgPSAoKGF1ZGlvbXV0ZWQubGVuZ3RoID4gMFxuICAgICAgICAgICAgJiYgYXVkaW9tdXRlZFswXVxuICAgICAgICAgICAgJiYgYXVkaW9tdXRlZFswXVtcInZhbHVlXCJdID09PSBcInRydWVcIik/IHRydWUgOiBmYWxzZSk7XG4gICAgfVxuXG4gICAgdGhpcy5ldmVudEVtaXR0ZXIuZW1pdChYTVBQRXZlbnRzLlJFTU9URV9TVFJFQU1fUkVDRUlWRUQsIGRhdGEsIHNpZCwgdGhlc3NyYyk7XG59O1xuXG5DaGF0Um9vbS5wcm90b3R5cGUuZ2V0SmlkQnlTU1JDID0gZnVuY3Rpb24gKHNzcmMpIHtcbiAgICBpZiAoIXRoaXMuc2Vzc2lvbilcbiAgICAgICAgcmV0dXJuIG51bGw7XG4gICAgcmV0dXJuIHRoaXMuc2Vzc2lvbi5nZXRTc3JjT3duZXIoc3NyYyk7XG59O1xuXG4vKipcbiAqIFJldHVybnMgdHJ1ZSBpZiB0aGUgcmVjb3JkaW5nIGlzIHN1cHByb3RlZCBhbmQgZmFsc2UgaWYgbm90LlxuICovXG5DaGF0Um9vbS5wcm90b3R5cGUuaXNSZWNvcmRpbmdTdXBwb3J0ZWQgPSBmdW5jdGlvbiAoKSB7XG4gICAgaWYodGhpcy5yZWNvcmRpbmcpXG4gICAgICAgIHJldHVybiB0aGlzLnJlY29yZGluZy5pc1N1cHBvcnRlZCgpO1xuICAgIHJldHVybiBmYWxzZTtcbn07XG5cbi8qKlxuICogUmV0dXJucyBudWxsIGlmIHRoZSByZWNvcmRpbmcgaXMgbm90IHN1cHBvcnRlZCwgXCJvblwiIGlmIHRoZSByZWNvcmRpbmcgc3RhcnRlZFxuICogYW5kIFwib2ZmXCIgaWYgdGhlIHJlY29yZGluZyBpcyBub3Qgc3RhcnRlZC5cbiAqL1xuQ2hhdFJvb20ucHJvdG90eXBlLmdldFJlY29yZGluZ1N0YXRlID0gZnVuY3Rpb24gKCkge1xuICAgIGlmKHRoaXMucmVjb3JkaW5nKVxuICAgICAgICByZXR1cm4gdGhpcy5yZWNvcmRpbmcuZ2V0U3RhdGUoKTtcbiAgICByZXR1cm4gXCJvZmZcIjtcbn1cblxuLyoqXG4gKiBSZXR1cm5zIHRoZSB1cmwgb2YgdGhlIHJlY29yZGVkIHZpZGVvLlxuICovXG5DaGF0Um9vbS5wcm90b3R5cGUuZ2V0UmVjb3JkaW5nVVJMID0gZnVuY3Rpb24gKCkge1xuICAgIGlmKHRoaXMucmVjb3JkaW5nKVxuICAgICAgICByZXR1cm4gdGhpcy5yZWNvcmRpbmcuZ2V0VVJMKCk7XG4gICAgcmV0dXJuIG51bGw7XG59XG5cbi8qKlxuICogU3RhcnRzL3N0b3BzIHRoZSByZWNvcmRpbmdcbiAqIEBwYXJhbSB0b2tlbiB0b2tlbiBmb3IgYXV0aGVudGljYXRpb25cbiAqL1xuQ2hhdFJvb20ucHJvdG90eXBlLnRvZ2dsZVJlY29yZGluZyA9IGZ1bmN0aW9uICh0b2tlbiwgZm9sbG93RW50aXR5KSB7XG4gICAgaWYodGhpcy5yZWNvcmRpbmcpXG4gICAgICAgIHJldHVybiB0aGlzLnJlY29yZGluZy50b2dnbGVSZWNvcmRpbmcodG9rZW4sIGZvbGxvd0VudGl0eSk7XG5cbiAgICByZXR1cm4gbmV3IFByb21pc2UoZnVuY3Rpb24ocmVzb2x2ZSwgcmVqZWN0KXtcbiAgICAgICAgcmVqZWN0KG5ldyBFcnJvcihcIlRoZSBjb25mZXJlbmNlIGlzIG5vdCBjcmVhdGVkIHlldCFcIikpfSk7XG59XG5cbi8qKlxuICogUmV0dXJucyB0cnVlIGlmIHRoZSBTSVAgY2FsbHMgYXJlIHN1cHBvcnRlZCBhbmQgZmFsc2Ugb3RoZXJ3aXNlXG4gKi9cbkNoYXRSb29tLnByb3RvdHlwZS5pc1NJUENhbGxpbmdTdXBwb3J0ZWQgPSBmdW5jdGlvbiAoKSB7XG4gICAgaWYodGhpcy5tb2RlcmF0b3IpXG4gICAgICAgIHJldHVybiB0aGlzLm1vZGVyYXRvci5pc1NpcEdhdGV3YXlFbmFibGVkKCk7XG4gICAgcmV0dXJuIGZhbHNlO1xufVxuXG4vKipcbiAqIERpYWxzIGEgbnVtYmVyLlxuICogQHBhcmFtIG51bWJlciB0aGUgbnVtYmVyXG4gKi9cbkNoYXRSb29tLnByb3RvdHlwZS5kaWFsID0gZnVuY3Rpb24gKG51bWJlcikge1xuICAgIHJldHVybiB0aGlzLmNvbm5lY3Rpb24ucmF5by5kaWFsKG51bWJlciwgXCJmcm9tbnVtYmVyXCIsXG4gICAgICAgIFN0cm9waGUuZ2V0Tm9kZUZyb21KaWQodGhpcy5teXJvb21qaWQpLCB0aGlzLnBhc3N3b3JkLFxuICAgICAgICB0aGlzLmZvY3VzTXVjSmlkKTtcbn1cblxuLyoqXG4gKiBIYW5ndXAgYW4gZXhpc3RpbmcgY2FsbFxuICovXG5DaGF0Um9vbS5wcm90b3R5cGUuaGFuZ3VwID0gZnVuY3Rpb24gKCkge1xuICAgIHJldHVybiB0aGlzLmNvbm5lY3Rpb24ucmF5by5oYW5ndXAoKTtcbn1cblxuLyoqXG4gKiBSZXR1cm5zIHRoZSBwaG9uZSBudW1iZXIgZm9yIGpvaW5pbmcgdGhlIGNvbmZlcmVuY2UuXG4gKi9cbkNoYXRSb29tLnByb3RvdHlwZS5nZXRQaG9uZU51bWJlciA9IGZ1bmN0aW9uICgpIHtcbiAgICByZXR1cm4gdGhpcy5waG9uZU51bWJlcjtcbn1cblxuLyoqXG4gKiBSZXR1cm5zIHRoZSBwaW4gZm9yIGpvaW5pbmcgdGhlIGNvbmZlcmVuY2Ugd2l0aCBwaG9uZS5cbiAqL1xuQ2hhdFJvb20ucHJvdG90eXBlLmdldFBob25lUGluID0gZnVuY3Rpb24gKCkge1xuICAgIHJldHVybiB0aGlzLnBob25lUGluO1xufVxuXG4vKipcbiAqIFJldHVybnMgdGhlIGNvbm5lY3Rpb24gc3RhdGUgZm9yIHRoZSBjdXJyZW50IHNlc3Npb24uXG4gKi9cbkNoYXRSb29tLnByb3RvdHlwZS5nZXRDb25uZWN0aW9uU3RhdGUgPSBmdW5jdGlvbiAoKSB7XG4gICAgaWYoIXRoaXMuc2Vzc2lvbilcbiAgICAgICAgcmV0dXJuIG51bGw7XG4gICAgcmV0dXJuIHRoaXMuc2Vzc2lvbi5nZXRJY2VDb25uZWN0aW9uU3RhdGUoKTtcbn1cblxubW9kdWxlLmV4cG9ydHMgPSBDaGF0Um9vbTtcbiIsIi8qXG4gKiBKaW5nbGVTZXNzaW9uIHByb3ZpZGVzIGFuIEFQSSB0byBtYW5hZ2UgYSBzaW5nbGUgSmluZ2xlIHNlc3Npb24uIFdlIHdpbGxcbiAqIGhhdmUgZGlmZmVyZW50IGltcGxlbWVudGF0aW9ucyBkZXBlbmRpbmcgb24gdGhlIHVuZGVybHlpbmcgaW50ZXJmYWNlIHVzZWRcbiAqIChpLmUuIFdlYlJUQyBhbmQgT1JUQykgYW5kIGhlcmUgd2UgaG9sZCB0aGUgY29kZSBjb21tb24gdG8gYWxsIG9mIHRoZW0uXG4gKi9cbnZhciBsb2dnZXIgPSByZXF1aXJlKFwiaml0c2ktbWVldC1sb2dnZXJcIikuZ2V0TG9nZ2VyKF9fZmlsZW5hbWUpO1xuXG5mdW5jdGlvbiBKaW5nbGVTZXNzaW9uKG1lLCBzaWQsIGNvbm5lY3Rpb24sIHNlcnZpY2UsIGV2ZW50RW1pdHRlcikge1xuICAgIC8qKlxuICAgICAqIE91ciBKSUQuXG4gICAgICovXG4gICAgdGhpcy5tZSA9IG1lO1xuXG4gICAgLyoqXG4gICAgICogVGhlIEppbmdsZSBzZXNzaW9uIGlkZW50aWZpZXIuXG4gICAgICovXG4gICAgdGhpcy5zaWQgPSBzaWQ7XG5cbiAgICAvKipcbiAgICAgKiBUaGUgWE1QUCBjb25uZWN0aW9uLlxuICAgICAqL1xuICAgIHRoaXMuY29ubmVjdGlvbiA9IGNvbm5lY3Rpb247XG5cbiAgICAvKipcbiAgICAgKiBUaGUgWE1QUCBzZXJ2aWNlLlxuICAgICAqL1xuICAgIHRoaXMuc2VydmljZSA9IHNlcnZpY2U7XG5cbiAgICAvKipcbiAgICAgKiBUaGUgZXZlbnQgZW1pdHRlci5cbiAgICAgKi9cbiAgICB0aGlzLmV2ZW50RW1pdHRlciA9IGV2ZW50RW1pdHRlcjtcblxuICAgIC8qKlxuICAgICAqIFdoZXRoZXIgdG8gdXNlIGRyaXBwaW5nIG9yIG5vdC4gRHJpcHBpbmcgaXMgc2VuZGluZyB0cmlja2xlIGNhbmRpZGF0ZXNcbiAgICAgKiBub3Qgb25lLWJ5LW9uZS5cbiAgICAgKiBOb3RlOiBjdXJyZW50bHkgd2UgZG8gbm90IHN1cHBvcnQgJ2ZhbHNlJy5cbiAgICAgKi9cbiAgICB0aGlzLnVzZWRyaXAgPSB0cnVlO1xuXG4gICAgLyoqXG4gICAgICogIFdoZW4gZHJpcHBpbmcgaXMgdXNlZCwgc3RvcmVzIElDRSBjYW5kaWRhdGVzIHdoaWNoIGFyZSB0byBiZSBzZW50LlxuICAgICAqL1xuICAgIHRoaXMuZHJpcF9jb250YWluZXIgPSBbXTtcblxuICAgIC8vIE1lZGlhIGNvbnN0cmFpbnRzLiBJcyB0aGlzIFdlYlJUQyBvbmx5P1xuICAgIHRoaXMubWVkaWFfY29uc3RyYWludHMgPSBudWxsO1xuXG4gICAgLy8gSUNFIHNlcnZlcnMgY29uZmlnIChSVENDb25maWd1cmF0aW9uPykuXG4gICAgdGhpcy5pY2VfY29uZmlnID0ge307XG5cbiAgICAvLyBUaGUgY2hhdCByb29tIGluc3RhbmNlIGFzc29jaWF0ZWQgd2l0aCB0aGUgc2Vzc2lvbi5cbiAgICB0aGlzLnJvb20gPSBudWxsO1xufVxuXG4vKipcbiAqIFByZXBhcmVzIHRoaXMgb2JqZWN0IHRvIGluaXRpYXRlIGEgc2Vzc2lvbi5cbiAqIEBwYXJhbSBwZWVyamlkIHRoZSBKSUQgb2YgdGhlIHJlbW90ZSBwZWVyLlxuICogQHBhcmFtIGlzSW5pdGlhdG9yIHdoZXRoZXIgd2Ugd2lsbCBiZSB0aGUgSmluZ2xlIGluaXRpYXRvci5cbiAqIEBwYXJhbSBtZWRpYV9jb25zdHJhaW50c1xuICogQHBhcmFtIGljZV9jb25maWdcbiAqL1xuSmluZ2xlU2Vzc2lvbi5wcm90b3R5cGUuaW5pdGlhbGl6ZSA9IGZ1bmN0aW9uKHBlZXJqaWQsIGlzSW5pdGlhdG9yLFxuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIG1lZGlhX2NvbnN0cmFpbnRzLCBpY2VfY29uZmlnKSB7XG4gICAgdGhpcy5tZWRpYV9jb25zdHJhaW50cyA9IG1lZGlhX2NvbnN0cmFpbnRzO1xuICAgIHRoaXMuaWNlX2NvbmZpZyA9IGljZV9jb25maWc7XG5cbiAgICBpZiAodGhpcy5zdGF0ZSAhPT0gbnVsbCkge1xuICAgICAgICBsb2dnZXIuZXJyb3IoJ2F0dGVtcHQgdG8gaW5pdGlhdGUgb24gc2Vzc2lvbiAnICsgdGhpcy5zaWQgK1xuICAgICAgICAnaW4gc3RhdGUgJyArIHRoaXMuc3RhdGUpO1xuICAgICAgICByZXR1cm47XG4gICAgfVxuICAgIHRoaXMuc3RhdGUgPSAncGVuZGluZyc7XG4gICAgdGhpcy5pbml0aWF0b3IgPSBpc0luaXRpYXRvciA/IHRoaXMubWUgOiBwZWVyamlkO1xuICAgIHRoaXMucmVzcG9uZGVyID0gIWlzSW5pdGlhdG9yID8gdGhpcy5tZSA6IHBlZXJqaWQ7XG4gICAgdGhpcy5wZWVyamlkID0gcGVlcmppZDtcblxuICAgIHRoaXMuZG9Jbml0aWFsaXplKCk7XG59O1xuXG4vKipcbiAqIEZpbmlzaGVzIGluaXRpYWxpemF0aW9uLlxuICovXG5KaW5nbGVTZXNzaW9uLnByb3RvdHlwZS5kb0luaXRpYWxpemUgPSBmdW5jdGlvbigpIHt9O1xuXG4vKipcbiAqIEFkZHMgdGhlIElDRSBjYW5kaWRhdGVzIGZvdW5kIGluIHRoZSAnY29udGVudHMnIGFycmF5IGFzIHJlbW90ZSBjYW5kaWRhdGVzP1xuICogTm90ZTogY3VycmVudGx5IG9ubHkgdXNlZCBvbiB0cmFuc3BvcnQtaW5mb1xuICovXG5KaW5nbGVTZXNzaW9uLnByb3RvdHlwZS5hZGRJY2VDYW5kaWRhdGVzID0gZnVuY3Rpb24oY29udGVudHMpIHt9O1xuXG4vKipcbiAqIEhhbmRsZXMgYW4gJ2FkZC1zb3VyY2UnIGV2ZW50LlxuICpcbiAqIEBwYXJhbSBjb250ZW50cyBhbiBhcnJheSBvZiBKaW5nbGUgJ2NvbnRlbnQnIGVsZW1lbnRzLlxuICovXG5KaW5nbGVTZXNzaW9uLnByb3RvdHlwZS5hZGRTb3VyY2VzID0gZnVuY3Rpb24oY29udGVudHMpIHt9O1xuXG4vKipcbiAqIEhhbmRsZXMgYSAncmVtb3ZlLXNvdXJjZScgZXZlbnQuXG4gKlxuICogQHBhcmFtIGNvbnRlbnRzIGFuIGFycmF5IG9mIEppbmdsZSAnY29udGVudCcgZWxlbWVudHMuXG4gKi9cbkppbmdsZVNlc3Npb24ucHJvdG90eXBlLnJlbW92ZVNvdXJjZXMgPSBmdW5jdGlvbihjb250ZW50cykge307XG5cbi8qKlxuICogVGVybWluYXRlcyB0aGlzIEppbmdsZSBzZXNzaW9uIChzdG9wcyBzZW5kaW5nIG1lZGlhIGFuZCBjbG9zZXMgdGhlIHN0cmVhbXM/KVxuICovXG5KaW5nbGVTZXNzaW9uLnByb3RvdHlwZS50ZXJtaW5hdGUgPSBmdW5jdGlvbigpIHt9O1xuXG4vKipcbiAqIFNlbmRzIGEgSmluZ2xlIHNlc3Npb24tdGVybWluYXRlIG1lc3NhZ2UgdG8gdGhlIHBlZXIgYW5kIHRlcm1pbmF0ZXMgdGhlXG4gKiBzZXNzaW9uLlxuICogQHBhcmFtIHJlYXNvblxuICogQHBhcmFtIHRleHRcbiAqL1xuSmluZ2xlU2Vzc2lvbi5wcm90b3R5cGUuc2VuZFRlcm1pbmF0ZSA9IGZ1bmN0aW9uKHJlYXNvbiwgdGV4dCkge307XG5cbi8qKlxuICogSGFuZGxlcyBhbiBvZmZlciBmcm9tIHRoZSByZW1vdGUgcGVlciAocHJlcGFyZXMgdG8gYWNjZXB0IGEgc2Vzc2lvbikuXG4gKiBAcGFyYW0gamluZ2xlIHRoZSAnamluZ2xlJyBYTUwgZWxlbWVudC5cbiAqL1xuSmluZ2xlU2Vzc2lvbi5wcm90b3R5cGUuc2V0T2ZmZXIgPSBmdW5jdGlvbihqaW5nbGUpIHt9O1xuXG4vKipcbiAqIEhhbmRsZXMgYW4gYW5zd2VyIGZyb20gdGhlIHJlbW90ZSBwZWVyIChwcmVwYXJlcyB0byBhY2NlcHQgYSBzZXNzaW9uKS5cbiAqIEBwYXJhbSBqaW5nbGUgdGhlICdqaW5nbGUnIFhNTCBlbGVtZW50LlxuICovXG5KaW5nbGVTZXNzaW9uLnByb3RvdHlwZS5zZXRBbnN3ZXIgPSBmdW5jdGlvbihqaW5nbGUpIHt9O1xuXG5cbm1vZHVsZS5leHBvcnRzID0gSmluZ2xlU2Vzc2lvbjtcbiIsIi8qIGpzaGludCAtVzExNyAqL1xuXG52YXIgbG9nZ2VyID0gcmVxdWlyZShcImppdHNpLW1lZXQtbG9nZ2VyXCIpLmdldExvZ2dlcihfX2ZpbGVuYW1lKTtcbnZhciBKaW5nbGVTZXNzaW9uID0gcmVxdWlyZShcIi4vSmluZ2xlU2Vzc2lvblwiKTtcbnZhciBUcmFjZWFibGVQZWVyQ29ubmVjdGlvbiA9IHJlcXVpcmUoXCIuL1RyYWNlYWJsZVBlZXJDb25uZWN0aW9uXCIpO1xudmFyIFNEUERpZmZlciA9IHJlcXVpcmUoXCIuL1NEUERpZmZlclwiKTtcbnZhciBTRFBVdGlsID0gcmVxdWlyZShcIi4vU0RQVXRpbFwiKTtcbnZhciBTRFAgPSByZXF1aXJlKFwiLi9TRFBcIik7XG52YXIgYXN5bmMgPSByZXF1aXJlKFwiYXN5bmNcIik7XG52YXIgdHJhbnNmb3JtID0gcmVxdWlyZShcInNkcC10cmFuc2Zvcm1cIik7XG52YXIgWE1QUEV2ZW50cyA9IHJlcXVpcmUoXCIuLi8uLi9zZXJ2aWNlL3htcHAvWE1QUEV2ZW50c1wiKTtcbnZhciBSVENCcm93c2VyVHlwZSA9IHJlcXVpcmUoXCIuLi9SVEMvUlRDQnJvd3NlclR5cGVcIik7XG52YXIgU1NSQ1JlcGxhY2VtZW50ID0gcmVxdWlyZShcIi4vTG9jYWxTU1JDUmVwbGFjZW1lbnRcIik7XG52YXIgUlRDID0gcmVxdWlyZShcIi4uL1JUQy9SVENcIik7XG5cbi8vIEppbmdsZSBzdHVmZlxuZnVuY3Rpb24gSmluZ2xlU2Vzc2lvblBDKG1lLCBzaWQsIGNvbm5lY3Rpb24sIHNlcnZpY2UpIHtcbiAgICBKaW5nbGVTZXNzaW9uLmNhbGwodGhpcywgbWUsIHNpZCwgY29ubmVjdGlvbiwgc2VydmljZSk7XG4gICAgdGhpcy5pbml0aWF0b3IgPSBudWxsO1xuICAgIHRoaXMucmVzcG9uZGVyID0gbnVsbDtcbiAgICB0aGlzLnBlZXJqaWQgPSBudWxsO1xuICAgIHRoaXMuc3RhdGUgPSBudWxsO1xuICAgIHRoaXMubG9jYWxTRFAgPSBudWxsO1xuICAgIHRoaXMucmVtb3RlU0RQID0gbnVsbDtcbiAgICB0aGlzLnJlbGF5ZWRTdHJlYW1zID0gW107XG5cbiAgICB0aGlzLnVzZXRyaWNrbGUgPSB0cnVlO1xuICAgIHRoaXMudXNlcHJhbnN3ZXIgPSBmYWxzZTsgLy8gZWFybHkgdHJhbnNwb3J0IHdhcm11cCAtLSBtaW5kIHlvdSwgdGhpcyBtaWdodCBmYWlsLiBkZXBlbmRzIG9uIHdlYnJ0YyBpc3N1ZSAxNzE4XG5cbiAgICB0aGlzLmhhZHN0dW5jYW5kaWRhdGUgPSBmYWxzZTtcbiAgICB0aGlzLmhhZHR1cm5jYW5kaWRhdGUgPSBmYWxzZTtcbiAgICB0aGlzLmxhc3RpY2VjYW5kaWRhdGUgPSBmYWxzZTtcblxuICAgIHRoaXMuc3RhdHNpbnRlcnZhbCA9IG51bGw7XG5cbiAgICB0aGlzLnJlYXNvbiA9IG51bGw7XG5cbiAgICB0aGlzLmFkZHNzcmMgPSBbXTtcbiAgICB0aGlzLnJlbW92ZXNzcmMgPSBbXTtcbiAgICB0aGlzLnBlbmRpbmdvcCA9IG51bGw7XG4gICAgdGhpcy5zd2l0Y2hzdHJlYW1zID0gZmFsc2U7XG4gICAgdGhpcy5hZGRpbmdTdHJlYW1zID0gZmFsc2U7XG5cbiAgICB0aGlzLndhaXQgPSB0cnVlO1xuICAgIC8qKlxuICAgICAqIEEgbWFwIHRoYXQgc3RvcmVzIFNTUkNzIG9mIGxvY2FsIHN0cmVhbXNcbiAgICAgKiBAdHlwZSB7e319IG1hcHMgbWVkaWEgdHlwZSgnYXVkaW8nIG9yICd2aWRlbycpIHRvIFNTUkMgbnVtYmVyXG4gICAgICovXG4gICAgdGhpcy5sb2NhbFN0cmVhbXNTU1JDID0ge307XG4gICAgdGhpcy5zc3JjT3duZXJzID0ge307XG4gICAgdGhpcy5zc3JjVmlkZW9UeXBlcyA9IHt9O1xuXG4gICAgdGhpcy53ZWJydGNJY2VVZHBEaXNhYmxlID0gISF0aGlzLnNlcnZpY2Uub3B0aW9ucy53ZWJydGNJY2VVZHBEaXNhYmxlO1xuICAgIHRoaXMud2VicnRjSWNlVGNwRGlzYWJsZSA9ICEhdGhpcy5zZXJ2aWNlLm9wdGlvbnMud2VicnRjSWNlVGNwRGlzYWJsZTtcblxuICAgIC8qKlxuICAgICAqIFRoZSBpbmRpY2F0b3Igd2hpY2ggZGV0ZXJtaW5lcyB3aGV0aGVyIHRoZSAobG9jYWwpIHZpZGVvIGhhcyBiZWVuIG11dGVkXG4gICAgICogaW4gcmVzcG9uc2UgdG8gYSB1c2VyIGNvbW1hbmQgaW4gY29udHJhc3QgdG8gYW4gYXV0b21hdGljIGRlY2lzaW9uIG1hZGVcbiAgICAgKiBieSB0aGUgYXBwbGljYXRpb24gbG9naWMuXG4gICAgICovXG4gICAgdGhpcy52aWRlb011dGVCeVVzZXIgPSBmYWxzZTtcblxuICAgIHRoaXMubW9kaWZ5U291cmNlc1F1ZXVlID0gYXN5bmMucXVldWUodGhpcy5fbW9kaWZ5U291cmNlcy5iaW5kKHRoaXMpLCAxKTtcbiAgICAvLyBXZSBzdGFydCB3aXRoIHRoZSBxdWV1ZSBwYXVzZWQuIFdlIHJlc3VtZSBpdCB3aGVuIHRoZSBzaWduYWxpbmcgc3RhdGUgaXNcbiAgICAvLyBzdGFibGUgYW5kIHRoZSBpY2UgY29ubmVjdGlvbiBzdGF0ZSBpcyBjb25uZWN0ZWQuXG4gICAgdGhpcy5tb2RpZnlTb3VyY2VzUXVldWUucGF1c2UoKTtcbn1cbi8vWFhYIHRoaXMgaXMgYmFkbHkgYnJva2VuLi4uXG5KaW5nbGVTZXNzaW9uUEMucHJvdG90eXBlID0gSmluZ2xlU2Vzc2lvbi5wcm90b3R5cGU7XG5KaW5nbGVTZXNzaW9uUEMucHJvdG90eXBlLmNvbnN0cnVjdG9yID0gSmluZ2xlU2Vzc2lvblBDO1xuXG5cbkppbmdsZVNlc3Npb25QQy5wcm90b3R5cGUuc2V0T2ZmZXIgPSBmdW5jdGlvbihvZmZlcikge1xuICAgIHRoaXMuc2V0UmVtb3RlRGVzY3JpcHRpb24ob2ZmZXIsICdvZmZlcicpO1xufTtcblxuSmluZ2xlU2Vzc2lvblBDLnByb3RvdHlwZS5zZXRBbnN3ZXIgPSBmdW5jdGlvbihhbnN3ZXIpIHtcbiAgICB0aGlzLnNldFJlbW90ZURlc2NyaXB0aW9uKGFuc3dlciwgJ2Fuc3dlcicpO1xufTtcblxuSmluZ2xlU2Vzc2lvblBDLnByb3RvdHlwZS51cGRhdGVNb2RpZnlTb3VyY2VzUXVldWUgPSBmdW5jdGlvbigpIHtcbiAgICB2YXIgc2lnbmFsaW5nU3RhdGUgPSB0aGlzLnBlZXJjb25uZWN0aW9uLnNpZ25hbGluZ1N0YXRlO1xuICAgIHZhciBpY2VDb25uZWN0aW9uU3RhdGUgPSB0aGlzLnBlZXJjb25uZWN0aW9uLmljZUNvbm5lY3Rpb25TdGF0ZTtcbiAgICBpZiAoc2lnbmFsaW5nU3RhdGUgPT09ICdzdGFibGUnICYmIGljZUNvbm5lY3Rpb25TdGF0ZSA9PT0gJ2Nvbm5lY3RlZCcpIHtcbiAgICAgICAgdGhpcy5tb2RpZnlTb3VyY2VzUXVldWUucmVzdW1lKCk7XG4gICAgfSBlbHNlIHtcbiAgICAgICAgdGhpcy5tb2RpZnlTb3VyY2VzUXVldWUucGF1c2UoKTtcbiAgICB9XG59O1xuXG5KaW5nbGVTZXNzaW9uUEMucHJvdG90eXBlLmRvSW5pdGlhbGl6ZSA9IGZ1bmN0aW9uICgpIHtcbiAgICB2YXIgc2VsZiA9IHRoaXM7XG5cbiAgICB0aGlzLmhhZHN0dW5jYW5kaWRhdGUgPSBmYWxzZTtcbiAgICB0aGlzLmhhZHR1cm5jYW5kaWRhdGUgPSBmYWxzZTtcbiAgICB0aGlzLmxhc3RpY2VjYW5kaWRhdGUgPSBmYWxzZTtcbiAgICAvLyBUcnVlIGlmIHJlY29ubmVjdCBpcyBpbiBwcm9ncmVzc1xuICAgIHRoaXMuaXNyZWNvbm5lY3QgPSBmYWxzZTtcbiAgICAvLyBTZXQgdG8gdHJ1ZSBpZiB0aGUgY29ubmVjdGlvbiB3YXMgZXZlciBzdGFibGVcbiAgICB0aGlzLndhc3N0YWJsZSA9IGZhbHNlO1xuXG4gICAgdGhpcy5wZWVyY29ubmVjdGlvbiA9IG5ldyBUcmFjZWFibGVQZWVyQ29ubmVjdGlvbihcbiAgICAgICAgICAgIHRoaXMuY29ubmVjdGlvbi5qaW5nbGUuaWNlX2NvbmZpZyxcbiAgICAgICAgICAgIFJUQy5nZXRQQ0NvbnN0cmFpbnRzKCksXG4gICAgICAgICAgICB0aGlzKTtcblxuICAgIHRoaXMucGVlcmNvbm5lY3Rpb24ub25pY2VjYW5kaWRhdGUgPSBmdW5jdGlvbiAoZXZlbnQpIHtcbiAgICAgICAgdmFyIHByb3RvY29sO1xuICAgICAgICBpZiAoZXZlbnQgJiYgZXZlbnQuY2FuZGlkYXRlKSB7XG4gICAgICAgICAgICBwcm90b2NvbCA9ICh0eXBlb2YgZXZlbnQuY2FuZGlkYXRlLnByb3RvY29sID09PSAnc3RyaW5nJylcbiAgICAgICAgICAgICAgICA/IGV2ZW50LmNhbmRpZGF0ZS5wcm90b2NvbC50b0xvd2VyQ2FzZSgpIDogJyc7XG4gICAgICAgICAgICBpZiAoKHNlbGYud2VicnRjSWNlVGNwRGlzYWJsZSAmJiBwcm90b2NvbCA9PSAndGNwJykgfHxcbiAgICAgICAgICAgICAgICAoc2VsZi53ZWJydGNJY2VVZHBEaXNhYmxlICYmIHByb3RvY29sID09ICd1ZHAnKSkge1xuICAgICAgICAgICAgICAgIHJldHVybjtcbiAgICAgICAgICAgIH1cbiAgICAgICAgfVxuICAgICAgICBzZWxmLnNlbmRJY2VDYW5kaWRhdGUoZXZlbnQuY2FuZGlkYXRlKTtcbiAgICB9O1xuICAgIHRoaXMucGVlcmNvbm5lY3Rpb24ub25hZGRzdHJlYW0gPSBmdW5jdGlvbiAoZXZlbnQpIHtcbiAgICAgICAgaWYgKGV2ZW50LnN0cmVhbS5pZCAhPT0gJ2RlZmF1bHQnKSB7XG4gICAgICAgICAgICBsb2dnZXIubG9nKFwiUkVNT1RFIFNUUkVBTSBBRERFRDogXCIsIGV2ZW50LnN0cmVhbSAsIGV2ZW50LnN0cmVhbS5pZCk7XG4gICAgICAgICAgICBzZWxmLnJlbW90ZVN0cmVhbUFkZGVkKGV2ZW50KTtcbiAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgIC8vIFRoaXMgaXMgYSByZWN2b25seSBzdHJlYW0uIENsaWVudHMgdGhhdCBpbXBsZW1lbnQgVW5pZmllZCBQbGFuLFxuICAgICAgICAgICAgLy8gc3VjaCBhcyBGaXJlZm94IHVzZSByZWN2b25seSBcInN0cmVhbXMvY2hhbm5lbHMvdHJhY2tzXCIgZm9yXG4gICAgICAgICAgICAvLyByZWNlaXZpbmcgcmVtb3RlIHN0cmVhbS90cmFja3MsIGFzIG9wcG9zZWQgdG8gUGxhbiBCIHdoZXJlIHRoZXJlXG4gICAgICAgICAgICAvLyBhcmUgb25seSAzIGNoYW5uZWxzOiBhdWRpbywgdmlkZW8gYW5kIGRhdGEuXG4gICAgICAgICAgICBsb2dnZXIubG9nKFwiUkVDVk9OTFkgUkVNT1RFIFNUUkVBTSBJR05PUkVEOiBcIiArIGV2ZW50LnN0cmVhbSArIFwiIC0gXCIgKyBldmVudC5zdHJlYW0uaWQpO1xuICAgICAgICB9XG4gICAgfTtcbiAgICB0aGlzLnBlZXJjb25uZWN0aW9uLm9ucmVtb3Zlc3RyZWFtID0gZnVuY3Rpb24gKGV2ZW50KSB7XG4gICAgICAgIC8vIFJlbW92ZSB0aGUgc3RyZWFtIGZyb20gcmVtb3RlU3RyZWFtc1xuICAgICAgICAvLyBGSVhNRTogcmVtb3Rlc3RyZWFtcmVtb3ZlZC5qaW5nbGUgbm90IGRlZmluZWQgYW55d2hlcmUodW51c2VkKVxuXG4gICAgICAgICQoZG9jdW1lbnQpLnRyaWdnZXIoJ3JlbW90ZXN0cmVhbXJlbW92ZWQuamluZ2xlJywgW2V2ZW50LCBzZWxmLnNpZF0pO1xuICAgIH07XG4gICAgdGhpcy5wZWVyY29ubmVjdGlvbi5vbnNpZ25hbGluZ3N0YXRlY2hhbmdlID0gZnVuY3Rpb24gKGV2ZW50KSB7XG4gICAgICAgIGlmICghKHNlbGYgJiYgc2VsZi5wZWVyY29ubmVjdGlvbikpIHJldHVybjtcbiAgICAgICAgaWYgKHNlbGYucGVlcmNvbm5lY3Rpb24uc2lnbmFsaW5nU3RhdGUgPT09ICdzdGFibGUnKSB7XG4gICAgICAgICAgICBzZWxmLndhc3N0YWJsZSA9IHRydWU7XG4gICAgICAgIH1cbiAgICAgICAgc2VsZi51cGRhdGVNb2RpZnlTb3VyY2VzUXVldWUoKTtcbiAgICB9O1xuICAgIC8qKlxuICAgICAqIFRoZSBvbmljZWNvbm5lY3Rpb25zdGF0ZWNoYW5nZSBldmVudCBoYW5kbGVyIGNvbnRhaW5zIHRoZSBjb2RlIHRvIGV4ZWN1dGUgd2hlbiB0aGUgaWNlY29ubmVjdGlvbnN0YXRlY2hhbmdlIGV2ZW50LFxuICAgICAqIG9mIHR5cGUgRXZlbnQsIGlzIHJlY2VpdmVkIGJ5IHRoaXMgUlRDUGVlckNvbm5lY3Rpb24uIFN1Y2ggYW4gZXZlbnQgaXMgc2VudCB3aGVuIHRoZSB2YWx1ZSBvZlxuICAgICAqIFJUQ1BlZXJDb25uZWN0aW9uLmljZUNvbm5lY3Rpb25TdGF0ZSBjaGFuZ2VzLlxuICAgICAqXG4gICAgICogQHBhcmFtIGV2ZW50IHRoZSBldmVudCBjb250YWluaW5nIGluZm9ybWF0aW9uIGFib3V0IHRoZSBjaGFuZ2VcbiAgICAgKi9cbiAgICB0aGlzLnBlZXJjb25uZWN0aW9uLm9uaWNlY29ubmVjdGlvbnN0YXRlY2hhbmdlID0gZnVuY3Rpb24gKGV2ZW50KSB7XG4gICAgICAgIGlmICghKHNlbGYgJiYgc2VsZi5wZWVyY29ubmVjdGlvbikpIHJldHVybjtcbiAgICAgICAgbG9nZ2VyLmxvZyhcIihUSU1FKSBJQ0UgXCIgKyBzZWxmLnBlZXJjb25uZWN0aW9uLmljZUNvbm5lY3Rpb25TdGF0ZSArXG4gICAgICAgICAgICAgICAgICAgIFwiOlxcdFwiLCB3aW5kb3cucGVyZm9ybWFuY2Uubm93KCkpO1xuICAgICAgICBzZWxmLnVwZGF0ZU1vZGlmeVNvdXJjZXNRdWV1ZSgpO1xuICAgICAgICBzd2l0Y2ggKHNlbGYucGVlcmNvbm5lY3Rpb24uaWNlQ29ubmVjdGlvblN0YXRlKSB7XG4gICAgICAgICAgICBjYXNlICdjb25uZWN0ZWQnOlxuXG4gICAgICAgICAgICAgICAgLy8gSW5mb3JtcyBpbnRlcmVzdGVkIHBhcnRpZXMgdGhhdCB0aGUgY29ubmVjdGlvbiBoYXMgYmVlbiByZXN0b3JlZC5cbiAgICAgICAgICAgICAgICBpZiAoc2VsZi5wZWVyY29ubmVjdGlvbi5zaWduYWxpbmdTdGF0ZSA9PT0gJ3N0YWJsZScgJiYgc2VsZi5pc3JlY29ubmVjdClcbiAgICAgICAgICAgICAgICAgICAgc2VsZi5yb29tLmV2ZW50RW1pdHRlci5lbWl0KFhNUFBFdmVudHMuQ09OTkVDVElPTl9SRVNUT1JFRCk7XG4gICAgICAgICAgICAgICAgc2VsZi5pc3JlY29ubmVjdCA9IGZhbHNlO1xuXG4gICAgICAgICAgICAgICAgYnJlYWs7XG4gICAgICAgICAgICBjYXNlICdkaXNjb25uZWN0ZWQnOlxuICAgICAgICAgICAgICAgIHNlbGYuaXNyZWNvbm5lY3QgPSB0cnVlO1xuICAgICAgICAgICAgICAgIC8vIEluZm9ybXMgaW50ZXJlc3RlZCBwYXJ0aWVzIHRoYXQgdGhlIGNvbm5lY3Rpb24gaGFzIGJlZW4gaW50ZXJydXB0ZWQuXG4gICAgICAgICAgICAgICAgaWYgKHNlbGYud2Fzc3RhYmxlKVxuICAgICAgICAgICAgICAgICAgICBzZWxmLnJvb20uZXZlbnRFbWl0dGVyLmVtaXQoWE1QUEV2ZW50cy5DT05ORUNUSU9OX0lOVEVSUlVQVEVEKTtcbiAgICAgICAgICAgICAgICBicmVhaztcbiAgICAgICAgICAgIGNhc2UgJ2ZhaWxlZCc6XG4gICAgICAgICAgICAgICAgc2VsZi5yb29tLmV2ZW50RW1pdHRlci5lbWl0KFhNUFBFdmVudHMuQ09ORkVSRU5DRV9TRVRVUF9GQUlMRUQpO1xuICAgICAgICAgICAgICAgIGJyZWFrO1xuICAgICAgICB9XG4gICAgICAgIG9uSWNlQ29ubmVjdGlvblN0YXRlQ2hhbmdlKHNlbGYuc2lkLCBzZWxmKTtcbiAgICB9O1xuICAgIHRoaXMucGVlcmNvbm5lY3Rpb24ub25uZWdvdGlhdGlvbm5lZWRlZCA9IGZ1bmN0aW9uIChldmVudCkge1xuICAgICAgICBzZWxmLnJvb20uZXZlbnRFbWl0dGVyLmVtaXQoWE1QUEV2ZW50cy5QRUVSQ09OTkVDVElPTl9SRUFEWSwgc2VsZik7XG4gICAgfTtcblxuICAgIHRoaXMucmVsYXllZFN0cmVhbXMuZm9yRWFjaChmdW5jdGlvbihzdHJlYW0pIHtcbiAgICAgICAgc2VsZi5wZWVyY29ubmVjdGlvbi5hZGRTdHJlYW0oc3RyZWFtKTtcbiAgICB9KTtcbn07XG5cbmZ1bmN0aW9uIG9uSWNlQ29ubmVjdGlvblN0YXRlQ2hhbmdlKHNpZCwgc2Vzc2lvbikge1xuICAgIHN3aXRjaCAoc2Vzc2lvbi5wZWVyY29ubmVjdGlvbi5pY2VDb25uZWN0aW9uU3RhdGUpIHtcbiAgICAgICAgY2FzZSAnY2hlY2tpbmcnOlxuICAgICAgICAgICAgc2Vzc2lvbi50aW1lQ2hlY2tpbmcgPSAobmV3IERhdGUoKSkuZ2V0VGltZSgpO1xuICAgICAgICAgICAgc2Vzc2lvbi5maXJzdGNvbm5lY3QgPSB0cnVlO1xuICAgICAgICAgICAgYnJlYWs7XG4gICAgICAgIGNhc2UgJ2NvbXBsZXRlZCc6IC8vIG9uIGNhbGxlciBzaWRlXG4gICAgICAgIGNhc2UgJ2Nvbm5lY3RlZCc6XG4gICAgICAgICAgICBpZiAoc2Vzc2lvbi5maXJzdGNvbm5lY3QpIHtcbiAgICAgICAgICAgICAgICBzZXNzaW9uLmZpcnN0Y29ubmVjdCA9IGZhbHNlO1xuICAgICAgICAgICAgICAgIHZhciBtZXRhZGF0YSA9IHt9O1xuICAgICAgICAgICAgICAgIG1ldGFkYXRhLnNldHVwVGltZVxuICAgICAgICAgICAgICAgICAgICA9IChuZXcgRGF0ZSgpKS5nZXRUaW1lKCkgLSBzZXNzaW9uLnRpbWVDaGVja2luZztcbiAgICAgICAgICAgICAgICBzZXNzaW9uLnBlZXJjb25uZWN0aW9uLmdldFN0YXRzKGZ1bmN0aW9uIChyZXMpIHtcbiAgICAgICAgICAgICAgICAgICAgaWYocmVzICYmIHJlcy5yZXN1bHQpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgIHJlcy5yZXN1bHQoKS5mb3JFYWNoKGZ1bmN0aW9uIChyZXBvcnQpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICBpZiAocmVwb3J0LnR5cGUgPT0gJ2dvb2dDYW5kaWRhdGVQYWlyJyAmJlxuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICByZXBvcnQuc3RhdCgnZ29vZ0FjdGl2ZUNvbm5lY3Rpb24nKSA9PSAndHJ1ZScpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgbWV0YWRhdGEubG9jYWxDYW5kaWRhdGVUeXBlXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICA9IHJlcG9ydC5zdGF0KCdnb29nTG9jYWxDYW5kaWRhdGVUeXBlJyk7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIG1ldGFkYXRhLnJlbW90ZUNhbmRpZGF0ZVR5cGVcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgID0gcmVwb3J0LnN0YXQoJ2dvb2dSZW1vdGVDYW5kaWRhdGVUeXBlJyk7XG5cbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgLy8gbG9nIHBhaXIgYXMgd2VsbCBzbyB3ZSBjYW4gZ2V0IG5pY2UgcGllXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIC8vIGNoYXJ0c1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBtZXRhZGF0YS5jYW5kaWRhdGVQYWlyXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICA9IHJlcG9ydC5zdGF0KCdnb29nTG9jYWxDYW5kaWRhdGVUeXBlJykgK1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICc7JyArXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgcmVwb3J0LnN0YXQoJ2dvb2dSZW1vdGVDYW5kaWRhdGVUeXBlJyk7XG5cbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgaWYgKHJlcG9ydC5zdGF0KCdnb29nUmVtb3RlQWRkcmVzcycpLmluZGV4T2YoJ1snKSA9PT0gMClcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAge1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgbWV0YWRhdGEuaXB2NiA9IHRydWU7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgICAgICAgICB9KTtcbiAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgIH0pO1xuICAgICAgICAgICAgfVxuICAgICAgICAgICAgYnJlYWs7XG4gICAgfVxufVxuXG5KaW5nbGVTZXNzaW9uUEMucHJvdG90eXBlLmFjY2VwdCA9IGZ1bmN0aW9uICgpIHtcbiAgICB0aGlzLnN0YXRlID0gJ2FjdGl2ZSc7XG5cbiAgICB2YXIgcHJhbnN3ZXIgPSB0aGlzLnBlZXJjb25uZWN0aW9uLmxvY2FsRGVzY3JpcHRpb247XG4gICAgaWYgKCFwcmFuc3dlciB8fCBwcmFuc3dlci50eXBlICE9ICdwcmFuc3dlcicpIHtcbiAgICAgICAgcmV0dXJuO1xuICAgIH1cbiAgICBsb2dnZXIubG9nKCdnb2luZyBmcm9tIHByYW5zd2VyIHRvIGFuc3dlcicpO1xuICAgIGlmICh0aGlzLnVzZXRyaWNrbGUpIHtcbiAgICAgICAgLy8gcmVtb3ZlIGNhbmRpZGF0ZXMgYWxyZWFkeSBzZW50IGZyb20gc2Vzc2lvbi1hY2NlcHRcbiAgICAgICAgdmFyIGxpbmVzID0gU0RQVXRpbC5maW5kX2xpbmVzKHByYW5zd2VyLnNkcCwgJ2E9Y2FuZGlkYXRlOicpO1xuICAgICAgICBmb3IgKHZhciBpID0gMDsgaSA8IGxpbmVzLmxlbmd0aDsgaSsrKSB7XG4gICAgICAgICAgICBwcmFuc3dlci5zZHAgPSBwcmFuc3dlci5zZHAucmVwbGFjZShsaW5lc1tpXSArICdcXHJcXG4nLCAnJyk7XG4gICAgICAgIH1cbiAgICB9XG4gICAgd2hpbGUgKFNEUFV0aWwuZmluZF9saW5lKHByYW5zd2VyLnNkcCwgJ2E9aW5hY3RpdmUnKSkge1xuICAgICAgICAvLyBGSVhNRTogY2hhbmdlIGFueSBpbmFjdGl2ZSB0byBzZW5kcmVjdiBvciB3aGF0ZXZlciB0aGV5IHdlcmUgb3JpZ2luYWxseVxuICAgICAgICBwcmFuc3dlci5zZHAgPSBwcmFuc3dlci5zZHAucmVwbGFjZSgnYT1pbmFjdGl2ZScsICdhPXNlbmRyZWN2Jyk7XG4gICAgfVxuICAgIHZhciBwcnNkcCA9IG5ldyBTRFAocHJhbnN3ZXIuc2RwKTtcbiAgICBpZiAoc2VsZi53ZWJydGNJY2VUY3BEaXNhYmxlKSB7XG4gICAgICAgIHByc2RwLnJlbW92ZVRjcENhbmRpZGF0ZXMgPSB0cnVlO1xuICAgIH1cbiAgICBpZiAoc2VsZi53ZWJydGNJY2VVZHBEaXNhYmxlKSB7XG4gICAgICAgIHByc2RwLnJlbW92ZVVkcENhbmRpZGF0ZXMgPSB0cnVlO1xuICAgIH1cbiAgICB2YXIgYWNjZXB0ID0gJGlxKHt0bzogdGhpcy5wZWVyamlkLFxuICAgICAgICB0eXBlOiAnc2V0J30pXG4gICAgICAgIC5jKCdqaW5nbGUnLCB7eG1sbnM6ICd1cm46eG1wcDpqaW5nbGU6MScsXG4gICAgICAgICAgICBhY3Rpb246ICdzZXNzaW9uLWFjY2VwdCcsXG4gICAgICAgICAgICBpbml0aWF0b3I6IHRoaXMuaW5pdGlhdG9yLFxuICAgICAgICAgICAgcmVzcG9uZGVyOiB0aGlzLnJlc3BvbmRlcixcbiAgICAgICAgICAgIHNpZDogdGhpcy5zaWQgfSk7XG4gICAgLy8gRklYTUUgd2h5IGRvIHdlIGdlbmVyYXRlIHNlc3Npb24tYWNjZXB0IGluIDMgZGlmZmVyZW50IHBsYWNlcyA/XG4gICAgcHJzZHAudG9KaW5nbGUoXG4gICAgICAgIGFjY2VwdCxcbiAgICAgICAgdGhpcy5pbml0aWF0b3IgPT0gdGhpcy5tZSA/ICdpbml0aWF0b3InIDogJ3Jlc3BvbmRlcicpO1xuICAgIHZhciBzZHAgPSB0aGlzLnBlZXJjb25uZWN0aW9uLmxvY2FsRGVzY3JpcHRpb24uc2RwO1xuICAgIHdoaWxlIChTRFBVdGlsLmZpbmRfbGluZShzZHAsICdhPWluYWN0aXZlJykpIHtcbiAgICAgICAgLy8gRklYTUU6IGNoYW5nZSBhbnkgaW5hY3RpdmUgdG8gc2VuZHJlY3Ygb3Igd2hhdGV2ZXIgdGhleSB3ZXJlIG9yaWdpbmFsbHlcbiAgICAgICAgc2RwID0gc2RwLnJlcGxhY2UoJ2E9aW5hY3RpdmUnLCAnYT1zZW5kcmVjdicpO1xuICAgIH1cbiAgICB2YXIgc2VsZiA9IHRoaXM7XG4gICAgdGhpcy5wZWVyY29ubmVjdGlvbi5zZXRMb2NhbERlc2NyaXB0aW9uKG5ldyBSVENTZXNzaW9uRGVzY3JpcHRpb24oe3R5cGU6ICdhbnN3ZXInLCBzZHA6IHNkcH0pLFxuICAgICAgICBmdW5jdGlvbiAoKSB7XG4gICAgICAgICAgICAvL2xvZ2dlci5sb2coJ3NldExvY2FsRGVzY3JpcHRpb24gc3VjY2VzcycpO1xuICAgICAgICAgICAgc2VsZi5zZXRMb2NhbERlc2NyaXB0aW9uKCk7XG5cbiAgICAgICAgICAgIFNTUkNSZXBsYWNlbWVudC5wcm9jZXNzU2Vzc2lvbkluaXQoYWNjZXB0KTtcblxuICAgICAgICAgICAgc2VsZi5jb25uZWN0aW9uLnNlbmRJUShhY2NlcHQsXG4gICAgICAgICAgICAgICAgZnVuY3Rpb24gKCkge1xuICAgICAgICAgICAgICAgICAgICB2YXIgYWNrID0ge307XG4gICAgICAgICAgICAgICAgICAgIGFjay5zb3VyY2UgPSAnYW5zd2VyJztcbiAgICAgICAgICAgICAgICAgICAgJChkb2N1bWVudCkudHJpZ2dlcignYWNrLmppbmdsZScsIFtzZWxmLnNpZCwgYWNrXSk7XG4gICAgICAgICAgICAgICAgfSxcbiAgICAgICAgICAgICAgICBmdW5jdGlvbiAoc3RhbnphKSB7XG4gICAgICAgICAgICAgICAgICAgIHZhciBlcnJvciA9ICgkKHN0YW56YSkuZmluZCgnZXJyb3InKS5sZW5ndGgpID8ge1xuICAgICAgICAgICAgICAgICAgICAgICAgY29kZTogJChzdGFuemEpLmZpbmQoJ2Vycm9yJykuYXR0cignY29kZScpLFxuICAgICAgICAgICAgICAgICAgICAgICAgcmVhc29uOiAkKHN0YW56YSkuZmluZCgnZXJyb3IgOmZpcnN0JylbMF0udGFnTmFtZVxuICAgICAgICAgICAgICAgICAgICB9Ont9O1xuICAgICAgICAgICAgICAgICAgICBlcnJvci5zb3VyY2UgPSAnYW5zd2VyJztcbiAgICAgICAgICAgICAgICAgICAgSmluZ2xlU2Vzc2lvblBDLm9uSmluZ2xlRXJyb3Ioc2VsZi5zaWQsIGVycm9yKTtcbiAgICAgICAgICAgICAgICB9LFxuICAgICAgICAgICAgICAgIDEwMDAwKTtcbiAgICAgICAgfSxcbiAgICAgICAgZnVuY3Rpb24gKGUpIHtcbiAgICAgICAgICAgIGxvZ2dlci5lcnJvcignc2V0TG9jYWxEZXNjcmlwdGlvbiBmYWlsZWQnLCBlKTtcbiAgICAgICAgICAgIHNlbGYucm9vbS5ldmVudEVtaXR0ZXIuZW1pdChYTVBQRXZlbnRzLkNPTkZFUkVOQ0VfU0VUVVBfRkFJTEVEKTtcbiAgICAgICAgfVxuICAgICk7XG59O1xuXG5KaW5nbGVTZXNzaW9uUEMucHJvdG90eXBlLnRlcm1pbmF0ZSA9IGZ1bmN0aW9uIChyZWFzb24pIHtcbiAgICB0aGlzLnN0YXRlID0gJ2VuZGVkJztcbiAgICB0aGlzLnJlYXNvbiA9IHJlYXNvbjtcbiAgICB0aGlzLnBlZXJjb25uZWN0aW9uLmNsb3NlKCk7XG4gICAgaWYgKHRoaXMuc3RhdHNpbnRlcnZhbCAhPT0gbnVsbCkge1xuICAgICAgICB3aW5kb3cuY2xlYXJJbnRlcnZhbCh0aGlzLnN0YXRzaW50ZXJ2YWwpO1xuICAgICAgICB0aGlzLnN0YXRzaW50ZXJ2YWwgPSBudWxsO1xuICAgIH1cbn07XG5cbkppbmdsZVNlc3Npb25QQy5wcm90b3R5cGUuYWN0aXZlID0gZnVuY3Rpb24gKCkge1xuICAgIHJldHVybiB0aGlzLnN0YXRlID09ICdhY3RpdmUnO1xufTtcblxuSmluZ2xlU2Vzc2lvblBDLnByb3RvdHlwZS5zZW5kSWNlQ2FuZGlkYXRlID0gZnVuY3Rpb24gKGNhbmRpZGF0ZSkge1xuICAgIHZhciBzZWxmID0gdGhpcztcbiAgICBpZiAoY2FuZGlkYXRlICYmICF0aGlzLmxhc3RpY2VjYW5kaWRhdGUpIHtcbiAgICAgICAgdmFyIGljZSA9IFNEUFV0aWwuaWNlcGFyYW1zKHRoaXMubG9jYWxTRFAubWVkaWFbY2FuZGlkYXRlLnNkcE1MaW5lSW5kZXhdLCB0aGlzLmxvY2FsU0RQLnNlc3Npb24pO1xuICAgICAgICB2YXIgamNhbmQgPSBTRFBVdGlsLmNhbmRpZGF0ZVRvSmluZ2xlKGNhbmRpZGF0ZS5jYW5kaWRhdGUpO1xuICAgICAgICBpZiAoIShpY2UgJiYgamNhbmQpKSB7XG4gICAgICAgICAgICBsb2dnZXIuZXJyb3IoJ2ZhaWxlZCB0byBnZXQgaWNlICYmIGpjYW5kJyk7XG4gICAgICAgICAgICByZXR1cm47XG4gICAgICAgIH1cbiAgICAgICAgaWNlLnhtbG5zID0gJ3Vybjp4bXBwOmppbmdsZTp0cmFuc3BvcnRzOmljZS11ZHA6MSc7XG5cbiAgICAgICAgaWYgKGpjYW5kLnR5cGUgPT09ICdzcmZseCcpIHtcbiAgICAgICAgICAgIHRoaXMuaGFkc3R1bmNhbmRpZGF0ZSA9IHRydWU7XG4gICAgICAgIH0gZWxzZSBpZiAoamNhbmQudHlwZSA9PT0gJ3JlbGF5Jykge1xuICAgICAgICAgICAgdGhpcy5oYWR0dXJuY2FuZGlkYXRlID0gdHJ1ZTtcbiAgICAgICAgfVxuXG4gICAgICAgIGlmICh0aGlzLnVzZXRyaWNrbGUpIHtcbiAgICAgICAgICAgIGlmICh0aGlzLnVzZWRyaXApIHtcbiAgICAgICAgICAgICAgICBpZiAodGhpcy5kcmlwX2NvbnRhaW5lci5sZW5ndGggPT09IDApIHtcbiAgICAgICAgICAgICAgICAgICAgLy8gc3RhcnQgMjBtcyBjYWxsb3V0XG4gICAgICAgICAgICAgICAgICAgIHdpbmRvdy5zZXRUaW1lb3V0KGZ1bmN0aW9uICgpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgIGlmIChzZWxmLmRyaXBfY29udGFpbmVyLmxlbmd0aCA9PT0gMCkgcmV0dXJuO1xuICAgICAgICAgICAgICAgICAgICAgICAgc2VsZi5zZW5kSWNlQ2FuZGlkYXRlcyhzZWxmLmRyaXBfY29udGFpbmVyKTtcbiAgICAgICAgICAgICAgICAgICAgICAgIHNlbGYuZHJpcF9jb250YWluZXIgPSBbXTtcbiAgICAgICAgICAgICAgICAgICAgfSwgMjApO1xuXG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgIHRoaXMuZHJpcF9jb250YWluZXIucHVzaChjYW5kaWRhdGUpO1xuICAgICAgICAgICAgICAgIHJldHVybjtcbiAgICAgICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICAgICAgc2VsZi5zZW5kSWNlQ2FuZGlkYXRlKFtjYW5kaWRhdGVdKTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgfVxuICAgIH0gZWxzZSB7XG4gICAgICAgIC8vbG9nZ2VyLmxvZygnc2VuZEljZUNhbmRpZGF0ZTogbGFzdCBjYW5kaWRhdGUuJyk7XG4gICAgICAgIGlmICghdGhpcy51c2V0cmlja2xlKSB7XG4gICAgICAgICAgICAvL2xvZ2dlci5sb2coJ3Nob3VsZCBzZW5kIGZ1bGwgb2ZmZXIgbm93Li4uJyk7XG4gICAgICAgICAgICAvL0ZJWE1FIHdoeSBkbyB3ZSBnZW5lcmF0ZSBzZXNzaW9uLWFjY2VwdCBpbiAzIGRpZmZlcmVudCBwbGFjZXMgP1xuICAgICAgICAgICAgdmFyIGluaXQgPSAkaXEoe3RvOiB0aGlzLnBlZXJqaWQsXG4gICAgICAgICAgICAgICAgdHlwZTogJ3NldCd9KVxuICAgICAgICAgICAgICAgIC5jKCdqaW5nbGUnLCB7eG1sbnM6ICd1cm46eG1wcDpqaW5nbGU6MScsXG4gICAgICAgICAgICAgICAgICAgIGFjdGlvbjogdGhpcy5wZWVyY29ubmVjdGlvbi5sb2NhbERlc2NyaXB0aW9uLnR5cGUgPT0gJ29mZmVyJyA/ICdzZXNzaW9uLWluaXRpYXRlJyA6ICdzZXNzaW9uLWFjY2VwdCcsXG4gICAgICAgICAgICAgICAgICAgIGluaXRpYXRvcjogdGhpcy5pbml0aWF0b3IsXG4gICAgICAgICAgICAgICAgICAgIHNpZDogdGhpcy5zaWR9KTtcbiAgICAgICAgICAgIHRoaXMubG9jYWxTRFAgPSBuZXcgU0RQKHRoaXMucGVlcmNvbm5lY3Rpb24ubG9jYWxEZXNjcmlwdGlvbi5zZHApO1xuICAgICAgICAgICAgaWYgKHNlbGYud2VicnRjSWNlVGNwRGlzYWJsZSkge1xuICAgICAgICAgICAgICAgIHRoaXMubG9jYWxTRFAucmVtb3ZlVGNwQ2FuZGlkYXRlcyA9IHRydWU7XG4gICAgICAgICAgICB9XG4gICAgICAgICAgICBpZiAoc2VsZi53ZWJydGNJY2VVZHBEaXNhYmxlKSB7XG4gICAgICAgICAgICAgICAgdGhpcy5sb2NhbFNEUC5yZW1vdmVVZHBDYW5kaWRhdGVzID0gdHJ1ZTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgICAgIHZhciBzZW5kSmluZ2xlID0gZnVuY3Rpb24gKHNzcmMpIHtcbiAgICAgICAgICAgICAgICBpZighc3NyYylcbiAgICAgICAgICAgICAgICAgICAgc3NyYyA9IHt9O1xuICAgICAgICAgICAgICAgIHNlbGYubG9jYWxTRFAudG9KaW5nbGUoXG4gICAgICAgICAgICAgICAgICAgIGluaXQsXG4gICAgICAgICAgICAgICAgICAgIHNlbGYuaW5pdGlhdG9yID09IHNlbGYubWUgPyAnaW5pdGlhdG9yJyA6ICdyZXNwb25kZXInLFxuICAgICAgICAgICAgICAgICAgICBzc3JjKTtcblxuICAgICAgICAgICAgICAgIFNTUkNSZXBsYWNlbWVudC5wcm9jZXNzU2Vzc2lvbkluaXQoaW5pdCk7XG5cbiAgICAgICAgICAgICAgICBzZWxmLmNvbm5lY3Rpb24uc2VuZElRKGluaXQsXG4gICAgICAgICAgICAgICAgICAgIGZ1bmN0aW9uICgpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgIC8vbG9nZ2VyLmxvZygnc2Vzc2lvbiBpbml0aWF0ZSBhY2snKTtcbiAgICAgICAgICAgICAgICAgICAgICAgIHZhciBhY2sgPSB7fTtcbiAgICAgICAgICAgICAgICAgICAgICAgIGFjay5zb3VyY2UgPSAnb2ZmZXInO1xuICAgICAgICAgICAgICAgICAgICAgICAgJChkb2N1bWVudCkudHJpZ2dlcignYWNrLmppbmdsZScsIFtzZWxmLnNpZCwgYWNrXSk7XG4gICAgICAgICAgICAgICAgICAgIH0sXG4gICAgICAgICAgICAgICAgICAgIGZ1bmN0aW9uIChzdGFuemEpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgIHNlbGYuc3RhdGUgPSAnZXJyb3InO1xuICAgICAgICAgICAgICAgICAgICAgICAgc2VsZi5wZWVyY29ubmVjdGlvbi5jbG9zZSgpO1xuICAgICAgICAgICAgICAgICAgICAgICAgdmFyIGVycm9yID0gKCQoc3RhbnphKS5maW5kKCdlcnJvcicpLmxlbmd0aCkgPyB7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgY29kZTogJChzdGFuemEpLmZpbmQoJ2Vycm9yJykuYXR0cignY29kZScpLFxuICAgICAgICAgICAgICAgICAgICAgICAgICAgIHJlYXNvbjogJChzdGFuemEpLmZpbmQoJ2Vycm9yIDpmaXJzdCcpWzBdLnRhZ05hbWUsXG4gICAgICAgICAgICAgICAgICAgICAgICB9Ont9O1xuICAgICAgICAgICAgICAgICAgICAgICAgZXJyb3Iuc291cmNlID0gJ29mZmVyJztcbiAgICAgICAgICAgICAgICAgICAgICAgIEppbmdsZVNlc3Npb25QQy5vbkppbmdsZUVycm9yKHNlbGYuc2lkLCBlcnJvcik7XG4gICAgICAgICAgICAgICAgICAgIH0sXG4gICAgICAgICAgICAgICAgICAgIDEwMDAwKTtcbiAgICAgICAgICAgIH07XG4gICAgICAgICAgICBzZW5kSmluZ2xlKCk7XG4gICAgICAgIH1cbiAgICAgICAgdGhpcy5sYXN0aWNlY2FuZGlkYXRlID0gdHJ1ZTtcbiAgICAgICAgbG9nZ2VyLmxvZygnSGF2ZSB3ZSBlbmNvdW50ZXJlZCBhbnkgc3JmbHggY2FuZGlkYXRlcz8gJyArIHRoaXMuaGFkc3R1bmNhbmRpZGF0ZSk7XG4gICAgICAgIGxvZ2dlci5sb2coJ0hhdmUgd2UgZW5jb3VudGVyZWQgYW55IHJlbGF5IGNhbmRpZGF0ZXM/ICcgKyB0aGlzLmhhZHR1cm5jYW5kaWRhdGUpO1xuXG4gICAgICAgIGlmICghKHRoaXMuaGFkc3R1bmNhbmRpZGF0ZSB8fCB0aGlzLmhhZHR1cm5jYW5kaWRhdGUpICYmIHRoaXMucGVlcmNvbm5lY3Rpb24uc2lnbmFsaW5nU3RhdGUgIT0gJ2Nsb3NlZCcpIHtcbiAgICAgICAgICAgICQoZG9jdW1lbnQpLnRyaWdnZXIoJ25vc3R1bmNhbmRpZGF0ZXMuamluZ2xlJywgW3RoaXMuc2lkXSk7XG4gICAgICAgIH1cbiAgICB9XG59O1xuXG5KaW5nbGVTZXNzaW9uUEMucHJvdG90eXBlLnNlbmRJY2VDYW5kaWRhdGVzID0gZnVuY3Rpb24gKGNhbmRpZGF0ZXMpIHtcbiAgICBsb2dnZXIubG9nKCdzZW5kSWNlQ2FuZGlkYXRlcycsIGNhbmRpZGF0ZXMpO1xuICAgIHZhciBjYW5kID0gJGlxKHt0bzogdGhpcy5wZWVyamlkLCB0eXBlOiAnc2V0J30pXG4gICAgICAgIC5jKCdqaW5nbGUnLCB7eG1sbnM6ICd1cm46eG1wcDpqaW5nbGU6MScsXG4gICAgICAgICAgICBhY3Rpb246ICd0cmFuc3BvcnQtaW5mbycsXG4gICAgICAgICAgICBpbml0aWF0b3I6IHRoaXMuaW5pdGlhdG9yLFxuICAgICAgICAgICAgc2lkOiB0aGlzLnNpZH0pO1xuICAgIGZvciAodmFyIG1pZCA9IDA7IG1pZCA8IHRoaXMubG9jYWxTRFAubWVkaWEubGVuZ3RoOyBtaWQrKykge1xuICAgICAgICB2YXIgY2FuZHMgPSBjYW5kaWRhdGVzLmZpbHRlcihmdW5jdGlvbiAoZWwpIHsgcmV0dXJuIGVsLnNkcE1MaW5lSW5kZXggPT0gbWlkOyB9KTtcbiAgICAgICAgdmFyIG1saW5lID0gU0RQVXRpbC5wYXJzZV9tbGluZSh0aGlzLmxvY2FsU0RQLm1lZGlhW21pZF0uc3BsaXQoJ1xcclxcbicpWzBdKTtcbiAgICAgICAgaWYgKGNhbmRzLmxlbmd0aCA+IDApIHtcbiAgICAgICAgICAgIHZhciBpY2UgPSBTRFBVdGlsLmljZXBhcmFtcyh0aGlzLmxvY2FsU0RQLm1lZGlhW21pZF0sIHRoaXMubG9jYWxTRFAuc2Vzc2lvbik7XG4gICAgICAgICAgICBpY2UueG1sbnMgPSAndXJuOnhtcHA6amluZ2xlOnRyYW5zcG9ydHM6aWNlLXVkcDoxJztcbiAgICAgICAgICAgIGNhbmQuYygnY29udGVudCcsIHtjcmVhdG9yOiB0aGlzLmluaXRpYXRvciA9PSB0aGlzLm1lID8gJ2luaXRpYXRvcicgOiAncmVzcG9uZGVyJyxcbiAgICAgICAgICAgICAgICBuYW1lOiAoY2FuZHNbMF0uc2RwTWlkPyBjYW5kc1swXS5zZHBNaWQgOiBtbGluZS5tZWRpYSlcbiAgICAgICAgICAgIH0pLmMoJ3RyYW5zcG9ydCcsIGljZSk7XG4gICAgICAgICAgICBmb3IgKHZhciBpID0gMDsgaSA8IGNhbmRzLmxlbmd0aDsgaSsrKSB7XG4gICAgICAgICAgICAgICAgY2FuZC5jKCdjYW5kaWRhdGUnLCBTRFBVdGlsLmNhbmRpZGF0ZVRvSmluZ2xlKGNhbmRzW2ldLmNhbmRpZGF0ZSkpLnVwKCk7XG4gICAgICAgICAgICB9XG4gICAgICAgICAgICAvLyBhZGQgZmluZ2VycHJpbnRcbiAgICAgICAgICAgIGlmIChTRFBVdGlsLmZpbmRfbGluZSh0aGlzLmxvY2FsU0RQLm1lZGlhW21pZF0sICdhPWZpbmdlcnByaW50OicsIHRoaXMubG9jYWxTRFAuc2Vzc2lvbikpIHtcbiAgICAgICAgICAgICAgICB2YXIgdG1wID0gU0RQVXRpbC5wYXJzZV9maW5nZXJwcmludChTRFBVdGlsLmZpbmRfbGluZSh0aGlzLmxvY2FsU0RQLm1lZGlhW21pZF0sICdhPWZpbmdlcnByaW50OicsIHRoaXMubG9jYWxTRFAuc2Vzc2lvbikpO1xuICAgICAgICAgICAgICAgIHRtcC5yZXF1aXJlZCA9IHRydWU7XG4gICAgICAgICAgICAgICAgY2FuZC5jKFxuICAgICAgICAgICAgICAgICAgICAnZmluZ2VycHJpbnQnLFxuICAgICAgICAgICAgICAgICAgICB7eG1sbnM6ICd1cm46eG1wcDpqaW5nbGU6YXBwczpkdGxzOjAnfSlcbiAgICAgICAgICAgICAgICAgICAgLnQodG1wLmZpbmdlcnByaW50KTtcbiAgICAgICAgICAgICAgICBkZWxldGUgdG1wLmZpbmdlcnByaW50O1xuICAgICAgICAgICAgICAgIGNhbmQuYXR0cnModG1wKTtcbiAgICAgICAgICAgICAgICBjYW5kLnVwKCk7XG4gICAgICAgICAgICB9XG4gICAgICAgICAgICBjYW5kLnVwKCk7IC8vIHRyYW5zcG9ydFxuICAgICAgICAgICAgY2FuZC51cCgpOyAvLyBjb250ZW50XG4gICAgICAgIH1cbiAgICB9XG4gICAgLy8gbWlnaHQgbWVyZ2UgbGFzdC1jYW5kaWRhdGUgbm90aWZpY2F0aW9uIGludG8gdGhpcywgYnV0IGl0IGlzIGNhbGxlZCBhbG90IGxhdGVyLiBTZWUgd2VicnRjIGlzc3VlICMyMzQwXG4gICAgLy9sb2dnZXIubG9nKCd3YXMgdGhpcyB0aGUgbGFzdCBjYW5kaWRhdGUnLCB0aGlzLmxhc3RpY2VjYW5kaWRhdGUpO1xuICAgIHRoaXMuY29ubmVjdGlvbi5zZW5kSVEoY2FuZCxcbiAgICAgICAgZnVuY3Rpb24gKCkge1xuICAgICAgICAgICAgdmFyIGFjayA9IHt9O1xuICAgICAgICAgICAgYWNrLnNvdXJjZSA9ICd0cmFuc3BvcnRpbmZvJztcbiAgICAgICAgICAgICQoZG9jdW1lbnQpLnRyaWdnZXIoJ2Fjay5qaW5nbGUnLCBbdGhpcy5zaWQsIGFja10pO1xuICAgICAgICB9LFxuICAgICAgICBmdW5jdGlvbiAoc3RhbnphKSB7XG4gICAgICAgICAgICB2YXIgZXJyb3IgPSAoJChzdGFuemEpLmZpbmQoJ2Vycm9yJykubGVuZ3RoKSA/IHtcbiAgICAgICAgICAgICAgICBjb2RlOiAkKHN0YW56YSkuZmluZCgnZXJyb3InKS5hdHRyKCdjb2RlJyksXG4gICAgICAgICAgICAgICAgcmVhc29uOiAkKHN0YW56YSkuZmluZCgnZXJyb3IgOmZpcnN0JylbMF0udGFnTmFtZSxcbiAgICAgICAgICAgIH06e307XG4gICAgICAgICAgICBlcnJvci5zb3VyY2UgPSAndHJhbnNwb3J0aW5mbyc7XG4gICAgICAgICAgICBKaW5nbGVTZXNzaW9uUEMub25KaW5nbGVFcnJvcih0aGlzLnNpZCwgZXJyb3IpO1xuICAgICAgICB9LFxuICAgICAgICAxMDAwMCk7XG59O1xuXG5cbkppbmdsZVNlc3Npb25QQy5wcm90b3R5cGUuc2VuZE9mZmVyID0gZnVuY3Rpb24gKCkge1xuICAgIC8vbG9nZ2VyLmxvZygnc2VuZE9mZmVyLi4uJyk7XG4gICAgdmFyIHNlbGYgPSB0aGlzO1xuICAgIHRoaXMucGVlcmNvbm5lY3Rpb24uY3JlYXRlT2ZmZXIoZnVuY3Rpb24gKHNkcCkge1xuICAgICAgICAgICAgc2VsZi5jcmVhdGVkT2ZmZXIoc2RwKTtcbiAgICAgICAgfSxcbiAgICAgICAgZnVuY3Rpb24gKGUpIHtcbiAgICAgICAgICAgIGxvZ2dlci5lcnJvcignY3JlYXRlT2ZmZXIgZmFpbGVkJywgZSk7XG4gICAgICAgIH0sXG4gICAgICAgIHRoaXMubWVkaWFfY29uc3RyYWludHNcbiAgICApO1xufTtcblxuLy8gRklYTUUgY3JlYXRlZE9mZmVyIGlzIG5ldmVyIHVzZWQgaW4gaml0c2ktbWVldFxuSmluZ2xlU2Vzc2lvblBDLnByb3RvdHlwZS5jcmVhdGVkT2ZmZXIgPSBmdW5jdGlvbiAoc2RwKSB7XG4gICAgLy9sb2dnZXIubG9nKCdjcmVhdGVkT2ZmZXInLCBzZHApO1xuICAgIHZhciBzZWxmID0gdGhpcztcbiAgICB0aGlzLmxvY2FsU0RQID0gbmV3IFNEUChzZHAuc2RwKTtcbiAgICAvL3RoaXMubG9jYWxTRFAubWFuZ2xlKCk7XG4gICAgdmFyIHNlbmRKaW5nbGUgPSBmdW5jdGlvbiAoKSB7XG4gICAgICAgIHZhciBpbml0ID0gJGlxKHt0bzogdGhpcy5wZWVyamlkLFxuICAgICAgICAgICAgdHlwZTogJ3NldCd9KVxuICAgICAgICAgICAgLmMoJ2ppbmdsZScsIHt4bWxuczogJ3Vybjp4bXBwOmppbmdsZToxJyxcbiAgICAgICAgICAgICAgICBhY3Rpb246ICdzZXNzaW9uLWluaXRpYXRlJyxcbiAgICAgICAgICAgICAgICBpbml0aWF0b3I6IHRoaXMuaW5pdGlhdG9yLFxuICAgICAgICAgICAgICAgIHNpZDogdGhpcy5zaWR9KTtcbiAgICAgICAgc2VsZi5sb2NhbFNEUC50b0ppbmdsZShcbiAgICAgICAgICAgIGluaXQsXG4gICAgICAgICAgICB0aGlzLmluaXRpYXRvciA9PSB0aGlzLm1lID8gJ2luaXRpYXRvcicgOiAncmVzcG9uZGVyJyk7XG5cbiAgICAgICAgU1NSQ1JlcGxhY2VtZW50LnByb2Nlc3NTZXNzaW9uSW5pdChpbml0KTtcblxuICAgICAgICBzZWxmLmNvbm5lY3Rpb24uc2VuZElRKGluaXQsXG4gICAgICAgICAgICBmdW5jdGlvbiAoKSB7XG4gICAgICAgICAgICAgICAgdmFyIGFjayA9IHt9O1xuICAgICAgICAgICAgICAgIGFjay5zb3VyY2UgPSAnb2ZmZXInO1xuICAgICAgICAgICAgICAgICQoZG9jdW1lbnQpLnRyaWdnZXIoJ2Fjay5qaW5nbGUnLCBbc2VsZi5zaWQsIGFja10pO1xuICAgICAgICAgICAgfSxcbiAgICAgICAgICAgIGZ1bmN0aW9uIChzdGFuemEpIHtcbiAgICAgICAgICAgICAgICBzZWxmLnN0YXRlID0gJ2Vycm9yJztcbiAgICAgICAgICAgICAgICBzZWxmLnBlZXJjb25uZWN0aW9uLmNsb3NlKCk7XG4gICAgICAgICAgICAgICAgdmFyIGVycm9yID0gKCQoc3RhbnphKS5maW5kKCdlcnJvcicpLmxlbmd0aCkgPyB7XG4gICAgICAgICAgICAgICAgICAgIGNvZGU6ICQoc3RhbnphKS5maW5kKCdlcnJvcicpLmF0dHIoJ2NvZGUnKSxcbiAgICAgICAgICAgICAgICAgICAgcmVhc29uOiAkKHN0YW56YSkuZmluZCgnZXJyb3IgOmZpcnN0JylbMF0udGFnTmFtZSxcbiAgICAgICAgICAgICAgICB9Ont9O1xuICAgICAgICAgICAgICAgIGVycm9yLnNvdXJjZSA9ICdvZmZlcic7XG4gICAgICAgICAgICAgICAgSmluZ2xlU2Vzc2lvblBDLm9uSmluZ2xlRXJyb3Ioc2VsZi5zaWQsIGVycm9yKTtcbiAgICAgICAgICAgIH0sXG4gICAgICAgICAgICAxMDAwMCk7XG4gICAgfVxuICAgIHNkcC5zZHAgPSB0aGlzLmxvY2FsU0RQLnJhdztcbiAgICB0aGlzLnBlZXJjb25uZWN0aW9uLnNldExvY2FsRGVzY3JpcHRpb24oc2RwLFxuICAgICAgICBmdW5jdGlvbiAoKSB7XG4gICAgICAgICAgICBpZihzZWxmLnVzZXRyaWNrbGUpXG4gICAgICAgICAgICB7XG4gICAgICAgICAgICAgICAgc2VuZEppbmdsZSgpO1xuICAgICAgICAgICAgfVxuICAgICAgICAgICAgc2VsZi5zZXRMb2NhbERlc2NyaXB0aW9uKCk7XG4gICAgICAgICAgICAvL2xvZ2dlci5sb2coJ3NldExvY2FsRGVzY3JpcHRpb24gc3VjY2VzcycpO1xuICAgICAgICB9LFxuICAgICAgICBmdW5jdGlvbiAoZSkge1xuICAgICAgICAgICAgbG9nZ2VyLmVycm9yKCdzZXRMb2NhbERlc2NyaXB0aW9uIGZhaWxlZCcsIGUpO1xuICAgICAgICAgICAgc2VsZi5yb29tLmV2ZW50RW1pdHRlci5lbWl0KFhNUFBFdmVudHMuQ09ORkVSRU5DRV9TRVRVUF9GQUlMRUQpO1xuICAgICAgICB9XG4gICAgKTtcbiAgICB2YXIgY2FuZHMgPSBTRFBVdGlsLmZpbmRfbGluZXModGhpcy5sb2NhbFNEUC5yYXcsICdhPWNhbmRpZGF0ZTonKTtcbiAgICBmb3IgKHZhciBpID0gMDsgaSA8IGNhbmRzLmxlbmd0aDsgaSsrKSB7XG4gICAgICAgIHZhciBjYW5kID0gU0RQVXRpbC5wYXJzZV9pY2VjYW5kaWRhdGUoY2FuZHNbaV0pO1xuICAgICAgICBpZiAoY2FuZC50eXBlID09ICdzcmZseCcpIHtcbiAgICAgICAgICAgIHRoaXMuaGFkc3R1bmNhbmRpZGF0ZSA9IHRydWU7XG4gICAgICAgIH0gZWxzZSBpZiAoY2FuZC50eXBlID09ICdyZWxheScpIHtcbiAgICAgICAgICAgIHRoaXMuaGFkdHVybmNhbmRpZGF0ZSA9IHRydWU7XG4gICAgICAgIH1cbiAgICB9XG59O1xuXG5KaW5nbGVTZXNzaW9uUEMucHJvdG90eXBlLnJlYWRTc3JjSW5mbyA9IGZ1bmN0aW9uIChjb250ZW50cykge1xuICAgIHZhciBzZWxmID0gdGhpcztcbiAgICAkKGNvbnRlbnRzKS5lYWNoKGZ1bmN0aW9uIChpZHgsIGNvbnRlbnQpIHtcbiAgICAgICAgdmFyIG5hbWUgPSAkKGNvbnRlbnQpLmF0dHIoJ25hbWUnKTtcbiAgICAgICAgdmFyIG1lZGlhVHlwZSA9IHRoaXMuZ2V0QXR0cmlidXRlKCduYW1lJyk7XG4gICAgICAgIHZhciBzc3JjcyA9ICQoY29udGVudCkuZmluZCgnZGVzY3JpcHRpb24+c291cmNlW3htbG5zPVwidXJuOnhtcHA6amluZ2xlOmFwcHM6cnRwOnNzbWE6MFwiXScpO1xuICAgICAgICBzc3Jjcy5lYWNoKGZ1bmN0aW9uICgpIHtcbiAgICAgICAgICAgIHZhciBzc3JjID0gdGhpcy5nZXRBdHRyaWJ1dGUoJ3NzcmMnKTtcbiAgICAgICAgICAgICQodGhpcykuZmluZCgnPnNzcmMtaW5mb1t4bWxucz1cImh0dHA6Ly9qaXRzaS5vcmcvaml0bWVldFwiXScpLmVhY2goXG4gICAgICAgICAgICAgICAgZnVuY3Rpb24gKCkge1xuICAgICAgICAgICAgICAgICAgICB2YXIgb3duZXIgPSB0aGlzLmdldEF0dHJpYnV0ZSgnb3duZXInKTtcbiAgICAgICAgICAgICAgICAgICAgc2VsZi5zc3JjT3duZXJzW3NzcmNdID0gb3duZXI7XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgKTtcbiAgICAgICAgfSk7XG4gICAgfSk7XG59O1xuXG4vKipcbiAqIFJldHVybnMgdGhlIFNTUkMgb2YgbG9jYWwgYXVkaW8gc3RyZWFtLlxuICogQHBhcmFtIG1lZGlhVHlwZSAnYXVkaW8nIG9yICd2aWRlbycgbWVkaWEgdHlwZVxuICogQHJldHVybnMgeyp9IHRoZSBTU1JDIG51bWJlciBvZiBsb2NhbCBhdWRpbyBvciB2aWRlbyBzdHJlYW0uXG4gKi9cbkppbmdsZVNlc3Npb25QQy5wcm90b3R5cGUuZ2V0TG9jYWxTU1JDID0gZnVuY3Rpb24gKG1lZGlhVHlwZSkge1xuICAgIHJldHVybiB0aGlzLmxvY2FsU3RyZWFtc1NTUkNbbWVkaWFUeXBlXTtcbn07XG5cbkppbmdsZVNlc3Npb25QQy5wcm90b3R5cGUuZ2V0U3NyY093bmVyID0gZnVuY3Rpb24gKHNzcmMpIHtcbiAgICByZXR1cm4gdGhpcy5zc3JjT3duZXJzW3NzcmNdO1xufTtcblxuSmluZ2xlU2Vzc2lvblBDLnByb3RvdHlwZS5zZXRSZW1vdGVEZXNjcmlwdGlvbiA9IGZ1bmN0aW9uIChlbGVtLCBkZXNjdHlwZSkge1xuICAgIC8vbG9nZ2VyLmxvZygnc2V0dGluZyByZW1vdGUgZGVzY3JpcHRpb24uLi4gJywgZGVzY3R5cGUpO1xuICAgIHRoaXMucmVtb3RlU0RQID0gbmV3IFNEUCgnJyk7XG4gICAgaWYgKHNlbGYud2VicnRjSWNlVGNwRGlzYWJsZSkge1xuICAgICAgICB0aGlzLnJlbW90ZVNEUC5yZW1vdmVUY3BDYW5kaWRhdGVzID0gdHJ1ZTtcbiAgICB9XG4gICAgaWYgKHNlbGYud2VicnRjSWNlVWRwRGlzYWJsZSkge1xuICAgICAgICB0aGlzLnJlbW90ZVNEUC5yZW1vdmVVZHBDYW5kaWRhdGVzID0gdHJ1ZTtcbiAgICB9XG5cbiAgICB0aGlzLnJlbW90ZVNEUC5mcm9tSmluZ2xlKGVsZW0pO1xuICAgIHRoaXMucmVhZFNzcmNJbmZvKCQoZWxlbSkuZmluZChcIj5jb250ZW50XCIpKTtcbiAgICBpZiAodGhpcy5wZWVyY29ubmVjdGlvbi5yZW1vdGVEZXNjcmlwdGlvbikge1xuICAgICAgICBsb2dnZXIubG9nKCdzZXRSZW1vdGVEZXNjcmlwdGlvbiB3aGVuIHJlbW90ZSBkZXNjcmlwdGlvbiBpcyBub3QgbnVsbCwgc2hvdWxkIGJlIHByYW5zd2VyJywgdGhpcy5wZWVyY29ubmVjdGlvbi5yZW1vdGVEZXNjcmlwdGlvbik7XG4gICAgICAgIGlmICh0aGlzLnBlZXJjb25uZWN0aW9uLnJlbW90ZURlc2NyaXB0aW9uLnR5cGUgPT0gJ3ByYW5zd2VyJykge1xuICAgICAgICAgICAgdmFyIHByYW5zd2VyID0gbmV3IFNEUCh0aGlzLnBlZXJjb25uZWN0aW9uLnJlbW90ZURlc2NyaXB0aW9uLnNkcCk7XG4gICAgICAgICAgICBmb3IgKHZhciBpID0gMDsgaSA8IHByYW5zd2VyLm1lZGlhLmxlbmd0aDsgaSsrKSB7XG4gICAgICAgICAgICAgICAgLy8gbWFrZSBzdXJlIHdlIGhhdmUgaWNlIHVmcmFnIGFuZCBwd2RcbiAgICAgICAgICAgICAgICBpZiAoIVNEUFV0aWwuZmluZF9saW5lKHRoaXMucmVtb3RlU0RQLm1lZGlhW2ldLCAnYT1pY2UtdWZyYWc6JywgdGhpcy5yZW1vdGVTRFAuc2Vzc2lvbikpIHtcbiAgICAgICAgICAgICAgICAgICAgaWYgKFNEUFV0aWwuZmluZF9saW5lKHByYW5zd2VyLm1lZGlhW2ldLCAnYT1pY2UtdWZyYWc6JywgcHJhbnN3ZXIuc2Vzc2lvbikpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgIHRoaXMucmVtb3RlU0RQLm1lZGlhW2ldICs9IFNEUFV0aWwuZmluZF9saW5lKHByYW5zd2VyLm1lZGlhW2ldLCAnYT1pY2UtdWZyYWc6JywgcHJhbnN3ZXIuc2Vzc2lvbikgKyAnXFxyXFxuJztcbiAgICAgICAgICAgICAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgICAgICAgICAgICAgIGxvZ2dlci53YXJuKCdubyBpY2UgdWZyYWc/Jyk7XG4gICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICAgICAgaWYgKFNEUFV0aWwuZmluZF9saW5lKHByYW5zd2VyLm1lZGlhW2ldLCAnYT1pY2UtcHdkOicsIHByYW5zd2VyLnNlc3Npb24pKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICB0aGlzLnJlbW90ZVNEUC5tZWRpYVtpXSArPSBTRFBVdGlsLmZpbmRfbGluZShwcmFuc3dlci5tZWRpYVtpXSwgJ2E9aWNlLXB3ZDonLCBwcmFuc3dlci5zZXNzaW9uKSArICdcXHJcXG4nO1xuICAgICAgICAgICAgICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgICAgICAgICAgICAgbG9nZ2VyLndhcm4oJ25vIGljZSBwd2Q/Jyk7XG4gICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgLy8gY29weSBvdmVyIGNhbmRpZGF0ZXNcbiAgICAgICAgICAgICAgICB2YXIgbGluZXMgPSBTRFBVdGlsLmZpbmRfbGluZXMocHJhbnN3ZXIubWVkaWFbaV0sICdhPWNhbmRpZGF0ZTonKTtcbiAgICAgICAgICAgICAgICBmb3IgKHZhciBqID0gMDsgaiA8IGxpbmVzLmxlbmd0aDsgaisrKSB7XG4gICAgICAgICAgICAgICAgICAgIHRoaXMucmVtb3RlU0RQLm1lZGlhW2ldICs9IGxpbmVzW2pdICsgJ1xcclxcbic7XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgfVxuICAgICAgICAgICAgdGhpcy5yZW1vdGVTRFAucmF3ID0gdGhpcy5yZW1vdGVTRFAuc2Vzc2lvbiArIHRoaXMucmVtb3RlU0RQLm1lZGlhLmpvaW4oJycpO1xuICAgICAgICB9XG4gICAgfVxuICAgIHZhciByZW1vdGVkZXNjID0gbmV3IFJUQ1Nlc3Npb25EZXNjcmlwdGlvbih7dHlwZTogZGVzY3R5cGUsIHNkcDogdGhpcy5yZW1vdGVTRFAucmF3fSk7XG5cbiAgICB0aGlzLnBlZXJjb25uZWN0aW9uLnNldFJlbW90ZURlc2NyaXB0aW9uKHJlbW90ZWRlc2MsXG4gICAgICAgIGZ1bmN0aW9uICgpIHtcbiAgICAgICAgICAgIC8vbG9nZ2VyLmxvZygnc2V0UmVtb3RlRGVzY3JpcHRpb24gc3VjY2VzcycpO1xuICAgICAgICB9LFxuICAgICAgICBmdW5jdGlvbiAoZSkge1xuICAgICAgICAgICAgbG9nZ2VyLmVycm9yKCdzZXRSZW1vdGVEZXNjcmlwdGlvbiBlcnJvcicsIGUpO1xuICAgICAgICAgICAgSmluZ2xlU2Vzc2lvblBDLm9uSmluZ2xlRmF0YWxFcnJvcihzZWxmLCBlKTtcbiAgICAgICAgfVxuICAgICk7XG59O1xuXG4vKipcbiAqIEFkZHMgcmVtb3RlIElDRSBjYW5kaWRhdGVzIHRvIHRoaXMgSmluZ2xlIHNlc3Npb24uXG4gKiBAcGFyYW0gZWxlbSBBbiBhcnJheSBvZiBKaW5nbGUgXCJjb250ZW50XCIgZWxlbWVudHM/XG4gKi9cbkppbmdsZVNlc3Npb25QQy5wcm90b3R5cGUuYWRkSWNlQ2FuZGlkYXRlID0gZnVuY3Rpb24gKGVsZW0pIHtcbiAgICB2YXIgc2VsZiA9IHRoaXM7XG4gICAgaWYgKHRoaXMucGVlcmNvbm5lY3Rpb24uc2lnbmFsaW5nU3RhdGUgPT0gJ2Nsb3NlZCcpIHtcbiAgICAgICAgcmV0dXJuO1xuICAgIH1cbiAgICBpZiAoIXRoaXMucGVlcmNvbm5lY3Rpb24ucmVtb3RlRGVzY3JpcHRpb24gJiYgdGhpcy5wZWVyY29ubmVjdGlvbi5zaWduYWxpbmdTdGF0ZSA9PSAnaGF2ZS1sb2NhbC1vZmZlcicpIHtcbiAgICAgICAgbG9nZ2VyLmxvZygndHJpY2tsZSBpY2UgY2FuZGlkYXRlIGFycml2aW5nIGJlZm9yZSBzZXNzaW9uIGFjY2VwdC4uLicpO1xuICAgICAgICAvLyBjcmVhdGUgYSBQUkFOU1dFUiBmb3Igc2V0UmVtb3RlRGVzY3JpcHRpb25cbiAgICAgICAgaWYgKCF0aGlzLnJlbW90ZVNEUCkge1xuICAgICAgICAgICAgdmFyIGNvYmJsZWQgPSAndj0wXFxyXFxuJyArXG4gICAgICAgICAgICAgICAgJ289LSAxOTIzNTE4NTE2IDIgSU4gSVA0IDAuMC4wLjBcXHJcXG4nICsvLyBGSVhNRVxuICAgICAgICAgICAgICAgICdzPS1cXHJcXG4nICtcbiAgICAgICAgICAgICAgICAndD0wIDBcXHJcXG4nO1xuICAgICAgICAgICAgLy8gZmlyc3QsIHRha2Ugc29tZSB0aGluZ3MgZnJvbSB0aGUgbG9jYWwgZGVzY3JpcHRpb25cbiAgICAgICAgICAgIGZvciAodmFyIGkgPSAwOyBpIDwgdGhpcy5sb2NhbFNEUC5tZWRpYS5sZW5ndGg7IGkrKykge1xuICAgICAgICAgICAgICAgIGNvYmJsZWQgKz0gU0RQVXRpbC5maW5kX2xpbmUodGhpcy5sb2NhbFNEUC5tZWRpYVtpXSwgJ209JykgKyAnXFxyXFxuJztcbiAgICAgICAgICAgICAgICBjb2JibGVkICs9IFNEUFV0aWwuZmluZF9saW5lcyh0aGlzLmxvY2FsU0RQLm1lZGlhW2ldLCAnYT1ydHBtYXA6Jykuam9pbignXFxyXFxuJykgKyAnXFxyXFxuJztcbiAgICAgICAgICAgICAgICBpZiAoU0RQVXRpbC5maW5kX2xpbmUodGhpcy5sb2NhbFNEUC5tZWRpYVtpXSwgJ2E9bWlkOicpKSB7XG4gICAgICAgICAgICAgICAgICAgIGNvYmJsZWQgKz0gU0RQVXRpbC5maW5kX2xpbmUodGhpcy5sb2NhbFNEUC5tZWRpYVtpXSwgJ2E9bWlkOicpICsgJ1xcclxcbic7XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgIGNvYmJsZWQgKz0gJ2E9aW5hY3RpdmVcXHJcXG4nO1xuICAgICAgICAgICAgfVxuICAgICAgICAgICAgdGhpcy5yZW1vdGVTRFAgPSBuZXcgU0RQKGNvYmJsZWQpO1xuICAgICAgICB9XG4gICAgICAgIC8vIHRoZW4gYWRkIHRoaW5ncyBsaWtlIGljZSBhbmQgZHRscyBmcm9tIHJlbW90ZSBjYW5kaWRhdGVcbiAgICAgICAgZWxlbS5lYWNoKGZ1bmN0aW9uICgpIHtcbiAgICAgICAgICAgIGZvciAodmFyIGkgPSAwOyBpIDwgc2VsZi5yZW1vdGVTRFAubWVkaWEubGVuZ3RoOyBpKyspIHtcbiAgICAgICAgICAgICAgICBpZiAoU0RQVXRpbC5maW5kX2xpbmUoc2VsZi5yZW1vdGVTRFAubWVkaWFbaV0sICdhPW1pZDonICsgJCh0aGlzKS5hdHRyKCduYW1lJykpIHx8XG4gICAgICAgICAgICAgICAgICAgIHNlbGYucmVtb3RlU0RQLm1lZGlhW2ldLmluZGV4T2YoJ209JyArICQodGhpcykuYXR0cignbmFtZScpKSA9PT0gMCkge1xuICAgICAgICAgICAgICAgICAgICBpZiAoIVNEUFV0aWwuZmluZF9saW5lKHNlbGYucmVtb3RlU0RQLm1lZGlhW2ldLCAnYT1pY2UtdWZyYWc6JykpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgIHZhciB0bXAgPSAkKHRoaXMpLmZpbmQoJ3RyYW5zcG9ydCcpO1xuICAgICAgICAgICAgICAgICAgICAgICAgc2VsZi5yZW1vdGVTRFAubWVkaWFbaV0gKz0gJ2E9aWNlLXVmcmFnOicgKyB0bXAuYXR0cigndWZyYWcnKSArICdcXHJcXG4nO1xuICAgICAgICAgICAgICAgICAgICAgICAgc2VsZi5yZW1vdGVTRFAubWVkaWFbaV0gKz0gJ2E9aWNlLXB3ZDonICsgdG1wLmF0dHIoJ3B3ZCcpICsgJ1xcclxcbic7XG4gICAgICAgICAgICAgICAgICAgICAgICB0bXAgPSAkKHRoaXMpLmZpbmQoJ3RyYW5zcG9ydD5maW5nZXJwcmludCcpO1xuICAgICAgICAgICAgICAgICAgICAgICAgaWYgKHRtcC5sZW5ndGgpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICBzZWxmLnJlbW90ZVNEUC5tZWRpYVtpXSArPSAnYT1maW5nZXJwcmludDonICsgdG1wLmF0dHIoJ2hhc2gnKSArICcgJyArIHRtcC50ZXh0KCkgKyAnXFxyXFxuJztcbiAgICAgICAgICAgICAgICAgICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgbG9nZ2VyLmxvZygnbm8gZHRscyBmaW5nZXJwcmludCAod2VicnRjIGlzc3VlICMxNzE4PyknKTtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICBzZWxmLnJlbW90ZVNEUC5tZWRpYVtpXSArPSAnYT1jcnlwdG86MSBBRVNfQ01fMTI4X0hNQUNfU0hBMV84MCBpbmxpbmU6QkFBREJBQURCQUFEQkFBREJBQURCQUFEQkFBREJBQURCQUFEQkFBRFxcclxcbic7XG4gICAgICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgICAgICAgICBicmVhaztcbiAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgIH1cbiAgICAgICAgfSk7XG4gICAgICAgIHRoaXMucmVtb3RlU0RQLnJhdyA9IHRoaXMucmVtb3RlU0RQLnNlc3Npb24gKyB0aGlzLnJlbW90ZVNEUC5tZWRpYS5qb2luKCcnKTtcblxuICAgICAgICAvLyB3ZSBuZWVkIGEgY29tcGxldGUgU0RQIHdpdGggaWNlLXVmcmFnL2ljZS1wd2QgaW4gYWxsIHBhcnRzXG4gICAgICAgIC8vIHRoaXMgbWFrZXMgdGhlIGFzc3VtcHRpb24gdGhhdCB0aGUgUFJBTlNXRVIgaXMgY29uc3RydWN0ZWQgc3VjaCB0aGF0IHRoZSBpY2UtdWZyYWcgaXMgaW4gYWxsIG1lZGlhcGFydHNcbiAgICAgICAgLy8gYnV0IGl0IGNvdWxkIGJlIGluIHRoZSBzZXNzaW9uIHBhcnQgYXMgd2VsbC4gc2luY2UgdGhlIGNvZGUgYWJvdmUgY29uc3RydWN0cyB0aGlzIHNkcCB0aGlzIGNhbid0IGhhcHBlbiBob3dldmVyXG4gICAgICAgIHZhciBpc2NvbXBsZXRlID0gdGhpcy5yZW1vdGVTRFAubWVkaWEuZmlsdGVyKGZ1bmN0aW9uIChtZWRpYXBhcnQpIHtcbiAgICAgICAgICAgIHJldHVybiBTRFBVdGlsLmZpbmRfbGluZShtZWRpYXBhcnQsICdhPWljZS11ZnJhZzonKTtcbiAgICAgICAgfSkubGVuZ3RoID09IHRoaXMucmVtb3RlU0RQLm1lZGlhLmxlbmd0aDtcblxuICAgICAgICBpZiAoaXNjb21wbGV0ZSkge1xuICAgICAgICAgICAgbG9nZ2VyLmxvZygnc2V0dGluZyBwcmFuc3dlcicpO1xuICAgICAgICAgICAgdHJ5IHtcbiAgICAgICAgICAgICAgICB0aGlzLnBlZXJjb25uZWN0aW9uLnNldFJlbW90ZURlc2NyaXB0aW9uKG5ldyBSVENTZXNzaW9uRGVzY3JpcHRpb24oe3R5cGU6ICdwcmFuc3dlcicsIHNkcDogdGhpcy5yZW1vdGVTRFAucmF3IH0pLFxuICAgICAgICAgICAgICAgICAgICBmdW5jdGlvbigpIHtcbiAgICAgICAgICAgICAgICAgICAgfSxcbiAgICAgICAgICAgICAgICAgICAgZnVuY3Rpb24oZSkge1xuICAgICAgICAgICAgICAgICAgICAgICAgbG9nZ2VyLmxvZygnc2V0UmVtb3RlRGVzY3JpcHRpb24gcHJhbnN3ZXIgZmFpbGVkJywgZS50b1N0cmluZygpKTtcbiAgICAgICAgICAgICAgICAgICAgfSk7XG4gICAgICAgICAgICB9IGNhdGNoIChlKSB7XG4gICAgICAgICAgICAgICAgbG9nZ2VyLmVycm9yKCdzZXR0aW5nIHByYW5zd2VyIGZhaWxlZCcsIGUpO1xuICAgICAgICAgICAgfVxuICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgLy9sb2dnZXIubG9nKCdub3QgeWV0IHNldHRpbmcgcHJhbnN3ZXInKTtcbiAgICAgICAgfVxuICAgIH1cbiAgICAvLyBvcGVyYXRlIG9uIGVhY2ggY29udGVudCBlbGVtZW50XG4gICAgZWxlbS5lYWNoKGZ1bmN0aW9uICgpIHtcbiAgICAgICAgLy8gd291bGQgbG92ZSB0byBkZWFjdGl2YXRlIHRoaXMsIGJ1dCBmaXJlZm94IHN0aWxsIHJlcXVpcmVzIGl0XG4gICAgICAgIHZhciBpZHggPSAtMTtcbiAgICAgICAgdmFyIGk7XG4gICAgICAgIGZvciAoaSA9IDA7IGkgPCBzZWxmLnJlbW90ZVNEUC5tZWRpYS5sZW5ndGg7IGkrKykge1xuICAgICAgICAgICAgaWYgKFNEUFV0aWwuZmluZF9saW5lKHNlbGYucmVtb3RlU0RQLm1lZGlhW2ldLCAnYT1taWQ6JyArICQodGhpcykuYXR0cignbmFtZScpKSB8fFxuICAgICAgICAgICAgICAgIHNlbGYucmVtb3RlU0RQLm1lZGlhW2ldLmluZGV4T2YoJ209JyArICQodGhpcykuYXR0cignbmFtZScpKSA9PT0gMCkge1xuICAgICAgICAgICAgICAgIGlkeCA9IGk7XG4gICAgICAgICAgICAgICAgYnJlYWs7XG4gICAgICAgICAgICB9XG4gICAgICAgIH1cbiAgICAgICAgaWYgKGlkeCA9PSAtMSkgeyAvLyBmYWxsIGJhY2sgdG8gbG9jYWxkZXNjcmlwdGlvblxuICAgICAgICAgICAgZm9yIChpID0gMDsgaSA8IHNlbGYubG9jYWxTRFAubWVkaWEubGVuZ3RoOyBpKyspIHtcbiAgICAgICAgICAgICAgICBpZiAoU0RQVXRpbC5maW5kX2xpbmUoc2VsZi5sb2NhbFNEUC5tZWRpYVtpXSwgJ2E9bWlkOicgKyAkKHRoaXMpLmF0dHIoJ25hbWUnKSkgfHxcbiAgICAgICAgICAgICAgICAgICAgc2VsZi5sb2NhbFNEUC5tZWRpYVtpXS5pbmRleE9mKCdtPScgKyAkKHRoaXMpLmF0dHIoJ25hbWUnKSkgPT09IDApIHtcbiAgICAgICAgICAgICAgICAgICAgaWR4ID0gaTtcbiAgICAgICAgICAgICAgICAgICAgYnJlYWs7XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgfVxuICAgICAgICB9XG4gICAgICAgIHZhciBuYW1lID0gJCh0aGlzKS5hdHRyKCduYW1lJyk7XG4gICAgICAgIC8vIFRPRE86IGNoZWNrIGljZS1wd2QgYW5kIGljZS11ZnJhZz9cbiAgICAgICAgJCh0aGlzKS5maW5kKCd0cmFuc3BvcnQ+Y2FuZGlkYXRlJykuZWFjaChmdW5jdGlvbiAoKSB7XG4gICAgICAgICAgICB2YXIgbGluZSwgY2FuZGlkYXRlO1xuICAgICAgICAgICAgdmFyIHByb3RvY29sID0gdGhpcy5nZXRBdHRyaWJ1dGUoJ3Byb3RvY29sJyk7XG4gICAgICAgICAgICBwcm90b2NvbCA9XG4gICAgICAgICAgICAgICAgKHR5cGVvZiBwcm90b2NvbCA9PT0gJ3N0cmluZycpID8gcHJvdG9jb2wudG9Mb3dlckNhc2UoKSA6ICcnO1xuICAgICAgICAgICAgaWYgKChzZWxmLndlYnJ0Y0ljZVRjcERpc2FibGUgJiYgcHJvdG9jb2wgPT0gJ3RjcCcpIHx8XG4gICAgICAgICAgICAgICAgKHNlbGYud2VicnRjSWNlVWRwRGlzYWJsZSAmJiBwcm90b2NvbCA9PSAndWRwJykpIHtcbiAgICAgICAgICAgICAgICByZXR1cm47XG4gICAgICAgICAgICB9XG5cbiAgICAgICAgICAgIGxpbmUgPSBTRFBVdGlsLmNhbmRpZGF0ZUZyb21KaW5nbGUodGhpcyk7XG4gICAgICAgICAgICBjYW5kaWRhdGUgPSBuZXcgUlRDSWNlQ2FuZGlkYXRlKHtzZHBNTGluZUluZGV4OiBpZHgsXG4gICAgICAgICAgICAgICAgc2RwTWlkOiBuYW1lLFxuICAgICAgICAgICAgICAgIGNhbmRpZGF0ZTogbGluZX0pO1xuICAgICAgICAgICAgdHJ5IHtcbiAgICAgICAgICAgICAgICBzZWxmLnBlZXJjb25uZWN0aW9uLmFkZEljZUNhbmRpZGF0ZShjYW5kaWRhdGUpO1xuICAgICAgICAgICAgfSBjYXRjaCAoZSkge1xuICAgICAgICAgICAgICAgIGxvZ2dlci5lcnJvcignYWRkSWNlQ2FuZGlkYXRlIGZhaWxlZCcsIGUudG9TdHJpbmcoKSwgbGluZSk7XG4gICAgICAgICAgICB9XG4gICAgICAgIH0pO1xuICAgIH0pO1xufTtcblxuSmluZ2xlU2Vzc2lvblBDLnByb3RvdHlwZS5zZW5kQW5zd2VyID0gZnVuY3Rpb24gKHByb3Zpc2lvbmFsKSB7XG4gICAgLy9sb2dnZXIubG9nKCdjcmVhdGVBbnN3ZXInLCBwcm92aXNpb25hbCk7XG4gICAgdmFyIHNlbGYgPSB0aGlzO1xuICAgIHRoaXMucGVlcmNvbm5lY3Rpb24uY3JlYXRlQW5zd2VyKFxuICAgICAgICBmdW5jdGlvbiAoc2RwKSB7XG4gICAgICAgICAgICBzZWxmLmNyZWF0ZWRBbnN3ZXIoc2RwLCBwcm92aXNpb25hbCk7XG4gICAgICAgIH0sXG4gICAgICAgIGZ1bmN0aW9uIChlKSB7XG4gICAgICAgICAgICBsb2dnZXIuZXJyb3IoJ2NyZWF0ZUFuc3dlciBmYWlsZWQnLCBlKTtcbiAgICAgICAgICAgIHNlbGYucm9vbS5ldmVudEVtaXR0ZXIuZW1pdChYTVBQRXZlbnRzLkNPTkZFUkVOQ0VfU0VUVVBfRkFJTEVEKTtcbiAgICAgICAgfSxcbiAgICAgICAgdGhpcy5tZWRpYV9jb25zdHJhaW50c1xuICAgICk7XG59O1xuXG5KaW5nbGVTZXNzaW9uUEMucHJvdG90eXBlLmNyZWF0ZWRBbnN3ZXIgPSBmdW5jdGlvbiAoc2RwLCBwcm92aXNpb25hbCkge1xuICAgIC8vbG9nZ2VyLmxvZygnY3JlYXRlQW5zd2VyIGNhbGxiYWNrJyk7XG4gICAgdmFyIHNlbGYgPSB0aGlzO1xuICAgIHRoaXMubG9jYWxTRFAgPSBuZXcgU0RQKHNkcC5zZHApO1xuICAgIC8vdGhpcy5sb2NhbFNEUC5tYW5nbGUoKTtcbiAgICB0aGlzLnVzZXByYW5zd2VyID0gcHJvdmlzaW9uYWwgPT09IHRydWU7XG4gICAgaWYgKHRoaXMudXNldHJpY2tsZSkge1xuICAgICAgICBpZiAodGhpcy51c2VwcmFuc3dlcikge1xuICAgICAgICAgICAgc2RwLnR5cGUgPSAncHJhbnN3ZXInO1xuICAgICAgICAgICAgZm9yICh2YXIgaSA9IDA7IGkgPCB0aGlzLmxvY2FsU0RQLm1lZGlhLmxlbmd0aDsgaSsrKSB7XG4gICAgICAgICAgICAgICAgdGhpcy5sb2NhbFNEUC5tZWRpYVtpXSA9IHRoaXMubG9jYWxTRFAubWVkaWFbaV0ucmVwbGFjZSgnYT1zZW5kcmVjdlxcclxcbicsICdhPWluYWN0aXZlXFxyXFxuJyk7XG4gICAgICAgICAgICB9XG4gICAgICAgICAgICB0aGlzLmxvY2FsU0RQLnJhdyA9IHRoaXMubG9jYWxTRFAuc2Vzc2lvbiArICdcXHJcXG4nICsgdGhpcy5sb2NhbFNEUC5tZWRpYS5qb2luKCcnKTtcbiAgICAgICAgfVxuICAgIH1cbiAgICB2YXIgc2VsZiA9IHRoaXM7XG4gICAgdmFyIHNlbmRKaW5nbGUgPSBmdW5jdGlvbiAoc3NyY3MpIHtcbiAgICAgICAgICAgICAgICAvLyBGSVhNRSB3aHkgZG8gd2UgZ2VuZXJhdGUgc2Vzc2lvbi1hY2NlcHQgaW4gMyBkaWZmZXJlbnQgcGxhY2VzID9cbiAgICAgICAgICAgICAgICB2YXIgYWNjZXB0ID0gJGlxKHt0bzogc2VsZi5wZWVyamlkLFxuICAgICAgICAgICAgICAgICAgICB0eXBlOiAnc2V0J30pXG4gICAgICAgICAgICAgICAgICAgIC5jKCdqaW5nbGUnLCB7eG1sbnM6ICd1cm46eG1wcDpqaW5nbGU6MScsXG4gICAgICAgICAgICAgICAgICAgICAgICBhY3Rpb246ICdzZXNzaW9uLWFjY2VwdCcsXG4gICAgICAgICAgICAgICAgICAgICAgICBpbml0aWF0b3I6IHNlbGYuaW5pdGlhdG9yLFxuICAgICAgICAgICAgICAgICAgICAgICAgcmVzcG9uZGVyOiBzZWxmLnJlc3BvbmRlcixcbiAgICAgICAgICAgICAgICAgICAgICAgIHNpZDogc2VsZi5zaWQgfSk7XG4gICAgICAgICAgICAgICAgaWYgKHNlbGYud2VicnRjSWNlVGNwRGlzYWJsZSkge1xuICAgICAgICAgICAgICAgICAgICBzZWxmLmxvY2FsU0RQLnJlbW92ZVRjcENhbmRpZGF0ZXMgPSB0cnVlO1xuICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICBpZiAoc2VsZi53ZWJydGNJY2VVZHBEaXNhYmxlKSB7XG4gICAgICAgICAgICAgICAgICAgIHNlbGYubG9jYWxTRFAucmVtb3ZlVWRwQ2FuZGlkYXRlcyA9IHRydWU7XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgIHNlbGYubG9jYWxTRFAudG9KaW5nbGUoXG4gICAgICAgICAgICAgICAgICAgIGFjY2VwdCxcbiAgICAgICAgICAgICAgICAgICAgc2VsZi5pbml0aWF0b3IgPT0gc2VsZi5tZSA/ICdpbml0aWF0b3InIDogJ3Jlc3BvbmRlcicsXG4gICAgICAgICAgICAgICAgICAgIHNzcmNzKTtcblxuICAgICAgICAgICAgICAgIFNTUkNSZXBsYWNlbWVudC5wcm9jZXNzU2Vzc2lvbkluaXQoYWNjZXB0KTtcblxuICAgICAgICAgICAgICAgIHNlbGYuY29ubmVjdGlvbi5zZW5kSVEoYWNjZXB0LFxuICAgICAgICAgICAgICAgICAgICBmdW5jdGlvbiAoKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICB2YXIgYWNrID0ge307XG4gICAgICAgICAgICAgICAgICAgICAgICBhY2suc291cmNlID0gJ2Fuc3dlcic7XG4gICAgICAgICAgICAgICAgICAgICAgICAkKGRvY3VtZW50KS50cmlnZ2VyKCdhY2suamluZ2xlJywgW3NlbGYuc2lkLCBhY2tdKTtcbiAgICAgICAgICAgICAgICAgICAgfSxcbiAgICAgICAgICAgICAgICAgICAgZnVuY3Rpb24gKHN0YW56YSkge1xuICAgICAgICAgICAgICAgICAgICAgICAgdmFyIGVycm9yID0gKCQoc3RhbnphKS5maW5kKCdlcnJvcicpLmxlbmd0aCkgPyB7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgY29kZTogJChzdGFuemEpLmZpbmQoJ2Vycm9yJykuYXR0cignY29kZScpLFxuICAgICAgICAgICAgICAgICAgICAgICAgICAgIHJlYXNvbjogJChzdGFuemEpLmZpbmQoJ2Vycm9yIDpmaXJzdCcpWzBdLnRhZ05hbWUsXG4gICAgICAgICAgICAgICAgICAgICAgICB9Ont9O1xuICAgICAgICAgICAgICAgICAgICAgICAgZXJyb3Iuc291cmNlID0gJ2Fuc3dlcic7XG4gICAgICAgICAgICAgICAgICAgICAgICBKaW5nbGVTZXNzaW9uUEMub25KaW5nbGVFcnJvcihzZWxmLnNpZCwgZXJyb3IpO1xuICAgICAgICAgICAgICAgICAgICB9LFxuICAgICAgICAgICAgICAgICAgICAxMDAwMCk7XG4gICAgfVxuICAgIHNkcC5zZHAgPSB0aGlzLmxvY2FsU0RQLnJhdztcbiAgICB0aGlzLnBlZXJjb25uZWN0aW9uLnNldExvY2FsRGVzY3JpcHRpb24oc2RwLFxuICAgICAgICBmdW5jdGlvbiAoKSB7XG5cbiAgICAgICAgICAgIC8vbG9nZ2VyLmxvZygnc2V0TG9jYWxEZXNjcmlwdGlvbiBzdWNjZXNzJyk7XG4gICAgICAgICAgICBpZiAoc2VsZi51c2V0cmlja2xlICYmICFzZWxmLnVzZXByYW5zd2VyKSB7XG4gICAgICAgICAgICAgICAgc2VuZEppbmdsZSgpO1xuICAgICAgICAgICAgfVxuICAgICAgICAgICAgc2VsZi5zZXRMb2NhbERlc2NyaXB0aW9uKCk7XG4gICAgICAgIH0sXG4gICAgICAgIGZ1bmN0aW9uIChlKSB7XG4gICAgICAgICAgICBsb2dnZXIuZXJyb3IoJ3NldExvY2FsRGVzY3JpcHRpb24gZmFpbGVkJywgZSk7XG4gICAgICAgICAgICBzZWxmLnJvb20uZXZlbnRFbWl0dGVyLmVtaXQoWE1QUEV2ZW50cy5DT05GRVJFTkNFX1NFVFVQX0ZBSUxFRCk7XG4gICAgICAgIH1cbiAgICApO1xuICAgIHZhciBjYW5kcyA9IFNEUFV0aWwuZmluZF9saW5lcyh0aGlzLmxvY2FsU0RQLnJhdywgJ2E9Y2FuZGlkYXRlOicpO1xuICAgIGZvciAodmFyIGogPSAwOyBqIDwgY2FuZHMubGVuZ3RoOyBqKyspIHtcbiAgICAgICAgdmFyIGNhbmQgPSBTRFBVdGlsLnBhcnNlX2ljZWNhbmRpZGF0ZShjYW5kc1tqXSk7XG4gICAgICAgIGlmIChjYW5kLnR5cGUgPT0gJ3NyZmx4Jykge1xuICAgICAgICAgICAgdGhpcy5oYWRzdHVuY2FuZGlkYXRlID0gdHJ1ZTtcbiAgICAgICAgfSBlbHNlIGlmIChjYW5kLnR5cGUgPT0gJ3JlbGF5Jykge1xuICAgICAgICAgICAgdGhpcy5oYWR0dXJuY2FuZGlkYXRlID0gdHJ1ZTtcbiAgICAgICAgfVxuICAgIH1cbn07XG5cbkppbmdsZVNlc3Npb25QQy5wcm90b3R5cGUuc2VuZFRlcm1pbmF0ZSA9IGZ1bmN0aW9uIChyZWFzb24sIHRleHQpIHtcbiAgICB2YXIgc2VsZiA9IHRoaXMsXG4gICAgICAgIHRlcm0gPSAkaXEoe3RvOiB0aGlzLnBlZXJqaWQsXG4gICAgICAgICAgICB0eXBlOiAnc2V0J30pXG4gICAgICAgICAgICAuYygnamluZ2xlJywge3htbG5zOiAndXJuOnhtcHA6amluZ2xlOjEnLFxuICAgICAgICAgICAgICAgIGFjdGlvbjogJ3Nlc3Npb24tdGVybWluYXRlJyxcbiAgICAgICAgICAgICAgICBpbml0aWF0b3I6IHRoaXMuaW5pdGlhdG9yLFxuICAgICAgICAgICAgICAgIHNpZDogdGhpcy5zaWR9KVxuICAgICAgICAgICAgLmMoJ3JlYXNvbicpXG4gICAgICAgICAgICAuYyhyZWFzb24gfHwgJ3N1Y2Nlc3MnKTtcblxuICAgIGlmICh0ZXh0KSB7XG4gICAgICAgIHRlcm0udXAoKS5jKCd0ZXh0JykudCh0ZXh0KTtcbiAgICB9XG5cbiAgICB0aGlzLmNvbm5lY3Rpb24uc2VuZElRKHRlcm0sXG4gICAgICAgIGZ1bmN0aW9uICgpIHtcbiAgICAgICAgICAgIHNlbGYucGVlcmNvbm5lY3Rpb24uY2xvc2UoKTtcbiAgICAgICAgICAgIHNlbGYucGVlcmNvbm5lY3Rpb24gPSBudWxsO1xuICAgICAgICAgICAgc2VsZi50ZXJtaW5hdGUoKTtcbiAgICAgICAgICAgIHZhciBhY2sgPSB7fTtcbiAgICAgICAgICAgIGFjay5zb3VyY2UgPSAndGVybWluYXRlJztcbiAgICAgICAgICAgICQoZG9jdW1lbnQpLnRyaWdnZXIoJ2Fjay5qaW5nbGUnLCBbc2VsZi5zaWQsIGFja10pO1xuICAgICAgICB9LFxuICAgICAgICBmdW5jdGlvbiAoc3RhbnphKSB7XG4gICAgICAgICAgICB2YXIgZXJyb3IgPSAoJChzdGFuemEpLmZpbmQoJ2Vycm9yJykubGVuZ3RoKSA/IHtcbiAgICAgICAgICAgICAgICBjb2RlOiAkKHN0YW56YSkuZmluZCgnZXJyb3InKS5hdHRyKCdjb2RlJyksXG4gICAgICAgICAgICAgICAgcmVhc29uOiAkKHN0YW56YSkuZmluZCgnZXJyb3IgOmZpcnN0JylbMF0udGFnTmFtZSxcbiAgICAgICAgICAgIH06e307XG4gICAgICAgICAgICAkKGRvY3VtZW50KS50cmlnZ2VyKCdhY2suamluZ2xlJywgW3NlbGYuc2lkLCBlcnJvcl0pO1xuICAgICAgICB9LFxuICAgICAgICAxMDAwMCk7XG4gICAgaWYgKHRoaXMuc3RhdHNpbnRlcnZhbCAhPT0gbnVsbCkge1xuICAgICAgICB3aW5kb3cuY2xlYXJJbnRlcnZhbCh0aGlzLnN0YXRzaW50ZXJ2YWwpO1xuICAgICAgICB0aGlzLnN0YXRzaW50ZXJ2YWwgPSBudWxsO1xuICAgIH1cbn07XG5cbi8qKlxuICogSGFuZGxlcyBhIEppbmdsZSBzb3VyY2UtYWRkIG1lc3NhZ2UgZm9yIHRoaXMgSmluZ2xlIHNlc3Npb24uXG4gKiBAcGFyYW0gZWxlbSBBbiBhcnJheSBvZiBKaW5nbGUgXCJjb250ZW50XCIgZWxlbWVudHMuXG4gKi9cbkppbmdsZVNlc3Npb25QQy5wcm90b3R5cGUuYWRkU291cmNlID0gZnVuY3Rpb24gKGVsZW0pIHtcblxuICAgIHZhciBzZWxmID0gdGhpcztcbiAgICAvLyBGSVhNRTogZGlydHkgd2FpdGluZ1xuICAgIGlmICghdGhpcy5wZWVyY29ubmVjdGlvbi5sb2NhbERlc2NyaXB0aW9uKVxuICAgIHtcbiAgICAgICAgbG9nZ2VyLndhcm4oXCJhZGRTb3VyY2UgLSBsb2NhbERlc2NyaXB0aW9uIG5vdCByZWFkeSB5ZXRcIilcbiAgICAgICAgc2V0VGltZW91dChmdW5jdGlvbigpXG4gICAgICAgICAgICB7XG4gICAgICAgICAgICAgICAgc2VsZi5hZGRTb3VyY2UoZWxlbSk7XG4gICAgICAgICAgICB9LFxuICAgICAgICAgICAgMjAwXG4gICAgICAgICk7XG4gICAgICAgIHJldHVybjtcbiAgICB9XG5cbiAgICBsb2dnZXIubG9nKCdhZGRzc3JjJywgbmV3IERhdGUoKS5nZXRUaW1lKCkpO1xuICAgIGxvZ2dlci5sb2coJ2ljZScsIHRoaXMucGVlcmNvbm5lY3Rpb24uaWNlQ29ubmVjdGlvblN0YXRlKTtcblxuICAgIHRoaXMucmVhZFNzcmNJbmZvKGVsZW0pO1xuXG4gICAgdmFyIHNkcCA9IG5ldyBTRFAodGhpcy5wZWVyY29ubmVjdGlvbi5yZW1vdGVEZXNjcmlwdGlvbi5zZHApO1xuICAgIHZhciBteVNkcCA9IG5ldyBTRFAodGhpcy5wZWVyY29ubmVjdGlvbi5sb2NhbERlc2NyaXB0aW9uLnNkcCk7XG5cbiAgICAkKGVsZW0pLmVhY2goZnVuY3Rpb24gKGlkeCwgY29udGVudCkge1xuICAgICAgICB2YXIgbmFtZSA9ICQoY29udGVudCkuYXR0cignbmFtZScpO1xuICAgICAgICB2YXIgbGluZXMgPSAnJztcbiAgICAgICAgJChjb250ZW50KS5maW5kKCdzc3JjLWdyb3VwW3htbG5zPVwidXJuOnhtcHA6amluZ2xlOmFwcHM6cnRwOnNzbWE6MFwiXScpLmVhY2goZnVuY3Rpb24oKSB7XG4gICAgICAgICAgICB2YXIgc2VtYW50aWNzID0gdGhpcy5nZXRBdHRyaWJ1dGUoJ3NlbWFudGljcycpO1xuICAgICAgICAgICAgdmFyIHNzcmNzID0gJCh0aGlzKS5maW5kKCc+c291cmNlJykubWFwKGZ1bmN0aW9uICgpIHtcbiAgICAgICAgICAgICAgICByZXR1cm4gdGhpcy5nZXRBdHRyaWJ1dGUoJ3NzcmMnKTtcbiAgICAgICAgICAgIH0pLmdldCgpO1xuXG4gICAgICAgICAgICBpZiAoc3NyY3MubGVuZ3RoKSB7XG4gICAgICAgICAgICAgICAgbGluZXMgKz0gJ2E9c3NyYy1ncm91cDonICsgc2VtYW50aWNzICsgJyAnICsgc3NyY3Muam9pbignICcpICsgJ1xcclxcbic7XG4gICAgICAgICAgICB9XG4gICAgICAgIH0pO1xuICAgICAgICB2YXIgdG1wID0gJChjb250ZW50KS5maW5kKCdzb3VyY2VbeG1sbnM9XCJ1cm46eG1wcDpqaW5nbGU6YXBwczpydHA6c3NtYTowXCJdJyk7IC8vIGNhbiBoYW5kbGUgYm90aCA+c291cmNlIGFuZCA+ZGVzY3JpcHRpb24+c291cmNlXG4gICAgICAgIHRtcC5lYWNoKGZ1bmN0aW9uICgpIHtcbiAgICAgICAgICAgIHZhciBzc3JjID0gJCh0aGlzKS5hdHRyKCdzc3JjJyk7XG4gICAgICAgICAgICBpZihteVNkcC5jb250YWluc1NTUkMoc3NyYykpe1xuICAgICAgICAgICAgICAgIC8qKlxuICAgICAgICAgICAgICAgICAqIFRoaXMgaGFwcGVucyB3aGVuIG11bHRpcGxlIHBhcnRpY2lwYW50cyBjaGFuZ2UgdGhlaXIgc3RyZWFtcyBhdCB0aGUgc2FtZSB0aW1lIGFuZFxuICAgICAgICAgICAgICAgICAqIENvbGlicmlGb2N1cy5tb2RpZnlTb3VyY2VzIGhhdmUgdG8gd2FpdCBmb3Igc3RhYmxlIHN0YXRlLiBJbiB0aGUgbWVhbnRpbWUgbXVsdGlwbGVcbiAgICAgICAgICAgICAgICAgKiBhZGRzc3JjIGFyZSBzY2hlZHVsZWQgZm9yIHVwZGF0ZSBJUS4gU2VlXG4gICAgICAgICAgICAgICAgICovXG4gICAgICAgICAgICAgICAgbG9nZ2VyLndhcm4oXCJHb3QgYWRkIHN0cmVhbSByZXF1ZXN0IGZvciBteSBvd24gc3NyYzogXCIrc3NyYyk7XG4gICAgICAgICAgICAgICAgcmV0dXJuO1xuICAgICAgICAgICAgfVxuICAgICAgICAgICAgaWYgKHNkcC5jb250YWluc1NTUkMoc3NyYykpIHtcbiAgICAgICAgICAgICAgICBsb2dnZXIud2FybihcIlNvdXJjZS1hZGQgcmVxdWVzdCBmb3IgZXhpc3RpbmcgU1NSQzogXCIgKyBzc3JjKTtcbiAgICAgICAgICAgICAgICByZXR1cm47XG4gICAgICAgICAgICB9XG4gICAgICAgICAgICAkKHRoaXMpLmZpbmQoJz5wYXJhbWV0ZXInKS5lYWNoKGZ1bmN0aW9uICgpIHtcbiAgICAgICAgICAgICAgICBsaW5lcyArPSAnYT1zc3JjOicgKyBzc3JjICsgJyAnICsgJCh0aGlzKS5hdHRyKCduYW1lJyk7XG4gICAgICAgICAgICAgICAgaWYgKCQodGhpcykuYXR0cigndmFsdWUnKSAmJiAkKHRoaXMpLmF0dHIoJ3ZhbHVlJykubGVuZ3RoKVxuICAgICAgICAgICAgICAgICAgICBsaW5lcyArPSAnOicgKyAkKHRoaXMpLmF0dHIoJ3ZhbHVlJyk7XG4gICAgICAgICAgICAgICAgbGluZXMgKz0gJ1xcclxcbic7XG4gICAgICAgICAgICB9KTtcbiAgICAgICAgfSk7XG4gICAgICAgIHNkcC5tZWRpYS5mb3JFYWNoKGZ1bmN0aW9uKG1lZGlhLCBpZHgpIHtcbiAgICAgICAgICAgIGlmICghU0RQVXRpbC5maW5kX2xpbmUobWVkaWEsICdhPW1pZDonICsgbmFtZSkpXG4gICAgICAgICAgICAgICAgcmV0dXJuO1xuICAgICAgICAgICAgc2RwLm1lZGlhW2lkeF0gKz0gbGluZXM7XG4gICAgICAgICAgICBpZiAoIXNlbGYuYWRkc3NyY1tpZHhdKSBzZWxmLmFkZHNzcmNbaWR4XSA9ICcnO1xuICAgICAgICAgICAgc2VsZi5hZGRzc3JjW2lkeF0gKz0gbGluZXM7XG4gICAgICAgIH0pO1xuICAgICAgICBzZHAucmF3ID0gc2RwLnNlc3Npb24gKyBzZHAubWVkaWEuam9pbignJyk7XG4gICAgfSk7XG5cbiAgICB0aGlzLm1vZGlmeVNvdXJjZXNRdWV1ZS5wdXNoKGZ1bmN0aW9uKCkge1xuICAgICAgICAvLyBXaGVuIGEgc291cmNlIGlzIGFkZGVkIGFuZCBpZiB0aGlzIGlzIEZGLCBhIG5ldyBjaGFubmVsIGlzIGFsbG9jYXRlZFxuICAgICAgICAvLyBmb3IgcmVjZWl2aW5nIHRoZSBhZGRlZCBzb3VyY2UuIFdlIG5lZWQgdG8gZGlmZnVzZSB0aGUgU1NSQyBvZiB0aGlzXG4gICAgICAgIC8vIG5ldyByZWN2b25seSBjaGFubmVsIHRvIHRoZSByZXN0IG9mIHRoZSBwZWVycy5cbiAgICAgICAgbG9nZ2VyLmxvZygnbW9kaWZ5IHNvdXJjZXMgZG9uZScpO1xuXG4gICAgICAgIHZhciBuZXdTZHAgPSBuZXcgU0RQKHNlbGYucGVlcmNvbm5lY3Rpb24ubG9jYWxEZXNjcmlwdGlvbi5zZHApO1xuICAgICAgICBsb2dnZXIubG9nKFwiU0RQc1wiLCBteVNkcCwgbmV3U2RwKTtcbiAgICAgICAgc2VsZi5ub3RpZnlNeVNTUkNVcGRhdGUobXlTZHAsIG5ld1NkcCk7XG4gICAgfSk7XG59O1xuXG4vKipcbiAqIEhhbmRsZXMgYSBKaW5nbGUgc291cmNlLXJlbW92ZSBtZXNzYWdlIGZvciB0aGlzIEppbmdsZSBzZXNzaW9uLlxuICogQHBhcmFtIGVsZW0gQW4gYXJyYXkgb2YgSmluZ2xlIFwiY29udGVudFwiIGVsZW1lbnRzLlxuICovXG5KaW5nbGVTZXNzaW9uUEMucHJvdG90eXBlLnJlbW92ZVNvdXJjZSA9IGZ1bmN0aW9uIChlbGVtKSB7XG5cbiAgICB2YXIgc2VsZiA9IHRoaXM7XG4gICAgLy8gRklYTUU6IGRpcnR5IHdhaXRpbmdcbiAgICBpZiAoIXRoaXMucGVlcmNvbm5lY3Rpb24ubG9jYWxEZXNjcmlwdGlvbikge1xuICAgICAgICBsb2dnZXIud2FybihcInJlbW92ZVNvdXJjZSAtIGxvY2FsRGVzY3JpcHRpb24gbm90IHJlYWR5IHlldFwiKTtcbiAgICAgICAgc2V0VGltZW91dChmdW5jdGlvbigpIHtcbiAgICAgICAgICAgICAgICBzZWxmLnJlbW92ZVNvdXJjZShlbGVtKTtcbiAgICAgICAgICAgIH0sXG4gICAgICAgICAgICAyMDBcbiAgICAgICAgKTtcbiAgICAgICAgcmV0dXJuO1xuICAgIH1cblxuICAgIGxvZ2dlci5sb2coJ3JlbW92ZXNzcmMnLCBuZXcgRGF0ZSgpLmdldFRpbWUoKSk7XG4gICAgbG9nZ2VyLmxvZygnaWNlJywgdGhpcy5wZWVyY29ubmVjdGlvbi5pY2VDb25uZWN0aW9uU3RhdGUpO1xuICAgIHZhciBzZHAgPSBuZXcgU0RQKHRoaXMucGVlcmNvbm5lY3Rpb24ucmVtb3RlRGVzY3JpcHRpb24uc2RwKTtcbiAgICB2YXIgbXlTZHAgPSBuZXcgU0RQKHRoaXMucGVlcmNvbm5lY3Rpb24ubG9jYWxEZXNjcmlwdGlvbi5zZHApO1xuXG4gICAgJChlbGVtKS5lYWNoKGZ1bmN0aW9uIChpZHgsIGNvbnRlbnQpIHtcbiAgICAgICAgdmFyIG5hbWUgPSAkKGNvbnRlbnQpLmF0dHIoJ25hbWUnKTtcbiAgICAgICAgdmFyIGxpbmVzID0gJyc7XG4gICAgICAgICQoY29udGVudCkuZmluZCgnc3NyYy1ncm91cFt4bWxucz1cInVybjp4bXBwOmppbmdsZTphcHBzOnJ0cDpzc21hOjBcIl0nKS5lYWNoKGZ1bmN0aW9uKCkge1xuICAgICAgICAgICAgdmFyIHNlbWFudGljcyA9IHRoaXMuZ2V0QXR0cmlidXRlKCdzZW1hbnRpY3MnKTtcbiAgICAgICAgICAgIHZhciBzc3JjcyA9ICQodGhpcykuZmluZCgnPnNvdXJjZScpLm1hcChmdW5jdGlvbiAoKSB7XG4gICAgICAgICAgICAgICAgcmV0dXJuIHRoaXMuZ2V0QXR0cmlidXRlKCdzc3JjJyk7XG4gICAgICAgICAgICB9KS5nZXQoKTtcblxuICAgICAgICAgICAgaWYgKHNzcmNzLmxlbmd0aCkge1xuICAgICAgICAgICAgICAgIGxpbmVzICs9ICdhPXNzcmMtZ3JvdXA6JyArIHNlbWFudGljcyArICcgJyArIHNzcmNzLmpvaW4oJyAnKSArICdcXHJcXG4nO1xuICAgICAgICAgICAgfVxuICAgICAgICB9KTtcbiAgICAgICAgdmFyIHRtcCA9ICQoY29udGVudCkuZmluZCgnc291cmNlW3htbG5zPVwidXJuOnhtcHA6amluZ2xlOmFwcHM6cnRwOnNzbWE6MFwiXScpOyAvLyBjYW4gaGFuZGxlIGJvdGggPnNvdXJjZSBhbmQgPmRlc2NyaXB0aW9uPnNvdXJjZVxuICAgICAgICB0bXAuZWFjaChmdW5jdGlvbiAoKSB7XG4gICAgICAgICAgICB2YXIgc3NyYyA9ICQodGhpcykuYXR0cignc3NyYycpO1xuICAgICAgICAgICAgLy8gVGhpcyBzaG91bGQgbmV2ZXIgaGFwcGVuLCBidXQgY2FuIGJlIHVzZWZ1bCBmb3IgYnVnIGRldGVjdGlvblxuICAgICAgICAgICAgaWYobXlTZHAuY29udGFpbnNTU1JDKHNzcmMpKXtcbiAgICAgICAgICAgICAgICBsb2dnZXIuZXJyb3IoXCJHb3QgcmVtb3ZlIHN0cmVhbSByZXF1ZXN0IGZvciBteSBvd24gc3NyYzogXCIrc3NyYyk7XG4gICAgICAgICAgICAgICAgcmV0dXJuO1xuICAgICAgICAgICAgfVxuICAgICAgICAgICAgJCh0aGlzKS5maW5kKCc+cGFyYW1ldGVyJykuZWFjaChmdW5jdGlvbiAoKSB7XG4gICAgICAgICAgICAgICAgbGluZXMgKz0gJ2E9c3NyYzonICsgc3NyYyArICcgJyArICQodGhpcykuYXR0cignbmFtZScpO1xuICAgICAgICAgICAgICAgIGlmICgkKHRoaXMpLmF0dHIoJ3ZhbHVlJykgJiYgJCh0aGlzKS5hdHRyKCd2YWx1ZScpLmxlbmd0aClcbiAgICAgICAgICAgICAgICAgICAgbGluZXMgKz0gJzonICsgJCh0aGlzKS5hdHRyKCd2YWx1ZScpO1xuICAgICAgICAgICAgICAgIGxpbmVzICs9ICdcXHJcXG4nO1xuICAgICAgICAgICAgfSk7XG4gICAgICAgIH0pO1xuICAgICAgICBzZHAubWVkaWEuZm9yRWFjaChmdW5jdGlvbihtZWRpYSwgaWR4KSB7XG4gICAgICAgICAgICBpZiAoIVNEUFV0aWwuZmluZF9saW5lKG1lZGlhLCAnYT1taWQ6JyArIG5hbWUpKVxuICAgICAgICAgICAgICAgIHJldHVybjtcbiAgICAgICAgICAgIHNkcC5tZWRpYVtpZHhdICs9IGxpbmVzO1xuICAgICAgICAgICAgaWYgKCFzZWxmLnJlbW92ZXNzcmNbaWR4XSkgc2VsZi5yZW1vdmVzc3JjW2lkeF0gPSAnJztcbiAgICAgICAgICAgIHNlbGYucmVtb3Zlc3NyY1tpZHhdICs9IGxpbmVzO1xuICAgICAgICB9KTtcbiAgICAgICAgc2RwLnJhdyA9IHNkcC5zZXNzaW9uICsgc2RwLm1lZGlhLmpvaW4oJycpO1xuICAgIH0pO1xuXG4gICAgdGhpcy5tb2RpZnlTb3VyY2VzUXVldWUucHVzaChmdW5jdGlvbigpIHtcbiAgICAgICAgLy8gV2hlbiBhIHNvdXJjZSBpcyByZW1vdmVkIGFuZCBpZiB0aGlzIGlzIEZGLCB0aGUgcmVjdm9ubHkgY2hhbm5lbCB0aGF0XG4gICAgICAgIC8vIHJlY2VpdmVzIHRoZSByZW1vdGUgc3RyZWFtIGlzIGRlYWN0aXZhdGVkIC4gV2UgbmVlZCB0byBkaWZmdXNlIHRoZVxuICAgICAgICAvLyByZWN2b25seSBTU1JDIHJlbW92YWwgdG8gdGhlIHJlc3Qgb2YgdGhlIHBlZXJzLlxuICAgICAgICBsb2dnZXIubG9nKCdtb2RpZnkgc291cmNlcyBkb25lJyk7XG5cbiAgICAgICAgdmFyIG5ld1NkcCA9IG5ldyBTRFAoc2VsZi5wZWVyY29ubmVjdGlvbi5sb2NhbERlc2NyaXB0aW9uLnNkcCk7XG4gICAgICAgIGxvZ2dlci5sb2coXCJTRFBzXCIsIG15U2RwLCBuZXdTZHApO1xuICAgICAgICBzZWxmLm5vdGlmeU15U1NSQ1VwZGF0ZShteVNkcCwgbmV3U2RwKTtcbiAgICB9KTtcbn07XG5cbkppbmdsZVNlc3Npb25QQy5wcm90b3R5cGUuX21vZGlmeVNvdXJjZXMgPSBmdW5jdGlvbiAoc3VjY2Vzc0NhbGxiYWNrLCBxdWV1ZUNhbGxiYWNrKSB7XG4gICAgdmFyIHNlbGYgPSB0aGlzO1xuXG4gICAgaWYgKHRoaXMucGVlcmNvbm5lY3Rpb24uc2lnbmFsaW5nU3RhdGUgPT0gJ2Nsb3NlZCcpIHJldHVybjtcbiAgICBpZiAoISh0aGlzLmFkZHNzcmMubGVuZ3RoIHx8IHRoaXMucmVtb3Zlc3NyYy5sZW5ndGggfHwgdGhpcy5wZW5kaW5nb3AgIT09IG51bGxcbiAgICAgICAgfHwgdGhpcy5zd2l0Y2hzdHJlYW1zIHx8IHRoaXMuYWRkaW5nU3RyZWFtcykpe1xuICAgICAgICAvLyBUaGVyZSBpcyBub3RoaW5nIHRvIGRvIHNpbmNlIHNjaGVkdWxlZCBqb2IgbWlnaHQgaGF2ZSBiZWVuIGV4ZWN1dGVkIGJ5IGFub3RoZXIgc3VjY2VlZGluZyBjYWxsXG4gICAgICAgIHRoaXMuc2V0TG9jYWxEZXNjcmlwdGlvbigpO1xuICAgICAgICBpZihzdWNjZXNzQ2FsbGJhY2spe1xuICAgICAgICAgICAgc3VjY2Vzc0NhbGxiYWNrKCk7XG4gICAgICAgIH1cbiAgICAgICAgcXVldWVDYWxsYmFjaygpO1xuICAgICAgICByZXR1cm47XG4gICAgfVxuXG4gICAgLy8gUmVzZXQgc3dpdGNoIHN0cmVhbXMgZmxhZ3NcbiAgICB0aGlzLnN3aXRjaHN0cmVhbXMgPSBmYWxzZTtcbiAgICB0aGlzLmFkZGluZ1N0cmVhbXMgPSBmYWxzZTtcblxuICAgIHZhciBzZHAgPSBuZXcgU0RQKHRoaXMucGVlcmNvbm5lY3Rpb24ucmVtb3RlRGVzY3JpcHRpb24uc2RwKTtcblxuICAgIC8vIGFkZCBzb3VyY2VzXG4gICAgdGhpcy5hZGRzc3JjLmZvckVhY2goZnVuY3Rpb24obGluZXMsIGlkeCkge1xuICAgICAgICBzZHAubWVkaWFbaWR4XSArPSBsaW5lcztcbiAgICB9KTtcbiAgICB0aGlzLmFkZHNzcmMgPSBbXTtcblxuICAgIC8vIHJlbW92ZSBzb3VyY2VzXG4gICAgdGhpcy5yZW1vdmVzc3JjLmZvckVhY2goZnVuY3Rpb24obGluZXMsIGlkeCkge1xuICAgICAgICBsaW5lcyA9IGxpbmVzLnNwbGl0KCdcXHJcXG4nKTtcbiAgICAgICAgbGluZXMucG9wKCk7IC8vIHJlbW92ZSBlbXB0eSBsYXN0IGVsZW1lbnQ7XG4gICAgICAgIGxpbmVzLmZvckVhY2goZnVuY3Rpb24obGluZSkge1xuICAgICAgICAgICAgc2RwLm1lZGlhW2lkeF0gPSBzZHAubWVkaWFbaWR4XS5yZXBsYWNlKGxpbmUgKyAnXFxyXFxuJywgJycpO1xuICAgICAgICB9KTtcbiAgICB9KTtcbiAgICB0aGlzLnJlbW92ZXNzcmMgPSBbXTtcblxuICAgIHNkcC5yYXcgPSBzZHAuc2Vzc2lvbiArIHNkcC5tZWRpYS5qb2luKCcnKTtcbiAgICB0aGlzLnBlZXJjb25uZWN0aW9uLnNldFJlbW90ZURlc2NyaXB0aW9uKG5ldyBSVENTZXNzaW9uRGVzY3JpcHRpb24oe3R5cGU6ICdvZmZlcicsIHNkcDogc2RwLnJhd30pLFxuICAgICAgICBmdW5jdGlvbigpIHtcblxuICAgICAgICAgICAgaWYoc2VsZi5zaWduYWxpbmdTdGF0ZSA9PSAnY2xvc2VkJykge1xuICAgICAgICAgICAgICAgIGxvZ2dlci5lcnJvcihcImNyZWF0ZUFuc3dlciBhdHRlbXB0IG9uIGNsb3NlZCBzdGF0ZVwiKTtcbiAgICAgICAgICAgICAgICBxdWV1ZUNhbGxiYWNrKFwiY3JlYXRlQW5zd2VyIGF0dGVtcHQgb24gY2xvc2VkIHN0YXRlXCIpO1xuICAgICAgICAgICAgICAgIHJldHVybjtcbiAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgc2VsZi5wZWVyY29ubmVjdGlvbi5jcmVhdGVBbnN3ZXIoXG4gICAgICAgICAgICAgICAgZnVuY3Rpb24obW9kaWZpZWRBbnN3ZXIpIHtcbiAgICAgICAgICAgICAgICAgICAgLy8gY2hhbmdlIHZpZGVvIGRpcmVjdGlvbiwgc2VlIGh0dHBzOi8vZ2l0aHViLmNvbS9qaXRzaS9qaXRtZWV0L2lzc3Vlcy80MVxuICAgICAgICAgICAgICAgICAgICBpZiAoc2VsZi5wZW5kaW5nb3AgIT09IG51bGwpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgIHZhciBzZHAgPSBuZXcgU0RQKG1vZGlmaWVkQW5zd2VyLnNkcCk7XG4gICAgICAgICAgICAgICAgICAgICAgICBpZiAoc2RwLm1lZGlhLmxlbmd0aCA+IDEpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICBzd2l0Y2goc2VsZi5wZW5kaW5nb3ApIHtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgY2FzZSAnbXV0ZSc6XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBzZHAubWVkaWFbMV0gPSBzZHAubWVkaWFbMV0ucmVwbGFjZSgnYT1zZW5kcmVjdicsICdhPXJlY3Zvbmx5Jyk7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBicmVhaztcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgY2FzZSAndW5tdXRlJzpcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIHNkcC5tZWRpYVsxXSA9IHNkcC5tZWRpYVsxXS5yZXBsYWNlKCdhPXJlY3Zvbmx5JywgJ2E9c2VuZHJlY3YnKTtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGJyZWFrO1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICAgICAgICAgICAgICBzZHAucmF3ID0gc2RwLnNlc3Npb24gKyBzZHAubWVkaWEuam9pbignJyk7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgbW9kaWZpZWRBbnN3ZXIuc2RwID0gc2RwLnJhdztcbiAgICAgICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICAgICAgICAgIHNlbGYucGVuZGluZ29wID0gbnVsbDtcbiAgICAgICAgICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICAgICAgICAgIC8vIEZJWE1FOiBwdXNoaW5nIGRvd24gYW4gYW5zd2VyIHdoaWxlIGljZSBjb25uZWN0aW9uIHN0YXRlXG4gICAgICAgICAgICAgICAgICAgIC8vIGlzIHN0aWxsIGNoZWNraW5nIGlzIGJhZC4uLlxuICAgICAgICAgICAgICAgICAgICAvL2xvZ2dlci5sb2coc2VsZi5wZWVyY29ubmVjdGlvbi5pY2VDb25uZWN0aW9uU3RhdGUpO1xuXG4gICAgICAgICAgICAgICAgICAgIC8vIHRyeWluZyB0byB3b3JrIGFyb3VuZCBhbm90aGVyIGNocm9tZSBidWdcbiAgICAgICAgICAgICAgICAgICAgLy9tb2RpZmllZEFuc3dlci5zZHAgPSBtb2RpZmllZEFuc3dlci5zZHAucmVwbGFjZSgvYT1zZXR1cDphY3RpdmUvZywgJ2E9c2V0dXA6YWN0cGFzcycpO1xuICAgICAgICAgICAgICAgICAgICBzZWxmLnBlZXJjb25uZWN0aW9uLnNldExvY2FsRGVzY3JpcHRpb24obW9kaWZpZWRBbnN3ZXIsXG4gICAgICAgICAgICAgICAgICAgICAgICBmdW5jdGlvbigpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAvL2xvZ2dlci5sb2coJ21vZGlmaWVkIHNldExvY2FsRGVzY3JpcHRpb24gb2snKTtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICBzZWxmLnNldExvY2FsRGVzY3JpcHRpb24oKTtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICBpZihzdWNjZXNzQ2FsbGJhY2spe1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBzdWNjZXNzQ2FsbGJhY2soKTtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgcXVldWVDYWxsYmFjaygpO1xuICAgICAgICAgICAgICAgICAgICAgICAgfSxcbiAgICAgICAgICAgICAgICAgICAgICAgIGZ1bmN0aW9uKGVycm9yKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgbG9nZ2VyLmVycm9yKCdtb2RpZmllZCBzZXRMb2NhbERlc2NyaXB0aW9uIGZhaWxlZCcsIGVycm9yKTtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICBxdWV1ZUNhbGxiYWNrKGVycm9yKTtcbiAgICAgICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICAgICAgKTtcbiAgICAgICAgICAgICAgICB9LFxuICAgICAgICAgICAgICAgIGZ1bmN0aW9uKGVycm9yKSB7XG4gICAgICAgICAgICAgICAgICAgIGxvZ2dlci5lcnJvcignbW9kaWZpZWQgYW5zd2VyIGZhaWxlZCcsIGVycm9yKTtcbiAgICAgICAgICAgICAgICAgICAgcXVldWVDYWxsYmFjayhlcnJvcik7XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgKTtcbiAgICAgICAgfSxcbiAgICAgICAgZnVuY3Rpb24oZXJyb3IpIHtcbiAgICAgICAgICAgIGxvZ2dlci5lcnJvcignbW9kaWZ5IGZhaWxlZCcsIGVycm9yKTtcbiAgICAgICAgICAgIHF1ZXVlQ2FsbGJhY2soZXJyb3IpO1xuICAgICAgICB9XG4gICAgKTtcbn07XG5cblxuLyoqXG4gKiBTd2l0Y2hlcyB2aWRlbyBzdHJlYW1zLlxuICogQHBhcmFtIG5ld1N0cmVhbSBuZXcgc3RyZWFtIHRoYXQgd2lsbCBiZSB1c2VkIGFzIHZpZGVvIG9mIHRoaXMgc2Vzc2lvbi5cbiAqIEBwYXJhbSBvbGRTdHJlYW0gb2xkIHZpZGVvIHN0cmVhbSBvZiB0aGlzIHNlc3Npb24uXG4gKiBAcGFyYW0gc3VjY2Vzc0NhbGxiYWNrIGNhbGxiYWNrIGV4ZWN1dGVkIGFmdGVyIHN1Y2Nlc3NmdWwgc3RyZWFtIHN3aXRjaC5cbiAqIEBwYXJhbSBpc0F1ZGlvIHdoZXRoZXIgdGhlIHN0cmVhbXMgYXJlIGF1ZGlvIChpZiB0cnVlKSBvciB2aWRlbyAoaWYgZmFsc2UpLlxuICovXG5KaW5nbGVTZXNzaW9uUEMucHJvdG90eXBlLnN3aXRjaFN0cmVhbXMgPVxuICAgIGZ1bmN0aW9uIChuZXdTdHJlYW0sIG9sZFN0cmVhbSwgc3VjY2Vzc0NhbGxiYWNrLCBpc0F1ZGlvKSB7XG4gICAgdmFyIHNlbGYgPSB0aGlzO1xuICAgIHZhciBzZW5kZXIsIG5ld1RyYWNrO1xuICAgIHZhciBzZW5kZXJLaW5kID0gaXNBdWRpbyA/ICdhdWRpbycgOiAndmlkZW8nO1xuICAgIC8vIFJlbWVtYmVyIFNEUCB0byBmaWd1cmUgb3V0IGFkZGVkL3JlbW92ZWQgU1NSQ3NcbiAgICB2YXIgb2xkU2RwID0gbnVsbDtcblxuICAgIGlmIChzZWxmLnBlZXJjb25uZWN0aW9uKSB7XG4gICAgICAgIGlmIChzZWxmLnBlZXJjb25uZWN0aW9uLmxvY2FsRGVzY3JpcHRpb24pIHtcbiAgICAgICAgICAgIG9sZFNkcCA9IG5ldyBTRFAoc2VsZi5wZWVyY29ubmVjdGlvbi5sb2NhbERlc2NyaXB0aW9uLnNkcCk7XG4gICAgICAgIH1cbiAgICAgICAgaWYgKFJUQ0Jyb3dzZXJUeXBlLmdldEJyb3dzZXJUeXBlKCkgPT09XG4gICAgICAgICAgICAgICAgUlRDQnJvd3NlclR5cGUuUlRDX0JST1dTRVJfRklSRUZPWCkge1xuICAgICAgICAgICAgLy8gT24gRmlyZWZveCB3ZSBkb24ndCByZXBsYWNlIE1lZGlhU3RyZWFtcyBhcyB0aGlzIG1lc3NlcyB1cCB0aGVcbiAgICAgICAgICAgIC8vIG0tbGluZXMgKHdoaWNoIGNhbid0IGJlIHJlbW92ZWQgaW4gUGxhbiBVbmlmaWVkKSBhbmQgYnJpbmdzIGEgbG90XG4gICAgICAgICAgICAvLyBvZiBjb21wbGljYXRpb25zLiBJbnN0ZWFkLCB3ZSB1c2UgdGhlIFJUUFNlbmRlciBhbmQgcmVwbGFjZSBqdXN0XG4gICAgICAgICAgICAvLyB0aGUgdHJhY2suXG5cbiAgICAgICAgICAgIC8vIEZpbmQgdGhlIHJpZ2h0IHNlbmRlciAoZm9yIGF1ZGlvIG9yIHZpZGVvKVxuICAgICAgICAgICAgc2VsZi5wZWVyY29ubmVjdGlvbi5wZWVyY29ubmVjdGlvbi5nZXRTZW5kZXJzKCkuc29tZShmdW5jdGlvbiAocykge1xuICAgICAgICAgICAgICAgIGlmIChzLnRyYWNrICYmIHMudHJhY2sua2luZCA9PT0gc2VuZGVyS2luZCkge1xuICAgICAgICAgICAgICAgICAgICBzZW5kZXIgPSBzO1xuICAgICAgICAgICAgICAgICAgICByZXR1cm4gdHJ1ZTtcbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICB9KTtcblxuICAgICAgICAgICAgaWYgKHNlbmRlcikge1xuICAgICAgICAgICAgICAgIC8vIFdlIGFzc3VtZSB0aGF0IG91ciBzdHJlYW1zIGhhdmUgYSBzaW5nbGUgdHJhY2ssIGVpdGhlciBhdWRpb1xuICAgICAgICAgICAgICAgIC8vIG9yIHZpZGVvLlxuICAgICAgICAgICAgICAgIG5ld1RyYWNrID0gaXNBdWRpbyA/IG5ld1N0cmVhbS5nZXRBdWRpb1RyYWNrcygpWzBdIDpcbiAgICAgICAgICAgICAgICAgICAgbmV3U3RyZWFtLmdldFZpZGVvVHJhY2tzKClbMF07XG4gICAgICAgICAgICAgICAgc2VuZGVyLnJlcGxhY2VUcmFjayhuZXdUcmFjaylcbiAgICAgICAgICAgICAgICAgICAgLnRoZW4oZnVuY3Rpb24oKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICBjb25zb2xlLmxvZyhcIlJlcGxhY2VkIGEgdHJhY2ssIGlzQXVkaW89XCIgKyBpc0F1ZGlvKTtcbiAgICAgICAgICAgICAgICAgICAgfSlcbiAgICAgICAgICAgICAgICAgICAgLmNhdGNoKGZ1bmN0aW9uKGVycikge1xuICAgICAgICAgICAgICAgICAgICAgICAgY29uc29sZS5sb2coXCJGYWlsZWQgdG8gcmVwbGFjZSBhIHRyYWNrOiBcIiArIGVycik7XG4gICAgICAgICAgICAgICAgICAgIH0pO1xuICAgICAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgICAgICBjb25zb2xlLmxvZyhcIkNhbm5vdCBzd2l0Y2ggdHJhY2tzOiBubyBSVFBTZW5kZXIuXCIpO1xuICAgICAgICAgICAgfVxuICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgc2VsZi5wZWVyY29ubmVjdGlvbi5yZW1vdmVTdHJlYW0ob2xkU3RyZWFtLCB0cnVlKTtcbiAgICAgICAgICAgIGlmIChuZXdTdHJlYW0pIHtcbiAgICAgICAgICAgICAgICBzZWxmLnBlZXJjb25uZWN0aW9uLmFkZFN0cmVhbShuZXdTdHJlYW0pO1xuICAgICAgICAgICAgfVxuICAgICAgICB9XG4gICAgfVxuXG4gICAgLy8gQ29uZmVyZW5jZSBpcyBub3QgYWN0aXZlXG4gICAgaWYgKCFvbGRTZHApIHtcbiAgICAgICAgc3VjY2Vzc0NhbGxiYWNrKCk7XG4gICAgICAgIHJldHVybjtcbiAgICB9XG5cbiAgICBzZWxmLnN3aXRjaHN0cmVhbXMgPSB0cnVlO1xuICAgIHNlbGYubW9kaWZ5U291cmNlc1F1ZXVlLnB1c2goZnVuY3Rpb24oKSB7XG4gICAgICAgIGxvZ2dlci5sb2coJ21vZGlmeSBzb3VyY2VzIGRvbmUnKTtcblxuICAgICAgICBzdWNjZXNzQ2FsbGJhY2soKTtcblxuICAgICAgICB2YXIgbmV3U2RwID0gbmV3IFNEUChzZWxmLnBlZXJjb25uZWN0aW9uLmxvY2FsRGVzY3JpcHRpb24uc2RwKTtcbiAgICAgICAgbG9nZ2VyLmxvZyhcIlNEUHNcIiwgb2xkU2RwLCBuZXdTZHApO1xuICAgICAgICBzZWxmLm5vdGlmeU15U1NSQ1VwZGF0ZShvbGRTZHAsIG5ld1NkcCk7XG4gICAgfSk7XG59O1xuXG4vKipcbiAqIEFkZHMgc3RyZWFtcy5cbiAqIEBwYXJhbSBzdHJlYW0gbmV3IHN0cmVhbSB0aGF0IHdpbGwgYmUgYWRkZWQuXG4gKiBAcGFyYW0gc3VjY2Vzc19jYWxsYmFjayBjYWxsYmFjayBleGVjdXRlZCBhZnRlciBzdWNjZXNzZnVsIHN0cmVhbSBhZGRpdGlvbi5cbiAqL1xuSmluZ2xlU2Vzc2lvblBDLnByb3RvdHlwZS5hZGRTdHJlYW0gPSBmdW5jdGlvbiAoc3RyZWFtLCBjYWxsYmFjaykge1xuXG4gICAgdmFyIHNlbGYgPSB0aGlzO1xuXG4gICAgLy8gUmVtZW1iZXIgU0RQIHRvIGZpZ3VyZSBvdXQgYWRkZWQvcmVtb3ZlZCBTU1JDc1xuICAgIHZhciBvbGRTZHAgPSBudWxsO1xuICAgIGlmKHRoaXMucGVlcmNvbm5lY3Rpb24pIHtcbiAgICAgICAgaWYodGhpcy5wZWVyY29ubmVjdGlvbi5sb2NhbERlc2NyaXB0aW9uKSB7XG4gICAgICAgICAgICBvbGRTZHAgPSBuZXcgU0RQKHRoaXMucGVlcmNvbm5lY3Rpb24ubG9jYWxEZXNjcmlwdGlvbi5zZHApO1xuICAgICAgICB9XG4gICAgICAgIGlmKHN0cmVhbSlcbiAgICAgICAgICAgIHRoaXMucGVlcmNvbm5lY3Rpb24uYWRkU3RyZWFtKHN0cmVhbSk7XG4gICAgfVxuXG4gICAgLy8gQ29uZmVyZW5jZSBpcyBub3QgYWN0aXZlXG4gICAgaWYoIW9sZFNkcCB8fCAhdGhpcy5wZWVyY29ubmVjdGlvbikge1xuICAgICAgICBjYWxsYmFjaygpO1xuICAgICAgICByZXR1cm47XG4gICAgfVxuXG4gICAgdGhpcy5hZGRpbmdTdHJlYW1zID0gdHJ1ZTtcbiAgICB0aGlzLm1vZGlmeVNvdXJjZXNRdWV1ZS5wdXNoKGZ1bmN0aW9uKCkge1xuICAgICAgICBsb2dnZXIubG9nKCdtb2RpZnkgc291cmNlcyBkb25lJyk7XG5cbiAgICAgICAgY2FsbGJhY2soKTtcblxuICAgICAgICB2YXIgbmV3U2RwID0gbmV3IFNEUChzZWxmLnBlZXJjb25uZWN0aW9uLmxvY2FsRGVzY3JpcHRpb24uc2RwKTtcbiAgICAgICAgbG9nZ2VyLmxvZyhcIlNEUHNcIiwgb2xkU2RwLCBuZXdTZHApO1xuICAgICAgICBzZWxmLm5vdGlmeU15U1NSQ1VwZGF0ZShvbGRTZHAsIG5ld1NkcCk7XG4gICAgfSk7XG59XG5cbi8qKlxuICogUmVtb3ZlIHN0cmVhbXMuXG4gKiBAcGFyYW0gc3RyZWFtIHN0cmVhbSB0aGF0IHdpbGwgYmUgcmVtb3ZlZC5cbiAqIEBwYXJhbSBzdWNjZXNzX2NhbGxiYWNrIGNhbGxiYWNrIGV4ZWN1dGVkIGFmdGVyIHN1Y2Nlc3NmdWwgc3RyZWFtIGFkZGl0aW9uLlxuICovXG5KaW5nbGVTZXNzaW9uUEMucHJvdG90eXBlLnJlbW92ZVN0cmVhbSA9IGZ1bmN0aW9uIChzdHJlYW0sIGNhbGxiYWNrKSB7XG5cbiAgICB2YXIgc2VsZiA9IHRoaXM7XG5cbiAgICAvLyBSZW1lbWJlciBTRFAgdG8gZmlndXJlIG91dCBhZGRlZC9yZW1vdmVkIFNTUkNzXG4gICAgdmFyIG9sZFNkcCA9IG51bGw7XG4gICAgaWYodGhpcy5wZWVyY29ubmVjdGlvbikge1xuICAgICAgICBpZih0aGlzLnBlZXJjb25uZWN0aW9uLmxvY2FsRGVzY3JpcHRpb24pIHtcbiAgICAgICAgICAgIG9sZFNkcCA9IG5ldyBTRFAodGhpcy5wZWVyY29ubmVjdGlvbi5sb2NhbERlc2NyaXB0aW9uLnNkcCk7XG4gICAgICAgIH1cbiAgICAgICAgaWYoc3RyZWFtKVxuICAgICAgICAgICAgdGhpcy5wZWVyY29ubmVjdGlvbi5yZW1vdmVTdHJlYW0oc3RyZWFtKTtcbiAgICB9XG5cbiAgICAvLyBDb25mZXJlbmNlIGlzIG5vdCBhY3RpdmVcbiAgICBpZighb2xkU2RwIHx8ICF0aGlzLnBlZXJjb25uZWN0aW9uKSB7XG4gICAgICAgIGNhbGxiYWNrKCk7XG4gICAgICAgIHJldHVybjtcbiAgICB9XG5cbiAgICB0aGlzLmFkZGluZ1N0cmVhbXMgPSB0cnVlO1xuICAgIHRoaXMubW9kaWZ5U291cmNlc1F1ZXVlLnB1c2goZnVuY3Rpb24oKSB7XG4gICAgICAgIGxvZ2dlci5sb2coJ21vZGlmeSBzb3VyY2VzIGRvbmUnKTtcblxuICAgICAgICBjYWxsYmFjaygpO1xuXG4gICAgICAgIHZhciBuZXdTZHAgPSBuZXcgU0RQKHNlbGYucGVlcmNvbm5lY3Rpb24ubG9jYWxEZXNjcmlwdGlvbi5zZHApO1xuICAgICAgICBsb2dnZXIubG9nKFwiU0RQc1wiLCBvbGRTZHAsIG5ld1NkcCk7XG4gICAgICAgIHNlbGYubm90aWZ5TXlTU1JDVXBkYXRlKG9sZFNkcCwgbmV3U2RwKTtcbiAgICB9KTtcbn1cblxuLyoqXG4gKiBGaWd1cmVzIG91dCBhZGRlZC9yZW1vdmVkIHNzcmNzIGFuZCBzZW5kIHVwZGF0ZSBJUXMuXG4gKiBAcGFyYW0gb2xkX3NkcCBTRFAgb2JqZWN0IGZvciBvbGQgZGVzY3JpcHRpb24uXG4gKiBAcGFyYW0gbmV3X3NkcCBTRFAgb2JqZWN0IGZvciBuZXcgZGVzY3JpcHRpb24uXG4gKi9cbkppbmdsZVNlc3Npb25QQy5wcm90b3R5cGUubm90aWZ5TXlTU1JDVXBkYXRlID0gZnVuY3Rpb24gKG9sZF9zZHAsIG5ld19zZHApIHtcblxuICAgIGlmICghKHRoaXMucGVlcmNvbm5lY3Rpb24uc2lnbmFsaW5nU3RhdGUgPT0gJ3N0YWJsZScgJiZcbiAgICAgICAgdGhpcy5wZWVyY29ubmVjdGlvbi5pY2VDb25uZWN0aW9uU3RhdGUgPT0gJ2Nvbm5lY3RlZCcpKXtcbiAgICAgICAgbG9nZ2VyLmxvZyhcIlRvbyBlYXJseSB0byBzZW5kIHVwZGF0ZXNcIik7XG4gICAgICAgIHJldHVybjtcbiAgICB9XG5cbiAgICAvLyBzZW5kIHNvdXJjZS1yZW1vdmUgSVEuXG4gICAgc2RwRGlmZmVyID0gbmV3IFNEUERpZmZlcihuZXdfc2RwLCBvbGRfc2RwKTtcbiAgICB2YXIgcmVtb3ZlID0gJGlxKHt0bzogdGhpcy5wZWVyamlkLCB0eXBlOiAnc2V0J30pXG4gICAgICAgIC5jKCdqaW5nbGUnLCB7XG4gICAgICAgICAgICB4bWxuczogJ3Vybjp4bXBwOmppbmdsZToxJyxcbiAgICAgICAgICAgIGFjdGlvbjogJ3NvdXJjZS1yZW1vdmUnLFxuICAgICAgICAgICAgaW5pdGlhdG9yOiB0aGlzLmluaXRpYXRvcixcbiAgICAgICAgICAgIHNpZDogdGhpcy5zaWRcbiAgICAgICAgfVxuICAgICk7XG4gICAgdmFyIHJlbW92ZWQgPSBzZHBEaWZmZXIudG9KaW5nbGUocmVtb3ZlKTtcblxuICAgIC8vIExldCAnc291cmNlLXJlbW92ZScgSVEgdGhyb3VnaCB0aGUgaGFjayBhbmQgc2VlIGlmIHdlJ3JlIGFsbG93ZWQgdG8gc2VuZFxuICAgIC8vIGl0IGluIHRoZSBjdXJyZW50IGZvcm1cbiAgICBpZiAocmVtb3ZlZClcbiAgICAgICAgcmVtb3ZlID0gU1NSQ1JlcGxhY2VtZW50LnByb2Nlc3NTb3VyY2VSZW1vdmUocmVtb3ZlKTtcblxuICAgIGlmIChyZW1vdmVkICYmIHJlbW92ZSkge1xuICAgICAgICBsb2dnZXIuaW5mbyhcIlNlbmRpbmcgc291cmNlLXJlbW92ZVwiLCByZW1vdmUpO1xuICAgICAgICB0aGlzLmNvbm5lY3Rpb24uc2VuZElRKHJlbW92ZSxcbiAgICAgICAgICAgIGZ1bmN0aW9uIChyZXMpIHtcbiAgICAgICAgICAgICAgICBsb2dnZXIuaW5mbygnZ290IHJlbW92ZSByZXN1bHQnLCByZXMpO1xuICAgICAgICAgICAgfSxcbiAgICAgICAgICAgIGZ1bmN0aW9uIChlcnIpIHtcbiAgICAgICAgICAgICAgICBsb2dnZXIuZXJyb3IoJ2dvdCByZW1vdmUgZXJyb3InLCBlcnIpO1xuICAgICAgICAgICAgfVxuICAgICAgICApO1xuICAgIH0gZWxzZSB7XG4gICAgICAgIGxvZ2dlci5sb2coJ3JlbW92YWwgbm90IG5lY2Vzc2FyeScpO1xuICAgIH1cblxuICAgIC8vIHNlbmQgc291cmNlLWFkZCBJUS5cbiAgICB2YXIgc2RwRGlmZmVyID0gbmV3IFNEUERpZmZlcihvbGRfc2RwLCBuZXdfc2RwKTtcbiAgICB2YXIgYWRkID0gJGlxKHt0bzogdGhpcy5wZWVyamlkLCB0eXBlOiAnc2V0J30pXG4gICAgICAgIC5jKCdqaW5nbGUnLCB7XG4gICAgICAgICAgICB4bWxuczogJ3Vybjp4bXBwOmppbmdsZToxJyxcbiAgICAgICAgICAgIGFjdGlvbjogJ3NvdXJjZS1hZGQnLFxuICAgICAgICAgICAgaW5pdGlhdG9yOiB0aGlzLmluaXRpYXRvcixcbiAgICAgICAgICAgIHNpZDogdGhpcy5zaWRcbiAgICAgICAgfVxuICAgICk7XG4gICAgdmFyIGFkZGVkID0gc2RwRGlmZmVyLnRvSmluZ2xlKGFkZCk7XG5cbiAgICAvLyBMZXQgJ3NvdXJjZS1hZGQnIElRIHRocm91Z2ggdGhlIGhhY2sgYW5kIHNlZSBpZiB3ZSdyZSBhbGxvd2VkIHRvIHNlbmRcbiAgICAvLyBpdCBpbiB0aGUgY3VycmVudCBmb3JtXG4gICAgaWYgKGFkZGVkKVxuICAgICAgICBhZGQgPSBTU1JDUmVwbGFjZW1lbnQucHJvY2Vzc1NvdXJjZUFkZChhZGQpO1xuXG4gICAgaWYgKGFkZGVkICYmIGFkZCkge1xuICAgICAgICBsb2dnZXIuaW5mbyhcIlNlbmRpbmcgc291cmNlLWFkZFwiLCBhZGQpO1xuICAgICAgICB0aGlzLmNvbm5lY3Rpb24uc2VuZElRKGFkZCxcbiAgICAgICAgICAgIGZ1bmN0aW9uIChyZXMpIHtcbiAgICAgICAgICAgICAgICBsb2dnZXIuaW5mbygnZ290IGFkZCByZXN1bHQnLCByZXMpO1xuICAgICAgICAgICAgfSxcbiAgICAgICAgICAgIGZ1bmN0aW9uIChlcnIpIHtcbiAgICAgICAgICAgICAgICBsb2dnZXIuZXJyb3IoJ2dvdCBhZGQgZXJyb3InLCBlcnIpO1xuICAgICAgICAgICAgfVxuICAgICAgICApO1xuICAgIH0gZWxzZSB7XG4gICAgICAgIGxvZ2dlci5sb2coJ2FkZGl0aW9uIG5vdCBuZWNlc3NhcnknKTtcbiAgICB9XG59O1xuXG4vKipcbiAqIE11dGVzL3VubXV0ZXMgdGhlIChsb2NhbCkgdmlkZW8gaS5lLiBlbmFibGVzL2Rpc2FibGVzIGFsbCB2aWRlbyB0cmFja3MuXG4gKlxuICogQHBhcmFtIG11dGUgPHR0PnRydWU8L3R0PiB0byBtdXRlIHRoZSAobG9jYWwpIHZpZGVvIGkuZS4gdG8gZGlzYWJsZSBhbGwgdmlkZW9cbiAqIHRyYWNrczsgb3RoZXJ3aXNlLCA8dHQ+ZmFsc2U8L3R0PlxuICogQHBhcmFtIGNhbGxiYWNrIGEgZnVuY3Rpb24gdG8gYmUgaW52b2tlZCB3aXRoIDx0dD5tdXRlPC90dD4gYWZ0ZXIgYWxsIHZpZGVvXG4gKiB0cmFja3MgaGF2ZSBiZWVuIGVuYWJsZWQvZGlzYWJsZWQuIFRoZSBmdW5jdGlvbiBtYXksIG9wdGlvbmFsbHksIHJldHVyblxuICogYW5vdGhlciBmdW5jdGlvbiB3aGljaCBpcyB0byBiZSBpbnZva2VkIGFmdGVyIHRoZSB3aG9sZSBtdXRlL3VubXV0ZSBvcGVyYXRpb25cbiAqIGhhcyBjb21wbGV0ZWQgc3VjY2Vzc2Z1bGx5LlxuICogQHBhcmFtIG9wdGlvbnMgYW4gb2JqZWN0IHdoaWNoIHNwZWNpZmllcyBvcHRpb25hbCBhcmd1bWVudHMgc3VjaCBhcyB0aGVcbiAqIDx0dD5ib29sZWFuPC90dD4ga2V5IDx0dD5ieVVzZXI8L3R0PiB3aXRoIGRlZmF1bHQgdmFsdWUgPHR0PnRydWU8L3R0PiB3aGljaFxuICogc3BlY2lmaWVzIHdoZXRoZXIgdGhlIG1ldGhvZCB3YXMgaW5pdGlhdGVkIGluIHJlc3BvbnNlIHRvIGEgdXNlciBjb21tYW5kIChpblxuICogY29udHJhc3QgdG8gYW4gYXV0b21hdGljIGRlY2lzaW9uIG1hZGUgYnkgdGhlIGFwcGxpY2F0aW9uIGxvZ2ljKVxuICovXG5KaW5nbGVTZXNzaW9uUEMucHJvdG90eXBlLnNldFZpZGVvTXV0ZSA9IGZ1bmN0aW9uIChtdXRlLCBjYWxsYmFjaywgb3B0aW9ucykge1xuICAgIHZhciBieVVzZXI7XG5cbiAgICBpZiAob3B0aW9ucykge1xuICAgICAgICBieVVzZXIgPSBvcHRpb25zLmJ5VXNlcjtcbiAgICAgICAgaWYgKHR5cGVvZiBieVVzZXIgPT09ICd1bmRlZmluZWQnKSB7XG4gICAgICAgICAgICBieVVzZXIgPSB0cnVlO1xuICAgICAgICB9XG4gICAgfSBlbHNlIHtcbiAgICAgICAgYnlVc2VyID0gdHJ1ZTtcbiAgICB9XG4gICAgLy8gVGhlIHVzZXIncyBjb21tYW5kIHRvIG11dGUgdGhlIChsb2NhbCkgdmlkZW8gdGFrZXMgcHJlY2VkZW5jZSBvdmVyIGFueVxuICAgIC8vIGF1dG9tYXRpYyBkZWNpc2lvbiBtYWRlIGJ5IHRoZSBhcHBsaWNhdGlvbiBsb2dpYy5cbiAgICBpZiAoYnlVc2VyKSB7XG4gICAgICAgIHRoaXMudmlkZW9NdXRlQnlVc2VyID0gbXV0ZTtcbiAgICB9IGVsc2UgaWYgKHRoaXMudmlkZW9NdXRlQnlVc2VyKSB7XG4gICAgICAgIHJldHVybjtcbiAgICB9XG5cbiAgICB0aGlzLmhhcmRNdXRlVmlkZW8obXV0ZSk7XG5cbiAgICB2YXIgc2VsZiA9IHRoaXM7XG4gICAgdmFyIG9sZFNkcCA9IG51bGw7XG4gICAgaWYoc2VsZi5wZWVyY29ubmVjdGlvbikge1xuICAgICAgICBpZihzZWxmLnBlZXJjb25uZWN0aW9uLmxvY2FsRGVzY3JpcHRpb24pIHtcbiAgICAgICAgICAgIG9sZFNkcCA9IG5ldyBTRFAoc2VsZi5wZWVyY29ubmVjdGlvbi5sb2NhbERlc2NyaXB0aW9uLnNkcCk7XG4gICAgICAgIH1cbiAgICB9XG5cbiAgICB0aGlzLm1vZGlmeVNvdXJjZXNRdWV1ZS5wdXNoKGZ1bmN0aW9uKCkge1xuICAgICAgICBsb2dnZXIubG9nKCdtb2RpZnkgc291cmNlcyBkb25lJyk7XG5cbiAgICAgICAgY2FsbGJhY2sobXV0ZSk7XG5cbiAgICAgICAgdmFyIG5ld1NkcCA9IG5ldyBTRFAoc2VsZi5wZWVyY29ubmVjdGlvbi5sb2NhbERlc2NyaXB0aW9uLnNkcCk7XG4gICAgICAgIGxvZ2dlci5sb2coXCJTRFBzXCIsIG9sZFNkcCwgbmV3U2RwKTtcbiAgICAgICAgc2VsZi5ub3RpZnlNeVNTUkNVcGRhdGUob2xkU2RwLCBuZXdTZHApO1xuICAgIH0pO1xufTtcblxuSmluZ2xlU2Vzc2lvblBDLnByb3RvdHlwZS5oYXJkTXV0ZVZpZGVvID0gZnVuY3Rpb24gKG11dGVkKSB7XG4gICAgdGhpcy5wZW5kaW5nb3AgPSBtdXRlZCA/ICdtdXRlJyA6ICd1bm11dGUnO1xufTtcblxuSmluZ2xlU2Vzc2lvblBDLnByb3RvdHlwZS5zZW5kTXV0ZSA9IGZ1bmN0aW9uIChtdXRlZCwgY29udGVudCkge1xuICAgIHZhciBpbmZvID0gJGlxKHt0bzogdGhpcy5wZWVyamlkLFxuICAgICAgICB0eXBlOiAnc2V0J30pXG4gICAgICAgIC5jKCdqaW5nbGUnLCB7eG1sbnM6ICd1cm46eG1wcDpqaW5nbGU6MScsXG4gICAgICAgICAgICBhY3Rpb246ICdzZXNzaW9uLWluZm8nLFxuICAgICAgICAgICAgaW5pdGlhdG9yOiB0aGlzLmluaXRpYXRvcixcbiAgICAgICAgICAgIHNpZDogdGhpcy5zaWQgfSk7XG4gICAgaW5mby5jKG11dGVkID8gJ211dGUnIDogJ3VubXV0ZScsIHt4bWxuczogJ3Vybjp4bXBwOmppbmdsZTphcHBzOnJ0cDppbmZvOjEnfSk7XG4gICAgaW5mby5hdHRycyh7J2NyZWF0b3InOiB0aGlzLm1lID09IHRoaXMuaW5pdGlhdG9yID8gJ2NyZWF0b3InIDogJ3Jlc3BvbmRlcid9KTtcbiAgICBpZiAoY29udGVudCkge1xuICAgICAgICBpbmZvLmF0dHJzKHsnbmFtZSc6IGNvbnRlbnR9KTtcbiAgICB9XG4gICAgdGhpcy5jb25uZWN0aW9uLnNlbmQoaW5mbyk7XG59O1xuXG5KaW5nbGVTZXNzaW9uUEMucHJvdG90eXBlLnNlbmRSaW5naW5nID0gZnVuY3Rpb24gKCkge1xuICAgIHZhciBpbmZvID0gJGlxKHt0bzogdGhpcy5wZWVyamlkLFxuICAgICAgICB0eXBlOiAnc2V0J30pXG4gICAgICAgIC5jKCdqaW5nbGUnLCB7eG1sbnM6ICd1cm46eG1wcDpqaW5nbGU6MScsXG4gICAgICAgICAgICBhY3Rpb246ICdzZXNzaW9uLWluZm8nLFxuICAgICAgICAgICAgaW5pdGlhdG9yOiB0aGlzLmluaXRpYXRvcixcbiAgICAgICAgICAgIHNpZDogdGhpcy5zaWQgfSk7XG4gICAgaW5mby5jKCdyaW5naW5nJywge3htbG5zOiAndXJuOnhtcHA6amluZ2xlOmFwcHM6cnRwOmluZm86MSd9KTtcbiAgICB0aGlzLmNvbm5lY3Rpb24uc2VuZChpbmZvKTtcbn07XG5cbkppbmdsZVNlc3Npb25QQy5wcm90b3R5cGUuZ2V0U3RhdHMgPSBmdW5jdGlvbiAoaW50ZXJ2YWwpIHtcbiAgICB2YXIgc2VsZiA9IHRoaXM7XG4gICAgdmFyIHJlY3YgPSB7YXVkaW86IDAsIHZpZGVvOiAwfTtcbiAgICB2YXIgbG9zdCA9IHthdWRpbzogMCwgdmlkZW86IDB9O1xuICAgIHZhciBsYXN0cmVjdiA9IHthdWRpbzogMCwgdmlkZW86IDB9O1xuICAgIHZhciBsYXN0bG9zdCA9IHthdWRpbzogMCwgdmlkZW86IDB9O1xuICAgIHZhciBsb3NzID0ge2F1ZGlvOiAwLCB2aWRlbzogMH07XG4gICAgdmFyIGRlbHRhID0ge2F1ZGlvOiAwLCB2aWRlbzogMH07XG4gICAgdGhpcy5zdGF0c2ludGVydmFsID0gd2luZG93LnNldEludGVydmFsKGZ1bmN0aW9uICgpIHtcbiAgICAgICAgaWYgKHNlbGYgJiYgc2VsZi5wZWVyY29ubmVjdGlvbiAmJiBzZWxmLnBlZXJjb25uZWN0aW9uLmdldFN0YXRzKSB7XG4gICAgICAgICAgICBzZWxmLnBlZXJjb25uZWN0aW9uLmdldFN0YXRzKGZ1bmN0aW9uIChzdGF0cykge1xuICAgICAgICAgICAgICAgIHZhciByZXN1bHRzID0gc3RhdHMucmVzdWx0KCk7XG4gICAgICAgICAgICAgICAgLy8gVE9ETzogdGhlcmUgYXJlIHNvIG11Y2ggc3RhdGlzdGljcyB5b3UgY2FuIGdldCBmcm9tIHRoaXMuLlxuICAgICAgICAgICAgICAgIGZvciAodmFyIGkgPSAwOyBpIDwgcmVzdWx0cy5sZW5ndGg7ICsraSkge1xuICAgICAgICAgICAgICAgICAgICBpZiAocmVzdWx0c1tpXS50eXBlID09ICdzc3JjJykge1xuICAgICAgICAgICAgICAgICAgICAgICAgdmFyIHBhY2tldHNyZWN2ID0gcmVzdWx0c1tpXS5zdGF0KCdwYWNrZXRzUmVjZWl2ZWQnKTtcbiAgICAgICAgICAgICAgICAgICAgICAgIHZhciBwYWNrZXRzbG9zdCA9IHJlc3VsdHNbaV0uc3RhdCgncGFja2V0c0xvc3QnKTtcbiAgICAgICAgICAgICAgICAgICAgICAgIGlmIChwYWNrZXRzcmVjdiAmJiBwYWNrZXRzbG9zdCkge1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgIHBhY2tldHNyZWN2ID0gcGFyc2VJbnQocGFja2V0c3JlY3YsIDEwKTtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICBwYWNrZXRzbG9zdCA9IHBhcnNlSW50KHBhY2tldHNsb3N0LCAxMCk7XG5cbiAgICAgICAgICAgICAgICAgICAgICAgICAgICBpZiAocmVzdWx0c1tpXS5zdGF0KCdnb29nRnJhbWVSYXRlUmVjZWl2ZWQnKSkge1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBsYXN0bG9zdC52aWRlbyA9IGxvc3QudmlkZW87XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGxhc3RyZWN2LnZpZGVvID0gcmVjdi52aWRlbztcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgcmVjdi52aWRlbyA9IHBhY2tldHNyZWN2O1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBsb3N0LnZpZGVvID0gcGFja2V0c2xvc3Q7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgbGFzdGxvc3QuYXVkaW8gPSBsb3N0LmF1ZGlvO1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBsYXN0cmVjdi5hdWRpbyA9IHJlY3YuYXVkaW87XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIHJlY3YuYXVkaW8gPSBwYWNrZXRzcmVjdjtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgbG9zdC5hdWRpbyA9IHBhY2tldHNsb3N0O1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICBkZWx0YS5hdWRpbyA9IHJlY3YuYXVkaW8gLSBsYXN0cmVjdi5hdWRpbztcbiAgICAgICAgICAgICAgICBkZWx0YS52aWRlbyA9IHJlY3YudmlkZW8gLSBsYXN0cmVjdi52aWRlbztcbiAgICAgICAgICAgICAgICBsb3NzLmF1ZGlvID0gKGRlbHRhLmF1ZGlvID4gMCkgPyBNYXRoLmNlaWwoMTAwICogKGxvc3QuYXVkaW8gLSBsYXN0bG9zdC5hdWRpbykgLyBkZWx0YS5hdWRpbykgOiAwO1xuICAgICAgICAgICAgICAgIGxvc3MudmlkZW8gPSAoZGVsdGEudmlkZW8gPiAwKSA/IE1hdGguY2VpbCgxMDAgKiAobG9zdC52aWRlbyAtIGxhc3Rsb3N0LnZpZGVvKSAvIGRlbHRhLnZpZGVvKSA6IDA7XG4gICAgICAgICAgICAgICAgJChkb2N1bWVudCkudHJpZ2dlcigncGFja2V0bG9zcy5qaW5nbGUnLCBbc2VsZi5zaWQsIGxvc3NdKTtcbiAgICAgICAgICAgIH0pO1xuICAgICAgICB9XG4gICAgfSwgaW50ZXJ2YWwgfHwgMzAwMCk7XG4gICAgcmV0dXJuIHRoaXMuc3RhdHNpbnRlcnZhbDtcbn07XG5cbkppbmdsZVNlc3Npb25QQy5vbkppbmdsZUVycm9yID0gZnVuY3Rpb24gKHNlc3Npb24sIGVycm9yKVxue1xuICAgIGxvZ2dlci5lcnJvcihcIkppbmdsZSBlcnJvclwiLCBlcnJvcik7XG59XG5cbkppbmdsZVNlc3Npb25QQy5vbkppbmdsZUZhdGFsRXJyb3IgPSBmdW5jdGlvbiAoc2Vzc2lvbiwgZXJyb3IpXG57XG4gICAgdGhpcy5yb29tLmV2ZW50RW1pdHRlci5lbWl0KFhNUFBFdmVudHMuQ09ORkVSRU5DRV9TRVRVUF9GQUlMRUQpO1xuICAgIHRoaXMucm9vbS5ldmVudEVtaXR0ZXIuZW1pdChYTVBQRXZlbnRzLkpJTkdMRV9GQVRBTF9FUlJPUiwgc2Vzc2lvbiwgZXJyb3IpO1xufVxuXG5KaW5nbGVTZXNzaW9uUEMucHJvdG90eXBlLnNldExvY2FsRGVzY3JpcHRpb24gPSBmdW5jdGlvbiAoKSB7XG4gICAgdmFyIHNlbGYgPSB0aGlzO1xuICAgIHZhciBuZXdzc3JjcyA9IFtdO1xuICAgIGlmKCF0aGlzLnBlZXJjb25uZWN0aW9uLmxvY2FsRGVzY3JpcHRpb24pXG4gICAgICAgIHJldHVybjtcbiAgICB2YXIgc2Vzc2lvbiA9IHRyYW5zZm9ybS5wYXJzZSh0aGlzLnBlZXJjb25uZWN0aW9uLmxvY2FsRGVzY3JpcHRpb24uc2RwKTtcbiAgICB2YXIgaTtcbiAgICBzZXNzaW9uLm1lZGlhLmZvckVhY2goZnVuY3Rpb24gKG1lZGlhKSB7XG5cbiAgICAgICAgaWYgKG1lZGlhLnNzcmNzICYmIG1lZGlhLnNzcmNzLmxlbmd0aCA+IDApIHtcbiAgICAgICAgICAgIC8vIFRPRE8oZ3ApIG1heWJlIGV4Y2x1ZGUgRklEIHN0cmVhbXM/XG4gICAgICAgICAgICBtZWRpYS5zc3Jjcy5mb3JFYWNoKGZ1bmN0aW9uIChzc3JjKSB7XG4gICAgICAgICAgICAgICAgaWYgKHNzcmMuYXR0cmlidXRlICE9PSAnY25hbWUnKSB7XG4gICAgICAgICAgICAgICAgICAgIHJldHVybjtcbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgbmV3c3NyY3MucHVzaCh7XG4gICAgICAgICAgICAgICAgICAgICdzc3JjJzogc3NyYy5pZCxcbiAgICAgICAgICAgICAgICAgICAgJ3R5cGUnOiBtZWRpYS50eXBlXG4gICAgICAgICAgICAgICAgfSk7XG4gICAgICAgICAgICAgICAgLy8gRklYTUUgYWxsb3dzIGZvciBvbmx5IG9uZSBTU1JDIHBlciBtZWRpYSB0eXBlXG4gICAgICAgICAgICAgICAgc2VsZi5sb2NhbFN0cmVhbXNTU1JDW21lZGlhLnR5cGVdID0gc3NyYy5pZDtcbiAgICAgICAgICAgIH0pO1xuICAgICAgICB9XG5cbiAgICB9KTtcblxuICAgIGxvZ2dlci5sb2coJ25ldyBzc3JjcycsIG5ld3NzcmNzKTtcblxuICAgIC8vIEJpbmQgdXMgYXMgbG9jYWwgU1NSQ3Mgb3duZXJcbiAgICBpZiAobmV3c3NyY3MubGVuZ3RoID4gMCkge1xuICAgICAgICBmb3IgKGkgPSAwOyBpIDwgbmV3c3NyY3MubGVuZ3RoOyBpKyspIHtcbiAgICAgICAgICAgIHZhciBzc3JjID0gbmV3c3NyY3NbaV0uc3NyYztcbiAgICAgICAgICAgIHZhciBteUppZCA9IHNlbGYuY29ubmVjdGlvbi5lbXVjLm15cm9vbWppZDtcbiAgICAgICAgICAgIHNlbGYuc3NyY093bmVyc1tzc3JjXSA9IG15SmlkO1xuICAgICAgICB9XG4gICAgfVxufVxuXG4vLyBhbiBhdHRlbXB0IHRvIHdvcmsgYXJvdW5kIGh0dHBzOi8vZ2l0aHViLmNvbS9qaXRzaS9qaXRtZWV0L2lzc3Vlcy8zMlxuSmluZ2xlU2Vzc2lvblBDLnByb3RvdHlwZS5zZW5kS2V5ZnJhbWUgPSBmdW5jdGlvbiAoKSB7XG4gICAgdmFyIHBjID0gdGhpcy5wZWVyY29ubmVjdGlvbjtcbiAgICBsb2dnZXIubG9nKCdzZW5ka2V5ZnJhbWUnLCBwYy5pY2VDb25uZWN0aW9uU3RhdGUpO1xuICAgIGlmIChwYy5pY2VDb25uZWN0aW9uU3RhdGUgIT09ICdjb25uZWN0ZWQnKSByZXR1cm47IC8vIHNhZmUuLi5cbiAgICB2YXIgc2VsZiA9IHRoaXM7XG4gICAgcGMuc2V0UmVtb3RlRGVzY3JpcHRpb24oXG4gICAgICAgIHBjLnJlbW90ZURlc2NyaXB0aW9uLFxuICAgICAgICBmdW5jdGlvbiAoKSB7XG4gICAgICAgICAgICBwYy5jcmVhdGVBbnN3ZXIoXG4gICAgICAgICAgICAgICAgZnVuY3Rpb24gKG1vZGlmaWVkQW5zd2VyKSB7XG4gICAgICAgICAgICAgICAgICAgIHBjLnNldExvY2FsRGVzY3JpcHRpb24oXG4gICAgICAgICAgICAgICAgICAgICAgICBtb2RpZmllZEFuc3dlcixcbiAgICAgICAgICAgICAgICAgICAgICAgIGZ1bmN0aW9uICgpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAvLyBub29wXG4gICAgICAgICAgICAgICAgICAgICAgICB9LFxuICAgICAgICAgICAgICAgICAgICAgICAgZnVuY3Rpb24gKGVycm9yKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgbG9nZ2VyLmxvZygndHJpZ2dlcktleWZyYW1lIHNldExvY2FsRGVzY3JpcHRpb24gZmFpbGVkJywgZXJyb3IpO1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgIHNlbGYucm9vbS5ldmVudEVtaXR0ZXIuZW1pdChYTVBQRXZlbnRzLlNFVF9MT0NBTF9ERVNDUklQVElPTl9FUlJPUik7XG4gICAgICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgICAgICk7XG4gICAgICAgICAgICAgICAgfSxcbiAgICAgICAgICAgICAgICBmdW5jdGlvbiAoZXJyb3IpIHtcbiAgICAgICAgICAgICAgICAgICAgbG9nZ2VyLmxvZygndHJpZ2dlcktleWZyYW1lIGNyZWF0ZUFuc3dlciBmYWlsZWQnLCBlcnJvcik7XG4gICAgICAgICAgICAgICAgICAgIHNlbGYucm9vbS5ldmVudEVtaXR0ZXIuZW1pdChYTVBQRXZlbnRzLkNSRUFURV9BTlNXRVJfRVJST1IpO1xuICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICk7XG4gICAgICAgIH0sXG4gICAgICAgIGZ1bmN0aW9uIChlcnJvcikge1xuICAgICAgICAgICAgbG9nZ2VyLmxvZygndHJpZ2dlcktleWZyYW1lIHNldFJlbW90ZURlc2NyaXB0aW9uIGZhaWxlZCcsIGVycm9yKTtcbiAgICAgICAgICAgIGV2ZW50RW1pdHRlci5lbWl0KFhNUFBFdmVudHMuU0VUX1JFTU9URV9ERVNDUklQVElPTl9FUlJPUik7XG4gICAgICAgIH1cbiAgICApO1xufVxuXG5cbkppbmdsZVNlc3Npb25QQy5wcm90b3R5cGUucmVtb3RlU3RyZWFtQWRkZWQgPSBmdW5jdGlvbiAoZGF0YSwgdGltZXMpIHtcbiAgICB2YXIgc2VsZiA9IHRoaXM7XG4gICAgdmFyIHRoZXNzcmM7XG4gICAgdmFyIHN0cmVhbUlkID0gUlRDLmdldFN0cmVhbUlEKGRhdGEuc3RyZWFtKTtcblxuICAgIC8vIGxvb2sgdXAgYW4gYXNzb2NpYXRlZCBKSUQgZm9yIGEgc3RyZWFtIGlkXG4gICAgaWYgKCFzdHJlYW1JZCkge1xuICAgICAgICBsb2dnZXIuZXJyb3IoXCJObyBzdHJlYW0gSUQgZm9yXCIsIGRhdGEuc3RyZWFtKTtcbiAgICB9IGVsc2UgaWYgKHN0cmVhbUlkICYmIHN0cmVhbUlkLmluZGV4T2YoJ21peGVkbXNsYWJlbCcpID09PSAtMSkge1xuICAgICAgICAvLyBsb29rIG9ubHkgYXQgYT1zc3JjOiBhbmQgX25vdF8gYXQgYT1zc3JjLWdyb3VwOiBsaW5lc1xuXG4gICAgICAgIHZhciBzc3JjbGluZXMgPSB0aGlzLnBlZXJjb25uZWN0aW9uLnJlbW90ZURlc2NyaXB0aW9uP1xuICAgICAgICAgICAgU0RQVXRpbC5maW5kX2xpbmVzKHRoaXMucGVlcmNvbm5lY3Rpb24ucmVtb3RlRGVzY3JpcHRpb24uc2RwLCAnYT1zc3JjOicpIDogW107XG4gICAgICAgIHNzcmNsaW5lcyA9IHNzcmNsaW5lcy5maWx0ZXIoZnVuY3Rpb24gKGxpbmUpIHtcbiAgICAgICAgICAgIC8vIE5PVEUoZ3ApIHByZXZpb3VzbHkgd2UgZmlsdGVyZWQgb24gdGhlIG1zbGFiZWwsIGJ1dCB0aGF0IHByb3BlcnR5XG4gICAgICAgICAgICAvLyBpcyBub3QgYWx3YXlzIHByZXNlbnQuXG4gICAgICAgICAgICAvLyByZXR1cm4gbGluZS5pbmRleE9mKCdtc2xhYmVsOicgKyBkYXRhLnN0cmVhbS5sYWJlbCkgIT09IC0xO1xuXG4gICAgICAgICAgICBpZiAoUlRDQnJvd3NlclR5cGUuaXNUZW1hc3lzUGx1Z2luVXNlZCgpKSB7XG4gICAgICAgICAgICAgICAgcmV0dXJuICgobGluZS5pbmRleE9mKCdtc2xhYmVsOicgKyBzdHJlYW1JZCkgIT09IC0xKSk7XG4gICAgICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgICAgIHJldHVybiAoKGxpbmUuaW5kZXhPZignbXNpZDonICsgc3RyZWFtSWQpICE9PSAtMSkpO1xuICAgICAgICAgICAgfVxuICAgICAgICB9KTtcbiAgICAgICAgaWYgKHNzcmNsaW5lcy5sZW5ndGgpIHtcbiAgICAgICAgICAgIHRoZXNzcmMgPSBzc3JjbGluZXNbMF0uc3Vic3RyaW5nKDcpLnNwbGl0KCcgJylbMF07XG5cbiAgICAgICAgICAgIGlmICghc2VsZi5zc3JjT3duZXJzW3RoZXNzcmNdKSB7XG4gICAgICAgICAgICAgICAgbG9nZ2VyLmVycm9yKFwiTm8gU1NSQyBvd25lciBrbm93biBmb3I6IFwiICsgdGhlc3NyYyk7XG4gICAgICAgICAgICAgICAgcmV0dXJuO1xuICAgICAgICAgICAgfVxuICAgICAgICAgICAgZGF0YS5wZWVyamlkID0gc2VsZi5zc3JjT3duZXJzW3RoZXNzcmNdO1xuICAgICAgICAgICAgbG9nZ2VyLmxvZygnYXNzb2NpYXRlZCBqaWQnLCBzZWxmLnNzcmNPd25lcnNbdGhlc3NyY10pO1xuICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgbG9nZ2VyLmVycm9yKFwiTm8gU1NSQyBsaW5lcyBmb3IgXCIsIHN0cmVhbUlkKTtcbiAgICAgICAgfVxuICAgIH1cblxuICAgIHRoaXMucm9vbS5yZW1vdGVTdHJlYW1BZGRlZChkYXRhLCB0aGlzLnNpZCwgdGhlc3NyYyk7XG5cbiAgICB2YXIgaXNWaWRlbyA9IGRhdGEuc3RyZWFtLmdldFZpZGVvVHJhY2tzKCkubGVuZ3RoID4gMDtcbiAgICAvLyBhbiBhdHRlbXB0IHRvIHdvcmsgYXJvdW5kIGh0dHBzOi8vZ2l0aHViLmNvbS9qaXRzaS9qaXRtZWV0L2lzc3Vlcy8zMlxuICAgIGlmIChpc1ZpZGVvICYmXG4gICAgICAgIGRhdGEucGVlcmppZCAmJiB0aGlzLnBlZXJqaWQgPT09IGRhdGEucGVlcmppZCAmJlxuICAgICAgICBkYXRhLnN0cmVhbS5nZXRWaWRlb1RyYWNrcygpLmxlbmd0aCA9PT0gMCAmJlxuICAgICAgICBSVEMubG9jYWxWaWRlby5nZXRUcmFja3MoKS5sZW5ndGggPiAwKSB7XG4gICAgICAgIHdpbmRvdy5zZXRUaW1lb3V0KGZ1bmN0aW9uICgpIHtcbiAgICAgICAgICAgIHNlbGYuc2VuZEtleWZyYW1lKCk7XG4gICAgICAgIH0sIDMwMDApO1xuICAgIH1cbn1cblxuLyoqXG4gKiBSZXR1cm5zIHRoZSBpY2UgY29ubmVjdGlvbiBzdGF0ZSBmb3IgdGhlIHBlZXIgY29ubmVjdGlvbi5cbiAqIEByZXR1cm5zIHRoZSBpY2UgY29ubmVjdGlvbiBzdGF0ZSBmb3IgdGhlIHBlZXIgY29ubmVjdGlvbi5cbiAqL1xuSmluZ2xlU2Vzc2lvblBDLnByb3RvdHlwZS5nZXRJY2VDb25uZWN0aW9uU3RhdGUgPSBmdW5jdGlvbiAoKSB7XG4gICAgcmV0dXJuIHRoaXMucGVlcmNvbm5lY3Rpb24uaWNlQ29ubmVjdGlvblN0YXRlO1xufVxuXG5tb2R1bGUuZXhwb3J0cyA9IEppbmdsZVNlc3Npb25QQztcbiIsIi8qIGdsb2JhbCAkICovXG52YXIgbG9nZ2VyID0gcmVxdWlyZShcImppdHNpLW1lZXQtbG9nZ2VyXCIpLmdldExvZ2dlcihfX2ZpbGVuYW1lKTtcblxuXG4vKlxuIEhlcmUgd2UgZG8gbW9kaWZpY2F0aW9ucyBvZiBsb2NhbCB2aWRlbyBTU1JDcy4gVGhlcmUgYXJlIDIgc2l0dWF0aW9ucyB3ZSBoYXZlXG4gdG8gaGFuZGxlOlxuXG4gMS4gV2UgZ2VuZXJhdGUgU1NSQyBmb3IgbG9jYWwgcmVjdm9ubHkgdmlkZW8gc3RyZWFtLiBUaGlzIGlzIHRoZSBjYXNlIHdoZW4gd2VcbiAgICBoYXZlIG5vIGxvY2FsIGNhbWVyYSBhbmQgaXQgaXMgbm90IGdlbmVyYXRlZCBhdXRvbWF0aWNhbGx5LCBidXQgU1NSQz0xIGlzXG4gICAgdXNlZCBpbXBsaWNpdGx5LiBJZiB0aGF0IGhhcHBlbnMgUlRDUCBwYWNrZXRzIHdpbGwgYmUgZHJvcHBlZCBieSB0aGUgSlZCXG4gICAgYW5kIHdlIHdvbid0IGJlIGFibGUgdG8gcmVxdWVzdCB2aWRlbyBrZXkgZnJhbWVzIGNvcnJlY3RseS5cblxuIDIuIEEgaGFjayB0byByZS11c2UgU1NSQyBvZiB0aGUgZmlyc3QgdmlkZW8gc3RyZWFtIGZvciBhbnkgbmV3IHN0cmVhbSBjcmVhdGVkXG4gICAgaW4gZnV0dXJlLiBJdCB0dXJuZWQgb3V0IHRoYXQgQ2hyb21lIG1heSBrZWVwIG9uIHVzaW5nIHRoZSBTU1JDIG9mIHJlbW92ZWRcbiAgICB2aWRlbyBzdHJlYW0gaW4gUlRDUCBldmVuIHRob3VnaCBhIG5ldyBvbmUgaGFzIGJlZW4gY3JlYXRlZC4gU28gd2UganVzdFxuICAgIHdhbnQgdG8gYXZvaWQgdGhhdCBieSByZS11c2luZyBpdC4gSmluZ2xlICdzb3VyY2UtcmVtb3ZlJy8nc291cmNlLWFkZCdcbiAgICBub3RpZmljYXRpb25zIGFyZSBibG9ja2VkIG9uY2UgZmlyc3QgdmlkZW8gU1NSQyBpcyBhZHZlcnRpc2VkIHRvIHRoZSBmb2N1cy5cblxuIFdoYXQgdGhpcyBoYWNrIGRvZXM6XG5cbiAxLiBTdG9yZXMgdGhlIFNTUkMgb2YgdGhlIGZpcnN0IHZpZGVvIHN0cmVhbSBjcmVhdGVkIGJ5XG4gICBhKSBzY2FubmluZyBKaW5nbGUgc2Vzc2lvbi1hY2NlcHQvc2Vzc2lvbi1pbnZpdGUgZm9yIGV4aXN0aW5nIHZpZGVvIFNTUkNcbiAgIGIpIHdhdGNoaW5nIGZvciAnc291cmNlLWFkZCcgZm9yIG5ldyB2aWRlbyBzdHJlYW0gaWYgaXQgaGFzIG5vdCBiZWVuXG4gICAgICBjcmVhdGVkIGluIHN0ZXAgYSlcbiAyLiBFeHBvc2VzIG1ldGhvZCAnbXVuZ2VMb2NhbFZpZGVvU1NSQycgd2hpY2ggcmVwbGFjZXMgYW55IG5ldyB2aWRlbyBTU1JDIHdpdGhcbiAgICB0aGUgc3RvcmVkIG9uZS4gSXQgaXMgY2FsbGVkIGJ5ICdUcmFjYWJsZVBlZXJDb25uZWN0aW9uJyBiZWZvcmUgbG9jYWwgU0RQIGlzXG4gICAgcmV0dXJuZWQgdG8gdGhlIG90aGVyIHBhcnRzIG9mIHRoZSBhcHBsaWNhdGlvbi5cbiAzLiBTY2FucyAnc291cmNlLXJlbW92ZScvJ3NvdXJjZS1hZGQnIG5vdGlmaWNhdGlvbnMgZm9yIHN0b3JlZCB2aWRlbyBTU1JDIGFuZFxuICAgIGJsb2NrcyB0aG9zZSBub3RpZmljYXRpb25zLiBUaGlzIG1ha2VzIEppY29mbyBhbmQgYWxsIHBhcnRpY2lwYW50cyB0aGlua1xuICAgIHRoYXQgaXQgZXhpc3RzIGFsbCB0aGUgdGltZSBldmVuIGlmIHRoZSB2aWRlbyBzdHJlYW0gaGFzIGJlZW4gcmVtb3ZlZCBvclxuICAgIHJlcGxhY2VkIGxvY2FsbHkuIFRoYW5rcyB0byB0aGF0IHRoZXJlIGlzIG5vIGFkZGl0aW9uYWwgc2lnbmFsaW5nIGFjdGl2aXR5XG4gICAgb24gdmlkZW8gbXV0ZSBvciB3aGVuIHN3aXRjaGluZyB0byB0aGUgZGVza3RvcCBzdHJlYW0uXG4gKi9cblxudmFyIFNEUCA9IHJlcXVpcmUoJy4vU0RQJyk7XG52YXIgUmFuZG9tVXRpbCA9IHJlcXVpcmUoJy4uL3V0aWwvUmFuZG9tVXRpbCcpO1xudmFyIFJUQ0Jyb3dzZXJUeXBlID0gcmVxdWlyZSgnLi4vUlRDL1JUQ0Jyb3dzZXJUeXBlJyk7XG5cbi8qKlxuICogVGhlIGhhY2sgaXMgZW5hYmxlZCBvbiBhbGwgYnJvd3NlcnMgZXhjZXB0IEZGIGJ5IGRlZmF1bHRcbiAqIEZJWE1FIGZpbmlzaCB0aGUgaGFjayBvbmNlIHJlbW92ZVN0cmVhbSBtZXRob2QgaXMgaW1wbGVtZW50ZWQgaW4gRkZcbiAqIEB0eXBlIHtib29sZWFufVxuICovXG52YXIgaXNFbmFibGVkID0gIVJUQ0Jyb3dzZXJUeXBlLmlzRmlyZWZveCgpO1xuXG5cbi8qKlxuICogU3RvcmVkIFNTUkMgb2YgbG9jYWwgdmlkZW8gc3RyZWFtLlxuICovXG52YXIgbG9jYWxWaWRlb1NTUkM7XG5cbi8qKlxuICogU1NSQyB1c2VkIGZvciByZWN2b25seSB2aWRlbyBzdHJlYW0gd2hlbiB3ZSBoYXZlIG5vIGxvY2FsIGNhbWVyYS5cbiAqIFRoaXMgaXMgaW4gb3JkZXIgdG8gdGVsbCBDaHJvbWUgd2hhdCBTU1JDIHNob3VsZCBiZSB1c2VkIGluIFJUQ1AgcmVxdWVzdHNcbiAqIGluc3RlYWQgb2YgMS5cbiAqL1xudmFyIGxvY2FsUmVjdk9ubHlTU1JDLCBsb2NhbFJlY3ZPbmx5TVNJRCwgbG9jYWxSZWN2T25seU1TTGFiZWwsIGxvY2FsUmVjdk9ubHlMYWJlbDtcblxuLyoqXG4gKiBjbmFtZSBmb3IgPHR0PmxvY2FsUmVjdk9ubHlTU1JDPC90dD5cbiAqL1xudmFyIGxvY2FsUmVjdk9ubHlDTmFtZTtcblxuLyoqXG4gKiBNZXRob2QgcmVtb3ZlcyA8c291cmNlPiBlbGVtZW50IHdoaWNoIGRlc2NyaWJlcyA8dHQ+bG9jYWxWaWRlb1NTUkM8L3R0PlxuICogZnJvbSBnaXZlbiBKaW5nbGUgSVEuXG4gKiBAcGFyYW0gbW9kaWZ5SXEgJ3NvdXJjZS1hZGQnIG9yICdzb3VyY2UtcmVtb3ZlJyBKaW5nbGUgSVEuXG4gKiBAcGFyYW0gYWN0aW9uTmFtZSBkaXNwbGF5IG5hbWUgb2YgdGhlIGFjdGlvbiB3aGljaCB3aWxsIGJlIHByaW50ZWQgaW4gbG9nXG4gKiAgICAgICAgbWVzc2FnZXMuXG4gKiBAcmV0dXJucyB7Kn0gbW9kaWZpZWQgSmluZ2xlIElRLCBzbyB0aGF0IGl0IGRvZXMgbm90IGNvbnRhaW4gPHNvdXJjZT4gZWxlbWVudFxuICogICAgICAgICAgY29ycmVzcG9uZGluZyB0byA8dHQ+bG9jYWxWaWRlb1NTUkM8L3R0PiBvciA8dHQ+bnVsbDwvdHQ+IGlmIG5vXG4gKiAgICAgICAgICBvdGhlciBTU1JDcyBsZWZ0IHRvIGJlIHNpZ25hbGVkIGFmdGVyIHJlbW92aW5nIGl0LlxuICovXG52YXIgZmlsdGVyT3V0U291cmNlID0gZnVuY3Rpb24gKG1vZGlmeUlxLCBhY3Rpb25OYW1lKSB7XG4gICAgdmFyIG1vZGlmeUlxVHJlZSA9ICQobW9kaWZ5SXEudHJlZSgpKTtcblxuICAgIGlmICghbG9jYWxWaWRlb1NTUkMpXG4gICAgICAgIHJldHVybiBtb2RpZnlJcVRyZWVbMF07XG5cbiAgICB2YXIgdmlkZW9TU1JDID0gbW9kaWZ5SXFUcmVlLmZpbmQoXG4gICAgICAgICc+amluZ2xlPmNvbnRlbnRbbmFtZT1cInZpZGVvXCJdJyArXG4gICAgICAgICc+ZGVzY3JpcHRpb24+c291cmNlW3NzcmM9XCInICsgbG9jYWxWaWRlb1NTUkMgKyAnXCJdJyk7XG5cbiAgICBpZiAoIXZpZGVvU1NSQy5sZW5ndGgpIHtcbiAgICAgICAgcmV0dXJuIG1vZGlmeUlxVHJlZVswXTtcbiAgICB9XG5cbiAgICBsb2dnZXIuaW5mbyhcbiAgICAgICAgJ0Jsb2NraW5nICcgKyBhY3Rpb25OYW1lICsgJyBmb3IgbG9jYWwgdmlkZW8gU1NSQzogJyArIGxvY2FsVmlkZW9TU1JDKTtcblxuICAgIHZpZGVvU1NSQy5yZW1vdmUoKTtcblxuICAgIC8vIENoZWNrIGlmIGFueSBzb3VyY2VzIHN0aWxsIGxlZnQgdG8gYmUgYWRkZWQvcmVtb3ZlZFxuICAgIGlmIChtb2RpZnlJcVRyZWUuZmluZCgnPmppbmdsZT5jb250ZW50PmRlc2NyaXB0aW9uPnNvdXJjZScpLmxlbmd0aCkge1xuICAgICAgICByZXR1cm4gbW9kaWZ5SXFUcmVlWzBdO1xuICAgIH0gZWxzZSB7XG4gICAgICAgIHJldHVybiBudWxsO1xuICAgIH1cbn07XG5cbi8qKlxuICogU2NhbnMgZ2l2ZW4gSmluZ2xlIElRIGZvciB2aWRlbyBTU1JDIGFuZCBzdG9yZXMgaXQuXG4gKiBAcGFyYW0gamluZ2xlSXEgdGhlIEppbmdsZSBJUSB0byBiZSBzY2FubmVkIGZvciB2aWRlbyBTU1JDLlxuICovXG52YXIgc3RvcmVMb2NhbFZpZGVvU1NSQyA9IGZ1bmN0aW9uIChqaW5nbGVJcSkge1xuICAgIHZhciB2aWRlb1NTUkNzID1cbiAgICAgICAgJChqaW5nbGVJcS50cmVlKCkpXG4gICAgICAgICAgICAuZmluZCgnPmppbmdsZT5jb250ZW50W25hbWU9XCJ2aWRlb1wiXT5kZXNjcmlwdGlvbj5zb3VyY2UnKTtcblxuICAgIHZpZGVvU1NSQ3MuZWFjaChmdW5jdGlvbiAoaWR4LCBzc3JjRWxlbSkge1xuICAgICAgICBpZiAobG9jYWxWaWRlb1NTUkMpXG4gICAgICAgICAgICByZXR1cm47XG4gICAgICAgIC8vIFdlIGNvbnNpZGVyIFNTUkMgcmVhbCBvbmx5IGlmIGl0IGhhcyBtc2lkIGF0dHJpYnV0ZVxuICAgICAgICAvLyByZWN2b25seSBzdHJlYW1zIGluIEZGIGRvIG5vdCBoYXZlIGl0IGFzIHdlbGwgYXMgbG9jYWwgU1NSQ3NcbiAgICAgICAgLy8gd2UgZ2VuZXJhdGUgZm9yIHJlY3Zvbmx5IHN0cmVhbXMgaW4gQ2hyb21lXG4gICAgICAgIHZhciBzc3JTZWwgPSAkKHNzcmNFbGVtKTtcbiAgICAgICAgdmFyIG1zaWQgPSBzc3JTZWwuZmluZCgnPnBhcmFtZXRlcltuYW1lPVwibXNpZFwiXScpO1xuICAgICAgICBpZiAobXNpZC5sZW5ndGgpIHtcbiAgICAgICAgICAgIHZhciBzc3JjVmFsID0gc3NyU2VsLmF0dHIoJ3NzcmMnKTtcbiAgICAgICAgICAgIGlmIChzc3JjVmFsKSB7XG4gICAgICAgICAgICAgICAgbG9jYWxWaWRlb1NTUkMgPSBzc3JjVmFsO1xuICAgICAgICAgICAgICAgIGxvZ2dlci5pbmZvKCdTdG9yZWQgbG9jYWwgdmlkZW8gU1NSQycgK1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAnIGZvciBmdXR1cmUgcmUtdXNlOiAnICsgbG9jYWxWaWRlb1NTUkMpO1xuICAgICAgICAgICAgfVxuICAgICAgICB9XG4gICAgfSk7XG59O1xuXG4vKipcbiAqIEdlbmVyYXRlcyBuZXcgbGFiZWwvbXNsYWJlbCBhdHRyaWJ1dGVcbiAqIEByZXR1cm5zIHtzdHJpbmd9IGxhYmVsL21zbGFiZWwgYXR0cmlidXRlXG4gKi9cbmZ1bmN0aW9uIGdlbmVyYXRlTGFiZWwoKSB7XG4gICAgcmV0dXJuIFJhbmRvbVV0aWwucmFuZG9tSGV4U3RyaW5nKDgpICsgXCItXCIgKyBSYW5kb21VdGlsLnJhbmRvbUhleFN0cmluZyg0KSArXG4gICAgICAgIFwiLVwiICsgUmFuZG9tVXRpbC5yYW5kb21IZXhTdHJpbmcoNCkgKyBcIi1cIiArXG4gICAgICAgIFJhbmRvbVV0aWwucmFuZG9tSGV4U3RyaW5nKDQpICsgXCItXCIgKyBSYW5kb21VdGlsLnJhbmRvbUhleFN0cmluZygxMik7XG59XG5cbi8qKlxuICogR2VuZXJhdGVzIG5ldyBTU1JDIGZvciBsb2NhbCB2aWRlbyByZWN2b25seSBzdHJlYW0uXG4gKiBGSVhNRSB3aGF0IGFib3V0IGV2ZW50dWFsIFNTUkMgY29sbGlzaW9uID9cbiAqL1xuZnVuY3Rpb24gZ2VuZXJhdGVSZWN2b25seVNTUkMoKSB7XG5cbiAgICBsb2NhbFZpZGVvU1NSQyA9IGxvY2FsUmVjdk9ubHlTU1JDID1cbiAgICAgICAgbG9jYWxWaWRlb1NTUkMgP1xuICAgICAgICAgICAgbG9jYWxWaWRlb1NTUkMgOiBNYXRoLnJhbmRvbSgpLnRvU3RyaW5nKDEwKS5zdWJzdHJpbmcoMiwgMTEpO1xuXG4gICAgbG9jYWxSZWN2T25seUNOYW1lID1cbiAgICAgICAgTWF0aC5yYW5kb20oKS50b1N0cmluZygzNikuc3Vic3RyaW5nKDIpO1xuXG4gICAgbG9jYWxSZWN2T25seU1TTGFiZWwgPSBnZW5lcmF0ZUxhYmVsKCk7XG4gICAgbG9jYWxSZWN2T25seUxhYmVsID0gZ2VuZXJhdGVMYWJlbCgpO1xuICAgIGxvY2FsUmVjdk9ubHlNU0lEID0gbG9jYWxSZWN2T25seU1TTGFiZWwgKyBcIiBcIiArIGxvY2FsUmVjdk9ubHlMYWJlbDtcblxuICAgIGxvZ2dlci5pbmZvKFxuICAgICAgICBcIkdlbmVyYXRlZCBsb2NhbCByZWN2b25seSBTU1JDOiBcIiArIGxvY2FsUmVjdk9ubHlTU1JDICtcbiAgICAgICAgXCIsIGNuYW1lOiBcIiArIGxvY2FsUmVjdk9ubHlDTmFtZSk7XG59XG5cbnZhciBMb2NhbFNTUkNSZXBsYWNlbWVudCA9IHtcbiAgICAvKipcbiAgICAgKiBNZXRob2QgbXVzdCBiZSBjYWxsZWQgYmVmb3JlICdzZXNzaW9uLWluaXRpYXRlJyBvciAnc2Vzc2lvbi1pbnZpdGUnIGlzXG4gICAgICogc2VudC4gU2NhbnMgdGhlIElRIGZvciBsb2NhbCB2aWRlbyBTU1JDIGFuZCBzdG9yZXMgaXQgaWYgZGV0ZWN0ZWQuXG4gICAgICpcbiAgICAgKiBAcGFyYW0gc2Vzc2lvbkluaXQgb3VyICdzZXNzaW9uLWluaXRpYXRlJyBvciAnc2Vzc2lvbi1hY2NlcHQnIEppbmdsZSBJUVxuICAgICAqICAgICAgICB3aGljaCB3aWxsIGJlIHNjYW5uZWQgZm9yIGxvY2FsIHZpZGVvIFNTUkMuXG4gICAgICovXG4gICAgcHJvY2Vzc1Nlc3Npb25Jbml0OiBmdW5jdGlvbiAoc2Vzc2lvbkluaXQpIHtcbiAgICAgICAgaWYgKCFpc0VuYWJsZWQpXG4gICAgICAgICAgICByZXR1cm47XG5cbiAgICAgICAgaWYgKGxvY2FsVmlkZW9TU1JDKSB7XG4gICAgICAgICAgICBsb2dnZXIuZXJyb3IoXCJMb2NhbCBTU1JDIHN0b3JlZCBhbHJlYWR5OiBcIiArIGxvY2FsVmlkZW9TU1JDKTtcbiAgICAgICAgICAgIHJldHVybjtcbiAgICAgICAgfVxuICAgICAgICBzdG9yZUxvY2FsVmlkZW9TU1JDKHNlc3Npb25Jbml0KTtcbiAgICB9LFxuICAgIC8qKlxuICAgICAqIElmIHdlIGhhdmUgbG9jYWwgdmlkZW8gU1NSQyBzdG9yZWQgc2VhcmNoZWQgZ2l2ZW5cbiAgICAgKiA8dHQ+bG9jYWxEZXNjcmlwdGlvbjwvdHQ+IGZvciB2aWRlbyBTU1JDIGFuZCBtYWtlcyBzdXJlIGl0IGlzIHJlcGxhY2VkXG4gICAgICogd2l0aCB0aGUgc3RvcmVkIG9uZS5cbiAgICAgKiBAcGFyYW0gbG9jYWxEZXNjcmlwdGlvbiBsb2NhbCBkZXNjcmlwdGlvbiBvYmplY3QgdGhhdCB3aWxsIGhhdmUgbG9jYWxcbiAgICAgKiAgICAgICAgdmlkZW8gU1NSQyByZXBsYWNlZCB3aXRoIHRoZSBzdG9yZWQgb25lXG4gICAgICogQHJldHVybnMgbW9kaWZpZWQgPHR0PmxvY2FsRGVzY3JpcHRpb248L3R0PiBvYmplY3QuXG4gICAgICovXG4gICAgbXVuZ2VMb2NhbFZpZGVvU1NSQzogZnVuY3Rpb24gKGxvY2FsRGVzY3JpcHRpb24pIHtcbiAgICAgICAgaWYgKCFpc0VuYWJsZWQpXG4gICAgICAgICAgICByZXR1cm4gbG9jYWxEZXNjcmlwdGlvbjtcblxuICAgICAgICBpZiAoIWxvY2FsRGVzY3JpcHRpb24pIHtcbiAgICAgICAgICAgIGxvZ2dlci53YXJuKFwibG9jYWxEZXNjcmlwdGlvbiBpcyBudWxsIG9yIHVuZGVmaW5lZFwiKTtcbiAgICAgICAgICAgIHJldHVybiBsb2NhbERlc2NyaXB0aW9uO1xuICAgICAgICB9XG5cbiAgICAgICAgLy8gSUYgd2UgaGF2ZSBsb2NhbCB2aWRlbyBTU1JDIHN0b3JlZCBtYWtlIHN1cmUgaXQgaXMgcmVwbGFjZWRcbiAgICAgICAgLy8gd2l0aCBvbGQgU1NSQ1xuICAgICAgICB2YXIgc2RwID0gbmV3IFNEUChsb2NhbERlc2NyaXB0aW9uLnNkcCk7XG4gICAgICAgIGlmIChzZHAubWVkaWEubGVuZ3RoIDwgMilcbiAgICAgICAgICAgIHJldHVybjtcblxuICAgICAgICBpZiAobG9jYWxWaWRlb1NTUkMgJiYgc2RwLm1lZGlhWzFdLmluZGV4T2YoXCJhPXNzcmM6XCIpICE9PSAtMSAmJlxuICAgICAgICAgICAgIXNkcC5jb250YWluc1NTUkMobG9jYWxWaWRlb1NTUkMpKSB7XG4gICAgICAgICAgICAvLyBHZXQgbmV3IHZpZGVvIFNTUkNcbiAgICAgICAgICAgIHZhciBtYXAgPSBzZHAuZ2V0TWVkaWFTc3JjTWFwKCk7XG4gICAgICAgICAgICB2YXIgdmlkZW9QYXJ0ID0gbWFwWzFdO1xuICAgICAgICAgICAgdmFyIHZpZGVvU1NSQ3MgPSB2aWRlb1BhcnQuc3NyY3M7XG4gICAgICAgICAgICB2YXIgbmV3U1NSQyA9IE9iamVjdC5rZXlzKHZpZGVvU1NSQ3MpWzBdO1xuXG4gICAgICAgICAgICBsb2dnZXIuaW5mbyhcbiAgICAgICAgICAgICAgICBcIlJlcGxhY2luZyBuZXcgdmlkZW8gU1NSQzogXCIgKyBuZXdTU1JDICtcbiAgICAgICAgICAgICAgICBcIiB3aXRoIFwiICsgbG9jYWxWaWRlb1NTUkMpO1xuXG4gICAgICAgICAgICBsb2NhbERlc2NyaXB0aW9uLnNkcCA9XG4gICAgICAgICAgICAgICAgc2RwLnJhdy5yZXBsYWNlKFxuICAgICAgICAgICAgICAgICAgICBuZXcgUmVnRXhwKCdhPXNzcmM6JyArIG5ld1NTUkMsICdnJyksXG4gICAgICAgICAgICAgICAgICAgICdhPXNzcmM6JyArIGxvY2FsVmlkZW9TU1JDKTtcbiAgICAgICAgfVxuICAgICAgICBlbHNlIGlmIChzZHAubWVkaWFbMV0uaW5kZXhPZignYT1zc3JjOicpID09PSAtMSAmJlxuICAgICAgICAgICAgICAgICBzZHAubWVkaWFbMV0uaW5kZXhPZignYT1yZWN2b25seScpICE9PSAtMSkge1xuICAgICAgICAgICAgLy8gTWFrZSBzdXJlIHdlIGhhdmUgYW55IFNTUkMgZm9yIHJlY3Zvbmx5IHZpZGVvIHN0cmVhbVxuICAgICAgICAgICAgaWYgKCFsb2NhbFJlY3ZPbmx5U1NSQykge1xuICAgICAgICAgICAgICAgIGdlbmVyYXRlUmVjdm9ubHlTU1JDKCk7XG4gICAgICAgICAgICB9XG5cbiAgICAgICAgICAgIGxvZ2dlci5pbmZvKCdObyBTU1JDIGluIHZpZGVvIHJlY3Zvbmx5IHN0cmVhbScgK1xuICAgICAgICAgICAgICAgICAgICAgICAgICcgLSBhZGRpbmcgU1NSQzogJyArIGxvY2FsUmVjdk9ubHlTU1JDKTtcblxuICAgICAgICAgICAgc2RwLm1lZGlhWzFdICs9ICdhPXNzcmM6JyArIGxvY2FsUmVjdk9ubHlTU1JDICtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAnIGNuYW1lOicgKyBsb2NhbFJlY3ZPbmx5Q05hbWUgKyAnXFxyXFxuJyArXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgJ2E9c3NyYzonICsgbG9jYWxSZWN2T25seVNTUkMgK1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgICcgbXNpZDonICsgbG9jYWxSZWN2T25seU1TSUQgKyAnXFxyXFxuJyArXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgJ2E9c3NyYzonICsgbG9jYWxSZWN2T25seVNTUkMgK1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgICcgbXNsYWJlbDonICsgbG9jYWxSZWN2T25seU1TTGFiZWwgKyAnXFxyXFxuJyArXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgJ2E9c3NyYzonICsgbG9jYWxSZWN2T25seVNTUkMgK1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgICcgbGFiZWw6JyArIGxvY2FsUmVjdk9ubHlMYWJlbCArICdcXHJcXG4nO1xuXG4gICAgICAgICAgICBsb2NhbERlc2NyaXB0aW9uLnNkcCA9IHNkcC5zZXNzaW9uICsgc2RwLm1lZGlhLmpvaW4oJycpO1xuICAgICAgICB9XG4gICAgICAgIHJldHVybiBsb2NhbERlc2NyaXB0aW9uO1xuICAgIH0sXG4gICAgLyoqXG4gICAgICogTWV0aG9kIG11c3QgYmUgY2FsbGVkIGJlZm9yZSAnc291cmNlLWFkZCcgbm90aWZpY2F0aW9uIGlzIHNlbnQuIEluIGNhc2VcbiAgICAgKiB3ZSBoYXZlIGxvY2FsIHZpZGVvIFNTUkMgYWR2ZXJ0aXNlZCBhbHJlYWR5IGl0IHdpbGwgYmUgcmVtb3ZlZCBmcm9tIHRoZVxuICAgICAqIG5vdGlmaWNhdGlvbi4gSWYgbm8gb3RoZXIgU1NSQ3MgYXJlIGRlc2NyaWJlZCBieSBnaXZlbiBJUSBudWxsIHdpbGwgYmVcbiAgICAgKiByZXR1cm5lZCB3aGljaCBtZWFucyB0aGF0IHRoZXJlIGlzIG5vIHBvaW50IGluIHNlbmRpbmcgdGhlIG5vdGlmaWNhdGlvbi5cbiAgICAgKiBAcGFyYW0gc291cmNlQWRkICdzb3VyY2UtYWRkJyBKaW5nbGUgSVEgdG8gYmUgcHJvY2Vzc2VkXG4gICAgICogQHJldHVybnMgbW9kaWZpZWQgJ3NvdXJjZS1hZGQnIElRIHdoaWNoIGNhbiBiZSBzZW50IHRvIHRoZSBmb2N1cyBvclxuICAgICAqICAgICAgICAgIDx0dD5udWxsPC90dD4gaWYgbm8gbm90aWZpY2F0aW9uIHNoYWxsIGJlIHNlbnQuIEl0IGlzIG5vIGxvbmdlclxuICAgICAqICAgICAgICAgIGEgU3Ryb3BoZSBJUSBCdWlsZGVyIGluc3RhbmNlLCBidXQgRE9NIGVsZW1lbnQgdHJlZS5cbiAgICAgKi9cbiAgICBwcm9jZXNzU291cmNlQWRkOiBmdW5jdGlvbiAoc291cmNlQWRkKSB7XG4gICAgICAgIGlmICghaXNFbmFibGVkKVxuICAgICAgICAgICAgcmV0dXJuIHNvdXJjZUFkZDtcblxuICAgICAgICBpZiAoIWxvY2FsVmlkZW9TU1JDKSB7XG4gICAgICAgICAgICAvLyBTdG9yZSBsb2NhbCBTU1JDIGlmIGF2YWlsYWJsZVxuICAgICAgICAgICAgc3RvcmVMb2NhbFZpZGVvU1NSQyhzb3VyY2VBZGQpO1xuICAgICAgICAgICAgcmV0dXJuIHNvdXJjZUFkZDtcbiAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgIHJldHVybiBmaWx0ZXJPdXRTb3VyY2Uoc291cmNlQWRkLCAnc291cmNlLWFkZCcpO1xuICAgICAgICB9XG4gICAgfSxcbiAgICAvKipcbiAgICAgKiBNZXRob2QgbXVzdCBiZSBjYWxsZWQgYmVmb3JlICdzb3VyY2UtcmVtb3ZlJyBub3RpZmljYXRpb24gaXMgc2VudC5cbiAgICAgKiBSZW1vdmVzIGxvY2FsIHZpZGVvIFNTUkMgZnJvbSB0aGUgbm90aWZpY2F0aW9uLiBJZiB0aGVyZSBhcmUgbm8gb3RoZXJcbiAgICAgKiBTU1JDcyBkZXNjcmliZWQgaW4gdGhlIGdpdmVuIElRIDx0dD5udWxsPC90dD4gd2lsbCBiZSByZXR1cm5lZCB3aGljaFxuICAgICAqIG1lYW5zIHRoYXQgdGhlcmUgaXMgbm8gcG9pbnQgaW4gc2VuZGluZyB0aGUgbm90aWZpY2F0aW9uLlxuICAgICAqIEBwYXJhbSBzb3VyY2VSZW1vdmUgJ3NvdXJjZS1yZW1vdmUnIEppbmdsZSBJUSB0byBiZSBwcm9jZXNzZWRcbiAgICAgKiBAcmV0dXJucyBtb2RpZmllZCAnc291cmNlLXJlbW92ZScgSVEgd2hpY2ggY2FuIGJlIHNlbnQgdG8gdGhlIGZvY3VzIG9yXG4gICAgICogICAgICAgICAgPHR0Pm51bGw8L3R0PiBpZiBubyBub3RpZmljYXRpb24gc2hhbGwgYmUgc2VudC4gSXQgaXMgbm8gbG9uZ2VyXG4gICAgICogICAgICAgICAgYSBTdHJvcGhlIElRIEJ1aWxkZXIgaW5zdGFuY2UsIGJ1dCBET00gZWxlbWVudCB0cmVlLlxuICAgICAqL1xuICAgIHByb2Nlc3NTb3VyY2VSZW1vdmU6IGZ1bmN0aW9uIChzb3VyY2VSZW1vdmUpIHtcbiAgICAgICAgaWYgKCFpc0VuYWJsZWQpXG4gICAgICAgICAgICByZXR1cm4gc291cmNlUmVtb3ZlO1xuXG4gICAgICAgIHJldHVybiBmaWx0ZXJPdXRTb3VyY2Uoc291cmNlUmVtb3ZlLCAnc291cmNlLXJlbW92ZScpO1xuICAgIH0sXG5cbiAgICAvKipcbiAgICAgKiBUdXJucyB0aGUgaGFjayBvbiBvciBvZmZcbiAgICAgKiBAcGFyYW0gZW5hYmxlZCA8dHQ+dHJ1ZTwvdHQ+IHRvIGVuYWJsZSB0aGUgaGFjayBvciA8dHQ+ZmFsc2U8L3R0PlxuICAgICAqICAgICAgICAgICAgICAgIHRvIGRpc2FibGUgaXRcbiAgICAgKi9cbiAgICBzZXRFbmFibGVkOiBmdW5jdGlvbiAoZW5hYmxlZCkge1xuICAgICAgICBpc0VuYWJsZWQgPSBlbmFibGVkO1xuICAgIH1cbn07XG5cbm1vZHVsZS5leHBvcnRzID0gTG9jYWxTU1JDUmVwbGFjZW1lbnQ7XG4iLCIvKiBqc2hpbnQgLVcxMTcgKi9cblxudmFyIGxvZ2dlciA9IHJlcXVpcmUoXCJqaXRzaS1tZWV0LWxvZ2dlclwiKS5nZXRMb2dnZXIoX19maWxlbmFtZSk7XG52YXIgU0RQVXRpbCA9IHJlcXVpcmUoXCIuL1NEUFV0aWxcIik7XG5cbi8vIFNEUCBTVFVGRlxuZnVuY3Rpb24gU0RQKHNkcCkge1xuICAgIC8qKlxuICAgICAqIFdoZXRoZXIgb3Igbm90IHRvIHJlbW92ZSBUQ1AgaWNlIGNhbmRpZGF0ZXMgd2hlbiB0cmFuc2xhdGluZyBmcm9tL3RvIGppbmdsZS5cbiAgICAgKiBAdHlwZSB7Ym9vbGVhbn1cbiAgICAgKi9cbiAgICB0aGlzLnJlbW92ZVRjcENhbmRpZGF0ZXMgPSBmYWxzZTtcblxuICAgIC8qKlxuICAgICAqIFdoZXRoZXIgb3Igbm90IHRvIHJlbW92ZSBVRFAgaWNlIGNhbmRpZGF0ZXMgd2hlbiB0cmFuc2xhdGluZyBmcm9tL3RvIGppbmdsZS5cbiAgICAgKiBAdHlwZSB7Ym9vbGVhbn1cbiAgICAgKi9cbiAgICB0aGlzLnJlbW92ZVVkcENhbmRpZGF0ZXMgPSBmYWxzZTtcblxuICAgIHRoaXMubWVkaWEgPSBzZHAuc3BsaXQoJ1xcclxcbm09Jyk7XG4gICAgZm9yICh2YXIgaSA9IDE7IGkgPCB0aGlzLm1lZGlhLmxlbmd0aDsgaSsrKSB7XG4gICAgICAgIHRoaXMubWVkaWFbaV0gPSAnbT0nICsgdGhpcy5tZWRpYVtpXTtcbiAgICAgICAgaWYgKGkgIT0gdGhpcy5tZWRpYS5sZW5ndGggLSAxKSB7XG4gICAgICAgICAgICB0aGlzLm1lZGlhW2ldICs9ICdcXHJcXG4nO1xuICAgICAgICB9XG4gICAgfVxuICAgIHRoaXMuc2Vzc2lvbiA9IHRoaXMubWVkaWEuc2hpZnQoKSArICdcXHJcXG4nO1xuICAgIHRoaXMucmF3ID0gdGhpcy5zZXNzaW9uICsgdGhpcy5tZWRpYS5qb2luKCcnKTtcbn1cblxuLyoqXG4gKiBSZXR1cm5zIG1hcCBvZiBNZWRpYUNoYW5uZWwgbWFwcGVkIHBlciBjaGFubmVsIGlkeC5cbiAqL1xuU0RQLnByb3RvdHlwZS5nZXRNZWRpYVNzcmNNYXAgPSBmdW5jdGlvbigpIHtcbiAgICB2YXIgc2VsZiA9IHRoaXM7XG4gICAgdmFyIG1lZGlhX3NzcmNzID0ge307XG4gICAgdmFyIHRtcDtcbiAgICBmb3IgKHZhciBtZWRpYWluZGV4ID0gMDsgbWVkaWFpbmRleCA8IHNlbGYubWVkaWEubGVuZ3RoOyBtZWRpYWluZGV4KyspIHtcbiAgICAgICAgdG1wID0gU0RQVXRpbC5maW5kX2xpbmVzKHNlbGYubWVkaWFbbWVkaWFpbmRleF0sICdhPXNzcmM6Jyk7XG4gICAgICAgIHZhciBtaWQgPSBTRFBVdGlsLnBhcnNlX21pZChTRFBVdGlsLmZpbmRfbGluZShzZWxmLm1lZGlhW21lZGlhaW5kZXhdLCAnYT1taWQ6JykpO1xuICAgICAgICB2YXIgbWVkaWEgPSB7XG4gICAgICAgICAgICBtZWRpYWluZGV4OiBtZWRpYWluZGV4LFxuICAgICAgICAgICAgbWlkOiBtaWQsXG4gICAgICAgICAgICBzc3Jjczoge30sXG4gICAgICAgICAgICBzc3JjR3JvdXBzOiBbXVxuICAgICAgICB9O1xuICAgICAgICBtZWRpYV9zc3Jjc1ttZWRpYWluZGV4XSA9IG1lZGlhO1xuICAgICAgICB0bXAuZm9yRWFjaChmdW5jdGlvbiAobGluZSkge1xuICAgICAgICAgICAgdmFyIGxpbmVzc3JjID0gbGluZS5zdWJzdHJpbmcoNykuc3BsaXQoJyAnKVswXTtcbiAgICAgICAgICAgIC8vIGFsbG9jYXRlIG5ldyBDaGFubmVsU3NyY1xuICAgICAgICAgICAgaWYoIW1lZGlhLnNzcmNzW2xpbmVzc3JjXSkge1xuICAgICAgICAgICAgICAgIG1lZGlhLnNzcmNzW2xpbmVzc3JjXSA9IHtcbiAgICAgICAgICAgICAgICAgICAgc3NyYzogbGluZXNzcmMsXG4gICAgICAgICAgICAgICAgICAgIGxpbmVzOiBbXVxuICAgICAgICAgICAgICAgIH07XG4gICAgICAgICAgICB9XG4gICAgICAgICAgICBtZWRpYS5zc3Jjc1tsaW5lc3NyY10ubGluZXMucHVzaChsaW5lKTtcbiAgICAgICAgfSk7XG4gICAgICAgIHRtcCA9IFNEUFV0aWwuZmluZF9saW5lcyhzZWxmLm1lZGlhW21lZGlhaW5kZXhdLCAnYT1zc3JjLWdyb3VwOicpO1xuICAgICAgICB0bXAuZm9yRWFjaChmdW5jdGlvbihsaW5lKXtcbiAgICAgICAgICAgIHZhciBpZHggPSBsaW5lLmluZGV4T2YoJyAnKTtcbiAgICAgICAgICAgIHZhciBzZW1hbnRpY3MgPSBsaW5lLnN1YnN0cigwLCBpZHgpLnN1YnN0cigxMyk7XG4gICAgICAgICAgICB2YXIgc3NyY3MgPSBsaW5lLnN1YnN0cigxNCArIHNlbWFudGljcy5sZW5ndGgpLnNwbGl0KCcgJyk7XG4gICAgICAgICAgICBpZiAoc3NyY3MubGVuZ3RoKSB7XG4gICAgICAgICAgICAgICAgbWVkaWEuc3NyY0dyb3Vwcy5wdXNoKHtcbiAgICAgICAgICAgICAgICAgICAgc2VtYW50aWNzOiBzZW1hbnRpY3MsXG4gICAgICAgICAgICAgICAgICAgIHNzcmNzOiBzc3Jjc1xuICAgICAgICAgICAgICAgIH0pO1xuICAgICAgICAgICAgfVxuICAgICAgICB9KTtcbiAgICB9XG4gICAgcmV0dXJuIG1lZGlhX3NzcmNzO1xufTtcbi8qKlxuICogUmV0dXJucyA8dHQ+dHJ1ZTwvdHQ+IGlmIHRoaXMgU0RQIGNvbnRhaW5zIGdpdmVuIFNTUkMuXG4gKiBAcGFyYW0gc3NyYyB0aGUgc3NyYyB0byBjaGVjay5cbiAqIEByZXR1cm5zIHtib29sZWFufSA8dHQ+dHJ1ZTwvdHQ+IGlmIHRoaXMgU0RQIGNvbnRhaW5zIGdpdmVuIFNTUkMuXG4gKi9cblNEUC5wcm90b3R5cGUuY29udGFpbnNTU1JDID0gZnVuY3Rpb24gKHNzcmMpIHtcbiAgICAvLyBGSVhNRSB0aGlzIGNvZGUgaXMgcmVhbGx5IHN0cmFuZ2UgLSBpbXByb3ZlIGl0IGlmIHlvdSBjYW5cbiAgICB2YXIgbWVkaWFzID0gdGhpcy5nZXRNZWRpYVNzcmNNYXAoKTtcbiAgICB2YXIgcmVzdWx0ID0gZmFsc2U7XG4gICAgT2JqZWN0LmtleXMobWVkaWFzKS5mb3JFYWNoKGZ1bmN0aW9uIChtZWRpYWluZGV4KSB7XG4gICAgICAgIGlmIChyZXN1bHQpXG4gICAgICAgICAgICByZXR1cm47XG4gICAgICAgIGlmIChtZWRpYXNbbWVkaWFpbmRleF0uc3NyY3Nbc3NyY10pIHtcbiAgICAgICAgICAgIHJlc3VsdCA9IHRydWU7XG4gICAgICAgIH1cbiAgICB9KTtcbiAgICByZXR1cm4gcmVzdWx0O1xufTtcblxuLy8gcmVtb3ZlIGlTQUMgYW5kIENOIGZyb20gU0RQXG5TRFAucHJvdG90eXBlLm1hbmdsZSA9IGZ1bmN0aW9uICgpIHtcbiAgICB2YXIgaSwgaiwgbWxpbmUsIGxpbmVzLCBydHBtYXAsIG5ld2Rlc2M7XG4gICAgZm9yIChpID0gMDsgaSA8IHRoaXMubWVkaWEubGVuZ3RoOyBpKyspIHtcbiAgICAgICAgbGluZXMgPSB0aGlzLm1lZGlhW2ldLnNwbGl0KCdcXHJcXG4nKTtcbiAgICAgICAgbGluZXMucG9wKCk7IC8vIHJlbW92ZSBlbXB0eSBsYXN0IGVsZW1lbnRcbiAgICAgICAgbWxpbmUgPSBTRFBVdGlsLnBhcnNlX21saW5lKGxpbmVzLnNoaWZ0KCkpO1xuICAgICAgICBpZiAobWxpbmUubWVkaWEgIT0gJ2F1ZGlvJylcbiAgICAgICAgICAgIGNvbnRpbnVlO1xuICAgICAgICBuZXdkZXNjID0gJyc7XG4gICAgICAgIG1saW5lLmZtdC5sZW5ndGggPSAwO1xuICAgICAgICBmb3IgKGogPSAwOyBqIDwgbGluZXMubGVuZ3RoOyBqKyspIHtcbiAgICAgICAgICAgIGlmIChsaW5lc1tqXS5zdWJzdHIoMCwgOSkgPT0gJ2E9cnRwbWFwOicpIHtcbiAgICAgICAgICAgICAgICBydHBtYXAgPSBTRFBVdGlsLnBhcnNlX3J0cG1hcChsaW5lc1tqXSk7XG4gICAgICAgICAgICAgICAgaWYgKHJ0cG1hcC5uYW1lID09ICdDTicgfHwgcnRwbWFwLm5hbWUgPT0gJ0lTQUMnKVxuICAgICAgICAgICAgICAgICAgICBjb250aW51ZTtcbiAgICAgICAgICAgICAgICBtbGluZS5mbXQucHVzaChydHBtYXAuaWQpO1xuICAgICAgICAgICAgICAgIG5ld2Rlc2MgKz0gbGluZXNbal0gKyAnXFxyXFxuJztcbiAgICAgICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICAgICAgbmV3ZGVzYyArPSBsaW5lc1tqXSArICdcXHJcXG4nO1xuICAgICAgICAgICAgfVxuICAgICAgICB9XG4gICAgICAgIHRoaXMubWVkaWFbaV0gPSBTRFBVdGlsLmJ1aWxkX21saW5lKG1saW5lKSArICdcXHJcXG4nO1xuICAgICAgICB0aGlzLm1lZGlhW2ldICs9IG5ld2Rlc2M7XG4gICAgfVxuICAgIHRoaXMucmF3ID0gdGhpcy5zZXNzaW9uICsgdGhpcy5tZWRpYS5qb2luKCcnKTtcbn07XG5cbi8vIHJlbW92ZSBsaW5lcyBtYXRjaGluZyBwcmVmaXggZnJvbSBzZXNzaW9uIHNlY3Rpb25cblNEUC5wcm90b3R5cGUucmVtb3ZlU2Vzc2lvbkxpbmVzID0gZnVuY3Rpb24ocHJlZml4KSB7XG4gICAgdmFyIHNlbGYgPSB0aGlzO1xuICAgIHZhciBsaW5lcyA9IFNEUFV0aWwuZmluZF9saW5lcyh0aGlzLnNlc3Npb24sIHByZWZpeCk7XG4gICAgbGluZXMuZm9yRWFjaChmdW5jdGlvbihsaW5lKSB7XG4gICAgICAgIHNlbGYuc2Vzc2lvbiA9IHNlbGYuc2Vzc2lvbi5yZXBsYWNlKGxpbmUgKyAnXFxyXFxuJywgJycpO1xuICAgIH0pO1xuICAgIHRoaXMucmF3ID0gdGhpcy5zZXNzaW9uICsgdGhpcy5tZWRpYS5qb2luKCcnKTtcbiAgICByZXR1cm4gbGluZXM7XG59XG4vLyByZW1vdmUgbGluZXMgbWF0Y2hpbmcgcHJlZml4IGZyb20gYSBtZWRpYSBzZWN0aW9uIHNwZWNpZmllZCBieSBtZWRpYWluZGV4XG4vLyBUT0RPOiBub24tbnVtZXJpYyBtZWRpYWluZGV4IGNvdWxkIG1hdGNoIG1pZFxuU0RQLnByb3RvdHlwZS5yZW1vdmVNZWRpYUxpbmVzID0gZnVuY3Rpb24obWVkaWFpbmRleCwgcHJlZml4KSB7XG4gICAgdmFyIHNlbGYgPSB0aGlzO1xuICAgIHZhciBsaW5lcyA9IFNEUFV0aWwuZmluZF9saW5lcyh0aGlzLm1lZGlhW21lZGlhaW5kZXhdLCBwcmVmaXgpO1xuICAgIGxpbmVzLmZvckVhY2goZnVuY3Rpb24obGluZSkge1xuICAgICAgICBzZWxmLm1lZGlhW21lZGlhaW5kZXhdID0gc2VsZi5tZWRpYVttZWRpYWluZGV4XS5yZXBsYWNlKGxpbmUgKyAnXFxyXFxuJywgJycpO1xuICAgIH0pO1xuICAgIHRoaXMucmF3ID0gdGhpcy5zZXNzaW9uICsgdGhpcy5tZWRpYS5qb2luKCcnKTtcbiAgICByZXR1cm4gbGluZXM7XG59XG5cbi8vIGFkZCBjb250ZW50J3MgdG8gYSBqaW5nbGUgZWxlbWVudFxuU0RQLnByb3RvdHlwZS50b0ppbmdsZSA9IGZ1bmN0aW9uIChlbGVtLCB0aGVjcmVhdG9yKSB7XG4vLyAgICBsb2dnZXIubG9nKFwiU1NSQ1wiICsgc3NyY3NbXCJhdWRpb1wiXSArIFwiIC0gXCIgKyBzc3Jjc1tcInZpZGVvXCJdKTtcbiAgICB2YXIgc2VsZiA9IHRoaXM7XG4gICAgdmFyIGksIGosIGssIG1saW5lLCBzc3JjLCBydHBtYXAsIHRtcCwgbGluZXM7XG4gICAgLy8gbmV3IGJ1bmRsZSBwbGFuXG4gICAgaWYgKFNEUFV0aWwuZmluZF9saW5lKHRoaXMuc2Vzc2lvbiwgJ2E9Z3JvdXA6JykpIHtcbiAgICAgICAgbGluZXMgPSBTRFBVdGlsLmZpbmRfbGluZXModGhpcy5zZXNzaW9uLCAnYT1ncm91cDonKTtcbiAgICAgICAgZm9yIChpID0gMDsgaSA8IGxpbmVzLmxlbmd0aDsgaSsrKSB7XG4gICAgICAgICAgICB0bXAgPSBsaW5lc1tpXS5zcGxpdCgnICcpO1xuICAgICAgICAgICAgdmFyIHNlbWFudGljcyA9IHRtcC5zaGlmdCgpLnN1YnN0cig4KTtcbiAgICAgICAgICAgIGVsZW0uYygnZ3JvdXAnLCB7eG1sbnM6ICd1cm46eG1wcDpqaW5nbGU6YXBwczpncm91cGluZzowJywgc2VtYW50aWNzOnNlbWFudGljc30pO1xuICAgICAgICAgICAgZm9yIChqID0gMDsgaiA8IHRtcC5sZW5ndGg7IGorKykge1xuICAgICAgICAgICAgICAgIGVsZW0uYygnY29udGVudCcsIHtuYW1lOiB0bXBbal19KS51cCgpO1xuICAgICAgICAgICAgfVxuICAgICAgICAgICAgZWxlbS51cCgpO1xuICAgICAgICB9XG4gICAgfVxuICAgIGZvciAoaSA9IDA7IGkgPCB0aGlzLm1lZGlhLmxlbmd0aDsgaSsrKSB7XG4gICAgICAgIG1saW5lID0gU0RQVXRpbC5wYXJzZV9tbGluZSh0aGlzLm1lZGlhW2ldLnNwbGl0KCdcXHJcXG4nKVswXSk7XG4gICAgICAgIGlmICghKG1saW5lLm1lZGlhID09PSAnYXVkaW8nIHx8XG4gICAgICAgICAgICAgIG1saW5lLm1lZGlhID09PSAndmlkZW8nIHx8XG4gICAgICAgICAgICAgIG1saW5lLm1lZGlhID09PSAnYXBwbGljYXRpb24nKSlcbiAgICAgICAge1xuICAgICAgICAgICAgY29udGludWU7XG4gICAgICAgIH1cbiAgICAgICAgaWYgKFNEUFV0aWwuZmluZF9saW5lKHRoaXMubWVkaWFbaV0sICdhPXNzcmM6JykpIHtcbiAgICAgICAgICAgIHNzcmMgPSBTRFBVdGlsLmZpbmRfbGluZSh0aGlzLm1lZGlhW2ldLCAnYT1zc3JjOicpLnN1YnN0cmluZyg3KS5zcGxpdCgnICcpWzBdOyAvLyB0YWtlIHRoZSBmaXJzdFxuICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgc3NyYyA9IGZhbHNlO1xuICAgICAgICB9XG5cbiAgICAgICAgZWxlbS5jKCdjb250ZW50Jywge2NyZWF0b3I6IHRoZWNyZWF0b3IsIG5hbWU6IG1saW5lLm1lZGlhfSk7XG4gICAgICAgIGlmIChTRFBVdGlsLmZpbmRfbGluZSh0aGlzLm1lZGlhW2ldLCAnYT1taWQ6JykpIHtcbiAgICAgICAgICAgIC8vIHByZWZlciBpZGVudGlmaWVyIGZyb20gYT1taWQgaWYgcHJlc2VudFxuICAgICAgICAgICAgdmFyIG1pZCA9IFNEUFV0aWwucGFyc2VfbWlkKFNEUFV0aWwuZmluZF9saW5lKHRoaXMubWVkaWFbaV0sICdhPW1pZDonKSk7XG4gICAgICAgICAgICBlbGVtLmF0dHJzKHsgbmFtZTogbWlkIH0pO1xuICAgICAgICB9XG5cbiAgICAgICAgaWYgKFNEUFV0aWwuZmluZF9saW5lKHRoaXMubWVkaWFbaV0sICdhPXJ0cG1hcDonKS5sZW5ndGgpIHtcbiAgICAgICAgICAgIGVsZW0uYygnZGVzY3JpcHRpb24nLFxuICAgICAgICAgICAgICAgIHt4bWxuczogJ3Vybjp4bXBwOmppbmdsZTphcHBzOnJ0cDoxJyxcbiAgICAgICAgICAgICAgICAgICAgbWVkaWE6IG1saW5lLm1lZGlhIH0pO1xuICAgICAgICAgICAgaWYgKHNzcmMpIHtcbiAgICAgICAgICAgICAgICBlbGVtLmF0dHJzKHtzc3JjOiBzc3JjfSk7XG4gICAgICAgICAgICB9XG4gICAgICAgICAgICBmb3IgKGogPSAwOyBqIDwgbWxpbmUuZm10Lmxlbmd0aDsgaisrKSB7XG4gICAgICAgICAgICAgICAgcnRwbWFwID0gU0RQVXRpbC5maW5kX2xpbmUodGhpcy5tZWRpYVtpXSwgJ2E9cnRwbWFwOicgKyBtbGluZS5mbXRbal0pO1xuICAgICAgICAgICAgICAgIGVsZW0uYygncGF5bG9hZC10eXBlJywgU0RQVXRpbC5wYXJzZV9ydHBtYXAocnRwbWFwKSk7XG4gICAgICAgICAgICAgICAgLy8gcHV0IGFueSAnYT1mbXRwOicgKyBtbGluZS5mbXRbal0gbGluZXMgaW50byA8cGFyYW0gbmFtZT1mb28gdmFsdWU9YmFyLz5cbiAgICAgICAgICAgICAgICBpZiAoU0RQVXRpbC5maW5kX2xpbmUodGhpcy5tZWRpYVtpXSwgJ2E9Zm10cDonICsgbWxpbmUuZm10W2pdKSkge1xuICAgICAgICAgICAgICAgICAgICB0bXAgPSBTRFBVdGlsLnBhcnNlX2ZtdHAoU0RQVXRpbC5maW5kX2xpbmUodGhpcy5tZWRpYVtpXSwgJ2E9Zm10cDonICsgbWxpbmUuZm10W2pdKSk7XG4gICAgICAgICAgICAgICAgICAgIGZvciAoayA9IDA7IGsgPCB0bXAubGVuZ3RoOyBrKyspIHtcbiAgICAgICAgICAgICAgICAgICAgICAgIGVsZW0uYygncGFyYW1ldGVyJywgdG1wW2tdKS51cCgpO1xuICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgIHRoaXMucnRjcEZiVG9KaW5nbGUoaSwgZWxlbSwgbWxpbmUuZm10W2pdKTsgLy8gWEVQLTAyOTMgLS0gbWFwIGE9cnRjcC1mYlxuXG4gICAgICAgICAgICAgICAgZWxlbS51cCgpO1xuICAgICAgICAgICAgfVxuICAgICAgICAgICAgaWYgKFNEUFV0aWwuZmluZF9saW5lKHRoaXMubWVkaWFbaV0sICdhPWNyeXB0bzonLCB0aGlzLnNlc3Npb24pKSB7XG4gICAgICAgICAgICAgICAgZWxlbS5jKCdlbmNyeXB0aW9uJywge3JlcXVpcmVkOiAxfSk7XG4gICAgICAgICAgICAgICAgdmFyIGNyeXB0byA9IFNEUFV0aWwuZmluZF9saW5lcyh0aGlzLm1lZGlhW2ldLCAnYT1jcnlwdG86JywgdGhpcy5zZXNzaW9uKTtcbiAgICAgICAgICAgICAgICBjcnlwdG8uZm9yRWFjaChmdW5jdGlvbihsaW5lKSB7XG4gICAgICAgICAgICAgICAgICAgIGVsZW0uYygnY3J5cHRvJywgU0RQVXRpbC5wYXJzZV9jcnlwdG8obGluZSkpLnVwKCk7XG4gICAgICAgICAgICAgICAgfSk7XG4gICAgICAgICAgICAgICAgZWxlbS51cCgpOyAvLyBlbmQgb2YgZW5jcnlwdGlvblxuICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICBpZiAoc3NyYykge1xuICAgICAgICAgICAgICAgIC8vIG5ldyBzdHlsZSBtYXBwaW5nXG4gICAgICAgICAgICAgICAgZWxlbS5jKCdzb3VyY2UnLCB7IHNzcmM6IHNzcmMsIHhtbG5zOiAndXJuOnhtcHA6amluZ2xlOmFwcHM6cnRwOnNzbWE6MCcgfSk7XG4gICAgICAgICAgICAgICAgLy8gRklYTUU6IGdyb3VwIGJ5IHNzcmMgYW5kIHN1cHBvcnQgbXVsdGlwbGUgZGlmZmVyZW50IHNzcmNzXG4gICAgICAgICAgICAgICAgdmFyIHNzcmNsaW5lcyA9IFNEUFV0aWwuZmluZF9saW5lcyh0aGlzLm1lZGlhW2ldLCAnYT1zc3JjOicpO1xuICAgICAgICAgICAgICAgIGlmKHNzcmNsaW5lcy5sZW5ndGggPiAwKSB7XG4gICAgICAgICAgICAgICAgICAgIHNzcmNsaW5lcy5mb3JFYWNoKGZ1bmN0aW9uIChsaW5lKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICB2YXIgaWR4ID0gbGluZS5pbmRleE9mKCcgJyk7XG4gICAgICAgICAgICAgICAgICAgICAgICB2YXIgbGluZXNzcmMgPSBsaW5lLnN1YnN0cigwLCBpZHgpLnN1YnN0cig3KTtcbiAgICAgICAgICAgICAgICAgICAgICAgIGlmIChsaW5lc3NyYyAhPSBzc3JjKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgZWxlbS51cCgpO1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgIHNzcmMgPSBsaW5lc3NyYztcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICBlbGVtLmMoJ3NvdXJjZScsIHsgc3NyYzogc3NyYywgeG1sbnM6ICd1cm46eG1wcDpqaW5nbGU6YXBwczpydHA6c3NtYTowJyB9KTtcbiAgICAgICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICAgICAgICAgIHZhciBrdiA9IGxpbmUuc3Vic3RyKGlkeCArIDEpO1xuICAgICAgICAgICAgICAgICAgICAgICAgZWxlbS5jKCdwYXJhbWV0ZXInKTtcbiAgICAgICAgICAgICAgICAgICAgICAgIGlmIChrdi5pbmRleE9mKCc6JykgPT0gLTEpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICBlbGVtLmF0dHJzKHsgbmFtZToga3YgfSk7XG4gICAgICAgICAgICAgICAgICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgIHZhciBrID0ga3Yuc3BsaXQoJzonLCAyKVswXTtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICBlbGVtLmF0dHJzKHsgbmFtZTogayB9KTtcblxuICAgICAgICAgICAgICAgICAgICAgICAgICAgIHZhciB2ID0ga3Yuc3BsaXQoJzonLCAyKVsxXTtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICB2ID0gU0RQVXRpbC5maWx0ZXJfc3BlY2lhbF9jaGFycyh2KTtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICBlbGVtLmF0dHJzKHsgdmFsdWU6IHYgfSk7XG4gICAgICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgICAgICAgICBlbGVtLnVwKCk7XG4gICAgICAgICAgICAgICAgICAgIH0pO1xuICAgICAgICAgICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICAgICAgICAgIGVsZW0udXAoKTtcbiAgICAgICAgICAgICAgICAgICAgZWxlbS5jKCdzb3VyY2UnLCB7IHNzcmM6IHNzcmMsIHhtbG5zOiAndXJuOnhtcHA6amluZ2xlOmFwcHM6cnRwOnNzbWE6MCcgfSk7XG4gICAgICAgICAgICAgICAgICAgIGVsZW0uYygncGFyYW1ldGVyJyk7XG4gICAgICAgICAgICAgICAgICAgIGVsZW0uYXR0cnMoe25hbWU6IFwiY25hbWVcIiwgdmFsdWU6TWF0aC5yYW5kb20oKS50b1N0cmluZygzNikuc3Vic3RyaW5nKDcpfSk7XG4gICAgICAgICAgICAgICAgICAgIGVsZW0udXAoKTtcbiAgICAgICAgICAgICAgICAgICAgdmFyIG1zaWQgPSBudWxsO1xuICAgICAgICAgICAgICAgICAgICBpZihtbGluZS5tZWRpYSA9PSBcImF1ZGlvXCIpXG4gICAgICAgICAgICAgICAgICAgIHtcbiAgICAgICAgICAgICAgICAgICAgICAgIG1zaWQgPSBBUFAuUlRDLmxvY2FsQXVkaW8uX2dldElkKCk7XG4gICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICAgICAgZWxzZVxuICAgICAgICAgICAgICAgICAgICB7XG4gICAgICAgICAgICAgICAgICAgICAgICBtc2lkID0gQVBQLlJUQy5sb2NhbFZpZGVvLl9nZXRJZCgpO1xuICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgICAgIGlmKG1zaWQgIT0gbnVsbClcbiAgICAgICAgICAgICAgICAgICAge1xuICAgICAgICAgICAgICAgICAgICAgICAgbXNpZCA9IFNEUFV0aWwuZmlsdGVyX3NwZWNpYWxfY2hhcnMobXNpZCk7XG4gICAgICAgICAgICAgICAgICAgICAgICBlbGVtLmMoJ3BhcmFtZXRlcicpO1xuICAgICAgICAgICAgICAgICAgICAgICAgZWxlbS5hdHRycyh7bmFtZTogXCJtc2lkXCIsIHZhbHVlOm1zaWR9KTtcbiAgICAgICAgICAgICAgICAgICAgICAgIGVsZW0udXAoKTtcbiAgICAgICAgICAgICAgICAgICAgICAgIGVsZW0uYygncGFyYW1ldGVyJyk7XG4gICAgICAgICAgICAgICAgICAgICAgICBlbGVtLmF0dHJzKHtuYW1lOiBcIm1zbGFiZWxcIiwgdmFsdWU6bXNpZH0pO1xuICAgICAgICAgICAgICAgICAgICAgICAgZWxlbS51cCgpO1xuICAgICAgICAgICAgICAgICAgICAgICAgZWxlbS5jKCdwYXJhbWV0ZXInKTtcbiAgICAgICAgICAgICAgICAgICAgICAgIGVsZW0uYXR0cnMoe25hbWU6IFwibGFiZWxcIiwgdmFsdWU6bXNpZH0pO1xuICAgICAgICAgICAgICAgICAgICAgICAgZWxlbS51cCgpO1xuICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgIGVsZW0udXAoKTtcblxuICAgICAgICAgICAgICAgIC8vIFhFUC0wMzM5IGhhbmRsZSBzc3JjLWdyb3VwIGF0dHJpYnV0ZXNcbiAgICAgICAgICAgICAgICB2YXIgc3NyY19ncm91cF9saW5lcyA9IFNEUFV0aWwuZmluZF9saW5lcyh0aGlzLm1lZGlhW2ldLCAnYT1zc3JjLWdyb3VwOicpO1xuICAgICAgICAgICAgICAgIHNzcmNfZ3JvdXBfbGluZXMuZm9yRWFjaChmdW5jdGlvbihsaW5lKSB7XG4gICAgICAgICAgICAgICAgICAgIHZhciBpZHggPSBsaW5lLmluZGV4T2YoJyAnKTtcbiAgICAgICAgICAgICAgICAgICAgdmFyIHNlbWFudGljcyA9IGxpbmUuc3Vic3RyKDAsIGlkeCkuc3Vic3RyKDEzKTtcbiAgICAgICAgICAgICAgICAgICAgdmFyIHNzcmNzID0gbGluZS5zdWJzdHIoMTQgKyBzZW1hbnRpY3MubGVuZ3RoKS5zcGxpdCgnICcpO1xuICAgICAgICAgICAgICAgICAgICBpZiAoc3NyY3MubGVuZ3RoKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICBlbGVtLmMoJ3NzcmMtZ3JvdXAnLCB7IHNlbWFudGljczogc2VtYW50aWNzLCB4bWxuczogJ3Vybjp4bXBwOmppbmdsZTphcHBzOnJ0cDpzc21hOjAnIH0pO1xuICAgICAgICAgICAgICAgICAgICAgICAgc3NyY3MuZm9yRWFjaChmdW5jdGlvbihzc3JjKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgZWxlbS5jKCdzb3VyY2UnLCB7IHNzcmM6IHNzcmMgfSlcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgLnVwKCk7XG4gICAgICAgICAgICAgICAgICAgICAgICB9KTtcbiAgICAgICAgICAgICAgICAgICAgICAgIGVsZW0udXAoKTtcbiAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgIH0pO1xuICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICBpZiAoU0RQVXRpbC5maW5kX2xpbmUodGhpcy5tZWRpYVtpXSwgJ2E9cnRjcC1tdXgnKSkge1xuICAgICAgICAgICAgICAgIGVsZW0uYygncnRjcC1tdXgnKS51cCgpO1xuICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICAvLyBYRVAtMDI5MyAtLSBtYXAgYT1ydGNwLWZiOipcbiAgICAgICAgICAgIHRoaXMucnRjcEZiVG9KaW5nbGUoaSwgZWxlbSwgJyonKTtcblxuICAgICAgICAgICAgLy8gWEVQLTAyOTRcbiAgICAgICAgICAgIGlmIChTRFBVdGlsLmZpbmRfbGluZSh0aGlzLm1lZGlhW2ldLCAnYT1leHRtYXA6JykpIHtcbiAgICAgICAgICAgICAgICBsaW5lcyA9IFNEUFV0aWwuZmluZF9saW5lcyh0aGlzLm1lZGlhW2ldLCAnYT1leHRtYXA6Jyk7XG4gICAgICAgICAgICAgICAgZm9yIChqID0gMDsgaiA8IGxpbmVzLmxlbmd0aDsgaisrKSB7XG4gICAgICAgICAgICAgICAgICAgIHRtcCA9IFNEUFV0aWwucGFyc2VfZXh0bWFwKGxpbmVzW2pdKTtcbiAgICAgICAgICAgICAgICAgICAgZWxlbS5jKCdydHAtaGRyZXh0JywgeyB4bWxuczogJ3Vybjp4bXBwOmppbmdsZTphcHBzOnJ0cDpydHAtaGRyZXh0OjAnLFxuICAgICAgICAgICAgICAgICAgICAgICAgdXJpOiB0bXAudXJpLFxuICAgICAgICAgICAgICAgICAgICAgICAgaWQ6IHRtcC52YWx1ZSB9KTtcbiAgICAgICAgICAgICAgICAgICAgaWYgKHRtcC5oYXNPd25Qcm9wZXJ0eSgnZGlyZWN0aW9uJykpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgIHN3aXRjaCAodG1wLmRpcmVjdGlvbikge1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgIGNhc2UgJ3NlbmRvbmx5JzpcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgZWxlbS5hdHRycyh7c2VuZGVyczogJ3Jlc3BvbmRlcid9KTtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgYnJlYWs7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgY2FzZSAncmVjdm9ubHknOlxuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBlbGVtLmF0dHJzKHtzZW5kZXJzOiAnaW5pdGlhdG9yJ30pO1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBicmVhaztcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICBjYXNlICdzZW5kcmVjdic6XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGVsZW0uYXR0cnMoe3NlbmRlcnM6ICdib3RoJ30pO1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBicmVhaztcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICBjYXNlICdpbmFjdGl2ZSc6XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGVsZW0uYXR0cnMoe3NlbmRlcnM6ICdub25lJ30pO1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBicmVhaztcbiAgICAgICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgICAgICAvLyBUT0RPOiBoYW5kbGUgcGFyYW1zXG4gICAgICAgICAgICAgICAgICAgIGVsZW0udXAoKTtcbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICB9XG4gICAgICAgICAgICBlbGVtLnVwKCk7IC8vIGVuZCBvZiBkZXNjcmlwdGlvblxuICAgICAgICB9XG5cbiAgICAgICAgLy8gbWFwIGljZS11ZnJhZy9wd2QsIGR0bHMgZmluZ2VycHJpbnQsIGNhbmRpZGF0ZXNcbiAgICAgICAgdGhpcy50cmFuc3BvcnRUb0ppbmdsZShpLCBlbGVtKTtcblxuICAgICAgICBpZiAoU0RQVXRpbC5maW5kX2xpbmUodGhpcy5tZWRpYVtpXSwgJ2E9c2VuZHJlY3YnLCB0aGlzLnNlc3Npb24pKSB7XG4gICAgICAgICAgICBlbGVtLmF0dHJzKHtzZW5kZXJzOiAnYm90aCd9KTtcbiAgICAgICAgfSBlbHNlIGlmIChTRFBVdGlsLmZpbmRfbGluZSh0aGlzLm1lZGlhW2ldLCAnYT1zZW5kb25seScsIHRoaXMuc2Vzc2lvbikpIHtcbiAgICAgICAgICAgIGVsZW0uYXR0cnMoe3NlbmRlcnM6ICdpbml0aWF0b3InfSk7XG4gICAgICAgIH0gZWxzZSBpZiAoU0RQVXRpbC5maW5kX2xpbmUodGhpcy5tZWRpYVtpXSwgJ2E9cmVjdm9ubHknLCB0aGlzLnNlc3Npb24pKSB7XG4gICAgICAgICAgICBlbGVtLmF0dHJzKHtzZW5kZXJzOiAncmVzcG9uZGVyJ30pO1xuICAgICAgICB9IGVsc2UgaWYgKFNEUFV0aWwuZmluZF9saW5lKHRoaXMubWVkaWFbaV0sICdhPWluYWN0aXZlJywgdGhpcy5zZXNzaW9uKSkge1xuICAgICAgICAgICAgZWxlbS5hdHRycyh7c2VuZGVyczogJ25vbmUnfSk7XG4gICAgICAgIH1cbiAgICAgICAgaWYgKG1saW5lLnBvcnQgPT0gJzAnKSB7XG4gICAgICAgICAgICAvLyBlc3RvcyBoYWNrIHRvIHJlamVjdCBhbiBtLWxpbmVcbiAgICAgICAgICAgIGVsZW0uYXR0cnMoe3NlbmRlcnM6ICdyZWplY3RlZCd9KTtcbiAgICAgICAgfVxuICAgICAgICBlbGVtLnVwKCk7IC8vIGVuZCBvZiBjb250ZW50XG4gICAgfVxuICAgIGVsZW0udXAoKTtcbiAgICByZXR1cm4gZWxlbTtcbn07XG5cblNEUC5wcm90b3R5cGUudHJhbnNwb3J0VG9KaW5nbGUgPSBmdW5jdGlvbiAobWVkaWFpbmRleCwgZWxlbSkge1xuICAgIHZhciB0bXAsIHNjdHBtYXAsIHNjdHBBdHRycywgZmluZ2VycHJpbnRzO1xuICAgIHZhciBzZWxmID0gdGhpcztcbiAgICBlbGVtLmMoJ3RyYW5zcG9ydCcpO1xuXG4gICAgLy8gWEVQLTAzNDMgRFRMUy9TQ1RQXG4gICAgaWYgKFNEUFV0aWwuZmluZF9saW5lKHRoaXMubWVkaWFbbWVkaWFpbmRleF0sICdhPXNjdHBtYXA6JykubGVuZ3RoKVxuICAgIHtcbiAgICAgICAgc2N0cG1hcCA9IFNEUFV0aWwuZmluZF9saW5lKFxuICAgICAgICAgICAgdGhpcy5tZWRpYVttZWRpYWluZGV4XSwgJ2E9c2N0cG1hcDonLCBzZWxmLnNlc3Npb24pO1xuICAgICAgICBpZiAoc2N0cG1hcClcbiAgICAgICAge1xuICAgICAgICAgICAgc2N0cEF0dHJzID0gU0RQVXRpbC5wYXJzZV9zY3RwbWFwKHNjdHBtYXApO1xuICAgICAgICAgICAgZWxlbS5jKCdzY3RwbWFwJyxcbiAgICAgICAgICAgICAgICB7XG4gICAgICAgICAgICAgICAgICAgIHhtbG5zOiAndXJuOnhtcHA6amluZ2xlOnRyYW5zcG9ydHM6ZHRscy1zY3RwOjEnLFxuICAgICAgICAgICAgICAgICAgICBudW1iZXI6IHNjdHBBdHRyc1swXSwgLyogU0NUUCBwb3J0ICovXG4gICAgICAgICAgICAgICAgICAgIHByb3RvY29sOiBzY3RwQXR0cnNbMV0gLyogcHJvdG9jb2wgKi9cbiAgICAgICAgICAgICAgICB9KTtcbiAgICAgICAgICAgIC8vIE9wdGlvbmFsIHN0cmVhbSBjb3VudCBhdHRyaWJ1dGVcbiAgICAgICAgICAgIGlmIChzY3RwQXR0cnMubGVuZ3RoID4gMilcbiAgICAgICAgICAgICAgICBlbGVtLmF0dHJzKHsgc3RyZWFtczogc2N0cEF0dHJzWzJdfSk7XG4gICAgICAgICAgICBlbGVtLnVwKCk7XG4gICAgICAgIH1cbiAgICB9XG4gICAgLy8gWEVQLTAzMjBcbiAgICBmaW5nZXJwcmludHMgPSBTRFBVdGlsLmZpbmRfbGluZXModGhpcy5tZWRpYVttZWRpYWluZGV4XSwgJ2E9ZmluZ2VycHJpbnQ6JywgdGhpcy5zZXNzaW9uKTtcbiAgICBmaW5nZXJwcmludHMuZm9yRWFjaChmdW5jdGlvbihsaW5lKSB7XG4gICAgICAgIHRtcCA9IFNEUFV0aWwucGFyc2VfZmluZ2VycHJpbnQobGluZSk7XG4gICAgICAgIHRtcC54bWxucyA9ICd1cm46eG1wcDpqaW5nbGU6YXBwczpkdGxzOjAnO1xuICAgICAgICBlbGVtLmMoJ2ZpbmdlcnByaW50JykudCh0bXAuZmluZ2VycHJpbnQpO1xuICAgICAgICBkZWxldGUgdG1wLmZpbmdlcnByaW50O1xuICAgICAgICBsaW5lID0gU0RQVXRpbC5maW5kX2xpbmUoc2VsZi5tZWRpYVttZWRpYWluZGV4XSwgJ2E9c2V0dXA6Jywgc2VsZi5zZXNzaW9uKTtcbiAgICAgICAgaWYgKGxpbmUpIHtcbiAgICAgICAgICAgIHRtcC5zZXR1cCA9IGxpbmUuc3Vic3RyKDgpO1xuICAgICAgICB9XG4gICAgICAgIGVsZW0uYXR0cnModG1wKTtcbiAgICAgICAgZWxlbS51cCgpOyAvLyBlbmQgb2YgZmluZ2VycHJpbnRcbiAgICB9KTtcbiAgICB0bXAgPSBTRFBVdGlsLmljZXBhcmFtcyh0aGlzLm1lZGlhW21lZGlhaW5kZXhdLCB0aGlzLnNlc3Npb24pO1xuICAgIGlmICh0bXApIHtcbiAgICAgICAgdG1wLnhtbG5zID0gJ3Vybjp4bXBwOmppbmdsZTp0cmFuc3BvcnRzOmljZS11ZHA6MSc7XG4gICAgICAgIGVsZW0uYXR0cnModG1wKTtcbiAgICAgICAgLy8gWEVQLTAxNzZcbiAgICAgICAgaWYgKFNEUFV0aWwuZmluZF9saW5lKHRoaXMubWVkaWFbbWVkaWFpbmRleF0sICdhPWNhbmRpZGF0ZTonLCB0aGlzLnNlc3Npb24pKSB7IC8vIGFkZCBhbnkgYT1jYW5kaWRhdGUgbGluZXNcbiAgICAgICAgICAgIHZhciBsaW5lcyA9IFNEUFV0aWwuZmluZF9saW5lcyh0aGlzLm1lZGlhW21lZGlhaW5kZXhdLCAnYT1jYW5kaWRhdGU6JywgdGhpcy5zZXNzaW9uKTtcbiAgICAgICAgICAgIGxpbmVzLmZvckVhY2goZnVuY3Rpb24gKGxpbmUpIHtcbiAgICAgICAgICAgICAgICB2YXIgY2FuZGlkYXRlID0gU0RQVXRpbC5jYW5kaWRhdGVUb0ppbmdsZShsaW5lKTtcbiAgICAgICAgICAgICAgICB2YXIgcHJvdG9jb2wgPSAoY2FuZGlkYXRlICYmXG4gICAgICAgICAgICAgICAgICAgICAgICB0eXBlb2YgY2FuZGlkYXRlLnByb3RvY29sID09PSAnc3RyaW5nJylcbiAgICAgICAgICAgICAgICAgICAgPyBjYW5kaWRhdGUucHJvdG9jb2wudG9Mb3dlckNhc2UoKSA6ICcnO1xuICAgICAgICAgICAgICAgIGlmICgoc2VsZi5yZW1vdmVUY3BDYW5kaWRhdGVzICYmIHByb3RvY29sID09PSAndGNwJykgfHxcbiAgICAgICAgICAgICAgICAgICAgKHNlbGYucmVtb3ZlVWRwQ2FuZGlkYXRlcyAmJiBwcm90b2NvbCA9PT0gJ3VkcCcpKSB7XG4gICAgICAgICAgICAgICAgICAgIHJldHVybjtcbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgZWxlbS5jKCdjYW5kaWRhdGUnLCBjYW5kaWRhdGUpLnVwKCk7XG4gICAgICAgICAgICB9KTtcbiAgICAgICAgfVxuICAgIH1cbiAgICBlbGVtLnVwKCk7IC8vIGVuZCBvZiB0cmFuc3BvcnRcbn1cblxuU0RQLnByb3RvdHlwZS5ydGNwRmJUb0ppbmdsZSA9IGZ1bmN0aW9uIChtZWRpYWluZGV4LCBlbGVtLCBwYXlsb2FkdHlwZSkgeyAvLyBYRVAtMDI5M1xuICAgIHZhciBsaW5lcyA9IFNEUFV0aWwuZmluZF9saW5lcyh0aGlzLm1lZGlhW21lZGlhaW5kZXhdLCAnYT1ydGNwLWZiOicgKyBwYXlsb2FkdHlwZSk7XG4gICAgbGluZXMuZm9yRWFjaChmdW5jdGlvbiAobGluZSkge1xuICAgICAgICB2YXIgdG1wID0gU0RQVXRpbC5wYXJzZV9ydGNwZmIobGluZSk7XG4gICAgICAgIGlmICh0bXAudHlwZSA9PSAndHJyLWludCcpIHtcbiAgICAgICAgICAgIGVsZW0uYygncnRjcC1mYi10cnItaW50Jywge3htbG5zOiAndXJuOnhtcHA6amluZ2xlOmFwcHM6cnRwOnJ0Y3AtZmI6MCcsIHZhbHVlOiB0bXAucGFyYW1zWzBdfSk7XG4gICAgICAgICAgICBlbGVtLnVwKCk7XG4gICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICBlbGVtLmMoJ3J0Y3AtZmInLCB7eG1sbnM6ICd1cm46eG1wcDpqaW5nbGU6YXBwczpydHA6cnRjcC1mYjowJywgdHlwZTogdG1wLnR5cGV9KTtcbiAgICAgICAgICAgIGlmICh0bXAucGFyYW1zLmxlbmd0aCA+IDApIHtcbiAgICAgICAgICAgICAgICBlbGVtLmF0dHJzKHsnc3VidHlwZSc6IHRtcC5wYXJhbXNbMF19KTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgICAgIGVsZW0udXAoKTtcbiAgICAgICAgfVxuICAgIH0pO1xufTtcblxuU0RQLnByb3RvdHlwZS5ydGNwRmJGcm9tSmluZ2xlID0gZnVuY3Rpb24gKGVsZW0sIHBheWxvYWR0eXBlKSB7IC8vIFhFUC0wMjkzXG4gICAgdmFyIG1lZGlhID0gJyc7XG4gICAgdmFyIHRtcCA9IGVsZW0uZmluZCgnPnJ0Y3AtZmItdHJyLWludFt4bWxucz1cInVybjp4bXBwOmppbmdsZTphcHBzOnJ0cDpydGNwLWZiOjBcIl0nKTtcbiAgICBpZiAodG1wLmxlbmd0aCkge1xuICAgICAgICBtZWRpYSArPSAnYT1ydGNwLWZiOicgKyAnKicgKyAnICcgKyAndHJyLWludCcgKyAnICc7XG4gICAgICAgIGlmICh0bXAuYXR0cigndmFsdWUnKSkge1xuICAgICAgICAgICAgbWVkaWEgKz0gdG1wLmF0dHIoJ3ZhbHVlJyk7XG4gICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICBtZWRpYSArPSAnMCc7XG4gICAgICAgIH1cbiAgICAgICAgbWVkaWEgKz0gJ1xcclxcbic7XG4gICAgfVxuICAgIHRtcCA9IGVsZW0uZmluZCgnPnJ0Y3AtZmJbeG1sbnM9XCJ1cm46eG1wcDpqaW5nbGU6YXBwczpydHA6cnRjcC1mYjowXCJdJyk7XG4gICAgdG1wLmVhY2goZnVuY3Rpb24gKCkge1xuICAgICAgICBtZWRpYSArPSAnYT1ydGNwLWZiOicgKyBwYXlsb2FkdHlwZSArICcgJyArICQodGhpcykuYXR0cigndHlwZScpO1xuICAgICAgICBpZiAoJCh0aGlzKS5hdHRyKCdzdWJ0eXBlJykpIHtcbiAgICAgICAgICAgIG1lZGlhICs9ICcgJyArICQodGhpcykuYXR0cignc3VidHlwZScpO1xuICAgICAgICB9XG4gICAgICAgIG1lZGlhICs9ICdcXHJcXG4nO1xuICAgIH0pO1xuICAgIHJldHVybiBtZWRpYTtcbn07XG5cbi8vIGNvbnN0cnVjdCBhbiBTRFAgZnJvbSBhIGppbmdsZSBzdGFuemFcblNEUC5wcm90b3R5cGUuZnJvbUppbmdsZSA9IGZ1bmN0aW9uIChqaW5nbGUpIHtcbiAgICB2YXIgc2VsZiA9IHRoaXM7XG4gICAgdGhpcy5yYXcgPSAndj0wXFxyXFxuJyArXG4gICAgICAgICdvPS0gMTkyMzUxODUxNiAyIElOIElQNCAwLjAuMC4wXFxyXFxuJyArLy8gRklYTUVcbiAgICAgICAgJ3M9LVxcclxcbicgK1xuICAgICAgICAndD0wIDBcXHJcXG4nO1xuICAgIC8vIGh0dHA6Ly90b29scy5pZXRmLm9yZy9odG1sL2RyYWZ0LWlldGYtbW11c2ljLXNkcC1idW5kbGUtbmVnb3RpYXRpb24tMDQjc2VjdGlvbi04XG4gICAgaWYgKCQoamluZ2xlKS5maW5kKCc+Z3JvdXBbeG1sbnM9XCJ1cm46eG1wcDpqaW5nbGU6YXBwczpncm91cGluZzowXCJdJykubGVuZ3RoKSB7XG4gICAgICAgICQoamluZ2xlKS5maW5kKCc+Z3JvdXBbeG1sbnM9XCJ1cm46eG1wcDpqaW5nbGU6YXBwczpncm91cGluZzowXCJdJykuZWFjaChmdW5jdGlvbiAoaWR4LCBncm91cCkge1xuICAgICAgICAgICAgdmFyIGNvbnRlbnRzID0gJChncm91cCkuZmluZCgnPmNvbnRlbnQnKS5tYXAoZnVuY3Rpb24gKGlkeCwgY29udGVudCkge1xuICAgICAgICAgICAgICAgIHJldHVybiBjb250ZW50LmdldEF0dHJpYnV0ZSgnbmFtZScpO1xuICAgICAgICAgICAgfSkuZ2V0KCk7XG4gICAgICAgICAgICBpZiAoY29udGVudHMubGVuZ3RoID4gMCkge1xuICAgICAgICAgICAgICAgIHNlbGYucmF3ICs9ICdhPWdyb3VwOicgKyAoZ3JvdXAuZ2V0QXR0cmlidXRlKCdzZW1hbnRpY3MnKSB8fCBncm91cC5nZXRBdHRyaWJ1dGUoJ3R5cGUnKSkgKyAnICcgKyBjb250ZW50cy5qb2luKCcgJykgKyAnXFxyXFxuJztcbiAgICAgICAgICAgIH1cbiAgICAgICAgfSk7XG4gICAgfVxuXG4gICAgdGhpcy5zZXNzaW9uID0gdGhpcy5yYXc7XG4gICAgamluZ2xlLmZpbmQoJz5jb250ZW50JykuZWFjaChmdW5jdGlvbiAoKSB7XG4gICAgICAgIHZhciBtID0gc2VsZi5qaW5nbGUybWVkaWEoJCh0aGlzKSk7XG4gICAgICAgIHNlbGYubWVkaWEucHVzaChtKTtcbiAgICB9KTtcblxuICAgIC8vIHJlY29uc3RydWN0IG1zaWQtc2VtYW50aWMgLS0gYXBwYXJlbnRseSBub3QgbmVjZXNzYXJ5XG4gICAgLypcbiAgICAgdmFyIG1zaWQgPSBTRFBVdGlsLnBhcnNlX3NzcmModGhpcy5yYXcpO1xuICAgICBpZiAobXNpZC5oYXNPd25Qcm9wZXJ0eSgnbXNsYWJlbCcpKSB7XG4gICAgIHRoaXMuc2Vzc2lvbiArPSBcImE9bXNpZC1zZW1hbnRpYzogV01TIFwiICsgbXNpZC5tc2xhYmVsICsgXCJcXHJcXG5cIjtcbiAgICAgfVxuICAgICAqL1xuXG4gICAgdGhpcy5yYXcgPSB0aGlzLnNlc3Npb24gKyB0aGlzLm1lZGlhLmpvaW4oJycpO1xufTtcblxuLy8gdHJhbnNsYXRlIGEgamluZ2xlIGNvbnRlbnQgZWxlbWVudCBpbnRvIGFuIGFuIFNEUCBtZWRpYSBwYXJ0XG5TRFAucHJvdG90eXBlLmppbmdsZTJtZWRpYSA9IGZ1bmN0aW9uIChjb250ZW50KSB7XG4gICAgdmFyIG1lZGlhID0gJycsXG4gICAgICAgIGRlc2MgPSBjb250ZW50LmZpbmQoJ2Rlc2NyaXB0aW9uJyksXG4gICAgICAgIHNzcmMgPSBkZXNjLmF0dHIoJ3NzcmMnKSxcbiAgICAgICAgc2VsZiA9IHRoaXMsXG4gICAgICAgIHRtcDtcbiAgICB2YXIgc2N0cCA9IGNvbnRlbnQuZmluZChcbiAgICAgICAgJz50cmFuc3BvcnQ+c2N0cG1hcFt4bWxucz1cInVybjp4bXBwOmppbmdsZTp0cmFuc3BvcnRzOmR0bHMtc2N0cDoxXCJdJyk7XG5cbiAgICB0bXAgPSB7IG1lZGlhOiBkZXNjLmF0dHIoJ21lZGlhJykgfTtcbiAgICB0bXAucG9ydCA9ICcxJztcbiAgICBpZiAoY29udGVudC5hdHRyKCdzZW5kZXJzJykgPT0gJ3JlamVjdGVkJykge1xuICAgICAgICAvLyBlc3RvcyBoYWNrIHRvIHJlamVjdCBhbiBtLWxpbmUuXG4gICAgICAgIHRtcC5wb3J0ID0gJzAnO1xuICAgIH1cbiAgICBpZiAoY29udGVudC5maW5kKCc+dHJhbnNwb3J0PmZpbmdlcnByaW50JykubGVuZ3RoIHx8IGRlc2MuZmluZCgnZW5jcnlwdGlvbicpLmxlbmd0aCkge1xuICAgICAgICBpZiAoc2N0cC5sZW5ndGgpXG4gICAgICAgICAgICB0bXAucHJvdG8gPSAnRFRMUy9TQ1RQJztcbiAgICAgICAgZWxzZVxuICAgICAgICAgICAgdG1wLnByb3RvID0gJ1JUUC9TQVZQRic7XG4gICAgfSBlbHNlIHtcbiAgICAgICAgdG1wLnByb3RvID0gJ1JUUC9BVlBGJztcbiAgICB9XG4gICAgaWYgKCFzY3RwLmxlbmd0aCkge1xuICAgICAgICB0bXAuZm10ID0gZGVzYy5maW5kKCdwYXlsb2FkLXR5cGUnKS5tYXAoXG4gICAgICAgICAgICBmdW5jdGlvbiAoKSB7IHJldHVybiB0aGlzLmdldEF0dHJpYnV0ZSgnaWQnKTsgfSkuZ2V0KCk7XG4gICAgICAgIG1lZGlhICs9IFNEUFV0aWwuYnVpbGRfbWxpbmUodG1wKSArICdcXHJcXG4nO1xuICAgIH0gZWxzZSB7XG4gICAgICAgIG1lZGlhICs9ICdtPWFwcGxpY2F0aW9uIDEgRFRMUy9TQ1RQICcgKyBzY3RwLmF0dHIoJ251bWJlcicpICsgJ1xcclxcbic7XG4gICAgICAgIG1lZGlhICs9ICdhPXNjdHBtYXA6JyArIHNjdHAuYXR0cignbnVtYmVyJykgK1xuICAgICAgICAgICAgJyAnICsgc2N0cC5hdHRyKCdwcm90b2NvbCcpO1xuXG4gICAgICAgIHZhciBzdHJlYW1Db3VudCA9IHNjdHAuYXR0cignc3RyZWFtcycpO1xuICAgICAgICBpZiAoc3RyZWFtQ291bnQpXG4gICAgICAgICAgICBtZWRpYSArPSAnICcgKyBzdHJlYW1Db3VudCArICdcXHJcXG4nO1xuICAgICAgICBlbHNlXG4gICAgICAgICAgICBtZWRpYSArPSAnXFxyXFxuJztcbiAgICB9XG5cbiAgICBtZWRpYSArPSAnYz1JTiBJUDQgMC4wLjAuMFxcclxcbic7XG4gICAgaWYgKCFzY3RwLmxlbmd0aClcbiAgICAgICAgbWVkaWEgKz0gJ2E9cnRjcDoxIElOIElQNCAwLjAuMC4wXFxyXFxuJztcbiAgICB0bXAgPSBjb250ZW50LmZpbmQoJz50cmFuc3BvcnRbeG1sbnM9XCJ1cm46eG1wcDpqaW5nbGU6dHJhbnNwb3J0czppY2UtdWRwOjFcIl0nKTtcbiAgICBpZiAodG1wLmxlbmd0aCkge1xuICAgICAgICBpZiAodG1wLmF0dHIoJ3VmcmFnJykpIHtcbiAgICAgICAgICAgIG1lZGlhICs9IFNEUFV0aWwuYnVpbGRfaWNldWZyYWcodG1wLmF0dHIoJ3VmcmFnJykpICsgJ1xcclxcbic7XG4gICAgICAgIH1cbiAgICAgICAgaWYgKHRtcC5hdHRyKCdwd2QnKSkge1xuICAgICAgICAgICAgbWVkaWEgKz0gU0RQVXRpbC5idWlsZF9pY2Vwd2QodG1wLmF0dHIoJ3B3ZCcpKSArICdcXHJcXG4nO1xuICAgICAgICB9XG4gICAgICAgIHRtcC5maW5kKCc+ZmluZ2VycHJpbnQnKS5lYWNoKGZ1bmN0aW9uICgpIHtcbiAgICAgICAgICAgIC8vIEZJWE1FOiBjaGVjayBuYW1lc3BhY2UgYXQgc29tZSBwb2ludFxuICAgICAgICAgICAgbWVkaWEgKz0gJ2E9ZmluZ2VycHJpbnQ6JyArIHRoaXMuZ2V0QXR0cmlidXRlKCdoYXNoJyk7XG4gICAgICAgICAgICBtZWRpYSArPSAnICcgKyAkKHRoaXMpLnRleHQoKTtcbiAgICAgICAgICAgIG1lZGlhICs9ICdcXHJcXG4nO1xuICAgICAgICAgICAgaWYgKHRoaXMuZ2V0QXR0cmlidXRlKCdzZXR1cCcpKSB7XG4gICAgICAgICAgICAgICAgbWVkaWEgKz0gJ2E9c2V0dXA6JyArIHRoaXMuZ2V0QXR0cmlidXRlKCdzZXR1cCcpICsgJ1xcclxcbic7XG4gICAgICAgICAgICB9XG4gICAgICAgIH0pO1xuICAgIH1cbiAgICBzd2l0Y2ggKGNvbnRlbnQuYXR0cignc2VuZGVycycpKSB7XG4gICAgICAgIGNhc2UgJ2luaXRpYXRvcic6XG4gICAgICAgICAgICBtZWRpYSArPSAnYT1zZW5kb25seVxcclxcbic7XG4gICAgICAgICAgICBicmVhaztcbiAgICAgICAgY2FzZSAncmVzcG9uZGVyJzpcbiAgICAgICAgICAgIG1lZGlhICs9ICdhPXJlY3Zvbmx5XFxyXFxuJztcbiAgICAgICAgICAgIGJyZWFrO1xuICAgICAgICBjYXNlICdub25lJzpcbiAgICAgICAgICAgIG1lZGlhICs9ICdhPWluYWN0aXZlXFxyXFxuJztcbiAgICAgICAgICAgIGJyZWFrO1xuICAgICAgICBjYXNlICdib3RoJzpcbiAgICAgICAgICAgIG1lZGlhICs9ICdhPXNlbmRyZWN2XFxyXFxuJztcbiAgICAgICAgICAgIGJyZWFrO1xuICAgIH1cbiAgICBtZWRpYSArPSAnYT1taWQ6JyArIGNvbnRlbnQuYXR0cignbmFtZScpICsgJ1xcclxcbic7XG5cbiAgICAvLyA8ZGVzY3JpcHRpb24+PHJ0Y3AtbXV4Lz48L2Rlc2NyaXB0aW9uPlxuICAgIC8vIHNlZSBodHRwOi8vY29kZS5nb29nbGUuY29tL3AvbGliamluZ2xlL2lzc3Vlcy9kZXRhaWw/aWQ9MzA5IC0tIG5vIHNwZWMgdGhvdWdoXG4gICAgLy8gYW5kIGh0dHA6Ly9tYWlsLmphYmJlci5vcmcvcGlwZXJtYWlsL2ppbmdsZS8yMDExLURlY2VtYmVyLzAwMTc2MS5odG1sXG4gICAgaWYgKGRlc2MuZmluZCgncnRjcC1tdXgnKS5sZW5ndGgpIHtcbiAgICAgICAgbWVkaWEgKz0gJ2E9cnRjcC1tdXhcXHJcXG4nO1xuICAgIH1cblxuICAgIGlmIChkZXNjLmZpbmQoJ2VuY3J5cHRpb24nKS5sZW5ndGgpIHtcbiAgICAgICAgZGVzYy5maW5kKCdlbmNyeXB0aW9uPmNyeXB0bycpLmVhY2goZnVuY3Rpb24gKCkge1xuICAgICAgICAgICAgbWVkaWEgKz0gJ2E9Y3J5cHRvOicgKyB0aGlzLmdldEF0dHJpYnV0ZSgndGFnJyk7XG4gICAgICAgICAgICBtZWRpYSArPSAnICcgKyB0aGlzLmdldEF0dHJpYnV0ZSgnY3J5cHRvLXN1aXRlJyk7XG4gICAgICAgICAgICBtZWRpYSArPSAnICcgKyB0aGlzLmdldEF0dHJpYnV0ZSgna2V5LXBhcmFtcycpO1xuICAgICAgICAgICAgaWYgKHRoaXMuZ2V0QXR0cmlidXRlKCdzZXNzaW9uLXBhcmFtcycpKSB7XG4gICAgICAgICAgICAgICAgbWVkaWEgKz0gJyAnICsgdGhpcy5nZXRBdHRyaWJ1dGUoJ3Nlc3Npb24tcGFyYW1zJyk7XG4gICAgICAgICAgICB9XG4gICAgICAgICAgICBtZWRpYSArPSAnXFxyXFxuJztcbiAgICAgICAgfSk7XG4gICAgfVxuICAgIGRlc2MuZmluZCgncGF5bG9hZC10eXBlJykuZWFjaChmdW5jdGlvbiAoKSB7XG4gICAgICAgIG1lZGlhICs9IFNEUFV0aWwuYnVpbGRfcnRwbWFwKHRoaXMpICsgJ1xcclxcbic7XG4gICAgICAgIGlmICgkKHRoaXMpLmZpbmQoJz5wYXJhbWV0ZXInKS5sZW5ndGgpIHtcbiAgICAgICAgICAgIG1lZGlhICs9ICdhPWZtdHA6JyArIHRoaXMuZ2V0QXR0cmlidXRlKCdpZCcpICsgJyAnO1xuICAgICAgICAgICAgbWVkaWEgKz0gJCh0aGlzKS5maW5kKCdwYXJhbWV0ZXInKS5tYXAoZnVuY3Rpb24gKCkge1xuICAgICAgICAgICAgICAgIHJldHVybiAodGhpcy5nZXRBdHRyaWJ1dGUoJ25hbWUnKVxuICAgICAgICAgICAgICAgICAgICAgICAgPyAodGhpcy5nZXRBdHRyaWJ1dGUoJ25hbWUnKSArICc9JykgOiAnJykgK1xuICAgICAgICAgICAgICAgICAgICB0aGlzLmdldEF0dHJpYnV0ZSgndmFsdWUnKTtcbiAgICAgICAgICAgIH0pLmdldCgpLmpvaW4oJzsgJyk7XG4gICAgICAgICAgICBtZWRpYSArPSAnXFxyXFxuJztcbiAgICAgICAgfVxuICAgICAgICAvLyB4ZXAtMDI5M1xuICAgICAgICBtZWRpYSArPSBzZWxmLnJ0Y3BGYkZyb21KaW5nbGUoJCh0aGlzKSwgdGhpcy5nZXRBdHRyaWJ1dGUoJ2lkJykpO1xuICAgIH0pO1xuXG4gICAgLy8geGVwLTAyOTNcbiAgICBtZWRpYSArPSBzZWxmLnJ0Y3BGYkZyb21KaW5nbGUoZGVzYywgJyonKTtcblxuICAgIC8vIHhlcC0wMjk0XG4gICAgdG1wID0gZGVzYy5maW5kKCc+cnRwLWhkcmV4dFt4bWxucz1cInVybjp4bXBwOmppbmdsZTphcHBzOnJ0cDpydHAtaGRyZXh0OjBcIl0nKTtcbiAgICB0bXAuZWFjaChmdW5jdGlvbiAoKSB7XG4gICAgICAgIG1lZGlhICs9ICdhPWV4dG1hcDonICsgdGhpcy5nZXRBdHRyaWJ1dGUoJ2lkJykgKyAnICcgKyB0aGlzLmdldEF0dHJpYnV0ZSgndXJpJykgKyAnXFxyXFxuJztcbiAgICB9KTtcblxuICAgIGNvbnRlbnQuZmluZCgnPnRyYW5zcG9ydFt4bWxucz1cInVybjp4bXBwOmppbmdsZTp0cmFuc3BvcnRzOmljZS11ZHA6MVwiXT5jYW5kaWRhdGUnKS5lYWNoKGZ1bmN0aW9uICgpIHtcbiAgICAgICAgdmFyIHByb3RvY29sID0gdGhpcy5nZXRBdHRyaWJ1dGUoJ3Byb3RvY29sJyk7XG4gICAgICAgIHByb3RvY29sID0gKHR5cGVvZiBwcm90b2NvbCA9PT0gJ3N0cmluZycpID8gcHJvdG9jb2wudG9Mb3dlckNhc2UoKTogJyc7XG5cbiAgICAgICAgaWYgKChzZWxmLnJlbW92ZVRjcENhbmRpZGF0ZXMgJiYgcHJvdG9jb2wgPT09ICd0Y3AnKSB8fFxuICAgICAgICAgICAgKHNlbGYucmVtb3ZlVWRwQ2FuZGlkYXRlcyAmJiBwcm90b2NvbCA9PT0gJ3VkcCcpKSB7XG4gICAgICAgICAgICByZXR1cm47XG4gICAgICAgIH1cblxuICAgICAgICBtZWRpYSArPSBTRFBVdGlsLmNhbmRpZGF0ZUZyb21KaW5nbGUodGhpcyk7XG4gICAgfSk7XG5cbiAgICAvLyBYRVAtMDMzOSBoYW5kbGUgc3NyYy1ncm91cCBhdHRyaWJ1dGVzXG4gICAgY29udGVudC5maW5kKCdkZXNjcmlwdGlvbj5zc3JjLWdyb3VwW3htbG5zPVwidXJuOnhtcHA6amluZ2xlOmFwcHM6cnRwOnNzbWE6MFwiXScpLmVhY2goZnVuY3Rpb24oKSB7XG4gICAgICAgIHZhciBzZW1hbnRpY3MgPSB0aGlzLmdldEF0dHJpYnV0ZSgnc2VtYW50aWNzJyk7XG4gICAgICAgIHZhciBzc3JjcyA9ICQodGhpcykuZmluZCgnPnNvdXJjZScpLm1hcChmdW5jdGlvbigpIHtcbiAgICAgICAgICAgIHJldHVybiB0aGlzLmdldEF0dHJpYnV0ZSgnc3NyYycpO1xuICAgICAgICB9KS5nZXQoKTtcblxuICAgICAgICBpZiAoc3NyY3MubGVuZ3RoKSB7XG4gICAgICAgICAgICBtZWRpYSArPSAnYT1zc3JjLWdyb3VwOicgKyBzZW1hbnRpY3MgKyAnICcgKyBzc3Jjcy5qb2luKCcgJykgKyAnXFxyXFxuJztcbiAgICAgICAgfVxuICAgIH0pO1xuXG4gICAgdG1wID0gY29udGVudC5maW5kKCdkZXNjcmlwdGlvbj5zb3VyY2VbeG1sbnM9XCJ1cm46eG1wcDpqaW5nbGU6YXBwczpydHA6c3NtYTowXCJdJyk7XG4gICAgdG1wLmVhY2goZnVuY3Rpb24gKCkge1xuICAgICAgICB2YXIgc3NyYyA9IHRoaXMuZ2V0QXR0cmlidXRlKCdzc3JjJyk7XG4gICAgICAgICQodGhpcykuZmluZCgnPnBhcmFtZXRlcicpLmVhY2goZnVuY3Rpb24gKCkge1xuICAgICAgICAgICAgdmFyIG5hbWUgPSB0aGlzLmdldEF0dHJpYnV0ZSgnbmFtZScpO1xuICAgICAgICAgICAgdmFyIHZhbHVlID0gdGhpcy5nZXRBdHRyaWJ1dGUoJ3ZhbHVlJyk7XG4gICAgICAgICAgICB2YWx1ZSA9IFNEUFV0aWwuZmlsdGVyX3NwZWNpYWxfY2hhcnModmFsdWUpO1xuICAgICAgICAgICAgbWVkaWEgKz0gJ2E9c3NyYzonICsgc3NyYyArICcgJyArIG5hbWU7XG4gICAgICAgICAgICBpZiAodmFsdWUgJiYgdmFsdWUubGVuZ3RoKVxuICAgICAgICAgICAgICAgIG1lZGlhICs9ICc6JyArIHZhbHVlO1xuICAgICAgICAgICAgbWVkaWEgKz0gJ1xcclxcbic7XG4gICAgICAgIH0pO1xuICAgIH0pO1xuXG4gICAgcmV0dXJuIG1lZGlhO1xufTtcblxuXG5tb2R1bGUuZXhwb3J0cyA9IFNEUDtcbiIsInZhciBTRFBVdGlsID0gcmVxdWlyZShcIi4vU0RQVXRpbFwiKTtcblxuZnVuY3Rpb24gU0RQRGlmZmVyKG15U0RQLCBvdGhlclNEUClcbntcbiAgICB0aGlzLm15U0RQID0gbXlTRFA7XG4gICAgdGhpcy5vdGhlclNEUCA9IG90aGVyU0RQO1xufVxuXG4vKipcbiAqIFJldHVybnMgbWFwIG9mIE1lZGlhQ2hhbm5lbCB0aGF0IGNvbnRhaW5zIG1lZGlhIGNvbnRhaW5lZCBpblxuICogJ215U0RQJywgYnV0IG5vdCBjb250YWluZWQgaW4gJ290aGVyU2RwJy4gTWFwcGVkIGJ5IGNoYW5uZWwgaWR4LlxuICovXG5TRFBEaWZmZXIucHJvdG90eXBlLmdldE5ld01lZGlhID0gZnVuY3Rpb24oKSB7XG5cbiAgICAvLyB0aGlzIGNvdWxkIGJlIHVzZWZ1bCBpbiBBcnJheS5wcm90b3R5cGUuXG4gICAgZnVuY3Rpb24gYXJyYXlFcXVhbHMoYXJyYXkpIHtcbiAgICAgICAgLy8gaWYgdGhlIG90aGVyIGFycmF5IGlzIGEgZmFsc3kgdmFsdWUsIHJldHVyblxuICAgICAgICBpZiAoIWFycmF5KVxuICAgICAgICAgICAgcmV0dXJuIGZhbHNlO1xuXG4gICAgICAgIC8vIGNvbXBhcmUgbGVuZ3RocyAtIGNhbiBzYXZlIGEgbG90IG9mIHRpbWVcbiAgICAgICAgaWYgKHRoaXMubGVuZ3RoICE9IGFycmF5Lmxlbmd0aClcbiAgICAgICAgICAgIHJldHVybiBmYWxzZTtcblxuICAgICAgICBmb3IgKHZhciBpID0gMCwgbD10aGlzLmxlbmd0aDsgaSA8IGw7IGkrKykge1xuICAgICAgICAgICAgLy8gQ2hlY2sgaWYgd2UgaGF2ZSBuZXN0ZWQgYXJyYXlzXG4gICAgICAgICAgICBpZiAodGhpc1tpXSBpbnN0YW5jZW9mIEFycmF5ICYmIGFycmF5W2ldIGluc3RhbmNlb2YgQXJyYXkpIHtcbiAgICAgICAgICAgICAgICAvLyByZWN1cnNlIGludG8gdGhlIG5lc3RlZCBhcnJheXNcbiAgICAgICAgICAgICAgICBpZiAoIXRoaXNbaV0uZXF1YWxzKGFycmF5W2ldKSlcbiAgICAgICAgICAgICAgICAgICAgcmV0dXJuIGZhbHNlO1xuICAgICAgICAgICAgfVxuICAgICAgICAgICAgZWxzZSBpZiAodGhpc1tpXSAhPSBhcnJheVtpXSkge1xuICAgICAgICAgICAgICAgIC8vIFdhcm5pbmcgLSB0d28gZGlmZmVyZW50IG9iamVjdCBpbnN0YW5jZXMgd2lsbCBuZXZlciBiZVxuICAgICAgICAgICAgICAgIC8vIGVxdWFsOiB7eDoyMH0gIT0ge3g6MjB9XG4gICAgICAgICAgICAgICAgcmV0dXJuIGZhbHNlO1xuICAgICAgICAgICAgfVxuICAgICAgICB9XG4gICAgICAgIHJldHVybiB0cnVlO1xuICAgIH1cblxuICAgIHZhciBteU1lZGlhcyA9IHRoaXMubXlTRFAuZ2V0TWVkaWFTc3JjTWFwKCk7XG4gICAgdmFyIG90aGVyc01lZGlhcyA9IHRoaXMub3RoZXJTRFAuZ2V0TWVkaWFTc3JjTWFwKCk7XG4gICAgdmFyIG5ld01lZGlhID0ge307XG4gICAgT2JqZWN0LmtleXMob3RoZXJzTWVkaWFzKS5mb3JFYWNoKGZ1bmN0aW9uKG90aGVyc01lZGlhSWR4KSB7XG4gICAgICAgIHZhciBteU1lZGlhID0gbXlNZWRpYXNbb3RoZXJzTWVkaWFJZHhdO1xuICAgICAgICB2YXIgb3RoZXJzTWVkaWEgPSBvdGhlcnNNZWRpYXNbb3RoZXJzTWVkaWFJZHhdO1xuICAgICAgICBpZighbXlNZWRpYSAmJiBvdGhlcnNNZWRpYSkge1xuICAgICAgICAgICAgLy8gQWRkIHdob2xlIGNoYW5uZWxcbiAgICAgICAgICAgIG5ld01lZGlhW290aGVyc01lZGlhSWR4XSA9IG90aGVyc01lZGlhO1xuICAgICAgICAgICAgcmV0dXJuO1xuICAgICAgICB9XG4gICAgICAgIC8vIExvb2sgZm9yIG5ldyBzc3JjcyBhY3Jvc3MgdGhlIGNoYW5uZWxcbiAgICAgICAgT2JqZWN0LmtleXMob3RoZXJzTWVkaWEuc3NyY3MpLmZvckVhY2goZnVuY3Rpb24oc3NyYykge1xuICAgICAgICAgICAgaWYoT2JqZWN0LmtleXMobXlNZWRpYS5zc3JjcykuaW5kZXhPZihzc3JjKSA9PT0gLTEpIHtcbiAgICAgICAgICAgICAgICAvLyBBbGxvY2F0ZSBjaGFubmVsIGlmIHdlJ3ZlIGZvdW5kIHNzcmMgdGhhdCBkb2Vzbid0IGV4aXN0IGluXG4gICAgICAgICAgICAgICAgLy8gb3VyIGNoYW5uZWxcbiAgICAgICAgICAgICAgICBpZighbmV3TWVkaWFbb3RoZXJzTWVkaWFJZHhdKXtcbiAgICAgICAgICAgICAgICAgICAgbmV3TWVkaWFbb3RoZXJzTWVkaWFJZHhdID0ge1xuICAgICAgICAgICAgICAgICAgICAgICAgbWVkaWFpbmRleDogb3RoZXJzTWVkaWEubWVkaWFpbmRleCxcbiAgICAgICAgICAgICAgICAgICAgICAgIG1pZDogb3RoZXJzTWVkaWEubWlkLFxuICAgICAgICAgICAgICAgICAgICAgICAgc3NyY3M6IHt9LFxuICAgICAgICAgICAgICAgICAgICAgICAgc3NyY0dyb3VwczogW11cbiAgICAgICAgICAgICAgICAgICAgfTtcbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgbmV3TWVkaWFbb3RoZXJzTWVkaWFJZHhdLnNzcmNzW3NzcmNdID0gb3RoZXJzTWVkaWEuc3NyY3Nbc3NyY107XG4gICAgICAgICAgICB9XG4gICAgICAgIH0pO1xuXG4gICAgICAgIC8vIExvb2sgZm9yIG5ldyBzc3JjIGdyb3VwcyBhY3Jvc3MgdGhlIGNoYW5uZWxzXG4gICAgICAgIG90aGVyc01lZGlhLnNzcmNHcm91cHMuZm9yRWFjaChmdW5jdGlvbihvdGhlclNzcmNHcm91cCl7XG5cbiAgICAgICAgICAgIC8vIHRyeSB0byBtYXRjaCB0aGUgb3RoZXIgc3NyYy1ncm91cCB3aXRoIGFuIHNzcmMtZ3JvdXAgb2Ygb3Vyc1xuICAgICAgICAgICAgdmFyIG1hdGNoZWQgPSBmYWxzZTtcbiAgICAgICAgICAgIGZvciAodmFyIGkgPSAwOyBpIDwgbXlNZWRpYS5zc3JjR3JvdXBzLmxlbmd0aDsgaSsrKSB7XG4gICAgICAgICAgICAgICAgdmFyIG15U3NyY0dyb3VwID0gbXlNZWRpYS5zc3JjR3JvdXBzW2ldO1xuICAgICAgICAgICAgICAgIGlmIChvdGhlclNzcmNHcm91cC5zZW1hbnRpY3MgPT0gbXlTc3JjR3JvdXAuc2VtYW50aWNzICYmXG4gICAgICAgICAgICAgICAgICAgIGFycmF5RXF1YWxzLmFwcGx5KG90aGVyU3NyY0dyb3VwLnNzcmNzLFxuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBbbXlTc3JjR3JvdXAuc3NyY3NdKSkge1xuXG4gICAgICAgICAgICAgICAgICAgIG1hdGNoZWQgPSB0cnVlO1xuICAgICAgICAgICAgICAgICAgICBicmVhaztcbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICB9XG5cbiAgICAgICAgICAgIGlmICghbWF0Y2hlZCkge1xuICAgICAgICAgICAgICAgIC8vIEFsbG9jYXRlIGNoYW5uZWwgaWYgd2UndmUgZm91bmQgYW4gc3NyYy1ncm91cCB0aGF0IGRvZXNuJ3RcbiAgICAgICAgICAgICAgICAvLyBleGlzdCBpbiBvdXIgY2hhbm5lbFxuXG4gICAgICAgICAgICAgICAgaWYoIW5ld01lZGlhW290aGVyc01lZGlhSWR4XSl7XG4gICAgICAgICAgICAgICAgICAgIG5ld01lZGlhW290aGVyc01lZGlhSWR4XSA9IHtcbiAgICAgICAgICAgICAgICAgICAgICAgIG1lZGlhaW5kZXg6IG90aGVyc01lZGlhLm1lZGlhaW5kZXgsXG4gICAgICAgICAgICAgICAgICAgICAgICBtaWQ6IG90aGVyc01lZGlhLm1pZCxcbiAgICAgICAgICAgICAgICAgICAgICAgIHNzcmNzOiB7fSxcbiAgICAgICAgICAgICAgICAgICAgICAgIHNzcmNHcm91cHM6IFtdXG4gICAgICAgICAgICAgICAgICAgIH07XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgIG5ld01lZGlhW290aGVyc01lZGlhSWR4XS5zc3JjR3JvdXBzLnB1c2gob3RoZXJTc3JjR3JvdXApO1xuICAgICAgICAgICAgfVxuICAgICAgICB9KTtcbiAgICB9KTtcbiAgICByZXR1cm4gbmV3TWVkaWE7XG59O1xuXG4vKipcbiAqIFRPRE86IGRvY3VtZW50IVxuICovXG5TRFBEaWZmZXIucHJvdG90eXBlLnRvSmluZ2xlID0gZnVuY3Rpb24obW9kaWZ5KSB7XG4gICAgdmFyIHNkcE1lZGlhU3NyY3MgPSB0aGlzLmdldE5ld01lZGlhKCk7XG5cbiAgICB2YXIgbW9kaWZpZWQgPSBmYWxzZTtcbiAgICBPYmplY3Qua2V5cyhzZHBNZWRpYVNzcmNzKS5mb3JFYWNoKGZ1bmN0aW9uKG1lZGlhaW5kZXgpe1xuICAgICAgICBtb2RpZmllZCA9IHRydWU7XG4gICAgICAgIHZhciBtZWRpYSA9IHNkcE1lZGlhU3NyY3NbbWVkaWFpbmRleF07XG4gICAgICAgIG1vZGlmeS5jKCdjb250ZW50Jywge25hbWU6IG1lZGlhLm1pZH0pO1xuXG4gICAgICAgIG1vZGlmeS5jKCdkZXNjcmlwdGlvbicsXG4gICAgICAgICAgICAgICAgIHt4bWxuczondXJuOnhtcHA6amluZ2xlOmFwcHM6cnRwOjEnLCBtZWRpYTogbWVkaWEubWlkfSk7XG4gICAgICAgIC8vIEZJWE1FOiBub3QgY29tcGxldGVseSBzdXJlIHRoaXMgb3BlcmF0ZXMgb24gYmxvY2tzIGFuZCAvIG9yIGhhbmRsZXNcbiAgICAgICAgLy8gZGlmZmVyZW50IHNzcmNzIGNvcnJlY3RseVxuICAgICAgICAvLyBnZW5lcmF0ZSBzb3VyY2VzIGZyb20gbGluZXNcbiAgICAgICAgT2JqZWN0LmtleXMobWVkaWEuc3NyY3MpLmZvckVhY2goZnVuY3Rpb24oc3NyY051bSkge1xuICAgICAgICAgICAgdmFyIG1lZGlhU3NyYyA9IG1lZGlhLnNzcmNzW3NzcmNOdW1dO1xuICAgICAgICAgICAgbW9kaWZ5LmMoJ3NvdXJjZScsIHsgeG1sbnM6ICd1cm46eG1wcDpqaW5nbGU6YXBwczpydHA6c3NtYTowJyB9KTtcbiAgICAgICAgICAgIG1vZGlmeS5hdHRycyh7c3NyYzogbWVkaWFTc3JjLnNzcmN9KTtcbiAgICAgICAgICAgIC8vIGl0ZXJhdGUgb3ZlciBzc3JjIGxpbmVzXG4gICAgICAgICAgICBtZWRpYVNzcmMubGluZXMuZm9yRWFjaChmdW5jdGlvbiAobGluZSkge1xuICAgICAgICAgICAgICAgIHZhciBpZHggPSBsaW5lLmluZGV4T2YoJyAnKTtcbiAgICAgICAgICAgICAgICB2YXIga3YgPSBsaW5lLnN1YnN0cihpZHggKyAxKTtcbiAgICAgICAgICAgICAgICBtb2RpZnkuYygncGFyYW1ldGVyJyk7XG4gICAgICAgICAgICAgICAgaWYgKGt2LmluZGV4T2YoJzonKSA9PSAtMSkge1xuICAgICAgICAgICAgICAgICAgICBtb2RpZnkuYXR0cnMoeyBuYW1lOiBrdiB9KTtcbiAgICAgICAgICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgICAgICAgICB2YXIgbnYgPSBrdi5zcGxpdCgnOicsIDIpO1xuICAgICAgICAgICAgICAgICAgICB2YXIgbmFtZSA9IG52WzBdO1xuICAgICAgICAgICAgICAgICAgICB2YXIgdmFsdWUgPSBTRFBVdGlsLmZpbHRlcl9zcGVjaWFsX2NoYXJzKG52WzFdKTtcbiAgICAgICAgICAgICAgICAgICAgbW9kaWZ5LmF0dHJzKHsgbmFtZTogbmFtZSB9KTtcbiAgICAgICAgICAgICAgICAgICAgbW9kaWZ5LmF0dHJzKHsgdmFsdWU6IHZhbHVlIH0pO1xuICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICBtb2RpZnkudXAoKTsgLy8gZW5kIG9mIHBhcmFtZXRlclxuICAgICAgICAgICAgfSk7XG4gICAgICAgICAgICBtb2RpZnkudXAoKTsgLy8gZW5kIG9mIHNvdXJjZVxuICAgICAgICB9KTtcblxuICAgICAgICAvLyBnZW5lcmF0ZSBzb3VyY2UgZ3JvdXBzIGZyb20gbGluZXNcbiAgICAgICAgbWVkaWEuc3NyY0dyb3Vwcy5mb3JFYWNoKGZ1bmN0aW9uKHNzcmNHcm91cCkge1xuICAgICAgICAgICAgaWYgKHNzcmNHcm91cC5zc3Jjcy5sZW5ndGgpIHtcblxuICAgICAgICAgICAgICAgIG1vZGlmeS5jKCdzc3JjLWdyb3VwJywge1xuICAgICAgICAgICAgICAgICAgICBzZW1hbnRpY3M6IHNzcmNHcm91cC5zZW1hbnRpY3MsXG4gICAgICAgICAgICAgICAgICAgIHhtbG5zOiAndXJuOnhtcHA6amluZ2xlOmFwcHM6cnRwOnNzbWE6MCdcbiAgICAgICAgICAgICAgICB9KTtcblxuICAgICAgICAgICAgICAgIHNzcmNHcm91cC5zc3Jjcy5mb3JFYWNoKGZ1bmN0aW9uIChzc3JjKSB7XG4gICAgICAgICAgICAgICAgICAgIG1vZGlmeS5jKCdzb3VyY2UnLCB7IHNzcmM6IHNzcmMgfSlcbiAgICAgICAgICAgICAgICAgICAgICAgIC51cCgpOyAvLyBlbmQgb2Ygc291cmNlXG4gICAgICAgICAgICAgICAgfSk7XG4gICAgICAgICAgICAgICAgbW9kaWZ5LnVwKCk7IC8vIGVuZCBvZiBzc3JjLWdyb3VwXG4gICAgICAgICAgICB9XG4gICAgICAgIH0pO1xuXG4gICAgICAgIG1vZGlmeS51cCgpOyAvLyBlbmQgb2YgZGVzY3JpcHRpb25cbiAgICAgICAgbW9kaWZ5LnVwKCk7IC8vIGVuZCBvZiBjb250ZW50XG4gICAgfSk7XG5cbiAgICByZXR1cm4gbW9kaWZpZWQ7XG59O1xuXG5tb2R1bGUuZXhwb3J0cyA9IFNEUERpZmZlcjsiLCJ2YXIgbG9nZ2VyID0gcmVxdWlyZShcImppdHNpLW1lZXQtbG9nZ2VyXCIpLmdldExvZ2dlcihfX2ZpbGVuYW1lKTtcbnZhciBSVENCcm93c2VyVHlwZSA9IHJlcXVpcmUoXCIuLi9SVEMvUlRDQnJvd3NlclR5cGVcIik7XG5cblxuU0RQVXRpbCA9IHtcbiAgICBmaWx0ZXJfc3BlY2lhbF9jaGFyczogZnVuY3Rpb24gKHRleHQpIHtcbiAgICAgICAgcmV0dXJuIHRleHQucmVwbGFjZSgvW1xcXFxcXC9cXHssXFx9XFwrXS9nLCBcIlwiKTtcbiAgICB9LFxuICAgIGljZXBhcmFtczogZnVuY3Rpb24gKG1lZGlhZGVzYywgc2Vzc2lvbmRlc2MpIHtcbiAgICAgICAgdmFyIGRhdGEgPSBudWxsO1xuICAgICAgICBpZiAoU0RQVXRpbC5maW5kX2xpbmUobWVkaWFkZXNjLCAnYT1pY2UtdWZyYWc6Jywgc2Vzc2lvbmRlc2MpICYmXG4gICAgICAgICAgICBTRFBVdGlsLmZpbmRfbGluZShtZWRpYWRlc2MsICdhPWljZS1wd2Q6Jywgc2Vzc2lvbmRlc2MpKSB7XG4gICAgICAgICAgICBkYXRhID0ge1xuICAgICAgICAgICAgICAgIHVmcmFnOiBTRFBVdGlsLnBhcnNlX2ljZXVmcmFnKFNEUFV0aWwuZmluZF9saW5lKG1lZGlhZGVzYywgJ2E9aWNlLXVmcmFnOicsIHNlc3Npb25kZXNjKSksXG4gICAgICAgICAgICAgICAgcHdkOiBTRFBVdGlsLnBhcnNlX2ljZXB3ZChTRFBVdGlsLmZpbmRfbGluZShtZWRpYWRlc2MsICdhPWljZS1wd2Q6Jywgc2Vzc2lvbmRlc2MpKVxuICAgICAgICAgICAgfTtcbiAgICAgICAgfVxuICAgICAgICByZXR1cm4gZGF0YTtcbiAgICB9LFxuICAgIHBhcnNlX2ljZXVmcmFnOiBmdW5jdGlvbiAobGluZSkge1xuICAgICAgICByZXR1cm4gbGluZS5zdWJzdHJpbmcoMTIpO1xuICAgIH0sXG4gICAgYnVpbGRfaWNldWZyYWc6IGZ1bmN0aW9uIChmcmFnKSB7XG4gICAgICAgIHJldHVybiAnYT1pY2UtdWZyYWc6JyArIGZyYWc7XG4gICAgfSxcbiAgICBwYXJzZV9pY2Vwd2Q6IGZ1bmN0aW9uIChsaW5lKSB7XG4gICAgICAgIHJldHVybiBsaW5lLnN1YnN0cmluZygxMCk7XG4gICAgfSxcbiAgICBidWlsZF9pY2Vwd2Q6IGZ1bmN0aW9uIChwd2QpIHtcbiAgICAgICAgcmV0dXJuICdhPWljZS1wd2Q6JyArIHB3ZDtcbiAgICB9LFxuICAgIHBhcnNlX21pZDogZnVuY3Rpb24gKGxpbmUpIHtcbiAgICAgICAgcmV0dXJuIGxpbmUuc3Vic3RyaW5nKDYpO1xuICAgIH0sXG4gICAgcGFyc2VfbWxpbmU6IGZ1bmN0aW9uIChsaW5lKSB7XG4gICAgICAgIHZhciBwYXJ0cyA9IGxpbmUuc3Vic3RyaW5nKDIpLnNwbGl0KCcgJyksXG4gICAgICAgICAgICBkYXRhID0ge307XG4gICAgICAgIGRhdGEubWVkaWEgPSBwYXJ0cy5zaGlmdCgpO1xuICAgICAgICBkYXRhLnBvcnQgPSBwYXJ0cy5zaGlmdCgpO1xuICAgICAgICBkYXRhLnByb3RvID0gcGFydHMuc2hpZnQoKTtcbiAgICAgICAgaWYgKHBhcnRzW3BhcnRzLmxlbmd0aCAtIDFdID09PSAnJykgeyAvLyB0cmFpbGluZyB3aGl0ZXNwYWNlXG4gICAgICAgICAgICBwYXJ0cy5wb3AoKTtcbiAgICAgICAgfVxuICAgICAgICBkYXRhLmZtdCA9IHBhcnRzO1xuICAgICAgICByZXR1cm4gZGF0YTtcbiAgICB9LFxuICAgIGJ1aWxkX21saW5lOiBmdW5jdGlvbiAobWxpbmUpIHtcbiAgICAgICAgcmV0dXJuICdtPScgKyBtbGluZS5tZWRpYSArICcgJyArIG1saW5lLnBvcnQgKyAnICcgKyBtbGluZS5wcm90byArICcgJyArIG1saW5lLmZtdC5qb2luKCcgJyk7XG4gICAgfSxcbiAgICBwYXJzZV9ydHBtYXA6IGZ1bmN0aW9uIChsaW5lKSB7XG4gICAgICAgIHZhciBwYXJ0cyA9IGxpbmUuc3Vic3RyaW5nKDkpLnNwbGl0KCcgJyksXG4gICAgICAgICAgICBkYXRhID0ge307XG4gICAgICAgIGRhdGEuaWQgPSBwYXJ0cy5zaGlmdCgpO1xuICAgICAgICBwYXJ0cyA9IHBhcnRzWzBdLnNwbGl0KCcvJyk7XG4gICAgICAgIGRhdGEubmFtZSA9IHBhcnRzLnNoaWZ0KCk7XG4gICAgICAgIGRhdGEuY2xvY2tyYXRlID0gcGFydHMuc2hpZnQoKTtcbiAgICAgICAgZGF0YS5jaGFubmVscyA9IHBhcnRzLmxlbmd0aCA/IHBhcnRzLnNoaWZ0KCkgOiAnMSc7XG4gICAgICAgIHJldHVybiBkYXRhO1xuICAgIH0sXG4gICAgLyoqXG4gICAgICogUGFyc2VzIFNEUCBsaW5lIFwiYT1zY3RwbWFwOi4uLlwiIGFuZCBleHRyYWN0cyBTQ1RQIHBvcnQgZnJvbSBpdC5cbiAgICAgKiBAcGFyYW0gbGluZSBlZy4gXCJhPXNjdHBtYXA6NTAwMCB3ZWJydGMtZGF0YWNoYW5uZWxcIlxuICAgICAqIEByZXR1cm5zIFtTQ1RQIHBvcnQgbnVtYmVyLCBwcm90b2NvbCwgc3RyZWFtc11cbiAgICAgKi9cbiAgICBwYXJzZV9zY3RwbWFwOiBmdW5jdGlvbiAobGluZSlcbiAgICB7XG4gICAgICAgIHZhciBwYXJ0cyA9IGxpbmUuc3Vic3RyaW5nKDEwKS5zcGxpdCgnICcpO1xuICAgICAgICB2YXIgc2N0cFBvcnQgPSBwYXJ0c1swXTtcbiAgICAgICAgdmFyIHByb3RvY29sID0gcGFydHNbMV07XG4gICAgICAgIC8vIFN0cmVhbSBjb3VudCBpcyBvcHRpb25hbFxuICAgICAgICB2YXIgc3RyZWFtQ291bnQgPSBwYXJ0cy5sZW5ndGggPiAyID8gcGFydHNbMl0gOiBudWxsO1xuICAgICAgICByZXR1cm4gW3NjdHBQb3J0LCBwcm90b2NvbCwgc3RyZWFtQ291bnRdOy8vIFNDVFAgcG9ydFxuICAgIH0sXG4gICAgYnVpbGRfcnRwbWFwOiBmdW5jdGlvbiAoZWwpIHtcbiAgICAgICAgdmFyIGxpbmUgPSAnYT1ydHBtYXA6JyArIGVsLmdldEF0dHJpYnV0ZSgnaWQnKSArICcgJyArIGVsLmdldEF0dHJpYnV0ZSgnbmFtZScpICsgJy8nICsgZWwuZ2V0QXR0cmlidXRlKCdjbG9ja3JhdGUnKTtcbiAgICAgICAgaWYgKGVsLmdldEF0dHJpYnV0ZSgnY2hhbm5lbHMnKSAmJiBlbC5nZXRBdHRyaWJ1dGUoJ2NoYW5uZWxzJykgIT0gJzEnKSB7XG4gICAgICAgICAgICBsaW5lICs9ICcvJyArIGVsLmdldEF0dHJpYnV0ZSgnY2hhbm5lbHMnKTtcbiAgICAgICAgfVxuICAgICAgICByZXR1cm4gbGluZTtcbiAgICB9LFxuICAgIHBhcnNlX2NyeXB0bzogZnVuY3Rpb24gKGxpbmUpIHtcbiAgICAgICAgdmFyIHBhcnRzID0gbGluZS5zdWJzdHJpbmcoOSkuc3BsaXQoJyAnKSxcbiAgICAgICAgICAgIGRhdGEgPSB7fTtcbiAgICAgICAgZGF0YS50YWcgPSBwYXJ0cy5zaGlmdCgpO1xuICAgICAgICBkYXRhWydjcnlwdG8tc3VpdGUnXSA9IHBhcnRzLnNoaWZ0KCk7XG4gICAgICAgIGRhdGFbJ2tleS1wYXJhbXMnXSA9IHBhcnRzLnNoaWZ0KCk7XG4gICAgICAgIGlmIChwYXJ0cy5sZW5ndGgpIHtcbiAgICAgICAgICAgIGRhdGFbJ3Nlc3Npb24tcGFyYW1zJ10gPSBwYXJ0cy5qb2luKCcgJyk7XG4gICAgICAgIH1cbiAgICAgICAgcmV0dXJuIGRhdGE7XG4gICAgfSxcbiAgICBwYXJzZV9maW5nZXJwcmludDogZnVuY3Rpb24gKGxpbmUpIHsgLy8gUkZDIDQ1NzJcbiAgICAgICAgdmFyIHBhcnRzID0gbGluZS5zdWJzdHJpbmcoMTQpLnNwbGl0KCcgJyksXG4gICAgICAgICAgICBkYXRhID0ge307XG4gICAgICAgIGRhdGEuaGFzaCA9IHBhcnRzLnNoaWZ0KCk7XG4gICAgICAgIGRhdGEuZmluZ2VycHJpbnQgPSBwYXJ0cy5zaGlmdCgpO1xuICAgICAgICAvLyBUT0RPIGFzc2VydCB0aGF0IGZpbmdlcnByaW50IHNhdGlzZmllcyAyVUhFWCAqKFwiOlwiIDJVSEVYKSA/XG4gICAgICAgIHJldHVybiBkYXRhO1xuICAgIH0sXG4gICAgcGFyc2VfZm10cDogZnVuY3Rpb24gKGxpbmUpIHtcbiAgICAgICAgdmFyIHBhcnRzID0gbGluZS5zcGxpdCgnICcpLFxuICAgICAgICAgICAgaSwga2V5LCB2YWx1ZSxcbiAgICAgICAgICAgIGRhdGEgPSBbXTtcbiAgICAgICAgcGFydHMuc2hpZnQoKTtcbiAgICAgICAgcGFydHMgPSBwYXJ0cy5qb2luKCcgJykuc3BsaXQoJzsnKTtcbiAgICAgICAgZm9yIChpID0gMDsgaSA8IHBhcnRzLmxlbmd0aDsgaSsrKSB7XG4gICAgICAgICAgICBrZXkgPSBwYXJ0c1tpXS5zcGxpdCgnPScpWzBdO1xuICAgICAgICAgICAgd2hpbGUgKGtleS5sZW5ndGggJiYga2V5WzBdID09ICcgJykge1xuICAgICAgICAgICAgICAgIGtleSA9IGtleS5zdWJzdHJpbmcoMSk7XG4gICAgICAgICAgICB9XG4gICAgICAgICAgICB2YWx1ZSA9IHBhcnRzW2ldLnNwbGl0KCc9JylbMV07XG4gICAgICAgICAgICBpZiAoa2V5ICYmIHZhbHVlKSB7XG4gICAgICAgICAgICAgICAgZGF0YS5wdXNoKHtuYW1lOiBrZXksIHZhbHVlOiB2YWx1ZX0pO1xuICAgICAgICAgICAgfSBlbHNlIGlmIChrZXkpIHtcbiAgICAgICAgICAgICAgICAvLyByZmMgNDczMyAoRFRNRikgc3R5bGUgc3R1ZmZcbiAgICAgICAgICAgICAgICBkYXRhLnB1c2goe25hbWU6ICcnLCB2YWx1ZToga2V5fSk7XG4gICAgICAgICAgICB9XG4gICAgICAgIH1cbiAgICAgICAgcmV0dXJuIGRhdGE7XG4gICAgfSxcbiAgICBwYXJzZV9pY2VjYW5kaWRhdGU6IGZ1bmN0aW9uIChsaW5lKSB7XG4gICAgICAgIHZhciBjYW5kaWRhdGUgPSB7fSxcbiAgICAgICAgICAgIGVsZW1zID0gbGluZS5zcGxpdCgnICcpO1xuICAgICAgICBjYW5kaWRhdGUuZm91bmRhdGlvbiA9IGVsZW1zWzBdLnN1YnN0cmluZygxMik7XG4gICAgICAgIGNhbmRpZGF0ZS5jb21wb25lbnQgPSBlbGVtc1sxXTtcbiAgICAgICAgY2FuZGlkYXRlLnByb3RvY29sID0gZWxlbXNbMl0udG9Mb3dlckNhc2UoKTtcbiAgICAgICAgY2FuZGlkYXRlLnByaW9yaXR5ID0gZWxlbXNbM107XG4gICAgICAgIGNhbmRpZGF0ZS5pcCA9IGVsZW1zWzRdO1xuICAgICAgICBjYW5kaWRhdGUucG9ydCA9IGVsZW1zWzVdO1xuICAgICAgICAvLyBlbGVtc1s2XSA9PiBcInR5cFwiXG4gICAgICAgIGNhbmRpZGF0ZS50eXBlID0gZWxlbXNbN107XG4gICAgICAgIGNhbmRpZGF0ZS5nZW5lcmF0aW9uID0gMDsgLy8gZGVmYXVsdCB2YWx1ZSwgbWF5IGJlIG92ZXJ3cml0dGVuIGJlbG93XG4gICAgICAgIGZvciAodmFyIGkgPSA4OyBpIDwgZWxlbXMubGVuZ3RoOyBpICs9IDIpIHtcbiAgICAgICAgICAgIHN3aXRjaCAoZWxlbXNbaV0pIHtcbiAgICAgICAgICAgICAgICBjYXNlICdyYWRkcic6XG4gICAgICAgICAgICAgICAgICAgIGNhbmRpZGF0ZVsncmVsLWFkZHInXSA9IGVsZW1zW2kgKyAxXTtcbiAgICAgICAgICAgICAgICAgICAgYnJlYWs7XG4gICAgICAgICAgICAgICAgY2FzZSAncnBvcnQnOlxuICAgICAgICAgICAgICAgICAgICBjYW5kaWRhdGVbJ3JlbC1wb3J0J10gPSBlbGVtc1tpICsgMV07XG4gICAgICAgICAgICAgICAgICAgIGJyZWFrO1xuICAgICAgICAgICAgICAgIGNhc2UgJ2dlbmVyYXRpb24nOlxuICAgICAgICAgICAgICAgICAgICBjYW5kaWRhdGUuZ2VuZXJhdGlvbiA9IGVsZW1zW2kgKyAxXTtcbiAgICAgICAgICAgICAgICAgICAgYnJlYWs7XG4gICAgICAgICAgICAgICAgY2FzZSAndGNwdHlwZSc6XG4gICAgICAgICAgICAgICAgICAgIGNhbmRpZGF0ZS50Y3B0eXBlID0gZWxlbXNbaSArIDFdO1xuICAgICAgICAgICAgICAgICAgICBicmVhaztcbiAgICAgICAgICAgICAgICBkZWZhdWx0OiAvLyBUT0RPXG4gICAgICAgICAgICAgICAgICAgIGxvZ2dlci5sb2coJ3BhcnNlX2ljZWNhbmRpZGF0ZSBub3QgdHJhbnNsYXRpbmcgXCInICsgZWxlbXNbaV0gKyAnXCIgPSBcIicgKyBlbGVtc1tpICsgMV0gKyAnXCInKTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgfVxuICAgICAgICBjYW5kaWRhdGUubmV0d29yayA9ICcxJztcbiAgICAgICAgY2FuZGlkYXRlLmlkID0gTWF0aC5yYW5kb20oKS50b1N0cmluZygzNikuc3Vic3RyKDIsIDEwKTsgLy8gbm90IGFwcGxpY2FibGUgdG8gU0RQIC0tIEZJWE1FOiBzaG91bGQgYmUgdW5pcXVlLCBub3QganVzdCByYW5kb21cbiAgICAgICAgcmV0dXJuIGNhbmRpZGF0ZTtcbiAgICB9LFxuICAgIGJ1aWxkX2ljZWNhbmRpZGF0ZTogZnVuY3Rpb24gKGNhbmQpIHtcbiAgICAgICAgdmFyIGxpbmUgPSBbJ2E9Y2FuZGlkYXRlOicgKyBjYW5kLmZvdW5kYXRpb24sIGNhbmQuY29tcG9uZW50LCBjYW5kLnByb3RvY29sLCBjYW5kLnByaW9yaXR5LCBjYW5kLmlwLCBjYW5kLnBvcnQsICd0eXAnLCBjYW5kLnR5cGVdLmpvaW4oJyAnKTtcbiAgICAgICAgbGluZSArPSAnICc7XG4gICAgICAgIHN3aXRjaCAoY2FuZC50eXBlKSB7XG4gICAgICAgICAgICBjYXNlICdzcmZseCc6XG4gICAgICAgICAgICBjYXNlICdwcmZseCc6XG4gICAgICAgICAgICBjYXNlICdyZWxheSc6XG4gICAgICAgICAgICAgICAgaWYgKGNhbmQuaGFzT3duQXR0cmlidXRlKCdyZWwtYWRkcicpICYmIGNhbmQuaGFzT3duQXR0cmlidXRlKCdyZWwtcG9ydCcpKSB7XG4gICAgICAgICAgICAgICAgICAgIGxpbmUgKz0gJ3JhZGRyJztcbiAgICAgICAgICAgICAgICAgICAgbGluZSArPSAnICc7XG4gICAgICAgICAgICAgICAgICAgIGxpbmUgKz0gY2FuZFsncmVsLWFkZHInXTtcbiAgICAgICAgICAgICAgICAgICAgbGluZSArPSAnICc7XG4gICAgICAgICAgICAgICAgICAgIGxpbmUgKz0gJ3Jwb3J0JztcbiAgICAgICAgICAgICAgICAgICAgbGluZSArPSAnICc7XG4gICAgICAgICAgICAgICAgICAgIGxpbmUgKz0gY2FuZFsncmVsLXBvcnQnXTtcbiAgICAgICAgICAgICAgICAgICAgbGluZSArPSAnICc7XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgIGJyZWFrO1xuICAgICAgICB9XG4gICAgICAgIGlmIChjYW5kLmhhc093bkF0dHJpYnV0ZSgndGNwdHlwZScpKSB7XG4gICAgICAgICAgICBsaW5lICs9ICd0Y3B0eXBlJztcbiAgICAgICAgICAgIGxpbmUgKz0gJyAnO1xuICAgICAgICAgICAgbGluZSArPSBjYW5kLnRjcHR5cGU7XG4gICAgICAgICAgICBsaW5lICs9ICcgJztcbiAgICAgICAgfVxuICAgICAgICBsaW5lICs9ICdnZW5lcmF0aW9uJztcbiAgICAgICAgbGluZSArPSAnICc7XG4gICAgICAgIGxpbmUgKz0gY2FuZC5oYXNPd25BdHRyaWJ1dGUoJ2dlbmVyYXRpb24nKSA/IGNhbmQuZ2VuZXJhdGlvbiA6ICcwJztcbiAgICAgICAgcmV0dXJuIGxpbmU7XG4gICAgfSxcbiAgICBwYXJzZV9zc3JjOiBmdW5jdGlvbiAoZGVzYykge1xuICAgICAgICAvLyBwcm9wcmlldGFyeSBtYXBwaW5nIG9mIGE9c3NyYyBsaW5lc1xuICAgICAgICAvLyBUT0RPOiBzZWUgXCJKaW5nbGUgUlRQIFNvdXJjZSBEZXNjcmlwdGlvblwiIGJ5IEp1YmVydGkgYW5kIFAuIFRoYXRjaGVyIG9uIGdvb2dsZSBkb2NzXG4gICAgICAgIC8vIGFuZCBwYXJzZSBhY2NvcmRpbmcgdG8gdGhhdFxuICAgICAgICB2YXIgbGluZXMgPSBkZXNjLnNwbGl0KCdcXHJcXG4nKSxcbiAgICAgICAgICAgIGRhdGEgPSB7fTtcbiAgICAgICAgZm9yICh2YXIgaSA9IDA7IGkgPCBsaW5lcy5sZW5ndGg7IGkrKykge1xuICAgICAgICAgICAgaWYgKGxpbmVzW2ldLnN1YnN0cmluZygwLCA3KSA9PSAnYT1zc3JjOicpIHtcbiAgICAgICAgICAgICAgICB2YXIgaWR4ID0gbGluZXNbaV0uaW5kZXhPZignICcpO1xuICAgICAgICAgICAgICAgIGRhdGFbbGluZXNbaV0uc3Vic3RyKGlkeCArIDEpLnNwbGl0KCc6JywgMilbMF1dID0gbGluZXNbaV0uc3Vic3RyKGlkeCArIDEpLnNwbGl0KCc6JywgMilbMV07XG4gICAgICAgICAgICB9XG4gICAgICAgIH1cbiAgICAgICAgcmV0dXJuIGRhdGE7XG4gICAgfSxcbiAgICBwYXJzZV9ydGNwZmI6IGZ1bmN0aW9uIChsaW5lKSB7XG4gICAgICAgIHZhciBwYXJ0cyA9IGxpbmUuc3Vic3RyKDEwKS5zcGxpdCgnICcpO1xuICAgICAgICB2YXIgZGF0YSA9IHt9O1xuICAgICAgICBkYXRhLnB0ID0gcGFydHMuc2hpZnQoKTtcbiAgICAgICAgZGF0YS50eXBlID0gcGFydHMuc2hpZnQoKTtcbiAgICAgICAgZGF0YS5wYXJhbXMgPSBwYXJ0cztcbiAgICAgICAgcmV0dXJuIGRhdGE7XG4gICAgfSxcbiAgICBwYXJzZV9leHRtYXA6IGZ1bmN0aW9uIChsaW5lKSB7XG4gICAgICAgIHZhciBwYXJ0cyA9IGxpbmUuc3Vic3RyKDkpLnNwbGl0KCcgJyk7XG4gICAgICAgIHZhciBkYXRhID0ge307XG4gICAgICAgIGRhdGEudmFsdWUgPSBwYXJ0cy5zaGlmdCgpO1xuICAgICAgICBpZiAoZGF0YS52YWx1ZS5pbmRleE9mKCcvJykgIT0gLTEpIHtcbiAgICAgICAgICAgIGRhdGEuZGlyZWN0aW9uID0gZGF0YS52YWx1ZS5zdWJzdHIoZGF0YS52YWx1ZS5pbmRleE9mKCcvJykgKyAxKTtcbiAgICAgICAgICAgIGRhdGEudmFsdWUgPSBkYXRhLnZhbHVlLnN1YnN0cigwLCBkYXRhLnZhbHVlLmluZGV4T2YoJy8nKSk7XG4gICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICBkYXRhLmRpcmVjdGlvbiA9ICdib3RoJztcbiAgICAgICAgfVxuICAgICAgICBkYXRhLnVyaSA9IHBhcnRzLnNoaWZ0KCk7XG4gICAgICAgIGRhdGEucGFyYW1zID0gcGFydHM7XG4gICAgICAgIHJldHVybiBkYXRhO1xuICAgIH0sXG4gICAgZmluZF9saW5lOiBmdW5jdGlvbiAoaGF5c3RhY2ssIG5lZWRsZSwgc2Vzc2lvbnBhcnQpIHtcbiAgICAgICAgdmFyIGxpbmVzID0gaGF5c3RhY2suc3BsaXQoJ1xcclxcbicpO1xuICAgICAgICBmb3IgKHZhciBpID0gMDsgaSA8IGxpbmVzLmxlbmd0aDsgaSsrKSB7XG4gICAgICAgICAgICBpZiAobGluZXNbaV0uc3Vic3RyaW5nKDAsIG5lZWRsZS5sZW5ndGgpID09IG5lZWRsZSkge1xuICAgICAgICAgICAgICAgIHJldHVybiBsaW5lc1tpXTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgfVxuICAgICAgICBpZiAoIXNlc3Npb25wYXJ0KSB7XG4gICAgICAgICAgICByZXR1cm4gZmFsc2U7XG4gICAgICAgIH1cbiAgICAgICAgLy8gc2VhcmNoIHNlc3Npb24gcGFydFxuICAgICAgICBsaW5lcyA9IHNlc3Npb25wYXJ0LnNwbGl0KCdcXHJcXG4nKTtcbiAgICAgICAgZm9yICh2YXIgaiA9IDA7IGogPCBsaW5lcy5sZW5ndGg7IGorKykge1xuICAgICAgICAgICAgaWYgKGxpbmVzW2pdLnN1YnN0cmluZygwLCBuZWVkbGUubGVuZ3RoKSA9PSBuZWVkbGUpIHtcbiAgICAgICAgICAgICAgICByZXR1cm4gbGluZXNbal07XG4gICAgICAgICAgICB9XG4gICAgICAgIH1cbiAgICAgICAgcmV0dXJuIGZhbHNlO1xuICAgIH0sXG4gICAgZmluZF9saW5lczogZnVuY3Rpb24gKGhheXN0YWNrLCBuZWVkbGUsIHNlc3Npb25wYXJ0KSB7XG4gICAgICAgIHZhciBsaW5lcyA9IGhheXN0YWNrLnNwbGl0KCdcXHJcXG4nKSxcbiAgICAgICAgICAgIG5lZWRsZXMgPSBbXTtcbiAgICAgICAgZm9yICh2YXIgaSA9IDA7IGkgPCBsaW5lcy5sZW5ndGg7IGkrKykge1xuICAgICAgICAgICAgaWYgKGxpbmVzW2ldLnN1YnN0cmluZygwLCBuZWVkbGUubGVuZ3RoKSA9PSBuZWVkbGUpXG4gICAgICAgICAgICAgICAgbmVlZGxlcy5wdXNoKGxpbmVzW2ldKTtcbiAgICAgICAgfVxuICAgICAgICBpZiAobmVlZGxlcy5sZW5ndGggfHwgIXNlc3Npb25wYXJ0KSB7XG4gICAgICAgICAgICByZXR1cm4gbmVlZGxlcztcbiAgICAgICAgfVxuICAgICAgICAvLyBzZWFyY2ggc2Vzc2lvbiBwYXJ0XG4gICAgICAgIGxpbmVzID0gc2Vzc2lvbnBhcnQuc3BsaXQoJ1xcclxcbicpO1xuICAgICAgICBmb3IgKHZhciBqID0gMDsgaiA8IGxpbmVzLmxlbmd0aDsgaisrKSB7XG4gICAgICAgICAgICBpZiAobGluZXNbal0uc3Vic3RyaW5nKDAsIG5lZWRsZS5sZW5ndGgpID09IG5lZWRsZSkge1xuICAgICAgICAgICAgICAgIG5lZWRsZXMucHVzaChsaW5lc1tqXSk7XG4gICAgICAgICAgICB9XG4gICAgICAgIH1cbiAgICAgICAgcmV0dXJuIG5lZWRsZXM7XG4gICAgfSxcbiAgICBjYW5kaWRhdGVUb0ppbmdsZTogZnVuY3Rpb24gKGxpbmUpIHtcbiAgICAgICAgLy8gYT1jYW5kaWRhdGU6Mjk3OTE2NjY2MiAxIHVkcCAyMTEzOTM3MTUxIDE5Mi4xNjguMi4xMDAgNTc2OTggdHlwIGhvc3QgZ2VuZXJhdGlvbiAwXG4gICAgICAgIC8vICAgICAgPGNhbmRpZGF0ZSBjb21wb25lbnQ9Li4uIGZvdW5kYXRpb249Li4uIGdlbmVyYXRpb249Li4uIGlkPS4uLiBpcD0uLi4gbmV0d29yaz0uLi4gcG9ydD0uLi4gcHJpb3JpdHk9Li4uIHByb3RvY29sPS4uLiB0eXBlPS4uLi8+XG4gICAgICAgIGlmIChsaW5lLmluZGV4T2YoJ2NhbmRpZGF0ZTonKSA9PT0gMCkge1xuICAgICAgICAgICAgbGluZSA9ICdhPScgKyBsaW5lO1xuICAgICAgICB9IGVsc2UgaWYgKGxpbmUuc3Vic3RyaW5nKDAsIDEyKSAhPSAnYT1jYW5kaWRhdGU6Jykge1xuICAgICAgICAgICAgbG9nZ2VyLmxvZygncGFyc2VDYW5kaWRhdGUgY2FsbGVkIHdpdGggYSBsaW5lIHRoYXQgaXMgbm90IGEgY2FuZGlkYXRlIGxpbmUnKTtcbiAgICAgICAgICAgIGxvZ2dlci5sb2cobGluZSk7XG4gICAgICAgICAgICByZXR1cm4gbnVsbDtcbiAgICAgICAgfVxuICAgICAgICBpZiAobGluZS5zdWJzdHJpbmcobGluZS5sZW5ndGggLSAyKSA9PSAnXFxyXFxuJykgLy8gY2hvbXAgaXRcbiAgICAgICAgICAgIGxpbmUgPSBsaW5lLnN1YnN0cmluZygwLCBsaW5lLmxlbmd0aCAtIDIpO1xuICAgICAgICB2YXIgY2FuZGlkYXRlID0ge30sXG4gICAgICAgICAgICBlbGVtcyA9IGxpbmUuc3BsaXQoJyAnKSxcbiAgICAgICAgICAgIGk7XG4gICAgICAgIGlmIChlbGVtc1s2XSAhPSAndHlwJykge1xuICAgICAgICAgICAgbG9nZ2VyLmxvZygnZGlkIG5vdCBmaW5kIHR5cCBpbiB0aGUgcmlnaHQgcGxhY2UnKTtcbiAgICAgICAgICAgIGxvZ2dlci5sb2cobGluZSk7XG4gICAgICAgICAgICByZXR1cm4gbnVsbDtcbiAgICAgICAgfVxuICAgICAgICBjYW5kaWRhdGUuZm91bmRhdGlvbiA9IGVsZW1zWzBdLnN1YnN0cmluZygxMik7XG4gICAgICAgIGNhbmRpZGF0ZS5jb21wb25lbnQgPSBlbGVtc1sxXTtcbiAgICAgICAgY2FuZGlkYXRlLnByb3RvY29sID0gZWxlbXNbMl0udG9Mb3dlckNhc2UoKTtcbiAgICAgICAgY2FuZGlkYXRlLnByaW9yaXR5ID0gZWxlbXNbM107XG4gICAgICAgIGNhbmRpZGF0ZS5pcCA9IGVsZW1zWzRdO1xuICAgICAgICBjYW5kaWRhdGUucG9ydCA9IGVsZW1zWzVdO1xuICAgICAgICAvLyBlbGVtc1s2XSA9PiBcInR5cFwiXG4gICAgICAgIGNhbmRpZGF0ZS50eXBlID0gZWxlbXNbN107XG5cbiAgICAgICAgY2FuZGlkYXRlLmdlbmVyYXRpb24gPSAnMCc7IC8vIGRlZmF1bHQsIG1heSBiZSBvdmVyd3JpdHRlbiBiZWxvd1xuICAgICAgICBmb3IgKGkgPSA4OyBpIDwgZWxlbXMubGVuZ3RoOyBpICs9IDIpIHtcbiAgICAgICAgICAgIHN3aXRjaCAoZWxlbXNbaV0pIHtcbiAgICAgICAgICAgICAgICBjYXNlICdyYWRkcic6XG4gICAgICAgICAgICAgICAgICAgIGNhbmRpZGF0ZVsncmVsLWFkZHInXSA9IGVsZW1zW2kgKyAxXTtcbiAgICAgICAgICAgICAgICAgICAgYnJlYWs7XG4gICAgICAgICAgICAgICAgY2FzZSAncnBvcnQnOlxuICAgICAgICAgICAgICAgICAgICBjYW5kaWRhdGVbJ3JlbC1wb3J0J10gPSBlbGVtc1tpICsgMV07XG4gICAgICAgICAgICAgICAgICAgIGJyZWFrO1xuICAgICAgICAgICAgICAgIGNhc2UgJ2dlbmVyYXRpb24nOlxuICAgICAgICAgICAgICAgICAgICBjYW5kaWRhdGUuZ2VuZXJhdGlvbiA9IGVsZW1zW2kgKyAxXTtcbiAgICAgICAgICAgICAgICAgICAgYnJlYWs7XG4gICAgICAgICAgICAgICAgY2FzZSAndGNwdHlwZSc6XG4gICAgICAgICAgICAgICAgICAgIGNhbmRpZGF0ZS50Y3B0eXBlID0gZWxlbXNbaSArIDFdO1xuICAgICAgICAgICAgICAgICAgICBicmVhaztcbiAgICAgICAgICAgICAgICBkZWZhdWx0OiAvLyBUT0RPXG4gICAgICAgICAgICAgICAgICAgIGxvZ2dlci5sb2coJ25vdCB0cmFuc2xhdGluZyBcIicgKyBlbGVtc1tpXSArICdcIiA9IFwiJyArIGVsZW1zW2kgKyAxXSArICdcIicpO1xuICAgICAgICAgICAgfVxuICAgICAgICB9XG4gICAgICAgIGNhbmRpZGF0ZS5uZXR3b3JrID0gJzEnO1xuICAgICAgICBjYW5kaWRhdGUuaWQgPSBNYXRoLnJhbmRvbSgpLnRvU3RyaW5nKDM2KS5zdWJzdHIoMiwgMTApOyAvLyBub3QgYXBwbGljYWJsZSB0byBTRFAgLS0gRklYTUU6IHNob3VsZCBiZSB1bmlxdWUsIG5vdCBqdXN0IHJhbmRvbVxuICAgICAgICByZXR1cm4gY2FuZGlkYXRlO1xuICAgIH0sXG4gICAgY2FuZGlkYXRlRnJvbUppbmdsZTogZnVuY3Rpb24gKGNhbmQpIHtcbiAgICAgICAgdmFyIGxpbmUgPSAnYT1jYW5kaWRhdGU6JztcbiAgICAgICAgbGluZSArPSBjYW5kLmdldEF0dHJpYnV0ZSgnZm91bmRhdGlvbicpO1xuICAgICAgICBsaW5lICs9ICcgJztcbiAgICAgICAgbGluZSArPSBjYW5kLmdldEF0dHJpYnV0ZSgnY29tcG9uZW50Jyk7XG4gICAgICAgIGxpbmUgKz0gJyAnO1xuXG4gICAgICAgIHZhciBwcm90b2NvbCA9IGNhbmQuZ2V0QXR0cmlidXRlKCdwcm90b2NvbCcpO1xuICAgICAgICAvLyB1c2UgdGNwIGNhbmRpZGF0ZXMgZm9yIEZGXG4gICAgICAgIGlmIChSVENCcm93c2VyVHlwZS5pc0ZpcmVmb3goKSAmJiBwcm90b2NvbC50b0xvd2VyQ2FzZSgpID09ICdzc2x0Y3AnKSB7XG4gICAgICAgICAgICBwcm90b2NvbCA9ICd0Y3AnO1xuICAgICAgICB9XG5cbiAgICAgICAgbGluZSArPSBwcm90b2NvbDsgLy8udG9VcHBlckNhc2UoKTsgLy8gY2hyb21lIE0yMyBkb2Vzbid0IGxpa2UgdGhpc1xuICAgICAgICBsaW5lICs9ICcgJztcbiAgICAgICAgbGluZSArPSBjYW5kLmdldEF0dHJpYnV0ZSgncHJpb3JpdHknKTtcbiAgICAgICAgbGluZSArPSAnICc7XG4gICAgICAgIGxpbmUgKz0gY2FuZC5nZXRBdHRyaWJ1dGUoJ2lwJyk7XG4gICAgICAgIGxpbmUgKz0gJyAnO1xuICAgICAgICBsaW5lICs9IGNhbmQuZ2V0QXR0cmlidXRlKCdwb3J0Jyk7XG4gICAgICAgIGxpbmUgKz0gJyAnO1xuICAgICAgICBsaW5lICs9ICd0eXAnO1xuICAgICAgICBsaW5lICs9ICcgJyArIGNhbmQuZ2V0QXR0cmlidXRlKCd0eXBlJyk7XG4gICAgICAgIGxpbmUgKz0gJyAnO1xuICAgICAgICBzd2l0Y2ggKGNhbmQuZ2V0QXR0cmlidXRlKCd0eXBlJykpIHtcbiAgICAgICAgICAgIGNhc2UgJ3NyZmx4JzpcbiAgICAgICAgICAgIGNhc2UgJ3ByZmx4JzpcbiAgICAgICAgICAgIGNhc2UgJ3JlbGF5JzpcbiAgICAgICAgICAgICAgICBpZiAoY2FuZC5nZXRBdHRyaWJ1dGUoJ3JlbC1hZGRyJykgJiYgY2FuZC5nZXRBdHRyaWJ1dGUoJ3JlbC1wb3J0JykpIHtcbiAgICAgICAgICAgICAgICAgICAgbGluZSArPSAncmFkZHInO1xuICAgICAgICAgICAgICAgICAgICBsaW5lICs9ICcgJztcbiAgICAgICAgICAgICAgICAgICAgbGluZSArPSBjYW5kLmdldEF0dHJpYnV0ZSgncmVsLWFkZHInKTtcbiAgICAgICAgICAgICAgICAgICAgbGluZSArPSAnICc7XG4gICAgICAgICAgICAgICAgICAgIGxpbmUgKz0gJ3Jwb3J0JztcbiAgICAgICAgICAgICAgICAgICAgbGluZSArPSAnICc7XG4gICAgICAgICAgICAgICAgICAgIGxpbmUgKz0gY2FuZC5nZXRBdHRyaWJ1dGUoJ3JlbC1wb3J0Jyk7XG4gICAgICAgICAgICAgICAgICAgIGxpbmUgKz0gJyAnO1xuICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICBicmVhaztcbiAgICAgICAgfVxuICAgICAgICBpZiAocHJvdG9jb2wudG9Mb3dlckNhc2UoKSA9PSAndGNwJykge1xuICAgICAgICAgICAgbGluZSArPSAndGNwdHlwZSc7XG4gICAgICAgICAgICBsaW5lICs9ICcgJztcbiAgICAgICAgICAgIGxpbmUgKz0gY2FuZC5nZXRBdHRyaWJ1dGUoJ3RjcHR5cGUnKTtcbiAgICAgICAgICAgIGxpbmUgKz0gJyAnO1xuICAgICAgICB9XG4gICAgICAgIGxpbmUgKz0gJ2dlbmVyYXRpb24nO1xuICAgICAgICBsaW5lICs9ICcgJztcbiAgICAgICAgbGluZSArPSBjYW5kLmdldEF0dHJpYnV0ZSgnZ2VuZXJhdGlvbicpIHx8ICcwJztcbiAgICAgICAgcmV0dXJuIGxpbmUgKyAnXFxyXFxuJztcbiAgICB9XG59O1xuXG5tb2R1bGUuZXhwb3J0cyA9IFNEUFV0aWw7XG4iLCIvKiBnbG9iYWwgJCAqL1xudmFyIFJUQyA9IHJlcXVpcmUoJy4uL1JUQy9SVEMnKTtcblxudmFyIGxvZ2dlciA9IHJlcXVpcmUoXCJqaXRzaS1tZWV0LWxvZ2dlclwiKS5nZXRMb2dnZXIoX19maWxlbmFtZSk7XG52YXIgUlRDQnJvd3NlclR5cGUgPSByZXF1aXJlKFwiLi4vUlRDL1JUQ0Jyb3dzZXJUeXBlLmpzXCIpO1xudmFyIFhNUFBFdmVudHMgPSByZXF1aXJlKFwiLi4vLi4vc2VydmljZS94bXBwL1hNUFBFdmVudHNcIik7XG52YXIgU1NSQ1JlcGxhY2VtZW50ID0gcmVxdWlyZShcIi4vTG9jYWxTU1JDUmVwbGFjZW1lbnRcIik7XG5cbmZ1bmN0aW9uIFRyYWNlYWJsZVBlZXJDb25uZWN0aW9uKGljZV9jb25maWcsIGNvbnN0cmFpbnRzLCBzZXNzaW9uKSB7XG4gICAgdmFyIHNlbGYgPSB0aGlzO1xuICAgIHRoaXMuc2Vzc2lvbiA9IHNlc3Npb247XG4gICAgdmFyIFJUQ1BlZXJDb25uZWN0aW9uVHlwZSA9IG51bGw7XG4gICAgaWYgKFJUQ0Jyb3dzZXJUeXBlLmlzRmlyZWZveCgpKSB7XG4gICAgICAgIFJUQ1BlZXJDb25uZWN0aW9uVHlwZSA9IG1velJUQ1BlZXJDb25uZWN0aW9uO1xuICAgIH0gZWxzZSBpZiAoUlRDQnJvd3NlclR5cGUuaXNUZW1hc3lzUGx1Z2luVXNlZCgpKSB7XG4gICAgICAgIFJUQ1BlZXJDb25uZWN0aW9uVHlwZSA9IFJUQ1BlZXJDb25uZWN0aW9uO1xuICAgIH0gZWxzZSB7XG4gICAgICAgIFJUQ1BlZXJDb25uZWN0aW9uVHlwZSA9IHdlYmtpdFJUQ1BlZXJDb25uZWN0aW9uO1xuICAgIH1cbiAgICB0aGlzLnBlZXJjb25uZWN0aW9uID0gbmV3IFJUQ1BlZXJDb25uZWN0aW9uVHlwZShpY2VfY29uZmlnLCBjb25zdHJhaW50cyk7XG4gICAgdGhpcy51cGRhdGVMb2cgPSBbXTtcbiAgICB0aGlzLnN0YXRzID0ge307XG4gICAgdGhpcy5zdGF0c2ludGVydmFsID0gbnVsbDtcbiAgICB0aGlzLm1heHN0YXRzID0gMDsgLy8gbGltaXQgdG8gMzAwIHZhbHVlcywgaS5lLiA1IG1pbnV0ZXM7IHNldCB0byAwIHRvIGRpc2FibGVcbiAgICB2YXIgSW50ZXJvcCA9IHJlcXVpcmUoJ3NkcC1pbnRlcm9wJykuSW50ZXJvcDtcbiAgICB0aGlzLmludGVyb3AgPSBuZXcgSW50ZXJvcCgpO1xuICAgIHZhciBTaW11bGNhc3QgPSByZXF1aXJlKCdzZHAtc2ltdWxjYXN0Jyk7XG4gICAgdGhpcy5zaW11bGNhc3QgPSBuZXcgU2ltdWxjYXN0KHtudW1PZkxheWVyczogMywgZXhwbG9kZVJlbW90ZVNpbXVsY2FzdDogZmFsc2V9KTtcblxuICAgIC8vIG92ZXJyaWRlIGFzIGRlc2lyZWRcbiAgICB0aGlzLnRyYWNlID0gZnVuY3Rpb24gKHdoYXQsIGluZm8pIHtcbiAgICAgICAgLypsb2dnZXIud2FybignV1RSQUNFJywgd2hhdCwgaW5mbyk7XG4gICAgICAgIGlmIChpbmZvICYmIFJUQ0Jyb3dzZXJUeXBlLmlzSUV4cGxvcmVyKCkpIHtcbiAgICAgICAgICAgIGlmIChpbmZvLmxlbmd0aCA+IDEwMjQpIHtcbiAgICAgICAgICAgICAgICBsb2dnZXIud2FybignV1RSQUNFJywgd2hhdCwgaW5mby5zdWJzdHIoMTAyNCkpO1xuICAgICAgICAgICAgfVxuICAgICAgICAgICAgaWYgKGluZm8ubGVuZ3RoID4gMjA0OCkge1xuICAgICAgICAgICAgICAgIGxvZ2dlci53YXJuKCdXVFJBQ0UnLCB3aGF0LCBpbmZvLnN1YnN0cigyMDQ4KSk7XG4gICAgICAgICAgICB9XG4gICAgICAgIH0qL1xuICAgICAgICBzZWxmLnVwZGF0ZUxvZy5wdXNoKHtcbiAgICAgICAgICAgIHRpbWU6IG5ldyBEYXRlKCksXG4gICAgICAgICAgICB0eXBlOiB3aGF0LFxuICAgICAgICAgICAgdmFsdWU6IGluZm8gfHwgXCJcIlxuICAgICAgICB9KTtcbiAgICB9O1xuICAgIHRoaXMub25pY2VjYW5kaWRhdGUgPSBudWxsO1xuICAgIHRoaXMucGVlcmNvbm5lY3Rpb24ub25pY2VjYW5kaWRhdGUgPSBmdW5jdGlvbiAoZXZlbnQpIHtcbiAgICAgICAgLy8gRklYTUU6IHRoaXMgY2F1c2VzIHN0YWNrIG92ZXJmbG93IHdpdGggVGVtYXN5cyBQbHVnaW5cbiAgICAgICAgaWYgKCFSVENCcm93c2VyVHlwZS5pc1RlbWFzeXNQbHVnaW5Vc2VkKCkpXG4gICAgICAgICAgICBzZWxmLnRyYWNlKCdvbmljZWNhbmRpZGF0ZScsIEpTT04uc3RyaW5naWZ5KGV2ZW50LmNhbmRpZGF0ZSwgbnVsbCwgJyAnKSk7XG4gICAgICAgIGlmIChzZWxmLm9uaWNlY2FuZGlkYXRlICE9PSBudWxsKSB7XG4gICAgICAgICAgICBzZWxmLm9uaWNlY2FuZGlkYXRlKGV2ZW50KTtcbiAgICAgICAgfVxuICAgIH07XG4gICAgdGhpcy5vbmFkZHN0cmVhbSA9IG51bGw7XG4gICAgdGhpcy5wZWVyY29ubmVjdGlvbi5vbmFkZHN0cmVhbSA9IGZ1bmN0aW9uIChldmVudCkge1xuICAgICAgICBzZWxmLnRyYWNlKCdvbmFkZHN0cmVhbScsIGV2ZW50LnN0cmVhbS5pZCk7XG4gICAgICAgIGlmIChzZWxmLm9uYWRkc3RyZWFtICE9PSBudWxsKSB7XG4gICAgICAgICAgICBzZWxmLm9uYWRkc3RyZWFtKGV2ZW50KTtcbiAgICAgICAgfVxuICAgIH07XG4gICAgdGhpcy5vbnJlbW92ZXN0cmVhbSA9IG51bGw7XG4gICAgdGhpcy5wZWVyY29ubmVjdGlvbi5vbnJlbW92ZXN0cmVhbSA9IGZ1bmN0aW9uIChldmVudCkge1xuICAgICAgICBzZWxmLnRyYWNlKCdvbnJlbW92ZXN0cmVhbScsIGV2ZW50LnN0cmVhbS5pZCk7XG4gICAgICAgIGlmIChzZWxmLm9ucmVtb3Zlc3RyZWFtICE9PSBudWxsKSB7XG4gICAgICAgICAgICBzZWxmLm9ucmVtb3Zlc3RyZWFtKGV2ZW50KTtcbiAgICAgICAgfVxuICAgIH07XG4gICAgdGhpcy5vbnNpZ25hbGluZ3N0YXRlY2hhbmdlID0gbnVsbDtcbiAgICB0aGlzLnBlZXJjb25uZWN0aW9uLm9uc2lnbmFsaW5nc3RhdGVjaGFuZ2UgPSBmdW5jdGlvbiAoZXZlbnQpIHtcbiAgICAgICAgc2VsZi50cmFjZSgnb25zaWduYWxpbmdzdGF0ZWNoYW5nZScsIHNlbGYuc2lnbmFsaW5nU3RhdGUpO1xuICAgICAgICBpZiAoc2VsZi5vbnNpZ25hbGluZ3N0YXRlY2hhbmdlICE9PSBudWxsKSB7XG4gICAgICAgICAgICBzZWxmLm9uc2lnbmFsaW5nc3RhdGVjaGFuZ2UoZXZlbnQpO1xuICAgICAgICB9XG4gICAgfTtcbiAgICB0aGlzLm9uaWNlY29ubmVjdGlvbnN0YXRlY2hhbmdlID0gbnVsbDtcbiAgICB0aGlzLnBlZXJjb25uZWN0aW9uLm9uaWNlY29ubmVjdGlvbnN0YXRlY2hhbmdlID0gZnVuY3Rpb24gKGV2ZW50KSB7XG4gICAgICAgIHNlbGYudHJhY2UoJ29uaWNlY29ubmVjdGlvbnN0YXRlY2hhbmdlJywgc2VsZi5pY2VDb25uZWN0aW9uU3RhdGUpO1xuICAgICAgICBpZiAoc2VsZi5vbmljZWNvbm5lY3Rpb25zdGF0ZWNoYW5nZSAhPT0gbnVsbCkge1xuICAgICAgICAgICAgc2VsZi5vbmljZWNvbm5lY3Rpb25zdGF0ZWNoYW5nZShldmVudCk7XG4gICAgICAgIH1cbiAgICB9O1xuICAgIHRoaXMub25uZWdvdGlhdGlvbm5lZWRlZCA9IG51bGw7XG4gICAgdGhpcy5wZWVyY29ubmVjdGlvbi5vbm5lZ290aWF0aW9ubmVlZGVkID0gZnVuY3Rpb24gKGV2ZW50KSB7XG4gICAgICAgIHNlbGYudHJhY2UoJ29ubmVnb3RpYXRpb25uZWVkZWQnKTtcbiAgICAgICAgaWYgKHNlbGYub25uZWdvdGlhdGlvbm5lZWRlZCAhPT0gbnVsbCkge1xuICAgICAgICAgICAgc2VsZi5vbm5lZ290aWF0aW9ubmVlZGVkKGV2ZW50KTtcbiAgICAgICAgfVxuICAgIH07XG4gICAgc2VsZi5vbmRhdGFjaGFubmVsID0gbnVsbDtcbiAgICB0aGlzLnBlZXJjb25uZWN0aW9uLm9uZGF0YWNoYW5uZWwgPSBmdW5jdGlvbiAoZXZlbnQpIHtcbiAgICAgICAgc2VsZi50cmFjZSgnb25kYXRhY2hhbm5lbCcsIGV2ZW50KTtcbiAgICAgICAgaWYgKHNlbGYub25kYXRhY2hhbm5lbCAhPT0gbnVsbCkge1xuICAgICAgICAgICAgc2VsZi5vbmRhdGFjaGFubmVsKGV2ZW50KTtcbiAgICAgICAgfVxuICAgIH07XG4gICAgLy8gWFhYOiBkbyBhbGwgbm9uLWZpcmVmb3ggYnJvd3NlcnMgd2hpY2ggd2Ugc3VwcG9ydCBhbHNvIHN1cHBvcnQgdGhpcz9cbiAgICBpZiAoIVJUQ0Jyb3dzZXJUeXBlLmlzRmlyZWZveCgpICYmIHRoaXMubWF4c3RhdHMpIHtcbiAgICAgICAgdGhpcy5zdGF0c2ludGVydmFsID0gd2luZG93LnNldEludGVydmFsKGZ1bmN0aW9uKCkge1xuICAgICAgICAgICAgc2VsZi5wZWVyY29ubmVjdGlvbi5nZXRTdGF0cyhmdW5jdGlvbihzdGF0cykge1xuICAgICAgICAgICAgICAgIHZhciByZXN1bHRzID0gc3RhdHMucmVzdWx0KCk7XG4gICAgICAgICAgICAgICAgdmFyIG5vdyA9IG5ldyBEYXRlKCk7XG4gICAgICAgICAgICAgICAgZm9yICh2YXIgaSA9IDA7IGkgPCByZXN1bHRzLmxlbmd0aDsgKytpKSB7XG4gICAgICAgICAgICAgICAgICAgIHJlc3VsdHNbaV0ubmFtZXMoKS5mb3JFYWNoKGZ1bmN0aW9uIChuYW1lKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICB2YXIgaWQgPSByZXN1bHRzW2ldLmlkICsgJy0nICsgbmFtZTtcbiAgICAgICAgICAgICAgICAgICAgICAgIGlmICghc2VsZi5zdGF0c1tpZF0pIHtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICBzZWxmLnN0YXRzW2lkXSA9IHtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgc3RhcnRUaW1lOiBub3csXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGVuZFRpbWU6IG5vdyxcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgdmFsdWVzOiBbXSxcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgdGltZXM6IFtdXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgfTtcbiAgICAgICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICAgICAgICAgIHNlbGYuc3RhdHNbaWRdLnZhbHVlcy5wdXNoKHJlc3VsdHNbaV0uc3RhdChuYW1lKSk7XG4gICAgICAgICAgICAgICAgICAgICAgICBzZWxmLnN0YXRzW2lkXS50aW1lcy5wdXNoKG5vdy5nZXRUaW1lKCkpO1xuICAgICAgICAgICAgICAgICAgICAgICAgaWYgKHNlbGYuc3RhdHNbaWRdLnZhbHVlcy5sZW5ndGggPiBzZWxmLm1heHN0YXRzKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgc2VsZi5zdGF0c1tpZF0udmFsdWVzLnNoaWZ0KCk7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgc2VsZi5zdGF0c1tpZF0udGltZXMuc2hpZnQoKTtcbiAgICAgICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICAgICAgICAgIHNlbGYuc3RhdHNbaWRdLmVuZFRpbWUgPSBub3c7XG4gICAgICAgICAgICAgICAgICAgIH0pO1xuICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgIH0pO1xuXG4gICAgICAgIH0sIDEwMDApO1xuICAgIH1cbn1cblxuLyoqXG4gKiBSZXR1cm5zIGEgc3RyaW5nIHJlcHJlc2VudGF0aW9uIG9mIGEgU2Vzc2lvbkRlc2NyaXB0aW9uIG9iamVjdC5cbiAqL1xudmFyIGR1bXBTRFAgPSBmdW5jdGlvbihkZXNjcmlwdGlvbikge1xuICAgIGlmICh0eXBlb2YgZGVzY3JpcHRpb24gPT09ICd1bmRlZmluZWQnIHx8IGRlc2NyaXB0aW9uID09IG51bGwpIHtcbiAgICAgICAgcmV0dXJuICcnO1xuICAgIH1cblxuICAgIHJldHVybiAndHlwZTogJyArIGRlc2NyaXB0aW9uLnR5cGUgKyAnXFxyXFxuJyArIGRlc2NyaXB0aW9uLnNkcDtcbn07XG5cbi8qKlxuICogVGFrZXMgYSBTZXNzaW9uRGVzY3JpcHRpb24gb2JqZWN0IGFuZCByZXR1cm5zIGEgXCJub3JtYWxpemVkXCIgdmVyc2lvbi5cbiAqIEN1cnJlbnRseSBpdCBvbmx5IHRha2VzIGNhcmUgb2Ygb3JkZXJpbmcgdGhlIGE9c3NyYyBsaW5lcy5cbiAqL1xudmFyIG5vcm1hbGl6ZVBsYW5CID0gZnVuY3Rpb24oZGVzYykge1xuICAgIGlmICh0eXBlb2YgZGVzYyAhPT0gJ29iamVjdCcgfHwgZGVzYyA9PT0gbnVsbCB8fFxuICAgICAgICB0eXBlb2YgZGVzYy5zZHAgIT09ICdzdHJpbmcnKSB7XG4gICAgICAgIGxvZ2dlci53YXJuKCdBbiBlbXB0eSBkZXNjcmlwdGlvbiB3YXMgcGFzc2VkIGFzIGFuIGFyZ3VtZW50LicpO1xuICAgICAgICByZXR1cm4gZGVzYztcbiAgICB9XG5cbiAgICB2YXIgdHJhbnNmb3JtID0gcmVxdWlyZSgnc2RwLXRyYW5zZm9ybScpO1xuICAgIHZhciBzZXNzaW9uID0gdHJhbnNmb3JtLnBhcnNlKGRlc2Muc2RwKTtcblxuICAgIGlmICh0eXBlb2Ygc2Vzc2lvbiAhPT0gJ3VuZGVmaW5lZCcgJiYgdHlwZW9mIHNlc3Npb24ubWVkaWEgIT09ICd1bmRlZmluZWQnICYmXG4gICAgICAgIEFycmF5LmlzQXJyYXkoc2Vzc2lvbi5tZWRpYSkpIHtcbiAgICAgICAgc2Vzc2lvbi5tZWRpYS5mb3JFYWNoKGZ1bmN0aW9uIChtTGluZSkge1xuXG4gICAgICAgICAgICAvLyBDaHJvbWUgYXBwZWFycyB0byBiZSBwaWNreSBhYm91dCB0aGUgb3JkZXIgaW4gd2hpY2ggYT1zc3JjIGxpbmVzXG4gICAgICAgICAgICAvLyBhcmUgbGlzdGVkIGluIGFuIG0tbGluZSB3aGVuIHJ0eCBpcyBlbmFibGVkIChhbmQgdGh1cyB0aGVyZSBhcmVcbiAgICAgICAgICAgIC8vIGE9c3NyYy1ncm91cCBsaW5lcyB3aXRoIEZJRCBzZW1hbnRpY3MpLiBTcGVjaWZpY2FsbHkgaWYgd2UgaGF2ZVxuICAgICAgICAgICAgLy8gXCJhPXNzcmMtZ3JvdXA6RklEIFMxIFMyXCIgYW5kIHRoZSBcImE9c3NyYzpTMlwiIGxpbmVzIGFwcGVhciBiZWZvcmVcbiAgICAgICAgICAgIC8vIHRoZSBcImE9c3NyYzpTMVwiIGxpbmVzLCBTUkQgZmFpbHMuXG4gICAgICAgICAgICAvLyBTbywgcHV0IFNTUkMgd2hpY2ggYXBwZWFyIGFzIHRoZSBmaXJzdCBTU1JDIGluIGFuIEZJRCBzc3JjLWdyb3VwXG4gICAgICAgICAgICAvLyBmaXJzdC5cbiAgICAgICAgICAgIHZhciBmaXJzdFNzcmNzID0gW107XG4gICAgICAgICAgICB2YXIgbmV3U3NyY0xpbmVzID0gW107XG5cbiAgICAgICAgICAgIGlmICh0eXBlb2YgbUxpbmUuc3NyY0dyb3VwcyAhPT0gJ3VuZGVmaW5lZCcgJiYgQXJyYXkuaXNBcnJheShtTGluZS5zc3JjR3JvdXBzKSkge1xuICAgICAgICAgICAgICAgIG1MaW5lLnNzcmNHcm91cHMuZm9yRWFjaChmdW5jdGlvbiAoZ3JvdXApIHtcbiAgICAgICAgICAgICAgICAgICAgaWYgKHR5cGVvZiBncm91cC5zZW1hbnRpY3MgIT09ICd1bmRlZmluZWQnICYmXG4gICAgICAgICAgICAgICAgICAgICAgICBncm91cC5zZW1hbnRpY3MgPT09ICdGSUQnKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICBpZiAodHlwZW9mIGdyb3VwLnNzcmNzICE9PSAndW5kZWZpbmVkJykge1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgIGZpcnN0U3NyY3MucHVzaChOdW1iZXIoZ3JvdXAuc3NyY3Muc3BsaXQoJyAnKVswXSkpO1xuICAgICAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgfSk7XG4gICAgICAgICAgICB9XG5cbiAgICAgICAgICAgIGlmICh0eXBlb2YgbUxpbmUuc3NyY3MgIT09ICd1bmRlZmluZWQnICYmIEFycmF5LmlzQXJyYXkobUxpbmUuc3NyY3MpKSB7XG4gICAgICAgICAgICAgICAgdmFyIGk7XG4gICAgICAgICAgICAgICAgZm9yIChpID0gMDsgaTxtTGluZS5zc3Jjcy5sZW5ndGg7IGkrKyl7XG4gICAgICAgICAgICAgICAgICAgIGlmICh0eXBlb2YgbUxpbmUuc3NyY3NbaV0gPT09ICdvYmplY3QnXG4gICAgICAgICAgICAgICAgICAgICAgICAmJiB0eXBlb2YgbUxpbmUuc3NyY3NbaV0uaWQgIT09ICd1bmRlZmluZWQnXG4gICAgICAgICAgICAgICAgICAgICAgICAmJiAhJC5pbkFycmF5KG1MaW5lLnNzcmNzW2ldLmlkLCBmaXJzdFNzcmNzKSkge1xuICAgICAgICAgICAgICAgICAgICAgICAgbmV3U3NyY0xpbmVzLnB1c2gobUxpbmUuc3NyY3NbaV0pO1xuICAgICAgICAgICAgICAgICAgICAgICAgZGVsZXRlIG1MaW5lLnNzcmNzW2ldO1xuICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICAgICAgZm9yIChpID0gMDsgaTxtTGluZS5zc3Jjcy5sZW5ndGg7IGkrKyl7XG4gICAgICAgICAgICAgICAgICAgIGlmICh0eXBlb2YgbUxpbmUuc3NyY3NbaV0gIT09ICd1bmRlZmluZWQnKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICBuZXdTc3JjTGluZXMucHVzaChtTGluZS5zc3Jjc1tpXSk7XG4gICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICB9XG5cbiAgICAgICAgICAgICAgICBtTGluZS5zc3JjcyA9IG5ld1NzcmNMaW5lcztcbiAgICAgICAgICAgIH1cbiAgICAgICAgfSk7XG4gICAgfVxuXG4gICAgdmFyIHJlc1N0ciA9IHRyYW5zZm9ybS53cml0ZShzZXNzaW9uKTtcbiAgICByZXR1cm4gbmV3IFJUQ1Nlc3Npb25EZXNjcmlwdGlvbih7XG4gICAgICAgIHR5cGU6IGRlc2MudHlwZSxcbiAgICAgICAgc2RwOiByZXNTdHJcbiAgICB9KTtcbn07XG5cbnZhciBnZXR0ZXJzID0ge1xuICAgIHNpZ25hbGluZ1N0YXRlOiBmdW5jdGlvbiAoKSB7XG4gICAgICAgIHJldHVybiB0aGlzLnBlZXJjb25uZWN0aW9uLnNpZ25hbGluZ1N0YXRlO1xuICAgIH0sXG4gICAgaWNlQ29ubmVjdGlvblN0YXRlOiBmdW5jdGlvbiAoKSB7XG4gICAgICAgIHJldHVybiB0aGlzLnBlZXJjb25uZWN0aW9uLmljZUNvbm5lY3Rpb25TdGF0ZTtcbiAgICB9LFxuICAgIGxvY2FsRGVzY3JpcHRpb246ICBmdW5jdGlvbigpIHtcbiAgICAgICAgdmFyIGRlc2MgPSB0aGlzLnBlZXJjb25uZWN0aW9uLmxvY2FsRGVzY3JpcHRpb247XG5cbiAgICAgICAgICAgIC8vIEZJWE1FIHRoaXMgc2hvdWxkIHByb2JhYmx5IGJlIGFmdGVyIHRoZSBVbmlmaWVkIFBsYW4gLT4gUGxhbiBCXG4gICAgICAgICAgICAvLyB0cmFuc2Zvcm1hdGlvbi5cbiAgICAgICAgZGVzYyA9IFNTUkNSZXBsYWNlbWVudC5tdW5nZUxvY2FsVmlkZW9TU1JDKGRlc2MpO1xuXG4gICAgICAgIHRoaXMudHJhY2UoJ2dldExvY2FsRGVzY3JpcHRpb246OnByZVRyYW5zZm9ybScsIGR1bXBTRFAoZGVzYykpO1xuXG4gICAgICAgIC8vIGlmIHdlJ3JlIHJ1bm5pbmcgb24gRkYsIHRyYW5zZm9ybSB0byBQbGFuIEIgZmlyc3QuXG4gICAgICAgIGlmIChSVENCcm93c2VyVHlwZS51c2VzVW5pZmllZFBsYW4oKSkge1xuICAgICAgICAgICAgZGVzYyA9IHRoaXMuaW50ZXJvcC50b1BsYW5CKGRlc2MpO1xuICAgICAgICAgICAgdGhpcy50cmFjZSgnZ2V0TG9jYWxEZXNjcmlwdGlvbjo6cG9zdFRyYW5zZm9ybSAoUGxhbiBCKScsIGR1bXBTRFAoZGVzYykpO1xuICAgICAgICB9XG4gICAgICAgIHJldHVybiBkZXNjO1xuICAgIH0sXG4gICAgcmVtb3RlRGVzY3JpcHRpb246ICBmdW5jdGlvbigpIHtcbiAgICAgICAgdmFyIGRlc2MgPSB0aGlzLnBlZXJjb25uZWN0aW9uLnJlbW90ZURlc2NyaXB0aW9uO1xuICAgICAgICB0aGlzLnRyYWNlKCdnZXRSZW1vdGVEZXNjcmlwdGlvbjo6cHJlVHJhbnNmb3JtJywgZHVtcFNEUChkZXNjKSk7XG5cbiAgICAgICAgLy8gaWYgd2UncmUgcnVubmluZyBvbiBGRiwgdHJhbnNmb3JtIHRvIFBsYW4gQiBmaXJzdC5cbiAgICAgICAgaWYgKFJUQ0Jyb3dzZXJUeXBlLnVzZXNVbmlmaWVkUGxhbigpKSB7XG4gICAgICAgICAgICBkZXNjID0gdGhpcy5pbnRlcm9wLnRvUGxhbkIoZGVzYyk7XG4gICAgICAgICAgICB0aGlzLnRyYWNlKCdnZXRSZW1vdGVEZXNjcmlwdGlvbjo6cG9zdFRyYW5zZm9ybSAoUGxhbiBCKScsIGR1bXBTRFAoZGVzYykpO1xuICAgICAgICB9XG4gICAgICAgIHJldHVybiBkZXNjO1xuICAgIH1cbn07XG5PYmplY3Qua2V5cyhnZXR0ZXJzKS5mb3JFYWNoKGZ1bmN0aW9uIChwcm9wKSB7XG4gICAgT2JqZWN0LmRlZmluZVByb3BlcnR5KFxuICAgICAgICBUcmFjZWFibGVQZWVyQ29ubmVjdGlvbi5wcm90b3R5cGUsXG4gICAgICAgIHByb3AsIHtcbiAgICAgICAgICAgIGdldDogZ2V0dGVyc1twcm9wXVxuICAgICAgICB9XG4gICAgKTtcbn0pO1xuXG5UcmFjZWFibGVQZWVyQ29ubmVjdGlvbi5wcm90b3R5cGUuYWRkU3RyZWFtID0gZnVuY3Rpb24gKHN0cmVhbSkge1xuICAgIHRoaXMudHJhY2UoJ2FkZFN0cmVhbScsIHN0cmVhbS5pZCk7XG4gICAgdHJ5XG4gICAge1xuICAgICAgICB0aGlzLnBlZXJjb25uZWN0aW9uLmFkZFN0cmVhbShzdHJlYW0pO1xuICAgIH1cbiAgICBjYXRjaCAoZSlcbiAgICB7XG4gICAgICAgIGxvZ2dlci5lcnJvcihlKTtcbiAgICB9XG59O1xuXG5UcmFjZWFibGVQZWVyQ29ubmVjdGlvbi5wcm90b3R5cGUucmVtb3ZlU3RyZWFtID0gZnVuY3Rpb24gKHN0cmVhbSwgc3RvcFN0cmVhbXMpIHtcbiAgICB0aGlzLnRyYWNlKCdyZW1vdmVTdHJlYW0nLCBzdHJlYW0uaWQpO1xuICAgIGlmKHN0b3BTdHJlYW1zKSB7XG4gICAgICAgIFJUQy5zdG9wTWVkaWFTdHJlYW0oc3RyZWFtKTtcbiAgICB9XG5cbiAgICB0cnkge1xuICAgICAgICAvLyBGRiBkb2Vzbid0IHN1cHBvcnQgdGhpcyB5ZXQuXG4gICAgICAgIGlmICh0aGlzLnBlZXJjb25uZWN0aW9uLnJlbW92ZVN0cmVhbSlcbiAgICAgICAgICAgIHRoaXMucGVlcmNvbm5lY3Rpb24ucmVtb3ZlU3RyZWFtKHN0cmVhbSk7XG4gICAgfSBjYXRjaCAoZSkge1xuICAgICAgICBsb2dnZXIuZXJyb3IoZSk7XG4gICAgfVxufTtcblxuVHJhY2VhYmxlUGVlckNvbm5lY3Rpb24ucHJvdG90eXBlLmNyZWF0ZURhdGFDaGFubmVsID0gZnVuY3Rpb24gKGxhYmVsLCBvcHRzKSB7XG4gICAgdGhpcy50cmFjZSgnY3JlYXRlRGF0YUNoYW5uZWwnLCBsYWJlbCwgb3B0cyk7XG4gICAgcmV0dXJuIHRoaXMucGVlcmNvbm5lY3Rpb24uY3JlYXRlRGF0YUNoYW5uZWwobGFiZWwsIG9wdHMpO1xufTtcblxuVHJhY2VhYmxlUGVlckNvbm5lY3Rpb24ucHJvdG90eXBlLnNldExvY2FsRGVzY3JpcHRpb25cbiAgICAgICAgPSBmdW5jdGlvbiAoZGVzY3JpcHRpb24sIHN1Y2Nlc3NDYWxsYmFjaywgZmFpbHVyZUNhbGxiYWNrKSB7XG4gICAgdGhpcy50cmFjZSgnc2V0TG9jYWxEZXNjcmlwdGlvbjo6cHJlVHJhbnNmb3JtJywgZHVtcFNEUChkZXNjcmlwdGlvbikpO1xuICAgIC8vIGlmIHdlJ3JlIHJ1bm5pbmcgb24gRkYsIHRyYW5zZm9ybSB0byBQbGFuIEEgZmlyc3QuXG4gICAgaWYgKFJUQ0Jyb3dzZXJUeXBlLnVzZXNVbmlmaWVkUGxhbigpKSB7XG4gICAgICAgIGRlc2NyaXB0aW9uID0gdGhpcy5pbnRlcm9wLnRvVW5pZmllZFBsYW4oZGVzY3JpcHRpb24pO1xuICAgICAgICB0aGlzLnRyYWNlKCdzZXRMb2NhbERlc2NyaXB0aW9uOjpwb3N0VHJhbnNmb3JtIChQbGFuIEEpJywgZHVtcFNEUChkZXNjcmlwdGlvbikpO1xuICAgIH1cblxuICAgIHZhciBzZWxmID0gdGhpcztcbiAgICB0aGlzLnBlZXJjb25uZWN0aW9uLnNldExvY2FsRGVzY3JpcHRpb24oZGVzY3JpcHRpb24sXG4gICAgICAgIGZ1bmN0aW9uICgpIHtcbiAgICAgICAgICAgIHNlbGYudHJhY2UoJ3NldExvY2FsRGVzY3JpcHRpb25PblN1Y2Nlc3MnKTtcbiAgICAgICAgICAgIHN1Y2Nlc3NDYWxsYmFjaygpO1xuICAgICAgICB9LFxuICAgICAgICBmdW5jdGlvbiAoZXJyKSB7XG4gICAgICAgICAgICBzZWxmLnRyYWNlKCdzZXRMb2NhbERlc2NyaXB0aW9uT25GYWlsdXJlJywgZXJyKTtcbiAgICAgICAgICAgIGZhaWx1cmVDYWxsYmFjayhlcnIpO1xuICAgICAgICB9XG4gICAgKTtcbiAgICAvKlxuICAgICBpZiAodGhpcy5zdGF0c2ludGVydmFsID09PSBudWxsICYmIHRoaXMubWF4c3RhdHMgPiAwKSB7XG4gICAgIC8vIHN0YXJ0IGdhdGhlcmluZyBzdGF0c1xuICAgICB9XG4gICAgICovXG59O1xuXG5UcmFjZWFibGVQZWVyQ29ubmVjdGlvbi5wcm90b3R5cGUuc2V0UmVtb3RlRGVzY3JpcHRpb25cbiAgICAgICAgPSBmdW5jdGlvbiAoZGVzY3JpcHRpb24sIHN1Y2Nlc3NDYWxsYmFjaywgZmFpbHVyZUNhbGxiYWNrKSB7XG4gICAgdGhpcy50cmFjZSgnc2V0UmVtb3RlRGVzY3JpcHRpb246OnByZVRyYW5zZm9ybScsIGR1bXBTRFAoZGVzY3JpcHRpb24pKTtcbiAgICAvLyBUT0RPIHRoZSBmb2N1cyBzaG91bGQgc3F1ZXplIG9yIGV4cGxvZGUgdGhlIHJlbW90ZSBzaW11bGNhc3RcbiAgICBkZXNjcmlwdGlvbiA9IHRoaXMuc2ltdWxjYXN0Lm11bmdlUmVtb3RlRGVzY3JpcHRpb24oZGVzY3JpcHRpb24pO1xuICAgIHRoaXMudHJhY2UoJ3NldFJlbW90ZURlc2NyaXB0aW9uOjpwb3N0VHJhbnNmb3JtIChzaW11bGNhc3QpJywgZHVtcFNEUChkZXNjcmlwdGlvbikpO1xuXG4gICAgLy8gaWYgd2UncmUgcnVubmluZyBvbiBGRiwgdHJhbnNmb3JtIHRvIFBsYW4gQSBmaXJzdC5cbiAgICBpZiAoUlRDQnJvd3NlclR5cGUudXNlc1VuaWZpZWRQbGFuKCkpIHtcbiAgICAgICAgZGVzY3JpcHRpb24gPSB0aGlzLmludGVyb3AudG9VbmlmaWVkUGxhbihkZXNjcmlwdGlvbik7XG4gICAgICAgIHRoaXMudHJhY2UoJ3NldFJlbW90ZURlc2NyaXB0aW9uOjpwb3N0VHJhbnNmb3JtIChQbGFuIEEpJywgZHVtcFNEUChkZXNjcmlwdGlvbikpO1xuICAgIH1cblxuICAgIGlmIChSVENCcm93c2VyVHlwZS51c2VzUGxhbkIoKSkge1xuICAgICAgICBkZXNjcmlwdGlvbiA9IG5vcm1hbGl6ZVBsYW5CKGRlc2NyaXB0aW9uKTtcbiAgICB9XG5cbiAgICB2YXIgc2VsZiA9IHRoaXM7XG4gICAgdGhpcy5wZWVyY29ubmVjdGlvbi5zZXRSZW1vdGVEZXNjcmlwdGlvbihkZXNjcmlwdGlvbixcbiAgICAgICAgZnVuY3Rpb24gKCkge1xuICAgICAgICAgICAgc2VsZi50cmFjZSgnc2V0UmVtb3RlRGVzY3JpcHRpb25PblN1Y2Nlc3MnKTtcbiAgICAgICAgICAgIHN1Y2Nlc3NDYWxsYmFjaygpO1xuICAgICAgICB9LFxuICAgICAgICBmdW5jdGlvbiAoZXJyKSB7XG4gICAgICAgICAgICBzZWxmLnRyYWNlKCdzZXRSZW1vdGVEZXNjcmlwdGlvbk9uRmFpbHVyZScsIGVycik7XG4gICAgICAgICAgICBmYWlsdXJlQ2FsbGJhY2soZXJyKTtcbiAgICAgICAgfVxuICAgICk7XG4gICAgLypcbiAgICAgaWYgKHRoaXMuc3RhdHNpbnRlcnZhbCA9PT0gbnVsbCAmJiB0aGlzLm1heHN0YXRzID4gMCkge1xuICAgICAvLyBzdGFydCBnYXRoZXJpbmcgc3RhdHNcbiAgICAgfVxuICAgICAqL1xufTtcblxuVHJhY2VhYmxlUGVlckNvbm5lY3Rpb24ucHJvdG90eXBlLmNsb3NlID0gZnVuY3Rpb24gKCkge1xuICAgIHRoaXMudHJhY2UoJ3N0b3AnKTtcbiAgICBpZiAodGhpcy5zdGF0c2ludGVydmFsICE9PSBudWxsKSB7XG4gICAgICAgIHdpbmRvdy5jbGVhckludGVydmFsKHRoaXMuc3RhdHNpbnRlcnZhbCk7XG4gICAgICAgIHRoaXMuc3RhdHNpbnRlcnZhbCA9IG51bGw7XG4gICAgfVxuICAgIHRoaXMucGVlcmNvbm5lY3Rpb24uY2xvc2UoKTtcbn07XG5cblRyYWNlYWJsZVBlZXJDb25uZWN0aW9uLnByb3RvdHlwZS5jcmVhdGVPZmZlclxuICAgICAgICA9IGZ1bmN0aW9uIChzdWNjZXNzQ2FsbGJhY2ssIGZhaWx1cmVDYWxsYmFjaywgY29uc3RyYWludHMpIHtcbiAgICB2YXIgc2VsZiA9IHRoaXM7XG4gICAgdGhpcy50cmFjZSgnY3JlYXRlT2ZmZXInLCBKU09OLnN0cmluZ2lmeShjb25zdHJhaW50cywgbnVsbCwgJyAnKSk7XG4gICAgdGhpcy5wZWVyY29ubmVjdGlvbi5jcmVhdGVPZmZlcihcbiAgICAgICAgZnVuY3Rpb24gKG9mZmVyKSB7XG4gICAgICAgICAgICBzZWxmLnRyYWNlKCdjcmVhdGVPZmZlck9uU3VjY2Vzczo6cHJlVHJhbnNmb3JtJywgZHVtcFNEUChvZmZlcikpO1xuICAgICAgICAgICAgLy8gTk9URSB0aGlzIGlzIG5vdCB0ZXN0ZWQgYmVjYXVzZSBpbiBtZWV0IHRoZSBmb2N1cyBnZW5lcmF0ZXMgdGhlXG4gICAgICAgICAgICAvLyBvZmZlci5cblxuICAgICAgICAgICAgLy8gaWYgd2UncmUgcnVubmluZyBvbiBGRiwgdHJhbnNmb3JtIHRvIFBsYW4gQiBmaXJzdC5cbiAgICAgICAgICAgIGlmIChSVENCcm93c2VyVHlwZS51c2VzVW5pZmllZFBsYW4oKSkge1xuICAgICAgICAgICAgICAgIG9mZmVyID0gc2VsZi5pbnRlcm9wLnRvUGxhbkIob2ZmZXIpO1xuICAgICAgICAgICAgICAgIHNlbGYudHJhY2UoJ2NyZWF0ZU9mZmVyT25TdWNjZXNzOjpwb3N0VHJhbnNmb3JtIChQbGFuIEIpJywgZHVtcFNEUChvZmZlcikpO1xuICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICBvZmZlciA9IFNTUkNSZXBsYWNlbWVudC5tdW5nZUxvY2FsVmlkZW9TU1JDKG9mZmVyKTtcblxuICAgICAgICAgICAgaWYgKHNlbGYuc2Vzc2lvbi5yb29tLm9wdGlvbnMuZW5hYmxlU2ltdWxjYXN0ICYmIHNlbGYuc2ltdWxjYXN0LmlzU3VwcG9ydGVkKCkpIHtcbiAgICAgICAgICAgICAgICBvZmZlciA9IHNlbGYuc2ltdWxjYXN0Lm11bmdlTG9jYWxEZXNjcmlwdGlvbihvZmZlcik7XG4gICAgICAgICAgICAgICAgc2VsZi50cmFjZSgnY3JlYXRlT2ZmZXJPblN1Y2Nlc3M6OnBvc3RUcmFuc2Zvcm0gKHNpbXVsY2FzdCknLCBkdW1wU0RQKG9mZmVyKSk7XG4gICAgICAgICAgICB9XG4gICAgICAgICAgICBzdWNjZXNzQ2FsbGJhY2sob2ZmZXIpO1xuICAgICAgICB9LFxuICAgICAgICBmdW5jdGlvbihlcnIpIHtcbiAgICAgICAgICAgIHNlbGYudHJhY2UoJ2NyZWF0ZU9mZmVyT25GYWlsdXJlJywgZXJyKTtcbiAgICAgICAgICAgIGZhaWx1cmVDYWxsYmFjayhlcnIpO1xuICAgICAgICB9LFxuICAgICAgICBjb25zdHJhaW50c1xuICAgICk7XG59O1xuXG5UcmFjZWFibGVQZWVyQ29ubmVjdGlvbi5wcm90b3R5cGUuY3JlYXRlQW5zd2VyXG4gICAgICAgID0gZnVuY3Rpb24gKHN1Y2Nlc3NDYWxsYmFjaywgZmFpbHVyZUNhbGxiYWNrLCBjb25zdHJhaW50cykge1xuICAgIHZhciBzZWxmID0gdGhpcztcbiAgICB0aGlzLnRyYWNlKCdjcmVhdGVBbnN3ZXInLCBKU09OLnN0cmluZ2lmeShjb25zdHJhaW50cywgbnVsbCwgJyAnKSk7XG4gICAgdGhpcy5wZWVyY29ubmVjdGlvbi5jcmVhdGVBbnN3ZXIoXG4gICAgICAgIGZ1bmN0aW9uIChhbnN3ZXIpIHtcbiAgICAgICAgICAgIHNlbGYudHJhY2UoJ2NyZWF0ZUFuc3dlck9uU3VjY2Vzczo6cHJlVHJhbnNmb3JtJywgZHVtcFNEUChhbnN3ZXIpKTtcbiAgICAgICAgICAgIC8vIGlmIHdlJ3JlIHJ1bm5pbmcgb24gRkYsIHRyYW5zZm9ybSB0byBQbGFuIEEgZmlyc3QuXG4gICAgICAgICAgICBpZiAoUlRDQnJvd3NlclR5cGUudXNlc1VuaWZpZWRQbGFuKCkpIHtcbiAgICAgICAgICAgICAgICBhbnN3ZXIgPSBzZWxmLmludGVyb3AudG9QbGFuQihhbnN3ZXIpO1xuICAgICAgICAgICAgICAgIHNlbGYudHJhY2UoJ2NyZWF0ZUFuc3dlck9uU3VjY2Vzczo6cG9zdFRyYW5zZm9ybSAoUGxhbiBCKScsIGR1bXBTRFAoYW5zd2VyKSk7XG4gICAgICAgICAgICB9XG5cbiAgICAgICAgICAgIC8vIG11bmdlIGxvY2FsIHZpZGVvIFNTUkNcbiAgICAgICAgICAgIGFuc3dlciA9IFNTUkNSZXBsYWNlbWVudC5tdW5nZUxvY2FsVmlkZW9TU1JDKGFuc3dlcik7XG5cbiAgICAgICAgICAgIGlmIChzZWxmLnNlc3Npb24ucm9vbS5vcHRpb25zLmVuYWJsZVNpbXVsY2FzdCAmJiBzZWxmLnNpbXVsY2FzdC5pc1N1cHBvcnRlZCgpKSB7XG4gICAgICAgICAgICAgICAgYW5zd2VyID0gc2VsZi5zaW11bGNhc3QubXVuZ2VMb2NhbERlc2NyaXB0aW9uKGFuc3dlcik7XG4gICAgICAgICAgICAgICAgc2VsZi50cmFjZSgnY3JlYXRlQW5zd2VyT25TdWNjZXNzOjpwb3N0VHJhbnNmb3JtIChzaW11bGNhc3QpJywgZHVtcFNEUChhbnN3ZXIpKTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgICAgIHN1Y2Nlc3NDYWxsYmFjayhhbnN3ZXIpO1xuICAgICAgICB9LFxuICAgICAgICBmdW5jdGlvbihlcnIpIHtcbiAgICAgICAgICAgIHNlbGYudHJhY2UoJ2NyZWF0ZUFuc3dlck9uRmFpbHVyZScsIGVycik7XG4gICAgICAgICAgICBmYWlsdXJlQ2FsbGJhY2soZXJyKTtcbiAgICAgICAgfSxcbiAgICAgICAgY29uc3RyYWludHNcbiAgICApO1xufTtcblxuVHJhY2VhYmxlUGVlckNvbm5lY3Rpb24ucHJvdG90eXBlLmFkZEljZUNhbmRpZGF0ZVxuICAgICAgICA9IGZ1bmN0aW9uIChjYW5kaWRhdGUsIHN1Y2Nlc3NDYWxsYmFjaywgZmFpbHVyZUNhbGxiYWNrKSB7XG4gICAgLy92YXIgc2VsZiA9IHRoaXM7XG4gICAgdGhpcy50cmFjZSgnYWRkSWNlQ2FuZGlkYXRlJywgSlNPTi5zdHJpbmdpZnkoY2FuZGlkYXRlLCBudWxsLCAnICcpKTtcbiAgICB0aGlzLnBlZXJjb25uZWN0aW9uLmFkZEljZUNhbmRpZGF0ZShjYW5kaWRhdGUpO1xuICAgIC8qIG1heWJlIGxhdGVyXG4gICAgIHRoaXMucGVlcmNvbm5lY3Rpb24uYWRkSWNlQ2FuZGlkYXRlKGNhbmRpZGF0ZSxcbiAgICAgZnVuY3Rpb24gKCkge1xuICAgICBzZWxmLnRyYWNlKCdhZGRJY2VDYW5kaWRhdGVPblN1Y2Nlc3MnKTtcbiAgICAgc3VjY2Vzc0NhbGxiYWNrKCk7XG4gICAgIH0sXG4gICAgIGZ1bmN0aW9uIChlcnIpIHtcbiAgICAgc2VsZi50cmFjZSgnYWRkSWNlQ2FuZGlkYXRlT25GYWlsdXJlJywgZXJyKTtcbiAgICAgZmFpbHVyZUNhbGxiYWNrKGVycik7XG4gICAgIH1cbiAgICAgKTtcbiAgICAgKi9cbn07XG5cblRyYWNlYWJsZVBlZXJDb25uZWN0aW9uLnByb3RvdHlwZS5nZXRTdGF0cyA9IGZ1bmN0aW9uKGNhbGxiYWNrLCBlcnJiYWNrKSB7XG4gICAgLy8gVE9ETzogSXMgdGhpcyB0aGUgY29ycmVjdCB3YXkgdG8gaGFuZGxlIE9wZXJhLCBUZW1hc3lzP1xuICAgIGlmIChSVENCcm93c2VyVHlwZS5pc0ZpcmVmb3goKSkge1xuICAgICAgICAvLyBpZ25vcmUgZm9yIG5vdy4uLlxuICAgICAgICBpZighZXJyYmFjaylcbiAgICAgICAgICAgIGVycmJhY2sgPSBmdW5jdGlvbiAoKSB7fTtcbiAgICAgICAgdGhpcy5wZWVyY29ubmVjdGlvbi5nZXRTdGF0cyhudWxsLCBjYWxsYmFjaywgZXJyYmFjayk7XG4gICAgfSBlbHNlIHtcbiAgICAgICAgdGhpcy5wZWVyY29ubmVjdGlvbi5nZXRTdGF0cyhjYWxsYmFjayk7XG4gICAgfVxufTtcblxubW9kdWxlLmV4cG9ydHMgPSBUcmFjZWFibGVQZWVyQ29ubmVjdGlvbjtcbiIsIi8qIGdsb2JhbCAkLCAkaXEsIFByb21pc2UsIFN0cm9waGUgKi9cblxudmFyIGxvZ2dlciA9IHJlcXVpcmUoXCJqaXRzaS1tZWV0LWxvZ2dlclwiKS5nZXRMb2dnZXIoX19maWxlbmFtZSk7XG52YXIgWE1QUEV2ZW50cyA9IHJlcXVpcmUoXCIuLi8uLi9zZXJ2aWNlL3htcHAvWE1QUEV2ZW50c1wiKTtcbnZhciBTZXR0aW5ncyA9IHJlcXVpcmUoXCIuLi9zZXR0aW5ncy9TZXR0aW5nc1wiKTtcblxudmFyIEF1dGhlbnRpY2F0aW9uRXZlbnRzXG4gICAgPSByZXF1aXJlKFwiLi4vLi4vc2VydmljZS9hdXRoZW50aWNhdGlvbi9BdXRoZW50aWNhdGlvbkV2ZW50c1wiKTtcblxuZnVuY3Rpb24gY3JlYXRlRXhwQmFja29mZlRpbWVyKHN0ZXApIHtcbiAgICB2YXIgY291bnQgPSAxO1xuICAgIHJldHVybiBmdW5jdGlvbiAocmVzZXQpIHtcbiAgICAgICAgLy8gUmVzZXQgY2FsbFxuICAgICAgICBpZiAocmVzZXQpIHtcbiAgICAgICAgICAgIGNvdW50ID0gMTtcbiAgICAgICAgICAgIHJldHVybjtcbiAgICAgICAgfVxuICAgICAgICAvLyBDYWxjdWxhdGUgbmV4dCB0aW1lb3V0XG4gICAgICAgIHZhciB0aW1lb3V0ID0gTWF0aC5wb3coMiwgY291bnQgLSAxKTtcbiAgICAgICAgY291bnQgKz0gMTtcbiAgICAgICAgcmV0dXJuIHRpbWVvdXQgKiBzdGVwO1xuICAgIH07XG59XG5cblxuXG5cblxuZnVuY3Rpb24gTW9kZXJhdG9yKHJvb21OYW1lLCB4bXBwLCBlbWl0dGVyKSB7XG4gICAgdGhpcy5yb29tTmFtZSA9IHJvb21OYW1lO1xuICAgIHRoaXMueG1wcFNlcnZpY2UgPSB4bXBwO1xuICAgIHRoaXMuZ2V0TmV4dFRpbWVvdXQgPSBjcmVhdGVFeHBCYWNrb2ZmVGltZXIoMTAwMCk7XG4gICAgdGhpcy5nZXROZXh0RXJyb3JUaW1lb3V0ID0gY3JlYXRlRXhwQmFja29mZlRpbWVyKDEwMDApO1xuICAgIC8vIEV4dGVybmFsIGF1dGhlbnRpY2F0aW9uIHN0dWZmXG4gICAgdGhpcy5leHRlcm5hbEF1dGhFbmFibGVkID0gZmFsc2U7XG4gICAgdGhpcy5zZXR0aW5ncyA9IG5ldyBTZXR0aW5ncyhyb29tTmFtZSk7XG4gICAgLy8gU2lwIGdhdGV3YXkgY2FuIGJlIGVuYWJsZWQgYnkgY29uZmlndXJpbmcgSmlnYXNpIGhvc3QgaW4gY29uZmlnLmpzIG9yXG4gICAgLy8gaXQgd2lsbCBiZSBlbmFibGVkIGF1dG9tYXRpY2FsbHkgaWYgZm9jdXMgZGV0ZWN0cyB0aGUgY29tcG9uZW50IHRocm91Z2hcbiAgICAvLyBzZXJ2aWNlIGRpc2NvdmVyeS5cbiAgICB0aGlzLnNpcEdhdGV3YXlFbmFibGVkID0gdGhpcy54bXBwU2VydmljZS5vcHRpb25zLmhvc3RzICYmXG4gICAgICAgIHRoaXMueG1wcFNlcnZpY2Uub3B0aW9ucy5ob3N0cy5jYWxsX2NvbnRyb2wgIT09IHVuZGVmaW5lZDtcblxuICAgIHRoaXMuZXZlbnRFbWl0dGVyID0gZW1pdHRlcjtcblxuICAgIHRoaXMuY29ubmVjdGlvbiA9IHRoaXMueG1wcFNlcnZpY2UuY29ubmVjdGlvbjtcbiAgICB0aGlzLmZvY3VzVXNlckppZDtcbiAgICAvL0ZJWE1FOlxuICAgIC8vIE1lc3NhZ2UgbGlzdGVuZXIgdGhhdCB0YWxrcyB0byBQT1BVUCB3aW5kb3dcbiAgICBmdW5jdGlvbiBsaXN0ZW5lcihldmVudCkge1xuICAgICAgICBpZiAoZXZlbnQuZGF0YSAmJiBldmVudC5kYXRhLnNlc3Npb25JZCkge1xuICAgICAgICAgICAgaWYgKGV2ZW50Lm9yaWdpbiAhPT0gd2luZG93LmxvY2F0aW9uLm9yaWdpbikge1xuICAgICAgICAgICAgICAgIGxvZ2dlci53YXJuKFwiSWdub3Jpbmcgc2Vzc2lvbklkIGZyb20gZGlmZmVyZW50IG9yaWdpbjogXCIgK1xuICAgICAgICAgICAgICAgICAgICBldmVudC5vcmlnaW4pO1xuICAgICAgICAgICAgICAgIHJldHVybjtcbiAgICAgICAgICAgIH1cbiAgICAgICAgICAgIGxvY2FsU3RvcmFnZS5zZXRJdGVtKCdzZXNzaW9uSWQnLCBldmVudC5kYXRhLnNlc3Npb25JZCk7XG4gICAgICAgICAgICAvLyBBZnRlciBwb3B1cCBpcyBjbG9zZWQgd2Ugd2lsbCBhdXRoZW50aWNhdGVcbiAgICAgICAgfVxuICAgIH1cbiAgICAvLyBSZWdpc3RlclxuICAgIGlmICh3aW5kb3cuYWRkRXZlbnRMaXN0ZW5lcikge1xuICAgICAgICB3aW5kb3cuYWRkRXZlbnRMaXN0ZW5lcihcIm1lc3NhZ2VcIiwgbGlzdGVuZXIsIGZhbHNlKTtcbiAgICB9IGVsc2Uge1xuICAgICAgICB3aW5kb3cuYXR0YWNoRXZlbnQoXCJvbm1lc3NhZ2VcIiwgbGlzdGVuZXIpO1xuICAgIH1cbn1cblxuTW9kZXJhdG9yLnByb3RvdHlwZS5pc0V4dGVybmFsQXV0aEVuYWJsZWQgPSAgZnVuY3Rpb24gKCkge1xuICAgIHJldHVybiB0aGlzLmV4dGVybmFsQXV0aEVuYWJsZWQ7XG59O1xuXG5Nb2RlcmF0b3IucHJvdG90eXBlLmlzU2lwR2F0ZXdheUVuYWJsZWQgPSAgZnVuY3Rpb24gKCkge1xuICAgIHJldHVybiB0aGlzLnNpcEdhdGV3YXlFbmFibGVkO1xufTtcblxuXG5Nb2RlcmF0b3IucHJvdG90eXBlLm9uTXVjTWVtYmVyTGVmdCA9ICBmdW5jdGlvbiAoamlkKSB7XG4gICAgbG9nZ2VyLmluZm8oXCJTb21lb25lIGxlZnQgaXMgaXQgZm9jdXMgPyBcIiArIGppZCk7XG4gICAgdmFyIHJlc291cmNlID0gU3Ryb3BoZS5nZXRSZXNvdXJjZUZyb21KaWQoamlkKTtcbiAgICBpZiAocmVzb3VyY2UgPT09ICdmb2N1cycgJiYgIXRoaXMueG1wcFNlcnZpY2Uuc2Vzc2lvblRlcm1pbmF0ZWQpIHtcbiAgICAgICAgbG9nZ2VyLmluZm8oXG4gICAgICAgICAgICBcIkZvY3VzIGhhcyBsZWZ0IHRoZSByb29tIC0gbGVhdmluZyBjb25mZXJlbmNlXCIpO1xuICAgICAgICAvL2hhbmdVcCgpO1xuICAgICAgICAvLyBXZSdkIHJhdGhlciByZWxvYWQgdG8gaGF2ZSBldmVyeXRoaW5nIHJlLWluaXRpYWxpemVkXG4gICAgICAgIC8vRklYTUU6IHNob3cgc29tZSBtZXNzYWdlIGJlZm9yZSByZWxvYWRcbiAgICAgICAgdGhpcy5ldmVudEVtaXR0ZXIuZW1pdChYTVBQRXZlbnRzLkZPQ1VTX0xFRlQpO1xuICAgIH1cbn07XG5cblxuTW9kZXJhdG9yLnByb3RvdHlwZS5zZXRGb2N1c1VzZXJKaWQgPSAgZnVuY3Rpb24gKGZvY3VzSmlkKSB7XG4gICAgaWYgKCF0aGlzLmZvY3VzVXNlckppZCkge1xuICAgICAgICB0aGlzLmZvY3VzVXNlckppZCA9IGZvY3VzSmlkO1xuICAgICAgICBsb2dnZXIuaW5mbyhcIkZvY3VzIGppZCBzZXQgdG86ICBcIiArIHRoaXMuZm9jdXNVc2VySmlkKTtcbiAgICB9XG59O1xuXG5cbk1vZGVyYXRvci5wcm90b3R5cGUuZ2V0Rm9jdXNVc2VySmlkID0gIGZ1bmN0aW9uICgpIHtcbiAgICByZXR1cm4gdGhpcy5mb2N1c1VzZXJKaWQ7XG59O1xuXG5Nb2RlcmF0b3IucHJvdG90eXBlLmdldEZvY3VzQ29tcG9uZW50ID0gIGZ1bmN0aW9uICgpIHtcbiAgICAvLyBHZXQgZm9jdXMgY29tcG9uZW50IGFkZHJlc3NcbiAgICB2YXIgZm9jdXNDb21wb25lbnQgPSB0aGlzLnhtcHBTZXJ2aWNlLm9wdGlvbnMuaG9zdHMuZm9jdXM7XG4gICAgLy8gSWYgbm90IHNwZWNpZmllZCB1c2UgZGVmYXVsdDogICdmb2N1cy5kb21haW4nXG4gICAgaWYgKCFmb2N1c0NvbXBvbmVudCkge1xuICAgICAgICBmb2N1c0NvbXBvbmVudCA9ICdmb2N1cy4nICsgdGhpcy54bXBwU2VydmljZS5vcHRpb25zLmhvc3RzLmRvbWFpbjtcbiAgICB9XG4gICAgcmV0dXJuIGZvY3VzQ29tcG9uZW50O1xufTtcblxuTW9kZXJhdG9yLnByb3RvdHlwZS5jcmVhdGVDb25mZXJlbmNlSXEgPSAgZnVuY3Rpb24gKCkge1xuICAgIC8vIEdlbmVyYXRlIGNyZWF0ZSBjb25mZXJlbmNlIElRXG4gICAgdmFyIGVsZW0gPSAkaXEoe3RvOiB0aGlzLmdldEZvY3VzQ29tcG9uZW50KCksIHR5cGU6ICdzZXQnfSk7XG5cbiAgICAvLyBTZXNzaW9uIElkIHVzZWQgZm9yIGF1dGhlbnRpY2F0aW9uXG4gICAgdmFyIHNlc3Npb25JZCA9IGxvY2FsU3RvcmFnZS5nZXRJdGVtKCdzZXNzaW9uSWQnKTtcbiAgICB2YXIgbWFjaGluZVVJRCA9IHRoaXMuc2V0dGluZ3MuZ2V0U2V0dGluZ3MoKS51aWQ7XG5cbiAgICBsb2dnZXIuaW5mbyhcbiAgICAgICAgICAgIFwiU2Vzc2lvbiBJRDogXCIgKyBzZXNzaW9uSWQgKyBcIiBtYWNoaW5lIFVJRDogXCIgKyBtYWNoaW5lVUlEKTtcblxuICAgIGVsZW0uYygnY29uZmVyZW5jZScsIHtcbiAgICAgICAgeG1sbnM6ICdodHRwOi8vaml0c2kub3JnL3Byb3RvY29sL2ZvY3VzJyxcbiAgICAgICAgcm9vbTogdGhpcy5yb29tTmFtZSxcbiAgICAgICAgJ21hY2hpbmUtdWlkJzogbWFjaGluZVVJRFxuICAgIH0pO1xuXG4gICAgaWYgKHNlc3Npb25JZCkge1xuICAgICAgICBlbGVtLmF0dHJzKHsgJ3Nlc3Npb24taWQnOiBzZXNzaW9uSWR9KTtcbiAgICB9XG4gICAgaWYgKHRoaXMueG1wcFNlcnZpY2Uub3B0aW9ucy5ob3N0cy5icmlkZ2UgIT09IHVuZGVmaW5lZCkge1xuICAgICAgICBlbGVtLmMoXG4gICAgICAgICAgICAncHJvcGVydHknLCB7XG4gICAgICAgICAgICAgICAgbmFtZTogJ2JyaWRnZScsXG4gICAgICAgICAgICAgICAgdmFsdWU6IHRoaXMueG1wcFNlcnZpY2Uub3B0aW9ucy5ob3N0cy5icmlkZ2VcbiAgICAgICAgICAgIH0pLnVwKCk7XG4gICAgfVxuICAgIGlmICh0aGlzLnhtcHBTZXJ2aWNlLm9wdGlvbnMuZW5mb3JjZWRCcmlkZ2UgIT09IHVuZGVmaW5lZCkge1xuICAgICAgICBlbGVtLmMoXG4gICAgICAgICAgICAncHJvcGVydHknLCB7XG4gICAgICAgICAgICAgICAgbmFtZTogJ2VuZm9yY2VkQnJpZGdlJyxcbiAgICAgICAgICAgICAgICB2YWx1ZTogdGhpcy54bXBwU2VydmljZS5vcHRpb25zLmVuZm9yY2VkQnJpZGdlXG4gICAgICAgICAgICB9KS51cCgpO1xuICAgIH1cbiAgICAvLyBUZWxsIHRoZSBmb2N1cyB3ZSBoYXZlIEppZ2FzaSBjb25maWd1cmVkXG4gICAgaWYgKHRoaXMueG1wcFNlcnZpY2Uub3B0aW9ucy5ob3N0cy5jYWxsX2NvbnRyb2wgIT09IHVuZGVmaW5lZCkge1xuICAgICAgICBlbGVtLmMoXG4gICAgICAgICAgICAncHJvcGVydHknLCB7XG4gICAgICAgICAgICAgICAgbmFtZTogJ2NhbGxfY29udHJvbCcsXG4gICAgICAgICAgICAgICAgdmFsdWU6ICB0aGlzLnhtcHBTZXJ2aWNlLm9wdGlvbnMuaG9zdHMuY2FsbF9jb250cm9sXG4gICAgICAgICAgICB9KS51cCgpO1xuICAgIH1cbiAgICBpZiAodGhpcy54bXBwU2VydmljZS5vcHRpb25zLmNoYW5uZWxMYXN0TiAhPT0gdW5kZWZpbmVkKSB7XG4gICAgICAgIGVsZW0uYyhcbiAgICAgICAgICAgICdwcm9wZXJ0eScsIHtcbiAgICAgICAgICAgICAgICBuYW1lOiAnY2hhbm5lbExhc3ROJyxcbiAgICAgICAgICAgICAgICB2YWx1ZTogdGhpcy54bXBwU2VydmljZS5vcHRpb25zLmNoYW5uZWxMYXN0TlxuICAgICAgICAgICAgfSkudXAoKTtcbiAgICB9XG4gICAgaWYgKHRoaXMueG1wcFNlcnZpY2Uub3B0aW9ucy5hZGFwdGl2ZUxhc3ROICE9PSB1bmRlZmluZWQpIHtcbiAgICAgICAgZWxlbS5jKFxuICAgICAgICAgICAgJ3Byb3BlcnR5Jywge1xuICAgICAgICAgICAgICAgIG5hbWU6ICdhZGFwdGl2ZUxhc3ROJyxcbiAgICAgICAgICAgICAgICB2YWx1ZTogdGhpcy54bXBwU2VydmljZS5vcHRpb25zLmFkYXB0aXZlTGFzdE5cbiAgICAgICAgICAgIH0pLnVwKCk7XG4gICAgfVxuICAgIGlmICh0aGlzLnhtcHBTZXJ2aWNlLm9wdGlvbnMuYWRhcHRpdmVTaW11bGNhc3QgIT09IHVuZGVmaW5lZCkge1xuICAgICAgICBlbGVtLmMoXG4gICAgICAgICAgICAncHJvcGVydHknLCB7XG4gICAgICAgICAgICAgICAgbmFtZTogJ2FkYXB0aXZlU2ltdWxjYXN0JyxcbiAgICAgICAgICAgICAgICB2YWx1ZTogdGhpcy54bXBwU2VydmljZS5vcHRpb25zLmFkYXB0aXZlU2ltdWxjYXN0XG4gICAgICAgICAgICB9KS51cCgpO1xuICAgIH1cbiAgICBpZiAodGhpcy54bXBwU2VydmljZS5vcHRpb25zLm9wZW5TY3RwICE9PSB1bmRlZmluZWQpIHtcbiAgICAgICAgZWxlbS5jKFxuICAgICAgICAgICAgJ3Byb3BlcnR5Jywge1xuICAgICAgICAgICAgICAgIG5hbWU6ICdvcGVuU2N0cCcsXG4gICAgICAgICAgICAgICAgdmFsdWU6IHRoaXMueG1wcFNlcnZpY2Uub3B0aW9ucy5vcGVuU2N0cFxuICAgICAgICAgICAgfSkudXAoKTtcbiAgICB9XG4gICAgaWYgKHRoaXMueG1wcFNlcnZpY2Uub3B0aW9ucy5zdGFydEF1ZGlvTXV0ZWQgIT09IHVuZGVmaW5lZClcbiAgICB7XG4gICAgICAgIGVsZW0uYyhcbiAgICAgICAgICAgICdwcm9wZXJ0eScsIHtcbiAgICAgICAgICAgICAgICBuYW1lOiAnc3RhcnRBdWRpb011dGVkJyxcbiAgICAgICAgICAgICAgICB2YWx1ZTogdGhpcy54bXBwU2VydmljZS5vcHRpb25zLnN0YXJ0QXVkaW9NdXRlZFxuICAgICAgICAgICAgfSkudXAoKTtcbiAgICB9XG4gICAgaWYgKHRoaXMueG1wcFNlcnZpY2Uub3B0aW9ucy5zdGFydFZpZGVvTXV0ZWQgIT09IHVuZGVmaW5lZClcbiAgICB7XG4gICAgICAgIGVsZW0uYyhcbiAgICAgICAgICAgICdwcm9wZXJ0eScsIHtcbiAgICAgICAgICAgICAgICBuYW1lOiAnc3RhcnRWaWRlb011dGVkJyxcbiAgICAgICAgICAgICAgICB2YWx1ZTogdGhpcy54bXBwU2VydmljZS5vcHRpb25zLnN0YXJ0VmlkZW9NdXRlZFxuICAgICAgICAgICAgfSkudXAoKTtcbiAgICB9XG4gICAgZWxlbS5jKFxuICAgICAgICAncHJvcGVydHknLCB7XG4gICAgICAgICAgICBuYW1lOiAnc2ltdWxjYXN0TW9kZScsXG4gICAgICAgICAgICB2YWx1ZTogJ3Jld3JpdGluZydcbiAgICAgICAgfSkudXAoKTtcbiAgICBlbGVtLnVwKCk7XG4gICAgcmV0dXJuIGVsZW07XG59O1xuXG5cbk1vZGVyYXRvci5wcm90b3R5cGUucGFyc2VTZXNzaW9uSWQgPSAgZnVuY3Rpb24gKHJlc3VsdElxKSB7XG4gICAgdmFyIHNlc3Npb25JZCA9ICQocmVzdWx0SXEpLmZpbmQoJ2NvbmZlcmVuY2UnKS5hdHRyKCdzZXNzaW9uLWlkJyk7XG4gICAgaWYgKHNlc3Npb25JZCkge1xuICAgICAgICBsb2dnZXIuaW5mbygnUmVjZWl2ZWQgc2Vzc2lvbklkOiAgJyArIHNlc3Npb25JZCk7XG4gICAgICAgIGxvY2FsU3RvcmFnZS5zZXRJdGVtKCdzZXNzaW9uSWQnLCBzZXNzaW9uSWQpO1xuICAgIH1cbn07XG5cbk1vZGVyYXRvci5wcm90b3R5cGUucGFyc2VDb25maWdPcHRpb25zID0gIGZ1bmN0aW9uIChyZXN1bHRJcSkge1xuXG4gICAgdGhpcy5zZXRGb2N1c1VzZXJKaWQoXG4gICAgICAgICQocmVzdWx0SXEpLmZpbmQoJ2NvbmZlcmVuY2UnKS5hdHRyKCdmb2N1c2ppZCcpKTtcblxuICAgIHZhciBhdXRoZW50aWNhdGlvbkVuYWJsZWRcbiAgICAgICAgPSAkKHJlc3VsdElxKS5maW5kKFxuICAgICAgICAgICAgJz5jb25mZXJlbmNlPnByb3BlcnR5JyArXG4gICAgICAgICAgICAnW25hbWU9XFwnYXV0aGVudGljYXRpb25cXCddW3ZhbHVlPVxcJ3RydWVcXCddJykubGVuZ3RoID4gMDtcblxuICAgIGxvZ2dlci5pbmZvKFwiQXV0aGVudGljYXRpb24gZW5hYmxlZDogXCIgKyBhdXRoZW50aWNhdGlvbkVuYWJsZWQpO1xuXG4gICAgdGhpcy5leHRlcm5hbEF1dGhFbmFibGVkID0gJChyZXN1bHRJcSkuZmluZChcbiAgICAgICAgICAgICc+Y29uZmVyZW5jZT5wcm9wZXJ0eScgK1xuICAgICAgICAgICAgJ1tuYW1lPVxcJ2V4dGVybmFsQXV0aFxcJ11bdmFsdWU9XFwndHJ1ZVxcJ10nKS5sZW5ndGggPiAwO1xuXG4gICAgY29uc29sZS5pbmZvKFxuICAgICAgICAnRXh0ZXJuYWwgYXV0aGVudGljYXRpb24gZW5hYmxlZDogJyArIHRoaXMuZXh0ZXJuYWxBdXRoRW5hYmxlZCk7XG5cbiAgICBpZiAoIXRoaXMuZXh0ZXJuYWxBdXRoRW5hYmxlZCkge1xuICAgICAgICAvLyBXZSBleHBlY3QgdG8gcmVjZWl2ZSBzZXNzaW9uSWQgaW4gJ2ludGVybmFsJyBhdXRoZW50aWNhdGlvbiBtb2RlXG4gICAgICAgIHRoaXMucGFyc2VTZXNzaW9uSWQocmVzdWx0SXEpO1xuICAgIH1cblxuICAgIHZhciBhdXRoSWRlbnRpdHkgPSAkKHJlc3VsdElxKS5maW5kKCc+Y29uZmVyZW5jZScpLmF0dHIoJ2lkZW50aXR5Jyk7XG5cbiAgICB0aGlzLmV2ZW50RW1pdHRlci5lbWl0KEF1dGhlbnRpY2F0aW9uRXZlbnRzLklERU5USVRZX1VQREFURUQsXG4gICAgICAgIGF1dGhlbnRpY2F0aW9uRW5hYmxlZCwgYXV0aElkZW50aXR5KTtcblxuICAgIC8vIENoZWNrIGlmIGZvY3VzIGhhcyBhdXRvLWRldGVjdGVkIEppZ2FzaSBjb21wb25lbnQodGhpcyB3aWxsIGJlIGFsc29cbiAgICAvLyBpbmNsdWRlZCBpZiB3ZSBoYXZlIHBhc3NlZCBvdXIgaG9zdCBmcm9tIHRoZSBjb25maWcpXG4gICAgaWYgKCQocmVzdWx0SXEpLmZpbmQoXG4gICAgICAgICc+Y29uZmVyZW5jZT5wcm9wZXJ0eScgK1xuICAgICAgICAnW25hbWU9XFwnc2lwR2F0ZXdheUVuYWJsZWRcXCddW3ZhbHVlPVxcJ3RydWVcXCddJykubGVuZ3RoKSB7XG4gICAgICAgIHRoaXMuc2lwR2F0ZXdheUVuYWJsZWQgPSB0cnVlO1xuICAgIH1cblxuICAgIGxvZ2dlci5pbmZvKFwiU2lwIGdhdGV3YXkgZW5hYmxlZDogIFwiICsgdGhpcy5zaXBHYXRld2F5RW5hYmxlZCk7XG59O1xuXG4vLyBGSVhNRSA9ICB3ZSBuZWVkIHRvIHNob3cgdGhlIGZhY3QgdGhhdCB3ZSdyZSB3YWl0aW5nIGZvciB0aGUgZm9jdXNcbi8vIHRvIHRoZSB1c2VyKG9yIHRoYXQgZm9jdXMgaXMgbm90IGF2YWlsYWJsZSlcbk1vZGVyYXRvci5wcm90b3R5cGUuYWxsb2NhdGVDb25mZXJlbmNlRm9jdXMgPSAgZnVuY3Rpb24gKGNhbGxiYWNrKSB7XG4gICAgLy8gVHJ5IHRvIHVzZSBmb2N1cyB1c2VyIEpJRCBmcm9tIHRoZSBjb25maWdcbiAgICB0aGlzLnNldEZvY3VzVXNlckppZCh0aGlzLnhtcHBTZXJ2aWNlLm9wdGlvbnMuZm9jdXNVc2VySmlkKTtcbiAgICAvLyBTZW5kIGNyZWF0ZSBjb25mZXJlbmNlIElRXG4gICAgdmFyIGlxID0gdGhpcy5jcmVhdGVDb25mZXJlbmNlSXEoKTtcbiAgICB2YXIgc2VsZiA9IHRoaXM7XG4gICAgdGhpcy5jb25uZWN0aW9uLnNlbmRJUShcbiAgICAgICAgaXEsXG4gICAgICAgIGZ1bmN0aW9uIChyZXN1bHQpIHtcblxuICAgICAgICAgICAgLy8gU2V0dXAgY29uZmlnIG9wdGlvbnNcbiAgICAgICAgICAgIHNlbGYucGFyc2VDb25maWdPcHRpb25zKHJlc3VsdCk7XG5cbiAgICAgICAgICAgIGlmICgndHJ1ZScgPT09ICQocmVzdWx0KS5maW5kKCdjb25mZXJlbmNlJykuYXR0cigncmVhZHknKSkge1xuICAgICAgICAgICAgICAgIC8vIFJlc2V0IGJvdGggdGltZXJzXG4gICAgICAgICAgICAgICAgc2VsZi5nZXROZXh0VGltZW91dCh0cnVlKTtcbiAgICAgICAgICAgICAgICBzZWxmLmdldE5leHRFcnJvclRpbWVvdXQodHJ1ZSk7XG4gICAgICAgICAgICAgICAgLy8gRXhlYyBjYWxsYmFja1xuICAgICAgICAgICAgICAgIGNhbGxiYWNrKCk7XG4gICAgICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgICAgIHZhciB3YWl0TXMgPSBzZWxmLmdldE5leHRUaW1lb3V0KCk7XG4gICAgICAgICAgICAgICAgbG9nZ2VyLmluZm8oXCJXYWl0aW5nIGZvciB0aGUgZm9jdXMuLi4gXCIgKyB3YWl0TXMpO1xuICAgICAgICAgICAgICAgIC8vIFJlc2V0IGVycm9yIHRpbWVvdXRcbiAgICAgICAgICAgICAgICBzZWxmLmdldE5leHRFcnJvclRpbWVvdXQodHJ1ZSk7XG4gICAgICAgICAgICAgICAgd2luZG93LnNldFRpbWVvdXQoXG4gICAgICAgICAgICAgICAgICAgIGZ1bmN0aW9uICgpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgIHNlbGYuYWxsb2NhdGVDb25mZXJlbmNlRm9jdXMoY2FsbGJhY2spO1xuICAgICAgICAgICAgICAgICAgICB9LCB3YWl0TXMpO1xuICAgICAgICAgICAgfVxuICAgICAgICB9LFxuICAgICAgICBmdW5jdGlvbiAoZXJyb3IpIHtcbiAgICAgICAgICAgIC8vIEludmFsaWQgc2Vzc2lvbiA/IHJlbW92ZSBhbmQgdHJ5IGFnYWluXG4gICAgICAgICAgICAvLyB3aXRob3V0IHNlc3Npb24gSUQgdG8gZ2V0IGEgbmV3IG9uZVxuICAgICAgICAgICAgdmFyIGludmFsaWRTZXNzaW9uXG4gICAgICAgICAgICAgICAgPSAkKGVycm9yKS5maW5kKCc+ZXJyb3I+c2Vzc2lvbi1pbnZhbGlkJykubGVuZ3RoO1xuICAgICAgICAgICAgaWYgKGludmFsaWRTZXNzaW9uKSB7XG4gICAgICAgICAgICAgICAgbG9nZ2VyLmluZm8oXCJTZXNzaW9uIGV4cGlyZWQhIC0gcmVtb3ZpbmdcIik7XG4gICAgICAgICAgICAgICAgbG9jYWxTdG9yYWdlLnJlbW92ZUl0ZW0oXCJzZXNzaW9uSWRcIik7XG4gICAgICAgICAgICB9XG4gICAgICAgICAgICBpZiAoJChlcnJvcikuZmluZCgnPmVycm9yPmdyYWNlZnVsLXNodXRkb3duJykubGVuZ3RoKSB7XG4gICAgICAgICAgICAgICAgc2VsZi5ldmVudEVtaXR0ZXIuZW1pdChYTVBQRXZlbnRzLkdSQUNFRlVMX1NIVVRET1dOKTtcbiAgICAgICAgICAgICAgICByZXR1cm47XG4gICAgICAgICAgICB9XG4gICAgICAgICAgICAvLyBDaGVjayBmb3IgZXJyb3IgcmV0dXJuZWQgYnkgdGhlIHJlc2VydmF0aW9uIHN5c3RlbVxuICAgICAgICAgICAgdmFyIHJlc2VydmF0aW9uRXJyID0gJChlcnJvcikuZmluZCgnPmVycm9yPnJlc2VydmF0aW9uLWVycm9yJyk7XG4gICAgICAgICAgICBpZiAocmVzZXJ2YXRpb25FcnIubGVuZ3RoKSB7XG4gICAgICAgICAgICAgICAgLy8gVHJpZ2dlciBlcnJvciBldmVudFxuICAgICAgICAgICAgICAgIHZhciBlcnJvckNvZGUgPSByZXNlcnZhdGlvbkVyci5hdHRyKCdlcnJvci1jb2RlJyk7XG4gICAgICAgICAgICAgICAgdmFyIGVycm9yTXNnO1xuICAgICAgICAgICAgICAgIGlmICgkKGVycm9yKS5maW5kKCc+ZXJyb3I+dGV4dCcpKSB7XG4gICAgICAgICAgICAgICAgICAgIGVycm9yTXNnID0gJChlcnJvcikuZmluZCgnPmVycm9yPnRleHQnKS50ZXh0KCk7XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgIHNlbGYuZXZlbnRFbWl0dGVyLmVtaXQoXG4gICAgICAgICAgICAgICAgICAgIFhNUFBFdmVudHMuUkVTRVJWQVRJT05fRVJST1IsIGVycm9yQ29kZSwgZXJyb3JNc2cpO1xuICAgICAgICAgICAgICAgIHJldHVybjtcbiAgICAgICAgICAgIH1cbiAgICAgICAgICAgIC8vIE5vdCBhdXRob3JpemVkIHRvIGNyZWF0ZSBuZXcgcm9vbVxuICAgICAgICAgICAgaWYgKCQoZXJyb3IpLmZpbmQoJz5lcnJvcj5ub3QtYXV0aG9yaXplZCcpLmxlbmd0aCkge1xuICAgICAgICAgICAgICAgIGxvZ2dlci53YXJuKFwiVW5hdXRob3JpemVkIHRvIHN0YXJ0IHRoZSBjb25mZXJlbmNlXCIsIGVycm9yKTtcbiAgICAgICAgICAgICAgICB2YXIgdG9Eb21haW5cbiAgICAgICAgICAgICAgICAgICAgPSBTdHJvcGhlLmdldERvbWFpbkZyb21KaWQoZXJyb3IuZ2V0QXR0cmlidXRlKCd0bycpKTtcbiAgICAgICAgICAgICAgICBpZiAodG9Eb21haW4gIT09XG4gICAgICAgICAgICAgICAgICAgIHRoaXMueG1wcFNlcnZpY2Uub3B0aW9ucy5ob3N0cy5hbm9ueW1vdXNkb21haW4pIHtcbiAgICAgICAgICAgICAgICAgICAgLy9GSVhNRTogIFwiaXMgZXh0ZXJuYWxcIiBzaG91bGQgY29tZSBlaXRoZXIgZnJvbVxuICAgICAgICAgICAgICAgICAgICAvLyB0aGUgZm9jdXMgb3IgY29uZmlnLmpzXG4gICAgICAgICAgICAgICAgICAgIHNlbGYuZXh0ZXJuYWxBdXRoRW5hYmxlZCA9IHRydWU7XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgIHNlbGYuZXZlbnRFbWl0dGVyLmVtaXQoXG4gICAgICAgICAgICAgICAgICAgIFhNUFBFdmVudHMuQVVUSEVOVElDQVRJT05fUkVRVUlSRUQsXG4gICAgICAgICAgICAgICAgICAgIGZ1bmN0aW9uICgpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgIHNlbGYuYWxsb2NhdGVDb25mZXJlbmNlRm9jdXMoXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgY2FsbGJhY2spO1xuICAgICAgICAgICAgICAgICAgICB9KTtcbiAgICAgICAgICAgICAgICByZXR1cm47XG4gICAgICAgICAgICB9XG4gICAgICAgICAgICB2YXIgd2FpdE1zID0gc2VsZi5nZXROZXh0RXJyb3JUaW1lb3V0KCk7XG4gICAgICAgICAgICBsb2dnZXIuZXJyb3IoXCJGb2N1cyBlcnJvciwgcmV0cnkgYWZ0ZXIgXCIgKyB3YWl0TXMsIGVycm9yKTtcbiAgICAgICAgICAgIC8vIFNob3cgbWVzc2FnZVxuICAgICAgICAgICAgdmFyIGZvY3VzQ29tcG9uZW50ID0gc2VsZi5nZXRGb2N1c0NvbXBvbmVudCgpO1xuICAgICAgICAgICAgdmFyIHJldHJ5U2VjID0gd2FpdE1zIC8gMTAwMDtcbiAgICAgICAgICAgIC8vRklYTUU6ICBtZXNzYWdlIGlzIGR1cGxpY2F0ZWQgP1xuICAgICAgICAgICAgLy8gRG8gbm90IHNob3cgaW4gY2FzZSBvZiBzZXNzaW9uIGludmFsaWRcbiAgICAgICAgICAgIC8vIHdoaWNoIG1lYW5zIGp1c3QgYSByZXRyeVxuICAgICAgICAgICAgaWYgKCFpbnZhbGlkU2Vzc2lvbikge1xuICAgICAgICAgICAgICAgIHNlbGYuZXZlbnRFbWl0dGVyLmVtaXQoWE1QUEV2ZW50cy5GT0NVU19ESVNDT05ORUNURUQsXG4gICAgICAgICAgICAgICAgICAgIGZvY3VzQ29tcG9uZW50LCByZXRyeVNlYyk7XG4gICAgICAgICAgICB9XG4gICAgICAgICAgICAvLyBSZXNldCByZXNwb25zZSB0aW1lb3V0XG4gICAgICAgICAgICBzZWxmLmdldE5leHRUaW1lb3V0KHRydWUpO1xuICAgICAgICAgICAgd2luZG93LnNldFRpbWVvdXQoXG4gICAgICAgICAgICAgICAgZnVuY3Rpb24gKCkge1xuICAgICAgICAgICAgICAgICAgICBzZWxmLmFsbG9jYXRlQ29uZmVyZW5jZUZvY3VzKGNhbGxiYWNrKTtcbiAgICAgICAgICAgICAgICB9LCB3YWl0TXMpO1xuICAgICAgICB9XG4gICAgKTtcbn07XG5cbk1vZGVyYXRvci5wcm90b3R5cGUuYXV0aGVudGljYXRlID0gZnVuY3Rpb24gKCkge1xuICAgIHZhciBzZWxmID0gdGhpcztcbiAgICByZXR1cm4gbmV3IFByb21pc2UoZnVuY3Rpb24gKHJlc29sdmUsIHJlamVjdCkge1xuICAgICAgICBzZWxmLmNvbm5lY3Rpb24uc2VuZElRKFxuICAgICAgICAgICAgc2VsZi5jcmVhdGVDb25mZXJlbmNlSXEoKSxcbiAgICAgICAgICAgIGZ1bmN0aW9uIChyZXN1bHQpIHtcbiAgICAgICAgICAgICAgICBzZWxmLnBhcnNlU2Vzc2lvbklkKHJlc3VsdCk7XG4gICAgICAgICAgICAgICAgcmVzb2x2ZSgpO1xuICAgICAgICAgICAgfSwgZnVuY3Rpb24gKGVycm9yKSB7XG4gICAgICAgICAgICAgICAgdmFyIGNvZGUgPSAkKGVycm9yKS5maW5kKCc+ZXJyb3InKS5hdHRyKCdjb2RlJyk7XG4gICAgICAgICAgICAgICAgcmVqZWN0KGVycm9yLCBjb2RlKTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgKTtcbiAgICB9KTtcbn07XG5cbk1vZGVyYXRvci5wcm90b3R5cGUuZ2V0TG9naW5VcmwgPSAgZnVuY3Rpb24gKHVybENhbGxiYWNrLCBmYWlsdXJlQ2FsbGJhY2spIHtcbiAgICB2YXIgaXEgPSAkaXEoe3RvOiB0aGlzLmdldEZvY3VzQ29tcG9uZW50KCksIHR5cGU6ICdnZXQnfSk7XG4gICAgaXEuYygnbG9naW4tdXJsJywge1xuICAgICAgICB4bWxuczogJ2h0dHA6Ly9qaXRzaS5vcmcvcHJvdG9jb2wvZm9jdXMnLFxuICAgICAgICByb29tOiB0aGlzLnJvb21OYW1lLFxuICAgICAgICAnbWFjaGluZS11aWQnOiB0aGlzLnNldHRpbmdzLmdldFNldHRpbmdzKCkudWlkXG4gICAgfSk7XG4gICAgdGhpcy5jb25uZWN0aW9uLnNlbmRJUShcbiAgICAgICAgaXEsXG4gICAgICAgIGZ1bmN0aW9uIChyZXN1bHQpIHtcbiAgICAgICAgICAgIHZhciB1cmwgPSAkKHJlc3VsdCkuZmluZCgnbG9naW4tdXJsJykuYXR0cigndXJsJyk7XG4gICAgICAgICAgICB1cmwgPSB1cmwgPSBkZWNvZGVVUklDb21wb25lbnQodXJsKTtcbiAgICAgICAgICAgIGlmICh1cmwpIHtcbiAgICAgICAgICAgICAgICBsb2dnZXIuaW5mbyhcIkdvdCBhdXRoIHVybDogXCIgKyB1cmwpO1xuICAgICAgICAgICAgICAgIHVybENhbGxiYWNrKHVybCk7XG4gICAgICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgICAgIGxvZ2dlci5lcnJvcihcbiAgICAgICAgICAgICAgICAgICAgXCJGYWlsZWQgdG8gZ2V0IGF1dGggdXJsIGZyb20gdGhlIGZvY3VzXCIsIHJlc3VsdCk7XG4gICAgICAgICAgICAgICAgZmFpbHVyZUNhbGxiYWNrKHJlc3VsdCk7XG4gICAgICAgICAgICB9XG4gICAgICAgIH0sXG4gICAgICAgIGZ1bmN0aW9uIChlcnJvcikge1xuICAgICAgICAgICAgbG9nZ2VyLmVycm9yKFwiR2V0IGF1dGggdXJsIGVycm9yXCIsIGVycm9yKTtcbiAgICAgICAgICAgIGZhaWx1cmVDYWxsYmFjayhlcnJvcik7XG4gICAgICAgIH1cbiAgICApO1xufTtcblxuTW9kZXJhdG9yLnByb3RvdHlwZS5nZXRQb3B1cExvZ2luVXJsID0gZnVuY3Rpb24gKHVybENhbGxiYWNrLCBmYWlsdXJlQ2FsbGJhY2spIHtcbiAgICB2YXIgaXEgPSAkaXEoe3RvOiB0aGlzLmdldEZvY3VzQ29tcG9uZW50KCksIHR5cGU6ICdnZXQnfSk7XG4gICAgaXEuYygnbG9naW4tdXJsJywge1xuICAgICAgICB4bWxuczogJ2h0dHA6Ly9qaXRzaS5vcmcvcHJvdG9jb2wvZm9jdXMnLFxuICAgICAgICByb29tOiB0aGlzLnJvb21OYW1lLFxuICAgICAgICAnbWFjaGluZS11aWQnOiB0aGlzLnNldHRpbmdzLmdldFNldHRpbmdzKCkudWlkLFxuICAgICAgICBwb3B1cDogdHJ1ZVxuICAgIH0pO1xuICAgIHRoaXMuY29ubmVjdGlvbi5zZW5kSVEoXG4gICAgICAgIGlxLFxuICAgICAgICBmdW5jdGlvbiAocmVzdWx0KSB7XG4gICAgICAgICAgICB2YXIgdXJsID0gJChyZXN1bHQpLmZpbmQoJ2xvZ2luLXVybCcpLmF0dHIoJ3VybCcpO1xuICAgICAgICAgICAgdXJsID0gdXJsID0gZGVjb2RlVVJJQ29tcG9uZW50KHVybCk7XG4gICAgICAgICAgICBpZiAodXJsKSB7XG4gICAgICAgICAgICAgICAgbG9nZ2VyLmluZm8oXCJHb3QgUE9QVVAgYXV0aCB1cmw6ICBcIiArIHVybCk7XG4gICAgICAgICAgICAgICAgdXJsQ2FsbGJhY2sodXJsKTtcbiAgICAgICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICAgICAgbG9nZ2VyLmVycm9yKFxuICAgICAgICAgICAgICAgICAgICBcIkZhaWxlZCB0byBnZXQgUE9QVVAgYXV0aCB1cmwgZnJvbSB0aGUgZm9jdXNcIiwgcmVzdWx0KTtcbiAgICAgICAgICAgICAgIGZhaWx1cmVDYWxsYmFjayhyZXN1bHQpO1xuICAgICAgICAgICAgfVxuICAgICAgICB9LFxuICAgICAgICBmdW5jdGlvbiAoZXJyb3IpIHtcbiAgICAgICAgICAgIGxvZ2dlci5lcnJvcignR2V0IFBPUFVQIGF1dGggdXJsIGVycm9yJywgZXJyb3IpO1xuICAgICAgICAgICAgZmFpbHVyZUNhbGxiYWNrKGVycm9yKTtcbiAgICAgICAgfVxuICAgICk7XG59O1xuXG5Nb2RlcmF0b3IucHJvdG90eXBlLmxvZ291dCA9ICBmdW5jdGlvbiAoY2FsbGJhY2spIHtcbiAgICB2YXIgaXEgPSAkaXEoe3RvOiB0aGlzLmdldEZvY3VzQ29tcG9uZW50KCksIHR5cGU6ICdzZXQnfSk7XG4gICAgdmFyIHNlc3Npb25JZCA9IGxvY2FsU3RvcmFnZS5nZXRJdGVtKCdzZXNzaW9uSWQnKTtcbiAgICBpZiAoIXNlc3Npb25JZCkge1xuICAgICAgICBjYWxsYmFjaygpO1xuICAgICAgICByZXR1cm47XG4gICAgfVxuICAgIGlxLmMoJ2xvZ291dCcsIHtcbiAgICAgICAgeG1sbnM6ICdodHRwOi8vaml0c2kub3JnL3Byb3RvY29sL2ZvY3VzJyxcbiAgICAgICAgJ3Nlc3Npb24taWQnOiBzZXNzaW9uSWRcbiAgICB9KTtcbiAgICB0aGlzLmNvbm5lY3Rpb24uc2VuZElRKFxuICAgICAgICBpcSxcbiAgICAgICAgZnVuY3Rpb24gKHJlc3VsdCkge1xuICAgICAgICAgICAgdmFyIGxvZ291dFVybCA9ICQocmVzdWx0KS5maW5kKCdsb2dvdXQnKS5hdHRyKCdsb2dvdXQtdXJsJyk7XG4gICAgICAgICAgICBpZiAobG9nb3V0VXJsKSB7XG4gICAgICAgICAgICAgICAgbG9nb3V0VXJsID0gZGVjb2RlVVJJQ29tcG9uZW50KGxvZ291dFVybCk7XG4gICAgICAgICAgICB9XG4gICAgICAgICAgICBsb2dnZXIuaW5mbyhcIkxvZyBvdXQgT0ssIHVybDogXCIgKyBsb2dvdXRVcmwsIHJlc3VsdCk7XG4gICAgICAgICAgICBsb2NhbFN0b3JhZ2UucmVtb3ZlSXRlbSgnc2Vzc2lvbklkJyk7XG4gICAgICAgICAgICBjYWxsYmFjayhsb2dvdXRVcmwpO1xuICAgICAgICB9LFxuICAgICAgICBmdW5jdGlvbiAoZXJyb3IpIHtcbiAgICAgICAgICAgIGxvZ2dlci5lcnJvcihcIkxvZ291dCBlcnJvclwiLCBlcnJvcik7XG4gICAgICAgIH1cbiAgICApO1xufTtcblxubW9kdWxlLmV4cG9ydHMgPSBNb2RlcmF0b3I7XG4iLCIvKiBnbG9iYWwgJCwgJGlxLCBjb25maWcsIGNvbm5lY3Rpb24sIGZvY3VzTXVjSmlkLCBtZXNzYWdlSGFuZGxlcixcbiAgIFRvb2xiYXIsIFV0aWwsIFByb21pc2UgKi9cbnZhciBYTVBQRXZlbnRzID0gcmVxdWlyZShcIi4uLy4uL3NlcnZpY2UvWE1QUC9YTVBQRXZlbnRzXCIpO1xudmFyIGxvZ2dlciA9IHJlcXVpcmUoXCJqaXRzaS1tZWV0LWxvZ2dlclwiKS5nZXRMb2dnZXIoX19maWxlbmFtZSk7XG5cbmZ1bmN0aW9uIFJlY29yZGluZyhlZSwgY29ubmVjdGlvbiwgZm9jdXNNdWNKaWQpIHtcbiAgICB0aGlzLmV2ZW50RW1pdHRlciA9IGVlO1xuICAgIHRoaXMuY29ubmVjdGlvbiA9IGNvbm5lY3Rpb247XG4gICAgdGhpcy5zdGF0ZSA9IFwib2ZmXCI7XG4gICAgdGhpcy5mb2N1c011Y0ppZCA9IGZvY3VzTXVjSmlkO1xuICAgIHRoaXMudXJsID0gbnVsbDtcbiAgICB0aGlzLl9pc1N1cHBvcnRlZCA9IGZhbHNlO1xufVxuXG5SZWNvcmRpbmcucHJvdG90eXBlLmhhbmRsZUppYnJpUHJlc2VuY2UgPSBmdW5jdGlvbiAoamlicmkpIHtcbiAgICB2YXIgYXR0cmlidXRlcyA9IGppYnJpLmF0dHJpYnV0ZXM7XG4gICAgaWYoIWF0dHJpYnV0ZXMpXG4gICAgICAgIHJldHVybjtcblxuICAgIHRoaXMuX2lzU3VwcG9ydGVkID1cbiAgICAgICAgKGF0dHJpYnV0ZXMuc3RhdHVzICYmIGF0dHJpYnV0ZXMuc3RhdHVzICE9PSBcInVuZGVmaW5lZFwiKTtcbiAgICBpZih0aGlzLl9pc1N1cHBvcnRlZCkge1xuICAgICAgICB0aGlzLnVybCA9IGF0dHJpYnV0ZXMudXJsIHx8IG51bGw7XG4gICAgICAgIHRoaXMuc3RhdGUgPSBhdHRyaWJ1dGVzLnN0YXR1cyB8fCBcIm9mZlwiO1xuICAgIH1cbiAgICB0aGlzLmV2ZW50RW1pdHRlci5lbWl0KFhNUFBFdmVudHMuUkVDT1JESU5HX1NUQVRFX0NIQU5HRUQpO1xufTtcblxuUmVjb3JkaW5nLnByb3RvdHlwZS5zZXRSZWNvcmRpbmcgPSBmdW5jdGlvbiAoc3RhdGUsIHN0cmVhbUlkLCBmb2xsb3dFbnRpdHksXG4gICAgY2FsbGJhY2ssIGVyckNhbGxiYWNrKXtcbiAgICBpZiAoc3RhdGUgPT0gdGhpcy5zdGF0ZSl7XG4gICAgICAgIHJldHVybjtcbiAgICB9XG5cbiAgICAvLyBGSVhNRSBqaWJyaSBkb2VzIG5vdCBhY2NlcHQgSVEgd2l0aG91dCAndXJsJyBhdHRyaWJ1dGUgc2V0ID9cblxuICAgIHZhciBpcSA9ICRpcSh7dG86IHRoaXMuZm9jdXNNdWNKaWQsIHR5cGU6ICdzZXQnfSlcbiAgICAgICAgLmMoJ2ppYnJpJywge1xuICAgICAgICAgICAgXCJ4bWxuc1wiOiAnaHR0cDovL2ppdHNpLm9yZy9wcm90b2NvbC9qaWJyaScsXG4gICAgICAgICAgICBcImFjdGlvblwiOiAoc3RhdGUgPT09ICdvbicpID8gJ3N0YXJ0JyA6ICdzdG9wJyxcbiAgICAgICAgICAgIFwic3RyZWFtaWRcIjogc3RyZWFtSWQsXG4gICAgICAgICAgICBcImZvbGxvdy1lbnRpdHlcIjogZm9sbG93RW50aXR5XG4gICAgICAgIH0pLnVwKCk7XG5cbiAgICBsb2dnZXIubG9nKCdTZXQgamlicmkgcmVjb3JkaW5nOiAnK3N0YXRlLCBpcS5ub2RlVHJlZSk7XG4gICAgY29uc29sZS5sb2coaXEubm9kZVRyZWUpO1xuICAgIHRoaXMuY29ubmVjdGlvbi5zZW5kSVEoXG4gICAgICAgIGlxLFxuICAgICAgICBmdW5jdGlvbiAocmVzdWx0KSB7XG4gICAgICAgICAgICBjYWxsYmFjaygkKHJlc3VsdCkuZmluZCgnamlicmknKS5hdHRyKCdzdGF0ZScpLFxuICAgICAgICAgICAgJChyZXN1bHQpLmZpbmQoJ2ppYnJpJykuYXR0cigndXJsJykpO1xuICAgICAgICB9LFxuICAgICAgICBmdW5jdGlvbiAoZXJyb3IpIHtcbiAgICAgICAgICAgIGxvZ2dlci5sb2coJ0ZhaWxlZCB0byBzdGFydCByZWNvcmRpbmcsIGVycm9yOiAnLCBlcnJvcik7XG4gICAgICAgICAgICBlcnJDYWxsYmFjayhlcnJvcik7XG4gICAgICAgIH0pO1xufTtcblxuUmVjb3JkaW5nLnByb3RvdHlwZS50b2dnbGVSZWNvcmRpbmcgPSBmdW5jdGlvbiAodG9rZW4sIGZvbGxvd0VudGl0eSkge1xuICAgIHZhciBzZWxmID0gdGhpcztcbiAgICByZXR1cm4gbmV3IFByb21pc2UoZnVuY3Rpb24ocmVzb2x2ZSwgcmVqZWN0KSB7XG4gICAgICAgIGlmICghdG9rZW4pIHtcbiAgICAgICAgICAgIHJlamVjdChuZXcgRXJyb3IoXCJObyB0b2tlbiBwYXNzZWQhXCIpKTtcbiAgICAgICAgICAgIGxvZ2dlci5lcnJvcihcIk5vIHRva2VuIHBhc3NlZCFcIik7XG4gICAgICAgICAgICByZXR1cm47XG4gICAgICAgIH1cbiAgICAgICAgaWYoc2VsZi5zdGF0ZSA9PT0gXCJvblwiKSB7XG4gICAgICAgICAgICByZWplY3QobmV3IEVycm9yKFwiUmVjb3JkaW5nIGlzIGFscmVhZHkgc3RhcnRlZCFcIikpO1xuICAgICAgICAgICAgbG9nZ2VyLmVycm9yKFwiUmVjb3JkaW5nIGlzIGFscmVhZHkgc3RhcnRlZCFcIik7XG4gICAgICAgICAgICByZXR1cm47XG4gICAgICAgIH1cblxuICAgICAgICB2YXIgb2xkU3RhdGUgPSBzZWxmLnN0YXRlO1xuICAgICAgICB2YXIgbmV3U3RhdGUgPSAob2xkU3RhdGUgPT09ICdvZmYnIHx8ICFvbGRTdGF0ZSkgPyAnb24nIDogJ29mZic7XG5cbiAgICAgICAgc2VsZi5zZXRSZWNvcmRpbmcobmV3U3RhdGUsXG4gICAgICAgICAgICB0b2tlbiwgZm9sbG93RW50aXR5LFxuICAgICAgICAgICAgZnVuY3Rpb24gKHN0YXRlLCB1cmwpIHtcbiAgICAgICAgICAgICAgICBsb2dnZXIubG9nKFwiTmV3IHJlY29yZGluZyBzdGF0ZTogXCIsIHN0YXRlKTtcbiAgICAgICAgICAgICAgICBpZiAoc3RhdGUgJiYgc3RhdGUgIT09IG9sZFN0YXRlKSB7XG4gICAgICAgICAgICAgICAgICAgIHNlbGYuc3RhdGUgPSBzdGF0ZTtcbiAgICAgICAgICAgICAgICAgICAgc2VsZi51cmwgPSB1cmw7XG4gICAgICAgICAgICAgICAgICAgIHJlc29sdmUoKTtcbiAgICAgICAgICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgICAgICAgICByZWplY3QobmV3IEVycm9yKFwiU3RhdGUgbm90IGNoYW5nZWQhXCIpKTtcbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICB9LFxuICAgICAgICAgICAgZnVuY3Rpb24gKGVycm9yKSB7XG4gICAgICAgICAgICAgICAgcmVqZWN0KGVycm9yKTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgKTtcbiAgICB9KTtcbn07XG5cbi8qKlxuICogUmV0dXJucyB0cnVlIGlmIHRoZSByZWNvcmRpbmcgaXMgc3VwcHJvdGVkIGFuZCBmYWxzZSBpZiBub3QuXG4gKi9cblJlY29yZGluZy5wcm90b3R5cGUuaXNTdXBwb3J0ZWQgPSBmdW5jdGlvbiAoKSB7XG4gICAgcmV0dXJuIHRoaXMuX2lzU3VwcG9ydGVkO1xufTtcblxuLyoqXG4gKiBSZXR1cm5zIG51bGwgaWYgdGhlIHJlY29yZGluZyBpcyBub3Qgc3VwcG9ydGVkLCBcIm9uXCIgaWYgdGhlIHJlY29yZGluZyBzdGFydGVkXG4gKiBhbmQgXCJvZmZcIiBpZiB0aGUgcmVjb3JkaW5nIGlzIG5vdCBzdGFydGVkLlxuICovXG5SZWNvcmRpbmcucHJvdG90eXBlLmdldFN0YXRlID0gZnVuY3Rpb24gKCkge1xuICAgIHJldHVybiB0aGlzLnN0YXRlO1xufTtcblxuLyoqXG4gKiBSZXR1cm5zIHRoZSB1cmwgb2YgdGhlIHJlY29yZGVkIHZpZGVvLlxuICovXG5SZWNvcmRpbmcucHJvdG90eXBlLmdldFVSTCA9IGZ1bmN0aW9uICgpIHtcbiAgICByZXR1cm4gdGhpcy51cmw7XG59O1xuXG5tb2R1bGUuZXhwb3J0cyA9IFJlY29yZGluZztcbiIsIi8qIGpzaGludCAtVzExNyAqL1xuLyogYSBzaW1wbGUgTVVDIGNvbm5lY3Rpb24gcGx1Z2luXG4gKiBjYW4gb25seSBoYW5kbGUgYSBzaW5nbGUgTVVDIHJvb21cbiAqL1xuXG52YXIgbG9nZ2VyID0gcmVxdWlyZShcImppdHNpLW1lZXQtbG9nZ2VyXCIpLmdldExvZ2dlcihfX2ZpbGVuYW1lKTtcbnZhciBDaGF0Um9vbSA9IHJlcXVpcmUoXCIuL0NoYXRSb29tXCIpO1xuXG5tb2R1bGUuZXhwb3J0cyA9IGZ1bmN0aW9uKFhNUFApIHtcbiAgICBTdHJvcGhlLmFkZENvbm5lY3Rpb25QbHVnaW4oJ2VtdWMnLCB7XG4gICAgICAgIGNvbm5lY3Rpb246IG51bGwsXG4gICAgICAgIHJvb21zOiB7fSwvL21hcCB3aXRoIHRoZSByb29tc1xuICAgICAgICBpbml0OiBmdW5jdGlvbiAoY29ubikge1xuICAgICAgICAgICAgdGhpcy5jb25uZWN0aW9uID0gY29ubjtcbiAgICAgICAgICAgIC8vIGFkZCBoYW5kbGVycyAoanVzdCBvbmNlKVxuICAgICAgICAgICAgdGhpcy5jb25uZWN0aW9uLmFkZEhhbmRsZXIodGhpcy5vblByZXNlbmNlLmJpbmQodGhpcyksIG51bGwsICdwcmVzZW5jZScsIG51bGwsIG51bGwsIG51bGwsIG51bGwpO1xuICAgICAgICAgICAgdGhpcy5jb25uZWN0aW9uLmFkZEhhbmRsZXIodGhpcy5vblByZXNlbmNlVW5hdmFpbGFibGUuYmluZCh0aGlzKSwgbnVsbCwgJ3ByZXNlbmNlJywgJ3VuYXZhaWxhYmxlJywgbnVsbCk7XG4gICAgICAgICAgICB0aGlzLmNvbm5lY3Rpb24uYWRkSGFuZGxlcih0aGlzLm9uUHJlc2VuY2VFcnJvci5iaW5kKHRoaXMpLCBudWxsLCAncHJlc2VuY2UnLCAnZXJyb3InLCBudWxsKTtcbiAgICAgICAgICAgIHRoaXMuY29ubmVjdGlvbi5hZGRIYW5kbGVyKHRoaXMub25NZXNzYWdlLmJpbmQodGhpcyksIG51bGwsICdtZXNzYWdlJywgbnVsbCwgbnVsbCk7XG4gICAgICAgIH0sXG4gICAgICAgIGNyZWF0ZVJvb206IGZ1bmN0aW9uIChqaWQsIHBhc3N3b3JkLCBvcHRpb25zKSB7XG4gICAgICAgICAgICB2YXIgcm9vbUppZCA9IFN0cm9waGUuZ2V0QmFyZUppZEZyb21KaWQoamlkKTtcbiAgICAgICAgICAgIGlmICh0aGlzLnJvb21zW3Jvb21KaWRdKSB7XG4gICAgICAgICAgICAgICAgbG9nZ2VyLmVycm9yKFwiWW91IGFyZSBhbHJlYWR5IGluIHRoZSByb29tIVwiKTtcbiAgICAgICAgICAgICAgICByZXR1cm47XG4gICAgICAgICAgICB9XG4gICAgICAgICAgICB0aGlzLnJvb21zW3Jvb21KaWRdID0gbmV3IENoYXRSb29tKHRoaXMuY29ubmVjdGlvbiwgamlkLCBwYXNzd29yZCwgWE1QUCwgb3B0aW9ucyk7XG4gICAgICAgICAgICByZXR1cm4gdGhpcy5yb29tc1tyb29tSmlkXTtcbiAgICAgICAgfSxcbiAgICAgICAgZG9MZWF2ZTogZnVuY3Rpb24gKGppZCkge1xuICAgICAgICAgICAgdGhpcy5yb29tc1tqaWRdLmRvTGVhdmUoKTtcbiAgICAgICAgICAgIGRlbGV0ZSB0aGlzLnJvb21zW2ppZF07XG4gICAgICAgIH0sXG4gICAgICAgIG9uUHJlc2VuY2U6IGZ1bmN0aW9uIChwcmVzKSB7XG4gICAgICAgICAgICB2YXIgZnJvbSA9IHByZXMuZ2V0QXR0cmlidXRlKCdmcm9tJyk7XG5cbiAgICAgICAgICAgIC8vIFdoYXQgaXMgdGhpcyBmb3I/IEEgd29ya2Fyb3VuZCBmb3Igc29tZXRoaW5nP1xuICAgICAgICAgICAgaWYgKHByZXMuZ2V0QXR0cmlidXRlKCd0eXBlJykpIHtcbiAgICAgICAgICAgICAgICByZXR1cm4gdHJ1ZTtcbiAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgdmFyIHJvb20gPSB0aGlzLnJvb21zW1N0cm9waGUuZ2V0QmFyZUppZEZyb21KaWQoZnJvbSldO1xuICAgICAgICAgICAgaWYoIXJvb20pXG4gICAgICAgICAgICAgICAgcmV0dXJuO1xuXG4gICAgICAgICAgICAvLyBQYXJzZSBzdGF0dXMuXG4gICAgICAgICAgICBpZiAoJChwcmVzKS5maW5kKCc+eFt4bWxucz1cImh0dHA6Ly9qYWJiZXIub3JnL3Byb3RvY29sL211YyN1c2VyXCJdPnN0YXR1c1tjb2RlPVwiMjAxXCJdJykubGVuZ3RoKSB7XG4gICAgICAgICAgICAgICAgcm9vbS5jcmVhdGVOb25Bbm9ueW1vdXNSb29tKCk7XG4gICAgICAgICAgICB9XG5cbiAgICAgICAgICAgIHJvb20ub25QcmVzZW5jZShwcmVzKTtcblxuICAgICAgICAgICAgcmV0dXJuIHRydWU7XG4gICAgICAgIH0sXG4gICAgICAgIG9uUHJlc2VuY2VVbmF2YWlsYWJsZTogZnVuY3Rpb24gKHByZXMpIHtcbiAgICAgICAgICAgIHZhciBmcm9tID0gcHJlcy5nZXRBdHRyaWJ1dGUoJ2Zyb20nKTtcbiAgICAgICAgICAgIHZhciByb29tID0gdGhpcy5yb29tc1tTdHJvcGhlLmdldEJhcmVKaWRGcm9tSmlkKGZyb20pXTtcbiAgICAgICAgICAgIGlmKCFyb29tKVxuICAgICAgICAgICAgICAgIHJldHVybjtcblxuICAgICAgICAgICAgcm9vbS5vblByZXNlbmNlVW5hdmFpbGFibGUocHJlcywgZnJvbSk7XG4gICAgICAgICAgICByZXR1cm4gdHJ1ZTtcbiAgICAgICAgfSxcbiAgICAgICAgb25QcmVzZW5jZUVycm9yOiBmdW5jdGlvbiAocHJlcykge1xuICAgICAgICAgICAgdmFyIGZyb20gPSBwcmVzLmdldEF0dHJpYnV0ZSgnZnJvbScpO1xuICAgICAgICAgICAgdmFyIHJvb20gPSB0aGlzLnJvb21zW1N0cm9waGUuZ2V0QmFyZUppZEZyb21KaWQoZnJvbSldO1xuICAgICAgICAgICAgaWYoIXJvb20pXG4gICAgICAgICAgICAgICAgcmV0dXJuO1xuXG4gICAgICAgICAgICByb29tLm9uUHJlc2VuY2VFcnJvcihwcmVzLCBmcm9tKTtcbiAgICAgICAgICAgIHJldHVybiB0cnVlO1xuICAgICAgICB9LFxuICAgICAgICBvbk1lc3NhZ2U6IGZ1bmN0aW9uIChtc2cpIHtcbiAgICAgICAgICAgIC8vIEZJWE1FOiB0aGlzIGlzIGEgaGFjay4gYnV0IGppbmdsZSBvbiBtdWMgbWFrZXMgbmlja2NoYW5nZXMgaGFyZFxuICAgICAgICAgICAgdmFyIGZyb20gPSBtc2cuZ2V0QXR0cmlidXRlKCdmcm9tJyk7XG4gICAgICAgICAgICB2YXIgcm9vbSA9IHRoaXMucm9vbXNbU3Ryb3BoZS5nZXRCYXJlSmlkRnJvbUppZChmcm9tKV07XG4gICAgICAgICAgICBpZighcm9vbSlcbiAgICAgICAgICAgICAgICByZXR1cm47XG5cbiAgICAgICAgICAgIHJvb20ub25NZXNzYWdlKG1zZywgZnJvbSk7XG4gICAgICAgICAgICByZXR1cm4gdHJ1ZTtcbiAgICAgICAgfSxcblxuICAgICAgICBzZXRKaW5nbGVTZXNzaW9uOiBmdW5jdGlvbiAoZnJvbSwgc2Vzc2lvbikge1xuICAgICAgICAgICAgdmFyIHJvb20gPSB0aGlzLnJvb21zW1N0cm9waGUuZ2V0QmFyZUppZEZyb21KaWQoZnJvbSldO1xuICAgICAgICAgICAgaWYoIXJvb20pXG4gICAgICAgICAgICAgICAgcmV0dXJuO1xuXG4gICAgICAgICAgICByb29tLnNldEppbmdsZVNlc3Npb24oc2Vzc2lvbik7XG4gICAgICAgIH1cbiAgICB9KTtcbn07XG5cbiIsIi8qIGpzaGludCAtVzExNyAqL1xuXG5cbnZhciBsb2dnZXIgPSByZXF1aXJlKFwiaml0c2ktbWVldC1sb2dnZXJcIikuZ2V0TG9nZ2VyKF9fZmlsZW5hbWUpO1xudmFyIEppbmdsZVNlc3Npb24gPSByZXF1aXJlKFwiLi9KaW5nbGVTZXNzaW9uUENcIik7XG52YXIgWE1QUEV2ZW50cyA9IHJlcXVpcmUoXCIuLi8uLi9zZXJ2aWNlL3htcHAvWE1QUEV2ZW50c1wiKTtcbnZhciBSVENCcm93c2VyVHlwZSA9IHJlcXVpcmUoXCIuLi9SVEMvUlRDQnJvd3NlclR5cGVcIik7XG5cblxubW9kdWxlLmV4cG9ydHMgPSBmdW5jdGlvbihYTVBQLCBldmVudEVtaXR0ZXIpIHtcbiAgICBTdHJvcGhlLmFkZENvbm5lY3Rpb25QbHVnaW4oJ2ppbmdsZScsIHtcbiAgICAgICAgY29ubmVjdGlvbjogbnVsbCxcbiAgICAgICAgc2Vzc2lvbnM6IHt9LFxuICAgICAgICBqaWQyc2Vzc2lvbjoge30sXG4gICAgICAgIGljZV9jb25maWc6IHtpY2VTZXJ2ZXJzOiBbXX0sXG4gICAgICAgIG1lZGlhX2NvbnN0cmFpbnRzOiB7XG4gICAgICAgICAgICBtYW5kYXRvcnk6IHtcbiAgICAgICAgICAgICAgICAnT2ZmZXJUb1JlY2VpdmVBdWRpbyc6IHRydWUsXG4gICAgICAgICAgICAgICAgJ09mZmVyVG9SZWNlaXZlVmlkZW8nOiB0cnVlXG4gICAgICAgICAgICB9XG4gICAgICAgICAgICAvLyBNb3pEb250T2ZmZXJEYXRhQ2hhbm5lbDogdHJ1ZSB3aGVuIHRoaXMgaXMgZmlyZWZveFxuICAgICAgICB9LFxuICAgICAgICBpbml0OiBmdW5jdGlvbiAoY29ubikge1xuICAgICAgICAgICAgdGhpcy5jb25uZWN0aW9uID0gY29ubjtcbiAgICAgICAgICAgIGlmICh0aGlzLmNvbm5lY3Rpb24uZGlzY28pIHtcbiAgICAgICAgICAgICAgICAvLyBodHRwOi8veG1wcC5vcmcvZXh0ZW5zaW9ucy94ZXAtMDE2Ny5odG1sI3N1cHBvcnRcbiAgICAgICAgICAgICAgICAvLyBodHRwOi8veG1wcC5vcmcvZXh0ZW5zaW9ucy94ZXAtMDE3Ni5odG1sI3N1cHBvcnRcbiAgICAgICAgICAgICAgICB0aGlzLmNvbm5lY3Rpb24uZGlzY28uYWRkRmVhdHVyZSgndXJuOnhtcHA6amluZ2xlOjEnKTtcbiAgICAgICAgICAgICAgICB0aGlzLmNvbm5lY3Rpb24uZGlzY28uYWRkRmVhdHVyZSgndXJuOnhtcHA6amluZ2xlOmFwcHM6cnRwOjEnKTtcbiAgICAgICAgICAgICAgICB0aGlzLmNvbm5lY3Rpb24uZGlzY28uYWRkRmVhdHVyZSgndXJuOnhtcHA6amluZ2xlOnRyYW5zcG9ydHM6aWNlLXVkcDoxJyk7XG4gICAgICAgICAgICAgICAgdGhpcy5jb25uZWN0aW9uLmRpc2NvLmFkZEZlYXR1cmUoJ3Vybjp4bXBwOmppbmdsZTphcHBzOmR0bHM6MCcpO1xuICAgICAgICAgICAgICAgIHRoaXMuY29ubmVjdGlvbi5kaXNjby5hZGRGZWF0dXJlKCd1cm46eG1wcDpqaW5nbGU6dHJhbnNwb3J0czpkdGxzLXNjdHA6MScpO1xuICAgICAgICAgICAgICAgIHRoaXMuY29ubmVjdGlvbi5kaXNjby5hZGRGZWF0dXJlKCd1cm46eG1wcDpqaW5nbGU6YXBwczpydHA6YXVkaW8nKTtcbiAgICAgICAgICAgICAgICB0aGlzLmNvbm5lY3Rpb24uZGlzY28uYWRkRmVhdHVyZSgndXJuOnhtcHA6amluZ2xlOmFwcHM6cnRwOnZpZGVvJyk7XG5cbiAgICAgICAgICAgICAgICBpZiAoUlRDQnJvd3NlclR5cGUuaXNDaHJvbWUoKSB8fCBSVENCcm93c2VyVHlwZS5pc09wZXJhKClcbiAgICAgICAgICAgICAgICAgICAgfHwgUlRDQnJvd3NlclR5cGUuaXNUZW1hc3lzUGx1Z2luVXNlZCgpKSB7XG4gICAgICAgICAgICAgICAgICAgIHRoaXMuY29ubmVjdGlvbi5kaXNjby5hZGRGZWF0dXJlKCd1cm46aWV0ZjpyZmM6NDU4OCcpO1xuICAgICAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgICAgIC8vIHRoaXMgaXMgZGVhbHQgd2l0aCBieSBTRFAgTy9BIHNvIHdlIGRvbid0IG5lZWQgdG8gYW5ub3VuY2UgdGhpc1xuICAgICAgICAgICAgICAgIC8vdGhpcy5jb25uZWN0aW9uLmRpc2NvLmFkZEZlYXR1cmUoJ3Vybjp4bXBwOmppbmdsZTphcHBzOnJ0cDpydGNwLWZiOjAnKTsgLy8gWEVQLTAyOTNcbiAgICAgICAgICAgICAgICAvL3RoaXMuY29ubmVjdGlvbi5kaXNjby5hZGRGZWF0dXJlKCd1cm46eG1wcDpqaW5nbGU6YXBwczpydHA6cnRwLWhkcmV4dDowJyk7IC8vIFhFUC0wMjk0XG5cbiAgICAgICAgICAgICAgICB0aGlzLmNvbm5lY3Rpb24uZGlzY28uYWRkRmVhdHVyZSgndXJuOmlldGY6cmZjOjU3NjEnKTsgLy8gcnRjcC1tdXhcbiAgICAgICAgICAgICAgICB0aGlzLmNvbm5lY3Rpb24uZGlzY28uYWRkRmVhdHVyZSgndXJuOmlldGY6cmZjOjU4ODgnKTsgLy8gYT1ncm91cCwgZS5nLiBidW5kbGVcblxuICAgICAgICAgICAgICAgIC8vdGhpcy5jb25uZWN0aW9uLmRpc2NvLmFkZEZlYXR1cmUoJ3VybjppZXRmOnJmYzo1NTc2Jyk7IC8vIGE9c3NyY1xuICAgICAgICAgICAgfVxuICAgICAgICAgICAgdGhpcy5jb25uZWN0aW9uLmFkZEhhbmRsZXIodGhpcy5vbkppbmdsZS5iaW5kKHRoaXMpLCAndXJuOnhtcHA6amluZ2xlOjEnLCAnaXEnLCAnc2V0JywgbnVsbCwgbnVsbCk7XG4gICAgICAgIH0sXG4gICAgICAgIG9uSmluZ2xlOiBmdW5jdGlvbiAoaXEpIHtcbiAgICAgICAgICAgIHZhciBzaWQgPSAkKGlxKS5maW5kKCdqaW5nbGUnKS5hdHRyKCdzaWQnKTtcbiAgICAgICAgICAgIHZhciBhY3Rpb24gPSAkKGlxKS5maW5kKCdqaW5nbGUnKS5hdHRyKCdhY3Rpb24nKTtcbiAgICAgICAgICAgIHZhciBmcm9tSmlkID0gaXEuZ2V0QXR0cmlidXRlKCdmcm9tJyk7XG4gICAgICAgICAgICAvLyBzZW5kIGFjayBmaXJzdFxuICAgICAgICAgICAgdmFyIGFjayA9ICRpcSh7dHlwZTogJ3Jlc3VsdCcsXG4gICAgICAgICAgICAgICAgdG86IGZyb21KaWQsXG4gICAgICAgICAgICAgICAgaWQ6IGlxLmdldEF0dHJpYnV0ZSgnaWQnKVxuICAgICAgICAgICAgfSk7XG4gICAgICAgICAgICBsb2dnZXIubG9nKCdvbiBqaW5nbGUgJyArIGFjdGlvbiArICcgZnJvbSAnICsgZnJvbUppZCwgaXEpO1xuICAgICAgICAgICAgdmFyIHNlc3MgPSB0aGlzLnNlc3Npb25zW3NpZF07XG4gICAgICAgICAgICBpZiAoJ3Nlc3Npb24taW5pdGlhdGUnICE9IGFjdGlvbikge1xuICAgICAgICAgICAgICAgIGlmIChzZXNzID09PSBudWxsKSB7XG4gICAgICAgICAgICAgICAgICAgIGFjay50eXBlID0gJ2Vycm9yJztcbiAgICAgICAgICAgICAgICAgICAgYWNrLmMoJ2Vycm9yJywge3R5cGU6ICdjYW5jZWwnfSlcbiAgICAgICAgICAgICAgICAgICAgICAgIC5jKCdpdGVtLW5vdC1mb3VuZCcsIHt4bWxuczogJ3VybjppZXRmOnBhcmFtczp4bWw6bnM6eG1wcC1zdGFuemFzJ30pLnVwKClcbiAgICAgICAgICAgICAgICAgICAgICAgIC5jKCd1bmtub3duLXNlc3Npb24nLCB7eG1sbnM6ICd1cm46eG1wcDpqaW5nbGU6ZXJyb3JzOjEnfSk7XG4gICAgICAgICAgICAgICAgICAgIHRoaXMuY29ubmVjdGlvbi5zZW5kKGFjayk7XG4gICAgICAgICAgICAgICAgICAgIHJldHVybiB0cnVlO1xuICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICAvLyBsb2NhbCBqaWQgaXMgbm90IGNoZWNrZWRcbiAgICAgICAgICAgICAgICBpZiAoZnJvbUppZCAhPSBzZXNzLnBlZXJqaWQpIHtcbiAgICAgICAgICAgICAgICAgICAgbG9nZ2VyLndhcm4oJ2ppZCBtaXNtYXRjaCBmb3Igc2Vzc2lvbiBpZCcsIHNpZCwgZnJvbUppZCwgc2Vzcy5wZWVyamlkKTtcbiAgICAgICAgICAgICAgICAgICAgYWNrLnR5cGUgPSAnZXJyb3InO1xuICAgICAgICAgICAgICAgICAgICBhY2suYygnZXJyb3InLCB7dHlwZTogJ2NhbmNlbCd9KVxuICAgICAgICAgICAgICAgICAgICAgICAgLmMoJ2l0ZW0tbm90LWZvdW5kJywge3htbG5zOiAndXJuOmlldGY6cGFyYW1zOnhtbDpuczp4bXBwLXN0YW56YXMnfSkudXAoKVxuICAgICAgICAgICAgICAgICAgICAgICAgLmMoJ3Vua25vd24tc2Vzc2lvbicsIHt4bWxuczogJ3Vybjp4bXBwOmppbmdsZTplcnJvcnM6MSd9KTtcbiAgICAgICAgICAgICAgICAgICAgdGhpcy5jb25uZWN0aW9uLnNlbmQoYWNrKTtcbiAgICAgICAgICAgICAgICAgICAgcmV0dXJuIHRydWU7XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgfSBlbHNlIGlmIChzZXNzICE9PSB1bmRlZmluZWQpIHtcbiAgICAgICAgICAgICAgICAvLyBleGlzdGluZyBzZXNzaW9uIHdpdGggc2FtZSBzZXNzaW9uIGlkXG4gICAgICAgICAgICAgICAgLy8gdGhpcyBtaWdodCBiZSBvdXQtb2Ytb3JkZXIgaWYgdGhlIHNlc3MucGVlcmppZCBpcyB0aGUgc2FtZSBhcyBmcm9tXG4gICAgICAgICAgICAgICAgYWNrLnR5cGUgPSAnZXJyb3InO1xuICAgICAgICAgICAgICAgIGFjay5jKCdlcnJvcicsIHt0eXBlOiAnY2FuY2VsJ30pXG4gICAgICAgICAgICAgICAgICAgIC5jKCdzZXJ2aWNlLXVuYXZhaWxhYmxlJywge3htbG5zOiAndXJuOmlldGY6cGFyYW1zOnhtbDpuczp4bXBwLXN0YW56YXMnfSkudXAoKTtcbiAgICAgICAgICAgICAgICBsb2dnZXIud2FybignZHVwbGljYXRlIHNlc3Npb24gaWQnLCBzaWQpO1xuICAgICAgICAgICAgICAgIHRoaXMuY29ubmVjdGlvbi5zZW5kKGFjayk7XG4gICAgICAgICAgICAgICAgcmV0dXJuIHRydWU7XG4gICAgICAgICAgICB9XG4gICAgICAgICAgICAvLyBGSVhNRTogY2hlY2sgZm9yIGEgZGVmaW5lZCBhY3Rpb25cbiAgICAgICAgICAgIHRoaXMuY29ubmVjdGlvbi5zZW5kKGFjayk7XG4gICAgICAgICAgICAvLyBzZWUgaHR0cDovL3htcHAub3JnL2V4dGVuc2lvbnMveGVwLTAxNjYuaHRtbCNjb25jZXB0cy1zZXNzaW9uXG4gICAgICAgICAgICBzd2l0Y2ggKGFjdGlvbikge1xuICAgICAgICAgICAgICAgIGNhc2UgJ3Nlc3Npb24taW5pdGlhdGUnOlxuICAgICAgICAgICAgICAgICAgICBjb25zb2xlLmxvZyhcIihUSU1FKSByZWNlaXZlZCBzZXNzaW9uLWluaXRpYXRlOlxcdFwiLFxuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICB3aW5kb3cucGVyZm9ybWFuY2Uubm93KCkpO1xuICAgICAgICAgICAgICAgICAgICB2YXIgc3RhcnRNdXRlZCA9ICQoaXEpLmZpbmQoJ2ppbmdsZT5zdGFydG11dGVkJyk7XG4gICAgICAgICAgICAgICAgICAgIGlmIChzdGFydE11dGVkICYmIHN0YXJ0TXV0ZWQubGVuZ3RoID4gMCkge1xuICAgICAgICAgICAgICAgICAgICAgICAgdmFyIGF1ZGlvTXV0ZWQgPSBzdGFydE11dGVkLmF0dHIoXCJhdWRpb1wiKTtcbiAgICAgICAgICAgICAgICAgICAgICAgIHZhciB2aWRlb011dGVkID0gc3RhcnRNdXRlZC5hdHRyKFwidmlkZW9cIik7XG4gICAgICAgICAgICAgICAgICAgICAgICBldmVudEVtaXR0ZXIuZW1pdChYTVBQRXZlbnRzLlNUQVJUX01VVEVEX0ZST01fRk9DVVMsXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGF1ZGlvTXV0ZWQgPT09IFwidHJ1ZVwiLCB2aWRlb011dGVkID09PSBcInRydWVcIik7XG4gICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICAgICAgc2VzcyA9IG5ldyBKaW5nbGVTZXNzaW9uKFxuICAgICAgICAgICAgICAgICAgICAgICAgJChpcSkuYXR0cigndG8nKSwgJChpcSkuZmluZCgnamluZ2xlJykuYXR0cignc2lkJyksXG4gICAgICAgICAgICAgICAgICAgICAgICB0aGlzLmNvbm5lY3Rpb24sIFhNUFApO1xuICAgICAgICAgICAgICAgICAgICAvLyBjb25maWd1cmUgc2Vzc2lvblxuXG4gICAgICAgICAgICAgICAgICAgIHZhciBmcm9tQmFyZUppZCA9IFN0cm9waGUuZ2V0QmFyZUppZEZyb21KaWQoZnJvbUppZCk7XG4gICAgICAgICAgICAgICAgICAgIHRoaXMuY29ubmVjdGlvbi5lbXVjLnNldEppbmdsZVNlc3Npb24oZnJvbUJhcmVKaWQsIHNlc3MpO1xuXG4gICAgICAgICAgICAgICAgICAgIHNlc3MubWVkaWFfY29uc3RyYWludHMgPSB0aGlzLm1lZGlhX2NvbnN0cmFpbnRzO1xuICAgICAgICAgICAgICAgICAgICBzZXNzLmljZV9jb25maWcgPSB0aGlzLmljZV9jb25maWc7XG5cbiAgICAgICAgICAgICAgICAgICAgc2Vzcy5pbml0aWFsaXplKGZyb21KaWQsIGZhbHNlKTtcbiAgICAgICAgICAgICAgICAgICAgZXZlbnRFbWl0dGVyLmVtaXQoWE1QUEV2ZW50cy5DQUxMX0lOQ09NSU5HLCBzZXNzKTtcbiAgICAgICAgICAgICAgICAgICAgLy8gRklYTUU6IHNldFJlbW90ZURlc2NyaXB0aW9uIHNob3VsZCBvbmx5IGJlIGRvbmUgd2hlbiB0aGlzIGNhbGwgaXMgdG8gYmUgYWNjZXB0ZWRcbiAgICAgICAgICAgICAgICAgICAgc2Vzcy5zZXRPZmZlcigkKGlxKS5maW5kKCc+amluZ2xlJykpO1xuXG4gICAgICAgICAgICAgICAgICAgIHRoaXMuc2Vzc2lvbnNbc2Vzcy5zaWRdID0gc2VzcztcbiAgICAgICAgICAgICAgICAgICAgdGhpcy5qaWQyc2Vzc2lvbltzZXNzLnBlZXJqaWRdID0gc2VzcztcblxuICAgICAgICAgICAgICAgICAgICAvLyB0aGUgY2FsbGJhY2sgc2hvdWxkIGVpdGhlclxuICAgICAgICAgICAgICAgICAgICAvLyAuc2VuZEFuc3dlciBhbmQgLmFjY2VwdFxuICAgICAgICAgICAgICAgICAgICAvLyBvciAuc2VuZFRlcm1pbmF0ZSAtLSBub3QgbmVjZXNzYXJpbHkgc3luY2hyb25vdXNcblxuICAgICAgICAgICAgICAgICAgICBzZXNzLnNlbmRBbnN3ZXIoKTtcbiAgICAgICAgICAgICAgICAgICAgc2Vzcy5hY2NlcHQoKTtcbiAgICAgICAgICAgICAgICAgICAgYnJlYWs7XG4gICAgICAgICAgICAgICAgY2FzZSAnc2Vzc2lvbi1hY2NlcHQnOlxuICAgICAgICAgICAgICAgICAgICBzZXNzLnNldEFuc3dlcigkKGlxKS5maW5kKCc+amluZ2xlJykpO1xuICAgICAgICAgICAgICAgICAgICBzZXNzLmFjY2VwdCgpO1xuICAgICAgICAgICAgICAgICAgICBicmVhaztcbiAgICAgICAgICAgICAgICBjYXNlICdzZXNzaW9uLXRlcm1pbmF0ZSc6XG4gICAgICAgICAgICAgICAgICAgIC8vIElmIHRoaXMgaXMgbm90IHRoZSBmb2N1cyBzZW5kaW5nIHRoZSB0ZXJtaW5hdGUsIHdlIGhhdmVcbiAgICAgICAgICAgICAgICAgICAgLy8gbm90aGluZyBtb3JlIHRvIGRvIGhlcmUuXG4gICAgICAgICAgICAgICAgICAgIGlmIChPYmplY3Qua2V5cyh0aGlzLnNlc3Npb25zKS5sZW5ndGggPCAxXG4gICAgICAgICAgICAgICAgICAgICAgICB8fCAhKHRoaXMuc2Vzc2lvbnNbT2JqZWN0LmtleXModGhpcy5zZXNzaW9ucylbMF1dXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgaW5zdGFuY2VvZiBKaW5nbGVTZXNzaW9uKSlcbiAgICAgICAgICAgICAgICAgICAge1xuICAgICAgICAgICAgICAgICAgICAgICAgYnJlYWs7XG4gICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICAgICAgbG9nZ2VyLmxvZygndGVybWluYXRpbmcuLi4nLCBzZXNzLnNpZCk7XG4gICAgICAgICAgICAgICAgICAgIHNlc3MudGVybWluYXRlKCk7XG4gICAgICAgICAgICAgICAgICAgIHRoaXMudGVybWluYXRlKHNlc3Muc2lkKTtcbiAgICAgICAgICAgICAgICAgICAgaWYgKCQoaXEpLmZpbmQoJz5qaW5nbGU+cmVhc29uJykubGVuZ3RoKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICAkKGRvY3VtZW50KS50cmlnZ2VyKCdjYWxsdGVybWluYXRlZC5qaW5nbGUnLCBbXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgc2Vzcy5zaWQsXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgc2Vzcy5wZWVyamlkLFxuICAgICAgICAgICAgICAgICAgICAgICAgICAgICQoaXEpLmZpbmQoJz5qaW5nbGU+cmVhc29uPjpmaXJzdCcpWzBdLnRhZ05hbWUsXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgJChpcSkuZmluZCgnPmppbmdsZT5yZWFzb24+dGV4dCcpLnRleHQoKVxuICAgICAgICAgICAgICAgICAgICAgICAgXSk7XG4gICAgICAgICAgICAgICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICAgICAgICAgICAgICAkKGRvY3VtZW50KS50cmlnZ2VyKCdjYWxsdGVybWluYXRlZC5qaW5nbGUnLFxuICAgICAgICAgICAgICAgICAgICAgICAgICAgIFtzZXNzLnNpZCwgc2Vzcy5wZWVyamlkXSk7XG4gICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICAgICAgYnJlYWs7XG4gICAgICAgICAgICAgICAgY2FzZSAndHJhbnNwb3J0LWluZm8nOlxuICAgICAgICAgICAgICAgICAgICBzZXNzLmFkZEljZUNhbmRpZGF0ZSgkKGlxKS5maW5kKCc+amluZ2xlPmNvbnRlbnQnKSk7XG4gICAgICAgICAgICAgICAgICAgIGJyZWFrO1xuICAgICAgICAgICAgICAgIGNhc2UgJ3Nlc3Npb24taW5mbyc6XG4gICAgICAgICAgICAgICAgICAgIHZhciBhZmZlY3RlZDtcbiAgICAgICAgICAgICAgICAgICAgaWYgKCQoaXEpLmZpbmQoJz5qaW5nbGU+cmluZ2luZ1t4bWxucz1cInVybjp4bXBwOmppbmdsZTphcHBzOnJ0cDppbmZvOjFcIl0nKS5sZW5ndGgpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgICQoZG9jdW1lbnQpLnRyaWdnZXIoJ3JpbmdpbmcuamluZ2xlJywgW3Nlc3Muc2lkXSk7XG4gICAgICAgICAgICAgICAgICAgIH0gZWxzZSBpZiAoJChpcSkuZmluZCgnPmppbmdsZT5tdXRlW3htbG5zPVwidXJuOnhtcHA6amluZ2xlOmFwcHM6cnRwOmluZm86MVwiXScpLmxlbmd0aCkge1xuICAgICAgICAgICAgICAgICAgICAgICAgYWZmZWN0ZWQgPSAkKGlxKS5maW5kKCc+amluZ2xlPm11dGVbeG1sbnM9XCJ1cm46eG1wcDpqaW5nbGU6YXBwczpydHA6aW5mbzoxXCJdJykuYXR0cignbmFtZScpO1xuICAgICAgICAgICAgICAgICAgICAgICAgJChkb2N1bWVudCkudHJpZ2dlcignbXV0ZS5qaW5nbGUnLCBbc2Vzcy5zaWQsIGFmZmVjdGVkXSk7XG4gICAgICAgICAgICAgICAgICAgIH0gZWxzZSBpZiAoJChpcSkuZmluZCgnPmppbmdsZT51bm11dGVbeG1sbnM9XCJ1cm46eG1wcDpqaW5nbGU6YXBwczpydHA6aW5mbzoxXCJdJykubGVuZ3RoKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICBhZmZlY3RlZCA9ICQoaXEpLmZpbmQoJz5qaW5nbGU+dW5tdXRlW3htbG5zPVwidXJuOnhtcHA6amluZ2xlOmFwcHM6cnRwOmluZm86MVwiXScpLmF0dHIoJ25hbWUnKTtcbiAgICAgICAgICAgICAgICAgICAgICAgICQoZG9jdW1lbnQpLnRyaWdnZXIoJ3VubXV0ZS5qaW5nbGUnLCBbc2Vzcy5zaWQsIGFmZmVjdGVkXSk7XG4gICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICAgICAgYnJlYWs7XG4gICAgICAgICAgICAgICAgY2FzZSAnYWRkc291cmNlJzogLy8gRklYTUU6IHByb3ByaWV0YXJ5LCB1bi1qaW5nbGVpc2hcbiAgICAgICAgICAgICAgICBjYXNlICdzb3VyY2UtYWRkJzogLy8gRklYTUU6IHByb3ByaWV0YXJ5XG4gICAgICAgICAgICAgICAgICAgIHNlc3MuYWRkU291cmNlKCQoaXEpLmZpbmQoJz5qaW5nbGU+Y29udGVudCcpKTtcbiAgICAgICAgICAgICAgICAgICAgYnJlYWs7XG4gICAgICAgICAgICAgICAgY2FzZSAncmVtb3Zlc291cmNlJzogLy8gRklYTUU6IHByb3ByaWV0YXJ5LCB1bi1qaW5nbGVpc2hcbiAgICAgICAgICAgICAgICBjYXNlICdzb3VyY2UtcmVtb3ZlJzogLy8gRklYTUU6IHByb3ByaWV0YXJ5XG4gICAgICAgICAgICAgICAgICAgIHNlc3MucmVtb3ZlU291cmNlKCQoaXEpLmZpbmQoJz5qaW5nbGU+Y29udGVudCcpKTtcbiAgICAgICAgICAgICAgICAgICAgYnJlYWs7XG4gICAgICAgICAgICAgICAgZGVmYXVsdDpcbiAgICAgICAgICAgICAgICAgICAgbG9nZ2VyLndhcm4oJ2ppbmdsZSBhY3Rpb24gbm90IGltcGxlbWVudGVkJywgYWN0aW9uKTtcbiAgICAgICAgICAgICAgICAgICAgYnJlYWs7XG4gICAgICAgICAgICB9XG4gICAgICAgICAgICByZXR1cm4gdHJ1ZTtcbiAgICAgICAgfSxcbiAgICAgICAgdGVybWluYXRlOiBmdW5jdGlvbiAoc2lkLCByZWFzb24sIHRleHQpIHsgLy8gdGVybWluYXRlIGJ5IHNlc3Npb25pZCAob3IgYWxsIHNlc3Npb25zKVxuICAgICAgICAgICAgaWYgKHNpZCA9PT0gbnVsbCB8fCBzaWQgPT09IHVuZGVmaW5lZCkge1xuICAgICAgICAgICAgICAgIGZvciAoc2lkIGluIHRoaXMuc2Vzc2lvbnMpIHtcbiAgICAgICAgICAgICAgICAgICAgaWYgKHRoaXMuc2Vzc2lvbnNbc2lkXS5zdGF0ZSAhPSAnZW5kZWQnKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICB0aGlzLnNlc3Npb25zW3NpZF0uc2VuZFRlcm1pbmF0ZShyZWFzb24gfHwgKCF0aGlzLnNlc3Npb25zW3NpZF0uYWN0aXZlKCkpID8gJ2NhbmNlbCcgOiBudWxsLCB0ZXh0KTtcbiAgICAgICAgICAgICAgICAgICAgICAgIHRoaXMuc2Vzc2lvbnNbc2lkXS50ZXJtaW5hdGUoKTtcbiAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgICAgICBkZWxldGUgdGhpcy5qaWQyc2Vzc2lvblt0aGlzLnNlc3Npb25zW3NpZF0ucGVlcmppZF07XG4gICAgICAgICAgICAgICAgICAgIGRlbGV0ZSB0aGlzLnNlc3Npb25zW3NpZF07XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgfSBlbHNlIGlmICh0aGlzLnNlc3Npb25zLmhhc093blByb3BlcnR5KHNpZCkpIHtcbiAgICAgICAgICAgICAgICBpZiAodGhpcy5zZXNzaW9uc1tzaWRdLnN0YXRlICE9ICdlbmRlZCcpIHtcbiAgICAgICAgICAgICAgICAgICAgdGhpcy5zZXNzaW9uc1tzaWRdLnNlbmRUZXJtaW5hdGUocmVhc29uIHx8ICghdGhpcy5zZXNzaW9uc1tzaWRdLmFjdGl2ZSgpKSA/ICdjYW5jZWwnIDogbnVsbCwgdGV4dCk7XG4gICAgICAgICAgICAgICAgICAgIHRoaXMuc2Vzc2lvbnNbc2lkXS50ZXJtaW5hdGUoKTtcbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgZGVsZXRlIHRoaXMuamlkMnNlc3Npb25bdGhpcy5zZXNzaW9uc1tzaWRdLnBlZXJqaWRdO1xuICAgICAgICAgICAgICAgIGRlbGV0ZSB0aGlzLnNlc3Npb25zW3NpZF07XG4gICAgICAgICAgICB9XG4gICAgICAgIH0sXG4gICAgICAgIGdldFN0dW5BbmRUdXJuQ3JlZGVudGlhbHM6IGZ1bmN0aW9uICgpIHtcbiAgICAgICAgICAgIC8vIGdldCBzdHVuIGFuZCB0dXJuIGNvbmZpZ3VyYXRpb24gZnJvbSBzZXJ2ZXIgdmlhIHhlcC0wMjE1XG4gICAgICAgICAgICAvLyB1c2VzIHRpbWUtbGltaXRlZCBjcmVkZW50aWFscyBhcyBkZXNjcmliZWQgaW5cbiAgICAgICAgICAgIC8vIGh0dHA6Ly90b29scy5pZXRmLm9yZy9odG1sL2RyYWZ0LXViZXJ0aS1iZWhhdmUtdHVybi1yZXN0LTAwXG4gICAgICAgICAgICAvL1xuICAgICAgICAgICAgLy8gc2VlIGh0dHBzOi8vY29kZS5nb29nbGUuY29tL3AvcHJvc29keS1tb2R1bGVzL3NvdXJjZS9icm93c2UvbW9kX3R1cm5jcmVkZW50aWFscy9tb2RfdHVybmNyZWRlbnRpYWxzLmx1YVxuICAgICAgICAgICAgLy8gZm9yIGEgcHJvc29keSBtb2R1bGUgd2hpY2ggaW1wbGVtZW50cyB0aGlzXG4gICAgICAgICAgICAvL1xuICAgICAgICAgICAgLy8gY3VycmVudGx5LCB0aGlzIGRvZXNuJ3Qgd29yayB3aXRoIHVwZGF0ZUljZSBhbmQgdGhlcmVmb3JlIGNyZWRlbnRpYWxzIHdpdGggYSBsb25nXG4gICAgICAgICAgICAvLyB2YWxpZGl0eSBoYXZlIHRvIGJlIGZldGNoZWQgYmVmb3JlIGNyZWF0aW5nIHRoZSBwZWVyY29ubmVjdGlvblxuICAgICAgICAgICAgLy8gVE9ETzogaW1wbGVtZW50IHJlZnJlc2ggdmlhIHVwZGF0ZUljZSBhcyBkZXNjcmliZWQgaW5cbiAgICAgICAgICAgIC8vICAgICAgaHR0cHM6Ly9jb2RlLmdvb2dsZS5jb20vcC93ZWJydGMvaXNzdWVzL2RldGFpbD9pZD0xNjUwXG4gICAgICAgICAgICB2YXIgc2VsZiA9IHRoaXM7XG4gICAgICAgICAgICB0aGlzLmNvbm5lY3Rpb24uc2VuZElRKFxuICAgICAgICAgICAgICAgICRpcSh7dHlwZTogJ2dldCcsIHRvOiB0aGlzLmNvbm5lY3Rpb24uZG9tYWlufSlcbiAgICAgICAgICAgICAgICAgICAgLmMoJ3NlcnZpY2VzJywge3htbG5zOiAndXJuOnhtcHA6ZXh0ZGlzY286MSd9KS5jKCdzZXJ2aWNlJywge2hvc3Q6ICd0dXJuLicgKyB0aGlzLmNvbm5lY3Rpb24uZG9tYWlufSksXG4gICAgICAgICAgICAgICAgZnVuY3Rpb24gKHJlcykge1xuICAgICAgICAgICAgICAgICAgICB2YXIgaWNlc2VydmVycyA9IFtdO1xuICAgICAgICAgICAgICAgICAgICAkKHJlcykuZmluZCgnPnNlcnZpY2VzPnNlcnZpY2UnKS5lYWNoKGZ1bmN0aW9uIChpZHgsIGVsKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICBlbCA9ICQoZWwpO1xuICAgICAgICAgICAgICAgICAgICAgICAgdmFyIGRpY3QgPSB7fTtcbiAgICAgICAgICAgICAgICAgICAgICAgIHZhciB0eXBlID0gZWwuYXR0cigndHlwZScpO1xuICAgICAgICAgICAgICAgICAgICAgICAgc3dpdGNoICh0eXBlKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgY2FzZSAnc3R1bic6XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGRpY3QudXJsID0gJ3N0dW46JyArIGVsLmF0dHIoJ2hvc3QnKTtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgaWYgKGVsLmF0dHIoJ3BvcnQnKSkge1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgZGljdC51cmwgKz0gJzonICsgZWwuYXR0cigncG9ydCcpO1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGljZXNlcnZlcnMucHVzaChkaWN0KTtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgYnJlYWs7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgY2FzZSAndHVybic6XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgY2FzZSAndHVybnMnOlxuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBkaWN0LnVybCA9IHR5cGUgKyAnOic7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGlmIChlbC5hdHRyKCd1c2VybmFtZScpKSB7IC8vIGh0dHBzOi8vY29kZS5nb29nbGUuY29tL3Avd2VicnRjL2lzc3Vlcy9kZXRhaWw/aWQ9MTUwOFxuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgaWYgKG5hdmlnYXRvci51c2VyQWdlbnQubWF0Y2goL0Nocm9tKGV8aXVtKVxcLyhbMC05XSspXFwuLykgJiYgcGFyc2VJbnQobmF2aWdhdG9yLnVzZXJBZ2VudC5tYXRjaCgvQ2hyb20oZXxpdW0pXFwvKFswLTldKylcXC4vKVsyXSwgMTApIDwgMjgpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBkaWN0LnVybCArPSBlbC5hdHRyKCd1c2VybmFtZScpICsgJ0AnO1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBkaWN0LnVzZXJuYW1lID0gZWwuYXR0cigndXNlcm5hbWUnKTsgLy8gb25seSB3b3JrcyBpbiBNMjhcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBkaWN0LnVybCArPSBlbC5hdHRyKCdob3N0Jyk7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGlmIChlbC5hdHRyKCdwb3J0JykgJiYgZWwuYXR0cigncG9ydCcpICE9ICczNDc4Jykge1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgZGljdC51cmwgKz0gJzonICsgZWwuYXR0cigncG9ydCcpO1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGlmIChlbC5hdHRyKCd0cmFuc3BvcnQnKSAmJiBlbC5hdHRyKCd0cmFuc3BvcnQnKSAhPSAndWRwJykge1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgZGljdC51cmwgKz0gJz90cmFuc3BvcnQ9JyArIGVsLmF0dHIoJ3RyYW5zcG9ydCcpO1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGlmIChlbC5hdHRyKCdwYXNzd29yZCcpKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBkaWN0LmNyZWRlbnRpYWwgPSBlbC5hdHRyKCdwYXNzd29yZCcpO1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGljZXNlcnZlcnMucHVzaChkaWN0KTtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgYnJlYWs7XG4gICAgICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgICAgIH0pO1xuICAgICAgICAgICAgICAgICAgICBzZWxmLmljZV9jb25maWcuaWNlU2VydmVycyA9IGljZXNlcnZlcnM7XG4gICAgICAgICAgICAgICAgfSxcbiAgICAgICAgICAgICAgICBmdW5jdGlvbiAoZXJyKSB7XG4gICAgICAgICAgICAgICAgICAgIGxvZ2dlci53YXJuKCdnZXR0aW5nIHR1cm4gY3JlZGVudGlhbHMgZmFpbGVkJywgZXJyKTtcbiAgICAgICAgICAgICAgICAgICAgbG9nZ2VyLndhcm4oJ2lzIG1vZF90dXJuY3JlZGVudGlhbHMgb3Igc2ltaWxhciBpbnN0YWxsZWQ/Jyk7XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgKTtcbiAgICAgICAgICAgIC8vIGltcGxlbWVudCBwdXNoP1xuICAgICAgICB9LFxuXG4gICAgICAgIC8qKlxuICAgICAgICAgKiBSZXR1cm5zIHRoZSBkYXRhIHNhdmVkIGluICd1cGRhdGVMb2cnIGluIGEgZm9ybWF0IHRvIGJlIGxvZ2dlZC5cbiAgICAgICAgICovXG4gICAgICAgIGdldExvZzogZnVuY3Rpb24gKCkge1xuICAgICAgICAgICAgdmFyIGRhdGEgPSB7fTtcbiAgICAgICAgICAgIHZhciBzZWxmID0gdGhpcztcbiAgICAgICAgICAgIE9iamVjdC5rZXlzKHRoaXMuc2Vzc2lvbnMpLmZvckVhY2goZnVuY3Rpb24gKHNpZCkge1xuICAgICAgICAgICAgICAgIHZhciBzZXNzaW9uID0gc2VsZi5zZXNzaW9uc1tzaWRdO1xuICAgICAgICAgICAgICAgIGlmIChzZXNzaW9uLnBlZXJjb25uZWN0aW9uICYmIHNlc3Npb24ucGVlcmNvbm5lY3Rpb24udXBkYXRlTG9nKSB7XG4gICAgICAgICAgICAgICAgICAgIC8vIEZJWE1FOiBzaG91bGQgcHJvYmFibHkgYmUgYSAuZHVtcCBjYWxsXG4gICAgICAgICAgICAgICAgICAgIGRhdGFbXCJqaW5nbGVfXCIgKyBzZXNzaW9uLnNpZF0gPSB7XG4gICAgICAgICAgICAgICAgICAgICAgICB1cGRhdGVMb2c6IHNlc3Npb24ucGVlcmNvbm5lY3Rpb24udXBkYXRlTG9nLFxuICAgICAgICAgICAgICAgICAgICAgICAgc3RhdHM6IHNlc3Npb24ucGVlcmNvbm5lY3Rpb24uc3RhdHMsXG4gICAgICAgICAgICAgICAgICAgICAgICB1cmw6IHdpbmRvdy5sb2NhdGlvbi5ocmVmXG4gICAgICAgICAgICAgICAgICAgIH07XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgfSk7XG4gICAgICAgICAgICByZXR1cm4gZGF0YTtcbiAgICAgICAgfVxuICAgIH0pO1xufTtcblxuIiwiLyogZ2xvYmFsIFN0cm9waGUgKi9cbm1vZHVsZS5leHBvcnRzID0gZnVuY3Rpb24gKCkge1xuXG4gICAgU3Ryb3BoZS5hZGRDb25uZWN0aW9uUGx1Z2luKCdsb2dnZXInLCB7XG4gICAgICAgIC8vIGxvZ3MgcmF3IHN0YW56YXMgYW5kIG1ha2VzIHRoZW0gYXZhaWxhYmxlIGZvciBkb3dubG9hZCBhcyBKU09OXG4gICAgICAgIGNvbm5lY3Rpb246IG51bGwsXG4gICAgICAgIGxvZzogW10sXG4gICAgICAgIGluaXQ6IGZ1bmN0aW9uIChjb25uKSB7XG4gICAgICAgICAgICB0aGlzLmNvbm5lY3Rpb24gPSBjb25uO1xuICAgICAgICAgICAgdGhpcy5jb25uZWN0aW9uLnJhd0lucHV0ID0gdGhpcy5sb2dfaW5jb21pbmcuYmluZCh0aGlzKTtcbiAgICAgICAgICAgIHRoaXMuY29ubmVjdGlvbi5yYXdPdXRwdXQgPSB0aGlzLmxvZ19vdXRnb2luZy5iaW5kKHRoaXMpO1xuICAgICAgICB9LFxuICAgICAgICBsb2dfaW5jb21pbmc6IGZ1bmN0aW9uIChzdGFuemEpIHtcbiAgICAgICAgICAgIHRoaXMubG9nLnB1c2goW25ldyBEYXRlKCkuZ2V0VGltZSgpLCAnaW5jb21pbmcnLCBzdGFuemFdKTtcbiAgICAgICAgfSxcbiAgICAgICAgbG9nX291dGdvaW5nOiBmdW5jdGlvbiAoc3RhbnphKSB7XG4gICAgICAgICAgICB0aGlzLmxvZy5wdXNoKFtuZXcgRGF0ZSgpLmdldFRpbWUoKSwgJ291dGdvaW5nJywgc3RhbnphXSk7XG4gICAgICAgIH1cbiAgICB9KTtcbn07IiwiLyogZ2xvYmFsICQsICRpcSwgU3Ryb3BoZSAqL1xuXG52YXIgbG9nZ2VyID0gcmVxdWlyZShcImppdHNpLW1lZXQtbG9nZ2VyXCIpLmdldExvZ2dlcihfX2ZpbGVuYW1lKTtcblxudmFyIFhNUFBFdmVudHMgPSByZXF1aXJlKFwiLi4vLi4vc2VydmljZS94bXBwL1hNUFBFdmVudHNcIik7XG5cbi8qKlxuICogUGluZyBldmVyeSAyMCBzZWNcbiAqL1xudmFyIFBJTkdfSU5URVJWQUwgPSAyMDAwMDtcblxuLyoqXG4gKiBQaW5nIHRpbWVvdXQgZXJyb3IgYWZ0ZXIgMTUgc2VjIG9mIHdhaXRpbmcuXG4gKi9cbnZhciBQSU5HX1RJTUVPVVQgPSAxNTAwMDtcblxuLyoqXG4gKiBXaWxsIGNsb3NlIHRoZSBjb25uZWN0aW9uIGFmdGVyIDMgY29uc2VjdXRpdmUgcGluZyBlcnJvcnMuXG4gKi9cbnZhciBQSU5HX1RIUkVTSE9MRCA9IDM7XG5cbi8qKlxuICogWEVQLTAxOTkgcGluZyBwbHVnaW4uXG4gKlxuICogUmVnaXN0ZXJzIFwidXJuOnhtcHA6cGluZ1wiIG5hbWVzcGFjZSB1bmRlciBTdHJvcGhlLk5TLlBJTkcuXG4gKi9cbm1vZHVsZS5leHBvcnRzID0gZnVuY3Rpb24gKFhNUFAsIGV2ZW50RW1pdHRlcikge1xuICAgIFN0cm9waGUuYWRkQ29ubmVjdGlvblBsdWdpbigncGluZycsIHtcblxuICAgICAgICBjb25uZWN0aW9uOiBudWxsLFxuXG4gICAgICAgIGZhaWxlZFBpbmdzOiAwLFxuXG4gICAgICAgIC8qKlxuICAgICAgICAgKiBJbml0aWFsaXplcyB0aGUgcGx1Z2luLiBNZXRob2QgY2FsbGVkIGJ5IFN0cm9waGUuXG4gICAgICAgICAqIEBwYXJhbSBjb25uZWN0aW9uIFN0cm9waGUgY29ubmVjdGlvbiBpbnN0YW5jZS5cbiAgICAgICAgICovXG4gICAgICAgIGluaXQ6IGZ1bmN0aW9uIChjb25uZWN0aW9uKSB7XG4gICAgICAgICAgICB0aGlzLmNvbm5lY3Rpb24gPSBjb25uZWN0aW9uO1xuICAgICAgICAgICAgU3Ryb3BoZS5hZGROYW1lc3BhY2UoJ1BJTkcnLCBcInVybjp4bXBwOnBpbmdcIik7XG4gICAgICAgIH0sXG5cbiAgICAgICAgLyoqXG4gICAgICAgICAqIFNlbmRzIFwicGluZ1wiIHRvIGdpdmVuIDx0dD5qaWQ8L3R0PlxuICAgICAgICAgKiBAcGFyYW0gamlkIHRoZSBKSUQgdG8gd2hpY2ggcGluZyByZXF1ZXN0IHdpbGwgYmUgc2VudC5cbiAgICAgICAgICogQHBhcmFtIHN1Y2Nlc3MgY2FsbGJhY2sgY2FsbGVkIG9uIHN1Y2Nlc3MuXG4gICAgICAgICAqIEBwYXJhbSBlcnJvciBjYWxsYmFjayBjYWxsZWQgb24gZXJyb3IuXG4gICAgICAgICAqIEBwYXJhbSB0aW1lb3V0IG1zIGhvdyBsb25nIGFyZSB3ZSBnb2luZyB0byB3YWl0IGZvciB0aGUgcmVzcG9uc2UuIE9uXG4gICAgICAgICAqICAgICAgICB0aW1lb3V0IDx0dD5lcnJvcjwvL3Q+IGNhbGxiYWNrIGlzIGNhbGxlZCB3aXRoIHVuZGVmaW5lZCBlcnJvclxuICAgICAgICAgKiAgICAgICAgYXJndW1lbnQuXG4gICAgICAgICAqL1xuICAgICAgICBwaW5nOiBmdW5jdGlvbiAoamlkLCBzdWNjZXNzLCBlcnJvciwgdGltZW91dCkge1xuICAgICAgICAgICAgdmFyIGlxID0gJGlxKHt0eXBlOiAnZ2V0JywgdG86IGppZH0pO1xuICAgICAgICAgICAgaXEuYygncGluZycsIHt4bWxuczogU3Ryb3BoZS5OUy5QSU5HfSk7XG4gICAgICAgICAgICB0aGlzLmNvbm5lY3Rpb24uc2VuZElRKGlxLCBzdWNjZXNzLCBlcnJvciwgdGltZW91dCk7XG4gICAgICAgIH0sXG5cbiAgICAgICAgLyoqXG4gICAgICAgICAqIENoZWNrcyBpZiBnaXZlbiA8dHQ+amlkPC90dD4gaGFzIFhFUC0wMTk5IHBpbmcgc3VwcG9ydC5cbiAgICAgICAgICogQHBhcmFtIGppZCB0aGUgSklEIHRvIGJlIGNoZWNrZWQgZm9yIHBpbmcgc3VwcG9ydC5cbiAgICAgICAgICogQHBhcmFtIGNhbGxiYWNrIGZ1bmN0aW9uIHdpdGggYm9vbGVhbiBhcmd1bWVudCB3aGljaCB3aWxsIGJlXG4gICAgICAgICAqIDx0dD50cnVlPC90dD4gaWYgWEVQLTAxOTkgcGluZyBpcyBzdXBwb3J0ZWQgYnkgZ2l2ZW4gPHR0PmppZDwvdHQ+XG4gICAgICAgICAqL1xuICAgICAgICBoYXNQaW5nU3VwcG9ydDogZnVuY3Rpb24gKGppZCwgY2FsbGJhY2spIHtcbiAgICAgICAgICAgIHRoaXMuY29ubmVjdGlvbi5kaXNjby5pbmZvKFxuICAgICAgICAgICAgICAgIGppZCwgbnVsbCxcbiAgICAgICAgICAgICAgICBmdW5jdGlvbiAocmVzdWx0KSB7XG4gICAgICAgICAgICAgICAgICAgIHZhciBwaW5nID0gJChyZXN1bHQpLmZpbmQoJz4+ZmVhdHVyZVt2YXI9XCJ1cm46eG1wcDpwaW5nXCJdJyk7XG4gICAgICAgICAgICAgICAgICAgIGNhbGxiYWNrKHBpbmcubGVuZ3RoID4gMCk7XG4gICAgICAgICAgICAgICAgfSxcbiAgICAgICAgICAgICAgICBmdW5jdGlvbiAoZXJyb3IpIHtcbiAgICAgICAgICAgICAgICAgICAgbG9nZ2VyLmVycm9yKFwiUGluZyBmZWF0dXJlIGRpc2NvdmVyeSBlcnJvclwiLCBlcnJvcik7XG4gICAgICAgICAgICAgICAgICAgIGNhbGxiYWNrKGZhbHNlKTtcbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICApO1xuICAgICAgICB9LFxuXG4gICAgICAgIC8qKlxuICAgICAgICAgKiBTdGFydHMgdG8gc2VuZCBwaW5nIGluIGdpdmVuIGludGVydmFsIHRvIHNwZWNpZmllZCByZW1vdGUgSklELlxuICAgICAgICAgKiBUaGlzIHBsdWdpbiBzdXBwb3J0cyBvbmx5IG9uZSBzdWNoIHRhc2sgYW5kIDx0dD5zdG9wSW50ZXJ2YWw8L3R0PlxuICAgICAgICAgKiBtdXN0IGJlIGNhbGxlZCBiZWZvcmUgc3RhcnRpbmcgYSBuZXcgb25lLlxuICAgICAgICAgKiBAcGFyYW0gcmVtb3RlSmlkIHJlbW90ZSBKSUQgdG8gd2hpY2ggcGluZyByZXF1ZXN0cyB3aWxsIGJlIHNlbnQgdG8uXG4gICAgICAgICAqIEBwYXJhbSBpbnRlcnZhbCB0YXNrIGludGVydmFsIGluIG1zLlxuICAgICAgICAgKi9cbiAgICAgICAgc3RhcnRJbnRlcnZhbDogZnVuY3Rpb24gKHJlbW90ZUppZCwgaW50ZXJ2YWwpIHtcbiAgICAgICAgICAgIGlmICh0aGlzLmludGVydmFsSWQpIHtcbiAgICAgICAgICAgICAgICBsb2dnZXIuZXJyb3IoXCJQaW5nIHRhc2sgc2NoZWR1bGVkIGFscmVhZHlcIik7XG4gICAgICAgICAgICAgICAgcmV0dXJuO1xuICAgICAgICAgICAgfVxuICAgICAgICAgICAgaWYgKCFpbnRlcnZhbClcbiAgICAgICAgICAgICAgICBpbnRlcnZhbCA9IFBJTkdfSU5URVJWQUw7XG4gICAgICAgICAgICB2YXIgc2VsZiA9IHRoaXM7XG4gICAgICAgICAgICB0aGlzLmludGVydmFsSWQgPSB3aW5kb3cuc2V0SW50ZXJ2YWwoZnVuY3Rpb24gKCkge1xuICAgICAgICAgICAgICAgIHNlbGYucGluZyhyZW1vdGVKaWQsXG4gICAgICAgICAgICAgICAgZnVuY3Rpb24gKHJlc3VsdCkge1xuICAgICAgICAgICAgICAgICAgICAvLyBQaW5nIE9LXG4gICAgICAgICAgICAgICAgICAgIHNlbGYuZmFpbGVkUGluZ3MgPSAwO1xuICAgICAgICAgICAgICAgIH0sXG4gICAgICAgICAgICAgICAgZnVuY3Rpb24gKGVycm9yKSB7XG4gICAgICAgICAgICAgICAgICAgIHNlbGYuZmFpbGVkUGluZ3MgKz0gMTtcbiAgICAgICAgICAgICAgICAgICAgbG9nZ2VyLmVycm9yKFxuICAgICAgICAgICAgICAgICAgICAgICAgXCJQaW5nIFwiICsgKGVycm9yID8gXCJlcnJvclwiIDogXCJ0aW1lb3V0XCIpLCBlcnJvcik7XG4gICAgICAgICAgICAgICAgICAgIGlmIChzZWxmLmZhaWxlZFBpbmdzID49IFBJTkdfVEhSRVNIT0xEKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICBzZWxmLmNvbm5lY3Rpb24uZGlzY29ubmVjdCgpO1xuICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgfSwgUElOR19USU1FT1VUKTtcbiAgICAgICAgICAgIH0sIGludGVydmFsKTtcbiAgICAgICAgICAgIGxvZ2dlci5pbmZvKFwiWE1QUCBwaW5ncyB3aWxsIGJlIHNlbnQgZXZlcnkgXCIgKyBpbnRlcnZhbCArIFwiIG1zXCIpO1xuICAgICAgICB9LFxuXG4gICAgICAgIC8qKlxuICAgICAgICAgKiBTdG9wcyBjdXJyZW50IFwicGluZ1wiICBpbnRlcnZhbCB0YXNrLlxuICAgICAgICAgKi9cbiAgICAgICAgc3RvcEludGVydmFsOiBmdW5jdGlvbiAoKSB7XG4gICAgICAgICAgICBpZiAodGhpcy5pbnRlcnZhbElkKSB7XG4gICAgICAgICAgICAgICAgd2luZG93LmNsZWFySW50ZXJ2YWwodGhpcy5pbnRlcnZhbElkKTtcbiAgICAgICAgICAgICAgICB0aGlzLmludGVydmFsSWQgPSBudWxsO1xuICAgICAgICAgICAgICAgIHRoaXMuZmFpbGVkUGluZ3MgPSAwO1xuICAgICAgICAgICAgICAgIGxvZ2dlci5pbmZvKFwiUGluZyBpbnRlcnZhbCBjbGVhcmVkXCIpO1xuICAgICAgICAgICAgfVxuICAgICAgICB9XG4gICAgfSk7XG59O1xuIiwiLyoganNoaW50IC1XMTE3ICovXG52YXIgbG9nZ2VyID0gcmVxdWlyZShcImppdHNpLW1lZXQtbG9nZ2VyXCIpLmdldExvZ2dlcihfX2ZpbGVuYW1lKTtcblxubW9kdWxlLmV4cG9ydHMgPSBmdW5jdGlvbigpIHtcbiAgICBTdHJvcGhlLmFkZENvbm5lY3Rpb25QbHVnaW4oJ3JheW8nLFxuICAgICAgICB7XG4gICAgICAgICAgICBSQVlPX1hNTE5TOiAndXJuOnhtcHA6cmF5bzoxJyxcbiAgICAgICAgICAgIGNvbm5lY3Rpb246IG51bGwsXG4gICAgICAgICAgICBpbml0OiBmdW5jdGlvbiAoY29ubikge1xuICAgICAgICAgICAgICAgIHRoaXMuY29ubmVjdGlvbiA9IGNvbm47XG4gICAgICAgICAgICAgICAgaWYgKHRoaXMuY29ubmVjdGlvbi5kaXNjbykge1xuICAgICAgICAgICAgICAgICAgICB0aGlzLmNvbm5lY3Rpb24uZGlzY28uYWRkRmVhdHVyZSgndXJuOnhtcHA6cmF5bzpjbGllbnQ6MScpO1xuICAgICAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgICAgIHRoaXMuY29ubmVjdGlvbi5hZGRIYW5kbGVyKFxuICAgICAgICAgICAgICAgICAgICB0aGlzLm9uUmF5by5iaW5kKHRoaXMpLCB0aGlzLlJBWU9fWE1MTlMsICdpcScsICdzZXQnLFxuICAgICAgICAgICAgICAgICAgICBudWxsLCBudWxsKTtcbiAgICAgICAgICAgIH0sXG4gICAgICAgICAgICBvblJheW86IGZ1bmN0aW9uIChpcSkge1xuICAgICAgICAgICAgICAgIGxvZ2dlci5pbmZvKFwiUmF5byBJUVwiLCBpcSk7XG4gICAgICAgICAgICB9LFxuICAgICAgICAgICAgZGlhbDogZnVuY3Rpb24gKHRvLCBmcm9tLCByb29tTmFtZSwgcm9vbVBhc3MsIGZvY3VzTXVjSmlkKSB7XG4gICAgICAgICAgICAgICAgdmFyIHNlbGYgPSB0aGlzO1xuICAgICAgICAgICAgICAgIHJldHVybiBuZXcgUHJvbWlzZShmdW5jdGlvbiAocmVzb2x2ZSwgcmVqZWN0KSB7XG4gICAgICAgICAgICAgICAgICAgIGlmKCFmb2N1c011Y0ppZCkge1xuICAgICAgICAgICAgICAgICAgICAgICAgcmVqZWN0KG5ldyBFcnJvcihcIkludGVybmFsIGVycm9yIVwiKSk7XG4gICAgICAgICAgICAgICAgICAgICAgICByZXR1cm47XG4gICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICAgICAgdmFyIHJlcSA9ICRpcShcbiAgICAgICAgICAgICAgICAgICAgICAgIHtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICB0eXBlOiAnc2V0JyxcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICB0bzogZm9jdXNNdWNKaWRcbiAgICAgICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICAgICAgKTtcbiAgICAgICAgICAgICAgICAgICAgcmVxLmMoJ2RpYWwnLFxuICAgICAgICAgICAgICAgICAgICAgICAge1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgIHhtbG5zOiBzZWxmLlJBWU9fWE1MTlMsXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgdG86IHRvLFxuICAgICAgICAgICAgICAgICAgICAgICAgICAgIGZyb206IGZyb21cbiAgICAgICAgICAgICAgICAgICAgICAgIH0pO1xuICAgICAgICAgICAgICAgICAgICByZXEuYygnaGVhZGVyJyxcbiAgICAgICAgICAgICAgICAgICAgICAgIHtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICBuYW1lOiAnSnZiUm9vbU5hbWUnLFxuICAgICAgICAgICAgICAgICAgICAgICAgICAgIHZhbHVlOiByb29tTmFtZVxuICAgICAgICAgICAgICAgICAgICAgICAgfSkudXAoKTtcblxuICAgICAgICAgICAgICAgICAgICBpZiAocm9vbVBhc3MgIT09IG51bGwgJiYgcm9vbVBhc3MubGVuZ3RoKSB7XG5cbiAgICAgICAgICAgICAgICAgICAgICAgIHJlcS5jKCdoZWFkZXInLFxuICAgICAgICAgICAgICAgICAgICAgICAgICAgIHtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgbmFtZTogJ0p2YlJvb21QYXNzd29yZCcsXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIHZhbHVlOiByb29tUGFzc1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgIH0pLnVwKCk7XG4gICAgICAgICAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgICAgICAgICBzZWxmLmNvbm5lY3Rpb24uc2VuZElRKFxuICAgICAgICAgICAgICAgICAgICAgICAgcmVxLFxuICAgICAgICAgICAgICAgICAgICAgICAgZnVuY3Rpb24gKHJlc3VsdCkge1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgIGxvZ2dlci5pbmZvKCdEaWFsIHJlc3VsdCAnLCByZXN1bHQpO1xuXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgdmFyIHJlc291cmNlID0gJChyZXN1bHQpLmZpbmQoJ3JlZicpLmF0dHIoJ3VyaScpO1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgIHNlbGYuY2FsbF9yZXNvdXJjZSA9XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIHJlc291cmNlLnN1YnN0cigneG1wcDonLmxlbmd0aCk7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgbG9nZ2VyLmluZm8oXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIFwiUmVjZWl2ZWQgY2FsbCByZXNvdXJjZTogXCIgK1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBzZWxmLmNhbGxfcmVzb3VyY2UpO1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgIHJlc29sdmUoKTtcbiAgICAgICAgICAgICAgICAgICAgICAgIH0sXG4gICAgICAgICAgICAgICAgICAgICAgICBmdW5jdGlvbiAoZXJyb3IpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICBsb2dnZXIuaW5mbygnRGlhbCBlcnJvciAnLCBlcnJvcik7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgcmVqZWN0KGVycm9yKTtcbiAgICAgICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICAgICAgKTtcbiAgICAgICAgICAgICAgICB9KTtcbiAgICAgICAgICAgIH0sXG4gICAgICAgICAgICBoYW5ndXA6IGZ1bmN0aW9uICgpIHtcbiAgICAgICAgICAgICAgICB2YXIgc2VsZiA9IHRoaXM7XG4gICAgICAgICAgICAgICAgcmV0dXJuIG5ldyBQcm9taXNlKGZ1bmN0aW9uIChyZXNvbHZlLCByZWplY3QpIHtcbiAgICAgICAgICAgICAgICAgICAgaWYgKCFzZWxmLmNhbGxfcmVzb3VyY2UpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgIHJlamVjdChuZXcgRXJyb3IoXCJObyBjYWxsIGluIHByb2dyZXNzXCIpKTtcbiAgICAgICAgICAgICAgICAgICAgICAgIGxvZ2dlci53YXJuKFwiTm8gY2FsbCBpbiBwcm9ncmVzc1wiKTtcbiAgICAgICAgICAgICAgICAgICAgICAgIHJldHVybjtcbiAgICAgICAgICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICAgICAgICAgIHZhciByZXEgPSAkaXEoXG4gICAgICAgICAgICAgICAgICAgICAgICB7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgdHlwZTogJ3NldCcsXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgdG86IHNlbGYuY2FsbF9yZXNvdXJjZVxuICAgICAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgICAgICApO1xuICAgICAgICAgICAgICAgICAgICByZXEuYygnaGFuZ3VwJyxcbiAgICAgICAgICAgICAgICAgICAgICAgIHtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICB4bWxuczogc2VsZi5SQVlPX1hNTE5TXG4gICAgICAgICAgICAgICAgICAgICAgICB9KTtcblxuICAgICAgICAgICAgICAgICAgICBzZWxmLmNvbm5lY3Rpb24uc2VuZElRKFxuICAgICAgICAgICAgICAgICAgICAgICAgcmVxLFxuICAgICAgICAgICAgICAgICAgICAgICAgZnVuY3Rpb24gKHJlc3VsdCkge1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgIGxvZ2dlci5pbmZvKCdIYW5ndXAgcmVzdWx0ICcsIHJlc3VsdCk7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgc2VsZi5jYWxsX3Jlc291cmNlID0gbnVsbDtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICByZXNvbHZlKCk7XG4gICAgICAgICAgICAgICAgICAgICAgICB9LFxuICAgICAgICAgICAgICAgICAgICAgICAgZnVuY3Rpb24gKGVycm9yKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgbG9nZ2VyLmluZm8oJ0hhbmd1cCBlcnJvciAnLCBlcnJvcik7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgc2VsZi5jYWxsX3Jlc291cmNlID0gbnVsbDtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICByZWplY3QobmV3IEVycm9yKCdIYW5ndXAgZXJyb3IgJykpO1xuICAgICAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgICAgICApO1xuICAgICAgICAgICAgICAgIH0pO1xuICAgICAgICAgICAgfVxuICAgICAgICB9XG4gICAgKTtcbn07XG4iLCIvKiBnbG9iYWwgU3Ryb3BoZSAqL1xuLyoqXG4gKiBTdHJvcGhlIGxvZ2dlciBpbXBsZW1lbnRhdGlvbi4gTG9ncyBmcm9tIGxldmVsIFdBUk4gYW5kIGFib3ZlLlxuICovXG52YXIgbG9nZ2VyID0gcmVxdWlyZShcImppdHNpLW1lZXQtbG9nZ2VyXCIpLmdldExvZ2dlcihfX2ZpbGVuYW1lKTtcblxubW9kdWxlLmV4cG9ydHMgPSBmdW5jdGlvbiAoKSB7XG5cbiAgICBTdHJvcGhlLmxvZyA9IGZ1bmN0aW9uIChsZXZlbCwgbXNnKSB7XG4gICAgICAgIHN3aXRjaCAobGV2ZWwpIHtcbiAgICAgICAgICAgIGNhc2UgU3Ryb3BoZS5Mb2dMZXZlbC5XQVJOOlxuICAgICAgICAgICAgICAgIGxvZ2dlci53YXJuKFwiU3Ryb3BoZTogXCIgKyBtc2cpO1xuICAgICAgICAgICAgICAgIGJyZWFrO1xuICAgICAgICAgICAgY2FzZSBTdHJvcGhlLkxvZ0xldmVsLkVSUk9SOlxuICAgICAgICAgICAgY2FzZSBTdHJvcGhlLkxvZ0xldmVsLkZBVEFMOlxuICAgICAgICAgICAgICAgIGxvZ2dlci5lcnJvcihcIlN0cm9waGU6IFwiICsgbXNnKTtcbiAgICAgICAgICAgICAgICBicmVhaztcbiAgICAgICAgfVxuICAgIH07XG5cbiAgICBTdHJvcGhlLmdldFN0YXR1c1N0cmluZyA9IGZ1bmN0aW9uIChzdGF0dXMpIHtcbiAgICAgICAgc3dpdGNoIChzdGF0dXMpIHtcbiAgICAgICAgICAgIGNhc2UgU3Ryb3BoZS5TdGF0dXMuRVJST1I6XG4gICAgICAgICAgICAgICAgcmV0dXJuIFwiRVJST1JcIjtcbiAgICAgICAgICAgIGNhc2UgU3Ryb3BoZS5TdGF0dXMuQ09OTkVDVElORzpcbiAgICAgICAgICAgICAgICByZXR1cm4gXCJDT05ORUNUSU5HXCI7XG4gICAgICAgICAgICBjYXNlIFN0cm9waGUuU3RhdHVzLkNPTk5GQUlMOlxuICAgICAgICAgICAgICAgIHJldHVybiBcIkNPTk5GQUlMXCI7XG4gICAgICAgICAgICBjYXNlIFN0cm9waGUuU3RhdHVzLkFVVEhFTlRJQ0FUSU5HOlxuICAgICAgICAgICAgICAgIHJldHVybiBcIkFVVEhFTlRJQ0FUSU5HXCI7XG4gICAgICAgICAgICBjYXNlIFN0cm9waGUuU3RhdHVzLkFVVEhGQUlMOlxuICAgICAgICAgICAgICAgIHJldHVybiBcIkFVVEhGQUlMXCI7XG4gICAgICAgICAgICBjYXNlIFN0cm9waGUuU3RhdHVzLkNPTk5FQ1RFRDpcbiAgICAgICAgICAgICAgICByZXR1cm4gXCJDT05ORUNURURcIjtcbiAgICAgICAgICAgIGNhc2UgU3Ryb3BoZS5TdGF0dXMuRElTQ09OTkVDVEVEOlxuICAgICAgICAgICAgICAgIHJldHVybiBcIkRJU0NPTk5FQ1RFRFwiO1xuICAgICAgICAgICAgY2FzZSBTdHJvcGhlLlN0YXR1cy5ESVNDT05ORUNUSU5HOlxuICAgICAgICAgICAgICAgIHJldHVybiBcIkRJU0NPTk5FQ1RJTkdcIjtcbiAgICAgICAgICAgIGNhc2UgU3Ryb3BoZS5TdGF0dXMuQVRUQUNIRUQ6XG4gICAgICAgICAgICAgICAgcmV0dXJuIFwiQVRUQUNIRURcIjtcbiAgICAgICAgICAgIGRlZmF1bHQ6XG4gICAgICAgICAgICAgICAgcmV0dXJuIFwidW5rbm93blwiO1xuICAgICAgICB9XG4gICAgfTtcbn07XG4iLCIvKiBnbG9iYWwgJCwgQVBQLCBjb25maWcsIFN0cm9waGUqL1xuXG52YXIgbG9nZ2VyID0gcmVxdWlyZShcImppdHNpLW1lZXQtbG9nZ2VyXCIpLmdldExvZ2dlcihfX2ZpbGVuYW1lKTtcbnZhciBFdmVudEVtaXR0ZXIgPSByZXF1aXJlKFwiZXZlbnRzXCIpO1xudmFyIFBha28gPSByZXF1aXJlKFwicGFrb1wiKTtcbnZhciBSVENFdmVudHMgPSByZXF1aXJlKFwiLi4vLi4vc2VydmljZS9SVEMvUlRDRXZlbnRzXCIpO1xudmFyIFhNUFBFdmVudHMgPSByZXF1aXJlKFwiLi4vLi4vc2VydmljZS94bXBwL1hNUFBFdmVudHNcIik7XG52YXIgSml0c2lDb25uZWN0aW9uRXJyb3JzID0gcmVxdWlyZShcIi4uLy4uL0ppdHNpQ29ubmVjdGlvbkVycm9yc1wiKTtcbnZhciBKaXRzaUNvbm5lY3Rpb25FdmVudHMgPSByZXF1aXJlKFwiLi4vLi4vSml0c2lDb25uZWN0aW9uRXZlbnRzXCIpO1xudmFyIFJUQyA9IHJlcXVpcmUoXCIuLi9SVEMvUlRDXCIpO1xuXG52YXIgYXV0aGVudGljYXRlZFVzZXIgPSBmYWxzZTtcblxuZnVuY3Rpb24gY3JlYXRlQ29ubmVjdGlvbihib3NoKSB7XG4gICAgYm9zaCA9IGJvc2ggfHwgJy9odHRwLWJpbmQnO1xuXG4gICAgLy8gQXBwZW5kIHRva2VuIGFzIFVSTCBwYXJhbVxuICAgIGlmICh0aGlzLnRva2VuKSB7XG4gICAgICAgIGJvc2ggKz0gYm9zaC5pbmRleE9mKCc/JykgPT0gLTEgP1xuICAgICAgICAgICAgICAgICc/dG9rZW49JyArIHRoaXMudG9rZW4gOiAnJnRva2VuPScgKyB0aGlzLnRva2VuO1xuICAgIH1cblxuICAgIHJldHVybiBuZXcgU3Ryb3BoZS5Db25uZWN0aW9uKGJvc2gpO1xufTtcblxuXG5cbi8vISEhISEhISEhISBGSVhNRTogLi4uXG5mdW5jdGlvbiBpbml0U3Ryb3BoZVBsdWdpbnMoWE1QUClcbntcbiAgICByZXF1aXJlKFwiLi9zdHJvcGhlLmVtdWNcIikoWE1QUCk7XG4gICAgcmVxdWlyZShcIi4vc3Ryb3BoZS5qaW5nbGVcIikoWE1QUCwgWE1QUC5ldmVudEVtaXR0ZXIpO1xuLy8gICAgcmVxdWlyZShcIi4vc3Ryb3BoZS5tb2RlcmF0ZVwiKShYTVBQLCBldmVudEVtaXR0ZXIpO1xuICAgIHJlcXVpcmUoXCIuL3N0cm9waGUudXRpbFwiKSgpO1xuICAgIHJlcXVpcmUoXCIuL3N0cm9waGUucGluZ1wiKShYTVBQLCBYTVBQLmV2ZW50RW1pdHRlcik7XG4gICAgcmVxdWlyZShcIi4vc3Ryb3BoZS5yYXlvXCIpKCk7XG4gICAgcmVxdWlyZShcIi4vc3Ryb3BoZS5sb2dnZXJcIikoKTtcbn1cblxuLy8hISEhISEhISEhIEZJWE1FOiAuLi5cbi8vLyoqXG4vLyAqIElmIGdpdmVuIDx0dD5sb2NhbFN0cmVhbTwvdHQ+IGlzIHZpZGVvIG9uZSB0aGlzIG1ldGhvZCB3aWxsIGFkdmVydGlzZSBpdCdzXG4vLyAqIHZpZGVvIHR5cGUgaW4gTVVDIHByZXNlbmNlLlxuLy8gKiBAcGFyYW0gbG9jYWxTdHJlYW0gbmV3IG9yIG1vZGlmaWVkIDx0dD5Mb2NhbFN0cmVhbTwvdHQ+LlxuLy8gKi9cbi8vZnVuY3Rpb24gYnJvYWRjYXN0TG9jYWxWaWRlb1R5cGUobG9jYWxTdHJlYW0pIHtcbi8vICAgIGlmIChsb2NhbFN0cmVhbS52aWRlb1R5cGUpXG4vLyAgICAgICAgWE1QUC5hZGRUb1ByZXNlbmNlKCd2aWRlb1R5cGUnLCBsb2NhbFN0cmVhbS52aWRlb1R5cGUpO1xuLy99XG4vL1xuLy9mdW5jdGlvbiByZWdpc3Rlckxpc3RlbmVycygpIHtcbi8vICAgIFJUQy5hZGRTdHJlYW1MaXN0ZW5lcihcbi8vICAgICAgICBicm9hZGNhc3RMb2NhbFZpZGVvVHlwZSxcbi8vICAgICAgICBTdHJlYW1FdmVudFR5cGVzLkVWRU5UX1RZUEVfTE9DQUxfQ0hBTkdFRFxuLy8gICAgKTtcbi8vICAgIFJUQy5hZGRMaXN0ZW5lcihSVENFdmVudHMuQVZBSUxBQkxFX0RFVklDRVNfQ0hBTkdFRCwgZnVuY3Rpb24gKGRldmljZXMpIHtcbi8vICAgICAgICBYTVBQLmFkZFRvUHJlc2VuY2UoXCJkZXZpY2VzXCIsIGRldmljZXMpO1xuLy8gICAgfSk7XG4vL31cblxuZnVuY3Rpb24gWE1QUChvcHRpb25zKSB7XG4gICAgdGhpcy5ldmVudEVtaXR0ZXIgPSBuZXcgRXZlbnRFbWl0dGVyKCk7XG4gICAgdGhpcy5jb25uZWN0aW9uID0gbnVsbDtcbiAgICB0aGlzLmRpc2Nvbm5lY3RJblByb2dyZXNzID0gZmFsc2U7XG5cbiAgICB0aGlzLmZvcmNlTXV0ZWQgPSBmYWxzZTtcbiAgICB0aGlzLm9wdGlvbnMgPSBvcHRpb25zO1xuICAgIGluaXRTdHJvcGhlUGx1Z2lucyh0aGlzKTtcbi8vICAgIHJlZ2lzdGVyTGlzdGVuZXJzKCk7XG5cbiAgICB0aGlzLmNvbm5lY3Rpb24gPSBjcmVhdGVDb25uZWN0aW9uKG9wdGlvbnMuYm9zaCk7XG59XG5cblxuWE1QUC5wcm90b3R5cGUuZ2V0Q29ubmVjdGlvbiA9IGZ1bmN0aW9uKCl7IHJldHVybiBjb25uZWN0aW9uOyB9O1xuXG5YTVBQLnByb3RvdHlwZS5fY29ubmVjdCA9IGZ1bmN0aW9uIChqaWQsIHBhc3N3b3JkKSB7XG5cbiAgICB2YXIgc2VsZiA9IHRoaXM7XG4gICAgLy8gY29ubmVjdGlvbi5jb25uZWN0KCkgc3RhcnRzIHRoZSBjb25uZWN0aW9uIHByb2Nlc3MuXG4gICAgLy9cbiAgICAvLyBBcyB0aGUgY29ubmVjdGlvbiBwcm9jZXNzIHByb2NlZWRzLCB0aGUgdXNlciBzdXBwbGllZCBjYWxsYmFjayB3aWxsXG4gICAgLy8gYmUgdHJpZ2dlcmVkIG11bHRpcGxlIHRpbWVzIHdpdGggc3RhdHVzIHVwZGF0ZXMuIFRoZSBjYWxsYmFjayBzaG91bGRcbiAgICAvLyB0YWtlIHR3byBhcmd1bWVudHMgLSB0aGUgc3RhdHVzIGNvZGUgYW5kIHRoZSBlcnJvciBjb25kaXRpb24uXG4gICAgLy9cbiAgICAvLyBUaGUgc3RhdHVzIGNvZGUgd2lsbCBiZSBvbmUgb2YgdGhlIHZhbHVlcyBpbiB0aGUgU3Ryb3BoZS5TdGF0dXNcbiAgICAvLyBjb25zdGFudHMuIFRoZSBlcnJvciBjb25kaXRpb24gd2lsbCBiZSBvbmUgb2YgdGhlIGNvbmRpdGlvbnMgZGVmaW5lZFxuICAgIC8vIGluIFJGQyAzOTIwIG9yIHRoZSBjb25kaXRpb24g4oCYc3Ryb3BoZS1wYXJzZXJlcnJvcuKAmS5cbiAgICAvL1xuICAgIC8vIFRoZSBQYXJhbWV0ZXJzIHdhaXQsIGhvbGQgYW5kIHJvdXRlIGFyZSBvcHRpb25hbCBhbmQgb25seSByZWxldmFudFxuICAgIC8vIGZvciBCT1NIIGNvbm5lY3Rpb25zLiBQbGVhc2Ugc2VlIFhFUCAxMjQgZm9yIGEgbW9yZSBkZXRhaWxlZFxuICAgIC8vIGV4cGxhbmF0aW9uIG9mIHRoZSBvcHRpb25hbCBwYXJhbWV0ZXJzLlxuICAgIC8vXG4gICAgLy8gQ29ubmVjdGlvbiBzdGF0dXMgY29uc3RhbnRzIGZvciB1c2UgYnkgdGhlIGNvbm5lY3Rpb24gaGFuZGxlclxuICAgIC8vIGNhbGxiYWNrLlxuICAgIC8vXG4gICAgLy8gIFN0YXR1cy5FUlJPUiAtIEFuIGVycm9yIGhhcyBvY2N1cnJlZCAod2Vic29ja2V0cyBzcGVjaWZpYylcbiAgICAvLyAgU3RhdHVzLkNPTk5FQ1RJTkcgLSBUaGUgY29ubmVjdGlvbiBpcyBjdXJyZW50bHkgYmVpbmcgbWFkZVxuICAgIC8vICBTdGF0dXMuQ09OTkZBSUwgLSBUaGUgY29ubmVjdGlvbiBhdHRlbXB0IGZhaWxlZFxuICAgIC8vICBTdGF0dXMuQVVUSEVOVElDQVRJTkcgLSBUaGUgY29ubmVjdGlvbiBpcyBhdXRoZW50aWNhdGluZ1xuICAgIC8vICBTdGF0dXMuQVVUSEZBSUwgLSBUaGUgYXV0aGVudGljYXRpb24gYXR0ZW1wdCBmYWlsZWRcbiAgICAvLyAgU3RhdHVzLkNPTk5FQ1RFRCAtIFRoZSBjb25uZWN0aW9uIGhhcyBzdWNjZWVkZWRcbiAgICAvLyAgU3RhdHVzLkRJU0NPTk5FQ1RFRCAtIFRoZSBjb25uZWN0aW9uIGhhcyBiZWVuIHRlcm1pbmF0ZWRcbiAgICAvLyAgU3RhdHVzLkRJU0NPTk5FQ1RJTkcgLSBUaGUgY29ubmVjdGlvbiBpcyBjdXJyZW50bHkgYmVpbmcgdGVybWluYXRlZFxuICAgIC8vICBTdGF0dXMuQVRUQUNIRUQgLSBUaGUgY29ubmVjdGlvbiBoYXMgYmVlbiBhdHRhY2hlZFxuXG4gICAgdmFyIGFub255bW91c0Nvbm5lY3Rpb25GYWlsZWQgPSBmYWxzZTtcbiAgICB2YXIgY29ubmVjdGlvbkZhaWxlZCA9IGZhbHNlO1xuICAgIHZhciBsYXN0RXJyb3JNc2c7XG4gICAgdGhpcy5jb25uZWN0aW9uLmNvbm5lY3QoamlkLCBwYXNzd29yZCwgZnVuY3Rpb24gKHN0YXR1cywgbXNnKSB7XG4gICAgICAgIGxvZ2dlci5sb2coXCIoVElNRSkgU3Ryb3BoZSBcIiArIFN0cm9waGUuZ2V0U3RhdHVzU3RyaW5nKHN0YXR1cykgK1xuICAgICAgICAgICAgKG1zZyA/IFwiW1wiICsgbXNnICsgXCJdXCIgOiBcIlwiKSArIFwiXFx0OlwiICsgd2luZG93LnBlcmZvcm1hbmNlLm5vdygpKTtcbiAgICAgICAgaWYgKHN0YXR1cyA9PT0gU3Ryb3BoZS5TdGF0dXMuQ09OTkVDVEVEKSB7XG4gICAgICAgICAgICBpZiAoc2VsZi5vcHRpb25zLnVzZVN0dW5UdXJuKSB7XG4gICAgICAgICAgICAgICAgc2VsZi5jb25uZWN0aW9uLmppbmdsZS5nZXRTdHVuQW5kVHVybkNyZWRlbnRpYWxzKCk7XG4gICAgICAgICAgICB9XG5cblxuICAgICAgICAgICAgbG9nZ2VyLmluZm8oXCJNeSBKYWJiZXIgSUQ6IFwiICsgc2VsZi5jb25uZWN0aW9uLmppZCk7XG5cbiAgICAgICAgICAgIC8vIFNjaGVkdWxlIHBpbmcgP1xuICAgICAgICAgICAgdmFyIHBpbmdKaWQgPSBzZWxmLmNvbm5lY3Rpb24uZG9tYWluO1xuICAgICAgICAgICAgc2VsZi5jb25uZWN0aW9uLnBpbmcuaGFzUGluZ1N1cHBvcnQoXG4gICAgICAgICAgICAgICAgcGluZ0ppZCxcbiAgICAgICAgICAgICAgICBmdW5jdGlvbiAoaGFzUGluZykge1xuICAgICAgICAgICAgICAgICAgICBpZiAoaGFzUGluZylcbiAgICAgICAgICAgICAgICAgICAgICAgIHNlbGYuY29ubmVjdGlvbi5waW5nLnN0YXJ0SW50ZXJ2YWwocGluZ0ppZCk7XG4gICAgICAgICAgICAgICAgICAgIGVsc2VcbiAgICAgICAgICAgICAgICAgICAgICAgIGxvZ2dlci53YXJuKFwiUGluZyBOT1Qgc3VwcG9ydGVkIGJ5IFwiICsgcGluZ0ppZCk7XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgKTtcblxuICAgICAgICAgICAgaWYgKHBhc3N3b3JkKVxuICAgICAgICAgICAgICAgIGF1dGhlbnRpY2F0ZWRVc2VyID0gdHJ1ZTtcbiAgICAgICAgICAgIGlmIChzZWxmLmNvbm5lY3Rpb24gJiYgc2VsZi5jb25uZWN0aW9uLmNvbm5lY3RlZCAmJlxuICAgICAgICAgICAgICAgIFN0cm9waGUuZ2V0UmVzb3VyY2VGcm9tSmlkKHNlbGYuY29ubmVjdGlvbi5qaWQpKSB7XG4gICAgICAgICAgICAgICAgLy8gLmNvbm5lY3RlZCBpcyB0cnVlIHdoaWxlIGNvbm5lY3Rpbmc/XG4vLyAgICAgICAgICAgICAgICBzZWxmLmNvbm5lY3Rpb24uc2VuZCgkcHJlcygpKTtcbiAgICAgICAgICAgICAgICBzZWxmLmV2ZW50RW1pdHRlci5lbWl0KEppdHNpQ29ubmVjdGlvbkV2ZW50cy5DT05ORUNUSU9OX0VTVEFCTElTSEVELFxuICAgICAgICAgICAgICAgICAgICBTdHJvcGhlLmdldFJlc291cmNlRnJvbUppZChzZWxmLmNvbm5lY3Rpb24uamlkKSk7XG4gICAgICAgICAgICB9XG4gICAgICAgIH0gZWxzZSBpZiAoc3RhdHVzID09PSBTdHJvcGhlLlN0YXR1cy5DT05ORkFJTCkge1xuICAgICAgICAgICAgaWYgKG1zZyA9PT0gJ3gtc3Ryb3BoZS1iYWQtbm9uLWFub24tamlkJykge1xuICAgICAgICAgICAgICAgIGFub255bW91c0Nvbm5lY3Rpb25GYWlsZWQgPSB0cnVlO1xuICAgICAgICAgICAgfVxuICAgICAgICAgICAgZWxzZVxuICAgICAgICAgICAge1xuICAgICAgICAgICAgICAgIGNvbm5lY3Rpb25GYWlsZWQgPSB0cnVlO1xuICAgICAgICAgICAgfVxuICAgICAgICAgICAgbGFzdEVycm9yTXNnID0gbXNnO1xuICAgICAgICB9IGVsc2UgaWYgKHN0YXR1cyA9PT0gU3Ryb3BoZS5TdGF0dXMuRElTQ09OTkVDVEVEKSB7XG4gICAgICAgICAgICAvLyBTdG9wIHBpbmcgaW50ZXJ2YWxcbiAgICAgICAgICAgIHNlbGYuY29ubmVjdGlvbi5waW5nLnN0b3BJbnRlcnZhbCgpO1xuICAgICAgICAgICAgc2VsZi5kaXNjb25uZWN0SW5Qcm9ncmVzcyA9IGZhbHNlO1xuICAgICAgICAgICAgaWYgKGFub255bW91c0Nvbm5lY3Rpb25GYWlsZWQpIHtcbiAgICAgICAgICAgICAgICAvLyBwcm9tcHQgdXNlciBmb3IgdXNlcm5hbWUgYW5kIHBhc3N3b3JkXG4gICAgICAgICAgICAgICAgc2VsZi5ldmVudEVtaXR0ZXIuZW1pdChKaXRzaUNvbm5lY3Rpb25FdmVudHMuQ09OTkVDVElPTl9GQUlMRUQsXG4gICAgICAgICAgICAgICAgICAgIEppdHNpQ29ubmVjdGlvbkVycm9ycy5QQVNTV09SRF9SRVFVSVJFRCk7XG4gICAgICAgICAgICB9IGVsc2UgaWYoY29ubmVjdGlvbkZhaWxlZCkge1xuICAgICAgICAgICAgICAgIHNlbGYuZXZlbnRFbWl0dGVyLmVtaXQoSml0c2lDb25uZWN0aW9uRXZlbnRzLkNPTk5FQ1RJT05fRkFJTEVELFxuICAgICAgICAgICAgICAgICAgICBKaXRzaUNvbm5lY3Rpb25FcnJvcnMuT1RIRVJfRVJST1IsXG4gICAgICAgICAgICAgICAgICAgIG1zZyA/IG1zZyA6IGxhc3RFcnJvck1zZyk7XG4gICAgICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgICAgIHNlbGYuZXZlbnRFbWl0dGVyLmVtaXQoSml0c2lDb25uZWN0aW9uRXZlbnRzLkNPTk5FQ1RJT05fRElTQ09OTkVDVEVELFxuICAgICAgICAgICAgICAgICAgICBtc2cgPyBtc2cgOiBsYXN0RXJyb3JNc2cpO1xuICAgICAgICAgICAgfVxuICAgICAgICB9IGVsc2UgaWYgKHN0YXR1cyA9PT0gU3Ryb3BoZS5TdGF0dXMuQVVUSEZBSUwpIHtcbiAgICAgICAgICAgIC8vIHdyb25nIHBhc3N3b3JkIG9yIHVzZXJuYW1lLCBwcm9tcHQgdXNlclxuICAgICAgICAgICAgc2VsZi5ldmVudEVtaXR0ZXIuZW1pdChKaXRzaUNvbm5lY3Rpb25FdmVudHMuQ09OTkVDVElPTl9GQUlMRUQsXG4gICAgICAgICAgICAgICAgSml0c2lDb25uZWN0aW9uRXJyb3JzLlBBU1NXT1JEX1JFUVVJUkVEKTtcblxuICAgICAgICB9XG4gICAgfSk7XG59XG5cblhNUFAucHJvdG90eXBlLmNvbm5lY3QgPSBmdW5jdGlvbiAoamlkLCBwYXNzd29yZCkge1xuICAgIGlmKCFqaWQpIHtcbiAgICAgICAgdmFyIGNvbmZpZ0RvbWFpbiA9IHRoaXMub3B0aW9ucy5ob3N0cy5hbm9ueW1vdXNkb21haW4gfHwgdGhpcy5vcHRpb25zLmhvc3RzLmRvbWFpbjtcbiAgICAgICAgLy8gRm9yY2UgYXV0aGVudGljYXRlZCBkb21haW4gaWYgcm9vbSBpcyBhcHBlbmRlZCB3aXRoICc/bG9naW49dHJ1ZSdcbiAgICAgICAgaWYgKHRoaXMub3B0aW9ucy5ob3N0cy5hbm9ueW1vdXNkb21haW4gJiZcbiAgICAgICAgICAgIHdpbmRvdy5sb2NhdGlvbi5zZWFyY2guaW5kZXhPZihcImxvZ2luPXRydWVcIikgIT09IC0xKSB7XG4gICAgICAgICAgICBjb25maWdEb21haW4gPSB0aGlzLm9wdGlvbnMuaG9zdHMuZG9tYWluO1xuICAgICAgICB9XG4gICAgICAgIGppZCA9IGNvbmZpZ0RvbWFpbiB8fCB3aW5kb3cubG9jYXRpb24uaG9zdG5hbWU7XG4gICAgfVxuICAgIHJldHVybiB0aGlzLl9jb25uZWN0KGppZCwgcGFzc3dvcmQpO1xufTtcblxuWE1QUC5wcm90b3R5cGUuY3JlYXRlUm9vbSA9IGZ1bmN0aW9uIChyb29tTmFtZSwgb3B0aW9ucykge1xuICAgIHZhciByb29tamlkID0gcm9vbU5hbWUgICsgJ0AnICsgdGhpcy5vcHRpb25zLmhvc3RzLm11YztcblxuICAgIGlmIChvcHRpb25zLnVzZU5pY2tzKSB7XG4gICAgICAgIGlmIChvcHRpb25zLm5pY2spIHtcbiAgICAgICAgICAgIHJvb21qaWQgKz0gJy8nICsgb3B0aW9ucy5uaWNrO1xuICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgcm9vbWppZCArPSAnLycgKyBTdHJvcGhlLmdldE5vZGVGcm9tSmlkKHRoaXMuY29ubmVjdGlvbi5qaWQpO1xuICAgICAgICB9XG4gICAgfSBlbHNlIHtcbiAgICAgICAgdmFyIHRtcEppZCA9IFN0cm9waGUuZ2V0Tm9kZUZyb21KaWQodGhpcy5jb25uZWN0aW9uLmppZCk7XG5cbiAgICAgICAgaWYoIWF1dGhlbnRpY2F0ZWRVc2VyKVxuICAgICAgICAgICAgdG1wSmlkID0gdG1wSmlkLnN1YnN0cigwLCA4KTtcblxuICAgICAgICByb29tamlkICs9ICcvJyArIHRtcEppZDtcbiAgICB9XG5cbiAgICByZXR1cm4gdGhpcy5jb25uZWN0aW9uLmVtdWMuY3JlYXRlUm9vbShyb29tamlkLCBudWxsLCBvcHRpb25zKTtcbn1cblxuWE1QUC5wcm90b3R5cGUuYWRkTGlzdGVuZXIgPSBmdW5jdGlvbih0eXBlLCBsaXN0ZW5lcikge1xuICAgIHRoaXMuZXZlbnRFbWl0dGVyLm9uKHR5cGUsIGxpc3RlbmVyKTtcbn07XG5cblhNUFAucHJvdG90eXBlLnJlbW92ZUxpc3RlbmVyID0gZnVuY3Rpb24gKHR5cGUsIGxpc3RlbmVyKSB7XG4gICAgdGhpcy5ldmVudEVtaXR0ZXIucmVtb3ZlTGlzdGVuZXIodHlwZSwgbGlzdGVuZXIpO1xufTtcblxuLy9GSVhNRTogdGhpcyBzaG91bGQgd29yayB3aXRoIHRoZSByb29tXG5YTVBQLnByb3RvdHlwZS5sZWF2ZVJvb20gPSBmdW5jdGlvbiAoamlkKSB7XG4gICAgdmFyIGhhbmRsZXIgPSB0aGlzLmNvbm5lY3Rpb24uamluZ2xlLmppZDJzZXNzaW9uW2ppZF07XG4gICAgaWYgKGhhbmRsZXIgJiYgaGFuZGxlci5wZWVyY29ubmVjdGlvbikge1xuICAgICAgICAvLyBGSVhNRTogcHJvYmFibHkgcmVtb3Zpbmcgc3RyZWFtcyBpcyBub3QgcmVxdWlyZWQgYW5kIGNsb3NlKCkgc2hvdWxkXG4gICAgICAgIC8vIGJlIGVub3VnaFxuICAgICAgICBpZiAoUlRDLmxvY2FsQXVkaW8pIHtcbiAgICAgICAgICAgIGhhbmRsZXIucGVlcmNvbm5lY3Rpb24ucmVtb3ZlU3RyZWFtKFxuICAgICAgICAgICAgICAgIFJUQy5sb2NhbEF1ZGlvLmdldE9yaWdpbmFsU3RyZWFtKCksIHRydWUpO1xuICAgICAgICB9XG4gICAgICAgIGlmIChSVEMubG9jYWxWaWRlbykge1xuICAgICAgICAgICAgaGFuZGxlci5wZWVyY29ubmVjdGlvbi5yZW1vdmVTdHJlYW0oXG4gICAgICAgICAgICAgICAgUlRDLmxvY2FsVmlkZW8uZ2V0T3JpZ2luYWxTdHJlYW0oKSwgdHJ1ZSk7XG4gICAgICAgIH1cbiAgICAgICAgaGFuZGxlci5wZWVyY29ubmVjdGlvbi5jbG9zZSgpO1xuICAgIH1cbiAgICB0aGlzLmV2ZW50RW1pdHRlci5lbWl0KFhNUFBFdmVudHMuRElTUE9TRV9DT05GRVJFTkNFKTtcbiAgICB0aGlzLmNvbm5lY3Rpb24uZW11Yy5kb0xlYXZlKGppZCk7XG59O1xuXG4vKipcbiAqIFNlbmRzICdkYXRhJyBhcyBhIGxvZyBtZXNzYWdlIHRvIHRoZSBmb2N1cy4gUmV0dXJucyB0cnVlIGlmZiBhIG1lc3NhZ2VcbiAqIHdhcyBzZW50LlxuICogQHBhcmFtIGRhdGFcbiAqIEByZXR1cm5zIHtib29sZWFufSB0cnVlIGlmZiBhIG1lc3NhZ2Ugd2FzIHNlbnQuXG4gKi9cblhNUFAucHJvdG90eXBlLnNlbmRMb2dzID0gZnVuY3Rpb24gKGRhdGEpIHtcbiAgICBpZighdGhpcy5jb25uZWN0aW9uLmVtdWMuZm9jdXNNdWNKaWQpXG4gICAgICAgIHJldHVybiBmYWxzZTtcblxuICAgIHZhciBkZWZsYXRlID0gdHJ1ZTtcblxuICAgIHZhciBjb250ZW50ID0gSlNPTi5zdHJpbmdpZnkoZGF0YSk7XG4gICAgaWYgKGRlZmxhdGUpIHtcbiAgICAgICAgY29udGVudCA9IFN0cmluZy5mcm9tQ2hhckNvZGUuYXBwbHkobnVsbCwgUGFrby5kZWZsYXRlUmF3KGNvbnRlbnQpKTtcbiAgICB9XG4gICAgY29udGVudCA9IEJhc2U2NC5lbmNvZGUoY29udGVudCk7XG4gICAgLy8gWEVQLTAzMzctaXNoXG4gICAgdmFyIG1lc3NhZ2UgPSAkbXNnKHt0bzogdGhpcy5jb25uZWN0aW9uLmVtdWMuZm9jdXNNdWNKaWQsIHR5cGU6ICdub3JtYWwnfSk7XG4gICAgbWVzc2FnZS5jKCdsb2cnLCB7IHhtbG5zOiAndXJuOnhtcHA6ZXZlbnRsb2cnLFxuICAgICAgICBpZDogJ1BlZXJDb25uZWN0aW9uU3RhdHMnfSk7XG4gICAgbWVzc2FnZS5jKCdtZXNzYWdlJykudChjb250ZW50KS51cCgpO1xuICAgIGlmIChkZWZsYXRlKSB7XG4gICAgICAgIG1lc3NhZ2UuYygndGFnJywge25hbWU6IFwiZGVmbGF0ZWRcIiwgdmFsdWU6IFwidHJ1ZVwifSkudXAoKTtcbiAgICB9XG4gICAgbWVzc2FnZS51cCgpO1xuXG4gICAgdGhpcy5jb25uZWN0aW9uLnNlbmQobWVzc2FnZSk7XG4gICAgcmV0dXJuIHRydWU7XG59O1xuXG4vLyBHZXRzIHRoZSBsb2dzIGZyb20gc3Ryb3BoZS5qaW5nbGUuXG5YTVBQLnByb3RvdHlwZS5nZXRKaW5nbGVMb2cgPSBmdW5jdGlvbiAoKSB7XG4gICAgcmV0dXJuIHRoaXMuY29ubmVjdGlvbi5qaW5nbGUgPyB0aGlzLmNvbm5lY3Rpb24uamluZ2xlLmdldExvZygpIDoge307XG59O1xuXG4vLyBHZXRzIHRoZSBsb2dzIGZyb20gc3Ryb3BoZS5cblhNUFAucHJvdG90eXBlLmdldFhtcHBMb2cgPSBmdW5jdGlvbiAoKSB7XG4gICAgcmV0dXJuIHRoaXMuY29ubmVjdGlvbi5sb2dnZXIgPyB0aGlzLmNvbm5lY3Rpb24ubG9nZ2VyLmxvZyA6IG51bGw7XG59O1xuXG5cblhNUFAucHJvdG90eXBlLmRpYWwgPSBmdW5jdGlvbiAodG8sIGZyb20sIHJvb21OYW1lLHJvb21QYXNzKSB7XG4gICAgdGhpcy5jb25uZWN0aW9uLnJheW8uZGlhbCh0bywgZnJvbSwgcm9vbU5hbWUscm9vbVBhc3MpO1xufTtcblxuWE1QUC5wcm90b3R5cGUuc2V0TXV0ZSA9IGZ1bmN0aW9uIChqaWQsIG11dGUpIHtcbiAgICB0aGlzLmNvbm5lY3Rpb24ubW9kZXJhdGUuc2V0TXV0ZShqaWQsIG11dGUpO1xufTtcblxuWE1QUC5wcm90b3R5cGUuZWplY3QgPSBmdW5jdGlvbiAoamlkKSB7XG4gICAgdGhpcy5jb25uZWN0aW9uLm1vZGVyYXRlLmVqZWN0KGppZCk7XG59O1xuXG5YTVBQLnByb3RvdHlwZS5nZXRTZXNzaW9ucyA9IGZ1bmN0aW9uICgpIHtcbiAgICByZXR1cm4gdGhpcy5jb25uZWN0aW9uLmppbmdsZS5zZXNzaW9ucztcbn07XG5cblhNUFAucHJvdG90eXBlLmRpc2Nvbm5lY3QgPSBmdW5jdGlvbiAoKSB7XG4gICAgaWYgKHRoaXMuZGlzY29ubmVjdEluUHJvZ3Jlc3MgfHwgIXRoaXMuY29ubmVjdGlvbiB8fCAhdGhpcy5jb25uZWN0aW9uLmNvbm5lY3RlZClcbiAgICB7XG4gICAgICAgIHRoaXMuZXZlbnRFbWl0dGVyLmVtaXQoSml0c2lDb25uZWN0aW9uRXZlbnRzLldST05HX1NUQVRFKTtcbiAgICAgICAgcmV0dXJuO1xuICAgIH1cblxuICAgIHRoaXMuZGlzY29ubmVjdEluUHJvZ3Jlc3MgPSB0cnVlO1xuXG4gICAgdGhpcy5jb25uZWN0aW9uLmRpc2Nvbm5lY3QoKTtcbn07XG5cbi8qKlxuICogR2V0cyB0aGUgU1NSQyBvZiBsb2NhbCBtZWRpYSBzdHJlYW0uXG4gKiBAcGFyYW0gbWVkaWFUeXBlIHRoZSBtZWRpYSB0eXBlIHRoYXQgdGVsbHMgd2hldGhlciB3ZSB3YW50IHRvIGdldFxuICogICAgICAgIHRoZSBTU1JDIG9mIGxvY2FsIGF1ZGlvIG9yIHZpZGVvIHN0cmVhbS5cbiAqIEByZXR1cm5zIHsqfSB0aGUgU1NSQyBudW1iZXIgZm9yIGxvY2FsIG1lZGlhIHN0cmVhbSBvciA8dHQ+bnVsbDwvdHQ+IGlmXG4gKiAgICAgICAgICAgICAgbm90IGF2YWlsYWJsZS5cbiAqL1xuWE1QUC5wcm90b3R5cGUuZ2V0TG9jYWxTU1JDID0gZnVuY3Rpb24gKG1lZGlhVHlwZSkge1xuICAgIGlmICh0aGlzLmNvbm5lY3Rpb24uamluZ2xlLmFjdGl2ZWNhbGwgJiZcbiAgICAgICAgdGhpcy5jb25uZWN0aW9uLmppbmdsZS5hY3RpdmVjYWxsLnBlZXJjb25uZWN0aW9uKSB7XG4gICAgICAgIHJldHVybiB0aGlzLmNvbm5lY3Rpb24uamluZ2xlLmFjdGl2ZWNhbGwuZ2V0TG9jYWxTU1JDKG1lZGlhVHlwZSk7XG4gICAgfSBlbHNlIHtcbiAgICAgICAgcmV0dXJuIG51bGw7XG4gICAgfVxufTtcblxubW9kdWxlLmV4cG9ydHMgPSBYTVBQO1xuIiwiLyohXG4gKiBhc3luY1xuICogaHR0cHM6Ly9naXRodWIuY29tL2Nhb2xhbi9hc3luY1xuICpcbiAqIENvcHlyaWdodCAyMDEwLTIwMTQgQ2FvbGFuIE1jTWFob25cbiAqIFJlbGVhc2VkIHVuZGVyIHRoZSBNSVQgbGljZW5zZVxuICovXG4vKmpzaGludCBvbmV2YXI6IGZhbHNlLCBpbmRlbnQ6NCAqL1xuLypnbG9iYWwgc2V0SW1tZWRpYXRlOiBmYWxzZSwgc2V0VGltZW91dDogZmFsc2UsIGNvbnNvbGU6IGZhbHNlICovXG4oZnVuY3Rpb24gKCkge1xuXG4gICAgdmFyIGFzeW5jID0ge307XG5cbiAgICAvLyBnbG9iYWwgb24gdGhlIHNlcnZlciwgd2luZG93IGluIHRoZSBicm93c2VyXG4gICAgdmFyIHJvb3QsIHByZXZpb3VzX2FzeW5jO1xuXG4gICAgcm9vdCA9IHRoaXM7XG4gICAgaWYgKHJvb3QgIT0gbnVsbCkge1xuICAgICAgcHJldmlvdXNfYXN5bmMgPSByb290LmFzeW5jO1xuICAgIH1cblxuICAgIGFzeW5jLm5vQ29uZmxpY3QgPSBmdW5jdGlvbiAoKSB7XG4gICAgICAgIHJvb3QuYXN5bmMgPSBwcmV2aW91c19hc3luYztcbiAgICAgICAgcmV0dXJuIGFzeW5jO1xuICAgIH07XG5cbiAgICBmdW5jdGlvbiBvbmx5X29uY2UoZm4pIHtcbiAgICAgICAgdmFyIGNhbGxlZCA9IGZhbHNlO1xuICAgICAgICByZXR1cm4gZnVuY3Rpb24oKSB7XG4gICAgICAgICAgICBpZiAoY2FsbGVkKSB0aHJvdyBuZXcgRXJyb3IoXCJDYWxsYmFjayB3YXMgYWxyZWFkeSBjYWxsZWQuXCIpO1xuICAgICAgICAgICAgY2FsbGVkID0gdHJ1ZTtcbiAgICAgICAgICAgIGZuLmFwcGx5KHJvb3QsIGFyZ3VtZW50cyk7XG4gICAgICAgIH1cbiAgICB9XG5cbiAgICAvLy8vIGNyb3NzLWJyb3dzZXIgY29tcGF0aWJsaXR5IGZ1bmN0aW9ucyAvLy8vXG5cbiAgICB2YXIgX3RvU3RyaW5nID0gT2JqZWN0LnByb3RvdHlwZS50b1N0cmluZztcblxuICAgIHZhciBfaXNBcnJheSA9IEFycmF5LmlzQXJyYXkgfHwgZnVuY3Rpb24gKG9iaikge1xuICAgICAgICByZXR1cm4gX3RvU3RyaW5nLmNhbGwob2JqKSA9PT0gJ1tvYmplY3QgQXJyYXldJztcbiAgICB9O1xuXG4gICAgdmFyIF9lYWNoID0gZnVuY3Rpb24gKGFyciwgaXRlcmF0b3IpIHtcbiAgICAgICAgaWYgKGFyci5mb3JFYWNoKSB7XG4gICAgICAgICAgICByZXR1cm4gYXJyLmZvckVhY2goaXRlcmF0b3IpO1xuICAgICAgICB9XG4gICAgICAgIGZvciAodmFyIGkgPSAwOyBpIDwgYXJyLmxlbmd0aDsgaSArPSAxKSB7XG4gICAgICAgICAgICBpdGVyYXRvcihhcnJbaV0sIGksIGFycik7XG4gICAgICAgIH1cbiAgICB9O1xuXG4gICAgdmFyIF9tYXAgPSBmdW5jdGlvbiAoYXJyLCBpdGVyYXRvcikge1xuICAgICAgICBpZiAoYXJyLm1hcCkge1xuICAgICAgICAgICAgcmV0dXJuIGFyci5tYXAoaXRlcmF0b3IpO1xuICAgICAgICB9XG4gICAgICAgIHZhciByZXN1bHRzID0gW107XG4gICAgICAgIF9lYWNoKGFyciwgZnVuY3Rpb24gKHgsIGksIGEpIHtcbiAgICAgICAgICAgIHJlc3VsdHMucHVzaChpdGVyYXRvcih4LCBpLCBhKSk7XG4gICAgICAgIH0pO1xuICAgICAgICByZXR1cm4gcmVzdWx0cztcbiAgICB9O1xuXG4gICAgdmFyIF9yZWR1Y2UgPSBmdW5jdGlvbiAoYXJyLCBpdGVyYXRvciwgbWVtbykge1xuICAgICAgICBpZiAoYXJyLnJlZHVjZSkge1xuICAgICAgICAgICAgcmV0dXJuIGFyci5yZWR1Y2UoaXRlcmF0b3IsIG1lbW8pO1xuICAgICAgICB9XG4gICAgICAgIF9lYWNoKGFyciwgZnVuY3Rpb24gKHgsIGksIGEpIHtcbiAgICAgICAgICAgIG1lbW8gPSBpdGVyYXRvcihtZW1vLCB4LCBpLCBhKTtcbiAgICAgICAgfSk7XG4gICAgICAgIHJldHVybiBtZW1vO1xuICAgIH07XG5cbiAgICB2YXIgX2tleXMgPSBmdW5jdGlvbiAob2JqKSB7XG4gICAgICAgIGlmIChPYmplY3Qua2V5cykge1xuICAgICAgICAgICAgcmV0dXJuIE9iamVjdC5rZXlzKG9iaik7XG4gICAgICAgIH1cbiAgICAgICAgdmFyIGtleXMgPSBbXTtcbiAgICAgICAgZm9yICh2YXIgayBpbiBvYmopIHtcbiAgICAgICAgICAgIGlmIChvYmouaGFzT3duUHJvcGVydHkoaykpIHtcbiAgICAgICAgICAgICAgICBrZXlzLnB1c2goayk7XG4gICAgICAgICAgICB9XG4gICAgICAgIH1cbiAgICAgICAgcmV0dXJuIGtleXM7XG4gICAgfTtcblxuICAgIC8vLy8gZXhwb3J0ZWQgYXN5bmMgbW9kdWxlIGZ1bmN0aW9ucyAvLy8vXG5cbiAgICAvLy8vIG5leHRUaWNrIGltcGxlbWVudGF0aW9uIHdpdGggYnJvd3Nlci1jb21wYXRpYmxlIGZhbGxiYWNrIC8vLy9cbiAgICBpZiAodHlwZW9mIHByb2Nlc3MgPT09ICd1bmRlZmluZWQnIHx8ICEocHJvY2Vzcy5uZXh0VGljaykpIHtcbiAgICAgICAgaWYgKHR5cGVvZiBzZXRJbW1lZGlhdGUgPT09ICdmdW5jdGlvbicpIHtcbiAgICAgICAgICAgIGFzeW5jLm5leHRUaWNrID0gZnVuY3Rpb24gKGZuKSB7XG4gICAgICAgICAgICAgICAgLy8gbm90IGEgZGlyZWN0IGFsaWFzIGZvciBJRTEwIGNvbXBhdGliaWxpdHlcbiAgICAgICAgICAgICAgICBzZXRJbW1lZGlhdGUoZm4pO1xuICAgICAgICAgICAgfTtcbiAgICAgICAgICAgIGFzeW5jLnNldEltbWVkaWF0ZSA9IGFzeW5jLm5leHRUaWNrO1xuICAgICAgICB9XG4gICAgICAgIGVsc2Uge1xuICAgICAgICAgICAgYXN5bmMubmV4dFRpY2sgPSBmdW5jdGlvbiAoZm4pIHtcbiAgICAgICAgICAgICAgICBzZXRUaW1lb3V0KGZuLCAwKTtcbiAgICAgICAgICAgIH07XG4gICAgICAgICAgICBhc3luYy5zZXRJbW1lZGlhdGUgPSBhc3luYy5uZXh0VGljaztcbiAgICAgICAgfVxuICAgIH1cbiAgICBlbHNlIHtcbiAgICAgICAgYXN5bmMubmV4dFRpY2sgPSBwcm9jZXNzLm5leHRUaWNrO1xuICAgICAgICBpZiAodHlwZW9mIHNldEltbWVkaWF0ZSAhPT0gJ3VuZGVmaW5lZCcpIHtcbiAgICAgICAgICAgIGFzeW5jLnNldEltbWVkaWF0ZSA9IGZ1bmN0aW9uIChmbikge1xuICAgICAgICAgICAgICAvLyBub3QgYSBkaXJlY3QgYWxpYXMgZm9yIElFMTAgY29tcGF0aWJpbGl0eVxuICAgICAgICAgICAgICBzZXRJbW1lZGlhdGUoZm4pO1xuICAgICAgICAgICAgfTtcbiAgICAgICAgfVxuICAgICAgICBlbHNlIHtcbiAgICAgICAgICAgIGFzeW5jLnNldEltbWVkaWF0ZSA9IGFzeW5jLm5leHRUaWNrO1xuICAgICAgICB9XG4gICAgfVxuXG4gICAgYXN5bmMuZWFjaCA9IGZ1bmN0aW9uIChhcnIsIGl0ZXJhdG9yLCBjYWxsYmFjaykge1xuICAgICAgICBjYWxsYmFjayA9IGNhbGxiYWNrIHx8IGZ1bmN0aW9uICgpIHt9O1xuICAgICAgICBpZiAoIWFyci5sZW5ndGgpIHtcbiAgICAgICAgICAgIHJldHVybiBjYWxsYmFjaygpO1xuICAgICAgICB9XG4gICAgICAgIHZhciBjb21wbGV0ZWQgPSAwO1xuICAgICAgICBfZWFjaChhcnIsIGZ1bmN0aW9uICh4KSB7XG4gICAgICAgICAgICBpdGVyYXRvcih4LCBvbmx5X29uY2UoZG9uZSkgKTtcbiAgICAgICAgfSk7XG4gICAgICAgIGZ1bmN0aW9uIGRvbmUoZXJyKSB7XG4gICAgICAgICAgaWYgKGVycikge1xuICAgICAgICAgICAgICBjYWxsYmFjayhlcnIpO1xuICAgICAgICAgICAgICBjYWxsYmFjayA9IGZ1bmN0aW9uICgpIHt9O1xuICAgICAgICAgIH1cbiAgICAgICAgICBlbHNlIHtcbiAgICAgICAgICAgICAgY29tcGxldGVkICs9IDE7XG4gICAgICAgICAgICAgIGlmIChjb21wbGV0ZWQgPj0gYXJyLmxlbmd0aCkge1xuICAgICAgICAgICAgICAgICAgY2FsbGJhY2soKTtcbiAgICAgICAgICAgICAgfVxuICAgICAgICAgIH1cbiAgICAgICAgfVxuICAgIH07XG4gICAgYXN5bmMuZm9yRWFjaCA9IGFzeW5jLmVhY2g7XG5cbiAgICBhc3luYy5lYWNoU2VyaWVzID0gZnVuY3Rpb24gKGFyciwgaXRlcmF0b3IsIGNhbGxiYWNrKSB7XG4gICAgICAgIGNhbGxiYWNrID0gY2FsbGJhY2sgfHwgZnVuY3Rpb24gKCkge307XG4gICAgICAgIGlmICghYXJyLmxlbmd0aCkge1xuICAgICAgICAgICAgcmV0dXJuIGNhbGxiYWNrKCk7XG4gICAgICAgIH1cbiAgICAgICAgdmFyIGNvbXBsZXRlZCA9IDA7XG4gICAgICAgIHZhciBpdGVyYXRlID0gZnVuY3Rpb24gKCkge1xuICAgICAgICAgICAgaXRlcmF0b3IoYXJyW2NvbXBsZXRlZF0sIGZ1bmN0aW9uIChlcnIpIHtcbiAgICAgICAgICAgICAgICBpZiAoZXJyKSB7XG4gICAgICAgICAgICAgICAgICAgIGNhbGxiYWNrKGVycik7XG4gICAgICAgICAgICAgICAgICAgIGNhbGxiYWNrID0gZnVuY3Rpb24gKCkge307XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgIGVsc2Uge1xuICAgICAgICAgICAgICAgICAgICBjb21wbGV0ZWQgKz0gMTtcbiAgICAgICAgICAgICAgICAgICAgaWYgKGNvbXBsZXRlZCA+PSBhcnIubGVuZ3RoKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICBjYWxsYmFjaygpO1xuICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgICAgIGVsc2Uge1xuICAgICAgICAgICAgICAgICAgICAgICAgaXRlcmF0ZSgpO1xuICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgfSk7XG4gICAgICAgIH07XG4gICAgICAgIGl0ZXJhdGUoKTtcbiAgICB9O1xuICAgIGFzeW5jLmZvckVhY2hTZXJpZXMgPSBhc3luYy5lYWNoU2VyaWVzO1xuXG4gICAgYXN5bmMuZWFjaExpbWl0ID0gZnVuY3Rpb24gKGFyciwgbGltaXQsIGl0ZXJhdG9yLCBjYWxsYmFjaykge1xuICAgICAgICB2YXIgZm4gPSBfZWFjaExpbWl0KGxpbWl0KTtcbiAgICAgICAgZm4uYXBwbHkobnVsbCwgW2FyciwgaXRlcmF0b3IsIGNhbGxiYWNrXSk7XG4gICAgfTtcbiAgICBhc3luYy5mb3JFYWNoTGltaXQgPSBhc3luYy5lYWNoTGltaXQ7XG5cbiAgICB2YXIgX2VhY2hMaW1pdCA9IGZ1bmN0aW9uIChsaW1pdCkge1xuXG4gICAgICAgIHJldHVybiBmdW5jdGlvbiAoYXJyLCBpdGVyYXRvciwgY2FsbGJhY2spIHtcbiAgICAgICAgICAgIGNhbGxiYWNrID0gY2FsbGJhY2sgfHwgZnVuY3Rpb24gKCkge307XG4gICAgICAgICAgICBpZiAoIWFyci5sZW5ndGggfHwgbGltaXQgPD0gMCkge1xuICAgICAgICAgICAgICAgIHJldHVybiBjYWxsYmFjaygpO1xuICAgICAgICAgICAgfVxuICAgICAgICAgICAgdmFyIGNvbXBsZXRlZCA9IDA7XG4gICAgICAgICAgICB2YXIgc3RhcnRlZCA9IDA7XG4gICAgICAgICAgICB2YXIgcnVubmluZyA9IDA7XG5cbiAgICAgICAgICAgIChmdW5jdGlvbiByZXBsZW5pc2ggKCkge1xuICAgICAgICAgICAgICAgIGlmIChjb21wbGV0ZWQgPj0gYXJyLmxlbmd0aCkge1xuICAgICAgICAgICAgICAgICAgICByZXR1cm4gY2FsbGJhY2soKTtcbiAgICAgICAgICAgICAgICB9XG5cbiAgICAgICAgICAgICAgICB3aGlsZSAocnVubmluZyA8IGxpbWl0ICYmIHN0YXJ0ZWQgPCBhcnIubGVuZ3RoKSB7XG4gICAgICAgICAgICAgICAgICAgIHN0YXJ0ZWQgKz0gMTtcbiAgICAgICAgICAgICAgICAgICAgcnVubmluZyArPSAxO1xuICAgICAgICAgICAgICAgICAgICBpdGVyYXRvcihhcnJbc3RhcnRlZCAtIDFdLCBmdW5jdGlvbiAoZXJyKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICBpZiAoZXJyKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgY2FsbGJhY2soZXJyKTtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICBjYWxsYmFjayA9IGZ1bmN0aW9uICgpIHt9O1xuICAgICAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgICAgICAgICAgZWxzZSB7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgY29tcGxldGVkICs9IDE7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgcnVubmluZyAtPSAxO1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgIGlmIChjb21wbGV0ZWQgPj0gYXJyLmxlbmd0aCkge1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBjYWxsYmFjaygpO1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICAgICAgICAgICAgICBlbHNlIHtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgcmVwbGVuaXNoKCk7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgICAgICB9KTtcbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICB9KSgpO1xuICAgICAgICB9O1xuICAgIH07XG5cblxuICAgIHZhciBkb1BhcmFsbGVsID0gZnVuY3Rpb24gKGZuKSB7XG4gICAgICAgIHJldHVybiBmdW5jdGlvbiAoKSB7XG4gICAgICAgICAgICB2YXIgYXJncyA9IEFycmF5LnByb3RvdHlwZS5zbGljZS5jYWxsKGFyZ3VtZW50cyk7XG4gICAgICAgICAgICByZXR1cm4gZm4uYXBwbHkobnVsbCwgW2FzeW5jLmVhY2hdLmNvbmNhdChhcmdzKSk7XG4gICAgICAgIH07XG4gICAgfTtcbiAgICB2YXIgZG9QYXJhbGxlbExpbWl0ID0gZnVuY3Rpb24obGltaXQsIGZuKSB7XG4gICAgICAgIHJldHVybiBmdW5jdGlvbiAoKSB7XG4gICAgICAgICAgICB2YXIgYXJncyA9IEFycmF5LnByb3RvdHlwZS5zbGljZS5jYWxsKGFyZ3VtZW50cyk7XG4gICAgICAgICAgICByZXR1cm4gZm4uYXBwbHkobnVsbCwgW19lYWNoTGltaXQobGltaXQpXS5jb25jYXQoYXJncykpO1xuICAgICAgICB9O1xuICAgIH07XG4gICAgdmFyIGRvU2VyaWVzID0gZnVuY3Rpb24gKGZuKSB7XG4gICAgICAgIHJldHVybiBmdW5jdGlvbiAoKSB7XG4gICAgICAgICAgICB2YXIgYXJncyA9IEFycmF5LnByb3RvdHlwZS5zbGljZS5jYWxsKGFyZ3VtZW50cyk7XG4gICAgICAgICAgICByZXR1cm4gZm4uYXBwbHkobnVsbCwgW2FzeW5jLmVhY2hTZXJpZXNdLmNvbmNhdChhcmdzKSk7XG4gICAgICAgIH07XG4gICAgfTtcblxuXG4gICAgdmFyIF9hc3luY01hcCA9IGZ1bmN0aW9uIChlYWNoZm4sIGFyciwgaXRlcmF0b3IsIGNhbGxiYWNrKSB7XG4gICAgICAgIGFyciA9IF9tYXAoYXJyLCBmdW5jdGlvbiAoeCwgaSkge1xuICAgICAgICAgICAgcmV0dXJuIHtpbmRleDogaSwgdmFsdWU6IHh9O1xuICAgICAgICB9KTtcbiAgICAgICAgaWYgKCFjYWxsYmFjaykge1xuICAgICAgICAgICAgZWFjaGZuKGFyciwgZnVuY3Rpb24gKHgsIGNhbGxiYWNrKSB7XG4gICAgICAgICAgICAgICAgaXRlcmF0b3IoeC52YWx1ZSwgZnVuY3Rpb24gKGVycikge1xuICAgICAgICAgICAgICAgICAgICBjYWxsYmFjayhlcnIpO1xuICAgICAgICAgICAgICAgIH0pO1xuICAgICAgICAgICAgfSk7XG4gICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICB2YXIgcmVzdWx0cyA9IFtdO1xuICAgICAgICAgICAgZWFjaGZuKGFyciwgZnVuY3Rpb24gKHgsIGNhbGxiYWNrKSB7XG4gICAgICAgICAgICAgICAgaXRlcmF0b3IoeC52YWx1ZSwgZnVuY3Rpb24gKGVyciwgdikge1xuICAgICAgICAgICAgICAgICAgICByZXN1bHRzW3guaW5kZXhdID0gdjtcbiAgICAgICAgICAgICAgICAgICAgY2FsbGJhY2soZXJyKTtcbiAgICAgICAgICAgICAgICB9KTtcbiAgICAgICAgICAgIH0sIGZ1bmN0aW9uIChlcnIpIHtcbiAgICAgICAgICAgICAgICBjYWxsYmFjayhlcnIsIHJlc3VsdHMpO1xuICAgICAgICAgICAgfSk7XG4gICAgICAgIH1cbiAgICB9O1xuICAgIGFzeW5jLm1hcCA9IGRvUGFyYWxsZWwoX2FzeW5jTWFwKTtcbiAgICBhc3luYy5tYXBTZXJpZXMgPSBkb1NlcmllcyhfYXN5bmNNYXApO1xuICAgIGFzeW5jLm1hcExpbWl0ID0gZnVuY3Rpb24gKGFyciwgbGltaXQsIGl0ZXJhdG9yLCBjYWxsYmFjaykge1xuICAgICAgICByZXR1cm4gX21hcExpbWl0KGxpbWl0KShhcnIsIGl0ZXJhdG9yLCBjYWxsYmFjayk7XG4gICAgfTtcblxuICAgIHZhciBfbWFwTGltaXQgPSBmdW5jdGlvbihsaW1pdCkge1xuICAgICAgICByZXR1cm4gZG9QYXJhbGxlbExpbWl0KGxpbWl0LCBfYXN5bmNNYXApO1xuICAgIH07XG5cbiAgICAvLyByZWR1Y2Ugb25seSBoYXMgYSBzZXJpZXMgdmVyc2lvbiwgYXMgZG9pbmcgcmVkdWNlIGluIHBhcmFsbGVsIHdvbid0XG4gICAgLy8gd29yayBpbiBtYW55IHNpdHVhdGlvbnMuXG4gICAgYXN5bmMucmVkdWNlID0gZnVuY3Rpb24gKGFyciwgbWVtbywgaXRlcmF0b3IsIGNhbGxiYWNrKSB7XG4gICAgICAgIGFzeW5jLmVhY2hTZXJpZXMoYXJyLCBmdW5jdGlvbiAoeCwgY2FsbGJhY2spIHtcbiAgICAgICAgICAgIGl0ZXJhdG9yKG1lbW8sIHgsIGZ1bmN0aW9uIChlcnIsIHYpIHtcbiAgICAgICAgICAgICAgICBtZW1vID0gdjtcbiAgICAgICAgICAgICAgICBjYWxsYmFjayhlcnIpO1xuICAgICAgICAgICAgfSk7XG4gICAgICAgIH0sIGZ1bmN0aW9uIChlcnIpIHtcbiAgICAgICAgICAgIGNhbGxiYWNrKGVyciwgbWVtbyk7XG4gICAgICAgIH0pO1xuICAgIH07XG4gICAgLy8gaW5qZWN0IGFsaWFzXG4gICAgYXN5bmMuaW5qZWN0ID0gYXN5bmMucmVkdWNlO1xuICAgIC8vIGZvbGRsIGFsaWFzXG4gICAgYXN5bmMuZm9sZGwgPSBhc3luYy5yZWR1Y2U7XG5cbiAgICBhc3luYy5yZWR1Y2VSaWdodCA9IGZ1bmN0aW9uIChhcnIsIG1lbW8sIGl0ZXJhdG9yLCBjYWxsYmFjaykge1xuICAgICAgICB2YXIgcmV2ZXJzZWQgPSBfbWFwKGFyciwgZnVuY3Rpb24gKHgpIHtcbiAgICAgICAgICAgIHJldHVybiB4O1xuICAgICAgICB9KS5yZXZlcnNlKCk7XG4gICAgICAgIGFzeW5jLnJlZHVjZShyZXZlcnNlZCwgbWVtbywgaXRlcmF0b3IsIGNhbGxiYWNrKTtcbiAgICB9O1xuICAgIC8vIGZvbGRyIGFsaWFzXG4gICAgYXN5bmMuZm9sZHIgPSBhc3luYy5yZWR1Y2VSaWdodDtcblxuICAgIHZhciBfZmlsdGVyID0gZnVuY3Rpb24gKGVhY2hmbiwgYXJyLCBpdGVyYXRvciwgY2FsbGJhY2spIHtcbiAgICAgICAgdmFyIHJlc3VsdHMgPSBbXTtcbiAgICAgICAgYXJyID0gX21hcChhcnIsIGZ1bmN0aW9uICh4LCBpKSB7XG4gICAgICAgICAgICByZXR1cm4ge2luZGV4OiBpLCB2YWx1ZTogeH07XG4gICAgICAgIH0pO1xuICAgICAgICBlYWNoZm4oYXJyLCBmdW5jdGlvbiAoeCwgY2FsbGJhY2spIHtcbiAgICAgICAgICAgIGl0ZXJhdG9yKHgudmFsdWUsIGZ1bmN0aW9uICh2KSB7XG4gICAgICAgICAgICAgICAgaWYgKHYpIHtcbiAgICAgICAgICAgICAgICAgICAgcmVzdWx0cy5wdXNoKHgpO1xuICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICBjYWxsYmFjaygpO1xuICAgICAgICAgICAgfSk7XG4gICAgICAgIH0sIGZ1bmN0aW9uIChlcnIpIHtcbiAgICAgICAgICAgIGNhbGxiYWNrKF9tYXAocmVzdWx0cy5zb3J0KGZ1bmN0aW9uIChhLCBiKSB7XG4gICAgICAgICAgICAgICAgcmV0dXJuIGEuaW5kZXggLSBiLmluZGV4O1xuICAgICAgICAgICAgfSksIGZ1bmN0aW9uICh4KSB7XG4gICAgICAgICAgICAgICAgcmV0dXJuIHgudmFsdWU7XG4gICAgICAgICAgICB9KSk7XG4gICAgICAgIH0pO1xuICAgIH07XG4gICAgYXN5bmMuZmlsdGVyID0gZG9QYXJhbGxlbChfZmlsdGVyKTtcbiAgICBhc3luYy5maWx0ZXJTZXJpZXMgPSBkb1NlcmllcyhfZmlsdGVyKTtcbiAgICAvLyBzZWxlY3QgYWxpYXNcbiAgICBhc3luYy5zZWxlY3QgPSBhc3luYy5maWx0ZXI7XG4gICAgYXN5bmMuc2VsZWN0U2VyaWVzID0gYXN5bmMuZmlsdGVyU2VyaWVzO1xuXG4gICAgdmFyIF9yZWplY3QgPSBmdW5jdGlvbiAoZWFjaGZuLCBhcnIsIGl0ZXJhdG9yLCBjYWxsYmFjaykge1xuICAgICAgICB2YXIgcmVzdWx0cyA9IFtdO1xuICAgICAgICBhcnIgPSBfbWFwKGFyciwgZnVuY3Rpb24gKHgsIGkpIHtcbiAgICAgICAgICAgIHJldHVybiB7aW5kZXg6IGksIHZhbHVlOiB4fTtcbiAgICAgICAgfSk7XG4gICAgICAgIGVhY2hmbihhcnIsIGZ1bmN0aW9uICh4LCBjYWxsYmFjaykge1xuICAgICAgICAgICAgaXRlcmF0b3IoeC52YWx1ZSwgZnVuY3Rpb24gKHYpIHtcbiAgICAgICAgICAgICAgICBpZiAoIXYpIHtcbiAgICAgICAgICAgICAgICAgICAgcmVzdWx0cy5wdXNoKHgpO1xuICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICBjYWxsYmFjaygpO1xuICAgICAgICAgICAgfSk7XG4gICAgICAgIH0sIGZ1bmN0aW9uIChlcnIpIHtcbiAgICAgICAgICAgIGNhbGxiYWNrKF9tYXAocmVzdWx0cy5zb3J0KGZ1bmN0aW9uIChhLCBiKSB7XG4gICAgICAgICAgICAgICAgcmV0dXJuIGEuaW5kZXggLSBiLmluZGV4O1xuICAgICAgICAgICAgfSksIGZ1bmN0aW9uICh4KSB7XG4gICAgICAgICAgICAgICAgcmV0dXJuIHgudmFsdWU7XG4gICAgICAgICAgICB9KSk7XG4gICAgICAgIH0pO1xuICAgIH07XG4gICAgYXN5bmMucmVqZWN0ID0gZG9QYXJhbGxlbChfcmVqZWN0KTtcbiAgICBhc3luYy5yZWplY3RTZXJpZXMgPSBkb1NlcmllcyhfcmVqZWN0KTtcblxuICAgIHZhciBfZGV0ZWN0ID0gZnVuY3Rpb24gKGVhY2hmbiwgYXJyLCBpdGVyYXRvciwgbWFpbl9jYWxsYmFjaykge1xuICAgICAgICBlYWNoZm4oYXJyLCBmdW5jdGlvbiAoeCwgY2FsbGJhY2spIHtcbiAgICAgICAgICAgIGl0ZXJhdG9yKHgsIGZ1bmN0aW9uIChyZXN1bHQpIHtcbiAgICAgICAgICAgICAgICBpZiAocmVzdWx0KSB7XG4gICAgICAgICAgICAgICAgICAgIG1haW5fY2FsbGJhY2soeCk7XG4gICAgICAgICAgICAgICAgICAgIG1haW5fY2FsbGJhY2sgPSBmdW5jdGlvbiAoKSB7fTtcbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgZWxzZSB7XG4gICAgICAgICAgICAgICAgICAgIGNhbGxiYWNrKCk7XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgfSk7XG4gICAgICAgIH0sIGZ1bmN0aW9uIChlcnIpIHtcbiAgICAgICAgICAgIG1haW5fY2FsbGJhY2soKTtcbiAgICAgICAgfSk7XG4gICAgfTtcbiAgICBhc3luYy5kZXRlY3QgPSBkb1BhcmFsbGVsKF9kZXRlY3QpO1xuICAgIGFzeW5jLmRldGVjdFNlcmllcyA9IGRvU2VyaWVzKF9kZXRlY3QpO1xuXG4gICAgYXN5bmMuc29tZSA9IGZ1bmN0aW9uIChhcnIsIGl0ZXJhdG9yLCBtYWluX2NhbGxiYWNrKSB7XG4gICAgICAgIGFzeW5jLmVhY2goYXJyLCBmdW5jdGlvbiAoeCwgY2FsbGJhY2spIHtcbiAgICAgICAgICAgIGl0ZXJhdG9yKHgsIGZ1bmN0aW9uICh2KSB7XG4gICAgICAgICAgICAgICAgaWYgKHYpIHtcbiAgICAgICAgICAgICAgICAgICAgbWFpbl9jYWxsYmFjayh0cnVlKTtcbiAgICAgICAgICAgICAgICAgICAgbWFpbl9jYWxsYmFjayA9IGZ1bmN0aW9uICgpIHt9O1xuICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICBjYWxsYmFjaygpO1xuICAgICAgICAgICAgfSk7XG4gICAgICAgIH0sIGZ1bmN0aW9uIChlcnIpIHtcbiAgICAgICAgICAgIG1haW5fY2FsbGJhY2soZmFsc2UpO1xuICAgICAgICB9KTtcbiAgICB9O1xuICAgIC8vIGFueSBhbGlhc1xuICAgIGFzeW5jLmFueSA9IGFzeW5jLnNvbWU7XG5cbiAgICBhc3luYy5ldmVyeSA9IGZ1bmN0aW9uIChhcnIsIGl0ZXJhdG9yLCBtYWluX2NhbGxiYWNrKSB7XG4gICAgICAgIGFzeW5jLmVhY2goYXJyLCBmdW5jdGlvbiAoeCwgY2FsbGJhY2spIHtcbiAgICAgICAgICAgIGl0ZXJhdG9yKHgsIGZ1bmN0aW9uICh2KSB7XG4gICAgICAgICAgICAgICAgaWYgKCF2KSB7XG4gICAgICAgICAgICAgICAgICAgIG1haW5fY2FsbGJhY2soZmFsc2UpO1xuICAgICAgICAgICAgICAgICAgICBtYWluX2NhbGxiYWNrID0gZnVuY3Rpb24gKCkge307XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgIGNhbGxiYWNrKCk7XG4gICAgICAgICAgICB9KTtcbiAgICAgICAgfSwgZnVuY3Rpb24gKGVycikge1xuICAgICAgICAgICAgbWFpbl9jYWxsYmFjayh0cnVlKTtcbiAgICAgICAgfSk7XG4gICAgfTtcbiAgICAvLyBhbGwgYWxpYXNcbiAgICBhc3luYy5hbGwgPSBhc3luYy5ldmVyeTtcblxuICAgIGFzeW5jLnNvcnRCeSA9IGZ1bmN0aW9uIChhcnIsIGl0ZXJhdG9yLCBjYWxsYmFjaykge1xuICAgICAgICBhc3luYy5tYXAoYXJyLCBmdW5jdGlvbiAoeCwgY2FsbGJhY2spIHtcbiAgICAgICAgICAgIGl0ZXJhdG9yKHgsIGZ1bmN0aW9uIChlcnIsIGNyaXRlcmlhKSB7XG4gICAgICAgICAgICAgICAgaWYgKGVycikge1xuICAgICAgICAgICAgICAgICAgICBjYWxsYmFjayhlcnIpO1xuICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICBlbHNlIHtcbiAgICAgICAgICAgICAgICAgICAgY2FsbGJhY2sobnVsbCwge3ZhbHVlOiB4LCBjcml0ZXJpYTogY3JpdGVyaWF9KTtcbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICB9KTtcbiAgICAgICAgfSwgZnVuY3Rpb24gKGVyciwgcmVzdWx0cykge1xuICAgICAgICAgICAgaWYgKGVycikge1xuICAgICAgICAgICAgICAgIHJldHVybiBjYWxsYmFjayhlcnIpO1xuICAgICAgICAgICAgfVxuICAgICAgICAgICAgZWxzZSB7XG4gICAgICAgICAgICAgICAgdmFyIGZuID0gZnVuY3Rpb24gKGxlZnQsIHJpZ2h0KSB7XG4gICAgICAgICAgICAgICAgICAgIHZhciBhID0gbGVmdC5jcml0ZXJpYSwgYiA9IHJpZ2h0LmNyaXRlcmlhO1xuICAgICAgICAgICAgICAgICAgICByZXR1cm4gYSA8IGIgPyAtMSA6IGEgPiBiID8gMSA6IDA7XG4gICAgICAgICAgICAgICAgfTtcbiAgICAgICAgICAgICAgICBjYWxsYmFjayhudWxsLCBfbWFwKHJlc3VsdHMuc29ydChmbiksIGZ1bmN0aW9uICh4KSB7XG4gICAgICAgICAgICAgICAgICAgIHJldHVybiB4LnZhbHVlO1xuICAgICAgICAgICAgICAgIH0pKTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgfSk7XG4gICAgfTtcblxuICAgIGFzeW5jLmF1dG8gPSBmdW5jdGlvbiAodGFza3MsIGNhbGxiYWNrKSB7XG4gICAgICAgIGNhbGxiYWNrID0gY2FsbGJhY2sgfHwgZnVuY3Rpb24gKCkge307XG4gICAgICAgIHZhciBrZXlzID0gX2tleXModGFza3MpO1xuICAgICAgICB2YXIgcmVtYWluaW5nVGFza3MgPSBrZXlzLmxlbmd0aFxuICAgICAgICBpZiAoIXJlbWFpbmluZ1Rhc2tzKSB7XG4gICAgICAgICAgICByZXR1cm4gY2FsbGJhY2soKTtcbiAgICAgICAgfVxuXG4gICAgICAgIHZhciByZXN1bHRzID0ge307XG5cbiAgICAgICAgdmFyIGxpc3RlbmVycyA9IFtdO1xuICAgICAgICB2YXIgYWRkTGlzdGVuZXIgPSBmdW5jdGlvbiAoZm4pIHtcbiAgICAgICAgICAgIGxpc3RlbmVycy51bnNoaWZ0KGZuKTtcbiAgICAgICAgfTtcbiAgICAgICAgdmFyIHJlbW92ZUxpc3RlbmVyID0gZnVuY3Rpb24gKGZuKSB7XG4gICAgICAgICAgICBmb3IgKHZhciBpID0gMDsgaSA8IGxpc3RlbmVycy5sZW5ndGg7IGkgKz0gMSkge1xuICAgICAgICAgICAgICAgIGlmIChsaXN0ZW5lcnNbaV0gPT09IGZuKSB7XG4gICAgICAgICAgICAgICAgICAgIGxpc3RlbmVycy5zcGxpY2UoaSwgMSk7XG4gICAgICAgICAgICAgICAgICAgIHJldHVybjtcbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICB9XG4gICAgICAgIH07XG4gICAgICAgIHZhciB0YXNrQ29tcGxldGUgPSBmdW5jdGlvbiAoKSB7XG4gICAgICAgICAgICByZW1haW5pbmdUYXNrcy0tXG4gICAgICAgICAgICBfZWFjaChsaXN0ZW5lcnMuc2xpY2UoMCksIGZ1bmN0aW9uIChmbikge1xuICAgICAgICAgICAgICAgIGZuKCk7XG4gICAgICAgICAgICB9KTtcbiAgICAgICAgfTtcblxuICAgICAgICBhZGRMaXN0ZW5lcihmdW5jdGlvbiAoKSB7XG4gICAgICAgICAgICBpZiAoIXJlbWFpbmluZ1Rhc2tzKSB7XG4gICAgICAgICAgICAgICAgdmFyIHRoZUNhbGxiYWNrID0gY2FsbGJhY2s7XG4gICAgICAgICAgICAgICAgLy8gcHJldmVudCBmaW5hbCBjYWxsYmFjayBmcm9tIGNhbGxpbmcgaXRzZWxmIGlmIGl0IGVycm9yc1xuICAgICAgICAgICAgICAgIGNhbGxiYWNrID0gZnVuY3Rpb24gKCkge307XG5cbiAgICAgICAgICAgICAgICB0aGVDYWxsYmFjayhudWxsLCByZXN1bHRzKTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgfSk7XG5cbiAgICAgICAgX2VhY2goa2V5cywgZnVuY3Rpb24gKGspIHtcbiAgICAgICAgICAgIHZhciB0YXNrID0gX2lzQXJyYXkodGFza3Nba10pID8gdGFza3Nba106IFt0YXNrc1trXV07XG4gICAgICAgICAgICB2YXIgdGFza0NhbGxiYWNrID0gZnVuY3Rpb24gKGVycikge1xuICAgICAgICAgICAgICAgIHZhciBhcmdzID0gQXJyYXkucHJvdG90eXBlLnNsaWNlLmNhbGwoYXJndW1lbnRzLCAxKTtcbiAgICAgICAgICAgICAgICBpZiAoYXJncy5sZW5ndGggPD0gMSkge1xuICAgICAgICAgICAgICAgICAgICBhcmdzID0gYXJnc1swXTtcbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgaWYgKGVycikge1xuICAgICAgICAgICAgICAgICAgICB2YXIgc2FmZVJlc3VsdHMgPSB7fTtcbiAgICAgICAgICAgICAgICAgICAgX2VhY2goX2tleXMocmVzdWx0cyksIGZ1bmN0aW9uKHJrZXkpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgIHNhZmVSZXN1bHRzW3JrZXldID0gcmVzdWx0c1tya2V5XTtcbiAgICAgICAgICAgICAgICAgICAgfSk7XG4gICAgICAgICAgICAgICAgICAgIHNhZmVSZXN1bHRzW2tdID0gYXJncztcbiAgICAgICAgICAgICAgICAgICAgY2FsbGJhY2soZXJyLCBzYWZlUmVzdWx0cyk7XG4gICAgICAgICAgICAgICAgICAgIC8vIHN0b3Agc3Vic2VxdWVudCBlcnJvcnMgaGl0dGluZyBjYWxsYmFjayBtdWx0aXBsZSB0aW1lc1xuICAgICAgICAgICAgICAgICAgICBjYWxsYmFjayA9IGZ1bmN0aW9uICgpIHt9O1xuICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICBlbHNlIHtcbiAgICAgICAgICAgICAgICAgICAgcmVzdWx0c1trXSA9IGFyZ3M7XG4gICAgICAgICAgICAgICAgICAgIGFzeW5jLnNldEltbWVkaWF0ZSh0YXNrQ29tcGxldGUpO1xuICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgIH07XG4gICAgICAgICAgICB2YXIgcmVxdWlyZXMgPSB0YXNrLnNsaWNlKDAsIE1hdGguYWJzKHRhc2subGVuZ3RoIC0gMSkpIHx8IFtdO1xuICAgICAgICAgICAgdmFyIHJlYWR5ID0gZnVuY3Rpb24gKCkge1xuICAgICAgICAgICAgICAgIHJldHVybiBfcmVkdWNlKHJlcXVpcmVzLCBmdW5jdGlvbiAoYSwgeCkge1xuICAgICAgICAgICAgICAgICAgICByZXR1cm4gKGEgJiYgcmVzdWx0cy5oYXNPd25Qcm9wZXJ0eSh4KSk7XG4gICAgICAgICAgICAgICAgfSwgdHJ1ZSkgJiYgIXJlc3VsdHMuaGFzT3duUHJvcGVydHkoayk7XG4gICAgICAgICAgICB9O1xuICAgICAgICAgICAgaWYgKHJlYWR5KCkpIHtcbiAgICAgICAgICAgICAgICB0YXNrW3Rhc2subGVuZ3RoIC0gMV0odGFza0NhbGxiYWNrLCByZXN1bHRzKTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgICAgIGVsc2Uge1xuICAgICAgICAgICAgICAgIHZhciBsaXN0ZW5lciA9IGZ1bmN0aW9uICgpIHtcbiAgICAgICAgICAgICAgICAgICAgaWYgKHJlYWR5KCkpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgIHJlbW92ZUxpc3RlbmVyKGxpc3RlbmVyKTtcbiAgICAgICAgICAgICAgICAgICAgICAgIHRhc2tbdGFzay5sZW5ndGggLSAxXSh0YXNrQ2FsbGJhY2ssIHJlc3VsdHMpO1xuICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgfTtcbiAgICAgICAgICAgICAgICBhZGRMaXN0ZW5lcihsaXN0ZW5lcik7XG4gICAgICAgICAgICB9XG4gICAgICAgIH0pO1xuICAgIH07XG5cbiAgICBhc3luYy5yZXRyeSA9IGZ1bmN0aW9uKHRpbWVzLCB0YXNrLCBjYWxsYmFjaykge1xuICAgICAgICB2YXIgREVGQVVMVF9USU1FUyA9IDU7XG4gICAgICAgIHZhciBhdHRlbXB0cyA9IFtdO1xuICAgICAgICAvLyBVc2UgZGVmYXVsdHMgaWYgdGltZXMgbm90IHBhc3NlZFxuICAgICAgICBpZiAodHlwZW9mIHRpbWVzID09PSAnZnVuY3Rpb24nKSB7XG4gICAgICAgICAgICBjYWxsYmFjayA9IHRhc2s7XG4gICAgICAgICAgICB0YXNrID0gdGltZXM7XG4gICAgICAgICAgICB0aW1lcyA9IERFRkFVTFRfVElNRVM7XG4gICAgICAgIH1cbiAgICAgICAgLy8gTWFrZSBzdXJlIHRpbWVzIGlzIGEgbnVtYmVyXG4gICAgICAgIHRpbWVzID0gcGFyc2VJbnQodGltZXMsIDEwKSB8fCBERUZBVUxUX1RJTUVTO1xuICAgICAgICB2YXIgd3JhcHBlZFRhc2sgPSBmdW5jdGlvbih3cmFwcGVkQ2FsbGJhY2ssIHdyYXBwZWRSZXN1bHRzKSB7XG4gICAgICAgICAgICB2YXIgcmV0cnlBdHRlbXB0ID0gZnVuY3Rpb24odGFzaywgZmluYWxBdHRlbXB0KSB7XG4gICAgICAgICAgICAgICAgcmV0dXJuIGZ1bmN0aW9uKHNlcmllc0NhbGxiYWNrKSB7XG4gICAgICAgICAgICAgICAgICAgIHRhc2soZnVuY3Rpb24oZXJyLCByZXN1bHQpe1xuICAgICAgICAgICAgICAgICAgICAgICAgc2VyaWVzQ2FsbGJhY2soIWVyciB8fCBmaW5hbEF0dGVtcHQsIHtlcnI6IGVyciwgcmVzdWx0OiByZXN1bHR9KTtcbiAgICAgICAgICAgICAgICAgICAgfSwgd3JhcHBlZFJlc3VsdHMpO1xuICAgICAgICAgICAgICAgIH07XG4gICAgICAgICAgICB9O1xuICAgICAgICAgICAgd2hpbGUgKHRpbWVzKSB7XG4gICAgICAgICAgICAgICAgYXR0ZW1wdHMucHVzaChyZXRyeUF0dGVtcHQodGFzaywgISh0aW1lcy09MSkpKTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgICAgIGFzeW5jLnNlcmllcyhhdHRlbXB0cywgZnVuY3Rpb24oZG9uZSwgZGF0YSl7XG4gICAgICAgICAgICAgICAgZGF0YSA9IGRhdGFbZGF0YS5sZW5ndGggLSAxXTtcbiAgICAgICAgICAgICAgICAod3JhcHBlZENhbGxiYWNrIHx8IGNhbGxiYWNrKShkYXRhLmVyciwgZGF0YS5yZXN1bHQpO1xuICAgICAgICAgICAgfSk7XG4gICAgICAgIH1cbiAgICAgICAgLy8gSWYgYSBjYWxsYmFjayBpcyBwYXNzZWQsIHJ1biB0aGlzIGFzIGEgY29udHJvbGwgZmxvd1xuICAgICAgICByZXR1cm4gY2FsbGJhY2sgPyB3cmFwcGVkVGFzaygpIDogd3JhcHBlZFRhc2tcbiAgICB9O1xuXG4gICAgYXN5bmMud2F0ZXJmYWxsID0gZnVuY3Rpb24gKHRhc2tzLCBjYWxsYmFjaykge1xuICAgICAgICBjYWxsYmFjayA9IGNhbGxiYWNrIHx8IGZ1bmN0aW9uICgpIHt9O1xuICAgICAgICBpZiAoIV9pc0FycmF5KHRhc2tzKSkge1xuICAgICAgICAgIHZhciBlcnIgPSBuZXcgRXJyb3IoJ0ZpcnN0IGFyZ3VtZW50IHRvIHdhdGVyZmFsbCBtdXN0IGJlIGFuIGFycmF5IG9mIGZ1bmN0aW9ucycpO1xuICAgICAgICAgIHJldHVybiBjYWxsYmFjayhlcnIpO1xuICAgICAgICB9XG4gICAgICAgIGlmICghdGFza3MubGVuZ3RoKSB7XG4gICAgICAgICAgICByZXR1cm4gY2FsbGJhY2soKTtcbiAgICAgICAgfVxuICAgICAgICB2YXIgd3JhcEl0ZXJhdG9yID0gZnVuY3Rpb24gKGl0ZXJhdG9yKSB7XG4gICAgICAgICAgICByZXR1cm4gZnVuY3Rpb24gKGVycikge1xuICAgICAgICAgICAgICAgIGlmIChlcnIpIHtcbiAgICAgICAgICAgICAgICAgICAgY2FsbGJhY2suYXBwbHkobnVsbCwgYXJndW1lbnRzKTtcbiAgICAgICAgICAgICAgICAgICAgY2FsbGJhY2sgPSBmdW5jdGlvbiAoKSB7fTtcbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgZWxzZSB7XG4gICAgICAgICAgICAgICAgICAgIHZhciBhcmdzID0gQXJyYXkucHJvdG90eXBlLnNsaWNlLmNhbGwoYXJndW1lbnRzLCAxKTtcbiAgICAgICAgICAgICAgICAgICAgdmFyIG5leHQgPSBpdGVyYXRvci5uZXh0KCk7XG4gICAgICAgICAgICAgICAgICAgIGlmIChuZXh0KSB7XG4gICAgICAgICAgICAgICAgICAgICAgICBhcmdzLnB1c2god3JhcEl0ZXJhdG9yKG5leHQpKTtcbiAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgICAgICBlbHNlIHtcbiAgICAgICAgICAgICAgICAgICAgICAgIGFyZ3MucHVzaChjYWxsYmFjayk7XG4gICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICAgICAgYXN5bmMuc2V0SW1tZWRpYXRlKGZ1bmN0aW9uICgpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgIGl0ZXJhdG9yLmFwcGx5KG51bGwsIGFyZ3MpO1xuICAgICAgICAgICAgICAgICAgICB9KTtcbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICB9O1xuICAgICAgICB9O1xuICAgICAgICB3cmFwSXRlcmF0b3IoYXN5bmMuaXRlcmF0b3IodGFza3MpKSgpO1xuICAgIH07XG5cbiAgICB2YXIgX3BhcmFsbGVsID0gZnVuY3Rpb24oZWFjaGZuLCB0YXNrcywgY2FsbGJhY2spIHtcbiAgICAgICAgY2FsbGJhY2sgPSBjYWxsYmFjayB8fCBmdW5jdGlvbiAoKSB7fTtcbiAgICAgICAgaWYgKF9pc0FycmF5KHRhc2tzKSkge1xuICAgICAgICAgICAgZWFjaGZuLm1hcCh0YXNrcywgZnVuY3Rpb24gKGZuLCBjYWxsYmFjaykge1xuICAgICAgICAgICAgICAgIGlmIChmbikge1xuICAgICAgICAgICAgICAgICAgICBmbihmdW5jdGlvbiAoZXJyKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICB2YXIgYXJncyA9IEFycmF5LnByb3RvdHlwZS5zbGljZS5jYWxsKGFyZ3VtZW50cywgMSk7XG4gICAgICAgICAgICAgICAgICAgICAgICBpZiAoYXJncy5sZW5ndGggPD0gMSkge1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgIGFyZ3MgPSBhcmdzWzBdO1xuICAgICAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgICAgICAgICAgY2FsbGJhY2suY2FsbChudWxsLCBlcnIsIGFyZ3MpO1xuICAgICAgICAgICAgICAgICAgICB9KTtcbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICB9LCBjYWxsYmFjayk7XG4gICAgICAgIH1cbiAgICAgICAgZWxzZSB7XG4gICAgICAgICAgICB2YXIgcmVzdWx0cyA9IHt9O1xuICAgICAgICAgICAgZWFjaGZuLmVhY2goX2tleXModGFza3MpLCBmdW5jdGlvbiAoaywgY2FsbGJhY2spIHtcbiAgICAgICAgICAgICAgICB0YXNrc1trXShmdW5jdGlvbiAoZXJyKSB7XG4gICAgICAgICAgICAgICAgICAgIHZhciBhcmdzID0gQXJyYXkucHJvdG90eXBlLnNsaWNlLmNhbGwoYXJndW1lbnRzLCAxKTtcbiAgICAgICAgICAgICAgICAgICAgaWYgKGFyZ3MubGVuZ3RoIDw9IDEpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgIGFyZ3MgPSBhcmdzWzBdO1xuICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgICAgIHJlc3VsdHNba10gPSBhcmdzO1xuICAgICAgICAgICAgICAgICAgICBjYWxsYmFjayhlcnIpO1xuICAgICAgICAgICAgICAgIH0pO1xuICAgICAgICAgICAgfSwgZnVuY3Rpb24gKGVycikge1xuICAgICAgICAgICAgICAgIGNhbGxiYWNrKGVyciwgcmVzdWx0cyk7XG4gICAgICAgICAgICB9KTtcbiAgICAgICAgfVxuICAgIH07XG5cbiAgICBhc3luYy5wYXJhbGxlbCA9IGZ1bmN0aW9uICh0YXNrcywgY2FsbGJhY2spIHtcbiAgICAgICAgX3BhcmFsbGVsKHsgbWFwOiBhc3luYy5tYXAsIGVhY2g6IGFzeW5jLmVhY2ggfSwgdGFza3MsIGNhbGxiYWNrKTtcbiAgICB9O1xuXG4gICAgYXN5bmMucGFyYWxsZWxMaW1pdCA9IGZ1bmN0aW9uKHRhc2tzLCBsaW1pdCwgY2FsbGJhY2spIHtcbiAgICAgICAgX3BhcmFsbGVsKHsgbWFwOiBfbWFwTGltaXQobGltaXQpLCBlYWNoOiBfZWFjaExpbWl0KGxpbWl0KSB9LCB0YXNrcywgY2FsbGJhY2spO1xuICAgIH07XG5cbiAgICBhc3luYy5zZXJpZXMgPSBmdW5jdGlvbiAodGFza3MsIGNhbGxiYWNrKSB7XG4gICAgICAgIGNhbGxiYWNrID0gY2FsbGJhY2sgfHwgZnVuY3Rpb24gKCkge307XG4gICAgICAgIGlmIChfaXNBcnJheSh0YXNrcykpIHtcbiAgICAgICAgICAgIGFzeW5jLm1hcFNlcmllcyh0YXNrcywgZnVuY3Rpb24gKGZuLCBjYWxsYmFjaykge1xuICAgICAgICAgICAgICAgIGlmIChmbikge1xuICAgICAgICAgICAgICAgICAgICBmbihmdW5jdGlvbiAoZXJyKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICB2YXIgYXJncyA9IEFycmF5LnByb3RvdHlwZS5zbGljZS5jYWxsKGFyZ3VtZW50cywgMSk7XG4gICAgICAgICAgICAgICAgICAgICAgICBpZiAoYXJncy5sZW5ndGggPD0gMSkge1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgIGFyZ3MgPSBhcmdzWzBdO1xuICAgICAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgICAgICAgICAgY2FsbGJhY2suY2FsbChudWxsLCBlcnIsIGFyZ3MpO1xuICAgICAgICAgICAgICAgICAgICB9KTtcbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICB9LCBjYWxsYmFjayk7XG4gICAgICAgIH1cbiAgICAgICAgZWxzZSB7XG4gICAgICAgICAgICB2YXIgcmVzdWx0cyA9IHt9O1xuICAgICAgICAgICAgYXN5bmMuZWFjaFNlcmllcyhfa2V5cyh0YXNrcyksIGZ1bmN0aW9uIChrLCBjYWxsYmFjaykge1xuICAgICAgICAgICAgICAgIHRhc2tzW2tdKGZ1bmN0aW9uIChlcnIpIHtcbiAgICAgICAgICAgICAgICAgICAgdmFyIGFyZ3MgPSBBcnJheS5wcm90b3R5cGUuc2xpY2UuY2FsbChhcmd1bWVudHMsIDEpO1xuICAgICAgICAgICAgICAgICAgICBpZiAoYXJncy5sZW5ndGggPD0gMSkge1xuICAgICAgICAgICAgICAgICAgICAgICAgYXJncyA9IGFyZ3NbMF07XG4gICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICAgICAgcmVzdWx0c1trXSA9IGFyZ3M7XG4gICAgICAgICAgICAgICAgICAgIGNhbGxiYWNrKGVycik7XG4gICAgICAgICAgICAgICAgfSk7XG4gICAgICAgICAgICB9LCBmdW5jdGlvbiAoZXJyKSB7XG4gICAgICAgICAgICAgICAgY2FsbGJhY2soZXJyLCByZXN1bHRzKTtcbiAgICAgICAgICAgIH0pO1xuICAgICAgICB9XG4gICAgfTtcblxuICAgIGFzeW5jLml0ZXJhdG9yID0gZnVuY3Rpb24gKHRhc2tzKSB7XG4gICAgICAgIHZhciBtYWtlQ2FsbGJhY2sgPSBmdW5jdGlvbiAoaW5kZXgpIHtcbiAgICAgICAgICAgIHZhciBmbiA9IGZ1bmN0aW9uICgpIHtcbiAgICAgICAgICAgICAgICBpZiAodGFza3MubGVuZ3RoKSB7XG4gICAgICAgICAgICAgICAgICAgIHRhc2tzW2luZGV4XS5hcHBseShudWxsLCBhcmd1bWVudHMpO1xuICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICByZXR1cm4gZm4ubmV4dCgpO1xuICAgICAgICAgICAgfTtcbiAgICAgICAgICAgIGZuLm5leHQgPSBmdW5jdGlvbiAoKSB7XG4gICAgICAgICAgICAgICAgcmV0dXJuIChpbmRleCA8IHRhc2tzLmxlbmd0aCAtIDEpID8gbWFrZUNhbGxiYWNrKGluZGV4ICsgMSk6IG51bGw7XG4gICAgICAgICAgICB9O1xuICAgICAgICAgICAgcmV0dXJuIGZuO1xuICAgICAgICB9O1xuICAgICAgICByZXR1cm4gbWFrZUNhbGxiYWNrKDApO1xuICAgIH07XG5cbiAgICBhc3luYy5hcHBseSA9IGZ1bmN0aW9uIChmbikge1xuICAgICAgICB2YXIgYXJncyA9IEFycmF5LnByb3RvdHlwZS5zbGljZS5jYWxsKGFyZ3VtZW50cywgMSk7XG4gICAgICAgIHJldHVybiBmdW5jdGlvbiAoKSB7XG4gICAgICAgICAgICByZXR1cm4gZm4uYXBwbHkoXG4gICAgICAgICAgICAgICAgbnVsbCwgYXJncy5jb25jYXQoQXJyYXkucHJvdG90eXBlLnNsaWNlLmNhbGwoYXJndW1lbnRzKSlcbiAgICAgICAgICAgICk7XG4gICAgICAgIH07XG4gICAgfTtcblxuICAgIHZhciBfY29uY2F0ID0gZnVuY3Rpb24gKGVhY2hmbiwgYXJyLCBmbiwgY2FsbGJhY2spIHtcbiAgICAgICAgdmFyIHIgPSBbXTtcbiAgICAgICAgZWFjaGZuKGFyciwgZnVuY3Rpb24gKHgsIGNiKSB7XG4gICAgICAgICAgICBmbih4LCBmdW5jdGlvbiAoZXJyLCB5KSB7XG4gICAgICAgICAgICAgICAgciA9IHIuY29uY2F0KHkgfHwgW10pO1xuICAgICAgICAgICAgICAgIGNiKGVycik7XG4gICAgICAgICAgICB9KTtcbiAgICAgICAgfSwgZnVuY3Rpb24gKGVycikge1xuICAgICAgICAgICAgY2FsbGJhY2soZXJyLCByKTtcbiAgICAgICAgfSk7XG4gICAgfTtcbiAgICBhc3luYy5jb25jYXQgPSBkb1BhcmFsbGVsKF9jb25jYXQpO1xuICAgIGFzeW5jLmNvbmNhdFNlcmllcyA9IGRvU2VyaWVzKF9jb25jYXQpO1xuXG4gICAgYXN5bmMud2hpbHN0ID0gZnVuY3Rpb24gKHRlc3QsIGl0ZXJhdG9yLCBjYWxsYmFjaykge1xuICAgICAgICBpZiAodGVzdCgpKSB7XG4gICAgICAgICAgICBpdGVyYXRvcihmdW5jdGlvbiAoZXJyKSB7XG4gICAgICAgICAgICAgICAgaWYgKGVycikge1xuICAgICAgICAgICAgICAgICAgICByZXR1cm4gY2FsbGJhY2soZXJyKTtcbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgYXN5bmMud2hpbHN0KHRlc3QsIGl0ZXJhdG9yLCBjYWxsYmFjayk7XG4gICAgICAgICAgICB9KTtcbiAgICAgICAgfVxuICAgICAgICBlbHNlIHtcbiAgICAgICAgICAgIGNhbGxiYWNrKCk7XG4gICAgICAgIH1cbiAgICB9O1xuXG4gICAgYXN5bmMuZG9XaGlsc3QgPSBmdW5jdGlvbiAoaXRlcmF0b3IsIHRlc3QsIGNhbGxiYWNrKSB7XG4gICAgICAgIGl0ZXJhdG9yKGZ1bmN0aW9uIChlcnIpIHtcbiAgICAgICAgICAgIGlmIChlcnIpIHtcbiAgICAgICAgICAgICAgICByZXR1cm4gY2FsbGJhY2soZXJyKTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgICAgIHZhciBhcmdzID0gQXJyYXkucHJvdG90eXBlLnNsaWNlLmNhbGwoYXJndW1lbnRzLCAxKTtcbiAgICAgICAgICAgIGlmICh0ZXN0LmFwcGx5KG51bGwsIGFyZ3MpKSB7XG4gICAgICAgICAgICAgICAgYXN5bmMuZG9XaGlsc3QoaXRlcmF0b3IsIHRlc3QsIGNhbGxiYWNrKTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgICAgIGVsc2Uge1xuICAgICAgICAgICAgICAgIGNhbGxiYWNrKCk7XG4gICAgICAgICAgICB9XG4gICAgICAgIH0pO1xuICAgIH07XG5cbiAgICBhc3luYy51bnRpbCA9IGZ1bmN0aW9uICh0ZXN0LCBpdGVyYXRvciwgY2FsbGJhY2spIHtcbiAgICAgICAgaWYgKCF0ZXN0KCkpIHtcbiAgICAgICAgICAgIGl0ZXJhdG9yKGZ1bmN0aW9uIChlcnIpIHtcbiAgICAgICAgICAgICAgICBpZiAoZXJyKSB7XG4gICAgICAgICAgICAgICAgICAgIHJldHVybiBjYWxsYmFjayhlcnIpO1xuICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICBhc3luYy51bnRpbCh0ZXN0LCBpdGVyYXRvciwgY2FsbGJhY2spO1xuICAgICAgICAgICAgfSk7XG4gICAgICAgIH1cbiAgICAgICAgZWxzZSB7XG4gICAgICAgICAgICBjYWxsYmFjaygpO1xuICAgICAgICB9XG4gICAgfTtcblxuICAgIGFzeW5jLmRvVW50aWwgPSBmdW5jdGlvbiAoaXRlcmF0b3IsIHRlc3QsIGNhbGxiYWNrKSB7XG4gICAgICAgIGl0ZXJhdG9yKGZ1bmN0aW9uIChlcnIpIHtcbiAgICAgICAgICAgIGlmIChlcnIpIHtcbiAgICAgICAgICAgICAgICByZXR1cm4gY2FsbGJhY2soZXJyKTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgICAgIHZhciBhcmdzID0gQXJyYXkucHJvdG90eXBlLnNsaWNlLmNhbGwoYXJndW1lbnRzLCAxKTtcbiAgICAgICAgICAgIGlmICghdGVzdC5hcHBseShudWxsLCBhcmdzKSkge1xuICAgICAgICAgICAgICAgIGFzeW5jLmRvVW50aWwoaXRlcmF0b3IsIHRlc3QsIGNhbGxiYWNrKTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgICAgIGVsc2Uge1xuICAgICAgICAgICAgICAgIGNhbGxiYWNrKCk7XG4gICAgICAgICAgICB9XG4gICAgICAgIH0pO1xuICAgIH07XG5cbiAgICBhc3luYy5xdWV1ZSA9IGZ1bmN0aW9uICh3b3JrZXIsIGNvbmN1cnJlbmN5KSB7XG4gICAgICAgIGlmIChjb25jdXJyZW5jeSA9PT0gdW5kZWZpbmVkKSB7XG4gICAgICAgICAgICBjb25jdXJyZW5jeSA9IDE7XG4gICAgICAgIH1cbiAgICAgICAgZnVuY3Rpb24gX2luc2VydChxLCBkYXRhLCBwb3MsIGNhbGxiYWNrKSB7XG4gICAgICAgICAgaWYgKCFxLnN0YXJ0ZWQpe1xuICAgICAgICAgICAgcS5zdGFydGVkID0gdHJ1ZTtcbiAgICAgICAgICB9XG4gICAgICAgICAgaWYgKCFfaXNBcnJheShkYXRhKSkge1xuICAgICAgICAgICAgICBkYXRhID0gW2RhdGFdO1xuICAgICAgICAgIH1cbiAgICAgICAgICBpZihkYXRhLmxlbmd0aCA9PSAwKSB7XG4gICAgICAgICAgICAgLy8gY2FsbCBkcmFpbiBpbW1lZGlhdGVseSBpZiB0aGVyZSBhcmUgbm8gdGFza3NcbiAgICAgICAgICAgICByZXR1cm4gYXN5bmMuc2V0SW1tZWRpYXRlKGZ1bmN0aW9uKCkge1xuICAgICAgICAgICAgICAgICBpZiAocS5kcmFpbikge1xuICAgICAgICAgICAgICAgICAgICAgcS5kcmFpbigpO1xuICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgfSk7XG4gICAgICAgICAgfVxuICAgICAgICAgIF9lYWNoKGRhdGEsIGZ1bmN0aW9uKHRhc2spIHtcbiAgICAgICAgICAgICAgdmFyIGl0ZW0gPSB7XG4gICAgICAgICAgICAgICAgICBkYXRhOiB0YXNrLFxuICAgICAgICAgICAgICAgICAgY2FsbGJhY2s6IHR5cGVvZiBjYWxsYmFjayA9PT0gJ2Z1bmN0aW9uJyA/IGNhbGxiYWNrIDogbnVsbFxuICAgICAgICAgICAgICB9O1xuXG4gICAgICAgICAgICAgIGlmIChwb3MpIHtcbiAgICAgICAgICAgICAgICBxLnRhc2tzLnVuc2hpZnQoaXRlbSk7XG4gICAgICAgICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICAgICAgcS50YXNrcy5wdXNoKGl0ZW0pO1xuICAgICAgICAgICAgICB9XG5cbiAgICAgICAgICAgICAgaWYgKHEuc2F0dXJhdGVkICYmIHEudGFza3MubGVuZ3RoID09PSBxLmNvbmN1cnJlbmN5KSB7XG4gICAgICAgICAgICAgICAgICBxLnNhdHVyYXRlZCgpO1xuICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgIGFzeW5jLnNldEltbWVkaWF0ZShxLnByb2Nlc3MpO1xuICAgICAgICAgIH0pO1xuICAgICAgICB9XG5cbiAgICAgICAgdmFyIHdvcmtlcnMgPSAwO1xuICAgICAgICB2YXIgcSA9IHtcbiAgICAgICAgICAgIHRhc2tzOiBbXSxcbiAgICAgICAgICAgIGNvbmN1cnJlbmN5OiBjb25jdXJyZW5jeSxcbiAgICAgICAgICAgIHNhdHVyYXRlZDogbnVsbCxcbiAgICAgICAgICAgIGVtcHR5OiBudWxsLFxuICAgICAgICAgICAgZHJhaW46IG51bGwsXG4gICAgICAgICAgICBzdGFydGVkOiBmYWxzZSxcbiAgICAgICAgICAgIHBhdXNlZDogZmFsc2UsXG4gICAgICAgICAgICBwdXNoOiBmdW5jdGlvbiAoZGF0YSwgY2FsbGJhY2spIHtcbiAgICAgICAgICAgICAgX2luc2VydChxLCBkYXRhLCBmYWxzZSwgY2FsbGJhY2spO1xuICAgICAgICAgICAgfSxcbiAgICAgICAgICAgIGtpbGw6IGZ1bmN0aW9uICgpIHtcbiAgICAgICAgICAgICAgcS5kcmFpbiA9IG51bGw7XG4gICAgICAgICAgICAgIHEudGFza3MgPSBbXTtcbiAgICAgICAgICAgIH0sXG4gICAgICAgICAgICB1bnNoaWZ0OiBmdW5jdGlvbiAoZGF0YSwgY2FsbGJhY2spIHtcbiAgICAgICAgICAgICAgX2luc2VydChxLCBkYXRhLCB0cnVlLCBjYWxsYmFjayk7XG4gICAgICAgICAgICB9LFxuICAgICAgICAgICAgcHJvY2VzczogZnVuY3Rpb24gKCkge1xuICAgICAgICAgICAgICAgIGlmICghcS5wYXVzZWQgJiYgd29ya2VycyA8IHEuY29uY3VycmVuY3kgJiYgcS50YXNrcy5sZW5ndGgpIHtcbiAgICAgICAgICAgICAgICAgICAgdmFyIHRhc2sgPSBxLnRhc2tzLnNoaWZ0KCk7XG4gICAgICAgICAgICAgICAgICAgIGlmIChxLmVtcHR5ICYmIHEudGFza3MubGVuZ3RoID09PSAwKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICBxLmVtcHR5KCk7XG4gICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICAgICAgd29ya2VycyArPSAxO1xuICAgICAgICAgICAgICAgICAgICB2YXIgbmV4dCA9IGZ1bmN0aW9uICgpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgIHdvcmtlcnMgLT0gMTtcbiAgICAgICAgICAgICAgICAgICAgICAgIGlmICh0YXNrLmNhbGxiYWNrKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgdGFzay5jYWxsYmFjay5hcHBseSh0YXNrLCBhcmd1bWVudHMpO1xuICAgICAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgICAgICAgICAgaWYgKHEuZHJhaW4gJiYgcS50YXNrcy5sZW5ndGggKyB3b3JrZXJzID09PSAwKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgcS5kcmFpbigpO1xuICAgICAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgICAgICAgICAgcS5wcm9jZXNzKCk7XG4gICAgICAgICAgICAgICAgICAgIH07XG4gICAgICAgICAgICAgICAgICAgIHZhciBjYiA9IG9ubHlfb25jZShuZXh0KTtcbiAgICAgICAgICAgICAgICAgICAgd29ya2VyKHRhc2suZGF0YSwgY2IpO1xuICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgIH0sXG4gICAgICAgICAgICBsZW5ndGg6IGZ1bmN0aW9uICgpIHtcbiAgICAgICAgICAgICAgICByZXR1cm4gcS50YXNrcy5sZW5ndGg7XG4gICAgICAgICAgICB9LFxuICAgICAgICAgICAgcnVubmluZzogZnVuY3Rpb24gKCkge1xuICAgICAgICAgICAgICAgIHJldHVybiB3b3JrZXJzO1xuICAgICAgICAgICAgfSxcbiAgICAgICAgICAgIGlkbGU6IGZ1bmN0aW9uKCkge1xuICAgICAgICAgICAgICAgIHJldHVybiBxLnRhc2tzLmxlbmd0aCArIHdvcmtlcnMgPT09IDA7XG4gICAgICAgICAgICB9LFxuICAgICAgICAgICAgcGF1c2U6IGZ1bmN0aW9uICgpIHtcbiAgICAgICAgICAgICAgICBpZiAocS5wYXVzZWQgPT09IHRydWUpIHsgcmV0dXJuOyB9XG4gICAgICAgICAgICAgICAgcS5wYXVzZWQgPSB0cnVlO1xuICAgICAgICAgICAgICAgIHEucHJvY2VzcygpO1xuICAgICAgICAgICAgfSxcbiAgICAgICAgICAgIHJlc3VtZTogZnVuY3Rpb24gKCkge1xuICAgICAgICAgICAgICAgIGlmIChxLnBhdXNlZCA9PT0gZmFsc2UpIHsgcmV0dXJuOyB9XG4gICAgICAgICAgICAgICAgcS5wYXVzZWQgPSBmYWxzZTtcbiAgICAgICAgICAgICAgICBxLnByb2Nlc3MoKTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgfTtcbiAgICAgICAgcmV0dXJuIHE7XG4gICAgfTtcbiAgICBcbiAgICBhc3luYy5wcmlvcml0eVF1ZXVlID0gZnVuY3Rpb24gKHdvcmtlciwgY29uY3VycmVuY3kpIHtcbiAgICAgICAgXG4gICAgICAgIGZ1bmN0aW9uIF9jb21wYXJlVGFza3MoYSwgYil7XG4gICAgICAgICAgcmV0dXJuIGEucHJpb3JpdHkgLSBiLnByaW9yaXR5O1xuICAgICAgICB9O1xuICAgICAgICBcbiAgICAgICAgZnVuY3Rpb24gX2JpbmFyeVNlYXJjaChzZXF1ZW5jZSwgaXRlbSwgY29tcGFyZSkge1xuICAgICAgICAgIHZhciBiZWcgPSAtMSxcbiAgICAgICAgICAgICAgZW5kID0gc2VxdWVuY2UubGVuZ3RoIC0gMTtcbiAgICAgICAgICB3aGlsZSAoYmVnIDwgZW5kKSB7XG4gICAgICAgICAgICB2YXIgbWlkID0gYmVnICsgKChlbmQgLSBiZWcgKyAxKSA+Pj4gMSk7XG4gICAgICAgICAgICBpZiAoY29tcGFyZShpdGVtLCBzZXF1ZW5jZVttaWRdKSA+PSAwKSB7XG4gICAgICAgICAgICAgIGJlZyA9IG1pZDtcbiAgICAgICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICAgIGVuZCA9IG1pZCAtIDE7XG4gICAgICAgICAgICB9XG4gICAgICAgICAgfVxuICAgICAgICAgIHJldHVybiBiZWc7XG4gICAgICAgIH1cbiAgICAgICAgXG4gICAgICAgIGZ1bmN0aW9uIF9pbnNlcnQocSwgZGF0YSwgcHJpb3JpdHksIGNhbGxiYWNrKSB7XG4gICAgICAgICAgaWYgKCFxLnN0YXJ0ZWQpe1xuICAgICAgICAgICAgcS5zdGFydGVkID0gdHJ1ZTtcbiAgICAgICAgICB9XG4gICAgICAgICAgaWYgKCFfaXNBcnJheShkYXRhKSkge1xuICAgICAgICAgICAgICBkYXRhID0gW2RhdGFdO1xuICAgICAgICAgIH1cbiAgICAgICAgICBpZihkYXRhLmxlbmd0aCA9PSAwKSB7XG4gICAgICAgICAgICAgLy8gY2FsbCBkcmFpbiBpbW1lZGlhdGVseSBpZiB0aGVyZSBhcmUgbm8gdGFza3NcbiAgICAgICAgICAgICByZXR1cm4gYXN5bmMuc2V0SW1tZWRpYXRlKGZ1bmN0aW9uKCkge1xuICAgICAgICAgICAgICAgICBpZiAocS5kcmFpbikge1xuICAgICAgICAgICAgICAgICAgICAgcS5kcmFpbigpO1xuICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgfSk7XG4gICAgICAgICAgfVxuICAgICAgICAgIF9lYWNoKGRhdGEsIGZ1bmN0aW9uKHRhc2spIHtcbiAgICAgICAgICAgICAgdmFyIGl0ZW0gPSB7XG4gICAgICAgICAgICAgICAgICBkYXRhOiB0YXNrLFxuICAgICAgICAgICAgICAgICAgcHJpb3JpdHk6IHByaW9yaXR5LFxuICAgICAgICAgICAgICAgICAgY2FsbGJhY2s6IHR5cGVvZiBjYWxsYmFjayA9PT0gJ2Z1bmN0aW9uJyA/IGNhbGxiYWNrIDogbnVsbFxuICAgICAgICAgICAgICB9O1xuICAgICAgICAgICAgICBcbiAgICAgICAgICAgICAgcS50YXNrcy5zcGxpY2UoX2JpbmFyeVNlYXJjaChxLnRhc2tzLCBpdGVtLCBfY29tcGFyZVRhc2tzKSArIDEsIDAsIGl0ZW0pO1xuXG4gICAgICAgICAgICAgIGlmIChxLnNhdHVyYXRlZCAmJiBxLnRhc2tzLmxlbmd0aCA9PT0gcS5jb25jdXJyZW5jeSkge1xuICAgICAgICAgICAgICAgICAgcS5zYXR1cmF0ZWQoKTtcbiAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICBhc3luYy5zZXRJbW1lZGlhdGUocS5wcm9jZXNzKTtcbiAgICAgICAgICB9KTtcbiAgICAgICAgfVxuICAgICAgICBcbiAgICAgICAgLy8gU3RhcnQgd2l0aCBhIG5vcm1hbCBxdWV1ZVxuICAgICAgICB2YXIgcSA9IGFzeW5jLnF1ZXVlKHdvcmtlciwgY29uY3VycmVuY3kpO1xuICAgICAgICBcbiAgICAgICAgLy8gT3ZlcnJpZGUgcHVzaCB0byBhY2NlcHQgc2Vjb25kIHBhcmFtZXRlciByZXByZXNlbnRpbmcgcHJpb3JpdHlcbiAgICAgICAgcS5wdXNoID0gZnVuY3Rpb24gKGRhdGEsIHByaW9yaXR5LCBjYWxsYmFjaykge1xuICAgICAgICAgIF9pbnNlcnQocSwgZGF0YSwgcHJpb3JpdHksIGNhbGxiYWNrKTtcbiAgICAgICAgfTtcbiAgICAgICAgXG4gICAgICAgIC8vIFJlbW92ZSB1bnNoaWZ0IGZ1bmN0aW9uXG4gICAgICAgIGRlbGV0ZSBxLnVuc2hpZnQ7XG5cbiAgICAgICAgcmV0dXJuIHE7XG4gICAgfTtcblxuICAgIGFzeW5jLmNhcmdvID0gZnVuY3Rpb24gKHdvcmtlciwgcGF5bG9hZCkge1xuICAgICAgICB2YXIgd29ya2luZyAgICAgPSBmYWxzZSxcbiAgICAgICAgICAgIHRhc2tzICAgICAgID0gW107XG5cbiAgICAgICAgdmFyIGNhcmdvID0ge1xuICAgICAgICAgICAgdGFza3M6IHRhc2tzLFxuICAgICAgICAgICAgcGF5bG9hZDogcGF5bG9hZCxcbiAgICAgICAgICAgIHNhdHVyYXRlZDogbnVsbCxcbiAgICAgICAgICAgIGVtcHR5OiBudWxsLFxuICAgICAgICAgICAgZHJhaW46IG51bGwsXG4gICAgICAgICAgICBkcmFpbmVkOiB0cnVlLFxuICAgICAgICAgICAgcHVzaDogZnVuY3Rpb24gKGRhdGEsIGNhbGxiYWNrKSB7XG4gICAgICAgICAgICAgICAgaWYgKCFfaXNBcnJheShkYXRhKSkge1xuICAgICAgICAgICAgICAgICAgICBkYXRhID0gW2RhdGFdO1xuICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICBfZWFjaChkYXRhLCBmdW5jdGlvbih0YXNrKSB7XG4gICAgICAgICAgICAgICAgICAgIHRhc2tzLnB1c2goe1xuICAgICAgICAgICAgICAgICAgICAgICAgZGF0YTogdGFzayxcbiAgICAgICAgICAgICAgICAgICAgICAgIGNhbGxiYWNrOiB0eXBlb2YgY2FsbGJhY2sgPT09ICdmdW5jdGlvbicgPyBjYWxsYmFjayA6IG51bGxcbiAgICAgICAgICAgICAgICAgICAgfSk7XG4gICAgICAgICAgICAgICAgICAgIGNhcmdvLmRyYWluZWQgPSBmYWxzZTtcbiAgICAgICAgICAgICAgICAgICAgaWYgKGNhcmdvLnNhdHVyYXRlZCAmJiB0YXNrcy5sZW5ndGggPT09IHBheWxvYWQpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgIGNhcmdvLnNhdHVyYXRlZCgpO1xuICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgfSk7XG4gICAgICAgICAgICAgICAgYXN5bmMuc2V0SW1tZWRpYXRlKGNhcmdvLnByb2Nlc3MpO1xuICAgICAgICAgICAgfSxcbiAgICAgICAgICAgIHByb2Nlc3M6IGZ1bmN0aW9uIHByb2Nlc3MoKSB7XG4gICAgICAgICAgICAgICAgaWYgKHdvcmtpbmcpIHJldHVybjtcbiAgICAgICAgICAgICAgICBpZiAodGFza3MubGVuZ3RoID09PSAwKSB7XG4gICAgICAgICAgICAgICAgICAgIGlmKGNhcmdvLmRyYWluICYmICFjYXJnby5kcmFpbmVkKSBjYXJnby5kcmFpbigpO1xuICAgICAgICAgICAgICAgICAgICBjYXJnby5kcmFpbmVkID0gdHJ1ZTtcbiAgICAgICAgICAgICAgICAgICAgcmV0dXJuO1xuICAgICAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgICAgIHZhciB0cyA9IHR5cGVvZiBwYXlsb2FkID09PSAnbnVtYmVyJ1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgID8gdGFza3Muc3BsaWNlKDAsIHBheWxvYWQpXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgOiB0YXNrcy5zcGxpY2UoMCwgdGFza3MubGVuZ3RoKTtcblxuICAgICAgICAgICAgICAgIHZhciBkcyA9IF9tYXAodHMsIGZ1bmN0aW9uICh0YXNrKSB7XG4gICAgICAgICAgICAgICAgICAgIHJldHVybiB0YXNrLmRhdGE7XG4gICAgICAgICAgICAgICAgfSk7XG5cbiAgICAgICAgICAgICAgICBpZihjYXJnby5lbXB0eSkgY2FyZ28uZW1wdHkoKTtcbiAgICAgICAgICAgICAgICB3b3JraW5nID0gdHJ1ZTtcbiAgICAgICAgICAgICAgICB3b3JrZXIoZHMsIGZ1bmN0aW9uICgpIHtcbiAgICAgICAgICAgICAgICAgICAgd29ya2luZyA9IGZhbHNlO1xuXG4gICAgICAgICAgICAgICAgICAgIHZhciBhcmdzID0gYXJndW1lbnRzO1xuICAgICAgICAgICAgICAgICAgICBfZWFjaCh0cywgZnVuY3Rpb24gKGRhdGEpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgIGlmIChkYXRhLmNhbGxiYWNrKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgZGF0YS5jYWxsYmFjay5hcHBseShudWxsLCBhcmdzKTtcbiAgICAgICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICAgICAgfSk7XG5cbiAgICAgICAgICAgICAgICAgICAgcHJvY2VzcygpO1xuICAgICAgICAgICAgICAgIH0pO1xuICAgICAgICAgICAgfSxcbiAgICAgICAgICAgIGxlbmd0aDogZnVuY3Rpb24gKCkge1xuICAgICAgICAgICAgICAgIHJldHVybiB0YXNrcy5sZW5ndGg7XG4gICAgICAgICAgICB9LFxuICAgICAgICAgICAgcnVubmluZzogZnVuY3Rpb24gKCkge1xuICAgICAgICAgICAgICAgIHJldHVybiB3b3JraW5nO1xuICAgICAgICAgICAgfVxuICAgICAgICB9O1xuICAgICAgICByZXR1cm4gY2FyZ287XG4gICAgfTtcblxuICAgIHZhciBfY29uc29sZV9mbiA9IGZ1bmN0aW9uIChuYW1lKSB7XG4gICAgICAgIHJldHVybiBmdW5jdGlvbiAoZm4pIHtcbiAgICAgICAgICAgIHZhciBhcmdzID0gQXJyYXkucHJvdG90eXBlLnNsaWNlLmNhbGwoYXJndW1lbnRzLCAxKTtcbiAgICAgICAgICAgIGZuLmFwcGx5KG51bGwsIGFyZ3MuY29uY2F0KFtmdW5jdGlvbiAoZXJyKSB7XG4gICAgICAgICAgICAgICAgdmFyIGFyZ3MgPSBBcnJheS5wcm90b3R5cGUuc2xpY2UuY2FsbChhcmd1bWVudHMsIDEpO1xuICAgICAgICAgICAgICAgIGlmICh0eXBlb2YgY29uc29sZSAhPT0gJ3VuZGVmaW5lZCcpIHtcbiAgICAgICAgICAgICAgICAgICAgaWYgKGVycikge1xuICAgICAgICAgICAgICAgICAgICAgICAgaWYgKGNvbnNvbGUuZXJyb3IpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICBjb25zb2xlLmVycm9yKGVycik7XG4gICAgICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICAgICAgZWxzZSBpZiAoY29uc29sZVtuYW1lXSkge1xuICAgICAgICAgICAgICAgICAgICAgICAgX2VhY2goYXJncywgZnVuY3Rpb24gKHgpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICBjb25zb2xlW25hbWVdKHgpO1xuICAgICAgICAgICAgICAgICAgICAgICAgfSk7XG4gICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICB9XSkpO1xuICAgICAgICB9O1xuICAgIH07XG4gICAgYXN5bmMubG9nID0gX2NvbnNvbGVfZm4oJ2xvZycpO1xuICAgIGFzeW5jLmRpciA9IF9jb25zb2xlX2ZuKCdkaXInKTtcbiAgICAvKmFzeW5jLmluZm8gPSBfY29uc29sZV9mbignaW5mbycpO1xuICAgIGFzeW5jLndhcm4gPSBfY29uc29sZV9mbignd2FybicpO1xuICAgIGFzeW5jLmVycm9yID0gX2NvbnNvbGVfZm4oJ2Vycm9yJyk7Ki9cblxuICAgIGFzeW5jLm1lbW9pemUgPSBmdW5jdGlvbiAoZm4sIGhhc2hlcikge1xuICAgICAgICB2YXIgbWVtbyA9IHt9O1xuICAgICAgICB2YXIgcXVldWVzID0ge307XG4gICAgICAgIGhhc2hlciA9IGhhc2hlciB8fCBmdW5jdGlvbiAoeCkge1xuICAgICAgICAgICAgcmV0dXJuIHg7XG4gICAgICAgIH07XG4gICAgICAgIHZhciBtZW1vaXplZCA9IGZ1bmN0aW9uICgpIHtcbiAgICAgICAgICAgIHZhciBhcmdzID0gQXJyYXkucHJvdG90eXBlLnNsaWNlLmNhbGwoYXJndW1lbnRzKTtcbiAgICAgICAgICAgIHZhciBjYWxsYmFjayA9IGFyZ3MucG9wKCk7XG4gICAgICAgICAgICB2YXIga2V5ID0gaGFzaGVyLmFwcGx5KG51bGwsIGFyZ3MpO1xuICAgICAgICAgICAgaWYgKGtleSBpbiBtZW1vKSB7XG4gICAgICAgICAgICAgICAgYXN5bmMubmV4dFRpY2soZnVuY3Rpb24gKCkge1xuICAgICAgICAgICAgICAgICAgICBjYWxsYmFjay5hcHBseShudWxsLCBtZW1vW2tleV0pO1xuICAgICAgICAgICAgICAgIH0pO1xuICAgICAgICAgICAgfVxuICAgICAgICAgICAgZWxzZSBpZiAoa2V5IGluIHF1ZXVlcykge1xuICAgICAgICAgICAgICAgIHF1ZXVlc1trZXldLnB1c2goY2FsbGJhY2spO1xuICAgICAgICAgICAgfVxuICAgICAgICAgICAgZWxzZSB7XG4gICAgICAgICAgICAgICAgcXVldWVzW2tleV0gPSBbY2FsbGJhY2tdO1xuICAgICAgICAgICAgICAgIGZuLmFwcGx5KG51bGwsIGFyZ3MuY29uY2F0KFtmdW5jdGlvbiAoKSB7XG4gICAgICAgICAgICAgICAgICAgIG1lbW9ba2V5XSA9IGFyZ3VtZW50cztcbiAgICAgICAgICAgICAgICAgICAgdmFyIHEgPSBxdWV1ZXNba2V5XTtcbiAgICAgICAgICAgICAgICAgICAgZGVsZXRlIHF1ZXVlc1trZXldO1xuICAgICAgICAgICAgICAgICAgICBmb3IgKHZhciBpID0gMCwgbCA9IHEubGVuZ3RoOyBpIDwgbDsgaSsrKSB7XG4gICAgICAgICAgICAgICAgICAgICAgcVtpXS5hcHBseShudWxsLCBhcmd1bWVudHMpO1xuICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgfV0pKTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgfTtcbiAgICAgICAgbWVtb2l6ZWQubWVtbyA9IG1lbW87XG4gICAgICAgIG1lbW9pemVkLnVubWVtb2l6ZWQgPSBmbjtcbiAgICAgICAgcmV0dXJuIG1lbW9pemVkO1xuICAgIH07XG5cbiAgICBhc3luYy51bm1lbW9pemUgPSBmdW5jdGlvbiAoZm4pIHtcbiAgICAgIHJldHVybiBmdW5jdGlvbiAoKSB7XG4gICAgICAgIHJldHVybiAoZm4udW5tZW1vaXplZCB8fCBmbikuYXBwbHkobnVsbCwgYXJndW1lbnRzKTtcbiAgICAgIH07XG4gICAgfTtcblxuICAgIGFzeW5jLnRpbWVzID0gZnVuY3Rpb24gKGNvdW50LCBpdGVyYXRvciwgY2FsbGJhY2spIHtcbiAgICAgICAgdmFyIGNvdW50ZXIgPSBbXTtcbiAgICAgICAgZm9yICh2YXIgaSA9IDA7IGkgPCBjb3VudDsgaSsrKSB7XG4gICAgICAgICAgICBjb3VudGVyLnB1c2goaSk7XG4gICAgICAgIH1cbiAgICAgICAgcmV0dXJuIGFzeW5jLm1hcChjb3VudGVyLCBpdGVyYXRvciwgY2FsbGJhY2spO1xuICAgIH07XG5cbiAgICBhc3luYy50aW1lc1NlcmllcyA9IGZ1bmN0aW9uIChjb3VudCwgaXRlcmF0b3IsIGNhbGxiYWNrKSB7XG4gICAgICAgIHZhciBjb3VudGVyID0gW107XG4gICAgICAgIGZvciAodmFyIGkgPSAwOyBpIDwgY291bnQ7IGkrKykge1xuICAgICAgICAgICAgY291bnRlci5wdXNoKGkpO1xuICAgICAgICB9XG4gICAgICAgIHJldHVybiBhc3luYy5tYXBTZXJpZXMoY291bnRlciwgaXRlcmF0b3IsIGNhbGxiYWNrKTtcbiAgICB9O1xuXG4gICAgYXN5bmMuc2VxID0gZnVuY3Rpb24gKC8qIGZ1bmN0aW9ucy4uLiAqLykge1xuICAgICAgICB2YXIgZm5zID0gYXJndW1lbnRzO1xuICAgICAgICByZXR1cm4gZnVuY3Rpb24gKCkge1xuICAgICAgICAgICAgdmFyIHRoYXQgPSB0aGlzO1xuICAgICAgICAgICAgdmFyIGFyZ3MgPSBBcnJheS5wcm90b3R5cGUuc2xpY2UuY2FsbChhcmd1bWVudHMpO1xuICAgICAgICAgICAgdmFyIGNhbGxiYWNrID0gYXJncy5wb3AoKTtcbiAgICAgICAgICAgIGFzeW5jLnJlZHVjZShmbnMsIGFyZ3MsIGZ1bmN0aW9uIChuZXdhcmdzLCBmbiwgY2IpIHtcbiAgICAgICAgICAgICAgICBmbi5hcHBseSh0aGF0LCBuZXdhcmdzLmNvbmNhdChbZnVuY3Rpb24gKCkge1xuICAgICAgICAgICAgICAgICAgICB2YXIgZXJyID0gYXJndW1lbnRzWzBdO1xuICAgICAgICAgICAgICAgICAgICB2YXIgbmV4dGFyZ3MgPSBBcnJheS5wcm90b3R5cGUuc2xpY2UuY2FsbChhcmd1bWVudHMsIDEpO1xuICAgICAgICAgICAgICAgICAgICBjYihlcnIsIG5leHRhcmdzKTtcbiAgICAgICAgICAgICAgICB9XSkpXG4gICAgICAgICAgICB9LFxuICAgICAgICAgICAgZnVuY3Rpb24gKGVyciwgcmVzdWx0cykge1xuICAgICAgICAgICAgICAgIGNhbGxiYWNrLmFwcGx5KHRoYXQsIFtlcnJdLmNvbmNhdChyZXN1bHRzKSk7XG4gICAgICAgICAgICB9KTtcbiAgICAgICAgfTtcbiAgICB9O1xuXG4gICAgYXN5bmMuY29tcG9zZSA9IGZ1bmN0aW9uICgvKiBmdW5jdGlvbnMuLi4gKi8pIHtcbiAgICAgIHJldHVybiBhc3luYy5zZXEuYXBwbHkobnVsbCwgQXJyYXkucHJvdG90eXBlLnJldmVyc2UuY2FsbChhcmd1bWVudHMpKTtcbiAgICB9O1xuXG4gICAgdmFyIF9hcHBseUVhY2ggPSBmdW5jdGlvbiAoZWFjaGZuLCBmbnMgLyphcmdzLi4uKi8pIHtcbiAgICAgICAgdmFyIGdvID0gZnVuY3Rpb24gKCkge1xuICAgICAgICAgICAgdmFyIHRoYXQgPSB0aGlzO1xuICAgICAgICAgICAgdmFyIGFyZ3MgPSBBcnJheS5wcm90b3R5cGUuc2xpY2UuY2FsbChhcmd1bWVudHMpO1xuICAgICAgICAgICAgdmFyIGNhbGxiYWNrID0gYXJncy5wb3AoKTtcbiAgICAgICAgICAgIHJldHVybiBlYWNoZm4oZm5zLCBmdW5jdGlvbiAoZm4sIGNiKSB7XG4gICAgICAgICAgICAgICAgZm4uYXBwbHkodGhhdCwgYXJncy5jb25jYXQoW2NiXSkpO1xuICAgICAgICAgICAgfSxcbiAgICAgICAgICAgIGNhbGxiYWNrKTtcbiAgICAgICAgfTtcbiAgICAgICAgaWYgKGFyZ3VtZW50cy5sZW5ndGggPiAyKSB7XG4gICAgICAgICAgICB2YXIgYXJncyA9IEFycmF5LnByb3RvdHlwZS5zbGljZS5jYWxsKGFyZ3VtZW50cywgMik7XG4gICAgICAgICAgICByZXR1cm4gZ28uYXBwbHkodGhpcywgYXJncyk7XG4gICAgICAgIH1cbiAgICAgICAgZWxzZSB7XG4gICAgICAgICAgICByZXR1cm4gZ287XG4gICAgICAgIH1cbiAgICB9O1xuICAgIGFzeW5jLmFwcGx5RWFjaCA9IGRvUGFyYWxsZWwoX2FwcGx5RWFjaCk7XG4gICAgYXN5bmMuYXBwbHlFYWNoU2VyaWVzID0gZG9TZXJpZXMoX2FwcGx5RWFjaCk7XG5cbiAgICBhc3luYy5mb3JldmVyID0gZnVuY3Rpb24gKGZuLCBjYWxsYmFjaykge1xuICAgICAgICBmdW5jdGlvbiBuZXh0KGVycikge1xuICAgICAgICAgICAgaWYgKGVycikge1xuICAgICAgICAgICAgICAgIGlmIChjYWxsYmFjaykge1xuICAgICAgICAgICAgICAgICAgICByZXR1cm4gY2FsbGJhY2soZXJyKTtcbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgdGhyb3cgZXJyO1xuICAgICAgICAgICAgfVxuICAgICAgICAgICAgZm4obmV4dCk7XG4gICAgICAgIH1cbiAgICAgICAgbmV4dCgpO1xuICAgIH07XG5cbiAgICAvLyBOb2RlLmpzXG4gICAgaWYgKHR5cGVvZiBtb2R1bGUgIT09ICd1bmRlZmluZWQnICYmIG1vZHVsZS5leHBvcnRzKSB7XG4gICAgICAgIG1vZHVsZS5leHBvcnRzID0gYXN5bmM7XG4gICAgfVxuICAgIC8vIEFNRCAvIFJlcXVpcmVKU1xuICAgIGVsc2UgaWYgKHR5cGVvZiBkZWZpbmUgIT09ICd1bmRlZmluZWQnICYmIGRlZmluZS5hbWQpIHtcbiAgICAgICAgZGVmaW5lKFtdLCBmdW5jdGlvbiAoKSB7XG4gICAgICAgICAgICByZXR1cm4gYXN5bmM7XG4gICAgICAgIH0pO1xuICAgIH1cbiAgICAvLyBpbmNsdWRlZCBkaXJlY3RseSB2aWEgPHNjcmlwdD4gdGFnXG4gICAgZWxzZSB7XG4gICAgICAgIHJvb3QuYXN5bmMgPSBhc3luYztcbiAgICB9XG5cbn0oKSk7XG4iLCIvLyBDb3B5cmlnaHQgSm95ZW50LCBJbmMuIGFuZCBvdGhlciBOb2RlIGNvbnRyaWJ1dG9ycy5cbi8vXG4vLyBQZXJtaXNzaW9uIGlzIGhlcmVieSBncmFudGVkLCBmcmVlIG9mIGNoYXJnZSwgdG8gYW55IHBlcnNvbiBvYnRhaW5pbmcgYVxuLy8gY29weSBvZiB0aGlzIHNvZnR3YXJlIGFuZCBhc3NvY2lhdGVkIGRvY3VtZW50YXRpb24gZmlsZXMgKHRoZVxuLy8gXCJTb2Z0d2FyZVwiKSwgdG8gZGVhbCBpbiB0aGUgU29mdHdhcmUgd2l0aG91dCByZXN0cmljdGlvbiwgaW5jbHVkaW5nXG4vLyB3aXRob3V0IGxpbWl0YXRpb24gdGhlIHJpZ2h0cyB0byB1c2UsIGNvcHksIG1vZGlmeSwgbWVyZ2UsIHB1Ymxpc2gsXG4vLyBkaXN0cmlidXRlLCBzdWJsaWNlbnNlLCBhbmQvb3Igc2VsbCBjb3BpZXMgb2YgdGhlIFNvZnR3YXJlLCBhbmQgdG8gcGVybWl0XG4vLyBwZXJzb25zIHRvIHdob20gdGhlIFNvZnR3YXJlIGlzIGZ1cm5pc2hlZCB0byBkbyBzbywgc3ViamVjdCB0byB0aGVcbi8vIGZvbGxvd2luZyBjb25kaXRpb25zOlxuLy9cbi8vIFRoZSBhYm92ZSBjb3B5cmlnaHQgbm90aWNlIGFuZCB0aGlzIHBlcm1pc3Npb24gbm90aWNlIHNoYWxsIGJlIGluY2x1ZGVkXG4vLyBpbiBhbGwgY29waWVzIG9yIHN1YnN0YW50aWFsIHBvcnRpb25zIG9mIHRoZSBTb2Z0d2FyZS5cbi8vXG4vLyBUSEUgU09GVFdBUkUgSVMgUFJPVklERUQgXCJBUyBJU1wiLCBXSVRIT1VUIFdBUlJBTlRZIE9GIEFOWSBLSU5ELCBFWFBSRVNTXG4vLyBPUiBJTVBMSUVELCBJTkNMVURJTkcgQlVUIE5PVCBMSU1JVEVEIFRPIFRIRSBXQVJSQU5USUVTIE9GXG4vLyBNRVJDSEFOVEFCSUxJVFksIEZJVE5FU1MgRk9SIEEgUEFSVElDVUxBUiBQVVJQT1NFIEFORCBOT05JTkZSSU5HRU1FTlQuIElOXG4vLyBOTyBFVkVOVCBTSEFMTCBUSEUgQVVUSE9SUyBPUiBDT1BZUklHSFQgSE9MREVSUyBCRSBMSUFCTEUgRk9SIEFOWSBDTEFJTSxcbi8vIERBTUFHRVMgT1IgT1RIRVIgTElBQklMSVRZLCBXSEVUSEVSIElOIEFOIEFDVElPTiBPRiBDT05UUkFDVCwgVE9SVCBPUlxuLy8gT1RIRVJXSVNFLCBBUklTSU5HIEZST00sIE9VVCBPRiBPUiBJTiBDT05ORUNUSU9OIFdJVEggVEhFIFNPRlRXQVJFIE9SIFRIRVxuLy8gVVNFIE9SIE9USEVSIERFQUxJTkdTIElOIFRIRSBTT0ZUV0FSRS5cblxuZnVuY3Rpb24gRXZlbnRFbWl0dGVyKCkge1xuICB0aGlzLl9ldmVudHMgPSB0aGlzLl9ldmVudHMgfHwge307XG4gIHRoaXMuX21heExpc3RlbmVycyA9IHRoaXMuX21heExpc3RlbmVycyB8fCB1bmRlZmluZWQ7XG59XG5tb2R1bGUuZXhwb3J0cyA9IEV2ZW50RW1pdHRlcjtcblxuLy8gQmFja3dhcmRzLWNvbXBhdCB3aXRoIG5vZGUgMC4xMC54XG5FdmVudEVtaXR0ZXIuRXZlbnRFbWl0dGVyID0gRXZlbnRFbWl0dGVyO1xuXG5FdmVudEVtaXR0ZXIucHJvdG90eXBlLl9ldmVudHMgPSB1bmRlZmluZWQ7XG5FdmVudEVtaXR0ZXIucHJvdG90eXBlLl9tYXhMaXN0ZW5lcnMgPSB1bmRlZmluZWQ7XG5cbi8vIEJ5IGRlZmF1bHQgRXZlbnRFbWl0dGVycyB3aWxsIHByaW50IGEgd2FybmluZyBpZiBtb3JlIHRoYW4gMTAgbGlzdGVuZXJzIGFyZVxuLy8gYWRkZWQgdG8gaXQuIFRoaXMgaXMgYSB1c2VmdWwgZGVmYXVsdCB3aGljaCBoZWxwcyBmaW5kaW5nIG1lbW9yeSBsZWFrcy5cbkV2ZW50RW1pdHRlci5kZWZhdWx0TWF4TGlzdGVuZXJzID0gMTA7XG5cbi8vIE9idmlvdXNseSBub3QgYWxsIEVtaXR0ZXJzIHNob3VsZCBiZSBsaW1pdGVkIHRvIDEwLiBUaGlzIGZ1bmN0aW9uIGFsbG93c1xuLy8gdGhhdCB0byBiZSBpbmNyZWFzZWQuIFNldCB0byB6ZXJvIGZvciB1bmxpbWl0ZWQuXG5FdmVudEVtaXR0ZXIucHJvdG90eXBlLnNldE1heExpc3RlbmVycyA9IGZ1bmN0aW9uKG4pIHtcbiAgaWYgKCFpc051bWJlcihuKSB8fCBuIDwgMCB8fCBpc05hTihuKSlcbiAgICB0aHJvdyBUeXBlRXJyb3IoJ24gbXVzdCBiZSBhIHBvc2l0aXZlIG51bWJlcicpO1xuICB0aGlzLl9tYXhMaXN0ZW5lcnMgPSBuO1xuICByZXR1cm4gdGhpcztcbn07XG5cbkV2ZW50RW1pdHRlci5wcm90b3R5cGUuZW1pdCA9IGZ1bmN0aW9uKHR5cGUpIHtcbiAgdmFyIGVyLCBoYW5kbGVyLCBsZW4sIGFyZ3MsIGksIGxpc3RlbmVycztcblxuICBpZiAoIXRoaXMuX2V2ZW50cylcbiAgICB0aGlzLl9ldmVudHMgPSB7fTtcblxuICAvLyBJZiB0aGVyZSBpcyBubyAnZXJyb3InIGV2ZW50IGxpc3RlbmVyIHRoZW4gdGhyb3cuXG4gIGlmICh0eXBlID09PSAnZXJyb3InKSB7XG4gICAgaWYgKCF0aGlzLl9ldmVudHMuZXJyb3IgfHxcbiAgICAgICAgKGlzT2JqZWN0KHRoaXMuX2V2ZW50cy5lcnJvcikgJiYgIXRoaXMuX2V2ZW50cy5lcnJvci5sZW5ndGgpKSB7XG4gICAgICBlciA9IGFyZ3VtZW50c1sxXTtcbiAgICAgIGlmIChlciBpbnN0YW5jZW9mIEVycm9yKSB7XG4gICAgICAgIHRocm93IGVyOyAvLyBVbmhhbmRsZWQgJ2Vycm9yJyBldmVudFxuICAgICAgfVxuICAgICAgdGhyb3cgVHlwZUVycm9yKCdVbmNhdWdodCwgdW5zcGVjaWZpZWQgXCJlcnJvclwiIGV2ZW50LicpO1xuICAgIH1cbiAgfVxuXG4gIGhhbmRsZXIgPSB0aGlzLl9ldmVudHNbdHlwZV07XG5cbiAgaWYgKGlzVW5kZWZpbmVkKGhhbmRsZXIpKVxuICAgIHJldHVybiBmYWxzZTtcblxuICBpZiAoaXNGdW5jdGlvbihoYW5kbGVyKSkge1xuICAgIHN3aXRjaCAoYXJndW1lbnRzLmxlbmd0aCkge1xuICAgICAgLy8gZmFzdCBjYXNlc1xuICAgICAgY2FzZSAxOlxuICAgICAgICBoYW5kbGVyLmNhbGwodGhpcyk7XG4gICAgICAgIGJyZWFrO1xuICAgICAgY2FzZSAyOlxuICAgICAgICBoYW5kbGVyLmNhbGwodGhpcywgYXJndW1lbnRzWzFdKTtcbiAgICAgICAgYnJlYWs7XG4gICAgICBjYXNlIDM6XG4gICAgICAgIGhhbmRsZXIuY2FsbCh0aGlzLCBhcmd1bWVudHNbMV0sIGFyZ3VtZW50c1syXSk7XG4gICAgICAgIGJyZWFrO1xuICAgICAgLy8gc2xvd2VyXG4gICAgICBkZWZhdWx0OlxuICAgICAgICBsZW4gPSBhcmd1bWVudHMubGVuZ3RoO1xuICAgICAgICBhcmdzID0gbmV3IEFycmF5KGxlbiAtIDEpO1xuICAgICAgICBmb3IgKGkgPSAxOyBpIDwgbGVuOyBpKyspXG4gICAgICAgICAgYXJnc1tpIC0gMV0gPSBhcmd1bWVudHNbaV07XG4gICAgICAgIGhhbmRsZXIuYXBwbHkodGhpcywgYXJncyk7XG4gICAgfVxuICB9IGVsc2UgaWYgKGlzT2JqZWN0KGhhbmRsZXIpKSB7XG4gICAgbGVuID0gYXJndW1lbnRzLmxlbmd0aDtcbiAgICBhcmdzID0gbmV3IEFycmF5KGxlbiAtIDEpO1xuICAgIGZvciAoaSA9IDE7IGkgPCBsZW47IGkrKylcbiAgICAgIGFyZ3NbaSAtIDFdID0gYXJndW1lbnRzW2ldO1xuXG4gICAgbGlzdGVuZXJzID0gaGFuZGxlci5zbGljZSgpO1xuICAgIGxlbiA9IGxpc3RlbmVycy5sZW5ndGg7XG4gICAgZm9yIChpID0gMDsgaSA8IGxlbjsgaSsrKVxuICAgICAgbGlzdGVuZXJzW2ldLmFwcGx5KHRoaXMsIGFyZ3MpO1xuICB9XG5cbiAgcmV0dXJuIHRydWU7XG59O1xuXG5FdmVudEVtaXR0ZXIucHJvdG90eXBlLmFkZExpc3RlbmVyID0gZnVuY3Rpb24odHlwZSwgbGlzdGVuZXIpIHtcbiAgdmFyIG07XG5cbiAgaWYgKCFpc0Z1bmN0aW9uKGxpc3RlbmVyKSlcbiAgICB0aHJvdyBUeXBlRXJyb3IoJ2xpc3RlbmVyIG11c3QgYmUgYSBmdW5jdGlvbicpO1xuXG4gIGlmICghdGhpcy5fZXZlbnRzKVxuICAgIHRoaXMuX2V2ZW50cyA9IHt9O1xuXG4gIC8vIFRvIGF2b2lkIHJlY3Vyc2lvbiBpbiB0aGUgY2FzZSB0aGF0IHR5cGUgPT09IFwibmV3TGlzdGVuZXJcIiEgQmVmb3JlXG4gIC8vIGFkZGluZyBpdCB0byB0aGUgbGlzdGVuZXJzLCBmaXJzdCBlbWl0IFwibmV3TGlzdGVuZXJcIi5cbiAgaWYgKHRoaXMuX2V2ZW50cy5uZXdMaXN0ZW5lcilcbiAgICB0aGlzLmVtaXQoJ25ld0xpc3RlbmVyJywgdHlwZSxcbiAgICAgICAgICAgICAgaXNGdW5jdGlvbihsaXN0ZW5lci5saXN0ZW5lcikgP1xuICAgICAgICAgICAgICBsaXN0ZW5lci5saXN0ZW5lciA6IGxpc3RlbmVyKTtcblxuICBpZiAoIXRoaXMuX2V2ZW50c1t0eXBlXSlcbiAgICAvLyBPcHRpbWl6ZSB0aGUgY2FzZSBvZiBvbmUgbGlzdGVuZXIuIERvbid0IG5lZWQgdGhlIGV4dHJhIGFycmF5IG9iamVjdC5cbiAgICB0aGlzLl9ldmVudHNbdHlwZV0gPSBsaXN0ZW5lcjtcbiAgZWxzZSBpZiAoaXNPYmplY3QodGhpcy5fZXZlbnRzW3R5cGVdKSlcbiAgICAvLyBJZiB3ZSd2ZSBhbHJlYWR5IGdvdCBhbiBhcnJheSwganVzdCBhcHBlbmQuXG4gICAgdGhpcy5fZXZlbnRzW3R5cGVdLnB1c2gobGlzdGVuZXIpO1xuICBlbHNlXG4gICAgLy8gQWRkaW5nIHRoZSBzZWNvbmQgZWxlbWVudCwgbmVlZCB0byBjaGFuZ2UgdG8gYXJyYXkuXG4gICAgdGhpcy5fZXZlbnRzW3R5cGVdID0gW3RoaXMuX2V2ZW50c1t0eXBlXSwgbGlzdGVuZXJdO1xuXG4gIC8vIENoZWNrIGZvciBsaXN0ZW5lciBsZWFrXG4gIGlmIChpc09iamVjdCh0aGlzLl9ldmVudHNbdHlwZV0pICYmICF0aGlzLl9ldmVudHNbdHlwZV0ud2FybmVkKSB7XG4gICAgdmFyIG07XG4gICAgaWYgKCFpc1VuZGVmaW5lZCh0aGlzLl9tYXhMaXN0ZW5lcnMpKSB7XG4gICAgICBtID0gdGhpcy5fbWF4TGlzdGVuZXJzO1xuICAgIH0gZWxzZSB7XG4gICAgICBtID0gRXZlbnRFbWl0dGVyLmRlZmF1bHRNYXhMaXN0ZW5lcnM7XG4gICAgfVxuXG4gICAgaWYgKG0gJiYgbSA+IDAgJiYgdGhpcy5fZXZlbnRzW3R5cGVdLmxlbmd0aCA+IG0pIHtcbiAgICAgIHRoaXMuX2V2ZW50c1t0eXBlXS53YXJuZWQgPSB0cnVlO1xuICAgICAgY29uc29sZS5lcnJvcignKG5vZGUpIHdhcm5pbmc6IHBvc3NpYmxlIEV2ZW50RW1pdHRlciBtZW1vcnkgJyArXG4gICAgICAgICAgICAgICAgICAgICdsZWFrIGRldGVjdGVkLiAlZCBsaXN0ZW5lcnMgYWRkZWQuICcgK1xuICAgICAgICAgICAgICAgICAgICAnVXNlIGVtaXR0ZXIuc2V0TWF4TGlzdGVuZXJzKCkgdG8gaW5jcmVhc2UgbGltaXQuJyxcbiAgICAgICAgICAgICAgICAgICAgdGhpcy5fZXZlbnRzW3R5cGVdLmxlbmd0aCk7XG4gICAgICBpZiAodHlwZW9mIGNvbnNvbGUudHJhY2UgPT09ICdmdW5jdGlvbicpIHtcbiAgICAgICAgLy8gbm90IHN1cHBvcnRlZCBpbiBJRSAxMFxuICAgICAgICBjb25zb2xlLnRyYWNlKCk7XG4gICAgICB9XG4gICAgfVxuICB9XG5cbiAgcmV0dXJuIHRoaXM7XG59O1xuXG5FdmVudEVtaXR0ZXIucHJvdG90eXBlLm9uID0gRXZlbnRFbWl0dGVyLnByb3RvdHlwZS5hZGRMaXN0ZW5lcjtcblxuRXZlbnRFbWl0dGVyLnByb3RvdHlwZS5vbmNlID0gZnVuY3Rpb24odHlwZSwgbGlzdGVuZXIpIHtcbiAgaWYgKCFpc0Z1bmN0aW9uKGxpc3RlbmVyKSlcbiAgICB0aHJvdyBUeXBlRXJyb3IoJ2xpc3RlbmVyIG11c3QgYmUgYSBmdW5jdGlvbicpO1xuXG4gIHZhciBmaXJlZCA9IGZhbHNlO1xuXG4gIGZ1bmN0aW9uIGcoKSB7XG4gICAgdGhpcy5yZW1vdmVMaXN0ZW5lcih0eXBlLCBnKTtcblxuICAgIGlmICghZmlyZWQpIHtcbiAgICAgIGZpcmVkID0gdHJ1ZTtcbiAgICAgIGxpc3RlbmVyLmFwcGx5KHRoaXMsIGFyZ3VtZW50cyk7XG4gICAgfVxuICB9XG5cbiAgZy5saXN0ZW5lciA9IGxpc3RlbmVyO1xuICB0aGlzLm9uKHR5cGUsIGcpO1xuXG4gIHJldHVybiB0aGlzO1xufTtcblxuLy8gZW1pdHMgYSAncmVtb3ZlTGlzdGVuZXInIGV2ZW50IGlmZiB0aGUgbGlzdGVuZXIgd2FzIHJlbW92ZWRcbkV2ZW50RW1pdHRlci5wcm90b3R5cGUucmVtb3ZlTGlzdGVuZXIgPSBmdW5jdGlvbih0eXBlLCBsaXN0ZW5lcikge1xuICB2YXIgbGlzdCwgcG9zaXRpb24sIGxlbmd0aCwgaTtcblxuICBpZiAoIWlzRnVuY3Rpb24obGlzdGVuZXIpKVxuICAgIHRocm93IFR5cGVFcnJvcignbGlzdGVuZXIgbXVzdCBiZSBhIGZ1bmN0aW9uJyk7XG5cbiAgaWYgKCF0aGlzLl9ldmVudHMgfHwgIXRoaXMuX2V2ZW50c1t0eXBlXSlcbiAgICByZXR1cm4gdGhpcztcblxuICBsaXN0ID0gdGhpcy5fZXZlbnRzW3R5cGVdO1xuICBsZW5ndGggPSBsaXN0Lmxlbmd0aDtcbiAgcG9zaXRpb24gPSAtMTtcblxuICBpZiAobGlzdCA9PT0gbGlzdGVuZXIgfHxcbiAgICAgIChpc0Z1bmN0aW9uKGxpc3QubGlzdGVuZXIpICYmIGxpc3QubGlzdGVuZXIgPT09IGxpc3RlbmVyKSkge1xuICAgIGRlbGV0ZSB0aGlzLl9ldmVudHNbdHlwZV07XG4gICAgaWYgKHRoaXMuX2V2ZW50cy5yZW1vdmVMaXN0ZW5lcilcbiAgICAgIHRoaXMuZW1pdCgncmVtb3ZlTGlzdGVuZXInLCB0eXBlLCBsaXN0ZW5lcik7XG5cbiAgfSBlbHNlIGlmIChpc09iamVjdChsaXN0KSkge1xuICAgIGZvciAoaSA9IGxlbmd0aDsgaS0tID4gMDspIHtcbiAgICAgIGlmIChsaXN0W2ldID09PSBsaXN0ZW5lciB8fFxuICAgICAgICAgIChsaXN0W2ldLmxpc3RlbmVyICYmIGxpc3RbaV0ubGlzdGVuZXIgPT09IGxpc3RlbmVyKSkge1xuICAgICAgICBwb3NpdGlvbiA9IGk7XG4gICAgICAgIGJyZWFrO1xuICAgICAgfVxuICAgIH1cblxuICAgIGlmIChwb3NpdGlvbiA8IDApXG4gICAgICByZXR1cm4gdGhpcztcblxuICAgIGlmIChsaXN0Lmxlbmd0aCA9PT0gMSkge1xuICAgICAgbGlzdC5sZW5ndGggPSAwO1xuICAgICAgZGVsZXRlIHRoaXMuX2V2ZW50c1t0eXBlXTtcbiAgICB9IGVsc2Uge1xuICAgICAgbGlzdC5zcGxpY2UocG9zaXRpb24sIDEpO1xuICAgIH1cblxuICAgIGlmICh0aGlzLl9ldmVudHMucmVtb3ZlTGlzdGVuZXIpXG4gICAgICB0aGlzLmVtaXQoJ3JlbW92ZUxpc3RlbmVyJywgdHlwZSwgbGlzdGVuZXIpO1xuICB9XG5cbiAgcmV0dXJuIHRoaXM7XG59O1xuXG5FdmVudEVtaXR0ZXIucHJvdG90eXBlLnJlbW92ZUFsbExpc3RlbmVycyA9IGZ1bmN0aW9uKHR5cGUpIHtcbiAgdmFyIGtleSwgbGlzdGVuZXJzO1xuXG4gIGlmICghdGhpcy5fZXZlbnRzKVxuICAgIHJldHVybiB0aGlzO1xuXG4gIC8vIG5vdCBsaXN0ZW5pbmcgZm9yIHJlbW92ZUxpc3RlbmVyLCBubyBuZWVkIHRvIGVtaXRcbiAgaWYgKCF0aGlzLl9ldmVudHMucmVtb3ZlTGlzdGVuZXIpIHtcbiAgICBpZiAoYXJndW1lbnRzLmxlbmd0aCA9PT0gMClcbiAgICAgIHRoaXMuX2V2ZW50cyA9IHt9O1xuICAgIGVsc2UgaWYgKHRoaXMuX2V2ZW50c1t0eXBlXSlcbiAgICAgIGRlbGV0ZSB0aGlzLl9ldmVudHNbdHlwZV07XG4gICAgcmV0dXJuIHRoaXM7XG4gIH1cblxuICAvLyBlbWl0IHJlbW92ZUxpc3RlbmVyIGZvciBhbGwgbGlzdGVuZXJzIG9uIGFsbCBldmVudHNcbiAgaWYgKGFyZ3VtZW50cy5sZW5ndGggPT09IDApIHtcbiAgICBmb3IgKGtleSBpbiB0aGlzLl9ldmVudHMpIHtcbiAgICAgIGlmIChrZXkgPT09ICdyZW1vdmVMaXN0ZW5lcicpIGNvbnRpbnVlO1xuICAgICAgdGhpcy5yZW1vdmVBbGxMaXN0ZW5lcnMoa2V5KTtcbiAgICB9XG4gICAgdGhpcy5yZW1vdmVBbGxMaXN0ZW5lcnMoJ3JlbW92ZUxpc3RlbmVyJyk7XG4gICAgdGhpcy5fZXZlbnRzID0ge307XG4gICAgcmV0dXJuIHRoaXM7XG4gIH1cblxuICBsaXN0ZW5lcnMgPSB0aGlzLl9ldmVudHNbdHlwZV07XG5cbiAgaWYgKGlzRnVuY3Rpb24obGlzdGVuZXJzKSkge1xuICAgIHRoaXMucmVtb3ZlTGlzdGVuZXIodHlwZSwgbGlzdGVuZXJzKTtcbiAgfSBlbHNlIHtcbiAgICAvLyBMSUZPIG9yZGVyXG4gICAgd2hpbGUgKGxpc3RlbmVycy5sZW5ndGgpXG4gICAgICB0aGlzLnJlbW92ZUxpc3RlbmVyKHR5cGUsIGxpc3RlbmVyc1tsaXN0ZW5lcnMubGVuZ3RoIC0gMV0pO1xuICB9XG4gIGRlbGV0ZSB0aGlzLl9ldmVudHNbdHlwZV07XG5cbiAgcmV0dXJuIHRoaXM7XG59O1xuXG5FdmVudEVtaXR0ZXIucHJvdG90eXBlLmxpc3RlbmVycyA9IGZ1bmN0aW9uKHR5cGUpIHtcbiAgdmFyIHJldDtcbiAgaWYgKCF0aGlzLl9ldmVudHMgfHwgIXRoaXMuX2V2ZW50c1t0eXBlXSlcbiAgICByZXQgPSBbXTtcbiAgZWxzZSBpZiAoaXNGdW5jdGlvbih0aGlzLl9ldmVudHNbdHlwZV0pKVxuICAgIHJldCA9IFt0aGlzLl9ldmVudHNbdHlwZV1dO1xuICBlbHNlXG4gICAgcmV0ID0gdGhpcy5fZXZlbnRzW3R5cGVdLnNsaWNlKCk7XG4gIHJldHVybiByZXQ7XG59O1xuXG5FdmVudEVtaXR0ZXIubGlzdGVuZXJDb3VudCA9IGZ1bmN0aW9uKGVtaXR0ZXIsIHR5cGUpIHtcbiAgdmFyIHJldDtcbiAgaWYgKCFlbWl0dGVyLl9ldmVudHMgfHwgIWVtaXR0ZXIuX2V2ZW50c1t0eXBlXSlcbiAgICByZXQgPSAwO1xuICBlbHNlIGlmIChpc0Z1bmN0aW9uKGVtaXR0ZXIuX2V2ZW50c1t0eXBlXSkpXG4gICAgcmV0ID0gMTtcbiAgZWxzZVxuICAgIHJldCA9IGVtaXR0ZXIuX2V2ZW50c1t0eXBlXS5sZW5ndGg7XG4gIHJldHVybiByZXQ7XG59O1xuXG5mdW5jdGlvbiBpc0Z1bmN0aW9uKGFyZykge1xuICByZXR1cm4gdHlwZW9mIGFyZyA9PT0gJ2Z1bmN0aW9uJztcbn1cblxuZnVuY3Rpb24gaXNOdW1iZXIoYXJnKSB7XG4gIHJldHVybiB0eXBlb2YgYXJnID09PSAnbnVtYmVyJztcbn1cblxuZnVuY3Rpb24gaXNPYmplY3QoYXJnKSB7XG4gIHJldHVybiB0eXBlb2YgYXJnID09PSAnb2JqZWN0JyAmJiBhcmcgIT09IG51bGw7XG59XG5cbmZ1bmN0aW9uIGlzVW5kZWZpbmVkKGFyZykge1xuICByZXR1cm4gYXJnID09PSB2b2lkIDA7XG59XG4iLCIvLyBzaGltIGZvciB1c2luZyBwcm9jZXNzIGluIGJyb3dzZXJcblxudmFyIHByb2Nlc3MgPSBtb2R1bGUuZXhwb3J0cyA9IHt9O1xudmFyIHF1ZXVlID0gW107XG52YXIgZHJhaW5pbmcgPSBmYWxzZTtcbnZhciBjdXJyZW50UXVldWU7XG52YXIgcXVldWVJbmRleCA9IC0xO1xuXG5mdW5jdGlvbiBjbGVhblVwTmV4dFRpY2soKSB7XG4gICAgZHJhaW5pbmcgPSBmYWxzZTtcbiAgICBpZiAoY3VycmVudFF1ZXVlLmxlbmd0aCkge1xuICAgICAgICBxdWV1ZSA9IGN1cnJlbnRRdWV1ZS5jb25jYXQocXVldWUpO1xuICAgIH0gZWxzZSB7XG4gICAgICAgIHF1ZXVlSW5kZXggPSAtMTtcbiAgICB9XG4gICAgaWYgKHF1ZXVlLmxlbmd0aCkge1xuICAgICAgICBkcmFpblF1ZXVlKCk7XG4gICAgfVxufVxuXG5mdW5jdGlvbiBkcmFpblF1ZXVlKCkge1xuICAgIGlmIChkcmFpbmluZykge1xuICAgICAgICByZXR1cm47XG4gICAgfVxuICAgIHZhciB0aW1lb3V0ID0gc2V0VGltZW91dChjbGVhblVwTmV4dFRpY2spO1xuICAgIGRyYWluaW5nID0gdHJ1ZTtcblxuICAgIHZhciBsZW4gPSBxdWV1ZS5sZW5ndGg7XG4gICAgd2hpbGUobGVuKSB7XG4gICAgICAgIGN1cnJlbnRRdWV1ZSA9IHF1ZXVlO1xuICAgICAgICBxdWV1ZSA9IFtdO1xuICAgICAgICB3aGlsZSAoKytxdWV1ZUluZGV4IDwgbGVuKSB7XG4gICAgICAgICAgICBpZiAoY3VycmVudFF1ZXVlKSB7XG4gICAgICAgICAgICAgICAgY3VycmVudFF1ZXVlW3F1ZXVlSW5kZXhdLnJ1bigpO1xuICAgICAgICAgICAgfVxuICAgICAgICB9XG4gICAgICAgIHF1ZXVlSW5kZXggPSAtMTtcbiAgICAgICAgbGVuID0gcXVldWUubGVuZ3RoO1xuICAgIH1cbiAgICBjdXJyZW50UXVldWUgPSBudWxsO1xuICAgIGRyYWluaW5nID0gZmFsc2U7XG4gICAgY2xlYXJUaW1lb3V0KHRpbWVvdXQpO1xufVxuXG5wcm9jZXNzLm5leHRUaWNrID0gZnVuY3Rpb24gKGZ1bikge1xuICAgIHZhciBhcmdzID0gbmV3IEFycmF5KGFyZ3VtZW50cy5sZW5ndGggLSAxKTtcbiAgICBpZiAoYXJndW1lbnRzLmxlbmd0aCA+IDEpIHtcbiAgICAgICAgZm9yICh2YXIgaSA9IDE7IGkgPCBhcmd1bWVudHMubGVuZ3RoOyBpKyspIHtcbiAgICAgICAgICAgIGFyZ3NbaSAtIDFdID0gYXJndW1lbnRzW2ldO1xuICAgICAgICB9XG4gICAgfVxuICAgIHF1ZXVlLnB1c2gobmV3IEl0ZW0oZnVuLCBhcmdzKSk7XG4gICAgaWYgKHF1ZXVlLmxlbmd0aCA9PT0gMSAmJiAhZHJhaW5pbmcpIHtcbiAgICAgICAgc2V0VGltZW91dChkcmFpblF1ZXVlLCAwKTtcbiAgICB9XG59O1xuXG4vLyB2OCBsaWtlcyBwcmVkaWN0aWJsZSBvYmplY3RzXG5mdW5jdGlvbiBJdGVtKGZ1biwgYXJyYXkpIHtcbiAgICB0aGlzLmZ1biA9IGZ1bjtcbiAgICB0aGlzLmFycmF5ID0gYXJyYXk7XG59XG5JdGVtLnByb3RvdHlwZS5ydW4gPSBmdW5jdGlvbiAoKSB7XG4gICAgdGhpcy5mdW4uYXBwbHkobnVsbCwgdGhpcy5hcnJheSk7XG59O1xucHJvY2Vzcy50aXRsZSA9ICdicm93c2VyJztcbnByb2Nlc3MuYnJvd3NlciA9IHRydWU7XG5wcm9jZXNzLmVudiA9IHt9O1xucHJvY2Vzcy5hcmd2ID0gW107XG5wcm9jZXNzLnZlcnNpb24gPSAnJzsgLy8gZW1wdHkgc3RyaW5nIHRvIGF2b2lkIHJlZ2V4cCBpc3N1ZXNcbnByb2Nlc3MudmVyc2lvbnMgPSB7fTtcblxuZnVuY3Rpb24gbm9vcCgpIHt9XG5cbnByb2Nlc3Mub24gPSBub29wO1xucHJvY2Vzcy5hZGRMaXN0ZW5lciA9IG5vb3A7XG5wcm9jZXNzLm9uY2UgPSBub29wO1xucHJvY2Vzcy5vZmYgPSBub29wO1xucHJvY2Vzcy5yZW1vdmVMaXN0ZW5lciA9IG5vb3A7XG5wcm9jZXNzLnJlbW92ZUFsbExpc3RlbmVycyA9IG5vb3A7XG5wcm9jZXNzLmVtaXQgPSBub29wO1xuXG5wcm9jZXNzLmJpbmRpbmcgPSBmdW5jdGlvbiAobmFtZSkge1xuICAgIHRocm93IG5ldyBFcnJvcigncHJvY2Vzcy5iaW5kaW5nIGlzIG5vdCBzdXBwb3J0ZWQnKTtcbn07XG5cbnByb2Nlc3MuY3dkID0gZnVuY3Rpb24gKCkgeyByZXR1cm4gJy8nIH07XG5wcm9jZXNzLmNoZGlyID0gZnVuY3Rpb24gKGRpcikge1xuICAgIHRocm93IG5ldyBFcnJvcigncHJvY2Vzcy5jaGRpciBpcyBub3Qgc3VwcG9ydGVkJyk7XG59O1xucHJvY2Vzcy51bWFzayA9IGZ1bmN0aW9uKCkgeyByZXR1cm4gMDsgfTtcbiIsIi8qIVxuICogQG92ZXJ2aWV3IGVzNi1wcm9taXNlIC0gYSB0aW55IGltcGxlbWVudGF0aW9uIG9mIFByb21pc2VzL0ErLlxuICogQGNvcHlyaWdodCBDb3B5cmlnaHQgKGMpIDIwMTQgWWVodWRhIEthdHosIFRvbSBEYWxlLCBTdGVmYW4gUGVubmVyIGFuZCBjb250cmlidXRvcnMgKENvbnZlcnNpb24gdG8gRVM2IEFQSSBieSBKYWtlIEFyY2hpYmFsZClcbiAqIEBsaWNlbnNlICAgTGljZW5zZWQgdW5kZXIgTUlUIGxpY2Vuc2VcbiAqICAgICAgICAgICAgU2VlIGh0dHBzOi8vcmF3LmdpdGh1YnVzZXJjb250ZW50LmNvbS9qYWtlYXJjaGliYWxkL2VzNi1wcm9taXNlL21hc3Rlci9MSUNFTlNFXG4gKiBAdmVyc2lvbiAgIDMuMC4yXG4gKi9cblxuKGZ1bmN0aW9uKCkge1xuICAgIFwidXNlIHN0cmljdFwiO1xuICAgIGZ1bmN0aW9uIGxpYiRlczYkcHJvbWlzZSR1dGlscyQkb2JqZWN0T3JGdW5jdGlvbih4KSB7XG4gICAgICByZXR1cm4gdHlwZW9mIHggPT09ICdmdW5jdGlvbicgfHwgKHR5cGVvZiB4ID09PSAnb2JqZWN0JyAmJiB4ICE9PSBudWxsKTtcbiAgICB9XG5cbiAgICBmdW5jdGlvbiBsaWIkZXM2JHByb21pc2UkdXRpbHMkJGlzRnVuY3Rpb24oeCkge1xuICAgICAgcmV0dXJuIHR5cGVvZiB4ID09PSAnZnVuY3Rpb24nO1xuICAgIH1cblxuICAgIGZ1bmN0aW9uIGxpYiRlczYkcHJvbWlzZSR1dGlscyQkaXNNYXliZVRoZW5hYmxlKHgpIHtcbiAgICAgIHJldHVybiB0eXBlb2YgeCA9PT0gJ29iamVjdCcgJiYgeCAhPT0gbnVsbDtcbiAgICB9XG5cbiAgICB2YXIgbGliJGVzNiRwcm9taXNlJHV0aWxzJCRfaXNBcnJheTtcbiAgICBpZiAoIUFycmF5LmlzQXJyYXkpIHtcbiAgICAgIGxpYiRlczYkcHJvbWlzZSR1dGlscyQkX2lzQXJyYXkgPSBmdW5jdGlvbiAoeCkge1xuICAgICAgICByZXR1cm4gT2JqZWN0LnByb3RvdHlwZS50b1N0cmluZy5jYWxsKHgpID09PSAnW29iamVjdCBBcnJheV0nO1xuICAgICAgfTtcbiAgICB9IGVsc2Uge1xuICAgICAgbGliJGVzNiRwcm9taXNlJHV0aWxzJCRfaXNBcnJheSA9IEFycmF5LmlzQXJyYXk7XG4gICAgfVxuXG4gICAgdmFyIGxpYiRlczYkcHJvbWlzZSR1dGlscyQkaXNBcnJheSA9IGxpYiRlczYkcHJvbWlzZSR1dGlscyQkX2lzQXJyYXk7XG4gICAgdmFyIGxpYiRlczYkcHJvbWlzZSRhc2FwJCRsZW4gPSAwO1xuICAgIHZhciBsaWIkZXM2JHByb21pc2UkYXNhcCQkdG9TdHJpbmcgPSB7fS50b1N0cmluZztcbiAgICB2YXIgbGliJGVzNiRwcm9taXNlJGFzYXAkJHZlcnR4TmV4dDtcbiAgICB2YXIgbGliJGVzNiRwcm9taXNlJGFzYXAkJGN1c3RvbVNjaGVkdWxlckZuO1xuXG4gICAgdmFyIGxpYiRlczYkcHJvbWlzZSRhc2FwJCRhc2FwID0gZnVuY3Rpb24gYXNhcChjYWxsYmFjaywgYXJnKSB7XG4gICAgICBsaWIkZXM2JHByb21pc2UkYXNhcCQkcXVldWVbbGliJGVzNiRwcm9taXNlJGFzYXAkJGxlbl0gPSBjYWxsYmFjaztcbiAgICAgIGxpYiRlczYkcHJvbWlzZSRhc2FwJCRxdWV1ZVtsaWIkZXM2JHByb21pc2UkYXNhcCQkbGVuICsgMV0gPSBhcmc7XG4gICAgICBsaWIkZXM2JHByb21pc2UkYXNhcCQkbGVuICs9IDI7XG4gICAgICBpZiAobGliJGVzNiRwcm9taXNlJGFzYXAkJGxlbiA9PT0gMikge1xuICAgICAgICAvLyBJZiBsZW4gaXMgMiwgdGhhdCBtZWFucyB0aGF0IHdlIG5lZWQgdG8gc2NoZWR1bGUgYW4gYXN5bmMgZmx1c2guXG4gICAgICAgIC8vIElmIGFkZGl0aW9uYWwgY2FsbGJhY2tzIGFyZSBxdWV1ZWQgYmVmb3JlIHRoZSBxdWV1ZSBpcyBmbHVzaGVkLCB0aGV5XG4gICAgICAgIC8vIHdpbGwgYmUgcHJvY2Vzc2VkIGJ5IHRoaXMgZmx1c2ggdGhhdCB3ZSBhcmUgc2NoZWR1bGluZy5cbiAgICAgICAgaWYgKGxpYiRlczYkcHJvbWlzZSRhc2FwJCRjdXN0b21TY2hlZHVsZXJGbikge1xuICAgICAgICAgIGxpYiRlczYkcHJvbWlzZSRhc2FwJCRjdXN0b21TY2hlZHVsZXJGbihsaWIkZXM2JHByb21pc2UkYXNhcCQkZmx1c2gpO1xuICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgIGxpYiRlczYkcHJvbWlzZSRhc2FwJCRzY2hlZHVsZUZsdXNoKCk7XG4gICAgICAgIH1cbiAgICAgIH1cbiAgICB9XG5cbiAgICBmdW5jdGlvbiBsaWIkZXM2JHByb21pc2UkYXNhcCQkc2V0U2NoZWR1bGVyKHNjaGVkdWxlRm4pIHtcbiAgICAgIGxpYiRlczYkcHJvbWlzZSRhc2FwJCRjdXN0b21TY2hlZHVsZXJGbiA9IHNjaGVkdWxlRm47XG4gICAgfVxuXG4gICAgZnVuY3Rpb24gbGliJGVzNiRwcm9taXNlJGFzYXAkJHNldEFzYXAoYXNhcEZuKSB7XG4gICAgICBsaWIkZXM2JHByb21pc2UkYXNhcCQkYXNhcCA9IGFzYXBGbjtcbiAgICB9XG5cbiAgICB2YXIgbGliJGVzNiRwcm9taXNlJGFzYXAkJGJyb3dzZXJXaW5kb3cgPSAodHlwZW9mIHdpbmRvdyAhPT0gJ3VuZGVmaW5lZCcpID8gd2luZG93IDogdW5kZWZpbmVkO1xuICAgIHZhciBsaWIkZXM2JHByb21pc2UkYXNhcCQkYnJvd3Nlckdsb2JhbCA9IGxpYiRlczYkcHJvbWlzZSRhc2FwJCRicm93c2VyV2luZG93IHx8IHt9O1xuICAgIHZhciBsaWIkZXM2JHByb21pc2UkYXNhcCQkQnJvd3Nlck11dGF0aW9uT2JzZXJ2ZXIgPSBsaWIkZXM2JHByb21pc2UkYXNhcCQkYnJvd3Nlckdsb2JhbC5NdXRhdGlvbk9ic2VydmVyIHx8IGxpYiRlczYkcHJvbWlzZSRhc2FwJCRicm93c2VyR2xvYmFsLldlYktpdE11dGF0aW9uT2JzZXJ2ZXI7XG4gICAgdmFyIGxpYiRlczYkcHJvbWlzZSRhc2FwJCRpc05vZGUgPSB0eXBlb2YgcHJvY2VzcyAhPT0gJ3VuZGVmaW5lZCcgJiYge30udG9TdHJpbmcuY2FsbChwcm9jZXNzKSA9PT0gJ1tvYmplY3QgcHJvY2Vzc10nO1xuXG4gICAgLy8gdGVzdCBmb3Igd2ViIHdvcmtlciBidXQgbm90IGluIElFMTBcbiAgICB2YXIgbGliJGVzNiRwcm9taXNlJGFzYXAkJGlzV29ya2VyID0gdHlwZW9mIFVpbnQ4Q2xhbXBlZEFycmF5ICE9PSAndW5kZWZpbmVkJyAmJlxuICAgICAgdHlwZW9mIGltcG9ydFNjcmlwdHMgIT09ICd1bmRlZmluZWQnICYmXG4gICAgICB0eXBlb2YgTWVzc2FnZUNoYW5uZWwgIT09ICd1bmRlZmluZWQnO1xuXG4gICAgLy8gbm9kZVxuICAgIGZ1bmN0aW9uIGxpYiRlczYkcHJvbWlzZSRhc2FwJCR1c2VOZXh0VGljaygpIHtcbiAgICAgIC8vIG5vZGUgdmVyc2lvbiAwLjEwLnggZGlzcGxheXMgYSBkZXByZWNhdGlvbiB3YXJuaW5nIHdoZW4gbmV4dFRpY2sgaXMgdXNlZCByZWN1cnNpdmVseVxuICAgICAgLy8gc2VlIGh0dHBzOi8vZ2l0aHViLmNvbS9jdWpvanMvd2hlbi9pc3N1ZXMvNDEwIGZvciBkZXRhaWxzXG4gICAgICByZXR1cm4gZnVuY3Rpb24oKSB7XG4gICAgICAgIHByb2Nlc3MubmV4dFRpY2sobGliJGVzNiRwcm9taXNlJGFzYXAkJGZsdXNoKTtcbiAgICAgIH07XG4gICAgfVxuXG4gICAgLy8gdmVydHhcbiAgICBmdW5jdGlvbiBsaWIkZXM2JHByb21pc2UkYXNhcCQkdXNlVmVydHhUaW1lcigpIHtcbiAgICAgIHJldHVybiBmdW5jdGlvbigpIHtcbiAgICAgICAgbGliJGVzNiRwcm9taXNlJGFzYXAkJHZlcnR4TmV4dChsaWIkZXM2JHByb21pc2UkYXNhcCQkZmx1c2gpO1xuICAgICAgfTtcbiAgICB9XG5cbiAgICBmdW5jdGlvbiBsaWIkZXM2JHByb21pc2UkYXNhcCQkdXNlTXV0YXRpb25PYnNlcnZlcigpIHtcbiAgICAgIHZhciBpdGVyYXRpb25zID0gMDtcbiAgICAgIHZhciBvYnNlcnZlciA9IG5ldyBsaWIkZXM2JHByb21pc2UkYXNhcCQkQnJvd3Nlck11dGF0aW9uT2JzZXJ2ZXIobGliJGVzNiRwcm9taXNlJGFzYXAkJGZsdXNoKTtcbiAgICAgIHZhciBub2RlID0gZG9jdW1lbnQuY3JlYXRlVGV4dE5vZGUoJycpO1xuICAgICAgb2JzZXJ2ZXIub2JzZXJ2ZShub2RlLCB7IGNoYXJhY3RlckRhdGE6IHRydWUgfSk7XG5cbiAgICAgIHJldHVybiBmdW5jdGlvbigpIHtcbiAgICAgICAgbm9kZS5kYXRhID0gKGl0ZXJhdGlvbnMgPSArK2l0ZXJhdGlvbnMgJSAyKTtcbiAgICAgIH07XG4gICAgfVxuXG4gICAgLy8gd2ViIHdvcmtlclxuICAgIGZ1bmN0aW9uIGxpYiRlczYkcHJvbWlzZSRhc2FwJCR1c2VNZXNzYWdlQ2hhbm5lbCgpIHtcbiAgICAgIHZhciBjaGFubmVsID0gbmV3IE1lc3NhZ2VDaGFubmVsKCk7XG4gICAgICBjaGFubmVsLnBvcnQxLm9ubWVzc2FnZSA9IGxpYiRlczYkcHJvbWlzZSRhc2FwJCRmbHVzaDtcbiAgICAgIHJldHVybiBmdW5jdGlvbiAoKSB7XG4gICAgICAgIGNoYW5uZWwucG9ydDIucG9zdE1lc3NhZ2UoMCk7XG4gICAgICB9O1xuICAgIH1cblxuICAgIGZ1bmN0aW9uIGxpYiRlczYkcHJvbWlzZSRhc2FwJCR1c2VTZXRUaW1lb3V0KCkge1xuICAgICAgcmV0dXJuIGZ1bmN0aW9uKCkge1xuICAgICAgICBzZXRUaW1lb3V0KGxpYiRlczYkcHJvbWlzZSRhc2FwJCRmbHVzaCwgMSk7XG4gICAgICB9O1xuICAgIH1cblxuICAgIHZhciBsaWIkZXM2JHByb21pc2UkYXNhcCQkcXVldWUgPSBuZXcgQXJyYXkoMTAwMCk7XG4gICAgZnVuY3Rpb24gbGliJGVzNiRwcm9taXNlJGFzYXAkJGZsdXNoKCkge1xuICAgICAgZm9yICh2YXIgaSA9IDA7IGkgPCBsaWIkZXM2JHByb21pc2UkYXNhcCQkbGVuOyBpKz0yKSB7XG4gICAgICAgIHZhciBjYWxsYmFjayA9IGxpYiRlczYkcHJvbWlzZSRhc2FwJCRxdWV1ZVtpXTtcbiAgICAgICAgdmFyIGFyZyA9IGxpYiRlczYkcHJvbWlzZSRhc2FwJCRxdWV1ZVtpKzFdO1xuXG4gICAgICAgIGNhbGxiYWNrKGFyZyk7XG5cbiAgICAgICAgbGliJGVzNiRwcm9taXNlJGFzYXAkJHF1ZXVlW2ldID0gdW5kZWZpbmVkO1xuICAgICAgICBsaWIkZXM2JHByb21pc2UkYXNhcCQkcXVldWVbaSsxXSA9IHVuZGVmaW5lZDtcbiAgICAgIH1cblxuICAgICAgbGliJGVzNiRwcm9taXNlJGFzYXAkJGxlbiA9IDA7XG4gICAgfVxuXG4gICAgZnVuY3Rpb24gbGliJGVzNiRwcm9taXNlJGFzYXAkJGF0dGVtcHRWZXJ0eCgpIHtcbiAgICAgIHRyeSB7XG4gICAgICAgIHZhciByID0gcmVxdWlyZTtcbiAgICAgICAgdmFyIHZlcnR4ID0gcigndmVydHgnKTtcbiAgICAgICAgbGliJGVzNiRwcm9taXNlJGFzYXAkJHZlcnR4TmV4dCA9IHZlcnR4LnJ1bk9uTG9vcCB8fCB2ZXJ0eC5ydW5PbkNvbnRleHQ7XG4gICAgICAgIHJldHVybiBsaWIkZXM2JHByb21pc2UkYXNhcCQkdXNlVmVydHhUaW1lcigpO1xuICAgICAgfSBjYXRjaChlKSB7XG4gICAgICAgIHJldHVybiBsaWIkZXM2JHByb21pc2UkYXNhcCQkdXNlU2V0VGltZW91dCgpO1xuICAgICAgfVxuICAgIH1cblxuICAgIHZhciBsaWIkZXM2JHByb21pc2UkYXNhcCQkc2NoZWR1bGVGbHVzaDtcbiAgICAvLyBEZWNpZGUgd2hhdCBhc3luYyBtZXRob2QgdG8gdXNlIHRvIHRyaWdnZXJpbmcgcHJvY2Vzc2luZyBvZiBxdWV1ZWQgY2FsbGJhY2tzOlxuICAgIGlmIChsaWIkZXM2JHByb21pc2UkYXNhcCQkaXNOb2RlKSB7XG4gICAgICBsaWIkZXM2JHByb21pc2UkYXNhcCQkc2NoZWR1bGVGbHVzaCA9IGxpYiRlczYkcHJvbWlzZSRhc2FwJCR1c2VOZXh0VGljaygpO1xuICAgIH0gZWxzZSBpZiAobGliJGVzNiRwcm9taXNlJGFzYXAkJEJyb3dzZXJNdXRhdGlvbk9ic2VydmVyKSB7XG4gICAgICBsaWIkZXM2JHByb21pc2UkYXNhcCQkc2NoZWR1bGVGbHVzaCA9IGxpYiRlczYkcHJvbWlzZSRhc2FwJCR1c2VNdXRhdGlvbk9ic2VydmVyKCk7XG4gICAgfSBlbHNlIGlmIChsaWIkZXM2JHByb21pc2UkYXNhcCQkaXNXb3JrZXIpIHtcbiAgICAgIGxpYiRlczYkcHJvbWlzZSRhc2FwJCRzY2hlZHVsZUZsdXNoID0gbGliJGVzNiRwcm9taXNlJGFzYXAkJHVzZU1lc3NhZ2VDaGFubmVsKCk7XG4gICAgfSBlbHNlIGlmIChsaWIkZXM2JHByb21pc2UkYXNhcCQkYnJvd3NlcldpbmRvdyA9PT0gdW5kZWZpbmVkICYmIHR5cGVvZiByZXF1aXJlID09PSAnZnVuY3Rpb24nKSB7XG4gICAgICBsaWIkZXM2JHByb21pc2UkYXNhcCQkc2NoZWR1bGVGbHVzaCA9IGxpYiRlczYkcHJvbWlzZSRhc2FwJCRhdHRlbXB0VmVydHgoKTtcbiAgICB9IGVsc2Uge1xuICAgICAgbGliJGVzNiRwcm9taXNlJGFzYXAkJHNjaGVkdWxlRmx1c2ggPSBsaWIkZXM2JHByb21pc2UkYXNhcCQkdXNlU2V0VGltZW91dCgpO1xuICAgIH1cblxuICAgIGZ1bmN0aW9uIGxpYiRlczYkcHJvbWlzZSQkaW50ZXJuYWwkJG5vb3AoKSB7fVxuXG4gICAgdmFyIGxpYiRlczYkcHJvbWlzZSQkaW50ZXJuYWwkJFBFTkRJTkcgICA9IHZvaWQgMDtcbiAgICB2YXIgbGliJGVzNiRwcm9taXNlJCRpbnRlcm5hbCQkRlVMRklMTEVEID0gMTtcbiAgICB2YXIgbGliJGVzNiRwcm9taXNlJCRpbnRlcm5hbCQkUkVKRUNURUQgID0gMjtcblxuICAgIHZhciBsaWIkZXM2JHByb21pc2UkJGludGVybmFsJCRHRVRfVEhFTl9FUlJPUiA9IG5ldyBsaWIkZXM2JHByb21pc2UkJGludGVybmFsJCRFcnJvck9iamVjdCgpO1xuXG4gICAgZnVuY3Rpb24gbGliJGVzNiRwcm9taXNlJCRpbnRlcm5hbCQkc2VsZkZ1bGZpbGxtZW50KCkge1xuICAgICAgcmV0dXJuIG5ldyBUeXBlRXJyb3IoXCJZb3UgY2Fubm90IHJlc29sdmUgYSBwcm9taXNlIHdpdGggaXRzZWxmXCIpO1xuICAgIH1cblxuICAgIGZ1bmN0aW9uIGxpYiRlczYkcHJvbWlzZSQkaW50ZXJuYWwkJGNhbm5vdFJldHVybk93bigpIHtcbiAgICAgIHJldHVybiBuZXcgVHlwZUVycm9yKCdBIHByb21pc2VzIGNhbGxiYWNrIGNhbm5vdCByZXR1cm4gdGhhdCBzYW1lIHByb21pc2UuJyk7XG4gICAgfVxuXG4gICAgZnVuY3Rpb24gbGliJGVzNiRwcm9taXNlJCRpbnRlcm5hbCQkZ2V0VGhlbihwcm9taXNlKSB7XG4gICAgICB0cnkge1xuICAgICAgICByZXR1cm4gcHJvbWlzZS50aGVuO1xuICAgICAgfSBjYXRjaChlcnJvcikge1xuICAgICAgICBsaWIkZXM2JHByb21pc2UkJGludGVybmFsJCRHRVRfVEhFTl9FUlJPUi5lcnJvciA9IGVycm9yO1xuICAgICAgICByZXR1cm4gbGliJGVzNiRwcm9taXNlJCRpbnRlcm5hbCQkR0VUX1RIRU5fRVJST1I7XG4gICAgICB9XG4gICAgfVxuXG4gICAgZnVuY3Rpb24gbGliJGVzNiRwcm9taXNlJCRpbnRlcm5hbCQkdHJ5VGhlbih0aGVuLCB2YWx1ZSwgZnVsZmlsbG1lbnRIYW5kbGVyLCByZWplY3Rpb25IYW5kbGVyKSB7XG4gICAgICB0cnkge1xuICAgICAgICB0aGVuLmNhbGwodmFsdWUsIGZ1bGZpbGxtZW50SGFuZGxlciwgcmVqZWN0aW9uSGFuZGxlcik7XG4gICAgICB9IGNhdGNoKGUpIHtcbiAgICAgICAgcmV0dXJuIGU7XG4gICAgICB9XG4gICAgfVxuXG4gICAgZnVuY3Rpb24gbGliJGVzNiRwcm9taXNlJCRpbnRlcm5hbCQkaGFuZGxlRm9yZWlnblRoZW5hYmxlKHByb21pc2UsIHRoZW5hYmxlLCB0aGVuKSB7XG4gICAgICAgbGliJGVzNiRwcm9taXNlJGFzYXAkJGFzYXAoZnVuY3Rpb24ocHJvbWlzZSkge1xuICAgICAgICB2YXIgc2VhbGVkID0gZmFsc2U7XG4gICAgICAgIHZhciBlcnJvciA9IGxpYiRlczYkcHJvbWlzZSQkaW50ZXJuYWwkJHRyeVRoZW4odGhlbiwgdGhlbmFibGUsIGZ1bmN0aW9uKHZhbHVlKSB7XG4gICAgICAgICAgaWYgKHNlYWxlZCkgeyByZXR1cm47IH1cbiAgICAgICAgICBzZWFsZWQgPSB0cnVlO1xuICAgICAgICAgIGlmICh0aGVuYWJsZSAhPT0gdmFsdWUpIHtcbiAgICAgICAgICAgIGxpYiRlczYkcHJvbWlzZSQkaW50ZXJuYWwkJHJlc29sdmUocHJvbWlzZSwgdmFsdWUpO1xuICAgICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICBsaWIkZXM2JHByb21pc2UkJGludGVybmFsJCRmdWxmaWxsKHByb21pc2UsIHZhbHVlKTtcbiAgICAgICAgICB9XG4gICAgICAgIH0sIGZ1bmN0aW9uKHJlYXNvbikge1xuICAgICAgICAgIGlmIChzZWFsZWQpIHsgcmV0dXJuOyB9XG4gICAgICAgICAgc2VhbGVkID0gdHJ1ZTtcblxuICAgICAgICAgIGxpYiRlczYkcHJvbWlzZSQkaW50ZXJuYWwkJHJlamVjdChwcm9taXNlLCByZWFzb24pO1xuICAgICAgICB9LCAnU2V0dGxlOiAnICsgKHByb21pc2UuX2xhYmVsIHx8ICcgdW5rbm93biBwcm9taXNlJykpO1xuXG4gICAgICAgIGlmICghc2VhbGVkICYmIGVycm9yKSB7XG4gICAgICAgICAgc2VhbGVkID0gdHJ1ZTtcbiAgICAgICAgICBsaWIkZXM2JHByb21pc2UkJGludGVybmFsJCRyZWplY3QocHJvbWlzZSwgZXJyb3IpO1xuICAgICAgICB9XG4gICAgICB9LCBwcm9taXNlKTtcbiAgICB9XG5cbiAgICBmdW5jdGlvbiBsaWIkZXM2JHByb21pc2UkJGludGVybmFsJCRoYW5kbGVPd25UaGVuYWJsZShwcm9taXNlLCB0aGVuYWJsZSkge1xuICAgICAgaWYgKHRoZW5hYmxlLl9zdGF0ZSA9PT0gbGliJGVzNiRwcm9taXNlJCRpbnRlcm5hbCQkRlVMRklMTEVEKSB7XG4gICAgICAgIGxpYiRlczYkcHJvbWlzZSQkaW50ZXJuYWwkJGZ1bGZpbGwocHJvbWlzZSwgdGhlbmFibGUuX3Jlc3VsdCk7XG4gICAgICB9IGVsc2UgaWYgKHRoZW5hYmxlLl9zdGF0ZSA9PT0gbGliJGVzNiRwcm9taXNlJCRpbnRlcm5hbCQkUkVKRUNURUQpIHtcbiAgICAgICAgbGliJGVzNiRwcm9taXNlJCRpbnRlcm5hbCQkcmVqZWN0KHByb21pc2UsIHRoZW5hYmxlLl9yZXN1bHQpO1xuICAgICAgfSBlbHNlIHtcbiAgICAgICAgbGliJGVzNiRwcm9taXNlJCRpbnRlcm5hbCQkc3Vic2NyaWJlKHRoZW5hYmxlLCB1bmRlZmluZWQsIGZ1bmN0aW9uKHZhbHVlKSB7XG4gICAgICAgICAgbGliJGVzNiRwcm9taXNlJCRpbnRlcm5hbCQkcmVzb2x2ZShwcm9taXNlLCB2YWx1ZSk7XG4gICAgICAgIH0sIGZ1bmN0aW9uKHJlYXNvbikge1xuICAgICAgICAgIGxpYiRlczYkcHJvbWlzZSQkaW50ZXJuYWwkJHJlamVjdChwcm9taXNlLCByZWFzb24pO1xuICAgICAgICB9KTtcbiAgICAgIH1cbiAgICB9XG5cbiAgICBmdW5jdGlvbiBsaWIkZXM2JHByb21pc2UkJGludGVybmFsJCRoYW5kbGVNYXliZVRoZW5hYmxlKHByb21pc2UsIG1heWJlVGhlbmFibGUpIHtcbiAgICAgIGlmIChtYXliZVRoZW5hYmxlLmNvbnN0cnVjdG9yID09PSBwcm9taXNlLmNvbnN0cnVjdG9yKSB7XG4gICAgICAgIGxpYiRlczYkcHJvbWlzZSQkaW50ZXJuYWwkJGhhbmRsZU93blRoZW5hYmxlKHByb21pc2UsIG1heWJlVGhlbmFibGUpO1xuICAgICAgfSBlbHNlIHtcbiAgICAgICAgdmFyIHRoZW4gPSBsaWIkZXM2JHByb21pc2UkJGludGVybmFsJCRnZXRUaGVuKG1heWJlVGhlbmFibGUpO1xuXG4gICAgICAgIGlmICh0aGVuID09PSBsaWIkZXM2JHByb21pc2UkJGludGVybmFsJCRHRVRfVEhFTl9FUlJPUikge1xuICAgICAgICAgIGxpYiRlczYkcHJvbWlzZSQkaW50ZXJuYWwkJHJlamVjdChwcm9taXNlLCBsaWIkZXM2JHByb21pc2UkJGludGVybmFsJCRHRVRfVEhFTl9FUlJPUi5lcnJvcik7XG4gICAgICAgIH0gZWxzZSBpZiAodGhlbiA9PT0gdW5kZWZpbmVkKSB7XG4gICAgICAgICAgbGliJGVzNiRwcm9taXNlJCRpbnRlcm5hbCQkZnVsZmlsbChwcm9taXNlLCBtYXliZVRoZW5hYmxlKTtcbiAgICAgICAgfSBlbHNlIGlmIChsaWIkZXM2JHByb21pc2UkdXRpbHMkJGlzRnVuY3Rpb24odGhlbikpIHtcbiAgICAgICAgICBsaWIkZXM2JHByb21pc2UkJGludGVybmFsJCRoYW5kbGVGb3JlaWduVGhlbmFibGUocHJvbWlzZSwgbWF5YmVUaGVuYWJsZSwgdGhlbik7XG4gICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgbGliJGVzNiRwcm9taXNlJCRpbnRlcm5hbCQkZnVsZmlsbChwcm9taXNlLCBtYXliZVRoZW5hYmxlKTtcbiAgICAgICAgfVxuICAgICAgfVxuICAgIH1cblxuICAgIGZ1bmN0aW9uIGxpYiRlczYkcHJvbWlzZSQkaW50ZXJuYWwkJHJlc29sdmUocHJvbWlzZSwgdmFsdWUpIHtcbiAgICAgIGlmIChwcm9taXNlID09PSB2YWx1ZSkge1xuICAgICAgICBsaWIkZXM2JHByb21pc2UkJGludGVybmFsJCRyZWplY3QocHJvbWlzZSwgbGliJGVzNiRwcm9taXNlJCRpbnRlcm5hbCQkc2VsZkZ1bGZpbGxtZW50KCkpO1xuICAgICAgfSBlbHNlIGlmIChsaWIkZXM2JHByb21pc2UkdXRpbHMkJG9iamVjdE9yRnVuY3Rpb24odmFsdWUpKSB7XG4gICAgICAgIGxpYiRlczYkcHJvbWlzZSQkaW50ZXJuYWwkJGhhbmRsZU1heWJlVGhlbmFibGUocHJvbWlzZSwgdmFsdWUpO1xuICAgICAgfSBlbHNlIHtcbiAgICAgICAgbGliJGVzNiRwcm9taXNlJCRpbnRlcm5hbCQkZnVsZmlsbChwcm9taXNlLCB2YWx1ZSk7XG4gICAgICB9XG4gICAgfVxuXG4gICAgZnVuY3Rpb24gbGliJGVzNiRwcm9taXNlJCRpbnRlcm5hbCQkcHVibGlzaFJlamVjdGlvbihwcm9taXNlKSB7XG4gICAgICBpZiAocHJvbWlzZS5fb25lcnJvcikge1xuICAgICAgICBwcm9taXNlLl9vbmVycm9yKHByb21pc2UuX3Jlc3VsdCk7XG4gICAgICB9XG5cbiAgICAgIGxpYiRlczYkcHJvbWlzZSQkaW50ZXJuYWwkJHB1Ymxpc2gocHJvbWlzZSk7XG4gICAgfVxuXG4gICAgZnVuY3Rpb24gbGliJGVzNiRwcm9taXNlJCRpbnRlcm5hbCQkZnVsZmlsbChwcm9taXNlLCB2YWx1ZSkge1xuICAgICAgaWYgKHByb21pc2UuX3N0YXRlICE9PSBsaWIkZXM2JHByb21pc2UkJGludGVybmFsJCRQRU5ESU5HKSB7IHJldHVybjsgfVxuXG4gICAgICBwcm9taXNlLl9yZXN1bHQgPSB2YWx1ZTtcbiAgICAgIHByb21pc2UuX3N0YXRlID0gbGliJGVzNiRwcm9taXNlJCRpbnRlcm5hbCQkRlVMRklMTEVEO1xuXG4gICAgICBpZiAocHJvbWlzZS5fc3Vic2NyaWJlcnMubGVuZ3RoICE9PSAwKSB7XG4gICAgICAgIGxpYiRlczYkcHJvbWlzZSRhc2FwJCRhc2FwKGxpYiRlczYkcHJvbWlzZSQkaW50ZXJuYWwkJHB1Ymxpc2gsIHByb21pc2UpO1xuICAgICAgfVxuICAgIH1cblxuICAgIGZ1bmN0aW9uIGxpYiRlczYkcHJvbWlzZSQkaW50ZXJuYWwkJHJlamVjdChwcm9taXNlLCByZWFzb24pIHtcbiAgICAgIGlmIChwcm9taXNlLl9zdGF0ZSAhPT0gbGliJGVzNiRwcm9taXNlJCRpbnRlcm5hbCQkUEVORElORykgeyByZXR1cm47IH1cbiAgICAgIHByb21pc2UuX3N0YXRlID0gbGliJGVzNiRwcm9taXNlJCRpbnRlcm5hbCQkUkVKRUNURUQ7XG4gICAgICBwcm9taXNlLl9yZXN1bHQgPSByZWFzb247XG5cbiAgICAgIGxpYiRlczYkcHJvbWlzZSRhc2FwJCRhc2FwKGxpYiRlczYkcHJvbWlzZSQkaW50ZXJuYWwkJHB1Ymxpc2hSZWplY3Rpb24sIHByb21pc2UpO1xuICAgIH1cblxuICAgIGZ1bmN0aW9uIGxpYiRlczYkcHJvbWlzZSQkaW50ZXJuYWwkJHN1YnNjcmliZShwYXJlbnQsIGNoaWxkLCBvbkZ1bGZpbGxtZW50LCBvblJlamVjdGlvbikge1xuICAgICAgdmFyIHN1YnNjcmliZXJzID0gcGFyZW50Ll9zdWJzY3JpYmVycztcbiAgICAgIHZhciBsZW5ndGggPSBzdWJzY3JpYmVycy5sZW5ndGg7XG5cbiAgICAgIHBhcmVudC5fb25lcnJvciA9IG51bGw7XG5cbiAgICAgIHN1YnNjcmliZXJzW2xlbmd0aF0gPSBjaGlsZDtcbiAgICAgIHN1YnNjcmliZXJzW2xlbmd0aCArIGxpYiRlczYkcHJvbWlzZSQkaW50ZXJuYWwkJEZVTEZJTExFRF0gPSBvbkZ1bGZpbGxtZW50O1xuICAgICAgc3Vic2NyaWJlcnNbbGVuZ3RoICsgbGliJGVzNiRwcm9taXNlJCRpbnRlcm5hbCQkUkVKRUNURURdICA9IG9uUmVqZWN0aW9uO1xuXG4gICAgICBpZiAobGVuZ3RoID09PSAwICYmIHBhcmVudC5fc3RhdGUpIHtcbiAgICAgICAgbGliJGVzNiRwcm9taXNlJGFzYXAkJGFzYXAobGliJGVzNiRwcm9taXNlJCRpbnRlcm5hbCQkcHVibGlzaCwgcGFyZW50KTtcbiAgICAgIH1cbiAgICB9XG5cbiAgICBmdW5jdGlvbiBsaWIkZXM2JHByb21pc2UkJGludGVybmFsJCRwdWJsaXNoKHByb21pc2UpIHtcbiAgICAgIHZhciBzdWJzY3JpYmVycyA9IHByb21pc2UuX3N1YnNjcmliZXJzO1xuICAgICAgdmFyIHNldHRsZWQgPSBwcm9taXNlLl9zdGF0ZTtcblxuICAgICAgaWYgKHN1YnNjcmliZXJzLmxlbmd0aCA9PT0gMCkgeyByZXR1cm47IH1cblxuICAgICAgdmFyIGNoaWxkLCBjYWxsYmFjaywgZGV0YWlsID0gcHJvbWlzZS5fcmVzdWx0O1xuXG4gICAgICBmb3IgKHZhciBpID0gMDsgaSA8IHN1YnNjcmliZXJzLmxlbmd0aDsgaSArPSAzKSB7XG4gICAgICAgIGNoaWxkID0gc3Vic2NyaWJlcnNbaV07XG4gICAgICAgIGNhbGxiYWNrID0gc3Vic2NyaWJlcnNbaSArIHNldHRsZWRdO1xuXG4gICAgICAgIGlmIChjaGlsZCkge1xuICAgICAgICAgIGxpYiRlczYkcHJvbWlzZSQkaW50ZXJuYWwkJGludm9rZUNhbGxiYWNrKHNldHRsZWQsIGNoaWxkLCBjYWxsYmFjaywgZGV0YWlsKTtcbiAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICBjYWxsYmFjayhkZXRhaWwpO1xuICAgICAgICB9XG4gICAgICB9XG5cbiAgICAgIHByb21pc2UuX3N1YnNjcmliZXJzLmxlbmd0aCA9IDA7XG4gICAgfVxuXG4gICAgZnVuY3Rpb24gbGliJGVzNiRwcm9taXNlJCRpbnRlcm5hbCQkRXJyb3JPYmplY3QoKSB7XG4gICAgICB0aGlzLmVycm9yID0gbnVsbDtcbiAgICB9XG5cbiAgICB2YXIgbGliJGVzNiRwcm9taXNlJCRpbnRlcm5hbCQkVFJZX0NBVENIX0VSUk9SID0gbmV3IGxpYiRlczYkcHJvbWlzZSQkaW50ZXJuYWwkJEVycm9yT2JqZWN0KCk7XG5cbiAgICBmdW5jdGlvbiBsaWIkZXM2JHByb21pc2UkJGludGVybmFsJCR0cnlDYXRjaChjYWxsYmFjaywgZGV0YWlsKSB7XG4gICAgICB0cnkge1xuICAgICAgICByZXR1cm4gY2FsbGJhY2soZGV0YWlsKTtcbiAgICAgIH0gY2F0Y2goZSkge1xuICAgICAgICBsaWIkZXM2JHByb21pc2UkJGludGVybmFsJCRUUllfQ0FUQ0hfRVJST1IuZXJyb3IgPSBlO1xuICAgICAgICByZXR1cm4gbGliJGVzNiRwcm9taXNlJCRpbnRlcm5hbCQkVFJZX0NBVENIX0VSUk9SO1xuICAgICAgfVxuICAgIH1cblxuICAgIGZ1bmN0aW9uIGxpYiRlczYkcHJvbWlzZSQkaW50ZXJuYWwkJGludm9rZUNhbGxiYWNrKHNldHRsZWQsIHByb21pc2UsIGNhbGxiYWNrLCBkZXRhaWwpIHtcbiAgICAgIHZhciBoYXNDYWxsYmFjayA9IGxpYiRlczYkcHJvbWlzZSR1dGlscyQkaXNGdW5jdGlvbihjYWxsYmFjayksXG4gICAgICAgICAgdmFsdWUsIGVycm9yLCBzdWNjZWVkZWQsIGZhaWxlZDtcblxuICAgICAgaWYgKGhhc0NhbGxiYWNrKSB7XG4gICAgICAgIHZhbHVlID0gbGliJGVzNiRwcm9taXNlJCRpbnRlcm5hbCQkdHJ5Q2F0Y2goY2FsbGJhY2ssIGRldGFpbCk7XG5cbiAgICAgICAgaWYgKHZhbHVlID09PSBsaWIkZXM2JHByb21pc2UkJGludGVybmFsJCRUUllfQ0FUQ0hfRVJST1IpIHtcbiAgICAgICAgICBmYWlsZWQgPSB0cnVlO1xuICAgICAgICAgIGVycm9yID0gdmFsdWUuZXJyb3I7XG4gICAgICAgICAgdmFsdWUgPSBudWxsO1xuICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgIHN1Y2NlZWRlZCA9IHRydWU7XG4gICAgICAgIH1cblxuICAgICAgICBpZiAocHJvbWlzZSA9PT0gdmFsdWUpIHtcbiAgICAgICAgICBsaWIkZXM2JHByb21pc2UkJGludGVybmFsJCRyZWplY3QocHJvbWlzZSwgbGliJGVzNiRwcm9taXNlJCRpbnRlcm5hbCQkY2Fubm90UmV0dXJuT3duKCkpO1xuICAgICAgICAgIHJldHVybjtcbiAgICAgICAgfVxuXG4gICAgICB9IGVsc2Uge1xuICAgICAgICB2YWx1ZSA9IGRldGFpbDtcbiAgICAgICAgc3VjY2VlZGVkID0gdHJ1ZTtcbiAgICAgIH1cblxuICAgICAgaWYgKHByb21pc2UuX3N0YXRlICE9PSBsaWIkZXM2JHByb21pc2UkJGludGVybmFsJCRQRU5ESU5HKSB7XG4gICAgICAgIC8vIG5vb3BcbiAgICAgIH0gZWxzZSBpZiAoaGFzQ2FsbGJhY2sgJiYgc3VjY2VlZGVkKSB7XG4gICAgICAgIGxpYiRlczYkcHJvbWlzZSQkaW50ZXJuYWwkJHJlc29sdmUocHJvbWlzZSwgdmFsdWUpO1xuICAgICAgfSBlbHNlIGlmIChmYWlsZWQpIHtcbiAgICAgICAgbGliJGVzNiRwcm9taXNlJCRpbnRlcm5hbCQkcmVqZWN0KHByb21pc2UsIGVycm9yKTtcbiAgICAgIH0gZWxzZSBpZiAoc2V0dGxlZCA9PT0gbGliJGVzNiRwcm9taXNlJCRpbnRlcm5hbCQkRlVMRklMTEVEKSB7XG4gICAgICAgIGxpYiRlczYkcHJvbWlzZSQkaW50ZXJuYWwkJGZ1bGZpbGwocHJvbWlzZSwgdmFsdWUpO1xuICAgICAgfSBlbHNlIGlmIChzZXR0bGVkID09PSBsaWIkZXM2JHByb21pc2UkJGludGVybmFsJCRSRUpFQ1RFRCkge1xuICAgICAgICBsaWIkZXM2JHByb21pc2UkJGludGVybmFsJCRyZWplY3QocHJvbWlzZSwgdmFsdWUpO1xuICAgICAgfVxuICAgIH1cblxuICAgIGZ1bmN0aW9uIGxpYiRlczYkcHJvbWlzZSQkaW50ZXJuYWwkJGluaXRpYWxpemVQcm9taXNlKHByb21pc2UsIHJlc29sdmVyKSB7XG4gICAgICB0cnkge1xuICAgICAgICByZXNvbHZlcihmdW5jdGlvbiByZXNvbHZlUHJvbWlzZSh2YWx1ZSl7XG4gICAgICAgICAgbGliJGVzNiRwcm9taXNlJCRpbnRlcm5hbCQkcmVzb2x2ZShwcm9taXNlLCB2YWx1ZSk7XG4gICAgICAgIH0sIGZ1bmN0aW9uIHJlamVjdFByb21pc2UocmVhc29uKSB7XG4gICAgICAgICAgbGliJGVzNiRwcm9taXNlJCRpbnRlcm5hbCQkcmVqZWN0KHByb21pc2UsIHJlYXNvbik7XG4gICAgICAgIH0pO1xuICAgICAgfSBjYXRjaChlKSB7XG4gICAgICAgIGxpYiRlczYkcHJvbWlzZSQkaW50ZXJuYWwkJHJlamVjdChwcm9taXNlLCBlKTtcbiAgICAgIH1cbiAgICB9XG5cbiAgICBmdW5jdGlvbiBsaWIkZXM2JHByb21pc2UkZW51bWVyYXRvciQkRW51bWVyYXRvcihDb25zdHJ1Y3RvciwgaW5wdXQpIHtcbiAgICAgIHZhciBlbnVtZXJhdG9yID0gdGhpcztcblxuICAgICAgZW51bWVyYXRvci5faW5zdGFuY2VDb25zdHJ1Y3RvciA9IENvbnN0cnVjdG9yO1xuICAgICAgZW51bWVyYXRvci5wcm9taXNlID0gbmV3IENvbnN0cnVjdG9yKGxpYiRlczYkcHJvbWlzZSQkaW50ZXJuYWwkJG5vb3ApO1xuXG4gICAgICBpZiAoZW51bWVyYXRvci5fdmFsaWRhdGVJbnB1dChpbnB1dCkpIHtcbiAgICAgICAgZW51bWVyYXRvci5faW5wdXQgICAgID0gaW5wdXQ7XG4gICAgICAgIGVudW1lcmF0b3IubGVuZ3RoICAgICA9IGlucHV0Lmxlbmd0aDtcbiAgICAgICAgZW51bWVyYXRvci5fcmVtYWluaW5nID0gaW5wdXQubGVuZ3RoO1xuXG4gICAgICAgIGVudW1lcmF0b3IuX2luaXQoKTtcblxuICAgICAgICBpZiAoZW51bWVyYXRvci5sZW5ndGggPT09IDApIHtcbiAgICAgICAgICBsaWIkZXM2JHByb21pc2UkJGludGVybmFsJCRmdWxmaWxsKGVudW1lcmF0b3IucHJvbWlzZSwgZW51bWVyYXRvci5fcmVzdWx0KTtcbiAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICBlbnVtZXJhdG9yLmxlbmd0aCA9IGVudW1lcmF0b3IubGVuZ3RoIHx8IDA7XG4gICAgICAgICAgZW51bWVyYXRvci5fZW51bWVyYXRlKCk7XG4gICAgICAgICAgaWYgKGVudW1lcmF0b3IuX3JlbWFpbmluZyA9PT0gMCkge1xuICAgICAgICAgICAgbGliJGVzNiRwcm9taXNlJCRpbnRlcm5hbCQkZnVsZmlsbChlbnVtZXJhdG9yLnByb21pc2UsIGVudW1lcmF0b3IuX3Jlc3VsdCk7XG4gICAgICAgICAgfVxuICAgICAgICB9XG4gICAgICB9IGVsc2Uge1xuICAgICAgICBsaWIkZXM2JHByb21pc2UkJGludGVybmFsJCRyZWplY3QoZW51bWVyYXRvci5wcm9taXNlLCBlbnVtZXJhdG9yLl92YWxpZGF0aW9uRXJyb3IoKSk7XG4gICAgICB9XG4gICAgfVxuXG4gICAgbGliJGVzNiRwcm9taXNlJGVudW1lcmF0b3IkJEVudW1lcmF0b3IucHJvdG90eXBlLl92YWxpZGF0ZUlucHV0ID0gZnVuY3Rpb24oaW5wdXQpIHtcbiAgICAgIHJldHVybiBsaWIkZXM2JHByb21pc2UkdXRpbHMkJGlzQXJyYXkoaW5wdXQpO1xuICAgIH07XG5cbiAgICBsaWIkZXM2JHByb21pc2UkZW51bWVyYXRvciQkRW51bWVyYXRvci5wcm90b3R5cGUuX3ZhbGlkYXRpb25FcnJvciA9IGZ1bmN0aW9uKCkge1xuICAgICAgcmV0dXJuIG5ldyBFcnJvcignQXJyYXkgTWV0aG9kcyBtdXN0IGJlIHByb3ZpZGVkIGFuIEFycmF5Jyk7XG4gICAgfTtcblxuICAgIGxpYiRlczYkcHJvbWlzZSRlbnVtZXJhdG9yJCRFbnVtZXJhdG9yLnByb3RvdHlwZS5faW5pdCA9IGZ1bmN0aW9uKCkge1xuICAgICAgdGhpcy5fcmVzdWx0ID0gbmV3IEFycmF5KHRoaXMubGVuZ3RoKTtcbiAgICB9O1xuXG4gICAgdmFyIGxpYiRlczYkcHJvbWlzZSRlbnVtZXJhdG9yJCRkZWZhdWx0ID0gbGliJGVzNiRwcm9taXNlJGVudW1lcmF0b3IkJEVudW1lcmF0b3I7XG5cbiAgICBsaWIkZXM2JHByb21pc2UkZW51bWVyYXRvciQkRW51bWVyYXRvci5wcm90b3R5cGUuX2VudW1lcmF0ZSA9IGZ1bmN0aW9uKCkge1xuICAgICAgdmFyIGVudW1lcmF0b3IgPSB0aGlzO1xuXG4gICAgICB2YXIgbGVuZ3RoICA9IGVudW1lcmF0b3IubGVuZ3RoO1xuICAgICAgdmFyIHByb21pc2UgPSBlbnVtZXJhdG9yLnByb21pc2U7XG4gICAgICB2YXIgaW5wdXQgICA9IGVudW1lcmF0b3IuX2lucHV0O1xuXG4gICAgICBmb3IgKHZhciBpID0gMDsgcHJvbWlzZS5fc3RhdGUgPT09IGxpYiRlczYkcHJvbWlzZSQkaW50ZXJuYWwkJFBFTkRJTkcgJiYgaSA8IGxlbmd0aDsgaSsrKSB7XG4gICAgICAgIGVudW1lcmF0b3IuX2VhY2hFbnRyeShpbnB1dFtpXSwgaSk7XG4gICAgICB9XG4gICAgfTtcblxuICAgIGxpYiRlczYkcHJvbWlzZSRlbnVtZXJhdG9yJCRFbnVtZXJhdG9yLnByb3RvdHlwZS5fZWFjaEVudHJ5ID0gZnVuY3Rpb24oZW50cnksIGkpIHtcbiAgICAgIHZhciBlbnVtZXJhdG9yID0gdGhpcztcbiAgICAgIHZhciBjID0gZW51bWVyYXRvci5faW5zdGFuY2VDb25zdHJ1Y3RvcjtcblxuICAgICAgaWYgKGxpYiRlczYkcHJvbWlzZSR1dGlscyQkaXNNYXliZVRoZW5hYmxlKGVudHJ5KSkge1xuICAgICAgICBpZiAoZW50cnkuY29uc3RydWN0b3IgPT09IGMgJiYgZW50cnkuX3N0YXRlICE9PSBsaWIkZXM2JHByb21pc2UkJGludGVybmFsJCRQRU5ESU5HKSB7XG4gICAgICAgICAgZW50cnkuX29uZXJyb3IgPSBudWxsO1xuICAgICAgICAgIGVudW1lcmF0b3IuX3NldHRsZWRBdChlbnRyeS5fc3RhdGUsIGksIGVudHJ5Ll9yZXN1bHQpO1xuICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgIGVudW1lcmF0b3IuX3dpbGxTZXR0bGVBdChjLnJlc29sdmUoZW50cnkpLCBpKTtcbiAgICAgICAgfVxuICAgICAgfSBlbHNlIHtcbiAgICAgICAgZW51bWVyYXRvci5fcmVtYWluaW5nLS07XG4gICAgICAgIGVudW1lcmF0b3IuX3Jlc3VsdFtpXSA9IGVudHJ5O1xuICAgICAgfVxuICAgIH07XG5cbiAgICBsaWIkZXM2JHByb21pc2UkZW51bWVyYXRvciQkRW51bWVyYXRvci5wcm90b3R5cGUuX3NldHRsZWRBdCA9IGZ1bmN0aW9uKHN0YXRlLCBpLCB2YWx1ZSkge1xuICAgICAgdmFyIGVudW1lcmF0b3IgPSB0aGlzO1xuICAgICAgdmFyIHByb21pc2UgPSBlbnVtZXJhdG9yLnByb21pc2U7XG5cbiAgICAgIGlmIChwcm9taXNlLl9zdGF0ZSA9PT0gbGliJGVzNiRwcm9taXNlJCRpbnRlcm5hbCQkUEVORElORykge1xuICAgICAgICBlbnVtZXJhdG9yLl9yZW1haW5pbmctLTtcblxuICAgICAgICBpZiAoc3RhdGUgPT09IGxpYiRlczYkcHJvbWlzZSQkaW50ZXJuYWwkJFJFSkVDVEVEKSB7XG4gICAgICAgICAgbGliJGVzNiRwcm9taXNlJCRpbnRlcm5hbCQkcmVqZWN0KHByb21pc2UsIHZhbHVlKTtcbiAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICBlbnVtZXJhdG9yLl9yZXN1bHRbaV0gPSB2YWx1ZTtcbiAgICAgICAgfVxuICAgICAgfVxuXG4gICAgICBpZiAoZW51bWVyYXRvci5fcmVtYWluaW5nID09PSAwKSB7XG4gICAgICAgIGxpYiRlczYkcHJvbWlzZSQkaW50ZXJuYWwkJGZ1bGZpbGwocHJvbWlzZSwgZW51bWVyYXRvci5fcmVzdWx0KTtcbiAgICAgIH1cbiAgICB9O1xuXG4gICAgbGliJGVzNiRwcm9taXNlJGVudW1lcmF0b3IkJEVudW1lcmF0b3IucHJvdG90eXBlLl93aWxsU2V0dGxlQXQgPSBmdW5jdGlvbihwcm9taXNlLCBpKSB7XG4gICAgICB2YXIgZW51bWVyYXRvciA9IHRoaXM7XG5cbiAgICAgIGxpYiRlczYkcHJvbWlzZSQkaW50ZXJuYWwkJHN1YnNjcmliZShwcm9taXNlLCB1bmRlZmluZWQsIGZ1bmN0aW9uKHZhbHVlKSB7XG4gICAgICAgIGVudW1lcmF0b3IuX3NldHRsZWRBdChsaWIkZXM2JHByb21pc2UkJGludGVybmFsJCRGVUxGSUxMRUQsIGksIHZhbHVlKTtcbiAgICAgIH0sIGZ1bmN0aW9uKHJlYXNvbikge1xuICAgICAgICBlbnVtZXJhdG9yLl9zZXR0bGVkQXQobGliJGVzNiRwcm9taXNlJCRpbnRlcm5hbCQkUkVKRUNURUQsIGksIHJlYXNvbik7XG4gICAgICB9KTtcbiAgICB9O1xuICAgIGZ1bmN0aW9uIGxpYiRlczYkcHJvbWlzZSRwcm9taXNlJGFsbCQkYWxsKGVudHJpZXMpIHtcbiAgICAgIHJldHVybiBuZXcgbGliJGVzNiRwcm9taXNlJGVudW1lcmF0b3IkJGRlZmF1bHQodGhpcywgZW50cmllcykucHJvbWlzZTtcbiAgICB9XG4gICAgdmFyIGxpYiRlczYkcHJvbWlzZSRwcm9taXNlJGFsbCQkZGVmYXVsdCA9IGxpYiRlczYkcHJvbWlzZSRwcm9taXNlJGFsbCQkYWxsO1xuICAgIGZ1bmN0aW9uIGxpYiRlczYkcHJvbWlzZSRwcm9taXNlJHJhY2UkJHJhY2UoZW50cmllcykge1xuICAgICAgLypqc2hpbnQgdmFsaWR0aGlzOnRydWUgKi9cbiAgICAgIHZhciBDb25zdHJ1Y3RvciA9IHRoaXM7XG5cbiAgICAgIHZhciBwcm9taXNlID0gbmV3IENvbnN0cnVjdG9yKGxpYiRlczYkcHJvbWlzZSQkaW50ZXJuYWwkJG5vb3ApO1xuXG4gICAgICBpZiAoIWxpYiRlczYkcHJvbWlzZSR1dGlscyQkaXNBcnJheShlbnRyaWVzKSkge1xuICAgICAgICBsaWIkZXM2JHByb21pc2UkJGludGVybmFsJCRyZWplY3QocHJvbWlzZSwgbmV3IFR5cGVFcnJvcignWW91IG11c3QgcGFzcyBhbiBhcnJheSB0byByYWNlLicpKTtcbiAgICAgICAgcmV0dXJuIHByb21pc2U7XG4gICAgICB9XG5cbiAgICAgIHZhciBsZW5ndGggPSBlbnRyaWVzLmxlbmd0aDtcblxuICAgICAgZnVuY3Rpb24gb25GdWxmaWxsbWVudCh2YWx1ZSkge1xuICAgICAgICBsaWIkZXM2JHByb21pc2UkJGludGVybmFsJCRyZXNvbHZlKHByb21pc2UsIHZhbHVlKTtcbiAgICAgIH1cblxuICAgICAgZnVuY3Rpb24gb25SZWplY3Rpb24ocmVhc29uKSB7XG4gICAgICAgIGxpYiRlczYkcHJvbWlzZSQkaW50ZXJuYWwkJHJlamVjdChwcm9taXNlLCByZWFzb24pO1xuICAgICAgfVxuXG4gICAgICBmb3IgKHZhciBpID0gMDsgcHJvbWlzZS5fc3RhdGUgPT09IGxpYiRlczYkcHJvbWlzZSQkaW50ZXJuYWwkJFBFTkRJTkcgJiYgaSA8IGxlbmd0aDsgaSsrKSB7XG4gICAgICAgIGxpYiRlczYkcHJvbWlzZSQkaW50ZXJuYWwkJHN1YnNjcmliZShDb25zdHJ1Y3Rvci5yZXNvbHZlKGVudHJpZXNbaV0pLCB1bmRlZmluZWQsIG9uRnVsZmlsbG1lbnQsIG9uUmVqZWN0aW9uKTtcbiAgICAgIH1cblxuICAgICAgcmV0dXJuIHByb21pc2U7XG4gICAgfVxuICAgIHZhciBsaWIkZXM2JHByb21pc2UkcHJvbWlzZSRyYWNlJCRkZWZhdWx0ID0gbGliJGVzNiRwcm9taXNlJHByb21pc2UkcmFjZSQkcmFjZTtcbiAgICBmdW5jdGlvbiBsaWIkZXM2JHByb21pc2UkcHJvbWlzZSRyZXNvbHZlJCRyZXNvbHZlKG9iamVjdCkge1xuICAgICAgLypqc2hpbnQgdmFsaWR0aGlzOnRydWUgKi9cbiAgICAgIHZhciBDb25zdHJ1Y3RvciA9IHRoaXM7XG5cbiAgICAgIGlmIChvYmplY3QgJiYgdHlwZW9mIG9iamVjdCA9PT0gJ29iamVjdCcgJiYgb2JqZWN0LmNvbnN0cnVjdG9yID09PSBDb25zdHJ1Y3Rvcikge1xuICAgICAgICByZXR1cm4gb2JqZWN0O1xuICAgICAgfVxuXG4gICAgICB2YXIgcHJvbWlzZSA9IG5ldyBDb25zdHJ1Y3RvcihsaWIkZXM2JHByb21pc2UkJGludGVybmFsJCRub29wKTtcbiAgICAgIGxpYiRlczYkcHJvbWlzZSQkaW50ZXJuYWwkJHJlc29sdmUocHJvbWlzZSwgb2JqZWN0KTtcbiAgICAgIHJldHVybiBwcm9taXNlO1xuICAgIH1cbiAgICB2YXIgbGliJGVzNiRwcm9taXNlJHByb21pc2UkcmVzb2x2ZSQkZGVmYXVsdCA9IGxpYiRlczYkcHJvbWlzZSRwcm9taXNlJHJlc29sdmUkJHJlc29sdmU7XG4gICAgZnVuY3Rpb24gbGliJGVzNiRwcm9taXNlJHByb21pc2UkcmVqZWN0JCRyZWplY3QocmVhc29uKSB7XG4gICAgICAvKmpzaGludCB2YWxpZHRoaXM6dHJ1ZSAqL1xuICAgICAgdmFyIENvbnN0cnVjdG9yID0gdGhpcztcbiAgICAgIHZhciBwcm9taXNlID0gbmV3IENvbnN0cnVjdG9yKGxpYiRlczYkcHJvbWlzZSQkaW50ZXJuYWwkJG5vb3ApO1xuICAgICAgbGliJGVzNiRwcm9taXNlJCRpbnRlcm5hbCQkcmVqZWN0KHByb21pc2UsIHJlYXNvbik7XG4gICAgICByZXR1cm4gcHJvbWlzZTtcbiAgICB9XG4gICAgdmFyIGxpYiRlczYkcHJvbWlzZSRwcm9taXNlJHJlamVjdCQkZGVmYXVsdCA9IGxpYiRlczYkcHJvbWlzZSRwcm9taXNlJHJlamVjdCQkcmVqZWN0O1xuXG4gICAgdmFyIGxpYiRlczYkcHJvbWlzZSRwcm9taXNlJCRjb3VudGVyID0gMDtcblxuICAgIGZ1bmN0aW9uIGxpYiRlczYkcHJvbWlzZSRwcm9taXNlJCRuZWVkc1Jlc29sdmVyKCkge1xuICAgICAgdGhyb3cgbmV3IFR5cGVFcnJvcignWW91IG11c3QgcGFzcyBhIHJlc29sdmVyIGZ1bmN0aW9uIGFzIHRoZSBmaXJzdCBhcmd1bWVudCB0byB0aGUgcHJvbWlzZSBjb25zdHJ1Y3RvcicpO1xuICAgIH1cblxuICAgIGZ1bmN0aW9uIGxpYiRlczYkcHJvbWlzZSRwcm9taXNlJCRuZWVkc05ldygpIHtcbiAgICAgIHRocm93IG5ldyBUeXBlRXJyb3IoXCJGYWlsZWQgdG8gY29uc3RydWN0ICdQcm9taXNlJzogUGxlYXNlIHVzZSB0aGUgJ25ldycgb3BlcmF0b3IsIHRoaXMgb2JqZWN0IGNvbnN0cnVjdG9yIGNhbm5vdCBiZSBjYWxsZWQgYXMgYSBmdW5jdGlvbi5cIik7XG4gICAgfVxuXG4gICAgdmFyIGxpYiRlczYkcHJvbWlzZSRwcm9taXNlJCRkZWZhdWx0ID0gbGliJGVzNiRwcm9taXNlJHByb21pc2UkJFByb21pc2U7XG4gICAgLyoqXG4gICAgICBQcm9taXNlIG9iamVjdHMgcmVwcmVzZW50IHRoZSBldmVudHVhbCByZXN1bHQgb2YgYW4gYXN5bmNocm9ub3VzIG9wZXJhdGlvbi4gVGhlXG4gICAgICBwcmltYXJ5IHdheSBvZiBpbnRlcmFjdGluZyB3aXRoIGEgcHJvbWlzZSBpcyB0aHJvdWdoIGl0cyBgdGhlbmAgbWV0aG9kLCB3aGljaFxuICAgICAgcmVnaXN0ZXJzIGNhbGxiYWNrcyB0byByZWNlaXZlIGVpdGhlciBhIHByb21pc2UncyBldmVudHVhbCB2YWx1ZSBvciB0aGUgcmVhc29uXG4gICAgICB3aHkgdGhlIHByb21pc2UgY2Fubm90IGJlIGZ1bGZpbGxlZC5cblxuICAgICAgVGVybWlub2xvZ3lcbiAgICAgIC0tLS0tLS0tLS0tXG5cbiAgICAgIC0gYHByb21pc2VgIGlzIGFuIG9iamVjdCBvciBmdW5jdGlvbiB3aXRoIGEgYHRoZW5gIG1ldGhvZCB3aG9zZSBiZWhhdmlvciBjb25mb3JtcyB0byB0aGlzIHNwZWNpZmljYXRpb24uXG4gICAgICAtIGB0aGVuYWJsZWAgaXMgYW4gb2JqZWN0IG9yIGZ1bmN0aW9uIHRoYXQgZGVmaW5lcyBhIGB0aGVuYCBtZXRob2QuXG4gICAgICAtIGB2YWx1ZWAgaXMgYW55IGxlZ2FsIEphdmFTY3JpcHQgdmFsdWUgKGluY2x1ZGluZyB1bmRlZmluZWQsIGEgdGhlbmFibGUsIG9yIGEgcHJvbWlzZSkuXG4gICAgICAtIGBleGNlcHRpb25gIGlzIGEgdmFsdWUgdGhhdCBpcyB0aHJvd24gdXNpbmcgdGhlIHRocm93IHN0YXRlbWVudC5cbiAgICAgIC0gYHJlYXNvbmAgaXMgYSB2YWx1ZSB0aGF0IGluZGljYXRlcyB3aHkgYSBwcm9taXNlIHdhcyByZWplY3RlZC5cbiAgICAgIC0gYHNldHRsZWRgIHRoZSBmaW5hbCByZXN0aW5nIHN0YXRlIG9mIGEgcHJvbWlzZSwgZnVsZmlsbGVkIG9yIHJlamVjdGVkLlxuXG4gICAgICBBIHByb21pc2UgY2FuIGJlIGluIG9uZSBvZiB0aHJlZSBzdGF0ZXM6IHBlbmRpbmcsIGZ1bGZpbGxlZCwgb3IgcmVqZWN0ZWQuXG5cbiAgICAgIFByb21pc2VzIHRoYXQgYXJlIGZ1bGZpbGxlZCBoYXZlIGEgZnVsZmlsbG1lbnQgdmFsdWUgYW5kIGFyZSBpbiB0aGUgZnVsZmlsbGVkXG4gICAgICBzdGF0ZS4gIFByb21pc2VzIHRoYXQgYXJlIHJlamVjdGVkIGhhdmUgYSByZWplY3Rpb24gcmVhc29uIGFuZCBhcmUgaW4gdGhlXG4gICAgICByZWplY3RlZCBzdGF0ZS4gIEEgZnVsZmlsbG1lbnQgdmFsdWUgaXMgbmV2ZXIgYSB0aGVuYWJsZS5cblxuICAgICAgUHJvbWlzZXMgY2FuIGFsc28gYmUgc2FpZCB0byAqcmVzb2x2ZSogYSB2YWx1ZS4gIElmIHRoaXMgdmFsdWUgaXMgYWxzbyBhXG4gICAgICBwcm9taXNlLCB0aGVuIHRoZSBvcmlnaW5hbCBwcm9taXNlJ3Mgc2V0dGxlZCBzdGF0ZSB3aWxsIG1hdGNoIHRoZSB2YWx1ZSdzXG4gICAgICBzZXR0bGVkIHN0YXRlLiAgU28gYSBwcm9taXNlIHRoYXQgKnJlc29sdmVzKiBhIHByb21pc2UgdGhhdCByZWplY3RzIHdpbGxcbiAgICAgIGl0c2VsZiByZWplY3QsIGFuZCBhIHByb21pc2UgdGhhdCAqcmVzb2x2ZXMqIGEgcHJvbWlzZSB0aGF0IGZ1bGZpbGxzIHdpbGxcbiAgICAgIGl0c2VsZiBmdWxmaWxsLlxuXG5cbiAgICAgIEJhc2ljIFVzYWdlOlxuICAgICAgLS0tLS0tLS0tLS0tXG5cbiAgICAgIGBgYGpzXG4gICAgICB2YXIgcHJvbWlzZSA9IG5ldyBQcm9taXNlKGZ1bmN0aW9uKHJlc29sdmUsIHJlamVjdCkge1xuICAgICAgICAvLyBvbiBzdWNjZXNzXG4gICAgICAgIHJlc29sdmUodmFsdWUpO1xuXG4gICAgICAgIC8vIG9uIGZhaWx1cmVcbiAgICAgICAgcmVqZWN0KHJlYXNvbik7XG4gICAgICB9KTtcblxuICAgICAgcHJvbWlzZS50aGVuKGZ1bmN0aW9uKHZhbHVlKSB7XG4gICAgICAgIC8vIG9uIGZ1bGZpbGxtZW50XG4gICAgICB9LCBmdW5jdGlvbihyZWFzb24pIHtcbiAgICAgICAgLy8gb24gcmVqZWN0aW9uXG4gICAgICB9KTtcbiAgICAgIGBgYFxuXG4gICAgICBBZHZhbmNlZCBVc2FnZTpcbiAgICAgIC0tLS0tLS0tLS0tLS0tLVxuXG4gICAgICBQcm9taXNlcyBzaGluZSB3aGVuIGFic3RyYWN0aW5nIGF3YXkgYXN5bmNocm9ub3VzIGludGVyYWN0aW9ucyBzdWNoIGFzXG4gICAgICBgWE1MSHR0cFJlcXVlc3Rgcy5cblxuICAgICAgYGBganNcbiAgICAgIGZ1bmN0aW9uIGdldEpTT04odXJsKSB7XG4gICAgICAgIHJldHVybiBuZXcgUHJvbWlzZShmdW5jdGlvbihyZXNvbHZlLCByZWplY3Qpe1xuICAgICAgICAgIHZhciB4aHIgPSBuZXcgWE1MSHR0cFJlcXVlc3QoKTtcblxuICAgICAgICAgIHhoci5vcGVuKCdHRVQnLCB1cmwpO1xuICAgICAgICAgIHhoci5vbnJlYWR5c3RhdGVjaGFuZ2UgPSBoYW5kbGVyO1xuICAgICAgICAgIHhoci5yZXNwb25zZVR5cGUgPSAnanNvbic7XG4gICAgICAgICAgeGhyLnNldFJlcXVlc3RIZWFkZXIoJ0FjY2VwdCcsICdhcHBsaWNhdGlvbi9qc29uJyk7XG4gICAgICAgICAgeGhyLnNlbmQoKTtcblxuICAgICAgICAgIGZ1bmN0aW9uIGhhbmRsZXIoKSB7XG4gICAgICAgICAgICBpZiAodGhpcy5yZWFkeVN0YXRlID09PSB0aGlzLkRPTkUpIHtcbiAgICAgICAgICAgICAgaWYgKHRoaXMuc3RhdHVzID09PSAyMDApIHtcbiAgICAgICAgICAgICAgICByZXNvbHZlKHRoaXMucmVzcG9uc2UpO1xuICAgICAgICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgICAgIHJlamVjdChuZXcgRXJyb3IoJ2dldEpTT046IGAnICsgdXJsICsgJ2AgZmFpbGVkIHdpdGggc3RhdHVzOiBbJyArIHRoaXMuc3RhdHVzICsgJ10nKSk7XG4gICAgICAgICAgICAgIH1cbiAgICAgICAgICAgIH1cbiAgICAgICAgICB9O1xuICAgICAgICB9KTtcbiAgICAgIH1cblxuICAgICAgZ2V0SlNPTignL3Bvc3RzLmpzb24nKS50aGVuKGZ1bmN0aW9uKGpzb24pIHtcbiAgICAgICAgLy8gb24gZnVsZmlsbG1lbnRcbiAgICAgIH0sIGZ1bmN0aW9uKHJlYXNvbikge1xuICAgICAgICAvLyBvbiByZWplY3Rpb25cbiAgICAgIH0pO1xuICAgICAgYGBgXG5cbiAgICAgIFVubGlrZSBjYWxsYmFja3MsIHByb21pc2VzIGFyZSBncmVhdCBjb21wb3NhYmxlIHByaW1pdGl2ZXMuXG5cbiAgICAgIGBgYGpzXG4gICAgICBQcm9taXNlLmFsbChbXG4gICAgICAgIGdldEpTT04oJy9wb3N0cycpLFxuICAgICAgICBnZXRKU09OKCcvY29tbWVudHMnKVxuICAgICAgXSkudGhlbihmdW5jdGlvbih2YWx1ZXMpe1xuICAgICAgICB2YWx1ZXNbMF0gLy8gPT4gcG9zdHNKU09OXG4gICAgICAgIHZhbHVlc1sxXSAvLyA9PiBjb21tZW50c0pTT05cblxuICAgICAgICByZXR1cm4gdmFsdWVzO1xuICAgICAgfSk7XG4gICAgICBgYGBcblxuICAgICAgQGNsYXNzIFByb21pc2VcbiAgICAgIEBwYXJhbSB7ZnVuY3Rpb259IHJlc29sdmVyXG4gICAgICBVc2VmdWwgZm9yIHRvb2xpbmcuXG4gICAgICBAY29uc3RydWN0b3JcbiAgICAqL1xuICAgIGZ1bmN0aW9uIGxpYiRlczYkcHJvbWlzZSRwcm9taXNlJCRQcm9taXNlKHJlc29sdmVyKSB7XG4gICAgICB0aGlzLl9pZCA9IGxpYiRlczYkcHJvbWlzZSRwcm9taXNlJCRjb3VudGVyKys7XG4gICAgICB0aGlzLl9zdGF0ZSA9IHVuZGVmaW5lZDtcbiAgICAgIHRoaXMuX3Jlc3VsdCA9IHVuZGVmaW5lZDtcbiAgICAgIHRoaXMuX3N1YnNjcmliZXJzID0gW107XG5cbiAgICAgIGlmIChsaWIkZXM2JHByb21pc2UkJGludGVybmFsJCRub29wICE9PSByZXNvbHZlcikge1xuICAgICAgICBpZiAoIWxpYiRlczYkcHJvbWlzZSR1dGlscyQkaXNGdW5jdGlvbihyZXNvbHZlcikpIHtcbiAgICAgICAgICBsaWIkZXM2JHByb21pc2UkcHJvbWlzZSQkbmVlZHNSZXNvbHZlcigpO1xuICAgICAgICB9XG5cbiAgICAgICAgaWYgKCEodGhpcyBpbnN0YW5jZW9mIGxpYiRlczYkcHJvbWlzZSRwcm9taXNlJCRQcm9taXNlKSkge1xuICAgICAgICAgIGxpYiRlczYkcHJvbWlzZSRwcm9taXNlJCRuZWVkc05ldygpO1xuICAgICAgICB9XG5cbiAgICAgICAgbGliJGVzNiRwcm9taXNlJCRpbnRlcm5hbCQkaW5pdGlhbGl6ZVByb21pc2UodGhpcywgcmVzb2x2ZXIpO1xuICAgICAgfVxuICAgIH1cblxuICAgIGxpYiRlczYkcHJvbWlzZSRwcm9taXNlJCRQcm9taXNlLmFsbCA9IGxpYiRlczYkcHJvbWlzZSRwcm9taXNlJGFsbCQkZGVmYXVsdDtcbiAgICBsaWIkZXM2JHByb21pc2UkcHJvbWlzZSQkUHJvbWlzZS5yYWNlID0gbGliJGVzNiRwcm9taXNlJHByb21pc2UkcmFjZSQkZGVmYXVsdDtcbiAgICBsaWIkZXM2JHByb21pc2UkcHJvbWlzZSQkUHJvbWlzZS5yZXNvbHZlID0gbGliJGVzNiRwcm9taXNlJHByb21pc2UkcmVzb2x2ZSQkZGVmYXVsdDtcbiAgICBsaWIkZXM2JHByb21pc2UkcHJvbWlzZSQkUHJvbWlzZS5yZWplY3QgPSBsaWIkZXM2JHByb21pc2UkcHJvbWlzZSRyZWplY3QkJGRlZmF1bHQ7XG4gICAgbGliJGVzNiRwcm9taXNlJHByb21pc2UkJFByb21pc2UuX3NldFNjaGVkdWxlciA9IGxpYiRlczYkcHJvbWlzZSRhc2FwJCRzZXRTY2hlZHVsZXI7XG4gICAgbGliJGVzNiRwcm9taXNlJHByb21pc2UkJFByb21pc2UuX3NldEFzYXAgPSBsaWIkZXM2JHByb21pc2UkYXNhcCQkc2V0QXNhcDtcbiAgICBsaWIkZXM2JHByb21pc2UkcHJvbWlzZSQkUHJvbWlzZS5fYXNhcCA9IGxpYiRlczYkcHJvbWlzZSRhc2FwJCRhc2FwO1xuXG4gICAgbGliJGVzNiRwcm9taXNlJHByb21pc2UkJFByb21pc2UucHJvdG90eXBlID0ge1xuICAgICAgY29uc3RydWN0b3I6IGxpYiRlczYkcHJvbWlzZSRwcm9taXNlJCRQcm9taXNlLFxuXG4gICAgLyoqXG4gICAgICBUaGUgcHJpbWFyeSB3YXkgb2YgaW50ZXJhY3Rpbmcgd2l0aCBhIHByb21pc2UgaXMgdGhyb3VnaCBpdHMgYHRoZW5gIG1ldGhvZCxcbiAgICAgIHdoaWNoIHJlZ2lzdGVycyBjYWxsYmFja3MgdG8gcmVjZWl2ZSBlaXRoZXIgYSBwcm9taXNlJ3MgZXZlbnR1YWwgdmFsdWUgb3IgdGhlXG4gICAgICByZWFzb24gd2h5IHRoZSBwcm9taXNlIGNhbm5vdCBiZSBmdWxmaWxsZWQuXG5cbiAgICAgIGBgYGpzXG4gICAgICBmaW5kVXNlcigpLnRoZW4oZnVuY3Rpb24odXNlcil7XG4gICAgICAgIC8vIHVzZXIgaXMgYXZhaWxhYmxlXG4gICAgICB9LCBmdW5jdGlvbihyZWFzb24pe1xuICAgICAgICAvLyB1c2VyIGlzIHVuYXZhaWxhYmxlLCBhbmQgeW91IGFyZSBnaXZlbiB0aGUgcmVhc29uIHdoeVxuICAgICAgfSk7XG4gICAgICBgYGBcblxuICAgICAgQ2hhaW5pbmdcbiAgICAgIC0tLS0tLS0tXG5cbiAgICAgIFRoZSByZXR1cm4gdmFsdWUgb2YgYHRoZW5gIGlzIGl0c2VsZiBhIHByb21pc2UuICBUaGlzIHNlY29uZCwgJ2Rvd25zdHJlYW0nXG4gICAgICBwcm9taXNlIGlzIHJlc29sdmVkIHdpdGggdGhlIHJldHVybiB2YWx1ZSBvZiB0aGUgZmlyc3QgcHJvbWlzZSdzIGZ1bGZpbGxtZW50XG4gICAgICBvciByZWplY3Rpb24gaGFuZGxlciwgb3IgcmVqZWN0ZWQgaWYgdGhlIGhhbmRsZXIgdGhyb3dzIGFuIGV4Y2VwdGlvbi5cblxuICAgICAgYGBganNcbiAgICAgIGZpbmRVc2VyKCkudGhlbihmdW5jdGlvbiAodXNlcikge1xuICAgICAgICByZXR1cm4gdXNlci5uYW1lO1xuICAgICAgfSwgZnVuY3Rpb24gKHJlYXNvbikge1xuICAgICAgICByZXR1cm4gJ2RlZmF1bHQgbmFtZSc7XG4gICAgICB9KS50aGVuKGZ1bmN0aW9uICh1c2VyTmFtZSkge1xuICAgICAgICAvLyBJZiBgZmluZFVzZXJgIGZ1bGZpbGxlZCwgYHVzZXJOYW1lYCB3aWxsIGJlIHRoZSB1c2VyJ3MgbmFtZSwgb3RoZXJ3aXNlIGl0XG4gICAgICAgIC8vIHdpbGwgYmUgYCdkZWZhdWx0IG5hbWUnYFxuICAgICAgfSk7XG5cbiAgICAgIGZpbmRVc2VyKCkudGhlbihmdW5jdGlvbiAodXNlcikge1xuICAgICAgICB0aHJvdyBuZXcgRXJyb3IoJ0ZvdW5kIHVzZXIsIGJ1dCBzdGlsbCB1bmhhcHB5Jyk7XG4gICAgICB9LCBmdW5jdGlvbiAocmVhc29uKSB7XG4gICAgICAgIHRocm93IG5ldyBFcnJvcignYGZpbmRVc2VyYCByZWplY3RlZCBhbmQgd2UncmUgdW5oYXBweScpO1xuICAgICAgfSkudGhlbihmdW5jdGlvbiAodmFsdWUpIHtcbiAgICAgICAgLy8gbmV2ZXIgcmVhY2hlZFxuICAgICAgfSwgZnVuY3Rpb24gKHJlYXNvbikge1xuICAgICAgICAvLyBpZiBgZmluZFVzZXJgIGZ1bGZpbGxlZCwgYHJlYXNvbmAgd2lsbCBiZSAnRm91bmQgdXNlciwgYnV0IHN0aWxsIHVuaGFwcHknLlxuICAgICAgICAvLyBJZiBgZmluZFVzZXJgIHJlamVjdGVkLCBgcmVhc29uYCB3aWxsIGJlICdgZmluZFVzZXJgIHJlamVjdGVkIGFuZCB3ZSdyZSB1bmhhcHB5Jy5cbiAgICAgIH0pO1xuICAgICAgYGBgXG4gICAgICBJZiB0aGUgZG93bnN0cmVhbSBwcm9taXNlIGRvZXMgbm90IHNwZWNpZnkgYSByZWplY3Rpb24gaGFuZGxlciwgcmVqZWN0aW9uIHJlYXNvbnMgd2lsbCBiZSBwcm9wYWdhdGVkIGZ1cnRoZXIgZG93bnN0cmVhbS5cblxuICAgICAgYGBganNcbiAgICAgIGZpbmRVc2VyKCkudGhlbihmdW5jdGlvbiAodXNlcikge1xuICAgICAgICB0aHJvdyBuZXcgUGVkYWdvZ2ljYWxFeGNlcHRpb24oJ1Vwc3RyZWFtIGVycm9yJyk7XG4gICAgICB9KS50aGVuKGZ1bmN0aW9uICh2YWx1ZSkge1xuICAgICAgICAvLyBuZXZlciByZWFjaGVkXG4gICAgICB9KS50aGVuKGZ1bmN0aW9uICh2YWx1ZSkge1xuICAgICAgICAvLyBuZXZlciByZWFjaGVkXG4gICAgICB9LCBmdW5jdGlvbiAocmVhc29uKSB7XG4gICAgICAgIC8vIFRoZSBgUGVkZ2Fnb2NpYWxFeGNlcHRpb25gIGlzIHByb3BhZ2F0ZWQgYWxsIHRoZSB3YXkgZG93biB0byBoZXJlXG4gICAgICB9KTtcbiAgICAgIGBgYFxuXG4gICAgICBBc3NpbWlsYXRpb25cbiAgICAgIC0tLS0tLS0tLS0tLVxuXG4gICAgICBTb21ldGltZXMgdGhlIHZhbHVlIHlvdSB3YW50IHRvIHByb3BhZ2F0ZSB0byBhIGRvd25zdHJlYW0gcHJvbWlzZSBjYW4gb25seSBiZVxuICAgICAgcmV0cmlldmVkIGFzeW5jaHJvbm91c2x5LiBUaGlzIGNhbiBiZSBhY2hpZXZlZCBieSByZXR1cm5pbmcgYSBwcm9taXNlIGluIHRoZVxuICAgICAgZnVsZmlsbG1lbnQgb3IgcmVqZWN0aW9uIGhhbmRsZXIuIFRoZSBkb3duc3RyZWFtIHByb21pc2Ugd2lsbCB0aGVuIGJlIHBlbmRpbmdcbiAgICAgIHVudGlsIHRoZSByZXR1cm5lZCBwcm9taXNlIGlzIHNldHRsZWQuIFRoaXMgaXMgY2FsbGVkICphc3NpbWlsYXRpb24qLlxuXG4gICAgICBgYGBqc1xuICAgICAgZmluZFVzZXIoKS50aGVuKGZ1bmN0aW9uICh1c2VyKSB7XG4gICAgICAgIHJldHVybiBmaW5kQ29tbWVudHNCeUF1dGhvcih1c2VyKTtcbiAgICAgIH0pLnRoZW4oZnVuY3Rpb24gKGNvbW1lbnRzKSB7XG4gICAgICAgIC8vIFRoZSB1c2VyJ3MgY29tbWVudHMgYXJlIG5vdyBhdmFpbGFibGVcbiAgICAgIH0pO1xuICAgICAgYGBgXG5cbiAgICAgIElmIHRoZSBhc3NpbWxpYXRlZCBwcm9taXNlIHJlamVjdHMsIHRoZW4gdGhlIGRvd25zdHJlYW0gcHJvbWlzZSB3aWxsIGFsc28gcmVqZWN0LlxuXG4gICAgICBgYGBqc1xuICAgICAgZmluZFVzZXIoKS50aGVuKGZ1bmN0aW9uICh1c2VyKSB7XG4gICAgICAgIHJldHVybiBmaW5kQ29tbWVudHNCeUF1dGhvcih1c2VyKTtcbiAgICAgIH0pLnRoZW4oZnVuY3Rpb24gKGNvbW1lbnRzKSB7XG4gICAgICAgIC8vIElmIGBmaW5kQ29tbWVudHNCeUF1dGhvcmAgZnVsZmlsbHMsIHdlJ2xsIGhhdmUgdGhlIHZhbHVlIGhlcmVcbiAgICAgIH0sIGZ1bmN0aW9uIChyZWFzb24pIHtcbiAgICAgICAgLy8gSWYgYGZpbmRDb21tZW50c0J5QXV0aG9yYCByZWplY3RzLCB3ZSdsbCBoYXZlIHRoZSByZWFzb24gaGVyZVxuICAgICAgfSk7XG4gICAgICBgYGBcblxuICAgICAgU2ltcGxlIEV4YW1wbGVcbiAgICAgIC0tLS0tLS0tLS0tLS0tXG5cbiAgICAgIFN5bmNocm9ub3VzIEV4YW1wbGVcblxuICAgICAgYGBgamF2YXNjcmlwdFxuICAgICAgdmFyIHJlc3VsdDtcblxuICAgICAgdHJ5IHtcbiAgICAgICAgcmVzdWx0ID0gZmluZFJlc3VsdCgpO1xuICAgICAgICAvLyBzdWNjZXNzXG4gICAgICB9IGNhdGNoKHJlYXNvbikge1xuICAgICAgICAvLyBmYWlsdXJlXG4gICAgICB9XG4gICAgICBgYGBcblxuICAgICAgRXJyYmFjayBFeGFtcGxlXG5cbiAgICAgIGBgYGpzXG4gICAgICBmaW5kUmVzdWx0KGZ1bmN0aW9uKHJlc3VsdCwgZXJyKXtcbiAgICAgICAgaWYgKGVycikge1xuICAgICAgICAgIC8vIGZhaWx1cmVcbiAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAvLyBzdWNjZXNzXG4gICAgICAgIH1cbiAgICAgIH0pO1xuICAgICAgYGBgXG5cbiAgICAgIFByb21pc2UgRXhhbXBsZTtcblxuICAgICAgYGBgamF2YXNjcmlwdFxuICAgICAgZmluZFJlc3VsdCgpLnRoZW4oZnVuY3Rpb24ocmVzdWx0KXtcbiAgICAgICAgLy8gc3VjY2Vzc1xuICAgICAgfSwgZnVuY3Rpb24ocmVhc29uKXtcbiAgICAgICAgLy8gZmFpbHVyZVxuICAgICAgfSk7XG4gICAgICBgYGBcblxuICAgICAgQWR2YW5jZWQgRXhhbXBsZVxuICAgICAgLS0tLS0tLS0tLS0tLS1cblxuICAgICAgU3luY2hyb25vdXMgRXhhbXBsZVxuXG4gICAgICBgYGBqYXZhc2NyaXB0XG4gICAgICB2YXIgYXV0aG9yLCBib29rcztcblxuICAgICAgdHJ5IHtcbiAgICAgICAgYXV0aG9yID0gZmluZEF1dGhvcigpO1xuICAgICAgICBib29rcyAgPSBmaW5kQm9va3NCeUF1dGhvcihhdXRob3IpO1xuICAgICAgICAvLyBzdWNjZXNzXG4gICAgICB9IGNhdGNoKHJlYXNvbikge1xuICAgICAgICAvLyBmYWlsdXJlXG4gICAgICB9XG4gICAgICBgYGBcblxuICAgICAgRXJyYmFjayBFeGFtcGxlXG5cbiAgICAgIGBgYGpzXG5cbiAgICAgIGZ1bmN0aW9uIGZvdW5kQm9va3MoYm9va3MpIHtcblxuICAgICAgfVxuXG4gICAgICBmdW5jdGlvbiBmYWlsdXJlKHJlYXNvbikge1xuXG4gICAgICB9XG5cbiAgICAgIGZpbmRBdXRob3IoZnVuY3Rpb24oYXV0aG9yLCBlcnIpe1xuICAgICAgICBpZiAoZXJyKSB7XG4gICAgICAgICAgZmFpbHVyZShlcnIpO1xuICAgICAgICAgIC8vIGZhaWx1cmVcbiAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICB0cnkge1xuICAgICAgICAgICAgZmluZEJvb29rc0J5QXV0aG9yKGF1dGhvciwgZnVuY3Rpb24oYm9va3MsIGVycikge1xuICAgICAgICAgICAgICBpZiAoZXJyKSB7XG4gICAgICAgICAgICAgICAgZmFpbHVyZShlcnIpO1xuICAgICAgICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgICAgIHRyeSB7XG4gICAgICAgICAgICAgICAgICBmb3VuZEJvb2tzKGJvb2tzKTtcbiAgICAgICAgICAgICAgICB9IGNhdGNoKHJlYXNvbikge1xuICAgICAgICAgICAgICAgICAgZmFpbHVyZShyZWFzb24pO1xuICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgfSk7XG4gICAgICAgICAgfSBjYXRjaChlcnJvcikge1xuICAgICAgICAgICAgZmFpbHVyZShlcnIpO1xuICAgICAgICAgIH1cbiAgICAgICAgICAvLyBzdWNjZXNzXG4gICAgICAgIH1cbiAgICAgIH0pO1xuICAgICAgYGBgXG5cbiAgICAgIFByb21pc2UgRXhhbXBsZTtcblxuICAgICAgYGBgamF2YXNjcmlwdFxuICAgICAgZmluZEF1dGhvcigpLlxuICAgICAgICB0aGVuKGZpbmRCb29rc0J5QXV0aG9yKS5cbiAgICAgICAgdGhlbihmdW5jdGlvbihib29rcyl7XG4gICAgICAgICAgLy8gZm91bmQgYm9va3NcbiAgICAgIH0pLmNhdGNoKGZ1bmN0aW9uKHJlYXNvbil7XG4gICAgICAgIC8vIHNvbWV0aGluZyB3ZW50IHdyb25nXG4gICAgICB9KTtcbiAgICAgIGBgYFxuXG4gICAgICBAbWV0aG9kIHRoZW5cbiAgICAgIEBwYXJhbSB7RnVuY3Rpb259IG9uRnVsZmlsbGVkXG4gICAgICBAcGFyYW0ge0Z1bmN0aW9ufSBvblJlamVjdGVkXG4gICAgICBVc2VmdWwgZm9yIHRvb2xpbmcuXG4gICAgICBAcmV0dXJuIHtQcm9taXNlfVxuICAgICovXG4gICAgICB0aGVuOiBmdW5jdGlvbihvbkZ1bGZpbGxtZW50LCBvblJlamVjdGlvbikge1xuICAgICAgICB2YXIgcGFyZW50ID0gdGhpcztcbiAgICAgICAgdmFyIHN0YXRlID0gcGFyZW50Ll9zdGF0ZTtcblxuICAgICAgICBpZiAoc3RhdGUgPT09IGxpYiRlczYkcHJvbWlzZSQkaW50ZXJuYWwkJEZVTEZJTExFRCAmJiAhb25GdWxmaWxsbWVudCB8fCBzdGF0ZSA9PT0gbGliJGVzNiRwcm9taXNlJCRpbnRlcm5hbCQkUkVKRUNURUQgJiYgIW9uUmVqZWN0aW9uKSB7XG4gICAgICAgICAgcmV0dXJuIHRoaXM7XG4gICAgICAgIH1cblxuICAgICAgICB2YXIgY2hpbGQgPSBuZXcgdGhpcy5jb25zdHJ1Y3RvcihsaWIkZXM2JHByb21pc2UkJGludGVybmFsJCRub29wKTtcbiAgICAgICAgdmFyIHJlc3VsdCA9IHBhcmVudC5fcmVzdWx0O1xuXG4gICAgICAgIGlmIChzdGF0ZSkge1xuICAgICAgICAgIHZhciBjYWxsYmFjayA9IGFyZ3VtZW50c1tzdGF0ZSAtIDFdO1xuICAgICAgICAgIGxpYiRlczYkcHJvbWlzZSRhc2FwJCRhc2FwKGZ1bmN0aW9uKCl7XG4gICAgICAgICAgICBsaWIkZXM2JHByb21pc2UkJGludGVybmFsJCRpbnZva2VDYWxsYmFjayhzdGF0ZSwgY2hpbGQsIGNhbGxiYWNrLCByZXN1bHQpO1xuICAgICAgICAgIH0pO1xuICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgIGxpYiRlczYkcHJvbWlzZSQkaW50ZXJuYWwkJHN1YnNjcmliZShwYXJlbnQsIGNoaWxkLCBvbkZ1bGZpbGxtZW50LCBvblJlamVjdGlvbik7XG4gICAgICAgIH1cblxuICAgICAgICByZXR1cm4gY2hpbGQ7XG4gICAgICB9LFxuXG4gICAgLyoqXG4gICAgICBgY2F0Y2hgIGlzIHNpbXBseSBzdWdhciBmb3IgYHRoZW4odW5kZWZpbmVkLCBvblJlamVjdGlvbilgIHdoaWNoIG1ha2VzIGl0IHRoZSBzYW1lXG4gICAgICBhcyB0aGUgY2F0Y2ggYmxvY2sgb2YgYSB0cnkvY2F0Y2ggc3RhdGVtZW50LlxuXG4gICAgICBgYGBqc1xuICAgICAgZnVuY3Rpb24gZmluZEF1dGhvcigpe1xuICAgICAgICB0aHJvdyBuZXcgRXJyb3IoJ2NvdWxkbid0IGZpbmQgdGhhdCBhdXRob3InKTtcbiAgICAgIH1cblxuICAgICAgLy8gc3luY2hyb25vdXNcbiAgICAgIHRyeSB7XG4gICAgICAgIGZpbmRBdXRob3IoKTtcbiAgICAgIH0gY2F0Y2gocmVhc29uKSB7XG4gICAgICAgIC8vIHNvbWV0aGluZyB3ZW50IHdyb25nXG4gICAgICB9XG5cbiAgICAgIC8vIGFzeW5jIHdpdGggcHJvbWlzZXNcbiAgICAgIGZpbmRBdXRob3IoKS5jYXRjaChmdW5jdGlvbihyZWFzb24pe1xuICAgICAgICAvLyBzb21ldGhpbmcgd2VudCB3cm9uZ1xuICAgICAgfSk7XG4gICAgICBgYGBcblxuICAgICAgQG1ldGhvZCBjYXRjaFxuICAgICAgQHBhcmFtIHtGdW5jdGlvbn0gb25SZWplY3Rpb25cbiAgICAgIFVzZWZ1bCBmb3IgdG9vbGluZy5cbiAgICAgIEByZXR1cm4ge1Byb21pc2V9XG4gICAgKi9cbiAgICAgICdjYXRjaCc6IGZ1bmN0aW9uKG9uUmVqZWN0aW9uKSB7XG4gICAgICAgIHJldHVybiB0aGlzLnRoZW4obnVsbCwgb25SZWplY3Rpb24pO1xuICAgICAgfVxuICAgIH07XG4gICAgZnVuY3Rpb24gbGliJGVzNiRwcm9taXNlJHBvbHlmaWxsJCRwb2x5ZmlsbCgpIHtcbiAgICAgIHZhciBsb2NhbDtcblxuICAgICAgaWYgKHR5cGVvZiBnbG9iYWwgIT09ICd1bmRlZmluZWQnKSB7XG4gICAgICAgICAgbG9jYWwgPSBnbG9iYWw7XG4gICAgICB9IGVsc2UgaWYgKHR5cGVvZiBzZWxmICE9PSAndW5kZWZpbmVkJykge1xuICAgICAgICAgIGxvY2FsID0gc2VsZjtcbiAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgdHJ5IHtcbiAgICAgICAgICAgICAgbG9jYWwgPSBGdW5jdGlvbigncmV0dXJuIHRoaXMnKSgpO1xuICAgICAgICAgIH0gY2F0Y2ggKGUpIHtcbiAgICAgICAgICAgICAgdGhyb3cgbmV3IEVycm9yKCdwb2x5ZmlsbCBmYWlsZWQgYmVjYXVzZSBnbG9iYWwgb2JqZWN0IGlzIHVuYXZhaWxhYmxlIGluIHRoaXMgZW52aXJvbm1lbnQnKTtcbiAgICAgICAgICB9XG4gICAgICB9XG5cbiAgICAgIHZhciBQID0gbG9jYWwuUHJvbWlzZTtcblxuICAgICAgaWYgKFAgJiYgT2JqZWN0LnByb3RvdHlwZS50b1N0cmluZy5jYWxsKFAucmVzb2x2ZSgpKSA9PT0gJ1tvYmplY3QgUHJvbWlzZV0nICYmICFQLmNhc3QpIHtcbiAgICAgICAgcmV0dXJuO1xuICAgICAgfVxuXG4gICAgICBsb2NhbC5Qcm9taXNlID0gbGliJGVzNiRwcm9taXNlJHByb21pc2UkJGRlZmF1bHQ7XG4gICAgfVxuICAgIHZhciBsaWIkZXM2JHByb21pc2UkcG9seWZpbGwkJGRlZmF1bHQgPSBsaWIkZXM2JHByb21pc2UkcG9seWZpbGwkJHBvbHlmaWxsO1xuXG4gICAgdmFyIGxpYiRlczYkcHJvbWlzZSR1bWQkJEVTNlByb21pc2UgPSB7XG4gICAgICAnUHJvbWlzZSc6IGxpYiRlczYkcHJvbWlzZSRwcm9taXNlJCRkZWZhdWx0LFxuICAgICAgJ3BvbHlmaWxsJzogbGliJGVzNiRwcm9taXNlJHBvbHlmaWxsJCRkZWZhdWx0XG4gICAgfTtcblxuICAgIC8qIGdsb2JhbCBkZWZpbmU6dHJ1ZSBtb2R1bGU6dHJ1ZSB3aW5kb3c6IHRydWUgKi9cbiAgICBpZiAodHlwZW9mIGRlZmluZSA9PT0gJ2Z1bmN0aW9uJyAmJiBkZWZpbmVbJ2FtZCddKSB7XG4gICAgICBkZWZpbmUoZnVuY3Rpb24oKSB7IHJldHVybiBsaWIkZXM2JHByb21pc2UkdW1kJCRFUzZQcm9taXNlOyB9KTtcbiAgICB9IGVsc2UgaWYgKHR5cGVvZiBtb2R1bGUgIT09ICd1bmRlZmluZWQnICYmIG1vZHVsZVsnZXhwb3J0cyddKSB7XG4gICAgICBtb2R1bGVbJ2V4cG9ydHMnXSA9IGxpYiRlczYkcHJvbWlzZSR1bWQkJEVTNlByb21pc2U7XG4gICAgfSBlbHNlIGlmICh0eXBlb2YgdGhpcyAhPT0gJ3VuZGVmaW5lZCcpIHtcbiAgICAgIHRoaXNbJ0VTNlByb21pc2UnXSA9IGxpYiRlczYkcHJvbWlzZSR1bWQkJEVTNlByb21pc2U7XG4gICAgfVxuXG4gICAgbGliJGVzNiRwcm9taXNlJHBvbHlmaWxsJCRkZWZhdWx0KCk7XG59KS5jYWxsKHRoaXMpO1xuXG4iLCIvKiBDb3B5cmlnaHQgQCAyMDE1IEF0bGFzc2lhbiBQdHkgTHRkXG4gKlxuICogTGljZW5zZWQgdW5kZXIgdGhlIEFwYWNoZSBMaWNlbnNlLCBWZXJzaW9uIDIuMCAodGhlIFwiTGljZW5zZVwiKTtcbiAqIHlvdSBtYXkgbm90IHVzZSB0aGlzIGZpbGUgZXhjZXB0IGluIGNvbXBsaWFuY2Ugd2l0aCB0aGUgTGljZW5zZS5cbiAqIFlvdSBtYXkgb2J0YWluIGEgY29weSBvZiB0aGUgTGljZW5zZSBhdFxuICpcbiAqICAgICBodHRwOi8vd3d3LmFwYWNoZS5vcmcvbGljZW5zZXMvTElDRU5TRS0yLjBcbiAqXG4gKiBVbmxlc3MgcmVxdWlyZWQgYnkgYXBwbGljYWJsZSBsYXcgb3IgYWdyZWVkIHRvIGluIHdyaXRpbmcsIHNvZnR3YXJlXG4gKiBkaXN0cmlidXRlZCB1bmRlciB0aGUgTGljZW5zZSBpcyBkaXN0cmlidXRlZCBvbiBhbiBcIkFTIElTXCIgQkFTSVMsXG4gKiBXSVRIT1VUIFdBUlJBTlRJRVMgT1IgQ09ORElUSU9OUyBPRiBBTlkgS0lORCwgZWl0aGVyIGV4cHJlc3Mgb3IgaW1wbGllZC5cbiAqIFNlZSB0aGUgTGljZW5zZSBmb3IgdGhlIHNwZWNpZmljIGxhbmd1YWdlIGdvdmVybmluZyBwZXJtaXNzaW9ucyBhbmRcbiAqIGxpbWl0YXRpb25zIHVuZGVyIHRoZSBMaWNlbnNlLlxuICovXG5cbi8qKlxuICogT3JkZXJlZCBsb2cgbGV2ZWxzLlxuICovXG52YXIgbGV2ZWxzID0ge1xuICAgIFwidHJhY2VcIjogMCxcbiAgICBcImRlYnVnXCI6IDEsXG4gICAgXCJpbmZvXCI6IDIsXG4gICAgXCJsb2dcIjogMyxcbiAgICBcIndhcm5cIjogNCxcbiAgICBcImVycm9yXCI6IDVcbn07XG5cbi8qKlxuICogUGFyc2VzIEVycm9yJ3Mgb2JqZWN0IHN0YWNrIHRyYWNlIGFuZCBleHRyYWN0cyBpbmZvcm1hdGlvbiBhYm91dCB0aGUgbGFzdFxuICogY2FsbGVyIGJlZm9yZSB0aGUgbG9nIG1ldGhvZCB3YXMgY2FsbGVkLlxuICogQHJldHVybnMgSlMgb2JqZWN0IHdpdGggaW5mbyBhYm91dCB0aGUgY2FsbGVyIC0gbWV0aG9kIG5hbWUsIGZpbGUgbG9jYXRpb24sXG4gKiBsaW5lIGFuZCBjb2x1bW4uXG4gKi9cbmZ1bmN0aW9uIGdldENhbGxlckluZm8oKSB7XG4gICAgdmFyIGNhbGxlckluZm8gPSB7XG4gICAgICAgIG1ldGhvZE5hbWU6IFwiXCIsXG4gICAgICAgIGZpbGVMb2NhdGlvbjogXCJcIixcbiAgICAgICAgbGluZTogbnVsbCxcbiAgICAgICAgY29sdW1uOiBudWxsXG4gICAgfTtcbiAgICAvL2dldHMgdGhlIHBhcnQgb2YgdGhlIHN0YWNrIHdpdGhvdXQgdGhlIGxvZ2dlciB3cmFwcGVyc1xuICAgIHZhciBlcnJvciA9IG5ldyBFcnJvcigpO1xuICAgIHZhciBzdGFjayA9IGVycm9yLnN0YWNrPyBlcnJvci5zdGFjay5zcGxpdChcIlxcblwiKSA6IFtdO1xuICAgIGlmKCFzdGFjayB8fCBzdGFjay5sZW5ndGggPCAxKSB7XG4gICAgICAgIHJldHVybiBjYWxsZXJJbmZvO1xuICAgIH1cbiAgICB2YXIgbSA9IG51bGw7XG4gICAgaWYoc3RhY2tbM10pIHtcbiAgICAgICAgbSA9IHN0YWNrWzNdLm1hdGNoKC9cXHMqYXRcXHMqKC4rPylcXHMqXFwoKFxcUyopXFxzKjooXFxkKilcXHMqOihcXGQqKVxcKS8pO1xuICAgIH1cbiAgICBpZighbSB8fCBtLmxlbmd0aCA8PSA0KSB7XG4gICAgICAgIC8vRmlyZWZveCAmJiBTYWZhcmlcbiAgICAgICAgaWYoc3RhY2tbMl0uaW5kZXhPZihcImxvZ0BcIikgPT09IDApe1xuICAgICAgICAgICAgLy9TYWZhcmlcbiAgICAgICAgICAgIGNhbGxlckluZm8ubWV0aG9kTmFtZSA9IHN0YWNrWzNdLnN1YnN0cigwLCBzdGFja1szXS5pbmRleE9mKFwiQFwiKSk7XG4gICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICAvL0ZpcmVmb3hcbiAgICAgICAgICAgIGNhbGxlckluZm8ubWV0aG9kTmFtZSA9IHN0YWNrWzJdLnN1YnN0cigwLCBzdGFja1syXS5pbmRleE9mKFwiQFwiKSk7XG4gICAgICAgIH1cbiAgICAgICAgcmV0dXJuIGNhbGxlckluZm87XG4gICAgfVxuXG4gICAgY2FsbGVySW5mby5tZXRob2ROYW1lID0gbVsxXTtcbiAgICBjYWxsZXJJbmZvLmZpbGVMb2NhdGlvbiA9IG1bMl07XG4gICAgY2FsbGVySW5mby5saW5lID0gbVszXTtcbiAgICBjYWxsZXJJbmZvLmNvbHVtbiA9IG1bNF07XG4gICAgcmV0dXJuIGNhbGxlckluZm87XG59XG5cbi8qKlxuICogTG9ncyBtZXNzYWdlcyB1c2luZyB0aGUgdHJhbnNwb3J0cyBhbmQgbGV2ZWwgZnJvbSB0aGUgbG9nZ2VyLlxuICogQHBhcmFtIGxvZ2dlciBhIGxvZ2dlciBpbnN0YW5jZS5cbiAqIEBwYXJhbSBsZXZlbCB0aGUgbG9nIGxldmVsIG9mIHRoZSBtZXNzYWdlLiBTZWUgdGhlIGxldmVscyB2YXJpYWJsZS5cbiAqIEBwYXJhbSBhcmd1bWVudHMgYXJyYXkgd2l0aCBhcmd1bWVudHMgdGhhdCB3aWxsIGJlIGxvZ2dlZC5cbiAqL1xuZnVuY3Rpb24gbG9nKCkge1xuICAgIHZhciBsb2dnZXIgPSBhcmd1bWVudHNbMF0sIGxldmVsID0gYXJndW1lbnRzWzFdLFxuICAgICAgICBhcmdzID0gQXJyYXkucHJvdG90eXBlLnNsaWNlLmNhbGwoYXJndW1lbnRzLCAyKTtcbiAgICBpZihsZXZlbHNbbGV2ZWxdIDw9IGxvZ2dlci5sZXZlbCkge1xuICAgICAgICByZXR1cm47XG4gICAgfVxuXG4gICAgdmFyIGNhbGxlckluZm8gPSBnZXRDYWxsZXJJbmZvKCk7XG4gICAgZm9yKHZhciBpID0gMDsgaSA8IGxvZ2dlci50cmFuc3BvcnRzLmxlbmd0aDsgaSsrKSB7XG4gICAgICAgIHZhciB0ID0gbG9nZ2VyLnRyYW5zcG9ydHNbaV07XG4gICAgICAgIHZhciBsID0gdFtsZXZlbF07XG4gICAgICAgIGlmKGwgJiYgdHlwZW9mKGwpID09PSBcImZ1bmN0aW9uXCIpIHtcbiAgICAgICAgICAgIGwuYmluZCh0LCBsb2dnZXIuaWQ/IFwiW1wiICsgbG9nZ2VyLmlkICsgXCJdXCIgOiBcIlwiLCBcIjxcIiArIGNhbGxlckluZm8ubWV0aG9kTmFtZSArIFwiPjogXCIpXG4gICAgICAgICAgICAgICAgLmFwcGx5KHQsIGFyZ3MpO1xuICAgICAgICB9XG4gICAgfVxufVxuXG4vKipcbiAqXG4gKiBDb25zdHJ1Y3RzIG5ldyBsb2dnZXIgb2JqZWN0LlxuICogQHBhcmFtIGxldmVsIHRoZSBsb2dnaW5nIGxldmVsIGZvciB0aGUgbmV3IGxvZ2dlclxuICogQHBhcmFtIGlkIG9wdGlvbmFsIGlkZW50aWZpZXIgZm9yIHRoZSBsb2dnZXIgaW5zdGFuY2UuXG4gKiBAcGFyYW0gdHJhbnNwb3J0cyBvcHRpb25hbCBsaXN0IG9mIGhhbmRsZXJzKG9iamVjdHMpIGZvciB0aGUgbG9ncy5cbiAqIFRoZSBoYW5kbGVycyBtdXN0IHN1cHBvcnQgLSBsb2csIHdhcm4sIGVycm9yLCBkZWJ1ZywgaW5mbywgdHJhY2UuXG4gKiBAcGFyYW0gZm9ybWF0IG9wdGlvbmFsIChOT1QgaW1wbGVtZW50ZWQpIHN0cmluZy5cbiAqL1xuZnVuY3Rpb24gTG9nZ2VyKGxldmVsLCBpZCwgdHJhbnNwb3J0cywgZm9ybWF0KSB7XG4gICAgdGhpcy5pZCA9IGlkO1xuICAgIHRoaXMuZm9ybWF0ID0gZm9ybWF0O1xuICAgIGlmKCF0aGlzLnRyYW5zcG9ydHMpIHtcbiAgICAgICAgdGhpcy50cmFuc3BvcnRzID0gW107XG4gICAgICAgIHRoaXMudHJhbnNwb3J0cy5wdXNoKExvZ2dlci5jb25zb2xlVHJhbnNwb3J0KTtcbiAgICB9XG4gICAgdGhpcy5sZXZlbCA9IGxldmVsc1tsZXZlbF07XG4gICAgdmFyIG1ldGhvZHMgPSBPYmplY3Qua2V5cyhsZXZlbHMpO1xuICAgIGZvcih2YXIgaSA9IDA7IGkgPCBtZXRob2RzLmxlbmd0aDsgaSsrKXtcbiAgICAgICAgdGhpc1ttZXRob2RzW2ldXSA9XG4gICAgICAgICAgICBsb2cuYmluZChudWxsLCB0aGlzLCBtZXRob2RzW2ldKTtcbiAgICB9XG59XG5cbi8qKlxuICogU2V0cyB0aGUgbG9nIGxldmVsIGZvciB0aGUgbG9nZ2VyLlxuICogQHBhcmFtIGxldmVsIHRoZSBuZXcgbG9nIGxldmVsLlxuICovXG5Mb2dnZXIucHJvdG90eXBlLnNldExldmVsID0gZnVuY3Rpb24gKGxldmVsKSB7XG4gICAgdGhpcy5sZXZlbCA9IGxldmVsc1tsZXZlbF07XG59O1xubW9kdWxlLmV4cG9ydHMgPSBMb2dnZXI7XG5cbi8qKlxuICogVGhlIGRlZmF1bHQgdHJhbnNwb3J0IC0gY29uc29sZVxuICovXG5Mb2dnZXIuY29uc29sZVRyYW5zcG9ydCA9IGNvbnNvbGU7XG5cbi8qKlxuICogRW51bSBmb3IgdGhlIHN1cHBvcnRlZCBsb2cgbGV2ZWxzLlxuICovXG5Mb2dnZXIubGV2ZWxzID0ge1xuICAgIFRSQUNFOiBcInRyYWNlXCIsXG4gICAgREVCVUc6IFwiZGVidWdcIixcbiAgICBJTkZPOiBcImluZm9cIixcbiAgICBMT0c6IFwibG9nXCIsXG4gICAgV0FSTjogXCJ3YXJuXCIsXG4gICAgRVJST1I6IFwiZXJyb3JcIlxufTtcbiIsIi8qIENvcHlyaWdodCBAIDIwMTUgQXRsYXNzaWFuIFB0eSBMdGRcbiAqXG4gKiBMaWNlbnNlZCB1bmRlciB0aGUgQXBhY2hlIExpY2Vuc2UsIFZlcnNpb24gMi4wICh0aGUgXCJMaWNlbnNlXCIpO1xuICogeW91IG1heSBub3QgdXNlIHRoaXMgZmlsZSBleGNlcHQgaW4gY29tcGxpYW5jZSB3aXRoIHRoZSBMaWNlbnNlLlxuICogWW91IG1heSBvYnRhaW4gYSBjb3B5IG9mIHRoZSBMaWNlbnNlIGF0XG4gKlxuICogICAgIGh0dHA6Ly93d3cuYXBhY2hlLm9yZy9saWNlbnNlcy9MSUNFTlNFLTIuMFxuICpcbiAqIFVubGVzcyByZXF1aXJlZCBieSBhcHBsaWNhYmxlIGxhdyBvciBhZ3JlZWQgdG8gaW4gd3JpdGluZywgc29mdHdhcmVcbiAqIGRpc3RyaWJ1dGVkIHVuZGVyIHRoZSBMaWNlbnNlIGlzIGRpc3RyaWJ1dGVkIG9uIGFuIFwiQVMgSVNcIiBCQVNJUyxcbiAqIFdJVEhPVVQgV0FSUkFOVElFUyBPUiBDT05ESVRJT05TIE9GIEFOWSBLSU5ELCBlaXRoZXIgZXhwcmVzcyBvciBpbXBsaWVkLlxuICogU2VlIHRoZSBMaWNlbnNlIGZvciB0aGUgc3BlY2lmaWMgbGFuZ3VhZ2UgZ292ZXJuaW5nIHBlcm1pc3Npb25zIGFuZFxuICogbGltaXRhdGlvbnMgdW5kZXIgdGhlIExpY2Vuc2UuXG4gKi9cbnZhciBMb2dnZXIgPSByZXF1aXJlKFwiLi9Mb2dnZXJcIik7XG5cbi8qKlxuICogTWFwIHdpdGggdGhlIGNyZWF0ZWQgbG9nZ2VycyB3aXRoIElELlxuICovXG52YXIgaWRMb2dnZXJzID0ge307XG5cbi8qKlxuICogQXJyYXkgd2l0aCB0aGUgbG9nZ2VycyB3aXRob3V0IGlkLlxuICovXG52YXIgbG9nZ2VycyA9IFtdO1xuXG4vKipcbiAqIExvZyBsZXZlbCBmb3IgdGhlIGxicmFyeS5cbiAqL1xudmFyIGN1ckxldmVsID0gTG9nZ2VyLmxldmVscy5UUkFDRTtcblxuXG5tb2R1bGUuZXhwb3J0cyA9IHtcbiAgICAvKipcbiAgICAgKiBDcmVhdGVzIG5ldyBsb2dnZXIuXG4gICAgICogQGFyZ3VtZW50cyB0aGUgc2FtZSBhcyBMb2dnZXIgY29uc3RydWN0b3JcbiAgICAgKi9cbiAgICBnZXRMb2dnZXI6IGZ1bmN0aW9uKGlkLCB0cmFuc3BvcnRzLCBmb3JtYXQpIHtcbiAgICAgICAgdmFyIGxvZ2dlciA9IG5ldyBMb2dnZXIoY3VyTGV2ZWwsIGlkLCB0cmFuc3BvcnRzLCBmb3JtYXQpO1xuICAgICAgICBpZihpZCkge1xuICAgICAgICAgICAgaWRMb2dnZXJzW2lkXSA9IGlkTG9nZ2Vyc1tpZF0gfHwgW107XG4gICAgICAgICAgICBpZExvZ2dlcnNbaWRdLnB1c2gobG9nZ2VyKTtcbiAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgIGxvZ2dlcnMucHVzaChsb2dnZXIpO1xuICAgICAgICB9XG4gICAgICAgIHJldHVybiBsb2dnZXI7XG4gICAgfSxcbiAgICAvKipcbiAgICAgKiBDaGFuZ2VzIHRoZSBsb2cgbGV2ZWwgZm9yIHRoZSBleGlzdGluZyBsb2dnZXJzIGJ5IGlkLlxuICAgICAqIEBwYXJhbSBsZXZlbCB0aGUgbmV3IGxvZyBsZXZlbC5cbiAgICAgKiBAcGFyYW0gaWQgaWYgc3BlY2lmaWVkIHRoZSBsZXZlbCB3aWxsIGJlIGNoYW5nZWQgb25seSBmb3IgbG9nZ2VycyB3aXRoIHRoZVxuICAgICAqIHNhbWUgaWQuIE90aGVyd2lzZSB0aGUgb3BlcmF0aW9uIHdpbGwgYWZmZWN0IGFsbCBsb2dnZXJzIHRoYXQgZG9uJ3RcbiAgICAgKiBoYXZlIGlkLlxuICAgICAqL1xuICAgIHNldExvZ0xldmVsQnlJZDogZnVuY3Rpb24obGV2ZWwsIGlkKSB7XG4gICAgICAgIHZhciBsID0gaWQ/IChpZExvZ2dlcnNbaWRdIHx8IFtdKSA6IGxvZ2dlcnM7XG4gICAgICAgIGZvcih2YXIgaSA9IDA7IGkgPCBsLmxlbmd0aDsgaSsrKSB7XG4gICAgICAgICAgICBsW2ldLnNldExldmVsKGxldmVsKTtcbiAgICAgICAgfVxuICAgIH0sXG4gICAgLyoqXG4gICAgICogQ2hhbmdlcyB0aGUgbG9nIGxldmVsIGZvciBhbGwgZXhpc3RpbmcgbG9nZ2Vycy5cbiAgICAgKiBAcGFyYW0gbGV2ZWwgdGhlIG5ldyBsb2cgbGV2ZWwuXG4gICAgICovXG4gICAgc2V0TG9nTGV2ZWw6IGZ1bmN0aW9uIChsZXZlbCkge1xuICAgICAgICBjdXJMZXZlbCA9IGxldmVsO1xuICAgICAgICB2YXIgaSA9IDA7XG4gICAgICAgIGZvcig7IGkgPCBsb2dnZXJzLmxlbmd0aDsgaSsrKSB7XG4gICAgICAgICAgICBsb2dnZXJzW2ldLnNldExldmVsKGxldmVsKTtcbiAgICAgICAgfVxuXG4gICAgICAgIGZvcih2YXIgaWQgaW4gaWRMb2dnZXJzKSB7XG4gICAgICAgICAgICB2YXIgbCA9IGlkTG9nZ2Vyc1tpZF0gfHwgW107XG4gICAgICAgICAgICBmb3IoaSA9IDA7IGkgPCBsLmxlbmd0aDsgaSsrKSB7XG4gICAgICAgICAgICAgICAgbFtpXS5zZXRMZXZlbChsZXZlbCk7XG4gICAgICAgICAgICB9XG4gICAgICAgIH1cbiAgICB9LFxuICAgIC8qKlxuICAgICAqIFRoZSBzdXBwb3J0ZWQgbG9nIGxldmVscy5cbiAgICAgKi9cbiAgICBsZXZlbHM6IExvZ2dlci5sZXZlbHNcbn07XG4iLCIvLyBUb3AgbGV2ZWwgZmlsZSBpcyBqdXN0IGEgbWl4aW4gb2Ygc3VibW9kdWxlcyAmIGNvbnN0YW50c1xuJ3VzZSBzdHJpY3QnO1xuXG52YXIgYXNzaWduICAgID0gcmVxdWlyZSgnLi9saWIvdXRpbHMvY29tbW9uJykuYXNzaWduO1xuXG52YXIgZGVmbGF0ZSAgID0gcmVxdWlyZSgnLi9saWIvZGVmbGF0ZScpO1xudmFyIGluZmxhdGUgICA9IHJlcXVpcmUoJy4vbGliL2luZmxhdGUnKTtcbnZhciBjb25zdGFudHMgPSByZXF1aXJlKCcuL2xpYi96bGliL2NvbnN0YW50cycpO1xuXG52YXIgcGFrbyA9IHt9O1xuXG5hc3NpZ24ocGFrbywgZGVmbGF0ZSwgaW5mbGF0ZSwgY29uc3RhbnRzKTtcblxubW9kdWxlLmV4cG9ydHMgPSBwYWtvO1xuIiwiJ3VzZSBzdHJpY3QnO1xuXG5cbnZhciB6bGliX2RlZmxhdGUgPSByZXF1aXJlKCcuL3psaWIvZGVmbGF0ZS5qcycpO1xudmFyIHV0aWxzID0gcmVxdWlyZSgnLi91dGlscy9jb21tb24nKTtcbnZhciBzdHJpbmdzID0gcmVxdWlyZSgnLi91dGlscy9zdHJpbmdzJyk7XG52YXIgbXNnID0gcmVxdWlyZSgnLi96bGliL21lc3NhZ2VzJyk7XG52YXIgenN0cmVhbSA9IHJlcXVpcmUoJy4vemxpYi96c3RyZWFtJyk7XG5cbnZhciB0b1N0cmluZyA9IE9iamVjdC5wcm90b3R5cGUudG9TdHJpbmc7XG5cbi8qIFB1YmxpYyBjb25zdGFudHMgPT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PSovXG4vKiA9PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT0qL1xuXG52YXIgWl9OT19GTFVTSCAgICAgID0gMDtcbnZhciBaX0ZJTklTSCAgICAgICAgPSA0O1xuXG52YXIgWl9PSyAgICAgICAgICAgID0gMDtcbnZhciBaX1NUUkVBTV9FTkQgICAgPSAxO1xudmFyIFpfU1lOQ19GTFVTSCAgICA9IDI7XG5cbnZhciBaX0RFRkFVTFRfQ09NUFJFU1NJT04gPSAtMTtcblxudmFyIFpfREVGQVVMVF9TVFJBVEVHWSAgICA9IDA7XG5cbnZhciBaX0RFRkxBVEVEICA9IDg7XG5cbi8qID09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PSovXG5cblxuLyoqXG4gKiBjbGFzcyBEZWZsYXRlXG4gKlxuICogR2VuZXJpYyBKUy1zdHlsZSB3cmFwcGVyIGZvciB6bGliIGNhbGxzLiBJZiB5b3UgZG9uJ3QgbmVlZFxuICogc3RyZWFtaW5nIGJlaGF2aW91ciAtIHVzZSBtb3JlIHNpbXBsZSBmdW5jdGlvbnM6IFtbZGVmbGF0ZV1dLFxuICogW1tkZWZsYXRlUmF3XV0gYW5kIFtbZ3ppcF1dLlxuICoqL1xuXG4vKiBpbnRlcm5hbFxuICogRGVmbGF0ZS5jaHVua3MgLT4gQXJyYXlcbiAqXG4gKiBDaHVua3Mgb2Ygb3V0cHV0IGRhdGEsIGlmIFtbRGVmbGF0ZSNvbkRhdGFdXSBub3Qgb3ZlcnJpZGVuLlxuICoqL1xuXG4vKipcbiAqIERlZmxhdGUucmVzdWx0IC0+IFVpbnQ4QXJyYXl8QXJyYXlcbiAqXG4gKiBDb21wcmVzc2VkIHJlc3VsdCwgZ2VuZXJhdGVkIGJ5IGRlZmF1bHQgW1tEZWZsYXRlI29uRGF0YV1dXG4gKiBhbmQgW1tEZWZsYXRlI29uRW5kXV0gaGFuZGxlcnMuIEZpbGxlZCBhZnRlciB5b3UgcHVzaCBsYXN0IGNodW5rXG4gKiAoY2FsbCBbW0RlZmxhdGUjcHVzaF1dIHdpdGggYFpfRklOSVNIYCAvIGB0cnVlYCBwYXJhbSkgIG9yIGlmIHlvdVxuICogcHVzaCBhIGNodW5rIHdpdGggZXhwbGljaXQgZmx1c2ggKGNhbGwgW1tEZWZsYXRlI3B1c2hdXSB3aXRoXG4gKiBgWl9TWU5DX0ZMVVNIYCBwYXJhbSkuXG4gKiovXG5cbi8qKlxuICogRGVmbGF0ZS5lcnIgLT4gTnVtYmVyXG4gKlxuICogRXJyb3IgY29kZSBhZnRlciBkZWZsYXRlIGZpbmlzaGVkLiAwIChaX09LKSBvbiBzdWNjZXNzLlxuICogWW91IHdpbGwgbm90IG5lZWQgaXQgaW4gcmVhbCBsaWZlLCBiZWNhdXNlIGRlZmxhdGUgZXJyb3JzXG4gKiBhcmUgcG9zc2libGUgb25seSBvbiB3cm9uZyBvcHRpb25zIG9yIGJhZCBgb25EYXRhYCAvIGBvbkVuZGBcbiAqIGN1c3RvbSBoYW5kbGVycy5cbiAqKi9cblxuLyoqXG4gKiBEZWZsYXRlLm1zZyAtPiBTdHJpbmdcbiAqXG4gKiBFcnJvciBtZXNzYWdlLCBpZiBbW0RlZmxhdGUuZXJyXV0gIT0gMFxuICoqL1xuXG5cbi8qKlxuICogbmV3IERlZmxhdGUob3B0aW9ucylcbiAqIC0gb3B0aW9ucyAoT2JqZWN0KTogemxpYiBkZWZsYXRlIG9wdGlvbnMuXG4gKlxuICogQ3JlYXRlcyBuZXcgZGVmbGF0b3IgaW5zdGFuY2Ugd2l0aCBzcGVjaWZpZWQgcGFyYW1zLiBUaHJvd3MgZXhjZXB0aW9uXG4gKiBvbiBiYWQgcGFyYW1zLiBTdXBwb3J0ZWQgb3B0aW9uczpcbiAqXG4gKiAtIGBsZXZlbGBcbiAqIC0gYHdpbmRvd0JpdHNgXG4gKiAtIGBtZW1MZXZlbGBcbiAqIC0gYHN0cmF0ZWd5YFxuICpcbiAqIFtodHRwOi8vemxpYi5uZXQvbWFudWFsLmh0bWwjQWR2YW5jZWRdKGh0dHA6Ly96bGliLm5ldC9tYW51YWwuaHRtbCNBZHZhbmNlZClcbiAqIGZvciBtb3JlIGluZm9ybWF0aW9uIG9uIHRoZXNlLlxuICpcbiAqIEFkZGl0aW9uYWwgb3B0aW9ucywgZm9yIGludGVybmFsIG5lZWRzOlxuICpcbiAqIC0gYGNodW5rU2l6ZWAgLSBzaXplIG9mIGdlbmVyYXRlZCBkYXRhIGNodW5rcyAoMTZLIGJ5IGRlZmF1bHQpXG4gKiAtIGByYXdgIChCb29sZWFuKSAtIGRvIHJhdyBkZWZsYXRlXG4gKiAtIGBnemlwYCAoQm9vbGVhbikgLSBjcmVhdGUgZ3ppcCB3cmFwcGVyXG4gKiAtIGB0b2AgKFN0cmluZykgLSBpZiBlcXVhbCB0byAnc3RyaW5nJywgdGhlbiByZXN1bHQgd2lsbCBiZSBcImJpbmFyeSBzdHJpbmdcIlxuICogICAgKGVhY2ggY2hhciBjb2RlIFswLi4yNTVdKVxuICogLSBgaGVhZGVyYCAoT2JqZWN0KSAtIGN1c3RvbSBoZWFkZXIgZm9yIGd6aXBcbiAqICAgLSBgdGV4dGAgKEJvb2xlYW4pIC0gdHJ1ZSBpZiBjb21wcmVzc2VkIGRhdGEgYmVsaWV2ZWQgdG8gYmUgdGV4dFxuICogICAtIGB0aW1lYCAoTnVtYmVyKSAtIG1vZGlmaWNhdGlvbiB0aW1lLCB1bml4IHRpbWVzdGFtcFxuICogICAtIGBvc2AgKE51bWJlcikgLSBvcGVyYXRpb24gc3lzdGVtIGNvZGVcbiAqICAgLSBgZXh0cmFgIChBcnJheSkgLSBhcnJheSBvZiBieXRlcyB3aXRoIGV4dHJhIGRhdGEgKG1heCA2NTUzNilcbiAqICAgLSBgbmFtZWAgKFN0cmluZykgLSBmaWxlIG5hbWUgKGJpbmFyeSBzdHJpbmcpXG4gKiAgIC0gYGNvbW1lbnRgIChTdHJpbmcpIC0gY29tbWVudCAoYmluYXJ5IHN0cmluZylcbiAqICAgLSBgaGNyY2AgKEJvb2xlYW4pIC0gdHJ1ZSBpZiBoZWFkZXIgY3JjIHNob3VsZCBiZSBhZGRlZFxuICpcbiAqICMjIyMjIEV4YW1wbGU6XG4gKlxuICogYGBgamF2YXNjcmlwdFxuICogdmFyIHBha28gPSByZXF1aXJlKCdwYWtvJylcbiAqICAgLCBjaHVuazEgPSBVaW50OEFycmF5KFsxLDIsMyw0LDUsNiw3LDgsOV0pXG4gKiAgICwgY2h1bmsyID0gVWludDhBcnJheShbMTAsMTEsMTIsMTMsMTQsMTUsMTYsMTcsMTgsMTldKTtcbiAqXG4gKiB2YXIgZGVmbGF0ZSA9IG5ldyBwYWtvLkRlZmxhdGUoeyBsZXZlbDogM30pO1xuICpcbiAqIGRlZmxhdGUucHVzaChjaHVuazEsIGZhbHNlKTtcbiAqIGRlZmxhdGUucHVzaChjaHVuazIsIHRydWUpOyAgLy8gdHJ1ZSAtPiBsYXN0IGNodW5rXG4gKlxuICogaWYgKGRlZmxhdGUuZXJyKSB7IHRocm93IG5ldyBFcnJvcihkZWZsYXRlLmVycik7IH1cbiAqXG4gKiBjb25zb2xlLmxvZyhkZWZsYXRlLnJlc3VsdCk7XG4gKiBgYGBcbiAqKi9cbnZhciBEZWZsYXRlID0gZnVuY3Rpb24ob3B0aW9ucykge1xuXG4gIHRoaXMub3B0aW9ucyA9IHV0aWxzLmFzc2lnbih7XG4gICAgbGV2ZWw6IFpfREVGQVVMVF9DT01QUkVTU0lPTixcbiAgICBtZXRob2Q6IFpfREVGTEFURUQsXG4gICAgY2h1bmtTaXplOiAxNjM4NCxcbiAgICB3aW5kb3dCaXRzOiAxNSxcbiAgICBtZW1MZXZlbDogOCxcbiAgICBzdHJhdGVneTogWl9ERUZBVUxUX1NUUkFURUdZLFxuICAgIHRvOiAnJ1xuICB9LCBvcHRpb25zIHx8IHt9KTtcblxuICB2YXIgb3B0ID0gdGhpcy5vcHRpb25zO1xuXG4gIGlmIChvcHQucmF3ICYmIChvcHQud2luZG93Qml0cyA+IDApKSB7XG4gICAgb3B0LndpbmRvd0JpdHMgPSAtb3B0LndpbmRvd0JpdHM7XG4gIH1cblxuICBlbHNlIGlmIChvcHQuZ3ppcCAmJiAob3B0LndpbmRvd0JpdHMgPiAwKSAmJiAob3B0LndpbmRvd0JpdHMgPCAxNikpIHtcbiAgICBvcHQud2luZG93Qml0cyArPSAxNjtcbiAgfVxuXG4gIHRoaXMuZXJyICAgID0gMDsgICAgICAvLyBlcnJvciBjb2RlLCBpZiBoYXBwZW5zICgwID0gWl9PSylcbiAgdGhpcy5tc2cgICAgPSAnJzsgICAgIC8vIGVycm9yIG1lc3NhZ2VcbiAgdGhpcy5lbmRlZCAgPSBmYWxzZTsgIC8vIHVzZWQgdG8gYXZvaWQgbXVsdGlwbGUgb25FbmQoKSBjYWxsc1xuICB0aGlzLmNodW5rcyA9IFtdOyAgICAgLy8gY2h1bmtzIG9mIGNvbXByZXNzZWQgZGF0YVxuXG4gIHRoaXMuc3RybSA9IG5ldyB6c3RyZWFtKCk7XG4gIHRoaXMuc3RybS5hdmFpbF9vdXQgPSAwO1xuXG4gIHZhciBzdGF0dXMgPSB6bGliX2RlZmxhdGUuZGVmbGF0ZUluaXQyKFxuICAgIHRoaXMuc3RybSxcbiAgICBvcHQubGV2ZWwsXG4gICAgb3B0Lm1ldGhvZCxcbiAgICBvcHQud2luZG93Qml0cyxcbiAgICBvcHQubWVtTGV2ZWwsXG4gICAgb3B0LnN0cmF0ZWd5XG4gICk7XG5cbiAgaWYgKHN0YXR1cyAhPT0gWl9PSykge1xuICAgIHRocm93IG5ldyBFcnJvcihtc2dbc3RhdHVzXSk7XG4gIH1cblxuICBpZiAob3B0LmhlYWRlcikge1xuICAgIHpsaWJfZGVmbGF0ZS5kZWZsYXRlU2V0SGVhZGVyKHRoaXMuc3RybSwgb3B0LmhlYWRlcik7XG4gIH1cbn07XG5cbi8qKlxuICogRGVmbGF0ZSNwdXNoKGRhdGFbLCBtb2RlXSkgLT4gQm9vbGVhblxuICogLSBkYXRhIChVaW50OEFycmF5fEFycmF5fEFycmF5QnVmZmVyfFN0cmluZyk6IGlucHV0IGRhdGEuIFN0cmluZ3Mgd2lsbCBiZVxuICogICBjb252ZXJ0ZWQgdG8gdXRmOCBieXRlIHNlcXVlbmNlLlxuICogLSBtb2RlIChOdW1iZXJ8Qm9vbGVhbik6IDAuLjYgZm9yIGNvcnJlc3BvbmRpbmcgWl9OT19GTFVTSC4uWl9UUkVFIG1vZGVzLlxuICogICBTZWUgY29uc3RhbnRzLiBTa2lwcGVkIG9yIGBmYWxzZWAgbWVhbnMgWl9OT19GTFVTSCwgYHRydWVgIG1lYW5zaCBaX0ZJTklTSC5cbiAqXG4gKiBTZW5kcyBpbnB1dCBkYXRhIHRvIGRlZmxhdGUgcGlwZSwgZ2VuZXJhdGluZyBbW0RlZmxhdGUjb25EYXRhXV0gY2FsbHMgd2l0aFxuICogbmV3IGNvbXByZXNzZWQgY2h1bmtzLiBSZXR1cm5zIGB0cnVlYCBvbiBzdWNjZXNzLiBUaGUgbGFzdCBkYXRhIGJsb2NrIG11c3QgaGF2ZVxuICogbW9kZSBaX0ZJTklTSCAob3IgYHRydWVgKS4gVGhhdCB3aWxsIGZsdXNoIGludGVybmFsIHBlbmRpbmcgYnVmZmVycyBhbmQgY2FsbFxuICogW1tEZWZsYXRlI29uRW5kXV0uIEZvciBpbnRlcmltIGV4cGxpY2l0IGZsdXNoZXMgKHdpdGhvdXQgZW5kaW5nIHRoZSBzdHJlYW0pIHlvdVxuICogY2FuIHVzZSBtb2RlIFpfU1lOQ19GTFVTSCwga2VlcGluZyB0aGUgY29tcHJlc3Npb24gY29udGV4dC5cbiAqXG4gKiBPbiBmYWlsIGNhbGwgW1tEZWZsYXRlI29uRW5kXV0gd2l0aCBlcnJvciBjb2RlIGFuZCByZXR1cm4gZmFsc2UuXG4gKlxuICogV2Ugc3Ryb25nbHkgcmVjb21tZW5kIHRvIHVzZSBgVWludDhBcnJheWAgb24gaW5wdXQgZm9yIGJlc3Qgc3BlZWQgKG91dHB1dFxuICogYXJyYXkgZm9ybWF0IGlzIGRldGVjdGVkIGF1dG9tYXRpY2FsbHkpLiBBbHNvLCBkb24ndCBza2lwIGxhc3QgcGFyYW0gYW5kIGFsd2F5c1xuICogdXNlIHRoZSBzYW1lIHR5cGUgaW4geW91ciBjb2RlIChib29sZWFuIG9yIG51bWJlcikuIFRoYXQgd2lsbCBpbXByb3ZlIEpTIHNwZWVkLlxuICpcbiAqIEZvciByZWd1bGFyIGBBcnJheWAtcyBtYWtlIHN1cmUgYWxsIGVsZW1lbnRzIGFyZSBbMC4uMjU1XS5cbiAqXG4gKiAjIyMjIyBFeGFtcGxlXG4gKlxuICogYGBgamF2YXNjcmlwdFxuICogcHVzaChjaHVuaywgZmFsc2UpOyAvLyBwdXNoIG9uZSBvZiBkYXRhIGNodW5rc1xuICogLi4uXG4gKiBwdXNoKGNodW5rLCB0cnVlKTsgIC8vIHB1c2ggbGFzdCBjaHVua1xuICogYGBgXG4gKiovXG5EZWZsYXRlLnByb3RvdHlwZS5wdXNoID0gZnVuY3Rpb24oZGF0YSwgbW9kZSkge1xuICB2YXIgc3RybSA9IHRoaXMuc3RybTtcbiAgdmFyIGNodW5rU2l6ZSA9IHRoaXMub3B0aW9ucy5jaHVua1NpemU7XG4gIHZhciBzdGF0dXMsIF9tb2RlO1xuXG4gIGlmICh0aGlzLmVuZGVkKSB7IHJldHVybiBmYWxzZTsgfVxuXG4gIF9tb2RlID0gKG1vZGUgPT09IH5+bW9kZSkgPyBtb2RlIDogKChtb2RlID09PSB0cnVlKSA/IFpfRklOSVNIIDogWl9OT19GTFVTSCk7XG5cbiAgLy8gQ29udmVydCBkYXRhIGlmIG5lZWRlZFxuICBpZiAodHlwZW9mIGRhdGEgPT09ICdzdHJpbmcnKSB7XG4gICAgLy8gSWYgd2UgbmVlZCB0byBjb21wcmVzcyB0ZXh0LCBjaGFuZ2UgZW5jb2RpbmcgdG8gdXRmOC5cbiAgICBzdHJtLmlucHV0ID0gc3RyaW5ncy5zdHJpbmcyYnVmKGRhdGEpO1xuICB9IGVsc2UgaWYgKHRvU3RyaW5nLmNhbGwoZGF0YSkgPT09ICdbb2JqZWN0IEFycmF5QnVmZmVyXScpIHtcbiAgICBzdHJtLmlucHV0ID0gbmV3IFVpbnQ4QXJyYXkoZGF0YSk7XG4gIH0gZWxzZSB7XG4gICAgc3RybS5pbnB1dCA9IGRhdGE7XG4gIH1cblxuICBzdHJtLm5leHRfaW4gPSAwO1xuICBzdHJtLmF2YWlsX2luID0gc3RybS5pbnB1dC5sZW5ndGg7XG5cbiAgZG8ge1xuICAgIGlmIChzdHJtLmF2YWlsX291dCA9PT0gMCkge1xuICAgICAgc3RybS5vdXRwdXQgPSBuZXcgdXRpbHMuQnVmOChjaHVua1NpemUpO1xuICAgICAgc3RybS5uZXh0X291dCA9IDA7XG4gICAgICBzdHJtLmF2YWlsX291dCA9IGNodW5rU2l6ZTtcbiAgICB9XG4gICAgc3RhdHVzID0gemxpYl9kZWZsYXRlLmRlZmxhdGUoc3RybSwgX21vZGUpOyAgICAvKiBubyBiYWQgcmV0dXJuIHZhbHVlICovXG5cbiAgICBpZiAoc3RhdHVzICE9PSBaX1NUUkVBTV9FTkQgJiYgc3RhdHVzICE9PSBaX09LKSB7XG4gICAgICB0aGlzLm9uRW5kKHN0YXR1cyk7XG4gICAgICB0aGlzLmVuZGVkID0gdHJ1ZTtcbiAgICAgIHJldHVybiBmYWxzZTtcbiAgICB9XG4gICAgaWYgKHN0cm0uYXZhaWxfb3V0ID09PSAwIHx8IChzdHJtLmF2YWlsX2luID09PSAwICYmIChfbW9kZSA9PT0gWl9GSU5JU0ggfHwgX21vZGUgPT09IFpfU1lOQ19GTFVTSCkpKSB7XG4gICAgICBpZiAodGhpcy5vcHRpb25zLnRvID09PSAnc3RyaW5nJykge1xuICAgICAgICB0aGlzLm9uRGF0YShzdHJpbmdzLmJ1ZjJiaW5zdHJpbmcodXRpbHMuc2hyaW5rQnVmKHN0cm0ub3V0cHV0LCBzdHJtLm5leHRfb3V0KSkpO1xuICAgICAgfSBlbHNlIHtcbiAgICAgICAgdGhpcy5vbkRhdGEodXRpbHMuc2hyaW5rQnVmKHN0cm0ub3V0cHV0LCBzdHJtLm5leHRfb3V0KSk7XG4gICAgICB9XG4gICAgfVxuICB9IHdoaWxlICgoc3RybS5hdmFpbF9pbiA+IDAgfHwgc3RybS5hdmFpbF9vdXQgPT09IDApICYmIHN0YXR1cyAhPT0gWl9TVFJFQU1fRU5EKTtcblxuICAvLyBGaW5hbGl6ZSBvbiB0aGUgbGFzdCBjaHVuay5cbiAgaWYgKF9tb2RlID09PSBaX0ZJTklTSCkge1xuICAgIHN0YXR1cyA9IHpsaWJfZGVmbGF0ZS5kZWZsYXRlRW5kKHRoaXMuc3RybSk7XG4gICAgdGhpcy5vbkVuZChzdGF0dXMpO1xuICAgIHRoaXMuZW5kZWQgPSB0cnVlO1xuICAgIHJldHVybiBzdGF0dXMgPT09IFpfT0s7XG4gIH1cblxuICAvLyBjYWxsYmFjayBpbnRlcmltIHJlc3VsdHMgaWYgWl9TWU5DX0ZMVVNILlxuICBpZiAoX21vZGUgPT09IFpfU1lOQ19GTFVTSCkge1xuICAgIHRoaXMub25FbmQoWl9PSyk7XG4gICAgc3RybS5hdmFpbF9vdXQgPSAwO1xuICAgIHJldHVybiB0cnVlO1xuICB9XG5cbiAgcmV0dXJuIHRydWU7XG59O1xuXG5cbi8qKlxuICogRGVmbGF0ZSNvbkRhdGEoY2h1bmspIC0+IFZvaWRcbiAqIC0gY2h1bmsgKFVpbnQ4QXJyYXl8QXJyYXl8U3RyaW5nKTogb3VwdXQgZGF0YS4gVHlwZSBvZiBhcnJheSBkZXBlbmRzXG4gKiAgIG9uIGpzIGVuZ2luZSBzdXBwb3J0LiBXaGVuIHN0cmluZyBvdXRwdXQgcmVxdWVzdGVkLCBlYWNoIGNodW5rXG4gKiAgIHdpbGwgYmUgc3RyaW5nLlxuICpcbiAqIEJ5IGRlZmF1bHQsIHN0b3JlcyBkYXRhIGJsb2NrcyBpbiBgY2h1bmtzW11gIHByb3BlcnR5IGFuZCBnbHVlXG4gKiB0aG9zZSBpbiBgb25FbmRgLiBPdmVycmlkZSB0aGlzIGhhbmRsZXIsIGlmIHlvdSBuZWVkIGFub3RoZXIgYmVoYXZpb3VyLlxuICoqL1xuRGVmbGF0ZS5wcm90b3R5cGUub25EYXRhID0gZnVuY3Rpb24oY2h1bmspIHtcbiAgdGhpcy5jaHVua3MucHVzaChjaHVuayk7XG59O1xuXG5cbi8qKlxuICogRGVmbGF0ZSNvbkVuZChzdGF0dXMpIC0+IFZvaWRcbiAqIC0gc3RhdHVzIChOdW1iZXIpOiBkZWZsYXRlIHN0YXR1cy4gMCAoWl9PSykgb24gc3VjY2VzcyxcbiAqICAgb3RoZXIgaWYgbm90LlxuICpcbiAqIENhbGxlZCBvbmNlIGFmdGVyIHlvdSB0ZWxsIGRlZmxhdGUgdGhhdCB0aGUgaW5wdXQgc3RyZWFtIGlzXG4gKiBjb21wbGV0ZSAoWl9GSU5JU0gpIG9yIHNob3VsZCBiZSBmbHVzaGVkIChaX1NZTkNfRkxVU0gpXG4gKiBvciBpZiBhbiBlcnJvciBoYXBwZW5lZC4gQnkgZGVmYXVsdCAtIGpvaW4gY29sbGVjdGVkIGNodW5rcyxcbiAqIGZyZWUgbWVtb3J5IGFuZCBmaWxsIGByZXN1bHRzYCAvIGBlcnJgIHByb3BlcnRpZXMuXG4gKiovXG5EZWZsYXRlLnByb3RvdHlwZS5vbkVuZCA9IGZ1bmN0aW9uKHN0YXR1cykge1xuICAvLyBPbiBzdWNjZXNzIC0gam9pblxuICBpZiAoc3RhdHVzID09PSBaX09LKSB7XG4gICAgaWYgKHRoaXMub3B0aW9ucy50byA9PT0gJ3N0cmluZycpIHtcbiAgICAgIHRoaXMucmVzdWx0ID0gdGhpcy5jaHVua3Muam9pbignJyk7XG4gICAgfSBlbHNlIHtcbiAgICAgIHRoaXMucmVzdWx0ID0gdXRpbHMuZmxhdHRlbkNodW5rcyh0aGlzLmNodW5rcyk7XG4gICAgfVxuICB9XG4gIHRoaXMuY2h1bmtzID0gW107XG4gIHRoaXMuZXJyID0gc3RhdHVzO1xuICB0aGlzLm1zZyA9IHRoaXMuc3RybS5tc2c7XG59O1xuXG5cbi8qKlxuICogZGVmbGF0ZShkYXRhWywgb3B0aW9uc10pIC0+IFVpbnQ4QXJyYXl8QXJyYXl8U3RyaW5nXG4gKiAtIGRhdGEgKFVpbnQ4QXJyYXl8QXJyYXl8U3RyaW5nKTogaW5wdXQgZGF0YSB0byBjb21wcmVzcy5cbiAqIC0gb3B0aW9ucyAoT2JqZWN0KTogemxpYiBkZWZsYXRlIG9wdGlvbnMuXG4gKlxuICogQ29tcHJlc3MgYGRhdGFgIHdpdGggZGVmbGF0ZSBhbHJvcnl0aG0gYW5kIGBvcHRpb25zYC5cbiAqXG4gKiBTdXBwb3J0ZWQgb3B0aW9ucyBhcmU6XG4gKlxuICogLSBsZXZlbFxuICogLSB3aW5kb3dCaXRzXG4gKiAtIG1lbUxldmVsXG4gKiAtIHN0cmF0ZWd5XG4gKlxuICogW2h0dHA6Ly96bGliLm5ldC9tYW51YWwuaHRtbCNBZHZhbmNlZF0oaHR0cDovL3psaWIubmV0L21hbnVhbC5odG1sI0FkdmFuY2VkKVxuICogZm9yIG1vcmUgaW5mb3JtYXRpb24gb24gdGhlc2UuXG4gKlxuICogU3VnYXIgKG9wdGlvbnMpOlxuICpcbiAqIC0gYHJhd2AgKEJvb2xlYW4pIC0gc2F5IHRoYXQgd2Ugd29yayB3aXRoIHJhdyBzdHJlYW0sIGlmIHlvdSBkb24ndCB3aXNoIHRvIHNwZWNpZnlcbiAqICAgbmVnYXRpdmUgd2luZG93Qml0cyBpbXBsaWNpdGx5LlxuICogLSBgdG9gIChTdHJpbmcpIC0gaWYgZXF1YWwgdG8gJ3N0cmluZycsIHRoZW4gcmVzdWx0IHdpbGwgYmUgXCJiaW5hcnkgc3RyaW5nXCJcbiAqICAgIChlYWNoIGNoYXIgY29kZSBbMC4uMjU1XSlcbiAqXG4gKiAjIyMjIyBFeGFtcGxlOlxuICpcbiAqIGBgYGphdmFzY3JpcHRcbiAqIHZhciBwYWtvID0gcmVxdWlyZSgncGFrbycpXG4gKiAgICwgZGF0YSA9IFVpbnQ4QXJyYXkoWzEsMiwzLDQsNSw2LDcsOCw5XSk7XG4gKlxuICogY29uc29sZS5sb2cocGFrby5kZWZsYXRlKGRhdGEpKTtcbiAqIGBgYFxuICoqL1xuZnVuY3Rpb24gZGVmbGF0ZShpbnB1dCwgb3B0aW9ucykge1xuICB2YXIgZGVmbGF0b3IgPSBuZXcgRGVmbGF0ZShvcHRpb25zKTtcblxuICBkZWZsYXRvci5wdXNoKGlucHV0LCB0cnVlKTtcblxuICAvLyBUaGF0IHdpbGwgbmV2ZXIgaGFwcGVucywgaWYgeW91IGRvbid0IGNoZWF0IHdpdGggb3B0aW9ucyA6KVxuICBpZiAoZGVmbGF0b3IuZXJyKSB7IHRocm93IGRlZmxhdG9yLm1zZzsgfVxuXG4gIHJldHVybiBkZWZsYXRvci5yZXN1bHQ7XG59XG5cblxuLyoqXG4gKiBkZWZsYXRlUmF3KGRhdGFbLCBvcHRpb25zXSkgLT4gVWludDhBcnJheXxBcnJheXxTdHJpbmdcbiAqIC0gZGF0YSAoVWludDhBcnJheXxBcnJheXxTdHJpbmcpOiBpbnB1dCBkYXRhIHRvIGNvbXByZXNzLlxuICogLSBvcHRpb25zIChPYmplY3QpOiB6bGliIGRlZmxhdGUgb3B0aW9ucy5cbiAqXG4gKiBUaGUgc2FtZSBhcyBbW2RlZmxhdGVdXSwgYnV0IGNyZWF0ZXMgcmF3IGRhdGEsIHdpdGhvdXQgd3JhcHBlclxuICogKGhlYWRlciBhbmQgYWRsZXIzMiBjcmMpLlxuICoqL1xuZnVuY3Rpb24gZGVmbGF0ZVJhdyhpbnB1dCwgb3B0aW9ucykge1xuICBvcHRpb25zID0gb3B0aW9ucyB8fCB7fTtcbiAgb3B0aW9ucy5yYXcgPSB0cnVlO1xuICByZXR1cm4gZGVmbGF0ZShpbnB1dCwgb3B0aW9ucyk7XG59XG5cblxuLyoqXG4gKiBnemlwKGRhdGFbLCBvcHRpb25zXSkgLT4gVWludDhBcnJheXxBcnJheXxTdHJpbmdcbiAqIC0gZGF0YSAoVWludDhBcnJheXxBcnJheXxTdHJpbmcpOiBpbnB1dCBkYXRhIHRvIGNvbXByZXNzLlxuICogLSBvcHRpb25zIChPYmplY3QpOiB6bGliIGRlZmxhdGUgb3B0aW9ucy5cbiAqXG4gKiBUaGUgc2FtZSBhcyBbW2RlZmxhdGVdXSwgYnV0IGNyZWF0ZSBnemlwIHdyYXBwZXIgaW5zdGVhZCBvZlxuICogZGVmbGF0ZSBvbmUuXG4gKiovXG5mdW5jdGlvbiBnemlwKGlucHV0LCBvcHRpb25zKSB7XG4gIG9wdGlvbnMgPSBvcHRpb25zIHx8IHt9O1xuICBvcHRpb25zLmd6aXAgPSB0cnVlO1xuICByZXR1cm4gZGVmbGF0ZShpbnB1dCwgb3B0aW9ucyk7XG59XG5cblxuZXhwb3J0cy5EZWZsYXRlID0gRGVmbGF0ZTtcbmV4cG9ydHMuZGVmbGF0ZSA9IGRlZmxhdGU7XG5leHBvcnRzLmRlZmxhdGVSYXcgPSBkZWZsYXRlUmF3O1xuZXhwb3J0cy5nemlwID0gZ3ppcDtcbiIsIid1c2Ugc3RyaWN0JztcblxuXG52YXIgemxpYl9pbmZsYXRlID0gcmVxdWlyZSgnLi96bGliL2luZmxhdGUuanMnKTtcbnZhciB1dGlscyA9IHJlcXVpcmUoJy4vdXRpbHMvY29tbW9uJyk7XG52YXIgc3RyaW5ncyA9IHJlcXVpcmUoJy4vdXRpbHMvc3RyaW5ncycpO1xudmFyIGMgPSByZXF1aXJlKCcuL3psaWIvY29uc3RhbnRzJyk7XG52YXIgbXNnID0gcmVxdWlyZSgnLi96bGliL21lc3NhZ2VzJyk7XG52YXIgenN0cmVhbSA9IHJlcXVpcmUoJy4vemxpYi96c3RyZWFtJyk7XG52YXIgZ3poZWFkZXIgPSByZXF1aXJlKCcuL3psaWIvZ3poZWFkZXInKTtcblxudmFyIHRvU3RyaW5nID0gT2JqZWN0LnByb3RvdHlwZS50b1N0cmluZztcblxuLyoqXG4gKiBjbGFzcyBJbmZsYXRlXG4gKlxuICogR2VuZXJpYyBKUy1zdHlsZSB3cmFwcGVyIGZvciB6bGliIGNhbGxzLiBJZiB5b3UgZG9uJ3QgbmVlZFxuICogc3RyZWFtaW5nIGJlaGF2aW91ciAtIHVzZSBtb3JlIHNpbXBsZSBmdW5jdGlvbnM6IFtbaW5mbGF0ZV1dXG4gKiBhbmQgW1tpbmZsYXRlUmF3XV0uXG4gKiovXG5cbi8qIGludGVybmFsXG4gKiBpbmZsYXRlLmNodW5rcyAtPiBBcnJheVxuICpcbiAqIENodW5rcyBvZiBvdXRwdXQgZGF0YSwgaWYgW1tJbmZsYXRlI29uRGF0YV1dIG5vdCBvdmVycmlkZW4uXG4gKiovXG5cbi8qKlxuICogSW5mbGF0ZS5yZXN1bHQgLT4gVWludDhBcnJheXxBcnJheXxTdHJpbmdcbiAqXG4gKiBVbmNvbXByZXNzZWQgcmVzdWx0LCBnZW5lcmF0ZWQgYnkgZGVmYXVsdCBbW0luZmxhdGUjb25EYXRhXV1cbiAqIGFuZCBbW0luZmxhdGUjb25FbmRdXSBoYW5kbGVycy4gRmlsbGVkIGFmdGVyIHlvdSBwdXNoIGxhc3QgY2h1bmtcbiAqIChjYWxsIFtbSW5mbGF0ZSNwdXNoXV0gd2l0aCBgWl9GSU5JU0hgIC8gYHRydWVgIHBhcmFtKSBvciBpZiB5b3VcbiAqIHB1c2ggYSBjaHVuayB3aXRoIGV4cGxpY2l0IGZsdXNoIChjYWxsIFtbSW5mbGF0ZSNwdXNoXV0gd2l0aFxuICogYFpfU1lOQ19GTFVTSGAgcGFyYW0pLlxuICoqL1xuXG4vKipcbiAqIEluZmxhdGUuZXJyIC0+IE51bWJlclxuICpcbiAqIEVycm9yIGNvZGUgYWZ0ZXIgaW5mbGF0ZSBmaW5pc2hlZC4gMCAoWl9PSykgb24gc3VjY2Vzcy5cbiAqIFNob3VsZCBiZSBjaGVja2VkIGlmIGJyb2tlbiBkYXRhIHBvc3NpYmxlLlxuICoqL1xuXG4vKipcbiAqIEluZmxhdGUubXNnIC0+IFN0cmluZ1xuICpcbiAqIEVycm9yIG1lc3NhZ2UsIGlmIFtbSW5mbGF0ZS5lcnJdXSAhPSAwXG4gKiovXG5cblxuLyoqXG4gKiBuZXcgSW5mbGF0ZShvcHRpb25zKVxuICogLSBvcHRpb25zIChPYmplY3QpOiB6bGliIGluZmxhdGUgb3B0aW9ucy5cbiAqXG4gKiBDcmVhdGVzIG5ldyBpbmZsYXRvciBpbnN0YW5jZSB3aXRoIHNwZWNpZmllZCBwYXJhbXMuIFRocm93cyBleGNlcHRpb25cbiAqIG9uIGJhZCBwYXJhbXMuIFN1cHBvcnRlZCBvcHRpb25zOlxuICpcbiAqIC0gYHdpbmRvd0JpdHNgXG4gKlxuICogW2h0dHA6Ly96bGliLm5ldC9tYW51YWwuaHRtbCNBZHZhbmNlZF0oaHR0cDovL3psaWIubmV0L21hbnVhbC5odG1sI0FkdmFuY2VkKVxuICogZm9yIG1vcmUgaW5mb3JtYXRpb24gb24gdGhlc2UuXG4gKlxuICogQWRkaXRpb25hbCBvcHRpb25zLCBmb3IgaW50ZXJuYWwgbmVlZHM6XG4gKlxuICogLSBgY2h1bmtTaXplYCAtIHNpemUgb2YgZ2VuZXJhdGVkIGRhdGEgY2h1bmtzICgxNksgYnkgZGVmYXVsdClcbiAqIC0gYHJhd2AgKEJvb2xlYW4pIC0gZG8gcmF3IGluZmxhdGVcbiAqIC0gYHRvYCAoU3RyaW5nKSAtIGlmIGVxdWFsIHRvICdzdHJpbmcnLCB0aGVuIHJlc3VsdCB3aWxsIGJlIGNvbnZlcnRlZFxuICogICBmcm9tIHV0ZjggdG8gdXRmMTYgKGphdmFzY3JpcHQpIHN0cmluZy4gV2hlbiBzdHJpbmcgb3V0cHV0IHJlcXVlc3RlZCxcbiAqICAgY2h1bmsgbGVuZ3RoIGNhbiBkaWZmZXIgZnJvbSBgY2h1bmtTaXplYCwgZGVwZW5kaW5nIG9uIGNvbnRlbnQuXG4gKlxuICogQnkgZGVmYXVsdCwgd2hlbiBubyBvcHRpb25zIHNldCwgYXV0b2RldGVjdCBkZWZsYXRlL2d6aXAgZGF0YSBmb3JtYXQgdmlhXG4gKiB3cmFwcGVyIGhlYWRlci5cbiAqXG4gKiAjIyMjIyBFeGFtcGxlOlxuICpcbiAqIGBgYGphdmFzY3JpcHRcbiAqIHZhciBwYWtvID0gcmVxdWlyZSgncGFrbycpXG4gKiAgICwgY2h1bmsxID0gVWludDhBcnJheShbMSwyLDMsNCw1LDYsNyw4LDldKVxuICogICAsIGNodW5rMiA9IFVpbnQ4QXJyYXkoWzEwLDExLDEyLDEzLDE0LDE1LDE2LDE3LDE4LDE5XSk7XG4gKlxuICogdmFyIGluZmxhdGUgPSBuZXcgcGFrby5JbmZsYXRlKHsgbGV2ZWw6IDN9KTtcbiAqXG4gKiBpbmZsYXRlLnB1c2goY2h1bmsxLCBmYWxzZSk7XG4gKiBpbmZsYXRlLnB1c2goY2h1bmsyLCB0cnVlKTsgIC8vIHRydWUgLT4gbGFzdCBjaHVua1xuICpcbiAqIGlmIChpbmZsYXRlLmVycikgeyB0aHJvdyBuZXcgRXJyb3IoaW5mbGF0ZS5lcnIpOyB9XG4gKlxuICogY29uc29sZS5sb2coaW5mbGF0ZS5yZXN1bHQpO1xuICogYGBgXG4gKiovXG52YXIgSW5mbGF0ZSA9IGZ1bmN0aW9uKG9wdGlvbnMpIHtcblxuICB0aGlzLm9wdGlvbnMgPSB1dGlscy5hc3NpZ24oe1xuICAgIGNodW5rU2l6ZTogMTYzODQsXG4gICAgd2luZG93Qml0czogMCxcbiAgICB0bzogJydcbiAgfSwgb3B0aW9ucyB8fCB7fSk7XG5cbiAgdmFyIG9wdCA9IHRoaXMub3B0aW9ucztcblxuICAvLyBGb3JjZSB3aW5kb3cgc2l6ZSBmb3IgYHJhd2AgZGF0YSwgaWYgbm90IHNldCBkaXJlY3RseSxcbiAgLy8gYmVjYXVzZSB3ZSBoYXZlIG5vIGhlYWRlciBmb3IgYXV0b2RldGVjdC5cbiAgaWYgKG9wdC5yYXcgJiYgKG9wdC53aW5kb3dCaXRzID49IDApICYmIChvcHQud2luZG93Qml0cyA8IDE2KSkge1xuICAgIG9wdC53aW5kb3dCaXRzID0gLW9wdC53aW5kb3dCaXRzO1xuICAgIGlmIChvcHQud2luZG93Qml0cyA9PT0gMCkgeyBvcHQud2luZG93Qml0cyA9IC0xNTsgfVxuICB9XG5cbiAgLy8gSWYgYHdpbmRvd0JpdHNgIG5vdCBkZWZpbmVkIChhbmQgbW9kZSBub3QgcmF3KSAtIHNldCBhdXRvZGV0ZWN0IGZsYWcgZm9yIGd6aXAvZGVmbGF0ZVxuICBpZiAoKG9wdC53aW5kb3dCaXRzID49IDApICYmIChvcHQud2luZG93Qml0cyA8IDE2KSAmJlxuICAgICAgIShvcHRpb25zICYmIG9wdGlvbnMud2luZG93Qml0cykpIHtcbiAgICBvcHQud2luZG93Qml0cyArPSAzMjtcbiAgfVxuXG4gIC8vIEd6aXAgaGVhZGVyIGhhcyBubyBpbmZvIGFib3V0IHdpbmRvd3Mgc2l6ZSwgd2UgY2FuIGRvIGF1dG9kZXRlY3Qgb25seVxuICAvLyBmb3IgZGVmbGF0ZS4gU28sIGlmIHdpbmRvdyBzaXplIG5vdCBzZXQsIGZvcmNlIGl0IHRvIG1heCB3aGVuIGd6aXAgcG9zc2libGVcbiAgaWYgKChvcHQud2luZG93Qml0cyA+IDE1KSAmJiAob3B0LndpbmRvd0JpdHMgPCA0OCkpIHtcbiAgICAvLyBiaXQgMyAoMTYpIC0+IGd6aXBwZWQgZGF0YVxuICAgIC8vIGJpdCA0ICgzMikgLT4gYXV0b2RldGVjdCBnemlwL2RlZmxhdGVcbiAgICBpZiAoKG9wdC53aW5kb3dCaXRzICYgMTUpID09PSAwKSB7XG4gICAgICBvcHQud2luZG93Qml0cyB8PSAxNTtcbiAgICB9XG4gIH1cblxuICB0aGlzLmVyciAgICA9IDA7ICAgICAgLy8gZXJyb3IgY29kZSwgaWYgaGFwcGVucyAoMCA9IFpfT0spXG4gIHRoaXMubXNnICAgID0gJyc7ICAgICAvLyBlcnJvciBtZXNzYWdlXG4gIHRoaXMuZW5kZWQgID0gZmFsc2U7ICAvLyB1c2VkIHRvIGF2b2lkIG11bHRpcGxlIG9uRW5kKCkgY2FsbHNcbiAgdGhpcy5jaHVua3MgPSBbXTsgICAgIC8vIGNodW5rcyBvZiBjb21wcmVzc2VkIGRhdGFcblxuICB0aGlzLnN0cm0gICA9IG5ldyB6c3RyZWFtKCk7XG4gIHRoaXMuc3RybS5hdmFpbF9vdXQgPSAwO1xuXG4gIHZhciBzdGF0dXMgID0gemxpYl9pbmZsYXRlLmluZmxhdGVJbml0MihcbiAgICB0aGlzLnN0cm0sXG4gICAgb3B0LndpbmRvd0JpdHNcbiAgKTtcblxuICBpZiAoc3RhdHVzICE9PSBjLlpfT0spIHtcbiAgICB0aHJvdyBuZXcgRXJyb3IobXNnW3N0YXR1c10pO1xuICB9XG5cbiAgdGhpcy5oZWFkZXIgPSBuZXcgZ3poZWFkZXIoKTtcblxuICB6bGliX2luZmxhdGUuaW5mbGF0ZUdldEhlYWRlcih0aGlzLnN0cm0sIHRoaXMuaGVhZGVyKTtcbn07XG5cbi8qKlxuICogSW5mbGF0ZSNwdXNoKGRhdGFbLCBtb2RlXSkgLT4gQm9vbGVhblxuICogLSBkYXRhIChVaW50OEFycmF5fEFycmF5fEFycmF5QnVmZmVyfFN0cmluZyk6IGlucHV0IGRhdGFcbiAqIC0gbW9kZSAoTnVtYmVyfEJvb2xlYW4pOiAwLi42IGZvciBjb3JyZXNwb25kaW5nIFpfTk9fRkxVU0guLlpfVFJFRSBtb2Rlcy5cbiAqICAgU2VlIGNvbnN0YW50cy4gU2tpcHBlZCBvciBgZmFsc2VgIG1lYW5zIFpfTk9fRkxVU0gsIGB0cnVlYCBtZWFuc2ggWl9GSU5JU0guXG4gKlxuICogU2VuZHMgaW5wdXQgZGF0YSB0byBpbmZsYXRlIHBpcGUsIGdlbmVyYXRpbmcgW1tJbmZsYXRlI29uRGF0YV1dIGNhbGxzIHdpdGhcbiAqIG5ldyBvdXRwdXQgY2h1bmtzLiBSZXR1cm5zIGB0cnVlYCBvbiBzdWNjZXNzLiBUaGUgbGFzdCBkYXRhIGJsb2NrIG11c3QgaGF2ZVxuICogbW9kZSBaX0ZJTklTSCAob3IgYHRydWVgKS4gVGhhdCB3aWxsIGZsdXNoIGludGVybmFsIHBlbmRpbmcgYnVmZmVycyBhbmQgY2FsbFxuICogW1tJbmZsYXRlI29uRW5kXV0uIEZvciBpbnRlcmltIGV4cGxpY2l0IGZsdXNoZXMgKHdpdGhvdXQgZW5kaW5nIHRoZSBzdHJlYW0pIHlvdVxuICogY2FuIHVzZSBtb2RlIFpfU1lOQ19GTFVTSCwga2VlcGluZyB0aGUgZGVjb21wcmVzc2lvbiBjb250ZXh0LlxuICpcbiAqIE9uIGZhaWwgY2FsbCBbW0luZmxhdGUjb25FbmRdXSB3aXRoIGVycm9yIGNvZGUgYW5kIHJldHVybiBmYWxzZS5cbiAqXG4gKiBXZSBzdHJvbmdseSByZWNvbW1lbmQgdG8gdXNlIGBVaW50OEFycmF5YCBvbiBpbnB1dCBmb3IgYmVzdCBzcGVlZCAob3V0cHV0XG4gKiBmb3JtYXQgaXMgZGV0ZWN0ZWQgYXV0b21hdGljYWxseSkuIEFsc28sIGRvbid0IHNraXAgbGFzdCBwYXJhbSBhbmQgYWx3YXlzXG4gKiB1c2UgdGhlIHNhbWUgdHlwZSBpbiB5b3VyIGNvZGUgKGJvb2xlYW4gb3IgbnVtYmVyKS4gVGhhdCB3aWxsIGltcHJvdmUgSlMgc3BlZWQuXG4gKlxuICogRm9yIHJlZ3VsYXIgYEFycmF5YC1zIG1ha2Ugc3VyZSBhbGwgZWxlbWVudHMgYXJlIFswLi4yNTVdLlxuICpcbiAqICMjIyMjIEV4YW1wbGVcbiAqXG4gKiBgYGBqYXZhc2NyaXB0XG4gKiBwdXNoKGNodW5rLCBmYWxzZSk7IC8vIHB1c2ggb25lIG9mIGRhdGEgY2h1bmtzXG4gKiAuLi5cbiAqIHB1c2goY2h1bmssIHRydWUpOyAgLy8gcHVzaCBsYXN0IGNodW5rXG4gKiBgYGBcbiAqKi9cbkluZmxhdGUucHJvdG90eXBlLnB1c2ggPSBmdW5jdGlvbihkYXRhLCBtb2RlKSB7XG4gIHZhciBzdHJtID0gdGhpcy5zdHJtO1xuICB2YXIgY2h1bmtTaXplID0gdGhpcy5vcHRpb25zLmNodW5rU2l6ZTtcbiAgdmFyIHN0YXR1cywgX21vZGU7XG4gIHZhciBuZXh0X291dF91dGY4LCB0YWlsLCB1dGY4c3RyO1xuXG4gIC8vIEZsYWcgdG8gcHJvcGVybHkgcHJvY2VzcyBaX0JVRl9FUlJPUiBvbiB0ZXN0aW5nIGluZmxhdGUgY2FsbFxuICAvLyB3aGVuIHdlIGNoZWNrIHRoYXQgYWxsIG91dHB1dCBkYXRhIHdhcyBmbHVzaGVkLlxuICB2YXIgYWxsb3dCdWZFcnJvciA9IGZhbHNlO1xuXG4gIGlmICh0aGlzLmVuZGVkKSB7IHJldHVybiBmYWxzZTsgfVxuICBfbW9kZSA9IChtb2RlID09PSB+fm1vZGUpID8gbW9kZSA6ICgobW9kZSA9PT0gdHJ1ZSkgPyBjLlpfRklOSVNIIDogYy5aX05PX0ZMVVNIKTtcblxuICAvLyBDb252ZXJ0IGRhdGEgaWYgbmVlZGVkXG4gIGlmICh0eXBlb2YgZGF0YSA9PT0gJ3N0cmluZycpIHtcbiAgICAvLyBPbmx5IGJpbmFyeSBzdHJpbmdzIGNhbiBiZSBkZWNvbXByZXNzZWQgb24gcHJhY3RpY2VcbiAgICBzdHJtLmlucHV0ID0gc3RyaW5ncy5iaW5zdHJpbmcyYnVmKGRhdGEpO1xuICB9IGVsc2UgaWYgKHRvU3RyaW5nLmNhbGwoZGF0YSkgPT09ICdbb2JqZWN0IEFycmF5QnVmZmVyXScpIHtcbiAgICBzdHJtLmlucHV0ID0gbmV3IFVpbnQ4QXJyYXkoZGF0YSk7XG4gIH0gZWxzZSB7XG4gICAgc3RybS5pbnB1dCA9IGRhdGE7XG4gIH1cblxuICBzdHJtLm5leHRfaW4gPSAwO1xuICBzdHJtLmF2YWlsX2luID0gc3RybS5pbnB1dC5sZW5ndGg7XG5cbiAgZG8ge1xuICAgIGlmIChzdHJtLmF2YWlsX291dCA9PT0gMCkge1xuICAgICAgc3RybS5vdXRwdXQgPSBuZXcgdXRpbHMuQnVmOChjaHVua1NpemUpO1xuICAgICAgc3RybS5uZXh0X291dCA9IDA7XG4gICAgICBzdHJtLmF2YWlsX291dCA9IGNodW5rU2l6ZTtcbiAgICB9XG5cbiAgICBzdGF0dXMgPSB6bGliX2luZmxhdGUuaW5mbGF0ZShzdHJtLCBjLlpfTk9fRkxVU0gpOyAgICAvKiBubyBiYWQgcmV0dXJuIHZhbHVlICovXG5cbiAgICBpZiAoc3RhdHVzID09PSBjLlpfQlVGX0VSUk9SICYmIGFsbG93QnVmRXJyb3IgPT09IHRydWUpIHtcbiAgICAgIHN0YXR1cyA9IGMuWl9PSztcbiAgICAgIGFsbG93QnVmRXJyb3IgPSBmYWxzZTtcbiAgICB9XG5cbiAgICBpZiAoc3RhdHVzICE9PSBjLlpfU1RSRUFNX0VORCAmJiBzdGF0dXMgIT09IGMuWl9PSykge1xuICAgICAgdGhpcy5vbkVuZChzdGF0dXMpO1xuICAgICAgdGhpcy5lbmRlZCA9IHRydWU7XG4gICAgICByZXR1cm4gZmFsc2U7XG4gICAgfVxuXG4gICAgaWYgKHN0cm0ubmV4dF9vdXQpIHtcbiAgICAgIGlmIChzdHJtLmF2YWlsX291dCA9PT0gMCB8fCBzdGF0dXMgPT09IGMuWl9TVFJFQU1fRU5EIHx8IChzdHJtLmF2YWlsX2luID09PSAwICYmIChfbW9kZSA9PT0gYy5aX0ZJTklTSCB8fCBfbW9kZSA9PT0gYy5aX1NZTkNfRkxVU0gpKSkge1xuXG4gICAgICAgIGlmICh0aGlzLm9wdGlvbnMudG8gPT09ICdzdHJpbmcnKSB7XG5cbiAgICAgICAgICBuZXh0X291dF91dGY4ID0gc3RyaW5ncy51dGY4Ym9yZGVyKHN0cm0ub3V0cHV0LCBzdHJtLm5leHRfb3V0KTtcblxuICAgICAgICAgIHRhaWwgPSBzdHJtLm5leHRfb3V0IC0gbmV4dF9vdXRfdXRmODtcbiAgICAgICAgICB1dGY4c3RyID0gc3RyaW5ncy5idWYyc3RyaW5nKHN0cm0ub3V0cHV0LCBuZXh0X291dF91dGY4KTtcblxuICAgICAgICAgIC8vIG1vdmUgdGFpbFxuICAgICAgICAgIHN0cm0ubmV4dF9vdXQgPSB0YWlsO1xuICAgICAgICAgIHN0cm0uYXZhaWxfb3V0ID0gY2h1bmtTaXplIC0gdGFpbDtcbiAgICAgICAgICBpZiAodGFpbCkgeyB1dGlscy5hcnJheVNldChzdHJtLm91dHB1dCwgc3RybS5vdXRwdXQsIG5leHRfb3V0X3V0ZjgsIHRhaWwsIDApOyB9XG5cbiAgICAgICAgICB0aGlzLm9uRGF0YSh1dGY4c3RyKTtcblxuICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgIHRoaXMub25EYXRhKHV0aWxzLnNocmlua0J1ZihzdHJtLm91dHB1dCwgc3RybS5uZXh0X291dCkpO1xuICAgICAgICB9XG4gICAgICB9XG4gICAgfVxuXG4gICAgLy8gV2hlbiBubyBtb3JlIGlucHV0IGRhdGEsIHdlIHNob3VsZCBjaGVjayB0aGF0IGludGVybmFsIGluZmxhdGUgYnVmZmVyc1xuICAgIC8vIGFyZSBmbHVzaGVkLiBUaGUgb25seSB3YXkgdG8gZG8gaXQgd2hlbiBhdmFpbF9vdXQgPSAwIC0gcnVuIG9uZSBtb3JlXG4gICAgLy8gaW5mbGF0ZSBwYXNzLiBCdXQgaWYgb3V0cHV0IGRhdGEgbm90IGV4aXN0cywgaW5mbGF0ZSByZXR1cm4gWl9CVUZfRVJST1IuXG4gICAgLy8gSGVyZSB3ZSBzZXQgZmxhZyB0byBwcm9jZXNzIHRoaXMgZXJyb3IgcHJvcGVybHkuXG4gICAgLy9cbiAgICAvLyBOT1RFLiBEZWZsYXRlIGRvZXMgbm90IHJldHVybiBlcnJvciBpbiB0aGlzIGNhc2UgYW5kIGRvZXMgbm90IG5lZWRzIHN1Y2hcbiAgICAvLyBsb2dpYy5cbiAgICBpZiAoc3RybS5hdmFpbF9pbiA9PT0gMCAmJiBzdHJtLmF2YWlsX291dCA9PT0gMCkge1xuICAgICAgYWxsb3dCdWZFcnJvciA9IHRydWU7XG4gICAgfVxuXG4gIH0gd2hpbGUgKChzdHJtLmF2YWlsX2luID4gMCB8fCBzdHJtLmF2YWlsX291dCA9PT0gMCkgJiYgc3RhdHVzICE9PSBjLlpfU1RSRUFNX0VORCk7XG5cbiAgaWYgKHN0YXR1cyA9PT0gYy5aX1NUUkVBTV9FTkQpIHtcbiAgICBfbW9kZSA9IGMuWl9GSU5JU0g7XG4gIH1cblxuICAvLyBGaW5hbGl6ZSBvbiB0aGUgbGFzdCBjaHVuay5cbiAgaWYgKF9tb2RlID09PSBjLlpfRklOSVNIKSB7XG4gICAgc3RhdHVzID0gemxpYl9pbmZsYXRlLmluZmxhdGVFbmQodGhpcy5zdHJtKTtcbiAgICB0aGlzLm9uRW5kKHN0YXR1cyk7XG4gICAgdGhpcy5lbmRlZCA9IHRydWU7XG4gICAgcmV0dXJuIHN0YXR1cyA9PT0gYy5aX09LO1xuICB9XG5cbiAgLy8gY2FsbGJhY2sgaW50ZXJpbSByZXN1bHRzIGlmIFpfU1lOQ19GTFVTSC5cbiAgaWYgKF9tb2RlID09PSBjLlpfU1lOQ19GTFVTSCkge1xuICAgIHRoaXMub25FbmQoYy5aX09LKTtcbiAgICBzdHJtLmF2YWlsX291dCA9IDA7XG4gICAgcmV0dXJuIHRydWU7XG4gIH1cblxuICByZXR1cm4gdHJ1ZTtcbn07XG5cblxuLyoqXG4gKiBJbmZsYXRlI29uRGF0YShjaHVuaykgLT4gVm9pZFxuICogLSBjaHVuayAoVWludDhBcnJheXxBcnJheXxTdHJpbmcpOiBvdXB1dCBkYXRhLiBUeXBlIG9mIGFycmF5IGRlcGVuZHNcbiAqICAgb24ganMgZW5naW5lIHN1cHBvcnQuIFdoZW4gc3RyaW5nIG91dHB1dCByZXF1ZXN0ZWQsIGVhY2ggY2h1bmtcbiAqICAgd2lsbCBiZSBzdHJpbmcuXG4gKlxuICogQnkgZGVmYXVsdCwgc3RvcmVzIGRhdGEgYmxvY2tzIGluIGBjaHVua3NbXWAgcHJvcGVydHkgYW5kIGdsdWVcbiAqIHRob3NlIGluIGBvbkVuZGAuIE92ZXJyaWRlIHRoaXMgaGFuZGxlciwgaWYgeW91IG5lZWQgYW5vdGhlciBiZWhhdmlvdXIuXG4gKiovXG5JbmZsYXRlLnByb3RvdHlwZS5vbkRhdGEgPSBmdW5jdGlvbihjaHVuaykge1xuICB0aGlzLmNodW5rcy5wdXNoKGNodW5rKTtcbn07XG5cblxuLyoqXG4gKiBJbmZsYXRlI29uRW5kKHN0YXR1cykgLT4gVm9pZFxuICogLSBzdGF0dXMgKE51bWJlcik6IGluZmxhdGUgc3RhdHVzLiAwIChaX09LKSBvbiBzdWNjZXNzLFxuICogICBvdGhlciBpZiBub3QuXG4gKlxuICogQ2FsbGVkIGVpdGhlciBhZnRlciB5b3UgdGVsbCBpbmZsYXRlIHRoYXQgdGhlIGlucHV0IHN0cmVhbSBpc1xuICogY29tcGxldGUgKFpfRklOSVNIKSBvciBzaG91bGQgYmUgZmx1c2hlZCAoWl9TWU5DX0ZMVVNIKVxuICogb3IgaWYgYW4gZXJyb3IgaGFwcGVuZWQuIEJ5IGRlZmF1bHQgLSBqb2luIGNvbGxlY3RlZCBjaHVua3MsXG4gKiBmcmVlIG1lbW9yeSBhbmQgZmlsbCBgcmVzdWx0c2AgLyBgZXJyYCBwcm9wZXJ0aWVzLlxuICoqL1xuSW5mbGF0ZS5wcm90b3R5cGUub25FbmQgPSBmdW5jdGlvbihzdGF0dXMpIHtcbiAgLy8gT24gc3VjY2VzcyAtIGpvaW5cbiAgaWYgKHN0YXR1cyA9PT0gYy5aX09LKSB7XG4gICAgaWYgKHRoaXMub3B0aW9ucy50byA9PT0gJ3N0cmluZycpIHtcbiAgICAgIC8vIEdsdWUgJiBjb252ZXJ0IGhlcmUsIHVudGlsIHdlIHRlYWNoIHBha28gdG8gc2VuZFxuICAgICAgLy8gdXRmOCBhbGxpZ25lZCBzdHJpbmdzIHRvIG9uRGF0YVxuICAgICAgdGhpcy5yZXN1bHQgPSB0aGlzLmNodW5rcy5qb2luKCcnKTtcbiAgICB9IGVsc2Uge1xuICAgICAgdGhpcy5yZXN1bHQgPSB1dGlscy5mbGF0dGVuQ2h1bmtzKHRoaXMuY2h1bmtzKTtcbiAgICB9XG4gIH1cbiAgdGhpcy5jaHVua3MgPSBbXTtcbiAgdGhpcy5lcnIgPSBzdGF0dXM7XG4gIHRoaXMubXNnID0gdGhpcy5zdHJtLm1zZztcbn07XG5cblxuLyoqXG4gKiBpbmZsYXRlKGRhdGFbLCBvcHRpb25zXSkgLT4gVWludDhBcnJheXxBcnJheXxTdHJpbmdcbiAqIC0gZGF0YSAoVWludDhBcnJheXxBcnJheXxTdHJpbmcpOiBpbnB1dCBkYXRhIHRvIGRlY29tcHJlc3MuXG4gKiAtIG9wdGlvbnMgKE9iamVjdCk6IHpsaWIgaW5mbGF0ZSBvcHRpb25zLlxuICpcbiAqIERlY29tcHJlc3MgYGRhdGFgIHdpdGggaW5mbGF0ZS91bmd6aXAgYW5kIGBvcHRpb25zYC4gQXV0b2RldGVjdFxuICogZm9ybWF0IHZpYSB3cmFwcGVyIGhlYWRlciBieSBkZWZhdWx0LiBUaGF0J3Mgd2h5IHdlIGRvbid0IHByb3ZpZGVcbiAqIHNlcGFyYXRlIGB1bmd6aXBgIG1ldGhvZC5cbiAqXG4gKiBTdXBwb3J0ZWQgb3B0aW9ucyBhcmU6XG4gKlxuICogLSB3aW5kb3dCaXRzXG4gKlxuICogW2h0dHA6Ly96bGliLm5ldC9tYW51YWwuaHRtbCNBZHZhbmNlZF0oaHR0cDovL3psaWIubmV0L21hbnVhbC5odG1sI0FkdmFuY2VkKVxuICogZm9yIG1vcmUgaW5mb3JtYXRpb24uXG4gKlxuICogU3VnYXIgKG9wdGlvbnMpOlxuICpcbiAqIC0gYHJhd2AgKEJvb2xlYW4pIC0gc2F5IHRoYXQgd2Ugd29yayB3aXRoIHJhdyBzdHJlYW0sIGlmIHlvdSBkb24ndCB3aXNoIHRvIHNwZWNpZnlcbiAqICAgbmVnYXRpdmUgd2luZG93Qml0cyBpbXBsaWNpdGx5LlxuICogLSBgdG9gIChTdHJpbmcpIC0gaWYgZXF1YWwgdG8gJ3N0cmluZycsIHRoZW4gcmVzdWx0IHdpbGwgYmUgY29udmVydGVkXG4gKiAgIGZyb20gdXRmOCB0byB1dGYxNiAoamF2YXNjcmlwdCkgc3RyaW5nLiBXaGVuIHN0cmluZyBvdXRwdXQgcmVxdWVzdGVkLFxuICogICBjaHVuayBsZW5ndGggY2FuIGRpZmZlciBmcm9tIGBjaHVua1NpemVgLCBkZXBlbmRpbmcgb24gY29udGVudC5cbiAqXG4gKlxuICogIyMjIyMgRXhhbXBsZTpcbiAqXG4gKiBgYGBqYXZhc2NyaXB0XG4gKiB2YXIgcGFrbyA9IHJlcXVpcmUoJ3Bha28nKVxuICogICAsIGlucHV0ID0gcGFrby5kZWZsYXRlKFsxLDIsMyw0LDUsNiw3LDgsOV0pXG4gKiAgICwgb3V0cHV0O1xuICpcbiAqIHRyeSB7XG4gKiAgIG91dHB1dCA9IHBha28uaW5mbGF0ZShpbnB1dCk7XG4gKiB9IGNhdGNoIChlcnIpXG4gKiAgIGNvbnNvbGUubG9nKGVycik7XG4gKiB9XG4gKiBgYGBcbiAqKi9cbmZ1bmN0aW9uIGluZmxhdGUoaW5wdXQsIG9wdGlvbnMpIHtcbiAgdmFyIGluZmxhdG9yID0gbmV3IEluZmxhdGUob3B0aW9ucyk7XG5cbiAgaW5mbGF0b3IucHVzaChpbnB1dCwgdHJ1ZSk7XG5cbiAgLy8gVGhhdCB3aWxsIG5ldmVyIGhhcHBlbnMsIGlmIHlvdSBkb24ndCBjaGVhdCB3aXRoIG9wdGlvbnMgOilcbiAgaWYgKGluZmxhdG9yLmVycikgeyB0aHJvdyBpbmZsYXRvci5tc2c7IH1cblxuICByZXR1cm4gaW5mbGF0b3IucmVzdWx0O1xufVxuXG5cbi8qKlxuICogaW5mbGF0ZVJhdyhkYXRhWywgb3B0aW9uc10pIC0+IFVpbnQ4QXJyYXl8QXJyYXl8U3RyaW5nXG4gKiAtIGRhdGEgKFVpbnQ4QXJyYXl8QXJyYXl8U3RyaW5nKTogaW5wdXQgZGF0YSB0byBkZWNvbXByZXNzLlxuICogLSBvcHRpb25zIChPYmplY3QpOiB6bGliIGluZmxhdGUgb3B0aW9ucy5cbiAqXG4gKiBUaGUgc2FtZSBhcyBbW2luZmxhdGVdXSwgYnV0IGNyZWF0ZXMgcmF3IGRhdGEsIHdpdGhvdXQgd3JhcHBlclxuICogKGhlYWRlciBhbmQgYWRsZXIzMiBjcmMpLlxuICoqL1xuZnVuY3Rpb24gaW5mbGF0ZVJhdyhpbnB1dCwgb3B0aW9ucykge1xuICBvcHRpb25zID0gb3B0aW9ucyB8fCB7fTtcbiAgb3B0aW9ucy5yYXcgPSB0cnVlO1xuICByZXR1cm4gaW5mbGF0ZShpbnB1dCwgb3B0aW9ucyk7XG59XG5cblxuLyoqXG4gKiB1bmd6aXAoZGF0YVssIG9wdGlvbnNdKSAtPiBVaW50OEFycmF5fEFycmF5fFN0cmluZ1xuICogLSBkYXRhIChVaW50OEFycmF5fEFycmF5fFN0cmluZyk6IGlucHV0IGRhdGEgdG8gZGVjb21wcmVzcy5cbiAqIC0gb3B0aW9ucyAoT2JqZWN0KTogemxpYiBpbmZsYXRlIG9wdGlvbnMuXG4gKlxuICogSnVzdCBzaG9ydGN1dCB0byBbW2luZmxhdGVdXSwgYmVjYXVzZSBpdCBhdXRvZGV0ZWN0cyBmb3JtYXRcbiAqIGJ5IGhlYWRlci5jb250ZW50LiBEb25lIGZvciBjb252ZW5pZW5jZS5cbiAqKi9cblxuXG5leHBvcnRzLkluZmxhdGUgPSBJbmZsYXRlO1xuZXhwb3J0cy5pbmZsYXRlID0gaW5mbGF0ZTtcbmV4cG9ydHMuaW5mbGF0ZVJhdyA9IGluZmxhdGVSYXc7XG5leHBvcnRzLnVuZ3ppcCAgPSBpbmZsYXRlO1xuIiwiJ3VzZSBzdHJpY3QnO1xuXG5cbnZhciBUWVBFRF9PSyA9ICAodHlwZW9mIFVpbnQ4QXJyYXkgIT09ICd1bmRlZmluZWQnKSAmJlxuICAgICAgICAgICAgICAgICh0eXBlb2YgVWludDE2QXJyYXkgIT09ICd1bmRlZmluZWQnKSAmJlxuICAgICAgICAgICAgICAgICh0eXBlb2YgSW50MzJBcnJheSAhPT0gJ3VuZGVmaW5lZCcpO1xuXG5cbmV4cG9ydHMuYXNzaWduID0gZnVuY3Rpb24gKG9iaiAvKmZyb20xLCBmcm9tMiwgZnJvbTMsIC4uLiovKSB7XG4gIHZhciBzb3VyY2VzID0gQXJyYXkucHJvdG90eXBlLnNsaWNlLmNhbGwoYXJndW1lbnRzLCAxKTtcbiAgd2hpbGUgKHNvdXJjZXMubGVuZ3RoKSB7XG4gICAgdmFyIHNvdXJjZSA9IHNvdXJjZXMuc2hpZnQoKTtcbiAgICBpZiAoIXNvdXJjZSkgeyBjb250aW51ZTsgfVxuXG4gICAgaWYgKHR5cGVvZiBzb3VyY2UgIT09ICdvYmplY3QnKSB7XG4gICAgICB0aHJvdyBuZXcgVHlwZUVycm9yKHNvdXJjZSArICdtdXN0IGJlIG5vbi1vYmplY3QnKTtcbiAgICB9XG5cbiAgICBmb3IgKHZhciBwIGluIHNvdXJjZSkge1xuICAgICAgaWYgKHNvdXJjZS5oYXNPd25Qcm9wZXJ0eShwKSkge1xuICAgICAgICBvYmpbcF0gPSBzb3VyY2VbcF07XG4gICAgICB9XG4gICAgfVxuICB9XG5cbiAgcmV0dXJuIG9iajtcbn07XG5cblxuLy8gcmVkdWNlIGJ1ZmZlciBzaXplLCBhdm9pZGluZyBtZW0gY29weVxuZXhwb3J0cy5zaHJpbmtCdWYgPSBmdW5jdGlvbiAoYnVmLCBzaXplKSB7XG4gIGlmIChidWYubGVuZ3RoID09PSBzaXplKSB7IHJldHVybiBidWY7IH1cbiAgaWYgKGJ1Zi5zdWJhcnJheSkgeyByZXR1cm4gYnVmLnN1YmFycmF5KDAsIHNpemUpOyB9XG4gIGJ1Zi5sZW5ndGggPSBzaXplO1xuICByZXR1cm4gYnVmO1xufTtcblxuXG52YXIgZm5UeXBlZCA9IHtcbiAgYXJyYXlTZXQ6IGZ1bmN0aW9uIChkZXN0LCBzcmMsIHNyY19vZmZzLCBsZW4sIGRlc3Rfb2Zmcykge1xuICAgIGlmIChzcmMuc3ViYXJyYXkgJiYgZGVzdC5zdWJhcnJheSkge1xuICAgICAgZGVzdC5zZXQoc3JjLnN1YmFycmF5KHNyY19vZmZzLCBzcmNfb2ZmcytsZW4pLCBkZXN0X29mZnMpO1xuICAgICAgcmV0dXJuO1xuICAgIH1cbiAgICAvLyBGYWxsYmFjayB0byBvcmRpbmFyeSBhcnJheVxuICAgIGZvciAodmFyIGk9MDsgaTxsZW47IGkrKykge1xuICAgICAgZGVzdFtkZXN0X29mZnMgKyBpXSA9IHNyY1tzcmNfb2ZmcyArIGldO1xuICAgIH1cbiAgfSxcbiAgLy8gSm9pbiBhcnJheSBvZiBjaHVua3MgdG8gc2luZ2xlIGFycmF5LlxuICBmbGF0dGVuQ2h1bmtzOiBmdW5jdGlvbihjaHVua3MpIHtcbiAgICB2YXIgaSwgbCwgbGVuLCBwb3MsIGNodW5rLCByZXN1bHQ7XG5cbiAgICAvLyBjYWxjdWxhdGUgZGF0YSBsZW5ndGhcbiAgICBsZW4gPSAwO1xuICAgIGZvciAoaT0wLCBsPWNodW5rcy5sZW5ndGg7IGk8bDsgaSsrKSB7XG4gICAgICBsZW4gKz0gY2h1bmtzW2ldLmxlbmd0aDtcbiAgICB9XG5cbiAgICAvLyBqb2luIGNodW5rc1xuICAgIHJlc3VsdCA9IG5ldyBVaW50OEFycmF5KGxlbik7XG4gICAgcG9zID0gMDtcbiAgICBmb3IgKGk9MCwgbD1jaHVua3MubGVuZ3RoOyBpPGw7IGkrKykge1xuICAgICAgY2h1bmsgPSBjaHVua3NbaV07XG4gICAgICByZXN1bHQuc2V0KGNodW5rLCBwb3MpO1xuICAgICAgcG9zICs9IGNodW5rLmxlbmd0aDtcbiAgICB9XG5cbiAgICByZXR1cm4gcmVzdWx0O1xuICB9XG59O1xuXG52YXIgZm5VbnR5cGVkID0ge1xuICBhcnJheVNldDogZnVuY3Rpb24gKGRlc3QsIHNyYywgc3JjX29mZnMsIGxlbiwgZGVzdF9vZmZzKSB7XG4gICAgZm9yICh2YXIgaT0wOyBpPGxlbjsgaSsrKSB7XG4gICAgICBkZXN0W2Rlc3Rfb2ZmcyArIGldID0gc3JjW3NyY19vZmZzICsgaV07XG4gICAgfVxuICB9LFxuICAvLyBKb2luIGFycmF5IG9mIGNodW5rcyB0byBzaW5nbGUgYXJyYXkuXG4gIGZsYXR0ZW5DaHVua3M6IGZ1bmN0aW9uKGNodW5rcykge1xuICAgIHJldHVybiBbXS5jb25jYXQuYXBwbHkoW10sIGNodW5rcyk7XG4gIH1cbn07XG5cblxuLy8gRW5hYmxlL0Rpc2FibGUgdHlwZWQgYXJyYXlzIHVzZSwgZm9yIHRlc3Rpbmdcbi8vXG5leHBvcnRzLnNldFR5cGVkID0gZnVuY3Rpb24gKG9uKSB7XG4gIGlmIChvbikge1xuICAgIGV4cG9ydHMuQnVmOCAgPSBVaW50OEFycmF5O1xuICAgIGV4cG9ydHMuQnVmMTYgPSBVaW50MTZBcnJheTtcbiAgICBleHBvcnRzLkJ1ZjMyID0gSW50MzJBcnJheTtcbiAgICBleHBvcnRzLmFzc2lnbihleHBvcnRzLCBmblR5cGVkKTtcbiAgfSBlbHNlIHtcbiAgICBleHBvcnRzLkJ1ZjggID0gQXJyYXk7XG4gICAgZXhwb3J0cy5CdWYxNiA9IEFycmF5O1xuICAgIGV4cG9ydHMuQnVmMzIgPSBBcnJheTtcbiAgICBleHBvcnRzLmFzc2lnbihleHBvcnRzLCBmblVudHlwZWQpO1xuICB9XG59O1xuXG5leHBvcnRzLnNldFR5cGVkKFRZUEVEX09LKTtcbiIsIi8vIFN0cmluZyBlbmNvZGUvZGVjb2RlIGhlbHBlcnNcbid1c2Ugc3RyaWN0JztcblxuXG52YXIgdXRpbHMgPSByZXF1aXJlKCcuL2NvbW1vbicpO1xuXG5cbi8vIFF1aWNrIGNoZWNrIGlmIHdlIGNhbiB1c2UgZmFzdCBhcnJheSB0byBiaW4gc3RyaW5nIGNvbnZlcnNpb25cbi8vXG4vLyAtIGFwcGx5KEFycmF5KSBjYW4gZmFpbCBvbiBBbmRyb2lkIDIuMlxuLy8gLSBhcHBseShVaW50OEFycmF5KSBjYW4gZmFpbCBvbiBpT1MgNS4xIFNhZmFyeVxuLy9cbnZhciBTVFJfQVBQTFlfT0sgPSB0cnVlO1xudmFyIFNUUl9BUFBMWV9VSUFfT0sgPSB0cnVlO1xuXG50cnkgeyBTdHJpbmcuZnJvbUNoYXJDb2RlLmFwcGx5KG51bGwsIFswXSk7IH0gY2F0Y2goX18pIHsgU1RSX0FQUExZX09LID0gZmFsc2U7IH1cbnRyeSB7IFN0cmluZy5mcm9tQ2hhckNvZGUuYXBwbHkobnVsbCwgbmV3IFVpbnQ4QXJyYXkoMSkpOyB9IGNhdGNoKF9fKSB7IFNUUl9BUFBMWV9VSUFfT0sgPSBmYWxzZTsgfVxuXG5cbi8vIFRhYmxlIHdpdGggdXRmOCBsZW5ndGhzIChjYWxjdWxhdGVkIGJ5IGZpcnN0IGJ5dGUgb2Ygc2VxdWVuY2UpXG4vLyBOb3RlLCB0aGF0IDUgJiA2LWJ5dGUgdmFsdWVzIGFuZCBzb21lIDQtYnl0ZSB2YWx1ZXMgY2FuIG5vdCBiZSByZXByZXNlbnRlZCBpbiBKUyxcbi8vIGJlY2F1c2UgbWF4IHBvc3NpYmxlIGNvZGVwb2ludCBpcyAweDEwZmZmZlxudmFyIF91dGY4bGVuID0gbmV3IHV0aWxzLkJ1ZjgoMjU2KTtcbmZvciAodmFyIHE9MDsgcTwyNTY7IHErKykge1xuICBfdXRmOGxlbltxXSA9IChxID49IDI1MiA/IDYgOiBxID49IDI0OCA/IDUgOiBxID49IDI0MCA/IDQgOiBxID49IDIyNCA/IDMgOiBxID49IDE5MiA/IDIgOiAxKTtcbn1cbl91dGY4bGVuWzI1NF09X3V0ZjhsZW5bMjU0XT0xOyAvLyBJbnZhbGlkIHNlcXVlbmNlIHN0YXJ0XG5cblxuLy8gY29udmVydCBzdHJpbmcgdG8gYXJyYXkgKHR5cGVkLCB3aGVuIHBvc3NpYmxlKVxuZXhwb3J0cy5zdHJpbmcyYnVmID0gZnVuY3Rpb24gKHN0cikge1xuICB2YXIgYnVmLCBjLCBjMiwgbV9wb3MsIGksIHN0cl9sZW4gPSBzdHIubGVuZ3RoLCBidWZfbGVuID0gMDtcblxuICAvLyBjb3VudCBiaW5hcnkgc2l6ZVxuICBmb3IgKG1fcG9zID0gMDsgbV9wb3MgPCBzdHJfbGVuOyBtX3BvcysrKSB7XG4gICAgYyA9IHN0ci5jaGFyQ29kZUF0KG1fcG9zKTtcbiAgICBpZiAoKGMgJiAweGZjMDApID09PSAweGQ4MDAgJiYgKG1fcG9zKzEgPCBzdHJfbGVuKSkge1xuICAgICAgYzIgPSBzdHIuY2hhckNvZGVBdChtX3BvcysxKTtcbiAgICAgIGlmICgoYzIgJiAweGZjMDApID09PSAweGRjMDApIHtcbiAgICAgICAgYyA9IDB4MTAwMDAgKyAoKGMgLSAweGQ4MDApIDw8IDEwKSArIChjMiAtIDB4ZGMwMCk7XG4gICAgICAgIG1fcG9zKys7XG4gICAgICB9XG4gICAgfVxuICAgIGJ1Zl9sZW4gKz0gYyA8IDB4ODAgPyAxIDogYyA8IDB4ODAwID8gMiA6IGMgPCAweDEwMDAwID8gMyA6IDQ7XG4gIH1cblxuICAvLyBhbGxvY2F0ZSBidWZmZXJcbiAgYnVmID0gbmV3IHV0aWxzLkJ1ZjgoYnVmX2xlbik7XG5cbiAgLy8gY29udmVydFxuICBmb3IgKGk9MCwgbV9wb3MgPSAwOyBpIDwgYnVmX2xlbjsgbV9wb3MrKykge1xuICAgIGMgPSBzdHIuY2hhckNvZGVBdChtX3Bvcyk7XG4gICAgaWYgKChjICYgMHhmYzAwKSA9PT0gMHhkODAwICYmIChtX3BvcysxIDwgc3RyX2xlbikpIHtcbiAgICAgIGMyID0gc3RyLmNoYXJDb2RlQXQobV9wb3MrMSk7XG4gICAgICBpZiAoKGMyICYgMHhmYzAwKSA9PT0gMHhkYzAwKSB7XG4gICAgICAgIGMgPSAweDEwMDAwICsgKChjIC0gMHhkODAwKSA8PCAxMCkgKyAoYzIgLSAweGRjMDApO1xuICAgICAgICBtX3BvcysrO1xuICAgICAgfVxuICAgIH1cbiAgICBpZiAoYyA8IDB4ODApIHtcbiAgICAgIC8qIG9uZSBieXRlICovXG4gICAgICBidWZbaSsrXSA9IGM7XG4gICAgfSBlbHNlIGlmIChjIDwgMHg4MDApIHtcbiAgICAgIC8qIHR3byBieXRlcyAqL1xuICAgICAgYnVmW2krK10gPSAweEMwIHwgKGMgPj4+IDYpO1xuICAgICAgYnVmW2krK10gPSAweDgwIHwgKGMgJiAweDNmKTtcbiAgICB9IGVsc2UgaWYgKGMgPCAweDEwMDAwKSB7XG4gICAgICAvKiB0aHJlZSBieXRlcyAqL1xuICAgICAgYnVmW2krK10gPSAweEUwIHwgKGMgPj4+IDEyKTtcbiAgICAgIGJ1ZltpKytdID0gMHg4MCB8IChjID4+PiA2ICYgMHgzZik7XG4gICAgICBidWZbaSsrXSA9IDB4ODAgfCAoYyAmIDB4M2YpO1xuICAgIH0gZWxzZSB7XG4gICAgICAvKiBmb3VyIGJ5dGVzICovXG4gICAgICBidWZbaSsrXSA9IDB4ZjAgfCAoYyA+Pj4gMTgpO1xuICAgICAgYnVmW2krK10gPSAweDgwIHwgKGMgPj4+IDEyICYgMHgzZik7XG4gICAgICBidWZbaSsrXSA9IDB4ODAgfCAoYyA+Pj4gNiAmIDB4M2YpO1xuICAgICAgYnVmW2krK10gPSAweDgwIHwgKGMgJiAweDNmKTtcbiAgICB9XG4gIH1cblxuICByZXR1cm4gYnVmO1xufTtcblxuLy8gSGVscGVyICh1c2VkIGluIDIgcGxhY2VzKVxuZnVuY3Rpb24gYnVmMmJpbnN0cmluZyhidWYsIGxlbikge1xuICAvLyB1c2UgZmFsbGJhY2sgZm9yIGJpZyBhcnJheXMgdG8gYXZvaWQgc3RhY2sgb3ZlcmZsb3dcbiAgaWYgKGxlbiA8IDY1NTM3KSB7XG4gICAgaWYgKChidWYuc3ViYXJyYXkgJiYgU1RSX0FQUExZX1VJQV9PSykgfHwgKCFidWYuc3ViYXJyYXkgJiYgU1RSX0FQUExZX09LKSkge1xuICAgICAgcmV0dXJuIFN0cmluZy5mcm9tQ2hhckNvZGUuYXBwbHkobnVsbCwgdXRpbHMuc2hyaW5rQnVmKGJ1ZiwgbGVuKSk7XG4gICAgfVxuICB9XG5cbiAgdmFyIHJlc3VsdCA9ICcnO1xuICBmb3IgKHZhciBpPTA7IGkgPCBsZW47IGkrKykge1xuICAgIHJlc3VsdCArPSBTdHJpbmcuZnJvbUNoYXJDb2RlKGJ1ZltpXSk7XG4gIH1cbiAgcmV0dXJuIHJlc3VsdDtcbn1cblxuXG4vLyBDb252ZXJ0IGJ5dGUgYXJyYXkgdG8gYmluYXJ5IHN0cmluZ1xuZXhwb3J0cy5idWYyYmluc3RyaW5nID0gZnVuY3Rpb24oYnVmKSB7XG4gIHJldHVybiBidWYyYmluc3RyaW5nKGJ1ZiwgYnVmLmxlbmd0aCk7XG59O1xuXG5cbi8vIENvbnZlcnQgYmluYXJ5IHN0cmluZyAodHlwZWQsIHdoZW4gcG9zc2libGUpXG5leHBvcnRzLmJpbnN0cmluZzJidWYgPSBmdW5jdGlvbihzdHIpIHtcbiAgdmFyIGJ1ZiA9IG5ldyB1dGlscy5CdWY4KHN0ci5sZW5ndGgpO1xuICBmb3IgKHZhciBpPTAsIGxlbj1idWYubGVuZ3RoOyBpIDwgbGVuOyBpKyspIHtcbiAgICBidWZbaV0gPSBzdHIuY2hhckNvZGVBdChpKTtcbiAgfVxuICByZXR1cm4gYnVmO1xufTtcblxuXG4vLyBjb252ZXJ0IGFycmF5IHRvIHN0cmluZ1xuZXhwb3J0cy5idWYyc3RyaW5nID0gZnVuY3Rpb24gKGJ1ZiwgbWF4KSB7XG4gIHZhciBpLCBvdXQsIGMsIGNfbGVuO1xuICB2YXIgbGVuID0gbWF4IHx8IGJ1Zi5sZW5ndGg7XG5cbiAgLy8gUmVzZXJ2ZSBtYXggcG9zc2libGUgbGVuZ3RoICgyIHdvcmRzIHBlciBjaGFyKVxuICAvLyBOQjogYnkgdW5rbm93biByZWFzb25zLCBBcnJheSBpcyBzaWduaWZpY2FudGx5IGZhc3RlciBmb3JcbiAgLy8gICAgIFN0cmluZy5mcm9tQ2hhckNvZGUuYXBwbHkgdGhhbiBVaW50MTZBcnJheS5cbiAgdmFyIHV0ZjE2YnVmID0gbmV3IEFycmF5KGxlbioyKTtcblxuICBmb3IgKG91dD0wLCBpPTA7IGk8bGVuOykge1xuICAgIGMgPSBidWZbaSsrXTtcbiAgICAvLyBxdWljayBwcm9jZXNzIGFzY2lpXG4gICAgaWYgKGMgPCAweDgwKSB7IHV0ZjE2YnVmW291dCsrXSA9IGM7IGNvbnRpbnVlOyB9XG5cbiAgICBjX2xlbiA9IF91dGY4bGVuW2NdO1xuICAgIC8vIHNraXAgNSAmIDYgYnl0ZSBjb2Rlc1xuICAgIGlmIChjX2xlbiA+IDQpIHsgdXRmMTZidWZbb3V0KytdID0gMHhmZmZkOyBpICs9IGNfbGVuLTE7IGNvbnRpbnVlOyB9XG5cbiAgICAvLyBhcHBseSBtYXNrIG9uIGZpcnN0IGJ5dGVcbiAgICBjICY9IGNfbGVuID09PSAyID8gMHgxZiA6IGNfbGVuID09PSAzID8gMHgwZiA6IDB4MDc7XG4gICAgLy8gam9pbiB0aGUgcmVzdFxuICAgIHdoaWxlIChjX2xlbiA+IDEgJiYgaSA8IGxlbikge1xuICAgICAgYyA9IChjIDw8IDYpIHwgKGJ1ZltpKytdICYgMHgzZik7XG4gICAgICBjX2xlbi0tO1xuICAgIH1cblxuICAgIC8vIHRlcm1pbmF0ZWQgYnkgZW5kIG9mIHN0cmluZz9cbiAgICBpZiAoY19sZW4gPiAxKSB7IHV0ZjE2YnVmW291dCsrXSA9IDB4ZmZmZDsgY29udGludWU7IH1cblxuICAgIGlmIChjIDwgMHgxMDAwMCkge1xuICAgICAgdXRmMTZidWZbb3V0KytdID0gYztcbiAgICB9IGVsc2Uge1xuICAgICAgYyAtPSAweDEwMDAwO1xuICAgICAgdXRmMTZidWZbb3V0KytdID0gMHhkODAwIHwgKChjID4+IDEwKSAmIDB4M2ZmKTtcbiAgICAgIHV0ZjE2YnVmW291dCsrXSA9IDB4ZGMwMCB8IChjICYgMHgzZmYpO1xuICAgIH1cbiAgfVxuXG4gIHJldHVybiBidWYyYmluc3RyaW5nKHV0ZjE2YnVmLCBvdXQpO1xufTtcblxuXG4vLyBDYWxjdWxhdGUgbWF4IHBvc3NpYmxlIHBvc2l0aW9uIGluIHV0ZjggYnVmZmVyLFxuLy8gdGhhdCB3aWxsIG5vdCBicmVhayBzZXF1ZW5jZS4gSWYgdGhhdCdzIG5vdCBwb3NzaWJsZVxuLy8gLSAodmVyeSBzbWFsbCBsaW1pdHMpIHJldHVybiBtYXggc2l6ZSBhcyBpcy5cbi8vXG4vLyBidWZbXSAtIHV0ZjggYnl0ZXMgYXJyYXlcbi8vIG1heCAgIC0gbGVuZ3RoIGxpbWl0IChtYW5kYXRvcnkpO1xuZXhwb3J0cy51dGY4Ym9yZGVyID0gZnVuY3Rpb24oYnVmLCBtYXgpIHtcbiAgdmFyIHBvcztcblxuICBtYXggPSBtYXggfHwgYnVmLmxlbmd0aDtcbiAgaWYgKG1heCA+IGJ1Zi5sZW5ndGgpIHsgbWF4ID0gYnVmLmxlbmd0aDsgfVxuXG4gIC8vIGdvIGJhY2sgZnJvbSBsYXN0IHBvc2l0aW9uLCB1bnRpbCBzdGFydCBvZiBzZXF1ZW5jZSBmb3VuZFxuICBwb3MgPSBtYXgtMTtcbiAgd2hpbGUgKHBvcyA+PSAwICYmIChidWZbcG9zXSAmIDB4QzApID09PSAweDgwKSB7IHBvcy0tOyB9XG5cbiAgLy8gRnVja3VwIC0gdmVyeSBzbWFsbCBhbmQgYnJva2VuIHNlcXVlbmNlLFxuICAvLyByZXR1cm4gbWF4LCBiZWNhdXNlIHdlIHNob3VsZCByZXR1cm4gc29tZXRoaW5nIGFueXdheS5cbiAgaWYgKHBvcyA8IDApIHsgcmV0dXJuIG1heDsgfVxuXG4gIC8vIElmIHdlIGNhbWUgdG8gc3RhcnQgb2YgYnVmZmVyIC0gdGhhdCBtZWFucyB2dWZmZXIgaXMgdG9vIHNtYWxsLFxuICAvLyByZXR1cm4gbWF4IHRvby5cbiAgaWYgKHBvcyA9PT0gMCkgeyByZXR1cm4gbWF4OyB9XG5cbiAgcmV0dXJuIChwb3MgKyBfdXRmOGxlbltidWZbcG9zXV0gPiBtYXgpID8gcG9zIDogbWF4O1xufTtcbiIsIid1c2Ugc3RyaWN0JztcblxuLy8gTm90ZTogYWRsZXIzMiB0YWtlcyAxMiUgZm9yIGxldmVsIDAgYW5kIDIlIGZvciBsZXZlbCA2LlxuLy8gSXQgZG9lc24ndCB3b3J0aCB0byBtYWtlIGFkZGl0aW9uYWwgb3B0aW1pemF0aW9uYSBhcyBpbiBvcmlnaW5hbC5cbi8vIFNtYWxsIHNpemUgaXMgcHJlZmVyYWJsZS5cblxuZnVuY3Rpb24gYWRsZXIzMihhZGxlciwgYnVmLCBsZW4sIHBvcykge1xuICB2YXIgczEgPSAoYWRsZXIgJiAweGZmZmYpIHwwLFxuICAgICAgczIgPSAoKGFkbGVyID4+PiAxNikgJiAweGZmZmYpIHwwLFxuICAgICAgbiA9IDA7XG5cbiAgd2hpbGUgKGxlbiAhPT0gMCkge1xuICAgIC8vIFNldCBsaW1pdCB+IHR3aWNlIGxlc3MgdGhhbiA1NTUyLCB0byBrZWVwXG4gICAgLy8gczIgaW4gMzEtYml0cywgYmVjYXVzZSB3ZSBmb3JjZSBzaWduZWQgaW50cy5cbiAgICAvLyBpbiBvdGhlciBjYXNlICU9IHdpbGwgZmFpbC5cbiAgICBuID0gbGVuID4gMjAwMCA/IDIwMDAgOiBsZW47XG4gICAgbGVuIC09IG47XG5cbiAgICBkbyB7XG4gICAgICBzMSA9IChzMSArIGJ1Zltwb3MrK10pIHwwO1xuICAgICAgczIgPSAoczIgKyBzMSkgfDA7XG4gICAgfSB3aGlsZSAoLS1uKTtcblxuICAgIHMxICU9IDY1NTIxO1xuICAgIHMyICU9IDY1NTIxO1xuICB9XG5cbiAgcmV0dXJuIChzMSB8IChzMiA8PCAxNikpIHwwO1xufVxuXG5cbm1vZHVsZS5leHBvcnRzID0gYWRsZXIzMjtcbiIsIm1vZHVsZS5leHBvcnRzID0ge1xuXG4gIC8qIEFsbG93ZWQgZmx1c2ggdmFsdWVzOyBzZWUgZGVmbGF0ZSgpIGFuZCBpbmZsYXRlKCkgYmVsb3cgZm9yIGRldGFpbHMgKi9cbiAgWl9OT19GTFVTSDogICAgICAgICAwLFxuICBaX1BBUlRJQUxfRkxVU0g6ICAgIDEsXG4gIFpfU1lOQ19GTFVTSDogICAgICAgMixcbiAgWl9GVUxMX0ZMVVNIOiAgICAgICAzLFxuICBaX0ZJTklTSDogICAgICAgICAgIDQsXG4gIFpfQkxPQ0s6ICAgICAgICAgICAgNSxcbiAgWl9UUkVFUzogICAgICAgICAgICA2LFxuXG4gIC8qIFJldHVybiBjb2RlcyBmb3IgdGhlIGNvbXByZXNzaW9uL2RlY29tcHJlc3Npb24gZnVuY3Rpb25zLiBOZWdhdGl2ZSB2YWx1ZXNcbiAgKiBhcmUgZXJyb3JzLCBwb3NpdGl2ZSB2YWx1ZXMgYXJlIHVzZWQgZm9yIHNwZWNpYWwgYnV0IG5vcm1hbCBldmVudHMuXG4gICovXG4gIFpfT0s6ICAgICAgICAgICAgICAgMCxcbiAgWl9TVFJFQU1fRU5EOiAgICAgICAxLFxuICBaX05FRURfRElDVDogICAgICAgIDIsXG4gIFpfRVJSTk86ICAgICAgICAgICAtMSxcbiAgWl9TVFJFQU1fRVJST1I6ICAgIC0yLFxuICBaX0RBVEFfRVJST1I6ICAgICAgLTMsXG4gIC8vWl9NRU1fRVJST1I6ICAgICAtNCxcbiAgWl9CVUZfRVJST1I6ICAgICAgIC01LFxuICAvL1pfVkVSU0lPTl9FUlJPUjogLTYsXG5cbiAgLyogY29tcHJlc3Npb24gbGV2ZWxzICovXG4gIFpfTk9fQ09NUFJFU1NJT046ICAgICAgICAgMCxcbiAgWl9CRVNUX1NQRUVEOiAgICAgICAgICAgICAxLFxuICBaX0JFU1RfQ09NUFJFU1NJT046ICAgICAgIDksXG4gIFpfREVGQVVMVF9DT01QUkVTU0lPTjogICAtMSxcblxuXG4gIFpfRklMVEVSRUQ6ICAgICAgICAgICAgICAgMSxcbiAgWl9IVUZGTUFOX09OTFk6ICAgICAgICAgICAyLFxuICBaX1JMRTogICAgICAgICAgICAgICAgICAgIDMsXG4gIFpfRklYRUQ6ICAgICAgICAgICAgICAgICAgNCxcbiAgWl9ERUZBVUxUX1NUUkFURUdZOiAgICAgICAwLFxuXG4gIC8qIFBvc3NpYmxlIHZhbHVlcyBvZiB0aGUgZGF0YV90eXBlIGZpZWxkICh0aG91Z2ggc2VlIGluZmxhdGUoKSkgKi9cbiAgWl9CSU5BUlk6ICAgICAgICAgICAgICAgICAwLFxuICBaX1RFWFQ6ICAgICAgICAgICAgICAgICAgIDEsXG4gIC8vWl9BU0NJSTogICAgICAgICAgICAgICAgMSwgLy8gPSBaX1RFWFQgKGRlcHJlY2F0ZWQpXG4gIFpfVU5LTk9XTjogICAgICAgICAgICAgICAgMixcblxuICAvKiBUaGUgZGVmbGF0ZSBjb21wcmVzc2lvbiBtZXRob2QgKi9cbiAgWl9ERUZMQVRFRDogICAgICAgICAgICAgICA4XG4gIC8vWl9OVUxMOiAgICAgICAgICAgICAgICAgbnVsbCAvLyBVc2UgLTEgb3IgbnVsbCBpbmxpbmUsIGRlcGVuZGluZyBvbiB2YXIgdHlwZVxufTtcbiIsIid1c2Ugc3RyaWN0JztcblxuLy8gTm90ZTogd2UgY2FuJ3QgZ2V0IHNpZ25pZmljYW50IHNwZWVkIGJvb3N0IGhlcmUuXG4vLyBTbyB3cml0ZSBjb2RlIHRvIG1pbmltaXplIHNpemUgLSBubyBwcmVnZW5lcmF0ZWQgdGFibGVzXG4vLyBhbmQgYXJyYXkgdG9vbHMgZGVwZW5kZW5jaWVzLlxuXG5cbi8vIFVzZSBvcmRpbmFyeSBhcnJheSwgc2luY2UgdW50eXBlZCBtYWtlcyBubyBib29zdCBoZXJlXG5mdW5jdGlvbiBtYWtlVGFibGUoKSB7XG4gIHZhciBjLCB0YWJsZSA9IFtdO1xuXG4gIGZvciAodmFyIG4gPTA7IG4gPCAyNTY7IG4rKykge1xuICAgIGMgPSBuO1xuICAgIGZvciAodmFyIGsgPTA7IGsgPCA4OyBrKyspIHtcbiAgICAgIGMgPSAoKGMmMSkgPyAoMHhFREI4ODMyMCBeIChjID4+PiAxKSkgOiAoYyA+Pj4gMSkpO1xuICAgIH1cbiAgICB0YWJsZVtuXSA9IGM7XG4gIH1cblxuICByZXR1cm4gdGFibGU7XG59XG5cbi8vIENyZWF0ZSB0YWJsZSBvbiBsb2FkLiBKdXN0IDI1NSBzaWduZWQgbG9uZ3MuIE5vdCBhIHByb2JsZW0uXG52YXIgY3JjVGFibGUgPSBtYWtlVGFibGUoKTtcblxuXG5mdW5jdGlvbiBjcmMzMihjcmMsIGJ1ZiwgbGVuLCBwb3MpIHtcbiAgdmFyIHQgPSBjcmNUYWJsZSxcbiAgICAgIGVuZCA9IHBvcyArIGxlbjtcblxuICBjcmMgPSBjcmMgXiAoLTEpO1xuXG4gIGZvciAodmFyIGkgPSBwb3M7IGkgPCBlbmQ7IGkrKykge1xuICAgIGNyYyA9IChjcmMgPj4+IDgpIF4gdFsoY3JjIF4gYnVmW2ldKSAmIDB4RkZdO1xuICB9XG5cbiAgcmV0dXJuIChjcmMgXiAoLTEpKTsgLy8gPj4+IDA7XG59XG5cblxubW9kdWxlLmV4cG9ydHMgPSBjcmMzMjtcbiIsIid1c2Ugc3RyaWN0JztcblxudmFyIHV0aWxzICAgPSByZXF1aXJlKCcuLi91dGlscy9jb21tb24nKTtcbnZhciB0cmVlcyAgID0gcmVxdWlyZSgnLi90cmVlcycpO1xudmFyIGFkbGVyMzIgPSByZXF1aXJlKCcuL2FkbGVyMzInKTtcbnZhciBjcmMzMiAgID0gcmVxdWlyZSgnLi9jcmMzMicpO1xudmFyIG1zZyAgID0gcmVxdWlyZSgnLi9tZXNzYWdlcycpO1xuXG4vKiBQdWJsaWMgY29uc3RhbnRzID09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT0qL1xuLyogPT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09Ki9cblxuXG4vKiBBbGxvd2VkIGZsdXNoIHZhbHVlczsgc2VlIGRlZmxhdGUoKSBhbmQgaW5mbGF0ZSgpIGJlbG93IGZvciBkZXRhaWxzICovXG52YXIgWl9OT19GTFVTSCAgICAgID0gMDtcbnZhciBaX1BBUlRJQUxfRkxVU0ggPSAxO1xuLy92YXIgWl9TWU5DX0ZMVVNIICAgID0gMjtcbnZhciBaX0ZVTExfRkxVU0ggICAgPSAzO1xudmFyIFpfRklOSVNIICAgICAgICA9IDQ7XG52YXIgWl9CTE9DSyAgICAgICAgID0gNTtcbi8vdmFyIFpfVFJFRVMgICAgICAgICA9IDY7XG5cblxuLyogUmV0dXJuIGNvZGVzIGZvciB0aGUgY29tcHJlc3Npb24vZGVjb21wcmVzc2lvbiBmdW5jdGlvbnMuIE5lZ2F0aXZlIHZhbHVlc1xuICogYXJlIGVycm9ycywgcG9zaXRpdmUgdmFsdWVzIGFyZSB1c2VkIGZvciBzcGVjaWFsIGJ1dCBub3JtYWwgZXZlbnRzLlxuICovXG52YXIgWl9PSyAgICAgICAgICAgID0gMDtcbnZhciBaX1NUUkVBTV9FTkQgICAgPSAxO1xuLy92YXIgWl9ORUVEX0RJQ1QgICAgID0gMjtcbi8vdmFyIFpfRVJSTk8gICAgICAgICA9IC0xO1xudmFyIFpfU1RSRUFNX0VSUk9SICA9IC0yO1xudmFyIFpfREFUQV9FUlJPUiAgICA9IC0zO1xuLy92YXIgWl9NRU1fRVJST1IgICAgID0gLTQ7XG52YXIgWl9CVUZfRVJST1IgICAgID0gLTU7XG4vL3ZhciBaX1ZFUlNJT05fRVJST1IgPSAtNjtcblxuXG4vKiBjb21wcmVzc2lvbiBsZXZlbHMgKi9cbi8vdmFyIFpfTk9fQ09NUFJFU1NJT04gICAgICA9IDA7XG4vL3ZhciBaX0JFU1RfU1BFRUQgICAgICAgICAgPSAxO1xuLy92YXIgWl9CRVNUX0NPTVBSRVNTSU9OICAgID0gOTtcbnZhciBaX0RFRkFVTFRfQ09NUFJFU1NJT04gPSAtMTtcblxuXG52YXIgWl9GSUxURVJFRCAgICAgICAgICAgID0gMTtcbnZhciBaX0hVRkZNQU5fT05MWSAgICAgICAgPSAyO1xudmFyIFpfUkxFICAgICAgICAgICAgICAgICA9IDM7XG52YXIgWl9GSVhFRCAgICAgICAgICAgICAgID0gNDtcbnZhciBaX0RFRkFVTFRfU1RSQVRFR1kgICAgPSAwO1xuXG4vKiBQb3NzaWJsZSB2YWx1ZXMgb2YgdGhlIGRhdGFfdHlwZSBmaWVsZCAodGhvdWdoIHNlZSBpbmZsYXRlKCkpICovXG4vL3ZhciBaX0JJTkFSWSAgICAgICAgICAgICAgPSAwO1xuLy92YXIgWl9URVhUICAgICAgICAgICAgICAgID0gMTtcbi8vdmFyIFpfQVNDSUkgICAgICAgICAgICAgICA9IDE7IC8vID0gWl9URVhUXG52YXIgWl9VTktOT1dOICAgICAgICAgICAgID0gMjtcblxuXG4vKiBUaGUgZGVmbGF0ZSBjb21wcmVzc2lvbiBtZXRob2QgKi9cbnZhciBaX0RFRkxBVEVEICA9IDg7XG5cbi8qPT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PSovXG5cblxudmFyIE1BWF9NRU1fTEVWRUwgPSA5O1xuLyogTWF4aW11bSB2YWx1ZSBmb3IgbWVtTGV2ZWwgaW4gZGVmbGF0ZUluaXQyICovXG52YXIgTUFYX1dCSVRTID0gMTU7XG4vKiAzMksgTFo3NyB3aW5kb3cgKi9cbnZhciBERUZfTUVNX0xFVkVMID0gODtcblxuXG52YXIgTEVOR1RIX0NPREVTICA9IDI5O1xuLyogbnVtYmVyIG9mIGxlbmd0aCBjb2Rlcywgbm90IGNvdW50aW5nIHRoZSBzcGVjaWFsIEVORF9CTE9DSyBjb2RlICovXG52YXIgTElURVJBTFMgICAgICA9IDI1Njtcbi8qIG51bWJlciBvZiBsaXRlcmFsIGJ5dGVzIDAuLjI1NSAqL1xudmFyIExfQ09ERVMgICAgICAgPSBMSVRFUkFMUyArIDEgKyBMRU5HVEhfQ09ERVM7XG4vKiBudW1iZXIgb2YgTGl0ZXJhbCBvciBMZW5ndGggY29kZXMsIGluY2x1ZGluZyB0aGUgRU5EX0JMT0NLIGNvZGUgKi9cbnZhciBEX0NPREVTICAgICAgID0gMzA7XG4vKiBudW1iZXIgb2YgZGlzdGFuY2UgY29kZXMgKi9cbnZhciBCTF9DT0RFUyAgICAgID0gMTk7XG4vKiBudW1iZXIgb2YgY29kZXMgdXNlZCB0byB0cmFuc2ZlciB0aGUgYml0IGxlbmd0aHMgKi9cbnZhciBIRUFQX1NJWkUgICAgID0gMipMX0NPREVTICsgMTtcbi8qIG1heGltdW0gaGVhcCBzaXplICovXG52YXIgTUFYX0JJVFMgID0gMTU7XG4vKiBBbGwgY29kZXMgbXVzdCBub3QgZXhjZWVkIE1BWF9CSVRTIGJpdHMgKi9cblxudmFyIE1JTl9NQVRDSCA9IDM7XG52YXIgTUFYX01BVENIID0gMjU4O1xudmFyIE1JTl9MT09LQUhFQUQgPSAoTUFYX01BVENIICsgTUlOX01BVENIICsgMSk7XG5cbnZhciBQUkVTRVRfRElDVCA9IDB4MjA7XG5cbnZhciBJTklUX1NUQVRFID0gNDI7XG52YXIgRVhUUkFfU1RBVEUgPSA2OTtcbnZhciBOQU1FX1NUQVRFID0gNzM7XG52YXIgQ09NTUVOVF9TVEFURSA9IDkxO1xudmFyIEhDUkNfU1RBVEUgPSAxMDM7XG52YXIgQlVTWV9TVEFURSA9IDExMztcbnZhciBGSU5JU0hfU1RBVEUgPSA2NjY7XG5cbnZhciBCU19ORUVEX01PUkUgICAgICA9IDE7IC8qIGJsb2NrIG5vdCBjb21wbGV0ZWQsIG5lZWQgbW9yZSBpbnB1dCBvciBtb3JlIG91dHB1dCAqL1xudmFyIEJTX0JMT0NLX0RPTkUgICAgID0gMjsgLyogYmxvY2sgZmx1c2ggcGVyZm9ybWVkICovXG52YXIgQlNfRklOSVNIX1NUQVJURUQgPSAzOyAvKiBmaW5pc2ggc3RhcnRlZCwgbmVlZCBvbmx5IG1vcmUgb3V0cHV0IGF0IG5leHQgZGVmbGF0ZSAqL1xudmFyIEJTX0ZJTklTSF9ET05FICAgID0gNDsgLyogZmluaXNoIGRvbmUsIGFjY2VwdCBubyBtb3JlIGlucHV0IG9yIG91dHB1dCAqL1xuXG52YXIgT1NfQ09ERSA9IDB4MDM7IC8vIFVuaXggOikgLiBEb24ndCBkZXRlY3QsIHVzZSB0aGlzIGRlZmF1bHQuXG5cbmZ1bmN0aW9uIGVycihzdHJtLCBlcnJvckNvZGUpIHtcbiAgc3RybS5tc2cgPSBtc2dbZXJyb3JDb2RlXTtcbiAgcmV0dXJuIGVycm9yQ29kZTtcbn1cblxuZnVuY3Rpb24gcmFuayhmKSB7XG4gIHJldHVybiAoKGYpIDw8IDEpIC0gKChmKSA+IDQgPyA5IDogMCk7XG59XG5cbmZ1bmN0aW9uIHplcm8oYnVmKSB7IHZhciBsZW4gPSBidWYubGVuZ3RoOyB3aGlsZSAoLS1sZW4gPj0gMCkgeyBidWZbbGVuXSA9IDA7IH0gfVxuXG5cbi8qID09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT1cbiAqIEZsdXNoIGFzIG11Y2ggcGVuZGluZyBvdXRwdXQgYXMgcG9zc2libGUuIEFsbCBkZWZsYXRlKCkgb3V0cHV0IGdvZXNcbiAqIHRocm91Z2ggdGhpcyBmdW5jdGlvbiBzbyBzb21lIGFwcGxpY2F0aW9ucyBtYXkgd2lzaCB0byBtb2RpZnkgaXRcbiAqIHRvIGF2b2lkIGFsbG9jYXRpbmcgYSBsYXJnZSBzdHJtLT5vdXRwdXQgYnVmZmVyIGFuZCBjb3B5aW5nIGludG8gaXQuXG4gKiAoU2VlIGFsc28gcmVhZF9idWYoKSkuXG4gKi9cbmZ1bmN0aW9uIGZsdXNoX3BlbmRpbmcoc3RybSkge1xuICB2YXIgcyA9IHN0cm0uc3RhdGU7XG5cbiAgLy9fdHJfZmx1c2hfYml0cyhzKTtcbiAgdmFyIGxlbiA9IHMucGVuZGluZztcbiAgaWYgKGxlbiA+IHN0cm0uYXZhaWxfb3V0KSB7XG4gICAgbGVuID0gc3RybS5hdmFpbF9vdXQ7XG4gIH1cbiAgaWYgKGxlbiA9PT0gMCkgeyByZXR1cm47IH1cblxuICB1dGlscy5hcnJheVNldChzdHJtLm91dHB1dCwgcy5wZW5kaW5nX2J1Ziwgcy5wZW5kaW5nX291dCwgbGVuLCBzdHJtLm5leHRfb3V0KTtcbiAgc3RybS5uZXh0X291dCArPSBsZW47XG4gIHMucGVuZGluZ19vdXQgKz0gbGVuO1xuICBzdHJtLnRvdGFsX291dCArPSBsZW47XG4gIHN0cm0uYXZhaWxfb3V0IC09IGxlbjtcbiAgcy5wZW5kaW5nIC09IGxlbjtcbiAgaWYgKHMucGVuZGluZyA9PT0gMCkge1xuICAgIHMucGVuZGluZ19vdXQgPSAwO1xuICB9XG59XG5cblxuZnVuY3Rpb24gZmx1c2hfYmxvY2tfb25seSAocywgbGFzdCkge1xuICB0cmVlcy5fdHJfZmx1c2hfYmxvY2socywgKHMuYmxvY2tfc3RhcnQgPj0gMCA/IHMuYmxvY2tfc3RhcnQgOiAtMSksIHMuc3Ryc3RhcnQgLSBzLmJsb2NrX3N0YXJ0LCBsYXN0KTtcbiAgcy5ibG9ja19zdGFydCA9IHMuc3Ryc3RhcnQ7XG4gIGZsdXNoX3BlbmRpbmcocy5zdHJtKTtcbn1cblxuXG5mdW5jdGlvbiBwdXRfYnl0ZShzLCBiKSB7XG4gIHMucGVuZGluZ19idWZbcy5wZW5kaW5nKytdID0gYjtcbn1cblxuXG4vKiA9PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09XG4gKiBQdXQgYSBzaG9ydCBpbiB0aGUgcGVuZGluZyBidWZmZXIuIFRoZSAxNi1iaXQgdmFsdWUgaXMgcHV0IGluIE1TQiBvcmRlci5cbiAqIElOIGFzc2VydGlvbjogdGhlIHN0cmVhbSBzdGF0ZSBpcyBjb3JyZWN0IGFuZCB0aGVyZSBpcyBlbm91Z2ggcm9vbSBpblxuICogcGVuZGluZ19idWYuXG4gKi9cbmZ1bmN0aW9uIHB1dFNob3J0TVNCKHMsIGIpIHtcbi8vICBwdXRfYnl0ZShzLCAoQnl0ZSkoYiA+PiA4KSk7XG4vLyAgcHV0X2J5dGUocywgKEJ5dGUpKGIgJiAweGZmKSk7XG4gIHMucGVuZGluZ19idWZbcy5wZW5kaW5nKytdID0gKGIgPj4+IDgpICYgMHhmZjtcbiAgcy5wZW5kaW5nX2J1ZltzLnBlbmRpbmcrK10gPSBiICYgMHhmZjtcbn1cblxuXG4vKiA9PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT1cbiAqIFJlYWQgYSBuZXcgYnVmZmVyIGZyb20gdGhlIGN1cnJlbnQgaW5wdXQgc3RyZWFtLCB1cGRhdGUgdGhlIGFkbGVyMzJcbiAqIGFuZCB0b3RhbCBudW1iZXIgb2YgYnl0ZXMgcmVhZC4gIEFsbCBkZWZsYXRlKCkgaW5wdXQgZ29lcyB0aHJvdWdoXG4gKiB0aGlzIGZ1bmN0aW9uIHNvIHNvbWUgYXBwbGljYXRpb25zIG1heSB3aXNoIHRvIG1vZGlmeSBpdCB0byBhdm9pZFxuICogYWxsb2NhdGluZyBhIGxhcmdlIHN0cm0tPmlucHV0IGJ1ZmZlciBhbmQgY29weWluZyBmcm9tIGl0LlxuICogKFNlZSBhbHNvIGZsdXNoX3BlbmRpbmcoKSkuXG4gKi9cbmZ1bmN0aW9uIHJlYWRfYnVmKHN0cm0sIGJ1Ziwgc3RhcnQsIHNpemUpIHtcbiAgdmFyIGxlbiA9IHN0cm0uYXZhaWxfaW47XG5cbiAgaWYgKGxlbiA+IHNpemUpIHsgbGVuID0gc2l6ZTsgfVxuICBpZiAobGVuID09PSAwKSB7IHJldHVybiAwOyB9XG5cbiAgc3RybS5hdmFpbF9pbiAtPSBsZW47XG5cbiAgdXRpbHMuYXJyYXlTZXQoYnVmLCBzdHJtLmlucHV0LCBzdHJtLm5leHRfaW4sIGxlbiwgc3RhcnQpO1xuICBpZiAoc3RybS5zdGF0ZS53cmFwID09PSAxKSB7XG4gICAgc3RybS5hZGxlciA9IGFkbGVyMzIoc3RybS5hZGxlciwgYnVmLCBsZW4sIHN0YXJ0KTtcbiAgfVxuXG4gIGVsc2UgaWYgKHN0cm0uc3RhdGUud3JhcCA9PT0gMikge1xuICAgIHN0cm0uYWRsZXIgPSBjcmMzMihzdHJtLmFkbGVyLCBidWYsIGxlbiwgc3RhcnQpO1xuICB9XG5cbiAgc3RybS5uZXh0X2luICs9IGxlbjtcbiAgc3RybS50b3RhbF9pbiArPSBsZW47XG5cbiAgcmV0dXJuIGxlbjtcbn1cblxuXG4vKiA9PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT1cbiAqIFNldCBtYXRjaF9zdGFydCB0byB0aGUgbG9uZ2VzdCBtYXRjaCBzdGFydGluZyBhdCB0aGUgZ2l2ZW4gc3RyaW5nIGFuZFxuICogcmV0dXJuIGl0cyBsZW5ndGguIE1hdGNoZXMgc2hvcnRlciBvciBlcXVhbCB0byBwcmV2X2xlbmd0aCBhcmUgZGlzY2FyZGVkLFxuICogaW4gd2hpY2ggY2FzZSB0aGUgcmVzdWx0IGlzIGVxdWFsIHRvIHByZXZfbGVuZ3RoIGFuZCBtYXRjaF9zdGFydCBpc1xuICogZ2FyYmFnZS5cbiAqIElOIGFzc2VydGlvbnM6IGN1cl9tYXRjaCBpcyB0aGUgaGVhZCBvZiB0aGUgaGFzaCBjaGFpbiBmb3IgdGhlIGN1cnJlbnRcbiAqICAgc3RyaW5nIChzdHJzdGFydCkgYW5kIGl0cyBkaXN0YW5jZSBpcyA8PSBNQVhfRElTVCwgYW5kIHByZXZfbGVuZ3RoID49IDFcbiAqIE9VVCBhc3NlcnRpb246IHRoZSBtYXRjaCBsZW5ndGggaXMgbm90IGdyZWF0ZXIgdGhhbiBzLT5sb29rYWhlYWQuXG4gKi9cbmZ1bmN0aW9uIGxvbmdlc3RfbWF0Y2gocywgY3VyX21hdGNoKSB7XG4gIHZhciBjaGFpbl9sZW5ndGggPSBzLm1heF9jaGFpbl9sZW5ndGg7ICAgICAgLyogbWF4IGhhc2ggY2hhaW4gbGVuZ3RoICovXG4gIHZhciBzY2FuID0gcy5zdHJzdGFydDsgLyogY3VycmVudCBzdHJpbmcgKi9cbiAgdmFyIG1hdGNoOyAgICAgICAgICAgICAgICAgICAgICAgLyogbWF0Y2hlZCBzdHJpbmcgKi9cbiAgdmFyIGxlbjsgICAgICAgICAgICAgICAgICAgICAgICAgICAvKiBsZW5ndGggb2YgY3VycmVudCBtYXRjaCAqL1xuICB2YXIgYmVzdF9sZW4gPSBzLnByZXZfbGVuZ3RoOyAgICAgICAgICAgICAgLyogYmVzdCBtYXRjaCBsZW5ndGggc28gZmFyICovXG4gIHZhciBuaWNlX21hdGNoID0gcy5uaWNlX21hdGNoOyAgICAgICAgICAgICAvKiBzdG9wIGlmIG1hdGNoIGxvbmcgZW5vdWdoICovXG4gIHZhciBsaW1pdCA9IChzLnN0cnN0YXJ0ID4gKHMud19zaXplIC0gTUlOX0xPT0tBSEVBRCkpID9cbiAgICAgIHMuc3Ryc3RhcnQgLSAocy53X3NpemUgLSBNSU5fTE9PS0FIRUFEKSA6IDAvKk5JTCovO1xuXG4gIHZhciBfd2luID0gcy53aW5kb3c7IC8vIHNob3J0Y3V0XG5cbiAgdmFyIHdtYXNrID0gcy53X21hc2s7XG4gIHZhciBwcmV2ICA9IHMucHJldjtcblxuICAvKiBTdG9wIHdoZW4gY3VyX21hdGNoIGJlY29tZXMgPD0gbGltaXQuIFRvIHNpbXBsaWZ5IHRoZSBjb2RlLFxuICAgKiB3ZSBwcmV2ZW50IG1hdGNoZXMgd2l0aCB0aGUgc3RyaW5nIG9mIHdpbmRvdyBpbmRleCAwLlxuICAgKi9cblxuICB2YXIgc3RyZW5kID0gcy5zdHJzdGFydCArIE1BWF9NQVRDSDtcbiAgdmFyIHNjYW5fZW5kMSAgPSBfd2luW3NjYW4gKyBiZXN0X2xlbiAtIDFdO1xuICB2YXIgc2Nhbl9lbmQgICA9IF93aW5bc2NhbiArIGJlc3RfbGVuXTtcblxuICAvKiBUaGUgY29kZSBpcyBvcHRpbWl6ZWQgZm9yIEhBU0hfQklUUyA+PSA4IGFuZCBNQVhfTUFUQ0gtMiBtdWx0aXBsZSBvZiAxNi5cbiAgICogSXQgaXMgZWFzeSB0byBnZXQgcmlkIG9mIHRoaXMgb3B0aW1pemF0aW9uIGlmIG5lY2Vzc2FyeS5cbiAgICovXG4gIC8vIEFzc2VydChzLT5oYXNoX2JpdHMgPj0gOCAmJiBNQVhfTUFUQ0ggPT0gMjU4LCBcIkNvZGUgdG9vIGNsZXZlclwiKTtcblxuICAvKiBEbyBub3Qgd2FzdGUgdG9vIG11Y2ggdGltZSBpZiB3ZSBhbHJlYWR5IGhhdmUgYSBnb29kIG1hdGNoOiAqL1xuICBpZiAocy5wcmV2X2xlbmd0aCA+PSBzLmdvb2RfbWF0Y2gpIHtcbiAgICBjaGFpbl9sZW5ndGggPj49IDI7XG4gIH1cbiAgLyogRG8gbm90IGxvb2sgZm9yIG1hdGNoZXMgYmV5b25kIHRoZSBlbmQgb2YgdGhlIGlucHV0LiBUaGlzIGlzIG5lY2Vzc2FyeVxuICAgKiB0byBtYWtlIGRlZmxhdGUgZGV0ZXJtaW5pc3RpYy5cbiAgICovXG4gIGlmIChuaWNlX21hdGNoID4gcy5sb29rYWhlYWQpIHsgbmljZV9tYXRjaCA9IHMubG9va2FoZWFkOyB9XG5cbiAgLy8gQXNzZXJ0KCh1bGcpcy0+c3Ryc3RhcnQgPD0gcy0+d2luZG93X3NpemUtTUlOX0xPT0tBSEVBRCwgXCJuZWVkIGxvb2thaGVhZFwiKTtcblxuICBkbyB7XG4gICAgLy8gQXNzZXJ0KGN1cl9tYXRjaCA8IHMtPnN0cnN0YXJ0LCBcIm5vIGZ1dHVyZVwiKTtcbiAgICBtYXRjaCA9IGN1cl9tYXRjaDtcblxuICAgIC8qIFNraXAgdG8gbmV4dCBtYXRjaCBpZiB0aGUgbWF0Y2ggbGVuZ3RoIGNhbm5vdCBpbmNyZWFzZVxuICAgICAqIG9yIGlmIHRoZSBtYXRjaCBsZW5ndGggaXMgbGVzcyB0aGFuIDIuICBOb3RlIHRoYXQgdGhlIGNoZWNrcyBiZWxvd1xuICAgICAqIGZvciBpbnN1ZmZpY2llbnQgbG9va2FoZWFkIG9ubHkgb2NjdXIgb2NjYXNpb25hbGx5IGZvciBwZXJmb3JtYW5jZVxuICAgICAqIHJlYXNvbnMuICBUaGVyZWZvcmUgdW5pbml0aWFsaXplZCBtZW1vcnkgd2lsbCBiZSBhY2Nlc3NlZCwgYW5kXG4gICAgICogY29uZGl0aW9uYWwganVtcHMgd2lsbCBiZSBtYWRlIHRoYXQgZGVwZW5kIG9uIHRob3NlIHZhbHVlcy5cbiAgICAgKiBIb3dldmVyIHRoZSBsZW5ndGggb2YgdGhlIG1hdGNoIGlzIGxpbWl0ZWQgdG8gdGhlIGxvb2thaGVhZCwgc29cbiAgICAgKiB0aGUgb3V0cHV0IG9mIGRlZmxhdGUgaXMgbm90IGFmZmVjdGVkIGJ5IHRoZSB1bmluaXRpYWxpemVkIHZhbHVlcy5cbiAgICAgKi9cblxuICAgIGlmIChfd2luW21hdGNoICsgYmVzdF9sZW5dICAgICAhPT0gc2Nhbl9lbmQgIHx8XG4gICAgICAgIF93aW5bbWF0Y2ggKyBiZXN0X2xlbiAtIDFdICE9PSBzY2FuX2VuZDEgfHxcbiAgICAgICAgX3dpblttYXRjaF0gICAgICAgICAgICAgICAgIT09IF93aW5bc2Nhbl0gfHxcbiAgICAgICAgX3dpblsrK21hdGNoXSAgICAgICAgICAgICAgIT09IF93aW5bc2NhbiArIDFdKSB7XG4gICAgICBjb250aW51ZTtcbiAgICB9XG5cbiAgICAvKiBUaGUgY2hlY2sgYXQgYmVzdF9sZW4tMSBjYW4gYmUgcmVtb3ZlZCBiZWNhdXNlIGl0IHdpbGwgYmUgbWFkZVxuICAgICAqIGFnYWluIGxhdGVyLiAoVGhpcyBoZXVyaXN0aWMgaXMgbm90IGFsd2F5cyBhIHdpbi4pXG4gICAgICogSXQgaXMgbm90IG5lY2Vzc2FyeSB0byBjb21wYXJlIHNjYW5bMl0gYW5kIG1hdGNoWzJdIHNpbmNlIHRoZXlcbiAgICAgKiBhcmUgYWx3YXlzIGVxdWFsIHdoZW4gdGhlIG90aGVyIGJ5dGVzIG1hdGNoLCBnaXZlbiB0aGF0XG4gICAgICogdGhlIGhhc2gga2V5cyBhcmUgZXF1YWwgYW5kIHRoYXQgSEFTSF9CSVRTID49IDguXG4gICAgICovXG4gICAgc2NhbiArPSAyO1xuICAgIG1hdGNoKys7XG4gICAgLy8gQXNzZXJ0KCpzY2FuID09ICptYXRjaCwgXCJtYXRjaFsyXT9cIik7XG5cbiAgICAvKiBXZSBjaGVjayBmb3IgaW5zdWZmaWNpZW50IGxvb2thaGVhZCBvbmx5IGV2ZXJ5IDh0aCBjb21wYXJpc29uO1xuICAgICAqIHRoZSAyNTZ0aCBjaGVjayB3aWxsIGJlIG1hZGUgYXQgc3Ryc3RhcnQrMjU4LlxuICAgICAqL1xuICAgIGRvIHtcbiAgICAgIC8qanNoaW50IG5vZW1wdHk6ZmFsc2UqL1xuICAgIH0gd2hpbGUgKF93aW5bKytzY2FuXSA9PT0gX3dpblsrK21hdGNoXSAmJiBfd2luWysrc2Nhbl0gPT09IF93aW5bKyttYXRjaF0gJiZcbiAgICAgICAgICAgICBfd2luWysrc2Nhbl0gPT09IF93aW5bKyttYXRjaF0gJiYgX3dpblsrK3NjYW5dID09PSBfd2luWysrbWF0Y2hdICYmXG4gICAgICAgICAgICAgX3dpblsrK3NjYW5dID09PSBfd2luWysrbWF0Y2hdICYmIF93aW5bKytzY2FuXSA9PT0gX3dpblsrK21hdGNoXSAmJlxuICAgICAgICAgICAgIF93aW5bKytzY2FuXSA9PT0gX3dpblsrK21hdGNoXSAmJiBfd2luWysrc2Nhbl0gPT09IF93aW5bKyttYXRjaF0gJiZcbiAgICAgICAgICAgICBzY2FuIDwgc3RyZW5kKTtcblxuICAgIC8vIEFzc2VydChzY2FuIDw9IHMtPndpbmRvdysodW5zaWduZWQpKHMtPndpbmRvd19zaXplLTEpLCBcIndpbGQgc2NhblwiKTtcblxuICAgIGxlbiA9IE1BWF9NQVRDSCAtIChzdHJlbmQgLSBzY2FuKTtcbiAgICBzY2FuID0gc3RyZW5kIC0gTUFYX01BVENIO1xuXG4gICAgaWYgKGxlbiA+IGJlc3RfbGVuKSB7XG4gICAgICBzLm1hdGNoX3N0YXJ0ID0gY3VyX21hdGNoO1xuICAgICAgYmVzdF9sZW4gPSBsZW47XG4gICAgICBpZiAobGVuID49IG5pY2VfbWF0Y2gpIHtcbiAgICAgICAgYnJlYWs7XG4gICAgICB9XG4gICAgICBzY2FuX2VuZDEgID0gX3dpbltzY2FuICsgYmVzdF9sZW4gLSAxXTtcbiAgICAgIHNjYW5fZW5kICAgPSBfd2luW3NjYW4gKyBiZXN0X2xlbl07XG4gICAgfVxuICB9IHdoaWxlICgoY3VyX21hdGNoID0gcHJldltjdXJfbWF0Y2ggJiB3bWFza10pID4gbGltaXQgJiYgLS1jaGFpbl9sZW5ndGggIT09IDApO1xuXG4gIGlmIChiZXN0X2xlbiA8PSBzLmxvb2thaGVhZCkge1xuICAgIHJldHVybiBiZXN0X2xlbjtcbiAgfVxuICByZXR1cm4gcy5sb29rYWhlYWQ7XG59XG5cblxuLyogPT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09XG4gKiBGaWxsIHRoZSB3aW5kb3cgd2hlbiB0aGUgbG9va2FoZWFkIGJlY29tZXMgaW5zdWZmaWNpZW50LlxuICogVXBkYXRlcyBzdHJzdGFydCBhbmQgbG9va2FoZWFkLlxuICpcbiAqIElOIGFzc2VydGlvbjogbG9va2FoZWFkIDwgTUlOX0xPT0tBSEVBRFxuICogT1VUIGFzc2VydGlvbnM6IHN0cnN0YXJ0IDw9IHdpbmRvd19zaXplLU1JTl9MT09LQUhFQURcbiAqICAgIEF0IGxlYXN0IG9uZSBieXRlIGhhcyBiZWVuIHJlYWQsIG9yIGF2YWlsX2luID09IDA7IHJlYWRzIGFyZVxuICogICAgcGVyZm9ybWVkIGZvciBhdCBsZWFzdCB0d28gYnl0ZXMgKHJlcXVpcmVkIGZvciB0aGUgemlwIHRyYW5zbGF0ZV9lb2xcbiAqICAgIG9wdGlvbiAtLSBub3Qgc3VwcG9ydGVkIGhlcmUpLlxuICovXG5mdW5jdGlvbiBmaWxsX3dpbmRvdyhzKSB7XG4gIHZhciBfd19zaXplID0gcy53X3NpemU7XG4gIHZhciBwLCBuLCBtLCBtb3JlLCBzdHI7XG5cbiAgLy9Bc3NlcnQocy0+bG9va2FoZWFkIDwgTUlOX0xPT0tBSEVBRCwgXCJhbHJlYWR5IGVub3VnaCBsb29rYWhlYWRcIik7XG5cbiAgZG8ge1xuICAgIG1vcmUgPSBzLndpbmRvd19zaXplIC0gcy5sb29rYWhlYWQgLSBzLnN0cnN0YXJ0O1xuXG4gICAgLy8gSlMgaW50cyBoYXZlIDMyIGJpdCwgYmxvY2sgYmVsb3cgbm90IG5lZWRlZFxuICAgIC8qIERlYWwgd2l0aCAhQCMkJSA2NEsgbGltaXQ6ICovXG4gICAgLy9pZiAoc2l6ZW9mKGludCkgPD0gMikge1xuICAgIC8vICAgIGlmIChtb3JlID09IDAgJiYgcy0+c3Ryc3RhcnQgPT0gMCAmJiBzLT5sb29rYWhlYWQgPT0gMCkge1xuICAgIC8vICAgICAgICBtb3JlID0gd3NpemU7XG4gICAgLy9cbiAgICAvLyAgfSBlbHNlIGlmIChtb3JlID09ICh1bnNpZ25lZCkoLTEpKSB7XG4gICAgLy8gICAgICAgIC8qIFZlcnkgdW5saWtlbHksIGJ1dCBwb3NzaWJsZSBvbiAxNiBiaXQgbWFjaGluZSBpZlxuICAgIC8vICAgICAgICAgKiBzdHJzdGFydCA9PSAwICYmIGxvb2thaGVhZCA9PSAxIChpbnB1dCBkb25lIGEgYnl0ZSBhdCB0aW1lKVxuICAgIC8vICAgICAgICAgKi9cbiAgICAvLyAgICAgICAgbW9yZS0tO1xuICAgIC8vICAgIH1cbiAgICAvL31cblxuXG4gICAgLyogSWYgdGhlIHdpbmRvdyBpcyBhbG1vc3QgZnVsbCBhbmQgdGhlcmUgaXMgaW5zdWZmaWNpZW50IGxvb2thaGVhZCxcbiAgICAgKiBtb3ZlIHRoZSB1cHBlciBoYWxmIHRvIHRoZSBsb3dlciBvbmUgdG8gbWFrZSByb29tIGluIHRoZSB1cHBlciBoYWxmLlxuICAgICAqL1xuICAgIGlmIChzLnN0cnN0YXJ0ID49IF93X3NpemUgKyAoX3dfc2l6ZSAtIE1JTl9MT09LQUhFQUQpKSB7XG5cbiAgICAgIHV0aWxzLmFycmF5U2V0KHMud2luZG93LCBzLndpbmRvdywgX3dfc2l6ZSwgX3dfc2l6ZSwgMCk7XG4gICAgICBzLm1hdGNoX3N0YXJ0IC09IF93X3NpemU7XG4gICAgICBzLnN0cnN0YXJ0IC09IF93X3NpemU7XG4gICAgICAvKiB3ZSBub3cgaGF2ZSBzdHJzdGFydCA+PSBNQVhfRElTVCAqL1xuICAgICAgcy5ibG9ja19zdGFydCAtPSBfd19zaXplO1xuXG4gICAgICAvKiBTbGlkZSB0aGUgaGFzaCB0YWJsZSAoY291bGQgYmUgYXZvaWRlZCB3aXRoIDMyIGJpdCB2YWx1ZXNcbiAgICAgICBhdCB0aGUgZXhwZW5zZSBvZiBtZW1vcnkgdXNhZ2UpLiBXZSBzbGlkZSBldmVuIHdoZW4gbGV2ZWwgPT0gMFxuICAgICAgIHRvIGtlZXAgdGhlIGhhc2ggdGFibGUgY29uc2lzdGVudCBpZiB3ZSBzd2l0Y2ggYmFjayB0byBsZXZlbCA+IDBcbiAgICAgICBsYXRlci4gKFVzaW5nIGxldmVsIDAgcGVybWFuZW50bHkgaXMgbm90IGFuIG9wdGltYWwgdXNhZ2Ugb2ZcbiAgICAgICB6bGliLCBzbyB3ZSBkb24ndCBjYXJlIGFib3V0IHRoaXMgcGF0aG9sb2dpY2FsIGNhc2UuKVxuICAgICAgICovXG5cbiAgICAgIG4gPSBzLmhhc2hfc2l6ZTtcbiAgICAgIHAgPSBuO1xuICAgICAgZG8ge1xuICAgICAgICBtID0gcy5oZWFkWy0tcF07XG4gICAgICAgIHMuaGVhZFtwXSA9IChtID49IF93X3NpemUgPyBtIC0gX3dfc2l6ZSA6IDApO1xuICAgICAgfSB3aGlsZSAoLS1uKTtcblxuICAgICAgbiA9IF93X3NpemU7XG4gICAgICBwID0gbjtcbiAgICAgIGRvIHtcbiAgICAgICAgbSA9IHMucHJldlstLXBdO1xuICAgICAgICBzLnByZXZbcF0gPSAobSA+PSBfd19zaXplID8gbSAtIF93X3NpemUgOiAwKTtcbiAgICAgICAgLyogSWYgbiBpcyBub3Qgb24gYW55IGhhc2ggY2hhaW4sIHByZXZbbl0gaXMgZ2FyYmFnZSBidXRcbiAgICAgICAgICogaXRzIHZhbHVlIHdpbGwgbmV2ZXIgYmUgdXNlZC5cbiAgICAgICAgICovXG4gICAgICB9IHdoaWxlICgtLW4pO1xuXG4gICAgICBtb3JlICs9IF93X3NpemU7XG4gICAgfVxuICAgIGlmIChzLnN0cm0uYXZhaWxfaW4gPT09IDApIHtcbiAgICAgIGJyZWFrO1xuICAgIH1cblxuICAgIC8qIElmIHRoZXJlIHdhcyBubyBzbGlkaW5nOlxuICAgICAqICAgIHN0cnN0YXJ0IDw9IFdTSVpFK01BWF9ESVNULTEgJiYgbG9va2FoZWFkIDw9IE1JTl9MT09LQUhFQUQgLSAxICYmXG4gICAgICogICAgbW9yZSA9PSB3aW5kb3dfc2l6ZSAtIGxvb2thaGVhZCAtIHN0cnN0YXJ0XG4gICAgICogPT4gbW9yZSA+PSB3aW5kb3dfc2l6ZSAtIChNSU5fTE9PS0FIRUFELTEgKyBXU0laRSArIE1BWF9ESVNULTEpXG4gICAgICogPT4gbW9yZSA+PSB3aW5kb3dfc2l6ZSAtIDIqV1NJWkUgKyAyXG4gICAgICogSW4gdGhlIEJJR19NRU0gb3IgTU1BUCBjYXNlIChub3QgeWV0IHN1cHBvcnRlZCksXG4gICAgICogICB3aW5kb3dfc2l6ZSA9PSBpbnB1dF9zaXplICsgTUlOX0xPT0tBSEVBRCAgJiZcbiAgICAgKiAgIHN0cnN0YXJ0ICsgcy0+bG9va2FoZWFkIDw9IGlucHV0X3NpemUgPT4gbW9yZSA+PSBNSU5fTE9PS0FIRUFELlxuICAgICAqIE90aGVyd2lzZSwgd2luZG93X3NpemUgPT0gMipXU0laRSBzbyBtb3JlID49IDIuXG4gICAgICogSWYgdGhlcmUgd2FzIHNsaWRpbmcsIG1vcmUgPj0gV1NJWkUuIFNvIGluIGFsbCBjYXNlcywgbW9yZSA+PSAyLlxuICAgICAqL1xuICAgIC8vQXNzZXJ0KG1vcmUgPj0gMiwgXCJtb3JlIDwgMlwiKTtcbiAgICBuID0gcmVhZF9idWYocy5zdHJtLCBzLndpbmRvdywgcy5zdHJzdGFydCArIHMubG9va2FoZWFkLCBtb3JlKTtcbiAgICBzLmxvb2thaGVhZCArPSBuO1xuXG4gICAgLyogSW5pdGlhbGl6ZSB0aGUgaGFzaCB2YWx1ZSBub3cgdGhhdCB3ZSBoYXZlIHNvbWUgaW5wdXQ6ICovXG4gICAgaWYgKHMubG9va2FoZWFkICsgcy5pbnNlcnQgPj0gTUlOX01BVENIKSB7XG4gICAgICBzdHIgPSBzLnN0cnN0YXJ0IC0gcy5pbnNlcnQ7XG4gICAgICBzLmluc19oID0gcy53aW5kb3dbc3RyXTtcblxuICAgICAgLyogVVBEQVRFX0hBU0gocywgcy0+aW5zX2gsIHMtPndpbmRvd1tzdHIgKyAxXSk7ICovXG4gICAgICBzLmluc19oID0gKChzLmluc19oIDw8IHMuaGFzaF9zaGlmdCkgXiBzLndpbmRvd1tzdHIgKyAxXSkgJiBzLmhhc2hfbWFzaztcbi8vI2lmIE1JTl9NQVRDSCAhPSAzXG4vLyAgICAgICAgQ2FsbCB1cGRhdGVfaGFzaCgpIE1JTl9NQVRDSC0zIG1vcmUgdGltZXNcbi8vI2VuZGlmXG4gICAgICB3aGlsZSAocy5pbnNlcnQpIHtcbiAgICAgICAgLyogVVBEQVRFX0hBU0gocywgcy0+aW5zX2gsIHMtPndpbmRvd1tzdHIgKyBNSU5fTUFUQ0gtMV0pOyAqL1xuICAgICAgICBzLmluc19oID0gKChzLmluc19oIDw8IHMuaGFzaF9zaGlmdCkgXiBzLndpbmRvd1tzdHIgKyBNSU5fTUFUQ0gtMV0pICYgcy5oYXNoX21hc2s7XG5cbiAgICAgICAgcy5wcmV2W3N0ciAmIHMud19tYXNrXSA9IHMuaGVhZFtzLmluc19oXTtcbiAgICAgICAgcy5oZWFkW3MuaW5zX2hdID0gc3RyO1xuICAgICAgICBzdHIrKztcbiAgICAgICAgcy5pbnNlcnQtLTtcbiAgICAgICAgaWYgKHMubG9va2FoZWFkICsgcy5pbnNlcnQgPCBNSU5fTUFUQ0gpIHtcbiAgICAgICAgICBicmVhaztcbiAgICAgICAgfVxuICAgICAgfVxuICAgIH1cbiAgICAvKiBJZiB0aGUgd2hvbGUgaW5wdXQgaGFzIGxlc3MgdGhhbiBNSU5fTUFUQ0ggYnl0ZXMsIGluc19oIGlzIGdhcmJhZ2UsXG4gICAgICogYnV0IHRoaXMgaXMgbm90IGltcG9ydGFudCBzaW5jZSBvbmx5IGxpdGVyYWwgYnl0ZXMgd2lsbCBiZSBlbWl0dGVkLlxuICAgICAqL1xuXG4gIH0gd2hpbGUgKHMubG9va2FoZWFkIDwgTUlOX0xPT0tBSEVBRCAmJiBzLnN0cm0uYXZhaWxfaW4gIT09IDApO1xuXG4gIC8qIElmIHRoZSBXSU5fSU5JVCBieXRlcyBhZnRlciB0aGUgZW5kIG9mIHRoZSBjdXJyZW50IGRhdGEgaGF2ZSBuZXZlciBiZWVuXG4gICAqIHdyaXR0ZW4sIHRoZW4gemVybyB0aG9zZSBieXRlcyBpbiBvcmRlciB0byBhdm9pZCBtZW1vcnkgY2hlY2sgcmVwb3J0cyBvZlxuICAgKiB0aGUgdXNlIG9mIHVuaW5pdGlhbGl6ZWQgKG9yIHVuaW5pdGlhbGlzZWQgYXMgSnVsaWFuIHdyaXRlcykgYnl0ZXMgYnlcbiAgICogdGhlIGxvbmdlc3QgbWF0Y2ggcm91dGluZXMuICBVcGRhdGUgdGhlIGhpZ2ggd2F0ZXIgbWFyayBmb3IgdGhlIG5leHRcbiAgICogdGltZSB0aHJvdWdoIGhlcmUuICBXSU5fSU5JVCBpcyBzZXQgdG8gTUFYX01BVENIIHNpbmNlIHRoZSBsb25nZXN0IG1hdGNoXG4gICAqIHJvdXRpbmVzIGFsbG93IHNjYW5uaW5nIHRvIHN0cnN0YXJ0ICsgTUFYX01BVENILCBpZ25vcmluZyBsb29rYWhlYWQuXG4gICAqL1xuLy8gIGlmIChzLmhpZ2hfd2F0ZXIgPCBzLndpbmRvd19zaXplKSB7XG4vLyAgICB2YXIgY3VyciA9IHMuc3Ryc3RhcnQgKyBzLmxvb2thaGVhZDtcbi8vICAgIHZhciBpbml0ID0gMDtcbi8vXG4vLyAgICBpZiAocy5oaWdoX3dhdGVyIDwgY3Vycikge1xuLy8gICAgICAvKiBQcmV2aW91cyBoaWdoIHdhdGVyIG1hcmsgYmVsb3cgY3VycmVudCBkYXRhIC0tIHplcm8gV0lOX0lOSVRcbi8vICAgICAgICogYnl0ZXMgb3IgdXAgdG8gZW5kIG9mIHdpbmRvdywgd2hpY2hldmVyIGlzIGxlc3MuXG4vLyAgICAgICAqL1xuLy8gICAgICBpbml0ID0gcy53aW5kb3dfc2l6ZSAtIGN1cnI7XG4vLyAgICAgIGlmIChpbml0ID4gV0lOX0lOSVQpXG4vLyAgICAgICAgaW5pdCA9IFdJTl9JTklUO1xuLy8gICAgICB6bWVtemVybyhzLT53aW5kb3cgKyBjdXJyLCAodW5zaWduZWQpaW5pdCk7XG4vLyAgICAgIHMtPmhpZ2hfd2F0ZXIgPSBjdXJyICsgaW5pdDtcbi8vICAgIH1cbi8vICAgIGVsc2UgaWYgKHMtPmhpZ2hfd2F0ZXIgPCAodWxnKWN1cnIgKyBXSU5fSU5JVCkge1xuLy8gICAgICAvKiBIaWdoIHdhdGVyIG1hcmsgYXQgb3IgYWJvdmUgY3VycmVudCBkYXRhLCBidXQgYmVsb3cgY3VycmVudCBkYXRhXG4vLyAgICAgICAqIHBsdXMgV0lOX0lOSVQgLS0gemVybyBvdXQgdG8gY3VycmVudCBkYXRhIHBsdXMgV0lOX0lOSVQsIG9yIHVwXG4vLyAgICAgICAqIHRvIGVuZCBvZiB3aW5kb3csIHdoaWNoZXZlciBpcyBsZXNzLlxuLy8gICAgICAgKi9cbi8vICAgICAgaW5pdCA9ICh1bGcpY3VyciArIFdJTl9JTklUIC0gcy0+aGlnaF93YXRlcjtcbi8vICAgICAgaWYgKGluaXQgPiBzLT53aW5kb3dfc2l6ZSAtIHMtPmhpZ2hfd2F0ZXIpXG4vLyAgICAgICAgaW5pdCA9IHMtPndpbmRvd19zaXplIC0gcy0+aGlnaF93YXRlcjtcbi8vICAgICAgem1lbXplcm8ocy0+d2luZG93ICsgcy0+aGlnaF93YXRlciwgKHVuc2lnbmVkKWluaXQpO1xuLy8gICAgICBzLT5oaWdoX3dhdGVyICs9IGluaXQ7XG4vLyAgICB9XG4vLyAgfVxuLy9cbi8vICBBc3NlcnQoKHVsZylzLT5zdHJzdGFydCA8PSBzLT53aW5kb3dfc2l6ZSAtIE1JTl9MT09LQUhFQUQsXG4vLyAgICBcIm5vdCBlbm91Z2ggcm9vbSBmb3Igc2VhcmNoXCIpO1xufVxuXG4vKiA9PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT1cbiAqIENvcHkgd2l0aG91dCBjb21wcmVzc2lvbiBhcyBtdWNoIGFzIHBvc3NpYmxlIGZyb20gdGhlIGlucHV0IHN0cmVhbSwgcmV0dXJuXG4gKiB0aGUgY3VycmVudCBibG9jayBzdGF0ZS5cbiAqIFRoaXMgZnVuY3Rpb24gZG9lcyBub3QgaW5zZXJ0IG5ldyBzdHJpbmdzIGluIHRoZSBkaWN0aW9uYXJ5IHNpbmNlXG4gKiB1bmNvbXByZXNzaWJsZSBkYXRhIGlzIHByb2JhYmx5IG5vdCB1c2VmdWwuIFRoaXMgZnVuY3Rpb24gaXMgdXNlZFxuICogb25seSBmb3IgdGhlIGxldmVsPTAgY29tcHJlc3Npb24gb3B0aW9uLlxuICogTk9URTogdGhpcyBmdW5jdGlvbiBzaG91bGQgYmUgb3B0aW1pemVkIHRvIGF2b2lkIGV4dHJhIGNvcHlpbmcgZnJvbVxuICogd2luZG93IHRvIHBlbmRpbmdfYnVmLlxuICovXG5mdW5jdGlvbiBkZWZsYXRlX3N0b3JlZChzLCBmbHVzaCkge1xuICAvKiBTdG9yZWQgYmxvY2tzIGFyZSBsaW1pdGVkIHRvIDB4ZmZmZiBieXRlcywgcGVuZGluZ19idWYgaXMgbGltaXRlZFxuICAgKiB0byBwZW5kaW5nX2J1Zl9zaXplLCBhbmQgZWFjaCBzdG9yZWQgYmxvY2sgaGFzIGEgNSBieXRlIGhlYWRlcjpcbiAgICovXG4gIHZhciBtYXhfYmxvY2tfc2l6ZSA9IDB4ZmZmZjtcblxuICBpZiAobWF4X2Jsb2NrX3NpemUgPiBzLnBlbmRpbmdfYnVmX3NpemUgLSA1KSB7XG4gICAgbWF4X2Jsb2NrX3NpemUgPSBzLnBlbmRpbmdfYnVmX3NpemUgLSA1O1xuICB9XG5cbiAgLyogQ29weSBhcyBtdWNoIGFzIHBvc3NpYmxlIGZyb20gaW5wdXQgdG8gb3V0cHV0OiAqL1xuICBmb3IgKDs7KSB7XG4gICAgLyogRmlsbCB0aGUgd2luZG93IGFzIG11Y2ggYXMgcG9zc2libGU6ICovXG4gICAgaWYgKHMubG9va2FoZWFkIDw9IDEpIHtcblxuICAgICAgLy9Bc3NlcnQocy0+c3Ryc3RhcnQgPCBzLT53X3NpemUrTUFYX0RJU1QocykgfHxcbiAgICAgIC8vICBzLT5ibG9ja19zdGFydCA+PSAobG9uZylzLT53X3NpemUsIFwic2xpZGUgdG9vIGxhdGVcIik7XG4vLyAgICAgIGlmICghKHMuc3Ryc3RhcnQgPCBzLndfc2l6ZSArIChzLndfc2l6ZSAtIE1JTl9MT09LQUhFQUQpIHx8XG4vLyAgICAgICAgcy5ibG9ja19zdGFydCA+PSBzLndfc2l6ZSkpIHtcbi8vICAgICAgICB0aHJvdyAgbmV3IEVycm9yKFwic2xpZGUgdG9vIGxhdGVcIik7XG4vLyAgICAgIH1cblxuICAgICAgZmlsbF93aW5kb3cocyk7XG4gICAgICBpZiAocy5sb29rYWhlYWQgPT09IDAgJiYgZmx1c2ggPT09IFpfTk9fRkxVU0gpIHtcbiAgICAgICAgcmV0dXJuIEJTX05FRURfTU9SRTtcbiAgICAgIH1cblxuICAgICAgaWYgKHMubG9va2FoZWFkID09PSAwKSB7XG4gICAgICAgIGJyZWFrO1xuICAgICAgfVxuICAgICAgLyogZmx1c2ggdGhlIGN1cnJlbnQgYmxvY2sgKi9cbiAgICB9XG4gICAgLy9Bc3NlcnQocy0+YmxvY2tfc3RhcnQgPj0gMEwsIFwiYmxvY2sgZ29uZVwiKTtcbi8vICAgIGlmIChzLmJsb2NrX3N0YXJ0IDwgMCkgdGhyb3cgbmV3IEVycm9yKFwiYmxvY2sgZ29uZVwiKTtcblxuICAgIHMuc3Ryc3RhcnQgKz0gcy5sb29rYWhlYWQ7XG4gICAgcy5sb29rYWhlYWQgPSAwO1xuXG4gICAgLyogRW1pdCBhIHN0b3JlZCBibG9jayBpZiBwZW5kaW5nX2J1ZiB3aWxsIGJlIGZ1bGw6ICovXG4gICAgdmFyIG1heF9zdGFydCA9IHMuYmxvY2tfc3RhcnQgKyBtYXhfYmxvY2tfc2l6ZTtcblxuICAgIGlmIChzLnN0cnN0YXJ0ID09PSAwIHx8IHMuc3Ryc3RhcnQgPj0gbWF4X3N0YXJ0KSB7XG4gICAgICAvKiBzdHJzdGFydCA9PSAwIGlzIHBvc3NpYmxlIHdoZW4gd3JhcGFyb3VuZCBvbiAxNi1iaXQgbWFjaGluZSAqL1xuICAgICAgcy5sb29rYWhlYWQgPSBzLnN0cnN0YXJ0IC0gbWF4X3N0YXJ0O1xuICAgICAgcy5zdHJzdGFydCA9IG1heF9zdGFydDtcbiAgICAgIC8qKiogRkxVU0hfQkxPQ0socywgMCk7ICoqKi9cbiAgICAgIGZsdXNoX2Jsb2NrX29ubHkocywgZmFsc2UpO1xuICAgICAgaWYgKHMuc3RybS5hdmFpbF9vdXQgPT09IDApIHtcbiAgICAgICAgcmV0dXJuIEJTX05FRURfTU9SRTtcbiAgICAgIH1cbiAgICAgIC8qKiovXG5cblxuICAgIH1cbiAgICAvKiBGbHVzaCBpZiB3ZSBtYXkgaGF2ZSB0byBzbGlkZSwgb3RoZXJ3aXNlIGJsb2NrX3N0YXJ0IG1heSBiZWNvbWVcbiAgICAgKiBuZWdhdGl2ZSBhbmQgdGhlIGRhdGEgd2lsbCBiZSBnb25lOlxuICAgICAqL1xuICAgIGlmIChzLnN0cnN0YXJ0IC0gcy5ibG9ja19zdGFydCA+PSAocy53X3NpemUgLSBNSU5fTE9PS0FIRUFEKSkge1xuICAgICAgLyoqKiBGTFVTSF9CTE9DSyhzLCAwKTsgKioqL1xuICAgICAgZmx1c2hfYmxvY2tfb25seShzLCBmYWxzZSk7XG4gICAgICBpZiAocy5zdHJtLmF2YWlsX291dCA9PT0gMCkge1xuICAgICAgICByZXR1cm4gQlNfTkVFRF9NT1JFO1xuICAgICAgfVxuICAgICAgLyoqKi9cbiAgICB9XG4gIH1cblxuICBzLmluc2VydCA9IDA7XG5cbiAgaWYgKGZsdXNoID09PSBaX0ZJTklTSCkge1xuICAgIC8qKiogRkxVU0hfQkxPQ0socywgMSk7ICoqKi9cbiAgICBmbHVzaF9ibG9ja19vbmx5KHMsIHRydWUpO1xuICAgIGlmIChzLnN0cm0uYXZhaWxfb3V0ID09PSAwKSB7XG4gICAgICByZXR1cm4gQlNfRklOSVNIX1NUQVJURUQ7XG4gICAgfVxuICAgIC8qKiovXG4gICAgcmV0dXJuIEJTX0ZJTklTSF9ET05FO1xuICB9XG5cbiAgaWYgKHMuc3Ryc3RhcnQgPiBzLmJsb2NrX3N0YXJ0KSB7XG4gICAgLyoqKiBGTFVTSF9CTE9DSyhzLCAwKTsgKioqL1xuICAgIGZsdXNoX2Jsb2NrX29ubHkocywgZmFsc2UpO1xuICAgIGlmIChzLnN0cm0uYXZhaWxfb3V0ID09PSAwKSB7XG4gICAgICByZXR1cm4gQlNfTkVFRF9NT1JFO1xuICAgIH1cbiAgICAvKioqL1xuICB9XG5cbiAgcmV0dXJuIEJTX05FRURfTU9SRTtcbn1cblxuLyogPT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09XG4gKiBDb21wcmVzcyBhcyBtdWNoIGFzIHBvc3NpYmxlIGZyb20gdGhlIGlucHV0IHN0cmVhbSwgcmV0dXJuIHRoZSBjdXJyZW50XG4gKiBibG9jayBzdGF0ZS5cbiAqIFRoaXMgZnVuY3Rpb24gZG9lcyBub3QgcGVyZm9ybSBsYXp5IGV2YWx1YXRpb24gb2YgbWF0Y2hlcyBhbmQgaW5zZXJ0c1xuICogbmV3IHN0cmluZ3MgaW4gdGhlIGRpY3Rpb25hcnkgb25seSBmb3IgdW5tYXRjaGVkIHN0cmluZ3Mgb3IgZm9yIHNob3J0XG4gKiBtYXRjaGVzLiBJdCBpcyB1c2VkIG9ubHkgZm9yIHRoZSBmYXN0IGNvbXByZXNzaW9uIG9wdGlvbnMuXG4gKi9cbmZ1bmN0aW9uIGRlZmxhdGVfZmFzdChzLCBmbHVzaCkge1xuICB2YXIgaGFzaF9oZWFkOyAgICAgICAgLyogaGVhZCBvZiB0aGUgaGFzaCBjaGFpbiAqL1xuICB2YXIgYmZsdXNoOyAgICAgICAgICAgLyogc2V0IGlmIGN1cnJlbnQgYmxvY2sgbXVzdCBiZSBmbHVzaGVkICovXG5cbiAgZm9yICg7Oykge1xuICAgIC8qIE1ha2Ugc3VyZSB0aGF0IHdlIGFsd2F5cyBoYXZlIGVub3VnaCBsb29rYWhlYWQsIGV4Y2VwdFxuICAgICAqIGF0IHRoZSBlbmQgb2YgdGhlIGlucHV0IGZpbGUuIFdlIG5lZWQgTUFYX01BVENIIGJ5dGVzXG4gICAgICogZm9yIHRoZSBuZXh0IG1hdGNoLCBwbHVzIE1JTl9NQVRDSCBieXRlcyB0byBpbnNlcnQgdGhlXG4gICAgICogc3RyaW5nIGZvbGxvd2luZyB0aGUgbmV4dCBtYXRjaC5cbiAgICAgKi9cbiAgICBpZiAocy5sb29rYWhlYWQgPCBNSU5fTE9PS0FIRUFEKSB7XG4gICAgICBmaWxsX3dpbmRvdyhzKTtcbiAgICAgIGlmIChzLmxvb2thaGVhZCA8IE1JTl9MT09LQUhFQUQgJiYgZmx1c2ggPT09IFpfTk9fRkxVU0gpIHtcbiAgICAgICAgcmV0dXJuIEJTX05FRURfTU9SRTtcbiAgICAgIH1cbiAgICAgIGlmIChzLmxvb2thaGVhZCA9PT0gMCkge1xuICAgICAgICBicmVhazsgLyogZmx1c2ggdGhlIGN1cnJlbnQgYmxvY2sgKi9cbiAgICAgIH1cbiAgICB9XG5cbiAgICAvKiBJbnNlcnQgdGhlIHN0cmluZyB3aW5kb3dbc3Ryc3RhcnQgLi4gc3Ryc3RhcnQrMl0gaW4gdGhlXG4gICAgICogZGljdGlvbmFyeSwgYW5kIHNldCBoYXNoX2hlYWQgdG8gdGhlIGhlYWQgb2YgdGhlIGhhc2ggY2hhaW46XG4gICAgICovXG4gICAgaGFzaF9oZWFkID0gMC8qTklMKi87XG4gICAgaWYgKHMubG9va2FoZWFkID49IE1JTl9NQVRDSCkge1xuICAgICAgLyoqKiBJTlNFUlRfU1RSSU5HKHMsIHMuc3Ryc3RhcnQsIGhhc2hfaGVhZCk7ICoqKi9cbiAgICAgIHMuaW5zX2ggPSAoKHMuaW5zX2ggPDwgcy5oYXNoX3NoaWZ0KSBeIHMud2luZG93W3Muc3Ryc3RhcnQgKyBNSU5fTUFUQ0ggLSAxXSkgJiBzLmhhc2hfbWFzaztcbiAgICAgIGhhc2hfaGVhZCA9IHMucHJldltzLnN0cnN0YXJ0ICYgcy53X21hc2tdID0gcy5oZWFkW3MuaW5zX2hdO1xuICAgICAgcy5oZWFkW3MuaW5zX2hdID0gcy5zdHJzdGFydDtcbiAgICAgIC8qKiovXG4gICAgfVxuXG4gICAgLyogRmluZCB0aGUgbG9uZ2VzdCBtYXRjaCwgZGlzY2FyZGluZyB0aG9zZSA8PSBwcmV2X2xlbmd0aC5cbiAgICAgKiBBdCB0aGlzIHBvaW50IHdlIGhhdmUgYWx3YXlzIG1hdGNoX2xlbmd0aCA8IE1JTl9NQVRDSFxuICAgICAqL1xuICAgIGlmIChoYXNoX2hlYWQgIT09IDAvKk5JTCovICYmICgocy5zdHJzdGFydCAtIGhhc2hfaGVhZCkgPD0gKHMud19zaXplIC0gTUlOX0xPT0tBSEVBRCkpKSB7XG4gICAgICAvKiBUbyBzaW1wbGlmeSB0aGUgY29kZSwgd2UgcHJldmVudCBtYXRjaGVzIHdpdGggdGhlIHN0cmluZ1xuICAgICAgICogb2Ygd2luZG93IGluZGV4IDAgKGluIHBhcnRpY3VsYXIgd2UgaGF2ZSB0byBhdm9pZCBhIG1hdGNoXG4gICAgICAgKiBvZiB0aGUgc3RyaW5nIHdpdGggaXRzZWxmIGF0IHRoZSBzdGFydCBvZiB0aGUgaW5wdXQgZmlsZSkuXG4gICAgICAgKi9cbiAgICAgIHMubWF0Y2hfbGVuZ3RoID0gbG9uZ2VzdF9tYXRjaChzLCBoYXNoX2hlYWQpO1xuICAgICAgLyogbG9uZ2VzdF9tYXRjaCgpIHNldHMgbWF0Y2hfc3RhcnQgKi9cbiAgICB9XG4gICAgaWYgKHMubWF0Y2hfbGVuZ3RoID49IE1JTl9NQVRDSCkge1xuICAgICAgLy8gY2hlY2tfbWF0Y2gocywgcy5zdHJzdGFydCwgcy5tYXRjaF9zdGFydCwgcy5tYXRjaF9sZW5ndGgpOyAvLyBmb3IgZGVidWcgb25seVxuXG4gICAgICAvKioqIF90cl90YWxseV9kaXN0KHMsIHMuc3Ryc3RhcnQgLSBzLm1hdGNoX3N0YXJ0LFxuICAgICAgICAgICAgICAgICAgICAgcy5tYXRjaF9sZW5ndGggLSBNSU5fTUFUQ0gsIGJmbHVzaCk7ICoqKi9cbiAgICAgIGJmbHVzaCA9IHRyZWVzLl90cl90YWxseShzLCBzLnN0cnN0YXJ0IC0gcy5tYXRjaF9zdGFydCwgcy5tYXRjaF9sZW5ndGggLSBNSU5fTUFUQ0gpO1xuXG4gICAgICBzLmxvb2thaGVhZCAtPSBzLm1hdGNoX2xlbmd0aDtcblxuICAgICAgLyogSW5zZXJ0IG5ldyBzdHJpbmdzIGluIHRoZSBoYXNoIHRhYmxlIG9ubHkgaWYgdGhlIG1hdGNoIGxlbmd0aFxuICAgICAgICogaXMgbm90IHRvbyBsYXJnZS4gVGhpcyBzYXZlcyB0aW1lIGJ1dCBkZWdyYWRlcyBjb21wcmVzc2lvbi5cbiAgICAgICAqL1xuICAgICAgaWYgKHMubWF0Y2hfbGVuZ3RoIDw9IHMubWF4X2xhenlfbWF0Y2gvKm1heF9pbnNlcnRfbGVuZ3RoKi8gJiYgcy5sb29rYWhlYWQgPj0gTUlOX01BVENIKSB7XG4gICAgICAgIHMubWF0Y2hfbGVuZ3RoLS07IC8qIHN0cmluZyBhdCBzdHJzdGFydCBhbHJlYWR5IGluIHRhYmxlICovXG4gICAgICAgIGRvIHtcbiAgICAgICAgICBzLnN0cnN0YXJ0Kys7XG4gICAgICAgICAgLyoqKiBJTlNFUlRfU1RSSU5HKHMsIHMuc3Ryc3RhcnQsIGhhc2hfaGVhZCk7ICoqKi9cbiAgICAgICAgICBzLmluc19oID0gKChzLmluc19oIDw8IHMuaGFzaF9zaGlmdCkgXiBzLndpbmRvd1tzLnN0cnN0YXJ0ICsgTUlOX01BVENIIC0gMV0pICYgcy5oYXNoX21hc2s7XG4gICAgICAgICAgaGFzaF9oZWFkID0gcy5wcmV2W3Muc3Ryc3RhcnQgJiBzLndfbWFza10gPSBzLmhlYWRbcy5pbnNfaF07XG4gICAgICAgICAgcy5oZWFkW3MuaW5zX2hdID0gcy5zdHJzdGFydDtcbiAgICAgICAgICAvKioqL1xuICAgICAgICAgIC8qIHN0cnN0YXJ0IG5ldmVyIGV4Y2VlZHMgV1NJWkUtTUFYX01BVENILCBzbyB0aGVyZSBhcmVcbiAgICAgICAgICAgKiBhbHdheXMgTUlOX01BVENIIGJ5dGVzIGFoZWFkLlxuICAgICAgICAgICAqL1xuICAgICAgICB9IHdoaWxlICgtLXMubWF0Y2hfbGVuZ3RoICE9PSAwKTtcbiAgICAgICAgcy5zdHJzdGFydCsrO1xuICAgICAgfSBlbHNlXG4gICAgICB7XG4gICAgICAgIHMuc3Ryc3RhcnQgKz0gcy5tYXRjaF9sZW5ndGg7XG4gICAgICAgIHMubWF0Y2hfbGVuZ3RoID0gMDtcbiAgICAgICAgcy5pbnNfaCA9IHMud2luZG93W3Muc3Ryc3RhcnRdO1xuICAgICAgICAvKiBVUERBVEVfSEFTSChzLCBzLmluc19oLCBzLndpbmRvd1tzLnN0cnN0YXJ0KzFdKTsgKi9cbiAgICAgICAgcy5pbnNfaCA9ICgocy5pbnNfaCA8PCBzLmhhc2hfc2hpZnQpIF4gcy53aW5kb3dbcy5zdHJzdGFydCArIDFdKSAmIHMuaGFzaF9tYXNrO1xuXG4vLyNpZiBNSU5fTUFUQ0ggIT0gM1xuLy8gICAgICAgICAgICAgICAgQ2FsbCBVUERBVEVfSEFTSCgpIE1JTl9NQVRDSC0zIG1vcmUgdGltZXNcbi8vI2VuZGlmXG4gICAgICAgIC8qIElmIGxvb2thaGVhZCA8IE1JTl9NQVRDSCwgaW5zX2ggaXMgZ2FyYmFnZSwgYnV0IGl0IGRvZXMgbm90XG4gICAgICAgICAqIG1hdHRlciBzaW5jZSBpdCB3aWxsIGJlIHJlY29tcHV0ZWQgYXQgbmV4dCBkZWZsYXRlIGNhbGwuXG4gICAgICAgICAqL1xuICAgICAgfVxuICAgIH0gZWxzZSB7XG4gICAgICAvKiBObyBtYXRjaCwgb3V0cHV0IGEgbGl0ZXJhbCBieXRlICovXG4gICAgICAvL1RyYWNldnYoKHN0ZGVycixcIiVjXCIsIHMud2luZG93W3Muc3Ryc3RhcnRdKSk7XG4gICAgICAvKioqIF90cl90YWxseV9saXQocywgcy53aW5kb3dbcy5zdHJzdGFydF0sIGJmbHVzaCk7ICoqKi9cbiAgICAgIGJmbHVzaCA9IHRyZWVzLl90cl90YWxseShzLCAwLCBzLndpbmRvd1tzLnN0cnN0YXJ0XSk7XG5cbiAgICAgIHMubG9va2FoZWFkLS07XG4gICAgICBzLnN0cnN0YXJ0Kys7XG4gICAgfVxuICAgIGlmIChiZmx1c2gpIHtcbiAgICAgIC8qKiogRkxVU0hfQkxPQ0socywgMCk7ICoqKi9cbiAgICAgIGZsdXNoX2Jsb2NrX29ubHkocywgZmFsc2UpO1xuICAgICAgaWYgKHMuc3RybS5hdmFpbF9vdXQgPT09IDApIHtcbiAgICAgICAgcmV0dXJuIEJTX05FRURfTU9SRTtcbiAgICAgIH1cbiAgICAgIC8qKiovXG4gICAgfVxuICB9XG4gIHMuaW5zZXJ0ID0gKChzLnN0cnN0YXJ0IDwgKE1JTl9NQVRDSC0xKSkgPyBzLnN0cnN0YXJ0IDogTUlOX01BVENILTEpO1xuICBpZiAoZmx1c2ggPT09IFpfRklOSVNIKSB7XG4gICAgLyoqKiBGTFVTSF9CTE9DSyhzLCAxKTsgKioqL1xuICAgIGZsdXNoX2Jsb2NrX29ubHkocywgdHJ1ZSk7XG4gICAgaWYgKHMuc3RybS5hdmFpbF9vdXQgPT09IDApIHtcbiAgICAgIHJldHVybiBCU19GSU5JU0hfU1RBUlRFRDtcbiAgICB9XG4gICAgLyoqKi9cbiAgICByZXR1cm4gQlNfRklOSVNIX0RPTkU7XG4gIH1cbiAgaWYgKHMubGFzdF9saXQpIHtcbiAgICAvKioqIEZMVVNIX0JMT0NLKHMsIDApOyAqKiovXG4gICAgZmx1c2hfYmxvY2tfb25seShzLCBmYWxzZSk7XG4gICAgaWYgKHMuc3RybS5hdmFpbF9vdXQgPT09IDApIHtcbiAgICAgIHJldHVybiBCU19ORUVEX01PUkU7XG4gICAgfVxuICAgIC8qKiovXG4gIH1cbiAgcmV0dXJuIEJTX0JMT0NLX0RPTkU7XG59XG5cbi8qID09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PVxuICogU2FtZSBhcyBhYm92ZSwgYnV0IGFjaGlldmVzIGJldHRlciBjb21wcmVzc2lvbi4gV2UgdXNlIGEgbGF6eVxuICogZXZhbHVhdGlvbiBmb3IgbWF0Y2hlczogYSBtYXRjaCBpcyBmaW5hbGx5IGFkb3B0ZWQgb25seSBpZiB0aGVyZSBpc1xuICogbm8gYmV0dGVyIG1hdGNoIGF0IHRoZSBuZXh0IHdpbmRvdyBwb3NpdGlvbi5cbiAqL1xuZnVuY3Rpb24gZGVmbGF0ZV9zbG93KHMsIGZsdXNoKSB7XG4gIHZhciBoYXNoX2hlYWQ7ICAgICAgICAgIC8qIGhlYWQgb2YgaGFzaCBjaGFpbiAqL1xuICB2YXIgYmZsdXNoOyAgICAgICAgICAgICAgLyogc2V0IGlmIGN1cnJlbnQgYmxvY2sgbXVzdCBiZSBmbHVzaGVkICovXG5cbiAgdmFyIG1heF9pbnNlcnQ7XG5cbiAgLyogUHJvY2VzcyB0aGUgaW5wdXQgYmxvY2suICovXG4gIGZvciAoOzspIHtcbiAgICAvKiBNYWtlIHN1cmUgdGhhdCB3ZSBhbHdheXMgaGF2ZSBlbm91Z2ggbG9va2FoZWFkLCBleGNlcHRcbiAgICAgKiBhdCB0aGUgZW5kIG9mIHRoZSBpbnB1dCBmaWxlLiBXZSBuZWVkIE1BWF9NQVRDSCBieXRlc1xuICAgICAqIGZvciB0aGUgbmV4dCBtYXRjaCwgcGx1cyBNSU5fTUFUQ0ggYnl0ZXMgdG8gaW5zZXJ0IHRoZVxuICAgICAqIHN0cmluZyBmb2xsb3dpbmcgdGhlIG5leHQgbWF0Y2guXG4gICAgICovXG4gICAgaWYgKHMubG9va2FoZWFkIDwgTUlOX0xPT0tBSEVBRCkge1xuICAgICAgZmlsbF93aW5kb3cocyk7XG4gICAgICBpZiAocy5sb29rYWhlYWQgPCBNSU5fTE9PS0FIRUFEICYmIGZsdXNoID09PSBaX05PX0ZMVVNIKSB7XG4gICAgICAgIHJldHVybiBCU19ORUVEX01PUkU7XG4gICAgICB9XG4gICAgICBpZiAocy5sb29rYWhlYWQgPT09IDApIHsgYnJlYWs7IH0gLyogZmx1c2ggdGhlIGN1cnJlbnQgYmxvY2sgKi9cbiAgICB9XG5cbiAgICAvKiBJbnNlcnQgdGhlIHN0cmluZyB3aW5kb3dbc3Ryc3RhcnQgLi4gc3Ryc3RhcnQrMl0gaW4gdGhlXG4gICAgICogZGljdGlvbmFyeSwgYW5kIHNldCBoYXNoX2hlYWQgdG8gdGhlIGhlYWQgb2YgdGhlIGhhc2ggY2hhaW46XG4gICAgICovXG4gICAgaGFzaF9oZWFkID0gMC8qTklMKi87XG4gICAgaWYgKHMubG9va2FoZWFkID49IE1JTl9NQVRDSCkge1xuICAgICAgLyoqKiBJTlNFUlRfU1RSSU5HKHMsIHMuc3Ryc3RhcnQsIGhhc2hfaGVhZCk7ICoqKi9cbiAgICAgIHMuaW5zX2ggPSAoKHMuaW5zX2ggPDwgcy5oYXNoX3NoaWZ0KSBeIHMud2luZG93W3Muc3Ryc3RhcnQgKyBNSU5fTUFUQ0ggLSAxXSkgJiBzLmhhc2hfbWFzaztcbiAgICAgIGhhc2hfaGVhZCA9IHMucHJldltzLnN0cnN0YXJ0ICYgcy53X21hc2tdID0gcy5oZWFkW3MuaW5zX2hdO1xuICAgICAgcy5oZWFkW3MuaW5zX2hdID0gcy5zdHJzdGFydDtcbiAgICAgIC8qKiovXG4gICAgfVxuXG4gICAgLyogRmluZCB0aGUgbG9uZ2VzdCBtYXRjaCwgZGlzY2FyZGluZyB0aG9zZSA8PSBwcmV2X2xlbmd0aC5cbiAgICAgKi9cbiAgICBzLnByZXZfbGVuZ3RoID0gcy5tYXRjaF9sZW5ndGg7XG4gICAgcy5wcmV2X21hdGNoID0gcy5tYXRjaF9zdGFydDtcbiAgICBzLm1hdGNoX2xlbmd0aCA9IE1JTl9NQVRDSC0xO1xuXG4gICAgaWYgKGhhc2hfaGVhZCAhPT0gMC8qTklMKi8gJiYgcy5wcmV2X2xlbmd0aCA8IHMubWF4X2xhenlfbWF0Y2ggJiZcbiAgICAgICAgcy5zdHJzdGFydCAtIGhhc2hfaGVhZCA8PSAocy53X3NpemUtTUlOX0xPT0tBSEVBRCkvKk1BWF9ESVNUKHMpKi8pIHtcbiAgICAgIC8qIFRvIHNpbXBsaWZ5IHRoZSBjb2RlLCB3ZSBwcmV2ZW50IG1hdGNoZXMgd2l0aCB0aGUgc3RyaW5nXG4gICAgICAgKiBvZiB3aW5kb3cgaW5kZXggMCAoaW4gcGFydGljdWxhciB3ZSBoYXZlIHRvIGF2b2lkIGEgbWF0Y2hcbiAgICAgICAqIG9mIHRoZSBzdHJpbmcgd2l0aCBpdHNlbGYgYXQgdGhlIHN0YXJ0IG9mIHRoZSBpbnB1dCBmaWxlKS5cbiAgICAgICAqL1xuICAgICAgcy5tYXRjaF9sZW5ndGggPSBsb25nZXN0X21hdGNoKHMsIGhhc2hfaGVhZCk7XG4gICAgICAvKiBsb25nZXN0X21hdGNoKCkgc2V0cyBtYXRjaF9zdGFydCAqL1xuXG4gICAgICBpZiAocy5tYXRjaF9sZW5ndGggPD0gNSAmJlxuICAgICAgICAgKHMuc3RyYXRlZ3kgPT09IFpfRklMVEVSRUQgfHwgKHMubWF0Y2hfbGVuZ3RoID09PSBNSU5fTUFUQ0ggJiYgcy5zdHJzdGFydCAtIHMubWF0Y2hfc3RhcnQgPiA0MDk2LypUT09fRkFSKi8pKSkge1xuXG4gICAgICAgIC8qIElmIHByZXZfbWF0Y2ggaXMgYWxzbyBNSU5fTUFUQ0gsIG1hdGNoX3N0YXJ0IGlzIGdhcmJhZ2VcbiAgICAgICAgICogYnV0IHdlIHdpbGwgaWdub3JlIHRoZSBjdXJyZW50IG1hdGNoIGFueXdheS5cbiAgICAgICAgICovXG4gICAgICAgIHMubWF0Y2hfbGVuZ3RoID0gTUlOX01BVENILTE7XG4gICAgICB9XG4gICAgfVxuICAgIC8qIElmIHRoZXJlIHdhcyBhIG1hdGNoIGF0IHRoZSBwcmV2aW91cyBzdGVwIGFuZCB0aGUgY3VycmVudFxuICAgICAqIG1hdGNoIGlzIG5vdCBiZXR0ZXIsIG91dHB1dCB0aGUgcHJldmlvdXMgbWF0Y2g6XG4gICAgICovXG4gICAgaWYgKHMucHJldl9sZW5ndGggPj0gTUlOX01BVENIICYmIHMubWF0Y2hfbGVuZ3RoIDw9IHMucHJldl9sZW5ndGgpIHtcbiAgICAgIG1heF9pbnNlcnQgPSBzLnN0cnN0YXJ0ICsgcy5sb29rYWhlYWQgLSBNSU5fTUFUQ0g7XG4gICAgICAvKiBEbyBub3QgaW5zZXJ0IHN0cmluZ3MgaW4gaGFzaCB0YWJsZSBiZXlvbmQgdGhpcy4gKi9cblxuICAgICAgLy9jaGVja19tYXRjaChzLCBzLnN0cnN0YXJ0LTEsIHMucHJldl9tYXRjaCwgcy5wcmV2X2xlbmd0aCk7XG5cbiAgICAgIC8qKipfdHJfdGFsbHlfZGlzdChzLCBzLnN0cnN0YXJ0IC0gMSAtIHMucHJldl9tYXRjaCxcbiAgICAgICAgICAgICAgICAgICAgIHMucHJldl9sZW5ndGggLSBNSU5fTUFUQ0gsIGJmbHVzaCk7KioqL1xuICAgICAgYmZsdXNoID0gdHJlZXMuX3RyX3RhbGx5KHMsIHMuc3Ryc3RhcnQgLSAxLSBzLnByZXZfbWF0Y2gsIHMucHJldl9sZW5ndGggLSBNSU5fTUFUQ0gpO1xuICAgICAgLyogSW5zZXJ0IGluIGhhc2ggdGFibGUgYWxsIHN0cmluZ3MgdXAgdG8gdGhlIGVuZCBvZiB0aGUgbWF0Y2guXG4gICAgICAgKiBzdHJzdGFydC0xIGFuZCBzdHJzdGFydCBhcmUgYWxyZWFkeSBpbnNlcnRlZC4gSWYgdGhlcmUgaXMgbm90XG4gICAgICAgKiBlbm91Z2ggbG9va2FoZWFkLCB0aGUgbGFzdCB0d28gc3RyaW5ncyBhcmUgbm90IGluc2VydGVkIGluXG4gICAgICAgKiB0aGUgaGFzaCB0YWJsZS5cbiAgICAgICAqL1xuICAgICAgcy5sb29rYWhlYWQgLT0gcy5wcmV2X2xlbmd0aC0xO1xuICAgICAgcy5wcmV2X2xlbmd0aCAtPSAyO1xuICAgICAgZG8ge1xuICAgICAgICBpZiAoKytzLnN0cnN0YXJ0IDw9IG1heF9pbnNlcnQpIHtcbiAgICAgICAgICAvKioqIElOU0VSVF9TVFJJTkcocywgcy5zdHJzdGFydCwgaGFzaF9oZWFkKTsgKioqL1xuICAgICAgICAgIHMuaW5zX2ggPSAoKHMuaW5zX2ggPDwgcy5oYXNoX3NoaWZ0KSBeIHMud2luZG93W3Muc3Ryc3RhcnQgKyBNSU5fTUFUQ0ggLSAxXSkgJiBzLmhhc2hfbWFzaztcbiAgICAgICAgICBoYXNoX2hlYWQgPSBzLnByZXZbcy5zdHJzdGFydCAmIHMud19tYXNrXSA9IHMuaGVhZFtzLmluc19oXTtcbiAgICAgICAgICBzLmhlYWRbcy5pbnNfaF0gPSBzLnN0cnN0YXJ0O1xuICAgICAgICAgIC8qKiovXG4gICAgICAgIH1cbiAgICAgIH0gd2hpbGUgKC0tcy5wcmV2X2xlbmd0aCAhPT0gMCk7XG4gICAgICBzLm1hdGNoX2F2YWlsYWJsZSA9IDA7XG4gICAgICBzLm1hdGNoX2xlbmd0aCA9IE1JTl9NQVRDSC0xO1xuICAgICAgcy5zdHJzdGFydCsrO1xuXG4gICAgICBpZiAoYmZsdXNoKSB7XG4gICAgICAgIC8qKiogRkxVU0hfQkxPQ0socywgMCk7ICoqKi9cbiAgICAgICAgZmx1c2hfYmxvY2tfb25seShzLCBmYWxzZSk7XG4gICAgICAgIGlmIChzLnN0cm0uYXZhaWxfb3V0ID09PSAwKSB7XG4gICAgICAgICAgcmV0dXJuIEJTX05FRURfTU9SRTtcbiAgICAgICAgfVxuICAgICAgICAvKioqL1xuICAgICAgfVxuXG4gICAgfSBlbHNlIGlmIChzLm1hdGNoX2F2YWlsYWJsZSkge1xuICAgICAgLyogSWYgdGhlcmUgd2FzIG5vIG1hdGNoIGF0IHRoZSBwcmV2aW91cyBwb3NpdGlvbiwgb3V0cHV0IGFcbiAgICAgICAqIHNpbmdsZSBsaXRlcmFsLiBJZiB0aGVyZSB3YXMgYSBtYXRjaCBidXQgdGhlIGN1cnJlbnQgbWF0Y2hcbiAgICAgICAqIGlzIGxvbmdlciwgdHJ1bmNhdGUgdGhlIHByZXZpb3VzIG1hdGNoIHRvIGEgc2luZ2xlIGxpdGVyYWwuXG4gICAgICAgKi9cbiAgICAgIC8vVHJhY2V2digoc3RkZXJyLFwiJWNcIiwgcy0+d2luZG93W3MtPnN0cnN0YXJ0LTFdKSk7XG4gICAgICAvKioqIF90cl90YWxseV9saXQocywgcy53aW5kb3dbcy5zdHJzdGFydC0xXSwgYmZsdXNoKTsgKioqL1xuICAgICAgYmZsdXNoID0gdHJlZXMuX3RyX3RhbGx5KHMsIDAsIHMud2luZG93W3Muc3Ryc3RhcnQtMV0pO1xuXG4gICAgICBpZiAoYmZsdXNoKSB7XG4gICAgICAgIC8qKiogRkxVU0hfQkxPQ0tfT05MWShzLCAwKSAqKiovXG4gICAgICAgIGZsdXNoX2Jsb2NrX29ubHkocywgZmFsc2UpO1xuICAgICAgICAvKioqL1xuICAgICAgfVxuICAgICAgcy5zdHJzdGFydCsrO1xuICAgICAgcy5sb29rYWhlYWQtLTtcbiAgICAgIGlmIChzLnN0cm0uYXZhaWxfb3V0ID09PSAwKSB7XG4gICAgICAgIHJldHVybiBCU19ORUVEX01PUkU7XG4gICAgICB9XG4gICAgfSBlbHNlIHtcbiAgICAgIC8qIFRoZXJlIGlzIG5vIHByZXZpb3VzIG1hdGNoIHRvIGNvbXBhcmUgd2l0aCwgd2FpdCBmb3JcbiAgICAgICAqIHRoZSBuZXh0IHN0ZXAgdG8gZGVjaWRlLlxuICAgICAgICovXG4gICAgICBzLm1hdGNoX2F2YWlsYWJsZSA9IDE7XG4gICAgICBzLnN0cnN0YXJ0Kys7XG4gICAgICBzLmxvb2thaGVhZC0tO1xuICAgIH1cbiAgfVxuICAvL0Fzc2VydCAoZmx1c2ggIT0gWl9OT19GTFVTSCwgXCJubyBmbHVzaD9cIik7XG4gIGlmIChzLm1hdGNoX2F2YWlsYWJsZSkge1xuICAgIC8vVHJhY2V2digoc3RkZXJyLFwiJWNcIiwgcy0+d2luZG93W3MtPnN0cnN0YXJ0LTFdKSk7XG4gICAgLyoqKiBfdHJfdGFsbHlfbGl0KHMsIHMud2luZG93W3Muc3Ryc3RhcnQtMV0sIGJmbHVzaCk7ICoqKi9cbiAgICBiZmx1c2ggPSB0cmVlcy5fdHJfdGFsbHkocywgMCwgcy53aW5kb3dbcy5zdHJzdGFydC0xXSk7XG5cbiAgICBzLm1hdGNoX2F2YWlsYWJsZSA9IDA7XG4gIH1cbiAgcy5pbnNlcnQgPSBzLnN0cnN0YXJ0IDwgTUlOX01BVENILTEgPyBzLnN0cnN0YXJ0IDogTUlOX01BVENILTE7XG4gIGlmIChmbHVzaCA9PT0gWl9GSU5JU0gpIHtcbiAgICAvKioqIEZMVVNIX0JMT0NLKHMsIDEpOyAqKiovXG4gICAgZmx1c2hfYmxvY2tfb25seShzLCB0cnVlKTtcbiAgICBpZiAocy5zdHJtLmF2YWlsX291dCA9PT0gMCkge1xuICAgICAgcmV0dXJuIEJTX0ZJTklTSF9TVEFSVEVEO1xuICAgIH1cbiAgICAvKioqL1xuICAgIHJldHVybiBCU19GSU5JU0hfRE9ORTtcbiAgfVxuICBpZiAocy5sYXN0X2xpdCkge1xuICAgIC8qKiogRkxVU0hfQkxPQ0socywgMCk7ICoqKi9cbiAgICBmbHVzaF9ibG9ja19vbmx5KHMsIGZhbHNlKTtcbiAgICBpZiAocy5zdHJtLmF2YWlsX291dCA9PT0gMCkge1xuICAgICAgcmV0dXJuIEJTX05FRURfTU9SRTtcbiAgICB9XG4gICAgLyoqKi9cbiAgfVxuXG4gIHJldHVybiBCU19CTE9DS19ET05FO1xufVxuXG5cbi8qID09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PVxuICogRm9yIFpfUkxFLCBzaW1wbHkgbG9vayBmb3IgcnVucyBvZiBieXRlcywgZ2VuZXJhdGUgbWF0Y2hlcyBvbmx5IG9mIGRpc3RhbmNlXG4gKiBvbmUuICBEbyBub3QgbWFpbnRhaW4gYSBoYXNoIHRhYmxlLiAgKEl0IHdpbGwgYmUgcmVnZW5lcmF0ZWQgaWYgdGhpcyBydW4gb2ZcbiAqIGRlZmxhdGUgc3dpdGNoZXMgYXdheSBmcm9tIFpfUkxFLilcbiAqL1xuZnVuY3Rpb24gZGVmbGF0ZV9ybGUocywgZmx1c2gpIHtcbiAgdmFyIGJmbHVzaDsgICAgICAgICAgICAvKiBzZXQgaWYgY3VycmVudCBibG9jayBtdXN0IGJlIGZsdXNoZWQgKi9cbiAgdmFyIHByZXY7ICAgICAgICAgICAgICAvKiBieXRlIGF0IGRpc3RhbmNlIG9uZSB0byBtYXRjaCAqL1xuICB2YXIgc2Nhbiwgc3RyZW5kOyAgICAgIC8qIHNjYW4gZ29lcyB1cCB0byBzdHJlbmQgZm9yIGxlbmd0aCBvZiBydW4gKi9cblxuICB2YXIgX3dpbiA9IHMud2luZG93O1xuXG4gIGZvciAoOzspIHtcbiAgICAvKiBNYWtlIHN1cmUgdGhhdCB3ZSBhbHdheXMgaGF2ZSBlbm91Z2ggbG9va2FoZWFkLCBleGNlcHRcbiAgICAgKiBhdCB0aGUgZW5kIG9mIHRoZSBpbnB1dCBmaWxlLiBXZSBuZWVkIE1BWF9NQVRDSCBieXRlc1xuICAgICAqIGZvciB0aGUgbG9uZ2VzdCBydW4sIHBsdXMgb25lIGZvciB0aGUgdW5yb2xsZWQgbG9vcC5cbiAgICAgKi9cbiAgICBpZiAocy5sb29rYWhlYWQgPD0gTUFYX01BVENIKSB7XG4gICAgICBmaWxsX3dpbmRvdyhzKTtcbiAgICAgIGlmIChzLmxvb2thaGVhZCA8PSBNQVhfTUFUQ0ggJiYgZmx1c2ggPT09IFpfTk9fRkxVU0gpIHtcbiAgICAgICAgcmV0dXJuIEJTX05FRURfTU9SRTtcbiAgICAgIH1cbiAgICAgIGlmIChzLmxvb2thaGVhZCA9PT0gMCkgeyBicmVhazsgfSAvKiBmbHVzaCB0aGUgY3VycmVudCBibG9jayAqL1xuICAgIH1cblxuICAgIC8qIFNlZSBob3cgbWFueSB0aW1lcyB0aGUgcHJldmlvdXMgYnl0ZSByZXBlYXRzICovXG4gICAgcy5tYXRjaF9sZW5ndGggPSAwO1xuICAgIGlmIChzLmxvb2thaGVhZCA+PSBNSU5fTUFUQ0ggJiYgcy5zdHJzdGFydCA+IDApIHtcbiAgICAgIHNjYW4gPSBzLnN0cnN0YXJ0IC0gMTtcbiAgICAgIHByZXYgPSBfd2luW3NjYW5dO1xuICAgICAgaWYgKHByZXYgPT09IF93aW5bKytzY2FuXSAmJiBwcmV2ID09PSBfd2luWysrc2Nhbl0gJiYgcHJldiA9PT0gX3dpblsrK3NjYW5dKSB7XG4gICAgICAgIHN0cmVuZCA9IHMuc3Ryc3RhcnQgKyBNQVhfTUFUQ0g7XG4gICAgICAgIGRvIHtcbiAgICAgICAgICAvKmpzaGludCBub2VtcHR5OmZhbHNlKi9cbiAgICAgICAgfSB3aGlsZSAocHJldiA9PT0gX3dpblsrK3NjYW5dICYmIHByZXYgPT09IF93aW5bKytzY2FuXSAmJlxuICAgICAgICAgICAgICAgICBwcmV2ID09PSBfd2luWysrc2Nhbl0gJiYgcHJldiA9PT0gX3dpblsrK3NjYW5dICYmXG4gICAgICAgICAgICAgICAgIHByZXYgPT09IF93aW5bKytzY2FuXSAmJiBwcmV2ID09PSBfd2luWysrc2Nhbl0gJiZcbiAgICAgICAgICAgICAgICAgcHJldiA9PT0gX3dpblsrK3NjYW5dICYmIHByZXYgPT09IF93aW5bKytzY2FuXSAmJlxuICAgICAgICAgICAgICAgICBzY2FuIDwgc3RyZW5kKTtcbiAgICAgICAgcy5tYXRjaF9sZW5ndGggPSBNQVhfTUFUQ0ggLSAoc3RyZW5kIC0gc2Nhbik7XG4gICAgICAgIGlmIChzLm1hdGNoX2xlbmd0aCA+IHMubG9va2FoZWFkKSB7XG4gICAgICAgICAgcy5tYXRjaF9sZW5ndGggPSBzLmxvb2thaGVhZDtcbiAgICAgICAgfVxuICAgICAgfVxuICAgICAgLy9Bc3NlcnQoc2NhbiA8PSBzLT53aW5kb3crKHVJbnQpKHMtPndpbmRvd19zaXplLTEpLCBcIndpbGQgc2NhblwiKTtcbiAgICB9XG5cbiAgICAvKiBFbWl0IG1hdGNoIGlmIGhhdmUgcnVuIG9mIE1JTl9NQVRDSCBvciBsb25nZXIsIGVsc2UgZW1pdCBsaXRlcmFsICovXG4gICAgaWYgKHMubWF0Y2hfbGVuZ3RoID49IE1JTl9NQVRDSCkge1xuICAgICAgLy9jaGVja19tYXRjaChzLCBzLnN0cnN0YXJ0LCBzLnN0cnN0YXJ0IC0gMSwgcy5tYXRjaF9sZW5ndGgpO1xuXG4gICAgICAvKioqIF90cl90YWxseV9kaXN0KHMsIDEsIHMubWF0Y2hfbGVuZ3RoIC0gTUlOX01BVENILCBiZmx1c2gpOyAqKiovXG4gICAgICBiZmx1c2ggPSB0cmVlcy5fdHJfdGFsbHkocywgMSwgcy5tYXRjaF9sZW5ndGggLSBNSU5fTUFUQ0gpO1xuXG4gICAgICBzLmxvb2thaGVhZCAtPSBzLm1hdGNoX2xlbmd0aDtcbiAgICAgIHMuc3Ryc3RhcnQgKz0gcy5tYXRjaF9sZW5ndGg7XG4gICAgICBzLm1hdGNoX2xlbmd0aCA9IDA7XG4gICAgfSBlbHNlIHtcbiAgICAgIC8qIE5vIG1hdGNoLCBvdXRwdXQgYSBsaXRlcmFsIGJ5dGUgKi9cbiAgICAgIC8vVHJhY2V2digoc3RkZXJyLFwiJWNcIiwgcy0+d2luZG93W3MtPnN0cnN0YXJ0XSkpO1xuICAgICAgLyoqKiBfdHJfdGFsbHlfbGl0KHMsIHMud2luZG93W3Muc3Ryc3RhcnRdLCBiZmx1c2gpOyAqKiovXG4gICAgICBiZmx1c2ggPSB0cmVlcy5fdHJfdGFsbHkocywgMCwgcy53aW5kb3dbcy5zdHJzdGFydF0pO1xuXG4gICAgICBzLmxvb2thaGVhZC0tO1xuICAgICAgcy5zdHJzdGFydCsrO1xuICAgIH1cbiAgICBpZiAoYmZsdXNoKSB7XG4gICAgICAvKioqIEZMVVNIX0JMT0NLKHMsIDApOyAqKiovXG4gICAgICBmbHVzaF9ibG9ja19vbmx5KHMsIGZhbHNlKTtcbiAgICAgIGlmIChzLnN0cm0uYXZhaWxfb3V0ID09PSAwKSB7XG4gICAgICAgIHJldHVybiBCU19ORUVEX01PUkU7XG4gICAgICB9XG4gICAgICAvKioqL1xuICAgIH1cbiAgfVxuICBzLmluc2VydCA9IDA7XG4gIGlmIChmbHVzaCA9PT0gWl9GSU5JU0gpIHtcbiAgICAvKioqIEZMVVNIX0JMT0NLKHMsIDEpOyAqKiovXG4gICAgZmx1c2hfYmxvY2tfb25seShzLCB0cnVlKTtcbiAgICBpZiAocy5zdHJtLmF2YWlsX291dCA9PT0gMCkge1xuICAgICAgcmV0dXJuIEJTX0ZJTklTSF9TVEFSVEVEO1xuICAgIH1cbiAgICAvKioqL1xuICAgIHJldHVybiBCU19GSU5JU0hfRE9ORTtcbiAgfVxuICBpZiAocy5sYXN0X2xpdCkge1xuICAgIC8qKiogRkxVU0hfQkxPQ0socywgMCk7ICoqKi9cbiAgICBmbHVzaF9ibG9ja19vbmx5KHMsIGZhbHNlKTtcbiAgICBpZiAocy5zdHJtLmF2YWlsX291dCA9PT0gMCkge1xuICAgICAgcmV0dXJuIEJTX05FRURfTU9SRTtcbiAgICB9XG4gICAgLyoqKi9cbiAgfVxuICByZXR1cm4gQlNfQkxPQ0tfRE9ORTtcbn1cblxuLyogPT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09XG4gKiBGb3IgWl9IVUZGTUFOX09OTFksIGRvIG5vdCBsb29rIGZvciBtYXRjaGVzLiAgRG8gbm90IG1haW50YWluIGEgaGFzaCB0YWJsZS5cbiAqIChJdCB3aWxsIGJlIHJlZ2VuZXJhdGVkIGlmIHRoaXMgcnVuIG9mIGRlZmxhdGUgc3dpdGNoZXMgYXdheSBmcm9tIEh1ZmZtYW4uKVxuICovXG5mdW5jdGlvbiBkZWZsYXRlX2h1ZmYocywgZmx1c2gpIHtcbiAgdmFyIGJmbHVzaDsgICAgICAgICAgICAgLyogc2V0IGlmIGN1cnJlbnQgYmxvY2sgbXVzdCBiZSBmbHVzaGVkICovXG5cbiAgZm9yICg7Oykge1xuICAgIC8qIE1ha2Ugc3VyZSB0aGF0IHdlIGhhdmUgYSBsaXRlcmFsIHRvIHdyaXRlLiAqL1xuICAgIGlmIChzLmxvb2thaGVhZCA9PT0gMCkge1xuICAgICAgZmlsbF93aW5kb3cocyk7XG4gICAgICBpZiAocy5sb29rYWhlYWQgPT09IDApIHtcbiAgICAgICAgaWYgKGZsdXNoID09PSBaX05PX0ZMVVNIKSB7XG4gICAgICAgICAgcmV0dXJuIEJTX05FRURfTU9SRTtcbiAgICAgICAgfVxuICAgICAgICBicmVhazsgICAgICAvKiBmbHVzaCB0aGUgY3VycmVudCBibG9jayAqL1xuICAgICAgfVxuICAgIH1cblxuICAgIC8qIE91dHB1dCBhIGxpdGVyYWwgYnl0ZSAqL1xuICAgIHMubWF0Y2hfbGVuZ3RoID0gMDtcbiAgICAvL1RyYWNldnYoKHN0ZGVycixcIiVjXCIsIHMtPndpbmRvd1tzLT5zdHJzdGFydF0pKTtcbiAgICAvKioqIF90cl90YWxseV9saXQocywgcy53aW5kb3dbcy5zdHJzdGFydF0sIGJmbHVzaCk7ICoqKi9cbiAgICBiZmx1c2ggPSB0cmVlcy5fdHJfdGFsbHkocywgMCwgcy53aW5kb3dbcy5zdHJzdGFydF0pO1xuICAgIHMubG9va2FoZWFkLS07XG4gICAgcy5zdHJzdGFydCsrO1xuICAgIGlmIChiZmx1c2gpIHtcbiAgICAgIC8qKiogRkxVU0hfQkxPQ0socywgMCk7ICoqKi9cbiAgICAgIGZsdXNoX2Jsb2NrX29ubHkocywgZmFsc2UpO1xuICAgICAgaWYgKHMuc3RybS5hdmFpbF9vdXQgPT09IDApIHtcbiAgICAgICAgcmV0dXJuIEJTX05FRURfTU9SRTtcbiAgICAgIH1cbiAgICAgIC8qKiovXG4gICAgfVxuICB9XG4gIHMuaW5zZXJ0ID0gMDtcbiAgaWYgKGZsdXNoID09PSBaX0ZJTklTSCkge1xuICAgIC8qKiogRkxVU0hfQkxPQ0socywgMSk7ICoqKi9cbiAgICBmbHVzaF9ibG9ja19vbmx5KHMsIHRydWUpO1xuICAgIGlmIChzLnN0cm0uYXZhaWxfb3V0ID09PSAwKSB7XG4gICAgICByZXR1cm4gQlNfRklOSVNIX1NUQVJURUQ7XG4gICAgfVxuICAgIC8qKiovXG4gICAgcmV0dXJuIEJTX0ZJTklTSF9ET05FO1xuICB9XG4gIGlmIChzLmxhc3RfbGl0KSB7XG4gICAgLyoqKiBGTFVTSF9CTE9DSyhzLCAwKTsgKioqL1xuICAgIGZsdXNoX2Jsb2NrX29ubHkocywgZmFsc2UpO1xuICAgIGlmIChzLnN0cm0uYXZhaWxfb3V0ID09PSAwKSB7XG4gICAgICByZXR1cm4gQlNfTkVFRF9NT1JFO1xuICAgIH1cbiAgICAvKioqL1xuICB9XG4gIHJldHVybiBCU19CTE9DS19ET05FO1xufVxuXG4vKiBWYWx1ZXMgZm9yIG1heF9sYXp5X21hdGNoLCBnb29kX21hdGNoIGFuZCBtYXhfY2hhaW5fbGVuZ3RoLCBkZXBlbmRpbmcgb25cbiAqIHRoZSBkZXNpcmVkIHBhY2sgbGV2ZWwgKDAuLjkpLiBUaGUgdmFsdWVzIGdpdmVuIGJlbG93IGhhdmUgYmVlbiB0dW5lZCB0b1xuICogZXhjbHVkZSB3b3JzdCBjYXNlIHBlcmZvcm1hbmNlIGZvciBwYXRob2xvZ2ljYWwgZmlsZXMuIEJldHRlciB2YWx1ZXMgbWF5IGJlXG4gKiBmb3VuZCBmb3Igc3BlY2lmaWMgZmlsZXMuXG4gKi9cbnZhciBDb25maWcgPSBmdW5jdGlvbiAoZ29vZF9sZW5ndGgsIG1heF9sYXp5LCBuaWNlX2xlbmd0aCwgbWF4X2NoYWluLCBmdW5jKSB7XG4gIHRoaXMuZ29vZF9sZW5ndGggPSBnb29kX2xlbmd0aDtcbiAgdGhpcy5tYXhfbGF6eSA9IG1heF9sYXp5O1xuICB0aGlzLm5pY2VfbGVuZ3RoID0gbmljZV9sZW5ndGg7XG4gIHRoaXMubWF4X2NoYWluID0gbWF4X2NoYWluO1xuICB0aGlzLmZ1bmMgPSBmdW5jO1xufTtcblxudmFyIGNvbmZpZ3VyYXRpb25fdGFibGU7XG5cbmNvbmZpZ3VyYXRpb25fdGFibGUgPSBbXG4gIC8qICAgICAgZ29vZCBsYXp5IG5pY2UgY2hhaW4gKi9cbiAgbmV3IENvbmZpZygwLCAwLCAwLCAwLCBkZWZsYXRlX3N0b3JlZCksICAgICAgICAgIC8qIDAgc3RvcmUgb25seSAqL1xuICBuZXcgQ29uZmlnKDQsIDQsIDgsIDQsIGRlZmxhdGVfZmFzdCksICAgICAgICAgICAgLyogMSBtYXggc3BlZWQsIG5vIGxhenkgbWF0Y2hlcyAqL1xuICBuZXcgQ29uZmlnKDQsIDUsIDE2LCA4LCBkZWZsYXRlX2Zhc3QpLCAgICAgICAgICAgLyogMiAqL1xuICBuZXcgQ29uZmlnKDQsIDYsIDMyLCAzMiwgZGVmbGF0ZV9mYXN0KSwgICAgICAgICAgLyogMyAqL1xuXG4gIG5ldyBDb25maWcoNCwgNCwgMTYsIDE2LCBkZWZsYXRlX3Nsb3cpLCAgICAgICAgICAvKiA0IGxhenkgbWF0Y2hlcyAqL1xuICBuZXcgQ29uZmlnKDgsIDE2LCAzMiwgMzIsIGRlZmxhdGVfc2xvdyksICAgICAgICAgLyogNSAqL1xuICBuZXcgQ29uZmlnKDgsIDE2LCAxMjgsIDEyOCwgZGVmbGF0ZV9zbG93KSwgICAgICAgLyogNiAqL1xuICBuZXcgQ29uZmlnKDgsIDMyLCAxMjgsIDI1NiwgZGVmbGF0ZV9zbG93KSwgICAgICAgLyogNyAqL1xuICBuZXcgQ29uZmlnKDMyLCAxMjgsIDI1OCwgMTAyNCwgZGVmbGF0ZV9zbG93KSwgICAgLyogOCAqL1xuICBuZXcgQ29uZmlnKDMyLCAyNTgsIDI1OCwgNDA5NiwgZGVmbGF0ZV9zbG93KSAgICAgLyogOSBtYXggY29tcHJlc3Npb24gKi9cbl07XG5cblxuLyogPT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09XG4gKiBJbml0aWFsaXplIHRoZSBcImxvbmdlc3QgbWF0Y2hcIiByb3V0aW5lcyBmb3IgYSBuZXcgemxpYiBzdHJlYW1cbiAqL1xuZnVuY3Rpb24gbG1faW5pdChzKSB7XG4gIHMud2luZG93X3NpemUgPSAyICogcy53X3NpemU7XG5cbiAgLyoqKiBDTEVBUl9IQVNIKHMpOyAqKiovXG4gIHplcm8ocy5oZWFkKTsgLy8gRmlsbCB3aXRoIE5JTCAoPSAwKTtcblxuICAvKiBTZXQgdGhlIGRlZmF1bHQgY29uZmlndXJhdGlvbiBwYXJhbWV0ZXJzOlxuICAgKi9cbiAgcy5tYXhfbGF6eV9tYXRjaCA9IGNvbmZpZ3VyYXRpb25fdGFibGVbcy5sZXZlbF0ubWF4X2xhenk7XG4gIHMuZ29vZF9tYXRjaCA9IGNvbmZpZ3VyYXRpb25fdGFibGVbcy5sZXZlbF0uZ29vZF9sZW5ndGg7XG4gIHMubmljZV9tYXRjaCA9IGNvbmZpZ3VyYXRpb25fdGFibGVbcy5sZXZlbF0ubmljZV9sZW5ndGg7XG4gIHMubWF4X2NoYWluX2xlbmd0aCA9IGNvbmZpZ3VyYXRpb25fdGFibGVbcy5sZXZlbF0ubWF4X2NoYWluO1xuXG4gIHMuc3Ryc3RhcnQgPSAwO1xuICBzLmJsb2NrX3N0YXJ0ID0gMDtcbiAgcy5sb29rYWhlYWQgPSAwO1xuICBzLmluc2VydCA9IDA7XG4gIHMubWF0Y2hfbGVuZ3RoID0gcy5wcmV2X2xlbmd0aCA9IE1JTl9NQVRDSCAtIDE7XG4gIHMubWF0Y2hfYXZhaWxhYmxlID0gMDtcbiAgcy5pbnNfaCA9IDA7XG59XG5cblxuZnVuY3Rpb24gRGVmbGF0ZVN0YXRlKCkge1xuICB0aGlzLnN0cm0gPSBudWxsOyAgICAgICAgICAgIC8qIHBvaW50ZXIgYmFjayB0byB0aGlzIHpsaWIgc3RyZWFtICovXG4gIHRoaXMuc3RhdHVzID0gMDsgICAgICAgICAgICAvKiBhcyB0aGUgbmFtZSBpbXBsaWVzICovXG4gIHRoaXMucGVuZGluZ19idWYgPSBudWxsOyAgICAgIC8qIG91dHB1dCBzdGlsbCBwZW5kaW5nICovXG4gIHRoaXMucGVuZGluZ19idWZfc2l6ZSA9IDA7ICAvKiBzaXplIG9mIHBlbmRpbmdfYnVmICovXG4gIHRoaXMucGVuZGluZ19vdXQgPSAwOyAgICAgICAvKiBuZXh0IHBlbmRpbmcgYnl0ZSB0byBvdXRwdXQgdG8gdGhlIHN0cmVhbSAqL1xuICB0aGlzLnBlbmRpbmcgPSAwOyAgICAgICAgICAgLyogbmIgb2YgYnl0ZXMgaW4gdGhlIHBlbmRpbmcgYnVmZmVyICovXG4gIHRoaXMud3JhcCA9IDA7ICAgICAgICAgICAgICAvKiBiaXQgMCB0cnVlIGZvciB6bGliLCBiaXQgMSB0cnVlIGZvciBnemlwICovXG4gIHRoaXMuZ3poZWFkID0gbnVsbDsgICAgICAgICAvKiBnemlwIGhlYWRlciBpbmZvcm1hdGlvbiB0byB3cml0ZSAqL1xuICB0aGlzLmd6aW5kZXggPSAwOyAgICAgICAgICAgLyogd2hlcmUgaW4gZXh0cmEsIG5hbWUsIG9yIGNvbW1lbnQgKi9cbiAgdGhpcy5tZXRob2QgPSBaX0RFRkxBVEVEOyAvKiBjYW4gb25seSBiZSBERUZMQVRFRCAqL1xuICB0aGlzLmxhc3RfZmx1c2ggPSAtMTsgICAvKiB2YWx1ZSBvZiBmbHVzaCBwYXJhbSBmb3IgcHJldmlvdXMgZGVmbGF0ZSBjYWxsICovXG5cbiAgdGhpcy53X3NpemUgPSAwOyAgLyogTFo3NyB3aW5kb3cgc2l6ZSAoMzJLIGJ5IGRlZmF1bHQpICovXG4gIHRoaXMud19iaXRzID0gMDsgIC8qIGxvZzIod19zaXplKSAgKDguLjE2KSAqL1xuICB0aGlzLndfbWFzayA9IDA7ICAvKiB3X3NpemUgLSAxICovXG5cbiAgdGhpcy53aW5kb3cgPSBudWxsO1xuICAvKiBTbGlkaW5nIHdpbmRvdy4gSW5wdXQgYnl0ZXMgYXJlIHJlYWQgaW50byB0aGUgc2Vjb25kIGhhbGYgb2YgdGhlIHdpbmRvdyxcbiAgICogYW5kIG1vdmUgdG8gdGhlIGZpcnN0IGhhbGYgbGF0ZXIgdG8ga2VlcCBhIGRpY3Rpb25hcnkgb2YgYXQgbGVhc3Qgd1NpemVcbiAgICogYnl0ZXMuIFdpdGggdGhpcyBvcmdhbml6YXRpb24sIG1hdGNoZXMgYXJlIGxpbWl0ZWQgdG8gYSBkaXN0YW5jZSBvZlxuICAgKiB3U2l6ZS1NQVhfTUFUQ0ggYnl0ZXMsIGJ1dCB0aGlzIGVuc3VyZXMgdGhhdCBJTyBpcyBhbHdheXNcbiAgICogcGVyZm9ybWVkIHdpdGggYSBsZW5ndGggbXVsdGlwbGUgb2YgdGhlIGJsb2NrIHNpemUuXG4gICAqL1xuXG4gIHRoaXMud2luZG93X3NpemUgPSAwO1xuICAvKiBBY3R1YWwgc2l6ZSBvZiB3aW5kb3c6IDIqd1NpemUsIGV4Y2VwdCB3aGVuIHRoZSB1c2VyIGlucHV0IGJ1ZmZlclxuICAgKiBpcyBkaXJlY3RseSB1c2VkIGFzIHNsaWRpbmcgd2luZG93LlxuICAgKi9cblxuICB0aGlzLnByZXYgPSBudWxsO1xuICAvKiBMaW5rIHRvIG9sZGVyIHN0cmluZyB3aXRoIHNhbWUgaGFzaCBpbmRleC4gVG8gbGltaXQgdGhlIHNpemUgb2YgdGhpc1xuICAgKiBhcnJheSB0byA2NEssIHRoaXMgbGluayBpcyBtYWludGFpbmVkIG9ubHkgZm9yIHRoZSBsYXN0IDMySyBzdHJpbmdzLlxuICAgKiBBbiBpbmRleCBpbiB0aGlzIGFycmF5IGlzIHRodXMgYSB3aW5kb3cgaW5kZXggbW9kdWxvIDMySy5cbiAgICovXG5cbiAgdGhpcy5oZWFkID0gbnVsbDsgICAvKiBIZWFkcyBvZiB0aGUgaGFzaCBjaGFpbnMgb3IgTklMLiAqL1xuXG4gIHRoaXMuaW5zX2ggPSAwOyAgICAgICAvKiBoYXNoIGluZGV4IG9mIHN0cmluZyB0byBiZSBpbnNlcnRlZCAqL1xuICB0aGlzLmhhc2hfc2l6ZSA9IDA7ICAgLyogbnVtYmVyIG9mIGVsZW1lbnRzIGluIGhhc2ggdGFibGUgKi9cbiAgdGhpcy5oYXNoX2JpdHMgPSAwOyAgIC8qIGxvZzIoaGFzaF9zaXplKSAqL1xuICB0aGlzLmhhc2hfbWFzayA9IDA7ICAgLyogaGFzaF9zaXplLTEgKi9cblxuICB0aGlzLmhhc2hfc2hpZnQgPSAwO1xuICAvKiBOdW1iZXIgb2YgYml0cyBieSB3aGljaCBpbnNfaCBtdXN0IGJlIHNoaWZ0ZWQgYXQgZWFjaCBpbnB1dFxuICAgKiBzdGVwLiBJdCBtdXN0IGJlIHN1Y2ggdGhhdCBhZnRlciBNSU5fTUFUQ0ggc3RlcHMsIHRoZSBvbGRlc3RcbiAgICogYnl0ZSBubyBsb25nZXIgdGFrZXMgcGFydCBpbiB0aGUgaGFzaCBrZXksIHRoYXQgaXM6XG4gICAqICAgaGFzaF9zaGlmdCAqIE1JTl9NQVRDSCA+PSBoYXNoX2JpdHNcbiAgICovXG5cbiAgdGhpcy5ibG9ja19zdGFydCA9IDA7XG4gIC8qIFdpbmRvdyBwb3NpdGlvbiBhdCB0aGUgYmVnaW5uaW5nIG9mIHRoZSBjdXJyZW50IG91dHB1dCBibG9jay4gR2V0c1xuICAgKiBuZWdhdGl2ZSB3aGVuIHRoZSB3aW5kb3cgaXMgbW92ZWQgYmFja3dhcmRzLlxuICAgKi9cblxuICB0aGlzLm1hdGNoX2xlbmd0aCA9IDA7ICAgICAgLyogbGVuZ3RoIG9mIGJlc3QgbWF0Y2ggKi9cbiAgdGhpcy5wcmV2X21hdGNoID0gMDsgICAgICAgIC8qIHByZXZpb3VzIG1hdGNoICovXG4gIHRoaXMubWF0Y2hfYXZhaWxhYmxlID0gMDsgICAvKiBzZXQgaWYgcHJldmlvdXMgbWF0Y2ggZXhpc3RzICovXG4gIHRoaXMuc3Ryc3RhcnQgPSAwOyAgICAgICAgICAvKiBzdGFydCBvZiBzdHJpbmcgdG8gaW5zZXJ0ICovXG4gIHRoaXMubWF0Y2hfc3RhcnQgPSAwOyAgICAgICAvKiBzdGFydCBvZiBtYXRjaGluZyBzdHJpbmcgKi9cbiAgdGhpcy5sb29rYWhlYWQgPSAwOyAgICAgICAgIC8qIG51bWJlciBvZiB2YWxpZCBieXRlcyBhaGVhZCBpbiB3aW5kb3cgKi9cblxuICB0aGlzLnByZXZfbGVuZ3RoID0gMDtcbiAgLyogTGVuZ3RoIG9mIHRoZSBiZXN0IG1hdGNoIGF0IHByZXZpb3VzIHN0ZXAuIE1hdGNoZXMgbm90IGdyZWF0ZXIgdGhhbiB0aGlzXG4gICAqIGFyZSBkaXNjYXJkZWQuIFRoaXMgaXMgdXNlZCBpbiB0aGUgbGF6eSBtYXRjaCBldmFsdWF0aW9uLlxuICAgKi9cblxuICB0aGlzLm1heF9jaGFpbl9sZW5ndGggPSAwO1xuICAvKiBUbyBzcGVlZCB1cCBkZWZsYXRpb24sIGhhc2ggY2hhaW5zIGFyZSBuZXZlciBzZWFyY2hlZCBiZXlvbmQgdGhpc1xuICAgKiBsZW5ndGguICBBIGhpZ2hlciBsaW1pdCBpbXByb3ZlcyBjb21wcmVzc2lvbiByYXRpbyBidXQgZGVncmFkZXMgdGhlXG4gICAqIHNwZWVkLlxuICAgKi9cblxuICB0aGlzLm1heF9sYXp5X21hdGNoID0gMDtcbiAgLyogQXR0ZW1wdCB0byBmaW5kIGEgYmV0dGVyIG1hdGNoIG9ubHkgd2hlbiB0aGUgY3VycmVudCBtYXRjaCBpcyBzdHJpY3RseVxuICAgKiBzbWFsbGVyIHRoYW4gdGhpcyB2YWx1ZS4gVGhpcyBtZWNoYW5pc20gaXMgdXNlZCBvbmx5IGZvciBjb21wcmVzc2lvblxuICAgKiBsZXZlbHMgPj0gNC5cbiAgICovXG4gIC8vIFRoYXQncyBhbGlhcyB0byBtYXhfbGF6eV9tYXRjaCwgZG9uJ3QgdXNlIGRpcmVjdGx5XG4gIC8vdGhpcy5tYXhfaW5zZXJ0X2xlbmd0aCA9IDA7XG4gIC8qIEluc2VydCBuZXcgc3RyaW5ncyBpbiB0aGUgaGFzaCB0YWJsZSBvbmx5IGlmIHRoZSBtYXRjaCBsZW5ndGggaXMgbm90XG4gICAqIGdyZWF0ZXIgdGhhbiB0aGlzIGxlbmd0aC4gVGhpcyBzYXZlcyB0aW1lIGJ1dCBkZWdyYWRlcyBjb21wcmVzc2lvbi5cbiAgICogbWF4X2luc2VydF9sZW5ndGggaXMgdXNlZCBvbmx5IGZvciBjb21wcmVzc2lvbiBsZXZlbHMgPD0gMy5cbiAgICovXG5cbiAgdGhpcy5sZXZlbCA9IDA7ICAgICAvKiBjb21wcmVzc2lvbiBsZXZlbCAoMS4uOSkgKi9cbiAgdGhpcy5zdHJhdGVneSA9IDA7ICAvKiBmYXZvciBvciBmb3JjZSBIdWZmbWFuIGNvZGluZyovXG5cbiAgdGhpcy5nb29kX21hdGNoID0gMDtcbiAgLyogVXNlIGEgZmFzdGVyIHNlYXJjaCB3aGVuIHRoZSBwcmV2aW91cyBtYXRjaCBpcyBsb25nZXIgdGhhbiB0aGlzICovXG5cbiAgdGhpcy5uaWNlX21hdGNoID0gMDsgLyogU3RvcCBzZWFyY2hpbmcgd2hlbiBjdXJyZW50IG1hdGNoIGV4Y2VlZHMgdGhpcyAqL1xuXG4gICAgICAgICAgICAgIC8qIHVzZWQgYnkgdHJlZXMuYzogKi9cblxuICAvKiBEaWRuJ3QgdXNlIGN0X2RhdGEgdHlwZWRlZiBiZWxvdyB0byBzdXBwcmVzcyBjb21waWxlciB3YXJuaW5nICovXG5cbiAgLy8gc3RydWN0IGN0X2RhdGFfcyBkeW5fbHRyZWVbSEVBUF9TSVpFXTsgICAvKiBsaXRlcmFsIGFuZCBsZW5ndGggdHJlZSAqL1xuICAvLyBzdHJ1Y3QgY3RfZGF0YV9zIGR5bl9kdHJlZVsyKkRfQ09ERVMrMV07IC8qIGRpc3RhbmNlIHRyZWUgKi9cbiAgLy8gc3RydWN0IGN0X2RhdGFfcyBibF90cmVlWzIqQkxfQ09ERVMrMV07ICAvKiBIdWZmbWFuIHRyZWUgZm9yIGJpdCBsZW5ndGhzICovXG5cbiAgLy8gVXNlIGZsYXQgYXJyYXkgb2YgRE9VQkxFIHNpemUsIHdpdGggaW50ZXJsZWF2ZWQgZmF0YSxcbiAgLy8gYmVjYXVzZSBKUyBkb2VzIG5vdCBzdXBwb3J0IGVmZmVjdGl2ZVxuICB0aGlzLmR5bl9sdHJlZSAgPSBuZXcgdXRpbHMuQnVmMTYoSEVBUF9TSVpFICogMik7XG4gIHRoaXMuZHluX2R0cmVlICA9IG5ldyB1dGlscy5CdWYxNigoMipEX0NPREVTKzEpICogMik7XG4gIHRoaXMuYmxfdHJlZSAgICA9IG5ldyB1dGlscy5CdWYxNigoMipCTF9DT0RFUysxKSAqIDIpO1xuICB6ZXJvKHRoaXMuZHluX2x0cmVlKTtcbiAgemVybyh0aGlzLmR5bl9kdHJlZSk7XG4gIHplcm8odGhpcy5ibF90cmVlKTtcblxuICB0aGlzLmxfZGVzYyAgID0gbnVsbDsgICAgICAgICAvKiBkZXNjLiBmb3IgbGl0ZXJhbCB0cmVlICovXG4gIHRoaXMuZF9kZXNjICAgPSBudWxsOyAgICAgICAgIC8qIGRlc2MuIGZvciBkaXN0YW5jZSB0cmVlICovXG4gIHRoaXMuYmxfZGVzYyAgPSBudWxsOyAgICAgICAgIC8qIGRlc2MuIGZvciBiaXQgbGVuZ3RoIHRyZWUgKi9cblxuICAvL3VzaCBibF9jb3VudFtNQVhfQklUUysxXTtcbiAgdGhpcy5ibF9jb3VudCA9IG5ldyB1dGlscy5CdWYxNihNQVhfQklUUysxKTtcbiAgLyogbnVtYmVyIG9mIGNvZGVzIGF0IGVhY2ggYml0IGxlbmd0aCBmb3IgYW4gb3B0aW1hbCB0cmVlICovXG5cbiAgLy9pbnQgaGVhcFsyKkxfQ09ERVMrMV07ICAgICAgLyogaGVhcCB1c2VkIHRvIGJ1aWxkIHRoZSBIdWZmbWFuIHRyZWVzICovXG4gIHRoaXMuaGVhcCA9IG5ldyB1dGlscy5CdWYxNigyKkxfQ09ERVMrMSk7ICAvKiBoZWFwIHVzZWQgdG8gYnVpbGQgdGhlIEh1ZmZtYW4gdHJlZXMgKi9cbiAgemVybyh0aGlzLmhlYXApO1xuXG4gIHRoaXMuaGVhcF9sZW4gPSAwOyAgICAgICAgICAgICAgIC8qIG51bWJlciBvZiBlbGVtZW50cyBpbiB0aGUgaGVhcCAqL1xuICB0aGlzLmhlYXBfbWF4ID0gMDsgICAgICAgICAgICAgICAvKiBlbGVtZW50IG9mIGxhcmdlc3QgZnJlcXVlbmN5ICovXG4gIC8qIFRoZSBzb25zIG9mIGhlYXBbbl0gYXJlIGhlYXBbMipuXSBhbmQgaGVhcFsyKm4rMV0uIGhlYXBbMF0gaXMgbm90IHVzZWQuXG4gICAqIFRoZSBzYW1lIGhlYXAgYXJyYXkgaXMgdXNlZCB0byBidWlsZCBhbGwgdHJlZXMuXG4gICAqL1xuXG4gIHRoaXMuZGVwdGggPSBuZXcgdXRpbHMuQnVmMTYoMipMX0NPREVTKzEpOyAvL3VjaCBkZXB0aFsyKkxfQ09ERVMrMV07XG4gIHplcm8odGhpcy5kZXB0aCk7XG4gIC8qIERlcHRoIG9mIGVhY2ggc3VidHJlZSB1c2VkIGFzIHRpZSBicmVha2VyIGZvciB0cmVlcyBvZiBlcXVhbCBmcmVxdWVuY3lcbiAgICovXG5cbiAgdGhpcy5sX2J1ZiA9IDA7ICAgICAgICAgIC8qIGJ1ZmZlciBpbmRleCBmb3IgbGl0ZXJhbHMgb3IgbGVuZ3RocyAqL1xuXG4gIHRoaXMubGl0X2J1ZnNpemUgPSAwO1xuICAvKiBTaXplIG9mIG1hdGNoIGJ1ZmZlciBmb3IgbGl0ZXJhbHMvbGVuZ3Rocy4gIFRoZXJlIGFyZSA0IHJlYXNvbnMgZm9yXG4gICAqIGxpbWl0aW5nIGxpdF9idWZzaXplIHRvIDY0SzpcbiAgICogICAtIGZyZXF1ZW5jaWVzIGNhbiBiZSBrZXB0IGluIDE2IGJpdCBjb3VudGVyc1xuICAgKiAgIC0gaWYgY29tcHJlc3Npb24gaXMgbm90IHN1Y2Nlc3NmdWwgZm9yIHRoZSBmaXJzdCBibG9jaywgYWxsIGlucHV0XG4gICAqICAgICBkYXRhIGlzIHN0aWxsIGluIHRoZSB3aW5kb3cgc28gd2UgY2FuIHN0aWxsIGVtaXQgYSBzdG9yZWQgYmxvY2sgZXZlblxuICAgKiAgICAgd2hlbiBpbnB1dCBjb21lcyBmcm9tIHN0YW5kYXJkIGlucHV0LiAgKFRoaXMgY2FuIGFsc28gYmUgZG9uZSBmb3JcbiAgICogICAgIGFsbCBibG9ja3MgaWYgbGl0X2J1ZnNpemUgaXMgbm90IGdyZWF0ZXIgdGhhbiAzMksuKVxuICAgKiAgIC0gaWYgY29tcHJlc3Npb24gaXMgbm90IHN1Y2Nlc3NmdWwgZm9yIGEgZmlsZSBzbWFsbGVyIHRoYW4gNjRLLCB3ZSBjYW5cbiAgICogICAgIGV2ZW4gZW1pdCBhIHN0b3JlZCBmaWxlIGluc3RlYWQgb2YgYSBzdG9yZWQgYmxvY2sgKHNhdmluZyA1IGJ5dGVzKS5cbiAgICogICAgIFRoaXMgaXMgYXBwbGljYWJsZSBvbmx5IGZvciB6aXAgKG5vdCBnemlwIG9yIHpsaWIpLlxuICAgKiAgIC0gY3JlYXRpbmcgbmV3IEh1ZmZtYW4gdHJlZXMgbGVzcyBmcmVxdWVudGx5IG1heSBub3QgcHJvdmlkZSBmYXN0XG4gICAqICAgICBhZGFwdGF0aW9uIHRvIGNoYW5nZXMgaW4gdGhlIGlucHV0IGRhdGEgc3RhdGlzdGljcy4gKFRha2UgZm9yXG4gICAqICAgICBleGFtcGxlIGEgYmluYXJ5IGZpbGUgd2l0aCBwb29ybHkgY29tcHJlc3NpYmxlIGNvZGUgZm9sbG93ZWQgYnlcbiAgICogICAgIGEgaGlnaGx5IGNvbXByZXNzaWJsZSBzdHJpbmcgdGFibGUuKSBTbWFsbGVyIGJ1ZmZlciBzaXplcyBnaXZlXG4gICAqICAgICBmYXN0IGFkYXB0YXRpb24gYnV0IGhhdmUgb2YgY291cnNlIHRoZSBvdmVyaGVhZCBvZiB0cmFuc21pdHRpbmdcbiAgICogICAgIHRyZWVzIG1vcmUgZnJlcXVlbnRseS5cbiAgICogICAtIEkgY2FuJ3QgY291bnQgYWJvdmUgNFxuICAgKi9cblxuICB0aGlzLmxhc3RfbGl0ID0gMDsgICAgICAvKiBydW5uaW5nIGluZGV4IGluIGxfYnVmICovXG5cbiAgdGhpcy5kX2J1ZiA9IDA7XG4gIC8qIEJ1ZmZlciBpbmRleCBmb3IgZGlzdGFuY2VzLiBUbyBzaW1wbGlmeSB0aGUgY29kZSwgZF9idWYgYW5kIGxfYnVmIGhhdmVcbiAgICogdGhlIHNhbWUgbnVtYmVyIG9mIGVsZW1lbnRzLiBUbyB1c2UgZGlmZmVyZW50IGxlbmd0aHMsIGFuIGV4dHJhIGZsYWdcbiAgICogYXJyYXkgd291bGQgYmUgbmVjZXNzYXJ5LlxuICAgKi9cblxuICB0aGlzLm9wdF9sZW4gPSAwOyAgICAgICAvKiBiaXQgbGVuZ3RoIG9mIGN1cnJlbnQgYmxvY2sgd2l0aCBvcHRpbWFsIHRyZWVzICovXG4gIHRoaXMuc3RhdGljX2xlbiA9IDA7ICAgIC8qIGJpdCBsZW5ndGggb2YgY3VycmVudCBibG9jayB3aXRoIHN0YXRpYyB0cmVlcyAqL1xuICB0aGlzLm1hdGNoZXMgPSAwOyAgICAgICAvKiBudW1iZXIgb2Ygc3RyaW5nIG1hdGNoZXMgaW4gY3VycmVudCBibG9jayAqL1xuICB0aGlzLmluc2VydCA9IDA7ICAgICAgICAvKiBieXRlcyBhdCBlbmQgb2Ygd2luZG93IGxlZnQgdG8gaW5zZXJ0ICovXG5cblxuICB0aGlzLmJpX2J1ZiA9IDA7XG4gIC8qIE91dHB1dCBidWZmZXIuIGJpdHMgYXJlIGluc2VydGVkIHN0YXJ0aW5nIGF0IHRoZSBib3R0b20gKGxlYXN0XG4gICAqIHNpZ25pZmljYW50IGJpdHMpLlxuICAgKi9cbiAgdGhpcy5iaV92YWxpZCA9IDA7XG4gIC8qIE51bWJlciBvZiB2YWxpZCBiaXRzIGluIGJpX2J1Zi4gIEFsbCBiaXRzIGFib3ZlIHRoZSBsYXN0IHZhbGlkIGJpdFxuICAgKiBhcmUgYWx3YXlzIHplcm8uXG4gICAqL1xuXG4gIC8vIFVzZWQgZm9yIHdpbmRvdyBtZW1vcnkgaW5pdC4gV2Ugc2FmZWx5IGlnbm9yZSBpdCBmb3IgSlMuIFRoYXQgbWFrZXNcbiAgLy8gc2Vuc2Ugb25seSBmb3IgcG9pbnRlcnMgYW5kIG1lbW9yeSBjaGVjayB0b29scy5cbiAgLy90aGlzLmhpZ2hfd2F0ZXIgPSAwO1xuICAvKiBIaWdoIHdhdGVyIG1hcmsgb2Zmc2V0IGluIHdpbmRvdyBmb3IgaW5pdGlhbGl6ZWQgYnl0ZXMgLS0gYnl0ZXMgYWJvdmVcbiAgICogdGhpcyBhcmUgc2V0IHRvIHplcm8gaW4gb3JkZXIgdG8gYXZvaWQgbWVtb3J5IGNoZWNrIHdhcm5pbmdzIHdoZW5cbiAgICogbG9uZ2VzdCBtYXRjaCByb3V0aW5lcyBhY2Nlc3MgYnl0ZXMgcGFzdCB0aGUgaW5wdXQuICBUaGlzIGlzIHRoZW5cbiAgICogdXBkYXRlZCB0byB0aGUgbmV3IGhpZ2ggd2F0ZXIgbWFyay5cbiAgICovXG59XG5cblxuZnVuY3Rpb24gZGVmbGF0ZVJlc2V0S2VlcChzdHJtKSB7XG4gIHZhciBzO1xuXG4gIGlmICghc3RybSB8fCAhc3RybS5zdGF0ZSkge1xuICAgIHJldHVybiBlcnIoc3RybSwgWl9TVFJFQU1fRVJST1IpO1xuICB9XG5cbiAgc3RybS50b3RhbF9pbiA9IHN0cm0udG90YWxfb3V0ID0gMDtcbiAgc3RybS5kYXRhX3R5cGUgPSBaX1VOS05PV047XG5cbiAgcyA9IHN0cm0uc3RhdGU7XG4gIHMucGVuZGluZyA9IDA7XG4gIHMucGVuZGluZ19vdXQgPSAwO1xuXG4gIGlmIChzLndyYXAgPCAwKSB7XG4gICAgcy53cmFwID0gLXMud3JhcDtcbiAgICAvKiB3YXMgbWFkZSBuZWdhdGl2ZSBieSBkZWZsYXRlKC4uLiwgWl9GSU5JU0gpOyAqL1xuICB9XG4gIHMuc3RhdHVzID0gKHMud3JhcCA/IElOSVRfU1RBVEUgOiBCVVNZX1NUQVRFKTtcbiAgc3RybS5hZGxlciA9IChzLndyYXAgPT09IDIpID9cbiAgICAwICAvLyBjcmMzMigwLCBaX05VTEwsIDApXG4gIDpcbiAgICAxOyAvLyBhZGxlcjMyKDAsIFpfTlVMTCwgMClcbiAgcy5sYXN0X2ZsdXNoID0gWl9OT19GTFVTSDtcbiAgdHJlZXMuX3RyX2luaXQocyk7XG4gIHJldHVybiBaX09LO1xufVxuXG5cbmZ1bmN0aW9uIGRlZmxhdGVSZXNldChzdHJtKSB7XG4gIHZhciByZXQgPSBkZWZsYXRlUmVzZXRLZWVwKHN0cm0pO1xuICBpZiAocmV0ID09PSBaX09LKSB7XG4gICAgbG1faW5pdChzdHJtLnN0YXRlKTtcbiAgfVxuICByZXR1cm4gcmV0O1xufVxuXG5cbmZ1bmN0aW9uIGRlZmxhdGVTZXRIZWFkZXIoc3RybSwgaGVhZCkge1xuICBpZiAoIXN0cm0gfHwgIXN0cm0uc3RhdGUpIHsgcmV0dXJuIFpfU1RSRUFNX0VSUk9SOyB9XG4gIGlmIChzdHJtLnN0YXRlLndyYXAgIT09IDIpIHsgcmV0dXJuIFpfU1RSRUFNX0VSUk9SOyB9XG4gIHN0cm0uc3RhdGUuZ3poZWFkID0gaGVhZDtcbiAgcmV0dXJuIFpfT0s7XG59XG5cblxuZnVuY3Rpb24gZGVmbGF0ZUluaXQyKHN0cm0sIGxldmVsLCBtZXRob2QsIHdpbmRvd0JpdHMsIG1lbUxldmVsLCBzdHJhdGVneSkge1xuICBpZiAoIXN0cm0pIHsgLy8gPT09IFpfTlVMTFxuICAgIHJldHVybiBaX1NUUkVBTV9FUlJPUjtcbiAgfVxuICB2YXIgd3JhcCA9IDE7XG5cbiAgaWYgKGxldmVsID09PSBaX0RFRkFVTFRfQ09NUFJFU1NJT04pIHtcbiAgICBsZXZlbCA9IDY7XG4gIH1cblxuICBpZiAod2luZG93Qml0cyA8IDApIHsgLyogc3VwcHJlc3MgemxpYiB3cmFwcGVyICovXG4gICAgd3JhcCA9IDA7XG4gICAgd2luZG93Qml0cyA9IC13aW5kb3dCaXRzO1xuICB9XG5cbiAgZWxzZSBpZiAod2luZG93Qml0cyA+IDE1KSB7XG4gICAgd3JhcCA9IDI7ICAgICAgICAgICAvKiB3cml0ZSBnemlwIHdyYXBwZXIgaW5zdGVhZCAqL1xuICAgIHdpbmRvd0JpdHMgLT0gMTY7XG4gIH1cblxuXG4gIGlmIChtZW1MZXZlbCA8IDEgfHwgbWVtTGV2ZWwgPiBNQVhfTUVNX0xFVkVMIHx8IG1ldGhvZCAhPT0gWl9ERUZMQVRFRCB8fFxuICAgIHdpbmRvd0JpdHMgPCA4IHx8IHdpbmRvd0JpdHMgPiAxNSB8fCBsZXZlbCA8IDAgfHwgbGV2ZWwgPiA5IHx8XG4gICAgc3RyYXRlZ3kgPCAwIHx8IHN0cmF0ZWd5ID4gWl9GSVhFRCkge1xuICAgIHJldHVybiBlcnIoc3RybSwgWl9TVFJFQU1fRVJST1IpO1xuICB9XG5cblxuICBpZiAod2luZG93Qml0cyA9PT0gOCkge1xuICAgIHdpbmRvd0JpdHMgPSA5O1xuICB9XG4gIC8qIHVudGlsIDI1Ni1ieXRlIHdpbmRvdyBidWcgZml4ZWQgKi9cblxuICB2YXIgcyA9IG5ldyBEZWZsYXRlU3RhdGUoKTtcblxuICBzdHJtLnN0YXRlID0gcztcbiAgcy5zdHJtID0gc3RybTtcblxuICBzLndyYXAgPSB3cmFwO1xuICBzLmd6aGVhZCA9IG51bGw7XG4gIHMud19iaXRzID0gd2luZG93Qml0cztcbiAgcy53X3NpemUgPSAxIDw8IHMud19iaXRzO1xuICBzLndfbWFzayA9IHMud19zaXplIC0gMTtcblxuICBzLmhhc2hfYml0cyA9IG1lbUxldmVsICsgNztcbiAgcy5oYXNoX3NpemUgPSAxIDw8IHMuaGFzaF9iaXRzO1xuICBzLmhhc2hfbWFzayA9IHMuaGFzaF9zaXplIC0gMTtcbiAgcy5oYXNoX3NoaWZ0ID0gfn4oKHMuaGFzaF9iaXRzICsgTUlOX01BVENIIC0gMSkgLyBNSU5fTUFUQ0gpO1xuXG4gIHMud2luZG93ID0gbmV3IHV0aWxzLkJ1Zjgocy53X3NpemUgKiAyKTtcbiAgcy5oZWFkID0gbmV3IHV0aWxzLkJ1ZjE2KHMuaGFzaF9zaXplKTtcbiAgcy5wcmV2ID0gbmV3IHV0aWxzLkJ1ZjE2KHMud19zaXplKTtcblxuICAvLyBEb24ndCBuZWVkIG1lbSBpbml0IG1hZ2ljIGZvciBKUy5cbiAgLy9zLmhpZ2hfd2F0ZXIgPSAwOyAgLyogbm90aGluZyB3cml0dGVuIHRvIHMtPndpbmRvdyB5ZXQgKi9cblxuICBzLmxpdF9idWZzaXplID0gMSA8PCAobWVtTGV2ZWwgKyA2KTsgLyogMTZLIGVsZW1lbnRzIGJ5IGRlZmF1bHQgKi9cblxuICBzLnBlbmRpbmdfYnVmX3NpemUgPSBzLmxpdF9idWZzaXplICogNDtcbiAgcy5wZW5kaW5nX2J1ZiA9IG5ldyB1dGlscy5CdWY4KHMucGVuZGluZ19idWZfc2l6ZSk7XG5cbiAgcy5kX2J1ZiA9IHMubGl0X2J1ZnNpemUgPj4gMTtcbiAgcy5sX2J1ZiA9ICgxICsgMikgKiBzLmxpdF9idWZzaXplO1xuXG4gIHMubGV2ZWwgPSBsZXZlbDtcbiAgcy5zdHJhdGVneSA9IHN0cmF0ZWd5O1xuICBzLm1ldGhvZCA9IG1ldGhvZDtcblxuICByZXR1cm4gZGVmbGF0ZVJlc2V0KHN0cm0pO1xufVxuXG5mdW5jdGlvbiBkZWZsYXRlSW5pdChzdHJtLCBsZXZlbCkge1xuICByZXR1cm4gZGVmbGF0ZUluaXQyKHN0cm0sIGxldmVsLCBaX0RFRkxBVEVELCBNQVhfV0JJVFMsIERFRl9NRU1fTEVWRUwsIFpfREVGQVVMVF9TVFJBVEVHWSk7XG59XG5cblxuZnVuY3Rpb24gZGVmbGF0ZShzdHJtLCBmbHVzaCkge1xuICB2YXIgb2xkX2ZsdXNoLCBzO1xuICB2YXIgYmVnLCB2YWw7IC8vIGZvciBnemlwIGhlYWRlciB3cml0ZSBvbmx5XG5cbiAgaWYgKCFzdHJtIHx8ICFzdHJtLnN0YXRlIHx8XG4gICAgZmx1c2ggPiBaX0JMT0NLIHx8IGZsdXNoIDwgMCkge1xuICAgIHJldHVybiBzdHJtID8gZXJyKHN0cm0sIFpfU1RSRUFNX0VSUk9SKSA6IFpfU1RSRUFNX0VSUk9SO1xuICB9XG5cbiAgcyA9IHN0cm0uc3RhdGU7XG5cbiAgaWYgKCFzdHJtLm91dHB1dCB8fFxuICAgICAgKCFzdHJtLmlucHV0ICYmIHN0cm0uYXZhaWxfaW4gIT09IDApIHx8XG4gICAgICAocy5zdGF0dXMgPT09IEZJTklTSF9TVEFURSAmJiBmbHVzaCAhPT0gWl9GSU5JU0gpKSB7XG4gICAgcmV0dXJuIGVycihzdHJtLCAoc3RybS5hdmFpbF9vdXQgPT09IDApID8gWl9CVUZfRVJST1IgOiBaX1NUUkVBTV9FUlJPUik7XG4gIH1cblxuICBzLnN0cm0gPSBzdHJtOyAvKiBqdXN0IGluIGNhc2UgKi9cbiAgb2xkX2ZsdXNoID0gcy5sYXN0X2ZsdXNoO1xuICBzLmxhc3RfZmx1c2ggPSBmbHVzaDtcblxuICAvKiBXcml0ZSB0aGUgaGVhZGVyICovXG4gIGlmIChzLnN0YXR1cyA9PT0gSU5JVF9TVEFURSkge1xuXG4gICAgaWYgKHMud3JhcCA9PT0gMikgeyAvLyBHWklQIGhlYWRlclxuICAgICAgc3RybS5hZGxlciA9IDA7ICAvL2NyYzMyKDBMLCBaX05VTEwsIDApO1xuICAgICAgcHV0X2J5dGUocywgMzEpO1xuICAgICAgcHV0X2J5dGUocywgMTM5KTtcbiAgICAgIHB1dF9ieXRlKHMsIDgpO1xuICAgICAgaWYgKCFzLmd6aGVhZCkgeyAvLyBzLT5nemhlYWQgPT0gWl9OVUxMXG4gICAgICAgIHB1dF9ieXRlKHMsIDApO1xuICAgICAgICBwdXRfYnl0ZShzLCAwKTtcbiAgICAgICAgcHV0X2J5dGUocywgMCk7XG4gICAgICAgIHB1dF9ieXRlKHMsIDApO1xuICAgICAgICBwdXRfYnl0ZShzLCAwKTtcbiAgICAgICAgcHV0X2J5dGUocywgcy5sZXZlbCA9PT0gOSA/IDIgOlxuICAgICAgICAgICAgICAgICAgICAocy5zdHJhdGVneSA+PSBaX0hVRkZNQU5fT05MWSB8fCBzLmxldmVsIDwgMiA/XG4gICAgICAgICAgICAgICAgICAgICA0IDogMCkpO1xuICAgICAgICBwdXRfYnl0ZShzLCBPU19DT0RFKTtcbiAgICAgICAgcy5zdGF0dXMgPSBCVVNZX1NUQVRFO1xuICAgICAgfVxuICAgICAgZWxzZSB7XG4gICAgICAgIHB1dF9ieXRlKHMsIChzLmd6aGVhZC50ZXh0ID8gMSA6IDApICtcbiAgICAgICAgICAgICAgICAgICAgKHMuZ3poZWFkLmhjcmMgPyAyIDogMCkgK1xuICAgICAgICAgICAgICAgICAgICAoIXMuZ3poZWFkLmV4dHJhID8gMCA6IDQpICtcbiAgICAgICAgICAgICAgICAgICAgKCFzLmd6aGVhZC5uYW1lID8gMCA6IDgpICtcbiAgICAgICAgICAgICAgICAgICAgKCFzLmd6aGVhZC5jb21tZW50ID8gMCA6IDE2KVxuICAgICAgICAgICAgICAgICk7XG4gICAgICAgIHB1dF9ieXRlKHMsIHMuZ3poZWFkLnRpbWUgJiAweGZmKTtcbiAgICAgICAgcHV0X2J5dGUocywgKHMuZ3poZWFkLnRpbWUgPj4gOCkgJiAweGZmKTtcbiAgICAgICAgcHV0X2J5dGUocywgKHMuZ3poZWFkLnRpbWUgPj4gMTYpICYgMHhmZik7XG4gICAgICAgIHB1dF9ieXRlKHMsIChzLmd6aGVhZC50aW1lID4+IDI0KSAmIDB4ZmYpO1xuICAgICAgICBwdXRfYnl0ZShzLCBzLmxldmVsID09PSA5ID8gMiA6XG4gICAgICAgICAgICAgICAgICAgIChzLnN0cmF0ZWd5ID49IFpfSFVGRk1BTl9PTkxZIHx8IHMubGV2ZWwgPCAyID9cbiAgICAgICAgICAgICAgICAgICAgIDQgOiAwKSk7XG4gICAgICAgIHB1dF9ieXRlKHMsIHMuZ3poZWFkLm9zICYgMHhmZik7XG4gICAgICAgIGlmIChzLmd6aGVhZC5leHRyYSAmJiBzLmd6aGVhZC5leHRyYS5sZW5ndGgpIHtcbiAgICAgICAgICBwdXRfYnl0ZShzLCBzLmd6aGVhZC5leHRyYS5sZW5ndGggJiAweGZmKTtcbiAgICAgICAgICBwdXRfYnl0ZShzLCAocy5nemhlYWQuZXh0cmEubGVuZ3RoID4+IDgpICYgMHhmZik7XG4gICAgICAgIH1cbiAgICAgICAgaWYgKHMuZ3poZWFkLmhjcmMpIHtcbiAgICAgICAgICBzdHJtLmFkbGVyID0gY3JjMzIoc3RybS5hZGxlciwgcy5wZW5kaW5nX2J1Ziwgcy5wZW5kaW5nLCAwKTtcbiAgICAgICAgfVxuICAgICAgICBzLmd6aW5kZXggPSAwO1xuICAgICAgICBzLnN0YXR1cyA9IEVYVFJBX1NUQVRFO1xuICAgICAgfVxuICAgIH1cbiAgICBlbHNlIC8vIERFRkxBVEUgaGVhZGVyXG4gICAge1xuICAgICAgdmFyIGhlYWRlciA9IChaX0RFRkxBVEVEICsgKChzLndfYml0cyAtIDgpIDw8IDQpKSA8PCA4O1xuICAgICAgdmFyIGxldmVsX2ZsYWdzID0gLTE7XG5cbiAgICAgIGlmIChzLnN0cmF0ZWd5ID49IFpfSFVGRk1BTl9PTkxZIHx8IHMubGV2ZWwgPCAyKSB7XG4gICAgICAgIGxldmVsX2ZsYWdzID0gMDtcbiAgICAgIH0gZWxzZSBpZiAocy5sZXZlbCA8IDYpIHtcbiAgICAgICAgbGV2ZWxfZmxhZ3MgPSAxO1xuICAgICAgfSBlbHNlIGlmIChzLmxldmVsID09PSA2KSB7XG4gICAgICAgIGxldmVsX2ZsYWdzID0gMjtcbiAgICAgIH0gZWxzZSB7XG4gICAgICAgIGxldmVsX2ZsYWdzID0gMztcbiAgICAgIH1cbiAgICAgIGhlYWRlciB8PSAobGV2ZWxfZmxhZ3MgPDwgNik7XG4gICAgICBpZiAocy5zdHJzdGFydCAhPT0gMCkgeyBoZWFkZXIgfD0gUFJFU0VUX0RJQ1Q7IH1cbiAgICAgIGhlYWRlciArPSAzMSAtIChoZWFkZXIgJSAzMSk7XG5cbiAgICAgIHMuc3RhdHVzID0gQlVTWV9TVEFURTtcbiAgICAgIHB1dFNob3J0TVNCKHMsIGhlYWRlcik7XG5cbiAgICAgIC8qIFNhdmUgdGhlIGFkbGVyMzIgb2YgdGhlIHByZXNldCBkaWN0aW9uYXJ5OiAqL1xuICAgICAgaWYgKHMuc3Ryc3RhcnQgIT09IDApIHtcbiAgICAgICAgcHV0U2hvcnRNU0Iocywgc3RybS5hZGxlciA+Pj4gMTYpO1xuICAgICAgICBwdXRTaG9ydE1TQihzLCBzdHJtLmFkbGVyICYgMHhmZmZmKTtcbiAgICAgIH1cbiAgICAgIHN0cm0uYWRsZXIgPSAxOyAvLyBhZGxlcjMyKDBMLCBaX05VTEwsIDApO1xuICAgIH1cbiAgfVxuXG4vLyNpZmRlZiBHWklQXG4gIGlmIChzLnN0YXR1cyA9PT0gRVhUUkFfU1RBVEUpIHtcbiAgICBpZiAocy5nemhlYWQuZXh0cmEvKiAhPSBaX05VTEwqLykge1xuICAgICAgYmVnID0gcy5wZW5kaW5nOyAgLyogc3RhcnQgb2YgYnl0ZXMgdG8gdXBkYXRlIGNyYyAqL1xuXG4gICAgICB3aGlsZSAocy5nemluZGV4IDwgKHMuZ3poZWFkLmV4dHJhLmxlbmd0aCAmIDB4ZmZmZikpIHtcbiAgICAgICAgaWYgKHMucGVuZGluZyA9PT0gcy5wZW5kaW5nX2J1Zl9zaXplKSB7XG4gICAgICAgICAgaWYgKHMuZ3poZWFkLmhjcmMgJiYgcy5wZW5kaW5nID4gYmVnKSB7XG4gICAgICAgICAgICBzdHJtLmFkbGVyID0gY3JjMzIoc3RybS5hZGxlciwgcy5wZW5kaW5nX2J1Ziwgcy5wZW5kaW5nIC0gYmVnLCBiZWcpO1xuICAgICAgICAgIH1cbiAgICAgICAgICBmbHVzaF9wZW5kaW5nKHN0cm0pO1xuICAgICAgICAgIGJlZyA9IHMucGVuZGluZztcbiAgICAgICAgICBpZiAocy5wZW5kaW5nID09PSBzLnBlbmRpbmdfYnVmX3NpemUpIHtcbiAgICAgICAgICAgIGJyZWFrO1xuICAgICAgICAgIH1cbiAgICAgICAgfVxuICAgICAgICBwdXRfYnl0ZShzLCBzLmd6aGVhZC5leHRyYVtzLmd6aW5kZXhdICYgMHhmZik7XG4gICAgICAgIHMuZ3ppbmRleCsrO1xuICAgICAgfVxuICAgICAgaWYgKHMuZ3poZWFkLmhjcmMgJiYgcy5wZW5kaW5nID4gYmVnKSB7XG4gICAgICAgIHN0cm0uYWRsZXIgPSBjcmMzMihzdHJtLmFkbGVyLCBzLnBlbmRpbmdfYnVmLCBzLnBlbmRpbmcgLSBiZWcsIGJlZyk7XG4gICAgICB9XG4gICAgICBpZiAocy5nemluZGV4ID09PSBzLmd6aGVhZC5leHRyYS5sZW5ndGgpIHtcbiAgICAgICAgcy5nemluZGV4ID0gMDtcbiAgICAgICAgcy5zdGF0dXMgPSBOQU1FX1NUQVRFO1xuICAgICAgfVxuICAgIH1cbiAgICBlbHNlIHtcbiAgICAgIHMuc3RhdHVzID0gTkFNRV9TVEFURTtcbiAgICB9XG4gIH1cbiAgaWYgKHMuc3RhdHVzID09PSBOQU1FX1NUQVRFKSB7XG4gICAgaWYgKHMuZ3poZWFkLm5hbWUvKiAhPSBaX05VTEwqLykge1xuICAgICAgYmVnID0gcy5wZW5kaW5nOyAgLyogc3RhcnQgb2YgYnl0ZXMgdG8gdXBkYXRlIGNyYyAqL1xuICAgICAgLy9pbnQgdmFsO1xuXG4gICAgICBkbyB7XG4gICAgICAgIGlmIChzLnBlbmRpbmcgPT09IHMucGVuZGluZ19idWZfc2l6ZSkge1xuICAgICAgICAgIGlmIChzLmd6aGVhZC5oY3JjICYmIHMucGVuZGluZyA+IGJlZykge1xuICAgICAgICAgICAgc3RybS5hZGxlciA9IGNyYzMyKHN0cm0uYWRsZXIsIHMucGVuZGluZ19idWYsIHMucGVuZGluZyAtIGJlZywgYmVnKTtcbiAgICAgICAgICB9XG4gICAgICAgICAgZmx1c2hfcGVuZGluZyhzdHJtKTtcbiAgICAgICAgICBiZWcgPSBzLnBlbmRpbmc7XG4gICAgICAgICAgaWYgKHMucGVuZGluZyA9PT0gcy5wZW5kaW5nX2J1Zl9zaXplKSB7XG4gICAgICAgICAgICB2YWwgPSAxO1xuICAgICAgICAgICAgYnJlYWs7XG4gICAgICAgICAgfVxuICAgICAgICB9XG4gICAgICAgIC8vIEpTIHNwZWNpZmljOiBsaXR0bGUgbWFnaWMgdG8gYWRkIHplcm8gdGVybWluYXRvciB0byBlbmQgb2Ygc3RyaW5nXG4gICAgICAgIGlmIChzLmd6aW5kZXggPCBzLmd6aGVhZC5uYW1lLmxlbmd0aCkge1xuICAgICAgICAgIHZhbCA9IHMuZ3poZWFkLm5hbWUuY2hhckNvZGVBdChzLmd6aW5kZXgrKykgJiAweGZmO1xuICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgIHZhbCA9IDA7XG4gICAgICAgIH1cbiAgICAgICAgcHV0X2J5dGUocywgdmFsKTtcbiAgICAgIH0gd2hpbGUgKHZhbCAhPT0gMCk7XG5cbiAgICAgIGlmIChzLmd6aGVhZC5oY3JjICYmIHMucGVuZGluZyA+IGJlZykge1xuICAgICAgICBzdHJtLmFkbGVyID0gY3JjMzIoc3RybS5hZGxlciwgcy5wZW5kaW5nX2J1Ziwgcy5wZW5kaW5nIC0gYmVnLCBiZWcpO1xuICAgICAgfVxuICAgICAgaWYgKHZhbCA9PT0gMCkge1xuICAgICAgICBzLmd6aW5kZXggPSAwO1xuICAgICAgICBzLnN0YXR1cyA9IENPTU1FTlRfU1RBVEU7XG4gICAgICB9XG4gICAgfVxuICAgIGVsc2Uge1xuICAgICAgcy5zdGF0dXMgPSBDT01NRU5UX1NUQVRFO1xuICAgIH1cbiAgfVxuICBpZiAocy5zdGF0dXMgPT09IENPTU1FTlRfU1RBVEUpIHtcbiAgICBpZiAocy5nemhlYWQuY29tbWVudC8qICE9IFpfTlVMTCovKSB7XG4gICAgICBiZWcgPSBzLnBlbmRpbmc7ICAvKiBzdGFydCBvZiBieXRlcyB0byB1cGRhdGUgY3JjICovXG4gICAgICAvL2ludCB2YWw7XG5cbiAgICAgIGRvIHtcbiAgICAgICAgaWYgKHMucGVuZGluZyA9PT0gcy5wZW5kaW5nX2J1Zl9zaXplKSB7XG4gICAgICAgICAgaWYgKHMuZ3poZWFkLmhjcmMgJiYgcy5wZW5kaW5nID4gYmVnKSB7XG4gICAgICAgICAgICBzdHJtLmFkbGVyID0gY3JjMzIoc3RybS5hZGxlciwgcy5wZW5kaW5nX2J1Ziwgcy5wZW5kaW5nIC0gYmVnLCBiZWcpO1xuICAgICAgICAgIH1cbiAgICAgICAgICBmbHVzaF9wZW5kaW5nKHN0cm0pO1xuICAgICAgICAgIGJlZyA9IHMucGVuZGluZztcbiAgICAgICAgICBpZiAocy5wZW5kaW5nID09PSBzLnBlbmRpbmdfYnVmX3NpemUpIHtcbiAgICAgICAgICAgIHZhbCA9IDE7XG4gICAgICAgICAgICBicmVhaztcbiAgICAgICAgICB9XG4gICAgICAgIH1cbiAgICAgICAgLy8gSlMgc3BlY2lmaWM6IGxpdHRsZSBtYWdpYyB0byBhZGQgemVybyB0ZXJtaW5hdG9yIHRvIGVuZCBvZiBzdHJpbmdcbiAgICAgICAgaWYgKHMuZ3ppbmRleCA8IHMuZ3poZWFkLmNvbW1lbnQubGVuZ3RoKSB7XG4gICAgICAgICAgdmFsID0gcy5nemhlYWQuY29tbWVudC5jaGFyQ29kZUF0KHMuZ3ppbmRleCsrKSAmIDB4ZmY7XG4gICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgdmFsID0gMDtcbiAgICAgICAgfVxuICAgICAgICBwdXRfYnl0ZShzLCB2YWwpO1xuICAgICAgfSB3aGlsZSAodmFsICE9PSAwKTtcblxuICAgICAgaWYgKHMuZ3poZWFkLmhjcmMgJiYgcy5wZW5kaW5nID4gYmVnKSB7XG4gICAgICAgIHN0cm0uYWRsZXIgPSBjcmMzMihzdHJtLmFkbGVyLCBzLnBlbmRpbmdfYnVmLCBzLnBlbmRpbmcgLSBiZWcsIGJlZyk7XG4gICAgICB9XG4gICAgICBpZiAodmFsID09PSAwKSB7XG4gICAgICAgIHMuc3RhdHVzID0gSENSQ19TVEFURTtcbiAgICAgIH1cbiAgICB9XG4gICAgZWxzZSB7XG4gICAgICBzLnN0YXR1cyA9IEhDUkNfU1RBVEU7XG4gICAgfVxuICB9XG4gIGlmIChzLnN0YXR1cyA9PT0gSENSQ19TVEFURSkge1xuICAgIGlmIChzLmd6aGVhZC5oY3JjKSB7XG4gICAgICBpZiAocy5wZW5kaW5nICsgMiA+IHMucGVuZGluZ19idWZfc2l6ZSkge1xuICAgICAgICBmbHVzaF9wZW5kaW5nKHN0cm0pO1xuICAgICAgfVxuICAgICAgaWYgKHMucGVuZGluZyArIDIgPD0gcy5wZW5kaW5nX2J1Zl9zaXplKSB7XG4gICAgICAgIHB1dF9ieXRlKHMsIHN0cm0uYWRsZXIgJiAweGZmKTtcbiAgICAgICAgcHV0X2J5dGUocywgKHN0cm0uYWRsZXIgPj4gOCkgJiAweGZmKTtcbiAgICAgICAgc3RybS5hZGxlciA9IDA7IC8vY3JjMzIoMEwsIFpfTlVMTCwgMCk7XG4gICAgICAgIHMuc3RhdHVzID0gQlVTWV9TVEFURTtcbiAgICAgIH1cbiAgICB9XG4gICAgZWxzZSB7XG4gICAgICBzLnN0YXR1cyA9IEJVU1lfU1RBVEU7XG4gICAgfVxuICB9XG4vLyNlbmRpZlxuXG4gIC8qIEZsdXNoIGFzIG11Y2ggcGVuZGluZyBvdXRwdXQgYXMgcG9zc2libGUgKi9cbiAgaWYgKHMucGVuZGluZyAhPT0gMCkge1xuICAgIGZsdXNoX3BlbmRpbmcoc3RybSk7XG4gICAgaWYgKHN0cm0uYXZhaWxfb3V0ID09PSAwKSB7XG4gICAgICAvKiBTaW5jZSBhdmFpbF9vdXQgaXMgMCwgZGVmbGF0ZSB3aWxsIGJlIGNhbGxlZCBhZ2FpbiB3aXRoXG4gICAgICAgKiBtb3JlIG91dHB1dCBzcGFjZSwgYnV0IHBvc3NpYmx5IHdpdGggYm90aCBwZW5kaW5nIGFuZFxuICAgICAgICogYXZhaWxfaW4gZXF1YWwgdG8gemVyby4gVGhlcmUgd29uJ3QgYmUgYW55dGhpbmcgdG8gZG8sXG4gICAgICAgKiBidXQgdGhpcyBpcyBub3QgYW4gZXJyb3Igc2l0dWF0aW9uIHNvIG1ha2Ugc3VyZSB3ZVxuICAgICAgICogcmV0dXJuIE9LIGluc3RlYWQgb2YgQlVGX0VSUk9SIGF0IG5leHQgY2FsbCBvZiBkZWZsYXRlOlxuICAgICAgICovXG4gICAgICBzLmxhc3RfZmx1c2ggPSAtMTtcbiAgICAgIHJldHVybiBaX09LO1xuICAgIH1cblxuICAgIC8qIE1ha2Ugc3VyZSB0aGVyZSBpcyBzb21ldGhpbmcgdG8gZG8gYW5kIGF2b2lkIGR1cGxpY2F0ZSBjb25zZWN1dGl2ZVxuICAgICAqIGZsdXNoZXMuIEZvciByZXBlYXRlZCBhbmQgdXNlbGVzcyBjYWxscyB3aXRoIFpfRklOSVNILCB3ZSBrZWVwXG4gICAgICogcmV0dXJuaW5nIFpfU1RSRUFNX0VORCBpbnN0ZWFkIG9mIFpfQlVGX0VSUk9SLlxuICAgICAqL1xuICB9IGVsc2UgaWYgKHN0cm0uYXZhaWxfaW4gPT09IDAgJiYgcmFuayhmbHVzaCkgPD0gcmFuayhvbGRfZmx1c2gpICYmXG4gICAgZmx1c2ggIT09IFpfRklOSVNIKSB7XG4gICAgcmV0dXJuIGVycihzdHJtLCBaX0JVRl9FUlJPUik7XG4gIH1cblxuICAvKiBVc2VyIG11c3Qgbm90IHByb3ZpZGUgbW9yZSBpbnB1dCBhZnRlciB0aGUgZmlyc3QgRklOSVNIOiAqL1xuICBpZiAocy5zdGF0dXMgPT09IEZJTklTSF9TVEFURSAmJiBzdHJtLmF2YWlsX2luICE9PSAwKSB7XG4gICAgcmV0dXJuIGVycihzdHJtLCBaX0JVRl9FUlJPUik7XG4gIH1cblxuICAvKiBTdGFydCBhIG5ldyBibG9jayBvciBjb250aW51ZSB0aGUgY3VycmVudCBvbmUuXG4gICAqL1xuICBpZiAoc3RybS5hdmFpbF9pbiAhPT0gMCB8fCBzLmxvb2thaGVhZCAhPT0gMCB8fFxuICAgIChmbHVzaCAhPT0gWl9OT19GTFVTSCAmJiBzLnN0YXR1cyAhPT0gRklOSVNIX1NUQVRFKSkge1xuICAgIHZhciBic3RhdGUgPSAocy5zdHJhdGVneSA9PT0gWl9IVUZGTUFOX09OTFkpID8gZGVmbGF0ZV9odWZmKHMsIGZsdXNoKSA6XG4gICAgICAocy5zdHJhdGVneSA9PT0gWl9STEUgPyBkZWZsYXRlX3JsZShzLCBmbHVzaCkgOlxuICAgICAgICBjb25maWd1cmF0aW9uX3RhYmxlW3MubGV2ZWxdLmZ1bmMocywgZmx1c2gpKTtcblxuICAgIGlmIChic3RhdGUgPT09IEJTX0ZJTklTSF9TVEFSVEVEIHx8IGJzdGF0ZSA9PT0gQlNfRklOSVNIX0RPTkUpIHtcbiAgICAgIHMuc3RhdHVzID0gRklOSVNIX1NUQVRFO1xuICAgIH1cbiAgICBpZiAoYnN0YXRlID09PSBCU19ORUVEX01PUkUgfHwgYnN0YXRlID09PSBCU19GSU5JU0hfU1RBUlRFRCkge1xuICAgICAgaWYgKHN0cm0uYXZhaWxfb3V0ID09PSAwKSB7XG4gICAgICAgIHMubGFzdF9mbHVzaCA9IC0xO1xuICAgICAgICAvKiBhdm9pZCBCVUZfRVJST1IgbmV4dCBjYWxsLCBzZWUgYWJvdmUgKi9cbiAgICAgIH1cbiAgICAgIHJldHVybiBaX09LO1xuICAgICAgLyogSWYgZmx1c2ggIT0gWl9OT19GTFVTSCAmJiBhdmFpbF9vdXQgPT0gMCwgdGhlIG5leHQgY2FsbFxuICAgICAgICogb2YgZGVmbGF0ZSBzaG91bGQgdXNlIHRoZSBzYW1lIGZsdXNoIHBhcmFtZXRlciB0byBtYWtlIHN1cmVcbiAgICAgICAqIHRoYXQgdGhlIGZsdXNoIGlzIGNvbXBsZXRlLiBTbyB3ZSBkb24ndCBoYXZlIHRvIG91dHB1dCBhblxuICAgICAgICogZW1wdHkgYmxvY2sgaGVyZSwgdGhpcyB3aWxsIGJlIGRvbmUgYXQgbmV4dCBjYWxsLiBUaGlzIGFsc29cbiAgICAgICAqIGVuc3VyZXMgdGhhdCBmb3IgYSB2ZXJ5IHNtYWxsIG91dHB1dCBidWZmZXIsIHdlIGVtaXQgYXQgbW9zdFxuICAgICAgICogb25lIGVtcHR5IGJsb2NrLlxuICAgICAgICovXG4gICAgfVxuICAgIGlmIChic3RhdGUgPT09IEJTX0JMT0NLX0RPTkUpIHtcbiAgICAgIGlmIChmbHVzaCA9PT0gWl9QQVJUSUFMX0ZMVVNIKSB7XG4gICAgICAgIHRyZWVzLl90cl9hbGlnbihzKTtcbiAgICAgIH1cbiAgICAgIGVsc2UgaWYgKGZsdXNoICE9PSBaX0JMT0NLKSB7IC8qIEZVTExfRkxVU0ggb3IgU1lOQ19GTFVTSCAqL1xuXG4gICAgICAgIHRyZWVzLl90cl9zdG9yZWRfYmxvY2socywgMCwgMCwgZmFsc2UpO1xuICAgICAgICAvKiBGb3IgYSBmdWxsIGZsdXNoLCB0aGlzIGVtcHR5IGJsb2NrIHdpbGwgYmUgcmVjb2duaXplZFxuICAgICAgICAgKiBhcyBhIHNwZWNpYWwgbWFya2VyIGJ5IGluZmxhdGVfc3luYygpLlxuICAgICAgICAgKi9cbiAgICAgICAgaWYgKGZsdXNoID09PSBaX0ZVTExfRkxVU0gpIHtcbiAgICAgICAgICAvKioqIENMRUFSX0hBU0gocyk7ICoqKi8gICAgICAgICAgICAgLyogZm9yZ2V0IGhpc3RvcnkgKi9cbiAgICAgICAgICB6ZXJvKHMuaGVhZCk7IC8vIEZpbGwgd2l0aCBOSUwgKD0gMCk7XG5cbiAgICAgICAgICBpZiAocy5sb29rYWhlYWQgPT09IDApIHtcbiAgICAgICAgICAgIHMuc3Ryc3RhcnQgPSAwO1xuICAgICAgICAgICAgcy5ibG9ja19zdGFydCA9IDA7XG4gICAgICAgICAgICBzLmluc2VydCA9IDA7XG4gICAgICAgICAgfVxuICAgICAgICB9XG4gICAgICB9XG4gICAgICBmbHVzaF9wZW5kaW5nKHN0cm0pO1xuICAgICAgaWYgKHN0cm0uYXZhaWxfb3V0ID09PSAwKSB7XG4gICAgICAgIHMubGFzdF9mbHVzaCA9IC0xOyAvKiBhdm9pZCBCVUZfRVJST1IgYXQgbmV4dCBjYWxsLCBzZWUgYWJvdmUgKi9cbiAgICAgICAgcmV0dXJuIFpfT0s7XG4gICAgICB9XG4gICAgfVxuICB9XG4gIC8vQXNzZXJ0KHN0cm0tPmF2YWlsX291dCA+IDAsIFwiYnVnMlwiKTtcbiAgLy9pZiAoc3RybS5hdmFpbF9vdXQgPD0gMCkgeyB0aHJvdyBuZXcgRXJyb3IoXCJidWcyXCIpO31cblxuICBpZiAoZmx1c2ggIT09IFpfRklOSVNIKSB7IHJldHVybiBaX09LOyB9XG4gIGlmIChzLndyYXAgPD0gMCkgeyByZXR1cm4gWl9TVFJFQU1fRU5EOyB9XG5cbiAgLyogV3JpdGUgdGhlIHRyYWlsZXIgKi9cbiAgaWYgKHMud3JhcCA9PT0gMikge1xuICAgIHB1dF9ieXRlKHMsIHN0cm0uYWRsZXIgJiAweGZmKTtcbiAgICBwdXRfYnl0ZShzLCAoc3RybS5hZGxlciA+PiA4KSAmIDB4ZmYpO1xuICAgIHB1dF9ieXRlKHMsIChzdHJtLmFkbGVyID4+IDE2KSAmIDB4ZmYpO1xuICAgIHB1dF9ieXRlKHMsIChzdHJtLmFkbGVyID4+IDI0KSAmIDB4ZmYpO1xuICAgIHB1dF9ieXRlKHMsIHN0cm0udG90YWxfaW4gJiAweGZmKTtcbiAgICBwdXRfYnl0ZShzLCAoc3RybS50b3RhbF9pbiA+PiA4KSAmIDB4ZmYpO1xuICAgIHB1dF9ieXRlKHMsIChzdHJtLnRvdGFsX2luID4+IDE2KSAmIDB4ZmYpO1xuICAgIHB1dF9ieXRlKHMsIChzdHJtLnRvdGFsX2luID4+IDI0KSAmIDB4ZmYpO1xuICB9XG4gIGVsc2VcbiAge1xuICAgIHB1dFNob3J0TVNCKHMsIHN0cm0uYWRsZXIgPj4+IDE2KTtcbiAgICBwdXRTaG9ydE1TQihzLCBzdHJtLmFkbGVyICYgMHhmZmZmKTtcbiAgfVxuXG4gIGZsdXNoX3BlbmRpbmcoc3RybSk7XG4gIC8qIElmIGF2YWlsX291dCBpcyB6ZXJvLCB0aGUgYXBwbGljYXRpb24gd2lsbCBjYWxsIGRlZmxhdGUgYWdhaW5cbiAgICogdG8gZmx1c2ggdGhlIHJlc3QuXG4gICAqL1xuICBpZiAocy53cmFwID4gMCkgeyBzLndyYXAgPSAtcy53cmFwOyB9XG4gIC8qIHdyaXRlIHRoZSB0cmFpbGVyIG9ubHkgb25jZSEgKi9cbiAgcmV0dXJuIHMucGVuZGluZyAhPT0gMCA/IFpfT0sgOiBaX1NUUkVBTV9FTkQ7XG59XG5cbmZ1bmN0aW9uIGRlZmxhdGVFbmQoc3RybSkge1xuICB2YXIgc3RhdHVzO1xuXG4gIGlmICghc3RybS8qPT0gWl9OVUxMKi8gfHwgIXN0cm0uc3RhdGUvKj09IFpfTlVMTCovKSB7XG4gICAgcmV0dXJuIFpfU1RSRUFNX0VSUk9SO1xuICB9XG5cbiAgc3RhdHVzID0gc3RybS5zdGF0ZS5zdGF0dXM7XG4gIGlmIChzdGF0dXMgIT09IElOSVRfU1RBVEUgJiZcbiAgICBzdGF0dXMgIT09IEVYVFJBX1NUQVRFICYmXG4gICAgc3RhdHVzICE9PSBOQU1FX1NUQVRFICYmXG4gICAgc3RhdHVzICE9PSBDT01NRU5UX1NUQVRFICYmXG4gICAgc3RhdHVzICE9PSBIQ1JDX1NUQVRFICYmXG4gICAgc3RhdHVzICE9PSBCVVNZX1NUQVRFICYmXG4gICAgc3RhdHVzICE9PSBGSU5JU0hfU1RBVEVcbiAgKSB7XG4gICAgcmV0dXJuIGVycihzdHJtLCBaX1NUUkVBTV9FUlJPUik7XG4gIH1cblxuICBzdHJtLnN0YXRlID0gbnVsbDtcblxuICByZXR1cm4gc3RhdHVzID09PSBCVVNZX1NUQVRFID8gZXJyKHN0cm0sIFpfREFUQV9FUlJPUikgOiBaX09LO1xufVxuXG4vKiA9PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09XG4gKiBDb3B5IHRoZSBzb3VyY2Ugc3RhdGUgdG8gdGhlIGRlc3RpbmF0aW9uIHN0YXRlXG4gKi9cbi8vZnVuY3Rpb24gZGVmbGF0ZUNvcHkoZGVzdCwgc291cmNlKSB7XG4vL1xuLy99XG5cbmV4cG9ydHMuZGVmbGF0ZUluaXQgPSBkZWZsYXRlSW5pdDtcbmV4cG9ydHMuZGVmbGF0ZUluaXQyID0gZGVmbGF0ZUluaXQyO1xuZXhwb3J0cy5kZWZsYXRlUmVzZXQgPSBkZWZsYXRlUmVzZXQ7XG5leHBvcnRzLmRlZmxhdGVSZXNldEtlZXAgPSBkZWZsYXRlUmVzZXRLZWVwO1xuZXhwb3J0cy5kZWZsYXRlU2V0SGVhZGVyID0gZGVmbGF0ZVNldEhlYWRlcjtcbmV4cG9ydHMuZGVmbGF0ZSA9IGRlZmxhdGU7XG5leHBvcnRzLmRlZmxhdGVFbmQgPSBkZWZsYXRlRW5kO1xuZXhwb3J0cy5kZWZsYXRlSW5mbyA9ICdwYWtvIGRlZmxhdGUgKGZyb20gTm9kZWNhIHByb2plY3QpJztcblxuLyogTm90IGltcGxlbWVudGVkXG5leHBvcnRzLmRlZmxhdGVCb3VuZCA9IGRlZmxhdGVCb3VuZDtcbmV4cG9ydHMuZGVmbGF0ZUNvcHkgPSBkZWZsYXRlQ29weTtcbmV4cG9ydHMuZGVmbGF0ZVNldERpY3Rpb25hcnkgPSBkZWZsYXRlU2V0RGljdGlvbmFyeTtcbmV4cG9ydHMuZGVmbGF0ZVBhcmFtcyA9IGRlZmxhdGVQYXJhbXM7XG5leHBvcnRzLmRlZmxhdGVQZW5kaW5nID0gZGVmbGF0ZVBlbmRpbmc7XG5leHBvcnRzLmRlZmxhdGVQcmltZSA9IGRlZmxhdGVQcmltZTtcbmV4cG9ydHMuZGVmbGF0ZVR1bmUgPSBkZWZsYXRlVHVuZTtcbiovXG4iLCIndXNlIHN0cmljdCc7XG5cblxuZnVuY3Rpb24gR1poZWFkZXIoKSB7XG4gIC8qIHRydWUgaWYgY29tcHJlc3NlZCBkYXRhIGJlbGlldmVkIHRvIGJlIHRleHQgKi9cbiAgdGhpcy50ZXh0ICAgICAgID0gMDtcbiAgLyogbW9kaWZpY2F0aW9uIHRpbWUgKi9cbiAgdGhpcy50aW1lICAgICAgID0gMDtcbiAgLyogZXh0cmEgZmxhZ3MgKG5vdCB1c2VkIHdoZW4gd3JpdGluZyBhIGd6aXAgZmlsZSkgKi9cbiAgdGhpcy54ZmxhZ3MgICAgID0gMDtcbiAgLyogb3BlcmF0aW5nIHN5c3RlbSAqL1xuICB0aGlzLm9zICAgICAgICAgPSAwO1xuICAvKiBwb2ludGVyIHRvIGV4dHJhIGZpZWxkIG9yIFpfTlVMTCBpZiBub25lICovXG4gIHRoaXMuZXh0cmEgICAgICA9IG51bGw7XG4gIC8qIGV4dHJhIGZpZWxkIGxlbmd0aCAodmFsaWQgaWYgZXh0cmEgIT0gWl9OVUxMKSAqL1xuICB0aGlzLmV4dHJhX2xlbiAgPSAwOyAvLyBBY3R1YWxseSwgd2UgZG9uJ3QgbmVlZCBpdCBpbiBKUyxcbiAgICAgICAgICAgICAgICAgICAgICAgLy8gYnV0IGxlYXZlIGZvciBmZXcgY29kZSBtb2RpZmljYXRpb25zXG5cbiAgLy9cbiAgLy8gU2V0dXAgbGltaXRzIGlzIG5vdCBuZWNlc3NhcnkgYmVjYXVzZSBpbiBqcyB3ZSBzaG91bGQgbm90IHByZWFsbG9jYXRlIG1lbW9yeVxuICAvLyBmb3IgaW5mbGF0ZSB1c2UgY29uc3RhbnQgbGltaXQgaW4gNjU1MzYgYnl0ZXNcbiAgLy9cblxuICAvKiBzcGFjZSBhdCBleHRyYSAob25seSB3aGVuIHJlYWRpbmcgaGVhZGVyKSAqL1xuICAvLyB0aGlzLmV4dHJhX21heCAgPSAwO1xuICAvKiBwb2ludGVyIHRvIHplcm8tdGVybWluYXRlZCBmaWxlIG5hbWUgb3IgWl9OVUxMICovXG4gIHRoaXMubmFtZSAgICAgICA9ICcnO1xuICAvKiBzcGFjZSBhdCBuYW1lIChvbmx5IHdoZW4gcmVhZGluZyBoZWFkZXIpICovXG4gIC8vIHRoaXMubmFtZV9tYXggICA9IDA7XG4gIC8qIHBvaW50ZXIgdG8gemVyby10ZXJtaW5hdGVkIGNvbW1lbnQgb3IgWl9OVUxMICovXG4gIHRoaXMuY29tbWVudCAgICA9ICcnO1xuICAvKiBzcGFjZSBhdCBjb21tZW50IChvbmx5IHdoZW4gcmVhZGluZyBoZWFkZXIpICovXG4gIC8vIHRoaXMuY29tbV9tYXggICA9IDA7XG4gIC8qIHRydWUgaWYgdGhlcmUgd2FzIG9yIHdpbGwgYmUgYSBoZWFkZXIgY3JjICovXG4gIHRoaXMuaGNyYyAgICAgICA9IDA7XG4gIC8qIHRydWUgd2hlbiBkb25lIHJlYWRpbmcgZ3ppcCBoZWFkZXIgKG5vdCB1c2VkIHdoZW4gd3JpdGluZyBhIGd6aXAgZmlsZSkgKi9cbiAgdGhpcy5kb25lICAgICAgID0gZmFsc2U7XG59XG5cbm1vZHVsZS5leHBvcnRzID0gR1poZWFkZXI7XG4iLCIndXNlIHN0cmljdCc7XG5cbi8vIFNlZSBzdGF0ZSBkZWZzIGZyb20gaW5mbGF0ZS5qc1xudmFyIEJBRCA9IDMwOyAgICAgICAvKiBnb3QgYSBkYXRhIGVycm9yIC0tIHJlbWFpbiBoZXJlIHVudGlsIHJlc2V0ICovXG52YXIgVFlQRSA9IDEyOyAgICAgIC8qIGk6IHdhaXRpbmcgZm9yIHR5cGUgYml0cywgaW5jbHVkaW5nIGxhc3QtZmxhZyBiaXQgKi9cblxuLypcbiAgIERlY29kZSBsaXRlcmFsLCBsZW5ndGgsIGFuZCBkaXN0YW5jZSBjb2RlcyBhbmQgd3JpdGUgb3V0IHRoZSByZXN1bHRpbmdcbiAgIGxpdGVyYWwgYW5kIG1hdGNoIGJ5dGVzIHVudGlsIGVpdGhlciBub3QgZW5vdWdoIGlucHV0IG9yIG91dHB1dCBpc1xuICAgYXZhaWxhYmxlLCBhbiBlbmQtb2YtYmxvY2sgaXMgZW5jb3VudGVyZWQsIG9yIGEgZGF0YSBlcnJvciBpcyBlbmNvdW50ZXJlZC5cbiAgIFdoZW4gbGFyZ2UgZW5vdWdoIGlucHV0IGFuZCBvdXRwdXQgYnVmZmVycyBhcmUgc3VwcGxpZWQgdG8gaW5mbGF0ZSgpLCBmb3JcbiAgIGV4YW1wbGUsIGEgMTZLIGlucHV0IGJ1ZmZlciBhbmQgYSA2NEsgb3V0cHV0IGJ1ZmZlciwgbW9yZSB0aGFuIDk1JSBvZiB0aGVcbiAgIGluZmxhdGUgZXhlY3V0aW9uIHRpbWUgaXMgc3BlbnQgaW4gdGhpcyByb3V0aW5lLlxuXG4gICBFbnRyeSBhc3N1bXB0aW9uczpcblxuICAgICAgICBzdGF0ZS5tb2RlID09PSBMRU5cbiAgICAgICAgc3RybS5hdmFpbF9pbiA+PSA2XG4gICAgICAgIHN0cm0uYXZhaWxfb3V0ID49IDI1OFxuICAgICAgICBzdGFydCA+PSBzdHJtLmF2YWlsX291dFxuICAgICAgICBzdGF0ZS5iaXRzIDwgOFxuXG4gICBPbiByZXR1cm4sIHN0YXRlLm1vZGUgaXMgb25lIG9mOlxuXG4gICAgICAgIExFTiAtLSByYW4gb3V0IG9mIGVub3VnaCBvdXRwdXQgc3BhY2Ugb3IgZW5vdWdoIGF2YWlsYWJsZSBpbnB1dFxuICAgICAgICBUWVBFIC0tIHJlYWNoZWQgZW5kIG9mIGJsb2NrIGNvZGUsIGluZmxhdGUoKSB0byBpbnRlcnByZXQgbmV4dCBibG9ja1xuICAgICAgICBCQUQgLS0gZXJyb3IgaW4gYmxvY2sgZGF0YVxuXG4gICBOb3RlczpcblxuICAgIC0gVGhlIG1heGltdW0gaW5wdXQgYml0cyB1c2VkIGJ5IGEgbGVuZ3RoL2Rpc3RhbmNlIHBhaXIgaXMgMTUgYml0cyBmb3IgdGhlXG4gICAgICBsZW5ndGggY29kZSwgNSBiaXRzIGZvciB0aGUgbGVuZ3RoIGV4dHJhLCAxNSBiaXRzIGZvciB0aGUgZGlzdGFuY2UgY29kZSxcbiAgICAgIGFuZCAxMyBiaXRzIGZvciB0aGUgZGlzdGFuY2UgZXh0cmEuICBUaGlzIHRvdGFscyA0OCBiaXRzLCBvciBzaXggYnl0ZXMuXG4gICAgICBUaGVyZWZvcmUgaWYgc3RybS5hdmFpbF9pbiA+PSA2LCB0aGVuIHRoZXJlIGlzIGVub3VnaCBpbnB1dCB0byBhdm9pZFxuICAgICAgY2hlY2tpbmcgZm9yIGF2YWlsYWJsZSBpbnB1dCB3aGlsZSBkZWNvZGluZy5cblxuICAgIC0gVGhlIG1heGltdW0gYnl0ZXMgdGhhdCBhIHNpbmdsZSBsZW5ndGgvZGlzdGFuY2UgcGFpciBjYW4gb3V0cHV0IGlzIDI1OFxuICAgICAgYnl0ZXMsIHdoaWNoIGlzIHRoZSBtYXhpbXVtIGxlbmd0aCB0aGF0IGNhbiBiZSBjb2RlZC4gIGluZmxhdGVfZmFzdCgpXG4gICAgICByZXF1aXJlcyBzdHJtLmF2YWlsX291dCA+PSAyNTggZm9yIGVhY2ggbG9vcCB0byBhdm9pZCBjaGVja2luZyBmb3JcbiAgICAgIG91dHB1dCBzcGFjZS5cbiAqL1xubW9kdWxlLmV4cG9ydHMgPSBmdW5jdGlvbiBpbmZsYXRlX2Zhc3Qoc3RybSwgc3RhcnQpIHtcbiAgdmFyIHN0YXRlO1xuICB2YXIgX2luOyAgICAgICAgICAgICAgICAgICAgLyogbG9jYWwgc3RybS5pbnB1dCAqL1xuICB2YXIgbGFzdDsgICAgICAgICAgICAgICAgICAgLyogaGF2ZSBlbm91Z2ggaW5wdXQgd2hpbGUgaW4gPCBsYXN0ICovXG4gIHZhciBfb3V0OyAgICAgICAgICAgICAgICAgICAvKiBsb2NhbCBzdHJtLm91dHB1dCAqL1xuICB2YXIgYmVnOyAgICAgICAgICAgICAgICAgICAgLyogaW5mbGF0ZSgpJ3MgaW5pdGlhbCBzdHJtLm91dHB1dCAqL1xuICB2YXIgZW5kOyAgICAgICAgICAgICAgICAgICAgLyogd2hpbGUgb3V0IDwgZW5kLCBlbm91Z2ggc3BhY2UgYXZhaWxhYmxlICovXG4vLyNpZmRlZiBJTkZMQVRFX1NUUklDVFxuICB2YXIgZG1heDsgICAgICAgICAgICAgICAgICAgLyogbWF4aW11bSBkaXN0YW5jZSBmcm9tIHpsaWIgaGVhZGVyICovXG4vLyNlbmRpZlxuICB2YXIgd3NpemU7ICAgICAgICAgICAgICAgICAgLyogd2luZG93IHNpemUgb3IgemVybyBpZiBub3QgdXNpbmcgd2luZG93ICovXG4gIHZhciB3aGF2ZTsgICAgICAgICAgICAgICAgICAvKiB2YWxpZCBieXRlcyBpbiB0aGUgd2luZG93ICovXG4gIHZhciB3bmV4dDsgICAgICAgICAgICAgICAgICAvKiB3aW5kb3cgd3JpdGUgaW5kZXggKi9cbiAgLy8gVXNlIGBzX3dpbmRvd2AgaW5zdGVhZCBgd2luZG93YCwgYXZvaWQgY29uZmxpY3Qgd2l0aCBpbnN0cnVtZW50YXRpb24gdG9vbHNcbiAgdmFyIHNfd2luZG93OyAgICAgICAgICAgICAgIC8qIGFsbG9jYXRlZCBzbGlkaW5nIHdpbmRvdywgaWYgd3NpemUgIT0gMCAqL1xuICB2YXIgaG9sZDsgICAgICAgICAgICAgICAgICAgLyogbG9jYWwgc3RybS5ob2xkICovXG4gIHZhciBiaXRzOyAgICAgICAgICAgICAgICAgICAvKiBsb2NhbCBzdHJtLmJpdHMgKi9cbiAgdmFyIGxjb2RlOyAgICAgICAgICAgICAgICAgIC8qIGxvY2FsIHN0cm0ubGVuY29kZSAqL1xuICB2YXIgZGNvZGU7ICAgICAgICAgICAgICAgICAgLyogbG9jYWwgc3RybS5kaXN0Y29kZSAqL1xuICB2YXIgbG1hc2s7ICAgICAgICAgICAgICAgICAgLyogbWFzayBmb3IgZmlyc3QgbGV2ZWwgb2YgbGVuZ3RoIGNvZGVzICovXG4gIHZhciBkbWFzazsgICAgICAgICAgICAgICAgICAvKiBtYXNrIGZvciBmaXJzdCBsZXZlbCBvZiBkaXN0YW5jZSBjb2RlcyAqL1xuICB2YXIgaGVyZTsgICAgICAgICAgICAgICAgICAgLyogcmV0cmlldmVkIHRhYmxlIGVudHJ5ICovXG4gIHZhciBvcDsgICAgICAgICAgICAgICAgICAgICAvKiBjb2RlIGJpdHMsIG9wZXJhdGlvbiwgZXh0cmEgYml0cywgb3IgKi9cbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIC8qICB3aW5kb3cgcG9zaXRpb24sIHdpbmRvdyBieXRlcyB0byBjb3B5ICovXG4gIHZhciBsZW47ICAgICAgICAgICAgICAgICAgICAvKiBtYXRjaCBsZW5ndGgsIHVudXNlZCBieXRlcyAqL1xuICB2YXIgZGlzdDsgICAgICAgICAgICAgICAgICAgLyogbWF0Y2ggZGlzdGFuY2UgKi9cbiAgdmFyIGZyb207ICAgICAgICAgICAgICAgICAgIC8qIHdoZXJlIHRvIGNvcHkgbWF0Y2ggZnJvbSAqL1xuICB2YXIgZnJvbV9zb3VyY2U7XG5cblxuICB2YXIgaW5wdXQsIG91dHB1dDsgLy8gSlMgc3BlY2lmaWMsIGJlY2F1c2Ugd2UgaGF2ZSBubyBwb2ludGVyc1xuXG4gIC8qIGNvcHkgc3RhdGUgdG8gbG9jYWwgdmFyaWFibGVzICovXG4gIHN0YXRlID0gc3RybS5zdGF0ZTtcbiAgLy9oZXJlID0gc3RhdGUuaGVyZTtcbiAgX2luID0gc3RybS5uZXh0X2luO1xuICBpbnB1dCA9IHN0cm0uaW5wdXQ7XG4gIGxhc3QgPSBfaW4gKyAoc3RybS5hdmFpbF9pbiAtIDUpO1xuICBfb3V0ID0gc3RybS5uZXh0X291dDtcbiAgb3V0cHV0ID0gc3RybS5vdXRwdXQ7XG4gIGJlZyA9IF9vdXQgLSAoc3RhcnQgLSBzdHJtLmF2YWlsX291dCk7XG4gIGVuZCA9IF9vdXQgKyAoc3RybS5hdmFpbF9vdXQgLSAyNTcpO1xuLy8jaWZkZWYgSU5GTEFURV9TVFJJQ1RcbiAgZG1heCA9IHN0YXRlLmRtYXg7XG4vLyNlbmRpZlxuICB3c2l6ZSA9IHN0YXRlLndzaXplO1xuICB3aGF2ZSA9IHN0YXRlLndoYXZlO1xuICB3bmV4dCA9IHN0YXRlLnduZXh0O1xuICBzX3dpbmRvdyA9IHN0YXRlLndpbmRvdztcbiAgaG9sZCA9IHN0YXRlLmhvbGQ7XG4gIGJpdHMgPSBzdGF0ZS5iaXRzO1xuICBsY29kZSA9IHN0YXRlLmxlbmNvZGU7XG4gIGRjb2RlID0gc3RhdGUuZGlzdGNvZGU7XG4gIGxtYXNrID0gKDEgPDwgc3RhdGUubGVuYml0cykgLSAxO1xuICBkbWFzayA9ICgxIDw8IHN0YXRlLmRpc3RiaXRzKSAtIDE7XG5cblxuICAvKiBkZWNvZGUgbGl0ZXJhbHMgYW5kIGxlbmd0aC9kaXN0YW5jZXMgdW50aWwgZW5kLW9mLWJsb2NrIG9yIG5vdCBlbm91Z2hcbiAgICAgaW5wdXQgZGF0YSBvciBvdXRwdXQgc3BhY2UgKi9cblxuICB0b3A6XG4gIGRvIHtcbiAgICBpZiAoYml0cyA8IDE1KSB7XG4gICAgICBob2xkICs9IGlucHV0W19pbisrXSA8PCBiaXRzO1xuICAgICAgYml0cyArPSA4O1xuICAgICAgaG9sZCArPSBpbnB1dFtfaW4rK10gPDwgYml0cztcbiAgICAgIGJpdHMgKz0gODtcbiAgICB9XG5cbiAgICBoZXJlID0gbGNvZGVbaG9sZCAmIGxtYXNrXTtcblxuICAgIGRvbGVuOlxuICAgIGZvciAoOzspIHsgLy8gR290byBlbXVsYXRpb25cbiAgICAgIG9wID0gaGVyZSA+Pj4gMjQvKmhlcmUuYml0cyovO1xuICAgICAgaG9sZCA+Pj49IG9wO1xuICAgICAgYml0cyAtPSBvcDtcbiAgICAgIG9wID0gKGhlcmUgPj4+IDE2KSAmIDB4ZmYvKmhlcmUub3AqLztcbiAgICAgIGlmIChvcCA9PT0gMCkgeyAgICAgICAgICAgICAgICAgICAgICAgICAgLyogbGl0ZXJhbCAqL1xuICAgICAgICAvL1RyYWNldnYoKHN0ZGVyciwgaGVyZS52YWwgPj0gMHgyMCAmJiBoZXJlLnZhbCA8IDB4N2YgP1xuICAgICAgICAvLyAgICAgICAgXCJpbmZsYXRlOiAgICAgICAgIGxpdGVyYWwgJyVjJ1xcblwiIDpcbiAgICAgICAgLy8gICAgICAgIFwiaW5mbGF0ZTogICAgICAgICBsaXRlcmFsIDB4JTAyeFxcblwiLCBoZXJlLnZhbCkpO1xuICAgICAgICBvdXRwdXRbX291dCsrXSA9IGhlcmUgJiAweGZmZmYvKmhlcmUudmFsKi87XG4gICAgICB9XG4gICAgICBlbHNlIGlmIChvcCAmIDE2KSB7ICAgICAgICAgICAgICAgICAgICAgLyogbGVuZ3RoIGJhc2UgKi9cbiAgICAgICAgbGVuID0gaGVyZSAmIDB4ZmZmZi8qaGVyZS52YWwqLztcbiAgICAgICAgb3AgJj0gMTU7ICAgICAgICAgICAgICAgICAgICAgICAgICAgLyogbnVtYmVyIG9mIGV4dHJhIGJpdHMgKi9cbiAgICAgICAgaWYgKG9wKSB7XG4gICAgICAgICAgaWYgKGJpdHMgPCBvcCkge1xuICAgICAgICAgICAgaG9sZCArPSBpbnB1dFtfaW4rK10gPDwgYml0cztcbiAgICAgICAgICAgIGJpdHMgKz0gODtcbiAgICAgICAgICB9XG4gICAgICAgICAgbGVuICs9IGhvbGQgJiAoKDEgPDwgb3ApIC0gMSk7XG4gICAgICAgICAgaG9sZCA+Pj49IG9wO1xuICAgICAgICAgIGJpdHMgLT0gb3A7XG4gICAgICAgIH1cbiAgICAgICAgLy9UcmFjZXZ2KChzdGRlcnIsIFwiaW5mbGF0ZTogICAgICAgICBsZW5ndGggJXVcXG5cIiwgbGVuKSk7XG4gICAgICAgIGlmIChiaXRzIDwgMTUpIHtcbiAgICAgICAgICBob2xkICs9IGlucHV0W19pbisrXSA8PCBiaXRzO1xuICAgICAgICAgIGJpdHMgKz0gODtcbiAgICAgICAgICBob2xkICs9IGlucHV0W19pbisrXSA8PCBiaXRzO1xuICAgICAgICAgIGJpdHMgKz0gODtcbiAgICAgICAgfVxuICAgICAgICBoZXJlID0gZGNvZGVbaG9sZCAmIGRtYXNrXTtcblxuICAgICAgICBkb2Rpc3Q6XG4gICAgICAgIGZvciAoOzspIHsgLy8gZ290byBlbXVsYXRpb25cbiAgICAgICAgICBvcCA9IGhlcmUgPj4+IDI0LypoZXJlLmJpdHMqLztcbiAgICAgICAgICBob2xkID4+Pj0gb3A7XG4gICAgICAgICAgYml0cyAtPSBvcDtcbiAgICAgICAgICBvcCA9IChoZXJlID4+PiAxNikgJiAweGZmLypoZXJlLm9wKi87XG5cbiAgICAgICAgICBpZiAob3AgJiAxNikgeyAgICAgICAgICAgICAgICAgICAgICAvKiBkaXN0YW5jZSBiYXNlICovXG4gICAgICAgICAgICBkaXN0ID0gaGVyZSAmIDB4ZmZmZi8qaGVyZS52YWwqLztcbiAgICAgICAgICAgIG9wICY9IDE1OyAgICAgICAgICAgICAgICAgICAgICAgLyogbnVtYmVyIG9mIGV4dHJhIGJpdHMgKi9cbiAgICAgICAgICAgIGlmIChiaXRzIDwgb3ApIHtcbiAgICAgICAgICAgICAgaG9sZCArPSBpbnB1dFtfaW4rK10gPDwgYml0cztcbiAgICAgICAgICAgICAgYml0cyArPSA4O1xuICAgICAgICAgICAgICBpZiAoYml0cyA8IG9wKSB7XG4gICAgICAgICAgICAgICAgaG9sZCArPSBpbnB1dFtfaW4rK10gPDwgYml0cztcbiAgICAgICAgICAgICAgICBiaXRzICs9IDg7XG4gICAgICAgICAgICAgIH1cbiAgICAgICAgICAgIH1cbiAgICAgICAgICAgIGRpc3QgKz0gaG9sZCAmICgoMSA8PCBvcCkgLSAxKTtcbi8vI2lmZGVmIElORkxBVEVfU1RSSUNUXG4gICAgICAgICAgICBpZiAoZGlzdCA+IGRtYXgpIHtcbiAgICAgICAgICAgICAgc3RybS5tc2cgPSAnaW52YWxpZCBkaXN0YW5jZSB0b28gZmFyIGJhY2snO1xuICAgICAgICAgICAgICBzdGF0ZS5tb2RlID0gQkFEO1xuICAgICAgICAgICAgICBicmVhayB0b3A7XG4gICAgICAgICAgICB9XG4vLyNlbmRpZlxuICAgICAgICAgICAgaG9sZCA+Pj49IG9wO1xuICAgICAgICAgICAgYml0cyAtPSBvcDtcbiAgICAgICAgICAgIC8vVHJhY2V2digoc3RkZXJyLCBcImluZmxhdGU6ICAgICAgICAgZGlzdGFuY2UgJXVcXG5cIiwgZGlzdCkpO1xuICAgICAgICAgICAgb3AgPSBfb3V0IC0gYmVnOyAgICAgICAgICAgICAgICAvKiBtYXggZGlzdGFuY2UgaW4gb3V0cHV0ICovXG4gICAgICAgICAgICBpZiAoZGlzdCA+IG9wKSB7ICAgICAgICAgICAgICAgIC8qIHNlZSBpZiBjb3B5IGZyb20gd2luZG93ICovXG4gICAgICAgICAgICAgIG9wID0gZGlzdCAtIG9wOyAgICAgICAgICAgICAgIC8qIGRpc3RhbmNlIGJhY2sgaW4gd2luZG93ICovXG4gICAgICAgICAgICAgIGlmIChvcCA+IHdoYXZlKSB7XG4gICAgICAgICAgICAgICAgaWYgKHN0YXRlLnNhbmUpIHtcbiAgICAgICAgICAgICAgICAgIHN0cm0ubXNnID0gJ2ludmFsaWQgZGlzdGFuY2UgdG9vIGZhciBiYWNrJztcbiAgICAgICAgICAgICAgICAgIHN0YXRlLm1vZGUgPSBCQUQ7XG4gICAgICAgICAgICAgICAgICBicmVhayB0b3A7XG4gICAgICAgICAgICAgICAgfVxuXG4vLyAoISkgVGhpcyBibG9jayBpcyBkaXNhYmxlZCBpbiB6bGliIGRlZmFpbHRzLFxuLy8gZG9uJ3QgZW5hYmxlIGl0IGZvciBiaW5hcnkgY29tcGF0aWJpbGl0eVxuLy8jaWZkZWYgSU5GTEFURV9BTExPV19JTlZBTElEX0RJU1RBTkNFX1RPT0ZBUl9BUlJSXG4vLyAgICAgICAgICAgICAgICBpZiAobGVuIDw9IG9wIC0gd2hhdmUpIHtcbi8vICAgICAgICAgICAgICAgICAgZG8ge1xuLy8gICAgICAgICAgICAgICAgICAgIG91dHB1dFtfb3V0KytdID0gMDtcbi8vICAgICAgICAgICAgICAgICAgfSB3aGlsZSAoLS1sZW4pO1xuLy8gICAgICAgICAgICAgICAgICBjb250aW51ZSB0b3A7XG4vLyAgICAgICAgICAgICAgICB9XG4vLyAgICAgICAgICAgICAgICBsZW4gLT0gb3AgLSB3aGF2ZTtcbi8vICAgICAgICAgICAgICAgIGRvIHtcbi8vICAgICAgICAgICAgICAgICAgb3V0cHV0W19vdXQrK10gPSAwO1xuLy8gICAgICAgICAgICAgICAgfSB3aGlsZSAoLS1vcCA+IHdoYXZlKTtcbi8vICAgICAgICAgICAgICAgIGlmIChvcCA9PT0gMCkge1xuLy8gICAgICAgICAgICAgICAgICBmcm9tID0gX291dCAtIGRpc3Q7XG4vLyAgICAgICAgICAgICAgICAgIGRvIHtcbi8vICAgICAgICAgICAgICAgICAgICBvdXRwdXRbX291dCsrXSA9IG91dHB1dFtmcm9tKytdO1xuLy8gICAgICAgICAgICAgICAgICB9IHdoaWxlICgtLWxlbik7XG4vLyAgICAgICAgICAgICAgICAgIGNvbnRpbnVlIHRvcDtcbi8vICAgICAgICAgICAgICAgIH1cbi8vI2VuZGlmXG4gICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgZnJvbSA9IDA7IC8vIHdpbmRvdyBpbmRleFxuICAgICAgICAgICAgICBmcm9tX3NvdXJjZSA9IHNfd2luZG93O1xuICAgICAgICAgICAgICBpZiAod25leHQgPT09IDApIHsgICAgICAgICAgIC8qIHZlcnkgY29tbW9uIGNhc2UgKi9cbiAgICAgICAgICAgICAgICBmcm9tICs9IHdzaXplIC0gb3A7XG4gICAgICAgICAgICAgICAgaWYgKG9wIDwgbGVuKSB7ICAgICAgICAgLyogc29tZSBmcm9tIHdpbmRvdyAqL1xuICAgICAgICAgICAgICAgICAgbGVuIC09IG9wO1xuICAgICAgICAgICAgICAgICAgZG8ge1xuICAgICAgICAgICAgICAgICAgICBvdXRwdXRbX291dCsrXSA9IHNfd2luZG93W2Zyb20rK107XG4gICAgICAgICAgICAgICAgICB9IHdoaWxlICgtLW9wKTtcbiAgICAgICAgICAgICAgICAgIGZyb20gPSBfb3V0IC0gZGlzdDsgIC8qIHJlc3QgZnJvbSBvdXRwdXQgKi9cbiAgICAgICAgICAgICAgICAgIGZyb21fc291cmNlID0gb3V0cHV0O1xuICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICBlbHNlIGlmICh3bmV4dCA8IG9wKSB7ICAgICAgLyogd3JhcCBhcm91bmQgd2luZG93ICovXG4gICAgICAgICAgICAgICAgZnJvbSArPSB3c2l6ZSArIHduZXh0IC0gb3A7XG4gICAgICAgICAgICAgICAgb3AgLT0gd25leHQ7XG4gICAgICAgICAgICAgICAgaWYgKG9wIDwgbGVuKSB7ICAgICAgICAgLyogc29tZSBmcm9tIGVuZCBvZiB3aW5kb3cgKi9cbiAgICAgICAgICAgICAgICAgIGxlbiAtPSBvcDtcbiAgICAgICAgICAgICAgICAgIGRvIHtcbiAgICAgICAgICAgICAgICAgICAgb3V0cHV0W19vdXQrK10gPSBzX3dpbmRvd1tmcm9tKytdO1xuICAgICAgICAgICAgICAgICAgfSB3aGlsZSAoLS1vcCk7XG4gICAgICAgICAgICAgICAgICBmcm9tID0gMDtcbiAgICAgICAgICAgICAgICAgIGlmICh3bmV4dCA8IGxlbikgeyAgLyogc29tZSBmcm9tIHN0YXJ0IG9mIHdpbmRvdyAqL1xuICAgICAgICAgICAgICAgICAgICBvcCA9IHduZXh0O1xuICAgICAgICAgICAgICAgICAgICBsZW4gLT0gb3A7XG4gICAgICAgICAgICAgICAgICAgIGRvIHtcbiAgICAgICAgICAgICAgICAgICAgICBvdXRwdXRbX291dCsrXSA9IHNfd2luZG93W2Zyb20rK107XG4gICAgICAgICAgICAgICAgICAgIH0gd2hpbGUgKC0tb3ApO1xuICAgICAgICAgICAgICAgICAgICBmcm9tID0gX291dCAtIGRpc3Q7ICAgICAgLyogcmVzdCBmcm9tIG91dHB1dCAqL1xuICAgICAgICAgICAgICAgICAgICBmcm9tX3NvdXJjZSA9IG91dHB1dDtcbiAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgZWxzZSB7ICAgICAgICAgICAgICAgICAgICAgIC8qIGNvbnRpZ3VvdXMgaW4gd2luZG93ICovXG4gICAgICAgICAgICAgICAgZnJvbSArPSB3bmV4dCAtIG9wO1xuICAgICAgICAgICAgICAgIGlmIChvcCA8IGxlbikgeyAgICAgICAgIC8qIHNvbWUgZnJvbSB3aW5kb3cgKi9cbiAgICAgICAgICAgICAgICAgIGxlbiAtPSBvcDtcbiAgICAgICAgICAgICAgICAgIGRvIHtcbiAgICAgICAgICAgICAgICAgICAgb3V0cHV0W19vdXQrK10gPSBzX3dpbmRvd1tmcm9tKytdO1xuICAgICAgICAgICAgICAgICAgfSB3aGlsZSAoLS1vcCk7XG4gICAgICAgICAgICAgICAgICBmcm9tID0gX291dCAtIGRpc3Q7ICAvKiByZXN0IGZyb20gb3V0cHV0ICovXG4gICAgICAgICAgICAgICAgICBmcm9tX3NvdXJjZSA9IG91dHB1dDtcbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgd2hpbGUgKGxlbiA+IDIpIHtcbiAgICAgICAgICAgICAgICBvdXRwdXRbX291dCsrXSA9IGZyb21fc291cmNlW2Zyb20rK107XG4gICAgICAgICAgICAgICAgb3V0cHV0W19vdXQrK10gPSBmcm9tX3NvdXJjZVtmcm9tKytdO1xuICAgICAgICAgICAgICAgIG91dHB1dFtfb3V0KytdID0gZnJvbV9zb3VyY2VbZnJvbSsrXTtcbiAgICAgICAgICAgICAgICBsZW4gLT0gMztcbiAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICBpZiAobGVuKSB7XG4gICAgICAgICAgICAgICAgb3V0cHV0W19vdXQrK10gPSBmcm9tX3NvdXJjZVtmcm9tKytdO1xuICAgICAgICAgICAgICAgIGlmIChsZW4gPiAxKSB7XG4gICAgICAgICAgICAgICAgICBvdXRwdXRbX291dCsrXSA9IGZyb21fc291cmNlW2Zyb20rK107XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICB9XG4gICAgICAgICAgICB9XG4gICAgICAgICAgICBlbHNlIHtcbiAgICAgICAgICAgICAgZnJvbSA9IF9vdXQgLSBkaXN0OyAgICAgICAgICAvKiBjb3B5IGRpcmVjdCBmcm9tIG91dHB1dCAqL1xuICAgICAgICAgICAgICBkbyB7ICAgICAgICAgICAgICAgICAgICAgICAgLyogbWluaW11bSBsZW5ndGggaXMgdGhyZWUgKi9cbiAgICAgICAgICAgICAgICBvdXRwdXRbX291dCsrXSA9IG91dHB1dFtmcm9tKytdO1xuICAgICAgICAgICAgICAgIG91dHB1dFtfb3V0KytdID0gb3V0cHV0W2Zyb20rK107XG4gICAgICAgICAgICAgICAgb3V0cHV0W19vdXQrK10gPSBvdXRwdXRbZnJvbSsrXTtcbiAgICAgICAgICAgICAgICBsZW4gLT0gMztcbiAgICAgICAgICAgICAgfSB3aGlsZSAobGVuID4gMik7XG4gICAgICAgICAgICAgIGlmIChsZW4pIHtcbiAgICAgICAgICAgICAgICBvdXRwdXRbX291dCsrXSA9IG91dHB1dFtmcm9tKytdO1xuICAgICAgICAgICAgICAgIGlmIChsZW4gPiAxKSB7XG4gICAgICAgICAgICAgICAgICBvdXRwdXRbX291dCsrXSA9IG91dHB1dFtmcm9tKytdO1xuICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgfVxuICAgICAgICAgIH1cbiAgICAgICAgICBlbHNlIGlmICgob3AgJiA2NCkgPT09IDApIHsgICAgICAgICAgLyogMm5kIGxldmVsIGRpc3RhbmNlIGNvZGUgKi9cbiAgICAgICAgICAgIGhlcmUgPSBkY29kZVsoaGVyZSAmIDB4ZmZmZikvKmhlcmUudmFsKi8gKyAoaG9sZCAmICgoMSA8PCBvcCkgLSAxKSldO1xuICAgICAgICAgICAgY29udGludWUgZG9kaXN0O1xuICAgICAgICAgIH1cbiAgICAgICAgICBlbHNlIHtcbiAgICAgICAgICAgIHN0cm0ubXNnID0gJ2ludmFsaWQgZGlzdGFuY2UgY29kZSc7XG4gICAgICAgICAgICBzdGF0ZS5tb2RlID0gQkFEO1xuICAgICAgICAgICAgYnJlYWsgdG9wO1xuICAgICAgICAgIH1cblxuICAgICAgICAgIGJyZWFrOyAvLyBuZWVkIHRvIGVtdWxhdGUgZ290byB2aWEgXCJjb250aW51ZVwiXG4gICAgICAgIH1cbiAgICAgIH1cbiAgICAgIGVsc2UgaWYgKChvcCAmIDY0KSA9PT0gMCkgeyAgICAgICAgICAgICAgLyogMm5kIGxldmVsIGxlbmd0aCBjb2RlICovXG4gICAgICAgIGhlcmUgPSBsY29kZVsoaGVyZSAmIDB4ZmZmZikvKmhlcmUudmFsKi8gKyAoaG9sZCAmICgoMSA8PCBvcCkgLSAxKSldO1xuICAgICAgICBjb250aW51ZSBkb2xlbjtcbiAgICAgIH1cbiAgICAgIGVsc2UgaWYgKG9wICYgMzIpIHsgICAgICAgICAgICAgICAgICAgICAvKiBlbmQtb2YtYmxvY2sgKi9cbiAgICAgICAgLy9UcmFjZXZ2KChzdGRlcnIsIFwiaW5mbGF0ZTogICAgICAgICBlbmQgb2YgYmxvY2tcXG5cIikpO1xuICAgICAgICBzdGF0ZS5tb2RlID0gVFlQRTtcbiAgICAgICAgYnJlYWsgdG9wO1xuICAgICAgfVxuICAgICAgZWxzZSB7XG4gICAgICAgIHN0cm0ubXNnID0gJ2ludmFsaWQgbGl0ZXJhbC9sZW5ndGggY29kZSc7XG4gICAgICAgIHN0YXRlLm1vZGUgPSBCQUQ7XG4gICAgICAgIGJyZWFrIHRvcDtcbiAgICAgIH1cblxuICAgICAgYnJlYWs7IC8vIG5lZWQgdG8gZW11bGF0ZSBnb3RvIHZpYSBcImNvbnRpbnVlXCJcbiAgICB9XG4gIH0gd2hpbGUgKF9pbiA8IGxhc3QgJiYgX291dCA8IGVuZCk7XG5cbiAgLyogcmV0dXJuIHVudXNlZCBieXRlcyAob24gZW50cnksIGJpdHMgPCA4LCBzbyBpbiB3b24ndCBnbyB0b28gZmFyIGJhY2spICovXG4gIGxlbiA9IGJpdHMgPj4gMztcbiAgX2luIC09IGxlbjtcbiAgYml0cyAtPSBsZW4gPDwgMztcbiAgaG9sZCAmPSAoMSA8PCBiaXRzKSAtIDE7XG5cbiAgLyogdXBkYXRlIHN0YXRlIGFuZCByZXR1cm4gKi9cbiAgc3RybS5uZXh0X2luID0gX2luO1xuICBzdHJtLm5leHRfb3V0ID0gX291dDtcbiAgc3RybS5hdmFpbF9pbiA9IChfaW4gPCBsYXN0ID8gNSArIChsYXN0IC0gX2luKSA6IDUgLSAoX2luIC0gbGFzdCkpO1xuICBzdHJtLmF2YWlsX291dCA9IChfb3V0IDwgZW5kID8gMjU3ICsgKGVuZCAtIF9vdXQpIDogMjU3IC0gKF9vdXQgLSBlbmQpKTtcbiAgc3RhdGUuaG9sZCA9IGhvbGQ7XG4gIHN0YXRlLmJpdHMgPSBiaXRzO1xuICByZXR1cm47XG59O1xuIiwiJ3VzZSBzdHJpY3QnO1xuXG5cbnZhciB1dGlscyA9IHJlcXVpcmUoJy4uL3V0aWxzL2NvbW1vbicpO1xudmFyIGFkbGVyMzIgPSByZXF1aXJlKCcuL2FkbGVyMzInKTtcbnZhciBjcmMzMiAgID0gcmVxdWlyZSgnLi9jcmMzMicpO1xudmFyIGluZmxhdGVfZmFzdCA9IHJlcXVpcmUoJy4vaW5mZmFzdCcpO1xudmFyIGluZmxhdGVfdGFibGUgPSByZXF1aXJlKCcuL2luZnRyZWVzJyk7XG5cbnZhciBDT0RFUyA9IDA7XG52YXIgTEVOUyA9IDE7XG52YXIgRElTVFMgPSAyO1xuXG4vKiBQdWJsaWMgY29uc3RhbnRzID09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT0qL1xuLyogPT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09Ki9cblxuXG4vKiBBbGxvd2VkIGZsdXNoIHZhbHVlczsgc2VlIGRlZmxhdGUoKSBhbmQgaW5mbGF0ZSgpIGJlbG93IGZvciBkZXRhaWxzICovXG4vL3ZhciBaX05PX0ZMVVNIICAgICAgPSAwO1xuLy92YXIgWl9QQVJUSUFMX0ZMVVNIID0gMTtcbi8vdmFyIFpfU1lOQ19GTFVTSCAgICA9IDI7XG4vL3ZhciBaX0ZVTExfRkxVU0ggICAgPSAzO1xudmFyIFpfRklOSVNIICAgICAgICA9IDQ7XG52YXIgWl9CTE9DSyAgICAgICAgID0gNTtcbnZhciBaX1RSRUVTICAgICAgICAgPSA2O1xuXG5cbi8qIFJldHVybiBjb2RlcyBmb3IgdGhlIGNvbXByZXNzaW9uL2RlY29tcHJlc3Npb24gZnVuY3Rpb25zLiBOZWdhdGl2ZSB2YWx1ZXNcbiAqIGFyZSBlcnJvcnMsIHBvc2l0aXZlIHZhbHVlcyBhcmUgdXNlZCBmb3Igc3BlY2lhbCBidXQgbm9ybWFsIGV2ZW50cy5cbiAqL1xudmFyIFpfT0sgICAgICAgICAgICA9IDA7XG52YXIgWl9TVFJFQU1fRU5EICAgID0gMTtcbnZhciBaX05FRURfRElDVCAgICAgPSAyO1xuLy92YXIgWl9FUlJOTyAgICAgICAgID0gLTE7XG52YXIgWl9TVFJFQU1fRVJST1IgID0gLTI7XG52YXIgWl9EQVRBX0VSUk9SICAgID0gLTM7XG52YXIgWl9NRU1fRVJST1IgICAgID0gLTQ7XG52YXIgWl9CVUZfRVJST1IgICAgID0gLTU7XG4vL3ZhciBaX1ZFUlNJT05fRVJST1IgPSAtNjtcblxuLyogVGhlIGRlZmxhdGUgY29tcHJlc3Npb24gbWV0aG9kICovXG52YXIgWl9ERUZMQVRFRCAgPSA4O1xuXG5cbi8qIFNUQVRFUyA9PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PSovXG4vKiA9PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT0qL1xuXG5cbnZhciAgICBIRUFEID0gMTsgICAgICAgLyogaTogd2FpdGluZyBmb3IgbWFnaWMgaGVhZGVyICovXG52YXIgICAgRkxBR1MgPSAyOyAgICAgIC8qIGk6IHdhaXRpbmcgZm9yIG1ldGhvZCBhbmQgZmxhZ3MgKGd6aXApICovXG52YXIgICAgVElNRSA9IDM7ICAgICAgIC8qIGk6IHdhaXRpbmcgZm9yIG1vZGlmaWNhdGlvbiB0aW1lIChnemlwKSAqL1xudmFyICAgIE9TID0gNDsgICAgICAgICAvKiBpOiB3YWl0aW5nIGZvciBleHRyYSBmbGFncyBhbmQgb3BlcmF0aW5nIHN5c3RlbSAoZ3ppcCkgKi9cbnZhciAgICBFWExFTiA9IDU7ICAgICAgLyogaTogd2FpdGluZyBmb3IgZXh0cmEgbGVuZ3RoIChnemlwKSAqL1xudmFyICAgIEVYVFJBID0gNjsgICAgICAvKiBpOiB3YWl0aW5nIGZvciBleHRyYSBieXRlcyAoZ3ppcCkgKi9cbnZhciAgICBOQU1FID0gNzsgICAgICAgLyogaTogd2FpdGluZyBmb3IgZW5kIG9mIGZpbGUgbmFtZSAoZ3ppcCkgKi9cbnZhciAgICBDT01NRU5UID0gODsgICAgLyogaTogd2FpdGluZyBmb3IgZW5kIG9mIGNvbW1lbnQgKGd6aXApICovXG52YXIgICAgSENSQyA9IDk7ICAgICAgIC8qIGk6IHdhaXRpbmcgZm9yIGhlYWRlciBjcmMgKGd6aXApICovXG52YXIgICAgRElDVElEID0gMTA7ICAgIC8qIGk6IHdhaXRpbmcgZm9yIGRpY3Rpb25hcnkgY2hlY2sgdmFsdWUgKi9cbnZhciAgICBESUNUID0gMTE7ICAgICAgLyogd2FpdGluZyBmb3IgaW5mbGF0ZVNldERpY3Rpb25hcnkoKSBjYWxsICovXG52YXIgICAgICAgIFRZUEUgPSAxMjsgICAgICAvKiBpOiB3YWl0aW5nIGZvciB0eXBlIGJpdHMsIGluY2x1ZGluZyBsYXN0LWZsYWcgYml0ICovXG52YXIgICAgICAgIFRZUEVETyA9IDEzOyAgICAvKiBpOiBzYW1lLCBidXQgc2tpcCBjaGVjayB0byBleGl0IGluZmxhdGUgb24gbmV3IGJsb2NrICovXG52YXIgICAgICAgIFNUT1JFRCA9IDE0OyAgICAvKiBpOiB3YWl0aW5nIGZvciBzdG9yZWQgc2l6ZSAobGVuZ3RoIGFuZCBjb21wbGVtZW50KSAqL1xudmFyICAgICAgICBDT1BZXyA9IDE1OyAgICAgLyogaS9vOiBzYW1lIGFzIENPUFkgYmVsb3csIGJ1dCBvbmx5IGZpcnN0IHRpbWUgaW4gKi9cbnZhciAgICAgICAgQ09QWSA9IDE2OyAgICAgIC8qIGkvbzogd2FpdGluZyBmb3IgaW5wdXQgb3Igb3V0cHV0IHRvIGNvcHkgc3RvcmVkIGJsb2NrICovXG52YXIgICAgICAgIFRBQkxFID0gMTc7ICAgICAvKiBpOiB3YWl0aW5nIGZvciBkeW5hbWljIGJsb2NrIHRhYmxlIGxlbmd0aHMgKi9cbnZhciAgICAgICAgTEVOTEVOUyA9IDE4OyAgIC8qIGk6IHdhaXRpbmcgZm9yIGNvZGUgbGVuZ3RoIGNvZGUgbGVuZ3RocyAqL1xudmFyICAgICAgICBDT0RFTEVOUyA9IDE5OyAgLyogaTogd2FpdGluZyBmb3IgbGVuZ3RoL2xpdCBhbmQgZGlzdGFuY2UgY29kZSBsZW5ndGhzICovXG52YXIgICAgICAgICAgICBMRU5fID0gMjA7ICAgICAgLyogaTogc2FtZSBhcyBMRU4gYmVsb3csIGJ1dCBvbmx5IGZpcnN0IHRpbWUgaW4gKi9cbnZhciAgICAgICAgICAgIExFTiA9IDIxOyAgICAgICAvKiBpOiB3YWl0aW5nIGZvciBsZW5ndGgvbGl0L2VvYiBjb2RlICovXG52YXIgICAgICAgICAgICBMRU5FWFQgPSAyMjsgICAgLyogaTogd2FpdGluZyBmb3IgbGVuZ3RoIGV4dHJhIGJpdHMgKi9cbnZhciAgICAgICAgICAgIERJU1QgPSAyMzsgICAgICAvKiBpOiB3YWl0aW5nIGZvciBkaXN0YW5jZSBjb2RlICovXG52YXIgICAgICAgICAgICBESVNURVhUID0gMjQ7ICAgLyogaTogd2FpdGluZyBmb3IgZGlzdGFuY2UgZXh0cmEgYml0cyAqL1xudmFyICAgICAgICAgICAgTUFUQ0ggPSAyNTsgICAgIC8qIG86IHdhaXRpbmcgZm9yIG91dHB1dCBzcGFjZSB0byBjb3B5IHN0cmluZyAqL1xudmFyICAgICAgICAgICAgTElUID0gMjY7ICAgICAgIC8qIG86IHdhaXRpbmcgZm9yIG91dHB1dCBzcGFjZSB0byB3cml0ZSBsaXRlcmFsICovXG52YXIgICAgQ0hFQ0sgPSAyNzsgICAgIC8qIGk6IHdhaXRpbmcgZm9yIDMyLWJpdCBjaGVjayB2YWx1ZSAqL1xudmFyICAgIExFTkdUSCA9IDI4OyAgICAvKiBpOiB3YWl0aW5nIGZvciAzMi1iaXQgbGVuZ3RoIChnemlwKSAqL1xudmFyICAgIERPTkUgPSAyOTsgICAgICAvKiBmaW5pc2hlZCBjaGVjaywgZG9uZSAtLSByZW1haW4gaGVyZSB1bnRpbCByZXNldCAqL1xudmFyICAgIEJBRCA9IDMwOyAgICAgICAvKiBnb3QgYSBkYXRhIGVycm9yIC0tIHJlbWFpbiBoZXJlIHVudGlsIHJlc2V0ICovXG52YXIgICAgTUVNID0gMzE7ICAgICAgIC8qIGdvdCBhbiBpbmZsYXRlKCkgbWVtb3J5IGVycm9yIC0tIHJlbWFpbiBoZXJlIHVudGlsIHJlc2V0ICovXG52YXIgICAgU1lOQyA9IDMyOyAgICAgIC8qIGxvb2tpbmcgZm9yIHN5bmNocm9uaXphdGlvbiBieXRlcyB0byByZXN0YXJ0IGluZmxhdGUoKSAqL1xuXG4vKiA9PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT0qL1xuXG5cblxudmFyIEVOT1VHSF9MRU5TID0gODUyO1xudmFyIEVOT1VHSF9ESVNUUyA9IDU5Mjtcbi8vdmFyIEVOT1VHSCA9ICAoRU5PVUdIX0xFTlMrRU5PVUdIX0RJU1RTKTtcblxudmFyIE1BWF9XQklUUyA9IDE1O1xuLyogMzJLIExaNzcgd2luZG93ICovXG52YXIgREVGX1dCSVRTID0gTUFYX1dCSVRTO1xuXG5cbmZ1bmN0aW9uIFpTV0FQMzIocSkge1xuICByZXR1cm4gICgoKHEgPj4+IDI0KSAmIDB4ZmYpICtcbiAgICAgICAgICAoKHEgPj4+IDgpICYgMHhmZjAwKSArXG4gICAgICAgICAgKChxICYgMHhmZjAwKSA8PCA4KSArXG4gICAgICAgICAgKChxICYgMHhmZikgPDwgMjQpKTtcbn1cblxuXG5mdW5jdGlvbiBJbmZsYXRlU3RhdGUoKSB7XG4gIHRoaXMubW9kZSA9IDA7ICAgICAgICAgICAgIC8qIGN1cnJlbnQgaW5mbGF0ZSBtb2RlICovXG4gIHRoaXMubGFzdCA9IGZhbHNlOyAgICAgICAgICAvKiB0cnVlIGlmIHByb2Nlc3NpbmcgbGFzdCBibG9jayAqL1xuICB0aGlzLndyYXAgPSAwOyAgICAgICAgICAgICAgLyogYml0IDAgdHJ1ZSBmb3IgemxpYiwgYml0IDEgdHJ1ZSBmb3IgZ3ppcCAqL1xuICB0aGlzLmhhdmVkaWN0ID0gZmFsc2U7ICAgICAgLyogdHJ1ZSBpZiBkaWN0aW9uYXJ5IHByb3ZpZGVkICovXG4gIHRoaXMuZmxhZ3MgPSAwOyAgICAgICAgICAgICAvKiBnemlwIGhlYWRlciBtZXRob2QgYW5kIGZsYWdzICgwIGlmIHpsaWIpICovXG4gIHRoaXMuZG1heCA9IDA7ICAgICAgICAgICAgICAvKiB6bGliIGhlYWRlciBtYXggZGlzdGFuY2UgKElORkxBVEVfU1RSSUNUKSAqL1xuICB0aGlzLmNoZWNrID0gMDsgICAgICAgICAgICAgLyogcHJvdGVjdGVkIGNvcHkgb2YgY2hlY2sgdmFsdWUgKi9cbiAgdGhpcy50b3RhbCA9IDA7ICAgICAgICAgICAgIC8qIHByb3RlY3RlZCBjb3B5IG9mIG91dHB1dCBjb3VudCAqL1xuICAvLyBUT0RPOiBtYXkgYmUge31cbiAgdGhpcy5oZWFkID0gbnVsbDsgICAgICAgICAgIC8qIHdoZXJlIHRvIHNhdmUgZ3ppcCBoZWFkZXIgaW5mb3JtYXRpb24gKi9cblxuICAvKiBzbGlkaW5nIHdpbmRvdyAqL1xuICB0aGlzLndiaXRzID0gMDsgICAgICAgICAgICAgLyogbG9nIGJhc2UgMiBvZiByZXF1ZXN0ZWQgd2luZG93IHNpemUgKi9cbiAgdGhpcy53c2l6ZSA9IDA7ICAgICAgICAgICAgIC8qIHdpbmRvdyBzaXplIG9yIHplcm8gaWYgbm90IHVzaW5nIHdpbmRvdyAqL1xuICB0aGlzLndoYXZlID0gMDsgICAgICAgICAgICAgLyogdmFsaWQgYnl0ZXMgaW4gdGhlIHdpbmRvdyAqL1xuICB0aGlzLnduZXh0ID0gMDsgICAgICAgICAgICAgLyogd2luZG93IHdyaXRlIGluZGV4ICovXG4gIHRoaXMud2luZG93ID0gbnVsbDsgICAgICAgICAvKiBhbGxvY2F0ZWQgc2xpZGluZyB3aW5kb3csIGlmIG5lZWRlZCAqL1xuXG4gIC8qIGJpdCBhY2N1bXVsYXRvciAqL1xuICB0aGlzLmhvbGQgPSAwOyAgICAgICAgICAgICAgLyogaW5wdXQgYml0IGFjY3VtdWxhdG9yICovXG4gIHRoaXMuYml0cyA9IDA7ICAgICAgICAgICAgICAvKiBudW1iZXIgb2YgYml0cyBpbiBcImluXCIgKi9cblxuICAvKiBmb3Igc3RyaW5nIGFuZCBzdG9yZWQgYmxvY2sgY29weWluZyAqL1xuICB0aGlzLmxlbmd0aCA9IDA7ICAgICAgICAgICAgLyogbGl0ZXJhbCBvciBsZW5ndGggb2YgZGF0YSB0byBjb3B5ICovXG4gIHRoaXMub2Zmc2V0ID0gMDsgICAgICAgICAgICAvKiBkaXN0YW5jZSBiYWNrIHRvIGNvcHkgc3RyaW5nIGZyb20gKi9cblxuICAvKiBmb3IgdGFibGUgYW5kIGNvZGUgZGVjb2RpbmcgKi9cbiAgdGhpcy5leHRyYSA9IDA7ICAgICAgICAgICAgIC8qIGV4dHJhIGJpdHMgbmVlZGVkICovXG5cbiAgLyogZml4ZWQgYW5kIGR5bmFtaWMgY29kZSB0YWJsZXMgKi9cbiAgdGhpcy5sZW5jb2RlID0gbnVsbDsgICAgICAgICAgLyogc3RhcnRpbmcgdGFibGUgZm9yIGxlbmd0aC9saXRlcmFsIGNvZGVzICovXG4gIHRoaXMuZGlzdGNvZGUgPSBudWxsOyAgICAgICAgIC8qIHN0YXJ0aW5nIHRhYmxlIGZvciBkaXN0YW5jZSBjb2RlcyAqL1xuICB0aGlzLmxlbmJpdHMgPSAwOyAgICAgICAgICAgLyogaW5kZXggYml0cyBmb3IgbGVuY29kZSAqL1xuICB0aGlzLmRpc3RiaXRzID0gMDsgICAgICAgICAgLyogaW5kZXggYml0cyBmb3IgZGlzdGNvZGUgKi9cblxuICAvKiBkeW5hbWljIHRhYmxlIGJ1aWxkaW5nICovXG4gIHRoaXMubmNvZGUgPSAwOyAgICAgICAgICAgICAvKiBudW1iZXIgb2YgY29kZSBsZW5ndGggY29kZSBsZW5ndGhzICovXG4gIHRoaXMubmxlbiA9IDA7ICAgICAgICAgICAgICAvKiBudW1iZXIgb2YgbGVuZ3RoIGNvZGUgbGVuZ3RocyAqL1xuICB0aGlzLm5kaXN0ID0gMDsgICAgICAgICAgICAgLyogbnVtYmVyIG9mIGRpc3RhbmNlIGNvZGUgbGVuZ3RocyAqL1xuICB0aGlzLmhhdmUgPSAwOyAgICAgICAgICAgICAgLyogbnVtYmVyIG9mIGNvZGUgbGVuZ3RocyBpbiBsZW5zW10gKi9cbiAgdGhpcy5uZXh0ID0gbnVsbDsgICAgICAgICAgICAgIC8qIG5leHQgYXZhaWxhYmxlIHNwYWNlIGluIGNvZGVzW10gKi9cblxuICB0aGlzLmxlbnMgPSBuZXcgdXRpbHMuQnVmMTYoMzIwKTsgLyogdGVtcG9yYXJ5IHN0b3JhZ2UgZm9yIGNvZGUgbGVuZ3RocyAqL1xuICB0aGlzLndvcmsgPSBuZXcgdXRpbHMuQnVmMTYoMjg4KTsgLyogd29yayBhcmVhIGZvciBjb2RlIHRhYmxlIGJ1aWxkaW5nICovXG5cbiAgLypcbiAgIGJlY2F1c2Ugd2UgZG9uJ3QgaGF2ZSBwb2ludGVycyBpbiBqcywgd2UgdXNlIGxlbmNvZGUgYW5kIGRpc3Rjb2RlIGRpcmVjdGx5XG4gICBhcyBidWZmZXJzIHNvIHdlIGRvbid0IG5lZWQgY29kZXNcbiAgKi9cbiAgLy90aGlzLmNvZGVzID0gbmV3IHV0aWxzLkJ1ZjMyKEVOT1VHSCk7ICAgICAgIC8qIHNwYWNlIGZvciBjb2RlIHRhYmxlcyAqL1xuICB0aGlzLmxlbmR5biA9IG51bGw7ICAgICAgICAgICAgICAvKiBkeW5hbWljIHRhYmxlIGZvciBsZW5ndGgvbGl0ZXJhbCBjb2RlcyAoSlMgc3BlY2lmaWMpICovXG4gIHRoaXMuZGlzdGR5biA9IG51bGw7ICAgICAgICAgICAgIC8qIGR5bmFtaWMgdGFibGUgZm9yIGRpc3RhbmNlIGNvZGVzIChKUyBzcGVjaWZpYykgKi9cbiAgdGhpcy5zYW5lID0gMDsgICAgICAgICAgICAgICAgICAgLyogaWYgZmFsc2UsIGFsbG93IGludmFsaWQgZGlzdGFuY2UgdG9vIGZhciAqL1xuICB0aGlzLmJhY2sgPSAwOyAgICAgICAgICAgICAgICAgICAvKiBiaXRzIGJhY2sgb2YgbGFzdCB1bnByb2Nlc3NlZCBsZW5ndGgvbGl0ICovXG4gIHRoaXMud2FzID0gMDsgICAgICAgICAgICAgICAgICAgIC8qIGluaXRpYWwgbGVuZ3RoIG9mIG1hdGNoICovXG59XG5cbmZ1bmN0aW9uIGluZmxhdGVSZXNldEtlZXAoc3RybSkge1xuICB2YXIgc3RhdGU7XG5cbiAgaWYgKCFzdHJtIHx8ICFzdHJtLnN0YXRlKSB7IHJldHVybiBaX1NUUkVBTV9FUlJPUjsgfVxuICBzdGF0ZSA9IHN0cm0uc3RhdGU7XG4gIHN0cm0udG90YWxfaW4gPSBzdHJtLnRvdGFsX291dCA9IHN0YXRlLnRvdGFsID0gMDtcbiAgc3RybS5tc2cgPSAnJzsgLypaX05VTEwqL1xuICBpZiAoc3RhdGUud3JhcCkgeyAgICAgICAvKiB0byBzdXBwb3J0IGlsbC1jb25jZWl2ZWQgSmF2YSB0ZXN0IHN1aXRlICovXG4gICAgc3RybS5hZGxlciA9IHN0YXRlLndyYXAgJiAxO1xuICB9XG4gIHN0YXRlLm1vZGUgPSBIRUFEO1xuICBzdGF0ZS5sYXN0ID0gMDtcbiAgc3RhdGUuaGF2ZWRpY3QgPSAwO1xuICBzdGF0ZS5kbWF4ID0gMzI3Njg7XG4gIHN0YXRlLmhlYWQgPSBudWxsLypaX05VTEwqLztcbiAgc3RhdGUuaG9sZCA9IDA7XG4gIHN0YXRlLmJpdHMgPSAwO1xuICAvL3N0YXRlLmxlbmNvZGUgPSBzdGF0ZS5kaXN0Y29kZSA9IHN0YXRlLm5leHQgPSBzdGF0ZS5jb2RlcztcbiAgc3RhdGUubGVuY29kZSA9IHN0YXRlLmxlbmR5biA9IG5ldyB1dGlscy5CdWYzMihFTk9VR0hfTEVOUyk7XG4gIHN0YXRlLmRpc3Rjb2RlID0gc3RhdGUuZGlzdGR5biA9IG5ldyB1dGlscy5CdWYzMihFTk9VR0hfRElTVFMpO1xuXG4gIHN0YXRlLnNhbmUgPSAxO1xuICBzdGF0ZS5iYWNrID0gLTE7XG4gIC8vVHJhY2V2KChzdGRlcnIsIFwiaW5mbGF0ZTogcmVzZXRcXG5cIikpO1xuICByZXR1cm4gWl9PSztcbn1cblxuZnVuY3Rpb24gaW5mbGF0ZVJlc2V0KHN0cm0pIHtcbiAgdmFyIHN0YXRlO1xuXG4gIGlmICghc3RybSB8fCAhc3RybS5zdGF0ZSkgeyByZXR1cm4gWl9TVFJFQU1fRVJST1I7IH1cbiAgc3RhdGUgPSBzdHJtLnN0YXRlO1xuICBzdGF0ZS53c2l6ZSA9IDA7XG4gIHN0YXRlLndoYXZlID0gMDtcbiAgc3RhdGUud25leHQgPSAwO1xuICByZXR1cm4gaW5mbGF0ZVJlc2V0S2VlcChzdHJtKTtcblxufVxuXG5mdW5jdGlvbiBpbmZsYXRlUmVzZXQyKHN0cm0sIHdpbmRvd0JpdHMpIHtcbiAgdmFyIHdyYXA7XG4gIHZhciBzdGF0ZTtcblxuICAvKiBnZXQgdGhlIHN0YXRlICovXG4gIGlmICghc3RybSB8fCAhc3RybS5zdGF0ZSkgeyByZXR1cm4gWl9TVFJFQU1fRVJST1I7IH1cbiAgc3RhdGUgPSBzdHJtLnN0YXRlO1xuXG4gIC8qIGV4dHJhY3Qgd3JhcCByZXF1ZXN0IGZyb20gd2luZG93Qml0cyBwYXJhbWV0ZXIgKi9cbiAgaWYgKHdpbmRvd0JpdHMgPCAwKSB7XG4gICAgd3JhcCA9IDA7XG4gICAgd2luZG93Qml0cyA9IC13aW5kb3dCaXRzO1xuICB9XG4gIGVsc2Uge1xuICAgIHdyYXAgPSAod2luZG93Qml0cyA+PiA0KSArIDE7XG4gICAgaWYgKHdpbmRvd0JpdHMgPCA0OCkge1xuICAgICAgd2luZG93Qml0cyAmPSAxNTtcbiAgICB9XG4gIH1cblxuICAvKiBzZXQgbnVtYmVyIG9mIHdpbmRvdyBiaXRzLCBmcmVlIHdpbmRvdyBpZiBkaWZmZXJlbnQgKi9cbiAgaWYgKHdpbmRvd0JpdHMgJiYgKHdpbmRvd0JpdHMgPCA4IHx8IHdpbmRvd0JpdHMgPiAxNSkpIHtcbiAgICByZXR1cm4gWl9TVFJFQU1fRVJST1I7XG4gIH1cbiAgaWYgKHN0YXRlLndpbmRvdyAhPT0gbnVsbCAmJiBzdGF0ZS53Yml0cyAhPT0gd2luZG93Qml0cykge1xuICAgIHN0YXRlLndpbmRvdyA9IG51bGw7XG4gIH1cblxuICAvKiB1cGRhdGUgc3RhdGUgYW5kIHJlc2V0IHRoZSByZXN0IG9mIGl0ICovXG4gIHN0YXRlLndyYXAgPSB3cmFwO1xuICBzdGF0ZS53Yml0cyA9IHdpbmRvd0JpdHM7XG4gIHJldHVybiBpbmZsYXRlUmVzZXQoc3RybSk7XG59XG5cbmZ1bmN0aW9uIGluZmxhdGVJbml0MihzdHJtLCB3aW5kb3dCaXRzKSB7XG4gIHZhciByZXQ7XG4gIHZhciBzdGF0ZTtcblxuICBpZiAoIXN0cm0pIHsgcmV0dXJuIFpfU1RSRUFNX0VSUk9SOyB9XG4gIC8vc3RybS5tc2cgPSBaX05VTEw7ICAgICAgICAgICAgICAgICAvKiBpbiBjYXNlIHdlIHJldHVybiBhbiBlcnJvciAqL1xuXG4gIHN0YXRlID0gbmV3IEluZmxhdGVTdGF0ZSgpO1xuXG4gIC8vaWYgKHN0YXRlID09PSBaX05VTEwpIHJldHVybiBaX01FTV9FUlJPUjtcbiAgLy9UcmFjZXYoKHN0ZGVyciwgXCJpbmZsYXRlOiBhbGxvY2F0ZWRcXG5cIikpO1xuICBzdHJtLnN0YXRlID0gc3RhdGU7XG4gIHN0YXRlLndpbmRvdyA9IG51bGwvKlpfTlVMTCovO1xuICByZXQgPSBpbmZsYXRlUmVzZXQyKHN0cm0sIHdpbmRvd0JpdHMpO1xuICBpZiAocmV0ICE9PSBaX09LKSB7XG4gICAgc3RybS5zdGF0ZSA9IG51bGwvKlpfTlVMTCovO1xuICB9XG4gIHJldHVybiByZXQ7XG59XG5cbmZ1bmN0aW9uIGluZmxhdGVJbml0KHN0cm0pIHtcbiAgcmV0dXJuIGluZmxhdGVJbml0MihzdHJtLCBERUZfV0JJVFMpO1xufVxuXG5cbi8qXG4gUmV0dXJuIHN0YXRlIHdpdGggbGVuZ3RoIGFuZCBkaXN0YW5jZSBkZWNvZGluZyB0YWJsZXMgYW5kIGluZGV4IHNpemVzIHNldCB0b1xuIGZpeGVkIGNvZGUgZGVjb2RpbmcuICBOb3JtYWxseSB0aGlzIHJldHVybnMgZml4ZWQgdGFibGVzIGZyb20gaW5mZml4ZWQuaC5cbiBJZiBCVUlMREZJWEVEIGlzIGRlZmluZWQsIHRoZW4gaW5zdGVhZCB0aGlzIHJvdXRpbmUgYnVpbGRzIHRoZSB0YWJsZXMgdGhlXG4gZmlyc3QgdGltZSBpdCdzIGNhbGxlZCwgYW5kIHJldHVybnMgdGhvc2UgdGFibGVzIHRoZSBmaXJzdCB0aW1lIGFuZFxuIHRoZXJlYWZ0ZXIuICBUaGlzIHJlZHVjZXMgdGhlIHNpemUgb2YgdGhlIGNvZGUgYnkgYWJvdXQgMksgYnl0ZXMsIGluXG4gZXhjaGFuZ2UgZm9yIGEgbGl0dGxlIGV4ZWN1dGlvbiB0aW1lLiAgSG93ZXZlciwgQlVJTERGSVhFRCBzaG91bGQgbm90IGJlXG4gdXNlZCBmb3IgdGhyZWFkZWQgYXBwbGljYXRpb25zLCBzaW5jZSB0aGUgcmV3cml0aW5nIG9mIHRoZSB0YWJsZXMgYW5kIHZpcmdpblxuIG1heSBub3QgYmUgdGhyZWFkLXNhZmUuXG4gKi9cbnZhciB2aXJnaW4gPSB0cnVlO1xuXG52YXIgbGVuZml4LCBkaXN0Zml4OyAvLyBXZSBoYXZlIG5vIHBvaW50ZXJzIGluIEpTLCBzbyBrZWVwIHRhYmxlcyBzZXBhcmF0ZVxuXG5mdW5jdGlvbiBmaXhlZHRhYmxlcyhzdGF0ZSkge1xuICAvKiBidWlsZCBmaXhlZCBodWZmbWFuIHRhYmxlcyBpZiBmaXJzdCBjYWxsIChtYXkgbm90IGJlIHRocmVhZCBzYWZlKSAqL1xuICBpZiAodmlyZ2luKSB7XG4gICAgdmFyIHN5bTtcblxuICAgIGxlbmZpeCA9IG5ldyB1dGlscy5CdWYzMig1MTIpO1xuICAgIGRpc3RmaXggPSBuZXcgdXRpbHMuQnVmMzIoMzIpO1xuXG4gICAgLyogbGl0ZXJhbC9sZW5ndGggdGFibGUgKi9cbiAgICBzeW0gPSAwO1xuICAgIHdoaWxlIChzeW0gPCAxNDQpIHsgc3RhdGUubGVuc1tzeW0rK10gPSA4OyB9XG4gICAgd2hpbGUgKHN5bSA8IDI1NikgeyBzdGF0ZS5sZW5zW3N5bSsrXSA9IDk7IH1cbiAgICB3aGlsZSAoc3ltIDwgMjgwKSB7IHN0YXRlLmxlbnNbc3ltKytdID0gNzsgfVxuICAgIHdoaWxlIChzeW0gPCAyODgpIHsgc3RhdGUubGVuc1tzeW0rK10gPSA4OyB9XG5cbiAgICBpbmZsYXRlX3RhYmxlKExFTlMsICBzdGF0ZS5sZW5zLCAwLCAyODgsIGxlbmZpeCwgICAwLCBzdGF0ZS53b3JrLCB7Yml0czogOX0pO1xuXG4gICAgLyogZGlzdGFuY2UgdGFibGUgKi9cbiAgICBzeW0gPSAwO1xuICAgIHdoaWxlIChzeW0gPCAzMikgeyBzdGF0ZS5sZW5zW3N5bSsrXSA9IDU7IH1cblxuICAgIGluZmxhdGVfdGFibGUoRElTVFMsIHN0YXRlLmxlbnMsIDAsIDMyLCAgIGRpc3RmaXgsIDAsIHN0YXRlLndvcmssIHtiaXRzOiA1fSk7XG5cbiAgICAvKiBkbyB0aGlzIGp1c3Qgb25jZSAqL1xuICAgIHZpcmdpbiA9IGZhbHNlO1xuICB9XG5cbiAgc3RhdGUubGVuY29kZSA9IGxlbmZpeDtcbiAgc3RhdGUubGVuYml0cyA9IDk7XG4gIHN0YXRlLmRpc3Rjb2RlID0gZGlzdGZpeDtcbiAgc3RhdGUuZGlzdGJpdHMgPSA1O1xufVxuXG5cbi8qXG4gVXBkYXRlIHRoZSB3aW5kb3cgd2l0aCB0aGUgbGFzdCB3c2l6ZSAobm9ybWFsbHkgMzJLKSBieXRlcyB3cml0dGVuIGJlZm9yZVxuIHJldHVybmluZy4gIElmIHdpbmRvdyBkb2VzIG5vdCBleGlzdCB5ZXQsIGNyZWF0ZSBpdC4gIFRoaXMgaXMgb25seSBjYWxsZWRcbiB3aGVuIGEgd2luZG93IGlzIGFscmVhZHkgaW4gdXNlLCBvciB3aGVuIG91dHB1dCBoYXMgYmVlbiB3cml0dGVuIGR1cmluZyB0aGlzXG4gaW5mbGF0ZSBjYWxsLCBidXQgdGhlIGVuZCBvZiB0aGUgZGVmbGF0ZSBzdHJlYW0gaGFzIG5vdCBiZWVuIHJlYWNoZWQgeWV0LlxuIEl0IGlzIGFsc28gY2FsbGVkIHRvIGNyZWF0ZSBhIHdpbmRvdyBmb3IgZGljdGlvbmFyeSBkYXRhIHdoZW4gYSBkaWN0aW9uYXJ5XG4gaXMgbG9hZGVkLlxuXG4gUHJvdmlkaW5nIG91dHB1dCBidWZmZXJzIGxhcmdlciB0aGFuIDMySyB0byBpbmZsYXRlKCkgc2hvdWxkIHByb3ZpZGUgYSBzcGVlZFxuIGFkdmFudGFnZSwgc2luY2Ugb25seSB0aGUgbGFzdCAzMksgb2Ygb3V0cHV0IGlzIGNvcGllZCB0byB0aGUgc2xpZGluZyB3aW5kb3dcbiB1cG9uIHJldHVybiBmcm9tIGluZmxhdGUoKSwgYW5kIHNpbmNlIGFsbCBkaXN0YW5jZXMgYWZ0ZXIgdGhlIGZpcnN0IDMySyBvZlxuIG91dHB1dCB3aWxsIGZhbGwgaW4gdGhlIG91dHB1dCBkYXRhLCBtYWtpbmcgbWF0Y2ggY29waWVzIHNpbXBsZXIgYW5kIGZhc3Rlci5cbiBUaGUgYWR2YW50YWdlIG1heSBiZSBkZXBlbmRlbnQgb24gdGhlIHNpemUgb2YgdGhlIHByb2Nlc3NvcidzIGRhdGEgY2FjaGVzLlxuICovXG5mdW5jdGlvbiB1cGRhdGV3aW5kb3coc3RybSwgc3JjLCBlbmQsIGNvcHkpIHtcbiAgdmFyIGRpc3Q7XG4gIHZhciBzdGF0ZSA9IHN0cm0uc3RhdGU7XG5cbiAgLyogaWYgaXQgaGFzbid0IGJlZW4gZG9uZSBhbHJlYWR5LCBhbGxvY2F0ZSBzcGFjZSBmb3IgdGhlIHdpbmRvdyAqL1xuICBpZiAoc3RhdGUud2luZG93ID09PSBudWxsKSB7XG4gICAgc3RhdGUud3NpemUgPSAxIDw8IHN0YXRlLndiaXRzO1xuICAgIHN0YXRlLnduZXh0ID0gMDtcbiAgICBzdGF0ZS53aGF2ZSA9IDA7XG5cbiAgICBzdGF0ZS53aW5kb3cgPSBuZXcgdXRpbHMuQnVmOChzdGF0ZS53c2l6ZSk7XG4gIH1cblxuICAvKiBjb3B5IHN0YXRlLT53c2l6ZSBvciBsZXNzIG91dHB1dCBieXRlcyBpbnRvIHRoZSBjaXJjdWxhciB3aW5kb3cgKi9cbiAgaWYgKGNvcHkgPj0gc3RhdGUud3NpemUpIHtcbiAgICB1dGlscy5hcnJheVNldChzdGF0ZS53aW5kb3csc3JjLCBlbmQgLSBzdGF0ZS53c2l6ZSwgc3RhdGUud3NpemUsIDApO1xuICAgIHN0YXRlLnduZXh0ID0gMDtcbiAgICBzdGF0ZS53aGF2ZSA9IHN0YXRlLndzaXplO1xuICB9XG4gIGVsc2Uge1xuICAgIGRpc3QgPSBzdGF0ZS53c2l6ZSAtIHN0YXRlLnduZXh0O1xuICAgIGlmIChkaXN0ID4gY29weSkge1xuICAgICAgZGlzdCA9IGNvcHk7XG4gICAgfVxuICAgIC8vem1lbWNweShzdGF0ZS0+d2luZG93ICsgc3RhdGUtPnduZXh0LCBlbmQgLSBjb3B5LCBkaXN0KTtcbiAgICB1dGlscy5hcnJheVNldChzdGF0ZS53aW5kb3csc3JjLCBlbmQgLSBjb3B5LCBkaXN0LCBzdGF0ZS53bmV4dCk7XG4gICAgY29weSAtPSBkaXN0O1xuICAgIGlmIChjb3B5KSB7XG4gICAgICAvL3ptZW1jcHkoc3RhdGUtPndpbmRvdywgZW5kIC0gY29weSwgY29weSk7XG4gICAgICB1dGlscy5hcnJheVNldChzdGF0ZS53aW5kb3csc3JjLCBlbmQgLSBjb3B5LCBjb3B5LCAwKTtcbiAgICAgIHN0YXRlLnduZXh0ID0gY29weTtcbiAgICAgIHN0YXRlLndoYXZlID0gc3RhdGUud3NpemU7XG4gICAgfVxuICAgIGVsc2Uge1xuICAgICAgc3RhdGUud25leHQgKz0gZGlzdDtcbiAgICAgIGlmIChzdGF0ZS53bmV4dCA9PT0gc3RhdGUud3NpemUpIHsgc3RhdGUud25leHQgPSAwOyB9XG4gICAgICBpZiAoc3RhdGUud2hhdmUgPCBzdGF0ZS53c2l6ZSkgeyBzdGF0ZS53aGF2ZSArPSBkaXN0OyB9XG4gICAgfVxuICB9XG4gIHJldHVybiAwO1xufVxuXG5mdW5jdGlvbiBpbmZsYXRlKHN0cm0sIGZsdXNoKSB7XG4gIHZhciBzdGF0ZTtcbiAgdmFyIGlucHV0LCBvdXRwdXQ7ICAgICAgICAgIC8vIGlucHV0L291dHB1dCBidWZmZXJzXG4gIHZhciBuZXh0OyAgICAgICAgICAgICAgICAgICAvKiBuZXh0IGlucHV0IElOREVYICovXG4gIHZhciBwdXQ7ICAgICAgICAgICAgICAgICAgICAvKiBuZXh0IG91dHB1dCBJTkRFWCAqL1xuICB2YXIgaGF2ZSwgbGVmdDsgICAgICAgICAgICAgLyogYXZhaWxhYmxlIGlucHV0IGFuZCBvdXRwdXQgKi9cbiAgdmFyIGhvbGQ7ICAgICAgICAgICAgICAgICAgIC8qIGJpdCBidWZmZXIgKi9cbiAgdmFyIGJpdHM7ICAgICAgICAgICAgICAgICAgIC8qIGJpdHMgaW4gYml0IGJ1ZmZlciAqL1xuICB2YXIgX2luLCBfb3V0OyAgICAgICAgICAgICAgLyogc2F2ZSBzdGFydGluZyBhdmFpbGFibGUgaW5wdXQgYW5kIG91dHB1dCAqL1xuICB2YXIgY29weTsgICAgICAgICAgICAgICAgICAgLyogbnVtYmVyIG9mIHN0b3JlZCBvciBtYXRjaCBieXRlcyB0byBjb3B5ICovXG4gIHZhciBmcm9tOyAgICAgICAgICAgICAgICAgICAvKiB3aGVyZSB0byBjb3B5IG1hdGNoIGJ5dGVzIGZyb20gKi9cbiAgdmFyIGZyb21fc291cmNlO1xuICB2YXIgaGVyZSA9IDA7ICAgICAgICAgICAgICAgLyogY3VycmVudCBkZWNvZGluZyB0YWJsZSBlbnRyeSAqL1xuICB2YXIgaGVyZV9iaXRzLCBoZXJlX29wLCBoZXJlX3ZhbDsgLy8gcGFrZWQgXCJoZXJlXCIgZGVub3JtYWxpemVkIChKUyBzcGVjaWZpYylcbiAgLy92YXIgbGFzdDsgICAgICAgICAgICAgICAgICAgLyogcGFyZW50IHRhYmxlIGVudHJ5ICovXG4gIHZhciBsYXN0X2JpdHMsIGxhc3Rfb3AsIGxhc3RfdmFsOyAvLyBwYWtlZCBcImxhc3RcIiBkZW5vcm1hbGl6ZWQgKEpTIHNwZWNpZmljKVxuICB2YXIgbGVuOyAgICAgICAgICAgICAgICAgICAgLyogbGVuZ3RoIHRvIGNvcHkgZm9yIHJlcGVhdHMsIGJpdHMgdG8gZHJvcCAqL1xuICB2YXIgcmV0OyAgICAgICAgICAgICAgICAgICAgLyogcmV0dXJuIGNvZGUgKi9cbiAgdmFyIGhidWYgPSBuZXcgdXRpbHMuQnVmOCg0KTsgICAgLyogYnVmZmVyIGZvciBnemlwIGhlYWRlciBjcmMgY2FsY3VsYXRpb24gKi9cbiAgdmFyIG9wdHM7XG5cbiAgdmFyIG47IC8vIHRlbXBvcmFyeSB2YXIgZm9yIE5FRURfQklUU1xuXG4gIHZhciBvcmRlciA9IC8qIHBlcm11dGF0aW9uIG9mIGNvZGUgbGVuZ3RocyAqL1xuICAgIFsxNiwgMTcsIDE4LCAwLCA4LCA3LCA5LCA2LCAxMCwgNSwgMTEsIDQsIDEyLCAzLCAxMywgMiwgMTQsIDEsIDE1XTtcblxuXG4gIGlmICghc3RybSB8fCAhc3RybS5zdGF0ZSB8fCAhc3RybS5vdXRwdXQgfHxcbiAgICAgICghc3RybS5pbnB1dCAmJiBzdHJtLmF2YWlsX2luICE9PSAwKSkge1xuICAgIHJldHVybiBaX1NUUkVBTV9FUlJPUjtcbiAgfVxuXG4gIHN0YXRlID0gc3RybS5zdGF0ZTtcbiAgaWYgKHN0YXRlLm1vZGUgPT09IFRZUEUpIHsgc3RhdGUubW9kZSA9IFRZUEVETzsgfSAgICAvKiBza2lwIGNoZWNrICovXG5cblxuICAvLy0tLSBMT0FEKCkgLS0tXG4gIHB1dCA9IHN0cm0ubmV4dF9vdXQ7XG4gIG91dHB1dCA9IHN0cm0ub3V0cHV0O1xuICBsZWZ0ID0gc3RybS5hdmFpbF9vdXQ7XG4gIG5leHQgPSBzdHJtLm5leHRfaW47XG4gIGlucHV0ID0gc3RybS5pbnB1dDtcbiAgaGF2ZSA9IHN0cm0uYXZhaWxfaW47XG4gIGhvbGQgPSBzdGF0ZS5ob2xkO1xuICBiaXRzID0gc3RhdGUuYml0cztcbiAgLy8tLS1cblxuICBfaW4gPSBoYXZlO1xuICBfb3V0ID0gbGVmdDtcbiAgcmV0ID0gWl9PSztcblxuICBpbmZfbGVhdmU6IC8vIGdvdG8gZW11bGF0aW9uXG4gIGZvciAoOzspIHtcbiAgICBzd2l0Y2ggKHN0YXRlLm1vZGUpIHtcbiAgICBjYXNlIEhFQUQ6XG4gICAgICBpZiAoc3RhdGUud3JhcCA9PT0gMCkge1xuICAgICAgICBzdGF0ZS5tb2RlID0gVFlQRURPO1xuICAgICAgICBicmVhaztcbiAgICAgIH1cbiAgICAgIC8vPT09IE5FRURCSVRTKDE2KTtcbiAgICAgIHdoaWxlIChiaXRzIDwgMTYpIHtcbiAgICAgICAgaWYgKGhhdmUgPT09IDApIHsgYnJlYWsgaW5mX2xlYXZlOyB9XG4gICAgICAgIGhhdmUtLTtcbiAgICAgICAgaG9sZCArPSBpbnB1dFtuZXh0KytdIDw8IGJpdHM7XG4gICAgICAgIGJpdHMgKz0gODtcbiAgICAgIH1cbiAgICAgIC8vPT09Ly9cbiAgICAgIGlmICgoc3RhdGUud3JhcCAmIDIpICYmIGhvbGQgPT09IDB4OGIxZikgeyAgLyogZ3ppcCBoZWFkZXIgKi9cbiAgICAgICAgc3RhdGUuY2hlY2sgPSAwLypjcmMzMigwTCwgWl9OVUxMLCAwKSovO1xuICAgICAgICAvLz09PSBDUkMyKHN0YXRlLmNoZWNrLCBob2xkKTtcbiAgICAgICAgaGJ1ZlswXSA9IGhvbGQgJiAweGZmO1xuICAgICAgICBoYnVmWzFdID0gKGhvbGQgPj4+IDgpICYgMHhmZjtcbiAgICAgICAgc3RhdGUuY2hlY2sgPSBjcmMzMihzdGF0ZS5jaGVjaywgaGJ1ZiwgMiwgMCk7XG4gICAgICAgIC8vPT09Ly9cblxuICAgICAgICAvLz09PSBJTklUQklUUygpO1xuICAgICAgICBob2xkID0gMDtcbiAgICAgICAgYml0cyA9IDA7XG4gICAgICAgIC8vPT09Ly9cbiAgICAgICAgc3RhdGUubW9kZSA9IEZMQUdTO1xuICAgICAgICBicmVhaztcbiAgICAgIH1cbiAgICAgIHN0YXRlLmZsYWdzID0gMDsgICAgICAgICAgIC8qIGV4cGVjdCB6bGliIGhlYWRlciAqL1xuICAgICAgaWYgKHN0YXRlLmhlYWQpIHtcbiAgICAgICAgc3RhdGUuaGVhZC5kb25lID0gZmFsc2U7XG4gICAgICB9XG4gICAgICBpZiAoIShzdGF0ZS53cmFwICYgMSkgfHwgICAvKiBjaGVjayBpZiB6bGliIGhlYWRlciBhbGxvd2VkICovXG4gICAgICAgICgoKGhvbGQgJiAweGZmKS8qQklUUyg4KSovIDw8IDgpICsgKGhvbGQgPj4gOCkpICUgMzEpIHtcbiAgICAgICAgc3RybS5tc2cgPSAnaW5jb3JyZWN0IGhlYWRlciBjaGVjayc7XG4gICAgICAgIHN0YXRlLm1vZGUgPSBCQUQ7XG4gICAgICAgIGJyZWFrO1xuICAgICAgfVxuICAgICAgaWYgKChob2xkICYgMHgwZikvKkJJVFMoNCkqLyAhPT0gWl9ERUZMQVRFRCkge1xuICAgICAgICBzdHJtLm1zZyA9ICd1bmtub3duIGNvbXByZXNzaW9uIG1ldGhvZCc7XG4gICAgICAgIHN0YXRlLm1vZGUgPSBCQUQ7XG4gICAgICAgIGJyZWFrO1xuICAgICAgfVxuICAgICAgLy8tLS0gRFJPUEJJVFMoNCkgLS0tLy9cbiAgICAgIGhvbGQgPj4+PSA0O1xuICAgICAgYml0cyAtPSA0O1xuICAgICAgLy8tLS0vL1xuICAgICAgbGVuID0gKGhvbGQgJiAweDBmKS8qQklUUyg0KSovICsgODtcbiAgICAgIGlmIChzdGF0ZS53Yml0cyA9PT0gMCkge1xuICAgICAgICBzdGF0ZS53Yml0cyA9IGxlbjtcbiAgICAgIH1cbiAgICAgIGVsc2UgaWYgKGxlbiA+IHN0YXRlLndiaXRzKSB7XG4gICAgICAgIHN0cm0ubXNnID0gJ2ludmFsaWQgd2luZG93IHNpemUnO1xuICAgICAgICBzdGF0ZS5tb2RlID0gQkFEO1xuICAgICAgICBicmVhaztcbiAgICAgIH1cbiAgICAgIHN0YXRlLmRtYXggPSAxIDw8IGxlbjtcbiAgICAgIC8vVHJhY2V2KChzdGRlcnIsIFwiaW5mbGF0ZTogICB6bGliIGhlYWRlciBva1xcblwiKSk7XG4gICAgICBzdHJtLmFkbGVyID0gc3RhdGUuY2hlY2sgPSAxLyphZGxlcjMyKDBMLCBaX05VTEwsIDApKi87XG4gICAgICBzdGF0ZS5tb2RlID0gaG9sZCAmIDB4MjAwID8gRElDVElEIDogVFlQRTtcbiAgICAgIC8vPT09IElOSVRCSVRTKCk7XG4gICAgICBob2xkID0gMDtcbiAgICAgIGJpdHMgPSAwO1xuICAgICAgLy89PT0vL1xuICAgICAgYnJlYWs7XG4gICAgY2FzZSBGTEFHUzpcbiAgICAgIC8vPT09IE5FRURCSVRTKDE2KTsgKi9cbiAgICAgIHdoaWxlIChiaXRzIDwgMTYpIHtcbiAgICAgICAgaWYgKGhhdmUgPT09IDApIHsgYnJlYWsgaW5mX2xlYXZlOyB9XG4gICAgICAgIGhhdmUtLTtcbiAgICAgICAgaG9sZCArPSBpbnB1dFtuZXh0KytdIDw8IGJpdHM7XG4gICAgICAgIGJpdHMgKz0gODtcbiAgICAgIH1cbiAgICAgIC8vPT09Ly9cbiAgICAgIHN0YXRlLmZsYWdzID0gaG9sZDtcbiAgICAgIGlmICgoc3RhdGUuZmxhZ3MgJiAweGZmKSAhPT0gWl9ERUZMQVRFRCkge1xuICAgICAgICBzdHJtLm1zZyA9ICd1bmtub3duIGNvbXByZXNzaW9uIG1ldGhvZCc7XG4gICAgICAgIHN0YXRlLm1vZGUgPSBCQUQ7XG4gICAgICAgIGJyZWFrO1xuICAgICAgfVxuICAgICAgaWYgKHN0YXRlLmZsYWdzICYgMHhlMDAwKSB7XG4gICAgICAgIHN0cm0ubXNnID0gJ3Vua25vd24gaGVhZGVyIGZsYWdzIHNldCc7XG4gICAgICAgIHN0YXRlLm1vZGUgPSBCQUQ7XG4gICAgICAgIGJyZWFrO1xuICAgICAgfVxuICAgICAgaWYgKHN0YXRlLmhlYWQpIHtcbiAgICAgICAgc3RhdGUuaGVhZC50ZXh0ID0gKChob2xkID4+IDgpICYgMSk7XG4gICAgICB9XG4gICAgICBpZiAoc3RhdGUuZmxhZ3MgJiAweDAyMDApIHtcbiAgICAgICAgLy89PT0gQ1JDMihzdGF0ZS5jaGVjaywgaG9sZCk7XG4gICAgICAgIGhidWZbMF0gPSBob2xkICYgMHhmZjtcbiAgICAgICAgaGJ1ZlsxXSA9IChob2xkID4+PiA4KSAmIDB4ZmY7XG4gICAgICAgIHN0YXRlLmNoZWNrID0gY3JjMzIoc3RhdGUuY2hlY2ssIGhidWYsIDIsIDApO1xuICAgICAgICAvLz09PS8vXG4gICAgICB9XG4gICAgICAvLz09PSBJTklUQklUUygpO1xuICAgICAgaG9sZCA9IDA7XG4gICAgICBiaXRzID0gMDtcbiAgICAgIC8vPT09Ly9cbiAgICAgIHN0YXRlLm1vZGUgPSBUSU1FO1xuICAgICAgLyogZmFsbHMgdGhyb3VnaCAqL1xuICAgIGNhc2UgVElNRTpcbiAgICAgIC8vPT09IE5FRURCSVRTKDMyKTsgKi9cbiAgICAgIHdoaWxlIChiaXRzIDwgMzIpIHtcbiAgICAgICAgaWYgKGhhdmUgPT09IDApIHsgYnJlYWsgaW5mX2xlYXZlOyB9XG4gICAgICAgIGhhdmUtLTtcbiAgICAgICAgaG9sZCArPSBpbnB1dFtuZXh0KytdIDw8IGJpdHM7XG4gICAgICAgIGJpdHMgKz0gODtcbiAgICAgIH1cbiAgICAgIC8vPT09Ly9cbiAgICAgIGlmIChzdGF0ZS5oZWFkKSB7XG4gICAgICAgIHN0YXRlLmhlYWQudGltZSA9IGhvbGQ7XG4gICAgICB9XG4gICAgICBpZiAoc3RhdGUuZmxhZ3MgJiAweDAyMDApIHtcbiAgICAgICAgLy89PT0gQ1JDNChzdGF0ZS5jaGVjaywgaG9sZClcbiAgICAgICAgaGJ1ZlswXSA9IGhvbGQgJiAweGZmO1xuICAgICAgICBoYnVmWzFdID0gKGhvbGQgPj4+IDgpICYgMHhmZjtcbiAgICAgICAgaGJ1ZlsyXSA9IChob2xkID4+PiAxNikgJiAweGZmO1xuICAgICAgICBoYnVmWzNdID0gKGhvbGQgPj4+IDI0KSAmIDB4ZmY7XG4gICAgICAgIHN0YXRlLmNoZWNrID0gY3JjMzIoc3RhdGUuY2hlY2ssIGhidWYsIDQsIDApO1xuICAgICAgICAvLz09PVxuICAgICAgfVxuICAgICAgLy89PT0gSU5JVEJJVFMoKTtcbiAgICAgIGhvbGQgPSAwO1xuICAgICAgYml0cyA9IDA7XG4gICAgICAvLz09PS8vXG4gICAgICBzdGF0ZS5tb2RlID0gT1M7XG4gICAgICAvKiBmYWxscyB0aHJvdWdoICovXG4gICAgY2FzZSBPUzpcbiAgICAgIC8vPT09IE5FRURCSVRTKDE2KTsgKi9cbiAgICAgIHdoaWxlIChiaXRzIDwgMTYpIHtcbiAgICAgICAgaWYgKGhhdmUgPT09IDApIHsgYnJlYWsgaW5mX2xlYXZlOyB9XG4gICAgICAgIGhhdmUtLTtcbiAgICAgICAgaG9sZCArPSBpbnB1dFtuZXh0KytdIDw8IGJpdHM7XG4gICAgICAgIGJpdHMgKz0gODtcbiAgICAgIH1cbiAgICAgIC8vPT09Ly9cbiAgICAgIGlmIChzdGF0ZS5oZWFkKSB7XG4gICAgICAgIHN0YXRlLmhlYWQueGZsYWdzID0gKGhvbGQgJiAweGZmKTtcbiAgICAgICAgc3RhdGUuaGVhZC5vcyA9IChob2xkID4+IDgpO1xuICAgICAgfVxuICAgICAgaWYgKHN0YXRlLmZsYWdzICYgMHgwMjAwKSB7XG4gICAgICAgIC8vPT09IENSQzIoc3RhdGUuY2hlY2ssIGhvbGQpO1xuICAgICAgICBoYnVmWzBdID0gaG9sZCAmIDB4ZmY7XG4gICAgICAgIGhidWZbMV0gPSAoaG9sZCA+Pj4gOCkgJiAweGZmO1xuICAgICAgICBzdGF0ZS5jaGVjayA9IGNyYzMyKHN0YXRlLmNoZWNrLCBoYnVmLCAyLCAwKTtcbiAgICAgICAgLy89PT0vL1xuICAgICAgfVxuICAgICAgLy89PT0gSU5JVEJJVFMoKTtcbiAgICAgIGhvbGQgPSAwO1xuICAgICAgYml0cyA9IDA7XG4gICAgICAvLz09PS8vXG4gICAgICBzdGF0ZS5tb2RlID0gRVhMRU47XG4gICAgICAvKiBmYWxscyB0aHJvdWdoICovXG4gICAgY2FzZSBFWExFTjpcbiAgICAgIGlmIChzdGF0ZS5mbGFncyAmIDB4MDQwMCkge1xuICAgICAgICAvLz09PSBORUVEQklUUygxNik7ICovXG4gICAgICAgIHdoaWxlIChiaXRzIDwgMTYpIHtcbiAgICAgICAgICBpZiAoaGF2ZSA9PT0gMCkgeyBicmVhayBpbmZfbGVhdmU7IH1cbiAgICAgICAgICBoYXZlLS07XG4gICAgICAgICAgaG9sZCArPSBpbnB1dFtuZXh0KytdIDw8IGJpdHM7XG4gICAgICAgICAgYml0cyArPSA4O1xuICAgICAgICB9XG4gICAgICAgIC8vPT09Ly9cbiAgICAgICAgc3RhdGUubGVuZ3RoID0gaG9sZDtcbiAgICAgICAgaWYgKHN0YXRlLmhlYWQpIHtcbiAgICAgICAgICBzdGF0ZS5oZWFkLmV4dHJhX2xlbiA9IGhvbGQ7XG4gICAgICAgIH1cbiAgICAgICAgaWYgKHN0YXRlLmZsYWdzICYgMHgwMjAwKSB7XG4gICAgICAgICAgLy89PT0gQ1JDMihzdGF0ZS5jaGVjaywgaG9sZCk7XG4gICAgICAgICAgaGJ1ZlswXSA9IGhvbGQgJiAweGZmO1xuICAgICAgICAgIGhidWZbMV0gPSAoaG9sZCA+Pj4gOCkgJiAweGZmO1xuICAgICAgICAgIHN0YXRlLmNoZWNrID0gY3JjMzIoc3RhdGUuY2hlY2ssIGhidWYsIDIsIDApO1xuICAgICAgICAgIC8vPT09Ly9cbiAgICAgICAgfVxuICAgICAgICAvLz09PSBJTklUQklUUygpO1xuICAgICAgICBob2xkID0gMDtcbiAgICAgICAgYml0cyA9IDA7XG4gICAgICAgIC8vPT09Ly9cbiAgICAgIH1cbiAgICAgIGVsc2UgaWYgKHN0YXRlLmhlYWQpIHtcbiAgICAgICAgc3RhdGUuaGVhZC5leHRyYSA9IG51bGwvKlpfTlVMTCovO1xuICAgICAgfVxuICAgICAgc3RhdGUubW9kZSA9IEVYVFJBO1xuICAgICAgLyogZmFsbHMgdGhyb3VnaCAqL1xuICAgIGNhc2UgRVhUUkE6XG4gICAgICBpZiAoc3RhdGUuZmxhZ3MgJiAweDA0MDApIHtcbiAgICAgICAgY29weSA9IHN0YXRlLmxlbmd0aDtcbiAgICAgICAgaWYgKGNvcHkgPiBoYXZlKSB7IGNvcHkgPSBoYXZlOyB9XG4gICAgICAgIGlmIChjb3B5KSB7XG4gICAgICAgICAgaWYgKHN0YXRlLmhlYWQpIHtcbiAgICAgICAgICAgIGxlbiA9IHN0YXRlLmhlYWQuZXh0cmFfbGVuIC0gc3RhdGUubGVuZ3RoO1xuICAgICAgICAgICAgaWYgKCFzdGF0ZS5oZWFkLmV4dHJhKSB7XG4gICAgICAgICAgICAgIC8vIFVzZSB1bnR5cGVkIGFycmF5IGZvciBtb3JlIGNvbnZlbmllbmQgcHJvY2Vzc2luZyBsYXRlclxuICAgICAgICAgICAgICBzdGF0ZS5oZWFkLmV4dHJhID0gbmV3IEFycmF5KHN0YXRlLmhlYWQuZXh0cmFfbGVuKTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgICAgIHV0aWxzLmFycmF5U2V0KFxuICAgICAgICAgICAgICBzdGF0ZS5oZWFkLmV4dHJhLFxuICAgICAgICAgICAgICBpbnB1dCxcbiAgICAgICAgICAgICAgbmV4dCxcbiAgICAgICAgICAgICAgLy8gZXh0cmEgZmllbGQgaXMgbGltaXRlZCB0byA2NTUzNiBieXRlc1xuICAgICAgICAgICAgICAvLyAtIG5vIG5lZWQgZm9yIGFkZGl0aW9uYWwgc2l6ZSBjaGVja1xuICAgICAgICAgICAgICBjb3B5LFxuICAgICAgICAgICAgICAvKmxlbiArIGNvcHkgPiBzdGF0ZS5oZWFkLmV4dHJhX21heCAtIGxlbiA/IHN0YXRlLmhlYWQuZXh0cmFfbWF4IDogY29weSwqL1xuICAgICAgICAgICAgICBsZW5cbiAgICAgICAgICAgICk7XG4gICAgICAgICAgICAvL3ptZW1jcHkoc3RhdGUuaGVhZC5leHRyYSArIGxlbiwgbmV4dCxcbiAgICAgICAgICAgIC8vICAgICAgICBsZW4gKyBjb3B5ID4gc3RhdGUuaGVhZC5leHRyYV9tYXggP1xuICAgICAgICAgICAgLy8gICAgICAgIHN0YXRlLmhlYWQuZXh0cmFfbWF4IC0gbGVuIDogY29weSk7XG4gICAgICAgICAgfVxuICAgICAgICAgIGlmIChzdGF0ZS5mbGFncyAmIDB4MDIwMCkge1xuICAgICAgICAgICAgc3RhdGUuY2hlY2sgPSBjcmMzMihzdGF0ZS5jaGVjaywgaW5wdXQsIGNvcHksIG5leHQpO1xuICAgICAgICAgIH1cbiAgICAgICAgICBoYXZlIC09IGNvcHk7XG4gICAgICAgICAgbmV4dCArPSBjb3B5O1xuICAgICAgICAgIHN0YXRlLmxlbmd0aCAtPSBjb3B5O1xuICAgICAgICB9XG4gICAgICAgIGlmIChzdGF0ZS5sZW5ndGgpIHsgYnJlYWsgaW5mX2xlYXZlOyB9XG4gICAgICB9XG4gICAgICBzdGF0ZS5sZW5ndGggPSAwO1xuICAgICAgc3RhdGUubW9kZSA9IE5BTUU7XG4gICAgICAvKiBmYWxscyB0aHJvdWdoICovXG4gICAgY2FzZSBOQU1FOlxuICAgICAgaWYgKHN0YXRlLmZsYWdzICYgMHgwODAwKSB7XG4gICAgICAgIGlmIChoYXZlID09PSAwKSB7IGJyZWFrIGluZl9sZWF2ZTsgfVxuICAgICAgICBjb3B5ID0gMDtcbiAgICAgICAgZG8ge1xuICAgICAgICAgIC8vIFRPRE86IDIgb3IgMSBieXRlcz9cbiAgICAgICAgICBsZW4gPSBpbnB1dFtuZXh0ICsgY29weSsrXTtcbiAgICAgICAgICAvKiB1c2UgY29uc3RhbnQgbGltaXQgYmVjYXVzZSBpbiBqcyB3ZSBzaG91bGQgbm90IHByZWFsbG9jYXRlIG1lbW9yeSAqL1xuICAgICAgICAgIGlmIChzdGF0ZS5oZWFkICYmIGxlbiAmJlxuICAgICAgICAgICAgICAoc3RhdGUubGVuZ3RoIDwgNjU1MzYgLypzdGF0ZS5oZWFkLm5hbWVfbWF4Ki8pKSB7XG4gICAgICAgICAgICBzdGF0ZS5oZWFkLm5hbWUgKz0gU3RyaW5nLmZyb21DaGFyQ29kZShsZW4pO1xuICAgICAgICAgIH1cbiAgICAgICAgfSB3aGlsZSAobGVuICYmIGNvcHkgPCBoYXZlKTtcblxuICAgICAgICBpZiAoc3RhdGUuZmxhZ3MgJiAweDAyMDApIHtcbiAgICAgICAgICBzdGF0ZS5jaGVjayA9IGNyYzMyKHN0YXRlLmNoZWNrLCBpbnB1dCwgY29weSwgbmV4dCk7XG4gICAgICAgIH1cbiAgICAgICAgaGF2ZSAtPSBjb3B5O1xuICAgICAgICBuZXh0ICs9IGNvcHk7XG4gICAgICAgIGlmIChsZW4pIHsgYnJlYWsgaW5mX2xlYXZlOyB9XG4gICAgICB9XG4gICAgICBlbHNlIGlmIChzdGF0ZS5oZWFkKSB7XG4gICAgICAgIHN0YXRlLmhlYWQubmFtZSA9IG51bGw7XG4gICAgICB9XG4gICAgICBzdGF0ZS5sZW5ndGggPSAwO1xuICAgICAgc3RhdGUubW9kZSA9IENPTU1FTlQ7XG4gICAgICAvKiBmYWxscyB0aHJvdWdoICovXG4gICAgY2FzZSBDT01NRU5UOlxuICAgICAgaWYgKHN0YXRlLmZsYWdzICYgMHgxMDAwKSB7XG4gICAgICAgIGlmIChoYXZlID09PSAwKSB7IGJyZWFrIGluZl9sZWF2ZTsgfVxuICAgICAgICBjb3B5ID0gMDtcbiAgICAgICAgZG8ge1xuICAgICAgICAgIGxlbiA9IGlucHV0W25leHQgKyBjb3B5KytdO1xuICAgICAgICAgIC8qIHVzZSBjb25zdGFudCBsaW1pdCBiZWNhdXNlIGluIGpzIHdlIHNob3VsZCBub3QgcHJlYWxsb2NhdGUgbWVtb3J5ICovXG4gICAgICAgICAgaWYgKHN0YXRlLmhlYWQgJiYgbGVuICYmXG4gICAgICAgICAgICAgIChzdGF0ZS5sZW5ndGggPCA2NTUzNiAvKnN0YXRlLmhlYWQuY29tbV9tYXgqLykpIHtcbiAgICAgICAgICAgIHN0YXRlLmhlYWQuY29tbWVudCArPSBTdHJpbmcuZnJvbUNoYXJDb2RlKGxlbik7XG4gICAgICAgICAgfVxuICAgICAgICB9IHdoaWxlIChsZW4gJiYgY29weSA8IGhhdmUpO1xuICAgICAgICBpZiAoc3RhdGUuZmxhZ3MgJiAweDAyMDApIHtcbiAgICAgICAgICBzdGF0ZS5jaGVjayA9IGNyYzMyKHN0YXRlLmNoZWNrLCBpbnB1dCwgY29weSwgbmV4dCk7XG4gICAgICAgIH1cbiAgICAgICAgaGF2ZSAtPSBjb3B5O1xuICAgICAgICBuZXh0ICs9IGNvcHk7XG4gICAgICAgIGlmIChsZW4pIHsgYnJlYWsgaW5mX2xlYXZlOyB9XG4gICAgICB9XG4gICAgICBlbHNlIGlmIChzdGF0ZS5oZWFkKSB7XG4gICAgICAgIHN0YXRlLmhlYWQuY29tbWVudCA9IG51bGw7XG4gICAgICB9XG4gICAgICBzdGF0ZS5tb2RlID0gSENSQztcbiAgICAgIC8qIGZhbGxzIHRocm91Z2ggKi9cbiAgICBjYXNlIEhDUkM6XG4gICAgICBpZiAoc3RhdGUuZmxhZ3MgJiAweDAyMDApIHtcbiAgICAgICAgLy89PT0gTkVFREJJVFMoMTYpOyAqL1xuICAgICAgICB3aGlsZSAoYml0cyA8IDE2KSB7XG4gICAgICAgICAgaWYgKGhhdmUgPT09IDApIHsgYnJlYWsgaW5mX2xlYXZlOyB9XG4gICAgICAgICAgaGF2ZS0tO1xuICAgICAgICAgIGhvbGQgKz0gaW5wdXRbbmV4dCsrXSA8PCBiaXRzO1xuICAgICAgICAgIGJpdHMgKz0gODtcbiAgICAgICAgfVxuICAgICAgICAvLz09PS8vXG4gICAgICAgIGlmIChob2xkICE9PSAoc3RhdGUuY2hlY2sgJiAweGZmZmYpKSB7XG4gICAgICAgICAgc3RybS5tc2cgPSAnaGVhZGVyIGNyYyBtaXNtYXRjaCc7XG4gICAgICAgICAgc3RhdGUubW9kZSA9IEJBRDtcbiAgICAgICAgICBicmVhaztcbiAgICAgICAgfVxuICAgICAgICAvLz09PSBJTklUQklUUygpO1xuICAgICAgICBob2xkID0gMDtcbiAgICAgICAgYml0cyA9IDA7XG4gICAgICAgIC8vPT09Ly9cbiAgICAgIH1cbiAgICAgIGlmIChzdGF0ZS5oZWFkKSB7XG4gICAgICAgIHN0YXRlLmhlYWQuaGNyYyA9ICgoc3RhdGUuZmxhZ3MgPj4gOSkgJiAxKTtcbiAgICAgICAgc3RhdGUuaGVhZC5kb25lID0gdHJ1ZTtcbiAgICAgIH1cbiAgICAgIHN0cm0uYWRsZXIgPSBzdGF0ZS5jaGVjayA9IDAgLypjcmMzMigwTCwgWl9OVUxMLCAwKSovO1xuICAgICAgc3RhdGUubW9kZSA9IFRZUEU7XG4gICAgICBicmVhaztcbiAgICBjYXNlIERJQ1RJRDpcbiAgICAgIC8vPT09IE5FRURCSVRTKDMyKTsgKi9cbiAgICAgIHdoaWxlIChiaXRzIDwgMzIpIHtcbiAgICAgICAgaWYgKGhhdmUgPT09IDApIHsgYnJlYWsgaW5mX2xlYXZlOyB9XG4gICAgICAgIGhhdmUtLTtcbiAgICAgICAgaG9sZCArPSBpbnB1dFtuZXh0KytdIDw8IGJpdHM7XG4gICAgICAgIGJpdHMgKz0gODtcbiAgICAgIH1cbiAgICAgIC8vPT09Ly9cbiAgICAgIHN0cm0uYWRsZXIgPSBzdGF0ZS5jaGVjayA9IFpTV0FQMzIoaG9sZCk7XG4gICAgICAvLz09PSBJTklUQklUUygpO1xuICAgICAgaG9sZCA9IDA7XG4gICAgICBiaXRzID0gMDtcbiAgICAgIC8vPT09Ly9cbiAgICAgIHN0YXRlLm1vZGUgPSBESUNUO1xuICAgICAgLyogZmFsbHMgdGhyb3VnaCAqL1xuICAgIGNhc2UgRElDVDpcbiAgICAgIGlmIChzdGF0ZS5oYXZlZGljdCA9PT0gMCkge1xuICAgICAgICAvLy0tLSBSRVNUT1JFKCkgLS0tXG4gICAgICAgIHN0cm0ubmV4dF9vdXQgPSBwdXQ7XG4gICAgICAgIHN0cm0uYXZhaWxfb3V0ID0gbGVmdDtcbiAgICAgICAgc3RybS5uZXh0X2luID0gbmV4dDtcbiAgICAgICAgc3RybS5hdmFpbF9pbiA9IGhhdmU7XG4gICAgICAgIHN0YXRlLmhvbGQgPSBob2xkO1xuICAgICAgICBzdGF0ZS5iaXRzID0gYml0cztcbiAgICAgICAgLy8tLS1cbiAgICAgICAgcmV0dXJuIFpfTkVFRF9ESUNUO1xuICAgICAgfVxuICAgICAgc3RybS5hZGxlciA9IHN0YXRlLmNoZWNrID0gMS8qYWRsZXIzMigwTCwgWl9OVUxMLCAwKSovO1xuICAgICAgc3RhdGUubW9kZSA9IFRZUEU7XG4gICAgICAvKiBmYWxscyB0aHJvdWdoICovXG4gICAgY2FzZSBUWVBFOlxuICAgICAgaWYgKGZsdXNoID09PSBaX0JMT0NLIHx8IGZsdXNoID09PSBaX1RSRUVTKSB7IGJyZWFrIGluZl9sZWF2ZTsgfVxuICAgICAgLyogZmFsbHMgdGhyb3VnaCAqL1xuICAgIGNhc2UgVFlQRURPOlxuICAgICAgaWYgKHN0YXRlLmxhc3QpIHtcbiAgICAgICAgLy8tLS0gQllURUJJVFMoKSAtLS0vL1xuICAgICAgICBob2xkID4+Pj0gYml0cyAmIDc7XG4gICAgICAgIGJpdHMgLT0gYml0cyAmIDc7XG4gICAgICAgIC8vLS0tLy9cbiAgICAgICAgc3RhdGUubW9kZSA9IENIRUNLO1xuICAgICAgICBicmVhaztcbiAgICAgIH1cbiAgICAgIC8vPT09IE5FRURCSVRTKDMpOyAqL1xuICAgICAgd2hpbGUgKGJpdHMgPCAzKSB7XG4gICAgICAgIGlmIChoYXZlID09PSAwKSB7IGJyZWFrIGluZl9sZWF2ZTsgfVxuICAgICAgICBoYXZlLS07XG4gICAgICAgIGhvbGQgKz0gaW5wdXRbbmV4dCsrXSA8PCBiaXRzO1xuICAgICAgICBiaXRzICs9IDg7XG4gICAgICB9XG4gICAgICAvLz09PS8vXG4gICAgICBzdGF0ZS5sYXN0ID0gKGhvbGQgJiAweDAxKS8qQklUUygxKSovO1xuICAgICAgLy8tLS0gRFJPUEJJVFMoMSkgLS0tLy9cbiAgICAgIGhvbGQgPj4+PSAxO1xuICAgICAgYml0cyAtPSAxO1xuICAgICAgLy8tLS0vL1xuXG4gICAgICBzd2l0Y2ggKChob2xkICYgMHgwMykvKkJJVFMoMikqLykge1xuICAgICAgY2FzZSAwOiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgLyogc3RvcmVkIGJsb2NrICovXG4gICAgICAgIC8vVHJhY2V2KChzdGRlcnIsIFwiaW5mbGF0ZTogICAgIHN0b3JlZCBibG9jayVzXFxuXCIsXG4gICAgICAgIC8vICAgICAgICBzdGF0ZS5sYXN0ID8gXCIgKGxhc3QpXCIgOiBcIlwiKSk7XG4gICAgICAgIHN0YXRlLm1vZGUgPSBTVE9SRUQ7XG4gICAgICAgIGJyZWFrO1xuICAgICAgY2FzZSAxOiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgLyogZml4ZWQgYmxvY2sgKi9cbiAgICAgICAgZml4ZWR0YWJsZXMoc3RhdGUpO1xuICAgICAgICAvL1RyYWNldigoc3RkZXJyLCBcImluZmxhdGU6ICAgICBmaXhlZCBjb2RlcyBibG9jayVzXFxuXCIsXG4gICAgICAgIC8vICAgICAgICBzdGF0ZS5sYXN0ID8gXCIgKGxhc3QpXCIgOiBcIlwiKSk7XG4gICAgICAgIHN0YXRlLm1vZGUgPSBMRU5fOyAgICAgICAgICAgICAvKiBkZWNvZGUgY29kZXMgKi9cbiAgICAgICAgaWYgKGZsdXNoID09PSBaX1RSRUVTKSB7XG4gICAgICAgICAgLy8tLS0gRFJPUEJJVFMoMikgLS0tLy9cbiAgICAgICAgICBob2xkID4+Pj0gMjtcbiAgICAgICAgICBiaXRzIC09IDI7XG4gICAgICAgICAgLy8tLS0vL1xuICAgICAgICAgIGJyZWFrIGluZl9sZWF2ZTtcbiAgICAgICAgfVxuICAgICAgICBicmVhaztcbiAgICAgIGNhc2UgMjogICAgICAgICAgICAgICAgICAgICAgICAgICAgIC8qIGR5bmFtaWMgYmxvY2sgKi9cbiAgICAgICAgLy9UcmFjZXYoKHN0ZGVyciwgXCJpbmZsYXRlOiAgICAgZHluYW1pYyBjb2RlcyBibG9jayVzXFxuXCIsXG4gICAgICAgIC8vICAgICAgICBzdGF0ZS5sYXN0ID8gXCIgKGxhc3QpXCIgOiBcIlwiKSk7XG4gICAgICAgIHN0YXRlLm1vZGUgPSBUQUJMRTtcbiAgICAgICAgYnJlYWs7XG4gICAgICBjYXNlIDM6XG4gICAgICAgIHN0cm0ubXNnID0gJ2ludmFsaWQgYmxvY2sgdHlwZSc7XG4gICAgICAgIHN0YXRlLm1vZGUgPSBCQUQ7XG4gICAgICB9XG4gICAgICAvLy0tLSBEUk9QQklUUygyKSAtLS0vL1xuICAgICAgaG9sZCA+Pj49IDI7XG4gICAgICBiaXRzIC09IDI7XG4gICAgICAvLy0tLS8vXG4gICAgICBicmVhaztcbiAgICBjYXNlIFNUT1JFRDpcbiAgICAgIC8vLS0tIEJZVEVCSVRTKCkgLS0tLy8gLyogZ28gdG8gYnl0ZSBib3VuZGFyeSAqL1xuICAgICAgaG9sZCA+Pj49IGJpdHMgJiA3O1xuICAgICAgYml0cyAtPSBiaXRzICYgNztcbiAgICAgIC8vLS0tLy9cbiAgICAgIC8vPT09IE5FRURCSVRTKDMyKTsgKi9cbiAgICAgIHdoaWxlIChiaXRzIDwgMzIpIHtcbiAgICAgICAgaWYgKGhhdmUgPT09IDApIHsgYnJlYWsgaW5mX2xlYXZlOyB9XG4gICAgICAgIGhhdmUtLTtcbiAgICAgICAgaG9sZCArPSBpbnB1dFtuZXh0KytdIDw8IGJpdHM7XG4gICAgICAgIGJpdHMgKz0gODtcbiAgICAgIH1cbiAgICAgIC8vPT09Ly9cbiAgICAgIGlmICgoaG9sZCAmIDB4ZmZmZikgIT09ICgoaG9sZCA+Pj4gMTYpIF4gMHhmZmZmKSkge1xuICAgICAgICBzdHJtLm1zZyA9ICdpbnZhbGlkIHN0b3JlZCBibG9jayBsZW5ndGhzJztcbiAgICAgICAgc3RhdGUubW9kZSA9IEJBRDtcbiAgICAgICAgYnJlYWs7XG4gICAgICB9XG4gICAgICBzdGF0ZS5sZW5ndGggPSBob2xkICYgMHhmZmZmO1xuICAgICAgLy9UcmFjZXYoKHN0ZGVyciwgXCJpbmZsYXRlOiAgICAgICBzdG9yZWQgbGVuZ3RoICV1XFxuXCIsXG4gICAgICAvLyAgICAgICAgc3RhdGUubGVuZ3RoKSk7XG4gICAgICAvLz09PSBJTklUQklUUygpO1xuICAgICAgaG9sZCA9IDA7XG4gICAgICBiaXRzID0gMDtcbiAgICAgIC8vPT09Ly9cbiAgICAgIHN0YXRlLm1vZGUgPSBDT1BZXztcbiAgICAgIGlmIChmbHVzaCA9PT0gWl9UUkVFUykgeyBicmVhayBpbmZfbGVhdmU7IH1cbiAgICAgIC8qIGZhbGxzIHRocm91Z2ggKi9cbiAgICBjYXNlIENPUFlfOlxuICAgICAgc3RhdGUubW9kZSA9IENPUFk7XG4gICAgICAvKiBmYWxscyB0aHJvdWdoICovXG4gICAgY2FzZSBDT1BZOlxuICAgICAgY29weSA9IHN0YXRlLmxlbmd0aDtcbiAgICAgIGlmIChjb3B5KSB7XG4gICAgICAgIGlmIChjb3B5ID4gaGF2ZSkgeyBjb3B5ID0gaGF2ZTsgfVxuICAgICAgICBpZiAoY29weSA+IGxlZnQpIHsgY29weSA9IGxlZnQ7IH1cbiAgICAgICAgaWYgKGNvcHkgPT09IDApIHsgYnJlYWsgaW5mX2xlYXZlOyB9XG4gICAgICAgIC8vLS0tIHptZW1jcHkocHV0LCBuZXh0LCBjb3B5KTsgLS0tXG4gICAgICAgIHV0aWxzLmFycmF5U2V0KG91dHB1dCwgaW5wdXQsIG5leHQsIGNvcHksIHB1dCk7XG4gICAgICAgIC8vLS0tLy9cbiAgICAgICAgaGF2ZSAtPSBjb3B5O1xuICAgICAgICBuZXh0ICs9IGNvcHk7XG4gICAgICAgIGxlZnQgLT0gY29weTtcbiAgICAgICAgcHV0ICs9IGNvcHk7XG4gICAgICAgIHN0YXRlLmxlbmd0aCAtPSBjb3B5O1xuICAgICAgICBicmVhaztcbiAgICAgIH1cbiAgICAgIC8vVHJhY2V2KChzdGRlcnIsIFwiaW5mbGF0ZTogICAgICAgc3RvcmVkIGVuZFxcblwiKSk7XG4gICAgICBzdGF0ZS5tb2RlID0gVFlQRTtcbiAgICAgIGJyZWFrO1xuICAgIGNhc2UgVEFCTEU6XG4gICAgICAvLz09PSBORUVEQklUUygxNCk7ICovXG4gICAgICB3aGlsZSAoYml0cyA8IDE0KSB7XG4gICAgICAgIGlmIChoYXZlID09PSAwKSB7IGJyZWFrIGluZl9sZWF2ZTsgfVxuICAgICAgICBoYXZlLS07XG4gICAgICAgIGhvbGQgKz0gaW5wdXRbbmV4dCsrXSA8PCBiaXRzO1xuICAgICAgICBiaXRzICs9IDg7XG4gICAgICB9XG4gICAgICAvLz09PS8vXG4gICAgICBzdGF0ZS5ubGVuID0gKGhvbGQgJiAweDFmKS8qQklUUyg1KSovICsgMjU3O1xuICAgICAgLy8tLS0gRFJPUEJJVFMoNSkgLS0tLy9cbiAgICAgIGhvbGQgPj4+PSA1O1xuICAgICAgYml0cyAtPSA1O1xuICAgICAgLy8tLS0vL1xuICAgICAgc3RhdGUubmRpc3QgPSAoaG9sZCAmIDB4MWYpLypCSVRTKDUpKi8gKyAxO1xuICAgICAgLy8tLS0gRFJPUEJJVFMoNSkgLS0tLy9cbiAgICAgIGhvbGQgPj4+PSA1O1xuICAgICAgYml0cyAtPSA1O1xuICAgICAgLy8tLS0vL1xuICAgICAgc3RhdGUubmNvZGUgPSAoaG9sZCAmIDB4MGYpLypCSVRTKDQpKi8gKyA0O1xuICAgICAgLy8tLS0gRFJPUEJJVFMoNCkgLS0tLy9cbiAgICAgIGhvbGQgPj4+PSA0O1xuICAgICAgYml0cyAtPSA0O1xuICAgICAgLy8tLS0vL1xuLy8jaWZuZGVmIFBLWklQX0JVR19XT1JLQVJPVU5EXG4gICAgICBpZiAoc3RhdGUubmxlbiA+IDI4NiB8fCBzdGF0ZS5uZGlzdCA+IDMwKSB7XG4gICAgICAgIHN0cm0ubXNnID0gJ3RvbyBtYW55IGxlbmd0aCBvciBkaXN0YW5jZSBzeW1ib2xzJztcbiAgICAgICAgc3RhdGUubW9kZSA9IEJBRDtcbiAgICAgICAgYnJlYWs7XG4gICAgICB9XG4vLyNlbmRpZlxuICAgICAgLy9UcmFjZXYoKHN0ZGVyciwgXCJpbmZsYXRlOiAgICAgICB0YWJsZSBzaXplcyBva1xcblwiKSk7XG4gICAgICBzdGF0ZS5oYXZlID0gMDtcbiAgICAgIHN0YXRlLm1vZGUgPSBMRU5MRU5TO1xuICAgICAgLyogZmFsbHMgdGhyb3VnaCAqL1xuICAgIGNhc2UgTEVOTEVOUzpcbiAgICAgIHdoaWxlIChzdGF0ZS5oYXZlIDwgc3RhdGUubmNvZGUpIHtcbiAgICAgICAgLy89PT0gTkVFREJJVFMoMyk7XG4gICAgICAgIHdoaWxlIChiaXRzIDwgMykge1xuICAgICAgICAgIGlmIChoYXZlID09PSAwKSB7IGJyZWFrIGluZl9sZWF2ZTsgfVxuICAgICAgICAgIGhhdmUtLTtcbiAgICAgICAgICBob2xkICs9IGlucHV0W25leHQrK10gPDwgYml0cztcbiAgICAgICAgICBiaXRzICs9IDg7XG4gICAgICAgIH1cbiAgICAgICAgLy89PT0vL1xuICAgICAgICBzdGF0ZS5sZW5zW29yZGVyW3N0YXRlLmhhdmUrK11dID0gKGhvbGQgJiAweDA3KTsvL0JJVFMoMyk7XG4gICAgICAgIC8vLS0tIERST1BCSVRTKDMpIC0tLS8vXG4gICAgICAgIGhvbGQgPj4+PSAzO1xuICAgICAgICBiaXRzIC09IDM7XG4gICAgICAgIC8vLS0tLy9cbiAgICAgIH1cbiAgICAgIHdoaWxlIChzdGF0ZS5oYXZlIDwgMTkpIHtcbiAgICAgICAgc3RhdGUubGVuc1tvcmRlcltzdGF0ZS5oYXZlKytdXSA9IDA7XG4gICAgICB9XG4gICAgICAvLyBXZSBoYXZlIHNlcGFyYXRlIHRhYmxlcyAmIG5vIHBvaW50ZXJzLiAyIGNvbW1lbnRlZCBsaW5lcyBiZWxvdyBub3QgbmVlZGVkLlxuICAgICAgLy9zdGF0ZS5uZXh0ID0gc3RhdGUuY29kZXM7XG4gICAgICAvL3N0YXRlLmxlbmNvZGUgPSBzdGF0ZS5uZXh0O1xuICAgICAgLy8gU3dpdGNoIHRvIHVzZSBkeW5hbWljIHRhYmxlXG4gICAgICBzdGF0ZS5sZW5jb2RlID0gc3RhdGUubGVuZHluO1xuICAgICAgc3RhdGUubGVuYml0cyA9IDc7XG5cbiAgICAgIG9wdHMgPSB7Yml0czogc3RhdGUubGVuYml0c307XG4gICAgICByZXQgPSBpbmZsYXRlX3RhYmxlKENPREVTLCBzdGF0ZS5sZW5zLCAwLCAxOSwgc3RhdGUubGVuY29kZSwgMCwgc3RhdGUud29yaywgb3B0cyk7XG4gICAgICBzdGF0ZS5sZW5iaXRzID0gb3B0cy5iaXRzO1xuXG4gICAgICBpZiAocmV0KSB7XG4gICAgICAgIHN0cm0ubXNnID0gJ2ludmFsaWQgY29kZSBsZW5ndGhzIHNldCc7XG4gICAgICAgIHN0YXRlLm1vZGUgPSBCQUQ7XG4gICAgICAgIGJyZWFrO1xuICAgICAgfVxuICAgICAgLy9UcmFjZXYoKHN0ZGVyciwgXCJpbmZsYXRlOiAgICAgICBjb2RlIGxlbmd0aHMgb2tcXG5cIikpO1xuICAgICAgc3RhdGUuaGF2ZSA9IDA7XG4gICAgICBzdGF0ZS5tb2RlID0gQ09ERUxFTlM7XG4gICAgICAvKiBmYWxscyB0aHJvdWdoICovXG4gICAgY2FzZSBDT0RFTEVOUzpcbiAgICAgIHdoaWxlIChzdGF0ZS5oYXZlIDwgc3RhdGUubmxlbiArIHN0YXRlLm5kaXN0KSB7XG4gICAgICAgIGZvciAoOzspIHtcbiAgICAgICAgICBoZXJlID0gc3RhdGUubGVuY29kZVtob2xkICYgKCgxIDw8IHN0YXRlLmxlbmJpdHMpIC0gMSldOy8qQklUUyhzdGF0ZS5sZW5iaXRzKSovXG4gICAgICAgICAgaGVyZV9iaXRzID0gaGVyZSA+Pj4gMjQ7XG4gICAgICAgICAgaGVyZV9vcCA9IChoZXJlID4+PiAxNikgJiAweGZmO1xuICAgICAgICAgIGhlcmVfdmFsID0gaGVyZSAmIDB4ZmZmZjtcblxuICAgICAgICAgIGlmICgoaGVyZV9iaXRzKSA8PSBiaXRzKSB7IGJyZWFrOyB9XG4gICAgICAgICAgLy8tLS0gUFVMTEJZVEUoKSAtLS0vL1xuICAgICAgICAgIGlmIChoYXZlID09PSAwKSB7IGJyZWFrIGluZl9sZWF2ZTsgfVxuICAgICAgICAgIGhhdmUtLTtcbiAgICAgICAgICBob2xkICs9IGlucHV0W25leHQrK10gPDwgYml0cztcbiAgICAgICAgICBiaXRzICs9IDg7XG4gICAgICAgICAgLy8tLS0vL1xuICAgICAgICB9XG4gICAgICAgIGlmIChoZXJlX3ZhbCA8IDE2KSB7XG4gICAgICAgICAgLy8tLS0gRFJPUEJJVFMoaGVyZS5iaXRzKSAtLS0vL1xuICAgICAgICAgIGhvbGQgPj4+PSBoZXJlX2JpdHM7XG4gICAgICAgICAgYml0cyAtPSBoZXJlX2JpdHM7XG4gICAgICAgICAgLy8tLS0vL1xuICAgICAgICAgIHN0YXRlLmxlbnNbc3RhdGUuaGF2ZSsrXSA9IGhlcmVfdmFsO1xuICAgICAgICB9XG4gICAgICAgIGVsc2Uge1xuICAgICAgICAgIGlmIChoZXJlX3ZhbCA9PT0gMTYpIHtcbiAgICAgICAgICAgIC8vPT09IE5FRURCSVRTKGhlcmUuYml0cyArIDIpO1xuICAgICAgICAgICAgbiA9IGhlcmVfYml0cyArIDI7XG4gICAgICAgICAgICB3aGlsZSAoYml0cyA8IG4pIHtcbiAgICAgICAgICAgICAgaWYgKGhhdmUgPT09IDApIHsgYnJlYWsgaW5mX2xlYXZlOyB9XG4gICAgICAgICAgICAgIGhhdmUtLTtcbiAgICAgICAgICAgICAgaG9sZCArPSBpbnB1dFtuZXh0KytdIDw8IGJpdHM7XG4gICAgICAgICAgICAgIGJpdHMgKz0gODtcbiAgICAgICAgICAgIH1cbiAgICAgICAgICAgIC8vPT09Ly9cbiAgICAgICAgICAgIC8vLS0tIERST1BCSVRTKGhlcmUuYml0cykgLS0tLy9cbiAgICAgICAgICAgIGhvbGQgPj4+PSBoZXJlX2JpdHM7XG4gICAgICAgICAgICBiaXRzIC09IGhlcmVfYml0cztcbiAgICAgICAgICAgIC8vLS0tLy9cbiAgICAgICAgICAgIGlmIChzdGF0ZS5oYXZlID09PSAwKSB7XG4gICAgICAgICAgICAgIHN0cm0ubXNnID0gJ2ludmFsaWQgYml0IGxlbmd0aCByZXBlYXQnO1xuICAgICAgICAgICAgICBzdGF0ZS5tb2RlID0gQkFEO1xuICAgICAgICAgICAgICBicmVhaztcbiAgICAgICAgICAgIH1cbiAgICAgICAgICAgIGxlbiA9IHN0YXRlLmxlbnNbc3RhdGUuaGF2ZSAtIDFdO1xuICAgICAgICAgICAgY29weSA9IDMgKyAoaG9sZCAmIDB4MDMpOy8vQklUUygyKTtcbiAgICAgICAgICAgIC8vLS0tIERST1BCSVRTKDIpIC0tLS8vXG4gICAgICAgICAgICBob2xkID4+Pj0gMjtcbiAgICAgICAgICAgIGJpdHMgLT0gMjtcbiAgICAgICAgICAgIC8vLS0tLy9cbiAgICAgICAgICB9XG4gICAgICAgICAgZWxzZSBpZiAoaGVyZV92YWwgPT09IDE3KSB7XG4gICAgICAgICAgICAvLz09PSBORUVEQklUUyhoZXJlLmJpdHMgKyAzKTtcbiAgICAgICAgICAgIG4gPSBoZXJlX2JpdHMgKyAzO1xuICAgICAgICAgICAgd2hpbGUgKGJpdHMgPCBuKSB7XG4gICAgICAgICAgICAgIGlmIChoYXZlID09PSAwKSB7IGJyZWFrIGluZl9sZWF2ZTsgfVxuICAgICAgICAgICAgICBoYXZlLS07XG4gICAgICAgICAgICAgIGhvbGQgKz0gaW5wdXRbbmV4dCsrXSA8PCBiaXRzO1xuICAgICAgICAgICAgICBiaXRzICs9IDg7XG4gICAgICAgICAgICB9XG4gICAgICAgICAgICAvLz09PS8vXG4gICAgICAgICAgICAvLy0tLSBEUk9QQklUUyhoZXJlLmJpdHMpIC0tLS8vXG4gICAgICAgICAgICBob2xkID4+Pj0gaGVyZV9iaXRzO1xuICAgICAgICAgICAgYml0cyAtPSBoZXJlX2JpdHM7XG4gICAgICAgICAgICAvLy0tLS8vXG4gICAgICAgICAgICBsZW4gPSAwO1xuICAgICAgICAgICAgY29weSA9IDMgKyAoaG9sZCAmIDB4MDcpOy8vQklUUygzKTtcbiAgICAgICAgICAgIC8vLS0tIERST1BCSVRTKDMpIC0tLS8vXG4gICAgICAgICAgICBob2xkID4+Pj0gMztcbiAgICAgICAgICAgIGJpdHMgLT0gMztcbiAgICAgICAgICAgIC8vLS0tLy9cbiAgICAgICAgICB9XG4gICAgICAgICAgZWxzZSB7XG4gICAgICAgICAgICAvLz09PSBORUVEQklUUyhoZXJlLmJpdHMgKyA3KTtcbiAgICAgICAgICAgIG4gPSBoZXJlX2JpdHMgKyA3O1xuICAgICAgICAgICAgd2hpbGUgKGJpdHMgPCBuKSB7XG4gICAgICAgICAgICAgIGlmIChoYXZlID09PSAwKSB7IGJyZWFrIGluZl9sZWF2ZTsgfVxuICAgICAgICAgICAgICBoYXZlLS07XG4gICAgICAgICAgICAgIGhvbGQgKz0gaW5wdXRbbmV4dCsrXSA8PCBiaXRzO1xuICAgICAgICAgICAgICBiaXRzICs9IDg7XG4gICAgICAgICAgICB9XG4gICAgICAgICAgICAvLz09PS8vXG4gICAgICAgICAgICAvLy0tLSBEUk9QQklUUyhoZXJlLmJpdHMpIC0tLS8vXG4gICAgICAgICAgICBob2xkID4+Pj0gaGVyZV9iaXRzO1xuICAgICAgICAgICAgYml0cyAtPSBoZXJlX2JpdHM7XG4gICAgICAgICAgICAvLy0tLS8vXG4gICAgICAgICAgICBsZW4gPSAwO1xuICAgICAgICAgICAgY29weSA9IDExICsgKGhvbGQgJiAweDdmKTsvL0JJVFMoNyk7XG4gICAgICAgICAgICAvLy0tLSBEUk9QQklUUyg3KSAtLS0vL1xuICAgICAgICAgICAgaG9sZCA+Pj49IDc7XG4gICAgICAgICAgICBiaXRzIC09IDc7XG4gICAgICAgICAgICAvLy0tLS8vXG4gICAgICAgICAgfVxuICAgICAgICAgIGlmIChzdGF0ZS5oYXZlICsgY29weSA+IHN0YXRlLm5sZW4gKyBzdGF0ZS5uZGlzdCkge1xuICAgICAgICAgICAgc3RybS5tc2cgPSAnaW52YWxpZCBiaXQgbGVuZ3RoIHJlcGVhdCc7XG4gICAgICAgICAgICBzdGF0ZS5tb2RlID0gQkFEO1xuICAgICAgICAgICAgYnJlYWs7XG4gICAgICAgICAgfVxuICAgICAgICAgIHdoaWxlIChjb3B5LS0pIHtcbiAgICAgICAgICAgIHN0YXRlLmxlbnNbc3RhdGUuaGF2ZSsrXSA9IGxlbjtcbiAgICAgICAgICB9XG4gICAgICAgIH1cbiAgICAgIH1cblxuICAgICAgLyogaGFuZGxlIGVycm9yIGJyZWFrcyBpbiB3aGlsZSAqL1xuICAgICAgaWYgKHN0YXRlLm1vZGUgPT09IEJBRCkgeyBicmVhazsgfVxuXG4gICAgICAvKiBjaGVjayBmb3IgZW5kLW9mLWJsb2NrIGNvZGUgKGJldHRlciBoYXZlIG9uZSkgKi9cbiAgICAgIGlmIChzdGF0ZS5sZW5zWzI1Nl0gPT09IDApIHtcbiAgICAgICAgc3RybS5tc2cgPSAnaW52YWxpZCBjb2RlIC0tIG1pc3NpbmcgZW5kLW9mLWJsb2NrJztcbiAgICAgICAgc3RhdGUubW9kZSA9IEJBRDtcbiAgICAgICAgYnJlYWs7XG4gICAgICB9XG5cbiAgICAgIC8qIGJ1aWxkIGNvZGUgdGFibGVzIC0tIG5vdGU6IGRvIG5vdCBjaGFuZ2UgdGhlIGxlbmJpdHMgb3IgZGlzdGJpdHNcbiAgICAgICAgIHZhbHVlcyBoZXJlICg5IGFuZCA2KSB3aXRob3V0IHJlYWRpbmcgdGhlIGNvbW1lbnRzIGluIGluZnRyZWVzLmhcbiAgICAgICAgIGNvbmNlcm5pbmcgdGhlIEVOT1VHSCBjb25zdGFudHMsIHdoaWNoIGRlcGVuZCBvbiB0aG9zZSB2YWx1ZXMgKi9cbiAgICAgIHN0YXRlLmxlbmJpdHMgPSA5O1xuXG4gICAgICBvcHRzID0ge2JpdHM6IHN0YXRlLmxlbmJpdHN9O1xuICAgICAgcmV0ID0gaW5mbGF0ZV90YWJsZShMRU5TLCBzdGF0ZS5sZW5zLCAwLCBzdGF0ZS5ubGVuLCBzdGF0ZS5sZW5jb2RlLCAwLCBzdGF0ZS53b3JrLCBvcHRzKTtcbiAgICAgIC8vIFdlIGhhdmUgc2VwYXJhdGUgdGFibGVzICYgbm8gcG9pbnRlcnMuIDIgY29tbWVudGVkIGxpbmVzIGJlbG93IG5vdCBuZWVkZWQuXG4gICAgICAvLyBzdGF0ZS5uZXh0X2luZGV4ID0gb3B0cy50YWJsZV9pbmRleDtcbiAgICAgIHN0YXRlLmxlbmJpdHMgPSBvcHRzLmJpdHM7XG4gICAgICAvLyBzdGF0ZS5sZW5jb2RlID0gc3RhdGUubmV4dDtcblxuICAgICAgaWYgKHJldCkge1xuICAgICAgICBzdHJtLm1zZyA9ICdpbnZhbGlkIGxpdGVyYWwvbGVuZ3RocyBzZXQnO1xuICAgICAgICBzdGF0ZS5tb2RlID0gQkFEO1xuICAgICAgICBicmVhaztcbiAgICAgIH1cblxuICAgICAgc3RhdGUuZGlzdGJpdHMgPSA2O1xuICAgICAgLy9zdGF0ZS5kaXN0Y29kZS5jb3B5KHN0YXRlLmNvZGVzKTtcbiAgICAgIC8vIFN3aXRjaCB0byB1c2UgZHluYW1pYyB0YWJsZVxuICAgICAgc3RhdGUuZGlzdGNvZGUgPSBzdGF0ZS5kaXN0ZHluO1xuICAgICAgb3B0cyA9IHtiaXRzOiBzdGF0ZS5kaXN0Yml0c307XG4gICAgICByZXQgPSBpbmZsYXRlX3RhYmxlKERJU1RTLCBzdGF0ZS5sZW5zLCBzdGF0ZS5ubGVuLCBzdGF0ZS5uZGlzdCwgc3RhdGUuZGlzdGNvZGUsIDAsIHN0YXRlLndvcmssIG9wdHMpO1xuICAgICAgLy8gV2UgaGF2ZSBzZXBhcmF0ZSB0YWJsZXMgJiBubyBwb2ludGVycy4gMiBjb21tZW50ZWQgbGluZXMgYmVsb3cgbm90IG5lZWRlZC5cbiAgICAgIC8vIHN0YXRlLm5leHRfaW5kZXggPSBvcHRzLnRhYmxlX2luZGV4O1xuICAgICAgc3RhdGUuZGlzdGJpdHMgPSBvcHRzLmJpdHM7XG4gICAgICAvLyBzdGF0ZS5kaXN0Y29kZSA9IHN0YXRlLm5leHQ7XG5cbiAgICAgIGlmIChyZXQpIHtcbiAgICAgICAgc3RybS5tc2cgPSAnaW52YWxpZCBkaXN0YW5jZXMgc2V0JztcbiAgICAgICAgc3RhdGUubW9kZSA9IEJBRDtcbiAgICAgICAgYnJlYWs7XG4gICAgICB9XG4gICAgICAvL1RyYWNldigoc3RkZXJyLCAnaW5mbGF0ZTogICAgICAgY29kZXMgb2tcXG4nKSk7XG4gICAgICBzdGF0ZS5tb2RlID0gTEVOXztcbiAgICAgIGlmIChmbHVzaCA9PT0gWl9UUkVFUykgeyBicmVhayBpbmZfbGVhdmU7IH1cbiAgICAgIC8qIGZhbGxzIHRocm91Z2ggKi9cbiAgICBjYXNlIExFTl86XG4gICAgICBzdGF0ZS5tb2RlID0gTEVOO1xuICAgICAgLyogZmFsbHMgdGhyb3VnaCAqL1xuICAgIGNhc2UgTEVOOlxuICAgICAgaWYgKGhhdmUgPj0gNiAmJiBsZWZ0ID49IDI1OCkge1xuICAgICAgICAvLy0tLSBSRVNUT1JFKCkgLS0tXG4gICAgICAgIHN0cm0ubmV4dF9vdXQgPSBwdXQ7XG4gICAgICAgIHN0cm0uYXZhaWxfb3V0ID0gbGVmdDtcbiAgICAgICAgc3RybS5uZXh0X2luID0gbmV4dDtcbiAgICAgICAgc3RybS5hdmFpbF9pbiA9IGhhdmU7XG4gICAgICAgIHN0YXRlLmhvbGQgPSBob2xkO1xuICAgICAgICBzdGF0ZS5iaXRzID0gYml0cztcbiAgICAgICAgLy8tLS1cbiAgICAgICAgaW5mbGF0ZV9mYXN0KHN0cm0sIF9vdXQpO1xuICAgICAgICAvLy0tLSBMT0FEKCkgLS0tXG4gICAgICAgIHB1dCA9IHN0cm0ubmV4dF9vdXQ7XG4gICAgICAgIG91dHB1dCA9IHN0cm0ub3V0cHV0O1xuICAgICAgICBsZWZ0ID0gc3RybS5hdmFpbF9vdXQ7XG4gICAgICAgIG5leHQgPSBzdHJtLm5leHRfaW47XG4gICAgICAgIGlucHV0ID0gc3RybS5pbnB1dDtcbiAgICAgICAgaGF2ZSA9IHN0cm0uYXZhaWxfaW47XG4gICAgICAgIGhvbGQgPSBzdGF0ZS5ob2xkO1xuICAgICAgICBiaXRzID0gc3RhdGUuYml0cztcbiAgICAgICAgLy8tLS1cblxuICAgICAgICBpZiAoc3RhdGUubW9kZSA9PT0gVFlQRSkge1xuICAgICAgICAgIHN0YXRlLmJhY2sgPSAtMTtcbiAgICAgICAgfVxuICAgICAgICBicmVhaztcbiAgICAgIH1cbiAgICAgIHN0YXRlLmJhY2sgPSAwO1xuICAgICAgZm9yICg7Oykge1xuICAgICAgICBoZXJlID0gc3RhdGUubGVuY29kZVtob2xkICYgKCgxIDw8IHN0YXRlLmxlbmJpdHMpIC0xKV07ICAvKkJJVFMoc3RhdGUubGVuYml0cykqL1xuICAgICAgICBoZXJlX2JpdHMgPSBoZXJlID4+PiAyNDtcbiAgICAgICAgaGVyZV9vcCA9IChoZXJlID4+PiAxNikgJiAweGZmO1xuICAgICAgICBoZXJlX3ZhbCA9IGhlcmUgJiAweGZmZmY7XG5cbiAgICAgICAgaWYgKGhlcmVfYml0cyA8PSBiaXRzKSB7IGJyZWFrOyB9XG4gICAgICAgIC8vLS0tIFBVTExCWVRFKCkgLS0tLy9cbiAgICAgICAgaWYgKGhhdmUgPT09IDApIHsgYnJlYWsgaW5mX2xlYXZlOyB9XG4gICAgICAgIGhhdmUtLTtcbiAgICAgICAgaG9sZCArPSBpbnB1dFtuZXh0KytdIDw8IGJpdHM7XG4gICAgICAgIGJpdHMgKz0gODtcbiAgICAgICAgLy8tLS0vL1xuICAgICAgfVxuICAgICAgaWYgKGhlcmVfb3AgJiYgKGhlcmVfb3AgJiAweGYwKSA9PT0gMCkge1xuICAgICAgICBsYXN0X2JpdHMgPSBoZXJlX2JpdHM7XG4gICAgICAgIGxhc3Rfb3AgPSBoZXJlX29wO1xuICAgICAgICBsYXN0X3ZhbCA9IGhlcmVfdmFsO1xuICAgICAgICBmb3IgKDs7KSB7XG4gICAgICAgICAgaGVyZSA9IHN0YXRlLmxlbmNvZGVbbGFzdF92YWwgK1xuICAgICAgICAgICAgICAgICAgKChob2xkICYgKCgxIDw8IChsYXN0X2JpdHMgKyBsYXN0X29wKSkgLTEpKS8qQklUUyhsYXN0LmJpdHMgKyBsYXN0Lm9wKSovID4+IGxhc3RfYml0cyldO1xuICAgICAgICAgIGhlcmVfYml0cyA9IGhlcmUgPj4+IDI0O1xuICAgICAgICAgIGhlcmVfb3AgPSAoaGVyZSA+Pj4gMTYpICYgMHhmZjtcbiAgICAgICAgICBoZXJlX3ZhbCA9IGhlcmUgJiAweGZmZmY7XG5cbiAgICAgICAgICBpZiAoKGxhc3RfYml0cyArIGhlcmVfYml0cykgPD0gYml0cykgeyBicmVhazsgfVxuICAgICAgICAgIC8vLS0tIFBVTExCWVRFKCkgLS0tLy9cbiAgICAgICAgICBpZiAoaGF2ZSA9PT0gMCkgeyBicmVhayBpbmZfbGVhdmU7IH1cbiAgICAgICAgICBoYXZlLS07XG4gICAgICAgICAgaG9sZCArPSBpbnB1dFtuZXh0KytdIDw8IGJpdHM7XG4gICAgICAgICAgYml0cyArPSA4O1xuICAgICAgICAgIC8vLS0tLy9cbiAgICAgICAgfVxuICAgICAgICAvLy0tLSBEUk9QQklUUyhsYXN0LmJpdHMpIC0tLS8vXG4gICAgICAgIGhvbGQgPj4+PSBsYXN0X2JpdHM7XG4gICAgICAgIGJpdHMgLT0gbGFzdF9iaXRzO1xuICAgICAgICAvLy0tLS8vXG4gICAgICAgIHN0YXRlLmJhY2sgKz0gbGFzdF9iaXRzO1xuICAgICAgfVxuICAgICAgLy8tLS0gRFJPUEJJVFMoaGVyZS5iaXRzKSAtLS0vL1xuICAgICAgaG9sZCA+Pj49IGhlcmVfYml0cztcbiAgICAgIGJpdHMgLT0gaGVyZV9iaXRzO1xuICAgICAgLy8tLS0vL1xuICAgICAgc3RhdGUuYmFjayArPSBoZXJlX2JpdHM7XG4gICAgICBzdGF0ZS5sZW5ndGggPSBoZXJlX3ZhbDtcbiAgICAgIGlmIChoZXJlX29wID09PSAwKSB7XG4gICAgICAgIC8vVHJhY2V2digoc3RkZXJyLCBoZXJlLnZhbCA+PSAweDIwICYmIGhlcmUudmFsIDwgMHg3ZiA/XG4gICAgICAgIC8vICAgICAgICBcImluZmxhdGU6ICAgICAgICAgbGl0ZXJhbCAnJWMnXFxuXCIgOlxuICAgICAgICAvLyAgICAgICAgXCJpbmZsYXRlOiAgICAgICAgIGxpdGVyYWwgMHglMDJ4XFxuXCIsIGhlcmUudmFsKSk7XG4gICAgICAgIHN0YXRlLm1vZGUgPSBMSVQ7XG4gICAgICAgIGJyZWFrO1xuICAgICAgfVxuICAgICAgaWYgKGhlcmVfb3AgJiAzMikge1xuICAgICAgICAvL1RyYWNldnYoKHN0ZGVyciwgXCJpbmZsYXRlOiAgICAgICAgIGVuZCBvZiBibG9ja1xcblwiKSk7XG4gICAgICAgIHN0YXRlLmJhY2sgPSAtMTtcbiAgICAgICAgc3RhdGUubW9kZSA9IFRZUEU7XG4gICAgICAgIGJyZWFrO1xuICAgICAgfVxuICAgICAgaWYgKGhlcmVfb3AgJiA2NCkge1xuICAgICAgICBzdHJtLm1zZyA9ICdpbnZhbGlkIGxpdGVyYWwvbGVuZ3RoIGNvZGUnO1xuICAgICAgICBzdGF0ZS5tb2RlID0gQkFEO1xuICAgICAgICBicmVhaztcbiAgICAgIH1cbiAgICAgIHN0YXRlLmV4dHJhID0gaGVyZV9vcCAmIDE1O1xuICAgICAgc3RhdGUubW9kZSA9IExFTkVYVDtcbiAgICAgIC8qIGZhbGxzIHRocm91Z2ggKi9cbiAgICBjYXNlIExFTkVYVDpcbiAgICAgIGlmIChzdGF0ZS5leHRyYSkge1xuICAgICAgICAvLz09PSBORUVEQklUUyhzdGF0ZS5leHRyYSk7XG4gICAgICAgIG4gPSBzdGF0ZS5leHRyYTtcbiAgICAgICAgd2hpbGUgKGJpdHMgPCBuKSB7XG4gICAgICAgICAgaWYgKGhhdmUgPT09IDApIHsgYnJlYWsgaW5mX2xlYXZlOyB9XG4gICAgICAgICAgaGF2ZS0tO1xuICAgICAgICAgIGhvbGQgKz0gaW5wdXRbbmV4dCsrXSA8PCBiaXRzO1xuICAgICAgICAgIGJpdHMgKz0gODtcbiAgICAgICAgfVxuICAgICAgICAvLz09PS8vXG4gICAgICAgIHN0YXRlLmxlbmd0aCArPSBob2xkICYgKCgxIDw8IHN0YXRlLmV4dHJhKSAtMSkvKkJJVFMoc3RhdGUuZXh0cmEpKi87XG4gICAgICAgIC8vLS0tIERST1BCSVRTKHN0YXRlLmV4dHJhKSAtLS0vL1xuICAgICAgICBob2xkID4+Pj0gc3RhdGUuZXh0cmE7XG4gICAgICAgIGJpdHMgLT0gc3RhdGUuZXh0cmE7XG4gICAgICAgIC8vLS0tLy9cbiAgICAgICAgc3RhdGUuYmFjayArPSBzdGF0ZS5leHRyYTtcbiAgICAgIH1cbiAgICAgIC8vVHJhY2V2digoc3RkZXJyLCBcImluZmxhdGU6ICAgICAgICAgbGVuZ3RoICV1XFxuXCIsIHN0YXRlLmxlbmd0aCkpO1xuICAgICAgc3RhdGUud2FzID0gc3RhdGUubGVuZ3RoO1xuICAgICAgc3RhdGUubW9kZSA9IERJU1Q7XG4gICAgICAvKiBmYWxscyB0aHJvdWdoICovXG4gICAgY2FzZSBESVNUOlxuICAgICAgZm9yICg7Oykge1xuICAgICAgICBoZXJlID0gc3RhdGUuZGlzdGNvZGVbaG9sZCAmICgoMSA8PCBzdGF0ZS5kaXN0Yml0cykgLTEpXTsvKkJJVFMoc3RhdGUuZGlzdGJpdHMpKi9cbiAgICAgICAgaGVyZV9iaXRzID0gaGVyZSA+Pj4gMjQ7XG4gICAgICAgIGhlcmVfb3AgPSAoaGVyZSA+Pj4gMTYpICYgMHhmZjtcbiAgICAgICAgaGVyZV92YWwgPSBoZXJlICYgMHhmZmZmO1xuXG4gICAgICAgIGlmICgoaGVyZV9iaXRzKSA8PSBiaXRzKSB7IGJyZWFrOyB9XG4gICAgICAgIC8vLS0tIFBVTExCWVRFKCkgLS0tLy9cbiAgICAgICAgaWYgKGhhdmUgPT09IDApIHsgYnJlYWsgaW5mX2xlYXZlOyB9XG4gICAgICAgIGhhdmUtLTtcbiAgICAgICAgaG9sZCArPSBpbnB1dFtuZXh0KytdIDw8IGJpdHM7XG4gICAgICAgIGJpdHMgKz0gODtcbiAgICAgICAgLy8tLS0vL1xuICAgICAgfVxuICAgICAgaWYgKChoZXJlX29wICYgMHhmMCkgPT09IDApIHtcbiAgICAgICAgbGFzdF9iaXRzID0gaGVyZV9iaXRzO1xuICAgICAgICBsYXN0X29wID0gaGVyZV9vcDtcbiAgICAgICAgbGFzdF92YWwgPSBoZXJlX3ZhbDtcbiAgICAgICAgZm9yICg7Oykge1xuICAgICAgICAgIGhlcmUgPSBzdGF0ZS5kaXN0Y29kZVtsYXN0X3ZhbCArXG4gICAgICAgICAgICAgICAgICAoKGhvbGQgJiAoKDEgPDwgKGxhc3RfYml0cyArIGxhc3Rfb3ApKSAtMSkpLypCSVRTKGxhc3QuYml0cyArIGxhc3Qub3ApKi8gPj4gbGFzdF9iaXRzKV07XG4gICAgICAgICAgaGVyZV9iaXRzID0gaGVyZSA+Pj4gMjQ7XG4gICAgICAgICAgaGVyZV9vcCA9IChoZXJlID4+PiAxNikgJiAweGZmO1xuICAgICAgICAgIGhlcmVfdmFsID0gaGVyZSAmIDB4ZmZmZjtcblxuICAgICAgICAgIGlmICgobGFzdF9iaXRzICsgaGVyZV9iaXRzKSA8PSBiaXRzKSB7IGJyZWFrOyB9XG4gICAgICAgICAgLy8tLS0gUFVMTEJZVEUoKSAtLS0vL1xuICAgICAgICAgIGlmIChoYXZlID09PSAwKSB7IGJyZWFrIGluZl9sZWF2ZTsgfVxuICAgICAgICAgIGhhdmUtLTtcbiAgICAgICAgICBob2xkICs9IGlucHV0W25leHQrK10gPDwgYml0cztcbiAgICAgICAgICBiaXRzICs9IDg7XG4gICAgICAgICAgLy8tLS0vL1xuICAgICAgICB9XG4gICAgICAgIC8vLS0tIERST1BCSVRTKGxhc3QuYml0cykgLS0tLy9cbiAgICAgICAgaG9sZCA+Pj49IGxhc3RfYml0cztcbiAgICAgICAgYml0cyAtPSBsYXN0X2JpdHM7XG4gICAgICAgIC8vLS0tLy9cbiAgICAgICAgc3RhdGUuYmFjayArPSBsYXN0X2JpdHM7XG4gICAgICB9XG4gICAgICAvLy0tLSBEUk9QQklUUyhoZXJlLmJpdHMpIC0tLS8vXG4gICAgICBob2xkID4+Pj0gaGVyZV9iaXRzO1xuICAgICAgYml0cyAtPSBoZXJlX2JpdHM7XG4gICAgICAvLy0tLS8vXG4gICAgICBzdGF0ZS5iYWNrICs9IGhlcmVfYml0cztcbiAgICAgIGlmIChoZXJlX29wICYgNjQpIHtcbiAgICAgICAgc3RybS5tc2cgPSAnaW52YWxpZCBkaXN0YW5jZSBjb2RlJztcbiAgICAgICAgc3RhdGUubW9kZSA9IEJBRDtcbiAgICAgICAgYnJlYWs7XG4gICAgICB9XG4gICAgICBzdGF0ZS5vZmZzZXQgPSBoZXJlX3ZhbDtcbiAgICAgIHN0YXRlLmV4dHJhID0gKGhlcmVfb3ApICYgMTU7XG4gICAgICBzdGF0ZS5tb2RlID0gRElTVEVYVDtcbiAgICAgIC8qIGZhbGxzIHRocm91Z2ggKi9cbiAgICBjYXNlIERJU1RFWFQ6XG4gICAgICBpZiAoc3RhdGUuZXh0cmEpIHtcbiAgICAgICAgLy89PT0gTkVFREJJVFMoc3RhdGUuZXh0cmEpO1xuICAgICAgICBuID0gc3RhdGUuZXh0cmE7XG4gICAgICAgIHdoaWxlIChiaXRzIDwgbikge1xuICAgICAgICAgIGlmIChoYXZlID09PSAwKSB7IGJyZWFrIGluZl9sZWF2ZTsgfVxuICAgICAgICAgIGhhdmUtLTtcbiAgICAgICAgICBob2xkICs9IGlucHV0W25leHQrK10gPDwgYml0cztcbiAgICAgICAgICBiaXRzICs9IDg7XG4gICAgICAgIH1cbiAgICAgICAgLy89PT0vL1xuICAgICAgICBzdGF0ZS5vZmZzZXQgKz0gaG9sZCAmICgoMSA8PCBzdGF0ZS5leHRyYSkgLTEpLypCSVRTKHN0YXRlLmV4dHJhKSovO1xuICAgICAgICAvLy0tLSBEUk9QQklUUyhzdGF0ZS5leHRyYSkgLS0tLy9cbiAgICAgICAgaG9sZCA+Pj49IHN0YXRlLmV4dHJhO1xuICAgICAgICBiaXRzIC09IHN0YXRlLmV4dHJhO1xuICAgICAgICAvLy0tLS8vXG4gICAgICAgIHN0YXRlLmJhY2sgKz0gc3RhdGUuZXh0cmE7XG4gICAgICB9XG4vLyNpZmRlZiBJTkZMQVRFX1NUUklDVFxuICAgICAgaWYgKHN0YXRlLm9mZnNldCA+IHN0YXRlLmRtYXgpIHtcbiAgICAgICAgc3RybS5tc2cgPSAnaW52YWxpZCBkaXN0YW5jZSB0b28gZmFyIGJhY2snO1xuICAgICAgICBzdGF0ZS5tb2RlID0gQkFEO1xuICAgICAgICBicmVhaztcbiAgICAgIH1cbi8vI2VuZGlmXG4gICAgICAvL1RyYWNldnYoKHN0ZGVyciwgXCJpbmZsYXRlOiAgICAgICAgIGRpc3RhbmNlICV1XFxuXCIsIHN0YXRlLm9mZnNldCkpO1xuICAgICAgc3RhdGUubW9kZSA9IE1BVENIO1xuICAgICAgLyogZmFsbHMgdGhyb3VnaCAqL1xuICAgIGNhc2UgTUFUQ0g6XG4gICAgICBpZiAobGVmdCA9PT0gMCkgeyBicmVhayBpbmZfbGVhdmU7IH1cbiAgICAgIGNvcHkgPSBfb3V0IC0gbGVmdDtcbiAgICAgIGlmIChzdGF0ZS5vZmZzZXQgPiBjb3B5KSB7ICAgICAgICAgLyogY29weSBmcm9tIHdpbmRvdyAqL1xuICAgICAgICBjb3B5ID0gc3RhdGUub2Zmc2V0IC0gY29weTtcbiAgICAgICAgaWYgKGNvcHkgPiBzdGF0ZS53aGF2ZSkge1xuICAgICAgICAgIGlmIChzdGF0ZS5zYW5lKSB7XG4gICAgICAgICAgICBzdHJtLm1zZyA9ICdpbnZhbGlkIGRpc3RhbmNlIHRvbyBmYXIgYmFjayc7XG4gICAgICAgICAgICBzdGF0ZS5tb2RlID0gQkFEO1xuICAgICAgICAgICAgYnJlYWs7XG4gICAgICAgICAgfVxuLy8gKCEpIFRoaXMgYmxvY2sgaXMgZGlzYWJsZWQgaW4gemxpYiBkZWZhaWx0cyxcbi8vIGRvbid0IGVuYWJsZSBpdCBmb3IgYmluYXJ5IGNvbXBhdGliaWxpdHlcbi8vI2lmZGVmIElORkxBVEVfQUxMT1dfSU5WQUxJRF9ESVNUQU5DRV9UT09GQVJfQVJSUlxuLy8gICAgICAgICAgVHJhY2UoKHN0ZGVyciwgXCJpbmZsYXRlLmMgdG9vIGZhclxcblwiKSk7XG4vLyAgICAgICAgICBjb3B5IC09IHN0YXRlLndoYXZlO1xuLy8gICAgICAgICAgaWYgKGNvcHkgPiBzdGF0ZS5sZW5ndGgpIHsgY29weSA9IHN0YXRlLmxlbmd0aDsgfVxuLy8gICAgICAgICAgaWYgKGNvcHkgPiBsZWZ0KSB7IGNvcHkgPSBsZWZ0OyB9XG4vLyAgICAgICAgICBsZWZ0IC09IGNvcHk7XG4vLyAgICAgICAgICBzdGF0ZS5sZW5ndGggLT0gY29weTtcbi8vICAgICAgICAgIGRvIHtcbi8vICAgICAgICAgICAgb3V0cHV0W3B1dCsrXSA9IDA7XG4vLyAgICAgICAgICB9IHdoaWxlICgtLWNvcHkpO1xuLy8gICAgICAgICAgaWYgKHN0YXRlLmxlbmd0aCA9PT0gMCkgeyBzdGF0ZS5tb2RlID0gTEVOOyB9XG4vLyAgICAgICAgICBicmVhaztcbi8vI2VuZGlmXG4gICAgICAgIH1cbiAgICAgICAgaWYgKGNvcHkgPiBzdGF0ZS53bmV4dCkge1xuICAgICAgICAgIGNvcHkgLT0gc3RhdGUud25leHQ7XG4gICAgICAgICAgZnJvbSA9IHN0YXRlLndzaXplIC0gY29weTtcbiAgICAgICAgfVxuICAgICAgICBlbHNlIHtcbiAgICAgICAgICBmcm9tID0gc3RhdGUud25leHQgLSBjb3B5O1xuICAgICAgICB9XG4gICAgICAgIGlmIChjb3B5ID4gc3RhdGUubGVuZ3RoKSB7IGNvcHkgPSBzdGF0ZS5sZW5ndGg7IH1cbiAgICAgICAgZnJvbV9zb3VyY2UgPSBzdGF0ZS53aW5kb3c7XG4gICAgICB9XG4gICAgICBlbHNlIHsgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAvKiBjb3B5IGZyb20gb3V0cHV0ICovXG4gICAgICAgIGZyb21fc291cmNlID0gb3V0cHV0O1xuICAgICAgICBmcm9tID0gcHV0IC0gc3RhdGUub2Zmc2V0O1xuICAgICAgICBjb3B5ID0gc3RhdGUubGVuZ3RoO1xuICAgICAgfVxuICAgICAgaWYgKGNvcHkgPiBsZWZ0KSB7IGNvcHkgPSBsZWZ0OyB9XG4gICAgICBsZWZ0IC09IGNvcHk7XG4gICAgICBzdGF0ZS5sZW5ndGggLT0gY29weTtcbiAgICAgIGRvIHtcbiAgICAgICAgb3V0cHV0W3B1dCsrXSA9IGZyb21fc291cmNlW2Zyb20rK107XG4gICAgICB9IHdoaWxlICgtLWNvcHkpO1xuICAgICAgaWYgKHN0YXRlLmxlbmd0aCA9PT0gMCkgeyBzdGF0ZS5tb2RlID0gTEVOOyB9XG4gICAgICBicmVhaztcbiAgICBjYXNlIExJVDpcbiAgICAgIGlmIChsZWZ0ID09PSAwKSB7IGJyZWFrIGluZl9sZWF2ZTsgfVxuICAgICAgb3V0cHV0W3B1dCsrXSA9IHN0YXRlLmxlbmd0aDtcbiAgICAgIGxlZnQtLTtcbiAgICAgIHN0YXRlLm1vZGUgPSBMRU47XG4gICAgICBicmVhaztcbiAgICBjYXNlIENIRUNLOlxuICAgICAgaWYgKHN0YXRlLndyYXApIHtcbiAgICAgICAgLy89PT0gTkVFREJJVFMoMzIpO1xuICAgICAgICB3aGlsZSAoYml0cyA8IDMyKSB7XG4gICAgICAgICAgaWYgKGhhdmUgPT09IDApIHsgYnJlYWsgaW5mX2xlYXZlOyB9XG4gICAgICAgICAgaGF2ZS0tO1xuICAgICAgICAgIC8vIFVzZSAnfCcgaW5zZGVhZCBvZiAnKycgdG8gbWFrZSBzdXJlIHRoYXQgcmVzdWx0IGlzIHNpZ25lZFxuICAgICAgICAgIGhvbGQgfD0gaW5wdXRbbmV4dCsrXSA8PCBiaXRzO1xuICAgICAgICAgIGJpdHMgKz0gODtcbiAgICAgICAgfVxuICAgICAgICAvLz09PS8vXG4gICAgICAgIF9vdXQgLT0gbGVmdDtcbiAgICAgICAgc3RybS50b3RhbF9vdXQgKz0gX291dDtcbiAgICAgICAgc3RhdGUudG90YWwgKz0gX291dDtcbiAgICAgICAgaWYgKF9vdXQpIHtcbiAgICAgICAgICBzdHJtLmFkbGVyID0gc3RhdGUuY2hlY2sgPVxuICAgICAgICAgICAgICAvKlVQREFURShzdGF0ZS5jaGVjaywgcHV0IC0gX291dCwgX291dCk7Ki9cbiAgICAgICAgICAgICAgKHN0YXRlLmZsYWdzID8gY3JjMzIoc3RhdGUuY2hlY2ssIG91dHB1dCwgX291dCwgcHV0IC0gX291dCkgOiBhZGxlcjMyKHN0YXRlLmNoZWNrLCBvdXRwdXQsIF9vdXQsIHB1dCAtIF9vdXQpKTtcblxuICAgICAgICB9XG4gICAgICAgIF9vdXQgPSBsZWZ0O1xuICAgICAgICAvLyBOQjogY3JjMzIgc3RvcmVkIGFzIHNpZ25lZCAzMi1iaXQgaW50LCBaU1dBUDMyIHJldHVybnMgc2lnbmVkIHRvb1xuICAgICAgICBpZiAoKHN0YXRlLmZsYWdzID8gaG9sZCA6IFpTV0FQMzIoaG9sZCkpICE9PSBzdGF0ZS5jaGVjaykge1xuICAgICAgICAgIHN0cm0ubXNnID0gJ2luY29ycmVjdCBkYXRhIGNoZWNrJztcbiAgICAgICAgICBzdGF0ZS5tb2RlID0gQkFEO1xuICAgICAgICAgIGJyZWFrO1xuICAgICAgICB9XG4gICAgICAgIC8vPT09IElOSVRCSVRTKCk7XG4gICAgICAgIGhvbGQgPSAwO1xuICAgICAgICBiaXRzID0gMDtcbiAgICAgICAgLy89PT0vL1xuICAgICAgICAvL1RyYWNldigoc3RkZXJyLCBcImluZmxhdGU6ICAgY2hlY2sgbWF0Y2hlcyB0cmFpbGVyXFxuXCIpKTtcbiAgICAgIH1cbiAgICAgIHN0YXRlLm1vZGUgPSBMRU5HVEg7XG4gICAgICAvKiBmYWxscyB0aHJvdWdoICovXG4gICAgY2FzZSBMRU5HVEg6XG4gICAgICBpZiAoc3RhdGUud3JhcCAmJiBzdGF0ZS5mbGFncykge1xuICAgICAgICAvLz09PSBORUVEQklUUygzMik7XG4gICAgICAgIHdoaWxlIChiaXRzIDwgMzIpIHtcbiAgICAgICAgICBpZiAoaGF2ZSA9PT0gMCkgeyBicmVhayBpbmZfbGVhdmU7IH1cbiAgICAgICAgICBoYXZlLS07XG4gICAgICAgICAgaG9sZCArPSBpbnB1dFtuZXh0KytdIDw8IGJpdHM7XG4gICAgICAgICAgYml0cyArPSA4O1xuICAgICAgICB9XG4gICAgICAgIC8vPT09Ly9cbiAgICAgICAgaWYgKGhvbGQgIT09IChzdGF0ZS50b3RhbCAmIDB4ZmZmZmZmZmYpKSB7XG4gICAgICAgICAgc3RybS5tc2cgPSAnaW5jb3JyZWN0IGxlbmd0aCBjaGVjayc7XG4gICAgICAgICAgc3RhdGUubW9kZSA9IEJBRDtcbiAgICAgICAgICBicmVhaztcbiAgICAgICAgfVxuICAgICAgICAvLz09PSBJTklUQklUUygpO1xuICAgICAgICBob2xkID0gMDtcbiAgICAgICAgYml0cyA9IDA7XG4gICAgICAgIC8vPT09Ly9cbiAgICAgICAgLy9UcmFjZXYoKHN0ZGVyciwgXCJpbmZsYXRlOiAgIGxlbmd0aCBtYXRjaGVzIHRyYWlsZXJcXG5cIikpO1xuICAgICAgfVxuICAgICAgc3RhdGUubW9kZSA9IERPTkU7XG4gICAgICAvKiBmYWxscyB0aHJvdWdoICovXG4gICAgY2FzZSBET05FOlxuICAgICAgcmV0ID0gWl9TVFJFQU1fRU5EO1xuICAgICAgYnJlYWsgaW5mX2xlYXZlO1xuICAgIGNhc2UgQkFEOlxuICAgICAgcmV0ID0gWl9EQVRBX0VSUk9SO1xuICAgICAgYnJlYWsgaW5mX2xlYXZlO1xuICAgIGNhc2UgTUVNOlxuICAgICAgcmV0dXJuIFpfTUVNX0VSUk9SO1xuICAgIGNhc2UgU1lOQzpcbiAgICAgIC8qIGZhbGxzIHRocm91Z2ggKi9cbiAgICBkZWZhdWx0OlxuICAgICAgcmV0dXJuIFpfU1RSRUFNX0VSUk9SO1xuICAgIH1cbiAgfVxuXG4gIC8vIGluZl9sZWF2ZSA8LSBoZXJlIGlzIHJlYWwgcGxhY2UgZm9yIFwiZ290byBpbmZfbGVhdmVcIiwgZW11bGF0ZWQgdmlhIFwiYnJlYWsgaW5mX2xlYXZlXCJcblxuICAvKlxuICAgICBSZXR1cm4gZnJvbSBpbmZsYXRlKCksIHVwZGF0aW5nIHRoZSB0b3RhbCBjb3VudHMgYW5kIHRoZSBjaGVjayB2YWx1ZS5cbiAgICAgSWYgdGhlcmUgd2FzIG5vIHByb2dyZXNzIGR1cmluZyB0aGUgaW5mbGF0ZSgpIGNhbGwsIHJldHVybiBhIGJ1ZmZlclxuICAgICBlcnJvci4gIENhbGwgdXBkYXRld2luZG93KCkgdG8gY3JlYXRlIGFuZC9vciB1cGRhdGUgdGhlIHdpbmRvdyBzdGF0ZS5cbiAgICAgTm90ZTogYSBtZW1vcnkgZXJyb3IgZnJvbSBpbmZsYXRlKCkgaXMgbm9uLXJlY292ZXJhYmxlLlxuICAgKi9cblxuICAvLy0tLSBSRVNUT1JFKCkgLS0tXG4gIHN0cm0ubmV4dF9vdXQgPSBwdXQ7XG4gIHN0cm0uYXZhaWxfb3V0ID0gbGVmdDtcbiAgc3RybS5uZXh0X2luID0gbmV4dDtcbiAgc3RybS5hdmFpbF9pbiA9IGhhdmU7XG4gIHN0YXRlLmhvbGQgPSBob2xkO1xuICBzdGF0ZS5iaXRzID0gYml0cztcbiAgLy8tLS1cblxuICBpZiAoc3RhdGUud3NpemUgfHwgKF9vdXQgIT09IHN0cm0uYXZhaWxfb3V0ICYmIHN0YXRlLm1vZGUgPCBCQUQgJiZcbiAgICAgICAgICAgICAgICAgICAgICAoc3RhdGUubW9kZSA8IENIRUNLIHx8IGZsdXNoICE9PSBaX0ZJTklTSCkpKSB7XG4gICAgaWYgKHVwZGF0ZXdpbmRvdyhzdHJtLCBzdHJtLm91dHB1dCwgc3RybS5uZXh0X291dCwgX291dCAtIHN0cm0uYXZhaWxfb3V0KSkge1xuICAgICAgc3RhdGUubW9kZSA9IE1FTTtcbiAgICAgIHJldHVybiBaX01FTV9FUlJPUjtcbiAgICB9XG4gIH1cbiAgX2luIC09IHN0cm0uYXZhaWxfaW47XG4gIF9vdXQgLT0gc3RybS5hdmFpbF9vdXQ7XG4gIHN0cm0udG90YWxfaW4gKz0gX2luO1xuICBzdHJtLnRvdGFsX291dCArPSBfb3V0O1xuICBzdGF0ZS50b3RhbCArPSBfb3V0O1xuICBpZiAoc3RhdGUud3JhcCAmJiBfb3V0KSB7XG4gICAgc3RybS5hZGxlciA9IHN0YXRlLmNoZWNrID0gLypVUERBVEUoc3RhdGUuY2hlY2ssIHN0cm0ubmV4dF9vdXQgLSBfb3V0LCBfb3V0KTsqL1xuICAgICAgKHN0YXRlLmZsYWdzID8gY3JjMzIoc3RhdGUuY2hlY2ssIG91dHB1dCwgX291dCwgc3RybS5uZXh0X291dCAtIF9vdXQpIDogYWRsZXIzMihzdGF0ZS5jaGVjaywgb3V0cHV0LCBfb3V0LCBzdHJtLm5leHRfb3V0IC0gX291dCkpO1xuICB9XG4gIHN0cm0uZGF0YV90eXBlID0gc3RhdGUuYml0cyArIChzdGF0ZS5sYXN0ID8gNjQgOiAwKSArXG4gICAgICAgICAgICAgICAgICAgIChzdGF0ZS5tb2RlID09PSBUWVBFID8gMTI4IDogMCkgK1xuICAgICAgICAgICAgICAgICAgICAoc3RhdGUubW9kZSA9PT0gTEVOXyB8fCBzdGF0ZS5tb2RlID09PSBDT1BZXyA/IDI1NiA6IDApO1xuICBpZiAoKChfaW4gPT09IDAgJiYgX291dCA9PT0gMCkgfHwgZmx1c2ggPT09IFpfRklOSVNIKSAmJiByZXQgPT09IFpfT0spIHtcbiAgICByZXQgPSBaX0JVRl9FUlJPUjtcbiAgfVxuICByZXR1cm4gcmV0O1xufVxuXG5mdW5jdGlvbiBpbmZsYXRlRW5kKHN0cm0pIHtcblxuICBpZiAoIXN0cm0gfHwgIXN0cm0uc3RhdGUgLyp8fCBzdHJtLT56ZnJlZSA9PSAoZnJlZV9mdW5jKTAqLykge1xuICAgIHJldHVybiBaX1NUUkVBTV9FUlJPUjtcbiAgfVxuXG4gIHZhciBzdGF0ZSA9IHN0cm0uc3RhdGU7XG4gIGlmIChzdGF0ZS53aW5kb3cpIHtcbiAgICBzdGF0ZS53aW5kb3cgPSBudWxsO1xuICB9XG4gIHN0cm0uc3RhdGUgPSBudWxsO1xuICByZXR1cm4gWl9PSztcbn1cblxuZnVuY3Rpb24gaW5mbGF0ZUdldEhlYWRlcihzdHJtLCBoZWFkKSB7XG4gIHZhciBzdGF0ZTtcblxuICAvKiBjaGVjayBzdGF0ZSAqL1xuICBpZiAoIXN0cm0gfHwgIXN0cm0uc3RhdGUpIHsgcmV0dXJuIFpfU1RSRUFNX0VSUk9SOyB9XG4gIHN0YXRlID0gc3RybS5zdGF0ZTtcbiAgaWYgKChzdGF0ZS53cmFwICYgMikgPT09IDApIHsgcmV0dXJuIFpfU1RSRUFNX0VSUk9SOyB9XG5cbiAgLyogc2F2ZSBoZWFkZXIgc3RydWN0dXJlICovXG4gIHN0YXRlLmhlYWQgPSBoZWFkO1xuICBoZWFkLmRvbmUgPSBmYWxzZTtcbiAgcmV0dXJuIFpfT0s7XG59XG5cblxuZXhwb3J0cy5pbmZsYXRlUmVzZXQgPSBpbmZsYXRlUmVzZXQ7XG5leHBvcnRzLmluZmxhdGVSZXNldDIgPSBpbmZsYXRlUmVzZXQyO1xuZXhwb3J0cy5pbmZsYXRlUmVzZXRLZWVwID0gaW5mbGF0ZVJlc2V0S2VlcDtcbmV4cG9ydHMuaW5mbGF0ZUluaXQgPSBpbmZsYXRlSW5pdDtcbmV4cG9ydHMuaW5mbGF0ZUluaXQyID0gaW5mbGF0ZUluaXQyO1xuZXhwb3J0cy5pbmZsYXRlID0gaW5mbGF0ZTtcbmV4cG9ydHMuaW5mbGF0ZUVuZCA9IGluZmxhdGVFbmQ7XG5leHBvcnRzLmluZmxhdGVHZXRIZWFkZXIgPSBpbmZsYXRlR2V0SGVhZGVyO1xuZXhwb3J0cy5pbmZsYXRlSW5mbyA9ICdwYWtvIGluZmxhdGUgKGZyb20gTm9kZWNhIHByb2plY3QpJztcblxuLyogTm90IGltcGxlbWVudGVkXG5leHBvcnRzLmluZmxhdGVDb3B5ID0gaW5mbGF0ZUNvcHk7XG5leHBvcnRzLmluZmxhdGVHZXREaWN0aW9uYXJ5ID0gaW5mbGF0ZUdldERpY3Rpb25hcnk7XG5leHBvcnRzLmluZmxhdGVNYXJrID0gaW5mbGF0ZU1hcms7XG5leHBvcnRzLmluZmxhdGVQcmltZSA9IGluZmxhdGVQcmltZTtcbmV4cG9ydHMuaW5mbGF0ZVNldERpY3Rpb25hcnkgPSBpbmZsYXRlU2V0RGljdGlvbmFyeTtcbmV4cG9ydHMuaW5mbGF0ZVN5bmMgPSBpbmZsYXRlU3luYztcbmV4cG9ydHMuaW5mbGF0ZVN5bmNQb2ludCA9IGluZmxhdGVTeW5jUG9pbnQ7XG5leHBvcnRzLmluZmxhdGVVbmRlcm1pbmUgPSBpbmZsYXRlVW5kZXJtaW5lO1xuKi9cbiIsIid1c2Ugc3RyaWN0JztcblxuXG52YXIgdXRpbHMgPSByZXF1aXJlKCcuLi91dGlscy9jb21tb24nKTtcblxudmFyIE1BWEJJVFMgPSAxNTtcbnZhciBFTk9VR0hfTEVOUyA9IDg1MjtcbnZhciBFTk9VR0hfRElTVFMgPSA1OTI7XG4vL3ZhciBFTk9VR0ggPSAoRU5PVUdIX0xFTlMrRU5PVUdIX0RJU1RTKTtcblxudmFyIENPREVTID0gMDtcbnZhciBMRU5TID0gMTtcbnZhciBESVNUUyA9IDI7XG5cbnZhciBsYmFzZSA9IFsgLyogTGVuZ3RoIGNvZGVzIDI1Ny4uMjg1IGJhc2UgKi9cbiAgMywgNCwgNSwgNiwgNywgOCwgOSwgMTAsIDExLCAxMywgMTUsIDE3LCAxOSwgMjMsIDI3LCAzMSxcbiAgMzUsIDQzLCA1MSwgNTksIDY3LCA4MywgOTksIDExNSwgMTMxLCAxNjMsIDE5NSwgMjI3LCAyNTgsIDAsIDBcbl07XG5cbnZhciBsZXh0ID0gWyAvKiBMZW5ndGggY29kZXMgMjU3Li4yODUgZXh0cmEgKi9cbiAgMTYsIDE2LCAxNiwgMTYsIDE2LCAxNiwgMTYsIDE2LCAxNywgMTcsIDE3LCAxNywgMTgsIDE4LCAxOCwgMTgsXG4gIDE5LCAxOSwgMTksIDE5LCAyMCwgMjAsIDIwLCAyMCwgMjEsIDIxLCAyMSwgMjEsIDE2LCA3MiwgNzhcbl07XG5cbnZhciBkYmFzZSA9IFsgLyogRGlzdGFuY2UgY29kZXMgMC4uMjkgYmFzZSAqL1xuICAxLCAyLCAzLCA0LCA1LCA3LCA5LCAxMywgMTcsIDI1LCAzMywgNDksIDY1LCA5NywgMTI5LCAxOTMsXG4gIDI1NywgMzg1LCA1MTMsIDc2OSwgMTAyNSwgMTUzNywgMjA0OSwgMzA3MywgNDA5NywgNjE0NSxcbiAgODE5MywgMTIyODksIDE2Mzg1LCAyNDU3NywgMCwgMFxuXTtcblxudmFyIGRleHQgPSBbIC8qIERpc3RhbmNlIGNvZGVzIDAuLjI5IGV4dHJhICovXG4gIDE2LCAxNiwgMTYsIDE2LCAxNywgMTcsIDE4LCAxOCwgMTksIDE5LCAyMCwgMjAsIDIxLCAyMSwgMjIsIDIyLFxuICAyMywgMjMsIDI0LCAyNCwgMjUsIDI1LCAyNiwgMjYsIDI3LCAyNyxcbiAgMjgsIDI4LCAyOSwgMjksIDY0LCA2NFxuXTtcblxubW9kdWxlLmV4cG9ydHMgPSBmdW5jdGlvbiBpbmZsYXRlX3RhYmxlKHR5cGUsIGxlbnMsIGxlbnNfaW5kZXgsIGNvZGVzLCB0YWJsZSwgdGFibGVfaW5kZXgsIHdvcmssIG9wdHMpXG57XG4gIHZhciBiaXRzID0gb3B0cy5iaXRzO1xuICAgICAgLy9oZXJlID0gb3B0cy5oZXJlOyAvKiB0YWJsZSBlbnRyeSBmb3IgZHVwbGljYXRpb24gKi9cblxuICB2YXIgbGVuID0gMDsgICAgICAgICAgICAgICAvKiBhIGNvZGUncyBsZW5ndGggaW4gYml0cyAqL1xuICB2YXIgc3ltID0gMDsgICAgICAgICAgICAgICAvKiBpbmRleCBvZiBjb2RlIHN5bWJvbHMgKi9cbiAgdmFyIG1pbiA9IDAsIG1heCA9IDA7ICAgICAgICAgIC8qIG1pbmltdW0gYW5kIG1heGltdW0gY29kZSBsZW5ndGhzICovXG4gIHZhciByb290ID0gMDsgICAgICAgICAgICAgIC8qIG51bWJlciBvZiBpbmRleCBiaXRzIGZvciByb290IHRhYmxlICovXG4gIHZhciBjdXJyID0gMDsgICAgICAgICAgICAgIC8qIG51bWJlciBvZiBpbmRleCBiaXRzIGZvciBjdXJyZW50IHRhYmxlICovXG4gIHZhciBkcm9wID0gMDsgICAgICAgICAgICAgIC8qIGNvZGUgYml0cyB0byBkcm9wIGZvciBzdWItdGFibGUgKi9cbiAgdmFyIGxlZnQgPSAwOyAgICAgICAgICAgICAgICAgICAvKiBudW1iZXIgb2YgcHJlZml4IGNvZGVzIGF2YWlsYWJsZSAqL1xuICB2YXIgdXNlZCA9IDA7ICAgICAgICAgICAgICAvKiBjb2RlIGVudHJpZXMgaW4gdGFibGUgdXNlZCAqL1xuICB2YXIgaHVmZiA9IDA7ICAgICAgICAgICAgICAvKiBIdWZmbWFuIGNvZGUgKi9cbiAgdmFyIGluY3I7ICAgICAgICAgICAgICAvKiBmb3IgaW5jcmVtZW50aW5nIGNvZGUsIGluZGV4ICovXG4gIHZhciBmaWxsOyAgICAgICAgICAgICAgLyogaW5kZXggZm9yIHJlcGxpY2F0aW5nIGVudHJpZXMgKi9cbiAgdmFyIGxvdzsgICAgICAgICAgICAgICAvKiBsb3cgYml0cyBmb3IgY3VycmVudCByb290IGVudHJ5ICovXG4gIHZhciBtYXNrOyAgICAgICAgICAgICAgLyogbWFzayBmb3IgbG93IHJvb3QgYml0cyAqL1xuICB2YXIgbmV4dDsgICAgICAgICAgICAgLyogbmV4dCBhdmFpbGFibGUgc3BhY2UgaW4gdGFibGUgKi9cbiAgdmFyIGJhc2UgPSBudWxsOyAgICAgLyogYmFzZSB2YWx1ZSB0YWJsZSB0byB1c2UgKi9cbiAgdmFyIGJhc2VfaW5kZXggPSAwO1xuLy8gIHZhciBzaG9leHRyYTsgICAgLyogZXh0cmEgYml0cyB0YWJsZSB0byB1c2UgKi9cbiAgdmFyIGVuZDsgICAgICAgICAgICAgICAgICAgIC8qIHVzZSBiYXNlIGFuZCBleHRyYSBmb3Igc3ltYm9sID4gZW5kICovXG4gIHZhciBjb3VudCA9IG5ldyB1dGlscy5CdWYxNihNQVhCSVRTKzEpOyAvL1tNQVhCSVRTKzFdOyAgICAvKiBudW1iZXIgb2YgY29kZXMgb2YgZWFjaCBsZW5ndGggKi9cbiAgdmFyIG9mZnMgPSBuZXcgdXRpbHMuQnVmMTYoTUFYQklUUysxKTsgLy9bTUFYQklUUysxXTsgICAgIC8qIG9mZnNldHMgaW4gdGFibGUgZm9yIGVhY2ggbGVuZ3RoICovXG4gIHZhciBleHRyYSA9IG51bGw7XG4gIHZhciBleHRyYV9pbmRleCA9IDA7XG5cbiAgdmFyIGhlcmVfYml0cywgaGVyZV9vcCwgaGVyZV92YWw7XG5cbiAgLypcbiAgIFByb2Nlc3MgYSBzZXQgb2YgY29kZSBsZW5ndGhzIHRvIGNyZWF0ZSBhIGNhbm9uaWNhbCBIdWZmbWFuIGNvZGUuICBUaGVcbiAgIGNvZGUgbGVuZ3RocyBhcmUgbGVuc1swLi5jb2Rlcy0xXS4gIEVhY2ggbGVuZ3RoIGNvcnJlc3BvbmRzIHRvIHRoZVxuICAgc3ltYm9scyAwLi5jb2Rlcy0xLiAgVGhlIEh1ZmZtYW4gY29kZSBpcyBnZW5lcmF0ZWQgYnkgZmlyc3Qgc29ydGluZyB0aGVcbiAgIHN5bWJvbHMgYnkgbGVuZ3RoIGZyb20gc2hvcnQgdG8gbG9uZywgYW5kIHJldGFpbmluZyB0aGUgc3ltYm9sIG9yZGVyXG4gICBmb3IgY29kZXMgd2l0aCBlcXVhbCBsZW5ndGhzLiAgVGhlbiB0aGUgY29kZSBzdGFydHMgd2l0aCBhbGwgemVybyBiaXRzXG4gICBmb3IgdGhlIGZpcnN0IGNvZGUgb2YgdGhlIHNob3J0ZXN0IGxlbmd0aCwgYW5kIHRoZSBjb2RlcyBhcmUgaW50ZWdlclxuICAgaW5jcmVtZW50cyBmb3IgdGhlIHNhbWUgbGVuZ3RoLCBhbmQgemVyb3MgYXJlIGFwcGVuZGVkIGFzIHRoZSBsZW5ndGhcbiAgIGluY3JlYXNlcy4gIEZvciB0aGUgZGVmbGF0ZSBmb3JtYXQsIHRoZXNlIGJpdHMgYXJlIHN0b3JlZCBiYWNrd2FyZHNcbiAgIGZyb20gdGhlaXIgbW9yZSBuYXR1cmFsIGludGVnZXIgaW5jcmVtZW50IG9yZGVyaW5nLCBhbmQgc28gd2hlbiB0aGVcbiAgIGRlY29kaW5nIHRhYmxlcyBhcmUgYnVpbHQgaW4gdGhlIGxhcmdlIGxvb3AgYmVsb3csIHRoZSBpbnRlZ2VyIGNvZGVzXG4gICBhcmUgaW5jcmVtZW50ZWQgYmFja3dhcmRzLlxuXG4gICBUaGlzIHJvdXRpbmUgYXNzdW1lcywgYnV0IGRvZXMgbm90IGNoZWNrLCB0aGF0IGFsbCBvZiB0aGUgZW50cmllcyBpblxuICAgbGVuc1tdIGFyZSBpbiB0aGUgcmFuZ2UgMC4uTUFYQklUUy4gIFRoZSBjYWxsZXIgbXVzdCBhc3N1cmUgdGhpcy5cbiAgIDEuLk1BWEJJVFMgaXMgaW50ZXJwcmV0ZWQgYXMgdGhhdCBjb2RlIGxlbmd0aC4gIHplcm8gbWVhbnMgdGhhdCB0aGF0XG4gICBzeW1ib2wgZG9lcyBub3Qgb2NjdXIgaW4gdGhpcyBjb2RlLlxuXG4gICBUaGUgY29kZXMgYXJlIHNvcnRlZCBieSBjb21wdXRpbmcgYSBjb3VudCBvZiBjb2RlcyBmb3IgZWFjaCBsZW5ndGgsXG4gICBjcmVhdGluZyBmcm9tIHRoYXQgYSB0YWJsZSBvZiBzdGFydGluZyBpbmRpY2VzIGZvciBlYWNoIGxlbmd0aCBpbiB0aGVcbiAgIHNvcnRlZCB0YWJsZSwgYW5kIHRoZW4gZW50ZXJpbmcgdGhlIHN5bWJvbHMgaW4gb3JkZXIgaW4gdGhlIHNvcnRlZFxuICAgdGFibGUuICBUaGUgc29ydGVkIHRhYmxlIGlzIHdvcmtbXSwgd2l0aCB0aGF0IHNwYWNlIGJlaW5nIHByb3ZpZGVkIGJ5XG4gICB0aGUgY2FsbGVyLlxuXG4gICBUaGUgbGVuZ3RoIGNvdW50cyBhcmUgdXNlZCBmb3Igb3RoZXIgcHVycG9zZXMgYXMgd2VsbCwgaS5lLiBmaW5kaW5nXG4gICB0aGUgbWluaW11bSBhbmQgbWF4aW11bSBsZW5ndGggY29kZXMsIGRldGVybWluaW5nIGlmIHRoZXJlIGFyZSBhbnlcbiAgIGNvZGVzIGF0IGFsbCwgY2hlY2tpbmcgZm9yIGEgdmFsaWQgc2V0IG9mIGxlbmd0aHMsIGFuZCBsb29raW5nIGFoZWFkXG4gICBhdCBsZW5ndGggY291bnRzIHRvIGRldGVybWluZSBzdWItdGFibGUgc2l6ZXMgd2hlbiBidWlsZGluZyB0aGVcbiAgIGRlY29kaW5nIHRhYmxlcy5cbiAgICovXG5cbiAgLyogYWNjdW11bGF0ZSBsZW5ndGhzIGZvciBjb2RlcyAoYXNzdW1lcyBsZW5zW10gYWxsIGluIDAuLk1BWEJJVFMpICovXG4gIGZvciAobGVuID0gMDsgbGVuIDw9IE1BWEJJVFM7IGxlbisrKSB7XG4gICAgY291bnRbbGVuXSA9IDA7XG4gIH1cbiAgZm9yIChzeW0gPSAwOyBzeW0gPCBjb2Rlczsgc3ltKyspIHtcbiAgICBjb3VudFtsZW5zW2xlbnNfaW5kZXggKyBzeW1dXSsrO1xuICB9XG5cbiAgLyogYm91bmQgY29kZSBsZW5ndGhzLCBmb3JjZSByb290IHRvIGJlIHdpdGhpbiBjb2RlIGxlbmd0aHMgKi9cbiAgcm9vdCA9IGJpdHM7XG4gIGZvciAobWF4ID0gTUFYQklUUzsgbWF4ID49IDE7IG1heC0tKSB7XG4gICAgaWYgKGNvdW50W21heF0gIT09IDApIHsgYnJlYWs7IH1cbiAgfVxuICBpZiAocm9vdCA+IG1heCkge1xuICAgIHJvb3QgPSBtYXg7XG4gIH1cbiAgaWYgKG1heCA9PT0gMCkgeyAgICAgICAgICAgICAgICAgICAgIC8qIG5vIHN5bWJvbHMgdG8gY29kZSBhdCBhbGwgKi9cbiAgICAvL3RhYmxlLm9wW29wdHMudGFibGVfaW5kZXhdID0gNjQ7ICAvL2hlcmUub3AgPSAodmFyIGNoYXIpNjQ7ICAgIC8qIGludmFsaWQgY29kZSBtYXJrZXIgKi9cbiAgICAvL3RhYmxlLmJpdHNbb3B0cy50YWJsZV9pbmRleF0gPSAxOyAgIC8vaGVyZS5iaXRzID0gKHZhciBjaGFyKTE7XG4gICAgLy90YWJsZS52YWxbb3B0cy50YWJsZV9pbmRleCsrXSA9IDA7ICAgLy9oZXJlLnZhbCA9ICh2YXIgc2hvcnQpMDtcbiAgICB0YWJsZVt0YWJsZV9pbmRleCsrXSA9ICgxIDw8IDI0KSB8ICg2NCA8PCAxNikgfCAwO1xuXG5cbiAgICAvL3RhYmxlLm9wW29wdHMudGFibGVfaW5kZXhdID0gNjQ7XG4gICAgLy90YWJsZS5iaXRzW29wdHMudGFibGVfaW5kZXhdID0gMTtcbiAgICAvL3RhYmxlLnZhbFtvcHRzLnRhYmxlX2luZGV4KytdID0gMDtcbiAgICB0YWJsZVt0YWJsZV9pbmRleCsrXSA9ICgxIDw8IDI0KSB8ICg2NCA8PCAxNikgfCAwO1xuXG4gICAgb3B0cy5iaXRzID0gMTtcbiAgICByZXR1cm4gMDsgICAgIC8qIG5vIHN5bWJvbHMsIGJ1dCB3YWl0IGZvciBkZWNvZGluZyB0byByZXBvcnQgZXJyb3IgKi9cbiAgfVxuICBmb3IgKG1pbiA9IDE7IG1pbiA8IG1heDsgbWluKyspIHtcbiAgICBpZiAoY291bnRbbWluXSAhPT0gMCkgeyBicmVhazsgfVxuICB9XG4gIGlmIChyb290IDwgbWluKSB7XG4gICAgcm9vdCA9IG1pbjtcbiAgfVxuXG4gIC8qIGNoZWNrIGZvciBhbiBvdmVyLXN1YnNjcmliZWQgb3IgaW5jb21wbGV0ZSBzZXQgb2YgbGVuZ3RocyAqL1xuICBsZWZ0ID0gMTtcbiAgZm9yIChsZW4gPSAxOyBsZW4gPD0gTUFYQklUUzsgbGVuKyspIHtcbiAgICBsZWZ0IDw8PSAxO1xuICAgIGxlZnQgLT0gY291bnRbbGVuXTtcbiAgICBpZiAobGVmdCA8IDApIHtcbiAgICAgIHJldHVybiAtMTtcbiAgICB9ICAgICAgICAvKiBvdmVyLXN1YnNjcmliZWQgKi9cbiAgfVxuICBpZiAobGVmdCA+IDAgJiYgKHR5cGUgPT09IENPREVTIHx8IG1heCAhPT0gMSkpIHtcbiAgICByZXR1cm4gLTE7ICAgICAgICAgICAgICAgICAgICAgIC8qIGluY29tcGxldGUgc2V0ICovXG4gIH1cblxuICAvKiBnZW5lcmF0ZSBvZmZzZXRzIGludG8gc3ltYm9sIHRhYmxlIGZvciBlYWNoIGxlbmd0aCBmb3Igc29ydGluZyAqL1xuICBvZmZzWzFdID0gMDtcbiAgZm9yIChsZW4gPSAxOyBsZW4gPCBNQVhCSVRTOyBsZW4rKykge1xuICAgIG9mZnNbbGVuICsgMV0gPSBvZmZzW2xlbl0gKyBjb3VudFtsZW5dO1xuICB9XG5cbiAgLyogc29ydCBzeW1ib2xzIGJ5IGxlbmd0aCwgYnkgc3ltYm9sIG9yZGVyIHdpdGhpbiBlYWNoIGxlbmd0aCAqL1xuICBmb3IgKHN5bSA9IDA7IHN5bSA8IGNvZGVzOyBzeW0rKykge1xuICAgIGlmIChsZW5zW2xlbnNfaW5kZXggKyBzeW1dICE9PSAwKSB7XG4gICAgICB3b3JrW29mZnNbbGVuc1tsZW5zX2luZGV4ICsgc3ltXV0rK10gPSBzeW07XG4gICAgfVxuICB9XG5cbiAgLypcbiAgIENyZWF0ZSBhbmQgZmlsbCBpbiBkZWNvZGluZyB0YWJsZXMuICBJbiB0aGlzIGxvb3AsIHRoZSB0YWJsZSBiZWluZ1xuICAgZmlsbGVkIGlzIGF0IG5leHQgYW5kIGhhcyBjdXJyIGluZGV4IGJpdHMuICBUaGUgY29kZSBiZWluZyB1c2VkIGlzIGh1ZmZcbiAgIHdpdGggbGVuZ3RoIGxlbi4gIFRoYXQgY29kZSBpcyBjb252ZXJ0ZWQgdG8gYW4gaW5kZXggYnkgZHJvcHBpbmcgZHJvcFxuICAgYml0cyBvZmYgb2YgdGhlIGJvdHRvbS4gIEZvciBjb2RlcyB3aGVyZSBsZW4gaXMgbGVzcyB0aGFuIGRyb3AgKyBjdXJyLFxuICAgdGhvc2UgdG9wIGRyb3AgKyBjdXJyIC0gbGVuIGJpdHMgYXJlIGluY3JlbWVudGVkIHRocm91Z2ggYWxsIHZhbHVlcyB0b1xuICAgZmlsbCB0aGUgdGFibGUgd2l0aCByZXBsaWNhdGVkIGVudHJpZXMuXG5cbiAgIHJvb3QgaXMgdGhlIG51bWJlciBvZiBpbmRleCBiaXRzIGZvciB0aGUgcm9vdCB0YWJsZS4gIFdoZW4gbGVuIGV4Y2VlZHNcbiAgIHJvb3QsIHN1Yi10YWJsZXMgYXJlIGNyZWF0ZWQgcG9pbnRlZCB0byBieSB0aGUgcm9vdCBlbnRyeSB3aXRoIGFuIGluZGV4XG4gICBvZiB0aGUgbG93IHJvb3QgYml0cyBvZiBodWZmLiAgVGhpcyBpcyBzYXZlZCBpbiBsb3cgdG8gY2hlY2sgZm9yIHdoZW4gYVxuICAgbmV3IHN1Yi10YWJsZSBzaG91bGQgYmUgc3RhcnRlZC4gIGRyb3AgaXMgemVybyB3aGVuIHRoZSByb290IHRhYmxlIGlzXG4gICBiZWluZyBmaWxsZWQsIGFuZCBkcm9wIGlzIHJvb3Qgd2hlbiBzdWItdGFibGVzIGFyZSBiZWluZyBmaWxsZWQuXG5cbiAgIFdoZW4gYSBuZXcgc3ViLXRhYmxlIGlzIG5lZWRlZCwgaXQgaXMgbmVjZXNzYXJ5IHRvIGxvb2sgYWhlYWQgaW4gdGhlXG4gICBjb2RlIGxlbmd0aHMgdG8gZGV0ZXJtaW5lIHdoYXQgc2l6ZSBzdWItdGFibGUgaXMgbmVlZGVkLiAgVGhlIGxlbmd0aFxuICAgY291bnRzIGFyZSB1c2VkIGZvciB0aGlzLCBhbmQgc28gY291bnRbXSBpcyBkZWNyZW1lbnRlZCBhcyBjb2RlcyBhcmVcbiAgIGVudGVyZWQgaW4gdGhlIHRhYmxlcy5cblxuICAgdXNlZCBrZWVwcyB0cmFjayBvZiBob3cgbWFueSB0YWJsZSBlbnRyaWVzIGhhdmUgYmVlbiBhbGxvY2F0ZWQgZnJvbSB0aGVcbiAgIHByb3ZpZGVkICp0YWJsZSBzcGFjZS4gIEl0IGlzIGNoZWNrZWQgZm9yIExFTlMgYW5kIERJU1QgdGFibGVzIGFnYWluc3RcbiAgIHRoZSBjb25zdGFudHMgRU5PVUdIX0xFTlMgYW5kIEVOT1VHSF9ESVNUUyB0byBndWFyZCBhZ2FpbnN0IGNoYW5nZXMgaW5cbiAgIHRoZSBpbml0aWFsIHJvb3QgdGFibGUgc2l6ZSBjb25zdGFudHMuICBTZWUgdGhlIGNvbW1lbnRzIGluIGluZnRyZWVzLmhcbiAgIGZvciBtb3JlIGluZm9ybWF0aW9uLlxuXG4gICBzeW0gaW5jcmVtZW50cyB0aHJvdWdoIGFsbCBzeW1ib2xzLCBhbmQgdGhlIGxvb3AgdGVybWluYXRlcyB3aGVuXG4gICBhbGwgY29kZXMgb2YgbGVuZ3RoIG1heCwgaS5lLiBhbGwgY29kZXMsIGhhdmUgYmVlbiBwcm9jZXNzZWQuICBUaGlzXG4gICByb3V0aW5lIHBlcm1pdHMgaW5jb21wbGV0ZSBjb2Rlcywgc28gYW5vdGhlciBsb29wIGFmdGVyIHRoaXMgb25lIGZpbGxzXG4gICBpbiB0aGUgcmVzdCBvZiB0aGUgZGVjb2RpbmcgdGFibGVzIHdpdGggaW52YWxpZCBjb2RlIG1hcmtlcnMuXG4gICAqL1xuXG4gIC8qIHNldCB1cCBmb3IgY29kZSB0eXBlICovXG4gIC8vIHBvb3IgbWFuIG9wdGltaXphdGlvbiAtIHVzZSBpZi1lbHNlIGluc3RlYWQgb2Ygc3dpdGNoLFxuICAvLyB0byBhdm9pZCBkZW9wdHMgaW4gb2xkIHY4XG4gIGlmICh0eXBlID09PSBDT0RFUykge1xuICAgIGJhc2UgPSBleHRyYSA9IHdvcms7ICAgIC8qIGR1bW15IHZhbHVlLS1ub3QgdXNlZCAqL1xuICAgIGVuZCA9IDE5O1xuXG4gIH0gZWxzZSBpZiAodHlwZSA9PT0gTEVOUykge1xuICAgIGJhc2UgPSBsYmFzZTtcbiAgICBiYXNlX2luZGV4IC09IDI1NztcbiAgICBleHRyYSA9IGxleHQ7XG4gICAgZXh0cmFfaW5kZXggLT0gMjU3O1xuICAgIGVuZCA9IDI1NjtcblxuICB9IGVsc2UgeyAgICAgICAgICAgICAgICAgICAgLyogRElTVFMgKi9cbiAgICBiYXNlID0gZGJhc2U7XG4gICAgZXh0cmEgPSBkZXh0O1xuICAgIGVuZCA9IC0xO1xuICB9XG5cbiAgLyogaW5pdGlhbGl6ZSBvcHRzIGZvciBsb29wICovXG4gIGh1ZmYgPSAwOyAgICAgICAgICAgICAgICAgICAvKiBzdGFydGluZyBjb2RlICovXG4gIHN5bSA9IDA7ICAgICAgICAgICAgICAgICAgICAvKiBzdGFydGluZyBjb2RlIHN5bWJvbCAqL1xuICBsZW4gPSBtaW47ICAgICAgICAgICAgICAgICAgLyogc3RhcnRpbmcgY29kZSBsZW5ndGggKi9cbiAgbmV4dCA9IHRhYmxlX2luZGV4OyAgICAgICAgICAgICAgLyogY3VycmVudCB0YWJsZSB0byBmaWxsIGluICovXG4gIGN1cnIgPSByb290OyAgICAgICAgICAgICAgICAvKiBjdXJyZW50IHRhYmxlIGluZGV4IGJpdHMgKi9cbiAgZHJvcCA9IDA7ICAgICAgICAgICAgICAgICAgIC8qIGN1cnJlbnQgYml0cyB0byBkcm9wIGZyb20gY29kZSBmb3IgaW5kZXggKi9cbiAgbG93ID0gLTE7ICAgICAgICAgICAgICAgICAgIC8qIHRyaWdnZXIgbmV3IHN1Yi10YWJsZSB3aGVuIGxlbiA+IHJvb3QgKi9cbiAgdXNlZCA9IDEgPDwgcm9vdDsgICAgICAgICAgLyogdXNlIHJvb3QgdGFibGUgZW50cmllcyAqL1xuICBtYXNrID0gdXNlZCAtIDE7ICAgICAgICAgICAgLyogbWFzayBmb3IgY29tcGFyaW5nIGxvdyAqL1xuXG4gIC8qIGNoZWNrIGF2YWlsYWJsZSB0YWJsZSBzcGFjZSAqL1xuICBpZiAoKHR5cGUgPT09IExFTlMgJiYgdXNlZCA+IEVOT1VHSF9MRU5TKSB8fFxuICAgICh0eXBlID09PSBESVNUUyAmJiB1c2VkID4gRU5PVUdIX0RJU1RTKSkge1xuICAgIHJldHVybiAxO1xuICB9XG5cbiAgdmFyIGk9MDtcbiAgLyogcHJvY2VzcyBhbGwgY29kZXMgYW5kIG1ha2UgdGFibGUgZW50cmllcyAqL1xuICBmb3IgKDs7KSB7XG4gICAgaSsrO1xuICAgIC8qIGNyZWF0ZSB0YWJsZSBlbnRyeSAqL1xuICAgIGhlcmVfYml0cyA9IGxlbiAtIGRyb3A7XG4gICAgaWYgKHdvcmtbc3ltXSA8IGVuZCkge1xuICAgICAgaGVyZV9vcCA9IDA7XG4gICAgICBoZXJlX3ZhbCA9IHdvcmtbc3ltXTtcbiAgICB9XG4gICAgZWxzZSBpZiAod29ya1tzeW1dID4gZW5kKSB7XG4gICAgICBoZXJlX29wID0gZXh0cmFbZXh0cmFfaW5kZXggKyB3b3JrW3N5bV1dO1xuICAgICAgaGVyZV92YWwgPSBiYXNlW2Jhc2VfaW5kZXggKyB3b3JrW3N5bV1dO1xuICAgIH1cbiAgICBlbHNlIHtcbiAgICAgIGhlcmVfb3AgPSAzMiArIDY0OyAgICAgICAgIC8qIGVuZCBvZiBibG9jayAqL1xuICAgICAgaGVyZV92YWwgPSAwO1xuICAgIH1cblxuICAgIC8qIHJlcGxpY2F0ZSBmb3IgdGhvc2UgaW5kaWNlcyB3aXRoIGxvdyBsZW4gYml0cyBlcXVhbCB0byBodWZmICovXG4gICAgaW5jciA9IDEgPDwgKGxlbiAtIGRyb3ApO1xuICAgIGZpbGwgPSAxIDw8IGN1cnI7XG4gICAgbWluID0gZmlsbDsgICAgICAgICAgICAgICAgIC8qIHNhdmUgb2Zmc2V0IHRvIG5leHQgdGFibGUgKi9cbiAgICBkbyB7XG4gICAgICBmaWxsIC09IGluY3I7XG4gICAgICB0YWJsZVtuZXh0ICsgKGh1ZmYgPj4gZHJvcCkgKyBmaWxsXSA9IChoZXJlX2JpdHMgPDwgMjQpIHwgKGhlcmVfb3AgPDwgMTYpIHwgaGVyZV92YWwgfDA7XG4gICAgfSB3aGlsZSAoZmlsbCAhPT0gMCk7XG5cbiAgICAvKiBiYWNrd2FyZHMgaW5jcmVtZW50IHRoZSBsZW4tYml0IGNvZGUgaHVmZiAqL1xuICAgIGluY3IgPSAxIDw8IChsZW4gLSAxKTtcbiAgICB3aGlsZSAoaHVmZiAmIGluY3IpIHtcbiAgICAgIGluY3IgPj49IDE7XG4gICAgfVxuICAgIGlmIChpbmNyICE9PSAwKSB7XG4gICAgICBodWZmICY9IGluY3IgLSAxO1xuICAgICAgaHVmZiArPSBpbmNyO1xuICAgIH0gZWxzZSB7XG4gICAgICBodWZmID0gMDtcbiAgICB9XG5cbiAgICAvKiBnbyB0byBuZXh0IHN5bWJvbCwgdXBkYXRlIGNvdW50LCBsZW4gKi9cbiAgICBzeW0rKztcbiAgICBpZiAoLS1jb3VudFtsZW5dID09PSAwKSB7XG4gICAgICBpZiAobGVuID09PSBtYXgpIHsgYnJlYWs7IH1cbiAgICAgIGxlbiA9IGxlbnNbbGVuc19pbmRleCArIHdvcmtbc3ltXV07XG4gICAgfVxuXG4gICAgLyogY3JlYXRlIG5ldyBzdWItdGFibGUgaWYgbmVlZGVkICovXG4gICAgaWYgKGxlbiA+IHJvb3QgJiYgKGh1ZmYgJiBtYXNrKSAhPT0gbG93KSB7XG4gICAgICAvKiBpZiBmaXJzdCB0aW1lLCB0cmFuc2l0aW9uIHRvIHN1Yi10YWJsZXMgKi9cbiAgICAgIGlmIChkcm9wID09PSAwKSB7XG4gICAgICAgIGRyb3AgPSByb290O1xuICAgICAgfVxuXG4gICAgICAvKiBpbmNyZW1lbnQgcGFzdCBsYXN0IHRhYmxlICovXG4gICAgICBuZXh0ICs9IG1pbjsgICAgICAgICAgICAvKiBoZXJlIG1pbiBpcyAxIDw8IGN1cnIgKi9cblxuICAgICAgLyogZGV0ZXJtaW5lIGxlbmd0aCBvZiBuZXh0IHRhYmxlICovXG4gICAgICBjdXJyID0gbGVuIC0gZHJvcDtcbiAgICAgIGxlZnQgPSAxIDw8IGN1cnI7XG4gICAgICB3aGlsZSAoY3VyciArIGRyb3AgPCBtYXgpIHtcbiAgICAgICAgbGVmdCAtPSBjb3VudFtjdXJyICsgZHJvcF07XG4gICAgICAgIGlmIChsZWZ0IDw9IDApIHsgYnJlYWs7IH1cbiAgICAgICAgY3VycisrO1xuICAgICAgICBsZWZ0IDw8PSAxO1xuICAgICAgfVxuXG4gICAgICAvKiBjaGVjayBmb3IgZW5vdWdoIHNwYWNlICovXG4gICAgICB1c2VkICs9IDEgPDwgY3VycjtcbiAgICAgIGlmICgodHlwZSA9PT0gTEVOUyAmJiB1c2VkID4gRU5PVUdIX0xFTlMpIHx8XG4gICAgICAgICh0eXBlID09PSBESVNUUyAmJiB1c2VkID4gRU5PVUdIX0RJU1RTKSkge1xuICAgICAgICByZXR1cm4gMTtcbiAgICAgIH1cblxuICAgICAgLyogcG9pbnQgZW50cnkgaW4gcm9vdCB0YWJsZSB0byBzdWItdGFibGUgKi9cbiAgICAgIGxvdyA9IGh1ZmYgJiBtYXNrO1xuICAgICAgLyp0YWJsZS5vcFtsb3ddID0gY3VycjtcbiAgICAgIHRhYmxlLmJpdHNbbG93XSA9IHJvb3Q7XG4gICAgICB0YWJsZS52YWxbbG93XSA9IG5leHQgLSBvcHRzLnRhYmxlX2luZGV4OyovXG4gICAgICB0YWJsZVtsb3ddID0gKHJvb3QgPDwgMjQpIHwgKGN1cnIgPDwgMTYpIHwgKG5leHQgLSB0YWJsZV9pbmRleCkgfDA7XG4gICAgfVxuICB9XG5cbiAgLyogZmlsbCBpbiByZW1haW5pbmcgdGFibGUgZW50cnkgaWYgY29kZSBpcyBpbmNvbXBsZXRlIChndWFyYW50ZWVkIHRvIGhhdmVcbiAgIGF0IG1vc3Qgb25lIHJlbWFpbmluZyBlbnRyeSwgc2luY2UgaWYgdGhlIGNvZGUgaXMgaW5jb21wbGV0ZSwgdGhlXG4gICBtYXhpbXVtIGNvZGUgbGVuZ3RoIHRoYXQgd2FzIGFsbG93ZWQgdG8gZ2V0IHRoaXMgZmFyIGlzIG9uZSBiaXQpICovXG4gIGlmIChodWZmICE9PSAwKSB7XG4gICAgLy90YWJsZS5vcFtuZXh0ICsgaHVmZl0gPSA2NDsgICAgICAgICAgICAvKiBpbnZhbGlkIGNvZGUgbWFya2VyICovXG4gICAgLy90YWJsZS5iaXRzW25leHQgKyBodWZmXSA9IGxlbiAtIGRyb3A7XG4gICAgLy90YWJsZS52YWxbbmV4dCArIGh1ZmZdID0gMDtcbiAgICB0YWJsZVtuZXh0ICsgaHVmZl0gPSAoKGxlbiAtIGRyb3ApIDw8IDI0KSB8ICg2NCA8PCAxNikgfDA7XG4gIH1cblxuICAvKiBzZXQgcmV0dXJuIHBhcmFtZXRlcnMgKi9cbiAgLy9vcHRzLnRhYmxlX2luZGV4ICs9IHVzZWQ7XG4gIG9wdHMuYml0cyA9IHJvb3Q7XG4gIHJldHVybiAwO1xufTtcbiIsIid1c2Ugc3RyaWN0JztcblxubW9kdWxlLmV4cG9ydHMgPSB7XG4gICcyJzogICAgJ25lZWQgZGljdGlvbmFyeScsICAgICAvKiBaX05FRURfRElDVCAgICAgICAyICAqL1xuICAnMSc6ICAgICdzdHJlYW0gZW5kJywgICAgICAgICAgLyogWl9TVFJFQU1fRU5EICAgICAgMSAgKi9cbiAgJzAnOiAgICAnJywgICAgICAgICAgICAgICAgICAgIC8qIFpfT0sgICAgICAgICAgICAgIDAgICovXG4gICctMSc6ICAgJ2ZpbGUgZXJyb3InLCAgICAgICAgICAvKiBaX0VSUk5PICAgICAgICAgKC0xKSAqL1xuICAnLTInOiAgICdzdHJlYW0gZXJyb3InLCAgICAgICAgLyogWl9TVFJFQU1fRVJST1IgICgtMikgKi9cbiAgJy0zJzogICAnZGF0YSBlcnJvcicsICAgICAgICAgIC8qIFpfREFUQV9FUlJPUiAgICAoLTMpICovXG4gICctNCc6ICAgJ2luc3VmZmljaWVudCBtZW1vcnknLCAvKiBaX01FTV9FUlJPUiAgICAgKC00KSAqL1xuICAnLTUnOiAgICdidWZmZXIgZXJyb3InLCAgICAgICAgLyogWl9CVUZfRVJST1IgICAgICgtNSkgKi9cbiAgJy02JzogICAnaW5jb21wYXRpYmxlIHZlcnNpb24nIC8qIFpfVkVSU0lPTl9FUlJPUiAoLTYpICovXG59O1xuIiwiJ3VzZSBzdHJpY3QnO1xuXG5cbnZhciB1dGlscyA9IHJlcXVpcmUoJy4uL3V0aWxzL2NvbW1vbicpO1xuXG4vKiBQdWJsaWMgY29uc3RhbnRzID09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT0qL1xuLyogPT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09Ki9cblxuXG4vL3ZhciBaX0ZJTFRFUkVEICAgICAgICAgID0gMTtcbi8vdmFyIFpfSFVGRk1BTl9PTkxZICAgICAgPSAyO1xuLy92YXIgWl9STEUgICAgICAgICAgICAgICA9IDM7XG52YXIgWl9GSVhFRCAgICAgICAgICAgICAgID0gNDtcbi8vdmFyIFpfREVGQVVMVF9TVFJBVEVHWSAgPSAwO1xuXG4vKiBQb3NzaWJsZSB2YWx1ZXMgb2YgdGhlIGRhdGFfdHlwZSBmaWVsZCAodGhvdWdoIHNlZSBpbmZsYXRlKCkpICovXG52YXIgWl9CSU5BUlkgICAgICAgICAgICAgID0gMDtcbnZhciBaX1RFWFQgICAgICAgICAgICAgICAgPSAxO1xuLy92YXIgWl9BU0NJSSAgICAgICAgICAgICA9IDE7IC8vID0gWl9URVhUXG52YXIgWl9VTktOT1dOICAgICAgICAgICAgID0gMjtcblxuLyo9PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09Ki9cblxuXG5mdW5jdGlvbiB6ZXJvKGJ1ZikgeyB2YXIgbGVuID0gYnVmLmxlbmd0aDsgd2hpbGUgKC0tbGVuID49IDApIHsgYnVmW2xlbl0gPSAwOyB9IH1cblxuLy8gRnJvbSB6dXRpbC5oXG5cbnZhciBTVE9SRURfQkxPQ0sgPSAwO1xudmFyIFNUQVRJQ19UUkVFUyA9IDE7XG52YXIgRFlOX1RSRUVTICAgID0gMjtcbi8qIFRoZSB0aHJlZSBraW5kcyBvZiBibG9jayB0eXBlICovXG5cbnZhciBNSU5fTUFUQ0ggICAgPSAzO1xudmFyIE1BWF9NQVRDSCAgICA9IDI1ODtcbi8qIFRoZSBtaW5pbXVtIGFuZCBtYXhpbXVtIG1hdGNoIGxlbmd0aHMgKi9cblxuLy8gRnJvbSBkZWZsYXRlLmhcbi8qID09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PVxuICogSW50ZXJuYWwgY29tcHJlc3Npb24gc3RhdGUuXG4gKi9cblxudmFyIExFTkdUSF9DT0RFUyAgPSAyOTtcbi8qIG51bWJlciBvZiBsZW5ndGggY29kZXMsIG5vdCBjb3VudGluZyB0aGUgc3BlY2lhbCBFTkRfQkxPQ0sgY29kZSAqL1xuXG52YXIgTElURVJBTFMgICAgICA9IDI1Njtcbi8qIG51bWJlciBvZiBsaXRlcmFsIGJ5dGVzIDAuLjI1NSAqL1xuXG52YXIgTF9DT0RFUyAgICAgICA9IExJVEVSQUxTICsgMSArIExFTkdUSF9DT0RFUztcbi8qIG51bWJlciBvZiBMaXRlcmFsIG9yIExlbmd0aCBjb2RlcywgaW5jbHVkaW5nIHRoZSBFTkRfQkxPQ0sgY29kZSAqL1xuXG52YXIgRF9DT0RFUyAgICAgICA9IDMwO1xuLyogbnVtYmVyIG9mIGRpc3RhbmNlIGNvZGVzICovXG5cbnZhciBCTF9DT0RFUyAgICAgID0gMTk7XG4vKiBudW1iZXIgb2YgY29kZXMgdXNlZCB0byB0cmFuc2ZlciB0aGUgYml0IGxlbmd0aHMgKi9cblxudmFyIEhFQVBfU0laRSAgICAgPSAyKkxfQ09ERVMgKyAxO1xuLyogbWF4aW11bSBoZWFwIHNpemUgKi9cblxudmFyIE1BWF9CSVRTICAgICAgPSAxNTtcbi8qIEFsbCBjb2RlcyBtdXN0IG5vdCBleGNlZWQgTUFYX0JJVFMgYml0cyAqL1xuXG52YXIgQnVmX3NpemUgICAgICA9IDE2O1xuLyogc2l6ZSBvZiBiaXQgYnVmZmVyIGluIGJpX2J1ZiAqL1xuXG5cbi8qID09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PVxuICogQ29uc3RhbnRzXG4gKi9cblxudmFyIE1BWF9CTF9CSVRTID0gNztcbi8qIEJpdCBsZW5ndGggY29kZXMgbXVzdCBub3QgZXhjZWVkIE1BWF9CTF9CSVRTIGJpdHMgKi9cblxudmFyIEVORF9CTE9DSyAgID0gMjU2O1xuLyogZW5kIG9mIGJsb2NrIGxpdGVyYWwgY29kZSAqL1xuXG52YXIgUkVQXzNfNiAgICAgPSAxNjtcbi8qIHJlcGVhdCBwcmV2aW91cyBiaXQgbGVuZ3RoIDMtNiB0aW1lcyAoMiBiaXRzIG9mIHJlcGVhdCBjb3VudCkgKi9cblxudmFyIFJFUFpfM18xMCAgID0gMTc7XG4vKiByZXBlYXQgYSB6ZXJvIGxlbmd0aCAzLTEwIHRpbWVzICAoMyBiaXRzIG9mIHJlcGVhdCBjb3VudCkgKi9cblxudmFyIFJFUFpfMTFfMTM4ID0gMTg7XG4vKiByZXBlYXQgYSB6ZXJvIGxlbmd0aCAxMS0xMzggdGltZXMgICg3IGJpdHMgb2YgcmVwZWF0IGNvdW50KSAqL1xuXG52YXIgZXh0cmFfbGJpdHMgPSAgIC8qIGV4dHJhIGJpdHMgZm9yIGVhY2ggbGVuZ3RoIGNvZGUgKi9cbiAgWzAsMCwwLDAsMCwwLDAsMCwxLDEsMSwxLDIsMiwyLDIsMywzLDMsMyw0LDQsNCw0LDUsNSw1LDUsMF07XG5cbnZhciBleHRyYV9kYml0cyA9ICAgLyogZXh0cmEgYml0cyBmb3IgZWFjaCBkaXN0YW5jZSBjb2RlICovXG4gIFswLDAsMCwwLDEsMSwyLDIsMywzLDQsNCw1LDUsNiw2LDcsNyw4LDgsOSw5LDEwLDEwLDExLDExLDEyLDEyLDEzLDEzXTtcblxudmFyIGV4dHJhX2JsYml0cyA9ICAvKiBleHRyYSBiaXRzIGZvciBlYWNoIGJpdCBsZW5ndGggY29kZSAqL1xuICBbMCwwLDAsMCwwLDAsMCwwLDAsMCwwLDAsMCwwLDAsMCwyLDMsN107XG5cbnZhciBibF9vcmRlciA9XG4gIFsxNiwxNywxOCwwLDgsNyw5LDYsMTAsNSwxMSw0LDEyLDMsMTMsMiwxNCwxLDE1XTtcbi8qIFRoZSBsZW5ndGhzIG9mIHRoZSBiaXQgbGVuZ3RoIGNvZGVzIGFyZSBzZW50IGluIG9yZGVyIG9mIGRlY3JlYXNpbmdcbiAqIHByb2JhYmlsaXR5LCB0byBhdm9pZCB0cmFuc21pdHRpbmcgdGhlIGxlbmd0aHMgZm9yIHVudXNlZCBiaXQgbGVuZ3RoIGNvZGVzLlxuICovXG5cbi8qID09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PVxuICogTG9jYWwgZGF0YS4gVGhlc2UgYXJlIGluaXRpYWxpemVkIG9ubHkgb25jZS5cbiAqL1xuXG4vLyBXZSBwcmUtZmlsbCBhcnJheXMgd2l0aCAwIHRvIGF2b2lkIHVuaW5pdGlhbGl6ZWQgZ2Fwc1xuXG52YXIgRElTVF9DT0RFX0xFTiA9IDUxMjsgLyogc2VlIGRlZmluaXRpb24gb2YgYXJyYXkgZGlzdF9jb2RlIGJlbG93ICovXG5cbi8vICEhISEgVXNlIGZsYXQgYXJyYXkgaW5zZGVhZCBvZiBzdHJ1Y3R1cmUsIEZyZXEgPSBpKjIsIExlbiA9IGkqMisxXG52YXIgc3RhdGljX2x0cmVlICA9IG5ldyBBcnJheSgoTF9DT0RFUysyKSAqIDIpO1xuemVybyhzdGF0aWNfbHRyZWUpO1xuLyogVGhlIHN0YXRpYyBsaXRlcmFsIHRyZWUuIFNpbmNlIHRoZSBiaXQgbGVuZ3RocyBhcmUgaW1wb3NlZCwgdGhlcmUgaXMgbm9cbiAqIG5lZWQgZm9yIHRoZSBMX0NPREVTIGV4dHJhIGNvZGVzIHVzZWQgZHVyaW5nIGhlYXAgY29uc3RydWN0aW9uLiBIb3dldmVyXG4gKiBUaGUgY29kZXMgMjg2IGFuZCAyODcgYXJlIG5lZWRlZCB0byBidWlsZCBhIGNhbm9uaWNhbCB0cmVlIChzZWUgX3RyX2luaXRcbiAqIGJlbG93KS5cbiAqL1xuXG52YXIgc3RhdGljX2R0cmVlICA9IG5ldyBBcnJheShEX0NPREVTICogMik7XG56ZXJvKHN0YXRpY19kdHJlZSk7XG4vKiBUaGUgc3RhdGljIGRpc3RhbmNlIHRyZWUuIChBY3R1YWxseSBhIHRyaXZpYWwgdHJlZSBzaW5jZSBhbGwgY29kZXMgdXNlXG4gKiA1IGJpdHMuKVxuICovXG5cbnZhciBfZGlzdF9jb2RlICAgID0gbmV3IEFycmF5KERJU1RfQ09ERV9MRU4pO1xuemVybyhfZGlzdF9jb2RlKTtcbi8qIERpc3RhbmNlIGNvZGVzLiBUaGUgZmlyc3QgMjU2IHZhbHVlcyBjb3JyZXNwb25kIHRvIHRoZSBkaXN0YW5jZXNcbiAqIDMgLi4gMjU4LCB0aGUgbGFzdCAyNTYgdmFsdWVzIGNvcnJlc3BvbmQgdG8gdGhlIHRvcCA4IGJpdHMgb2ZcbiAqIHRoZSAxNSBiaXQgZGlzdGFuY2VzLlxuICovXG5cbnZhciBfbGVuZ3RoX2NvZGUgID0gbmV3IEFycmF5KE1BWF9NQVRDSC1NSU5fTUFUQ0grMSk7XG56ZXJvKF9sZW5ndGhfY29kZSk7XG4vKiBsZW5ndGggY29kZSBmb3IgZWFjaCBub3JtYWxpemVkIG1hdGNoIGxlbmd0aCAoMCA9PSBNSU5fTUFUQ0gpICovXG5cbnZhciBiYXNlX2xlbmd0aCAgID0gbmV3IEFycmF5KExFTkdUSF9DT0RFUyk7XG56ZXJvKGJhc2VfbGVuZ3RoKTtcbi8qIEZpcnN0IG5vcm1hbGl6ZWQgbGVuZ3RoIGZvciBlYWNoIGNvZGUgKDAgPSBNSU5fTUFUQ0gpICovXG5cbnZhciBiYXNlX2Rpc3QgICAgID0gbmV3IEFycmF5KERfQ09ERVMpO1xuemVybyhiYXNlX2Rpc3QpO1xuLyogRmlyc3Qgbm9ybWFsaXplZCBkaXN0YW5jZSBmb3IgZWFjaCBjb2RlICgwID0gZGlzdGFuY2Ugb2YgMSkgKi9cblxuXG52YXIgU3RhdGljVHJlZURlc2MgPSBmdW5jdGlvbiAoc3RhdGljX3RyZWUsIGV4dHJhX2JpdHMsIGV4dHJhX2Jhc2UsIGVsZW1zLCBtYXhfbGVuZ3RoKSB7XG5cbiAgdGhpcy5zdGF0aWNfdHJlZSAgPSBzdGF0aWNfdHJlZTsgIC8qIHN0YXRpYyB0cmVlIG9yIE5VTEwgKi9cbiAgdGhpcy5leHRyYV9iaXRzICAgPSBleHRyYV9iaXRzOyAgIC8qIGV4dHJhIGJpdHMgZm9yIGVhY2ggY29kZSBvciBOVUxMICovXG4gIHRoaXMuZXh0cmFfYmFzZSAgID0gZXh0cmFfYmFzZTsgICAvKiBiYXNlIGluZGV4IGZvciBleHRyYV9iaXRzICovXG4gIHRoaXMuZWxlbXMgICAgICAgID0gZWxlbXM7ICAgICAgICAvKiBtYXggbnVtYmVyIG9mIGVsZW1lbnRzIGluIHRoZSB0cmVlICovXG4gIHRoaXMubWF4X2xlbmd0aCAgID0gbWF4X2xlbmd0aDsgICAvKiBtYXggYml0IGxlbmd0aCBmb3IgdGhlIGNvZGVzICovXG5cbiAgLy8gc2hvdyBpZiBgc3RhdGljX3RyZWVgIGhhcyBkYXRhIG9yIGR1bW15IC0gbmVlZGVkIGZvciBtb25vbW9ycGhpYyBvYmplY3RzXG4gIHRoaXMuaGFzX3N0cmVlICAgID0gc3RhdGljX3RyZWUgJiYgc3RhdGljX3RyZWUubGVuZ3RoO1xufTtcblxuXG52YXIgc3RhdGljX2xfZGVzYztcbnZhciBzdGF0aWNfZF9kZXNjO1xudmFyIHN0YXRpY19ibF9kZXNjO1xuXG5cbnZhciBUcmVlRGVzYyA9IGZ1bmN0aW9uKGR5bl90cmVlLCBzdGF0X2Rlc2MpIHtcbiAgdGhpcy5keW5fdHJlZSA9IGR5bl90cmVlOyAgICAgLyogdGhlIGR5bmFtaWMgdHJlZSAqL1xuICB0aGlzLm1heF9jb2RlID0gMDsgICAgICAgICAgICAvKiBsYXJnZXN0IGNvZGUgd2l0aCBub24gemVybyBmcmVxdWVuY3kgKi9cbiAgdGhpcy5zdGF0X2Rlc2MgPSBzdGF0X2Rlc2M7ICAgLyogdGhlIGNvcnJlc3BvbmRpbmcgc3RhdGljIHRyZWUgKi9cbn07XG5cblxuXG5mdW5jdGlvbiBkX2NvZGUoZGlzdCkge1xuICByZXR1cm4gZGlzdCA8IDI1NiA/IF9kaXN0X2NvZGVbZGlzdF0gOiBfZGlzdF9jb2RlWzI1NiArIChkaXN0ID4+PiA3KV07XG59XG5cblxuLyogPT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09XG4gKiBPdXRwdXQgYSBzaG9ydCBMU0IgZmlyc3Qgb24gdGhlIHN0cmVhbS5cbiAqIElOIGFzc2VydGlvbjogdGhlcmUgaXMgZW5vdWdoIHJvb20gaW4gcGVuZGluZ0J1Zi5cbiAqL1xuZnVuY3Rpb24gcHV0X3Nob3J0IChzLCB3KSB7XG4vLyAgICBwdXRfYnl0ZShzLCAodWNoKSgodykgJiAweGZmKSk7XG4vLyAgICBwdXRfYnl0ZShzLCAodWNoKSgodXNoKSh3KSA+PiA4KSk7XG4gIHMucGVuZGluZ19idWZbcy5wZW5kaW5nKytdID0gKHcpICYgMHhmZjtcbiAgcy5wZW5kaW5nX2J1ZltzLnBlbmRpbmcrK10gPSAodyA+Pj4gOCkgJiAweGZmO1xufVxuXG5cbi8qID09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PVxuICogU2VuZCBhIHZhbHVlIG9uIGEgZ2l2ZW4gbnVtYmVyIG9mIGJpdHMuXG4gKiBJTiBhc3NlcnRpb246IGxlbmd0aCA8PSAxNiBhbmQgdmFsdWUgZml0cyBpbiBsZW5ndGggYml0cy5cbiAqL1xuZnVuY3Rpb24gc2VuZF9iaXRzKHMsIHZhbHVlLCBsZW5ndGgpIHtcbiAgaWYgKHMuYmlfdmFsaWQgPiAoQnVmX3NpemUgLSBsZW5ndGgpKSB7XG4gICAgcy5iaV9idWYgfD0gKHZhbHVlIDw8IHMuYmlfdmFsaWQpICYgMHhmZmZmO1xuICAgIHB1dF9zaG9ydChzLCBzLmJpX2J1Zik7XG4gICAgcy5iaV9idWYgPSB2YWx1ZSA+PiAoQnVmX3NpemUgLSBzLmJpX3ZhbGlkKTtcbiAgICBzLmJpX3ZhbGlkICs9IGxlbmd0aCAtIEJ1Zl9zaXplO1xuICB9IGVsc2Uge1xuICAgIHMuYmlfYnVmIHw9ICh2YWx1ZSA8PCBzLmJpX3ZhbGlkKSAmIDB4ZmZmZjtcbiAgICBzLmJpX3ZhbGlkICs9IGxlbmd0aDtcbiAgfVxufVxuXG5cbmZ1bmN0aW9uIHNlbmRfY29kZShzLCBjLCB0cmVlKSB7XG4gIHNlbmRfYml0cyhzLCB0cmVlW2MqMl0vKi5Db2RlKi8sIHRyZWVbYyoyICsgMV0vKi5MZW4qLyk7XG59XG5cblxuLyogPT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09XG4gKiBSZXZlcnNlIHRoZSBmaXJzdCBsZW4gYml0cyBvZiBhIGNvZGUsIHVzaW5nIHN0cmFpZ2h0Zm9yd2FyZCBjb2RlIChhIGZhc3RlclxuICogbWV0aG9kIHdvdWxkIHVzZSBhIHRhYmxlKVxuICogSU4gYXNzZXJ0aW9uOiAxIDw9IGxlbiA8PSAxNVxuICovXG5mdW5jdGlvbiBiaV9yZXZlcnNlKGNvZGUsIGxlbikge1xuICB2YXIgcmVzID0gMDtcbiAgZG8ge1xuICAgIHJlcyB8PSBjb2RlICYgMTtcbiAgICBjb2RlID4+Pj0gMTtcbiAgICByZXMgPDw9IDE7XG4gIH0gd2hpbGUgKC0tbGVuID4gMCk7XG4gIHJldHVybiByZXMgPj4+IDE7XG59XG5cblxuLyogPT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09XG4gKiBGbHVzaCB0aGUgYml0IGJ1ZmZlciwga2VlcGluZyBhdCBtb3N0IDcgYml0cyBpbiBpdC5cbiAqL1xuZnVuY3Rpb24gYmlfZmx1c2gocykge1xuICBpZiAocy5iaV92YWxpZCA9PT0gMTYpIHtcbiAgICBwdXRfc2hvcnQocywgcy5iaV9idWYpO1xuICAgIHMuYmlfYnVmID0gMDtcbiAgICBzLmJpX3ZhbGlkID0gMDtcblxuICB9IGVsc2UgaWYgKHMuYmlfdmFsaWQgPj0gOCkge1xuICAgIHMucGVuZGluZ19idWZbcy5wZW5kaW5nKytdID0gcy5iaV9idWYgJiAweGZmO1xuICAgIHMuYmlfYnVmID4+PSA4O1xuICAgIHMuYmlfdmFsaWQgLT0gODtcbiAgfVxufVxuXG5cbi8qID09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PVxuICogQ29tcHV0ZSB0aGUgb3B0aW1hbCBiaXQgbGVuZ3RocyBmb3IgYSB0cmVlIGFuZCB1cGRhdGUgdGhlIHRvdGFsIGJpdCBsZW5ndGhcbiAqIGZvciB0aGUgY3VycmVudCBibG9jay5cbiAqIElOIGFzc2VydGlvbjogdGhlIGZpZWxkcyBmcmVxIGFuZCBkYWQgYXJlIHNldCwgaGVhcFtoZWFwX21heF0gYW5kXG4gKiAgICBhYm92ZSBhcmUgdGhlIHRyZWUgbm9kZXMgc29ydGVkIGJ5IGluY3JlYXNpbmcgZnJlcXVlbmN5LlxuICogT1VUIGFzc2VydGlvbnM6IHRoZSBmaWVsZCBsZW4gaXMgc2V0IHRvIHRoZSBvcHRpbWFsIGJpdCBsZW5ndGgsIHRoZVxuICogICAgIGFycmF5IGJsX2NvdW50IGNvbnRhaW5zIHRoZSBmcmVxdWVuY2llcyBmb3IgZWFjaCBiaXQgbGVuZ3RoLlxuICogICAgIFRoZSBsZW5ndGggb3B0X2xlbiBpcyB1cGRhdGVkOyBzdGF0aWNfbGVuIGlzIGFsc28gdXBkYXRlZCBpZiBzdHJlZSBpc1xuICogICAgIG5vdCBudWxsLlxuICovXG5mdW5jdGlvbiBnZW5fYml0bGVuKHMsIGRlc2MpXG4vLyAgICBkZWZsYXRlX3N0YXRlICpzO1xuLy8gICAgdHJlZV9kZXNjICpkZXNjOyAgICAvKiB0aGUgdHJlZSBkZXNjcmlwdG9yICovXG57XG4gIHZhciB0cmVlICAgICAgICAgICAgPSBkZXNjLmR5bl90cmVlO1xuICB2YXIgbWF4X2NvZGUgICAgICAgID0gZGVzYy5tYXhfY29kZTtcbiAgdmFyIHN0cmVlICAgICAgICAgICA9IGRlc2Muc3RhdF9kZXNjLnN0YXRpY190cmVlO1xuICB2YXIgaGFzX3N0cmVlICAgICAgID0gZGVzYy5zdGF0X2Rlc2MuaGFzX3N0cmVlO1xuICB2YXIgZXh0cmEgICAgICAgICAgID0gZGVzYy5zdGF0X2Rlc2MuZXh0cmFfYml0cztcbiAgdmFyIGJhc2UgICAgICAgICAgICA9IGRlc2Muc3RhdF9kZXNjLmV4dHJhX2Jhc2U7XG4gIHZhciBtYXhfbGVuZ3RoICAgICAgPSBkZXNjLnN0YXRfZGVzYy5tYXhfbGVuZ3RoO1xuICB2YXIgaDsgICAgICAgICAgICAgIC8qIGhlYXAgaW5kZXggKi9cbiAgdmFyIG4sIG07ICAgICAgICAgICAvKiBpdGVyYXRlIG92ZXIgdGhlIHRyZWUgZWxlbWVudHMgKi9cbiAgdmFyIGJpdHM7ICAgICAgICAgICAvKiBiaXQgbGVuZ3RoICovXG4gIHZhciB4Yml0czsgICAgICAgICAgLyogZXh0cmEgYml0cyAqL1xuICB2YXIgZjsgICAgICAgICAgICAgIC8qIGZyZXF1ZW5jeSAqL1xuICB2YXIgb3ZlcmZsb3cgPSAwOyAgIC8qIG51bWJlciBvZiBlbGVtZW50cyB3aXRoIGJpdCBsZW5ndGggdG9vIGxhcmdlICovXG5cbiAgZm9yIChiaXRzID0gMDsgYml0cyA8PSBNQVhfQklUUzsgYml0cysrKSB7XG4gICAgcy5ibF9jb3VudFtiaXRzXSA9IDA7XG4gIH1cblxuICAvKiBJbiBhIGZpcnN0IHBhc3MsIGNvbXB1dGUgdGhlIG9wdGltYWwgYml0IGxlbmd0aHMgKHdoaWNoIG1heVxuICAgKiBvdmVyZmxvdyBpbiB0aGUgY2FzZSBvZiB0aGUgYml0IGxlbmd0aCB0cmVlKS5cbiAgICovXG4gIHRyZWVbcy5oZWFwW3MuaGVhcF9tYXhdKjIgKyAxXS8qLkxlbiovID0gMDsgLyogcm9vdCBvZiB0aGUgaGVhcCAqL1xuXG4gIGZvciAoaCA9IHMuaGVhcF9tYXgrMTsgaCA8IEhFQVBfU0laRTsgaCsrKSB7XG4gICAgbiA9IHMuaGVhcFtoXTtcbiAgICBiaXRzID0gdHJlZVt0cmVlW24qMiArMV0vKi5EYWQqLyAqIDIgKyAxXS8qLkxlbiovICsgMTtcbiAgICBpZiAoYml0cyA+IG1heF9sZW5ndGgpIHtcbiAgICAgIGJpdHMgPSBtYXhfbGVuZ3RoO1xuICAgICAgb3ZlcmZsb3crKztcbiAgICB9XG4gICAgdHJlZVtuKjIgKyAxXS8qLkxlbiovID0gYml0cztcbiAgICAvKiBXZSBvdmVyd3JpdGUgdHJlZVtuXS5EYWQgd2hpY2ggaXMgbm8gbG9uZ2VyIG5lZWRlZCAqL1xuXG4gICAgaWYgKG4gPiBtYXhfY29kZSkgeyBjb250aW51ZTsgfSAvKiBub3QgYSBsZWFmIG5vZGUgKi9cblxuICAgIHMuYmxfY291bnRbYml0c10rKztcbiAgICB4Yml0cyA9IDA7XG4gICAgaWYgKG4gPj0gYmFzZSkge1xuICAgICAgeGJpdHMgPSBleHRyYVtuLWJhc2VdO1xuICAgIH1cbiAgICBmID0gdHJlZVtuICogMl0vKi5GcmVxKi87XG4gICAgcy5vcHRfbGVuICs9IGYgKiAoYml0cyArIHhiaXRzKTtcbiAgICBpZiAoaGFzX3N0cmVlKSB7XG4gICAgICBzLnN0YXRpY19sZW4gKz0gZiAqIChzdHJlZVtuKjIgKyAxXS8qLkxlbiovICsgeGJpdHMpO1xuICAgIH1cbiAgfVxuICBpZiAob3ZlcmZsb3cgPT09IDApIHsgcmV0dXJuOyB9XG5cbiAgLy8gVHJhY2UoKHN0ZGVycixcIlxcbmJpdCBsZW5ndGggb3ZlcmZsb3dcXG5cIikpO1xuICAvKiBUaGlzIGhhcHBlbnMgZm9yIGV4YW1wbGUgb24gb2JqMiBhbmQgcGljIG9mIHRoZSBDYWxnYXJ5IGNvcnB1cyAqL1xuXG4gIC8qIEZpbmQgdGhlIGZpcnN0IGJpdCBsZW5ndGggd2hpY2ggY291bGQgaW5jcmVhc2U6ICovXG4gIGRvIHtcbiAgICBiaXRzID0gbWF4X2xlbmd0aC0xO1xuICAgIHdoaWxlIChzLmJsX2NvdW50W2JpdHNdID09PSAwKSB7IGJpdHMtLTsgfVxuICAgIHMuYmxfY291bnRbYml0c10tLTsgICAgICAvKiBtb3ZlIG9uZSBsZWFmIGRvd24gdGhlIHRyZWUgKi9cbiAgICBzLmJsX2NvdW50W2JpdHMrMV0gKz0gMjsgLyogbW92ZSBvbmUgb3ZlcmZsb3cgaXRlbSBhcyBpdHMgYnJvdGhlciAqL1xuICAgIHMuYmxfY291bnRbbWF4X2xlbmd0aF0tLTtcbiAgICAvKiBUaGUgYnJvdGhlciBvZiB0aGUgb3ZlcmZsb3cgaXRlbSBhbHNvIG1vdmVzIG9uZSBzdGVwIHVwLFxuICAgICAqIGJ1dCB0aGlzIGRvZXMgbm90IGFmZmVjdCBibF9jb3VudFttYXhfbGVuZ3RoXVxuICAgICAqL1xuICAgIG92ZXJmbG93IC09IDI7XG4gIH0gd2hpbGUgKG92ZXJmbG93ID4gMCk7XG5cbiAgLyogTm93IHJlY29tcHV0ZSBhbGwgYml0IGxlbmd0aHMsIHNjYW5uaW5nIGluIGluY3JlYXNpbmcgZnJlcXVlbmN5LlxuICAgKiBoIGlzIHN0aWxsIGVxdWFsIHRvIEhFQVBfU0laRS4gKEl0IGlzIHNpbXBsZXIgdG8gcmVjb25zdHJ1Y3QgYWxsXG4gICAqIGxlbmd0aHMgaW5zdGVhZCBvZiBmaXhpbmcgb25seSB0aGUgd3Jvbmcgb25lcy4gVGhpcyBpZGVhIGlzIHRha2VuXG4gICAqIGZyb20gJ2FyJyB3cml0dGVuIGJ5IEhhcnVoaWtvIE9rdW11cmEuKVxuICAgKi9cbiAgZm9yIChiaXRzID0gbWF4X2xlbmd0aDsgYml0cyAhPT0gMDsgYml0cy0tKSB7XG4gICAgbiA9IHMuYmxfY291bnRbYml0c107XG4gICAgd2hpbGUgKG4gIT09IDApIHtcbiAgICAgIG0gPSBzLmhlYXBbLS1oXTtcbiAgICAgIGlmIChtID4gbWF4X2NvZGUpIHsgY29udGludWU7IH1cbiAgICAgIGlmICh0cmVlW20qMiArIDFdLyouTGVuKi8gIT09IGJpdHMpIHtcbiAgICAgICAgLy8gVHJhY2UoKHN0ZGVycixcImNvZGUgJWQgYml0cyAlZC0+JWRcXG5cIiwgbSwgdHJlZVttXS5MZW4sIGJpdHMpKTtcbiAgICAgICAgcy5vcHRfbGVuICs9IChiaXRzIC0gdHJlZVttKjIgKyAxXS8qLkxlbiovKSp0cmVlW20qMl0vKi5GcmVxKi87XG4gICAgICAgIHRyZWVbbSoyICsgMV0vKi5MZW4qLyA9IGJpdHM7XG4gICAgICB9XG4gICAgICBuLS07XG4gICAgfVxuICB9XG59XG5cblxuLyogPT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09XG4gKiBHZW5lcmF0ZSB0aGUgY29kZXMgZm9yIGEgZ2l2ZW4gdHJlZSBhbmQgYml0IGNvdW50cyAod2hpY2ggbmVlZCBub3QgYmVcbiAqIG9wdGltYWwpLlxuICogSU4gYXNzZXJ0aW9uOiB0aGUgYXJyYXkgYmxfY291bnQgY29udGFpbnMgdGhlIGJpdCBsZW5ndGggc3RhdGlzdGljcyBmb3JcbiAqIHRoZSBnaXZlbiB0cmVlIGFuZCB0aGUgZmllbGQgbGVuIGlzIHNldCBmb3IgYWxsIHRyZWUgZWxlbWVudHMuXG4gKiBPVVQgYXNzZXJ0aW9uOiB0aGUgZmllbGQgY29kZSBpcyBzZXQgZm9yIGFsbCB0cmVlIGVsZW1lbnRzIG9mIG5vblxuICogICAgIHplcm8gY29kZSBsZW5ndGguXG4gKi9cbmZ1bmN0aW9uIGdlbl9jb2Rlcyh0cmVlLCBtYXhfY29kZSwgYmxfY291bnQpXG4vLyAgICBjdF9kYXRhICp0cmVlOyAgICAgICAgICAgICAvKiB0aGUgdHJlZSB0byBkZWNvcmF0ZSAqL1xuLy8gICAgaW50IG1heF9jb2RlOyAgICAgICAgICAgICAgLyogbGFyZ2VzdCBjb2RlIHdpdGggbm9uIHplcm8gZnJlcXVlbmN5ICovXG4vLyAgICB1c2hmICpibF9jb3VudDsgICAgICAgICAgICAvKiBudW1iZXIgb2YgY29kZXMgYXQgZWFjaCBiaXQgbGVuZ3RoICovXG57XG4gIHZhciBuZXh0X2NvZGUgPSBuZXcgQXJyYXkoTUFYX0JJVFMrMSk7IC8qIG5leHQgY29kZSB2YWx1ZSBmb3IgZWFjaCBiaXQgbGVuZ3RoICovXG4gIHZhciBjb2RlID0gMDsgICAgICAgICAgICAgIC8qIHJ1bm5pbmcgY29kZSB2YWx1ZSAqL1xuICB2YXIgYml0czsgICAgICAgICAgICAgICAgICAvKiBiaXQgaW5kZXggKi9cbiAgdmFyIG47ICAgICAgICAgICAgICAgICAgICAgLyogY29kZSBpbmRleCAqL1xuXG4gIC8qIFRoZSBkaXN0cmlidXRpb24gY291bnRzIGFyZSBmaXJzdCB1c2VkIHRvIGdlbmVyYXRlIHRoZSBjb2RlIHZhbHVlc1xuICAgKiB3aXRob3V0IGJpdCByZXZlcnNhbC5cbiAgICovXG4gIGZvciAoYml0cyA9IDE7IGJpdHMgPD0gTUFYX0JJVFM7IGJpdHMrKykge1xuICAgIG5leHRfY29kZVtiaXRzXSA9IGNvZGUgPSAoY29kZSArIGJsX2NvdW50W2JpdHMtMV0pIDw8IDE7XG4gIH1cbiAgLyogQ2hlY2sgdGhhdCB0aGUgYml0IGNvdW50cyBpbiBibF9jb3VudCBhcmUgY29uc2lzdGVudC4gVGhlIGxhc3QgY29kZVxuICAgKiBtdXN0IGJlIGFsbCBvbmVzLlxuICAgKi9cbiAgLy9Bc3NlcnQgKGNvZGUgKyBibF9jb3VudFtNQVhfQklUU10tMSA9PSAoMTw8TUFYX0JJVFMpLTEsXG4gIC8vICAgICAgICBcImluY29uc2lzdGVudCBiaXQgY291bnRzXCIpO1xuICAvL1RyYWNldigoc3RkZXJyLFwiXFxuZ2VuX2NvZGVzOiBtYXhfY29kZSAlZCBcIiwgbWF4X2NvZGUpKTtcblxuICBmb3IgKG4gPSAwOyAgbiA8PSBtYXhfY29kZTsgbisrKSB7XG4gICAgdmFyIGxlbiA9IHRyZWVbbioyICsgMV0vKi5MZW4qLztcbiAgICBpZiAobGVuID09PSAwKSB7IGNvbnRpbnVlOyB9XG4gICAgLyogTm93IHJldmVyc2UgdGhlIGJpdHMgKi9cbiAgICB0cmVlW24qMl0vKi5Db2RlKi8gPSBiaV9yZXZlcnNlKG5leHRfY29kZVtsZW5dKyssIGxlbik7XG5cbiAgICAvL1RyYWNlY3YodHJlZSAhPSBzdGF0aWNfbHRyZWUsIChzdGRlcnIsXCJcXG5uICUzZCAlYyBsICUyZCBjICU0eCAoJXgpIFwiLFxuICAgIC8vICAgICBuLCAoaXNncmFwaChuKSA/IG4gOiAnICcpLCBsZW4sIHRyZWVbbl0uQ29kZSwgbmV4dF9jb2RlW2xlbl0tMSkpO1xuICB9XG59XG5cblxuLyogPT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09XG4gKiBJbml0aWFsaXplIHRoZSB2YXJpb3VzICdjb25zdGFudCcgdGFibGVzLlxuICovXG5mdW5jdGlvbiB0cl9zdGF0aWNfaW5pdCgpIHtcbiAgdmFyIG47ICAgICAgICAvKiBpdGVyYXRlcyBvdmVyIHRyZWUgZWxlbWVudHMgKi9cbiAgdmFyIGJpdHM7ICAgICAvKiBiaXQgY291bnRlciAqL1xuICB2YXIgbGVuZ3RoOyAgIC8qIGxlbmd0aCB2YWx1ZSAqL1xuICB2YXIgY29kZTsgICAgIC8qIGNvZGUgdmFsdWUgKi9cbiAgdmFyIGRpc3Q7ICAgICAvKiBkaXN0YW5jZSBpbmRleCAqL1xuICB2YXIgYmxfY291bnQgPSBuZXcgQXJyYXkoTUFYX0JJVFMrMSk7XG4gIC8qIG51bWJlciBvZiBjb2RlcyBhdCBlYWNoIGJpdCBsZW5ndGggZm9yIGFuIG9wdGltYWwgdHJlZSAqL1xuXG4gIC8vIGRvIGNoZWNrIGluIF90cl9pbml0KClcbiAgLy9pZiAoc3RhdGljX2luaXRfZG9uZSkgcmV0dXJuO1xuXG4gIC8qIEZvciBzb21lIGVtYmVkZGVkIHRhcmdldHMsIGdsb2JhbCB2YXJpYWJsZXMgYXJlIG5vdCBpbml0aWFsaXplZDogKi9cbi8qI2lmZGVmIE5PX0lOSVRfR0xPQkFMX1BPSU5URVJTXG4gIHN0YXRpY19sX2Rlc2Muc3RhdGljX3RyZWUgPSBzdGF0aWNfbHRyZWU7XG4gIHN0YXRpY19sX2Rlc2MuZXh0cmFfYml0cyA9IGV4dHJhX2xiaXRzO1xuICBzdGF0aWNfZF9kZXNjLnN0YXRpY190cmVlID0gc3RhdGljX2R0cmVlO1xuICBzdGF0aWNfZF9kZXNjLmV4dHJhX2JpdHMgPSBleHRyYV9kYml0cztcbiAgc3RhdGljX2JsX2Rlc2MuZXh0cmFfYml0cyA9IGV4dHJhX2JsYml0cztcbiNlbmRpZiovXG5cbiAgLyogSW5pdGlhbGl6ZSB0aGUgbWFwcGluZyBsZW5ndGggKDAuLjI1NSkgLT4gbGVuZ3RoIGNvZGUgKDAuLjI4KSAqL1xuICBsZW5ndGggPSAwO1xuICBmb3IgKGNvZGUgPSAwOyBjb2RlIDwgTEVOR1RIX0NPREVTLTE7IGNvZGUrKykge1xuICAgIGJhc2VfbGVuZ3RoW2NvZGVdID0gbGVuZ3RoO1xuICAgIGZvciAobiA9IDA7IG4gPCAoMTw8ZXh0cmFfbGJpdHNbY29kZV0pOyBuKyspIHtcbiAgICAgIF9sZW5ndGhfY29kZVtsZW5ndGgrK10gPSBjb2RlO1xuICAgIH1cbiAgfVxuICAvL0Fzc2VydCAobGVuZ3RoID09IDI1NiwgXCJ0cl9zdGF0aWNfaW5pdDogbGVuZ3RoICE9IDI1NlwiKTtcbiAgLyogTm90ZSB0aGF0IHRoZSBsZW5ndGggMjU1IChtYXRjaCBsZW5ndGggMjU4KSBjYW4gYmUgcmVwcmVzZW50ZWRcbiAgICogaW4gdHdvIGRpZmZlcmVudCB3YXlzOiBjb2RlIDI4NCArIDUgYml0cyBvciBjb2RlIDI4NSwgc28gd2VcbiAgICogb3ZlcndyaXRlIGxlbmd0aF9jb2RlWzI1NV0gdG8gdXNlIHRoZSBiZXN0IGVuY29kaW5nOlxuICAgKi9cbiAgX2xlbmd0aF9jb2RlW2xlbmd0aC0xXSA9IGNvZGU7XG5cbiAgLyogSW5pdGlhbGl6ZSB0aGUgbWFwcGluZyBkaXN0ICgwLi4zMkspIC0+IGRpc3QgY29kZSAoMC4uMjkpICovXG4gIGRpc3QgPSAwO1xuICBmb3IgKGNvZGUgPSAwIDsgY29kZSA8IDE2OyBjb2RlKyspIHtcbiAgICBiYXNlX2Rpc3RbY29kZV0gPSBkaXN0O1xuICAgIGZvciAobiA9IDA7IG4gPCAoMTw8ZXh0cmFfZGJpdHNbY29kZV0pOyBuKyspIHtcbiAgICAgIF9kaXN0X2NvZGVbZGlzdCsrXSA9IGNvZGU7XG4gICAgfVxuICB9XG4gIC8vQXNzZXJ0IChkaXN0ID09IDI1NiwgXCJ0cl9zdGF0aWNfaW5pdDogZGlzdCAhPSAyNTZcIik7XG4gIGRpc3QgPj49IDc7IC8qIGZyb20gbm93IG9uLCBhbGwgZGlzdGFuY2VzIGFyZSBkaXZpZGVkIGJ5IDEyOCAqL1xuICBmb3IgKDsgY29kZSA8IERfQ09ERVM7IGNvZGUrKykge1xuICAgIGJhc2VfZGlzdFtjb2RlXSA9IGRpc3QgPDwgNztcbiAgICBmb3IgKG4gPSAwOyBuIDwgKDE8PChleHRyYV9kYml0c1tjb2RlXS03KSk7IG4rKykge1xuICAgICAgX2Rpc3RfY29kZVsyNTYgKyBkaXN0KytdID0gY29kZTtcbiAgICB9XG4gIH1cbiAgLy9Bc3NlcnQgKGRpc3QgPT0gMjU2LCBcInRyX3N0YXRpY19pbml0OiAyNTYrZGlzdCAhPSA1MTJcIik7XG5cbiAgLyogQ29uc3RydWN0IHRoZSBjb2RlcyBvZiB0aGUgc3RhdGljIGxpdGVyYWwgdHJlZSAqL1xuICBmb3IgKGJpdHMgPSAwOyBiaXRzIDw9IE1BWF9CSVRTOyBiaXRzKyspIHtcbiAgICBibF9jb3VudFtiaXRzXSA9IDA7XG4gIH1cblxuICBuID0gMDtcbiAgd2hpbGUgKG4gPD0gMTQzKSB7XG4gICAgc3RhdGljX2x0cmVlW24qMiArIDFdLyouTGVuKi8gPSA4O1xuICAgIG4rKztcbiAgICBibF9jb3VudFs4XSsrO1xuICB9XG4gIHdoaWxlIChuIDw9IDI1NSkge1xuICAgIHN0YXRpY19sdHJlZVtuKjIgKyAxXS8qLkxlbiovID0gOTtcbiAgICBuKys7XG4gICAgYmxfY291bnRbOV0rKztcbiAgfVxuICB3aGlsZSAobiA8PSAyNzkpIHtcbiAgICBzdGF0aWNfbHRyZWVbbioyICsgMV0vKi5MZW4qLyA9IDc7XG4gICAgbisrO1xuICAgIGJsX2NvdW50WzddKys7XG4gIH1cbiAgd2hpbGUgKG4gPD0gMjg3KSB7XG4gICAgc3RhdGljX2x0cmVlW24qMiArIDFdLyouTGVuKi8gPSA4O1xuICAgIG4rKztcbiAgICBibF9jb3VudFs4XSsrO1xuICB9XG4gIC8qIENvZGVzIDI4NiBhbmQgMjg3IGRvIG5vdCBleGlzdCwgYnV0IHdlIG11c3QgaW5jbHVkZSB0aGVtIGluIHRoZVxuICAgKiB0cmVlIGNvbnN0cnVjdGlvbiB0byBnZXQgYSBjYW5vbmljYWwgSHVmZm1hbiB0cmVlIChsb25nZXN0IGNvZGVcbiAgICogYWxsIG9uZXMpXG4gICAqL1xuICBnZW5fY29kZXMoc3RhdGljX2x0cmVlLCBMX0NPREVTKzEsIGJsX2NvdW50KTtcblxuICAvKiBUaGUgc3RhdGljIGRpc3RhbmNlIHRyZWUgaXMgdHJpdmlhbDogKi9cbiAgZm9yIChuID0gMDsgbiA8IERfQ09ERVM7IG4rKykge1xuICAgIHN0YXRpY19kdHJlZVtuKjIgKyAxXS8qLkxlbiovID0gNTtcbiAgICBzdGF0aWNfZHRyZWVbbioyXS8qLkNvZGUqLyA9IGJpX3JldmVyc2UobiwgNSk7XG4gIH1cblxuICAvLyBOb3cgZGF0YSByZWFkeSBhbmQgd2UgY2FuIGluaXQgc3RhdGljIHRyZWVzXG4gIHN0YXRpY19sX2Rlc2MgPSBuZXcgU3RhdGljVHJlZURlc2Moc3RhdGljX2x0cmVlLCBleHRyYV9sYml0cywgTElURVJBTFMrMSwgTF9DT0RFUywgTUFYX0JJVFMpO1xuICBzdGF0aWNfZF9kZXNjID0gbmV3IFN0YXRpY1RyZWVEZXNjKHN0YXRpY19kdHJlZSwgZXh0cmFfZGJpdHMsIDAsICAgICAgICAgIERfQ09ERVMsIE1BWF9CSVRTKTtcbiAgc3RhdGljX2JsX2Rlc2MgPW5ldyBTdGF0aWNUcmVlRGVzYyhuZXcgQXJyYXkoMCksIGV4dHJhX2JsYml0cywgMCwgICAgICAgICBCTF9DT0RFUywgTUFYX0JMX0JJVFMpO1xuXG4gIC8vc3RhdGljX2luaXRfZG9uZSA9IHRydWU7XG59XG5cblxuLyogPT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09XG4gKiBJbml0aWFsaXplIGEgbmV3IGJsb2NrLlxuICovXG5mdW5jdGlvbiBpbml0X2Jsb2NrKHMpIHtcbiAgdmFyIG47IC8qIGl0ZXJhdGVzIG92ZXIgdHJlZSBlbGVtZW50cyAqL1xuXG4gIC8qIEluaXRpYWxpemUgdGhlIHRyZWVzLiAqL1xuICBmb3IgKG4gPSAwOyBuIDwgTF9DT0RFUzsgIG4rKykgeyBzLmR5bl9sdHJlZVtuKjJdLyouRnJlcSovID0gMDsgfVxuICBmb3IgKG4gPSAwOyBuIDwgRF9DT0RFUzsgIG4rKykgeyBzLmR5bl9kdHJlZVtuKjJdLyouRnJlcSovID0gMDsgfVxuICBmb3IgKG4gPSAwOyBuIDwgQkxfQ09ERVM7IG4rKykgeyBzLmJsX3RyZWVbbioyXS8qLkZyZXEqLyA9IDA7IH1cblxuICBzLmR5bl9sdHJlZVtFTkRfQkxPQ0sqMl0vKi5GcmVxKi8gPSAxO1xuICBzLm9wdF9sZW4gPSBzLnN0YXRpY19sZW4gPSAwO1xuICBzLmxhc3RfbGl0ID0gcy5tYXRjaGVzID0gMDtcbn1cblxuXG4vKiA9PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT1cbiAqIEZsdXNoIHRoZSBiaXQgYnVmZmVyIGFuZCBhbGlnbiB0aGUgb3V0cHV0IG9uIGEgYnl0ZSBib3VuZGFyeVxuICovXG5mdW5jdGlvbiBiaV93aW5kdXAocylcbntcbiAgaWYgKHMuYmlfdmFsaWQgPiA4KSB7XG4gICAgcHV0X3Nob3J0KHMsIHMuYmlfYnVmKTtcbiAgfSBlbHNlIGlmIChzLmJpX3ZhbGlkID4gMCkge1xuICAgIC8vcHV0X2J5dGUocywgKEJ5dGUpcy0+YmlfYnVmKTtcbiAgICBzLnBlbmRpbmdfYnVmW3MucGVuZGluZysrXSA9IHMuYmlfYnVmO1xuICB9XG4gIHMuYmlfYnVmID0gMDtcbiAgcy5iaV92YWxpZCA9IDA7XG59XG5cbi8qID09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PVxuICogQ29weSBhIHN0b3JlZCBibG9jaywgc3RvcmluZyBmaXJzdCB0aGUgbGVuZ3RoIGFuZCBpdHNcbiAqIG9uZSdzIGNvbXBsZW1lbnQgaWYgcmVxdWVzdGVkLlxuICovXG5mdW5jdGlvbiBjb3B5X2Jsb2NrKHMsIGJ1ZiwgbGVuLCBoZWFkZXIpXG4vL0RlZmxhdGVTdGF0ZSAqcztcbi8vY2hhcmYgICAgKmJ1ZjsgICAgLyogdGhlIGlucHV0IGRhdGEgKi9cbi8vdW5zaWduZWQgbGVuOyAgICAgLyogaXRzIGxlbmd0aCAqL1xuLy9pbnQgICAgICBoZWFkZXI7ICAvKiB0cnVlIGlmIGJsb2NrIGhlYWRlciBtdXN0IGJlIHdyaXR0ZW4gKi9cbntcbiAgYmlfd2luZHVwKHMpOyAgICAgICAgLyogYWxpZ24gb24gYnl0ZSBib3VuZGFyeSAqL1xuXG4gIGlmIChoZWFkZXIpIHtcbiAgICBwdXRfc2hvcnQocywgbGVuKTtcbiAgICBwdXRfc2hvcnQocywgfmxlbik7XG4gIH1cbi8vICB3aGlsZSAobGVuLS0pIHtcbi8vICAgIHB1dF9ieXRlKHMsICpidWYrKyk7XG4vLyAgfVxuICB1dGlscy5hcnJheVNldChzLnBlbmRpbmdfYnVmLCBzLndpbmRvdywgYnVmLCBsZW4sIHMucGVuZGluZyk7XG4gIHMucGVuZGluZyArPSBsZW47XG59XG5cbi8qID09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PVxuICogQ29tcGFyZXMgdG8gc3VidHJlZXMsIHVzaW5nIHRoZSB0cmVlIGRlcHRoIGFzIHRpZSBicmVha2VyIHdoZW5cbiAqIHRoZSBzdWJ0cmVlcyBoYXZlIGVxdWFsIGZyZXF1ZW5jeS4gVGhpcyBtaW5pbWl6ZXMgdGhlIHdvcnN0IGNhc2UgbGVuZ3RoLlxuICovXG5mdW5jdGlvbiBzbWFsbGVyKHRyZWUsIG4sIG0sIGRlcHRoKSB7XG4gIHZhciBfbjIgPSBuKjI7XG4gIHZhciBfbTIgPSBtKjI7XG4gIHJldHVybiAodHJlZVtfbjJdLyouRnJlcSovIDwgdHJlZVtfbTJdLyouRnJlcSovIHx8XG4gICAgICAgICAodHJlZVtfbjJdLyouRnJlcSovID09PSB0cmVlW19tMl0vKi5GcmVxKi8gJiYgZGVwdGhbbl0gPD0gZGVwdGhbbV0pKTtcbn1cblxuLyogPT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09XG4gKiBSZXN0b3JlIHRoZSBoZWFwIHByb3BlcnR5IGJ5IG1vdmluZyBkb3duIHRoZSB0cmVlIHN0YXJ0aW5nIGF0IG5vZGUgayxcbiAqIGV4Y2hhbmdpbmcgYSBub2RlIHdpdGggdGhlIHNtYWxsZXN0IG9mIGl0cyB0d28gc29ucyBpZiBuZWNlc3NhcnksIHN0b3BwaW5nXG4gKiB3aGVuIHRoZSBoZWFwIHByb3BlcnR5IGlzIHJlLWVzdGFibGlzaGVkIChlYWNoIGZhdGhlciBzbWFsbGVyIHRoYW4gaXRzXG4gKiB0d28gc29ucykuXG4gKi9cbmZ1bmN0aW9uIHBxZG93bmhlYXAocywgdHJlZSwgaylcbi8vICAgIGRlZmxhdGVfc3RhdGUgKnM7XG4vLyAgICBjdF9kYXRhICp0cmVlOyAgLyogdGhlIHRyZWUgdG8gcmVzdG9yZSAqL1xuLy8gICAgaW50IGs7ICAgICAgICAgICAgICAgLyogbm9kZSB0byBtb3ZlIGRvd24gKi9cbntcbiAgdmFyIHYgPSBzLmhlYXBba107XG4gIHZhciBqID0gayA8PCAxOyAgLyogbGVmdCBzb24gb2YgayAqL1xuICB3aGlsZSAoaiA8PSBzLmhlYXBfbGVuKSB7XG4gICAgLyogU2V0IGogdG8gdGhlIHNtYWxsZXN0IG9mIHRoZSB0d28gc29uczogKi9cbiAgICBpZiAoaiA8IHMuaGVhcF9sZW4gJiZcbiAgICAgIHNtYWxsZXIodHJlZSwgcy5oZWFwW2orMV0sIHMuaGVhcFtqXSwgcy5kZXB0aCkpIHtcbiAgICAgIGorKztcbiAgICB9XG4gICAgLyogRXhpdCBpZiB2IGlzIHNtYWxsZXIgdGhhbiBib3RoIHNvbnMgKi9cbiAgICBpZiAoc21hbGxlcih0cmVlLCB2LCBzLmhlYXBbal0sIHMuZGVwdGgpKSB7IGJyZWFrOyB9XG5cbiAgICAvKiBFeGNoYW5nZSB2IHdpdGggdGhlIHNtYWxsZXN0IHNvbiAqL1xuICAgIHMuaGVhcFtrXSA9IHMuaGVhcFtqXTtcbiAgICBrID0gajtcblxuICAgIC8qIEFuZCBjb250aW51ZSBkb3duIHRoZSB0cmVlLCBzZXR0aW5nIGogdG8gdGhlIGxlZnQgc29uIG9mIGsgKi9cbiAgICBqIDw8PSAxO1xuICB9XG4gIHMuaGVhcFtrXSA9IHY7XG59XG5cblxuLy8gaW5saW5lZCBtYW51YWxseVxuLy8gdmFyIFNNQUxMRVNUID0gMTtcblxuLyogPT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09XG4gKiBTZW5kIHRoZSBibG9jayBkYXRhIGNvbXByZXNzZWQgdXNpbmcgdGhlIGdpdmVuIEh1ZmZtYW4gdHJlZXNcbiAqL1xuZnVuY3Rpb24gY29tcHJlc3NfYmxvY2socywgbHRyZWUsIGR0cmVlKVxuLy8gICAgZGVmbGF0ZV9zdGF0ZSAqcztcbi8vICAgIGNvbnN0IGN0X2RhdGEgKmx0cmVlOyAvKiBsaXRlcmFsIHRyZWUgKi9cbi8vICAgIGNvbnN0IGN0X2RhdGEgKmR0cmVlOyAvKiBkaXN0YW5jZSB0cmVlICovXG57XG4gIHZhciBkaXN0OyAgICAgICAgICAgLyogZGlzdGFuY2Ugb2YgbWF0Y2hlZCBzdHJpbmcgKi9cbiAgdmFyIGxjOyAgICAgICAgICAgICAvKiBtYXRjaCBsZW5ndGggb3IgdW5tYXRjaGVkIGNoYXIgKGlmIGRpc3QgPT0gMCkgKi9cbiAgdmFyIGx4ID0gMDsgICAgICAgICAvKiBydW5uaW5nIGluZGV4IGluIGxfYnVmICovXG4gIHZhciBjb2RlOyAgICAgICAgICAgLyogdGhlIGNvZGUgdG8gc2VuZCAqL1xuICB2YXIgZXh0cmE7ICAgICAgICAgIC8qIG51bWJlciBvZiBleHRyYSBiaXRzIHRvIHNlbmQgKi9cblxuICBpZiAocy5sYXN0X2xpdCAhPT0gMCkge1xuICAgIGRvIHtcbiAgICAgIGRpc3QgPSAocy5wZW5kaW5nX2J1ZltzLmRfYnVmICsgbHgqMl0gPDwgOCkgfCAocy5wZW5kaW5nX2J1ZltzLmRfYnVmICsgbHgqMiArIDFdKTtcbiAgICAgIGxjID0gcy5wZW5kaW5nX2J1ZltzLmxfYnVmICsgbHhdO1xuICAgICAgbHgrKztcblxuICAgICAgaWYgKGRpc3QgPT09IDApIHtcbiAgICAgICAgc2VuZF9jb2RlKHMsIGxjLCBsdHJlZSk7IC8qIHNlbmQgYSBsaXRlcmFsIGJ5dGUgKi9cbiAgICAgICAgLy9UcmFjZWN2KGlzZ3JhcGgobGMpLCAoc3RkZXJyLFwiICclYycgXCIsIGxjKSk7XG4gICAgICB9IGVsc2Uge1xuICAgICAgICAvKiBIZXJlLCBsYyBpcyB0aGUgbWF0Y2ggbGVuZ3RoIC0gTUlOX01BVENIICovXG4gICAgICAgIGNvZGUgPSBfbGVuZ3RoX2NvZGVbbGNdO1xuICAgICAgICBzZW5kX2NvZGUocywgY29kZStMSVRFUkFMUysxLCBsdHJlZSk7IC8qIHNlbmQgdGhlIGxlbmd0aCBjb2RlICovXG4gICAgICAgIGV4dHJhID0gZXh0cmFfbGJpdHNbY29kZV07XG4gICAgICAgIGlmIChleHRyYSAhPT0gMCkge1xuICAgICAgICAgIGxjIC09IGJhc2VfbGVuZ3RoW2NvZGVdO1xuICAgICAgICAgIHNlbmRfYml0cyhzLCBsYywgZXh0cmEpOyAgICAgICAvKiBzZW5kIHRoZSBleHRyYSBsZW5ndGggYml0cyAqL1xuICAgICAgICB9XG4gICAgICAgIGRpc3QtLTsgLyogZGlzdCBpcyBub3cgdGhlIG1hdGNoIGRpc3RhbmNlIC0gMSAqL1xuICAgICAgICBjb2RlID0gZF9jb2RlKGRpc3QpO1xuICAgICAgICAvL0Fzc2VydCAoY29kZSA8IERfQ09ERVMsIFwiYmFkIGRfY29kZVwiKTtcblxuICAgICAgICBzZW5kX2NvZGUocywgY29kZSwgZHRyZWUpOyAgICAgICAvKiBzZW5kIHRoZSBkaXN0YW5jZSBjb2RlICovXG4gICAgICAgIGV4dHJhID0gZXh0cmFfZGJpdHNbY29kZV07XG4gICAgICAgIGlmIChleHRyYSAhPT0gMCkge1xuICAgICAgICAgIGRpc3QgLT0gYmFzZV9kaXN0W2NvZGVdO1xuICAgICAgICAgIHNlbmRfYml0cyhzLCBkaXN0LCBleHRyYSk7ICAgLyogc2VuZCB0aGUgZXh0cmEgZGlzdGFuY2UgYml0cyAqL1xuICAgICAgICB9XG4gICAgICB9IC8qIGxpdGVyYWwgb3IgbWF0Y2ggcGFpciA/ICovXG5cbiAgICAgIC8qIENoZWNrIHRoYXQgdGhlIG92ZXJsYXkgYmV0d2VlbiBwZW5kaW5nX2J1ZiBhbmQgZF9idWYrbF9idWYgaXMgb2s6ICovXG4gICAgICAvL0Fzc2VydCgodUludCkocy0+cGVuZGluZykgPCBzLT5saXRfYnVmc2l6ZSArIDIqbHgsXG4gICAgICAvLyAgICAgICBcInBlbmRpbmdCdWYgb3ZlcmZsb3dcIik7XG5cbiAgICB9IHdoaWxlIChseCA8IHMubGFzdF9saXQpO1xuICB9XG5cbiAgc2VuZF9jb2RlKHMsIEVORF9CTE9DSywgbHRyZWUpO1xufVxuXG5cbi8qID09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PVxuICogQ29uc3RydWN0IG9uZSBIdWZmbWFuIHRyZWUgYW5kIGFzc2lnbnMgdGhlIGNvZGUgYml0IHN0cmluZ3MgYW5kIGxlbmd0aHMuXG4gKiBVcGRhdGUgdGhlIHRvdGFsIGJpdCBsZW5ndGggZm9yIHRoZSBjdXJyZW50IGJsb2NrLlxuICogSU4gYXNzZXJ0aW9uOiB0aGUgZmllbGQgZnJlcSBpcyBzZXQgZm9yIGFsbCB0cmVlIGVsZW1lbnRzLlxuICogT1VUIGFzc2VydGlvbnM6IHRoZSBmaWVsZHMgbGVuIGFuZCBjb2RlIGFyZSBzZXQgdG8gdGhlIG9wdGltYWwgYml0IGxlbmd0aFxuICogICAgIGFuZCBjb3JyZXNwb25kaW5nIGNvZGUuIFRoZSBsZW5ndGggb3B0X2xlbiBpcyB1cGRhdGVkOyBzdGF0aWNfbGVuIGlzXG4gKiAgICAgYWxzbyB1cGRhdGVkIGlmIHN0cmVlIGlzIG5vdCBudWxsLiBUaGUgZmllbGQgbWF4X2NvZGUgaXMgc2V0LlxuICovXG5mdW5jdGlvbiBidWlsZF90cmVlKHMsIGRlc2MpXG4vLyAgICBkZWZsYXRlX3N0YXRlICpzO1xuLy8gICAgdHJlZV9kZXNjICpkZXNjOyAvKiB0aGUgdHJlZSBkZXNjcmlwdG9yICovXG57XG4gIHZhciB0cmVlICAgICA9IGRlc2MuZHluX3RyZWU7XG4gIHZhciBzdHJlZSAgICA9IGRlc2Muc3RhdF9kZXNjLnN0YXRpY190cmVlO1xuICB2YXIgaGFzX3N0cmVlID0gZGVzYy5zdGF0X2Rlc2MuaGFzX3N0cmVlO1xuICB2YXIgZWxlbXMgICAgPSBkZXNjLnN0YXRfZGVzYy5lbGVtcztcbiAgdmFyIG4sIG07ICAgICAgICAgIC8qIGl0ZXJhdGUgb3ZlciBoZWFwIGVsZW1lbnRzICovXG4gIHZhciBtYXhfY29kZSA9IC0xOyAvKiBsYXJnZXN0IGNvZGUgd2l0aCBub24gemVybyBmcmVxdWVuY3kgKi9cbiAgdmFyIG5vZGU7ICAgICAgICAgIC8qIG5ldyBub2RlIGJlaW5nIGNyZWF0ZWQgKi9cblxuICAvKiBDb25zdHJ1Y3QgdGhlIGluaXRpYWwgaGVhcCwgd2l0aCBsZWFzdCBmcmVxdWVudCBlbGVtZW50IGluXG4gICAqIGhlYXBbU01BTExFU1RdLiBUaGUgc29ucyBvZiBoZWFwW25dIGFyZSBoZWFwWzIqbl0gYW5kIGhlYXBbMipuKzFdLlxuICAgKiBoZWFwWzBdIGlzIG5vdCB1c2VkLlxuICAgKi9cbiAgcy5oZWFwX2xlbiA9IDA7XG4gIHMuaGVhcF9tYXggPSBIRUFQX1NJWkU7XG5cbiAgZm9yIChuID0gMDsgbiA8IGVsZW1zOyBuKyspIHtcbiAgICBpZiAodHJlZVtuICogMl0vKi5GcmVxKi8gIT09IDApIHtcbiAgICAgIHMuaGVhcFsrK3MuaGVhcF9sZW5dID0gbWF4X2NvZGUgPSBuO1xuICAgICAgcy5kZXB0aFtuXSA9IDA7XG5cbiAgICB9IGVsc2Uge1xuICAgICAgdHJlZVtuKjIgKyAxXS8qLkxlbiovID0gMDtcbiAgICB9XG4gIH1cblxuICAvKiBUaGUgcGt6aXAgZm9ybWF0IHJlcXVpcmVzIHRoYXQgYXQgbGVhc3Qgb25lIGRpc3RhbmNlIGNvZGUgZXhpc3RzLFxuICAgKiBhbmQgdGhhdCBhdCBsZWFzdCBvbmUgYml0IHNob3VsZCBiZSBzZW50IGV2ZW4gaWYgdGhlcmUgaXMgb25seSBvbmVcbiAgICogcG9zc2libGUgY29kZS4gU28gdG8gYXZvaWQgc3BlY2lhbCBjaGVja3MgbGF0ZXIgb24gd2UgZm9yY2UgYXQgbGVhc3RcbiAgICogdHdvIGNvZGVzIG9mIG5vbiB6ZXJvIGZyZXF1ZW5jeS5cbiAgICovXG4gIHdoaWxlIChzLmhlYXBfbGVuIDwgMikge1xuICAgIG5vZGUgPSBzLmhlYXBbKytzLmhlYXBfbGVuXSA9IChtYXhfY29kZSA8IDIgPyArK21heF9jb2RlIDogMCk7XG4gICAgdHJlZVtub2RlICogMl0vKi5GcmVxKi8gPSAxO1xuICAgIHMuZGVwdGhbbm9kZV0gPSAwO1xuICAgIHMub3B0X2xlbi0tO1xuXG4gICAgaWYgKGhhc19zdHJlZSkge1xuICAgICAgcy5zdGF0aWNfbGVuIC09IHN0cmVlW25vZGUqMiArIDFdLyouTGVuKi87XG4gICAgfVxuICAgIC8qIG5vZGUgaXMgMCBvciAxIHNvIGl0IGRvZXMgbm90IGhhdmUgZXh0cmEgYml0cyAqL1xuICB9XG4gIGRlc2MubWF4X2NvZGUgPSBtYXhfY29kZTtcblxuICAvKiBUaGUgZWxlbWVudHMgaGVhcFtoZWFwX2xlbi8yKzEgLi4gaGVhcF9sZW5dIGFyZSBsZWF2ZXMgb2YgdGhlIHRyZWUsXG4gICAqIGVzdGFibGlzaCBzdWItaGVhcHMgb2YgaW5jcmVhc2luZyBsZW5ndGhzOlxuICAgKi9cbiAgZm9yIChuID0gKHMuaGVhcF9sZW4gPj4gMS8qaW50IC8yKi8pOyBuID49IDE7IG4tLSkgeyBwcWRvd25oZWFwKHMsIHRyZWUsIG4pOyB9XG5cbiAgLyogQ29uc3RydWN0IHRoZSBIdWZmbWFuIHRyZWUgYnkgcmVwZWF0ZWRseSBjb21iaW5pbmcgdGhlIGxlYXN0IHR3b1xuICAgKiBmcmVxdWVudCBub2Rlcy5cbiAgICovXG4gIG5vZGUgPSBlbGVtczsgICAgICAgICAgICAgIC8qIG5leHQgaW50ZXJuYWwgbm9kZSBvZiB0aGUgdHJlZSAqL1xuICBkbyB7XG4gICAgLy9wcXJlbW92ZShzLCB0cmVlLCBuKTsgIC8qIG4gPSBub2RlIG9mIGxlYXN0IGZyZXF1ZW5jeSAqL1xuICAgIC8qKiogcHFyZW1vdmUgKioqL1xuICAgIG4gPSBzLmhlYXBbMS8qU01BTExFU1QqL107XG4gICAgcy5oZWFwWzEvKlNNQUxMRVNUKi9dID0gcy5oZWFwW3MuaGVhcF9sZW4tLV07XG4gICAgcHFkb3duaGVhcChzLCB0cmVlLCAxLypTTUFMTEVTVCovKTtcbiAgICAvKioqL1xuXG4gICAgbSA9IHMuaGVhcFsxLypTTUFMTEVTVCovXTsgLyogbSA9IG5vZGUgb2YgbmV4dCBsZWFzdCBmcmVxdWVuY3kgKi9cblxuICAgIHMuaGVhcFstLXMuaGVhcF9tYXhdID0gbjsgLyoga2VlcCB0aGUgbm9kZXMgc29ydGVkIGJ5IGZyZXF1ZW5jeSAqL1xuICAgIHMuaGVhcFstLXMuaGVhcF9tYXhdID0gbTtcblxuICAgIC8qIENyZWF0ZSBhIG5ldyBub2RlIGZhdGhlciBvZiBuIGFuZCBtICovXG4gICAgdHJlZVtub2RlICogMl0vKi5GcmVxKi8gPSB0cmVlW24gKiAyXS8qLkZyZXEqLyArIHRyZWVbbSAqIDJdLyouRnJlcSovO1xuICAgIHMuZGVwdGhbbm9kZV0gPSAocy5kZXB0aFtuXSA+PSBzLmRlcHRoW21dID8gcy5kZXB0aFtuXSA6IHMuZGVwdGhbbV0pICsgMTtcbiAgICB0cmVlW24qMiArIDFdLyouRGFkKi8gPSB0cmVlW20qMiArIDFdLyouRGFkKi8gPSBub2RlO1xuXG4gICAgLyogYW5kIGluc2VydCB0aGUgbmV3IG5vZGUgaW4gdGhlIGhlYXAgKi9cbiAgICBzLmhlYXBbMS8qU01BTExFU1QqL10gPSBub2RlKys7XG4gICAgcHFkb3duaGVhcChzLCB0cmVlLCAxLypTTUFMTEVTVCovKTtcblxuICB9IHdoaWxlIChzLmhlYXBfbGVuID49IDIpO1xuXG4gIHMuaGVhcFstLXMuaGVhcF9tYXhdID0gcy5oZWFwWzEvKlNNQUxMRVNUKi9dO1xuXG4gIC8qIEF0IHRoaXMgcG9pbnQsIHRoZSBmaWVsZHMgZnJlcSBhbmQgZGFkIGFyZSBzZXQuIFdlIGNhbiBub3dcbiAgICogZ2VuZXJhdGUgdGhlIGJpdCBsZW5ndGhzLlxuICAgKi9cbiAgZ2VuX2JpdGxlbihzLCBkZXNjKTtcblxuICAvKiBUaGUgZmllbGQgbGVuIGlzIG5vdyBzZXQsIHdlIGNhbiBnZW5lcmF0ZSB0aGUgYml0IGNvZGVzICovXG4gIGdlbl9jb2Rlcyh0cmVlLCBtYXhfY29kZSwgcy5ibF9jb3VudCk7XG59XG5cblxuLyogPT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09XG4gKiBTY2FuIGEgbGl0ZXJhbCBvciBkaXN0YW5jZSB0cmVlIHRvIGRldGVybWluZSB0aGUgZnJlcXVlbmNpZXMgb2YgdGhlIGNvZGVzXG4gKiBpbiB0aGUgYml0IGxlbmd0aCB0cmVlLlxuICovXG5mdW5jdGlvbiBzY2FuX3RyZWUocywgdHJlZSwgbWF4X2NvZGUpXG4vLyAgICBkZWZsYXRlX3N0YXRlICpzO1xuLy8gICAgY3RfZGF0YSAqdHJlZTsgICAvKiB0aGUgdHJlZSB0byBiZSBzY2FubmVkICovXG4vLyAgICBpbnQgbWF4X2NvZGU7ICAgIC8qIGFuZCBpdHMgbGFyZ2VzdCBjb2RlIG9mIG5vbiB6ZXJvIGZyZXF1ZW5jeSAqL1xue1xuICB2YXIgbjsgICAgICAgICAgICAgICAgICAgICAvKiBpdGVyYXRlcyBvdmVyIGFsbCB0cmVlIGVsZW1lbnRzICovXG4gIHZhciBwcmV2bGVuID0gLTE7ICAgICAgICAgIC8qIGxhc3QgZW1pdHRlZCBsZW5ndGggKi9cbiAgdmFyIGN1cmxlbjsgICAgICAgICAgICAgICAgLyogbGVuZ3RoIG9mIGN1cnJlbnQgY29kZSAqL1xuXG4gIHZhciBuZXh0bGVuID0gdHJlZVswKjIgKyAxXS8qLkxlbiovOyAvKiBsZW5ndGggb2YgbmV4dCBjb2RlICovXG5cbiAgdmFyIGNvdW50ID0gMDsgICAgICAgICAgICAgLyogcmVwZWF0IGNvdW50IG9mIHRoZSBjdXJyZW50IGNvZGUgKi9cbiAgdmFyIG1heF9jb3VudCA9IDc7ICAgICAgICAgLyogbWF4IHJlcGVhdCBjb3VudCAqL1xuICB2YXIgbWluX2NvdW50ID0gNDsgICAgICAgICAvKiBtaW4gcmVwZWF0IGNvdW50ICovXG5cbiAgaWYgKG5leHRsZW4gPT09IDApIHtcbiAgICBtYXhfY291bnQgPSAxMzg7XG4gICAgbWluX2NvdW50ID0gMztcbiAgfVxuICB0cmVlWyhtYXhfY29kZSsxKSoyICsgMV0vKi5MZW4qLyA9IDB4ZmZmZjsgLyogZ3VhcmQgKi9cblxuICBmb3IgKG4gPSAwOyBuIDw9IG1heF9jb2RlOyBuKyspIHtcbiAgICBjdXJsZW4gPSBuZXh0bGVuO1xuICAgIG5leHRsZW4gPSB0cmVlWyhuKzEpKjIgKyAxXS8qLkxlbiovO1xuXG4gICAgaWYgKCsrY291bnQgPCBtYXhfY291bnQgJiYgY3VybGVuID09PSBuZXh0bGVuKSB7XG4gICAgICBjb250aW51ZTtcblxuICAgIH0gZWxzZSBpZiAoY291bnQgPCBtaW5fY291bnQpIHtcbiAgICAgIHMuYmxfdHJlZVtjdXJsZW4gKiAyXS8qLkZyZXEqLyArPSBjb3VudDtcblxuICAgIH0gZWxzZSBpZiAoY3VybGVuICE9PSAwKSB7XG5cbiAgICAgIGlmIChjdXJsZW4gIT09IHByZXZsZW4pIHsgcy5ibF90cmVlW2N1cmxlbiAqIDJdLyouRnJlcSovKys7IH1cbiAgICAgIHMuYmxfdHJlZVtSRVBfM182KjJdLyouRnJlcSovKys7XG5cbiAgICB9IGVsc2UgaWYgKGNvdW50IDw9IDEwKSB7XG4gICAgICBzLmJsX3RyZWVbUkVQWl8zXzEwKjJdLyouRnJlcSovKys7XG5cbiAgICB9IGVsc2Uge1xuICAgICAgcy5ibF90cmVlW1JFUFpfMTFfMTM4KjJdLyouRnJlcSovKys7XG4gICAgfVxuXG4gICAgY291bnQgPSAwO1xuICAgIHByZXZsZW4gPSBjdXJsZW47XG5cbiAgICBpZiAobmV4dGxlbiA9PT0gMCkge1xuICAgICAgbWF4X2NvdW50ID0gMTM4O1xuICAgICAgbWluX2NvdW50ID0gMztcblxuICAgIH0gZWxzZSBpZiAoY3VybGVuID09PSBuZXh0bGVuKSB7XG4gICAgICBtYXhfY291bnQgPSA2O1xuICAgICAgbWluX2NvdW50ID0gMztcblxuICAgIH0gZWxzZSB7XG4gICAgICBtYXhfY291bnQgPSA3O1xuICAgICAgbWluX2NvdW50ID0gNDtcbiAgICB9XG4gIH1cbn1cblxuXG4vKiA9PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT1cbiAqIFNlbmQgYSBsaXRlcmFsIG9yIGRpc3RhbmNlIHRyZWUgaW4gY29tcHJlc3NlZCBmb3JtLCB1c2luZyB0aGUgY29kZXMgaW5cbiAqIGJsX3RyZWUuXG4gKi9cbmZ1bmN0aW9uIHNlbmRfdHJlZShzLCB0cmVlLCBtYXhfY29kZSlcbi8vICAgIGRlZmxhdGVfc3RhdGUgKnM7XG4vLyAgICBjdF9kYXRhICp0cmVlOyAvKiB0aGUgdHJlZSB0byBiZSBzY2FubmVkICovXG4vLyAgICBpbnQgbWF4X2NvZGU7ICAgICAgIC8qIGFuZCBpdHMgbGFyZ2VzdCBjb2RlIG9mIG5vbiB6ZXJvIGZyZXF1ZW5jeSAqL1xue1xuICB2YXIgbjsgICAgICAgICAgICAgICAgICAgICAvKiBpdGVyYXRlcyBvdmVyIGFsbCB0cmVlIGVsZW1lbnRzICovXG4gIHZhciBwcmV2bGVuID0gLTE7ICAgICAgICAgIC8qIGxhc3QgZW1pdHRlZCBsZW5ndGggKi9cbiAgdmFyIGN1cmxlbjsgICAgICAgICAgICAgICAgLyogbGVuZ3RoIG9mIGN1cnJlbnQgY29kZSAqL1xuXG4gIHZhciBuZXh0bGVuID0gdHJlZVswKjIgKyAxXS8qLkxlbiovOyAvKiBsZW5ndGggb2YgbmV4dCBjb2RlICovXG5cbiAgdmFyIGNvdW50ID0gMDsgICAgICAgICAgICAgLyogcmVwZWF0IGNvdW50IG9mIHRoZSBjdXJyZW50IGNvZGUgKi9cbiAgdmFyIG1heF9jb3VudCA9IDc7ICAgICAgICAgLyogbWF4IHJlcGVhdCBjb3VudCAqL1xuICB2YXIgbWluX2NvdW50ID0gNDsgICAgICAgICAvKiBtaW4gcmVwZWF0IGNvdW50ICovXG5cbiAgLyogdHJlZVttYXhfY29kZSsxXS5MZW4gPSAtMTsgKi8gIC8qIGd1YXJkIGFscmVhZHkgc2V0ICovXG4gIGlmIChuZXh0bGVuID09PSAwKSB7XG4gICAgbWF4X2NvdW50ID0gMTM4O1xuICAgIG1pbl9jb3VudCA9IDM7XG4gIH1cblxuICBmb3IgKG4gPSAwOyBuIDw9IG1heF9jb2RlOyBuKyspIHtcbiAgICBjdXJsZW4gPSBuZXh0bGVuO1xuICAgIG5leHRsZW4gPSB0cmVlWyhuKzEpKjIgKyAxXS8qLkxlbiovO1xuXG4gICAgaWYgKCsrY291bnQgPCBtYXhfY291bnQgJiYgY3VybGVuID09PSBuZXh0bGVuKSB7XG4gICAgICBjb250aW51ZTtcblxuICAgIH0gZWxzZSBpZiAoY291bnQgPCBtaW5fY291bnQpIHtcbiAgICAgIGRvIHsgc2VuZF9jb2RlKHMsIGN1cmxlbiwgcy5ibF90cmVlKTsgfSB3aGlsZSAoLS1jb3VudCAhPT0gMCk7XG5cbiAgICB9IGVsc2UgaWYgKGN1cmxlbiAhPT0gMCkge1xuICAgICAgaWYgKGN1cmxlbiAhPT0gcHJldmxlbikge1xuICAgICAgICBzZW5kX2NvZGUocywgY3VybGVuLCBzLmJsX3RyZWUpO1xuICAgICAgICBjb3VudC0tO1xuICAgICAgfVxuICAgICAgLy9Bc3NlcnQoY291bnQgPj0gMyAmJiBjb3VudCA8PSA2LCBcIiAzXzY/XCIpO1xuICAgICAgc2VuZF9jb2RlKHMsIFJFUF8zXzYsIHMuYmxfdHJlZSk7XG4gICAgICBzZW5kX2JpdHMocywgY291bnQtMywgMik7XG5cbiAgICB9IGVsc2UgaWYgKGNvdW50IDw9IDEwKSB7XG4gICAgICBzZW5kX2NvZGUocywgUkVQWl8zXzEwLCBzLmJsX3RyZWUpO1xuICAgICAgc2VuZF9iaXRzKHMsIGNvdW50LTMsIDMpO1xuXG4gICAgfSBlbHNlIHtcbiAgICAgIHNlbmRfY29kZShzLCBSRVBaXzExXzEzOCwgcy5ibF90cmVlKTtcbiAgICAgIHNlbmRfYml0cyhzLCBjb3VudC0xMSwgNyk7XG4gICAgfVxuXG4gICAgY291bnQgPSAwO1xuICAgIHByZXZsZW4gPSBjdXJsZW47XG4gICAgaWYgKG5leHRsZW4gPT09IDApIHtcbiAgICAgIG1heF9jb3VudCA9IDEzODtcbiAgICAgIG1pbl9jb3VudCA9IDM7XG5cbiAgICB9IGVsc2UgaWYgKGN1cmxlbiA9PT0gbmV4dGxlbikge1xuICAgICAgbWF4X2NvdW50ID0gNjtcbiAgICAgIG1pbl9jb3VudCA9IDM7XG5cbiAgICB9IGVsc2Uge1xuICAgICAgbWF4X2NvdW50ID0gNztcbiAgICAgIG1pbl9jb3VudCA9IDQ7XG4gICAgfVxuICB9XG59XG5cblxuLyogPT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09XG4gKiBDb25zdHJ1Y3QgdGhlIEh1ZmZtYW4gdHJlZSBmb3IgdGhlIGJpdCBsZW5ndGhzIGFuZCByZXR1cm4gdGhlIGluZGV4IGluXG4gKiBibF9vcmRlciBvZiB0aGUgbGFzdCBiaXQgbGVuZ3RoIGNvZGUgdG8gc2VuZC5cbiAqL1xuZnVuY3Rpb24gYnVpbGRfYmxfdHJlZShzKSB7XG4gIHZhciBtYXhfYmxpbmRleDsgIC8qIGluZGV4IG9mIGxhc3QgYml0IGxlbmd0aCBjb2RlIG9mIG5vbiB6ZXJvIGZyZXEgKi9cblxuICAvKiBEZXRlcm1pbmUgdGhlIGJpdCBsZW5ndGggZnJlcXVlbmNpZXMgZm9yIGxpdGVyYWwgYW5kIGRpc3RhbmNlIHRyZWVzICovXG4gIHNjYW5fdHJlZShzLCBzLmR5bl9sdHJlZSwgcy5sX2Rlc2MubWF4X2NvZGUpO1xuICBzY2FuX3RyZWUocywgcy5keW5fZHRyZWUsIHMuZF9kZXNjLm1heF9jb2RlKTtcblxuICAvKiBCdWlsZCB0aGUgYml0IGxlbmd0aCB0cmVlOiAqL1xuICBidWlsZF90cmVlKHMsIHMuYmxfZGVzYyk7XG4gIC8qIG9wdF9sZW4gbm93IGluY2x1ZGVzIHRoZSBsZW5ndGggb2YgdGhlIHRyZWUgcmVwcmVzZW50YXRpb25zLCBleGNlcHRcbiAgICogdGhlIGxlbmd0aHMgb2YgdGhlIGJpdCBsZW5ndGhzIGNvZGVzIGFuZCB0aGUgNSs1KzQgYml0cyBmb3IgdGhlIGNvdW50cy5cbiAgICovXG5cbiAgLyogRGV0ZXJtaW5lIHRoZSBudW1iZXIgb2YgYml0IGxlbmd0aCBjb2RlcyB0byBzZW5kLiBUaGUgcGt6aXAgZm9ybWF0XG4gICAqIHJlcXVpcmVzIHRoYXQgYXQgbGVhc3QgNCBiaXQgbGVuZ3RoIGNvZGVzIGJlIHNlbnQuIChhcHBub3RlLnR4dCBzYXlzXG4gICAqIDMgYnV0IHRoZSBhY3R1YWwgdmFsdWUgdXNlZCBpcyA0LilcbiAgICovXG4gIGZvciAobWF4X2JsaW5kZXggPSBCTF9DT0RFUy0xOyBtYXhfYmxpbmRleCA+PSAzOyBtYXhfYmxpbmRleC0tKSB7XG4gICAgaWYgKHMuYmxfdHJlZVtibF9vcmRlclttYXhfYmxpbmRleF0qMiArIDFdLyouTGVuKi8gIT09IDApIHtcbiAgICAgIGJyZWFrO1xuICAgIH1cbiAgfVxuICAvKiBVcGRhdGUgb3B0X2xlbiB0byBpbmNsdWRlIHRoZSBiaXQgbGVuZ3RoIHRyZWUgYW5kIGNvdW50cyAqL1xuICBzLm9wdF9sZW4gKz0gMyoobWF4X2JsaW5kZXgrMSkgKyA1KzUrNDtcbiAgLy9UcmFjZXYoKHN0ZGVyciwgXCJcXG5keW4gdHJlZXM6IGR5biAlbGQsIHN0YXQgJWxkXCIsXG4gIC8vICAgICAgICBzLT5vcHRfbGVuLCBzLT5zdGF0aWNfbGVuKSk7XG5cbiAgcmV0dXJuIG1heF9ibGluZGV4O1xufVxuXG5cbi8qID09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PVxuICogU2VuZCB0aGUgaGVhZGVyIGZvciBhIGJsb2NrIHVzaW5nIGR5bmFtaWMgSHVmZm1hbiB0cmVlczogdGhlIGNvdW50cywgdGhlXG4gKiBsZW5ndGhzIG9mIHRoZSBiaXQgbGVuZ3RoIGNvZGVzLCB0aGUgbGl0ZXJhbCB0cmVlIGFuZCB0aGUgZGlzdGFuY2UgdHJlZS5cbiAqIElOIGFzc2VydGlvbjogbGNvZGVzID49IDI1NywgZGNvZGVzID49IDEsIGJsY29kZXMgPj0gNC5cbiAqL1xuZnVuY3Rpb24gc2VuZF9hbGxfdHJlZXMocywgbGNvZGVzLCBkY29kZXMsIGJsY29kZXMpXG4vLyAgICBkZWZsYXRlX3N0YXRlICpzO1xuLy8gICAgaW50IGxjb2RlcywgZGNvZGVzLCBibGNvZGVzOyAvKiBudW1iZXIgb2YgY29kZXMgZm9yIGVhY2ggdHJlZSAqL1xue1xuICB2YXIgcmFuazsgICAgICAgICAgICAgICAgICAgIC8qIGluZGV4IGluIGJsX29yZGVyICovXG5cbiAgLy9Bc3NlcnQgKGxjb2RlcyA+PSAyNTcgJiYgZGNvZGVzID49IDEgJiYgYmxjb2RlcyA+PSA0LCBcIm5vdCBlbm91Z2ggY29kZXNcIik7XG4gIC8vQXNzZXJ0IChsY29kZXMgPD0gTF9DT0RFUyAmJiBkY29kZXMgPD0gRF9DT0RFUyAmJiBibGNvZGVzIDw9IEJMX0NPREVTLFxuICAvLyAgICAgICAgXCJ0b28gbWFueSBjb2Rlc1wiKTtcbiAgLy9UcmFjZXYoKHN0ZGVyciwgXCJcXG5ibCBjb3VudHM6IFwiKSk7XG4gIHNlbmRfYml0cyhzLCBsY29kZXMtMjU3LCA1KTsgLyogbm90ICsyNTUgYXMgc3RhdGVkIGluIGFwcG5vdGUudHh0ICovXG4gIHNlbmRfYml0cyhzLCBkY29kZXMtMSwgICA1KTtcbiAgc2VuZF9iaXRzKHMsIGJsY29kZXMtNCwgIDQpOyAvKiBub3QgLTMgYXMgc3RhdGVkIGluIGFwcG5vdGUudHh0ICovXG4gIGZvciAocmFuayA9IDA7IHJhbmsgPCBibGNvZGVzOyByYW5rKyspIHtcbiAgICAvL1RyYWNldigoc3RkZXJyLCBcIlxcbmJsIGNvZGUgJTJkIFwiLCBibF9vcmRlcltyYW5rXSkpO1xuICAgIHNlbmRfYml0cyhzLCBzLmJsX3RyZWVbYmxfb3JkZXJbcmFua10qMiArIDFdLyouTGVuKi8sIDMpO1xuICB9XG4gIC8vVHJhY2V2KChzdGRlcnIsIFwiXFxuYmwgdHJlZTogc2VudCAlbGRcIiwgcy0+Yml0c19zZW50KSk7XG5cbiAgc2VuZF90cmVlKHMsIHMuZHluX2x0cmVlLCBsY29kZXMtMSk7IC8qIGxpdGVyYWwgdHJlZSAqL1xuICAvL1RyYWNldigoc3RkZXJyLCBcIlxcbmxpdCB0cmVlOiBzZW50ICVsZFwiLCBzLT5iaXRzX3NlbnQpKTtcblxuICBzZW5kX3RyZWUocywgcy5keW5fZHRyZWUsIGRjb2Rlcy0xKTsgLyogZGlzdGFuY2UgdHJlZSAqL1xuICAvL1RyYWNldigoc3RkZXJyLCBcIlxcbmRpc3QgdHJlZTogc2VudCAlbGRcIiwgcy0+Yml0c19zZW50KSk7XG59XG5cblxuLyogPT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09XG4gKiBDaGVjayBpZiB0aGUgZGF0YSB0eXBlIGlzIFRFWFQgb3IgQklOQVJZLCB1c2luZyB0aGUgZm9sbG93aW5nIGFsZ29yaXRobTpcbiAqIC0gVEVYVCBpZiB0aGUgdHdvIGNvbmRpdGlvbnMgYmVsb3cgYXJlIHNhdGlzZmllZDpcbiAqICAgIGEpIFRoZXJlIGFyZSBubyBub24tcG9ydGFibGUgY29udHJvbCBjaGFyYWN0ZXJzIGJlbG9uZ2luZyB0byB0aGVcbiAqICAgICAgIFwiYmxhY2sgbGlzdFwiICgwLi42LCAxNC4uMjUsIDI4Li4zMSkuXG4gKiAgICBiKSBUaGVyZSBpcyBhdCBsZWFzdCBvbmUgcHJpbnRhYmxlIGNoYXJhY3RlciBiZWxvbmdpbmcgdG8gdGhlXG4gKiAgICAgICBcIndoaXRlIGxpc3RcIiAoOSB7VEFCfSwgMTAge0xGfSwgMTMge0NSfSwgMzIuLjI1NSkuXG4gKiAtIEJJTkFSWSBvdGhlcndpc2UuXG4gKiAtIFRoZSBmb2xsb3dpbmcgcGFydGlhbGx5LXBvcnRhYmxlIGNvbnRyb2wgY2hhcmFjdGVycyBmb3JtIGFcbiAqICAgXCJncmF5IGxpc3RcIiB0aGF0IGlzIGlnbm9yZWQgaW4gdGhpcyBkZXRlY3Rpb24gYWxnb3JpdGhtOlxuICogICAoNyB7QkVMfSwgOCB7QlN9LCAxMSB7VlR9LCAxMiB7RkZ9LCAyNiB7U1VCfSwgMjcge0VTQ30pLlxuICogSU4gYXNzZXJ0aW9uOiB0aGUgZmllbGRzIEZyZXEgb2YgZHluX2x0cmVlIGFyZSBzZXQuXG4gKi9cbmZ1bmN0aW9uIGRldGVjdF9kYXRhX3R5cGUocykge1xuICAvKiBibGFja19tYXNrIGlzIHRoZSBiaXQgbWFzayBvZiBibGFjay1saXN0ZWQgYnl0ZXNcbiAgICogc2V0IGJpdHMgMC4uNiwgMTQuLjI1LCBhbmQgMjguLjMxXG4gICAqIDB4ZjNmZmMwN2YgPSBiaW5hcnkgMTExMTAwMTExMTExMTExMTExMDAwMDAwMDExMTExMTFcbiAgICovXG4gIHZhciBibGFja19tYXNrID0gMHhmM2ZmYzA3ZjtcbiAgdmFyIG47XG5cbiAgLyogQ2hlY2sgZm9yIG5vbi10ZXh0dWFsIChcImJsYWNrLWxpc3RlZFwiKSBieXRlcy4gKi9cbiAgZm9yIChuID0gMDsgbiA8PSAzMTsgbisrLCBibGFja19tYXNrID4+Pj0gMSkge1xuICAgIGlmICgoYmxhY2tfbWFzayAmIDEpICYmIChzLmR5bl9sdHJlZVtuKjJdLyouRnJlcSovICE9PSAwKSkge1xuICAgICAgcmV0dXJuIFpfQklOQVJZO1xuICAgIH1cbiAgfVxuXG4gIC8qIENoZWNrIGZvciB0ZXh0dWFsIChcIndoaXRlLWxpc3RlZFwiKSBieXRlcy4gKi9cbiAgaWYgKHMuZHluX2x0cmVlWzkgKiAyXS8qLkZyZXEqLyAhPT0gMCB8fCBzLmR5bl9sdHJlZVsxMCAqIDJdLyouRnJlcSovICE9PSAwIHx8XG4gICAgICBzLmR5bl9sdHJlZVsxMyAqIDJdLyouRnJlcSovICE9PSAwKSB7XG4gICAgcmV0dXJuIFpfVEVYVDtcbiAgfVxuICBmb3IgKG4gPSAzMjsgbiA8IExJVEVSQUxTOyBuKyspIHtcbiAgICBpZiAocy5keW5fbHRyZWVbbiAqIDJdLyouRnJlcSovICE9PSAwKSB7XG4gICAgICByZXR1cm4gWl9URVhUO1xuICAgIH1cbiAgfVxuXG4gIC8qIFRoZXJlIGFyZSBubyBcImJsYWNrLWxpc3RlZFwiIG9yIFwid2hpdGUtbGlzdGVkXCIgYnl0ZXM6XG4gICAqIHRoaXMgc3RyZWFtIGVpdGhlciBpcyBlbXB0eSBvciBoYXMgdG9sZXJhdGVkIChcImdyYXktbGlzdGVkXCIpIGJ5dGVzIG9ubHkuXG4gICAqL1xuICByZXR1cm4gWl9CSU5BUlk7XG59XG5cblxudmFyIHN0YXRpY19pbml0X2RvbmUgPSBmYWxzZTtcblxuLyogPT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09XG4gKiBJbml0aWFsaXplIHRoZSB0cmVlIGRhdGEgc3RydWN0dXJlcyBmb3IgYSBuZXcgemxpYiBzdHJlYW0uXG4gKi9cbmZ1bmN0aW9uIF90cl9pbml0KHMpXG57XG5cbiAgaWYgKCFzdGF0aWNfaW5pdF9kb25lKSB7XG4gICAgdHJfc3RhdGljX2luaXQoKTtcbiAgICBzdGF0aWNfaW5pdF9kb25lID0gdHJ1ZTtcbiAgfVxuXG4gIHMubF9kZXNjICA9IG5ldyBUcmVlRGVzYyhzLmR5bl9sdHJlZSwgc3RhdGljX2xfZGVzYyk7XG4gIHMuZF9kZXNjICA9IG5ldyBUcmVlRGVzYyhzLmR5bl9kdHJlZSwgc3RhdGljX2RfZGVzYyk7XG4gIHMuYmxfZGVzYyA9IG5ldyBUcmVlRGVzYyhzLmJsX3RyZWUsIHN0YXRpY19ibF9kZXNjKTtcblxuICBzLmJpX2J1ZiA9IDA7XG4gIHMuYmlfdmFsaWQgPSAwO1xuXG4gIC8qIEluaXRpYWxpemUgdGhlIGZpcnN0IGJsb2NrIG9mIHRoZSBmaXJzdCBmaWxlOiAqL1xuICBpbml0X2Jsb2NrKHMpO1xufVxuXG5cbi8qID09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PVxuICogU2VuZCBhIHN0b3JlZCBibG9ja1xuICovXG5mdW5jdGlvbiBfdHJfc3RvcmVkX2Jsb2NrKHMsIGJ1Ziwgc3RvcmVkX2xlbiwgbGFzdClcbi8vRGVmbGF0ZVN0YXRlICpzO1xuLy9jaGFyZiAqYnVmOyAgICAgICAvKiBpbnB1dCBibG9jayAqL1xuLy91bGcgc3RvcmVkX2xlbjsgICAvKiBsZW5ndGggb2YgaW5wdXQgYmxvY2sgKi9cbi8vaW50IGxhc3Q7ICAgICAgICAgLyogb25lIGlmIHRoaXMgaXMgdGhlIGxhc3QgYmxvY2sgZm9yIGEgZmlsZSAqL1xue1xuICBzZW5kX2JpdHMocywgKFNUT1JFRF9CTE9DSzw8MSkrKGxhc3QgPyAxIDogMCksIDMpOyAgICAvKiBzZW5kIGJsb2NrIHR5cGUgKi9cbiAgY29weV9ibG9jayhzLCBidWYsIHN0b3JlZF9sZW4sIHRydWUpOyAvKiB3aXRoIGhlYWRlciAqL1xufVxuXG5cbi8qID09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PVxuICogU2VuZCBvbmUgZW1wdHkgc3RhdGljIGJsb2NrIHRvIGdpdmUgZW5vdWdoIGxvb2thaGVhZCBmb3IgaW5mbGF0ZS5cbiAqIFRoaXMgdGFrZXMgMTAgYml0cywgb2Ygd2hpY2ggNyBtYXkgcmVtYWluIGluIHRoZSBiaXQgYnVmZmVyLlxuICovXG5mdW5jdGlvbiBfdHJfYWxpZ24ocykge1xuICBzZW5kX2JpdHMocywgU1RBVElDX1RSRUVTPDwxLCAzKTtcbiAgc2VuZF9jb2RlKHMsIEVORF9CTE9DSywgc3RhdGljX2x0cmVlKTtcbiAgYmlfZmx1c2gocyk7XG59XG5cblxuLyogPT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09XG4gKiBEZXRlcm1pbmUgdGhlIGJlc3QgZW5jb2RpbmcgZm9yIHRoZSBjdXJyZW50IGJsb2NrOiBkeW5hbWljIHRyZWVzLCBzdGF0aWNcbiAqIHRyZWVzIG9yIHN0b3JlLCBhbmQgb3V0cHV0IHRoZSBlbmNvZGVkIGJsb2NrIHRvIHRoZSB6aXAgZmlsZS5cbiAqL1xuZnVuY3Rpb24gX3RyX2ZsdXNoX2Jsb2NrKHMsIGJ1Ziwgc3RvcmVkX2xlbiwgbGFzdClcbi8vRGVmbGF0ZVN0YXRlICpzO1xuLy9jaGFyZiAqYnVmOyAgICAgICAvKiBpbnB1dCBibG9jaywgb3IgTlVMTCBpZiB0b28gb2xkICovXG4vL3VsZyBzdG9yZWRfbGVuOyAgIC8qIGxlbmd0aCBvZiBpbnB1dCBibG9jayAqL1xuLy9pbnQgbGFzdDsgICAgICAgICAvKiBvbmUgaWYgdGhpcyBpcyB0aGUgbGFzdCBibG9jayBmb3IgYSBmaWxlICovXG57XG4gIHZhciBvcHRfbGVuYiwgc3RhdGljX2xlbmI7ICAvKiBvcHRfbGVuIGFuZCBzdGF0aWNfbGVuIGluIGJ5dGVzICovXG4gIHZhciBtYXhfYmxpbmRleCA9IDA7ICAgICAgICAvKiBpbmRleCBvZiBsYXN0IGJpdCBsZW5ndGggY29kZSBvZiBub24gemVybyBmcmVxICovXG5cbiAgLyogQnVpbGQgdGhlIEh1ZmZtYW4gdHJlZXMgdW5sZXNzIGEgc3RvcmVkIGJsb2NrIGlzIGZvcmNlZCAqL1xuICBpZiAocy5sZXZlbCA+IDApIHtcblxuICAgIC8qIENoZWNrIGlmIHRoZSBmaWxlIGlzIGJpbmFyeSBvciB0ZXh0ICovXG4gICAgaWYgKHMuc3RybS5kYXRhX3R5cGUgPT09IFpfVU5LTk9XTikge1xuICAgICAgcy5zdHJtLmRhdGFfdHlwZSA9IGRldGVjdF9kYXRhX3R5cGUocyk7XG4gICAgfVxuXG4gICAgLyogQ29uc3RydWN0IHRoZSBsaXRlcmFsIGFuZCBkaXN0YW5jZSB0cmVlcyAqL1xuICAgIGJ1aWxkX3RyZWUocywgcy5sX2Rlc2MpO1xuICAgIC8vIFRyYWNldigoc3RkZXJyLCBcIlxcbmxpdCBkYXRhOiBkeW4gJWxkLCBzdGF0ICVsZFwiLCBzLT5vcHRfbGVuLFxuICAgIC8vICAgICAgICBzLT5zdGF0aWNfbGVuKSk7XG5cbiAgICBidWlsZF90cmVlKHMsIHMuZF9kZXNjKTtcbiAgICAvLyBUcmFjZXYoKHN0ZGVyciwgXCJcXG5kaXN0IGRhdGE6IGR5biAlbGQsIHN0YXQgJWxkXCIsIHMtPm9wdF9sZW4sXG4gICAgLy8gICAgICAgIHMtPnN0YXRpY19sZW4pKTtcbiAgICAvKiBBdCB0aGlzIHBvaW50LCBvcHRfbGVuIGFuZCBzdGF0aWNfbGVuIGFyZSB0aGUgdG90YWwgYml0IGxlbmd0aHMgb2ZcbiAgICAgKiB0aGUgY29tcHJlc3NlZCBibG9jayBkYXRhLCBleGNsdWRpbmcgdGhlIHRyZWUgcmVwcmVzZW50YXRpb25zLlxuICAgICAqL1xuXG4gICAgLyogQnVpbGQgdGhlIGJpdCBsZW5ndGggdHJlZSBmb3IgdGhlIGFib3ZlIHR3byB0cmVlcywgYW5kIGdldCB0aGUgaW5kZXhcbiAgICAgKiBpbiBibF9vcmRlciBvZiB0aGUgbGFzdCBiaXQgbGVuZ3RoIGNvZGUgdG8gc2VuZC5cbiAgICAgKi9cbiAgICBtYXhfYmxpbmRleCA9IGJ1aWxkX2JsX3RyZWUocyk7XG5cbiAgICAvKiBEZXRlcm1pbmUgdGhlIGJlc3QgZW5jb2RpbmcuIENvbXB1dGUgdGhlIGJsb2NrIGxlbmd0aHMgaW4gYnl0ZXMuICovXG4gICAgb3B0X2xlbmIgPSAocy5vcHRfbGVuKzMrNykgPj4+IDM7XG4gICAgc3RhdGljX2xlbmIgPSAocy5zdGF0aWNfbGVuKzMrNykgPj4+IDM7XG5cbiAgICAvLyBUcmFjZXYoKHN0ZGVyciwgXCJcXG5vcHQgJWx1KCVsdSkgc3RhdCAlbHUoJWx1KSBzdG9yZWQgJWx1IGxpdCAldSBcIixcbiAgICAvLyAgICAgICAgb3B0X2xlbmIsIHMtPm9wdF9sZW4sIHN0YXRpY19sZW5iLCBzLT5zdGF0aWNfbGVuLCBzdG9yZWRfbGVuLFxuICAgIC8vICAgICAgICBzLT5sYXN0X2xpdCkpO1xuXG4gICAgaWYgKHN0YXRpY19sZW5iIDw9IG9wdF9sZW5iKSB7IG9wdF9sZW5iID0gc3RhdGljX2xlbmI7IH1cblxuICB9IGVsc2Uge1xuICAgIC8vIEFzc2VydChidWYgIT0gKGNoYXIqKTAsIFwibG9zdCBidWZcIik7XG4gICAgb3B0X2xlbmIgPSBzdGF0aWNfbGVuYiA9IHN0b3JlZF9sZW4gKyA1OyAvKiBmb3JjZSBhIHN0b3JlZCBibG9jayAqL1xuICB9XG5cbiAgaWYgKChzdG9yZWRfbGVuKzQgPD0gb3B0X2xlbmIpICYmIChidWYgIT09IC0xKSkge1xuICAgIC8qIDQ6IHR3byB3b3JkcyBmb3IgdGhlIGxlbmd0aHMgKi9cblxuICAgIC8qIFRoZSB0ZXN0IGJ1ZiAhPSBOVUxMIGlzIG9ubHkgbmVjZXNzYXJ5IGlmIExJVF9CVUZTSVpFID4gV1NJWkUuXG4gICAgICogT3RoZXJ3aXNlIHdlIGNhbid0IGhhdmUgcHJvY2Vzc2VkIG1vcmUgdGhhbiBXU0laRSBpbnB1dCBieXRlcyBzaW5jZVxuICAgICAqIHRoZSBsYXN0IGJsb2NrIGZsdXNoLCBiZWNhdXNlIGNvbXByZXNzaW9uIHdvdWxkIGhhdmUgYmVlblxuICAgICAqIHN1Y2Nlc3NmdWwuIElmIExJVF9CVUZTSVpFIDw9IFdTSVpFLCBpdCBpcyBuZXZlciB0b28gbGF0ZSB0b1xuICAgICAqIHRyYW5zZm9ybSBhIGJsb2NrIGludG8gYSBzdG9yZWQgYmxvY2suXG4gICAgICovXG4gICAgX3RyX3N0b3JlZF9ibG9jayhzLCBidWYsIHN0b3JlZF9sZW4sIGxhc3QpO1xuXG4gIH0gZWxzZSBpZiAocy5zdHJhdGVneSA9PT0gWl9GSVhFRCB8fCBzdGF0aWNfbGVuYiA9PT0gb3B0X2xlbmIpIHtcblxuICAgIHNlbmRfYml0cyhzLCAoU1RBVElDX1RSRUVTPDwxKSArIChsYXN0ID8gMSA6IDApLCAzKTtcbiAgICBjb21wcmVzc19ibG9jayhzLCBzdGF0aWNfbHRyZWUsIHN0YXRpY19kdHJlZSk7XG5cbiAgfSBlbHNlIHtcbiAgICBzZW5kX2JpdHMocywgKERZTl9UUkVFUzw8MSkgKyAobGFzdCA/IDEgOiAwKSwgMyk7XG4gICAgc2VuZF9hbGxfdHJlZXMocywgcy5sX2Rlc2MubWF4X2NvZGUrMSwgcy5kX2Rlc2MubWF4X2NvZGUrMSwgbWF4X2JsaW5kZXgrMSk7XG4gICAgY29tcHJlc3NfYmxvY2socywgcy5keW5fbHRyZWUsIHMuZHluX2R0cmVlKTtcbiAgfVxuICAvLyBBc3NlcnQgKHMtPmNvbXByZXNzZWRfbGVuID09IHMtPmJpdHNfc2VudCwgXCJiYWQgY29tcHJlc3NlZCBzaXplXCIpO1xuICAvKiBUaGUgYWJvdmUgY2hlY2sgaXMgbWFkZSBtb2QgMl4zMiwgZm9yIGZpbGVzIGxhcmdlciB0aGFuIDUxMiBNQlxuICAgKiBhbmQgdUxvbmcgaW1wbGVtZW50ZWQgb24gMzIgYml0cy5cbiAgICovXG4gIGluaXRfYmxvY2socyk7XG5cbiAgaWYgKGxhc3QpIHtcbiAgICBiaV93aW5kdXAocyk7XG4gIH1cbiAgLy8gVHJhY2V2KChzdGRlcnIsXCJcXG5jb21wcmxlbiAlbHUoJWx1KSBcIiwgcy0+Y29tcHJlc3NlZF9sZW4+PjMsXG4gIC8vICAgICAgIHMtPmNvbXByZXNzZWRfbGVuLTcqbGFzdCkpO1xufVxuXG4vKiA9PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT1cbiAqIFNhdmUgdGhlIG1hdGNoIGluZm8gYW5kIHRhbGx5IHRoZSBmcmVxdWVuY3kgY291bnRzLiBSZXR1cm4gdHJ1ZSBpZlxuICogdGhlIGN1cnJlbnQgYmxvY2sgbXVzdCBiZSBmbHVzaGVkLlxuICovXG5mdW5jdGlvbiBfdHJfdGFsbHkocywgZGlzdCwgbGMpXG4vLyAgICBkZWZsYXRlX3N0YXRlICpzO1xuLy8gICAgdW5zaWduZWQgZGlzdDsgIC8qIGRpc3RhbmNlIG9mIG1hdGNoZWQgc3RyaW5nICovXG4vLyAgICB1bnNpZ25lZCBsYzsgICAgLyogbWF0Y2ggbGVuZ3RoLU1JTl9NQVRDSCBvciB1bm1hdGNoZWQgY2hhciAoaWYgZGlzdD09MCkgKi9cbntcbiAgLy92YXIgb3V0X2xlbmd0aCwgaW5fbGVuZ3RoLCBkY29kZTtcblxuICBzLnBlbmRpbmdfYnVmW3MuZF9idWYgKyBzLmxhc3RfbGl0ICogMl0gICAgID0gKGRpc3QgPj4+IDgpICYgMHhmZjtcbiAgcy5wZW5kaW5nX2J1ZltzLmRfYnVmICsgcy5sYXN0X2xpdCAqIDIgKyAxXSA9IGRpc3QgJiAweGZmO1xuXG4gIHMucGVuZGluZ19idWZbcy5sX2J1ZiArIHMubGFzdF9saXRdID0gbGMgJiAweGZmO1xuICBzLmxhc3RfbGl0Kys7XG5cbiAgaWYgKGRpc3QgPT09IDApIHtcbiAgICAvKiBsYyBpcyB0aGUgdW5tYXRjaGVkIGNoYXIgKi9cbiAgICBzLmR5bl9sdHJlZVtsYyoyXS8qLkZyZXEqLysrO1xuICB9IGVsc2Uge1xuICAgIHMubWF0Y2hlcysrO1xuICAgIC8qIEhlcmUsIGxjIGlzIHRoZSBtYXRjaCBsZW5ndGggLSBNSU5fTUFUQ0ggKi9cbiAgICBkaXN0LS07ICAgICAgICAgICAgIC8qIGRpc3QgPSBtYXRjaCBkaXN0YW5jZSAtIDEgKi9cbiAgICAvL0Fzc2VydCgodXNoKWRpc3QgPCAodXNoKU1BWF9ESVNUKHMpICYmXG4gICAgLy8gICAgICAgKHVzaClsYyA8PSAodXNoKShNQVhfTUFUQ0gtTUlOX01BVENIKSAmJlxuICAgIC8vICAgICAgICh1c2gpZF9jb2RlKGRpc3QpIDwgKHVzaClEX0NPREVTLCAgXCJfdHJfdGFsbHk6IGJhZCBtYXRjaFwiKTtcblxuICAgIHMuZHluX2x0cmVlWyhfbGVuZ3RoX2NvZGVbbGNdK0xJVEVSQUxTKzEpICogMl0vKi5GcmVxKi8rKztcbiAgICBzLmR5bl9kdHJlZVtkX2NvZGUoZGlzdCkgKiAyXS8qLkZyZXEqLysrO1xuICB9XG5cbi8vICghKSBUaGlzIGJsb2NrIGlzIGRpc2FibGVkIGluIHpsaWIgZGVmYWlsdHMsXG4vLyBkb24ndCBlbmFibGUgaXQgZm9yIGJpbmFyeSBjb21wYXRpYmlsaXR5XG5cbi8vI2lmZGVmIFRSVU5DQVRFX0JMT0NLXG4vLyAgLyogVHJ5IHRvIGd1ZXNzIGlmIGl0IGlzIHByb2ZpdGFibGUgdG8gc3RvcCB0aGUgY3VycmVudCBibG9jayBoZXJlICovXG4vLyAgaWYgKChzLmxhc3RfbGl0ICYgMHgxZmZmKSA9PT0gMCAmJiBzLmxldmVsID4gMikge1xuLy8gICAgLyogQ29tcHV0ZSBhbiB1cHBlciBib3VuZCBmb3IgdGhlIGNvbXByZXNzZWQgbGVuZ3RoICovXG4vLyAgICBvdXRfbGVuZ3RoID0gcy5sYXN0X2xpdCo4O1xuLy8gICAgaW5fbGVuZ3RoID0gcy5zdHJzdGFydCAtIHMuYmxvY2tfc3RhcnQ7XG4vL1xuLy8gICAgZm9yIChkY29kZSA9IDA7IGRjb2RlIDwgRF9DT0RFUzsgZGNvZGUrKykge1xuLy8gICAgICBvdXRfbGVuZ3RoICs9IHMuZHluX2R0cmVlW2Rjb2RlKjJdLyouRnJlcSovICogKDUgKyBleHRyYV9kYml0c1tkY29kZV0pO1xuLy8gICAgfVxuLy8gICAgb3V0X2xlbmd0aCA+Pj49IDM7XG4vLyAgICAvL1RyYWNldigoc3RkZXJyLFwiXFxubGFzdF9saXQgJXUsIGluICVsZCwgb3V0IH4lbGQoJWxkJSUpIFwiLFxuLy8gICAgLy8gICAgICAgcy0+bGFzdF9saXQsIGluX2xlbmd0aCwgb3V0X2xlbmd0aCxcbi8vICAgIC8vICAgICAgIDEwMEwgLSBvdXRfbGVuZ3RoKjEwMEwvaW5fbGVuZ3RoKSk7XG4vLyAgICBpZiAocy5tYXRjaGVzIDwgKHMubGFzdF9saXQ+PjEpLyppbnQgLzIqLyAmJiBvdXRfbGVuZ3RoIDwgKGluX2xlbmd0aD4+MSkvKmludCAvMiovKSB7XG4vLyAgICAgIHJldHVybiB0cnVlO1xuLy8gICAgfVxuLy8gIH1cbi8vI2VuZGlmXG5cbiAgcmV0dXJuIChzLmxhc3RfbGl0ID09PSBzLmxpdF9idWZzaXplLTEpO1xuICAvKiBXZSBhdm9pZCBlcXVhbGl0eSB3aXRoIGxpdF9idWZzaXplIGJlY2F1c2Ugb2Ygd3JhcGFyb3VuZCBhdCA2NEtcbiAgICogb24gMTYgYml0IG1hY2hpbmVzIGFuZCBiZWNhdXNlIHN0b3JlZCBibG9ja3MgYXJlIHJlc3RyaWN0ZWQgdG9cbiAgICogNjRLLTEgYnl0ZXMuXG4gICAqL1xufVxuXG5leHBvcnRzLl90cl9pbml0ICA9IF90cl9pbml0O1xuZXhwb3J0cy5fdHJfc3RvcmVkX2Jsb2NrID0gX3RyX3N0b3JlZF9ibG9jaztcbmV4cG9ydHMuX3RyX2ZsdXNoX2Jsb2NrICA9IF90cl9mbHVzaF9ibG9jaztcbmV4cG9ydHMuX3RyX3RhbGx5ID0gX3RyX3RhbGx5O1xuZXhwb3J0cy5fdHJfYWxpZ24gPSBfdHJfYWxpZ247XG4iLCIndXNlIHN0cmljdCc7XG5cblxuZnVuY3Rpb24gWlN0cmVhbSgpIHtcbiAgLyogbmV4dCBpbnB1dCBieXRlICovXG4gIHRoaXMuaW5wdXQgPSBudWxsOyAvLyBKUyBzcGVjaWZpYywgYmVjYXVzZSB3ZSBoYXZlIG5vIHBvaW50ZXJzXG4gIHRoaXMubmV4dF9pbiA9IDA7XG4gIC8qIG51bWJlciBvZiBieXRlcyBhdmFpbGFibGUgYXQgaW5wdXQgKi9cbiAgdGhpcy5hdmFpbF9pbiA9IDA7XG4gIC8qIHRvdGFsIG51bWJlciBvZiBpbnB1dCBieXRlcyByZWFkIHNvIGZhciAqL1xuICB0aGlzLnRvdGFsX2luID0gMDtcbiAgLyogbmV4dCBvdXRwdXQgYnl0ZSBzaG91bGQgYmUgcHV0IHRoZXJlICovXG4gIHRoaXMub3V0cHV0ID0gbnVsbDsgLy8gSlMgc3BlY2lmaWMsIGJlY2F1c2Ugd2UgaGF2ZSBubyBwb2ludGVyc1xuICB0aGlzLm5leHRfb3V0ID0gMDtcbiAgLyogcmVtYWluaW5nIGZyZWUgc3BhY2UgYXQgb3V0cHV0ICovXG4gIHRoaXMuYXZhaWxfb3V0ID0gMDtcbiAgLyogdG90YWwgbnVtYmVyIG9mIGJ5dGVzIG91dHB1dCBzbyBmYXIgKi9cbiAgdGhpcy50b3RhbF9vdXQgPSAwO1xuICAvKiBsYXN0IGVycm9yIG1lc3NhZ2UsIE5VTEwgaWYgbm8gZXJyb3IgKi9cbiAgdGhpcy5tc2cgPSAnJy8qWl9OVUxMKi87XG4gIC8qIG5vdCB2aXNpYmxlIGJ5IGFwcGxpY2F0aW9ucyAqL1xuICB0aGlzLnN0YXRlID0gbnVsbDtcbiAgLyogYmVzdCBndWVzcyBhYm91dCB0aGUgZGF0YSB0eXBlOiBiaW5hcnkgb3IgdGV4dCAqL1xuICB0aGlzLmRhdGFfdHlwZSA9IDIvKlpfVU5LTk9XTiovO1xuICAvKiBhZGxlcjMyIHZhbHVlIG9mIHRoZSB1bmNvbXByZXNzZWQgZGF0YSAqL1xuICB0aGlzLmFkbGVyID0gMDtcbn1cblxubW9kdWxlLmV4cG9ydHMgPSBaU3RyZWFtO1xuIiwiLyogQ29weXJpZ2h0IEAgMjAxNSBBdGxhc3NpYW4gUHR5IEx0ZFxuICpcbiAqIExpY2Vuc2VkIHVuZGVyIHRoZSBBcGFjaGUgTGljZW5zZSwgVmVyc2lvbiAyLjAgKHRoZSBcIkxpY2Vuc2VcIik7XG4gKiB5b3UgbWF5IG5vdCB1c2UgdGhpcyBmaWxlIGV4Y2VwdCBpbiBjb21wbGlhbmNlIHdpdGggdGhlIExpY2Vuc2UuXG4gKiBZb3UgbWF5IG9idGFpbiBhIGNvcHkgb2YgdGhlIExpY2Vuc2UgYXRcbiAqXG4gKiAgICAgaHR0cDovL3d3dy5hcGFjaGUub3JnL2xpY2Vuc2VzL0xJQ0VOU0UtMi4wXG4gKlxuICogVW5sZXNzIHJlcXVpcmVkIGJ5IGFwcGxpY2FibGUgbGF3IG9yIGFncmVlZCB0byBpbiB3cml0aW5nLCBzb2Z0d2FyZVxuICogZGlzdHJpYnV0ZWQgdW5kZXIgdGhlIExpY2Vuc2UgaXMgZGlzdHJpYnV0ZWQgb24gYW4gXCJBUyBJU1wiIEJBU0lTLFxuICogV0lUSE9VVCBXQVJSQU5USUVTIE9SIENPTkRJVElPTlMgT0YgQU5ZIEtJTkQsIGVpdGhlciBleHByZXNzIG9yIGltcGxpZWQuXG4gKiBTZWUgdGhlIExpY2Vuc2UgZm9yIHRoZSBzcGVjaWZpYyBsYW5ndWFnZSBnb3Zlcm5pbmcgcGVybWlzc2lvbnMgYW5kXG4gKiBsaW1pdGF0aW9ucyB1bmRlciB0aGUgTGljZW5zZS5cbiAqL1xuXG5tb2R1bGUuZXhwb3J0cyA9IGZ1bmN0aW9uIGFycmF5RXF1YWxzKGFycmF5KSB7XG4gICAgLy8gaWYgdGhlIG90aGVyIGFycmF5IGlzIGEgZmFsc3kgdmFsdWUsIHJldHVyblxuICAgIGlmICghYXJyYXkpXG4gICAgICAgIHJldHVybiBmYWxzZTtcblxuICAgIC8vIGNvbXBhcmUgbGVuZ3RocyAtIGNhbiBzYXZlIGEgbG90IG9mIHRpbWVcbiAgICBpZiAodGhpcy5sZW5ndGggIT0gYXJyYXkubGVuZ3RoKVxuICAgICAgICByZXR1cm4gZmFsc2U7XG5cbiAgICBmb3IgKHZhciBpID0gMCwgbCA9IHRoaXMubGVuZ3RoOyBpIDwgbDsgaSsrKSB7XG4gICAgICAgIC8vIENoZWNrIGlmIHdlIGhhdmUgbmVzdGVkIGFycmF5c1xuICAgICAgICBpZiAodGhpc1tpXSBpbnN0YW5jZW9mIEFycmF5ICYmIGFycmF5W2ldIGluc3RhbmNlb2YgQXJyYXkpIHtcbiAgICAgICAgICAgIC8vIHJlY3Vyc2UgaW50byB0aGUgbmVzdGVkIGFycmF5c1xuICAgICAgICAgICAgaWYgKCFhcnJheUVxdWFscy5hcHBseSh0aGlzW2ldLCBbYXJyYXlbaV1dKSlcbiAgICAgICAgICAgICAgICByZXR1cm4gZmFsc2U7XG4gICAgICAgIH0gZWxzZSBpZiAodGhpc1tpXSAhPSBhcnJheVtpXSkge1xuICAgICAgICAgICAgLy8gV2FybmluZyAtIHR3byBkaWZmZXJlbnQgb2JqZWN0IGluc3RhbmNlcyB3aWxsIG5ldmVyIGJlIGVxdWFsOlxuICAgICAgICAgICAgLy8ge3g6MjB9ICE9IHt4OjIwfVxuICAgICAgICAgICAgcmV0dXJuIGZhbHNlO1xuICAgICAgICB9XG4gICAgfVxuICAgIHJldHVybiB0cnVlO1xufTtcblxuIiwiLyogQ29weXJpZ2h0IEAgMjAxNSBBdGxhc3NpYW4gUHR5IEx0ZFxuICpcbiAqIExpY2Vuc2VkIHVuZGVyIHRoZSBBcGFjaGUgTGljZW5zZSwgVmVyc2lvbiAyLjAgKHRoZSBcIkxpY2Vuc2VcIik7XG4gKiB5b3UgbWF5IG5vdCB1c2UgdGhpcyBmaWxlIGV4Y2VwdCBpbiBjb21wbGlhbmNlIHdpdGggdGhlIExpY2Vuc2UuXG4gKiBZb3UgbWF5IG9idGFpbiBhIGNvcHkgb2YgdGhlIExpY2Vuc2UgYXRcbiAqXG4gKiAgICAgaHR0cDovL3d3dy5hcGFjaGUub3JnL2xpY2Vuc2VzL0xJQ0VOU0UtMi4wXG4gKlxuICogVW5sZXNzIHJlcXVpcmVkIGJ5IGFwcGxpY2FibGUgbGF3IG9yIGFncmVlZCB0byBpbiB3cml0aW5nLCBzb2Z0d2FyZVxuICogZGlzdHJpYnV0ZWQgdW5kZXIgdGhlIExpY2Vuc2UgaXMgZGlzdHJpYnV0ZWQgb24gYW4gXCJBUyBJU1wiIEJBU0lTLFxuICogV0lUSE9VVCBXQVJSQU5USUVTIE9SIENPTkRJVElPTlMgT0YgQU5ZIEtJTkQsIGVpdGhlciBleHByZXNzIG9yIGltcGxpZWQuXG4gKiBTZWUgdGhlIExpY2Vuc2UgZm9yIHRoZSBzcGVjaWZpYyBsYW5ndWFnZSBnb3Zlcm5pbmcgcGVybWlzc2lvbnMgYW5kXG4gKiBsaW1pdGF0aW9ucyB1bmRlciB0aGUgTGljZW5zZS5cbiAqL1xuXG5leHBvcnRzLkludGVyb3AgPSByZXF1aXJlKCcuL2ludGVyb3AnKTtcbiIsIi8qIENvcHlyaWdodCBAIDIwMTUgQXRsYXNzaWFuIFB0eSBMdGRcbiAqXG4gKiBMaWNlbnNlZCB1bmRlciB0aGUgQXBhY2hlIExpY2Vuc2UsIFZlcnNpb24gMi4wICh0aGUgXCJMaWNlbnNlXCIpO1xuICogeW91IG1heSBub3QgdXNlIHRoaXMgZmlsZSBleGNlcHQgaW4gY29tcGxpYW5jZSB3aXRoIHRoZSBMaWNlbnNlLlxuICogWW91IG1heSBvYnRhaW4gYSBjb3B5IG9mIHRoZSBMaWNlbnNlIGF0XG4gKlxuICogICAgIGh0dHA6Ly93d3cuYXBhY2hlLm9yZy9saWNlbnNlcy9MSUNFTlNFLTIuMFxuICpcbiAqIFVubGVzcyByZXF1aXJlZCBieSBhcHBsaWNhYmxlIGxhdyBvciBhZ3JlZWQgdG8gaW4gd3JpdGluZywgc29mdHdhcmVcbiAqIGRpc3RyaWJ1dGVkIHVuZGVyIHRoZSBMaWNlbnNlIGlzIGRpc3RyaWJ1dGVkIG9uIGFuIFwiQVMgSVNcIiBCQVNJUyxcbiAqIFdJVEhPVVQgV0FSUkFOVElFUyBPUiBDT05ESVRJT05TIE9GIEFOWSBLSU5ELCBlaXRoZXIgZXhwcmVzcyBvciBpbXBsaWVkLlxuICogU2VlIHRoZSBMaWNlbnNlIGZvciB0aGUgc3BlY2lmaWMgbGFuZ3VhZ2UgZ292ZXJuaW5nIHBlcm1pc3Npb25zIGFuZFxuICogbGltaXRhdGlvbnMgdW5kZXIgdGhlIExpY2Vuc2UuXG4gKi9cblxuLyogZ2xvYmFsIFJUQ1Nlc3Npb25EZXNjcmlwdGlvbiAqL1xuLyoganNoaW50IC1XMDk3ICovXG5cInVzZSBzdHJpY3RcIjtcblxudmFyIHRyYW5zZm9ybSA9IHJlcXVpcmUoJy4vdHJhbnNmb3JtJyk7XG52YXIgYXJyYXlFcXVhbHMgPSByZXF1aXJlKCcuL2FycmF5LWVxdWFscycpO1xuXG5mdW5jdGlvbiBJbnRlcm9wKCkge1xuXG4gICAgLyoqXG4gICAgICogVGhpcyBtYXAgaG9sZHMgdGhlIG1vc3QgcmVjZW50IFVuaWZpZWQgUGxhbiBvZmZlci9hbnN3ZXIgU0RQIHRoYXQgd2FzXG4gICAgICogY29udmVydGVkIHRvIFBsYW4gQiwgd2l0aCB0aGUgU0RQIHR5cGUgKCdvZmZlcicgb3IgJ2Fuc3dlcicpIGFzIGtleXMgYW5kXG4gICAgICogdGhlIFNEUCBzdHJpbmcgYXMgdmFsdWVzLlxuICAgICAqXG4gICAgICogQHR5cGUge3t9fVxuICAgICAqL1xuICAgIHRoaXMuY2FjaGUgPSB7fTtcbn1cblxubW9kdWxlLmV4cG9ydHMgPSBJbnRlcm9wO1xuXG4vKipcbiAqIFJldHVybnMgdGhlIGluZGV4IG9mIHRoZSBmaXJzdCBtLWxpbmUgd2l0aCB0aGUgZ2l2ZW4gbWVkaWEgdHlwZSBhbmQgd2l0aCBhXG4gKiBkaXJlY3Rpb24gd2hpY2ggYWxsb3dzIHNlbmRpbmcsIGluIHRoZSBsYXN0IFVuaWZpZWQgUGxhbiBkZXNjcmlwdGlvbiB3aXRoXG4gKiB0eXBlIFwiYW5zd2VyXCIgY29udmVydGVkIHRvIFBsYW4gQi4gUmV0dXJucyB7bnVsbH0gaWYgdGhlcmUgaXMgbm8gc2F2ZWRcbiAqIGFuc3dlciwgb3IgaWYgbm9uZSBvZiBpdHMgbS1saW5lcyB3aXRoIHRoZSBnaXZlbiB0eXBlIGFsbG93IHNlbmRpbmcuXG4gKiBAcGFyYW0gdHlwZSB0aGUgbWVkaWEgdHlwZSAoXCJhdWRpb1wiIG9yIFwidmlkZW9cIikuXG4gKiBAcmV0dXJucyB7Kn1cbiAqL1xuSW50ZXJvcC5wcm90b3R5cGUuZ2V0Rmlyc3RTZW5kaW5nSW5kZXhGcm9tQW5zd2VyID0gZnVuY3Rpb24odHlwZSkge1xuICAgIGlmICghdGhpcy5jYWNoZS5hbnN3ZXIpIHtcbiAgICAgICAgcmV0dXJuIG51bGw7XG4gICAgfVxuXG4gICAgdmFyIHNlc3Npb24gPSB0cmFuc2Zvcm0ucGFyc2UodGhpcy5jYWNoZS5hbnN3ZXIpO1xuICAgIGlmIChzZXNzaW9uICYmIHNlc3Npb24ubWVkaWEgJiYgQXJyYXkuaXNBcnJheShzZXNzaW9uLm1lZGlhKSl7XG4gICAgICAgIGZvciAodmFyIGkgPSAwOyBpIDwgc2Vzc2lvbi5tZWRpYS5sZW5ndGg7IGkrKykge1xuICAgICAgICAgICAgaWYgKHNlc3Npb24ubWVkaWFbaV0udHlwZSA9PSB0eXBlICYmXG4gICAgICAgICAgICAgICAgKCFzZXNzaW9uLm1lZGlhW2ldLmRpcmVjdGlvbiAvKiBkZWZhdWx0IHRvIHNlbmRyZWN2ICovIHx8XG4gICAgICAgICAgICAgICAgICAgIHNlc3Npb24ubWVkaWFbaV0uZGlyZWN0aW9uID09PSAnc2VuZHJlY3YnIHx8XG4gICAgICAgICAgICAgICAgICAgIHNlc3Npb24ubWVkaWFbaV0uZGlyZWN0aW9uID09PSAnc2VuZG9ubHknKSl7XG4gICAgICAgICAgICAgICAgcmV0dXJuIGk7XG4gICAgICAgICAgICB9XG4gICAgICAgIH1cbiAgICB9XG5cbiAgICByZXR1cm4gbnVsbDtcbn07XG5cbi8qKlxuICogVGhpcyBtZXRob2QgdHJhbnNmb3JtcyBhIFVuaWZpZWQgUGxhbiBTRFAgdG8gYW4gZXF1aXZhbGVudCBQbGFuIEIgU0RQLiBBXG4gKiBQZWVyQ29ubmVjdGlvbiB3cmFwcGVyIHRyYW5zZm9ybXMgdGhlIFNEUCB0byBQbGFuIEIgYmVmb3JlIHBhc3NpbmcgaXQgdG8gdGhlXG4gKiBhcHBsaWNhdGlvbi5cbiAqXG4gKiBAcGFyYW0gZGVzY1xuICogQHJldHVybnMgeyp9XG4gKi9cbkludGVyb3AucHJvdG90eXBlLnRvUGxhbkIgPSBmdW5jdGlvbihkZXNjKSB7XG4gICAgdmFyIHNlbGYgPSB0aGlzO1xuICAgIC8vI3JlZ2lvbiBQcmVsaW1pbmFyeSBpbnB1dCB2YWxpZGF0aW9uLlxuXG4gICAgaWYgKHR5cGVvZiBkZXNjICE9PSAnb2JqZWN0JyB8fCBkZXNjID09PSBudWxsIHx8XG4gICAgICAgIHR5cGVvZiBkZXNjLnNkcCAhPT0gJ3N0cmluZycpIHtcbiAgICAgICAgY29uc29sZS53YXJuKCdBbiBlbXB0eSBkZXNjcmlwdGlvbiB3YXMgcGFzc2VkIGFzIGFuIGFyZ3VtZW50LicpO1xuICAgICAgICByZXR1cm4gZGVzYztcbiAgICB9XG5cbiAgICAvLyBPYmplY3RpZnkgdGhlIFNEUCBmb3IgZWFzaWVyIG1hbmlwdWxhdGlvbi5cbiAgICB2YXIgc2Vzc2lvbiA9IHRyYW5zZm9ybS5wYXJzZShkZXNjLnNkcCk7XG5cbiAgICAvLyBJZiB0aGUgU0RQIGNvbnRhaW5zIG5vIG1lZGlhLCB0aGVyZSdzIG5vdGhpbmcgdG8gdHJhbnNmb3JtLlxuICAgIGlmICh0eXBlb2Ygc2Vzc2lvbi5tZWRpYSA9PT0gJ3VuZGVmaW5lZCcgfHxcbiAgICAgICAgIUFycmF5LmlzQXJyYXkoc2Vzc2lvbi5tZWRpYSkgfHwgc2Vzc2lvbi5tZWRpYS5sZW5ndGggPT09IDApIHtcbiAgICAgICAgY29uc29sZS53YXJuKCdUaGUgZGVzY3JpcHRpb24gaGFzIG5vIG1lZGlhLicpO1xuICAgICAgICByZXR1cm4gZGVzYztcbiAgICB9XG5cbiAgICAvLyBUcnkgc29tZSBoZXVyaXN0aWNzIHRvIFwibWFrZSBzdXJlXCIgdGhpcyBpcyBhIFVuaWZpZWQgUGxhbiBTRFAuIFBsYW4gQlxuICAgIC8vIFNEUCBoYXMgYSB2aWRlbywgYW4gYXVkaW8gYW5kIGEgZGF0YSBcImNoYW5uZWxcIiBhdCBtb3N0LlxuICAgIGlmIChzZXNzaW9uLm1lZGlhLmxlbmd0aCA8PSAzICYmIHNlc3Npb24ubWVkaWEuZXZlcnkoZnVuY3Rpb24obSkge1xuICAgICAgICAgICAgcmV0dXJuIFsndmlkZW8nLCAnYXVkaW8nLCAnZGF0YSddLmluZGV4T2YobS5taWQpICE9PSAtMTtcbiAgICAgICAgfSkpIHtcbiAgICAgICAgY29uc29sZS53YXJuKCdUaGlzIGRlc2NyaXB0aW9uIGRvZXMgbm90IGxvb2sgbGlrZSBVbmlmaWVkIFBsYW4uJyk7XG4gICAgICAgIHJldHVybiBkZXNjO1xuICAgIH1cblxuICAgIC8vI2VuZHJlZ2lvblxuXG4gICAgLy8gSEFDSyBodHRwczovL2J1Z3ppbGxhLm1vemlsbGEub3JnL3Nob3dfYnVnLmNnaT9pZD0xMTEzNDQzXG4gICAgdmFyIHNkcCA9IGRlc2Muc2RwO1xuICAgIHZhciByZXdyaXRlID0gZmFsc2U7XG4gICAgZm9yICh2YXIgaSA9IDA7IGkgPCBzZXNzaW9uLm1lZGlhLmxlbmd0aDsgaSsrKSB7XG4gICAgICAgIHZhciB1TGluZSA9IHNlc3Npb24ubWVkaWFbaV07XG4gICAgICAgIHVMaW5lLnJ0cC5mb3JFYWNoKGZ1bmN0aW9uKHJ0cCkge1xuICAgICAgICAgICAgaWYgKHJ0cC5jb2RlYyA9PT0gJ05VTEwnKVxuICAgICAgICAgICAge1xuICAgICAgICAgICAgICAgIHJld3JpdGUgPSB0cnVlO1xuICAgICAgICAgICAgICAgIHZhciBvZmZlciA9IHRyYW5zZm9ybS5wYXJzZShzZWxmLmNhY2hlWydvZmZlciddKTtcbiAgICAgICAgICAgICAgICBydHAuY29kZWMgPSBvZmZlci5tZWRpYVtpXS5ydHBbMF0uY29kZWM7XG4gICAgICAgICAgICB9XG4gICAgICAgIH0pO1xuICAgIH07XG4gICAgaWYgKHJld3JpdGUpIHtcbiAgICAgICAgc2RwID0gdHJhbnNmb3JtLndyaXRlKHNlc3Npb24pO1xuICAgIH1cblxuICAgIC8vIFVuaWZpZWQgUGxhbiBTRFAgaXMgb3VyIFwicHJlY2lvdXNcIi4gQ2FjaGUgaXQgZm9yIGxhdGVyIHVzZSBpbiB0aGUgUGxhbiBCXG4gICAgLy8gLT4gVW5pZmllZCBQbGFuIHRyYW5zZm9ybWF0aW9uLlxuICAgIHRoaXMuY2FjaGVbZGVzYy50eXBlXSA9IHNkcDtcblxuICAgIC8vI3JlZ2lvbiBDb252ZXJ0IGZyb20gVW5pZmllZCBQbGFuIHRvIFBsYW4gQi5cblxuICAgIC8vIFdlIHJlYnVpbGQgdGhlIHNlc3Npb24ubWVkaWEgYXJyYXkuXG4gICAgdmFyIG1lZGlhID0gc2Vzc2lvbi5tZWRpYTtcbiAgICBzZXNzaW9uLm1lZGlhID0gW107XG5cbiAgICAvLyBBc3NvY2lhdGl2ZSBhcnJheSB0aGF0IG1hcHMgY2hhbm5lbCB0eXBlcyB0byBjaGFubmVsIG9iamVjdHMgZm9yIGZhc3RcbiAgICAvLyBhY2Nlc3MgdG8gY2hhbm5lbCBvYmplY3RzIGJ5IHRoZWlyIHR5cGUsIGUuZy4gdHlwZTJibFsnYXVkaW8nXS0+Y2hhbm5lbFxuICAgIC8vIG9iai5cbiAgICB2YXIgdHlwZTJibCA9IHt9O1xuXG4gICAgLy8gVXNlZCB0byBidWlsZCB0aGUgZ3JvdXA6QlVORExFIHZhbHVlIGFmdGVyIHRoZSBjaGFubmVscyBjb25zdHJ1Y3Rpb25cbiAgICAvLyBsb29wLlxuICAgIHZhciB0eXBlcyA9IFtdO1xuXG4gICAgLy8gSW1wbG9kZSB0aGUgVW5pZmllZCBQbGFuIG0tbGluZXMvdHJhY2tzIGludG8gUGxhbiBCIGNoYW5uZWxzLlxuICAgIG1lZGlhLmZvckVhY2goZnVuY3Rpb24odUxpbmUpIHtcblxuICAgICAgICAvLyBydGNwLW11eCBpcyByZXF1aXJlZCBpbiB0aGUgUGxhbiBCIFNEUC5cbiAgICAgICAgaWYgKCh0eXBlb2YgdUxpbmUucnRjcE11eCAhPT0gJ3N0cmluZycgfHxcbiAgICAgICAgICAgIHVMaW5lLnJ0Y3BNdXggIT09ICdydGNwLW11eCcpICYmXG4gICAgICAgICAgICB1TGluZS5kaXJlY3Rpb24gIT09ICdpbmFjdGl2ZScpIHtcbiAgICAgICAgICAgIHRocm93IG5ldyBFcnJvcignQ2Fubm90IGNvbnZlcnQgdG8gUGxhbiBCIGJlY2F1c2UgbS1saW5lcyAnICtcbiAgICAgICAgICAgICAgICAnd2l0aG91dCB0aGUgcnRjcC1tdXggYXR0cmlidXRlIHdlcmUgZm91bmQuJyk7XG4gICAgICAgIH1cblxuICAgICAgICBpZiAodUxpbmUudHlwZSA9PT0gJ2FwcGxpY2F0aW9uJykge1xuICAgICAgICAgICAgc2Vzc2lvbi5tZWRpYS5wdXNoKHVMaW5lKTtcbiAgICAgICAgICAgIHR5cGVzLnB1c2godUxpbmUubWlkKTtcbiAgICAgICAgICAgIHJldHVybjtcbiAgICAgICAgfVxuXG4gICAgICAgIC8vIElmIHdlIGRvbid0IGhhdmUgYSBjaGFubmVsIGZvciB0aGlzIHVMaW5lLnR5cGUsIHRoZW4gdXNlIHRoaXNcbiAgICAgICAgLy8gdUxpbmUgYXMgdGhlIGNoYW5uZWwgYmFzaXMuXG4gICAgICAgIGlmICh0eXBlb2YgdHlwZTJibFt1TGluZS50eXBlXSA9PT0gJ3VuZGVmaW5lZCcpIHtcbiAgICAgICAgICAgIHR5cGUyYmxbdUxpbmUudHlwZV0gPSB1TGluZTtcbiAgICAgICAgfVxuXG4gICAgICAgIC8vIEFkZCBzb3VyY2VzIHRvIHRoZSBjaGFubmVsIGFuZCBoYW5kbGUgYT1tc2lkLlxuICAgICAgICBpZiAodHlwZW9mIHVMaW5lLnNvdXJjZXMgPT09ICdvYmplY3QnKSB7XG4gICAgICAgICAgICBPYmplY3Qua2V5cyh1TGluZS5zb3VyY2VzKS5mb3JFYWNoKGZ1bmN0aW9uKHNzcmMpIHtcbiAgICAgICAgICAgICAgICBpZiAodHlwZW9mIHR5cGUyYmxbdUxpbmUudHlwZV0uc291cmNlcyAhPT0gJ29iamVjdCcpXG4gICAgICAgICAgICAgICAgICAgIHR5cGUyYmxbdUxpbmUudHlwZV0uc291cmNlcyA9IHt9O1xuXG4gICAgICAgICAgICAgICAgLy8gQXNzaWduIHRoZSBzb3VyY2VzIHRvIHRoZSBjaGFubmVsLlxuICAgICAgICAgICAgICAgIHR5cGUyYmxbdUxpbmUudHlwZV0uc291cmNlc1tzc3JjXSA9XG4gICAgICAgICAgICAgICAgICAgIHVMaW5lLnNvdXJjZXNbc3NyY107XG5cbiAgICAgICAgICAgICAgICBpZiAodHlwZW9mIHVMaW5lLm1zaWQgIT09ICd1bmRlZmluZWQnKSB7XG4gICAgICAgICAgICAgICAgICAgIC8vIEluIFBsYW4gQiB0aGUgbXNpZCBpcyBhbiBTU1JDIGF0dHJpYnV0ZS4gQWxzbywgd2UgZG9uJ3RcbiAgICAgICAgICAgICAgICAgICAgLy8gY2FyZSBhYm91dCB0aGUgb2Jzb2xldGUgbGFiZWwgYW5kIG1zbGFiZWwgYXR0cmlidXRlcy5cbiAgICAgICAgICAgICAgICAgICAgLy9cbiAgICAgICAgICAgICAgICAgICAgLy8gTm90ZSB0aGF0IGl0IGlzIG5vdCBndWFyYW50ZWVkIHRoYXQgdGhlIHVMaW5lIHdpbGxcbiAgICAgICAgICAgICAgICAgICAgLy8gaGF2ZSBhbiBtc2lkLiByZWN2b25seSBjaGFubmVscyBpbiBwYXJ0aWN1bGFyIGRvbid0IGhhdmVcbiAgICAgICAgICAgICAgICAgICAgLy8gb25lLlxuICAgICAgICAgICAgICAgICAgICB0eXBlMmJsW3VMaW5lLnR5cGVdLnNvdXJjZXNbc3NyY10ubXNpZCA9XG4gICAgICAgICAgICAgICAgICAgICAgICB1TGluZS5tc2lkO1xuICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICAvLyBOT1RFIHNzcmNzIGluIHNzcmMgZ3JvdXBzIHdpbGwgc2hhcmUgbXNpZHMsIGFzXG4gICAgICAgICAgICAgICAgLy8gZHJhZnQtdWJlcnRpLXJ0Y3dlYi1wbGFuLTAwIG1hbmRhdGVzLlxuICAgICAgICAgICAgfSk7XG4gICAgICAgIH1cblxuICAgICAgICAvLyBBZGQgc3NyYyBncm91cHMgdG8gdGhlIGNoYW5uZWwuXG4gICAgICAgIGlmICh0eXBlb2YgdUxpbmUuc3NyY0dyb3VwcyAhPT0gJ3VuZGVmaW5lZCcgJiZcbiAgICAgICAgICAgICAgICBBcnJheS5pc0FycmF5KHVMaW5lLnNzcmNHcm91cHMpKSB7XG5cbiAgICAgICAgICAgIC8vIENyZWF0ZSB0aGUgc3NyY0dyb3VwcyBhcnJheSwgaWYgaXQncyBub3QgZGVmaW5lZC5cbiAgICAgICAgICAgIGlmICh0eXBlb2YgdHlwZTJibFt1TGluZS50eXBlXS5zc3JjR3JvdXBzID09PSAndW5kZWZpbmVkJyB8fFxuICAgICAgICAgICAgICAgICAgICAhQXJyYXkuaXNBcnJheSh0eXBlMmJsW3VMaW5lLnR5cGVdLnNzcmNHcm91cHMpKSB7XG4gICAgICAgICAgICAgICAgdHlwZTJibFt1TGluZS50eXBlXS5zc3JjR3JvdXBzID0gW107XG4gICAgICAgICAgICB9XG5cbiAgICAgICAgICAgIHR5cGUyYmxbdUxpbmUudHlwZV0uc3NyY0dyb3VwcyA9XG4gICAgICAgICAgICAgICAgdHlwZTJibFt1TGluZS50eXBlXS5zc3JjR3JvdXBzLmNvbmNhdChcbiAgICAgICAgICAgICAgICAgICAgdUxpbmUuc3NyY0dyb3Vwcyk7XG4gICAgICAgIH1cblxuICAgICAgICBpZiAodHlwZTJibFt1TGluZS50eXBlXSA9PT0gdUxpbmUpIHtcbiAgICAgICAgICAgIC8vIENvcHkgSUNFIHJlbGF0ZWQgc3R1ZmYgZnJvbSB0aGUgcHJpbmNpcGFsIG1lZGlhIGxpbmUuXG4gICAgICAgICAgICB1TGluZS5jYW5kaWRhdGVzID0gbWVkaWFbMF0uY2FuZGlkYXRlcztcbiAgICAgICAgICAgIHVMaW5lLmljZVVmcmFnID0gbWVkaWFbMF0uaWNlVWZyYWc7XG4gICAgICAgICAgICB1TGluZS5pY2VQd2QgPSBtZWRpYVswXS5pY2VQd2Q7XG4gICAgICAgICAgICB1TGluZS5maW5nZXJwcmludCA9IG1lZGlhWzBdLmZpbmdlcnByaW50O1xuXG4gICAgICAgICAgICAvLyBQbGFuIEIgbWlkcyBhcmUgaW4gWydhdWRpbycsICd2aWRlbycsICdkYXRhJ11cbiAgICAgICAgICAgIHVMaW5lLm1pZCA9IHVMaW5lLnR5cGU7XG5cbiAgICAgICAgICAgIC8vIFBsYW4gQiBkb2Vzbid0IHN1cHBvcnQvbmVlZCB0aGUgYnVuZGxlLW9ubHkgYXR0cmlidXRlLlxuICAgICAgICAgICAgZGVsZXRlIHVMaW5lLmJ1bmRsZU9ubHk7XG5cbiAgICAgICAgICAgIC8vIEluIFBsYW4gQiB0aGUgbXNpZCBpcyBhbiBTU1JDIGF0dHJpYnV0ZS5cbiAgICAgICAgICAgIGRlbGV0ZSB1TGluZS5tc2lkO1xuXG4gICAgICAgICAgICAvLyBVc2VkIHRvIGJ1aWxkIHRoZSBncm91cDpCVU5ETEUgdmFsdWUgYWZ0ZXIgdGhpcyBsb29wLlxuICAgICAgICAgICAgdHlwZXMucHVzaCh1TGluZS50eXBlKTtcblxuICAgICAgICAgICAgLy8gQWRkIHRoZSBjaGFubmVsIHRvIHRoZSBuZXcgbWVkaWEgYXJyYXkuXG4gICAgICAgICAgICBzZXNzaW9uLm1lZGlhLnB1c2godUxpbmUpO1xuICAgICAgICB9XG4gICAgfSk7XG5cbiAgICAvLyBXZSByZWdlbmVyYXRlIHRoZSBCVU5ETEUgZ3JvdXAgd2l0aCB0aGUgbmV3IG1pZHMuXG4gICAgc2Vzc2lvbi5ncm91cHMuc29tZShmdW5jdGlvbihncm91cCkge1xuICAgICAgICBpZiAoZ3JvdXAudHlwZSA9PT0gJ0JVTkRMRScpIHtcbiAgICAgICAgICAgIGdyb3VwLm1pZHMgPSB0eXBlcy5qb2luKCcgJyk7XG4gICAgICAgICAgICByZXR1cm4gdHJ1ZTtcbiAgICAgICAgfVxuICAgIH0pO1xuXG4gICAgLy8gbXNpZCBzZW1hbnRpY1xuICAgIHNlc3Npb24ubXNpZFNlbWFudGljID0ge1xuICAgICAgICBzZW1hbnRpYzogJ1dNUycsXG4gICAgICAgIHRva2VuOiAnKidcbiAgICB9O1xuXG4gICAgdmFyIHJlc1N0ciA9IHRyYW5zZm9ybS53cml0ZShzZXNzaW9uKTtcblxuICAgIHJldHVybiBuZXcgUlRDU2Vzc2lvbkRlc2NyaXB0aW9uKHtcbiAgICAgICAgdHlwZTogZGVzYy50eXBlLFxuICAgICAgICBzZHA6IHJlc1N0clxuICAgIH0pO1xuXG4gICAgLy8jZW5kcmVnaW9uXG59O1xuXG4vKipcbiAqIFRoaXMgbWV0aG9kIHRyYW5zZm9ybXMgYSBQbGFuIEIgU0RQIHRvIGFuIGVxdWl2YWxlbnQgVW5pZmllZCBQbGFuIFNEUC4gQVxuICogUGVlckNvbm5lY3Rpb24gd3JhcHBlciB0cmFuc2Zvcm1zIHRoZSBTRFAgdG8gVW5pZmllZCBQbGFuIGJlZm9yZSBwYXNzaW5nIGl0XG4gKiB0byBGRi5cbiAqXG4gKiBAcGFyYW0gZGVzY1xuICogQHJldHVybnMgeyp9XG4gKi9cbkludGVyb3AucHJvdG90eXBlLnRvVW5pZmllZFBsYW4gPSBmdW5jdGlvbihkZXNjKSB7XG4gICAgdmFyIHNlbGYgPSB0aGlzO1xuICAgIC8vI3JlZ2lvbiBQcmVsaW1pbmFyeSBpbnB1dCB2YWxpZGF0aW9uLlxuXG4gICAgaWYgKHR5cGVvZiBkZXNjICE9PSAnb2JqZWN0JyB8fCBkZXNjID09PSBudWxsIHx8XG4gICAgICAgIHR5cGVvZiBkZXNjLnNkcCAhPT0gJ3N0cmluZycpIHtcbiAgICAgICAgY29uc29sZS53YXJuKCdBbiBlbXB0eSBkZXNjcmlwdGlvbiB3YXMgcGFzc2VkIGFzIGFuIGFyZ3VtZW50LicpO1xuICAgICAgICByZXR1cm4gZGVzYztcbiAgICB9XG5cbiAgICB2YXIgc2Vzc2lvbiA9IHRyYW5zZm9ybS5wYXJzZShkZXNjLnNkcCk7XG5cbiAgICAvLyBJZiB0aGUgU0RQIGNvbnRhaW5zIG5vIG1lZGlhLCB0aGVyZSdzIG5vdGhpbmcgdG8gdHJhbnNmb3JtLlxuICAgIGlmICh0eXBlb2Ygc2Vzc2lvbi5tZWRpYSA9PT0gJ3VuZGVmaW5lZCcgfHxcbiAgICAgICAgIUFycmF5LmlzQXJyYXkoc2Vzc2lvbi5tZWRpYSkgfHwgc2Vzc2lvbi5tZWRpYS5sZW5ndGggPT09IDApIHtcbiAgICAgICAgY29uc29sZS53YXJuKCdUaGUgZGVzY3JpcHRpb24gaGFzIG5vIG1lZGlhLicpO1xuICAgICAgICByZXR1cm4gZGVzYztcbiAgICB9XG5cbiAgICAvLyBUcnkgc29tZSBoZXVyaXN0aWNzIHRvIFwibWFrZSBzdXJlXCIgdGhpcyBpcyBhIFBsYW4gQiBTRFAuIFBsYW4gQiBTRFAgaGFzXG4gICAgLy8gYSB2aWRlbywgYW4gYXVkaW8gYW5kIGEgZGF0YSBcImNoYW5uZWxcIiBhdCBtb3N0LlxuICAgIGlmIChzZXNzaW9uLm1lZGlhLmxlbmd0aCA+IDMgfHwgIXNlc3Npb24ubWVkaWEuZXZlcnkoZnVuY3Rpb24obSkge1xuICAgICAgICAgICAgcmV0dXJuIFsndmlkZW8nLCAnYXVkaW8nLCAnZGF0YSddLmluZGV4T2YobS5taWQpICE9PSAtMTtcbiAgICAgICAgfSkpIHtcbiAgICAgICAgY29uc29sZS53YXJuKCdUaGlzIGRlc2NyaXB0aW9uIGRvZXMgbm90IGxvb2sgbGlrZSBQbGFuIEIuJyk7XG4gICAgICAgIHJldHVybiBkZXNjO1xuICAgIH1cblxuICAgIC8vIE1ha2Ugc3VyZSB0aGlzIFBsYW4gQiBTRFAgY2FuIGJlIGNvbnZlcnRlZCB0byBhIFVuaWZpZWQgUGxhbiBTRFAuXG4gICAgdmFyIG1pZHMgPSBbXTtcbiAgICBzZXNzaW9uLm1lZGlhLmZvckVhY2goZnVuY3Rpb24obSkge1xuICAgICAgICBtaWRzLnB1c2gobS5taWQpO1xuICAgIH0pO1xuXG4gICAgdmFyIGhhc0J1bmRsZSA9IGZhbHNlO1xuICAgIGlmICh0eXBlb2Ygc2Vzc2lvbi5ncm91cHMgIT09ICd1bmRlZmluZWQnICYmXG4gICAgICAgIEFycmF5LmlzQXJyYXkoc2Vzc2lvbi5ncm91cHMpKSB7XG4gICAgICAgIGhhc0J1bmRsZSA9IHNlc3Npb24uZ3JvdXBzLmV2ZXJ5KGZ1bmN0aW9uKGcpIHtcbiAgICAgICAgICAgIHJldHVybiBnLnR5cGUgIT09ICdCVU5ETEUnIHx8XG4gICAgICAgICAgICAgICAgYXJyYXlFcXVhbHMuYXBwbHkoZy5taWRzLnNvcnQoKSwgW21pZHMuc29ydCgpXSk7XG4gICAgICAgIH0pO1xuICAgIH1cblxuICAgIGlmICghaGFzQnVuZGxlKSB7XG4gICAgICAgIHRocm93IG5ldyBFcnJvcihcIkNhbm5vdCBjb252ZXJ0IHRvIFVuaWZpZWQgUGxhbiBiZWNhdXNlIG0tbGluZXMgdGhhdFwiICtcbiAgICAgICAgICAgIFwiIGFyZSBub3QgYnVuZGxlZCB3ZXJlIGZvdW5kLlwiKTtcbiAgICB9XG5cbiAgICAvLyNlbmRyZWdpb25cblxuXG4gICAgLy8jcmVnaW9uIENvbnZlcnQgZnJvbSBQbGFuIEIgdG8gVW5pZmllZCBQbGFuLlxuXG4gICAgLy8gVW5mb3J0dW5hdGVseSwgYSBQbGFuIEIgb2ZmZXIvYW5zd2VyIGRvZXNuJ3QgaGF2ZSBlbm91Z2ggaW5mb3JtYXRpb24gdG9cbiAgICAvLyByZWJ1aWxkIGFuIGVxdWl2YWxlbnQgVW5pZmllZCBQbGFuIG9mZmVyL2Fuc3dlci5cbiAgICAvL1xuICAgIC8vIEZvciBleGFtcGxlLCBpZiB0aGlzIGlzIGEgbG9jYWwgYW5zd2VyIChpbiBVbmlmaWVkIFBsYW4gc3R5bGUpIHRoYXQgd2VcbiAgICAvLyBjb252ZXJ0IHRvIFBsYW4gQiBwcmlvciB0byBoYW5kaW5nIGl0IG92ZXIgdG8gdGhlIGFwcGxpY2F0aW9uICh0aGVcbiAgICAvLyBQZWVyQ29ubmVjdGlvbiB3cmFwcGVyIGNhbGxlZCB1cywgZm9yIGluc3RhbmNlLCBhZnRlciBhIHN1Y2Nlc3NmdWxcbiAgICAvLyBjcmVhdGVBbnN3ZXIpLCB3ZSB3YW50IHRvIHJlbWVtYmVyIHRoZSBtLWxpbmUgYXQgd2hpY2ggd2UndmUgc2VlbiB0aGVcbiAgICAvLyAobG9jYWwpIFNTUkMuIFRoYXQncyBiZWNhdXNlIHdoZW4gdGhlIGFwcGxpY2F0aW9uIHdhbnRzIHRvIGRvIGNhbGwgdGhlXG4gICAgLy8gU0xEIG1ldGhvZCwgZm9yY2luZyB1cyB0byBkbyB0aGUgaW52ZXJzZSB0cmFuc2Zvcm1hdGlvbiAoZnJvbSBQbGFuIEIgdG9cbiAgICAvLyBVbmlmaWVkIFBsYW4pLCB3ZSBuZWVkIHRvIGtub3cgdG8gd2hpY2ggbS1saW5lIHRvIGFzc2lnbiB0aGUgKGxvY2FsKVxuICAgIC8vIFNTUkMuIFdlIGFsc28gbmVlZCB0byBrbm93IGFsbCB0aGUgb3RoZXIgbS1saW5lcyB0aGF0IHRoZSBvcmlnaW5hbFxuICAgIC8vIGFuc3dlciBoYWQgYW5kIGluY2x1ZGUgdGhlbSBpbiB0aGUgdHJhbnNmb3JtZWQgYW5zd2VyIGFzIHdlbGwuXG4gICAgLy9cbiAgICAvLyBBbm90aGVyIGV4YW1wbGUgaXMgaWYgdGhpcyBpcyBhIHJlbW90ZSBvZmZlciB0aGF0IHdlIGNvbnZlcnQgdG8gUGxhbiBCXG4gICAgLy8gcHJpb3IgdG8gZ2l2aW5nIGl0IHRvIHRoZSBhcHBsaWNhdGlvbiwgd2Ugd2FudCB0byByZW1lbWJlciB0aGUgbWlkIGF0XG4gICAgLy8gd2hpY2ggd2UndmUgc2VlbiB0aGUgKHJlbW90ZSkgU1NSQy5cbiAgICAvL1xuICAgIC8vIEluIHRoZSBpdGVyYXRpb24gdGhhdCBmb2xsb3dzLCB3ZSB1c2UgdGhlIGNhY2hlZCBVbmlmaWVkIFBsYW4gKGlmIGl0XG4gICAgLy8gZXhpc3RzKSB0byBhc3NpZ24gbWlkcyB0byBzc3Jjcy5cblxuICAgIHZhciBjYWNoZWQ7XG4gICAgaWYgKHR5cGVvZiB0aGlzLmNhY2hlW2Rlc2MudHlwZV0gIT09ICd1bmRlZmluZWQnKSB7XG4gICAgICAgIGNhY2hlZCA9IHRyYW5zZm9ybS5wYXJzZSh0aGlzLmNhY2hlW2Rlc2MudHlwZV0pO1xuICAgIH1cblxuICAgIHZhciByZWN2b25seVNzcmNzID0ge1xuICAgICAgICBhdWRpbzoge30sXG4gICAgICAgIHZpZGVvOiB7fVxuICAgIH07XG5cbiAgICAvLyBBIGhlbHBlciBtYXAgdGhhdCBzZW5kcyBtaWRzIHRvIG0tbGluZSBvYmplY3RzLiBXZSB1c2UgaXQgbGF0ZXIgdG9cbiAgICAvLyByZWJ1aWxkIHRoZSBVbmlmaWVkIFBsYW4gc3R5bGUgc2Vzc2lvbi5tZWRpYSBhcnJheS5cbiAgICB2YXIgbWlkMnVsID0ge307XG4gICAgc2Vzc2lvbi5tZWRpYS5mb3JFYWNoKGZ1bmN0aW9uKGJMaW5lKSB7XG4gICAgICAgIGlmICgodHlwZW9mIGJMaW5lLnJ0Y3BNdXggIT09ICdzdHJpbmcnIHx8XG4gICAgICAgICAgICBiTGluZS5ydGNwTXV4ICE9PSAncnRjcC1tdXgnKSAmJlxuICAgICAgICAgICAgYkxpbmUuZGlyZWN0aW9uICE9PSAnaW5hY3RpdmUnKSB7XG4gICAgICAgICAgICB0aHJvdyBuZXcgRXJyb3IoXCJDYW5ub3QgY29udmVydCB0byBVbmlmaWVkIFBsYW4gYmVjYXVzZSBtLWxpbmVzIFwiICtcbiAgICAgICAgICAgICAgICBcIndpdGhvdXQgdGhlIHJ0Y3AtbXV4IGF0dHJpYnV0ZSB3ZXJlIGZvdW5kLlwiKTtcbiAgICAgICAgfVxuXG4gICAgICAgIGlmIChiTGluZS50eXBlID09PSAnYXBwbGljYXRpb24nKSB7XG4gICAgICAgICAgICBtaWQydWxbYkxpbmUubWlkXSA9IGJMaW5lO1xuICAgICAgICAgICAgcmV0dXJuO1xuICAgICAgICB9XG5cbiAgICAgICAgLy8gV2l0aCBydGNwLW11eCBhbmQgYnVuZGxlIGFsbCB0aGUgY2hhbm5lbHMgc2hvdWxkIGhhdmUgdGhlIHNhbWUgSUNFXG4gICAgICAgIC8vIHN0dWZmLlxuICAgICAgICB2YXIgc291cmNlcyA9IGJMaW5lLnNvdXJjZXM7XG4gICAgICAgIHZhciBzc3JjR3JvdXBzID0gYkxpbmUuc3NyY0dyb3VwcztcbiAgICAgICAgdmFyIGNhbmRpZGF0ZXMgPSBiTGluZS5jYW5kaWRhdGVzO1xuICAgICAgICB2YXIgaWNlVWZyYWcgPSBiTGluZS5pY2VVZnJhZztcbiAgICAgICAgdmFyIGljZVB3ZCA9IGJMaW5lLmljZVB3ZDtcbiAgICAgICAgdmFyIGZpbmdlcnByaW50ID0gYkxpbmUuZmluZ2VycHJpbnQ7XG4gICAgICAgIHZhciBwb3J0ID0gYkxpbmUucG9ydDtcblxuICAgICAgICAvLyBXZSdsbCB1c2UgdGhlIFwiYkxpbmVcIiBvYmplY3QgYXMgYSBwcm90b3R5cGUgZm9yIGVhY2ggbmV3IFwibUxpbmVcIlxuICAgICAgICAvLyB0aGF0IHdlIGNyZWF0ZSwgYnV0IGZpcnN0IHdlIG5lZWQgdG8gY2xlYW4gaXQgdXAgYSBiaXQuXG4gICAgICAgIGRlbGV0ZSBiTGluZS5zb3VyY2VzO1xuICAgICAgICBkZWxldGUgYkxpbmUuc3NyY0dyb3VwcztcbiAgICAgICAgZGVsZXRlIGJMaW5lLmNhbmRpZGF0ZXM7XG4gICAgICAgIGRlbGV0ZSBiTGluZS5pY2VVZnJhZztcbiAgICAgICAgZGVsZXRlIGJMaW5lLmljZVB3ZDtcbiAgICAgICAgZGVsZXRlIGJMaW5lLmZpbmdlcnByaW50O1xuICAgICAgICBkZWxldGUgYkxpbmUucG9ydDtcbiAgICAgICAgZGVsZXRlIGJMaW5lLm1pZDtcblxuICAgICAgICAvLyBpbnZlcnRlZCBzc3JjIGdyb3VwIG1hcFxuICAgICAgICB2YXIgc3NyYzJncm91cCA9IHt9O1xuICAgICAgICBpZiAodHlwZW9mIHNzcmNHcm91cHMgIT09ICd1bmRlZmluZWQnICYmIEFycmF5LmlzQXJyYXkoc3NyY0dyb3VwcykpIHtcbiAgICAgICAgICAgIHNzcmNHcm91cHMuZm9yRWFjaChmdW5jdGlvbiAoc3NyY0dyb3VwKSB7XG5cbiAgICAgICAgICAgICAgICAvLyBUT0RPKGdwKSBmaW5kIG91dCBob3cgdG8gcmVjZWl2ZSBzaW11bGNhc3Qgd2l0aCBGRi4gRm9yIHRoZVxuICAgICAgICAgICAgICAgIC8vIHRpbWUgYmVpbmcsIGhpZGUgaXQuXG4gICAgICAgICAgICAgICAgaWYgKHNzcmNHcm91cC5zZW1hbnRpY3MgPT09ICdTSU0nKSB7XG4gICAgICAgICAgICAgICAgICAgIHJldHVybjtcbiAgICAgICAgICAgICAgICB9XG5cbiAgICAgICAgICAgICAgICAvLyBYWFggVGhpcyBtaWdodCBicmFrZSBpZiBhbiBTU1JDIGlzIGluIG1vcmUgdGhhbiBvbmUgZ3JvdXBcbiAgICAgICAgICAgICAgICAvLyBmb3Igc29tZSByZWFzb24uXG4gICAgICAgICAgICAgICAgaWYgKHR5cGVvZiBzc3JjR3JvdXAuc3NyY3MgIT09ICd1bmRlZmluZWQnICYmXG4gICAgICAgICAgICAgICAgICAgIEFycmF5LmlzQXJyYXkoc3NyY0dyb3VwLnNzcmNzKSkge1xuICAgICAgICAgICAgICAgICAgICBzc3JjR3JvdXAuc3NyY3MuZm9yRWFjaChmdW5jdGlvbiAoc3NyYykge1xuICAgICAgICAgICAgICAgICAgICAgICAgaWYgKHR5cGVvZiBzc3JjMmdyb3VwW3NzcmNdID09PSAndW5kZWZpbmVkJykge1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgIHNzcmMyZ3JvdXBbc3NyY10gPSBbXTtcbiAgICAgICAgICAgICAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgICAgICAgICAgICAgc3NyYzJncm91cFtzc3JjXS5wdXNoKHNzcmNHcm91cCk7XG4gICAgICAgICAgICAgICAgICAgIH0pO1xuICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgIH0pO1xuICAgICAgICB9XG5cbiAgICAgICAgLy8gc3NyYyB0byBtLWxpbmUgaW5kZXguXG4gICAgICAgIHZhciBzc3JjMm1sID0ge307XG5cbiAgICAgICAgaWYgKHR5cGVvZiBzb3VyY2VzID09PSAnb2JqZWN0Jykge1xuXG4gICAgICAgICAgICAvLyBFeHBsb2RlIHRoZSBQbGFuIEIgY2hhbm5lbCBzb3VyY2VzIHdpdGggb25lIG0tbGluZSBwZXIgc291cmNlLlxuICAgICAgICAgICAgT2JqZWN0LmtleXMoc291cmNlcykuZm9yRWFjaChmdW5jdGlvbihzc3JjKSB7XG5cbiAgICAgICAgICAgICAgICAvLyBUaGUgKHVuaWZpZWQpIG0tbGluZSBmb3IgdGhpcyBTU1JDLiBXZSBlaXRoZXIgY3JlYXRlIGl0IGZyb21cbiAgICAgICAgICAgICAgICAvLyBzY3JhdGNoIG9yLCBpZiBpdCdzIGEgZ3JvdXBlZCBTU1JDLCB3ZSByZS11c2UgYSByZWxhdGVkXG4gICAgICAgICAgICAgICAgLy8gbWxpbmUuIEluIG90aGVyIHdvcmRzLCBpZiB0aGUgc291cmNlIGlzIGdyb3VwZWQgd2l0aCBhbm90aGVyXG4gICAgICAgICAgICAgICAgLy8gc291cmNlLCBwdXQgdGhlIHR3byB0b2dldGhlciBpbiB0aGUgc2FtZSBtLWxpbmUuXG4gICAgICAgICAgICAgICAgdmFyIHVMaW5lO1xuXG4gICAgICAgICAgICAgICAgLy8gV2UgYXNzdW1lIGhlcmUgdGhhdCB3ZSBhcmUgdGhlIGFuc3dlcmVyIGluIHRoZSBPL0EsIHNvIGFueVxuICAgICAgICAgICAgICAgIC8vIG9mZmVycyB3aGljaCB3ZSB0cmFuc2xhdGUgY29tZSBmcm9tIHRoZSByZW1vdGUgc2lkZSwgd2hpbGVcbiAgICAgICAgICAgICAgICAvLyBhbnN3ZXJzIGFyZSBsb2NhbC4gU28gdGhlIGNoZWNrIGJlbG93IGlzIHRvIG1ha2UgdGhhdCB3ZVxuICAgICAgICAgICAgICAgIC8vIGhhbmRsZSByZWNlaXZlLW9ubHkgU1NSQ3MgaW4gYSBzcGVjaWFsIHdheSBvbmx5IGlmIHRoZXkgY29tZVxuICAgICAgICAgICAgICAgIC8vIGZyb20gdGhlIHJlbW90ZSBzaWRlLlxuICAgICAgICAgICAgICAgIGlmIChkZXNjLnR5cGU9PT0nb2ZmZXInKSB7XG4gICAgICAgICAgICAgICAgICAgIC8vIFdlIHdhbnQgdG8gZGV0ZWN0IFNTUkNzIHdoaWNoIGFyZSB1c2VkIGJ5IGEgcmVtb3RlIHBlZXJcbiAgICAgICAgICAgICAgICAgICAgLy8gaW4gYW4gbS1saW5lIHdpdGggZGlyZWN0aW9uPXJlY3Zvbmx5IChpLmUuIHRoZXkgYXJlXG4gICAgICAgICAgICAgICAgICAgIC8vIGJlaW5nIHVzZWQgZm9yIFJUQ1Agb25seSkuXG4gICAgICAgICAgICAgICAgICAgIC8vIFRoaXMgaW5mb3JtYXRpb24gd291bGQgaGF2ZSBnb3R0ZW4gbG9zdCBpZiB0aGUgcmVtb3RlXG4gICAgICAgICAgICAgICAgICAgIC8vIHBlZXIgdXNlZCBVbmlmaWVkIFBsYW4gYW5kIHRoZWlyIGxvY2FsIGRlc2NyaXB0aW9uIHdhc1xuICAgICAgICAgICAgICAgICAgICAvLyB0cmFuc2xhdGVkIHRvIFBsYW4gQi4gU28gd2UgdXNlIHRoZSBsYWNrIG9mIGFuIE1TSURcbiAgICAgICAgICAgICAgICAgICAgLy8gYXR0cmlidXRlIHRvIGRlZHVjZSBhIFwicmVjZWl2ZSBvbmx5XCIgU1NSQy5cbiAgICAgICAgICAgICAgICAgICAgaWYgKCFzb3VyY2VzW3NzcmNdLm1zaWQpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgIHJlY3Zvbmx5U3NyY3NbYkxpbmUudHlwZV1bc3NyY10gPSBzb3VyY2VzW3NzcmNdO1xuICAgICAgICAgICAgICAgICAgICAgICAgLy8gUmVjZWl2ZS1vbmx5IFNTUkNzIG11c3Qgbm90IGNyZWF0ZSBuZXcgbS1saW5lcy4gV2VcbiAgICAgICAgICAgICAgICAgICAgICAgIC8vIHdpbGwgYXNzaWduIHRoZW0gdG8gYW4gZXhpc3RpbmcgbS1saW5lIGxhdGVyLlxuICAgICAgICAgICAgICAgICAgICAgICAgcmV0dXJuO1xuICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICAgICAgaWYgKHR5cGVvZiBzc3JjMmdyb3VwW3NzcmNdICE9PSAndW5kZWZpbmVkJyAmJlxuICAgICAgICAgICAgICAgICAgICBBcnJheS5pc0FycmF5KHNzcmMyZ3JvdXBbc3NyY10pKSB7XG4gICAgICAgICAgICAgICAgICAgIHNzcmMyZ3JvdXBbc3NyY10uc29tZShmdW5jdGlvbiAoc3NyY0dyb3VwKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICAvLyBzc3JjR3JvdXAuc3NyY3MgKmlzKiBhbiBBcnJheSwgbm8gbmVlZCB0byBjaGVja1xuICAgICAgICAgICAgICAgICAgICAgICAgLy8gYWdhaW4gaGVyZS5cbiAgICAgICAgICAgICAgICAgICAgICAgIHJldHVybiBzc3JjR3JvdXAuc3NyY3Muc29tZShmdW5jdGlvbiAocmVsYXRlZCkge1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgIGlmICh0eXBlb2Ygc3NyYzJtbFtyZWxhdGVkXSA9PT0gJ29iamVjdCcpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgdUxpbmUgPSBzc3JjMm1sW3JlbGF0ZWRdO1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICByZXR1cm4gdHJ1ZTtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgICAgICAgICB9KTtcbiAgICAgICAgICAgICAgICAgICAgfSk7XG4gICAgICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICAgICAgaWYgKHR5cGVvZiB1TGluZSA9PT0gJ29iamVjdCcpIHtcbiAgICAgICAgICAgICAgICAgICAgLy8gdGhlIG0tbGluZSBhbHJlYWR5IGV4aXN0cy4gSnVzdCBhZGQgdGhlIHNvdXJjZS5cbiAgICAgICAgICAgICAgICAgICAgdUxpbmUuc291cmNlc1tzc3JjXSA9IHNvdXJjZXNbc3NyY107XG4gICAgICAgICAgICAgICAgICAgIGRlbGV0ZSBzb3VyY2VzW3NzcmNdLm1zaWQ7XG4gICAgICAgICAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgICAgICAgICAgLy8gVXNlIHRoZSBcImJMaW5lXCIgYXMgYSBwcm90b3R5cGUgZm9yIHRoZSBcInVMaW5lXCIuXG4gICAgICAgICAgICAgICAgICAgIHVMaW5lID0gT2JqZWN0LmNyZWF0ZShiTGluZSk7XG4gICAgICAgICAgICAgICAgICAgIHNzcmMybWxbc3NyY10gPSB1TGluZTtcblxuICAgICAgICAgICAgICAgICAgICBpZiAodHlwZW9mIHNvdXJjZXNbc3NyY10ubXNpZCAhPT0gJ3VuZGVmaW5lZCcpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgIC8vIEFzc2lnbiB0aGUgbXNpZCBvZiB0aGUgc291cmNlIHRvIHRoZSBtLWxpbmUuIE5vdGVcbiAgICAgICAgICAgICAgICAgICAgICAgIC8vIHRoYXQgaXQgaXMgbm90IGd1YXJhbnRlZWQgdGhhdCB0aGUgc291cmNlIHdpbGwgaGF2ZVxuICAgICAgICAgICAgICAgICAgICAgICAgLy8gbXNpZC4gSW4gcGFydGljdWxhciBcInJlY3Zvbmx5XCIgc291cmNlcyBkb24ndCBoYXZlIGFuXG4gICAgICAgICAgICAgICAgICAgICAgICAvLyBtc2lkLiBOb3RlIHRoYXQgXCJyZWN2b25seVwiIGlzIGEgdGVybSBvbmx5IGRlZmluZWRcbiAgICAgICAgICAgICAgICAgICAgICAgIC8vIGZvciBtLWxpbmVzLlxuICAgICAgICAgICAgICAgICAgICAgICAgdUxpbmUubXNpZCA9IHNvdXJjZXNbc3NyY10ubXNpZDtcbiAgICAgICAgICAgICAgICAgICAgICAgIHVMaW5lLmRpcmVjdGlvbiA9ICdzZW5kcmVjdic7XG4gICAgICAgICAgICAgICAgICAgICAgICBkZWxldGUgc291cmNlc1tzc3JjXS5tc2lkO1xuICAgICAgICAgICAgICAgICAgICB9XG5cbiAgICAgICAgICAgICAgICAgICAgLy8gV2UgYXNzaWduIG9uZSBTU1JDIHBlciBtZWRpYSBsaW5lLlxuICAgICAgICAgICAgICAgICAgICB1TGluZS5zb3VyY2VzID0ge307XG4gICAgICAgICAgICAgICAgICAgIHVMaW5lLnNvdXJjZXNbc3NyY10gPSBzb3VyY2VzW3NzcmNdO1xuICAgICAgICAgICAgICAgICAgICB1TGluZS5zc3JjR3JvdXBzID0gc3NyYzJncm91cFtzc3JjXTtcblxuICAgICAgICAgICAgICAgICAgICAvLyBVc2UgdGhlIGNhY2hlZCBVbmlmaWVkIFBsYW4gU0RQIChpZiBpdCBleGlzdHMpIHRvIGFzc2lnblxuICAgICAgICAgICAgICAgICAgICAvLyBTU1JDcyB0byBtaWRzLlxuICAgICAgICAgICAgICAgICAgICBpZiAodHlwZW9mIGNhY2hlZCAhPT0gJ3VuZGVmaW5lZCcgJiZcbiAgICAgICAgICAgICAgICAgICAgICAgIHR5cGVvZiBjYWNoZWQubWVkaWEgIT09ICd1bmRlZmluZWQnICYmXG4gICAgICAgICAgICAgICAgICAgICAgICBBcnJheS5pc0FycmF5KGNhY2hlZC5tZWRpYSkpIHtcblxuICAgICAgICAgICAgICAgICAgICAgICAgY2FjaGVkLm1lZGlhLmZvckVhY2goZnVuY3Rpb24gKG0pIHtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICBpZiAodHlwZW9mIG0uc291cmNlcyA9PT0gJ29iamVjdCcpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgT2JqZWN0LmtleXMobS5zb3VyY2VzKS5mb3JFYWNoKGZ1bmN0aW9uIChzKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBpZiAocyA9PT0gc3NyYykge1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIHVMaW5lLm1pZCA9IG0ubWlkO1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICB9KTtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgICAgICAgICB9KTtcbiAgICAgICAgICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICAgICAgICAgIGlmICh0eXBlb2YgdUxpbmUubWlkID09PSAndW5kZWZpbmVkJykge1xuXG4gICAgICAgICAgICAgICAgICAgICAgICAvLyBJZiB0aGlzIGlzIGFuIFNTUkMgdGhhdCB3ZSBzZWUgZm9yIHRoZSBmaXJzdCB0aW1lXG4gICAgICAgICAgICAgICAgICAgICAgICAvLyBhc3NpZ24gaXQgYSBuZXcgbWlkLiBUaGlzIGlzIHR5cGljYWxseSB0aGUgY2FzZSB3aGVuXG4gICAgICAgICAgICAgICAgICAgICAgICAvLyB0aGlzIG1ldGhvZCBpcyBjYWxsZWQgdG8gdHJhbnNmb3JtIGEgcmVtb3RlXG4gICAgICAgICAgICAgICAgICAgICAgICAvLyBkZXNjcmlwdGlvbiBmb3IgdGhlIGZpcnN0IHRpbWUgb3Igd2hlbiB0aGVyZSBpcyBhXG4gICAgICAgICAgICAgICAgICAgICAgICAvLyBuZXcgU1NSQyBpbiB0aGUgcmVtb3RlIGRlc2NyaXB0aW9uIGJlY2F1c2UgYSBuZXdcbiAgICAgICAgICAgICAgICAgICAgICAgIC8vIHBlZXIgaGFzIGpvaW5lZCB0aGUgY29uZmVyZW5jZS4gTG9jYWwgU1NSQ3Mgc2hvdWxkXG4gICAgICAgICAgICAgICAgICAgICAgICAvLyBoYXZlIGFscmVhZHkgYmVlbiBhZGRlZCB0byB0aGUgbWFwIGluIHRoZSB0b1BsYW5CXG4gICAgICAgICAgICAgICAgICAgICAgICAvLyBtZXRob2QuXG4gICAgICAgICAgICAgICAgICAgICAgICAvL1xuICAgICAgICAgICAgICAgICAgICAgICAgLy8gQmVjYXVzZSBGRiBnZW5lcmF0ZXMgYW5zd2VycyBpbiBVbmlmaWVkIFBsYW4gc3R5bGUsXG4gICAgICAgICAgICAgICAgICAgICAgICAvLyB3ZSBNVVNUIGFscmVhZHkgaGF2ZSBhIGNhY2hlZCBhbnN3ZXIgd2l0aCBhbGwgdGhlXG4gICAgICAgICAgICAgICAgICAgICAgICAvLyBsb2NhbCBTU1JDcyBtYXBwZWQgdG8gc29tZSBtLWxpbmUvbWlkLlxuXG4gICAgICAgICAgICAgICAgICAgICAgICBpZiAoZGVzYy50eXBlID09PSAnYW5zd2VyJykge1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgIHRocm93IG5ldyBFcnJvcihcIkFuIHVubWFwcGVkIFNTUkMgd2FzIGZvdW5kLlwiKTtcbiAgICAgICAgICAgICAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgICAgICAgICAgICAgdUxpbmUubWlkID0gW2JMaW5lLnR5cGUsICctJywgc3NyY10uam9pbignJyk7XG4gICAgICAgICAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgICAgICAgICAvLyBJbmNsdWRlIHRoZSBjYW5kaWRhdGVzIGluIHRoZSAxc3QgbWVkaWEgbGluZS5cbiAgICAgICAgICAgICAgICAgICAgdUxpbmUuY2FuZGlkYXRlcyA9IGNhbmRpZGF0ZXM7XG4gICAgICAgICAgICAgICAgICAgIHVMaW5lLmljZVVmcmFnID0gaWNlVWZyYWc7XG4gICAgICAgICAgICAgICAgICAgIHVMaW5lLmljZVB3ZCA9IGljZVB3ZDtcbiAgICAgICAgICAgICAgICAgICAgdUxpbmUuZmluZ2VycHJpbnQgPSBmaW5nZXJwcmludDtcbiAgICAgICAgICAgICAgICAgICAgdUxpbmUucG9ydCA9IHBvcnQ7XG5cbiAgICAgICAgICAgICAgICAgICAgbWlkMnVsW3VMaW5lLm1pZF0gPSB1TGluZTtcbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICB9KTtcbiAgICAgICAgfVxuICAgIH0pO1xuXG4gICAgLy8gUmVidWlsZCB0aGUgbWVkaWEgYXJyYXkgaW4gdGhlIHJpZ2h0IG9yZGVyIGFuZCBhZGQgdGhlIG1pc3NpbmcgbUxpbmVzXG4gICAgLy8gKG1pc3NpbmcgZnJvbSB0aGUgUGxhbiBCIFNEUCkuXG4gICAgc2Vzc2lvbi5tZWRpYSA9IFtdO1xuICAgIG1pZHMgPSBbXTsgLy8gcmV1c2VcblxuICAgIGlmIChkZXNjLnR5cGUgPT09ICdhbnN3ZXInKSB7XG5cbiAgICAgICAgLy8gVGhlIG1lZGlhIGxpbmVzIGluIHRoZSBhbnN3ZXIgbXVzdCBtYXRjaCB0aGUgbWVkaWEgbGluZXMgaW4gdGhlXG4gICAgICAgIC8vIG9mZmVyLiBUaGUgb3JkZXIgaXMgaW1wb3J0YW50IHRvby4gSGVyZSB3ZSBhc3N1bWUgdGhhdCBGaXJlZm94IGlzXG4gICAgICAgIC8vIHRoZSBhbnN3ZXJlciwgc28gd2UgbWVyZWx5IGhhdmUgdG8gdXNlIHRoZSByZWNvbnN0cnVjdGVkICh1bmlmaWVkKVxuICAgICAgICAvLyBhbnN3ZXIgdG8gdXBkYXRlIHRoZSBjYWNoZWQgKHVuaWZpZWQpIGFuc3dlciBhY2NvcmRpbmdseS5cbiAgICAgICAgLy9cbiAgICAgICAgLy8gSW4gdGhlIGdlbmVyYWwgY2FzZSwgb25lIHdvdWxkIGhhdmUgdG8gdXNlIHRoZSBjYWNoZWQgKHVuaWZpZWQpXG4gICAgICAgIC8vIG9mZmVyIHRvIGZpbmQgdGhlIG0tbGluZXMgdGhhdCBhcmUgbWlzc2luZyBmcm9tIHRoZSByZWNvbnN0cnVjdGVkXG4gICAgICAgIC8vIGFuc3dlciwgcG90ZW50aWFsbHkgZ3JhYmJpbmcgdGhlbSBmcm9tIHRoZSBjYWNoZWQgKHVuaWZpZWQpIGFuc3dlci5cbiAgICAgICAgLy8gT25lIGhhcyB0byBiZSBjYXJlZnVsIHdpdGggdGhpcyBhcHByb2FjaCBiZWNhdXNlIGluYWN0aXZlIG0tbGluZXMgZG9cbiAgICAgICAgLy8gbm90IGFsd2F5cyBoYXZlIGFuIG1pZCwgbWFraW5nIGl0IHRyaWNreSAoaW1wb3NzaWJsZT8pIHRvIGZpbmQgd2hlcmVcbiAgICAgICAgLy8gZXhhY3RseSBhbmQgd2hpY2ggbS1saW5lcyBhcmUgbWlzc2luZyBmcm9tIHRoZSByZWNvbnN0cnVjdGVkIGFuc3dlci5cblxuICAgICAgICBmb3IgKHZhciBpID0gMDsgaSA8IGNhY2hlZC5tZWRpYS5sZW5ndGg7IGkrKykge1xuICAgICAgICAgICAgdmFyIHVMaW5lID0gY2FjaGVkLm1lZGlhW2ldO1xuXG4gICAgICAgICAgICBpZiAodHlwZW9mIG1pZDJ1bFt1TGluZS5taWRdID09PSAndW5kZWZpbmVkJykge1xuXG4gICAgICAgICAgICAgICAgLy8gVGhlIG1pZCBpc24ndCBpbiB0aGUgcmVjb25zdHJ1Y3RlZCAodW5pZmllZCkgYW5zd2VyLlxuICAgICAgICAgICAgICAgIC8vIFRoaXMgaXMgZWl0aGVyIGEgKHVuaWZpZWQpIG0tbGluZSBjb250YWluaW5nIGEgcmVtb3RlXG4gICAgICAgICAgICAgICAgLy8gdHJhY2sgb25seSwgb3IgYSAodW5pZmllZCkgbS1saW5lIGNvbnRhaW5pbmcgYSByZW1vdGVcbiAgICAgICAgICAgICAgICAvLyB0cmFjayBhbmQgYSBsb2NhbCB0cmFjayB0aGF0IGhhcyBiZWVuIHJlbW92ZWQuXG4gICAgICAgICAgICAgICAgLy8gSW4gZWl0aGVyIGNhc2UsIGl0IE1VU1QgZXhpc3QgaW4gdGhlIGNhY2hlZFxuICAgICAgICAgICAgICAgIC8vICh1bmlmaWVkKSBhbnN3ZXIuXG4gICAgICAgICAgICAgICAgLy9cbiAgICAgICAgICAgICAgICAvLyBJbiBjYXNlIHRoaXMgaXMgYSByZW1vdmVkIGxvY2FsIHRyYWNrLCBjbGVhbi11cFxuICAgICAgICAgICAgICAgIC8vIHRoZSAodW5pZmllZCkgbS1saW5lIGFuZCBtYWtlIHN1cmUgaXQncyAncmVjdm9ubHknIG9yXG4gICAgICAgICAgICAgICAgLy8gJ2luYWN0aXZlJy5cblxuICAgICAgICAgICAgICAgIGRlbGV0ZSB1TGluZS5tc2lkO1xuICAgICAgICAgICAgICAgIGRlbGV0ZSB1TGluZS5zb3VyY2VzO1xuICAgICAgICAgICAgICAgIGRlbGV0ZSB1TGluZS5zc3JjR3JvdXBzO1xuICAgICAgICAgICAgICAgIGlmICghdUxpbmUuZGlyZWN0aW9uXG4gICAgICAgICAgICAgICAgICAgIHx8IHVMaW5lLmRpcmVjdGlvbiA9PT0gJ3NlbmRyZWN2JylcbiAgICAgICAgICAgICAgICAgICAgdUxpbmUuZGlyZWN0aW9uID0gJ3JlY3Zvbmx5JztcbiAgICAgICAgICAgICAgICBlbHNlIGlmICh1TGluZS5kaXJlY3Rpb24gPT09ICdzZW5kb25seScpXG4gICAgICAgICAgICAgICAgICAgIHVMaW5lLmRpcmVjdGlvbiA9ICdpbmFjdGl2ZSc7XG4gICAgICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgICAgIC8vIFRoaXMgaXMgYW4gKHVuaWZpZWQpIG0tbGluZS9jaGFubmVsIHRoYXQgY29udGFpbnMgYSBsb2NhbFxuICAgICAgICAgICAgICAgIC8vIHRyYWNrIChzZW5kcmVjdiBvciBzZW5kb25seSBjaGFubmVsKSBvciBpdCdzIGEgdW5pZmllZFxuICAgICAgICAgICAgICAgIC8vIHJlY3Zvbmx5IG0tbGluZS9jaGFubmVsLiBJbiBlaXRoZXIgY2FzZSwgc2luY2Ugd2UncmVcbiAgICAgICAgICAgICAgICAvLyBnb2luZyBmcm9tIFBsYW5CIC0+IFVuaWZpZWQgUGxhbiB0aGlzIG0tbGluZSBNVVNUXG4gICAgICAgICAgICAgICAgLy8gZXhpc3QgaW4gdGhlIGNhY2hlZCBhbnN3ZXIuXG4gICAgICAgICAgICB9XG5cbiAgICAgICAgICAgIHNlc3Npb24ubWVkaWEucHVzaCh1TGluZSk7XG5cbiAgICAgICAgICAgIGlmICh0eXBlb2YgdUxpbmUubWlkID09PSAnc3RyaW5nJykge1xuICAgICAgICAgICAgICAgIC8vIGluYWN0aXZlIGxpbmVzIGRvbid0L21heSBub3QgaGF2ZSBhbiBtaWQuXG4gICAgICAgICAgICAgICAgbWlkcy5wdXNoKHVMaW5lLm1pZCk7XG4gICAgICAgICAgICB9XG4gICAgICAgIH1cbiAgICB9IGVsc2Uge1xuXG4gICAgICAgIC8vIFNEUCBvZmZlci9hbnN3ZXIgKGFuZCB0aGUgSlNFUCBzcGVjKSBmb3JiaWRzIHJlbW92aW5nIGFuIG0tc2VjdGlvblxuICAgICAgICAvLyB1bmRlciBhbnkgY2lyY3Vtc3RhbmNlcy4gSWYgd2UgYXJlIG5vIGxvbmdlciBpbnRlcmVzdGVkIGluIHNlbmRpbmcgYVxuICAgICAgICAvLyB0cmFjaywgd2UganVzdCByZW1vdmUgdGhlIG1zaWQgYW5kIHNzcmMgYXR0cmlidXRlcyBhbmQgc2V0IGl0IHRvXG4gICAgICAgIC8vIGVpdGhlciBhPXJlY3Zvbmx5IChhcyB0aGUgcmVvZmZlcmVyLCB3ZSBtdXN0IHVzZSByZWN2b25seSBpZiB0aGVcbiAgICAgICAgLy8gb3RoZXIgc2lkZSB3YXMgcHJldmlvdXNseSBzZW5kaW5nIG9uIHRoZSBtLXNlY3Rpb24sIGJ1dCB3ZSBjYW4gYWxzb1xuICAgICAgICAvLyBsZWF2ZSB0aGUgcG9zc2liaWxpdHkgb3BlbiBpZiBpdCB3YXNuJ3QgcHJldmlvdXNseSBpbiB1c2UpLCBvclxuICAgICAgICAvLyBhPWluYWN0aXZlLlxuXG4gICAgICAgIGlmICh0eXBlb2YgY2FjaGVkICE9PSAndW5kZWZpbmVkJyAmJlxuICAgICAgICAgICAgdHlwZW9mIGNhY2hlZC5tZWRpYSAhPT0gJ3VuZGVmaW5lZCcgJiZcbiAgICAgICAgICAgIEFycmF5LmlzQXJyYXkoY2FjaGVkLm1lZGlhKSkge1xuICAgICAgICAgICAgY2FjaGVkLm1lZGlhLmZvckVhY2goZnVuY3Rpb24odUxpbmUpIHtcbiAgICAgICAgICAgICAgICBtaWRzLnB1c2godUxpbmUubWlkKTtcbiAgICAgICAgICAgICAgICBpZiAodHlwZW9mIG1pZDJ1bFt1TGluZS5taWRdICE9PSAndW5kZWZpbmVkJykge1xuICAgICAgICAgICAgICAgICAgICBzZXNzaW9uLm1lZGlhLnB1c2gobWlkMnVsW3VMaW5lLm1pZF0pO1xuICAgICAgICAgICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICAgICAgICAgIGRlbGV0ZSB1TGluZS5tc2lkO1xuICAgICAgICAgICAgICAgICAgICBkZWxldGUgdUxpbmUuc291cmNlcztcbiAgICAgICAgICAgICAgICAgICAgZGVsZXRlIHVMaW5lLnNzcmNHcm91cHM7XG4gICAgICAgICAgICAgICAgICAgIGlmICghdUxpbmUuZGlyZWN0aW9uXG4gICAgICAgICAgICAgICAgICAgICAgICB8fCB1TGluZS5kaXJlY3Rpb24gPT09ICdzZW5kcmVjdicpXG4gICAgICAgICAgICAgICAgICAgICAgICB1TGluZS5kaXJlY3Rpb24gPSAncmVjdm9ubHknO1xuICAgICAgICAgICAgICAgICAgICBpZiAoIXVMaW5lLmRpcmVjdGlvblxuICAgICAgICAgICAgICAgICAgICAgICAgfHwgdUxpbmUuZGlyZWN0aW9uID09PSAnc2VuZG9ubHknKVxuICAgICAgICAgICAgICAgICAgICAgICAgdUxpbmUuZGlyZWN0aW9uID0gJ2luYWN0aXZlJztcbiAgICAgICAgICAgICAgICAgICAgc2Vzc2lvbi5tZWRpYS5wdXNoKHVMaW5lKTtcbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICB9KTtcbiAgICAgICAgfVxuXG4gICAgICAgIC8vIEFkZCBhbGwgdGhlIHJlbWFpbmluZyAobmV3KSBtLWxpbmVzIG9mIHRoZSB0cmFuc2Zvcm1lZCBTRFAuXG4gICAgICAgIE9iamVjdC5rZXlzKG1pZDJ1bCkuZm9yRWFjaChmdW5jdGlvbihtaWQpIHtcbiAgICAgICAgICAgIGlmIChtaWRzLmluZGV4T2YobWlkKSA9PT0gLTEpIHtcbiAgICAgICAgICAgICAgICBtaWRzLnB1c2gobWlkKTtcbiAgICAgICAgICAgICAgICBpZiAobWlkMnVsW21pZF0uZGlyZWN0aW9uID09PSAncmVjdm9ubHknKSB7XG4gICAgICAgICAgICAgICAgICAgIC8vIFRoaXMgaXMgYSByZW1vdGUgcmVjdm9ubHkgY2hhbm5lbC4gQWRkIGl0cyBTU1JDIHRvIHRoZVxuICAgICAgICAgICAgICAgICAgICAvLyBhcHByb3ByaWF0ZSBzZW5kcmVjdiBvciBzZW5kb25seSBjaGFubmVsLlxuICAgICAgICAgICAgICAgICAgICAvLyBUT0RPKGdwKSB3aGF0IGlmIHdlIGRvbid0IGhhdmUgc2VuZHJlY3Yvc2VuZG9ubHlcbiAgICAgICAgICAgICAgICAgICAgLy8gY2hhbm5lbD9cblxuICAgICAgICAgICAgICAgICAgICBzZXNzaW9uLm1lZGlhLnNvbWUoZnVuY3Rpb24gKHVMaW5lKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICBpZiAoKHVMaW5lLmRpcmVjdGlvbiA9PT0gJ3NlbmRyZWN2JyB8fFxuICAgICAgICAgICAgICAgICAgICAgICAgICAgIHVMaW5lLmRpcmVjdGlvbiA9PT0gJ3NlbmRvbmx5JykgJiZcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICB1TGluZS50eXBlID09PSBtaWQydWxbbWlkXS50eXBlKSB7XG5cbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAvLyBtaWQydWxbbWlkXSBzaG91bGRuJ3QgaGF2ZSBhbnkgc3NyYy1ncm91cHNcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICBPYmplY3Qua2V5cyhtaWQydWxbbWlkXS5zb3VyY2VzKS5mb3JFYWNoKFxuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBmdW5jdGlvbiAoc3NyYykge1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICB1TGluZS5zb3VyY2VzW3NzcmNdID1cbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIG1pZDJ1bFttaWRdLnNvdXJjZXNbc3NyY107XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgfSk7XG5cbiAgICAgICAgICAgICAgICAgICAgICAgICAgICByZXR1cm4gdHJ1ZTtcbiAgICAgICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICAgICAgfSk7XG4gICAgICAgICAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgICAgICAgICAgc2Vzc2lvbi5tZWRpYS5wdXNoKG1pZDJ1bFttaWRdKTtcbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICB9XG4gICAgICAgIH0pO1xuICAgIH1cblxuICAgIC8vIEFmdGVyIHdlIGhhdmUgY29uc3RydWN0ZWQgdGhlIFBsYW4gVW5pZmllZCBtLWxpbmVzIHdlIGNhbiBmaWd1cmUgb3V0XG4gICAgLy8gd2hlcmUgKGluIHdoaWNoIG0tbGluZSkgdG8gcGxhY2UgdGhlICdyZWN2b25seSBTU1JDcycuXG4gICAgLy8gTm90ZTogd2UgYXNzdW1lIGhlcmUgdGhhdCB3ZSBhcmUgdGhlIGFuc3dlcmVyIGluIHRoZSBPL0EsIHNvIGFueSBvZmZlcnNcbiAgICAvLyB3aGljaCB3ZSB0cmFuc2xhdGUgY29tZSBmcm9tIHRoZSByZW1vdGUgc2lkZSwgd2hpbGUgYW5zd2VycyBhcmUgbG9jYWxcbiAgICAvLyAoYW5kIHNvIG91ciBsYXN0IGxvY2FsIGRlc2NyaXB0aW9uIGlzIGNhY2hlZCBhcyBhbiAnYW5zd2VyJykuXG4gICAgW1wiYXVkaW9cIiwgXCJ2aWRlb1wiXS5mb3JFYWNoKGZ1bmN0aW9uICh0eXBlKSB7XG4gICAgICAgIGlmICghc2Vzc2lvbiB8fCAhc2Vzc2lvbi5tZWRpYSB8fCAhQXJyYXkuaXNBcnJheShzZXNzaW9uLm1lZGlhKSlcbiAgICAgICAgICAgIHJldHVybjtcblxuICAgICAgICB2YXIgaWR4ID0gbnVsbDtcbiAgICAgICAgaWYgKE9iamVjdC5rZXlzKHJlY3Zvbmx5U3NyY3NbdHlwZV0pLmxlbmd0aCA+IDApIHtcbiAgICAgICAgICAgIGlkeCA9IHNlbGYuZ2V0Rmlyc3RTZW5kaW5nSW5kZXhGcm9tQW5zd2VyKHR5cGUpO1xuICAgICAgICAgICAgaWYgKGlkeCA9PT0gbnVsbCl7XG4gICAgICAgICAgICAgICAgLy8gSWYgdGhpcyBpcyB0aGUgZmlyc3Qgb2ZmZXIgd2UgcmVjZWl2ZSwgd2UgZG9uJ3QgaGF2ZSBhXG4gICAgICAgICAgICAgICAgLy8gY2FjaGVkIGFuc3dlci4gQXNzdW1lIHRoYXQgd2Ugd2lsbCBiZSBzZW5kaW5nIG1lZGlhIHVzaW5nXG4gICAgICAgICAgICAgICAgLy8gdGhlIGZpcnN0IG0tbGluZSBmb3IgZWFjaCBtZWRpYSB0eXBlLlxuXG4gICAgICAgICAgICAgICAgZm9yICh2YXIgaSA9IDA7IGkgPCBzZXNzaW9uLm1lZGlhLmxlbmd0aDsgaSsrKSB7XG4gICAgICAgICAgICAgICAgICAgIGlmIChzZXNzaW9uLm1lZGlhW2ldLnR5cGUgPT09IHR5cGUpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgIGlkeCA9IGk7XG4gICAgICAgICAgICAgICAgICAgICAgICBicmVhaztcbiAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgIH1cbiAgICAgICAgfVxuXG4gICAgICAgIGlmIChpZHggJiYgc2Vzc2lvbi5tZWRpYS5sZW5ndGggPiBpZHgpIHtcbiAgICAgICAgICAgIHZhciBtTGluZSA9IHNlc3Npb24ubWVkaWFbaWR4XTtcbiAgICAgICAgICAgIE9iamVjdC5rZXlzKHJlY3Zvbmx5U3NyY3NbdHlwZV0pLmZvckVhY2goZnVuY3Rpb24oc3NyYykge1xuICAgICAgICAgICAgICAgIGlmIChtTGluZS5zb3VyY2VzICYmIG1MaW5lLnNvdXJjZXNbc3NyY10pIHtcbiAgICAgICAgICAgICAgICAgICAgY29uc29sZS53YXJuKFwiUmVwbGFjaW5nIGFuIGV4aXN0aW5nIFNTUkMuXCIpO1xuICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICBpZiAoIW1MaW5lLnNvdXJjZXMpIHtcbiAgICAgICAgICAgICAgICAgICAgbUxpbmUuc291cmNlcyA9IHt9O1xuICAgICAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgICAgIG1MaW5lLnNvdXJjZXNbc3NyY10gPSByZWN2b25seVNzcmNzW3R5cGVdW3NzcmNdO1xuICAgICAgICAgICAgfSk7XG4gICAgICAgIH1cbiAgICB9KTtcblxuICAgIC8vIFdlIHJlZ2VuZXJhdGUgdGhlIEJVTkRMRSBncm91cCAoc2luY2Ugd2UgcmVnZW5lcmF0ZWQgdGhlIG1pZHMpXG4gICAgc2Vzc2lvbi5ncm91cHMuc29tZShmdW5jdGlvbihncm91cCkge1xuICAgICAgICBpZiAoZ3JvdXAudHlwZSA9PT0gJ0JVTkRMRScpIHtcbiAgICAgICAgICAgIGdyb3VwLm1pZHMgPSBtaWRzLmpvaW4oJyAnKTtcbiAgICAgICAgICAgIHJldHVybiB0cnVlO1xuICAgICAgICB9XG4gICAgfSk7XG5cbiAgICAvLyBtc2lkIHNlbWFudGljXG4gICAgc2Vzc2lvbi5tc2lkU2VtYW50aWMgPSB7XG4gICAgICAgIHNlbWFudGljOiAnV01TJyxcbiAgICAgICAgdG9rZW46ICcqJ1xuICAgIH07XG5cbiAgICB2YXIgcmVzU3RyID0gdHJhbnNmb3JtLndyaXRlKHNlc3Npb24pO1xuXG4gICAgLy8gQ2FjaGUgdGhlIHRyYW5zZm9ybWVkIFNEUCAoVW5pZmllZCBQbGFuKSBmb3IgbGF0ZXIgcmUtdXNlIGluIHRoaXNcbiAgICAvLyBmdW5jdGlvbi5cbiAgICB0aGlzLmNhY2hlW2Rlc2MudHlwZV0gPSByZXNTdHI7XG5cbiAgICByZXR1cm4gbmV3IFJUQ1Nlc3Npb25EZXNjcmlwdGlvbih7XG4gICAgICAgIHR5cGU6IGRlc2MudHlwZSxcbiAgICAgICAgc2RwOiByZXNTdHJcbiAgICB9KTtcblxuICAgIC8vI2VuZHJlZ2lvblxufTtcbiIsIi8qIENvcHlyaWdodCBAIDIwMTUgQXRsYXNzaWFuIFB0eSBMdGRcbiAqXG4gKiBMaWNlbnNlZCB1bmRlciB0aGUgQXBhY2hlIExpY2Vuc2UsIFZlcnNpb24gMi4wICh0aGUgXCJMaWNlbnNlXCIpO1xuICogeW91IG1heSBub3QgdXNlIHRoaXMgZmlsZSBleGNlcHQgaW4gY29tcGxpYW5jZSB3aXRoIHRoZSBMaWNlbnNlLlxuICogWW91IG1heSBvYnRhaW4gYSBjb3B5IG9mIHRoZSBMaWNlbnNlIGF0XG4gKlxuICogICAgIGh0dHA6Ly93d3cuYXBhY2hlLm9yZy9saWNlbnNlcy9MSUNFTlNFLTIuMFxuICpcbiAqIFVubGVzcyByZXF1aXJlZCBieSBhcHBsaWNhYmxlIGxhdyBvciBhZ3JlZWQgdG8gaW4gd3JpdGluZywgc29mdHdhcmVcbiAqIGRpc3RyaWJ1dGVkIHVuZGVyIHRoZSBMaWNlbnNlIGlzIGRpc3RyaWJ1dGVkIG9uIGFuIFwiQVMgSVNcIiBCQVNJUyxcbiAqIFdJVEhPVVQgV0FSUkFOVElFUyBPUiBDT05ESVRJT05TIE9GIEFOWSBLSU5ELCBlaXRoZXIgZXhwcmVzcyBvciBpbXBsaWVkLlxuICogU2VlIHRoZSBMaWNlbnNlIGZvciB0aGUgc3BlY2lmaWMgbGFuZ3VhZ2UgZ292ZXJuaW5nIHBlcm1pc3Npb25zIGFuZFxuICogbGltaXRhdGlvbnMgdW5kZXIgdGhlIExpY2Vuc2UuXG4gKi9cblxudmFyIHRyYW5zZm9ybSA9IHJlcXVpcmUoJ3NkcC10cmFuc2Zvcm0nKTtcblxuZXhwb3J0cy53cml0ZSA9IGZ1bmN0aW9uKHNlc3Npb24sIG9wdHMpIHtcblxuICBpZiAodHlwZW9mIHNlc3Npb24gIT09ICd1bmRlZmluZWQnICYmXG4gICAgICB0eXBlb2Ygc2Vzc2lvbi5tZWRpYSAhPT0gJ3VuZGVmaW5lZCcgJiZcbiAgICAgIEFycmF5LmlzQXJyYXkoc2Vzc2lvbi5tZWRpYSkpIHtcblxuICAgIHNlc3Npb24ubWVkaWEuZm9yRWFjaChmdW5jdGlvbiAobUxpbmUpIHtcbiAgICAgIC8vIGV4cGFuZCBzb3VyY2VzIHRvIHNzcmNzXG4gICAgICBpZiAodHlwZW9mIG1MaW5lLnNvdXJjZXMgIT09ICd1bmRlZmluZWQnICYmXG4gICAgICAgIE9iamVjdC5rZXlzKG1MaW5lLnNvdXJjZXMpLmxlbmd0aCAhPT0gMCkge1xuICAgICAgICAgIG1MaW5lLnNzcmNzID0gW107XG4gICAgICAgICAgT2JqZWN0LmtleXMobUxpbmUuc291cmNlcykuZm9yRWFjaChmdW5jdGlvbiAoc3NyYykge1xuICAgICAgICAgICAgdmFyIHNvdXJjZSA9IG1MaW5lLnNvdXJjZXNbc3NyY107XG4gICAgICAgICAgICBPYmplY3Qua2V5cyhzb3VyY2UpLmZvckVhY2goZnVuY3Rpb24gKGF0dHJpYnV0ZSkge1xuICAgICAgICAgICAgICBtTGluZS5zc3Jjcy5wdXNoKHtcbiAgICAgICAgICAgICAgICBpZDogc3NyYyxcbiAgICAgICAgICAgICAgICBhdHRyaWJ1dGU6IGF0dHJpYnV0ZSxcbiAgICAgICAgICAgICAgICB2YWx1ZTogc291cmNlW2F0dHJpYnV0ZV1cbiAgICAgICAgICAgICAgfSk7XG4gICAgICAgICAgICB9KTtcbiAgICAgICAgICB9KTtcbiAgICAgICAgICBkZWxldGUgbUxpbmUuc291cmNlcztcbiAgICAgICAgfVxuXG4gICAgICAvLyBqb2luIHNzcmNzIGluIHNzcmMgZ3JvdXBzXG4gICAgICBpZiAodHlwZW9mIG1MaW5lLnNzcmNHcm91cHMgIT09ICd1bmRlZmluZWQnICYmXG4gICAgICAgIEFycmF5LmlzQXJyYXkobUxpbmUuc3NyY0dyb3VwcykpIHtcbiAgICAgICAgICBtTGluZS5zc3JjR3JvdXBzLmZvckVhY2goZnVuY3Rpb24gKHNzcmNHcm91cCkge1xuICAgICAgICAgICAgaWYgKHR5cGVvZiBzc3JjR3JvdXAuc3NyY3MgIT09ICd1bmRlZmluZWQnICYmXG4gICAgICAgICAgICAgICAgQXJyYXkuaXNBcnJheShzc3JjR3JvdXAuc3NyY3MpKSB7XG4gICAgICAgICAgICAgIHNzcmNHcm91cC5zc3JjcyA9IHNzcmNHcm91cC5zc3Jjcy5qb2luKCcgJyk7XG4gICAgICAgICAgICB9XG4gICAgICAgICAgfSk7XG4gICAgICAgIH1cbiAgICB9KTtcbiAgfVxuXG4gIC8vIGpvaW4gZ3JvdXAgbWlkc1xuICBpZiAodHlwZW9mIHNlc3Npb24gIT09ICd1bmRlZmluZWQnICYmXG4gICAgICB0eXBlb2Ygc2Vzc2lvbi5ncm91cHMgIT09ICd1bmRlZmluZWQnICYmIEFycmF5LmlzQXJyYXkoc2Vzc2lvbi5ncm91cHMpKSB7XG5cbiAgICBzZXNzaW9uLmdyb3Vwcy5mb3JFYWNoKGZ1bmN0aW9uIChnKSB7XG4gICAgICBpZiAodHlwZW9mIGcubWlkcyAhPT0gJ3VuZGVmaW5lZCcgJiYgQXJyYXkuaXNBcnJheShnLm1pZHMpKSB7XG4gICAgICAgIGcubWlkcyA9IGcubWlkcy5qb2luKCcgJyk7XG4gICAgICB9XG4gICAgfSk7XG4gIH1cblxuICByZXR1cm4gdHJhbnNmb3JtLndyaXRlKHNlc3Npb24sIG9wdHMpO1xufTtcblxuZXhwb3J0cy5wYXJzZSA9IGZ1bmN0aW9uKHNkcCkge1xuICB2YXIgc2Vzc2lvbiA9IHRyYW5zZm9ybS5wYXJzZShzZHApO1xuXG4gIGlmICh0eXBlb2Ygc2Vzc2lvbiAhPT0gJ3VuZGVmaW5lZCcgJiYgdHlwZW9mIHNlc3Npb24ubWVkaWEgIT09ICd1bmRlZmluZWQnICYmXG4gICAgICBBcnJheS5pc0FycmF5KHNlc3Npb24ubWVkaWEpKSB7XG5cbiAgICBzZXNzaW9uLm1lZGlhLmZvckVhY2goZnVuY3Rpb24gKG1MaW5lKSB7XG4gICAgICAvLyBncm91cCBzb3VyY2VzIGF0dHJpYnV0ZXMgYnkgc3NyY1xuICAgICAgaWYgKHR5cGVvZiBtTGluZS5zc3JjcyAhPT0gJ3VuZGVmaW5lZCcgJiYgQXJyYXkuaXNBcnJheShtTGluZS5zc3JjcykpIHtcbiAgICAgICAgbUxpbmUuc291cmNlcyA9IHt9O1xuICAgICAgICBtTGluZS5zc3Jjcy5mb3JFYWNoKGZ1bmN0aW9uIChzc3JjKSB7XG4gICAgICAgICAgaWYgKCFtTGluZS5zb3VyY2VzW3NzcmMuaWRdKVxuICAgICAgICAgIG1MaW5lLnNvdXJjZXNbc3NyYy5pZF0gPSB7fTtcbiAgICAgICAgbUxpbmUuc291cmNlc1tzc3JjLmlkXVtzc3JjLmF0dHJpYnV0ZV0gPSBzc3JjLnZhbHVlO1xuICAgICAgICB9KTtcblxuICAgICAgICBkZWxldGUgbUxpbmUuc3NyY3M7XG4gICAgICB9XG5cbiAgICAgIC8vIHNwbGl0IHNzcmNzIGluIHNzcmMgZ3JvdXBzXG4gICAgICBpZiAodHlwZW9mIG1MaW5lLnNzcmNHcm91cHMgIT09ICd1bmRlZmluZWQnICYmXG4gICAgICAgIEFycmF5LmlzQXJyYXkobUxpbmUuc3NyY0dyb3VwcykpIHtcbiAgICAgICAgICBtTGluZS5zc3JjR3JvdXBzLmZvckVhY2goZnVuY3Rpb24gKHNzcmNHcm91cCkge1xuICAgICAgICAgICAgaWYgKHR5cGVvZiBzc3JjR3JvdXAuc3NyY3MgPT09ICdzdHJpbmcnKSB7XG4gICAgICAgICAgICAgIHNzcmNHcm91cC5zc3JjcyA9IHNzcmNHcm91cC5zc3Jjcy5zcGxpdCgnICcpO1xuICAgICAgICAgICAgfVxuICAgICAgICAgIH0pO1xuICAgICAgICB9XG4gICAgfSk7XG4gIH1cbiAgLy8gc3BsaXQgZ3JvdXAgbWlkc1xuICBpZiAodHlwZW9mIHNlc3Npb24gIT09ICd1bmRlZmluZWQnICYmXG4gICAgICB0eXBlb2Ygc2Vzc2lvbi5ncm91cHMgIT09ICd1bmRlZmluZWQnICYmIEFycmF5LmlzQXJyYXkoc2Vzc2lvbi5ncm91cHMpKSB7XG5cbiAgICBzZXNzaW9uLmdyb3Vwcy5mb3JFYWNoKGZ1bmN0aW9uIChnKSB7XG4gICAgICBpZiAodHlwZW9mIGcubWlkcyA9PT0gJ3N0cmluZycpIHtcbiAgICAgICAgZy5taWRzID0gZy5taWRzLnNwbGl0KCcgJyk7XG4gICAgICB9XG4gICAgfSk7XG4gIH1cblxuICByZXR1cm4gc2Vzc2lvbjtcbn07XG5cbiIsInZhciBncmFtbWFyID0gbW9kdWxlLmV4cG9ydHMgPSB7XG4gIHY6IFt7XG4gICAgICBuYW1lOiAndmVyc2lvbicsXG4gICAgICByZWc6IC9eKFxcZCopJC9cbiAgfV0sXG4gIG86IFt7IC8vbz0tIDIwNTE4IDAgSU4gSVA0IDIwMy4wLjExMy4xXG4gICAgLy8gTkI6IHNlc3Npb25JZCB3aWxsIGJlIGEgU3RyaW5nIGluIG1vc3QgY2FzZXMgYmVjYXVzZSBpdCBpcyBodWdlXG4gICAgbmFtZTogJ29yaWdpbicsXG4gICAgcmVnOiAvXihcXFMqKSAoXFxkKikgKFxcZCopIChcXFMqKSBJUChcXGQpIChcXFMqKS8sXG4gICAgbmFtZXM6IFsndXNlcm5hbWUnLCAnc2Vzc2lvbklkJywgJ3Nlc3Npb25WZXJzaW9uJywgJ25ldFR5cGUnLCAnaXBWZXInLCAnYWRkcmVzcyddLFxuICAgIGZvcm1hdDogXCIlcyAlcyAlZCAlcyBJUCVkICVzXCJcbiAgfV0sXG4gIC8vIGRlZmF1bHQgcGFyc2luZyBvZiB0aGVzZSBvbmx5ICh0aG91Z2ggc29tZSBvZiB0aGVzZSBmZWVsIG91dGRhdGVkKVxuICBzOiBbeyBuYW1lOiAnbmFtZScgfV0sXG4gIGk6IFt7IG5hbWU6ICdkZXNjcmlwdGlvbicgfV0sXG4gIHU6IFt7IG5hbWU6ICd1cmknIH1dLFxuICBlOiBbeyBuYW1lOiAnZW1haWwnIH1dLFxuICBwOiBbeyBuYW1lOiAncGhvbmUnIH1dLFxuICB6OiBbeyBuYW1lOiAndGltZXpvbmVzJyB9XSwgLy8gVE9ETzogdGhpcyBvbmUgY2FuIGFjdHVhbGx5IGJlIHBhcnNlZCBwcm9wZXJseS4uXG4gIHI6IFt7IG5hbWU6ICdyZXBlYXRzJyB9XSwgICAvLyBUT0RPOiB0aGlzIG9uZSBjYW4gYWxzbyBiZSBwYXJzZWQgcHJvcGVybHlcbiAgLy9rOiBbe31dLCAvLyBvdXRkYXRlZCB0aGluZyBpZ25vcmVkXG4gIHQ6IFt7IC8vdD0wIDBcbiAgICBuYW1lOiAndGltaW5nJyxcbiAgICByZWc6IC9eKFxcZCopIChcXGQqKS8sXG4gICAgbmFtZXM6IFsnc3RhcnQnLCAnc3RvcCddLFxuICAgIGZvcm1hdDogXCIlZCAlZFwiXG4gIH1dLFxuICBjOiBbeyAvL2M9SU4gSVA0IDEwLjQ3LjE5Ny4yNlxuICAgICAgbmFtZTogJ2Nvbm5lY3Rpb24nLFxuICAgICAgcmVnOiAvXklOIElQKFxcZCkgKFxcUyopLyxcbiAgICAgIG5hbWVzOiBbJ3ZlcnNpb24nLCAnaXAnXSxcbiAgICAgIGZvcm1hdDogXCJJTiBJUCVkICVzXCJcbiAgfV0sXG4gIGI6IFt7IC8vYj1BUzo0MDAwXG4gICAgICBwdXNoOiAnYmFuZHdpZHRoJyxcbiAgICAgIHJlZzogL14oVElBU3xBU3xDVHxSUnxSUyk6KFxcZCopLyxcbiAgICAgIG5hbWVzOiBbJ3R5cGUnLCAnbGltaXQnXSxcbiAgICAgIGZvcm1hdDogXCIlczolc1wiXG4gIH1dLFxuICBtOiBbeyAvL209dmlkZW8gNTE3NDQgUlRQL0FWUCAxMjYgOTcgOTggMzQgMzFcbiAgICAgIC8vIE5COiBzcGVjaWFsIC0gcHVzaGVzIHRvIHNlc3Npb25cbiAgICAgIC8vIFRPRE86IHJ0cC9mbXRwIHNob3VsZCBiZSBmaWx0ZXJlZCBieSB0aGUgcGF5bG9hZHMgZm91bmQgaGVyZT9cbiAgICAgIHJlZzogL14oXFx3KikgKFxcZCopIChbXFx3XFwvXSopKD86ICguKikpPy8sXG4gICAgICBuYW1lczogWyd0eXBlJywgJ3BvcnQnLCAncHJvdG9jb2wnLCAncGF5bG9hZHMnXSxcbiAgICAgIGZvcm1hdDogXCIlcyAlZCAlcyAlc1wiXG4gIH1dLFxuICBhOiBbXG4gICAgeyAvL2E9cnRwbWFwOjExMCBvcHVzLzQ4MDAwLzJcbiAgICAgIHB1c2g6ICdydHAnLFxuICAgICAgcmVnOiAvXnJ0cG1hcDooXFxkKikgKFtcXHdcXC1dKikoPzpcXHMqXFwvKFxcZCopKD86XFxzKlxcLyhcXFMqKSk/KT8vLFxuICAgICAgbmFtZXM6IFsncGF5bG9hZCcsICdjb2RlYycsICdyYXRlJywgJ2VuY29kaW5nJ10sXG4gICAgICBmb3JtYXQ6IGZ1bmN0aW9uIChvKSB7XG4gICAgICAgIHJldHVybiAoby5lbmNvZGluZykgP1xuICAgICAgICAgIFwicnRwbWFwOiVkICVzLyVzLyVzXCI6XG4gICAgICAgICAgby5yYXRlID9cbiAgICAgICAgICBcInJ0cG1hcDolZCAlcy8lc1wiOlxuICAgICAgICAgIFwicnRwbWFwOiVkICVzXCI7XG4gICAgICB9XG4gICAgfSxcbiAgICB7XG4gICAgICAvL2E9Zm10cDoxMDggcHJvZmlsZS1sZXZlbC1pZD0yNDtvYmplY3Q9MjM7Yml0cmF0ZT02NDAwMFxuICAgICAgLy9hPWZtdHA6MTExIG1pbnB0aW1lPTEwOyB1c2VpbmJhbmRmZWM9MVxuICAgICAgcHVzaDogJ2ZtdHAnLFxuICAgICAgcmVnOiAvXmZtdHA6KFxcZCopIChbXFxTfCBdKikvLFxuICAgICAgbmFtZXM6IFsncGF5bG9hZCcsICdjb25maWcnXSxcbiAgICAgIGZvcm1hdDogXCJmbXRwOiVkICVzXCJcbiAgICB9LFxuICAgIHsgLy9hPWNvbnRyb2w6c3RyZWFtaWQ9MFxuICAgICAgICBuYW1lOiAnY29udHJvbCcsXG4gICAgICAgIHJlZzogL15jb250cm9sOiguKikvLFxuICAgICAgICBmb3JtYXQ6IFwiY29udHJvbDolc1wiXG4gICAgfSxcbiAgICB7IC8vYT1ydGNwOjY1MTc5IElOIElQNCAxOTMuODQuNzcuMTk0XG4gICAgICBuYW1lOiAncnRjcCcsXG4gICAgICByZWc6IC9ecnRjcDooXFxkKikoPzogKFxcUyopIElQKFxcZCkgKFxcUyopKT8vLFxuICAgICAgbmFtZXM6IFsncG9ydCcsICduZXRUeXBlJywgJ2lwVmVyJywgJ2FkZHJlc3MnXSxcbiAgICAgIGZvcm1hdDogZnVuY3Rpb24gKG8pIHtcbiAgICAgICAgcmV0dXJuIChvLmFkZHJlc3MgIT0gbnVsbCkgP1xuICAgICAgICAgIFwicnRjcDolZCAlcyBJUCVkICVzXCI6XG4gICAgICAgICAgXCJydGNwOiVkXCI7XG4gICAgICB9XG4gICAgfSxcbiAgICB7IC8vYT1ydGNwLWZiOjk4IHRyci1pbnQgMTAwXG4gICAgICBwdXNoOiAncnRjcEZiVHJySW50JyxcbiAgICAgIHJlZzogL15ydGNwLWZiOihcXCp8XFxkKikgdHJyLWludCAoXFxkKikvLFxuICAgICAgbmFtZXM6IFsncGF5bG9hZCcsICd2YWx1ZSddLFxuICAgICAgZm9ybWF0OiBcInJ0Y3AtZmI6JWQgdHJyLWludCAlZFwiXG4gICAgfSxcbiAgICB7IC8vYT1ydGNwLWZiOjk4IG5hY2sgcnBzaVxuICAgICAgcHVzaDogJ3J0Y3BGYicsXG4gICAgICByZWc6IC9ecnRjcC1mYjooXFwqfFxcZCopIChbXFx3LV9dKikoPzogKFtcXHctX10qKSk/LyxcbiAgICAgIG5hbWVzOiBbJ3BheWxvYWQnLCAndHlwZScsICdzdWJ0eXBlJ10sXG4gICAgICBmb3JtYXQ6IGZ1bmN0aW9uIChvKSB7XG4gICAgICAgIHJldHVybiAoby5zdWJ0eXBlICE9IG51bGwpID9cbiAgICAgICAgICBcInJ0Y3AtZmI6JXMgJXMgJXNcIjpcbiAgICAgICAgICBcInJ0Y3AtZmI6JXMgJXNcIjtcbiAgICAgIH1cbiAgICB9LFxuICAgIHsgLy9hPWV4dG1hcDoyIHVybjppZXRmOnBhcmFtczpydHAtaGRyZXh0OnRvZmZzZXRcbiAgICAgIC8vYT1leHRtYXA6MS9yZWN2b25seSBVUkktZ3BzLXN0cmluZ1xuICAgICAgcHVzaDogJ2V4dCcsXG4gICAgICByZWc6IC9eZXh0bWFwOihbXFx3X1xcL10qKSAoXFxTKikoPzogKFxcUyopKT8vLFxuICAgICAgbmFtZXM6IFsndmFsdWUnLCAndXJpJywgJ2NvbmZpZyddLCAvLyB2YWx1ZSBtYXkgaW5jbHVkZSBcIi9kaXJlY3Rpb25cIiBzdWZmaXhcbiAgICAgIGZvcm1hdDogZnVuY3Rpb24gKG8pIHtcbiAgICAgICAgcmV0dXJuIChvLmNvbmZpZyAhPSBudWxsKSA/XG4gICAgICAgICAgXCJleHRtYXA6JXMgJXMgJXNcIjpcbiAgICAgICAgICBcImV4dG1hcDolcyAlc1wiO1xuICAgICAgfVxuICAgIH0sXG4gICAge1xuICAgICAgLy9hPWNyeXB0bzoxIEFFU19DTV8xMjhfSE1BQ19TSEExXzgwIGlubGluZTpQUzF1UUNWZWVDRkNhblZtY2prcFB5d2pOV2hjWUQwbVhYdHhhVkJSfDJeMjB8MTozMlxuICAgICAgcHVzaDogJ2NyeXB0bycsXG4gICAgICByZWc6IC9eY3J5cHRvOihcXGQqKSAoW1xcd19dKikgKFxcUyopKD86IChcXFMqKSk/LyxcbiAgICAgIG5hbWVzOiBbJ2lkJywgJ3N1aXRlJywgJ2NvbmZpZycsICdzZXNzaW9uQ29uZmlnJ10sXG4gICAgICBmb3JtYXQ6IGZ1bmN0aW9uIChvKSB7XG4gICAgICAgIHJldHVybiAoby5zZXNzaW9uQ29uZmlnICE9IG51bGwpID9cbiAgICAgICAgICBcImNyeXB0bzolZCAlcyAlcyAlc1wiOlxuICAgICAgICAgIFwiY3J5cHRvOiVkICVzICVzXCI7XG4gICAgICB9XG4gICAgfSxcbiAgICB7IC8vYT1zZXR1cDphY3RwYXNzXG4gICAgICBuYW1lOiAnc2V0dXAnLFxuICAgICAgcmVnOiAvXnNldHVwOihcXHcqKS8sXG4gICAgICBmb3JtYXQ6IFwic2V0dXA6JXNcIlxuICAgIH0sXG4gICAgeyAvL2E9bWlkOjFcbiAgICAgIG5hbWU6ICdtaWQnLFxuICAgICAgcmVnOiAvXm1pZDooW15cXHNdKikvLFxuICAgICAgZm9ybWF0OiBcIm1pZDolc1wiXG4gICAgfSxcbiAgICB7IC8vYT1tc2lkOjBjOGIwNjRkLWQ4MDctNDNiNC1iNDM0LWY5MmE4ODlkODU4NyA5ODE3ODY4NS1kNDA5LTQ2ZTAtOGUxNi03ZWYwZGIwZGI2NGFcbiAgICAgIG5hbWU6ICdtc2lkJyxcbiAgICAgIHJlZzogL15tc2lkOiguKikvLFxuICAgICAgZm9ybWF0OiBcIm1zaWQ6JXNcIlxuICAgIH0sXG4gICAgeyAvL2E9cHRpbWU6MjBcbiAgICAgIG5hbWU6ICdwdGltZScsXG4gICAgICByZWc6IC9ecHRpbWU6KFxcZCopLyxcbiAgICAgIGZvcm1hdDogXCJwdGltZTolZFwiXG4gICAgfSxcbiAgICB7IC8vYT1tYXhwdGltZTo2MFxuICAgICAgbmFtZTogJ21heHB0aW1lJyxcbiAgICAgIHJlZzogL15tYXhwdGltZTooXFxkKikvLFxuICAgICAgZm9ybWF0OiBcIm1heHB0aW1lOiVkXCJcbiAgICB9LFxuICAgIHsgLy9hPXNlbmRyZWN2XG4gICAgICBuYW1lOiAnZGlyZWN0aW9uJyxcbiAgICAgIHJlZzogL14oc2VuZHJlY3Z8cmVjdm9ubHl8c2VuZG9ubHl8aW5hY3RpdmUpL1xuICAgIH0sXG4gICAgeyAvL2E9aWNlLWxpdGVcbiAgICAgIG5hbWU6ICdpY2VsaXRlJyxcbiAgICAgIHJlZzogL14oaWNlLWxpdGUpL1xuICAgIH0sXG4gICAgeyAvL2E9aWNlLXVmcmFnOkY3Z0lcbiAgICAgIG5hbWU6ICdpY2VVZnJhZycsXG4gICAgICByZWc6IC9eaWNlLXVmcmFnOihcXFMqKS8sXG4gICAgICBmb3JtYXQ6IFwiaWNlLXVmcmFnOiVzXCJcbiAgICB9LFxuICAgIHsgLy9hPWljZS1wd2Q6eDljbWwvWXppY2hWMitYbGhpTXU4Z1xuICAgICAgbmFtZTogJ2ljZVB3ZCcsXG4gICAgICByZWc6IC9eaWNlLXB3ZDooXFxTKikvLFxuICAgICAgZm9ybWF0OiBcImljZS1wd2Q6JXNcIlxuICAgIH0sXG4gICAgeyAvL2E9ZmluZ2VycHJpbnQ6U0hBLTEgMDA6MTE6MjI6MzM6NDQ6NTU6NjY6Nzc6ODg6OTk6QUE6QkI6Q0M6REQ6RUU6RkY6MDA6MTE6MjI6MzNcbiAgICAgIG5hbWU6ICdmaW5nZXJwcmludCcsXG4gICAgICByZWc6IC9eZmluZ2VycHJpbnQ6KFxcUyopIChcXFMqKS8sXG4gICAgICBuYW1lczogWyd0eXBlJywgJ2hhc2gnXSxcbiAgICAgIGZvcm1hdDogXCJmaW5nZXJwcmludDolcyAlc1wiXG4gICAgfSxcbiAgICB7XG4gICAgICAvL2E9Y2FuZGlkYXRlOjAgMSBVRFAgMjExMzY2NzMyNyAyMDMuMC4xMTMuMSA1NDQwMCB0eXAgaG9zdFxuICAgICAgLy9hPWNhbmRpZGF0ZToxMTYyODc1MDgxIDEgdWRwIDIxMTM5MzcxNTEgMTkyLjE2OC4zNC43NSA2MDAxNyB0eXAgaG9zdCBnZW5lcmF0aW9uIDBcbiAgICAgIC8vYT1jYW5kaWRhdGU6MzI4OTkxMjk1NyAyIHVkcCAxODQ1NTAxNjk1IDE5My44NC43Ny4xOTQgNjAwMTcgdHlwIHNyZmx4IHJhZGRyIDE5Mi4xNjguMzQuNzUgcnBvcnQgNjAwMTcgZ2VuZXJhdGlvbiAwXG4gICAgICAvL2E9Y2FuZGlkYXRlOjIyOTgxNTYyMCAxIHRjcCAxNTE4MjgwNDQ3IDE5Mi4xNjguMTUwLjE5IDYwMDE3IHR5cCBob3N0IHRjcHR5cGUgYWN0aXZlIGdlbmVyYXRpb24gMFxuICAgICAgLy9hPWNhbmRpZGF0ZTozMjg5OTEyOTU3IDIgdGNwIDE4NDU1MDE2OTUgMTkzLjg0Ljc3LjE5NCA2MDAxNyB0eXAgc3JmbHggcmFkZHIgMTkyLjE2OC4zNC43NSBycG9ydCA2MDAxNyB0Y3B0eXBlIHBhc3NpdmUgZ2VuZXJhdGlvbiAwXG4gICAgICBwdXNoOidjYW5kaWRhdGVzJyxcbiAgICAgIHJlZzogL15jYW5kaWRhdGU6KFxcUyopIChcXGQqKSAoXFxTKikgKFxcZCopIChcXFMqKSAoXFxkKikgdHlwIChcXFMqKSg/OiByYWRkciAoXFxTKikgcnBvcnQgKFxcZCopKT8oPzogdGNwdHlwZSAoXFxTKikpPyg/OiBnZW5lcmF0aW9uIChcXGQqKSk/LyxcbiAgICAgIG5hbWVzOiBbJ2ZvdW5kYXRpb24nLCAnY29tcG9uZW50JywgJ3RyYW5zcG9ydCcsICdwcmlvcml0eScsICdpcCcsICdwb3J0JywgJ3R5cGUnLCAncmFkZHInLCAncnBvcnQnLCAndGNwdHlwZScsICdnZW5lcmF0aW9uJ10sXG4gICAgICBmb3JtYXQ6IGZ1bmN0aW9uIChvKSB7XG4gICAgICAgIHZhciBzdHIgPSBcImNhbmRpZGF0ZTolcyAlZCAlcyAlZCAlcyAlZCB0eXAgJXNcIjtcblxuICAgICAgICBzdHIgKz0gKG8ucmFkZHIgIT0gbnVsbCkgPyBcIiByYWRkciAlcyBycG9ydCAlZFwiIDogXCIldiV2XCI7XG5cbiAgICAgICAgLy8gTkI6IGNhbmRpZGF0ZSBoYXMgdGhyZWUgb3B0aW9uYWwgY2h1bmtzLCBzbyAldm9pZCBtaWRkbGVzIG9uZSBpZiBpdCdzIG1pc3NpbmdcbiAgICAgICAgc3RyICs9IChvLnRjcHR5cGUgIT0gbnVsbCkgPyBcIiB0Y3B0eXBlICVzXCIgOiBcIiV2XCI7XG5cbiAgICAgICAgaWYgKG8uZ2VuZXJhdGlvbiAhPSBudWxsKSB7XG4gICAgICAgICAgc3RyICs9IFwiIGdlbmVyYXRpb24gJWRcIjtcbiAgICAgICAgfVxuICAgICAgICByZXR1cm4gc3RyO1xuICAgICAgfVxuICAgIH0sXG4gICAgeyAvL2E9ZW5kLW9mLWNhbmRpZGF0ZXMgKGtlZXAgYWZ0ZXIgdGhlIGNhbmRpZGF0ZXMgbGluZSBmb3IgcmVhZGFiaWxpdHkpXG4gICAgICBuYW1lOiAnZW5kT2ZDYW5kaWRhdGVzJyxcbiAgICAgIHJlZzogL14oZW5kLW9mLWNhbmRpZGF0ZXMpL1xuICAgIH0sXG4gICAgeyAvL2E9cmVtb3RlLWNhbmRpZGF0ZXM6MSAyMDMuMC4xMTMuMSA1NDQwMCAyIDIwMy4wLjExMy4xIDU0NDAxIC4uLlxuICAgICAgbmFtZTogJ3JlbW90ZUNhbmRpZGF0ZXMnLFxuICAgICAgcmVnOiAvXnJlbW90ZS1jYW5kaWRhdGVzOiguKikvLFxuICAgICAgZm9ybWF0OiBcInJlbW90ZS1jYW5kaWRhdGVzOiVzXCJcbiAgICB9LFxuICAgIHsgLy9hPWljZS1vcHRpb25zOmdvb2dsZS1pY2VcbiAgICAgIG5hbWU6ICdpY2VPcHRpb25zJyxcbiAgICAgIHJlZzogL15pY2Utb3B0aW9uczooXFxTKikvLFxuICAgICAgZm9ybWF0OiBcImljZS1vcHRpb25zOiVzXCJcbiAgICB9LFxuICAgIHsgLy9hPXNzcmM6MjU2NjEwNzU2OSBjbmFtZTp0OVlVOE0xVXhURjhZMUExXG4gICAgICBwdXNoOiBcInNzcmNzXCIsXG4gICAgICByZWc6IC9ec3NyYzooXFxkKikgKFtcXHdfXSopOiguKikvLFxuICAgICAgbmFtZXM6IFsnaWQnLCAnYXR0cmlidXRlJywgJ3ZhbHVlJ10sXG4gICAgICBmb3JtYXQ6IFwic3NyYzolZCAlczolc1wiXG4gICAgfSxcbiAgICB7IC8vYT1zc3JjLWdyb3VwOkZFQyAxIDJcbiAgICAgIHB1c2g6IFwic3NyY0dyb3Vwc1wiLFxuICAgICAgcmVnOiAvXnNzcmMtZ3JvdXA6KFxcdyopICguKikvLFxuICAgICAgbmFtZXM6IFsnc2VtYW50aWNzJywgJ3NzcmNzJ10sXG4gICAgICBmb3JtYXQ6IFwic3NyYy1ncm91cDolcyAlc1wiXG4gICAgfSxcbiAgICB7IC8vYT1tc2lkLXNlbWFudGljOiBXTVMgSnZsYW01WDNTWDFPUDZwbjIweldvZ3ZhS0p6NUhqZjlPbmxWXG4gICAgICBuYW1lOiBcIm1zaWRTZW1hbnRpY1wiLFxuICAgICAgcmVnOiAvXm1zaWQtc2VtYW50aWM6XFxzPyhcXHcqKSAoXFxTKikvLFxuICAgICAgbmFtZXM6IFsnc2VtYW50aWMnLCAndG9rZW4nXSxcbiAgICAgIGZvcm1hdDogXCJtc2lkLXNlbWFudGljOiAlcyAlc1wiIC8vIHNwYWNlIGFmdGVyIFwiOlwiIGlzIG5vdCBhY2NpZGVudGFsXG4gICAgfSxcbiAgICB7IC8vYT1ncm91cDpCVU5ETEUgYXVkaW8gdmlkZW9cbiAgICAgIHB1c2g6ICdncm91cHMnLFxuICAgICAgcmVnOiAvXmdyb3VwOihcXHcqKSAoLiopLyxcbiAgICAgIG5hbWVzOiBbJ3R5cGUnLCAnbWlkcyddLFxuICAgICAgZm9ybWF0OiBcImdyb3VwOiVzICVzXCJcbiAgICB9LFxuICAgIHsgLy9hPXJ0Y3AtbXV4XG4gICAgICBuYW1lOiAncnRjcE11eCcsXG4gICAgICByZWc6IC9eKHJ0Y3AtbXV4KS9cbiAgICB9LFxuICAgIHsgLy9hPXJ0Y3AtcnNpemVcbiAgICAgIG5hbWU6ICdydGNwUnNpemUnLFxuICAgICAgcmVnOiAvXihydGNwLXJzaXplKS9cbiAgICB9LFxuICAgIHsgLy8gYW55IGE9IHRoYXQgd2UgZG9uJ3QgdW5kZXJzdGFuZCBpcyBrZXB0cyB2ZXJiYXRpbSBvbiBtZWRpYS5pbnZhbGlkXG4gICAgICBwdXNoOiAnaW52YWxpZCcsXG4gICAgICBuYW1lczogW1widmFsdWVcIl1cbiAgICB9XG4gIF1cbn07XG5cbi8vIHNldCBzZW5zaWJsZSBkZWZhdWx0cyB0byBhdm9pZCBwb2xsdXRpbmcgdGhlIGdyYW1tYXIgd2l0aCBib3JpbmcgZGV0YWlsc1xuT2JqZWN0LmtleXMoZ3JhbW1hcikuZm9yRWFjaChmdW5jdGlvbiAoa2V5KSB7XG4gIHZhciBvYmpzID0gZ3JhbW1hcltrZXldO1xuICBvYmpzLmZvckVhY2goZnVuY3Rpb24gKG9iaikge1xuICAgIGlmICghb2JqLnJlZykge1xuICAgICAgb2JqLnJlZyA9IC8oLiopLztcbiAgICB9XG4gICAgaWYgKCFvYmouZm9ybWF0KSB7XG4gICAgICBvYmouZm9ybWF0ID0gXCIlc1wiO1xuICAgIH1cbiAgfSk7XG59KTtcbiIsInZhciBwYXJzZXIgPSByZXF1aXJlKCcuL3BhcnNlcicpO1xudmFyIHdyaXRlciA9IHJlcXVpcmUoJy4vd3JpdGVyJyk7XG5cbmV4cG9ydHMud3JpdGUgPSB3cml0ZXI7XG5leHBvcnRzLnBhcnNlID0gcGFyc2VyLnBhcnNlO1xuZXhwb3J0cy5wYXJzZUZtdHBDb25maWcgPSBwYXJzZXIucGFyc2VGbXRwQ29uZmlnO1xuZXhwb3J0cy5wYXJzZVBheWxvYWRzID0gcGFyc2VyLnBhcnNlUGF5bG9hZHM7XG5leHBvcnRzLnBhcnNlUmVtb3RlQ2FuZGlkYXRlcyA9IHBhcnNlci5wYXJzZVJlbW90ZUNhbmRpZGF0ZXM7XG4iLCJ2YXIgdG9JbnRJZkludCA9IGZ1bmN0aW9uICh2KSB7XG4gIHJldHVybiBTdHJpbmcoTnVtYmVyKHYpKSA9PT0gdiA/IE51bWJlcih2KSA6IHY7XG59O1xuXG52YXIgYXR0YWNoUHJvcGVydGllcyA9IGZ1bmN0aW9uIChtYXRjaCwgbG9jYXRpb24sIG5hbWVzLCByYXdOYW1lKSB7XG4gIGlmIChyYXdOYW1lICYmICFuYW1lcykge1xuICAgIGxvY2F0aW9uW3Jhd05hbWVdID0gdG9JbnRJZkludChtYXRjaFsxXSk7XG4gIH1cbiAgZWxzZSB7XG4gICAgZm9yICh2YXIgaSA9IDA7IGkgPCBuYW1lcy5sZW5ndGg7IGkgKz0gMSkge1xuICAgICAgaWYgKG1hdGNoW2krMV0gIT0gbnVsbCkge1xuICAgICAgICBsb2NhdGlvbltuYW1lc1tpXV0gPSB0b0ludElmSW50KG1hdGNoW2krMV0pO1xuICAgICAgfVxuICAgIH1cbiAgfVxufTtcblxudmFyIHBhcnNlUmVnID0gZnVuY3Rpb24gKG9iaiwgbG9jYXRpb24sIGNvbnRlbnQpIHtcbiAgdmFyIG5lZWRzQmxhbmsgPSBvYmoubmFtZSAmJiBvYmoubmFtZXM7XG4gIGlmIChvYmoucHVzaCAmJiAhbG9jYXRpb25bb2JqLnB1c2hdKSB7XG4gICAgbG9jYXRpb25bb2JqLnB1c2hdID0gW107XG4gIH1cbiAgZWxzZSBpZiAobmVlZHNCbGFuayAmJiAhbG9jYXRpb25bb2JqLm5hbWVdKSB7XG4gICAgbG9jYXRpb25bb2JqLm5hbWVdID0ge307XG4gIH1cbiAgdmFyIGtleUxvY2F0aW9uID0gb2JqLnB1c2ggP1xuICAgIHt9IDogIC8vIGJsYW5rIG9iamVjdCB0aGF0IHdpbGwgYmUgcHVzaGVkXG4gICAgbmVlZHNCbGFuayA/IGxvY2F0aW9uW29iai5uYW1lXSA6IGxvY2F0aW9uOyAvLyBvdGhlcndpc2UsIG5hbWVkIGxvY2F0aW9uIG9yIHJvb3RcblxuICBhdHRhY2hQcm9wZXJ0aWVzKGNvbnRlbnQubWF0Y2gob2JqLnJlZyksIGtleUxvY2F0aW9uLCBvYmoubmFtZXMsIG9iai5uYW1lKTtcblxuICBpZiAob2JqLnB1c2gpIHtcbiAgICBsb2NhdGlvbltvYmoucHVzaF0ucHVzaChrZXlMb2NhdGlvbik7XG4gIH1cbn07XG5cbnZhciBncmFtbWFyID0gcmVxdWlyZSgnLi9ncmFtbWFyJyk7XG52YXIgdmFsaWRMaW5lID0gUmVnRXhwLnByb3RvdHlwZS50ZXN0LmJpbmQoL14oW2Etel0pPSguKikvKTtcblxuZXhwb3J0cy5wYXJzZSA9IGZ1bmN0aW9uIChzZHApIHtcbiAgdmFyIHNlc3Npb24gPSB7fVxuICAgICwgbWVkaWEgPSBbXVxuICAgICwgbG9jYXRpb24gPSBzZXNzaW9uOyAvLyBwb2ludHMgYXQgd2hlcmUgcHJvcGVydGllcyBnbyB1bmRlciAob25lIG9mIHRoZSBhYm92ZSlcblxuICAvLyBwYXJzZSBsaW5lcyB3ZSB1bmRlcnN0YW5kXG4gIHNkcC5zcGxpdCgvKFxcclxcbnxcXHJ8XFxuKS8pLmZpbHRlcih2YWxpZExpbmUpLmZvckVhY2goZnVuY3Rpb24gKGwpIHtcbiAgICB2YXIgdHlwZSA9IGxbMF07XG4gICAgdmFyIGNvbnRlbnQgPSBsLnNsaWNlKDIpO1xuICAgIGlmICh0eXBlID09PSAnbScpIHtcbiAgICAgIG1lZGlhLnB1c2goe3J0cDogW10sIGZtdHA6IFtdfSk7XG4gICAgICBsb2NhdGlvbiA9IG1lZGlhW21lZGlhLmxlbmd0aC0xXTsgLy8gcG9pbnQgYXQgbGF0ZXN0IG1lZGlhIGxpbmVcbiAgICB9XG5cbiAgICBmb3IgKHZhciBqID0gMDsgaiA8IChncmFtbWFyW3R5cGVdIHx8IFtdKS5sZW5ndGg7IGogKz0gMSkge1xuICAgICAgdmFyIG9iaiA9IGdyYW1tYXJbdHlwZV1bal07XG4gICAgICBpZiAob2JqLnJlZy50ZXN0KGNvbnRlbnQpKSB7XG4gICAgICAgIHJldHVybiBwYXJzZVJlZyhvYmosIGxvY2F0aW9uLCBjb250ZW50KTtcbiAgICAgIH1cbiAgICB9XG4gIH0pO1xuXG4gIHNlc3Npb24ubWVkaWEgPSBtZWRpYTsgLy8gbGluayBpdCB1cFxuICByZXR1cm4gc2Vzc2lvbjtcbn07XG5cbnZhciBmbXRwUmVkdWNlciA9IGZ1bmN0aW9uIChhY2MsIGV4cHIpIHtcbiAgdmFyIHMgPSBleHByLnNwbGl0KCc9Jyk7XG4gIGlmIChzLmxlbmd0aCA9PT0gMikge1xuICAgIGFjY1tzWzBdXSA9IHRvSW50SWZJbnQoc1sxXSk7XG4gIH1cbiAgcmV0dXJuIGFjYztcbn07XG5cbmV4cG9ydHMucGFyc2VGbXRwQ29uZmlnID0gZnVuY3Rpb24gKHN0cikge1xuICByZXR1cm4gc3RyLnNwbGl0KC9cXDtcXHM/LykucmVkdWNlKGZtdHBSZWR1Y2VyLCB7fSk7XG59O1xuXG5leHBvcnRzLnBhcnNlUGF5bG9hZHMgPSBmdW5jdGlvbiAoc3RyKSB7XG4gIHJldHVybiBzdHIuc3BsaXQoJyAnKS5tYXAoTnVtYmVyKTtcbn07XG5cbmV4cG9ydHMucGFyc2VSZW1vdGVDYW5kaWRhdGVzID0gZnVuY3Rpb24gKHN0cikge1xuICB2YXIgY2FuZGlkYXRlcyA9IFtdO1xuICB2YXIgcGFydHMgPSBzdHIuc3BsaXQoJyAnKS5tYXAodG9JbnRJZkludCk7XG4gIGZvciAodmFyIGkgPSAwOyBpIDwgcGFydHMubGVuZ3RoOyBpICs9IDMpIHtcbiAgICBjYW5kaWRhdGVzLnB1c2goe1xuICAgICAgY29tcG9uZW50OiBwYXJ0c1tpXSxcbiAgICAgIGlwOiBwYXJ0c1tpICsgMV0sXG4gICAgICBwb3J0OiBwYXJ0c1tpICsgMl1cbiAgICB9KTtcbiAgfVxuICByZXR1cm4gY2FuZGlkYXRlcztcbn07XG4iLCJ2YXIgZ3JhbW1hciA9IHJlcXVpcmUoJy4vZ3JhbW1hcicpO1xuXG4vLyBjdXN0b21pemVkIHV0aWwuZm9ybWF0IC0gZGlzY2FyZHMgZXhjZXNzIGFyZ3VtZW50cyBhbmQgY2FuIHZvaWQgbWlkZGxlIG9uZXNcbnZhciBmb3JtYXRSZWdFeHAgPSAvJVtzZHYlXS9nO1xudmFyIGZvcm1hdCA9IGZ1bmN0aW9uIChmb3JtYXRTdHIpIHtcbiAgdmFyIGkgPSAxO1xuICB2YXIgYXJncyA9IGFyZ3VtZW50cztcbiAgdmFyIGxlbiA9IGFyZ3MubGVuZ3RoO1xuICByZXR1cm4gZm9ybWF0U3RyLnJlcGxhY2UoZm9ybWF0UmVnRXhwLCBmdW5jdGlvbiAoeCkge1xuICAgIGlmIChpID49IGxlbikge1xuICAgICAgcmV0dXJuIHg7IC8vIG1pc3NpbmcgYXJndW1lbnRcbiAgICB9XG4gICAgdmFyIGFyZyA9IGFyZ3NbaV07XG4gICAgaSArPSAxO1xuICAgIHN3aXRjaCAoeCkge1xuICAgICAgY2FzZSAnJSUnOlxuICAgICAgICByZXR1cm4gJyUnO1xuICAgICAgY2FzZSAnJXMnOlxuICAgICAgICByZXR1cm4gU3RyaW5nKGFyZyk7XG4gICAgICBjYXNlICclZCc6XG4gICAgICAgIHJldHVybiBOdW1iZXIoYXJnKTtcbiAgICAgIGNhc2UgJyV2JzpcbiAgICAgICAgcmV0dXJuICcnO1xuICAgIH1cbiAgfSk7XG4gIC8vIE5COiB3ZSBkaXNjYXJkIGV4Y2VzcyBhcmd1bWVudHMgLSB0aGV5IGFyZSB0eXBpY2FsbHkgdW5kZWZpbmVkIGZyb20gbWFrZUxpbmVcbn07XG5cbnZhciBtYWtlTGluZSA9IGZ1bmN0aW9uICh0eXBlLCBvYmosIGxvY2F0aW9uKSB7XG4gIHZhciBzdHIgPSBvYmouZm9ybWF0IGluc3RhbmNlb2YgRnVuY3Rpb24gP1xuICAgIChvYmouZm9ybWF0KG9iai5wdXNoID8gbG9jYXRpb24gOiBsb2NhdGlvbltvYmoubmFtZV0pKSA6XG4gICAgb2JqLmZvcm1hdDtcblxuICB2YXIgYXJncyA9IFt0eXBlICsgJz0nICsgc3RyXTtcbiAgaWYgKG9iai5uYW1lcykge1xuICAgIGZvciAodmFyIGkgPSAwOyBpIDwgb2JqLm5hbWVzLmxlbmd0aDsgaSArPSAxKSB7XG4gICAgICB2YXIgbiA9IG9iai5uYW1lc1tpXTtcbiAgICAgIGlmIChvYmoubmFtZSkge1xuICAgICAgICBhcmdzLnB1c2gobG9jYXRpb25bb2JqLm5hbWVdW25dKTtcbiAgICAgIH1cbiAgICAgIGVsc2UgeyAvLyBmb3IgbUxpbmUgYW5kIHB1c2ggYXR0cmlidXRlc1xuICAgICAgICBhcmdzLnB1c2gobG9jYXRpb25bb2JqLm5hbWVzW2ldXSk7XG4gICAgICB9XG4gICAgfVxuICB9XG4gIGVsc2Uge1xuICAgIGFyZ3MucHVzaChsb2NhdGlvbltvYmoubmFtZV0pO1xuICB9XG4gIHJldHVybiBmb3JtYXQuYXBwbHkobnVsbCwgYXJncyk7XG59O1xuXG4vLyBSRkMgc3BlY2lmaWVkIG9yZGVyXG4vLyBUT0RPOiBleHRlbmQgdGhpcyB3aXRoIGFsbCB0aGUgcmVzdFxudmFyIGRlZmF1bHRPdXRlck9yZGVyID0gW1xuICAndicsICdvJywgJ3MnLCAnaScsXG4gICd1JywgJ2UnLCAncCcsICdjJyxcbiAgJ2InLCAndCcsICdyJywgJ3onLCAnYSdcbl07XG52YXIgZGVmYXVsdElubmVyT3JkZXIgPSBbJ2knLCAnYycsICdiJywgJ2EnXTtcblxuXG5tb2R1bGUuZXhwb3J0cyA9IGZ1bmN0aW9uIChzZXNzaW9uLCBvcHRzKSB7XG4gIG9wdHMgPSBvcHRzIHx8IHt9O1xuICAvLyBlbnN1cmUgY2VydGFpbiBwcm9wZXJ0aWVzIGV4aXN0XG4gIGlmIChzZXNzaW9uLnZlcnNpb24gPT0gbnVsbCkge1xuICAgIHNlc3Npb24udmVyc2lvbiA9IDA7IC8vIFwidj0wXCIgbXVzdCBiZSB0aGVyZSAob25seSBkZWZpbmVkIHZlcnNpb24gYXRtKVxuICB9XG4gIGlmIChzZXNzaW9uLm5hbWUgPT0gbnVsbCkge1xuICAgIHNlc3Npb24ubmFtZSA9IFwiIFwiOyAvLyBcInM9IFwiIG11c3QgYmUgdGhlcmUgaWYgbm8gbWVhbmluZ2Z1bCBuYW1lIHNldFxuICB9XG4gIHNlc3Npb24ubWVkaWEuZm9yRWFjaChmdW5jdGlvbiAobUxpbmUpIHtcbiAgICBpZiAobUxpbmUucGF5bG9hZHMgPT0gbnVsbCkge1xuICAgICAgbUxpbmUucGF5bG9hZHMgPSBcIlwiO1xuICAgIH1cbiAgfSk7XG5cbiAgdmFyIG91dGVyT3JkZXIgPSBvcHRzLm91dGVyT3JkZXIgfHwgZGVmYXVsdE91dGVyT3JkZXI7XG4gIHZhciBpbm5lck9yZGVyID0gb3B0cy5pbm5lck9yZGVyIHx8IGRlZmF1bHRJbm5lck9yZGVyO1xuICB2YXIgc2RwID0gW107XG5cbiAgLy8gbG9vcCB0aHJvdWdoIG91dGVyT3JkZXIgZm9yIG1hdGNoaW5nIHByb3BlcnRpZXMgb24gc2Vzc2lvblxuICBvdXRlck9yZGVyLmZvckVhY2goZnVuY3Rpb24gKHR5cGUpIHtcbiAgICBncmFtbWFyW3R5cGVdLmZvckVhY2goZnVuY3Rpb24gKG9iaikge1xuICAgICAgaWYgKG9iai5uYW1lIGluIHNlc3Npb24gJiYgc2Vzc2lvbltvYmoubmFtZV0gIT0gbnVsbCkge1xuICAgICAgICBzZHAucHVzaChtYWtlTGluZSh0eXBlLCBvYmosIHNlc3Npb24pKTtcbiAgICAgIH1cbiAgICAgIGVsc2UgaWYgKG9iai5wdXNoIGluIHNlc3Npb24gJiYgc2Vzc2lvbltvYmoucHVzaF0gIT0gbnVsbCkge1xuICAgICAgICBzZXNzaW9uW29iai5wdXNoXS5mb3JFYWNoKGZ1bmN0aW9uIChlbCkge1xuICAgICAgICAgIHNkcC5wdXNoKG1ha2VMaW5lKHR5cGUsIG9iaiwgZWwpKTtcbiAgICAgICAgfSk7XG4gICAgICB9XG4gICAgfSk7XG4gIH0pO1xuXG4gIC8vIHRoZW4gZm9yIGVhY2ggbWVkaWEgbGluZSwgZm9sbG93IHRoZSBpbm5lck9yZGVyXG4gIHNlc3Npb24ubWVkaWEuZm9yRWFjaChmdW5jdGlvbiAobUxpbmUpIHtcbiAgICBzZHAucHVzaChtYWtlTGluZSgnbScsIGdyYW1tYXIubVswXSwgbUxpbmUpKTtcblxuICAgIGlubmVyT3JkZXIuZm9yRWFjaChmdW5jdGlvbiAodHlwZSkge1xuICAgICAgZ3JhbW1hclt0eXBlXS5mb3JFYWNoKGZ1bmN0aW9uIChvYmopIHtcbiAgICAgICAgaWYgKG9iai5uYW1lIGluIG1MaW5lICYmIG1MaW5lW29iai5uYW1lXSAhPSBudWxsKSB7XG4gICAgICAgICAgc2RwLnB1c2gobWFrZUxpbmUodHlwZSwgb2JqLCBtTGluZSkpO1xuICAgICAgICB9XG4gICAgICAgIGVsc2UgaWYgKG9iai5wdXNoIGluIG1MaW5lICYmIG1MaW5lW29iai5wdXNoXSAhPSBudWxsKSB7XG4gICAgICAgICAgbUxpbmVbb2JqLnB1c2hdLmZvckVhY2goZnVuY3Rpb24gKGVsKSB7XG4gICAgICAgICAgICBzZHAucHVzaChtYWtlTGluZSh0eXBlLCBvYmosIGVsKSk7XG4gICAgICAgICAgfSk7XG4gICAgICAgIH1cbiAgICAgIH0pO1xuICAgIH0pO1xuICB9KTtcblxuICByZXR1cm4gc2RwLmpvaW4oJ1xcclxcbicpICsgJ1xcclxcbic7XG59O1xuIiwiLyogQ29weXJpZ2h0IEAgMjAxNSBBdGxhc3NpYW4gUHR5IEx0ZFxuICpcbiAqIExpY2Vuc2VkIHVuZGVyIHRoZSBBcGFjaGUgTGljZW5zZSwgVmVyc2lvbiAyLjAgKHRoZSBcIkxpY2Vuc2VcIik7XG4gKiB5b3UgbWF5IG5vdCB1c2UgdGhpcyBmaWxlIGV4Y2VwdCBpbiBjb21wbGlhbmNlIHdpdGggdGhlIExpY2Vuc2UuXG4gKiBZb3UgbWF5IG9idGFpbiBhIGNvcHkgb2YgdGhlIExpY2Vuc2UgYXRcbiAqXG4gKiAgICAgaHR0cDovL3d3dy5hcGFjaGUub3JnL2xpY2Vuc2VzL0xJQ0VOU0UtMi4wXG4gKlxuICogVW5sZXNzIHJlcXVpcmVkIGJ5IGFwcGxpY2FibGUgbGF3IG9yIGFncmVlZCB0byBpbiB3cml0aW5nLCBzb2Z0d2FyZVxuICogZGlzdHJpYnV0ZWQgdW5kZXIgdGhlIExpY2Vuc2UgaXMgZGlzdHJpYnV0ZWQgb24gYW4gXCJBUyBJU1wiIEJBU0lTLFxuICogV0lUSE9VVCBXQVJSQU5USUVTIE9SIENPTkRJVElPTlMgT0YgQU5ZIEtJTkQsIGVpdGhlciBleHByZXNzIG9yIGltcGxpZWQuXG4gKiBTZWUgdGhlIExpY2Vuc2UgZm9yIHRoZSBzcGVjaWZpYyBsYW5ndWFnZSBnb3Zlcm5pbmcgcGVybWlzc2lvbnMgYW5kXG4gKiBsaW1pdGF0aW9ucyB1bmRlciB0aGUgTGljZW5zZS5cbiAqL1xuXG52YXIgdHJhbnNmb3JtID0gcmVxdWlyZSgnc2RwLXRyYW5zZm9ybScpO1xudmFyIHRyYW5zZm9ybVV0aWxzID0gcmVxdWlyZSgnLi90cmFuc2Zvcm0tdXRpbHMnKTtcbnZhciBwYXJzZVNzcmNzID0gdHJhbnNmb3JtVXRpbHMucGFyc2VTc3JjcztcbnZhciB3cml0ZVNzcmNzID0gdHJhbnNmb3JtVXRpbHMud3JpdGVTc3JjcztcblxuLy9yZWdpb24gQ29uc3RhbnRzXG5cbnZhciBERUZBVUxUX05VTV9PRl9MQVlFUlMgPSAzO1xuXG4vL2VuZHJlZ2lvblxuXG4vL3JlZ2lvbiBDdG9yXG5cbmZ1bmN0aW9uIFNpbXVsY2FzdChvcHRpb25zKSB7XG5cbiAgICB0aGlzLm9wdGlvbnMgPSBvcHRpb25zID8gb3B0aW9ucyA6IHt9O1xuXG4gICAgaWYgKCF0aGlzLm9wdGlvbnMubnVtT2ZMYXllcnMpIHtcbiAgICAgICAgdGhpcy5vcHRpb25zLm51bU9mTGF5ZXJzID0gREVGQVVMVF9OVU1fT0ZfTEFZRVJTO1xuICAgIH1cblxuICAgIHRoaXMubGF5ZXJzID0gW107XG59XG5cbi8vZW5kcmVnaW9uXG5cbi8vcmVnaW9uIFN0YXRlbGVzcyBwcml2YXRlIHV0aWxpdHkgZnVuY3Rpb25zXG5cbi8qKlxuICogUmV0dXJucyBhIHJhbmRvbSBpbnRlZ2VyIGJldHdlZW4gbWluIChpbmNsdWRlZCkgYW5kIG1heCAoZXhjbHVkZWQpXG4gKiBVc2luZyBNYXRoLnJvdW5kKCkgZ2l2ZXMgYSBub24tdW5pZm9ybSBkaXN0cmlidXRpb24hXG4gKiBAcmV0dXJucyB7bnVtYmVyfVxuICovXG5mdW5jdGlvbiBnZW5lcmF0ZVNTUkMoKSB7XG4gICAgdmFyIG1pbiA9IDAsIG1heCA9IDB4ZmZmZmZmZmY7XG4gICAgcmV0dXJuIE1hdGguZmxvb3IoTWF0aC5yYW5kb20oKSAqIChtYXggLSBtaW4pKSArIG1pbjtcbn07XG5cbmZ1bmN0aW9uIHByb2Nlc3NWaWRlbyhzZXNzaW9uLCBhY3Rpb24pIHtcbiAgICBpZiAoc2Vzc2lvbiA9PSBudWxsIHx8ICFBcnJheS5pc0FycmF5KHNlc3Npb24ubWVkaWEpKSB7XG4gICAgICAgIHJldHVybjtcbiAgICB9XG5cbiAgICBzZXNzaW9uLm1lZGlhLmZvckVhY2goZnVuY3Rpb24gKG1MaW5lKSB7XG4gICAgICAgIGlmIChtTGluZS50eXBlID09PSAndmlkZW8nKSB7XG4gICAgICAgICAgICBhY3Rpb24obUxpbmUpO1xuICAgICAgICB9XG4gICAgfSk7XG59XG5cbmZ1bmN0aW9uIHZhbGlkYXRlRGVzY3JpcHRpb24oZGVzYylcbntcbiAgICByZXR1cm4gZGVzYyAmJiBkZXNjICE9IG51bGxcbiAgICAgICAgJiYgZGVzYy50eXBlICYmIGRlc2MudHlwZSAhPSAnJ1xuICAgICAgICAmJiBkZXNjLnNkcCAmJiBkZXNjLnNkcCAhPSAnJztcbn1cblxuZnVuY3Rpb24gZXhwbG9kZVJlbW90ZVNpbXVsY2FzdChtTGluZSkge1xuXG4gICAgaWYgKCFtTGluZSB8fCAhQXJyYXkuaXNBcnJheShtTGluZS5zc3JjR3JvdXBzKSkge1xuICAgICAgICByZXR1cm47XG4gICAgfVxuXG4gICAgdmFyIHNvdXJjZXMgPSBwYXJzZVNzcmNzKG1MaW5lKTtcbiAgICB2YXIgb3JkZXIgPSBbXTtcblxuICAgIC8vIEZpbmQgdGhlIFNJTSBncm91cCBhbmQgZXhwbG9kZSBpdHMgc291cmNlcy5cbiAgICB2YXIgaiA9IG1MaW5lLnNzcmNHcm91cHMubGVuZ3RoO1xuICAgIHdoaWxlIChqLS0pIHtcblxuICAgICAgICBpZiAobUxpbmUuc3NyY0dyb3Vwc1tqXS5zZW1hbnRpY3MgIT09ICdTSU0nKSB7XG4gICAgICAgICAgICBjb250aW51ZTtcbiAgICAgICAgfVxuXG4gICAgICAgIHZhciBzaW11bGNhc3RTc3JjcyA9IG1MaW5lLnNzcmNHcm91cHNbal0uc3NyY3Muc3BsaXQoJyAnKTtcblxuICAgICAgICBmb3IgKHZhciBpID0gMDsgaSA8IHNpbXVsY2FzdFNzcmNzLmxlbmd0aDsgaSsrKSB7XG5cbiAgICAgICAgICAgIHZhciBzc3JjID0gc2ltdWxjYXN0U3NyY3NbaV07XG4gICAgICAgICAgICBvcmRlci5wdXNoKHNzcmMpO1xuXG4gICAgICAgICAgICB2YXIgcGFydHMgPSBzb3VyY2VzW3NzcmNdLm1zaWQuc3BsaXQoJyAnKTtcbiAgICAgICAgICAgIHNvdXJjZXNbc3NyY10ubXNpZCA9IFtwYXJ0c1swXSwgJy8nLCBpLCAnICcsIHBhcnRzWzFdLCAnLycsIGldLmpvaW4oJycpO1xuICAgICAgICAgICAgc291cmNlc1tzc3JjXS5jbmFtZSA9IFtzb3VyY2VzW3NzcmNdLmNuYW1lLCAnLycsIGldLmpvaW4oJycpO1xuXG4gICAgICAgICAgICAvLyBSZW1vdmUgYWxsIHRoZSBncm91cHMgdGhhdCB0aGlzIFNTUkMgcGFydGljaXBhdGVzIGluLlxuICAgICAgICAgICAgbUxpbmUuc3NyY0dyb3Vwcy5mb3JFYWNoKGZ1bmN0aW9uIChyZWxhdGVkR3JvdXApIHtcbiAgICAgICAgICAgICAgICBpZiAocmVsYXRlZEdyb3VwLnNlbWFudGljcyA9PT0gJ1NJTScpIHtcbiAgICAgICAgICAgICAgICAgICAgcmV0dXJuO1xuICAgICAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgICAgIHZhciByZWxhdGVkU3NyY3MgPSByZWxhdGVkR3JvdXAuc3NyY3Muc3BsaXQoJyAnKTtcbiAgICAgICAgICAgICAgICBpZiAocmVsYXRlZFNzcmNzLmluZGV4T2Yoc3NyYykgPT09IC0xKSB7XG4gICAgICAgICAgICAgICAgICAgIHJldHVybjtcbiAgICAgICAgICAgICAgICB9XG5cbiAgICAgICAgICAgICAgICAvLyBOdWtlIGFsbCB0aGUgcmVsYXRlZCBTU1JDcy5cbiAgICAgICAgICAgICAgICByZWxhdGVkU3NyY3MuZm9yRWFjaChmdW5jdGlvbiAocmVsYXRlZFNTUkMpIHtcbiAgICAgICAgICAgICAgICAgICAgc291cmNlc1tyZWxhdGVkU1NSQ10ubXNpZCA9IHNvdXJjZXNbc3NyY10ubXNpZDtcbiAgICAgICAgICAgICAgICAgICAgc291cmNlc1tyZWxhdGVkU1NSQ10uY25hbWUgPSBzb3VyY2VzW3NzcmNdLmNuYW1lO1xuICAgICAgICAgICAgICAgICAgICBpZiAocmVsYXRlZFNTUkMgIT09IHNzcmMpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgIG9yZGVyLnB1c2gocmVsYXRlZFNTUkMpO1xuICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgfSk7XG5cbiAgICAgICAgICAgICAgICAvLyBTY2hlZHVsZSB0aGUgcmVsYXRlZCBncm91cCBmb3IgbnVraW5nLlxuICAgICAgICAgICAgfSlcbiAgICAgICAgfVxuXG4gICAgICAgIG1MaW5lLnNzcmNzID0gd3JpdGVTc3Jjcyhzb3VyY2VzLCBvcmRlcik7XG4gICAgICAgIG1MaW5lLnNzcmNHcm91cHMuc3BsaWNlKGosIDEpO1xuICAgIH07XG59XG5cbmZ1bmN0aW9uIGltcGxvZGVSZW1vdGVTaW11bGNhc3QobUxpbmUpIHtcblxuICAgIGlmICghbUxpbmUgfHwgIUFycmF5LmlzQXJyYXkobUxpbmUuc3NyY0dyb3VwcykpIHtcbiAgICAgICAgY29uc29sZS5pbmZvKCdIYWx0OiBUaGVyZSBhcmUgbm8gU1NSQyBncm91cHMgaW4gdGhlIHJlbW90ZSAnICtcbiAgICAgICAgICAgICAgICAnZGVzY3JpcHRpb24uJyk7XG4gICAgICAgIHJldHVybjtcbiAgICB9XG5cbiAgICB2YXIgc291cmNlcyA9IHBhcnNlU3NyY3MobUxpbmUpO1xuXG4gICAgLy8gRmluZCB0aGUgU0lNIGdyb3VwIGFuZCBudWtlIGl0LlxuICAgIG1MaW5lLnNzcmNHcm91cHMuZm9yRWFjaChmdW5jdGlvbiAoc2ltdWxjYXN0R3JvdXApIHtcbiAgICAgICAgaWYgKHNpbXVsY2FzdEdyb3VwLnNlbWFudGljcyAhPT0gJ1NJTScpIHtcbiAgICAgICAgICAgIHJldHVybjtcbiAgICAgICAgfVxuXG4gICAgICAgIGNvbnNvbGUuaW5mbyhcIkltcGxvZGluZyBTSU0gZ3JvdXA6IFwiICsgc2ltdWxjYXN0R3JvdXAuc3NyY3MpO1xuICAgICAgICAvLyBTY2hlZHVsZSB0aGUgU0lNIGdyb3VwIGZvciBudWtpbmcuXG4gICAgICAgIHNpbXVsY2FzdEdyb3VwLm51a2UgPSB0cnVlO1xuXG4gICAgICAgIHZhciBzaW11bGNhc3RTc3JjcyA9IHNpbXVsY2FzdEdyb3VwLnNzcmNzLnNwbGl0KCcgJyk7XG5cbiAgICAgICAgLy8gTnVrZSBhbGwgdGhlIGhpZ2hlciBsYXllciBTU1JDcy5cbiAgICAgICAgZm9yICh2YXIgaSA9IDE7IGkgPCBzaW11bGNhc3RTc3Jjcy5sZW5ndGg7IGkrKykge1xuXG4gICAgICAgICAgICB2YXIgc3NyYyA9IHNpbXVsY2FzdFNzcmNzW2ldO1xuICAgICAgICAgICAgZGVsZXRlIHNvdXJjZXNbc3NyY107XG5cbiAgICAgICAgICAgIC8vIFJlbW92ZSBhbGwgdGhlIGdyb3VwcyB0aGF0IHRoaXMgU1NSQyBwYXJ0aWNpcGF0ZXMgaW4uXG4gICAgICAgICAgICBtTGluZS5zc3JjR3JvdXBzLmZvckVhY2goZnVuY3Rpb24gKHJlbGF0ZWRHcm91cCkge1xuICAgICAgICAgICAgICAgIGlmIChyZWxhdGVkR3JvdXAuc2VtYW50aWNzID09PSAnU0lNJykge1xuICAgICAgICAgICAgICAgICAgICByZXR1cm47XG4gICAgICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICAgICAgdmFyIHJlbGF0ZWRTc3JjcyA9IHJlbGF0ZWRHcm91cC5zc3Jjcy5zcGxpdCgnICcpO1xuICAgICAgICAgICAgICAgIGlmIChyZWxhdGVkU3NyY3MuaW5kZXhPZihzc3JjKSA9PT0gLTEpIHtcbiAgICAgICAgICAgICAgICAgICAgcmV0dXJuO1xuICAgICAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgICAgIC8vIE51a2UgYWxsIHRoZSByZWxhdGVkIFNTUkNzLlxuICAgICAgICAgICAgICAgIHJlbGF0ZWRTc3Jjcy5mb3JFYWNoKGZ1bmN0aW9uIChyZWxhdGVkU1NSQykge1xuICAgICAgICAgICAgICAgICAgICBkZWxldGUgc291cmNlc1tyZWxhdGVkU1NSQ107XG4gICAgICAgICAgICAgICAgfSk7XG5cbiAgICAgICAgICAgICAgICAvLyBTY2hlZHVsZSB0aGUgcmVsYXRlZCBncm91cCBmb3IgbnVraW5nLlxuICAgICAgICAgICAgICAgIHJlbGF0ZWRHcm91cC5udWtlID0gdHJ1ZTtcbiAgICAgICAgICAgIH0pXG4gICAgICAgIH1cblxuICAgICAgICByZXR1cm47XG4gICAgfSk7XG5cbiAgICBtTGluZS5zc3JjcyA9IHdyaXRlU3NyY3Moc291cmNlcyk7XG5cbiAgICAvLyBOdWtlIGFsbCB0aGUgc2NoZWR1bGVkIGdyb3Vwcy5cbiAgICB2YXIgaSA9IG1MaW5lLnNzcmNHcm91cHMubGVuZ3RoO1xuICAgIHdoaWxlIChpLS0pIHtcbiAgICAgICAgaWYgKG1MaW5lLnNzcmNHcm91cHNbaV0ubnVrZSkge1xuICAgICAgICAgICAgbUxpbmUuc3NyY0dyb3Vwcy5zcGxpY2UoaSwgMSk7XG4gICAgICAgIH1cbiAgICB9XG59XG5cbmZ1bmN0aW9uIHJlbW92ZUdvb2dDb25mZXJlbmNlKG1MaW5lKSB7XG4gICAgaWYgKCFtTGluZSB8fCAhQXJyYXkuaXNBcnJheShtTGluZS5pbnZhbGlkKSkge1xuICAgICAgICByZXR1cm47XG4gICAgfVxuXG4gICAgdmFyIGkgPSBtTGluZS5pbnZhbGlkLmxlbmd0aDtcbiAgICB3aGlsZSAoaS0tKSB7XG4gICAgICAgIGlmIChtTGluZS5pbnZhbGlkW2ldLnZhbHVlID09ICd4LWdvb2dsZS1mbGFnOmNvbmZlcmVuY2UnKSB7XG4gICAgICAgICAgICBtTGluZS5pbnZhbGlkLnNwbGljZShpLCAxKTtcbiAgICAgICAgfVxuICAgIH1cbn1cblxuZnVuY3Rpb24gYXNzZXJ0R29vZ0NvbmZlcmVuY2UobUxpbmUpIHtcbiAgICBpZiAoIW1MaW5lKSB7XG4gICAgICAgIHJldHVybjtcbiAgICB9XG5cbiAgICBpZiAoIUFycmF5LmlzQXJyYXkobUxpbmUuaW52YWxpZCkpIHtcbiAgICAgICAgbUxpbmUuaW52YWxpZCA9IFtdO1xuICAgIH1cblxuICAgIGlmICghbUxpbmUuaW52YWxpZC5zb21lKFxuICAgICAgICAgICAgZnVuY3Rpb24gKGkpIHsgcmV0dXJuIGkudmFsdWUgPT09ICd4LWdvb2dsZS1mbGFnOmNvbmZlcmVuY2UnIH0pKSB7XG4gICAgICAgIG1MaW5lLmludmFsaWQucHVzaCh7J3ZhbHVlJzogJ3gtZ29vZ2xlLWZsYWc6Y29uZmVyZW5jZSd9KTtcbiAgICB9XG59XG5cbi8vZW5kcmVnaW9uXG5cbi8vcmVnaW9uIFwiUHJpdmF0ZVwiIGZ1bmN0aW9uc1xuXG4vKipcbiAqXG4gKiBAcGFyYW0gbUxpbmVcbiAqIEBwcml2YXRlXG4gKi9cblNpbXVsY2FzdC5wcm90b3R5cGUuX21heWJlSW5pdGlhbGl6ZUxheWVycyA9IGZ1bmN0aW9uKG1MaW5lKSB7XG5cbiAgICBpZiAoIW1MaW5lIHx8IG1MaW5lLnR5cGUgIT09ICd2aWRlbycpIHtcbiAgICAgICAgcmV0dXJuO1xuICAgIH1cblxuICAgIHZhciBzb3VyY2VzID0gcGFyc2VTc3JjcyhtTGluZSk7XG5cbiAgICBpZiAoT2JqZWN0LmtleXMoc291cmNlcykubGVuZ3RoID09PSAwKSB7XG5cbiAgICAgICAgLy8gbm8gc291cmNlcywgZGlzYWJsZSBzaW11bGNhc3QuXG4gICAgICAgIGlmICh0aGlzLmxheWVycy5sZW5ndGggIT09IDApIHtcbiAgICAgICAgICAgIHRoaXMubGF5ZXJzID0gW107XG4gICAgICAgIH1cblxuICAgICAgICByZXR1cm47XG4gICAgfVxuXG4gICAgLy8gZmluZCB0aGUgYmFzZSBsYXllciAod2UnbGwgcmV1c2UgaXRzIG1zaWQgYW5kIGNuYW1lKS5cbiAgICB2YXIgYmFzZUxheWVyU1NSQyA9IE9iamVjdC5rZXlzKHNvdXJjZXMpWzBdO1xuICAgIHZhciBiYXNlTGF5ZXIgPSBzb3VyY2VzW2Jhc2VMYXllclNTUkNdO1xuXG4gICAgLy8gdG9kbyhncCkgaGFuZGxlIHNjcmVlbiBzaGFyaW5nLlxuXG4gICAgLy8gY2hlY2sgaWYgYmFzZSBDTkFNRSBoYXMgY2hhbmdlZCBhbmQgcmVpbml0aWFsaXNlIGxheWVycy5cbiAgICBpZiAodGhpcy5sYXllcnMubGVuZ3RoID4gMFxuICAgICAgICAmJiBzb3VyY2VzW2Jhc2VMYXllclNTUkNdLmNuYW1lICE9PSB0aGlzLmxheWVyc1swXS5jbmFtZSkge1xuICAgICAgICB0aGlzLmxheWVycyA9IFtdO1xuICAgIH1cblxuICAgIC8vIChyZSlpbml0aWFsaXNlIGxheWVyc1xuICAgIGlmICh0aGlzLmxheWVycy5sZW5ndGggPCAxKSB7XG5cbiAgICAgICAgLy8gZmlyc3QgcHVzaCB0aGUgYmFzZSBsYXllci5cbiAgICAgICAgdGhpcy5sYXllcnMucHVzaCh7XG4gICAgICAgICAgICBzc3JjOiBiYXNlTGF5ZXJTU1JDLFxuICAgICAgICAgICAgbXNpZDogYmFzZUxheWVyLm1zaWQsXG4gICAgICAgICAgICBjbmFtZTogYmFzZUxheWVyLmNuYW1lXG4gICAgICAgIH0pO1xuXG4gICAgICAgIHZhciBydHggPSBmYWxzZTsgLy8gUkZDIDQ1ODhcbiAgICAgICAgaWYgKEFycmF5LmlzQXJyYXkobUxpbmUucnRwKSkge1xuICAgICAgICAgICAgcnR4ID0gbUxpbmUucnRwLnNvbWUoXG4gICAgICAgICAgICAgICAgZnVuY3Rpb24gKHJ0cG1hcCkgeyByZXR1cm4gcnRwbWFwLmNvZGVjID09PSAncnR4JzsgfSk7XG4gICAgICAgIH1cblxuICAgICAgICBpZiAocnR4KSB7XG4gICAgICAgICAgICB0aGlzLmxheWVyc1swXS5ydHggPSBnZW5lcmF0ZVNTUkMoKTtcbiAgICAgICAgfVxuXG4gICAgICAgIC8vIG5vdyBwdXNoIGFkZGl0aW9uYWwgbGF5ZXJzLlxuICAgICAgICBmb3IgKHZhciBpID0gMTsgaSA8IE1hdGgubWF4KDEsIHRoaXMub3B0aW9ucy5udW1PZkxheWVycyk7IGkrKykge1xuXG4gICAgICAgICAgICB2YXIgbGF5ZXIgPSB7IHNzcmM6IGdlbmVyYXRlU1NSQygpIH07XG4gICAgICAgICAgICBpZiAocnR4KSB7XG4gICAgICAgICAgICAgICAgbGF5ZXIucnR4ID0gZ2VuZXJhdGVTU1JDKCk7XG4gICAgICAgICAgICB9XG5cbiAgICAgICAgICAgIHRoaXMubGF5ZXJzLnB1c2gobGF5ZXIpO1xuICAgICAgICB9XG4gICAgfVxufTtcblxuLyoqXG4gKlxuICogQHBhcmFtIG1MaW5lXG4gKiBAcHJpdmF0ZVxuICovXG5TaW11bGNhc3QucHJvdG90eXBlLl9yZXN0b3JlU2ltdWxjYXN0VmlldyA9IGZ1bmN0aW9uKG1MaW5lKSB7XG4gICAgaWYgKG1MaW5lICYmIG1MaW5lLnR5cGUgPT09ICd2aWRlbycgJiYgdGhpcy5sYXllcnMubGVuZ3RoICE9PSAwKSB7XG5cbiAgICAgICAgdmFyIHNvdXJjZXMgPSB7fTtcblxuICAgICAgICB2YXIgbXNpZCA9IHRoaXMubGF5ZXJzWzBdLm1zaWQ7XG4gICAgICAgIHZhciBjbmFtZSA9IHRoaXMubGF5ZXJzWzBdLmNuYW1lO1xuICAgICAgICB2YXIgc2ltdWxjYXN0U3NyY3MgPSBbXTtcbiAgICAgICAgdmFyIHNzcmNHcm91cHMgPSBbXTtcblxuICAgICAgICBmb3IgKHZhciBpID0gMDsgaSA8IHRoaXMubGF5ZXJzLmxlbmd0aDsgaSsrKSB7XG4gICAgICAgICAgICB2YXIgbGF5ZXIgPSB0aGlzLmxheWVyc1tpXTtcblxuICAgICAgICAgICAgc291cmNlc1tsYXllci5zc3JjXSA9IHsgbXNpZDogbXNpZCwgY25hbWU6IGNuYW1lIH07XG4gICAgICAgICAgICBzaW11bGNhc3RTc3Jjcy5wdXNoKGxheWVyLnNzcmMpO1xuXG4gICAgICAgICAgICBpZiAobGF5ZXIucnR4KSB7XG5cbiAgICAgICAgICAgICAgICBzb3VyY2VzW2xheWVyLnJ0eF0gPSB7XG4gICAgICAgICAgICAgICAgICAgIG1zaWQ6IG1zaWQsXG4gICAgICAgICAgICAgICAgICAgIGNuYW1lOiBjbmFtZVxuICAgICAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgICAgIHNzcmNHcm91cHMucHVzaCh7XG4gICAgICAgICAgICAgICAgICAgIHNlbWFudGljczogJ0ZJRCcsXG4gICAgICAgICAgICAgICAgICAgIHNzcmNzOiBbbGF5ZXIuc3NyYywgbGF5ZXIucnR4XS5qb2luKCcgJylcbiAgICAgICAgICAgICAgICB9KTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgfVxuXG4gICAgICAgIHNzcmNHcm91cHMucHVzaCh7XG4gICAgICAgICAgICBzZW1hbnRpY3M6ICdTSU0nLFxuICAgICAgICAgICAgc3NyY3M6IHNpbXVsY2FzdFNzcmNzLmpvaW4oJyAnKVxuICAgICAgICB9KTtcblxuICAgICAgICBtTGluZS5zc3JjR3JvdXBzID0gc3NyY0dyb3VwcztcbiAgICAgICAgbUxpbmUuc3NyY3MgPSB3cml0ZVNzcmNzKHNvdXJjZXMpO1xuICAgIH1cbn1cblxuLy9lbmRyZWdpb25cblxuLy9yZWdpb24gXCJQdWJsaWNcIiBmdW5jdGlvbnNcblxuU2ltdWxjYXN0LnByb3RvdHlwZS5pc1N1cHBvcnRlZCA9IGZ1bmN0aW9uICgpIHtcbiAgICByZXR1cm4gd2luZG93LmNocm9tZTtcblxuICAgIC8vIFRPRE8gdGhpcyBuZWVkcyBpbXByb3ZlbWVudHMuIEZvciBleGFtcGxlIEkgZG91YnQgdGhhdCBDaHJvbWUgaW4gQW5kcm9pZFxuICAgIC8vIGhhcyBzaW11bGNhc3Qgc3VwcG9ydC4gQWxzbywgb25seSByZWNlbnQgdmVyc2lvbnMgb2YgQ2hyb21pdW0gaGF2ZSBuYXRpdmVcbiAgICAvLyBzaW11bGNhc3Qgc3VwcG9ydC5cbn1cblxuLyoqXG4gKlxuICogQHBhcmFtIGRlc2NcbiAqIEByZXR1cm5zIHtSVENTZXNzaW9uRGVzY3JpcHRpb259XG4gKi9cblNpbXVsY2FzdC5wcm90b3R5cGUubXVuZ2VSZW1vdGVEZXNjcmlwdGlvbiA9IGZ1bmN0aW9uIChkZXNjKSB7XG5cbiAgICBpZiAoIXZhbGlkYXRlRGVzY3JpcHRpb24oZGVzYykpIHtcbiAgICAgICAgcmV0dXJuIGRlc2M7XG4gICAgfVxuXG4gICAgdmFyIHNlc3Npb24gPSB0cmFuc2Zvcm0ucGFyc2UoZGVzYy5zZHApO1xuXG4gICAgdmFyIHNlbGYgPSB0aGlzO1xuICAgIHByb2Nlc3NWaWRlbyhzZXNzaW9uLCBmdW5jdGlvbiAobUxpbmUpIHtcblxuICAgICAgICAvLyBIYW5kbGUgc2ltdWxjYXN0IHJlY2VwdGlvbi5cbiAgICAgICAgaWYgKHNlbGYub3B0aW9ucy5leHBsb2RlUmVtb3RlU2ltdWxjYXN0KSB7XG4gICAgICAgICAgICBleHBsb2RlUmVtb3RlU2ltdWxjYXN0KG1MaW5lKTtcbiAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgIGltcGxvZGVSZW1vdGVTaW11bGNhc3QobUxpbmUpO1xuICAgICAgICB9XG5cbiAgICAgICAgLy8gSWYgbmF0aXZlIHNpbXVsY2FzdCBpcyBlbmFibGVkLCB3ZSBtdXN0IGFwcGVuZCB0aGUgeC1nb29nLWNvbmZlcmVuY2VcbiAgICAgICAgLy8gYXR0cmlidXRlIHRvIHRoZSBTRFAuXG4gICAgICAgIGlmIChzZWxmLmxheWVycy5sZW5ndGggPCAxKSB7XG4gICAgICAgICAgICByZW1vdmVHb29nQ29uZmVyZW5jZShtTGluZSk7XG4gICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICBhc3NlcnRHb29nQ29uZmVyZW5jZShtTGluZSk7XG4gICAgICAgIH1cbiAgICB9KTtcblxuICAgIHJldHVybiBuZXcgUlRDU2Vzc2lvbkRlc2NyaXB0aW9uKHtcbiAgICAgICAgdHlwZTogZGVzYy50eXBlLFxuICAgICAgICBzZHA6IHRyYW5zZm9ybS53cml0ZShzZXNzaW9uKVxuICAgIH0pO1xufTtcblxuLyoqXG4gKlxuICogQHBhcmFtIGRlc2NcbiAqIEByZXR1cm5zIHtSVENTZXNzaW9uRGVzY3JpcHRpb259XG4gKi9cblNpbXVsY2FzdC5wcm90b3R5cGUubXVuZ2VMb2NhbERlc2NyaXB0aW9uID0gZnVuY3Rpb24gKGRlc2MpIHtcblxuICAgIGlmICghdmFsaWRhdGVEZXNjcmlwdGlvbihkZXNjKSB8fCAhdGhpcy5pc1N1cHBvcnRlZCgpKSB7XG4gICAgICAgIHJldHVybiBkZXNjO1xuICAgIH1cblxuICAgIHZhciBzZXNzaW9uID0gdHJhbnNmb3JtLnBhcnNlKGRlc2Muc2RwKTtcblxuICAgIHZhciBzZWxmID0gdGhpcztcbiAgICBwcm9jZXNzVmlkZW8oc2Vzc2lvbiwgZnVuY3Rpb24gKG1MaW5lKSB7XG4gICAgICAgIC8vIEluaXRpYWxpemUgbmF0aXZlIHNpbXVsY2FzdCBsYXllcnMsIGlmIG5vdCBhbHJlYWR5IGRvbmUuXG4gICAgICAgIHNlbGYuX21heWJlSW5pdGlhbGl6ZUxheWVycyhtTGluZSk7XG5cbiAgICAgICAgLy8gVXBkYXRlIHRoZSBTRFAgd2l0aCB0aGUgc2ltdWxjYXN0IGxheWVycy5cbiAgICAgICAgc2VsZi5fcmVzdG9yZVNpbXVsY2FzdFZpZXcobUxpbmUpO1xuICAgIH0pO1xuXG4gICAgcmV0dXJuIG5ldyBSVENTZXNzaW9uRGVzY3JpcHRpb24oe1xuICAgICAgICB0eXBlOiBkZXNjLnR5cGUsXG4gICAgICAgIHNkcDogdHJhbnNmb3JtLndyaXRlKHNlc3Npb24pXG4gICAgfSk7XG59O1xuXG4vL2VuZHJlZ2lvblxuXG5tb2R1bGUuZXhwb3J0cyA9IFNpbXVsY2FzdDtcbiIsIi8qIENvcHlyaWdodCBAIDIwMTUgQXRsYXNzaWFuIFB0eSBMdGRcbiAqXG4gKiBMaWNlbnNlZCB1bmRlciB0aGUgQXBhY2hlIExpY2Vuc2UsIFZlcnNpb24gMi4wICh0aGUgXCJMaWNlbnNlXCIpO1xuICogeW91IG1heSBub3QgdXNlIHRoaXMgZmlsZSBleGNlcHQgaW4gY29tcGxpYW5jZSB3aXRoIHRoZSBMaWNlbnNlLlxuICogWW91IG1heSBvYnRhaW4gYSBjb3B5IG9mIHRoZSBMaWNlbnNlIGF0XG4gKlxuICogICAgIGh0dHA6Ly93d3cuYXBhY2hlLm9yZy9saWNlbnNlcy9MSUNFTlNFLTIuMFxuICpcbiAqIFVubGVzcyByZXF1aXJlZCBieSBhcHBsaWNhYmxlIGxhdyBvciBhZ3JlZWQgdG8gaW4gd3JpdGluZywgc29mdHdhcmVcbiAqIGRpc3RyaWJ1dGVkIHVuZGVyIHRoZSBMaWNlbnNlIGlzIGRpc3RyaWJ1dGVkIG9uIGFuIFwiQVMgSVNcIiBCQVNJUyxcbiAqIFdJVEhPVVQgV0FSUkFOVElFUyBPUiBDT05ESVRJT05TIE9GIEFOWSBLSU5ELCBlaXRoZXIgZXhwcmVzcyBvciBpbXBsaWVkLlxuICogU2VlIHRoZSBMaWNlbnNlIGZvciB0aGUgc3BlY2lmaWMgbGFuZ3VhZ2UgZ292ZXJuaW5nIHBlcm1pc3Npb25zIGFuZFxuICogbGltaXRhdGlvbnMgdW5kZXIgdGhlIExpY2Vuc2UuXG4gKi9cblxuZXhwb3J0cy53cml0ZVNzcmNzID0gZnVuY3Rpb24oc291cmNlcywgb3JkZXIpIHtcbiAgdmFyIHNzcmNzID0gW107XG5cbiAgLy8gZXhwYW5kIHNvdXJjZXMgdG8gc3NyY3NcbiAgaWYgKHR5cGVvZiBzb3VyY2VzICE9PSAndW5kZWZpbmVkJyAmJlxuICAgICAgT2JqZWN0LmtleXMoc291cmNlcykubGVuZ3RoICE9PSAwKSB7XG5cbiAgICBpZiAoQXJyYXkuaXNBcnJheShvcmRlcikpIHtcbiAgICAgIGZvciAodmFyIGkgPSAwOyBpIDwgb3JkZXIubGVuZ3RoOyBpKyspIHtcbiAgICAgICAgdmFyIHNzcmMgPSBvcmRlcltpXTtcbiAgICAgICAgdmFyIHNvdXJjZSA9IHNvdXJjZXNbc3NyY107XG4gICAgICAgIE9iamVjdC5rZXlzKHNvdXJjZSkuZm9yRWFjaChmdW5jdGlvbiAoYXR0cmlidXRlKSB7XG4gICAgICAgICAgc3NyY3MucHVzaCh7XG4gICAgICAgICAgICBpZDogc3NyYyxcbiAgICAgICAgICAgIGF0dHJpYnV0ZTogYXR0cmlidXRlLFxuICAgICAgICAgICAgdmFsdWU6IHNvdXJjZVthdHRyaWJ1dGVdXG4gICAgICAgICAgfSk7XG4gICAgICAgIH0pO1xuICAgICAgfVxuICAgIH0gZWxzZSB7XG4gICAgICBPYmplY3Qua2V5cyhzb3VyY2VzKS5mb3JFYWNoKGZ1bmN0aW9uIChzc3JjKSB7XG4gICAgICAgIHZhciBzb3VyY2UgPSBzb3VyY2VzW3NzcmNdO1xuICAgICAgICBPYmplY3Qua2V5cyhzb3VyY2UpLmZvckVhY2goZnVuY3Rpb24gKGF0dHJpYnV0ZSkge1xuICAgICAgICAgIHNzcmNzLnB1c2goe1xuICAgICAgICAgICAgaWQ6IHNzcmMsXG4gICAgICAgICAgICBhdHRyaWJ1dGU6IGF0dHJpYnV0ZSxcbiAgICAgICAgICAgIHZhbHVlOiBzb3VyY2VbYXR0cmlidXRlXVxuICAgICAgICAgIH0pO1xuICAgICAgICB9KTtcbiAgICAgIH0pO1xuICAgIH1cbiAgfVxuXG4gIHJldHVybiBzc3Jjcztcbn07XG5cbmV4cG9ydHMucGFyc2VTc3JjcyA9IGZ1bmN0aW9uIChtTGluZSkge1xuICB2YXIgc291cmNlcyA9IHt9O1xuICAvLyBncm91cCBzb3VyY2VzIGF0dHJpYnV0ZXMgYnkgc3NyYy5cbiAgaWYgKHR5cGVvZiBtTGluZS5zc3JjcyAhPT0gJ3VuZGVmaW5lZCcgJiYgQXJyYXkuaXNBcnJheShtTGluZS5zc3JjcykpIHtcbiAgICBtTGluZS5zc3Jjcy5mb3JFYWNoKGZ1bmN0aW9uIChzc3JjKSB7XG4gICAgICBpZiAoIXNvdXJjZXNbc3NyYy5pZF0pXG4gICAgICAgIHNvdXJjZXNbc3NyYy5pZF0gPSB7fTtcbiAgICAgIHNvdXJjZXNbc3NyYy5pZF1bc3NyYy5hdHRyaWJ1dGVdID0gc3NyYy52YWx1ZTtcbiAgICB9KTtcbiAgfVxuICByZXR1cm4gc291cmNlcztcbn07XG5cbiIsInZhciBNZWRpYVN0cmVhbVR5cGUgPSB7XG4gICAgVklERU9fVFlQRTogXCJWaWRlb1wiLFxuXG4gICAgQVVESU9fVFlQRTogXCJBdWRpb1wiXG59O1xubW9kdWxlLmV4cG9ydHMgPSBNZWRpYVN0cmVhbVR5cGU7IiwidmFyIFJUQ0V2ZW50cyA9IHtcbiAgICBSVENfUkVBRFk6IFwicnRjLnJlYWR5XCIsXG4gICAgREFUQV9DSEFOTkVMX09QRU46IFwicnRjLmRhdGFfY2hhbm5lbF9vcGVuXCIsXG4gICAgTEFTVE5fQ0hBTkdFRDogXCJydGMubGFzdG5fY2hhbmdlZFwiLFxuICAgIERPTUlOQU5UU1BFQUtFUl9DSEFOR0VEOiBcInJ0Yy5kb21pbmFudHNwZWFrZXJfY2hhbmdlZFwiLFxuICAgIExBU1ROX0VORFBPSU5UX0NIQU5HRUQ6IFwicnRjLmxhc3RuX2VuZHBvaW50X2NoYW5nZWRcIixcbiAgICBBVkFJTEFCTEVfREVWSUNFU19DSEFOR0VEOiBcInJ0Yy5hdmFpbGFibGVfZGV2aWNlc19jaGFuZ2VkXCJcbn07XG5cbm1vZHVsZS5leHBvcnRzID0gUlRDRXZlbnRzOyIsInZhciBSZXNvbHV0aW9ucyA9IHtcbiAgICBcIjEwODBcIjoge1xuICAgICAgICB3aWR0aDogMTkyMCxcbiAgICAgICAgaGVpZ2h0OiAxMDgwLFxuICAgICAgICBvcmRlcjogN1xuICAgIH0sXG4gICAgXCJmdWxsaGRcIjoge1xuICAgICAgICB3aWR0aDogMTkyMCxcbiAgICAgICAgaGVpZ2h0OiAxMDgwLFxuICAgICAgICBvcmRlcjogN1xuICAgIH0sXG4gICAgXCI3MjBcIjoge1xuICAgICAgICB3aWR0aDogMTI4MCxcbiAgICAgICAgaGVpZ2h0OiA3MjAsXG4gICAgICAgIG9yZGVyOiA2XG4gICAgfSxcbiAgICBcImhkXCI6IHtcbiAgICAgICAgd2lkdGg6IDEyODAsXG4gICAgICAgIGhlaWdodDogNzIwLFxuICAgICAgICBvcmRlcjogNlxuICAgIH0sXG4gICAgXCI5NjBcIjoge1xuICAgICAgICB3aWR0aDogOTYwLFxuICAgICAgICBoZWlnaHQ6IDcyMCxcbiAgICAgICAgb3JkZXI6IDVcbiAgICB9LFxuICAgIFwiNjQwXCI6IHtcbiAgICAgICAgd2lkdGg6IDY0MCxcbiAgICAgICAgaGVpZ2h0OiA0ODAsXG4gICAgICAgIG9yZGVyOiA0XG4gICAgfSxcbiAgICBcInZnYVwiOiB7XG4gICAgICAgIHdpZHRoOiA2NDAsXG4gICAgICAgIGhlaWdodDogNDgwLFxuICAgICAgICBvcmRlcjogNFxuICAgIH0sXG4gICAgXCIzNjBcIjoge1xuICAgICAgICB3aWR0aDogNjQwLFxuICAgICAgICBoZWlnaHQ6IDM2MCxcbiAgICAgICAgb3JkZXI6IDNcbiAgICB9LFxuICAgIFwiMzIwXCI6IHtcbiAgICAgICAgd2lkdGg6IDMyMCxcbiAgICAgICAgaGVpZ2h0OiAyNDAsXG4gICAgICAgIG9yZGVyOiAyXG4gICAgfSxcbiAgICBcIjE4MFwiOiB7XG4gICAgICAgIHdpZHRoOiAzMjAsXG4gICAgICAgIGhlaWdodDogMTgwLFxuICAgICAgICBvcmRlcjogMVxuICAgIH1cbn07XG5tb2R1bGUuZXhwb3J0cyA9IFJlc29sdXRpb25zOyIsInZhciBYTVBQRXZlbnRzID0ge1xuICAgIC8vIERlc2lnbmF0ZXMgYW4gZXZlbnQgaW5kaWNhdGluZyB0aGF0IHRoZSBjb25uZWN0aW9uIHRvIHRoZSBYTVBQIHNlcnZlclxuICAgIC8vIGZhaWxlZC5cbiAgICBDT05ORUNUSU9OX0ZBSUxFRDogXCJ4bXBwLmNvbm5lY3Rpb24uZmFpbGVkXCIsXG4gICAgLy8gRGVzaWduYXRlcyBhbiBldmVudCBpbmRpY2F0aW5nIHRoYXQgdGhlIG1lZGlhIChJQ0UpIGNvbm5lY3Rpb24gd2FzXG4gICAgLy8gaW50ZXJydXB0ZWQuIFRoaXMgc2hvdWxkIGdvIHRvIHRoZSBSVEMgbW9kdWxlLlxuICAgIENPTk5FQ1RJT05fSU5URVJSVVBURUQ6IFwieG1wcC5jb25uZWN0aW9uLmludGVycnVwdGVkXCIsXG4gICAgLy8gRGVzaWduYXRlcyBhbiBldmVudCBpbmRpY2F0aW5nIHRoYXQgdGhlIG1lZGlhIChJQ0UpIGNvbm5lY3Rpb24gd2FzXG4gICAgLy8gcmVzdG9yZWQuIFRoaXMgc2hvdWxkIGdvIHRvIHRoZSBSVEMgbW9kdWxlLlxuICAgIENPTk5FQ1RJT05fUkVTVE9SRUQ6IFwieG1wcC5jb25uZWN0aW9uLnJlc3RvcmVkXCIsXG4gICAgLy8gRGVzaWduYXRlcyBhbiBldmVudCBpbmRpY2F0aW5nIHRoYXQgYW4gb2ZmZXIgKGUuZy4gSmluZ2xlXG4gICAgLy8gc2Vzc2lvbi1pbml0aWF0ZSkgd2FzIHJlY2VpdmVkLlxuICAgIENBTExfSU5DT01JTkc6IFwieG1wcC5jYWxsaW5jb21pbmcuamluZ2xlXCIsXG4gICAgLy8gRGVzaWduYXRlcyBhbiBldmVudCBpbmRpY2F0aW5nIHRoYXQgd2Ugd2VyZSBraWNrZWQgZnJvbSB0aGUgWE1QUCBNVUMuXG4gICAgS0lDS0VEOiBcInhtcHAua2lja2VkXCIsXG4gICAgLy8gRGVzaWduYXRlcyBhbiBldmVudCBpbmRpY2F0aW5nIHRoYXQgdGhlIHVzZXJJRCBmb3IgYSBzcGVjaWZpYyBKSUQgaGFzXG4gICAgLy8gY2hhbmdlZC5cbiAgICAvLyBOb3RlOiBjdXJyZW50bHkgdGhpcyBldmVudCBmaXJlcyBldmVyeSB0aW1lIHdlIHJlY2VpdmUgcHJlc2VuY2UgZnJvbVxuICAgIC8vIHNvbWVvbmUgKHJlZ2FyZGxlc3Mgb2Ygd2hldGhlciBvciBub3QgdGhlIFwidXNlcklEXCIgY2hhbmdlZCkuXG4gICAgVVNFUl9JRF9DSEFOR0VEOiBcInhtcHAudXNlcl9pZF9jaGFuZ2VkXCIsXG4gICAgLy8gRGVzaWduYXRlcyBhbiBldmVudCBpbmRpY2F0aW5nIHRoYXQgd2UgaGF2ZSBqb2luZWQgdGhlIFhNUFAgTVVDLlxuICAgIE1VQ19KT0lORUQ6IFwieG1wcC5tdWNfam9pbmVkXCIsXG4gICAgLy8gRGVzaWduYXRlcyBhbiBldmVudCBpbmRpY2F0aW5nIHRoYXQgYSBwYXJ0aWNpcGFudCBqb2luZWQgdGhlIFhNUFAgTVVDLlxuICAgIE1VQ19NRU1CRVJfSk9JTkVEOiBcInhtcHAubXVjX21lbWJlcl9qb2luZWRcIixcbiAgICAvLyBEZXNpZ25hdGVzIGFuIGV2ZW50IGluZGljYXRpbmcgdGhhdCBhIHBhcnRpY2lwYW50IGxlZnQgdGhlIFhNUFAgTVVDLlxuICAgIE1VQ19NRU1CRVJfTEVGVDogXCJ4bXBwLm11Y19tZW1iZXJfbGVmdFwiLFxuICAgIC8vIERlc2lnbmF0ZXMgYW4gZXZlbnQgaW5kaWNhdGluZyB0aGF0IHRoZSBNVUMgcm9sZSBvZiBhIHBhcnRpY2lwYW50IGhhc1xuICAgIC8vIGNoYW5nZWQuXG4gICAgTVVDX1JPTEVfQ0hBTkdFRDogXCJ4bXBwLm11Y19yb2xlX2NoYW5nZWRcIixcbiAgICAvLyBEZXNpZ25hdGVzIGFuIGV2ZW50IGluZGljYXRpbmcgdGhhdCB0aGUgWE1QUCBNVUMgd2FzIGRlc3Ryb3llZC5cbiAgICBNVUNfREVTVFJPWUVEOiBcInhtcHAubXVjX2Rlc3Ryb3llZFwiLFxuICAgIC8vIERlc2lnbmF0ZXMgYW4gZXZlbnQgaW5kaWNhdGluZyB0aGF0IHRoZSBkaXNwbGF5IG5hbWUgb2YgYSBwYXJ0aWNpcGFudFxuICAgIC8vIGhhcyBjaGFuZ2VkLlxuICAgIERJU1BMQVlfTkFNRV9DSEFOR0VEOiBcInhtcHAuZGlzcGxheV9uYW1lX2NoYW5nZWRcIixcbiAgICAvLyBEZXNpZ25hdGVzIGFuIGV2ZW50IGluZGljYXRpbmcgdGhhdCB3ZSByZWNlaXZlZCBzdGF0aXN0aWNzIGZyb20gYVxuICAgIC8vIHBhcnRpY2lwYW50IGluIHRoZSBNVUMuXG4gICAgUkVNT1RFX1NUQVRTOiBcInhtcHAucmVtb3RlX3N0YXRzXCIsXG4gICAgLy8gRGVzaWduYXRlcyBhbiBldmVudCBpbmRpY2F0aW5nIHRoYXQgb3VyIHJvbGUgaW4gdGhlIFhNUFAgTVVDIGhhcyBjaGFuZ2VkLlxuICAgIExPQ0FMX1JPTEVfQ0hBTkdFRDogXCJ4bXBwLmxvY2Fscm9sZV9jaGFuZ2VkXCIsXG4gICAgLy8gRGVzaWduYXRlcyBhbiBldmVudCBpbmRpY2F0aW5nIHRoYXQgdGhlIHN1YmplY3Qgb2YgdGhlIFhNUFAgTVVDIGhhc1xuICAgIC8vIGNoYW5nZWQuXG4gICAgU1VCSkVDVF9DSEFOR0VEOiBcInhtcHAuc3ViamVjdF9jaGFuZ2VkXCIsXG4gICAgLy8gRGVzaWduYXRlcyBhbiBldmVudCBpbmRpY2F0aW5nIHRoYXQgYW4gWE1QUCBtZXNzYWdlIGluIHRoZSBNVUMgd2FzXG4gICAgLy8gcmVjZWl2ZWQuXG4gICAgTUVTU0FHRV9SRUNFSVZFRDogXCJ4bXBwLm1lc3NhZ2VfcmVjZWl2ZWRcIixcbiAgICAvLyBEZXNpZ25hdGVzIGFuIGV2ZW50IGluZGljYXRpbmcgdGhhdCB3ZSBzZW50IGFuIFhNUFAgbWVzc2FnZSB0byB0aGUgTVVDLlxuICAgIFNFTkRJTkdfQ0hBVF9NRVNTQUdFOiBcInhtcHAuc2VuZGluZ19jaGF0X21lc3NhZ2VcIixcbiAgICAvLyBEZXNpZ25hdGVzIGFuIGV2ZW50IGluZGljYXRpbmcgdGhhdCB0aGUgdmlkZW8gdHlwZSAoZS5nLiAnY2FtZXJhJyBvclxuICAgIC8vICdzY3JlZW4nKSBmb3IgYSBwYXJ0aWNpcGFudCBoYXMgY2hhbmdlZC5cbiAgICAvLyBOb3RlOiBjdXJyZW50bHkgdGhpcyBldmVudCBmaXJlcyBldmVyeSB0aW1lIHdlIHJlY2VpdmUgcHJlc2VuY2UgZnJvbVxuICAgIC8vIHNvbWVvbmUgKHJlZ2FyZGxlc3Mgb2Ygd2hldGhlciBvciBub3QgdGhlIFwidmlkZW8gdHlwZVwiIGNoYW5nZWQpLlxuICAgIFBBUlRJQ0lQQU5UX1ZJREVPX1RZUEVfQ0hBTkdFRDogXCJ4bXBwLnZpZGVvX3R5cGVcIixcbiAgICAvLyBEZXNpZ25hdGVzIGFuIGV2ZW50IGluZGljYXRpbmcgdGhhdCBhIHBhcnRpY2lwYW50IGluIHRoZSBYTVBQIE1VQyBoYXNcbiAgICAvLyBhZHZlcnRpc2VkIHRoYXQgdGhleSBoYXZlIGF1ZGlvIG11dGVkIChvciB1bm11dGVkKS5cbiAgICBQQVJUSUNJUEFOVF9BVURJT19NVVRFRDogXCJ4bXBwLmF1ZGlvX211dGVkXCIsXG4gICAgLy8gRGVzaWduYXRlcyBhbiBldmVudCBpbmRpY2F0aW5nIHRoYXQgYSBwYXJ0aWNpcGFudCBpbiB0aGUgWE1QUCBNVUMgaGFzXG4gICAgLy8gYWR2ZXJ0aXNlZCB0aGF0IHRoZXkgaGF2ZSB2aWRlbyBtdXRlZCAob3IgdW5tdXRlZCkuXG4gICAgUEFSVElDSVBBTlRfVklERU9fTVVURUQ6IFwieG1wcC52aWRlb19tdXRlZFwiLFxuICAgIC8vIERlc2lnbmF0ZXMgYW4gZXZlbnQgaW5kaWNhdGluZyB0aGF0IHRoZSBmb2N1cyBoYXMgYXNrZWQgdXMgdG8gbXV0ZSBvdXJcbiAgICAvLyBhdWRpby5cbiAgICBBVURJT19NVVRFRF9CWV9GT0NVUzogXCJ4bXBwLmF1ZGlvX211dGVkX2J5X2ZvY3VzXCIsXG4gICAgLy8gRGVzaWduYXRlcyBhbiBldmVudCBpbmRpY2F0aW5nIHRoYXQgYSBtb2RlcmF0b3IgaW4gdGhlIHJvb20gY2hhbmdlZCB0aGVcbiAgICAvLyBcInN0YXJ0IG11dGVkXCIgc2V0dGluZ3MgZm9yIHRoZSBjb25mZXJlbmNlLlxuICAgIFNUQVJUX01VVEVEX1NFVFRJTkdfQ0hBTkdFRDogXCJ4bXBwLnN0YXJ0X211dGVkX3NldHRpbmdfY2hhbmdlZFwiLFxuICAgIC8vIERlc2lnbmF0ZXMgYW4gZXZlbnQgaW5kaWNhdGluZyB0aGF0IHdlIHNob3VsZCBqb2luIHRoZSBjb25mZXJlbmNlIHdpdGhcbiAgICAvLyBhdWRpbyBhbmQvb3IgdmlkZW8gbXV0ZWQuXG4gICAgU1RBUlRfTVVURURfRlJPTV9GT0NVUzogXCJ4bXBwLnN0YXJ0X211dGVkX2Zyb21fZm9jdXNcIixcbiAgICAvLyBEZXNpZ25hdGVzIGFuIGV2ZW50IGluZGljYXRpbmcgdGhhdCBhIHJlbW90ZSBwYXJ0aWNpcGFudCdzIGF2YWlsYWJsZVxuICAgIC8vIGRldmljZXMgKHdoZXRoZXIgaGUgc3VwcG9ydHMgYSBhdWRpbyBhbmQvb3IgdmlkZW8pIGNoYW5nZWQuXG4gICAgLy8gTm90ZTogY3VycmVudGx5IHRoaXMgZXZlbnQgZmlyZXMgZXZlcnkgdGltZSB3ZSByZWNlaXZlIHByZXNlbmNlIGZyb21cbiAgICAvLyBzb21lb25lIChyZWdhcmRsZXNzIG9mIHdoZXRoZXIgb3Igbm90IHRoZSBkZXZpY2VzIGNoYW5nZWQpLlxuICAgIERFVklDRV9BVkFJTEFCTEU6IFwieG1wcC5kZXZpY2VfYXZhaWxhYmxlXCIsXG5cblxuICAgIFBFRVJDT05ORUNUSU9OX1JFQURZOiBcInhtcHAucGVlcmNvbm5lY3Rpb25fcmVhZHlcIixcbiAgICBDT05GRVJFTkNFX1NFVFVQX0ZBSUxFRDogXCJ4bXBwLmNvbmZlcmVuY2Vfc2V0dXBfZmFpbGVkXCIsXG4gICAgUEFTU1dPUkRfUkVRVUlSRUQ6IFwieG1wcC5wYXNzd29yZF9yZXF1aXJlZFwiLFxuICAgIEFVVEhFTlRJQ0FUSU9OX1JFUVVJUkVEOiBcInhtcHAuYXV0aGVudGljYXRpb25fcmVxdWlyZWRcIixcbiAgICBDSEFUX0VSUk9SX1JFQ0VJVkVEOiBcInhtcHAuY2hhdF9lcnJvcl9yZWNlaXZlZFwiLFxuICAgIEVUSEVSUEFEOiBcInhtcHAuZXRoZXJwYWRcIixcbiAgICBCUklER0VfRE9XTjogXCJ4bXBwLmJyaWRnZV9kb3duXCIsXG4gICAgUFJFU0VOQ0VfU1RBVFVTOiBcInhtcHAucHJlc2VuY2Vfc3RhdHVzXCIsXG4gICAgUkVTRVJWQVRJT05fRVJST1I6IFwieG1wcC5yb29tX3Jlc2VydmF0aW9uX2Vycm9yXCIsXG4gICAgRElTUE9TRV9DT05GRVJFTkNFOiBcInhtcHAuZGlzcG9zZV9jb25mZXJlbmNlXCIsXG4gICAgR1JBQ0VGVUxfU0hVVERPV046IFwieG1wcC5ncmFjZWZ1bF9zaHV0ZG93blwiLFxuICAgIC8vIFRPRE86IG9ubHkgdXNlZCBpbiBhIGhhY2ssIHNob3VsZCBwcm9iYWJseSBiZSByZW1vdmVkLlxuICAgIFNFVF9MT0NBTF9ERVNDUklQVElPTl9FUlJPUjogJ3htcHAuc2V0X2xvY2FsX2Rlc2NyaXB0aW9uX2Vycm9yJyxcbiAgICAvLyBUT0RPOiBvbmx5IHVzZWQgaW4gYSBoYWNrLCBzaG91bGQgcHJvYmFibHkgYmUgcmVtb3ZlZC5cbiAgICBTRVRfUkVNT1RFX0RFU0NSSVBUSU9OX0VSUk9SOiAneG1wcC5zZXRfcmVtb3RlX2Rlc2NyaXB0aW9uX2Vycm9yJyxcbiAgICAvLyBUT0RPOiBvbmx5IHVzZWQgaW4gYSBoYWNrLCBzaG91bGQgcHJvYmFibHkgYmUgcmVtb3ZlZC5cbiAgICBDUkVBVEVfQU5TV0VSX0VSUk9SOiAneG1wcC5jcmVhdGVfYW5zd2VyX2Vycm9yJyxcbiAgICBKSU5HTEVfRkFUQUxfRVJST1I6ICd4bXBwLmppbmdsZV9mYXRhbF9lcnJvcicsXG4gICAgUFJPTVBUX0ZPUl9MT0dJTjogJ3htcHAucHJvbXB0X2Zvcl9sb2dpbicsXG4gICAgRk9DVVNfRElTQ09OTkVDVEVEOiAneG1wcC5mb2N1c19kaXNjb25uZWN0ZWQnLFxuICAgIFJPT01fSk9JTl9FUlJPUjogJ3htcHAucm9vbV9qb2luX2Vycm9yJyxcbiAgICBST09NX0NPTk5FQ1RfRVJST1I6ICd4bXBwLnJvb21fY29ubmVjdF9lcnJvcicsXG4gICAgLy8geG1wcCBpcyBjb25uZWN0ZWQgYW5kIG9idGFpbmVkIHVzZXIgbWVkaWFcbiAgICBSRUFEWV9UT19KT0lOOiAneG1wcC5yZWFkeV90b19qb2luJyxcbiAgICBGT0NVU19MRUZUOiBcInhtcHAuZm9jdXNfbGVmdFwiLFxuICAgIFJFTU9URV9TVFJFQU1fUkVDRUlWRUQ6IFwieG1wcC5yZW1vdGVfc3RyZWFtX3JlY2VpdmVkXCIsXG4gICAgLyoqXG4gICAgICogSW5kaWNhdGVzIHRoYXQgcmVjb3JkaW5nIHN0YXRlIGNoYW5nZWQuXG4gICAgICovXG4gICAgUkVDT1JESU5HX1NUQVRFX0NIQU5HRUQ6IFwieG1wcC5yZWNvcmRpbmdTdGF0ZUNoYW5nZWRcIixcbiAgICAvKipcbiAgICAgKiBJbmRpY2F0ZXMgdGhhdCBwaG9uZSBudW1iZXIgY2hhbmdlZC5cbiAgICAgKi9cbiAgICBQSE9ORV9OVU1CRVJfQ0hBTkdFRDogXCJjb25mZXJlbmNlLnBob25lTnVtYmVyQ2hhbmdlZFwiXG59O1xubW9kdWxlLmV4cG9ydHMgPSBYTVBQRXZlbnRzO1xuIiwidmFyIEF1dGhlbnRpY2F0aW9uRXZlbnRzID0ge1xuICAgIC8qKlxuICAgICAqIEV2ZW50IGNhbGxiYWNrIGFyZ3VtZW50czpcbiAgICAgKiBmdW5jdGlvbihhdXRoZW50aWNhdGlvbkVuYWJsZWQsIHVzZXJJZGVudGl0eSlcbiAgICAgKiBhdXRoZW50aWNhdGlvbkVuYWJsZWQgLSBpbmRpY2F0ZXMgd2hldGhlciBhdXRoZW50aWNhdGlvbiBoYXMgYmVlbiBlbmFibGVkXG4gICAgICogICAgICAgICAgICAgICAgICAgICAgICAgaW4gdGhpcyBzZXNzaW9uXG4gICAgICogdXNlcklkZW50aXR5IC0gaWYgdXNlciBoYXMgYmVlbiBsb2dnZWQgaW4gdGhlbiBpdCBjb250YWlucyB1c2VyIG5hbWUuIElmXG4gICAgICogICAgICAgICAgICAgICAgY29udGFpbnMgJ251bGwnIG9yICd1bmRlZmluZWQnIHRoZW4gdXNlciBpcyBub3QgbG9nZ2VkIGluLlxuICAgICAqL1xuICAgIElERU5USVRZX1VQREFURUQ6IFwiYXV0aGVudGljYXRpb24uaWRlbnRpdHlfdXBkYXRlZFwiXG59O1xubW9kdWxlLmV4cG9ydHMgPSBBdXRoZW50aWNhdGlvbkV2ZW50cztcbiIsInZhciBEZXNrdG9wU2hhcmluZ0V2ZW50VHlwZXMgPSB7XG4gICAgSU5JVDogXCJkcy5pbml0XCIsXG5cbiAgICBTV0lUQ0hJTkdfRE9ORTogXCJkcy5zd2l0Y2hpbmdfZG9uZVwiLFxuXG4gICAgTkVXX1NUUkVBTV9DUkVBVEVEOiBcImRzLm5ld19zdHJlYW1fY3JlYXRlZFwiLFxuICAgIC8qKlxuICAgICAqIEFuIGV2ZW50IHdoaWNoIGluZGljYXRlcyB0aGF0IHRoZSBqaWRlc2hhIGV4dGVuc2lvbiBmb3IgRmlyZWZveCBpc1xuICAgICAqIG5lZWRlZCB0byBwcm9jZWVkIHdpdGggc2NyZWVuIHNoYXJpbmcsIGFuZCB0aGF0IGl0IGlzIG5vdCBpbnN0YWxsZWQuXG4gICAgICovXG4gICAgRklSRUZPWF9FWFRFTlNJT05fTkVFREVEOiBcImRzLmZpcmVmb3hfZXh0ZW5zaW9uX25lZWRlZFwiXG59O1xuXG5tb2R1bGUuZXhwb3J0cyA9IERlc2t0b3BTaGFyaW5nRXZlbnRUeXBlcztcbiIsIm1vZHVsZS5leHBvcnRzID0ge1xuICAgIC8qKlxuICAgICAqIEFuIGV2ZW50IGNhcnJ5aW5nIGNvbm5lY3Rpb24gc3RhdGlzdGljcy5cbiAgICAgKi9cbiAgICBDT05ORUNUSU9OX1NUQVRTOiBcInN0YXRpc3RpY3MuY29ubmVjdGlvbnN0YXRzXCIsXG4gICAgLyoqXG4gICAgICogRklYTUU6IG5lZWRzIGRvY3VtZW50YXRpb24uXG4gICAgICovXG4gICAgQVVESU9fTEVWRUw6IFwic3RhdGlzdGljcy5hdWRpb0xldmVsXCIsXG4gICAgLyoqXG4gICAgICogRklYTUU6IG5lZWRzIGRvY3VtZW50YXRpb24uXG4gICAgICovXG4gICAgU1RPUDogXCJzdGF0aXN0aWNzLnN0b3BcIlxufTtcbiIsInZhciBDb25zdGFudHMgPSB7XG4gICAgTE9DQUxfSklEOiAnbG9jYWwnXG59O1xubW9kdWxlLmV4cG9ydHMgPSBDb25zdGFudHM7Il19 diff --git a/lib-jitsi-meet.js.map b/lib-jitsi-meet.js.map new file mode 100644 index 000000000..2efd64ff1 --- /dev/null +++ b/lib-jitsi-meet.js.map @@ -0,0 +1,177 @@ +{ + "version": 3, + "sources": [ + "node_modules/browserify/node_modules/browser-pack/_prelude.js", + "JitsiConference.js", + "JitsiConferenceErrors.js", + "JitsiConferenceEvents.js", + "JitsiConnection.js", + "JitsiConnectionErrors.js", + "JitsiConnectionEvents.js", + "JitsiMeetJS.js", + "JitsiParticipant.js", + "JitsiTrackErrors.js", + "JitsiTrackEvents.js", + "modules/DTMF/JitsiDTMFManager.js", + "modules/RTC/DataChannels.js", + "modules/RTC/JitsiLocalTrack.js", + "modules/RTC/JitsiRemoteTrack.js", + "modules/RTC/JitsiTrack.js", + "modules/RTC/RTC.js", + "modules/RTC/RTCBrowserType.js", + "modules/RTC/RTCUtils.js", + "modules/RTC/ScreenObtainer.js", + "modules/RTC/adapter.screenshare.js", + "modules/settings/Settings.js", + "modules/statistics/LocalStatsCollector.js", + "modules/statistics/RTPStatsCollector.js", + "modules/statistics/statistics.js", + "modules/util/RandomUtil.js", + "modules/xmpp/ChatRoom.js", + "modules/xmpp/JingleSession.js", + "modules/xmpp/JingleSessionPC.js", + "modules/xmpp/LocalSSRCReplacement.js", + "modules/xmpp/SDP.js", + "modules/xmpp/SDPDiffer.js", + "modules/xmpp/SDPUtil.js", + "modules/xmpp/TraceablePeerConnection.js", + "modules/xmpp/moderator.js", + "modules/xmpp/recording.js", + "modules/xmpp/strophe.emuc.js", + "modules/xmpp/strophe.jingle.js", + "modules/xmpp/strophe.logger.js", + "modules/xmpp/strophe.ping.js", + "modules/xmpp/strophe.rayo.js", + "modules/xmpp/strophe.util.js", + "modules/xmpp/xmpp.js", + "node_modules/async/lib/async.js", + "node_modules/browserify/node_modules/events/events.js", + "node_modules/browserify/node_modules/process/browser.js", + "node_modules/es6-promise/dist/es6-promise.js", + "node_modules/jitsi-meet-logger/lib/Logger.js", + "node_modules/jitsi-meet-logger/lib/index.js", + "node_modules/pako/index.js", + "node_modules/pako/lib/deflate.js", + "node_modules/pako/lib/inflate.js", + "node_modules/pako/lib/utils/common.js", + "node_modules/pako/lib/utils/strings.js", + "node_modules/pako/lib/zlib/adler32.js", + "node_modules/pako/lib/zlib/constants.js", + "node_modules/pako/lib/zlib/crc32.js", + "node_modules/pako/lib/zlib/deflate.js", + "node_modules/pako/lib/zlib/gzheader.js", + "node_modules/pako/lib/zlib/inffast.js", + "node_modules/pako/lib/zlib/inflate.js", + "node_modules/pako/lib/zlib/inftrees.js", + "node_modules/pako/lib/zlib/messages.js", + "node_modules/pako/lib/zlib/trees.js", + "node_modules/pako/lib/zlib/zstream.js", + "node_modules/sdp-interop/lib/array-equals.js", + "node_modules/sdp-interop/lib/index.js", + "node_modules/sdp-interop/lib/interop.js", + "node_modules/sdp-interop/lib/transform.js", + "node_modules/sdp-interop/node_modules/sdp-transform/lib/grammar.js", + "node_modules/sdp-interop/node_modules/sdp-transform/lib/index.js", + "node_modules/sdp-interop/node_modules/sdp-transform/lib/parser.js", + "node_modules/sdp-interop/node_modules/sdp-transform/lib/writer.js", + "node_modules/sdp-simulcast/lib/index.js", + "node_modules/sdp-simulcast/lib/transform-utils.js", + "service/RTC/MediaStreamTypes.js", + "service/RTC/RTCEvents.js", + "service/RTC/Resolutions.js", + "service/XMPP/XMPPEvents.js", + "service/authentication/AuthenticationEvents.js", + "service/desktopsharing/DesktopSharingEventTypes.js", + "service/statistics/Events.js", + "service/statistics/constants.js" + ], + "names": [], + "mappings": "AAAA;;ACAA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;;;;AC9vBA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;;ACpCA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;;ACrGA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;;AC3EA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;;ACrBA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;;ACzBA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;;ACrGA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;;AC5JA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;;ACxBA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;;;AChBA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;;;;;ACfA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;;;;ACpNA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;;AChKA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;;ACvEA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;;ACrQA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;;ACpOA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;;;AC3KA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;;;;;ACzwBA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;;;;;AClaA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;;;;;AC5pCA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;;;;AClFA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;;;AC3HA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;;;;ACntBA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;;AC7KA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;;;ACzEA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;;;;;ACtvBA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;;;;;ACpIA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;;;;;ACrmDA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;;;;;ACpSA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;;;;ACvoBA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;;;ACvKA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;;;;;AC5WA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;;;;;ACjcA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;;;;;ACzcA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;;;;;ACrHA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;;;;;AC7FA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;;;;ACrSA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;;;ACnBA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;;;;;AC3HA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;;;;;ACjHA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;;;;;AC7CA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;;;;;ACpUA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;;;;ACnmCA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;;AC7SA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;;;AC3FA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;;;;ACv8BA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;;AC9IA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;;ACnFA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;;ACdA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;;ACxXA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;;AChZA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;;ACtGA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;;ACzLA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;;AChCA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;;AC/CA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;;ACzCA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;;ACruDA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;;ACxCA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;;ACtUA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;;AC/9CA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;;ACvUA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;;ACbA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;;AC/qCA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;;AC7BA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;;ACvCA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;;AChBA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;;ACjtBA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;;AChHA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;;ACjQA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;;ACRA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;;AC7FA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;;AClHA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;;AClaA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;;;;;;;;;;AChEA;AACA;AACA;AACA;AACA;AACA;;ACLA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;;ACTA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;;ACpDA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;;AC9GA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;;ACZA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;;ACdA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;;ACdA;AACA;AACA;AACA", + "file": "generated.js", + "sourceRoot": "", + "sourcesContent": [ + "(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 a list of participant identifiers containing all conference participants.\n */\nJitsiConference.prototype.getParticipants = function() {\n return Object.keys(this.participants).map(function (key) {\n return this.participants[key];\n }, this);\n};\n\n/**\n * @returns {JitsiParticipant} the participant in this conference with the specified id (or\n * undefined if there isn't one).\n * @param id the id of the participant.\n */\nJitsiConference.prototype.getParticipantById = function(id) {\n return this.participants[id];\n};\n\n/**\n * Kick participant from this conference.\n * @param {string} id id of the participant to kick\n */\nJitsiConference.prototype.kickParticipant = function (id) {\n var participant = this.getParticipantById(id);\n if (!participant) {\n return;\n }\n this.room.kick(participant.getJid());\n};\n\nJitsiConference.prototype.onMemberJoined = function (jid, email, nick) {\n var id = Strophe.getResourceFromJid(jid);\n if (id === 'focus' || this.myUserId() === id) {\n return;\n }\n var participant = new JitsiParticipant(jid, this, nick);\n this.participants[id] = participant;\n this.eventEmitter.emit(JitsiConferenceEvents.USER_JOINED, id, participant);\n this.xmpp.connection.disco.info(\n jid, \"node\", function(iq) {\n participant._supportsDTMF = $(iq).find(\n '>query>feature[var=\"urn:xmpp:jingle:dtmf:0\"]').length > 0;\n this.updateDTMFSupport();\n }.bind(this)\n );\n};\n\nJitsiConference.prototype.onMemberLeft = function (jid) {\n var id = Strophe.getResourceFromJid(jid);\n if (id === 'focus' || this.myUserId() === id) {\n return;\n }\n var participant = this.participants[id];\n delete this.participants[id];\n this.eventEmitter.emit(JitsiConferenceEvents.USER_LEFT, id, participant);\n};\n\nJitsiConference.prototype.onUserRoleChanged = function (jid, role) {\n var id = Strophe.getResourceFromJid(jid);\n var participant = this.getParticipantById(id);\n if (!participant) {\n return;\n }\n participant._role = role;\n this.eventEmitter.emit(JitsiConferenceEvents.USER_ROLE_CHANGED, id, role);\n};\n\nJitsiConference.prototype.onDisplayNameChanged = function (jid, displayName) {\n var id = Strophe.getResourceFromJid(jid);\n var participant = this.getParticipantById(id);\n if (!participant) {\n return;\n }\n participant._displayName = displayName;\n this.eventEmitter.emit(JitsiConferenceEvents.DISPLAY_NAME_CHANGED, id, displayName);\n};\n\nJitsiConference.prototype.onTrackAdded = function (track) {\n var id = track.getParticipantId();\n var participant = this.getParticipantById(id);\n if (!participant) {\n return;\n }\n // add track to JitsiParticipant\n participant._tracks.push(track);\n\n var emitter = this.eventEmitter;\n track.addEventListener(\n JitsiTrackEvents.TRACK_STOPPED,\n function () {\n // remove track from JitsiParticipant\n var pos = participant._tracks.indexOf(track);\n if (pos > -1) {\n participant._tracks.splice(pos, 1);\n }\n emitter.emit(JitsiConferenceEvents.TRACK_REMOVED, track);\n }\n );\n track.addEventListener(\n JitsiTrackEvents.TRACK_MUTE_CHANGED,\n function () {\n emitter.emit(JitsiConferenceEvents.TRACK_MUTE_CHANGED, track);\n }\n );\n track.addEventListener(\n JitsiTrackEvents.TRACK_AUDIO_LEVEL_CHANGED,\n function (audioLevel) {\n emitter.emit(JitsiConferenceEvents.TRACK_AUDIO_LEVEL_CHANGED, id, audioLevel);\n }\n );\n\n this.eventEmitter.emit(JitsiConferenceEvents.TRACK_ADDED, track);\n};\n\nJitsiConference.prototype.updateDTMFSupport = function () {\n var somebodySupportsDTMF = false;\n var participants = this.getParticipants();\n\n // check if at least 1 participant supports DTMF\n for (var i = 0; i < participants.length; i += 1) {\n if (participants[i].supportsDTMF()) {\n somebodySupportsDTMF = true;\n break;\n }\n }\n if (somebodySupportsDTMF !== this.somebodySupportsDTMF) {\n this.somebodySupportsDTMF = somebodySupportsDTMF;\n this.eventEmitter.emit(JitsiConferenceEvents.DTMF_SUPPORT_CHANGED, somebodySupportsDTMF);\n }\n};\n\n/**\n * Allows to check if there is at least one user in the conference\n * that supports DTMF.\n * @returns {boolean} true if somebody supports DTMF, false otherwise\n */\nJitsiConference.prototype.isDTMFSupported = function () {\n return this.somebodySupportsDTMF;\n};\n\n/**\n * Returns the local user's ID\n * @return {string} local user's ID\n */\nJitsiConference.prototype.myUserId = function () {\n return (this.room && this.room.myroomjid)? Strophe.getResourceFromJid(this.room.myroomjid) : null;\n};\n\nJitsiConference.prototype.sendTones = function (tones, duration, pause) {\n if (!this.dtmfManager) {\n var connection = this.xmpp.connection.jingle.activecall.peerconnection;\n if (!connection) {\n logger.warn(\"cannot sendTones: no conneciton\");\n return;\n }\n\n var tracks = this.getLocalTracks().filter(function (track) {\n return track.isAudioTrack();\n });\n if (!tracks.length) {\n logger.warn(\"cannot sendTones: no local audio stream\");\n return;\n }\n this.dtmfManager = new JitsiDTMFManager(tracks[0], connection);\n }\n\n this.dtmfManager.sendTones(tones, duration, pause);\n};\n\n/**\n * Returns true if the recording is supproted and false if not.\n */\nJitsiConference.prototype.isRecordingSupported = function () {\n if(this.room)\n return this.room.isRecordingSupported();\n return false;\n};\n\n/**\n * Returns null if the recording is not supported, \"on\" if the recording started\n * and \"off\" if the recording is not started.\n */\nJitsiConference.prototype.getRecordingState = function () {\n if(this.room)\n return this.room.getRecordingState();\n return \"off\";\n}\n\n/**\n * Returns the url of the recorded video.\n */\nJitsiConference.prototype.getRecordingURL = function () {\n if(this.room)\n return this.room.getRecordingURL();\n return null;\n}\n\n/**\n * Starts/stops the recording\n * @param token a token for authentication.\n */\nJitsiConference.prototype.toggleRecording = function (token, followEntity) {\n if(this.room)\n return this.room.toggleRecording(token, followEntity);\n return new Promise(function(resolve, reject){\n reject(new Error(\"The conference is not created yet!\"))});\n}\n\n/**\n * Returns true if the SIP calls are supported and false otherwise\n */\nJitsiConference.prototype.isSIPCallingSupported = function () {\n if(this.room)\n return this.room.isSIPCallingSupported();\n return false;\n}\n\n/**\n * Dials a number.\n * @param number the number\n */\nJitsiConference.prototype.dial = function (number) {\n if(this.room)\n return this.room.dial(number);\n return new Promise(function(resolve, reject){\n reject(new Error(\"The conference is not created yet!\"))});\n}\n\n/**\n * Hangup an existing call\n */\nJitsiConference.prototype.hangup = function () {\n if(this.room)\n return this.room.hangup();\n return new Promise(function(resolve, reject){\n reject(new Error(\"The conference is not created yet!\"))});\n}\n\n/**\n * Returns the phone number for joining the conference.\n */\nJitsiConference.prototype.getPhoneNumber = function () {\n if(this.room)\n return this.room.getPhoneNumber();\n return null;\n}\n\n/**\n * Returns the pin for joining the conference with phone.\n */\nJitsiConference.prototype.getPhonePin = function () {\n if(this.room)\n return this.room.getPhonePin();\n return null;\n}\n\n/**\n * Returns the connection state for the current room. Its ice connection state\n * for its session.\n */\nJitsiConference.prototype.getConnectionState = function () {\n if(this.room)\n return this.room.getConnectionState();\n return null;\n}\n\n/**\n * Setups the listeners needed for the conference.\n * @param conference the conference\n */\nfunction setupListeners(conference) {\n conference.xmpp.addListener(XMPPEvents.CALL_INCOMING, function (event) {\n conference.rtc.onIncommingCall(event);\n if(conference.statistics)\n conference.statistics.startRemoteStats(event.peerconnection);\n });\n\n conference.room.addListener(XMPPEvents.REMOTE_STREAM_RECEIVED,\n function (data, sid, thessrc) {\n var track = conference.rtc.createRemoteStream(data, sid, thessrc);\n if (track) {\n conference.onTrackAdded(track);\n }\n }\n );\n\n conference.room.addListener(XMPPEvents.MUC_JOINED, function () {\n conference.eventEmitter.emit(JitsiConferenceEvents.CONFERENCE_JOINED);\n });\n conference.room.addListener(XMPPEvents.ROOM_JOIN_ERROR, function (pres) {\n conference.eventEmitter.emit(JitsiConferenceEvents.CONFERENCE_FAILED, JitsiConferenceErrors.CONNECTION_ERROR, pres);\n });\n conference.room.addListener(XMPPEvents.ROOM_CONNECT_ERROR, function (pres) {\n conference.eventEmitter.emit(JitsiConferenceEvents.CONFERENCE_FAILED, JitsiConferenceErrors.CONNECTION_ERROR, pres);\n });\n conference.room.addListener(XMPPEvents.PASSWORD_REQUIRED, function (pres) {\n conference.eventEmitter.emit(JitsiConferenceEvents.CONFERENCE_FAILED, JitsiConferenceErrors.PASSWORD_REQUIRED, pres);\n });\n conference.room.addListener(XMPPEvents.AUTHENTICATION_REQUIRED, function () {\n conference.eventEmitter.emit(JitsiConferenceEvents.CONFERENCE_FAILED, JitsiConferenceErrors.AUTHENTICATION_REQUIRED);\n });\n// FIXME\n// conference.room.addListener(XMPPEvents.MUC_JOINED, function () {\n// conference.eventEmitter.emit(JitsiConferenceEvents.CONFERENCE_LEFT);\n// });\n\n conference.room.addListener(XMPPEvents.KICKED, function () {\n conference.eventEmitter.emit(JitsiConferenceEvents.KICKED);\n });\n\n conference.room.addListener(XMPPEvents.MUC_MEMBER_JOINED, conference.onMemberJoined.bind(conference));\n conference.room.addListener(XMPPEvents.MUC_MEMBER_LEFT, conference.onMemberLeft.bind(conference));\n\n conference.room.addListener(XMPPEvents.DISPLAY_NAME_CHANGED, conference.onDisplayNameChanged.bind(conference));\n\n conference.room.addListener(XMPPEvents.LOCAL_ROLE_CHANGED, function (role) {\n conference.eventEmitter.emit(JitsiConferenceEvents.USER_ROLE_CHANGED, conference.myUserId(), role);\n });\n conference.room.addListener(XMPPEvents.MUC_ROLE_CHANGED, conference.onUserRoleChanged.bind(conference));\n\n conference.room.addListener(XMPPEvents.CONNECTION_INTERRUPTED, function () {\n conference.eventEmitter.emit(JitsiConferenceEvents.CONNECTION_INTERRUPTED);\n });\n\n conference.room.addListener(XMPPEvents.RECORDING_STATE_CHANGED,\n function () {\n conference.eventEmitter.emit(\n JitsiConferenceEvents.RECORDING_STATE_CHANGED);\n });\n\n conference.room.addListener(XMPPEvents.PHONE_NUMBER_CHANGED, function () {\n conference.eventEmitter.emit(\n JitsiConferenceEvents.PHONE_NUMBER_CHANGED);\n });\n\n conference.room.addListener(XMPPEvents.CONNECTION_RESTORED, function () {\n conference.eventEmitter.emit(JitsiConferenceEvents.CONNECTION_RESTORED);\n });\n conference.room.addListener(XMPPEvents.CONFERENCE_SETUP_FAILED, function () {\n conference.eventEmitter.emit(JitsiConferenceEvents.CONFERENCE_FAILED, JitsiConferenceErrors.SETUP_FAILED);\n });\n\n conference.room.addListener(AuthenticationEvents.IDENTITY_UPDATED, function (authEnabled, authIdentity) {\n conference.authEnabled = authEnabled;\n conference.authIdentity = authIdentity;\n });\n\n conference.room.addListener(XMPPEvents.MESSAGE_RECEIVED, function (jid, displayName, txt, myJid, ts) {\n var id = Strophe.getResourceFromJid(jid);\n conference.eventEmitter.emit(JitsiConferenceEvents.MESSAGE_RECEIVED, id, txt, ts);\n });\n\n conference.rtc.addListener(RTCEvents.DOMINANTSPEAKER_CHANGED, function (id) {\n if(conference.lastActiveSpeaker !== id && conference.room) {\n conference.lastActiveSpeaker = id;\n conference.eventEmitter.emit(JitsiConferenceEvents.ACTIVE_SPEAKER_CHANGED, id);\n }\n });\n\n conference.rtc.addListener(RTCEvents.LASTN_CHANGED, function (oldValue, newValue) {\n conference.eventEmitter.emit(JitsiConferenceEvents.IN_LAST_N_CHANGED, oldValue, newValue);\n });\n\n conference.rtc.addListener(RTCEvents.LASTN_ENDPOINT_CHANGED,\n function (lastNEndpoints, endpointsEnteringLastN) {\n conference.eventEmitter.emit(JitsiConferenceEvents.LAST_N_ENDPOINTS_CHANGED,\n lastNEndpoints, endpointsEnteringLastN);\n });\n conference.xmpp.addListener(XMPPEvents.PASSWORD_REQUIRED, function () {\n conference.eventEmitter.emit(JitsiConferenceErrors.PASSWORD_REQUIRED);\n });\n\n if(conference.statistics) {\n //FIXME: Maybe remove event should not be associated with the conference.\n conference.statistics.addAudioLevelListener(function (ssrc, level) {\n var userId = null;\n var jid = conference.room.getJidBySSRC(ssrc);\n if (!jid)\n return;\n\n conference.rtc.setAudioLevel(jid, level);\n });\n conference.xmpp.addListener(XMPPEvents.DISPOSE_CONFERENCE,\n function () {\n conference.statistics.dispose();\n });\n // FIXME: Maybe we should move this.\n // RTC.addListener(RTCEvents.AVAILABLE_DEVICES_CHANGED, function (devices) {\n // conference.room.updateDeviceAvailability(devices);\n // });\n }\n}\n\n\nmodule.exports = JitsiConference;\n", + "/**\n * Enumeration with the errors for the conference.\n * @type {{string: string}}\n */\nvar JitsiConferenceErrors = {\n /**\n * Indicates that a password is required in order to join the conference.\n */\n PASSWORD_REQUIRED: \"conference.passwordRequired\",\n /**\n * Indicates that client must be authenticated to create the conference.\n */\n AUTHENTICATION_REQUIRED: \"conference.authenticationRequired\",\n /**\n * Indicates that password cannot be set for this conference.\n */\n PASSWORD_NOT_SUPPORTED: \"conference.passwordNotSupported\",\n /**\n * Indicates that a connection error occurred when trying to join a\n * conference.\n */\n CONNECTION_ERROR: \"conference.connectionError\",\n /**\n * Indicates that the conference setup failed.\n */\n SETUP_FAILED: \"conference.setup_failed\",\n /**\n * Indicates that there is no available videobridge.\n */\n VIDEOBRIDGE_NOT_AVAILABLE: \"conference.videobridgeNotAvailable\"\n /**\n * Many more errors TBD here.\n */\n};\n\nmodule.exports = JitsiConferenceErrors;\n", + "/**\n * Enumeration with the events for the conference.\n * @type {{string: string}}\n */\nvar JitsiConferenceEvents = {\n /**\n * A new media track was added to the conference.\n */\n TRACK_ADDED: \"conference.trackAdded\",\n /**\n * The media track was removed from the conference.\n */\n TRACK_REMOVED: \"conference.trackRemoved\",\n /**\n * The active speaker was changed.\n */\n ACTIVE_SPEAKER_CHANGED: \"conference.activeSpeaker\",\n /**\n * A new user joinned the conference.\n */\n USER_JOINED: \"conference.userJoined\",\n /**\n * A user has left the conference.\n */\n USER_LEFT: \"conference.userLeft\",\n /**\n * User role changed.\n */\n USER_ROLE_CHANGED: \"conference.roleChanged\",\n /**\n * New text message was received.\n */\n MESSAGE_RECEIVED: \"conference.messageReceived\",\n /**\n * A user has changed it display name\n */\n DISPLAY_NAME_CHANGED: \"conference.displayNameChanged\",\n /**\n * A participant avatar has changed.\n */\n AVATAR_CHANGED: \"conference.avatarChanged\",\n /**\n * New connection statistics are received.\n */\n CONNECTION_STATS_RECEIVED: \"conference.connectionStatsReceived\",\n /**\n * The Last N set is changed.\n */\n LAST_N_ENDPOINTS_CHANGED: \"conference.lastNEndpointsChanged\",\n /**\n * You are included / excluded in somebody's last N set\n */\n IN_LAST_N_CHANGED: \"conference.lastNEndpointsChanged\",\n /**\n * A media track ( attached to the conference) mute status was changed.\n */\n TRACK_MUTE_CHANGED: \"conference.trackMuteChanged\",\n /**\n * Audio levels of a media track ( attached to the conference) was changed.\n */\n TRACK_AUDIO_LEVEL_CHANGED: \"conference.audioLevelsChanged\",\n /**\n * Indicates that the connection to the conference has been interrupted\n * for some reason.\n */\n CONNECTION_INTERRUPTED: \"conference.connectionInterrupted\",\n /**\n * Indicates that the connection to the conference has been restored.\n */\n CONNECTION_RESTORED: \"conference.connectionRestored\",\n /**\n * Indicates that conference failed.\n */\n CONFERENCE_FAILED: \"conference.failed\",\n /**\n * Indicates that conference has been joined.\n */\n CONFERENCE_JOINED: \"conference.joined\",\n /**\n * Indicates that conference has been left.\n */\n CONFERENCE_LEFT: \"conference.left\",\n /**\n * You are kicked from the conference.\n */\n KICKED: \"conferenece.kicked\",\n /**\n * Indicates that DTMF support changed.\n */\n DTMF_SUPPORT_CHANGED: \"conference.dtmfSupportChanged\",\n /**\n * Indicates that recording state changed.\n */\n RECORDING_STATE_CHANGED: \"conference.recordingStateChanged\",\n /**\n * Indicates that phone number changed.\n */\n PHONE_NUMBER_CHANGED: \"conference.phoneNumberChanged\"\n};\n\nmodule.exports = JitsiConferenceEvents;\n", + "var JitsiConference = require(\"./JitsiConference\");\nvar XMPP = require(\"./modules/xmpp/xmpp\");\n\n/**\n * Creates new connection object for the Jitsi Meet server side video conferencing service. Provides access to the\n * JitsiConference interface.\n * @param appID identification for the provider of Jitsi Meet video conferencing services.\n * @param token the JWT token used to authenticate with the server(optional)\n * @param options Object with properties / settings related to connection with the server.\n * @constructor\n */\nfunction JitsiConnection(appID, token, options) {\n this.appID = appID;\n this.token = token;\n this.options = options;\n this.xmpp = new XMPP(options);\n this.conferences = {};\n}\n\n/**\n * Connect the client with the server.\n * @param options {object} connecting options (for example authentications parameters).\n */\nJitsiConnection.prototype.connect = function (options) {\n if(!options)\n options = {};\n\n this.xmpp.connect(options.id, options.password);\n}\n\n/**\n * Disconnect the client from the server.\n */\nJitsiConnection.prototype.disconnect = function () {\n this.xmpp.disconnect();\n}\n\n/**\n * This method allows renewal of the tokens if they are expiring.\n * @param token the new token.\n */\nJitsiConnection.prototype.setToken = function (token) {\n this.token = token;\n}\n\n/**\n * Creates and joins new conference.\n * @param name the name of the conference; if null - a generated name will be provided from the api\n * @param options Object with properties / settings related to the conference that will be created.\n * @returns {JitsiConference} returns the new conference object.\n */\nJitsiConnection.prototype.initJitsiConference = function (name, options) {\n this.conferences[name] = new JitsiConference({name: name, config: options, connection: this});\n return this.conferences[name];\n}\n\n/**\n * Subscribes the passed listener to the event.\n * @param event {JitsiConnectionEvents} the connection event.\n * @param listener {Function} the function that will receive the event\n */\nJitsiConnection.prototype.addEventListener = function (event, listener) {\n this.xmpp.addListener(event, listener);\n}\n\n/**\n * Unsubscribes the passed handler.\n * @param event {JitsiConnectionEvents} the connection event.\n * @param listener {Function} the function that will receive the event\n */\nJitsiConnection.prototype.removeEventListener = function (event, listener) {\n this.xmpp.removeListener(event, listener);\n}\n\nmodule.exports = JitsiConnection;\n", + "/**\n * Enumeration with the errors for the connection.\n * @type {{string: string}}\n */\nvar JitsiConnectionErrors = {\n /**\n * Indicates that a password is required in order to join the conference.\n */\n PASSWORD_REQUIRED: \"connection.passwordRequired\",\n /**\n * Indicates that a connection error occurred when trying to join a\n * conference.\n */\n CONNECTION_ERROR: \"connection.connectionError\",\n /**\n * Not specified errors.\n */\n OTHER_ERROR: \"connection.otherError\"\n};\n\nmodule.exports = JitsiConnectionErrors;\n", + "/**\n * Enumeration with the events for the connection.\n * @type {{string: string}}\n */\nvar JitsiConnnectionEvents = {\n /**\n * Indicates that the connection has been failed for some reason.\n */\n CONNECTION_FAILED: \"connection.connectionFailed\",\n /**\n * Indicates that the connection has been established.\n */\n CONNECTION_ESTABLISHED: \"connection.connectionEstablished\",\n /**\n * Indicates that the connection has been disconnected.\n */\n CONNECTION_DISCONNECTED: \"connection.connectionDisconnected\",\n /**\n * Indicates that the perfomed action cannot be executed because the\n * connection is not in the correct state(connected, disconnected, etc.)\n */\n WRONG_STATE: \"connection.wrongState\"\n};\n\nmodule.exports = JitsiConnnectionEvents;\n", + "var JitsiConnection = require(\"./JitsiConnection\");\nvar JitsiConferenceEvents = require(\"./JitsiConferenceEvents\");\nvar JitsiConnectionEvents = require(\"./JitsiConnectionEvents\");\nvar JitsiConnectionErrors = require(\"./JitsiConnectionErrors\");\nvar JitsiConferenceErrors = require(\"./JitsiConferenceErrors\");\nvar JitsiTrackEvents = require(\"./JitsiTrackEvents\");\nvar JitsiTrackErrors = require(\"./JitsiTrackErrors\");\nvar Logger = require(\"jitsi-meet-logger\");\nvar RTC = require(\"./modules/RTC/RTC\");\nvar Statistics = require(\"./modules/statistics/statistics\");\n\n/**\n * Namespace for the interface of Jitsi Meet Library.\n */\nvar LibJitsiMeet = {\n\n JitsiConnection: JitsiConnection,\n events: {\n conference: JitsiConferenceEvents,\n connection: JitsiConnectionEvents,\n track: JitsiTrackEvents\n },\n errors: {\n conference: JitsiConferenceErrors,\n connection: JitsiConnectionErrors,\n track: JitsiTrackErrors\n },\n logLevels: Logger.levels,\n init: function (options) {\n return RTC.init(options || {});\n },\n /**\n * Returns whether the desktop sharing is enabled or not.\n * @returns {boolean}\n */\n isDesktopSharingEnabled: function () {\n return RTC.isDesktopSharingEnabled();\n },\n setLogLevel: function (level) {\n Logger.setLogLevel(level);\n },\n /**\n * Creates the media tracks and returns them trough the callback.\n * @param options Object with properties / settings specifying the tracks which should be created.\n * should be created or some additional configurations about resolution for example.\n * @param {Array} options.devices the devices that will be requested\n * @param {string} options.resolution resolution constraints\n * @param {bool} options.dontCreateJitsiTrack if true objects with the following structure {stream: the Media Stream,\n * type: \"audio\" or \"video\", videoType: \"camera\" or \"desktop\"}\n * will be returned trough the Promise, otherwise JitsiTrack objects will be returned.\n * @param {string} options.cameraDeviceId\n * @param {string} options.micDeviceId\n * @returns {Promise.<{Array.}, JitsiConferenceError>}\n * A promise that returns an array of created JitsiTracks if resolved,\n * or a JitsiConferenceError if rejected.\n */\n createLocalTracks: function (options) {\n return RTC.obtainAudioAndVideoPermissions(options || {}).then(\n function(tracks) {\n if(!RTC.options.disableAudioLevels)\n for(var i = 0; i < tracks.length; i++) {\n var track = tracks[i];\n var mStream = track.getOriginalStream();\n if(track.getType() === \"audio\"){\n Statistics.startLocalStats(mStream,\n track.setAudioLevel.bind(track));\n track.addEventListener(\n JitsiTrackEvents.TRACK_STOPPED,\n function(){\n Statistics.stopLocalStats(mStream);\n });\n }\n }\n return tracks;\n });\n },\n /**\n * Checks if its possible to enumerate available cameras/micropones.\n * @returns {boolean} true if available, false otherwise.\n */\n isDeviceListAvailable: function () {\n return RTC.isDeviceListAvailable();\n },\n /**\n * Returns true if changing the camera / microphone device is supported and\n * false if not.\n * @returns {boolean} true if available, false otherwise.\n */\n isDeviceChangeAvailable: function () {\n return RTC.isDeviceChangeAvailable();\n },\n enumerateDevices: function (callback) {\n RTC.enumerateDevices(callback);\n }\n};\n\nrequire(\"es6-promise\").polyfill()\n//Setups the promise object.\nwindow.Promise = window.Promise || require(\"es6-promise\").Promise;\n\nmodule.exports = LibJitsiMeet;\n", + "/* global Strophe */\n\n/**\n * Represents a participant in (a member of) a conference.\n */\nfunction JitsiParticipant(jid, conference, displayName){\n this._jid = jid;\n this._id = Strophe.getResourceFromJid(jid);\n this._conference = conference;\n this._displayName = displayName;\n this._supportsDTMF = false;\n this._tracks = [];\n this._role = 'none';\n}\n\n/**\n * @returns {JitsiConference} The conference that this participant belongs to.\n */\nJitsiParticipant.prototype.getConference = function() {\n return this._conference;\n};\n\n/**\n * @returns {Array.} The list of media tracks for this participant.\n */\nJitsiParticipant.prototype.getTracks = function() {\n return this._tracks;\n};\n\n/**\n * @returns {String} The ID of this participant.\n */\nJitsiParticipant.prototype.getId = function() {\n return this._id;\n};\n\n/**\n * @returns {String} The JID of this participant.\n */\nJitsiParticipant.prototype.getJid = function() {\n return this._jid;\n};\n\n/**\n * @returns {String} The human-readable display name of this participant.\n */\nJitsiParticipant.prototype.getDisplayName = function() {\n return this._displayName;\n};\n\n/**\n * @returns {Boolean} Whether this participant is a moderator or not.\n */\nJitsiParticipant.prototype.isModerator = function() {\n return this._role === 'moderator';\n};\n\n// Gets a link to an etherpad instance advertised by the participant?\n//JitsiParticipant.prototype.getEtherpad = function() {\n//\n//}\n\n\n/*\n * @returns {Boolean} Whether this participant has muted their audio.\n */\nJitsiParticipant.prototype.isAudioMuted = function() {\n return this.getTracks().reduce(function (track, isAudioMuted) {\n return isAudioMuted && (track.isVideoTrack() || track.isMuted());\n }, true);\n};\n\n/*\n * @returns {Boolean} Whether this participant has muted their video.\n */\nJitsiParticipant.prototype.isVideoMuted = function() {\n return this.getTracks().reduce(function (track, isVideoMuted) {\n return isVideoMuted && (track.isAudioTrack() || track.isMuted());\n }, true);\n};\n\n/*\n * @returns {???} The latest statistics reported by this participant\n * (i.e. info used to populate the GSM bars)\n * TODO: do we expose this or handle it internally?\n */\nJitsiParticipant.prototype.getLatestStats = function() {\n\n};\n\n/**\n * @returns {String} The role of this participant.\n */\nJitsiParticipant.prototype.getRole = function() {\n return this._role;\n};\n\n/*\n * @returns {Boolean} Whether this participant is\n * the conference focus (i.e. jicofo).\n */\nJitsiParticipant.prototype.isFocus = function() {\n\n};\n\n/*\n * @returns {Boolean} Whether this participant is\n * a conference recorder (i.e. jirecon).\n */\nJitsiParticipant.prototype.isRecorder = function() {\n\n};\n\n/*\n * @returns {Boolean} Whether this participant is a SIP gateway (i.e. jigasi).\n */\nJitsiParticipant.prototype.isSipGateway = function() {\n\n};\n\n/**\n * @returns {Boolean} Whether this participant\n * is currently sharing their screen.\n */\nJitsiParticipant.prototype.isScreenSharing = function() {\n\n};\n\n/**\n * @returns {String} The user agent of this participant\n * (i.e. browser userAgent string).\n */\nJitsiParticipant.prototype.getUserAgent = function() {\n\n};\n\n/**\n * Kicks the participant from the conference (requires certain privileges).\n */\nJitsiParticipant.prototype.kick = function() {\n\n};\n\n/**\n * Asks this participant to mute themselves.\n */\nJitsiParticipant.prototype.askToMute = function() {\n\n};\n\nJitsiParticipant.prototype.supportsDTMF = function () {\n return this._supportsDTMF;\n};\n\n\nmodule.exports = JitsiParticipant;\n", + "module.exports = {\n /**\n * Returns JitsiTrackErrors based on the error object passed by GUM\n * @param error the error\n * @param {Object} options the options object given to GUM.\n */\n parseError: function (error, options) {\n options = options || {};\n if (typeof error == \"object\" && error.constraintName && error.name\n && (error.name == \"ConstraintNotSatisfiedError\" ||\n error.name == \"OverconstrainedError\") &&\n (error.constraintName == \"minWidth\" ||\n error.constraintName == \"maxWidth\" ||\n error.constraintName == \"minHeight\" ||\n error.constraintName == \"maxHeight\") &&\n options.devices.indexOf(\"video\") !== -1) {\n return this.UNSUPPORTED_RESOLUTION;\n } else {\n return this.GENERAL;\n }\n },\n UNSUPPORTED_RESOLUTION: \"gum.unsupported_resolution\",\n GENERAL: \"gum.general\"\n};\n", + "var JitsiTrackEvents = {\n /**\n * A media track mute status was changed.\n */\n TRACK_MUTE_CHANGED: \"track.trackMuteChanged\",\n /**\n * Audio levels of a this track was changed.\n */\n TRACK_AUDIO_LEVEL_CHANGED: \"track.audioLevelsChanged\",\n /**\n * The media track was removed to the conference.\n */\n TRACK_STOPPED: \"track.stopped\"\n};\n\nmodule.exports = JitsiTrackEvents;\n", + "var logger = require(\"jitsi-meet-logger\").getLogger(__filename);\n\nfunction JitsiDTMFManager (localAudio, peerConnection) {\n var tracks = localAudio._getTracks();\n if (!tracks.length) {\n throw new Error(\"Failed to initialize DTMFSender: no audio track.\");\n }\n this.dtmfSender = peerConnection.peerconnection.createDTMFSender(tracks[0]);\n logger.debug(\"Initialized DTMFSender\");\n}\n\n\nJitsiDTMFManager.prototype.sendTones = function (tones, duration, pause) {\n this.dtmfSender.insertDTMF(tones, (duration || 200), (pause || 200));\n};\n", + "/* global config, APP, Strophe */\n\n// cache datachannels to avoid garbage collection\n// https://code.google.com/p/chromium/issues/detail?id=405545\n\nvar logger = require(\"jitsi-meet-logger\").getLogger(__filename);\nvar RTCEvents = require(\"../../service/RTC/RTCEvents\");\n\n\n/**\n * Binds \"ondatachannel\" event listener to given PeerConnection instance.\n * @param peerConnection WebRTC peer connection instance.\n */\nfunction DataChannels(peerConnection, emitter) {\n peerConnection.ondatachannel = this.onDataChannel.bind(this);\n this.eventEmitter = emitter;\n\n this._dataChannels = [];\n\n // Sample code for opening new data channel from Jitsi Meet to the bridge.\n // Although it's not a requirement to open separate channels from both bridge\n // and peer as single channel can be used for sending and receiving data.\n // So either channel opened by the bridge or the one opened here is enough\n // for communication with the bridge.\n /*var dataChannelOptions =\n {\n reliable: true\n };\n var dataChannel\n = peerConnection.createDataChannel(\"myChannel\", dataChannelOptions);\n\n // Can be used only when is in open state\n dataChannel.onopen = function ()\n {\n dataChannel.send(\"My channel !!!\");\n };\n dataChannel.onmessage = function (event)\n {\n var msgData = event.data;\n logger.info(\"Got My Data Channel Message:\", msgData, dataChannel);\n };*/\n};\n\n\n/**\n * Callback triggered by PeerConnection when new data channel is opened\n * on the bridge.\n * @param event the event info object.\n */\nDataChannels.prototype.onDataChannel = function (event) {\n var dataChannel = event.channel;\n var self = this;\n\n dataChannel.onopen = function () {\n logger.info(\"Data channel opened by the Videobridge!\", dataChannel);\n\n // Code sample for sending string and/or binary data\n // Sends String message to the bridge\n //dataChannel.send(\"Hello bridge!\");\n // Sends 12 bytes binary message to the bridge\n //dataChannel.send(new ArrayBuffer(12));\n\n self.eventEmitter.emit(RTCEvents.DATA_CHANNEL_OPEN);\n };\n\n dataChannel.onerror = function (error) {\n logger.error(\"Data Channel Error:\", error, dataChannel);\n };\n\n dataChannel.onmessage = function (event) {\n var data = event.data;\n // JSON\n var obj;\n\n try {\n obj = JSON.parse(data);\n }\n catch (e) {\n logger.error(\n \"Failed to parse data channel message as JSON: \",\n data,\n dataChannel);\n }\n if (('undefined' !== typeof(obj)) && (null !== obj)) {\n var colibriClass = obj.colibriClass;\n\n if (\"DominantSpeakerEndpointChangeEvent\" === colibriClass) {\n // Endpoint ID from the Videobridge.\n var dominantSpeakerEndpoint = obj.dominantSpeakerEndpoint;\n\n logger.info(\n \"Data channel new dominant speaker event: \",\n dominantSpeakerEndpoint);\n self.eventEmitter.emit(RTCEvents.DOMINANTSPEAKER_CHANGED, dominantSpeakerEndpoint);\n }\n else if (\"InLastNChangeEvent\" === colibriClass) {\n var oldValue = obj.oldValue;\n var newValue = obj.newValue;\n // Make sure that oldValue and newValue are of type boolean.\n var type;\n\n if ((type = typeof oldValue) !== 'boolean') {\n if (type === 'string') {\n oldValue = (oldValue == \"true\");\n } else {\n oldValue = new Boolean(oldValue).valueOf();\n }\n }\n if ((type = typeof newValue) !== 'boolean') {\n if (type === 'string') {\n newValue = (newValue == \"true\");\n } else {\n newValue = new Boolean(newValue).valueOf();\n }\n }\n\n self.eventEmitter.emit(RTCEvents.LASTN_CHANGED, oldValue, newValue);\n }\n else if (\"LastNEndpointsChangeEvent\" === colibriClass) {\n // The new/latest list of last-n endpoint IDs.\n var lastNEndpoints = obj.lastNEndpoints;\n // The list of endpoint IDs which are entering the list of\n // last-n at this time i.e. were not in the old list of last-n\n // endpoint IDs.\n var endpointsEnteringLastN = obj.endpointsEnteringLastN;\n\n logger.info(\n \"Data channel new last-n event: \",\n lastNEndpoints, endpointsEnteringLastN, obj);\n self.eventEmitter.emit(RTCEvents.LASTN_ENDPOINT_CHANGED,\n lastNEndpoints, endpointsEnteringLastN, obj);\n }\n else {\n logger.debug(\"Data channel JSON-formatted message: \", obj);\n // The received message appears to be appropriately formatted\n // (i.e. is a JSON object which assigns a value to the mandatory\n // property colibriClass) so don't just swallow it, expose it to\n // public consumption.\n self.eventEmitter.emit(\"rtc.datachannel.\" + colibriClass, obj);\n }\n }\n };\n\n dataChannel.onclose = function () {\n logger.info(\"The Data Channel closed\", dataChannel);\n var idx = self._dataChannels.indexOf(dataChannel);\n if (idx > -1)\n self._dataChannels = self._dataChannels.splice(idx, 1);\n };\n this._dataChannels.push(dataChannel);\n};\n\nDataChannels.prototype.handleSelectedEndpointEvent = function (userResource) {\n this._onXXXEndpointChanged(\"selected\", userResource);\n}\n\nDataChannels.prototype.handlePinnedEndpointEvent = function (userResource) {\n this._onXXXEndpointChanged(\"pinnned\", userResource);\n}\n\n/**\n * Notifies Videobridge about a change in the value of a specific\n * endpoint-related property such as selected endpoint and pinnned endpoint.\n *\n * @param xxx the name of the endpoint-related property whose value changed\n * @param userResource the new value of the endpoint-related property after the\n * change\n */\nDataChannels.prototype._onXXXEndpointChanged = function (xxx, userResource) {\n // Derive the correct words from xxx such as selected and Selected, pinned\n // and Pinned.\n var head = xxx.charAt(0);\n var tail = xxx.substring(1);\n var lower = head.toLowerCase() + tail;\n var upper = head.toUpperCase() + tail;\n\n // Notify Videobridge about the specified endpoint change.\n console.log(lower + ' endpoint changed: ', userResource);\n this._some(function (dataChannel) {\n if (dataChannel.readyState == 'open') {\n console.log(\n 'sending ' + lower\n + ' endpoint changed notification to the bridge: ',\n userResource);\n\n var jsonObject = {};\n\n jsonObject.colibriClass = (upper + 'EndpointChangedEvent');\n jsonObject[lower + \"Endpoint\"]\n = (userResource ? userResource : null);\n dataChannel.send(JSON.stringify(jsonObject));\n\n return true;\n }\n });\n}\n\nDataChannels.prototype._some = function (callback, thisArg) {\n var dataChannels = this._dataChannels;\n\n if (dataChannels && dataChannels.length !== 0) {\n if (thisArg)\n return dataChannels.some(callback, thisArg);\n else\n return dataChannels.some(callback);\n } else {\n return false;\n }\n}\n\nmodule.exports = DataChannels;\n\n", + "var JitsiTrack = require(\"./JitsiTrack\");\nvar RTCBrowserType = require(\"./RTCBrowserType\");\nvar JitsiTrackEvents = require('../../JitsiTrackEvents');\nvar RTC = require(\"./RTCUtils\");\n\n/**\n * Represents a single media track (either audio or video).\n * @constructor\n */\nfunction JitsiLocalTrack(stream, videoType,\n resolution)\n{\n this.videoType = videoType;\n this.dontFireRemoveEvent = false;\n this.resolution = resolution;\n this.startMuted = false;\n var self = this;\n JitsiTrack.call(this, null, stream,\n function () {\n if(!this.dontFireRemoveEvent)\n this.eventEmitter.emit(\n JitsiTrackEvents.TRACK_STOPPED);\n this.dontFireRemoveEvent = false;\n }.bind(this));\n\n}\n\nJitsiLocalTrack.prototype = Object.create(JitsiTrack.prototype);\nJitsiLocalTrack.prototype.constructor = JitsiLocalTrack;\n\n/**\n * Mutes / unmutes the track.\n * @param mute {boolean} if true the track will be muted. Otherwise the track will be unmuted.\n */\nJitsiLocalTrack.prototype._setMute = function (mute) {\n if(!this.rtc) {\n this.startMuted = mute;\n return;\n }\n var isAudio = this.type === JitsiTrack.AUDIO;\n this.dontFireRemoveEvent = false;\n\n if ((window.location.protocol != \"https:\") ||\n (isAudio) || this.videoType === \"desktop\" ||\n // FIXME FF does not support 'removeStream' method used to mute\n RTCBrowserType.isFirefox()) {\n\n var tracks = this._getTracks();\n for (var idx = 0; idx < tracks.length; idx++) {\n tracks[idx].enabled = !mute;\n }\n if(isAudio)\n this.rtc.room.setAudioMute(mute);\n else\n this.rtc.room.setVideoMute(mute);\n this.eventEmitter.emit(JitsiTrackEvents.TRACK_MUTE_CHANGED);\n } else {\n if (mute) {\n this.dontFireRemoveEvent = true;\n this.rtc.room.removeStream(this.stream, function () {});\n RTC.stopMediaStream(this.stream);\n if(isAudio)\n this.rtc.room.setAudioMute(mute);\n else\n this.rtc.room.setVideoMute(mute);\n this.stream = null;\n this.eventEmitter.emit(JitsiTrackEvents.TRACK_MUTE_CHANGED);\n //FIXME: Maybe here we should set the SRC for the containers to something\n } else {\n var self = this;\n RTC.obtainAudioAndVideoPermissions({\n devices: (isAudio ? [\"audio\"] : [\"video\"]),\n resolution: self.resolution})\n .then(function (streams) {\n var stream = null;\n for(var i = 0; i < streams.length; i++) {\n stream = streams[i];\n if(stream.type === self.type) {\n self.stream = stream.stream;\n self.videoType = stream.videoType;\n break;\n }\n }\n\n if(!stream)\n return;\n\n for(var i = 0; i < self.containers.length; i++)\n {\n RTC.attachMediaStream(self.containers[i], self.stream);\n }\n\n self.rtc.room.addStream(stream.stream,\n function () {\n if(isAudio)\n self.rtc.room.setAudioMute(mute);\n else\n self.rtc.room.setVideoMute(mute);\n self.eventEmitter.emit(\n JitsiTrackEvents.TRACK_MUTE_CHANGED);\n });\n });\n }\n }\n}\n\n/**\n * Stops sending the media track. And removes it from the HTML.\n * NOTE: Works for local tracks only.\n */\nJitsiLocalTrack.prototype.stop = function () {\n if(!this.stream)\n return;\n if(this.rtc)\n this.rtc.room.removeStream(this.stream, function () {});\n RTC.stopMediaStream(this.stream);\n this.detach();\n}\n\n/**\n * Returns true - if the stream is muted\n * and false otherwise.\n * @returns {boolean} true - if the stream is muted\n * and false otherwise.\n */\nJitsiLocalTrack.prototype.isMuted = function () {\n if (!this.stream)\n return true;\n var tracks = [];\n var isAudio = this.type === JitsiTrack.AUDIO;\n if (isAudio) {\n tracks = this.stream.getAudioTracks();\n } else {\n if (!this.isActive())\n return true;\n tracks = this.stream.getVideoTracks();\n }\n for (var idx = 0; idx < tracks.length; idx++) {\n if(tracks[idx].enabled)\n return false;\n }\n return true;\n};\n\n/**\n * Private method. Updates rtc property of the track.\n * @param rtc the rtc instance.\n */\nJitsiLocalTrack.prototype._setRTC = function (rtc) {\n this.rtc = rtc;\n};\n\n/**\n * Return true;\n */\nJitsiLocalTrack.prototype.isLocal = function () {\n return true;\n}\n\nmodule.exports = JitsiLocalTrack;\n", + "var JitsiTrack = require(\"./JitsiTrack\");\nvar JitsiTrackEvents = require(\"../../JitsiTrackEvents\");\n\n/**\n * Represents a single media track (either audio or video).\n * @param RTC the rtc instance.\n * @param data object with the stream and some details about it(participant id, video type, etc.)\n * @param sid sid for the Media Stream\n * @param ssrc ssrc for the Media Stream\n * @param eventEmitter the event emitter\n * @constructor\n */\nfunction JitsiRemoteTrack(RTC, data, sid, ssrc) {\n JitsiTrack.call(this, RTC, data.stream,\n function () {\n this.eventEmitter.emit(JitsiTrackEvents.TRACK_STOPPED);\n }.bind(this));\n this.rtc = RTC;\n this.sid = sid;\n this.stream = data.stream;\n this.peerjid = data.peerjid;\n this.videoType = data.videoType;\n this.ssrc = ssrc;\n this.muted = false;\n if((this.type === JitsiTrack.AUDIO && data.audiomuted)\n || (this.type === JitsiTrack.VIDEO && data.videomuted)) {\n this.muted = true;\n }\n}\n\nJitsiRemoteTrack.prototype = Object.create(JitsiTrack.prototype);\nJitsiRemoteTrack.prototype.constructor = JitsiRemoteTrack;\n\n/**\n * Sets current muted status and fires an events for the change.\n * @param value the muted status.\n */\nJitsiRemoteTrack.prototype.setMute = function (value) {\n this.stream.muted = value;\n this.muted = value;\n this.eventEmitter.emit(JitsiTrackEvents.TRACK_MUTE_CHANGED);\n};\n\n/**\n * Returns the current muted status of the track.\n * @returns {boolean|*|JitsiRemoteTrack.muted} true if the track is muted and false otherwise.\n */\nJitsiRemoteTrack.prototype.isMuted = function () {\n return this.muted;\n};\n\n/**\n * Returns the participant id which owns the track.\n * @returns {string} the id of the participants.\n */\nJitsiRemoteTrack.prototype.getParticipantId = function() {\n return Strophe.getResourceFromJid(this.peerjid);\n};\n\n/**\n * Return false;\n */\nJitsiRemoteTrack.prototype.isLocal = function () {\n return false;\n};\n\ndelete JitsiRemoteTrack.prototype.stop;\n\ndelete JitsiRemoteTrack.prototype.start;\n\nmodule.exports = JitsiRemoteTrack;\n", + "var RTCBrowserType = require(\"./RTCBrowserType\");\nvar JitsiTrackEvents = require(\"../../JitsiTrackEvents\");\nvar EventEmitter = require(\"events\");\nvar RTC = require(\"./RTCUtils\");\n\n/**\n * This implements 'onended' callback normally fired by WebRTC after the stream\n * is stopped. There is no such behaviour yet in FF, so we have to add it.\n * @param jitsiTrack our track object holding the original WebRTC stream object\n * to which 'onended' handling will be added.\n */\nfunction implementOnEndedHandling(jitsiTrack) {\n var stream = jitsiTrack.getOriginalStream();\n var originalStop = stream.stop;\n stream.stop = function () {\n originalStop.apply(stream);\n if (jitsiTrack.isActive()) {\n stream.onended();\n }\n };\n}\n\n/**\n * Adds onended/oninactive handler to a MediaStream.\n * @param mediaStream a MediaStream to attach onended/oninactive handler\n * @param handler the handler\n */\nfunction addMediaStreamInactiveHandler(mediaStream, handler) {\n if(RTCBrowserType.isTemasysPluginUsed()) {\n // themasys\n //FIXME: Seems that not working properly.\n if(mediaStream.onended) {\n mediaStream.onended = handler;\n } else if(mediaStream.addEventListener) {\n mediaStream.addEventListener('ended', function () {\n handler(mediaStream);\n });\n } else if(mediaStream.attachEvent) {\n mediaStream.attachEvent('ended', function () {\n handler(mediaStream);\n });\n }\n }\n else {\n if(typeof mediaStream.active !== \"undefined\")\n mediaStream.oninactive = handler;\n else\n mediaStream.onended = handler;\n }\n}\n\n/**\n * Represents a single media track (either audio or video).\n * @constructor\n * @param rtc the rtc instance\n * @param stream the stream\n * @param streamInactiveHandler the function that will handle\n * onended/oninactive events of the stream.\n */\nfunction JitsiTrack(rtc, stream, streamInactiveHandler)\n{\n /**\n * Array with the HTML elements that are displaying the streams.\n * @type {Array}\n */\n this.containers = [];\n this.rtc = rtc;\n this.stream = stream;\n this.eventEmitter = new EventEmitter();\n this.audioLevel = -1;\n this.type = (this.stream.getVideoTracks().length > 0)?\n JitsiTrack.VIDEO : JitsiTrack.AUDIO;\n if(this.type == \"audio\") {\n this._getTracks = function () {\n return this.stream.getAudioTracks();\n }.bind(this);\n } else {\n this._getTracks = function () {\n return this.stream.getVideoTracks();\n }.bind(this);\n }\n if (RTCBrowserType.isFirefox() && this.stream) {\n implementOnEndedHandling(this);\n }\n\n if(stream)\n addMediaStreamInactiveHandler(stream, streamInactiveHandler);\n}\n\n/**\n * JitsiTrack video type.\n * @type {string}\n */\nJitsiTrack.VIDEO = \"video\";\n\n/**\n * JitsiTrack audio type.\n * @type {string}\n */\nJitsiTrack.AUDIO = \"audio\";\n\n/**\n * Returns the type (audio or video) of this track.\n */\nJitsiTrack.prototype.getType = function() {\n return this.type;\n};\n\n/**\n * Check if this is audiotrack.\n */\nJitsiTrack.prototype.isAudioTrack = function () {\n return this.getType() === JitsiTrack.AUDIO;\n};\n\n/**\n * Check if this is videotrack.\n */\nJitsiTrack.prototype.isVideoTrack = function () {\n return this.getType() === JitsiTrack.VIDEO;\n};\n\n/**\n * Returns the RTCMediaStream from the browser (?).\n */\nJitsiTrack.prototype.getOriginalStream = function() {\n return this.stream;\n}\n\n/**\n * Mutes the track.\n */\nJitsiTrack.prototype.mute = function () {\n this._setMute(true);\n}\n\n/**\n * Unmutes the stream.\n */\nJitsiTrack.prototype.unmute = function () {\n this._setMute(false);\n}\n\n/**\n * Attaches the MediaStream of this track to an HTML container (?).\n * Adds the container to the list of containers that are displaying the track.\n * @param container the HTML container\n */\nJitsiTrack.prototype.attach = function (container) {\n if(this.stream)\n require(\"./RTCUtils\").attachMediaStream(container, this.stream);\n this.containers.push(container);\n}\n\n/**\n * Removes the track from the passed HTML container.\n * @param container the HTML container. If null all containers are removed.\n */\nJitsiTrack.prototype.detach = function (container) {\n for(var i = 0; i < this.containers.length; i++)\n {\n if(this.containers[i].is(container))\n {\n this.containers.splice(i,1);\n }\n if(!container)\n {\n this.containers[i].find(\">video\").remove();\n }\n }\n if(container)\n $(container).find(\">video\").remove();\n\n}\n\n/**\n * Stops sending the media track. And removes it from the HTML.\n * NOTE: Works for local tracks only.\n */\nJitsiTrack.prototype.stop = function () {\n}\n\n/**\n * Returns true if this is a video track and the source of the video is a\n * screen capture as opposed to a camera.\n */\nJitsiTrack.prototype.isScreenSharing = function(){\n\n}\n\n/**\n * Returns id of the track.\n * @returns {string} id of the track or null if this is fake track.\n */\nJitsiTrack.prototype._getId = function () {\n var tracks = this.stream.getTracks();\n if(!tracks || tracks.length === 0)\n return null;\n return tracks[0].id;\n};\n\n/**\n * Returns id of the track.\n * @returns {string} id of the track or null if this is fake track.\n */\nJitsiTrack.prototype.getId = function () {\n return RTC.getStreamID(this.stream);\n};\n\n/**\n * Checks whether the MediaStream is avtive/not ended.\n * When there is no check for active we don't have information and so\n * will return that stream is active (in case of FF).\n * @returns {boolean} whether MediaStream is active.\n */\nJitsiTrack.prototype.isActive = function () {\n if((typeof this.stream.active !== \"undefined\"))\n return this.stream.active;\n else\n return true;\n};\n\n/**\n * Attaches a handler for events(For example - \"audio level changed\".).\n * All possible event are defined in JitsiTrackEvents.\n * @param eventId the event ID.\n * @param handler handler for the event.\n */\nJitsiTrack.prototype.on = function (eventId, handler) {\n if(this.eventEmitter)\n this.eventEmitter.on(eventId, handler);\n}\n\n/**\n * Removes event listener\n * @param eventId the event ID.\n * @param [handler] optional, the specific handler to unbind\n */\nJitsiTrack.prototype.off = function (eventId, handler) {\n if(this.eventEmitter)\n this.eventEmitter.removeListener(eventId, handler);\n}\n\n// Common aliases for event emitter\nJitsiTrack.prototype.addEventListener = JitsiTrack.prototype.on;\nJitsiTrack.prototype.removeEventListener = JitsiTrack.prototype.off;\n\n\n/**\n * Sets the audio level for the stream\n * @param audioLevel the new audio level\n */\nJitsiTrack.prototype.setAudioLevel = function (audioLevel) {\n if(this.audioLevel !== audioLevel) {\n this.eventEmitter.emit(JitsiTrackEvents.TRACK_AUDIO_LEVEL_CHANGED,\n audioLevel);\n this.audioLevel = audioLevel;\n }\n }\n\nmodule.exports = JitsiTrack;\n", + "/* global APP */\nvar EventEmitter = require(\"events\");\nvar RTCBrowserType = require(\"./RTCBrowserType\");\nvar RTCUtils = require(\"./RTCUtils.js\");\nvar JitsiTrack = require(\"./JitsiTrack\");\nvar JitsiLocalTrack = require(\"./JitsiLocalTrack.js\");\nvar DataChannels = require(\"./DataChannels\");\nvar JitsiRemoteTrack = require(\"./JitsiRemoteTrack.js\");\nvar DesktopSharingEventTypes\n = require(\"../../service/desktopsharing/DesktopSharingEventTypes\");\nvar MediaStreamType = require(\"../../service/RTC/MediaStreamTypes\");\nvar RTCEvents = require(\"../../service/RTC/RTCEvents.js\");\n\nfunction createLocalTracks(streams) {\n var newStreams = []\n for (var i = 0; i < streams.length; i++) {\n var localStream = new JitsiLocalTrack(streams[i].stream,\n streams[i].videoType, streams[i].resolution);\n newStreams.push(localStream);\n if (streams[i].isMuted === true)\n localStream.setMute(true);\n }\n return newStreams;\n}\n\nfunction RTC(room, options) {\n this.room = room;\n this.localStreams = [];\n //FIXME: we should start removing those streams.\n //FIXME: We should support multiple streams per jid.\n this.remoteStreams = {};\n this.localAudio = null;\n this.localVideo = null;\n this.eventEmitter = new EventEmitter();\n var self = this;\n this.options = options || {};\n room.addPresenceListener(\"videomuted\", function (values, from) {\n if(self.remoteStreams[from]) {\n self.remoteStreams[from][JitsiTrack.VIDEO].setMute(values.value == \"true\");\n }\n });\n room.addPresenceListener(\"audiomuted\", function (values, from) {\n if(self.remoteStreams[from]) {\n self.remoteStreams[from][JitsiTrack.AUDIO].setMute(values.value == \"true\");\n }\n });\n}\n\n/**\n * Creates the local MediaStreams.\n * @param {Object} [options] optional parameters\n * @param {Array} options.devices the devices that will be requested\n * @param {string} options.resolution resolution constraints\n * @param {bool} options.dontCreateJitsiTrack if true objects with the following structure {stream: the Media Stream,\n * type: \"audio\" or \"video\", videoType: \"camera\" or \"desktop\"}\n * will be returned trough the Promise, otherwise JitsiTrack objects will be returned.\n * @param {string} options.cameraDeviceId\n * @param {string} options.micDeviceId\n * @returns {*} Promise object that will receive the new JitsiTracks\n */\nRTC.obtainAudioAndVideoPermissions = function (options) {\n return RTCUtils.obtainAudioAndVideoPermissions(options).then(createLocalTracks);\n}\n\nRTC.prototype.onIncommingCall = function(event) {\n if(this.options.config.openSctp)\n this.dataChannels = new DataChannels(event.peerconnection, this.eventEmitter);\n for(var i = 0; i < this.localStreams.length; i++)\n if(this.localStreams[i])\n {\n this.room.addStream(this.localStreams[i].getOriginalStream(), function () {});\n }\n}\n\nRTC.prototype.selectedEndpoint = function (id) {\n if(this.dataChannels)\n this.dataChannels.handleSelectedEndpointEvent(id);\n}\n\nRTC.prototype.pinEndpoint = function (id) {\n if(this.dataChannels)\n this.dataChannels.handlePinnedEndpointEvent(id);\n}\n\nRTC.prototype.addListener = function (type, listener) {\n this.eventEmitter.on(type, listener);\n};\n\nRTC.prototype.removeListener = function (eventType, listener) {\n this.eventEmitter.removeListener(eventType, listener);\n};\n\nRTC.addListener = function (eventType, listener) {\n RTCUtils.addListener(eventType, listener);\n}\n\nRTC.removeListener = function (eventType, listener) {\n RTCUtils.removeListener(eventType, listener)\n}\n\nRTC.isRTCReady = function () {\n return RTCUtils.isRTCReady();\n}\n\nRTC.init = function (options) {\n this.options = options || {};\n return RTCUtils.init(this.options);\n}\n\nRTC.getDeviceAvailability = function () {\n return RTCUtils.getDeviceAvailability();\n}\n\nRTC.prototype.addLocalStream = function (stream) {\n this.localStreams.push(stream);\n stream._setRTC(this);\n\n if (stream.type == \"audio\") {\n this.localAudio = stream;\n } else {\n this.localVideo = stream;\n }\n};\n\nRTC.prototype.removeLocalStream = function (stream) {\n for(var i = 0; i < this.localStreams.length; i++) {\n if(this.localStreams[i].getOriginalStream() === stream) {\n delete this.localStreams[i];\n return;\n }\n }\n};\n\nRTC.prototype.createRemoteStream = function (data, sid, thessrc) {\n var remoteStream = new JitsiRemoteTrack(this, data, sid, thessrc);\n if(!data.peerjid)\n return;\n var jid = data.peerjid;\n if(!this.remoteStreams[jid]) {\n this.remoteStreams[jid] = {};\n }\n this.remoteStreams[jid][remoteStream.type]= remoteStream;\n return remoteStream;\n};\n\nRTC.getPCConstraints = function () {\n return RTCUtils.pc_constraints;\n};\n\nRTC.attachMediaStream = function (elSelector, stream) {\n RTCUtils.attachMediaStream(elSelector, stream);\n};\n\nRTC.getStreamID = function (stream) {\n return RTCUtils.getStreamID(stream);\n};\n\nRTC.getVideoSrc = function (element) {\n return RTCUtils.getVideoSrc(element);\n};\n\n/**\n * Returns true if retrieving the the list of input devices is supported and\n * false if not.\n */\nRTC.isDeviceListAvailable = function () {\n return RTCUtils.isDeviceListAvailable();\n};\n\n/**\n * Returns true if changing the camera / microphone device is supported and\n * false if not.\n */\nRTC.isDeviceChangeAvailable = function () {\n return RTCUtils.isDeviceChangeAvailable();\n}\n/**\n * Allows to receive list of available cameras/microphones.\n * @param {function} callback would receive array of devices as an argument\n */\nRTC.enumerateDevices = function (callback) {\n RTCUtils.enumerateDevices(callback);\n};\n\nRTC.setVideoSrc = function (element, src) {\n RTCUtils.setVideoSrc(element, src);\n};\n\n/**\n * A method to handle stopping of the stream.\n * One point to handle the differences in various implementations.\n * @param mediaStream MediaStream object to stop.\n */\nRTC.stopMediaStream = function (mediaStream) {\n RTCUtils.stopMediaStream(mediaStream);\n};\n\n/**\n * Returns whether the desktop sharing is enabled or not.\n * @returns {boolean}\n */\nRTC.isDesktopSharingEnabled = function () {\n return RTCUtils.isDesktopSharingEnabled();\n}\n\nRTC.prototype.getVideoElementName = function () {\n return RTCBrowserType.isTemasysPluginUsed() ? 'object' : 'video';\n};\n\nRTC.prototype.dispose = function() {\n};\n\nRTC.prototype.switchVideoStreams = function (newStream) {\n this.localVideo.stream = newStream;\n\n this.localStreams = [];\n\n //in firefox we have only one stream object\n if (this.localAudio.getOriginalStream() != newStream)\n this.localStreams.push(this.localAudio);\n this.localStreams.push(this.localVideo);\n};\n\nRTC.prototype.setAudioLevel = function (jid, audioLevel) {\n if(this.remoteStreams[jid] && this.remoteStreams[jid][JitsiTrack.AUDIO])\n this.remoteStreams[jid][JitsiTrack.AUDIO].setAudioLevel(audioLevel);\n}\nmodule.exports = RTC;\n", + "\nvar currentBrowser;\n\nvar browserVersion;\n\nvar isAndroid;\n\nvar RTCBrowserType = {\n\n RTC_BROWSER_CHROME: \"rtc_browser.chrome\",\n\n RTC_BROWSER_OPERA: \"rtc_browser.opera\",\n\n RTC_BROWSER_FIREFOX: \"rtc_browser.firefox\",\n\n RTC_BROWSER_IEXPLORER: \"rtc_browser.iexplorer\",\n\n RTC_BROWSER_SAFARI: \"rtc_browser.safari\",\n\n getBrowserType: function () {\n return currentBrowser;\n },\n\n isChrome: function () {\n return currentBrowser === RTCBrowserType.RTC_BROWSER_CHROME;\n },\n\n isOpera: function () {\n return currentBrowser === RTCBrowserType.RTC_BROWSER_OPERA;\n },\n isFirefox: function () {\n return currentBrowser === RTCBrowserType.RTC_BROWSER_FIREFOX;\n },\n\n isIExplorer: function () {\n return currentBrowser === RTCBrowserType.RTC_BROWSER_IEXPLORER;\n },\n\n isSafari: function () {\n return currentBrowser === RTCBrowserType.RTC_BROWSER_SAFARI;\n },\n isTemasysPluginUsed: function () {\n return RTCBrowserType.isIExplorer() || RTCBrowserType.isSafari();\n },\n getFirefoxVersion: function () {\n return RTCBrowserType.isFirefox() ? browserVersion : null;\n },\n\n getChromeVersion: function () {\n return RTCBrowserType.isChrome() ? browserVersion : null;\n },\n\n usesPlanB: function() {\n return RTCBrowserType.isChrome() || RTCBrowserType.isOpera() ||\n RTCBrowserType.isTemasysPluginUsed();\n },\n\n usesUnifiedPlan: function() {\n return RTCBrowserType.isFirefox();\n },\n\n /**\n * Whether the browser is running on an android device.\n */\n isAndroid: function() {\n return isAndroid;\n }\n\n // Add version getters for other browsers when needed\n};\n\n// detectOpera() must be called before detectChrome() !!!\n// otherwise Opera wil be detected as Chrome\nfunction detectChrome() {\n if (navigator.webkitGetUserMedia) {\n currentBrowser = RTCBrowserType.RTC_BROWSER_CHROME;\n var userAgent = navigator.userAgent.toLowerCase();\n // We can assume that user agent is chrome, because it's\n // enforced when 'ext' streaming method is set\n var ver = parseInt(userAgent.match(/chrome\\/(\\d+)\\./)[1], 10);\n console.log(\"This appears to be Chrome, ver: \" + ver);\n return ver;\n }\n return null;\n}\n\nfunction detectOpera() {\n var userAgent = navigator.userAgent;\n if (userAgent.match(/Opera|OPR/)) {\n currentBrowser = RTCBrowserType.RTC_BROWSER_OPERA;\n var version = userAgent.match(/(Opera|OPR) ?\\/?(\\d+)\\.?/)[2];\n console.info(\"This appears to be Opera, ver: \" + version);\n return version;\n }\n return null;\n}\n\nfunction detectFirefox() {\n if (navigator.mozGetUserMedia) {\n currentBrowser = RTCBrowserType.RTC_BROWSER_FIREFOX;\n var version = parseInt(\n navigator.userAgent.match(/Firefox\\/([0-9]+)\\./)[1], 10);\n console.log('This appears to be Firefox, ver: ' + version);\n return version;\n }\n return null;\n}\n\nfunction detectSafari() {\n if ((/^((?!chrome).)*safari/i.test(navigator.userAgent))) {\n currentBrowser = RTCBrowserType.RTC_BROWSER_SAFARI;\n console.info(\"This appears to be Safari\");\n // FIXME detect Safari version when needed\n return 1;\n }\n return null;\n}\n\nfunction detectIE() {\n var version;\n var ua = window.navigator.userAgent;\n\n var msie = ua.indexOf('MSIE ');\n if (msie > 0) {\n // IE 10 or older => return version number\n version = parseInt(ua.substring(msie + 5, ua.indexOf('.', msie)), 10);\n }\n\n var trident = ua.indexOf('Trident/');\n if (!version && trident > 0) {\n // IE 11 => return version number\n var rv = ua.indexOf('rv:');\n version = parseInt(ua.substring(rv + 3, ua.indexOf('.', rv)), 10);\n }\n\n var edge = ua.indexOf('Edge/');\n if (!version && edge > 0) {\n // IE 12 => return version number\n version = parseInt(ua.substring(edge + 5, ua.indexOf('.', edge)), 10);\n }\n\n if (version) {\n currentBrowser = RTCBrowserType.RTC_BROWSER_IEXPLORER;\n console.info(\"This appears to be IExplorer, ver: \" + version);\n }\n return version;\n}\n\nfunction detectBrowser() {\n var version;\n var detectors = [\n detectOpera,\n detectChrome,\n detectFirefox,\n detectIE,\n detectSafari\n ];\n // Try all browser detectors\n for (var i = 0; i < detectors.length; i++) {\n version = detectors[i]();\n if (version)\n return version;\n }\n console.warn(\"Browser type defaults to Safari ver 1\");\n currentBrowser = RTCBrowserType.RTC_BROWSER_SAFARI;\n return 1;\n}\n\nbrowserVersion = detectBrowser();\nisAndroid = navigator.userAgent.indexOf('Android') != -1;\n\nmodule.exports = RTCBrowserType;", + "/* global config, require, attachMediaStream, getUserMedia,\n RTCPeerConnection, RTCSessionDescription, RTCIceCandidate, MediaStreamTrack,\n mozRTCPeerConnection, mozRTCSessionDescription, mozRTCIceCandidate,\n webkitRTCPeerConnection, webkitMediaStream, webkitURL\n*/\n/* jshint -W101 */\n\nvar logger = require(\"jitsi-meet-logger\").getLogger(__filename);\nvar RTCBrowserType = require(\"./RTCBrowserType\");\nvar Resolutions = require(\"../../service/RTC/Resolutions\");\nvar RTCEvents = require(\"../../service/RTC/RTCEvents\");\nvar AdapterJS = require(\"./adapter.screenshare\");\nvar SDPUtil = require(\"../xmpp/SDPUtil\");\nvar EventEmitter = require(\"events\");\nvar screenObtainer = require(\"./ScreenObtainer\");\nvar JitsiTrackErrors = require(\"../../JitsiTrackErrors\");\n\nvar eventEmitter = new EventEmitter();\n\nvar devices = {\n audio: true,\n video: true\n};\n\nvar rtcReady = false;\n\nfunction setResolutionConstraints(constraints, resolution) {\n var isAndroid = RTCBrowserType.isAndroid();\n\n if (Resolutions[resolution]) {\n constraints.video.mandatory.minWidth = Resolutions[resolution].width;\n constraints.video.mandatory.minHeight = Resolutions[resolution].height;\n }\n else if (isAndroid) {\n // FIXME can't remember if the purpose of this was to always request\n // low resolution on Android ? if yes it should be moved up front\n constraints.video.mandatory.minWidth = 320;\n constraints.video.mandatory.minHeight = 240;\n constraints.video.mandatory.maxFrameRate = 15;\n }\n\n if (constraints.video.mandatory.minWidth)\n constraints.video.mandatory.maxWidth =\n constraints.video.mandatory.minWidth;\n if (constraints.video.mandatory.minHeight)\n constraints.video.mandatory.maxHeight =\n constraints.video.mandatory.minHeight;\n}\n\n/**\n * @param {string[]} um required user media types\n *\n * @param {Object} [options={}] optional parameters\n * @param {string} options.resolution\n * @param {number} options.bandwidth\n * @param {number} options.fps\n * @param {string} options.desktopStream\n * @param {string} options.cameraDeviceId\n * @param {string} options.micDeviceId\n * @param {bool} firefox_fake_device\n */\nfunction getConstraints(um, options) {\n var constraints = {audio: false, video: false};\n\n if (um.indexOf('video') >= 0) {\n // same behaviour as true\n constraints.video = { mandatory: {}, optional: [] };\n\n if (options.cameraDeviceId) {\n constraints.video.optional.push({\n sourceId: options.cameraDeviceId\n });\n }\n\n constraints.video.optional.push({ googLeakyBucket: true });\n\n setResolutionConstraints(constraints, options.resolution);\n }\n if (um.indexOf('audio') >= 0) {\n if (!RTCBrowserType.isFirefox()) {\n // same behaviour as true\n constraints.audio = { mandatory: {}, optional: []};\n if (options.micDeviceId) {\n constraints.audio.optional.push({\n sourceId: options.micDeviceId\n });\n }\n // if it is good enough for hangouts...\n constraints.audio.optional.push(\n {googEchoCancellation: true},\n {googAutoGainControl: true},\n {googNoiseSupression: true},\n {googHighpassFilter: true},\n {googNoisesuppression2: true},\n {googEchoCancellation2: true},\n {googAutoGainControl2: true}\n );\n } else {\n if (options.micDeviceId) {\n constraints.audio = {\n mandatory: {},\n optional: [{\n sourceId: options.micDeviceId\n }]};\n } else {\n constraints.audio = true;\n }\n }\n }\n if (um.indexOf('screen') >= 0) {\n if (RTCBrowserType.isChrome()) {\n constraints.video = {\n mandatory: {\n chromeMediaSource: \"screen\",\n googLeakyBucket: true,\n maxWidth: window.screen.width,\n maxHeight: window.screen.height,\n maxFrameRate: 3\n },\n optional: []\n };\n } else if (RTCBrowserType.isTemasysPluginUsed()) {\n constraints.video = {\n optional: [\n {\n sourceId: AdapterJS.WebRTCPlugin.plugin.screensharingKey\n }\n ]\n };\n } else if (RTCBrowserType.isFirefox()) {\n constraints.video = {\n mozMediaSource: \"window\",\n mediaSource: \"window\"\n };\n\n } else {\n logger.error(\n \"'screen' WebRTC media source is supported only in Chrome\" +\n \" and with Temasys plugin\");\n }\n }\n if (um.indexOf('desktop') >= 0) {\n constraints.video = {\n mandatory: {\n chromeMediaSource: \"desktop\",\n chromeMediaSourceId: options.desktopStream,\n googLeakyBucket: true,\n maxWidth: window.screen.width,\n maxHeight: window.screen.height,\n maxFrameRate: 3\n },\n optional: []\n };\n }\n\n if (options.bandwidth) {\n if (!constraints.video) {\n //same behaviour as true\n constraints.video = {mandatory: {}, optional: []};\n }\n constraints.video.optional.push({bandwidth: options.bandwidth});\n }\n if (options.fps) {\n // for some cameras it might be necessary to request 30fps\n // so they choose 30fps mjpg over 10fps yuy2\n if (!constraints.video) {\n // same behaviour as true;\n constraints.video = {mandatory: {}, optional: []};\n }\n constraints.video.mandatory.minFrameRate = options.fps;\n }\n\n // we turn audio for both audio and video tracks, the fake audio & video seems to work\n // only when enabled in one getUserMedia call, we cannot get fake audio separate by fake video\n // this later can be a problem with some of the tests\n if(RTCBrowserType.isFirefox() && options.firefox_fake_device)\n {\n // seems to be fixed now, removing this experimental fix, as having\n // multiple audio tracks brake the tests\n //constraints.audio = true;\n constraints.fake = true;\n }\n\n return constraints;\n}\n\nfunction setAvailableDevices(um, available) {\n if (um.indexOf(\"video\") != -1) {\n devices.video = available;\n }\n if (um.indexOf(\"audio\") != -1) {\n devices.audio = available;\n }\n\n eventEmitter.emit(RTCEvents.AVAILABLE_DEVICES_CHANGED, devices);\n}\n\n// In case of IE we continue from 'onReady' callback\n// passed to RTCUtils constructor. It will be invoked by Temasys plugin\n// once it is initialized.\nfunction onReady (options, GUM) {\n rtcReady = true;\n eventEmitter.emit(RTCEvents.RTC_READY, true);\n screenObtainer.init(eventEmitter, options, GUM);\n}\n\n/**\n * Apply function with arguments if function exists.\n * Do nothing if function not provided.\n * @param {function} [fn] function to apply\n * @param {Array} [args=[]] arguments for function\n */\nfunction maybeApply(fn, args) {\n if (fn) {\n fn.apply(null, args || []);\n }\n}\n\nvar getUserMediaStatus = {\n initialized: false,\n callbacks: []\n};\n\n/**\n * Wrap `getUserMedia` to allow others to know if it was executed at least\n * once or not. Wrapper function uses `getUserMediaStatus` object.\n * @param {Function} getUserMedia native function\n * @returns {Function} wrapped function\n */\nfunction wrapGetUserMedia(getUserMedia) {\n return function (constraints, successCallback, errorCallback) {\n getUserMedia(constraints, function (stream) {\n maybeApply(successCallback, [stream]);\n if (!getUserMediaStatus.initialized) {\n getUserMediaStatus.initialized = true;\n getUserMediaStatus.callbacks.forEach(function (callback) {\n callback();\n });\n getUserMediaStatus.callbacks.length = 0;\n }\n }, function (error) {\n maybeApply(errorCallback, [error]);\n });\n };\n}\n\n/**\n * Create stub device which equals to auto selected device.\n * @param {string} kind if that should be `audio` or `video` device\n * @returns {Object} stub device description in `enumerateDevices` format\n */\nfunction createAutoDeviceInfo(kind) {\n return {\n facing: null,\n label: 'Auto',\n kind: kind,\n deviceId: '',\n groupId: null\n };\n}\n\n\n/**\n * Execute function after getUserMedia was executed at least once.\n * @param {Function} callback function to execute after getUserMedia\n */\nfunction afterUserMediaInitialized(callback) {\n if (getUserMediaStatus.initialized) {\n callback();\n } else {\n getUserMediaStatus.callbacks.push(callback);\n }\n}\n\n/**\n * Wrapper function which makes enumerateDevices to wait\n * until someone executes getUserMedia first time.\n * @param {Function} enumerateDevices native function\n * @returns {Funtion} wrapped function\n */\nfunction wrapEnumerateDevices(enumerateDevices) {\n return function (callback) {\n // enumerate devices only after initial getUserMedia\n afterUserMediaInitialized(function () {\n\n enumerateDevices().then(function (devices) {\n //add auto devices\n devices.unshift(\n createAutoDeviceInfo('audioinput'),\n createAutoDeviceInfo('videoinput')\n );\n\n callback(devices);\n }, function (err) {\n console.error('cannot enumerate devices: ', err);\n\n // return only auto devices\n callback([createAutoDeviceInfo('audioInput'),\n createAutoDeviceInfo('videoinput')]);\n });\n });\n };\n}\n\n/**\n * Use old MediaStreamTrack to get devices list and\n * convert it to enumerateDevices format.\n * @param {Function} callback function to call when received devices list.\n */\nfunction enumerateDevicesThroughMediaStreamTrack (callback) {\n MediaStreamTrack.getSources(function (sources) {\n var devices = sources.map(function (source) {\n var kind = (source.kind || '').toLowerCase();\n return {\n facing: source.facing || null,\n label: source.label,\n kind: kind ? kind + 'input': null,\n deviceId: source.id,\n groupId: source.groupId || null\n };\n });\n\n //add auto devices\n devices.unshift(\n createAutoDeviceInfo('audioinput'),\n createAutoDeviceInfo('videoinput')\n );\n callback(devices);\n });\n}\n\nfunction obtainDevices(options) {\n if(!options.devices || options.devices.length === 0) {\n return options.successCallback(options.streams || {});\n }\n\n var device = options.devices.splice(0, 1);\n options.deviceGUM[device](function (stream) {\n options.streams = options.streams || {};\n options.streams[device] = stream;\n obtainDevices(options);\n },\n function (error) {\n logger.error(\n \"failed to obtain \" + device + \" stream - stop\", error);\n options.errorCallback(JitsiTrackErrors.parseError(error));\n });\n}\n\n\n/**\n * Handles the newly created Media Streams.\n * @param streams the new Media Streams\n * @param resolution the resolution of the video streams\n * @returns {*[]} object that describes the new streams\n */\nfunction handleLocalStream(streams, resolution) {\n var audioStream, videoStream, desktopStream, res = [];\n // If this is FF, the stream parameter is *not* a MediaStream object, it's\n // an object with two properties: audioStream, videoStream.\n if (window.webkitMediaStream) {\n var audioVideo = streams.audioVideo;\n if (audioVideo) {\n var audioTracks = audioVideo.getAudioTracks();\n if(audioTracks.length) {\n audioStream = new webkitMediaStream();\n for (var i = 0; i < audioTracks.length; i++) {\n audioStream.addTrack(audioTracks[i]);\n }\n }\n\n var videoTracks = audioVideo.getVideoTracks();\n if(videoTracks.length) {\n videoStream = new webkitMediaStream();\n for (var j = 0; j < videoTracks.length; j++) {\n videoStream.addTrack(videoTracks[j]);\n }\n }\n }\n\n if (streams && streams.desktopStream)\n desktopStream = streams.desktopStream;\n\n }\n else if (RTCBrowserType.isFirefox() || RTCBrowserType.isTemasysPluginUsed()) { // Firefox and Temasys plugin\n if (streams && streams.audio)\n audioStream = streams.audio;\n\n if (streams && streams.video)\n videoStream = streams.video;\n\n if(streams && streams.desktop)\n desktopStream = streams.desktop;\n }\n\n if (desktopStream)\n res.push({stream: desktopStream,\n type: \"video\", videoType: \"desktop\"});\n\n if(audioStream)\n res.push({stream: audioStream, type: \"audio\", videoType: null});\n\n if(videoStream)\n res.push({stream: videoStream, type: \"video\", videoType: \"camera\",\n resolution: resolution});\n\n return res;\n}\n\n//Options parameter is to pass config options. Currently uses only \"useIPv6\".\nvar RTCUtils = {\n init: function (options) {\n return new Promise(function(resolve, reject) {\n if (RTCBrowserType.isFirefox()) {\n var FFversion = RTCBrowserType.getFirefoxVersion();\n if (FFversion < 40) {\n logger.error(\n \"Firefox version too old: \" + FFversion +\n \". Required >= 40.\");\n reject(new Error(\"Firefox version too old: \" + FFversion +\n \". Required >= 40.\"));\n return;\n }\n this.peerconnection = mozRTCPeerConnection;\n this.getUserMedia = wrapGetUserMedia(navigator.mozGetUserMedia.bind(navigator));\n this.enumerateDevices = wrapEnumerateDevices(\n navigator.mediaDevices.enumerateDevices.bind(navigator.mediaDevices)\n );\n this.pc_constraints = {};\n this.attachMediaStream = function (element, stream) {\n // srcObject is being standardized and FF will eventually\n // support that unprefixed. FF also supports the\n // \"element.src = URL.createObjectURL(...)\" combo, but that\n // will be deprecated in favour of srcObject.\n //\n // https://groups.google.com/forum/#!topic/mozilla.dev.media/pKOiioXonJg\n // https://github.com/webrtc/samples/issues/302\n if (!element[0])\n return;\n element[0].mozSrcObject = stream;\n element[0].play();\n };\n this.getStreamID = function (stream) {\n var id = stream.id;\n if (!id) {\n var tracks = stream.getVideoTracks();\n if (!tracks || tracks.length === 0) {\n tracks = stream.getAudioTracks();\n }\n id = tracks[0].id;\n }\n return SDPUtil.filter_special_chars(id);\n };\n this.getVideoSrc = function (element) {\n if (!element)\n return null;\n return element.mozSrcObject;\n };\n this.setVideoSrc = function (element, src) {\n if (element)\n element.mozSrcObject = src;\n };\n RTCSessionDescription = mozRTCSessionDescription;\n RTCIceCandidate = mozRTCIceCandidate;\n } else if (RTCBrowserType.isChrome() || RTCBrowserType.isOpera()) {\n this.peerconnection = webkitRTCPeerConnection;\n var getUserMedia = navigator.webkitGetUserMedia.bind(navigator);\n if (navigator.mediaDevices) {\n this.getUserMedia = wrapGetUserMedia(getUserMedia);\n this.enumerateDevices = wrapEnumerateDevices(\n navigator.mediaDevices.enumerateDevices.bind(navigator.mediaDevices)\n );\n } else {\n this.getUserMedia = getUserMedia;\n this.enumerateDevices = enumerateDevicesThroughMediaStreamTrack;\n }\n this.attachMediaStream = function (element, stream) {\n element.attr('src', webkitURL.createObjectURL(stream));\n };\n this.getStreamID = function (stream) {\n // streams from FF endpoints have the characters '{' and '}'\n // that make jQuery choke.\n return SDPUtil.filter_special_chars(stream.id);\n };\n this.getVideoSrc = function (element) {\n if (!element)\n return null;\n return element.getAttribute(\"src\");\n };\n this.setVideoSrc = function (element, src) {\n if (element)\n element.setAttribute(\"src\", src);\n };\n // DTLS should now be enabled by default but..\n this.pc_constraints = {'optional': [\n {'DtlsSrtpKeyAgreement': 'true'}\n ]};\n if (options.useIPv6) {\n // https://code.google.com/p/webrtc/issues/detail?id=2828\n this.pc_constraints.optional.push({googIPv6: true});\n }\n if (RTCBrowserType.isAndroid()) {\n this.pc_constraints = {}; // disable DTLS on Android\n }\n if (!webkitMediaStream.prototype.getVideoTracks) {\n webkitMediaStream.prototype.getVideoTracks = function () {\n return this.videoTracks;\n };\n }\n if (!webkitMediaStream.prototype.getAudioTracks) {\n webkitMediaStream.prototype.getAudioTracks = function () {\n return this.audioTracks;\n };\n }\n }\n // Detect IE/Safari\n else if (RTCBrowserType.isTemasysPluginUsed()) {\n\n //AdapterJS.WebRTCPlugin.setLogLevel(\n // AdapterJS.WebRTCPlugin.PLUGIN_LOG_LEVELS.VERBOSE);\n var self = this;\n AdapterJS.webRTCReady(function (isPlugin) {\n\n self.peerconnection = RTCPeerConnection;\n self.getUserMedia = window.getUserMedia;\n self.enumerateDevices = enumerateDevicesThroughMediaStreamTrack;\n self.attachMediaStream = function (elSel, stream) {\n\n if (stream.id === \"dummyAudio\" || stream.id === \"dummyVideo\") {\n return;\n }\n\n attachMediaStream(elSel[0], stream);\n };\n self.getStreamID = function (stream) {\n var id = SDPUtil.filter_special_chars(stream.label);\n return id;\n };\n self.getVideoSrc = function (element) {\n if (!element) {\n logger.warn(\"Attempt to get video SRC of null element\");\n return null;\n }\n var children = element.children;\n for (var i = 0; i !== children.length; ++i) {\n if (children[i].name === 'streamId') {\n return children[i].value;\n }\n }\n //logger.info(element.id + \" SRC: \" + src);\n return null;\n };\n self.setVideoSrc = function (element, src) {\n //logger.info(\"Set video src: \", element, src);\n if (!src) {\n logger.warn(\"Not attaching video stream, 'src' is null\");\n return;\n }\n AdapterJS.WebRTCPlugin.WaitForPluginReady();\n var stream = AdapterJS.WebRTCPlugin.plugin\n .getStreamWithId(AdapterJS.WebRTCPlugin.pageId, src);\n attachMediaStream(element, stream);\n };\n\n onReady(options, self.getUserMediaWithConstraints);\n resolve();\n });\n } else {\n try {\n logger.error('Browser does not appear to be WebRTC-capable');\n } catch (e) {\n }\n reject('Browser does not appear to be WebRTC-capable');\n return;\n }\n\n // Call onReady() if Temasys plugin is not used\n if (!RTCBrowserType.isTemasysPluginUsed()) {\n onReady(options, this.getUserMediaWithConstraints);\n resolve();\n }\n }.bind(this));\n },\n /**\n * @param {string[]} um required user media types\n * @param {function} success_callback\n * @param {Function} failure_callback\n * @param {Object} [options] optional parameters\n * @param {string} options.resolution\n * @param {number} options.bandwidth\n * @param {number} options.fps\n * @param {string} options.desktopStream\n * @param {string} options.cameraDeviceId\n * @param {string} options.micDeviceId\n **/\n getUserMediaWithConstraints: function ( um, success_callback, failure_callback, options) {\n options = options || {};\n var resolution = options.resolution;\n var constraints = getConstraints(um, options);\n\n logger.info(\"Get media constraints\", constraints);\n\n try {\n this.getUserMedia(constraints,\n function (stream) {\n logger.log('onUserMediaSuccess');\n setAvailableDevices(um, true);\n success_callback(stream);\n },\n function (error) {\n setAvailableDevices(um, false);\n logger.warn('Failed to get access to local media. Error ',\n error, constraints);\n if (failure_callback) {\n failure_callback(error, resolution);\n }\n });\n } catch (e) {\n logger.error('GUM failed: ', e);\n if (failure_callback) {\n failure_callback(e);\n }\n }\n },\n\n /**\n * Creates the local MediaStreams.\n * @param {Object} [options] optional parameters\n * @param {Array} options.devices the devices that will be requested\n * @param {string} options.resolution resolution constraints\n * @param {bool} options.dontCreateJitsiTrack if true objects with the following structure {stream: the Media Stream,\n * type: \"audio\" or \"video\", videoType: \"camera\" or \"desktop\"}\n * will be returned trough the Promise, otherwise JitsiTrack objects will be returned.\n * @param {string} options.cameraDeviceId\n * @param {string} options.micDeviceId\n * @returns {*} Promise object that will receive the new JitsiTracks\n */\n obtainAudioAndVideoPermissions: function (options) {\n var self = this;\n\n options = options || {};\n return new Promise(function (resolve, reject) {\n var successCallback = function (stream) {\n resolve(handleLocalStream(stream, options.resolution));\n };\n\n options.devices = options.devices || ['audio', 'video'];\n if(!screenObtainer.isSupported()\n && options.devices.indexOf(\"desktop\") !== -1){\n reject(new Error(\"Desktop sharing is not supported!\"));\n }\n if (RTCBrowserType.isFirefox() ||\n RTCBrowserType.isTemasysPluginUsed()) {\n var GUM = function (device, s, e) {\n this.getUserMediaWithConstraints(device, s, e, options);\n };\n var deviceGUM = {\n \"audio\": GUM.bind(self, [\"audio\"]),\n \"video\": GUM.bind(self, [\"video\"]),\n \"desktop\": screenObtainer.obtainStream.bind(screenObtainer)\n };\n // With FF/IE we can't split the stream into audio and video because FF\n // doesn't support media stream constructors. So, we need to get the\n // audio stream separately from the video stream using two distinct GUM\n // calls. Not very user friendly :-( but we don't have many other\n // options neither.\n //\n // Note that we pack those 2 streams in a single object and pass it to\n // the successCallback method.\n obtainDevices({\n devices: options.devices,\n streams: [],\n successCallback: successCallback,\n errorCallback: reject,\n deviceGUM: deviceGUM\n });\n } else {\n var hasDesktop = options.devices.indexOf('desktop') > -1;\n if (hasDesktop) {\n options.devices.splice(options.devices.indexOf(\"desktop\"), 1);\n }\n options.resolution = options.resolution || '360';\n if(options.devices.length) {\n this.getUserMediaWithConstraints(\n options.devices,\n function (stream) {\n if(hasDesktop) {\n screenObtainer.obtainStream(\n function (desktopStream) {\n successCallback({audioVideo: stream,\n desktopStream: desktopStream});\n }, function (error) {\n reject(\n JitsiTrackErrors.parseError(error));\n });\n } else {\n successCallback({audioVideo: stream});\n }\n },\n function (error) {\n reject(JitsiTrackErrors.parseError(error));\n },\n options);\n } else if (hasDesktop) {\n screenObtainer.obtainStream(\n function (stream) {\n successCallback({desktopStream: stream});\n }, function (error) {\n reject(\n JitsiTrackErrors.parseError(error));\n });\n }\n }\n }.bind(this));\n },\n addListener: function (eventType, listener) {\n eventEmitter.on(eventType, listener);\n },\n removeListener: function (eventType, listener) {\n eventEmitter.removeListener(eventType, listener);\n },\n getDeviceAvailability: function () {\n return devices;\n },\n isRTCReady: function () {\n return rtcReady;\n },\n /**\n * Checks if its possible to enumerate available cameras/micropones.\n * @returns {boolean} true if available, false otherwise.\n */\n isDeviceListAvailable: function () {\n var isEnumerateDevicesAvailable = navigator.mediaDevices && navigator.mediaDevices.enumerateDevices;\n if (isEnumerateDevicesAvailable) {\n return true;\n }\n return (MediaStreamTrack && MediaStreamTrack.getSources)? true : false;\n },\n /**\n * Returns true if changing the camera / microphone device is supported and\n * false if not.\n */\n isDeviceChangeAvailable: function () {\n if(RTCBrowserType.isChrome() || RTCBrowserType.isOpera() ||\n RTCBrowserType.isTemasysPluginUsed())\n return true;\n return false;\n },\n /**\n * A method to handle stopping of the stream.\n * One point to handle the differences in various implementations.\n * @param mediaStream MediaStream object to stop.\n */\n stopMediaStream: function (mediaStream) {\n mediaStream.getTracks().forEach(function (track) {\n // stop() not supported with IE\n if (track.stop) {\n track.stop();\n }\n });\n\n // leave stop for implementation still using it\n if (mediaStream.stop) {\n mediaStream.stop();\n }\n },\n /**\n * Returns whether the desktop sharing is enabled or not.\n * @returns {boolean}\n */\n isDesktopSharingEnabled: function () {\n return screenObtainer.isSupported();\n }\n\n};\n\nmodule.exports = RTCUtils;\n", + "/* global chrome, $, alert */\n/* jshint -W003 */\nvar logger = require(\"jitsi-meet-logger\").getLogger(__filename);\nvar RTCBrowserType = require(\"./RTCBrowserType\");\nvar AdapterJS = require(\"./adapter.screenshare\");\nvar DesktopSharingEventTypes\n = require(\"../../service/desktopsharing/DesktopSharingEventTypes\");\n\n/**\n * Indicates whether the Chrome desktop sharing extension is installed.\n * @type {boolean}\n */\nvar chromeExtInstalled = false;\n\n/**\n * Indicates whether an update of the Chrome desktop sharing extension is\n * required.\n * @type {boolean}\n */\nvar chromeExtUpdateRequired = false;\n\n/**\n * Whether the jidesha extension for firefox is installed for the domain on\n * which we are running. Null designates an unknown value.\n * @type {null}\n */\nvar firefoxExtInstalled = null;\n\n/**\n * If set to true, detection of an installed firefox extension will be started\n * again the next time obtainScreenOnFirefox is called (e.g. next time the\n * user tries to enable screen sharing).\n */\nvar reDetectFirefoxExtension = false;\n\nvar GUM = null;\n\n/**\n * Handles obtaining a stream from a screen capture on different browsers.\n */\nvar ScreenObtainer = {\n /**\n * The EventEmitter to use to emit events.\n * @type {null}\n */\n eventEmitter: null,\n obtainStream: null,\n /**\n * Initializes the function used to obtain a screen capture\n * (this.obtainStream).\n * \n * If the browser is Chrome, it uses the value of\n * 'options.desktopSharingChromeMethod' (or 'options.desktopSharing') to\n * decide whether to use the a Chrome extension (if the value is 'ext'),\n * use the \"screen\" media source (if the value is 'webrtc'),\n * or disable screen capture (if the value is other).\n * Note that for the \"screen\" media source to work the\n * 'chrome://flags/#enable-usermedia-screen-capture' flag must be set.\n */\n init: function(eventEmitter, options, gum) {\n this.eventEmitter = eventEmitter;\n var obtainDesktopStream = null;\n this.options = options = options || {};\n GUM = gum;\n\n if (RTCBrowserType.isFirefox())\n initFirefoxExtensionDetection(options);\n\n // TODO remove this, options.desktopSharing is deprecated.\n var chromeMethod =\n (options.desktopSharingChromeMethod || options.desktopSharing);\n\n if (RTCBrowserType.isTemasysPluginUsed()) {\n if (!AdapterJS.WebRTCPlugin.plugin.HasScreensharingFeature) {\n logger.info(\"Screensharing not supported by this plugin \" +\n \"version\");\n } else if(!AdapterJS.WebRTCPlugin.plugin.isScreensharingAvailable) {\n logger.info(\n \"Screensharing not available with Temasys plugin on\" +\n \" this site\");\n } else {\n obtainDesktopStream = obtainWebRTCScreen;\n logger.info(\"Using Temasys plugin for desktop sharing\");\n }\n } else if (RTCBrowserType.isChrome()) {\n if (chromeMethod == \"ext\") {\n if (RTCBrowserType.getChromeVersion() >= 34) {\n obtainDesktopStream =\n this.obtainScreenFromExtension;\n logger.info(\"Using Chrome extension for desktop sharing\");\n initChromeExtension(options);\n } else {\n logger.info(\"Chrome extension not supported until ver 34\");\n }\n } else if (chromeMethod == \"webrtc\") {\n obtainDesktopStream = obtainWebRTCScreen;\n logger.info(\"Using Chrome WebRTC for desktop sharing\");\n }\n } else if (RTCBrowserType.isFirefox()) {\n if (options.desktopSharingFirefoxDisabled) {\n obtainDesktopStream = null;\n } else if (window.location.protocol === \"http:\"){\n logger.log(\"Screen sharing is not supported over HTTP. \" +\n \"Use of HTTPS is required.\");\n obtainDesktopStream = null;\n } else {\n obtainDesktopStream = this.obtainScreenOnFirefox;\n }\n\n }\n\n if (!obtainDesktopStream) {\n logger.info(\"Desktop sharing disabled\");\n }\n\n this.obtainStream = obtainDesktopStream;\n },\n\n /**\n * Checks whether obtaining a screen capture is supported in the current\n * environment.\n * @returns {boolean}\n */\n isSupported: function() {\n return !!this.obtainStream;\n },\n /**\n * Obtains a screen capture stream on Firefox.\n * @param callback\n * @param errorCallback\n */\n obtainScreenOnFirefox:\n function (callback, errorCallback) {\n var self = this;\n var extensionRequired = false;\n if (this.options.desktopSharingFirefoxMaxVersionExtRequired === -1 ||\n (this.options.desktopSharingFirefoxMaxVersionExtRequired >= 0 &&\n RTCBrowserType.getFirefoxVersion() <=\n this.options.desktopSharingFirefoxMaxVersionExtRequired)) {\n extensionRequired = true;\n logger.log(\"Jidesha extension required on firefox version \" +\n RTCBrowserType.getFirefoxVersion());\n }\n\n if (!extensionRequired || firefoxExtInstalled === true) {\n obtainWebRTCScreen(callback, errorCallback);\n return;\n }\n\n if (reDetectFirefoxExtension) {\n reDetectFirefoxExtension = false;\n initFirefoxExtensionDetection(this.options);\n }\n\n // Give it some (more) time to initialize, and assume lack of\n // extension if it hasn't.\n if (firefoxExtInstalled === null) {\n window.setTimeout(\n function() {\n if (firefoxExtInstalled === null)\n firefoxExtInstalled = false;\n self.obtainScreenOnFirefox(callback, errorCallback);\n },\n 300\n );\n logger.log(\"Waiting for detection of jidesha on firefox to \" +\n \"finish.\");\n return;\n }\n\n // We need an extension and it isn't installed.\n\n // Make sure we check for the extension when the user clicks again.\n firefoxExtInstalled = null;\n reDetectFirefoxExtension = true;\n\n // Prompt the user to install the extension\n this.eventEmitter.emit(\n DesktopSharingEventTypes.FIREFOX_EXTENSION_NEEDED,\n this.options.desktopSharingFirefoxExtensionURL);\n\n // Make sure desktopsharing knows that we failed, so that it doesn't get\n // stuck in 'switching' mode.\n errorCallback('Firefox extension required.');\n },\n /**\n * Asks Chrome extension to call chooseDesktopMedia and gets chrome\n * 'desktop' stream for returned stream token.\n */\n obtainScreenFromExtension: function (streamCallback, failCallback) {\n if (chromeExtInstalled) {\n doGetStreamFromExtension(this.options, streamCallback,\n failCallback);\n } else {\n if (chromeExtUpdateRequired) {\n alert(\n 'Jitsi Desktop Streamer requires update. ' +\n 'Changes will take effect after next Chrome restart.');\n }\n\n chrome.webstore.install(\n getWebStoreInstallUrl(this.options),\n function (arg) {\n logger.log(\"Extension installed successfully\", arg);\n chromeExtInstalled = true;\n // We need to give a moment for the endpoint to become\n // available\n window.setTimeout(function () {\n doGetStreamFromExtension(this.options, streamCallback,\n failCallback);\n }, 500);\n },\n function (arg) {\n logger.log(\"Failed to install the extension\", arg);\n failCallback(arg);\n }\n );\n }\n }\n};\n\n\n\n/**\n * Obtains a desktop stream using getUserMedia.\n * For this to work on Chrome, the\n * 'chrome://flags/#enable-usermedia-screen-capture' flag must be enabled.\n *\n * On firefox, the document's domain must be white-listed in the\n * 'media.getusermedia.screensharing.allowed_domains' preference in\n * 'about:config'.\n */\nfunction obtainWebRTCScreen(streamCallback, failCallback) {\n GUM(\n ['screen'],\n streamCallback,\n failCallback\n );\n}\n\n/**\n * Constructs inline install URL for Chrome desktop streaming extension.\n * The 'chromeExtensionId' must be defined in options parameter.\n * @param options supports \"desktopSharingChromeExtId\" and \"chromeExtensionId\"\n * @returns {string}\n */\nfunction getWebStoreInstallUrl(options)\n{\n //TODO remove chromeExtensionId (deprecated)\n return \"https://chrome.google.com/webstore/detail/\" +\n (options.desktopSharingChromeExtId || options.chromeExtensionId);\n}\n\n/**\n * Checks whether an update of the Chrome extension is required.\n * @param minVersion minimal required version\n * @param extVersion current extension version\n * @returns {boolean}\n */\nfunction isUpdateRequired(minVersion, extVersion) {\n try {\n var s1 = minVersion.split('.');\n var s2 = extVersion.split('.');\n\n var len = Math.max(s1.length, s2.length);\n for (var i = 0; i < len; i++) {\n var n1 = 0,\n n2 = 0;\n\n if (i < s1.length)\n n1 = parseInt(s1[i]);\n if (i < s2.length)\n n2 = parseInt(s2[i]);\n\n if (isNaN(n1) || isNaN(n2)) {\n return true;\n } else if (n1 !== n2) {\n return n1 > n2;\n }\n }\n\n // will happen if both versions have identical numbers in\n // their components (even if one of them is longer, has more components)\n return false;\n }\n catch (e) {\n logger.error(\"Failed to parse extension version\", e);\n return true;\n }\n}\n\nfunction checkChromeExtInstalled(callback, options) {\n if (!chrome || !chrome.runtime) {\n // No API, so no extension for sure\n callback(false, false);\n return;\n }\n chrome.runtime.sendMessage(\n //TODO: remove chromeExtensionId (deprecated)\n (options.desktopSharingChromeExtId || options.chromeExtensionId),\n { getVersion: true },\n function (response) {\n if (!response || !response.version) {\n // Communication failure - assume that no endpoint exists\n logger.warn(\n \"Extension not installed?: \", chrome.runtime.lastError);\n callback(false, false);\n return;\n }\n // Check installed extension version\n var extVersion = response.version;\n logger.log('Extension version is: ' + extVersion);\n //TODO: remove minChromeExtVersion (deprecated)\n var updateRequired\n = isUpdateRequired(\n (options.desktopSharingChromeMinExtVersion ||\n options.minChromeExtVersion),\n extVersion);\n callback(!updateRequired, updateRequired);\n }\n );\n}\n\nfunction doGetStreamFromExtension(options, streamCallback, failCallback) {\n // Sends 'getStream' msg to the extension.\n // Extension id must be defined in the config.\n chrome.runtime.sendMessage(\n //TODO: remove chromeExtensionId (deprecated)\n (options.desktopSharingChromeExtId || options.chromeExtensionId),\n {\n getStream: true,\n //TODO: remove desktopSharingSources (deprecated).\n sources: (options.desktopSharingChromeSources ||\n options.desktopSharingSources)\n },\n function (response) {\n if (!response) {\n failCallback(chrome.runtime.lastError);\n return;\n }\n logger.log(\"Response from extension: \" + response);\n if (response.streamId) {\n GUM(\n ['desktop'],\n function (stream) {\n streamCallback(stream);\n },\n failCallback,\n {desktopStream: response.streamId});\n } else {\n failCallback(\"Extension failed to get the stream\");\n }\n }\n );\n}\n\n/**\n * Initializes with extension id set in\n * config.js to support inline installs. Host site must be selected as main\n * website of published extension.\n * @param options supports \"desktopSharingChromeExtId\" and \"chromeExtensionId\"\n */\nfunction initInlineInstalls(options)\n{\n $(\"link[rel=chrome-webstore-item]\").attr(\"href\",\n getWebStoreInstallUrl(options));\n}\n\nfunction initChromeExtension(options) {\n // Initialize Chrome extension inline installs\n initInlineInstalls(options);\n // Check if extension is installed\n checkChromeExtInstalled(function (installed, updateRequired) {\n chromeExtInstalled = installed;\n chromeExtUpdateRequired = updateRequired;\n logger.info(\n \"Chrome extension installed: \" + chromeExtInstalled +\n \" updateRequired: \" + chromeExtUpdateRequired);\n }, options);\n}\n\n/**\n * Starts the detection of an installed jidesha extension for firefox.\n * @param options supports \"desktopSharingFirefoxDisabled\",\n * \"desktopSharingFirefoxExtId\" and \"chromeExtensionId\"\n */\nfunction initFirefoxExtensionDetection(options) {\n if (options.desktopSharingFirefoxDisabled) {\n return;\n }\n if (firefoxExtInstalled === false || firefoxExtInstalled === true)\n return;\n if (!options.desktopSharingFirefoxExtId) {\n firefoxExtInstalled = false;\n return;\n }\n\n var img = document.createElement('img');\n img.onload = function(){\n logger.log(\"Detected firefox screen sharing extension.\");\n firefoxExtInstalled = true;\n };\n img.onerror = function(){\n logger.log(\"Detected lack of firefox screen sharing extension.\");\n firefoxExtInstalled = false;\n };\n\n // The jidesha extension exposes an empty image file under the url:\n // \"chrome://EXT_ID/content/DOMAIN.png\"\n // Where EXT_ID is the ID of the extension with \"@\" replaced by \".\", and\n // DOMAIN is a domain whitelisted by the extension.\n var src = \"chrome://\" +\n (options.desktopSharingFirefoxExtId.replace('@', '.')) +\n \"/content/\" + document.location.hostname + \".png\";\n img.setAttribute('src', src);\n}\n\nmodule.exports = ScreenObtainer;\n", + "/*! adapterjs - v0.12.3 - 2015-11-16 */\nvar console = require(\"jitsi-meet-logger\").getLogger(__filename);\n// Adapter's interface.\nvar AdapterJS = AdapterJS || {};\n\n// Browserify compatibility\nif(typeof exports !== 'undefined') {\n module.exports = AdapterJS;\n}\n\nAdapterJS.options = AdapterJS.options || {};\n\n// uncomment to get virtual webcams\n// AdapterJS.options.getAllCams = true;\n\n// uncomment to prevent the install prompt when the plugin in not yet installed\n// AdapterJS.options.hidePluginInstallPrompt = true;\n\n// AdapterJS version\nAdapterJS.VERSION = '0.12.3';\n\n// This function will be called when the WebRTC API is ready to be used\n// Whether it is the native implementation (Chrome, Firefox, Opera) or\n// the plugin\n// You may Override this function to synchronise the start of your application\n// with the WebRTC API being ready.\n// If you decide not to override use this synchronisation, it may result in\n// an extensive CPU usage on the plugin start (once per tab loaded)\n// Params:\n// - isUsingPlugin: true is the WebRTC plugin is being used, false otherwise\n//\nAdapterJS.onwebrtcready = AdapterJS.onwebrtcready || function(isUsingPlugin) {\n // The WebRTC API is ready.\n // Override me and do whatever you want here\n};\n\n// Sets a callback function to be called when the WebRTC interface is ready.\n// The first argument is the function to callback.\\\n// Throws an error if the first argument is not a function\nAdapterJS.webRTCReady = function (callback) {\n if (typeof callback !== 'function') {\n throw new Error('Callback provided is not a function');\n }\n\n if (true === AdapterJS.onwebrtcreadyDone) {\n // All WebRTC interfaces are ready, just call the callback\n callback(null !== AdapterJS.WebRTCPlugin.plugin);\n } else {\n // will be triggered automatically when your browser/plugin is ready.\n AdapterJS.onwebrtcready = callback;\n }\n};\n\n// Plugin namespace\nAdapterJS.WebRTCPlugin = AdapterJS.WebRTCPlugin || {};\n\n// The object to store plugin information\nAdapterJS.WebRTCPlugin.pluginInfo = {\n prefix : 'Tem',\n plugName : 'TemWebRTCPlugin',\n pluginId : 'plugin0',\n type : 'application/x-temwebrtcplugin',\n onload : '__TemWebRTCReady0',\n portalLink : 'http://skylink.io/plugin/',\n downloadLink : null, //set below\n companyName: 'Temasys'\n};\nif(!!navigator.platform.match(/^Mac/i)) {\n AdapterJS.WebRTCPlugin.pluginInfo.downloadLink = 'http://bit.ly/1n77hco';\n}\nelse if(!!navigator.platform.match(/^Win/i)) {\n AdapterJS.WebRTCPlugin.pluginInfo.downloadLink = 'http://bit.ly/1kkS4FN';\n}\n\nAdapterJS.WebRTCPlugin.TAGS = {\n NONE : 'none',\n AUDIO : 'audio',\n VIDEO : 'video'\n};\n\n// Unique identifier of each opened page\nAdapterJS.WebRTCPlugin.pageId = Math.random().toString(36).slice(2);\n\n// Use this whenever you want to call the plugin.\nAdapterJS.WebRTCPlugin.plugin = null;\n\n// Set log level for the plugin once it is ready.\n// The different values are\n// This is an asynchronous function that will run when the plugin is ready\nAdapterJS.WebRTCPlugin.setLogLevel = null;\n\n// Defines webrtc's JS interface according to the plugin's implementation.\n// Define plugin Browsers as WebRTC Interface.\nAdapterJS.WebRTCPlugin.defineWebRTCInterface = null;\n\n// This function detects whether or not a plugin is installed.\n// Checks if Not IE (firefox, for example), else if it's IE,\n// we're running IE and do something. If not it is not supported.\nAdapterJS.WebRTCPlugin.isPluginInstalled = null;\n\n // Lets adapter.js wait until the the document is ready before injecting the plugin\nAdapterJS.WebRTCPlugin.pluginInjectionInterval = null;\n\n// Inject the HTML DOM object element into the page.\nAdapterJS.WebRTCPlugin.injectPlugin = null;\n\n// States of readiness that the plugin goes through when\n// being injected and stated\nAdapterJS.WebRTCPlugin.PLUGIN_STATES = {\n NONE : 0, // no plugin use\n INITIALIZING : 1, // Detected need for plugin\n INJECTING : 2, // Injecting plugin\n INJECTED: 3, // Plugin element injected but not usable yet\n READY: 4 // Plugin ready to be used\n};\n\n// Current state of the plugin. You cannot use the plugin before this is\n// equal to AdapterJS.WebRTCPlugin.PLUGIN_STATES.READY\nAdapterJS.WebRTCPlugin.pluginState = AdapterJS.WebRTCPlugin.PLUGIN_STATES.NONE;\n\n// True is AdapterJS.onwebrtcready was already called, false otherwise\n// Used to make sure AdapterJS.onwebrtcready is only called once\nAdapterJS.onwebrtcreadyDone = false;\n\n// Log levels for the plugin.\n// To be set by calling AdapterJS.WebRTCPlugin.setLogLevel\n/*\nLog outputs are prefixed in some cases.\n INFO: Information reported by the plugin.\n ERROR: Errors originating from within the plugin.\n WEBRTC: Error originating from within the libWebRTC library\n*/\n// From the least verbose to the most verbose\nAdapterJS.WebRTCPlugin.PLUGIN_LOG_LEVELS = {\n NONE : 'NONE',\n ERROR : 'ERROR',\n WARNING : 'WARNING',\n INFO: 'INFO',\n VERBOSE: 'VERBOSE',\n SENSITIVE: 'SENSITIVE'\n};\n\n// Does a waiting check before proceeding to load the plugin.\nAdapterJS.WebRTCPlugin.WaitForPluginReady = null;\n\n// This methid will use an interval to wait for the plugin to be ready.\nAdapterJS.WebRTCPlugin.callWhenPluginReady = null;\n\n// !!!! WARNING: DO NOT OVERRIDE THIS FUNCTION. !!!\n// This function will be called when plugin is ready. It sends necessary\n// details to the plugin.\n// The function will wait for the document to be ready and the set the\n// plugin state to AdapterJS.WebRTCPlugin.PLUGIN_STATES.READY,\n// indicating that it can start being requested.\n// This function is not in the IE/Safari condition brackets so that\n// TemPluginLoaded function might be called on Chrome/Firefox.\n// This function is the only private function that is not encapsulated to\n// allow the plugin method to be called.\n__TemWebRTCReady0 = function () {\n if (document.readyState === 'complete') {\n AdapterJS.WebRTCPlugin.pluginState = AdapterJS.WebRTCPlugin.PLUGIN_STATES.READY;\n\n AdapterJS.maybeThroughWebRTCReady();\n } else {\n AdapterJS.WebRTCPlugin.documentReadyInterval = setInterval(function () {\n if (document.readyState === 'complete') {\n // TODO: update comments, we wait for the document to be ready\n clearInterval(AdapterJS.WebRTCPlugin.documentReadyInterval);\n AdapterJS.WebRTCPlugin.pluginState = AdapterJS.WebRTCPlugin.PLUGIN_STATES.READY;\n\n AdapterJS.maybeThroughWebRTCReady();\n }\n }, 100);\n }\n};\n\nAdapterJS.maybeThroughWebRTCReady = function() {\n if (!AdapterJS.onwebrtcreadyDone) {\n AdapterJS.onwebrtcreadyDone = true;\n\n if (typeof(AdapterJS.onwebrtcready) === 'function') {\n AdapterJS.onwebrtcready(AdapterJS.WebRTCPlugin.plugin !== null);\n }\n }\n};\n\n// Text namespace\nAdapterJS.TEXT = {\n PLUGIN: {\n REQUIRE_INSTALLATION: 'This website requires you to install a WebRTC-enabling plugin ' +\n 'to work on this browser.',\n NOT_SUPPORTED: 'Your browser does not support WebRTC.',\n BUTTON: 'Install Now'\n },\n REFRESH: {\n REQUIRE_REFRESH: 'Please refresh page',\n BUTTON: 'Refresh Page'\n }\n};\n\n// The result of ice connection states.\n// - starting: Ice connection is starting.\n// - checking: Ice connection is checking.\n// - connected Ice connection is connected.\n// - completed Ice connection is connected.\n// - done Ice connection has been completed.\n// - disconnected Ice connection has been disconnected.\n// - failed Ice connection has failed.\n// - closed Ice connection is closed.\nAdapterJS._iceConnectionStates = {\n starting : 'starting',\n checking : 'checking',\n connected : 'connected',\n completed : 'connected',\n done : 'completed',\n disconnected : 'disconnected',\n failed : 'failed',\n closed : 'closed'\n};\n\n//The IceConnection states that has been fired for each peer.\nAdapterJS._iceConnectionFiredStates = [];\n\n\n// Check if WebRTC Interface is defined.\nAdapterJS.isDefined = null;\n\n// This function helps to retrieve the webrtc detected browser information.\n// This sets:\n// - webrtcDetectedBrowser: The browser agent name.\n// - webrtcDetectedVersion: The browser version.\n// - webrtcDetectedType: The types of webRTC support.\n// - 'moz': Mozilla implementation of webRTC.\n// - 'webkit': WebKit implementation of webRTC.\n// - 'plugin': Using the plugin implementation.\nAdapterJS.parseWebrtcDetectedBrowser = function () {\n var hasMatch, checkMatch = navigator.userAgent.match(\n /(opera|chrome|safari|firefox|msie|trident(?=\\/))\\/?\\s*(\\d+)/i) || [];\n if (/trident/i.test(checkMatch[1])) {\n hasMatch = /\\brv[ :]+(\\d+)/g.exec(navigator.userAgent) || [];\n webrtcDetectedBrowser = 'IE';\n webrtcDetectedVersion = parseInt(hasMatch[1] || '0', 10);\n } else if (checkMatch[1] === 'Chrome') {\n hasMatch = navigator.userAgent.match(/\\bOPR\\/(\\d+)/);\n if (hasMatch !== null) {\n webrtcDetectedBrowser = 'opera';\n webrtcDetectedVersion = parseInt(hasMatch[1], 10);\n }\n }\n if (navigator.userAgent.indexOf('Safari')) {\n if (typeof InstallTrigger !== 'undefined') {\n webrtcDetectedBrowser = 'firefox';\n } else if (/*@cc_on!@*/ false || !!document.documentMode) {\n webrtcDetectedBrowser = 'IE';\n } else if (\n Object.prototype.toString.call(window.HTMLElement).indexOf('Constructor') > 0) {\n webrtcDetectedBrowser = 'safari';\n } else if (!!window.opera || navigator.userAgent.indexOf(' OPR/') >= 0) {\n webrtcDetectedBrowser = 'opera';\n } else if (!!window.chrome) {\n webrtcDetectedBrowser = 'chrome';\n }\n }\n if (!webrtcDetectedBrowser) {\n webrtcDetectedVersion = checkMatch[1];\n }\n if (!webrtcDetectedVersion) {\n try {\n checkMatch = (checkMatch[2]) ? [checkMatch[1], checkMatch[2]] :\n [navigator.appName, navigator.appVersion, '-?'];\n if ((hasMatch = navigator.userAgent.match(/version\\/(\\d+)/i)) !== null) {\n checkMatch.splice(1, 1, hasMatch[1]);\n }\n webrtcDetectedVersion = parseInt(checkMatch[1], 10);\n } catch (error) { }\n }\n};\n\n// To fix configuration as some browsers does not support\n// the 'urls' attribute.\nAdapterJS.maybeFixConfiguration = function (pcConfig) {\n if (pcConfig === null) {\n return;\n }\n for (var i = 0; i < pcConfig.iceServers.length; i++) {\n if (pcConfig.iceServers[i].hasOwnProperty('urls')) {\n pcConfig.iceServers[i].url = pcConfig.iceServers[i].urls;\n delete pcConfig.iceServers[i].urls;\n }\n }\n};\n\nAdapterJS.addEvent = function(elem, evnt, func) {\n if (elem.addEventListener) { // W3C DOM\n elem.addEventListener(evnt, func, false);\n } else if (elem.attachEvent) {// OLD IE DOM\n elem.attachEvent('on'+evnt, func);\n } else { // No much to do\n elem[evnt] = func;\n }\n};\n\nAdapterJS.renderNotificationBar = function (text, buttonText, buttonLink, openNewTab, displayRefreshBar) {\n // only inject once the page is ready\n if (document.readyState !== 'complete') {\n return;\n }\n\n var w = window;\n var i = document.createElement('iframe');\n i.style.position = 'fixed';\n i.style.top = '-41px';\n i.style.left = 0;\n i.style.right = 0;\n i.style.width = '100%';\n i.style.height = '40px';\n i.style.backgroundColor = '#ffffe1';\n i.style.border = 'none';\n i.style.borderBottom = '1px solid #888888';\n i.style.zIndex = '9999999';\n if(typeof i.style.webkitTransition === 'string') {\n i.style.webkitTransition = 'all .5s ease-out';\n } else if(typeof i.style.transition === 'string') {\n i.style.transition = 'all .5s ease-out';\n }\n document.body.appendChild(i);\n c = (i.contentWindow) ? i.contentWindow :\n (i.contentDocument.document) ? i.contentDocument.document : i.contentDocument;\n c.document.open();\n c.document.write('' + text + '');\n if(buttonText && buttonLink) {\n c.document.write('');\n c.document.close();\n\n // On click on okay\n AdapterJS.addEvent(c.document.getElementById('okay'), 'click', function(e) {\n if (!!displayRefreshBar) {\n AdapterJS.renderNotificationBar(AdapterJS.TEXT.EXTENSION ?\n AdapterJS.TEXT.EXTENSION.REQUIRE_REFRESH : AdapterJS.TEXT.REFRESH.REQUIRE_REFRESH,\n AdapterJS.TEXT.REFRESH.BUTTON, 'javascript:location.reload()');\n }\n window.open(buttonLink, !!openNewTab ? '_blank' : '_top');\n\n e.preventDefault();\n try {\n event.cancelBubble = true;\n } catch(error) { }\n\n var pluginInstallInterval = setInterval(function(){\n if(! isIE) {\n navigator.plugins.refresh(false);\n }\n AdapterJS.WebRTCPlugin.isPluginInstalled(\n AdapterJS.WebRTCPlugin.pluginInfo.prefix,\n AdapterJS.WebRTCPlugin.pluginInfo.plugName,\n function() { // plugin now installed\n clearInterval(pluginInstallInterval);\n AdapterJS.WebRTCPlugin.defineWebRTCInterface();\n },\n function() {\n // still no plugin detected, nothing to do\n });\n } , 500);\n });\n\n // On click on Cancel\n AdapterJS.addEvent(c.document.getElementById('cancel'), 'click', function(e) {\n w.document.body.removeChild(i);\n });\n } else {\n c.document.close();\n }\n setTimeout(function() {\n if(typeof i.style.webkitTransform === 'string') {\n i.style.webkitTransform = 'translateY(40px)';\n } else if(typeof i.style.transform === 'string') {\n i.style.transform = 'translateY(40px)';\n } else {\n i.style.top = '0px';\n }\n }, 300);\n};\n\n// -----------------------------------------------------------\n// Detected webrtc implementation. Types are:\n// - 'moz': Mozilla implementation of webRTC.\n// - 'webkit': WebKit implementation of webRTC.\n// - 'plugin': Using the plugin implementation.\nwebrtcDetectedType = null;\n\n// Detected webrtc datachannel support. Types are:\n// - 'SCTP': SCTP datachannel support.\n// - 'RTP': RTP datachannel support.\nwebrtcDetectedDCSupport = null;\n\n// Set the settings for creating DataChannels, MediaStream for\n// Cross-browser compability.\n// - This is only for SCTP based support browsers.\n// the 'urls' attribute.\ncheckMediaDataChannelSettings =\n function (peerBrowserAgent, peerBrowserVersion, callback, constraints) {\n if (typeof callback !== 'function') {\n return;\n }\n var beOfferer = true;\n var isLocalFirefox = webrtcDetectedBrowser === 'firefox';\n // Nightly version does not require MozDontOfferDataChannel for interop\n var isLocalFirefoxInterop = webrtcDetectedType === 'moz' && webrtcDetectedVersion > 30;\n var isPeerFirefox = peerBrowserAgent === 'firefox';\n var isPeerFirefoxInterop = peerBrowserAgent === 'firefox' &&\n ((peerBrowserVersion) ? (peerBrowserVersion > 30) : false);\n\n // Resends an updated version of constraints for MozDataChannel to work\n // If other userAgent is firefox and user is firefox, remove MozDataChannel\n if ((isLocalFirefox && isPeerFirefox) || (isLocalFirefoxInterop)) {\n try {\n delete constraints.mandatory.MozDontOfferDataChannel;\n } catch (error) {\n console.error('Failed deleting MozDontOfferDataChannel');\n console.error(error);\n }\n } else if ((isLocalFirefox && !isPeerFirefox)) {\n constraints.mandatory.MozDontOfferDataChannel = true;\n }\n if (!isLocalFirefox) {\n // temporary measure to remove Moz* constraints in non Firefox browsers\n for (var prop in constraints.mandatory) {\n if (constraints.mandatory.hasOwnProperty(prop)) {\n if (prop.indexOf('Moz') !== -1) {\n delete constraints.mandatory[prop];\n }\n }\n }\n }\n // Firefox (not interopable) cannot offer DataChannel as it will cause problems to the\n // interopability of the media stream\n if (isLocalFirefox && !isPeerFirefox && !isLocalFirefoxInterop) {\n beOfferer = false;\n }\n callback(beOfferer, constraints);\n};\n\n// Handles the differences for all browsers ice connection state output.\n// - Tested outcomes are:\n// - Chrome (offerer) : 'checking' > 'completed' > 'completed'\n// - Chrome (answerer) : 'checking' > 'connected'\n// - Firefox (offerer) : 'checking' > 'connected'\n// - Firefox (answerer): 'checking' > 'connected'\ncheckIceConnectionState = function (peerId, iceConnectionState, callback) {\n if (typeof callback !== 'function') {\n console.warn('No callback specified in checkIceConnectionState. Aborted.');\n return;\n }\n peerId = (peerId) ? peerId : 'peer';\n\n if (!AdapterJS._iceConnectionFiredStates[peerId] ||\n iceConnectionState === AdapterJS._iceConnectionStates.disconnected ||\n iceConnectionState === AdapterJS._iceConnectionStates.failed ||\n iceConnectionState === AdapterJS._iceConnectionStates.closed) {\n AdapterJS._iceConnectionFiredStates[peerId] = [];\n }\n iceConnectionState = AdapterJS._iceConnectionStates[iceConnectionState];\n if (AdapterJS._iceConnectionFiredStates[peerId].indexOf(iceConnectionState) < 0) {\n AdapterJS._iceConnectionFiredStates[peerId].push(iceConnectionState);\n if (iceConnectionState === AdapterJS._iceConnectionStates.connected) {\n setTimeout(function () {\n AdapterJS._iceConnectionFiredStates[peerId]\n .push(AdapterJS._iceConnectionStates.done);\n callback(AdapterJS._iceConnectionStates.done);\n }, 1000);\n }\n callback(iceConnectionState);\n }\n return;\n};\n\n// Firefox:\n// - Creates iceServer from the url for Firefox.\n// - Create iceServer with stun url.\n// - Create iceServer with turn url.\n// - Ignore the transport parameter from TURN url for FF version <=27.\n// - Return null for createIceServer if transport=tcp.\n// - FF 27 and above supports transport parameters in TURN url,\n// - So passing in the full url to create iceServer.\n// Chrome:\n// - Creates iceServer from the url for Chrome M33 and earlier.\n// - Create iceServer with stun url.\n// - Chrome M28 & above uses below TURN format.\n// Plugin:\n// - Creates Ice Server for Plugin Browsers\n// - If Stun - Create iceServer with stun url.\n// - Else - Create iceServer with turn url\n// - This is a WebRTC Function\ncreateIceServer = null;\n\n// Firefox:\n// - Creates IceServers for Firefox\n// - Use .url for FireFox.\n// - Multiple Urls support\n// Chrome:\n// - Creates iceServers from the urls for Chrome M34 and above.\n// - .urls is supported since Chrome M34.\n// - Multiple Urls support\n// Plugin:\n// - Creates Ice Servers for Plugin Browsers\n// - Multiple Urls support\n// - This is a WebRTC Function\ncreateIceServers = null;\n//------------------------------------------------------------\n\n//The RTCPeerConnection object.\nRTCPeerConnection = null;\n\n// Creates RTCSessionDescription object for Plugin Browsers\nRTCSessionDescription = (typeof RTCSessionDescription === 'function') ?\n RTCSessionDescription : null;\n\n// Creates RTCIceCandidate object for Plugin Browsers\nRTCIceCandidate = (typeof RTCIceCandidate === 'function') ?\n RTCIceCandidate : null;\n\n// Get UserMedia (only difference is the prefix).\n// Code from Adam Barth.\ngetUserMedia = null;\n\n// Attach a media stream to an element.\nattachMediaStream = null;\n\n// Re-attach a media stream to an element.\nreattachMediaStream = null;\n\n\n// Detected browser agent name. Types are:\n// - 'firefox': Firefox browser.\n// - 'chrome': Chrome browser.\n// - 'opera': Opera browser.\n// - 'safari': Safari browser.\n// - 'IE' - Internet Explorer browser.\nwebrtcDetectedBrowser = null;\n\n// Detected browser version.\nwebrtcDetectedVersion = null;\n\n// Check for browser types and react accordingly\nif (navigator.mozGetUserMedia) {\n webrtcDetectedBrowser = 'firefox';\n webrtcDetectedVersion = parseInt(navigator\n .userAgent.match(/Firefox\\/([0-9]+)\\./)[1], 10);\n webrtcDetectedType = 'moz';\n webrtcDetectedDCSupport = 'SCTP';\n\n RTCPeerConnection = function (pcConfig, pcConstraints) {\n AdapterJS.maybeFixConfiguration(pcConfig);\n return new mozRTCPeerConnection(pcConfig, pcConstraints);\n };\n\n // The RTCSessionDescription object.\n RTCSessionDescription = mozRTCSessionDescription;\n window.RTCSessionDescription = RTCSessionDescription;\n\n // The RTCIceCandidate object.\n RTCIceCandidate = mozRTCIceCandidate;\n window.RTCIceCandidate = RTCIceCandidate;\n\n window.getUserMedia = navigator.mozGetUserMedia.bind(navigator);\n navigator.getUserMedia = window.getUserMedia;\n\n // Shim for MediaStreamTrack.getSources.\n MediaStreamTrack.getSources = function(successCb) {\n setTimeout(function() {\n var infos = [\n { kind: 'audio', id: 'default', label:'', facing:'' },\n { kind: 'video', id: 'default', label:'', facing:'' }\n ];\n successCb(infos);\n }, 0);\n };\n\n createIceServer = function (url, username, password) {\n var iceServer = null;\n var url_parts = url.split(':');\n if (url_parts[0].indexOf('stun') === 0) {\n iceServer = { url : url };\n } else if (url_parts[0].indexOf('turn') === 0) {\n if (webrtcDetectedVersion < 27) {\n var turn_url_parts = url.split('?');\n if (turn_url_parts.length === 1 ||\n turn_url_parts[1].indexOf('transport=udp') === 0) {\n iceServer = {\n url : turn_url_parts[0],\n credential : password,\n username : username\n };\n }\n } else {\n iceServer = {\n url : url,\n credential : password,\n username : username\n };\n }\n }\n return iceServer;\n };\n\n createIceServers = function (urls, username, password) {\n var iceServers = [];\n for (var i = 0; i < urls.length; i++) {\n var iceServer = createIceServer(urls[i], username, password);\n if (iceServer !== null) {\n iceServers.push(iceServer);\n }\n }\n return iceServers;\n };\n\n attachMediaStream = function (element, stream) {\n element.mozSrcObject = stream;\n if (stream !== null)\n element.play();\n\n return element;\n };\n\n reattachMediaStream = function (to, from) {\n to.mozSrcObject = from.mozSrcObject;\n to.play();\n return to;\n };\n\n MediaStreamTrack.getSources = MediaStreamTrack.getSources || function (callback) {\n if (!callback) {\n throw new TypeError('Failed to execute \\'getSources\\' on \\'MediaStreamTrack\\'' +\n ': 1 argument required, but only 0 present.');\n }\n return callback([]);\n };\n\n // Fake get{Video,Audio}Tracks\n if (!MediaStream.prototype.getVideoTracks) {\n MediaStream.prototype.getVideoTracks = function () {\n return [];\n };\n }\n if (!MediaStream.prototype.getAudioTracks) {\n MediaStream.prototype.getAudioTracks = function () {\n return [];\n };\n }\n\n AdapterJS.maybeThroughWebRTCReady();\n} else if (navigator.webkitGetUserMedia) {\n webrtcDetectedBrowser = 'chrome';\n webrtcDetectedType = 'webkit';\n webrtcDetectedVersion = parseInt(navigator\n .userAgent.match(/Chrom(e|ium)\\/([0-9]+)\\./)[2], 10);\n // check if browser is opera 20+\n var checkIfOpera = navigator.userAgent.match(/\\bOPR\\/(\\d+)/);\n if (checkIfOpera !== null) {\n webrtcDetectedBrowser = 'opera';\n webrtcDetectedVersion = parseInt(checkIfOpera[1], 10);\n }\n // check browser datachannel support\n if ((webrtcDetectedBrowser === 'chrome' && webrtcDetectedVersion >= 31) ||\n (webrtcDetectedBrowser === 'opera' && webrtcDetectedVersion >= 20)) {\n webrtcDetectedDCSupport = 'SCTP';\n } else if (webrtcDetectedBrowser === 'chrome' && webrtcDetectedVersion < 30 &&\n webrtcDetectedVersion > 24) {\n webrtcDetectedDCSupport = 'RTP';\n } else {\n webrtcDetectedDCSupport = '';\n }\n\n createIceServer = function (url, username, password) {\n var iceServer = null;\n var url_parts = url.split(':');\n if (url_parts[0].indexOf('stun') === 0) {\n iceServer = { 'url' : url };\n } else if (url_parts[0].indexOf('turn') === 0) {\n iceServer = {\n 'url' : url,\n 'credential' : password,\n 'username' : username\n };\n }\n return iceServer;\n };\n\n createIceServers = function (urls, username, password) {\n var iceServers = [];\n if (webrtcDetectedVersion >= 34) {\n iceServers = {\n 'urls' : urls,\n 'credential' : password,\n 'username' : username\n };\n } else {\n for (var i = 0; i < urls.length; i++) {\n var iceServer = createIceServer(urls[i], username, password);\n if (iceServer !== null) {\n iceServers.push(iceServer);\n }\n }\n }\n return iceServers;\n };\n\n RTCPeerConnection = function (pcConfig, pcConstraints) {\n if (webrtcDetectedVersion < 34) {\n AdapterJS.maybeFixConfiguration(pcConfig);\n }\n return new webkitRTCPeerConnection(pcConfig, pcConstraints);\n };\n\n window.getUserMedia = navigator.webkitGetUserMedia.bind(navigator);\n navigator.getUserMedia = window.getUserMedia;\n\n attachMediaStream = function (element, stream) {\n if (typeof element.srcObject !== 'undefined') {\n element.srcObject = stream;\n } else if (typeof element.mozSrcObject !== 'undefined') {\n element.mozSrcObject = stream;\n } else if (typeof element.src !== 'undefined') {\n element.src = (stream === null ? '' : URL.createObjectURL(stream));\n } else {\n console.log('Error attaching stream to element.');\n }\n return element;\n };\n\n reattachMediaStream = function (to, from) {\n to.src = from.src;\n return to;\n };\n\n AdapterJS.maybeThroughWebRTCReady();\n} else if (navigator.mediaDevices && navigator.userAgent.match(\n /Edge\\/(\\d+).(\\d+)$/)) {\n webrtcDetectedBrowser = 'edge';\n\n webrtcDetectedVersion =\n parseInt(navigator.userAgent.match(/Edge\\/(\\d+).(\\d+)$/)[2], 10);\n\n // the minimum version still supported by adapter.\n webrtcMinimumVersion = 12;\n\n window.getUserMedia = navigator.getUserMedia.bind(navigator);\n\n attachMediaStream = function(element, stream) {\n element.srcObject = stream;\n return element;\n };\n reattachMediaStream = function(to, from) {\n to.srcObject = from.srcObject;\n return to;\n };\n\n AdapterJS.maybeThroughWebRTCReady();\n} else { // TRY TO USE PLUGIN\n // IE 9 is not offering an implementation of console.log until you open a console\n if (typeof console !== 'object' || typeof console.log !== 'function') {\n /* jshint -W020 */\n console = {} || console;\n // Implemented based on console specs from MDN\n // You may override these functions\n console.log = function (arg) {};\n console.info = function (arg) {};\n console.error = function (arg) {};\n console.dir = function (arg) {};\n console.exception = function (arg) {};\n console.trace = function (arg) {};\n console.warn = function (arg) {};\n console.count = function (arg) {};\n console.debug = function (arg) {};\n console.count = function (arg) {};\n console.time = function (arg) {};\n console.timeEnd = function (arg) {};\n console.group = function (arg) {};\n console.groupCollapsed = function (arg) {};\n console.groupEnd = function (arg) {};\n /* jshint +W020 */\n }\n webrtcDetectedType = 'plugin';\n webrtcDetectedDCSupport = 'plugin';\n AdapterJS.parseWebrtcDetectedBrowser();\n isIE = webrtcDetectedBrowser === 'IE';\n\n /* jshint -W035 */\n AdapterJS.WebRTCPlugin.WaitForPluginReady = function() {\n while (AdapterJS.WebRTCPlugin.pluginState !== AdapterJS.WebRTCPlugin.PLUGIN_STATES.READY) {\n /* empty because it needs to prevent the function from running. */\n }\n };\n /* jshint +W035 */\n\n AdapterJS.WebRTCPlugin.callWhenPluginReady = function (callback) {\n if (AdapterJS.WebRTCPlugin.pluginState === AdapterJS.WebRTCPlugin.PLUGIN_STATES.READY) {\n // Call immediately if possible\n // Once the plugin is set, the code will always take this path\n callback();\n } else {\n // otherwise start a 100ms interval\n var checkPluginReadyState = setInterval(function () {\n if (AdapterJS.WebRTCPlugin.pluginState === AdapterJS.WebRTCPlugin.PLUGIN_STATES.READY) {\n clearInterval(checkPluginReadyState);\n callback();\n }\n }, 100);\n }\n };\n\n AdapterJS.WebRTCPlugin.setLogLevel = function(logLevel) {\n AdapterJS.WebRTCPlugin.callWhenPluginReady(function() {\n AdapterJS.WebRTCPlugin.plugin.setLogLevel(logLevel);\n });\n };\n\n AdapterJS.WebRTCPlugin.injectPlugin = function () {\n // only inject once the page is ready\n if (document.readyState !== 'complete') {\n return;\n }\n\n // Prevent multiple injections\n if (AdapterJS.WebRTCPlugin.pluginState !== AdapterJS.WebRTCPlugin.PLUGIN_STATES.INITIALIZING) {\n return;\n }\n\n AdapterJS.WebRTCPlugin.pluginState = AdapterJS.WebRTCPlugin.PLUGIN_STATES.INJECTING;\n\n if (webrtcDetectedBrowser === 'IE' && webrtcDetectedVersion <= 10) {\n var frag = document.createDocumentFragment();\n AdapterJS.WebRTCPlugin.plugin = document.createElement('div');\n AdapterJS.WebRTCPlugin.plugin.innerHTML = '' +\n ' ' +\n ' ' +\n ' ' +\n '' +\n '' +\n // uncomment to be able to use virtual cams\n (AdapterJS.options.getAllCams ? '':'') +\n\n '';\n while (AdapterJS.WebRTCPlugin.plugin.firstChild) {\n frag.appendChild(AdapterJS.WebRTCPlugin.plugin.firstChild);\n }\n document.body.appendChild(frag);\n\n // Need to re-fetch the plugin\n AdapterJS.WebRTCPlugin.plugin =\n document.getElementById(AdapterJS.WebRTCPlugin.pluginInfo.pluginId);\n } else {\n // Load Plugin\n AdapterJS.WebRTCPlugin.plugin = document.createElement('object');\n AdapterJS.WebRTCPlugin.plugin.id =\n AdapterJS.WebRTCPlugin.pluginInfo.pluginId;\n // IE will only start the plugin if it's ACTUALLY visible\n if (isIE) {\n AdapterJS.WebRTCPlugin.plugin.width = '1px';\n AdapterJS.WebRTCPlugin.plugin.height = '1px';\n } else { // The size of the plugin on Safari should be 0x0px\n // so that the autorisation prompt is at the top\n AdapterJS.WebRTCPlugin.plugin.width = '0px';\n AdapterJS.WebRTCPlugin.plugin.height = '0px';\n }\n AdapterJS.WebRTCPlugin.plugin.type = AdapterJS.WebRTCPlugin.pluginInfo.type;\n AdapterJS.WebRTCPlugin.plugin.innerHTML = '' +\n '' +\n ' ' +\n (AdapterJS.options.getAllCams ? '':'') +\n '' +\n '';\n document.body.appendChild(AdapterJS.WebRTCPlugin.plugin);\n }\n\n\n AdapterJS.WebRTCPlugin.pluginState = AdapterJS.WebRTCPlugin.PLUGIN_STATES.INJECTED;\n };\n\n AdapterJS.WebRTCPlugin.isPluginInstalled =\n function (comName, plugName, installedCb, notInstalledCb) {\n if (!isIE) {\n var pluginArray = navigator.plugins;\n for (var i = 0; i < pluginArray.length; i++) {\n if (pluginArray[i].name.indexOf(plugName) >= 0) {\n installedCb();\n return;\n }\n }\n notInstalledCb();\n } else {\n try {\n var axo = new ActiveXObject(comName + '.' + plugName);\n } catch (e) {\n notInstalledCb();\n return;\n }\n installedCb();\n }\n };\n\n AdapterJS.WebRTCPlugin.defineWebRTCInterface = function () {\n if (AdapterJS.WebRTCPlugin.pluginState ===\n AdapterJS.WebRTCPlugin.PLUGIN_STATES.READY) {\n console.error(\"AdapterJS - WebRTC interface has already been defined\");\n return;\n }\n\n AdapterJS.WebRTCPlugin.pluginState = AdapterJS.WebRTCPlugin.PLUGIN_STATES.INITIALIZING;\n\n AdapterJS.isDefined = function (variable) {\n return variable !== null && variable !== undefined;\n };\n\n createIceServer = function (url, username, password) {\n var iceServer = null;\n var url_parts = url.split(':');\n if (url_parts[0].indexOf('stun') === 0) {\n iceServer = {\n 'url' : url,\n 'hasCredentials' : false\n };\n } else if (url_parts[0].indexOf('turn') === 0) {\n iceServer = {\n 'url' : url,\n 'hasCredentials' : true,\n 'credential' : password,\n 'username' : username\n };\n }\n return iceServer;\n };\n\n createIceServers = function (urls, username, password) {\n var iceServers = [];\n for (var i = 0; i < urls.length; ++i) {\n iceServers.push(createIceServer(urls[i], username, password));\n }\n return iceServers;\n };\n\n RTCSessionDescription = function (info) {\n AdapterJS.WebRTCPlugin.WaitForPluginReady();\n return AdapterJS.WebRTCPlugin.plugin.\n ConstructSessionDescription(info.type, info.sdp);\n };\n\n RTCPeerConnection = function (servers, constraints) {\n var iceServers = null;\n if (servers) {\n iceServers = servers.iceServers;\n for (var i = 0; i < iceServers.length; i++) {\n if (iceServers[i].urls && !iceServers[i].url) {\n iceServers[i].url = iceServers[i].urls;\n }\n iceServers[i].hasCredentials = AdapterJS.\n isDefined(iceServers[i].username) &&\n AdapterJS.isDefined(iceServers[i].credential);\n }\n }\n var mandatory = (constraints && constraints.mandatory) ?\n constraints.mandatory : null;\n var optional = (constraints && constraints.optional) ?\n constraints.optional : null;\n\n AdapterJS.WebRTCPlugin.WaitForPluginReady();\n return AdapterJS.WebRTCPlugin.plugin.\n PeerConnection(AdapterJS.WebRTCPlugin.pageId,\n iceServers, mandatory, optional);\n };\n\n MediaStreamTrack = {};\n MediaStreamTrack.getSources = function (callback) {\n AdapterJS.WebRTCPlugin.callWhenPluginReady(function() {\n AdapterJS.WebRTCPlugin.plugin.GetSources(callback);\n });\n };\n\n window.getUserMedia = function (constraints, successCallback, failureCallback) {\n constraints.audio = constraints.audio || false;\n constraints.video = constraints.video || false;\n\n AdapterJS.WebRTCPlugin.callWhenPluginReady(function() {\n AdapterJS.WebRTCPlugin.plugin.\n getUserMedia(constraints, successCallback, failureCallback);\n });\n };\n window.navigator.getUserMedia = window.getUserMedia;\n\n attachMediaStream = function (element, stream) {\n if (!element || !element.parentNode) {\n return;\n }\n\n var streamId;\n if (stream === null) {\n streamId = '';\n } else {\n if (typeof stream.enableSoundTracks !== 'undefined') {\n stream.enableSoundTracks(true);\n }\n streamId = stream.id;\n }\n\n var elementId = element.id.length === 0 ? Math.random().toString(36).slice(2) : element.id;\n var nodeName = element.nodeName.toLowerCase();\n if (nodeName !== 'object') { // not a plugin tag yet\n var tag;\n switch(nodeName) {\n case 'audio':\n tag = AdapterJS.WebRTCPlugin.TAGS.AUDIO;\n break;\n case 'video':\n tag = AdapterJS.WebRTCPlugin.TAGS.VIDEO;\n break;\n default:\n tag = AdapterJS.WebRTCPlugin.TAGS.NONE;\n }\n\n var frag = document.createDocumentFragment();\n var temp = document.createElement('div');\n var classHTML = '';\n if (element.className) {\n classHTML = 'class=\"' + element.className + '\" ';\n } else if (element.attributes && element.attributes['class']) {\n classHTML = 'class=\"' + element.attributes['class'].value + '\" ';\n }\n\n temp.innerHTML = '' +\n ' ' +\n ' ' +\n ' ' +\n ' ' +\n ' ' +\n '';\n while (temp.firstChild) {\n frag.appendChild(temp.firstChild);\n }\n\n var height = '';\n var width = '';\n if (element.clientWidth || element.clientHeight) {\n width = element.clientWidth;\n height = element.clientHeight;\n }\n else if (element.width || element.height) {\n width = element.width;\n height = element.height;\n }\n\n element.parentNode.insertBefore(frag, element);\n frag = document.getElementById(elementId);\n frag.width = width;\n frag.height = height;\n element.parentNode.removeChild(element);\n } else { // already an tag, just change the stream id\n var children = element.children;\n for (var i = 0; i !== children.length; ++i) {\n if (children[i].name === 'streamId') {\n children[i].value = streamId;\n break;\n }\n }\n element.setStreamId(streamId);\n }\n var newElement = document.getElementById(elementId);\n AdapterJS.forwardEventHandlers(newElement, element, Object.getPrototypeOf(element));\n\n return newElement;\n };\n\n reattachMediaStream = function (to, from) {\n var stream = null;\n var children = from.children;\n for (var i = 0; i !== children.length; ++i) {\n if (children[i].name === 'streamId') {\n AdapterJS.WebRTCPlugin.WaitForPluginReady();\n stream = AdapterJS.WebRTCPlugin.plugin\n .getStreamWithId(AdapterJS.WebRTCPlugin.pageId, children[i].value);\n break;\n }\n }\n if (stream !== null) {\n return attachMediaStream(to, stream);\n } else {\n console.log('Could not find the stream associated with this element');\n }\n };\n\n AdapterJS.forwardEventHandlers = function (destElem, srcElem, prototype) {\n\n properties = Object.getOwnPropertyNames( prototype );\n\n for(prop in properties) {\n propName = properties[prop];\n\n if (typeof(propName.slice) === 'function') {\n if (propName.slice(0,2) == 'on' && srcElem[propName] != null) {\n if (isIE) {\n destElem.attachEvent(propName,srcElem[propName]);\n } else {\n destElem.addEventListener(propName.slice(2), srcElem[propName], false)\n }\n } else {\n //TODO (http://jira.temasys.com.sg/browse/TWP-328) Forward non-event properties ?\n }\n }\n }\n\n var subPrototype = Object.getPrototypeOf(prototype)\n if(subPrototype != null) {\n AdapterJS.forwardEventHandlers(destElem, srcElem, subPrototype);\n }\n }\n\n RTCIceCandidate = function (candidate) {\n if (!candidate.sdpMid) {\n candidate.sdpMid = '';\n }\n\n AdapterJS.WebRTCPlugin.WaitForPluginReady();\n return AdapterJS.WebRTCPlugin.plugin.ConstructIceCandidate(\n candidate.sdpMid, candidate.sdpMLineIndex, candidate.candidate\n );\n };\n\n // inject plugin\n AdapterJS.addEvent(document, 'readystatechange', AdapterJS.WebRTCPlugin.injectPlugin);\n AdapterJS.WebRTCPlugin.injectPlugin();\n };\n\n // This function will be called if the plugin is needed (browser different\n // from Chrome or Firefox), but the plugin is not installed.\n AdapterJS.WebRTCPlugin.pluginNeededButNotInstalledCb = AdapterJS.WebRTCPlugin.pluginNeededButNotInstalledCb ||\n function() {\n AdapterJS.addEvent(document,\n 'readystatechange',\n AdapterJS.WebRTCPlugin.pluginNeededButNotInstalledCbPriv);\n AdapterJS.WebRTCPlugin.pluginNeededButNotInstalledCbPriv();\n };\n\n AdapterJS.WebRTCPlugin.pluginNeededButNotInstalledCbPriv = function () {\n if (AdapterJS.options.hidePluginInstallPrompt) {\n return;\n }\n\n var downloadLink = AdapterJS.WebRTCPlugin.pluginInfo.downloadLink;\n if(downloadLink) { // if download link\n var popupString;\n if (AdapterJS.WebRTCPlugin.pluginInfo.portalLink) { // is portal link\n popupString = 'This website requires you to install the ' +\n ' ' + AdapterJS.WebRTCPlugin.pluginInfo.companyName +\n ' WebRTC Plugin' +\n ' to work on this browser.';\n } else { // no portal link, just print a generic explanation\n popupString = AdapterJS.TEXT.PLUGIN.REQUIRE_INSTALLATION;\n }\n\n AdapterJS.renderNotificationBar(popupString, AdapterJS.TEXT.PLUGIN.BUTTON, downloadLink);\n } else { // no download link, just print a generic explanation\n AdapterJS.renderNotificationBar(AdapterJS.TEXT.PLUGIN.NOT_SUPPORTED);\n }\n };\n\n // Try to detect the plugin and act accordingly\n AdapterJS.WebRTCPlugin.isPluginInstalled(\n AdapterJS.WebRTCPlugin.pluginInfo.prefix,\n AdapterJS.WebRTCPlugin.pluginInfo.plugName,\n AdapterJS.WebRTCPlugin.defineWebRTCInterface,\n AdapterJS.WebRTCPlugin.pluginNeededButNotInstalledCb);\n}\n", + "\nvar logger = require(\"jitsi-meet-logger\").getLogger(__filename);\nfunction supportsLocalStorage() {\n try {\n return 'localStorage' in window && window.localStorage !== null;\n } catch (e) {\n logger.log(\"localstorage is not supported\");\n return false;\n }\n}\n\n\nfunction generateUniqueId() {\n function _p8() {\n return (Math.random().toString(16) + \"000000000\").substr(2, 8);\n }\n return _p8() + _p8() + _p8() + _p8();\n}\n\nfunction Settings(conferenceID) {\n this.email = '';\n this.displayName = '';\n this.userId;\n this.language = null;\n this.confSettings = null;\n this.conferenceID = conferenceID;\n if (supportsLocalStorage()) {\n if(!window.localStorage.getItem(conferenceID))\n this.confSettings = {};\n else\n this.confSettings = JSON.parse(window.localStorage.getItem(conferenceID));\n if(!this.confSettings.jitsiMeetId) {\n this.confSettings.jitsiMeetId = generateUniqueId();\n logger.log(\"generated id\",\n this.confSettings.jitsiMeetId);\n this.save();\n }\n this.userId = this.confSettings.jitsiMeetId || '';\n this.email = this.confSettings.email || '';\n this.displayName = this.confSettings.displayname || '';\n this.language = this.confSettings.language;\n } else {\n logger.log(\"local storage is not supported\");\n this.userId = generateUniqueId();\n }\n}\n\nSettings.prototype.save = function () {\n if(!supportsLocalStorage())\n window.localStorage.setItem(this.conferenceID, JSON.stringify(this.confSettings));\n}\n\nSettings.prototype.setDisplayName = function (newDisplayName) {\n this.displayName = newDisplayName;\n if(this.confSettings != null)\n this.confSettings.displayname = displayName;\n this.save();\n return this.displayName;\n},\nSettings.prototype.setEmail = function (newEmail) {\n this.email = newEmail;\n if(this.confSettings != null)\n this.confSettings.email = newEmail;\n this.save();\n return this.email;\n},\nSettings.prototype.getSettings = function () {\n return {\n email: this.email,\n displayName: this.displayName,\n uid: this.userId,\n language: this.language\n };\n},\nSettings.prototype.setLanguage = function (lang) {\n this.language = lang;\n if(this.confSettings != null)\n this.confSettings.language = lang;\n this.save();\n}\n\nmodule.exports = Settings;\n", + "/* global config */\n/**\n * Provides statistics for the local stream.\n */\n\nvar RTCBrowserType = require('../RTC/RTCBrowserType');\n\n/**\n * Size of the webaudio analyzer buffer.\n * @type {number}\n */\nvar WEBAUDIO_ANALYZER_FFT_SIZE = 2048;\n\n/**\n * Value of the webaudio analyzer smoothing time parameter.\n * @type {number}\n */\nvar WEBAUDIO_ANALYZER_SMOOTING_TIME = 0.8;\n\n/**\n * Converts time domain data array to audio level.\n * @param samples the time domain data array.\n * @returns {number} the audio level\n */\nfunction timeDomainDataToAudioLevel(samples) {\n\n var maxVolume = 0;\n\n var length = samples.length;\n\n for (var i = 0; i < length; i++) {\n if (maxVolume < samples[i])\n maxVolume = samples[i];\n }\n\n return parseFloat(((maxVolume - 127) / 128).toFixed(3));\n}\n\n/**\n * Animates audio level change\n * @param newLevel the new audio level\n * @param lastLevel the last audio level\n * @returns {Number} the audio level to be set\n */\nfunction animateLevel(newLevel, lastLevel) {\n var value = 0;\n var diff = lastLevel - newLevel;\n if(diff > 0.2) {\n value = lastLevel - 0.2;\n }\n else if(diff < -0.4) {\n value = lastLevel + 0.4;\n }\n else {\n value = newLevel;\n }\n\n return parseFloat(value.toFixed(3));\n}\n\n\n/**\n * LocalStatsCollector calculates statistics for the local stream.\n *\n * @param stream the local stream\n * @param interval stats refresh interval given in ms.\n * @param callback function that receives the audio levels.\n * @constructor\n */\nfunction LocalStatsCollector(stream, interval, callback) {\n window.AudioContext = window.AudioContext || window.webkitAudioContext;\n this.stream = stream;\n this.intervalId = null;\n this.intervalMilis = interval;\n this.audioLevel = 0;\n this.callback = callback;\n}\n\n/**\n * Starts the collecting the statistics.\n */\nLocalStatsCollector.prototype.start = function () {\n if (!window.AudioContext ||\n RTCBrowserType.isTemasysPluginUsed())\n return;\n\n var context = new AudioContext();\n var analyser = context.createAnalyser();\n analyser.smoothingTimeConstant = WEBAUDIO_ANALYZER_SMOOTING_TIME;\n analyser.fftSize = WEBAUDIO_ANALYZER_FFT_SIZE;\n\n\n var source = context.createMediaStreamSource(this.stream);\n source.connect(analyser);\n\n\n var self = this;\n\n this.intervalId = setInterval(\n function () {\n var array = new Uint8Array(analyser.frequencyBinCount);\n analyser.getByteTimeDomainData(array);\n var audioLevel = timeDomainDataToAudioLevel(array);\n if (audioLevel != self.audioLevel) {\n self.audioLevel = animateLevel(audioLevel, self.audioLevel);\n self.callback(self.audioLevel);\n }\n },\n this.intervalMilis\n );\n};\n\n/**\n * Stops collecting the statistics.\n */\nLocalStatsCollector.prototype.stop = function () {\n if (this.intervalId) {\n clearInterval(this.intervalId);\n this.intervalId = null;\n }\n};\n\nmodule.exports = LocalStatsCollector;\n", + "/* global require, ssrc2jid */\n/* jshint -W117 */\n\nvar logger = require(\"jitsi-meet-logger\").getLogger(__filename);\nvar RTCBrowserType = require(\"../RTC/RTCBrowserType\");\nvar StatisticsEvents = require(\"../../service/statistics/Events\");\n\n/* Whether we support the browser we are running into for logging statistics */\nvar browserSupported = RTCBrowserType.isChrome() ||\n RTCBrowserType.isOpera();\n\nvar keyMap = {};\nkeyMap[RTCBrowserType.RTC_BROWSER_FIREFOX] = {\n \"ssrc\": \"ssrc\",\n \"packetsReceived\": \"packetsReceived\",\n \"packetsLost\": \"packetsLost\",\n \"packetsSent\": \"packetsSent\",\n \"bytesReceived\": \"bytesReceived\",\n \"bytesSent\": \"bytesSent\"\n};\nkeyMap[RTCBrowserType.RTC_BROWSER_CHROME] = {\n \"receiveBandwidth\": \"googAvailableReceiveBandwidth\",\n \"sendBandwidth\": \"googAvailableSendBandwidth\",\n \"remoteAddress\": \"googRemoteAddress\",\n \"transportType\": \"googTransportType\",\n \"localAddress\": \"googLocalAddress\",\n \"activeConnection\": \"googActiveConnection\",\n \"ssrc\": \"ssrc\",\n \"packetsReceived\": \"packetsReceived\",\n \"packetsSent\": \"packetsSent\",\n \"packetsLost\": \"packetsLost\",\n \"bytesReceived\": \"bytesReceived\",\n \"bytesSent\": \"bytesSent\",\n \"googFrameHeightReceived\": \"googFrameHeightReceived\",\n \"googFrameWidthReceived\": \"googFrameWidthReceived\",\n \"googFrameHeightSent\": \"googFrameHeightSent\",\n \"googFrameWidthSent\": \"googFrameWidthSent\",\n \"audioInputLevel\": \"audioInputLevel\",\n \"audioOutputLevel\": \"audioOutputLevel\"\n};\nkeyMap[RTCBrowserType.RTC_BROWSER_OPERA] =\n keyMap[RTCBrowserType.RTC_BROWSER_CHROME];\n\n/**\n * Calculates packet lost percent using the number of lost packets and the\n * number of all packet.\n * @param lostPackets the number of lost packets\n * @param totalPackets the number of all packets.\n * @returns {number} packet loss percent\n */\nfunction calculatePacketLoss(lostPackets, totalPackets) {\n if(!totalPackets || totalPackets <= 0 || !lostPackets || lostPackets <= 0)\n return 0;\n return Math.round((lostPackets/totalPackets)*100);\n}\n\nfunction getStatValue(item, name) {\n var browserType = RTCBrowserType.getBrowserType();\n if (!keyMap[browserType][name])\n throw \"The property isn't supported!\";\n var key = keyMap[browserType][name];\n return (RTCBrowserType.isChrome() || RTCBrowserType.isOpera()) ?\n item.stat(key) : item[key];\n}\n\nfunction formatAudioLevel(audioLevel) {\n return Math.min(Math.max(audioLevel, 0), 1);\n}\n\n/**\n * Checks whether a certain record should be included in the logged statistics.\n */\nfunction acceptStat(reportId, reportType, statName) {\n if (reportType == \"googCandidatePair\" && statName == \"googChannelId\")\n return false;\n\n if (reportType == \"ssrc\") {\n if (statName == \"googTrackId\" ||\n statName == \"transportId\" ||\n statName == \"ssrc\")\n return false;\n }\n\n return true;\n}\n\n/**\n * Checks whether a certain record should be included in the logged statistics.\n */\nfunction acceptReport(id, type) {\n if (id.substring(0, 15) == \"googCertificate\" ||\n id.substring(0, 9) == \"googTrack\" ||\n id.substring(0, 20) == \"googLibjingleSession\")\n return false;\n\n if (type == \"googComponent\")\n return false;\n\n return true;\n}\n\n/**\n * Peer statistics data holder.\n * @constructor\n */\nfunction PeerStats()\n{\n this.ssrc2Loss = {};\n this.ssrc2AudioLevel = {};\n this.ssrc2bitrate = {};\n this.ssrc2resolution = {};\n}\n\n/**\n * Sets packets loss rate for given ssrc that blong to the peer\n * represented by this instance.\n * @param lossRate new packet loss rate value to be set.\n */\nPeerStats.prototype.setSsrcLoss = function (lossRate)\n{\n this.ssrc2Loss = lossRate;\n};\n\n/**\n * Sets resolution that belong to the ssrc\n * represented by this instance.\n * @param resolution new resolution value to be set.\n */\nPeerStats.prototype.setSsrcResolution = function (resolution)\n{\n if(resolution === null && this.ssrc2resolution[ssrc])\n {\n delete this.ssrc2resolution[ssrc];\n }\n else if(resolution !== null)\n this.ssrc2resolution[ssrc] = resolution;\n};\n\n/**\n * Sets the bit rate for given ssrc that blong to the peer\n * represented by this instance.\n * @param ssrc audio or video RTP stream SSRC.\n * @param bitrate new bitrate value to be set.\n */\nPeerStats.prototype.setSsrcBitrate = function (ssrc, bitrate)\n{\n if(this.ssrc2bitrate[ssrc])\n {\n this.ssrc2bitrate[ssrc].download += bitrate.download;\n this.ssrc2bitrate[ssrc].upload += bitrate.upload;\n }\n else {\n this.ssrc2bitrate[ssrc] = bitrate;\n }\n};\n\n/**\n * Sets new audio level(input or output) for given ssrc that identifies\n * the stream which belongs to the peer represented by this instance.\n * @param ssrc RTP stream SSRC for which current audio level value will be\n * updated.\n * @param audioLevel the new audio level value to be set. Value is truncated to\n * fit the range from 0 to 1.\n */\nPeerStats.prototype.setSsrcAudioLevel = function (ssrc, audioLevel)\n{\n // Range limit 0 - 1\n this.ssrc2AudioLevel[ssrc] = formatAudioLevel(audioLevel);\n};\n\nfunction ConferenceStats() {\n\n\n /**\n * The bandwidth\n * @type {{}}\n */\n this.bandwidth = {};\n\n /**\n * The bit rate\n * @type {{}}\n */\n this.bitrate = {};\n\n /**\n * The packet loss rate\n * @type {{}}\n */\n this.packetLoss = null;\n\n\n /**\n * Array with the transport information.\n * @type {Array}\n */\n this.transport = [];\n}\n\n/**\n * StatsCollector registers for stats updates of given\n * peerconnection in given interval. On each update particular\n * stats are extracted and put in {@link PeerStats} objects. Once the processing\n * is done audioLevelsUpdateCallback is called with this\n * instance as an event source.\n *\n * @param peerconnection webRTC peer connection object.\n * @param interval stats refresh interval given in ms.\n * @param {function(StatsCollector)} audioLevelsUpdateCallback the callback\n * called on stats update.\n * @param config {object} supports the following properties - disableAudioLevels, disableStats, logStats\n * @constructor\n */\nfunction StatsCollector(peerconnection, audioLevelsInterval, statsInterval, eventEmitter, config)\n{\n this.peerconnection = peerconnection;\n this.baselineAudioLevelsReport = null;\n this.currentAudioLevelsReport = null;\n this.currentStatsReport = null;\n this.baselineStatsReport = null;\n this.audioLevelsIntervalId = null;\n this.eventEmitter = eventEmitter;\n this.config = config || {};\n this.conferenceStats = new ConferenceStats();\n\n /**\n * Gather PeerConnection stats once every this many milliseconds.\n */\n this.GATHER_INTERVAL = 15000;\n\n /**\n * Log stats via the focus once every this many milliseconds.\n */\n this.LOG_INTERVAL = 60000;\n\n /**\n * Gather stats and store them in this.statsToBeLogged.\n */\n this.gatherStatsIntervalId = null;\n\n /**\n * Send the stats already saved in this.statsToBeLogged to be logged via\n * the focus.\n */\n this.logStatsIntervalId = null;\n\n /**\n * Stores the statistics which will be send to the focus to be logged.\n */\n this.statsToBeLogged =\n {\n timestamps: [],\n stats: {}\n };\n\n // Updates stats interval\n this.audioLevelsIntervalMilis = audioLevelsInterval;\n\n this.statsIntervalId = null;\n this.statsIntervalMilis = statsInterval;\n // Map of ssrcs to PeerStats\n this.ssrc2stats = {};\n}\n\nmodule.exports = StatsCollector;\n\n/**\n * Stops stats updates.\n */\nStatsCollector.prototype.stop = function () {\n if (this.audioLevelsIntervalId) {\n clearInterval(this.audioLevelsIntervalId);\n this.audioLevelsIntervalId = null;\n }\n\n if (this.statsIntervalId)\n {\n clearInterval(this.statsIntervalId);\n this.statsIntervalId = null;\n }\n\n if(this.logStatsIntervalId)\n {\n clearInterval(this.logStatsIntervalId);\n this.logStatsIntervalId = null;\n }\n\n if(this.gatherStatsIntervalId)\n {\n clearInterval(this.gatherStatsIntervalId);\n this.gatherStatsIntervalId = null;\n }\n};\n\n/**\n * Callback passed to getStats method.\n * @param error an error that occurred on getStats call.\n */\nStatsCollector.prototype.errorCallback = function (error)\n{\n logger.error(\"Get stats error\", error);\n this.stop();\n};\n\n/**\n * Starts stats updates.\n */\nStatsCollector.prototype.start = function ()\n{\n var self = this;\n this.audioLevelsIntervalId = setInterval(\n function () {\n // Interval updates\n self.peerconnection.getStats(\n function (report) {\n var results = null;\n if (!report || !report.result ||\n typeof report.result != 'function') {\n results = report;\n }\n else {\n results = report.result();\n }\n //logger.error(\"Got interval report\", results);\n self.currentAudioLevelsReport = results;\n self.processAudioLevelReport();\n self.baselineAudioLevelsReport =\n self.currentAudioLevelsReport;\n },\n self.errorCallback\n );\n },\n self.audioLevelsIntervalMilis\n );\n\n// if (!this.config.disableStats && browserSupported) {\n// this.statsIntervalId = setInterval(\n// function () {\n// // Interval updates\n// self.peerconnection.getStats(\n// function (report) {\n// var results = null;\n// if (!report || !report.result ||\n// typeof report.result != 'function') {\n// //firefox\n// results = report;\n// }\n// else {\n// //chrome\n// results = report.result();\n// }\n// //logger.error(\"Got interval report\", results);\n// self.currentStatsReport = results;\n// try {\n// self.processStatsReport();\n// }\n// catch (e) {\n// logger.error(\"Unsupported key:\" + e, e);\n// }\n//\n// self.baselineStatsReport = self.currentStatsReport;\n// },\n// self.errorCallback\n// );\n// },\n// self.statsIntervalMilis\n// );\n// }\n//\n// if (this.config.logStats && browserSupported) {\n// this.gatherStatsIntervalId = setInterval(\n// function () {\n// self.peerconnection.getStats(\n// function (report) {\n// self.addStatsToBeLogged(report.result());\n// },\n// function () {\n// }\n// );\n// },\n// this.GATHER_INTERVAL\n// );\n//\n// this.logStatsIntervalId = setInterval(\n// function() { self.logStats(); },\n// this.LOG_INTERVAL);\n// }\n};\n\n/**\n * Converts the stats to the format used for logging, and saves the data in\n * this.statsToBeLogged.\n * @param reports Reports as given by webkitRTCPerConnection.getStats.\n */\nStatsCollector.prototype.addStatsToBeLogged = function (reports) {\n var self = this;\n var num_records = this.statsToBeLogged.timestamps.length;\n this.statsToBeLogged.timestamps.push(new Date().getTime());\n reports.map(function (report) {\n if (!acceptReport(report.id, report.type))\n return;\n var stat = self.statsToBeLogged.stats[report.id];\n if (!stat) {\n stat = self.statsToBeLogged.stats[report.id] = {};\n }\n stat.type = report.type;\n report.names().map(function (name) {\n if (!acceptStat(report.id, report.type, name))\n return;\n var values = stat[name];\n if (!values) {\n values = stat[name] = [];\n }\n while (values.length < num_records) {\n values.push(null);\n }\n values.push(report.stat(name));\n });\n });\n};\n\n\n//FIXME:\n//StatsCollector.prototype.logStats = function () {\n//\n// if(!APP.xmpp.sendLogs(this.statsToBeLogged))\n// return;\n// // Reset the stats\n// this.statsToBeLogged.stats = {};\n// this.statsToBeLogged.timestamps = [];\n//};\n\n\n/**\n * Stats processing logic.\n */\nStatsCollector.prototype.processStatsReport = function () {\n if (!this.baselineStatsReport) {\n return;\n }\n\n for (var idx in this.currentStatsReport) {\n var now = this.currentStatsReport[idx];\n try {\n if (getStatValue(now, 'receiveBandwidth') ||\n getStatValue(now, 'sendBandwidth')) {\n this.conferenceStats.bandwidth = {\n \"download\": Math.round(\n (getStatValue(now, 'receiveBandwidth')) / 1000),\n \"upload\": Math.round(\n (getStatValue(now, 'sendBandwidth')) / 1000)\n };\n }\n }\n catch(e){/*not supported*/}\n\n if(now.type == 'googCandidatePair')\n {\n var ip, type, localIP, active;\n try {\n ip = getStatValue(now, 'remoteAddress');\n type = getStatValue(now, \"transportType\");\n localIP = getStatValue(now, \"localAddress\");\n active = getStatValue(now, \"activeConnection\");\n }\n catch(e){/*not supported*/}\n if(!ip || !type || !localIP || active != \"true\")\n continue;\n var addressSaved = false;\n for(var i = 0; i < this.conferenceStats.transport.length; i++)\n {\n if(this.conferenceStats.transport[i].ip == ip &&\n this.conferenceStats.transport[i].type == type &&\n this.conferenceStats.transport[i].localip == localIP)\n {\n addressSaved = true;\n }\n }\n if(addressSaved)\n continue;\n this.conferenceStats.transport.push({localip: localIP, ip: ip, type: type});\n continue;\n }\n\n if(now.type == \"candidatepair\")\n {\n if(now.state == \"succeeded\")\n continue;\n\n var local = this.currentStatsReport[now.localCandidateId];\n var remote = this.currentStatsReport[now.remoteCandidateId];\n this.conferenceStats.transport.push({localip: local.ipAddress + \":\" + local.portNumber,\n ip: remote.ipAddress + \":\" + remote.portNumber, type: local.transport});\n\n }\n\n if (now.type != 'ssrc' && now.type != \"outboundrtp\" &&\n now.type != \"inboundrtp\") {\n continue;\n }\n\n var before = this.baselineStatsReport[idx];\n if (!before) {\n logger.warn(getStatValue(now, 'ssrc') + ' not enough data');\n continue;\n }\n\n var ssrc = getStatValue(now, 'ssrc');\n if(!ssrc)\n continue;\n\n var ssrcStats = this.ssrc2stats[ssrc];\n if (!ssrcStats) {\n ssrcStats = new PeerStats();\n this.ssrc2stats[ssrc] = ssrcStats;\n }\n\n\n var isDownloadStream = true;\n var key = 'packetsReceived';\n var packetsNow = getStatValue(now, key);\n if (typeof packetsNow === 'undefined' || packetsNow === null) {\n isDownloadStream = false;\n key = 'packetsSent';\n packetsNow = getStatValue(now, key);\n if (typeof packetsNow === 'undefined' || packetsNow === null) {\n console.warn(\"No packetsReceived nor packetsSent stat found\");\n continue;\n }\n }\n if (!packetsNow || packetsNow < 0)\n packetsNow = 0;\n\n var packetsBefore = getStatValue(before, key);\n if (!packetsBefore || packetsBefore < 0)\n packetsBefore = 0;\n var packetRate = packetsNow - packetsBefore;\n if (!packetRate || packetRate < 0)\n packetRate = 0;\n var currentLoss = getStatValue(now, 'packetsLost');\n if (!currentLoss || currentLoss < 0)\n currentLoss = 0;\n var previousLoss = getStatValue(before, 'packetsLost');\n if (!previousLoss || previousLoss < 0)\n previousLoss = 0;\n var lossRate = currentLoss - previousLoss;\n if (!lossRate || lossRate < 0)\n lossRate = 0;\n var packetsTotal = (packetRate + lossRate);\n\n ssrcStats.setSsrcLoss(ssrc,\n {\"packetsTotal\": packetsTotal,\n \"packetsLost\": lossRate,\n \"isDownloadStream\": isDownloadStream});\n\n\n var bytesReceived = 0, bytesSent = 0;\n if(getStatValue(now, \"bytesReceived\")) {\n bytesReceived = getStatValue(now, \"bytesReceived\") -\n getStatValue(before, \"bytesReceived\");\n }\n\n if (getStatValue(now, \"bytesSent\")) {\n bytesSent = getStatValue(now, \"bytesSent\") -\n getStatValue(before, \"bytesSent\");\n }\n\n var time = Math.round((now.timestamp - before.timestamp) / 1000);\n if (bytesReceived <= 0 || time <= 0) {\n bytesReceived = 0;\n } else {\n bytesReceived = Math.round(((bytesReceived * 8) / time) / 1000);\n }\n\n if (bytesSent <= 0 || time <= 0) {\n bytesSent = 0;\n } else {\n bytesSent = Math.round(((bytesSent * 8) / time) / 1000);\n }\n\n ssrcStats.setSsrcBitrate(ssrc, {\n \"download\": bytesReceived,\n \"upload\": bytesSent});\n\n var resolution = {height: null, width: null};\n try {\n if (getStatValue(now, \"googFrameHeightReceived\") &&\n getStatValue(now, \"googFrameWidthReceived\")) {\n resolution.height =\n getStatValue(now, \"googFrameHeightReceived\");\n resolution.width = getStatValue(now, \"googFrameWidthReceived\");\n }\n else if (getStatValue(now, \"googFrameHeightSent\") &&\n getStatValue(now, \"googFrameWidthSent\")) {\n resolution.height = getStatValue(now, \"googFrameHeightSent\");\n resolution.width = getStatValue(now, \"googFrameWidthSent\");\n }\n }\n catch(e){/*not supported*/}\n\n if (resolution.height && resolution.width) {\n ssrcStats.setSsrcResolution(ssrc, resolution);\n } else {\n ssrcStats.setSsrcResolution(ssrc, null);\n }\n }\n\n var self = this;\n // Jid stats\n var totalPackets = {download: 0, upload: 0};\n var lostPackets = {download: 0, upload: 0};\n var bitrateDownload = 0;\n var bitrateUpload = 0;\n var resolutions = {};\n Object.keys(this.ssrc2stats).forEach(\n function (jid) {\n Object.keys(self.ssrc2stats[jid].ssrc2Loss).forEach(\n function (ssrc) {\n var type = \"upload\";\n if(self.ssrc2stats[jid].ssrc2Loss[ssrc].isDownloadStream)\n type = \"download\";\n totalPackets[type] +=\n self.ssrc2stats[jid].ssrc2Loss[ssrc].packetsTotal;\n lostPackets[type] +=\n self.ssrc2stats[jid].ssrc2Loss[ssrc].packetsLost;\n }\n );\n Object.keys(self.ssrc2stats[jid].ssrc2bitrate).forEach(\n function (ssrc) {\n bitrateDownload +=\n self.ssrc2stats[jid].ssrc2bitrate[ssrc].download;\n bitrateUpload +=\n self.ssrc2stats[jid].ssrc2bitrate[ssrc].upload;\n\n delete self.ssrc2stats[jid].ssrc2bitrate[ssrc];\n }\n );\n resolutions[jid] = self.ssrc2stats[jid].ssrc2resolution;\n }\n );\n\n this.conferenceStats.bitrate = {\"upload\": bitrateUpload, \"download\": bitrateDownload};\n\n this.conferenceStats.packetLoss = {\n total:\n calculatePacketLoss(lostPackets.download + lostPackets.upload,\n totalPackets.download + totalPackets.upload),\n download:\n calculatePacketLoss(lostPackets.download, totalPackets.download),\n upload:\n calculatePacketLoss(lostPackets.upload, totalPackets.upload)\n };\n this.eventEmitter.emit(StatisticsEvents.CONNECTION_STATS,\n {\n \"bitrate\": this.conferenceStats.bitrate,\n \"packetLoss\": this.conferenceStats.packetLoss,\n \"bandwidth\": this.conferenceStats.bandwidth,\n \"resolution\": resolutions,\n \"transport\": this.conferenceStats.transport\n });\n this.conferenceStats.transport = [];\n\n};\n\n/**\n * Stats processing logic.\n */\nStatsCollector.prototype.processAudioLevelReport = function () {\n if (!this.baselineAudioLevelsReport) {\n return;\n }\n\n for (var idx in this.currentAudioLevelsReport) {\n var now = this.currentAudioLevelsReport[idx];\n\n //if we don't have \"packetsReceived\" this is local stream\n if (now.type != 'ssrc' || !getStatValue(now, 'packetsReceived')) {\n continue;\n }\n\n var before = this.baselineAudioLevelsReport[idx];\n if (!before) {\n logger.warn(getStatValue(now, 'ssrc') + ' not enough data');\n continue;\n }\n\n var ssrc = getStatValue(now, 'ssrc');\n if (!ssrc) {\n if((Date.now() - now.timestamp) < 3000)\n logger.warn(\"No ssrc: \");\n continue;\n }\n\n var ssrcStats = this.ssrc2stats[ssrc];\n if (!ssrcStats) {\n ssrcStats = new PeerStats();\n this.ssrc2stats[ssrc] = ssrcStats;\n }\n\n // Audio level\n var audioLevel = null;\n\n try {\n audioLevel = getStatValue(now, 'audioInputLevel');\n if (!audioLevel)\n audioLevel = getStatValue(now, 'audioOutputLevel');\n }\n catch(e) {/*not supported*/\n logger.warn(\"Audio Levels are not available in the statistics.\");\n clearInterval(this.audioLevelsIntervalId);\n return;\n }\n\n if (audioLevel) {\n // TODO: can't find specs about what this value really is,\n // but it seems to vary between 0 and around 32k.\n audioLevel = audioLevel / 32767;\n ssrcStats.setSsrcAudioLevel(ssrc, audioLevel);\n this.eventEmitter.emit(\n StatisticsEvents.AUDIO_LEVEL, ssrc, audioLevel);\n }\n }\n};\n", + "/* global require, APP */\nvar LocalStats = require(\"./LocalStatsCollector.js\");\nvar RTPStats = require(\"./RTPStatsCollector.js\");\nvar EventEmitter = require(\"events\");\nvar StatisticsEvents = require(\"../../service/statistics/Events\");\n//var StreamEventTypes = require(\"../../service/RTC/StreamEventTypes.js\");\n//var XMPPEvents = require(\"../../service/xmpp/XMPPEvents\");\n//var CallStats = require(\"./CallStats\");\n//var RTCEvents = require(\"../../service/RTC/RTCEvents\");\n\n//\n//function onDisposeConference(onUnload) {\n// CallStats.sendTerminateEvent();\n// stopRemote();\n// if(onUnload) {\n// stopLocal();\n// eventEmitter.removeAllListeners();\n// }\n//}\n\nvar eventEmitter = new EventEmitter();\n\nfunction Statistics() {\n this.rtpStats = null;\n this.eventEmitter = new EventEmitter();\n}\n\nStatistics.prototype.startRemoteStats = function (peerconnection) {\n if (this.rtpStats) {\n this.rtpStats.stop();\n }\n\n this.rtpStats = new RTPStats(peerconnection, 200, 2000, this.eventEmitter);\n this.rtpStats.start();\n}\n\nStatistics.localStats = [];\n\nStatistics.startLocalStats = function (stream, callback) {\n var localStats = new LocalStats(stream, 200, callback);\n this.localStats.push(localStats);\n localStats.start();\n}\n\nStatistics.prototype.addAudioLevelListener = function(listener)\n{\n this.eventEmitter.on(StatisticsEvents.AUDIO_LEVEL, listener);\n}\n\nStatistics.prototype.removeAudioLevelListener = function(listener)\n{\n this.eventEmitter.removeListener(StatisticsEvents.AUDIO_LEVEL, listener);\n}\n\nStatistics.prototype.dispose = function () {\n Statistics.stopAllLocalStats();\n this.stopRemote();\n if(this.eventEmitter)\n this.eventEmitter.removeAllListeners();\n\n if(eventEmitter)\n eventEmitter.removeAllListeners();\n}\n\n\nStatistics.stopAllLocalStats = function () {\n for(var i = 0; i < this.localStats.length; i++)\n this.localStats[i].stop();\n this.localStats = [];\n}\n\nStatistics.stopLocalStats = function (stream) {\n for(var i = 0; i < Statistics.localStats.length; i++)\n if(Statistics.localStats[i].stream === stream){\n var localStats = Statistics.localStats.splice(i, 1);\n localStats.stop();\n break;\n }\n}\n\nStatistics.prototype.stopRemote = function () {\n if (this.rtpStats) {\n this.rtpStats.stop();\n this.eventEmitter.emit(StatisticsEvents.STOP);\n this.rtpStats = null;\n }\n};\n\n/**\n * Obtains audio level reported in the stats for specified peer.\n * @param peerJid full MUC jid of the user for whom we want to obtain last\n * audio level.\n * @param ssrc the SSRC of audio stream for which we want to obtain audio\n * level.\n * @returns {*} a float form 0 to 1 that represents current audio level or\n * null if for any reason the value is not available\n * at this time.\n */\nStatistics.prototype.getPeerSSRCAudioLevel = function (peerJid, ssrc) {\n\n var peerStats = this.rtpStats.jid2stats[peerJid];\n\n return peerStats ? peerStats.ssrc2AudioLevel[ssrc] : null;\n};\n\nStatistics.LOCAL_JID = require(\"../../service/statistics/constants\").LOCAL_JID;\n\n//\n//var statistics = {\n// /**\n// * Indicates that this audio level is for local jid.\n// * @type {string}\n// */\n// LOCAL_JID: 'local',\n//\n// addConnectionStatsListener: function(listener)\n// {\n// eventEmitter.on(\"statistics.connectionstats\", listener);\n// },\n//\n// removeConnectionStatsListener: function(listener)\n// {\n// eventEmitter.removeListener(\"statistics.connectionstats\", listener);\n// },\n//\n//\n// addRemoteStatsStopListener: function(listener)\n// {\n// eventEmitter.on(\"statistics.stop\", listener);\n// },\n//\n// removeRemoteStatsStopListener: function(listener)\n// {\n// eventEmitter.removeListener(\"statistics.stop\", listener);\n// },\n//\n//\n// stopRemoteStatistics: function()\n// {\n// stopRemote();\n// },\n//\n//// Already implemented with the constructor\n// start: function () {\n// APP.RTC.addStreamListener(onStreamCreated,\n// StreamEventTypes.EVENT_TYPE_LOCAL_CREATED);\n// APP.xmpp.addListener(XMPPEvents.DISPOSE_CONFERENCE, onDisposeConference);\n// //FIXME: we may want to change CALL INCOMING event to onnegotiationneeded\n// APP.xmpp.addListener(XMPPEvents.CALL_INCOMING, function (event) {\n// startRemoteStats(event.peerconnection);\n//// CallStats.init(event);\n// });\n//// APP.xmpp.addListener(XMPPEvents.PEERCONNECTION_READY, function (session) {\n//// CallStats.init(session);\n//// });\n// //FIXME: that event is changed to TRACK_MUTE_CHANGED\n//// APP.RTC.addListener(RTCEvents.AUDIO_MUTE, function (mute) {\n//// CallStats.sendMuteEvent(mute, \"audio\");\n//// });\n//// APP.xmpp.addListener(XMPPEvents.CONFERENCE_SETUP_FAILED, function () {\n//// CallStats.sendSetupFailedEvent();\n//// });\n// //FIXME: that event is changed to TRACK_MUTE_CHANGED\n//// APP.RTC.addListener(RTCEvents.VIDEO_MUTE, function (mute) {\n//// CallStats.sendMuteEvent(mute, \"video\");\n//// });\n// }\n//};\n\n\n\n\nmodule.exports = Statistics;\n", + "/**\n/**\n * @const\n */\nvar ALPHANUM = '0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ';\n\n/**\n * Hexadecimal digits.\n * @const\n */\nvar HEX_DIGITS = '0123456789abcdef';\n\n/**\n * Generates random int within the range [min, max]\n * @param min the minimum value for the generated number\n * @param max the maximum value for the generated number\n * @returns random int number\n */\nfunction randomInt(min, max) {\n return Math.floor(Math.random() * (max - min + 1)) + min;\n}\n\n/**\n * Get random element from array or string.\n * @param {Array|string} arr source\n * @returns array element or string character\n */\nfunction randomElement(arr) {\n return arr[randomInt(0, arr.length - 1)];\n}\n\n/**\n * Generate random alphanumeric string.\n * @param {number} length expected string length\n * @returns {string} random string of specified length\n */\nfunction randomAlphanumStr(length) {\n var result = '';\n\n for (var i = 0; i < length; i += 1) {\n result += randomElement(ALPHANUM);\n }\n\n return result;\n}\n\n/**\n * Exported interface.\n */\nvar RandomUtil = {\n /**\n * Returns a random hex digit.\n * @returns {*}\n */\n randomHexDigit: function() {\n return randomElement(HEX_DIGITS);\n },\n /**\n * Returns a random string of hex digits with length 'len'.\n * @param len the length.\n */\n randomHexString: function (len) {\n var ret = '';\n while (len--) {\n ret += this.randomHexDigit();\n }\n return ret;\n },\n randomElement: randomElement,\n randomAlphanumStr: randomAlphanumStr\n};\n\nmodule.exports = RandomUtil;\n", + "/* global Strophe, $, $pres, $iq, $msg */\n/* jshint -W101,-W069 */\nvar logger = require(\"jitsi-meet-logger\").getLogger(__filename);\nvar XMPPEvents = require(\"../../service/xmpp/XMPPEvents\");\nvar Moderator = require(\"./moderator\");\nvar EventEmitter = require(\"events\");\nvar Recorder = require(\"./recording\");\nvar JIBRI_XMLNS = 'http://jitsi.org/protocol/jibri';\n\nvar parser = {\n packet2JSON: function (packet, nodes) {\n var self = this;\n $(packet).children().each(function (index) {\n var tagName = $(this).prop(\"tagName\");\n var node = {\n tagName: tagName\n };\n node.attributes = {};\n $($(this)[0].attributes).each(function( index, attr ) {\n node.attributes[ attr.name ] = attr.value;\n });\n var text = Strophe.getText($(this)[0]);\n if (text) {\n node.value = text;\n }\n node.children = [];\n nodes.push(node);\n self.packet2JSON($(this), node.children);\n });\n },\n JSON2packet: function (nodes, packet) {\n for(var i = 0; i < nodes.length; i++) {\n var node = nodes[i];\n if(!node || node === null){\n continue;\n }\n packet.c(node.tagName, node.attributes);\n if(node.value)\n packet.t(node.value);\n if(node.children)\n this.JSON2packet(node.children, packet);\n packet.up();\n }\n // packet.up();\n }\n};\n\n/**\n * Returns array of JS objects from the presence JSON associated with the passed nodeName\n * @param pres the presence JSON\n * @param nodeName the name of the node (videomuted, audiomuted, etc)\n */\nfunction filterNodeFromPresenceJSON(pres, nodeName){\n var res = [];\n for(var i = 0; i < pres.length; i++)\n if(pres[i].tagName === nodeName)\n res.push(pres[i]);\n\n return res;\n}\n\nfunction ChatRoom(connection, jid, password, XMPP, options) {\n this.eventEmitter = new EventEmitter();\n this.xmpp = XMPP;\n this.connection = connection;\n this.roomjid = Strophe.getBareJidFromJid(jid);\n this.myroomjid = jid;\n this.password = password;\n logger.info(\"Joined MUC as \" + this.myroomjid);\n this.members = {};\n this.presMap = {};\n this.presHandlers = {};\n this.joined = false;\n this.role = 'none';\n this.focusMucJid = null;\n this.bridgeIsDown = false;\n this.options = options || {};\n this.moderator = new Moderator(this.roomjid, this.xmpp, this.eventEmitter);\n this.initPresenceMap();\n this.session = null;\n var self = this;\n this.lastPresences = {};\n this.phoneNumber = null;\n this.phonePin = null;\n}\n\nChatRoom.prototype.initPresenceMap = function () {\n this.presMap['to'] = this.myroomjid;\n this.presMap['xns'] = 'http://jabber.org/protocol/muc';\n this.presMap[\"nodes\"] = [];\n this.presMap[\"nodes\"].push( {\n \"tagName\": \"user-agent\",\n \"value\": navigator.userAgent,\n \"attributes\": {xmlns: 'http://jitsi.org/jitmeet/user-agent'}\n });\n\n};\n\nChatRoom.prototype.updateDeviceAvailability = function (devices) {\n this.presMap[\"nodes\"].push( {\n \"tagName\": \"devices\",\n \"children\": [\n {\n \"tagName\": \"audio\",\n \"value\": devices.audio,\n },\n {\n \"tagName\": \"video\",\n \"value\": devices.video,\n }\n ]\n });\n};\n\nChatRoom.prototype.join = function (password) {\n if(password)\n this.password = password;\n var self = this;\n this.moderator.allocateConferenceFocus(function()\n {\n self.sendPresence();\n }.bind(this));\n};\n\nChatRoom.prototype.sendPresence = function () {\n if (!this.presMap['to']) {\n // Too early to send presence - not initialized\n return;\n }\n var pres = $pres({to: this.presMap['to'] });\n pres.c('x', {xmlns: this.presMap['xns']});\n\n if (this.password) {\n pres.c('password').t(this.password).up();\n }\n\n pres.up();\n\n // Send XEP-0115 'c' stanza that contains our capabilities info\n if (this.connection.caps) {\n this.connection.caps.node = this.xmpp.options.clientNode;\n pres.c('c', this.connection.caps.generateCapsAttrs()).up();\n }\n\n parser.JSON2packet(this.presMap.nodes, pres);\n this.connection.send(pres);\n};\n\n\nChatRoom.prototype.doLeave = function () {\n logger.log(\"do leave\", this.myroomjid);\n var pres = $pres({to: this.myroomjid, type: 'unavailable' });\n this.presMap.length = 0;\n this.connection.send(pres);\n};\n\n\nChatRoom.prototype.createNonAnonymousRoom = function () {\n // http://xmpp.org/extensions/xep-0045.html#createroom-reserved\n\n var getForm = $iq({type: 'get', to: this.roomjid})\n .c('query', {xmlns: 'http://jabber.org/protocol/muc#owner'})\n .c('x', {xmlns: 'jabber:x:data', type: 'submit'});\n\n var self = this;\n\n this.connection.sendIQ(getForm, function (form) {\n\n if (!$(form).find(\n '>query>x[xmlns=\"jabber:x:data\"]' +\n '>field[var=\"muc#roomconfig_whois\"]').length) {\n\n logger.error('non-anonymous rooms not supported');\n return;\n }\n\n var formSubmit = $iq({to: this.roomjid, type: 'set'})\n .c('query', {xmlns: 'http://jabber.org/protocol/muc#owner'});\n\n formSubmit.c('x', {xmlns: 'jabber:x:data', type: 'submit'});\n\n formSubmit.c('field', {'var': 'FORM_TYPE'})\n .c('value')\n .t('http://jabber.org/protocol/muc#roomconfig').up().up();\n\n formSubmit.c('field', {'var': 'muc#roomconfig_whois'})\n .c('value').t('anyone').up().up();\n\n self.connection.sendIQ(formSubmit);\n\n }, function (error) {\n logger.error(\"Error getting room configuration form\");\n });\n};\n\nChatRoom.prototype.onPresence = function (pres) {\n console.log(pres);\n var from = pres.getAttribute('from');\n // Parse roles.\n var member = {};\n member.show = $(pres).find('>show').text();\n member.status = $(pres).find('>status').text();\n var tmp = $(pres).find('>x[xmlns=\"http://jabber.org/protocol/muc#user\"]>item');\n member.affiliation = tmp.attr('affiliation');\n member.role = tmp.attr('role');\n\n // Focus recognition\n member.jid = tmp.attr('jid');\n member.isFocus = false;\n if (member.jid\n && member.jid.indexOf(this.moderator.getFocusUserJid() + \"/\") === 0) {\n member.isFocus = true;\n }\n\n $(pres).find(\">x\").remove();\n var nodes = [];\n parser.packet2JSON(pres, nodes);\n this.lastPresences[from] = nodes;\n var jibri = null;\n for(var i = 0; i < nodes.length; i++)\n {\n var node = nodes[i];\n switch(node.tagName)\n {\n case \"nick\":\n member.nick = node.value;\n if(!member.isFocus) {\n var displayName = !this.xmpp.options.displayJids\n ? member.nick : Strophe.getResourceFromJid(from);\n\n if (displayName && displayName.length > 0) {\n this.eventEmitter.emit(XMPPEvents.DISPLAY_NAME_CHANGED, from, displayName);\n }\n logger.info(\"Display name: \" + displayName, pres);\n }\n break;\n case \"userId\":\n member.id = node.value;\n break;\n case \"email\":\n member.email = node.value;\n break;\n case \"bridgeIsDown\":\n if(!this.bridgeIsDown) {\n this.bridgeIsDown = true;\n this.eventEmitter.emit(XMPPEvents.BRIDGE_DOWN);\n }\n break;\n case \"jibri-recording-status\":\n var jibri = node;\n break;\n case \"call-control\":\n console.log(pres);\n var att = node.attributes;\n if(!att)\n break;\n this.phoneNumber = att.phone || null;\n this.phonePin = att.pin || null;\n this.eventEmitter.emit(XMPPEvents.PHONE_NUMBER_CHANGED);\n break;\n default :\n this.processNode(node, from);\n }\n\n }\n\n if (from == this.myroomjid) {\n if (member.affiliation == 'owner')\n\n if (this.role !== member.role) {\n this.role = member.role;\n\n this.eventEmitter.emit(XMPPEvents.LOCAL_ROLE_CHANGED, this.role);\n }\n if (!this.joined) {\n this.joined = true;\n console.log(\"(TIME) MUC joined:\\t\", window.performance.now());\n this.eventEmitter.emit(XMPPEvents.MUC_JOINED, from, member);\n }\n } else if (this.members[from] === undefined) {\n // new participant\n this.members[from] = member;\n logger.log('entered', from, member);\n if (member.isFocus) {\n this.focusMucJid = from;\n if(!this.recording) {\n this.recording = new Recorder(this.eventEmitter, this.connection,\n this.focusMucJid);\n if(this.lastJibri)\n this.recording.handleJibriPresence(this.lastJibri);\n }\n logger.info(\"Ignore focus: \" + from + \", real JID: \" + member.jid);\n }\n else {\n this.eventEmitter.emit(XMPPEvents.MUC_MEMBER_JOINED, from, member.id || member.email, member.nick);\n }\n } else {\n // Presence update for existing participant\n // Watch role change:\n if (this.members[from].role != member.role) {\n this.members[from].role = member.role;\n this.eventEmitter.emit(XMPPEvents.MUC_ROLE_CHANGED, from, member.role);\n }\n\n // store the new display name\n if(member.displayName)\n this.members[from].displayName = member.displayName;\n }\n\n\n\n if(!member.isFocus)\n this.eventEmitter.emit(XMPPEvents.USER_ID_CHANGED, from, member.id || member.email);\n\n // Trigger status message update\n if (member.status) {\n this.eventEmitter.emit(XMPPEvents.PRESENCE_STATUS, from, member);\n }\n\n if(jibri)\n {\n this.lastJibri = jibri;\n if(this.recording)\n this.recording.handleJibriPresence(jibri);\n }\n\n};\n\nChatRoom.prototype.processNode = function (node, from) {\n if(this.presHandlers[node.tagName])\n this.presHandlers[node.tagName](node, Strophe.getResourceFromJid(from));\n};\n\nChatRoom.prototype.sendMessage = function (body, nickname) {\n var msg = $msg({to: this.roomjid, type: 'groupchat'});\n msg.c('body', body).up();\n if (nickname) {\n msg.c('nick', {xmlns: 'http://jabber.org/protocol/nick'}).t(nickname).up().up();\n }\n this.connection.send(msg);\n this.eventEmitter.emit(XMPPEvents.SENDING_CHAT_MESSAGE, body);\n};\n\nChatRoom.prototype.setSubject = function (subject) {\n var msg = $msg({to: this.roomjid, type: 'groupchat'});\n msg.c('subject', subject);\n this.connection.send(msg);\n logger.log(\"topic changed to \" + subject);\n};\n\n\nChatRoom.prototype.onParticipantLeft = function (jid) {\n\n delete this.lastPresences[jid];\n this.eventEmitter.emit(XMPPEvents.MUC_MEMBER_LEFT, jid);\n\n this.moderator.onMucMemberLeft(jid);\n};\n\nChatRoom.prototype.onPresenceUnavailable = function (pres, from) {\n // room destroyed ?\n if ($(pres).find('>x[xmlns=\"http://jabber.org/protocol/muc#user\"]' +\n '>destroy').length) {\n var reason;\n var reasonSelect = $(pres).find(\n '>x[xmlns=\"http://jabber.org/protocol/muc#user\"]' +\n '>destroy>reason');\n if (reasonSelect.length) {\n reason = reasonSelect.text();\n }\n\n this.xmpp.leaveRoom(this.roomjid);\n\n this.eventEmitter.emit(XMPPEvents.MUC_DESTROYED, reason);\n delete this.connection.emuc.rooms[Strophe.getBareJidFromJid(from)];\n return true;\n }\n\n // Status code 110 indicates that this notification is \"self-presence\".\n if (!$(pres).find('>x[xmlns=\"http://jabber.org/protocol/muc#user\"]>status[code=\"110\"]').length) {\n delete this.members[from];\n this.onParticipantLeft(from);\n }\n // If the status code is 110 this means we're leaving and we would like\n // to remove everyone else from our view, so we trigger the event.\n else if (Object.keys(this.members).length > 1) {\n for (var i in this.members) {\n var member = this.members[i];\n delete this.members[i];\n this.onParticipantLeft(member);\n }\n }\n if ($(pres).find('>x[xmlns=\"http://jabber.org/protocol/muc#user\"]>status[code=\"307\"]').length) {\n if (this.myroomjid === from) {\n this.xmpp.leaveRoom(this.roomjid);\n this.eventEmitter.emit(XMPPEvents.KICKED);\n }\n }\n};\n\nChatRoom.prototype.onMessage = function (msg, from) {\n var nick =\n $(msg).find('>nick[xmlns=\"http://jabber.org/protocol/nick\"]')\n .text() ||\n Strophe.getResourceFromJid(from);\n\n var txt = $(msg).find('>body').text();\n var type = msg.getAttribute(\"type\");\n if (type == \"error\") {\n this.eventEmitter.emit(XMPPEvents.CHAT_ERROR_RECEIVED,\n $(msg).find('>text').text(), txt);\n return true;\n }\n\n var subject = $(msg).find('>subject');\n if (subject.length) {\n var subjectText = subject.text();\n if (subjectText || subjectText === \"\") {\n this.eventEmitter.emit(XMPPEvents.SUBJECT_CHANGED, subjectText);\n logger.log(\"Subject is changed to \" + subjectText);\n }\n }\n\n // xep-0203 delay\n var stamp = $(msg).find('>delay').attr('stamp');\n\n if (!stamp) {\n // or xep-0091 delay, UTC timestamp\n stamp = $(msg).find('>[xmlns=\"jabber:x:delay\"]').attr('stamp');\n\n if (stamp) {\n // the format is CCYYMMDDThh:mm:ss\n var dateParts = stamp.match(/(\\d{4})(\\d{2})(\\d{2}T\\d{2}:\\d{2}:\\d{2})/);\n stamp = dateParts[1] + \"-\" + dateParts[2] + \"-\" + dateParts[3] + \"Z\";\n }\n }\n\n if (txt) {\n logger.log('chat', nick, txt);\n this.eventEmitter.emit(XMPPEvents.MESSAGE_RECEIVED,\n from, nick, txt, this.myroomjid, stamp);\n }\n};\n\nChatRoom.prototype.onPresenceError = function (pres, from) {\n if ($(pres).find('>error[type=\"auth\"]>not-authorized[xmlns=\"urn:ietf:params:xml:ns:xmpp-stanzas\"]').length) {\n logger.log('on password required', from);\n this.eventEmitter.emit(XMPPEvents.PASSWORD_REQUIRED);\n } else if ($(pres).find(\n '>error[type=\"cancel\"]>not-allowed[xmlns=\"urn:ietf:params:xml:ns:xmpp-stanzas\"]').length) {\n var toDomain = Strophe.getDomainFromJid(pres.getAttribute('to'));\n if (toDomain === this.xmpp.options.hosts.anonymousdomain) {\n // enter the room by replying with 'not-authorized'. This would\n // result in reconnection from authorized domain.\n // We're either missing Jicofo/Prosody config for anonymous\n // domains or something is wrong.\n this.eventEmitter.emit(XMPPEvents.ROOM_JOIN_ERROR, pres);\n\n } else {\n logger.warn('onPresError ', pres);\n this.eventEmitter.emit(XMPPEvents.ROOM_CONNECT_ERROR, pres);\n }\n } else {\n logger.warn('onPresError ', pres);\n this.eventEmitter.emit(XMPPEvents.ROOM_CONNECT_ERROR, pres);\n }\n};\n\nChatRoom.prototype.kick = function (jid) {\n var kickIQ = $iq({to: this.roomjid, type: 'set'})\n .c('query', {xmlns: 'http://jabber.org/protocol/muc#admin'})\n .c('item', {nick: Strophe.getResourceFromJid(jid), role: 'none'})\n .c('reason').t('You have been kicked.').up().up().up();\n\n this.connection.sendIQ(\n kickIQ,\n function (result) {\n logger.log('Kick participant with jid: ', jid, result);\n },\n function (error) {\n logger.log('Kick participant error: ', error);\n });\n};\n\nChatRoom.prototype.lockRoom = function (key, onSuccess, onError, onNotSupported) {\n //http://xmpp.org/extensions/xep-0045.html#roomconfig\n var ob = this;\n this.connection.sendIQ($iq({to: this.roomjid, type: 'get'}).c('query', {xmlns: 'http://jabber.org/protocol/muc#owner'}),\n function (res) {\n if ($(res).find('>query>x[xmlns=\"jabber:x:data\"]>field[var=\"muc#roomconfig_roomsecret\"]').length) {\n var formsubmit = $iq({to: ob.roomjid, type: 'set'}).c('query', {xmlns: 'http://jabber.org/protocol/muc#owner'});\n formsubmit.c('x', {xmlns: 'jabber:x:data', type: 'submit'});\n formsubmit.c('field', {'var': 'FORM_TYPE'}).c('value').t('http://jabber.org/protocol/muc#roomconfig').up().up();\n formsubmit.c('field', {'var': 'muc#roomconfig_roomsecret'}).c('value').t(key).up().up();\n // Fixes a bug in prosody 0.9.+ https://code.google.com/p/lxmppd/issues/detail?id=373\n formsubmit.c('field', {'var': 'muc#roomconfig_whois'}).c('value').t('anyone').up().up();\n // FIXME: is muc#roomconfig_passwordprotectedroom required?\n ob.connection.sendIQ(formsubmit,\n onSuccess,\n onError);\n } else {\n onNotSupported();\n }\n }, onError);\n};\n\nChatRoom.prototype.addToPresence = function (key, values) {\n values.tagName = key;\n this.presMap[\"nodes\"].push(values);\n};\n\nChatRoom.prototype.removeFromPresence = function (key) {\n for(var i = 0; i < this.presMap.nodes.length; i++)\n {\n if(key === this.presMap.nodes[i].tagName)\n this.presMap.nodes.splice(i, 1);\n }\n};\n\nChatRoom.prototype.addPresenceListener = function (name, handler) {\n this.presHandlers[name] = handler;\n};\n\nChatRoom.prototype.removePresenceListener = function (name) {\n delete this.presHandlers[name];\n};\n\nChatRoom.prototype.isModerator = function () {\n return this.role === 'moderator';\n};\n\nChatRoom.prototype.getMemberRole = function (peerJid) {\n if (this.members[peerJid]) {\n return this.members[peerJid].role;\n }\n return null;\n};\n\nChatRoom.prototype.setJingleSession = function(session){\n this.session = session;\n this.session.room = this;\n};\n\n\nChatRoom.prototype.removeStream = function (stream, callback) {\n if(!this.session)\n return;\n this.session.removeStream(stream, callback);\n};\n\nChatRoom.prototype.switchStreams = function (stream, oldStream, callback, isAudio) {\n if(this.session) {\n // FIXME: will block switchInProgress on true value in case of exception\n this.session.switchStreams(stream, oldStream, callback, isAudio);\n } else {\n // We are done immediately\n logger.warn(\"No conference handler or conference not started yet\");\n callback();\n }\n};\n\nChatRoom.prototype.addStream = function (stream, callback) {\n if(this.session) {\n // FIXME: will block switchInProgress on true value in case of exception\n this.session.addStream(stream, callback);\n } else {\n // We are done immediately\n logger.warn(\"No conference handler or conference not started yet\");\n callback();\n }\n};\n\nChatRoom.prototype.setVideoMute = function (mute, callback, options) {\n var self = this;\n var localCallback = function (mute) {\n self.sendVideoInfoPresence(mute);\n if(callback)\n callback(mute);\n };\n\n if(this.session)\n {\n this.session.setVideoMute(\n mute, localCallback, options);\n }\n else {\n localCallback(mute);\n }\n\n};\n\nChatRoom.prototype.setAudioMute = function (mute, callback) {\n //This will be for remote streams only\n// if (this.forceMuted && !mute) {\n// logger.info(\"Asking focus for unmute\");\n// this.connection.moderate.setMute(this.connection.emuc.myroomjid, mute);\n// // FIXME: wait for result before resetting muted status\n// this.forceMuted = false;\n// }\n\n\n return this.sendAudioInfoPresence(mute, callback);\n};\n\nChatRoom.prototype.addAudioInfoToPresence = function (mute) {\n this.removeFromPresence(\"audiomuted\");\n this.addToPresence(\"audiomuted\",\n {attributes:\n {\"audions\": \"http://jitsi.org/jitmeet/audio\"},\n value: mute.toString()});\n};\n\nChatRoom.prototype.sendAudioInfoPresence = function(mute, callback) {\n this.addAudioInfoToPresence(mute);\n if(this.connection) {\n this.sendPresence();\n }\n if(callback)\n callback();\n};\n\nChatRoom.prototype.addVideoInfoToPresence = function (mute) {\n this.removeFromPresence(\"videomuted\");\n this.addToPresence(\"videomuted\",\n {attributes:\n {\"videons\": \"http://jitsi.org/jitmeet/video\"},\n value: mute.toString()});\n};\n\n\nChatRoom.prototype.sendVideoInfoPresence = function (mute) {\n this.addVideoInfoToPresence(mute);\n if(!this.connection)\n return;\n this.sendPresence();\n};\n\nChatRoom.prototype.addListener = function(type, listener) {\n this.eventEmitter.on(type, listener);\n};\n\nChatRoom.prototype.removeListener = function (type, listener) {\n this.eventEmitter.removeListener(type, listener);\n};\n\nChatRoom.prototype.remoteStreamAdded = function(data, sid, thessrc) {\n if(this.lastPresences[data.peerjid])\n {\n var pres = this.lastPresences[data.peerjid];\n var audiomuted = filterNodeFromPresenceJSON(pres, \"audiomuted\");\n var videomuted = filterNodeFromPresenceJSON(pres, \"videomuted\");\n data.videomuted = ((videomuted.length > 0\n && videomuted[0]\n && videomuted[0][\"value\"] === \"true\")? true : false);\n data.audiomuted = ((audiomuted.length > 0\n && audiomuted[0]\n && audiomuted[0][\"value\"] === \"true\")? true : false);\n }\n\n this.eventEmitter.emit(XMPPEvents.REMOTE_STREAM_RECEIVED, data, sid, thessrc);\n};\n\nChatRoom.prototype.getJidBySSRC = function (ssrc) {\n if (!this.session)\n return null;\n return this.session.getSsrcOwner(ssrc);\n};\n\n/**\n * Returns true if the recording is supproted and false if not.\n */\nChatRoom.prototype.isRecordingSupported = function () {\n if(this.recording)\n return this.recording.isSupported();\n return false;\n};\n\n/**\n * Returns null if the recording is not supported, \"on\" if the recording started\n * and \"off\" if the recording is not started.\n */\nChatRoom.prototype.getRecordingState = function () {\n if(this.recording)\n return this.recording.getState();\n return \"off\";\n}\n\n/**\n * Returns the url of the recorded video.\n */\nChatRoom.prototype.getRecordingURL = function () {\n if(this.recording)\n return this.recording.getURL();\n return null;\n}\n\n/**\n * Starts/stops the recording\n * @param token token for authentication\n */\nChatRoom.prototype.toggleRecording = function (token, followEntity) {\n if(this.recording)\n return this.recording.toggleRecording(token, followEntity);\n\n return new Promise(function(resolve, reject){\n reject(new Error(\"The conference is not created yet!\"))});\n}\n\n/**\n * Returns true if the SIP calls are supported and false otherwise\n */\nChatRoom.prototype.isSIPCallingSupported = function () {\n if(this.moderator)\n return this.moderator.isSipGatewayEnabled();\n return false;\n}\n\n/**\n * Dials a number.\n * @param number the number\n */\nChatRoom.prototype.dial = function (number) {\n return this.connection.rayo.dial(number, \"fromnumber\",\n Strophe.getNodeFromJid(this.myroomjid), this.password,\n this.focusMucJid);\n}\n\n/**\n * Hangup an existing call\n */\nChatRoom.prototype.hangup = function () {\n return this.connection.rayo.hangup();\n}\n\n/**\n * Returns the phone number for joining the conference.\n */\nChatRoom.prototype.getPhoneNumber = function () {\n return this.phoneNumber;\n}\n\n/**\n * Returns the pin for joining the conference with phone.\n */\nChatRoom.prototype.getPhonePin = function () {\n return this.phonePin;\n}\n\n/**\n * Returns the connection state for the current session.\n */\nChatRoom.prototype.getConnectionState = function () {\n if(!this.session)\n return null;\n return this.session.getIceConnectionState();\n}\n\nmodule.exports = ChatRoom;\n", + "/*\n * JingleSession provides an API to manage a single Jingle session. We will\n * have different implementations depending on the underlying interface used\n * (i.e. WebRTC and ORTC) and here we hold the code common to all of them.\n */\nvar logger = require(\"jitsi-meet-logger\").getLogger(__filename);\n\nfunction JingleSession(me, sid, connection, service, eventEmitter) {\n /**\n * Our JID.\n */\n this.me = me;\n\n /**\n * The Jingle session identifier.\n */\n this.sid = sid;\n\n /**\n * The XMPP connection.\n */\n this.connection = connection;\n\n /**\n * The XMPP service.\n */\n this.service = service;\n\n /**\n * The event emitter.\n */\n this.eventEmitter = eventEmitter;\n\n /**\n * Whether to use dripping or not. Dripping is sending trickle candidates\n * not one-by-one.\n * Note: currently we do not support 'false'.\n */\n this.usedrip = true;\n\n /**\n * When dripping is used, stores ICE candidates which are to be sent.\n */\n this.drip_container = [];\n\n // Media constraints. Is this WebRTC only?\n this.media_constraints = null;\n\n // ICE servers config (RTCConfiguration?).\n this.ice_config = {};\n\n // The chat room instance associated with the session.\n this.room = null;\n}\n\n/**\n * Prepares this object to initiate a session.\n * @param peerjid the JID of the remote peer.\n * @param isInitiator whether we will be the Jingle initiator.\n * @param media_constraints\n * @param ice_config\n */\nJingleSession.prototype.initialize = function(peerjid, isInitiator,\n media_constraints, ice_config) {\n this.media_constraints = media_constraints;\n this.ice_config = ice_config;\n\n if (this.state !== null) {\n logger.error('attempt to initiate on session ' + this.sid +\n 'in state ' + this.state);\n return;\n }\n this.state = 'pending';\n this.initiator = isInitiator ? this.me : peerjid;\n this.responder = !isInitiator ? this.me : peerjid;\n this.peerjid = peerjid;\n\n this.doInitialize();\n};\n\n/**\n * Finishes initialization.\n */\nJingleSession.prototype.doInitialize = function() {};\n\n/**\n * Adds the ICE candidates found in the 'contents' array as remote candidates?\n * Note: currently only used on transport-info\n */\nJingleSession.prototype.addIceCandidates = function(contents) {};\n\n/**\n * Handles an 'add-source' event.\n *\n * @param contents an array of Jingle 'content' elements.\n */\nJingleSession.prototype.addSources = function(contents) {};\n\n/**\n * Handles a 'remove-source' event.\n *\n * @param contents an array of Jingle 'content' elements.\n */\nJingleSession.prototype.removeSources = function(contents) {};\n\n/**\n * Terminates this Jingle session (stops sending media and closes the streams?)\n */\nJingleSession.prototype.terminate = function() {};\n\n/**\n * Sends a Jingle session-terminate message to the peer and terminates the\n * session.\n * @param reason\n * @param text\n */\nJingleSession.prototype.sendTerminate = function(reason, text) {};\n\n/**\n * Handles an offer from the remote peer (prepares to accept a session).\n * @param jingle the 'jingle' XML element.\n */\nJingleSession.prototype.setOffer = function(jingle) {};\n\n/**\n * Handles an answer from the remote peer (prepares to accept a session).\n * @param jingle the 'jingle' XML element.\n */\nJingleSession.prototype.setAnswer = function(jingle) {};\n\n\nmodule.exports = JingleSession;\n", + "/* jshint -W117 */\n\nvar logger = require(\"jitsi-meet-logger\").getLogger(__filename);\nvar JingleSession = require(\"./JingleSession\");\nvar TraceablePeerConnection = require(\"./TraceablePeerConnection\");\nvar SDPDiffer = require(\"./SDPDiffer\");\nvar SDPUtil = require(\"./SDPUtil\");\nvar SDP = require(\"./SDP\");\nvar async = require(\"async\");\nvar transform = require(\"sdp-transform\");\nvar XMPPEvents = require(\"../../service/xmpp/XMPPEvents\");\nvar RTCBrowserType = require(\"../RTC/RTCBrowserType\");\nvar SSRCReplacement = require(\"./LocalSSRCReplacement\");\nvar RTC = require(\"../RTC/RTC\");\n\n// Jingle stuff\nfunction JingleSessionPC(me, sid, connection, service) {\n JingleSession.call(this, me, sid, connection, service);\n this.initiator = null;\n this.responder = null;\n this.peerjid = null;\n this.state = null;\n this.localSDP = null;\n this.remoteSDP = null;\n this.relayedStreams = [];\n\n this.usetrickle = true;\n this.usepranswer = false; // early transport warmup -- mind you, this might fail. depends on webrtc issue 1718\n\n this.hadstuncandidate = false;\n this.hadturncandidate = false;\n this.lasticecandidate = false;\n\n this.statsinterval = null;\n\n this.reason = null;\n\n this.addssrc = [];\n this.removessrc = [];\n this.pendingop = null;\n this.switchstreams = false;\n this.addingStreams = false;\n\n this.wait = true;\n /**\n * A map that stores SSRCs of local streams\n * @type {{}} maps media type('audio' or 'video') to SSRC number\n */\n this.localStreamsSSRC = {};\n this.ssrcOwners = {};\n this.ssrcVideoTypes = {};\n\n this.webrtcIceUdpDisable = !!this.service.options.webrtcIceUdpDisable;\n this.webrtcIceTcpDisable = !!this.service.options.webrtcIceTcpDisable;\n\n /**\n * The indicator which determines whether the (local) video has been muted\n * in response to a user command in contrast to an automatic decision made\n * by the application logic.\n */\n this.videoMuteByUser = false;\n\n this.modifySourcesQueue = async.queue(this._modifySources.bind(this), 1);\n // We start with the queue paused. We resume it when the signaling state is\n // stable and the ice connection state is connected.\n this.modifySourcesQueue.pause();\n}\n//XXX this is badly broken...\nJingleSessionPC.prototype = JingleSession.prototype;\nJingleSessionPC.prototype.constructor = JingleSessionPC;\n\n\nJingleSessionPC.prototype.setOffer = function(offer) {\n this.setRemoteDescription(offer, 'offer');\n};\n\nJingleSessionPC.prototype.setAnswer = function(answer) {\n this.setRemoteDescription(answer, 'answer');\n};\n\nJingleSessionPC.prototype.updateModifySourcesQueue = function() {\n var signalingState = this.peerconnection.signalingState;\n var iceConnectionState = this.peerconnection.iceConnectionState;\n if (signalingState === 'stable' && iceConnectionState === 'connected') {\n this.modifySourcesQueue.resume();\n } else {\n this.modifySourcesQueue.pause();\n }\n};\n\nJingleSessionPC.prototype.doInitialize = function () {\n var self = this;\n\n this.hadstuncandidate = false;\n this.hadturncandidate = false;\n this.lasticecandidate = false;\n // True if reconnect is in progress\n this.isreconnect = false;\n // Set to true if the connection was ever stable\n this.wasstable = false;\n\n this.peerconnection = new TraceablePeerConnection(\n this.connection.jingle.ice_config,\n RTC.getPCConstraints(),\n this);\n\n this.peerconnection.onicecandidate = function (event) {\n var protocol;\n if (event && event.candidate) {\n protocol = (typeof event.candidate.protocol === 'string')\n ? event.candidate.protocol.toLowerCase() : '';\n if ((self.webrtcIceTcpDisable && protocol == 'tcp') ||\n (self.webrtcIceUdpDisable && protocol == 'udp')) {\n return;\n }\n }\n self.sendIceCandidate(event.candidate);\n };\n this.peerconnection.onaddstream = function (event) {\n if (event.stream.id !== 'default') {\n logger.log(\"REMOTE STREAM ADDED: \", event.stream , event.stream.id);\n self.remoteStreamAdded(event);\n } else {\n // This is a recvonly stream. Clients that implement Unified Plan,\n // such as Firefox use recvonly \"streams/channels/tracks\" for\n // receiving remote stream/tracks, as opposed to Plan B where there\n // are only 3 channels: audio, video and data.\n logger.log(\"RECVONLY REMOTE STREAM IGNORED: \" + event.stream + \" - \" + event.stream.id);\n }\n };\n this.peerconnection.onremovestream = function (event) {\n // Remove the stream from remoteStreams\n // FIXME: remotestreamremoved.jingle not defined anywhere(unused)\n\n $(document).trigger('remotestreamremoved.jingle', [event, self.sid]);\n };\n this.peerconnection.onsignalingstatechange = function (event) {\n if (!(self && self.peerconnection)) return;\n if (self.peerconnection.signalingState === 'stable') {\n self.wasstable = true;\n }\n self.updateModifySourcesQueue();\n };\n /**\n * The oniceconnectionstatechange event handler contains the code to execute when the iceconnectionstatechange event,\n * of type Event, is received by this RTCPeerConnection. Such an event is sent when the value of\n * RTCPeerConnection.iceConnectionState changes.\n *\n * @param event the event containing information about the change\n */\n this.peerconnection.oniceconnectionstatechange = function (event) {\n if (!(self && self.peerconnection)) return;\n logger.log(\"(TIME) ICE \" + self.peerconnection.iceConnectionState +\n \":\\t\", window.performance.now());\n self.updateModifySourcesQueue();\n switch (self.peerconnection.iceConnectionState) {\n case 'connected':\n\n // Informs interested parties that the connection has been restored.\n if (self.peerconnection.signalingState === 'stable' && self.isreconnect)\n self.room.eventEmitter.emit(XMPPEvents.CONNECTION_RESTORED);\n self.isreconnect = false;\n\n break;\n case 'disconnected':\n self.isreconnect = true;\n // Informs interested parties that the connection has been interrupted.\n if (self.wasstable)\n self.room.eventEmitter.emit(XMPPEvents.CONNECTION_INTERRUPTED);\n break;\n case 'failed':\n self.room.eventEmitter.emit(XMPPEvents.CONFERENCE_SETUP_FAILED);\n break;\n }\n onIceConnectionStateChange(self.sid, self);\n };\n this.peerconnection.onnegotiationneeded = function (event) {\n self.room.eventEmitter.emit(XMPPEvents.PEERCONNECTION_READY, self);\n };\n\n this.relayedStreams.forEach(function(stream) {\n self.peerconnection.addStream(stream);\n });\n};\n\nfunction onIceConnectionStateChange(sid, session) {\n switch (session.peerconnection.iceConnectionState) {\n case 'checking':\n session.timeChecking = (new Date()).getTime();\n session.firstconnect = true;\n break;\n case 'completed': // on caller side\n case 'connected':\n if (session.firstconnect) {\n session.firstconnect = false;\n var metadata = {};\n metadata.setupTime\n = (new Date()).getTime() - session.timeChecking;\n session.peerconnection.getStats(function (res) {\n if(res && res.result) {\n res.result().forEach(function (report) {\n if (report.type == 'googCandidatePair' &&\n report.stat('googActiveConnection') == 'true') {\n metadata.localCandidateType\n = report.stat('googLocalCandidateType');\n metadata.remoteCandidateType\n = report.stat('googRemoteCandidateType');\n\n // log pair as well so we can get nice pie\n // charts\n metadata.candidatePair\n = report.stat('googLocalCandidateType') +\n ';' +\n report.stat('googRemoteCandidateType');\n\n if (report.stat('googRemoteAddress').indexOf('[') === 0)\n {\n metadata.ipv6 = true;\n }\n }\n });\n }\n });\n }\n break;\n }\n}\n\nJingleSessionPC.prototype.accept = function () {\n this.state = 'active';\n\n var pranswer = this.peerconnection.localDescription;\n if (!pranswer || pranswer.type != 'pranswer') {\n return;\n }\n logger.log('going from pranswer to answer');\n if (this.usetrickle) {\n // remove candidates already sent from session-accept\n var lines = SDPUtil.find_lines(pranswer.sdp, 'a=candidate:');\n for (var i = 0; i < lines.length; i++) {\n pranswer.sdp = pranswer.sdp.replace(lines[i] + '\\r\\n', '');\n }\n }\n while (SDPUtil.find_line(pranswer.sdp, 'a=inactive')) {\n // FIXME: change any inactive to sendrecv or whatever they were originally\n pranswer.sdp = pranswer.sdp.replace('a=inactive', 'a=sendrecv');\n }\n var prsdp = new SDP(pranswer.sdp);\n if (self.webrtcIceTcpDisable) {\n prsdp.removeTcpCandidates = true;\n }\n if (self.webrtcIceUdpDisable) {\n prsdp.removeUdpCandidates = true;\n }\n var accept = $iq({to: this.peerjid,\n type: 'set'})\n .c('jingle', {xmlns: 'urn:xmpp:jingle:1',\n action: 'session-accept',\n initiator: this.initiator,\n responder: this.responder,\n sid: this.sid });\n // FIXME why do we generate session-accept in 3 different places ?\n prsdp.toJingle(\n accept,\n this.initiator == this.me ? 'initiator' : 'responder');\n var sdp = this.peerconnection.localDescription.sdp;\n while (SDPUtil.find_line(sdp, 'a=inactive')) {\n // FIXME: change any inactive to sendrecv or whatever they were originally\n sdp = sdp.replace('a=inactive', 'a=sendrecv');\n }\n var self = this;\n this.peerconnection.setLocalDescription(new RTCSessionDescription({type: 'answer', sdp: sdp}),\n function () {\n //logger.log('setLocalDescription success');\n self.setLocalDescription();\n\n SSRCReplacement.processSessionInit(accept);\n\n self.connection.sendIQ(accept,\n function () {\n var ack = {};\n ack.source = 'answer';\n $(document).trigger('ack.jingle', [self.sid, ack]);\n },\n function (stanza) {\n var error = ($(stanza).find('error').length) ? {\n code: $(stanza).find('error').attr('code'),\n reason: $(stanza).find('error :first')[0].tagName\n }:{};\n error.source = 'answer';\n JingleSessionPC.onJingleError(self.sid, error);\n },\n 10000);\n },\n function (e) {\n logger.error('setLocalDescription failed', e);\n self.room.eventEmitter.emit(XMPPEvents.CONFERENCE_SETUP_FAILED);\n }\n );\n};\n\nJingleSessionPC.prototype.terminate = function (reason) {\n this.state = 'ended';\n this.reason = reason;\n this.peerconnection.close();\n if (this.statsinterval !== null) {\n window.clearInterval(this.statsinterval);\n this.statsinterval = null;\n }\n};\n\nJingleSessionPC.prototype.active = function () {\n return this.state == 'active';\n};\n\nJingleSessionPC.prototype.sendIceCandidate = function (candidate) {\n var self = this;\n if (candidate && !this.lasticecandidate) {\n var ice = SDPUtil.iceparams(this.localSDP.media[candidate.sdpMLineIndex], this.localSDP.session);\n var jcand = SDPUtil.candidateToJingle(candidate.candidate);\n if (!(ice && jcand)) {\n logger.error('failed to get ice && jcand');\n return;\n }\n ice.xmlns = 'urn:xmpp:jingle:transports:ice-udp:1';\n\n if (jcand.type === 'srflx') {\n this.hadstuncandidate = true;\n } else if (jcand.type === 'relay') {\n this.hadturncandidate = true;\n }\n\n if (this.usetrickle) {\n if (this.usedrip) {\n if (this.drip_container.length === 0) {\n // start 20ms callout\n window.setTimeout(function () {\n if (self.drip_container.length === 0) return;\n self.sendIceCandidates(self.drip_container);\n self.drip_container = [];\n }, 20);\n\n }\n this.drip_container.push(candidate);\n return;\n } else {\n self.sendIceCandidate([candidate]);\n }\n }\n } else {\n //logger.log('sendIceCandidate: last candidate.');\n if (!this.usetrickle) {\n //logger.log('should send full offer now...');\n //FIXME why do we generate session-accept in 3 different places ?\n var init = $iq({to: this.peerjid,\n type: 'set'})\n .c('jingle', {xmlns: 'urn:xmpp:jingle:1',\n action: this.peerconnection.localDescription.type == 'offer' ? 'session-initiate' : 'session-accept',\n initiator: this.initiator,\n sid: this.sid});\n this.localSDP = new SDP(this.peerconnection.localDescription.sdp);\n if (self.webrtcIceTcpDisable) {\n this.localSDP.removeTcpCandidates = true;\n }\n if (self.webrtcIceUdpDisable) {\n this.localSDP.removeUdpCandidates = true;\n }\n var sendJingle = function (ssrc) {\n if(!ssrc)\n ssrc = {};\n self.localSDP.toJingle(\n init,\n self.initiator == self.me ? 'initiator' : 'responder',\n ssrc);\n\n SSRCReplacement.processSessionInit(init);\n\n self.connection.sendIQ(init,\n function () {\n //logger.log('session initiate ack');\n var ack = {};\n ack.source = 'offer';\n $(document).trigger('ack.jingle', [self.sid, ack]);\n },\n function (stanza) {\n self.state = 'error';\n self.peerconnection.close();\n var error = ($(stanza).find('error').length) ? {\n code: $(stanza).find('error').attr('code'),\n reason: $(stanza).find('error :first')[0].tagName,\n }:{};\n error.source = 'offer';\n JingleSessionPC.onJingleError(self.sid, error);\n },\n 10000);\n };\n sendJingle();\n }\n this.lasticecandidate = true;\n logger.log('Have we encountered any srflx candidates? ' + this.hadstuncandidate);\n logger.log('Have we encountered any relay candidates? ' + this.hadturncandidate);\n\n if (!(this.hadstuncandidate || this.hadturncandidate) && this.peerconnection.signalingState != 'closed') {\n $(document).trigger('nostuncandidates.jingle', [this.sid]);\n }\n }\n};\n\nJingleSessionPC.prototype.sendIceCandidates = function (candidates) {\n logger.log('sendIceCandidates', candidates);\n var cand = $iq({to: this.peerjid, type: 'set'})\n .c('jingle', {xmlns: 'urn:xmpp:jingle:1',\n action: 'transport-info',\n initiator: this.initiator,\n sid: this.sid});\n for (var mid = 0; mid < this.localSDP.media.length; mid++) {\n var cands = candidates.filter(function (el) { return el.sdpMLineIndex == mid; });\n var mline = SDPUtil.parse_mline(this.localSDP.media[mid].split('\\r\\n')[0]);\n if (cands.length > 0) {\n var ice = SDPUtil.iceparams(this.localSDP.media[mid], this.localSDP.session);\n ice.xmlns = 'urn:xmpp:jingle:transports:ice-udp:1';\n cand.c('content', {creator: this.initiator == this.me ? 'initiator' : 'responder',\n name: (cands[0].sdpMid? cands[0].sdpMid : mline.media)\n }).c('transport', ice);\n for (var i = 0; i < cands.length; i++) {\n cand.c('candidate', SDPUtil.candidateToJingle(cands[i].candidate)).up();\n }\n // add fingerprint\n if (SDPUtil.find_line(this.localSDP.media[mid], 'a=fingerprint:', this.localSDP.session)) {\n var tmp = SDPUtil.parse_fingerprint(SDPUtil.find_line(this.localSDP.media[mid], 'a=fingerprint:', this.localSDP.session));\n tmp.required = true;\n cand.c(\n 'fingerprint',\n {xmlns: 'urn:xmpp:jingle:apps:dtls:0'})\n .t(tmp.fingerprint);\n delete tmp.fingerprint;\n cand.attrs(tmp);\n cand.up();\n }\n cand.up(); // transport\n cand.up(); // content\n }\n }\n // might merge last-candidate notification into this, but it is called alot later. See webrtc issue #2340\n //logger.log('was this the last candidate', this.lasticecandidate);\n this.connection.sendIQ(cand,\n function () {\n var ack = {};\n ack.source = 'transportinfo';\n $(document).trigger('ack.jingle', [this.sid, ack]);\n },\n function (stanza) {\n var error = ($(stanza).find('error').length) ? {\n code: $(stanza).find('error').attr('code'),\n reason: $(stanza).find('error :first')[0].tagName,\n }:{};\n error.source = 'transportinfo';\n JingleSessionPC.onJingleError(this.sid, error);\n },\n 10000);\n};\n\n\nJingleSessionPC.prototype.sendOffer = function () {\n //logger.log('sendOffer...');\n var self = this;\n this.peerconnection.createOffer(function (sdp) {\n self.createdOffer(sdp);\n },\n function (e) {\n logger.error('createOffer failed', e);\n },\n this.media_constraints\n );\n};\n\n// FIXME createdOffer is never used in jitsi-meet\nJingleSessionPC.prototype.createdOffer = function (sdp) {\n //logger.log('createdOffer', sdp);\n var self = this;\n this.localSDP = new SDP(sdp.sdp);\n //this.localSDP.mangle();\n var sendJingle = function () {\n var init = $iq({to: this.peerjid,\n type: 'set'})\n .c('jingle', {xmlns: 'urn:xmpp:jingle:1',\n action: 'session-initiate',\n initiator: this.initiator,\n sid: this.sid});\n self.localSDP.toJingle(\n init,\n this.initiator == this.me ? 'initiator' : 'responder');\n\n SSRCReplacement.processSessionInit(init);\n\n self.connection.sendIQ(init,\n function () {\n var ack = {};\n ack.source = 'offer';\n $(document).trigger('ack.jingle', [self.sid, ack]);\n },\n function (stanza) {\n self.state = 'error';\n self.peerconnection.close();\n var error = ($(stanza).find('error').length) ? {\n code: $(stanza).find('error').attr('code'),\n reason: $(stanza).find('error :first')[0].tagName,\n }:{};\n error.source = 'offer';\n JingleSessionPC.onJingleError(self.sid, error);\n },\n 10000);\n }\n sdp.sdp = this.localSDP.raw;\n this.peerconnection.setLocalDescription(sdp,\n function () {\n if(self.usetrickle)\n {\n sendJingle();\n }\n self.setLocalDescription();\n //logger.log('setLocalDescription success');\n },\n function (e) {\n logger.error('setLocalDescription failed', e);\n self.room.eventEmitter.emit(XMPPEvents.CONFERENCE_SETUP_FAILED);\n }\n );\n var cands = SDPUtil.find_lines(this.localSDP.raw, 'a=candidate:');\n for (var i = 0; i < cands.length; i++) {\n var cand = SDPUtil.parse_icecandidate(cands[i]);\n if (cand.type == 'srflx') {\n this.hadstuncandidate = true;\n } else if (cand.type == 'relay') {\n this.hadturncandidate = true;\n }\n }\n};\n\nJingleSessionPC.prototype.readSsrcInfo = function (contents) {\n var self = this;\n $(contents).each(function (idx, content) {\n var name = $(content).attr('name');\n var mediaType = this.getAttribute('name');\n var ssrcs = $(content).find('description>source[xmlns=\"urn:xmpp:jingle:apps:rtp:ssma:0\"]');\n ssrcs.each(function () {\n var ssrc = this.getAttribute('ssrc');\n $(this).find('>ssrc-info[xmlns=\"http://jitsi.org/jitmeet\"]').each(\n function () {\n var owner = this.getAttribute('owner');\n self.ssrcOwners[ssrc] = owner;\n }\n );\n });\n });\n};\n\n/**\n * Returns the SSRC of local audio stream.\n * @param mediaType 'audio' or 'video' media type\n * @returns {*} the SSRC number of local audio or video stream.\n */\nJingleSessionPC.prototype.getLocalSSRC = function (mediaType) {\n return this.localStreamsSSRC[mediaType];\n};\n\nJingleSessionPC.prototype.getSsrcOwner = function (ssrc) {\n return this.ssrcOwners[ssrc];\n};\n\nJingleSessionPC.prototype.setRemoteDescription = function (elem, desctype) {\n //logger.log('setting remote description... ', desctype);\n this.remoteSDP = new SDP('');\n if (self.webrtcIceTcpDisable) {\n this.remoteSDP.removeTcpCandidates = true;\n }\n if (self.webrtcIceUdpDisable) {\n this.remoteSDP.removeUdpCandidates = true;\n }\n\n this.remoteSDP.fromJingle(elem);\n this.readSsrcInfo($(elem).find(\">content\"));\n if (this.peerconnection.remoteDescription) {\n logger.log('setRemoteDescription when remote description is not null, should be pranswer', this.peerconnection.remoteDescription);\n if (this.peerconnection.remoteDescription.type == 'pranswer') {\n var pranswer = new SDP(this.peerconnection.remoteDescription.sdp);\n for (var i = 0; i < pranswer.media.length; i++) {\n // make sure we have ice ufrag and pwd\n if (!SDPUtil.find_line(this.remoteSDP.media[i], 'a=ice-ufrag:', this.remoteSDP.session)) {\n if (SDPUtil.find_line(pranswer.media[i], 'a=ice-ufrag:', pranswer.session)) {\n this.remoteSDP.media[i] += SDPUtil.find_line(pranswer.media[i], 'a=ice-ufrag:', pranswer.session) + '\\r\\n';\n } else {\n logger.warn('no ice ufrag?');\n }\n if (SDPUtil.find_line(pranswer.media[i], 'a=ice-pwd:', pranswer.session)) {\n this.remoteSDP.media[i] += SDPUtil.find_line(pranswer.media[i], 'a=ice-pwd:', pranswer.session) + '\\r\\n';\n } else {\n logger.warn('no ice pwd?');\n }\n }\n // copy over candidates\n var lines = SDPUtil.find_lines(pranswer.media[i], 'a=candidate:');\n for (var j = 0; j < lines.length; j++) {\n this.remoteSDP.media[i] += lines[j] + '\\r\\n';\n }\n }\n this.remoteSDP.raw = this.remoteSDP.session + this.remoteSDP.media.join('');\n }\n }\n var remotedesc = new RTCSessionDescription({type: desctype, sdp: this.remoteSDP.raw});\n\n this.peerconnection.setRemoteDescription(remotedesc,\n function () {\n //logger.log('setRemoteDescription success');\n },\n function (e) {\n logger.error('setRemoteDescription error', e);\n JingleSessionPC.onJingleFatalError(self, e);\n }\n );\n};\n\n/**\n * Adds remote ICE candidates to this Jingle session.\n * @param elem An array of Jingle \"content\" elements?\n */\nJingleSessionPC.prototype.addIceCandidate = function (elem) {\n var self = this;\n if (this.peerconnection.signalingState == 'closed') {\n return;\n }\n if (!this.peerconnection.remoteDescription && this.peerconnection.signalingState == 'have-local-offer') {\n logger.log('trickle ice candidate arriving before session accept...');\n // create a PRANSWER for setRemoteDescription\n if (!this.remoteSDP) {\n var cobbled = 'v=0\\r\\n' +\n 'o=- 1923518516 2 IN IP4 0.0.0.0\\r\\n' +// FIXME\n 's=-\\r\\n' +\n 't=0 0\\r\\n';\n // first, take some things from the local description\n for (var i = 0; i < this.localSDP.media.length; i++) {\n cobbled += SDPUtil.find_line(this.localSDP.media[i], 'm=') + '\\r\\n';\n cobbled += SDPUtil.find_lines(this.localSDP.media[i], 'a=rtpmap:').join('\\r\\n') + '\\r\\n';\n if (SDPUtil.find_line(this.localSDP.media[i], 'a=mid:')) {\n cobbled += SDPUtil.find_line(this.localSDP.media[i], 'a=mid:') + '\\r\\n';\n }\n cobbled += 'a=inactive\\r\\n';\n }\n this.remoteSDP = new SDP(cobbled);\n }\n // then add things like ice and dtls from remote candidate\n elem.each(function () {\n for (var i = 0; i < self.remoteSDP.media.length; i++) {\n if (SDPUtil.find_line(self.remoteSDP.media[i], 'a=mid:' + $(this).attr('name')) ||\n self.remoteSDP.media[i].indexOf('m=' + $(this).attr('name')) === 0) {\n if (!SDPUtil.find_line(self.remoteSDP.media[i], 'a=ice-ufrag:')) {\n var tmp = $(this).find('transport');\n self.remoteSDP.media[i] += 'a=ice-ufrag:' + tmp.attr('ufrag') + '\\r\\n';\n self.remoteSDP.media[i] += 'a=ice-pwd:' + tmp.attr('pwd') + '\\r\\n';\n tmp = $(this).find('transport>fingerprint');\n if (tmp.length) {\n self.remoteSDP.media[i] += 'a=fingerprint:' + tmp.attr('hash') + ' ' + tmp.text() + '\\r\\n';\n } else {\n logger.log('no dtls fingerprint (webrtc issue #1718?)');\n self.remoteSDP.media[i] += 'a=crypto:1 AES_CM_128_HMAC_SHA1_80 inline:BAADBAADBAADBAADBAADBAADBAADBAADBAADBAAD\\r\\n';\n }\n break;\n }\n }\n }\n });\n this.remoteSDP.raw = this.remoteSDP.session + this.remoteSDP.media.join('');\n\n // we need a complete SDP with ice-ufrag/ice-pwd in all parts\n // this makes the assumption that the PRANSWER is constructed such that the ice-ufrag is in all mediaparts\n // but it could be in the session part as well. since the code above constructs this sdp this can't happen however\n var iscomplete = this.remoteSDP.media.filter(function (mediapart) {\n return SDPUtil.find_line(mediapart, 'a=ice-ufrag:');\n }).length == this.remoteSDP.media.length;\n\n if (iscomplete) {\n logger.log('setting pranswer');\n try {\n this.peerconnection.setRemoteDescription(new RTCSessionDescription({type: 'pranswer', sdp: this.remoteSDP.raw }),\n function() {\n },\n function(e) {\n logger.log('setRemoteDescription pranswer failed', e.toString());\n });\n } catch (e) {\n logger.error('setting pranswer failed', e);\n }\n } else {\n //logger.log('not yet setting pranswer');\n }\n }\n // operate on each content element\n elem.each(function () {\n // would love to deactivate this, but firefox still requires it\n var idx = -1;\n var i;\n for (i = 0; i < self.remoteSDP.media.length; i++) {\n if (SDPUtil.find_line(self.remoteSDP.media[i], 'a=mid:' + $(this).attr('name')) ||\n self.remoteSDP.media[i].indexOf('m=' + $(this).attr('name')) === 0) {\n idx = i;\n break;\n }\n }\n if (idx == -1) { // fall back to localdescription\n for (i = 0; i < self.localSDP.media.length; i++) {\n if (SDPUtil.find_line(self.localSDP.media[i], 'a=mid:' + $(this).attr('name')) ||\n self.localSDP.media[i].indexOf('m=' + $(this).attr('name')) === 0) {\n idx = i;\n break;\n }\n }\n }\n var name = $(this).attr('name');\n // TODO: check ice-pwd and ice-ufrag?\n $(this).find('transport>candidate').each(function () {\n var line, candidate;\n var protocol = this.getAttribute('protocol');\n protocol =\n (typeof protocol === 'string') ? protocol.toLowerCase() : '';\n if ((self.webrtcIceTcpDisable && protocol == 'tcp') ||\n (self.webrtcIceUdpDisable && protocol == 'udp')) {\n return;\n }\n\n line = SDPUtil.candidateFromJingle(this);\n candidate = new RTCIceCandidate({sdpMLineIndex: idx,\n sdpMid: name,\n candidate: line});\n try {\n self.peerconnection.addIceCandidate(candidate);\n } catch (e) {\n logger.error('addIceCandidate failed', e.toString(), line);\n }\n });\n });\n};\n\nJingleSessionPC.prototype.sendAnswer = function (provisional) {\n //logger.log('createAnswer', provisional);\n var self = this;\n this.peerconnection.createAnswer(\n function (sdp) {\n self.createdAnswer(sdp, provisional);\n },\n function (e) {\n logger.error('createAnswer failed', e);\n self.room.eventEmitter.emit(XMPPEvents.CONFERENCE_SETUP_FAILED);\n },\n this.media_constraints\n );\n};\n\nJingleSessionPC.prototype.createdAnswer = function (sdp, provisional) {\n //logger.log('createAnswer callback');\n var self = this;\n this.localSDP = new SDP(sdp.sdp);\n //this.localSDP.mangle();\n this.usepranswer = provisional === true;\n if (this.usetrickle) {\n if (this.usepranswer) {\n sdp.type = 'pranswer';\n for (var i = 0; i < this.localSDP.media.length; i++) {\n this.localSDP.media[i] = this.localSDP.media[i].replace('a=sendrecv\\r\\n', 'a=inactive\\r\\n');\n }\n this.localSDP.raw = this.localSDP.session + '\\r\\n' + this.localSDP.media.join('');\n }\n }\n var self = this;\n var sendJingle = function (ssrcs) {\n // FIXME why do we generate session-accept in 3 different places ?\n var accept = $iq({to: self.peerjid,\n type: 'set'})\n .c('jingle', {xmlns: 'urn:xmpp:jingle:1',\n action: 'session-accept',\n initiator: self.initiator,\n responder: self.responder,\n sid: self.sid });\n if (self.webrtcIceTcpDisable) {\n self.localSDP.removeTcpCandidates = true;\n }\n if (self.webrtcIceUdpDisable) {\n self.localSDP.removeUdpCandidates = true;\n }\n self.localSDP.toJingle(\n accept,\n self.initiator == self.me ? 'initiator' : 'responder',\n ssrcs);\n\n SSRCReplacement.processSessionInit(accept);\n\n self.connection.sendIQ(accept,\n function () {\n var ack = {};\n ack.source = 'answer';\n $(document).trigger('ack.jingle', [self.sid, ack]);\n },\n function (stanza) {\n var error = ($(stanza).find('error').length) ? {\n code: $(stanza).find('error').attr('code'),\n reason: $(stanza).find('error :first')[0].tagName,\n }:{};\n error.source = 'answer';\n JingleSessionPC.onJingleError(self.sid, error);\n },\n 10000);\n }\n sdp.sdp = this.localSDP.raw;\n this.peerconnection.setLocalDescription(sdp,\n function () {\n\n //logger.log('setLocalDescription success');\n if (self.usetrickle && !self.usepranswer) {\n sendJingle();\n }\n self.setLocalDescription();\n },\n function (e) {\n logger.error('setLocalDescription failed', e);\n self.room.eventEmitter.emit(XMPPEvents.CONFERENCE_SETUP_FAILED);\n }\n );\n var cands = SDPUtil.find_lines(this.localSDP.raw, 'a=candidate:');\n for (var j = 0; j < cands.length; j++) {\n var cand = SDPUtil.parse_icecandidate(cands[j]);\n if (cand.type == 'srflx') {\n this.hadstuncandidate = true;\n } else if (cand.type == 'relay') {\n this.hadturncandidate = true;\n }\n }\n};\n\nJingleSessionPC.prototype.sendTerminate = function (reason, text) {\n var self = this,\n term = $iq({to: this.peerjid,\n type: 'set'})\n .c('jingle', {xmlns: 'urn:xmpp:jingle:1',\n action: 'session-terminate',\n initiator: this.initiator,\n sid: this.sid})\n .c('reason')\n .c(reason || 'success');\n\n if (text) {\n term.up().c('text').t(text);\n }\n\n this.connection.sendIQ(term,\n function () {\n self.peerconnection.close();\n self.peerconnection = null;\n self.terminate();\n var ack = {};\n ack.source = 'terminate';\n $(document).trigger('ack.jingle', [self.sid, ack]);\n },\n function (stanza) {\n var error = ($(stanza).find('error').length) ? {\n code: $(stanza).find('error').attr('code'),\n reason: $(stanza).find('error :first')[0].tagName,\n }:{};\n $(document).trigger('ack.jingle', [self.sid, error]);\n },\n 10000);\n if (this.statsinterval !== null) {\n window.clearInterval(this.statsinterval);\n this.statsinterval = null;\n }\n};\n\n/**\n * Handles a Jingle source-add message for this Jingle session.\n * @param elem An array of Jingle \"content\" elements.\n */\nJingleSessionPC.prototype.addSource = function (elem) {\n\n var self = this;\n // FIXME: dirty waiting\n if (!this.peerconnection.localDescription)\n {\n logger.warn(\"addSource - localDescription not ready yet\")\n setTimeout(function()\n {\n self.addSource(elem);\n },\n 200\n );\n return;\n }\n\n logger.log('addssrc', new Date().getTime());\n logger.log('ice', this.peerconnection.iceConnectionState);\n\n this.readSsrcInfo(elem);\n\n var sdp = new SDP(this.peerconnection.remoteDescription.sdp);\n var mySdp = new SDP(this.peerconnection.localDescription.sdp);\n\n $(elem).each(function (idx, content) {\n var name = $(content).attr('name');\n var lines = '';\n $(content).find('ssrc-group[xmlns=\"urn:xmpp:jingle:apps:rtp:ssma:0\"]').each(function() {\n var semantics = this.getAttribute('semantics');\n var ssrcs = $(this).find('>source').map(function () {\n return this.getAttribute('ssrc');\n }).get();\n\n if (ssrcs.length) {\n lines += 'a=ssrc-group:' + semantics + ' ' + ssrcs.join(' ') + '\\r\\n';\n }\n });\n var tmp = $(content).find('source[xmlns=\"urn:xmpp:jingle:apps:rtp:ssma:0\"]'); // can handle both >source and >description>source\n tmp.each(function () {\n var ssrc = $(this).attr('ssrc');\n if(mySdp.containsSSRC(ssrc)){\n /**\n * This happens when multiple participants change their streams at the same time and\n * ColibriFocus.modifySources have to wait for stable state. In the meantime multiple\n * addssrc are scheduled for update IQ. See\n */\n logger.warn(\"Got add stream request for my own ssrc: \"+ssrc);\n return;\n }\n if (sdp.containsSSRC(ssrc)) {\n logger.warn(\"Source-add request for existing SSRC: \" + ssrc);\n return;\n }\n $(this).find('>parameter').each(function () {\n lines += 'a=ssrc:' + ssrc + ' ' + $(this).attr('name');\n if ($(this).attr('value') && $(this).attr('value').length)\n lines += ':' + $(this).attr('value');\n lines += '\\r\\n';\n });\n });\n sdp.media.forEach(function(media, idx) {\n if (!SDPUtil.find_line(media, 'a=mid:' + name))\n return;\n sdp.media[idx] += lines;\n if (!self.addssrc[idx]) self.addssrc[idx] = '';\n self.addssrc[idx] += lines;\n });\n sdp.raw = sdp.session + sdp.media.join('');\n });\n\n this.modifySourcesQueue.push(function() {\n // When a source is added and if this is FF, a new channel is allocated\n // for receiving the added source. We need to diffuse the SSRC of this\n // new recvonly channel to the rest of the peers.\n logger.log('modify sources done');\n\n var newSdp = new SDP(self.peerconnection.localDescription.sdp);\n logger.log(\"SDPs\", mySdp, newSdp);\n self.notifyMySSRCUpdate(mySdp, newSdp);\n });\n};\n\n/**\n * Handles a Jingle source-remove message for this Jingle session.\n * @param elem An array of Jingle \"content\" elements.\n */\nJingleSessionPC.prototype.removeSource = function (elem) {\n\n var self = this;\n // FIXME: dirty waiting\n if (!this.peerconnection.localDescription) {\n logger.warn(\"removeSource - localDescription not ready yet\");\n setTimeout(function() {\n self.removeSource(elem);\n },\n 200\n );\n return;\n }\n\n logger.log('removessrc', new Date().getTime());\n logger.log('ice', this.peerconnection.iceConnectionState);\n var sdp = new SDP(this.peerconnection.remoteDescription.sdp);\n var mySdp = new SDP(this.peerconnection.localDescription.sdp);\n\n $(elem).each(function (idx, content) {\n var name = $(content).attr('name');\n var lines = '';\n $(content).find('ssrc-group[xmlns=\"urn:xmpp:jingle:apps:rtp:ssma:0\"]').each(function() {\n var semantics = this.getAttribute('semantics');\n var ssrcs = $(this).find('>source').map(function () {\n return this.getAttribute('ssrc');\n }).get();\n\n if (ssrcs.length) {\n lines += 'a=ssrc-group:' + semantics + ' ' + ssrcs.join(' ') + '\\r\\n';\n }\n });\n var tmp = $(content).find('source[xmlns=\"urn:xmpp:jingle:apps:rtp:ssma:0\"]'); // can handle both >source and >description>source\n tmp.each(function () {\n var ssrc = $(this).attr('ssrc');\n // This should never happen, but can be useful for bug detection\n if(mySdp.containsSSRC(ssrc)){\n logger.error(\"Got remove stream request for my own ssrc: \"+ssrc);\n return;\n }\n $(this).find('>parameter').each(function () {\n lines += 'a=ssrc:' + ssrc + ' ' + $(this).attr('name');\n if ($(this).attr('value') && $(this).attr('value').length)\n lines += ':' + $(this).attr('value');\n lines += '\\r\\n';\n });\n });\n sdp.media.forEach(function(media, idx) {\n if (!SDPUtil.find_line(media, 'a=mid:' + name))\n return;\n sdp.media[idx] += lines;\n if (!self.removessrc[idx]) self.removessrc[idx] = '';\n self.removessrc[idx] += lines;\n });\n sdp.raw = sdp.session + sdp.media.join('');\n });\n\n this.modifySourcesQueue.push(function() {\n // When a source is removed and if this is FF, the recvonly channel that\n // receives the remote stream is deactivated . We need to diffuse the\n // recvonly SSRC removal to the rest of the peers.\n logger.log('modify sources done');\n\n var newSdp = new SDP(self.peerconnection.localDescription.sdp);\n logger.log(\"SDPs\", mySdp, newSdp);\n self.notifyMySSRCUpdate(mySdp, newSdp);\n });\n};\n\nJingleSessionPC.prototype._modifySources = function (successCallback, queueCallback) {\n var self = this;\n\n if (this.peerconnection.signalingState == 'closed') return;\n if (!(this.addssrc.length || this.removessrc.length || this.pendingop !== null\n || this.switchstreams || this.addingStreams)){\n // There is nothing to do since scheduled job might have been executed by another succeeding call\n this.setLocalDescription();\n if(successCallback){\n successCallback();\n }\n queueCallback();\n return;\n }\n\n // Reset switch streams flags\n this.switchstreams = false;\n this.addingStreams = false;\n\n var sdp = new SDP(this.peerconnection.remoteDescription.sdp);\n\n // add sources\n this.addssrc.forEach(function(lines, idx) {\n sdp.media[idx] += lines;\n });\n this.addssrc = [];\n\n // remove sources\n this.removessrc.forEach(function(lines, idx) {\n lines = lines.split('\\r\\n');\n lines.pop(); // remove empty last element;\n lines.forEach(function(line) {\n sdp.media[idx] = sdp.media[idx].replace(line + '\\r\\n', '');\n });\n });\n this.removessrc = [];\n\n sdp.raw = sdp.session + sdp.media.join('');\n this.peerconnection.setRemoteDescription(new RTCSessionDescription({type: 'offer', sdp: sdp.raw}),\n function() {\n\n if(self.signalingState == 'closed') {\n logger.error(\"createAnswer attempt on closed state\");\n queueCallback(\"createAnswer attempt on closed state\");\n return;\n }\n\n self.peerconnection.createAnswer(\n function(modifiedAnswer) {\n // change video direction, see https://github.com/jitsi/jitmeet/issues/41\n if (self.pendingop !== null) {\n var sdp = new SDP(modifiedAnswer.sdp);\n if (sdp.media.length > 1) {\n switch(self.pendingop) {\n case 'mute':\n sdp.media[1] = sdp.media[1].replace('a=sendrecv', 'a=recvonly');\n break;\n case 'unmute':\n sdp.media[1] = sdp.media[1].replace('a=recvonly', 'a=sendrecv');\n break;\n }\n sdp.raw = sdp.session + sdp.media.join('');\n modifiedAnswer.sdp = sdp.raw;\n }\n self.pendingop = null;\n }\n\n // FIXME: pushing down an answer while ice connection state\n // is still checking is bad...\n //logger.log(self.peerconnection.iceConnectionState);\n\n // trying to work around another chrome bug\n //modifiedAnswer.sdp = modifiedAnswer.sdp.replace(/a=setup:active/g, 'a=setup:actpass');\n self.peerconnection.setLocalDescription(modifiedAnswer,\n function() {\n //logger.log('modified setLocalDescription ok');\n self.setLocalDescription();\n if(successCallback){\n successCallback();\n }\n queueCallback();\n },\n function(error) {\n logger.error('modified setLocalDescription failed', error);\n queueCallback(error);\n }\n );\n },\n function(error) {\n logger.error('modified answer failed', error);\n queueCallback(error);\n }\n );\n },\n function(error) {\n logger.error('modify failed', error);\n queueCallback(error);\n }\n );\n};\n\n\n/**\n * Switches video streams.\n * @param newStream new stream that will be used as video of this session.\n * @param oldStream old video stream of this session.\n * @param successCallback callback executed after successful stream switch.\n * @param isAudio whether the streams are audio (if true) or video (if false).\n */\nJingleSessionPC.prototype.switchStreams =\n function (newStream, oldStream, successCallback, isAudio) {\n var self = this;\n var sender, newTrack;\n var senderKind = isAudio ? 'audio' : 'video';\n // Remember SDP to figure out added/removed SSRCs\n var oldSdp = null;\n\n if (self.peerconnection) {\n if (self.peerconnection.localDescription) {\n oldSdp = new SDP(self.peerconnection.localDescription.sdp);\n }\n if (RTCBrowserType.getBrowserType() ===\n RTCBrowserType.RTC_BROWSER_FIREFOX) {\n // On Firefox we don't replace MediaStreams as this messes up the\n // m-lines (which can't be removed in Plan Unified) and brings a lot\n // of complications. Instead, we use the RTPSender and replace just\n // the track.\n\n // Find the right sender (for audio or video)\n self.peerconnection.peerconnection.getSenders().some(function (s) {\n if (s.track && s.track.kind === senderKind) {\n sender = s;\n return true;\n }\n });\n\n if (sender) {\n // We assume that our streams have a single track, either audio\n // or video.\n newTrack = isAudio ? newStream.getAudioTracks()[0] :\n newStream.getVideoTracks()[0];\n sender.replaceTrack(newTrack)\n .then(function() {\n console.log(\"Replaced a track, isAudio=\" + isAudio);\n })\n .catch(function(err) {\n console.log(\"Failed to replace a track: \" + err);\n });\n } else {\n console.log(\"Cannot switch tracks: no RTPSender.\");\n }\n } else {\n self.peerconnection.removeStream(oldStream, true);\n if (newStream) {\n self.peerconnection.addStream(newStream);\n }\n }\n }\n\n // Conference is not active\n if (!oldSdp) {\n successCallback();\n return;\n }\n\n self.switchstreams = true;\n self.modifySourcesQueue.push(function() {\n logger.log('modify sources done');\n\n successCallback();\n\n var newSdp = new SDP(self.peerconnection.localDescription.sdp);\n logger.log(\"SDPs\", oldSdp, newSdp);\n self.notifyMySSRCUpdate(oldSdp, newSdp);\n });\n};\n\n/**\n * Adds streams.\n * @param stream new stream that will be added.\n * @param success_callback callback executed after successful stream addition.\n */\nJingleSessionPC.prototype.addStream = function (stream, callback) {\n\n var self = this;\n\n // Remember SDP to figure out added/removed SSRCs\n var oldSdp = null;\n if(this.peerconnection) {\n if(this.peerconnection.localDescription) {\n oldSdp = new SDP(this.peerconnection.localDescription.sdp);\n }\n if(stream)\n this.peerconnection.addStream(stream);\n }\n\n // Conference is not active\n if(!oldSdp || !this.peerconnection) {\n callback();\n return;\n }\n\n this.addingStreams = true;\n this.modifySourcesQueue.push(function() {\n logger.log('modify sources done');\n\n callback();\n\n var newSdp = new SDP(self.peerconnection.localDescription.sdp);\n logger.log(\"SDPs\", oldSdp, newSdp);\n self.notifyMySSRCUpdate(oldSdp, newSdp);\n });\n}\n\n/**\n * Remove streams.\n * @param stream stream that will be removed.\n * @param success_callback callback executed after successful stream addition.\n */\nJingleSessionPC.prototype.removeStream = function (stream, callback) {\n\n var self = this;\n\n // Remember SDP to figure out added/removed SSRCs\n var oldSdp = null;\n if(this.peerconnection) {\n if(this.peerconnection.localDescription) {\n oldSdp = new SDP(this.peerconnection.localDescription.sdp);\n }\n if(stream)\n this.peerconnection.removeStream(stream);\n }\n\n // Conference is not active\n if(!oldSdp || !this.peerconnection) {\n callback();\n return;\n }\n\n this.addingStreams = true;\n this.modifySourcesQueue.push(function() {\n logger.log('modify sources done');\n\n callback();\n\n var newSdp = new SDP(self.peerconnection.localDescription.sdp);\n logger.log(\"SDPs\", oldSdp, newSdp);\n self.notifyMySSRCUpdate(oldSdp, newSdp);\n });\n}\n\n/**\n * Figures out added/removed ssrcs and send update IQs.\n * @param old_sdp SDP object for old description.\n * @param new_sdp SDP object for new description.\n */\nJingleSessionPC.prototype.notifyMySSRCUpdate = function (old_sdp, new_sdp) {\n\n if (!(this.peerconnection.signalingState == 'stable' &&\n this.peerconnection.iceConnectionState == 'connected')){\n logger.log(\"Too early to send updates\");\n return;\n }\n\n // send source-remove IQ.\n sdpDiffer = new SDPDiffer(new_sdp, old_sdp);\n var remove = $iq({to: this.peerjid, type: 'set'})\n .c('jingle', {\n xmlns: 'urn:xmpp:jingle:1',\n action: 'source-remove',\n initiator: this.initiator,\n sid: this.sid\n }\n );\n var removed = sdpDiffer.toJingle(remove);\n\n // Let 'source-remove' IQ through the hack and see if we're allowed to send\n // it in the current form\n if (removed)\n remove = SSRCReplacement.processSourceRemove(remove);\n\n if (removed && remove) {\n logger.info(\"Sending source-remove\", remove);\n this.connection.sendIQ(remove,\n function (res) {\n logger.info('got remove result', res);\n },\n function (err) {\n logger.error('got remove error', err);\n }\n );\n } else {\n logger.log('removal not necessary');\n }\n\n // send source-add IQ.\n var sdpDiffer = new SDPDiffer(old_sdp, new_sdp);\n var add = $iq({to: this.peerjid, type: 'set'})\n .c('jingle', {\n xmlns: 'urn:xmpp:jingle:1',\n action: 'source-add',\n initiator: this.initiator,\n sid: this.sid\n }\n );\n var added = sdpDiffer.toJingle(add);\n\n // Let 'source-add' IQ through the hack and see if we're allowed to send\n // it in the current form\n if (added)\n add = SSRCReplacement.processSourceAdd(add);\n\n if (added && add) {\n logger.info(\"Sending source-add\", add);\n this.connection.sendIQ(add,\n function (res) {\n logger.info('got add result', res);\n },\n function (err) {\n logger.error('got add error', err);\n }\n );\n } else {\n logger.log('addition not necessary');\n }\n};\n\n/**\n * Mutes/unmutes the (local) video i.e. enables/disables all video tracks.\n *\n * @param mute true to mute the (local) video i.e. to disable all video\n * tracks; otherwise, false\n * @param callback a function to be invoked with mute after all video\n * tracks have been enabled/disabled. The function may, optionally, return\n * another function which is to be invoked after the whole mute/unmute operation\n * has completed successfully.\n * @param options an object which specifies optional arguments such as the\n * boolean key byUser with default value true which\n * specifies whether the method was initiated in response to a user command (in\n * contrast to an automatic decision made by the application logic)\n */\nJingleSessionPC.prototype.setVideoMute = function (mute, callback, options) {\n var byUser;\n\n if (options) {\n byUser = options.byUser;\n if (typeof byUser === 'undefined') {\n byUser = true;\n }\n } else {\n byUser = true;\n }\n // The user's command to mute the (local) video takes precedence over any\n // automatic decision made by the application logic.\n if (byUser) {\n this.videoMuteByUser = mute;\n } else if (this.videoMuteByUser) {\n return;\n }\n\n this.hardMuteVideo(mute);\n\n var self = this;\n var oldSdp = null;\n if(self.peerconnection) {\n if(self.peerconnection.localDescription) {\n oldSdp = new SDP(self.peerconnection.localDescription.sdp);\n }\n }\n\n this.modifySourcesQueue.push(function() {\n logger.log('modify sources done');\n\n callback(mute);\n\n var newSdp = new SDP(self.peerconnection.localDescription.sdp);\n logger.log(\"SDPs\", oldSdp, newSdp);\n self.notifyMySSRCUpdate(oldSdp, newSdp);\n });\n};\n\nJingleSessionPC.prototype.hardMuteVideo = function (muted) {\n this.pendingop = muted ? 'mute' : 'unmute';\n};\n\nJingleSessionPC.prototype.sendMute = function (muted, content) {\n var info = $iq({to: this.peerjid,\n type: 'set'})\n .c('jingle', {xmlns: 'urn:xmpp:jingle:1',\n action: 'session-info',\n initiator: this.initiator,\n sid: this.sid });\n info.c(muted ? 'mute' : 'unmute', {xmlns: 'urn:xmpp:jingle:apps:rtp:info:1'});\n info.attrs({'creator': this.me == this.initiator ? 'creator' : 'responder'});\n if (content) {\n info.attrs({'name': content});\n }\n this.connection.send(info);\n};\n\nJingleSessionPC.prototype.sendRinging = function () {\n var info = $iq({to: this.peerjid,\n type: 'set'})\n .c('jingle', {xmlns: 'urn:xmpp:jingle:1',\n action: 'session-info',\n initiator: this.initiator,\n sid: this.sid });\n info.c('ringing', {xmlns: 'urn:xmpp:jingle:apps:rtp:info:1'});\n this.connection.send(info);\n};\n\nJingleSessionPC.prototype.getStats = function (interval) {\n var self = this;\n var recv = {audio: 0, video: 0};\n var lost = {audio: 0, video: 0};\n var lastrecv = {audio: 0, video: 0};\n var lastlost = {audio: 0, video: 0};\n var loss = {audio: 0, video: 0};\n var delta = {audio: 0, video: 0};\n this.statsinterval = window.setInterval(function () {\n if (self && self.peerconnection && self.peerconnection.getStats) {\n self.peerconnection.getStats(function (stats) {\n var results = stats.result();\n // TODO: there are so much statistics you can get from this..\n for (var i = 0; i < results.length; ++i) {\n if (results[i].type == 'ssrc') {\n var packetsrecv = results[i].stat('packetsReceived');\n var packetslost = results[i].stat('packetsLost');\n if (packetsrecv && packetslost) {\n packetsrecv = parseInt(packetsrecv, 10);\n packetslost = parseInt(packetslost, 10);\n\n if (results[i].stat('googFrameRateReceived')) {\n lastlost.video = lost.video;\n lastrecv.video = recv.video;\n recv.video = packetsrecv;\n lost.video = packetslost;\n } else {\n lastlost.audio = lost.audio;\n lastrecv.audio = recv.audio;\n recv.audio = packetsrecv;\n lost.audio = packetslost;\n }\n }\n }\n }\n delta.audio = recv.audio - lastrecv.audio;\n delta.video = recv.video - lastrecv.video;\n loss.audio = (delta.audio > 0) ? Math.ceil(100 * (lost.audio - lastlost.audio) / delta.audio) : 0;\n loss.video = (delta.video > 0) ? Math.ceil(100 * (lost.video - lastlost.video) / delta.video) : 0;\n $(document).trigger('packetloss.jingle', [self.sid, loss]);\n });\n }\n }, interval || 3000);\n return this.statsinterval;\n};\n\nJingleSessionPC.onJingleError = function (session, error)\n{\n logger.error(\"Jingle error\", error);\n}\n\nJingleSessionPC.onJingleFatalError = function (session, error)\n{\n this.room.eventEmitter.emit(XMPPEvents.CONFERENCE_SETUP_FAILED);\n this.room.eventEmitter.emit(XMPPEvents.JINGLE_FATAL_ERROR, session, error);\n}\n\nJingleSessionPC.prototype.setLocalDescription = function () {\n var self = this;\n var newssrcs = [];\n if(!this.peerconnection.localDescription)\n return;\n var session = transform.parse(this.peerconnection.localDescription.sdp);\n var i;\n session.media.forEach(function (media) {\n\n if (media.ssrcs && media.ssrcs.length > 0) {\n // TODO(gp) maybe exclude FID streams?\n media.ssrcs.forEach(function (ssrc) {\n if (ssrc.attribute !== 'cname') {\n return;\n }\n newssrcs.push({\n 'ssrc': ssrc.id,\n 'type': media.type\n });\n // FIXME allows for only one SSRC per media type\n self.localStreamsSSRC[media.type] = ssrc.id;\n });\n }\n\n });\n\n logger.log('new ssrcs', newssrcs);\n\n // Bind us as local SSRCs owner\n if (newssrcs.length > 0) {\n for (i = 0; i < newssrcs.length; i++) {\n var ssrc = newssrcs[i].ssrc;\n var myJid = self.connection.emuc.myroomjid;\n self.ssrcOwners[ssrc] = myJid;\n }\n }\n}\n\n// an attempt to work around https://github.com/jitsi/jitmeet/issues/32\nJingleSessionPC.prototype.sendKeyframe = function () {\n var pc = this.peerconnection;\n logger.log('sendkeyframe', pc.iceConnectionState);\n if (pc.iceConnectionState !== 'connected') return; // safe...\n var self = this;\n pc.setRemoteDescription(\n pc.remoteDescription,\n function () {\n pc.createAnswer(\n function (modifiedAnswer) {\n pc.setLocalDescription(\n modifiedAnswer,\n function () {\n // noop\n },\n function (error) {\n logger.log('triggerKeyframe setLocalDescription failed', error);\n self.room.eventEmitter.emit(XMPPEvents.SET_LOCAL_DESCRIPTION_ERROR);\n }\n );\n },\n function (error) {\n logger.log('triggerKeyframe createAnswer failed', error);\n self.room.eventEmitter.emit(XMPPEvents.CREATE_ANSWER_ERROR);\n }\n );\n },\n function (error) {\n logger.log('triggerKeyframe setRemoteDescription failed', error);\n eventEmitter.emit(XMPPEvents.SET_REMOTE_DESCRIPTION_ERROR);\n }\n );\n}\n\n\nJingleSessionPC.prototype.remoteStreamAdded = function (data, times) {\n var self = this;\n var thessrc;\n var streamId = RTC.getStreamID(data.stream);\n\n // look up an associated JID for a stream id\n if (!streamId) {\n logger.error(\"No stream ID for\", data.stream);\n } else if (streamId && streamId.indexOf('mixedmslabel') === -1) {\n // look only at a=ssrc: and _not_ at a=ssrc-group: lines\n\n var ssrclines = this.peerconnection.remoteDescription?\n SDPUtil.find_lines(this.peerconnection.remoteDescription.sdp, 'a=ssrc:') : [];\n ssrclines = ssrclines.filter(function (line) {\n // NOTE(gp) previously we filtered on the mslabel, but that property\n // is not always present.\n // return line.indexOf('mslabel:' + data.stream.label) !== -1;\n\n if (RTCBrowserType.isTemasysPluginUsed()) {\n return ((line.indexOf('mslabel:' + streamId) !== -1));\n } else {\n return ((line.indexOf('msid:' + streamId) !== -1));\n }\n });\n if (ssrclines.length) {\n thessrc = ssrclines[0].substring(7).split(' ')[0];\n\n if (!self.ssrcOwners[thessrc]) {\n logger.error(\"No SSRC owner known for: \" + thessrc);\n return;\n }\n data.peerjid = self.ssrcOwners[thessrc];\n logger.log('associated jid', self.ssrcOwners[thessrc]);\n } else {\n logger.error(\"No SSRC lines for \", streamId);\n }\n }\n\n this.room.remoteStreamAdded(data, this.sid, thessrc);\n\n var isVideo = data.stream.getVideoTracks().length > 0;\n // an attempt to work around https://github.com/jitsi/jitmeet/issues/32\n if (isVideo &&\n data.peerjid && this.peerjid === data.peerjid &&\n data.stream.getVideoTracks().length === 0 &&\n RTC.localVideo.getTracks().length > 0) {\n window.setTimeout(function () {\n self.sendKeyframe();\n }, 3000);\n }\n}\n\n/**\n * Returns the ice connection state for the peer connection.\n * @returns the ice connection state for the peer connection.\n */\nJingleSessionPC.prototype.getIceConnectionState = function () {\n return this.peerconnection.iceConnectionState;\n}\n\nmodule.exports = JingleSessionPC;\n", + "/* global $ */\nvar logger = require(\"jitsi-meet-logger\").getLogger(__filename);\n\n\n/*\n Here we do modifications of local video SSRCs. There are 2 situations we have\n to handle:\n\n 1. We generate SSRC for local recvonly video stream. This is the case when we\n have no local camera and it is not generated automatically, but SSRC=1 is\n used implicitly. If that happens RTCP packets will be dropped by the JVB\n and we won't be able to request video key frames correctly.\n\n 2. A hack to re-use SSRC of the first video stream for any new stream created\n in future. It turned out that Chrome may keep on using the SSRC of removed\n video stream in RTCP even though a new one has been created. So we just\n want to avoid that by re-using it. Jingle 'source-remove'/'source-add'\n notifications are blocked once first video SSRC is advertised to the focus.\n\n What this hack does:\n\n 1. Stores the SSRC of the first video stream created by\n a) scanning Jingle session-accept/session-invite for existing video SSRC\n b) watching for 'source-add' for new video stream if it has not been\n created in step a)\n 2. Exposes method 'mungeLocalVideoSSRC' which replaces any new video SSRC with\n the stored one. It is called by 'TracablePeerConnection' before local SDP is\n returned to the other parts of the application.\n 3. Scans 'source-remove'/'source-add' notifications for stored video SSRC and\n blocks those notifications. This makes Jicofo and all participants think\n that it exists all the time even if the video stream has been removed or\n replaced locally. Thanks to that there is no additional signaling activity\n on video mute or when switching to the desktop stream.\n */\n\nvar SDP = require('./SDP');\nvar RandomUtil = require('../util/RandomUtil');\nvar RTCBrowserType = require('../RTC/RTCBrowserType');\n\n/**\n * The hack is enabled on all browsers except FF by default\n * FIXME finish the hack once removeStream method is implemented in FF\n * @type {boolean}\n */\nvar isEnabled = !RTCBrowserType.isFirefox();\n\n\n/**\n * Stored SSRC of local video stream.\n */\nvar localVideoSSRC;\n\n/**\n * SSRC used for recvonly video stream when we have no local camera.\n * This is in order to tell Chrome what SSRC should be used in RTCP requests\n * instead of 1.\n */\nvar localRecvOnlySSRC, localRecvOnlyMSID, localRecvOnlyMSLabel, localRecvOnlyLabel;\n\n/**\n * cname for localRecvOnlySSRC\n */\nvar localRecvOnlyCName;\n\n/**\n * Method removes element which describes localVideoSSRC\n * from given Jingle IQ.\n * @param modifyIq 'source-add' or 'source-remove' Jingle IQ.\n * @param actionName display name of the action which will be printed in log\n * messages.\n * @returns {*} modified Jingle IQ, so that it does not contain element\n * corresponding to localVideoSSRC or null if no\n * other SSRCs left to be signaled after removing it.\n */\nvar filterOutSource = function (modifyIq, actionName) {\n var modifyIqTree = $(modifyIq.tree());\n\n if (!localVideoSSRC)\n return modifyIqTree[0];\n\n var videoSSRC = modifyIqTree.find(\n '>jingle>content[name=\"video\"]' +\n '>description>source[ssrc=\"' + localVideoSSRC + '\"]');\n\n if (!videoSSRC.length) {\n return modifyIqTree[0];\n }\n\n logger.info(\n 'Blocking ' + actionName + ' for local video SSRC: ' + localVideoSSRC);\n\n videoSSRC.remove();\n\n // Check if any sources still left to be added/removed\n if (modifyIqTree.find('>jingle>content>description>source').length) {\n return modifyIqTree[0];\n } else {\n return null;\n }\n};\n\n/**\n * Scans given Jingle IQ for video SSRC and stores it.\n * @param jingleIq the Jingle IQ to be scanned for video SSRC.\n */\nvar storeLocalVideoSSRC = function (jingleIq) {\n var videoSSRCs =\n $(jingleIq.tree())\n .find('>jingle>content[name=\"video\"]>description>source');\n\n videoSSRCs.each(function (idx, ssrcElem) {\n if (localVideoSSRC)\n return;\n // We consider SSRC real only if it has msid attribute\n // recvonly streams in FF do not have it as well as local SSRCs\n // we generate for recvonly streams in Chrome\n var ssrSel = $(ssrcElem);\n var msid = ssrSel.find('>parameter[name=\"msid\"]');\n if (msid.length) {\n var ssrcVal = ssrSel.attr('ssrc');\n if (ssrcVal) {\n localVideoSSRC = ssrcVal;\n logger.info('Stored local video SSRC' +\n ' for future re-use: ' + localVideoSSRC);\n }\n }\n });\n};\n\n/**\n * Generates new label/mslabel attribute\n * @returns {string} label/mslabel attribute\n */\nfunction generateLabel() {\n return RandomUtil.randomHexString(8) + \"-\" + RandomUtil.randomHexString(4) +\n \"-\" + RandomUtil.randomHexString(4) + \"-\" +\n RandomUtil.randomHexString(4) + \"-\" + RandomUtil.randomHexString(12);\n}\n\n/**\n * Generates new SSRC for local video recvonly stream.\n * FIXME what about eventual SSRC collision ?\n */\nfunction generateRecvonlySSRC() {\n\n localVideoSSRC = localRecvOnlySSRC =\n localVideoSSRC ?\n localVideoSSRC : Math.random().toString(10).substring(2, 11);\n\n localRecvOnlyCName =\n Math.random().toString(36).substring(2);\n\n localRecvOnlyMSLabel = generateLabel();\n localRecvOnlyLabel = generateLabel();\n localRecvOnlyMSID = localRecvOnlyMSLabel + \" \" + localRecvOnlyLabel;\n\n logger.info(\n \"Generated local recvonly SSRC: \" + localRecvOnlySSRC +\n \", cname: \" + localRecvOnlyCName);\n}\n\nvar LocalSSRCReplacement = {\n /**\n * Method must be called before 'session-initiate' or 'session-invite' is\n * sent. Scans the IQ for local video SSRC and stores it if detected.\n *\n * @param sessionInit our 'session-initiate' or 'session-accept' Jingle IQ\n * which will be scanned for local video SSRC.\n */\n processSessionInit: function (sessionInit) {\n if (!isEnabled)\n return;\n\n if (localVideoSSRC) {\n logger.error(\"Local SSRC stored already: \" + localVideoSSRC);\n return;\n }\n storeLocalVideoSSRC(sessionInit);\n },\n /**\n * If we have local video SSRC stored searched given\n * localDescription for video SSRC and makes sure it is replaced\n * with the stored one.\n * @param localDescription local description object that will have local\n * video SSRC replaced with the stored one\n * @returns modified localDescription object.\n */\n mungeLocalVideoSSRC: function (localDescription) {\n if (!isEnabled)\n return localDescription;\n\n if (!localDescription) {\n logger.warn(\"localDescription is null or undefined\");\n return localDescription;\n }\n\n // IF we have local video SSRC stored make sure it is replaced\n // with old SSRC\n var sdp = new SDP(localDescription.sdp);\n if (sdp.media.length < 2)\n return;\n\n if (localVideoSSRC && sdp.media[1].indexOf(\"a=ssrc:\") !== -1 &&\n !sdp.containsSSRC(localVideoSSRC)) {\n // Get new video SSRC\n var map = sdp.getMediaSsrcMap();\n var videoPart = map[1];\n var videoSSRCs = videoPart.ssrcs;\n var newSSRC = Object.keys(videoSSRCs)[0];\n\n logger.info(\n \"Replacing new video SSRC: \" + newSSRC +\n \" with \" + localVideoSSRC);\n\n localDescription.sdp =\n sdp.raw.replace(\n new RegExp('a=ssrc:' + newSSRC, 'g'),\n 'a=ssrc:' + localVideoSSRC);\n }\n else if (sdp.media[1].indexOf('a=ssrc:') === -1 &&\n sdp.media[1].indexOf('a=recvonly') !== -1) {\n // Make sure we have any SSRC for recvonly video stream\n if (!localRecvOnlySSRC) {\n generateRecvonlySSRC();\n }\n\n logger.info('No SSRC in video recvonly stream' +\n ' - adding SSRC: ' + localRecvOnlySSRC);\n\n sdp.media[1] += 'a=ssrc:' + localRecvOnlySSRC +\n ' cname:' + localRecvOnlyCName + '\\r\\n' +\n 'a=ssrc:' + localRecvOnlySSRC +\n ' msid:' + localRecvOnlyMSID + '\\r\\n' +\n 'a=ssrc:' + localRecvOnlySSRC +\n ' mslabel:' + localRecvOnlyMSLabel + '\\r\\n' +\n 'a=ssrc:' + localRecvOnlySSRC +\n ' label:' + localRecvOnlyLabel + '\\r\\n';\n\n localDescription.sdp = sdp.session + sdp.media.join('');\n }\n return localDescription;\n },\n /**\n * Method must be called before 'source-add' notification is sent. In case\n * we have local video SSRC advertised already it will be removed from the\n * notification. If no other SSRCs are described by given IQ null will be\n * returned which means that there is no point in sending the notification.\n * @param sourceAdd 'source-add' Jingle IQ to be processed\n * @returns modified 'source-add' IQ which can be sent to the focus or\n * null if no notification shall be sent. It is no longer\n * a Strophe IQ Builder instance, but DOM element tree.\n */\n processSourceAdd: function (sourceAdd) {\n if (!isEnabled)\n return sourceAdd;\n\n if (!localVideoSSRC) {\n // Store local SSRC if available\n storeLocalVideoSSRC(sourceAdd);\n return sourceAdd;\n } else {\n return filterOutSource(sourceAdd, 'source-add');\n }\n },\n /**\n * Method must be called before 'source-remove' notification is sent.\n * Removes local video SSRC from the notification. If there are no other\n * SSRCs described in the given IQ null will be returned which\n * means that there is no point in sending the notification.\n * @param sourceRemove 'source-remove' Jingle IQ to be processed\n * @returns modified 'source-remove' IQ which can be sent to the focus or\n * null if no notification shall be sent. It is no longer\n * a Strophe IQ Builder instance, but DOM element tree.\n */\n processSourceRemove: function (sourceRemove) {\n if (!isEnabled)\n return sourceRemove;\n\n return filterOutSource(sourceRemove, 'source-remove');\n },\n\n /**\n * Turns the hack on or off\n * @param enabled true to enable the hack or false\n * to disable it\n */\n setEnabled: function (enabled) {\n isEnabled = enabled;\n }\n};\n\nmodule.exports = LocalSSRCReplacement;\n", + "/* jshint -W117 */\n\nvar logger = require(\"jitsi-meet-logger\").getLogger(__filename);\nvar SDPUtil = require(\"./SDPUtil\");\n\n// SDP STUFF\nfunction SDP(sdp) {\n /**\n * Whether or not to remove TCP ice candidates when translating from/to jingle.\n * @type {boolean}\n */\n this.removeTcpCandidates = false;\n\n /**\n * Whether or not to remove UDP ice candidates when translating from/to jingle.\n * @type {boolean}\n */\n this.removeUdpCandidates = false;\n\n this.media = sdp.split('\\r\\nm=');\n for (var i = 1; i < this.media.length; i++) {\n this.media[i] = 'm=' + this.media[i];\n if (i != this.media.length - 1) {\n this.media[i] += '\\r\\n';\n }\n }\n this.session = this.media.shift() + '\\r\\n';\n this.raw = this.session + this.media.join('');\n}\n\n/**\n * Returns map of MediaChannel mapped per channel idx.\n */\nSDP.prototype.getMediaSsrcMap = function() {\n var self = this;\n var media_ssrcs = {};\n var tmp;\n for (var mediaindex = 0; mediaindex < self.media.length; mediaindex++) {\n tmp = SDPUtil.find_lines(self.media[mediaindex], 'a=ssrc:');\n var mid = SDPUtil.parse_mid(SDPUtil.find_line(self.media[mediaindex], 'a=mid:'));\n var media = {\n mediaindex: mediaindex,\n mid: mid,\n ssrcs: {},\n ssrcGroups: []\n };\n media_ssrcs[mediaindex] = media;\n tmp.forEach(function (line) {\n var linessrc = line.substring(7).split(' ')[0];\n // allocate new ChannelSsrc\n if(!media.ssrcs[linessrc]) {\n media.ssrcs[linessrc] = {\n ssrc: linessrc,\n lines: []\n };\n }\n media.ssrcs[linessrc].lines.push(line);\n });\n tmp = SDPUtil.find_lines(self.media[mediaindex], 'a=ssrc-group:');\n tmp.forEach(function(line){\n var idx = line.indexOf(' ');\n var semantics = line.substr(0, idx).substr(13);\n var ssrcs = line.substr(14 + semantics.length).split(' ');\n if (ssrcs.length) {\n media.ssrcGroups.push({\n semantics: semantics,\n ssrcs: ssrcs\n });\n }\n });\n }\n return media_ssrcs;\n};\n/**\n * Returns true if this SDP contains given SSRC.\n * @param ssrc the ssrc to check.\n * @returns {boolean} true if this SDP contains given SSRC.\n */\nSDP.prototype.containsSSRC = function (ssrc) {\n // FIXME this code is really strange - improve it if you can\n var medias = this.getMediaSsrcMap();\n var result = false;\n Object.keys(medias).forEach(function (mediaindex) {\n if (result)\n return;\n if (medias[mediaindex].ssrcs[ssrc]) {\n result = true;\n }\n });\n return result;\n};\n\n// remove iSAC and CN from SDP\nSDP.prototype.mangle = function () {\n var i, j, mline, lines, rtpmap, newdesc;\n for (i = 0; i < this.media.length; i++) {\n lines = this.media[i].split('\\r\\n');\n lines.pop(); // remove empty last element\n mline = SDPUtil.parse_mline(lines.shift());\n if (mline.media != 'audio')\n continue;\n newdesc = '';\n mline.fmt.length = 0;\n for (j = 0; j < lines.length; j++) {\n if (lines[j].substr(0, 9) == 'a=rtpmap:') {\n rtpmap = SDPUtil.parse_rtpmap(lines[j]);\n if (rtpmap.name == 'CN' || rtpmap.name == 'ISAC')\n continue;\n mline.fmt.push(rtpmap.id);\n newdesc += lines[j] + '\\r\\n';\n } else {\n newdesc += lines[j] + '\\r\\n';\n }\n }\n this.media[i] = SDPUtil.build_mline(mline) + '\\r\\n';\n this.media[i] += newdesc;\n }\n this.raw = this.session + this.media.join('');\n};\n\n// remove lines matching prefix from session section\nSDP.prototype.removeSessionLines = function(prefix) {\n var self = this;\n var lines = SDPUtil.find_lines(this.session, prefix);\n lines.forEach(function(line) {\n self.session = self.session.replace(line + '\\r\\n', '');\n });\n this.raw = this.session + this.media.join('');\n return lines;\n}\n// remove lines matching prefix from a media section specified by mediaindex\n// TODO: non-numeric mediaindex could match mid\nSDP.prototype.removeMediaLines = function(mediaindex, prefix) {\n var self = this;\n var lines = SDPUtil.find_lines(this.media[mediaindex], prefix);\n lines.forEach(function(line) {\n self.media[mediaindex] = self.media[mediaindex].replace(line + '\\r\\n', '');\n });\n this.raw = this.session + this.media.join('');\n return lines;\n}\n\n// add content's to a jingle element\nSDP.prototype.toJingle = function (elem, thecreator) {\n// logger.log(\"SSRC\" + ssrcs[\"audio\"] + \" - \" + ssrcs[\"video\"]);\n var self = this;\n var i, j, k, mline, ssrc, rtpmap, tmp, lines;\n // new bundle plan\n if (SDPUtil.find_line(this.session, 'a=group:')) {\n lines = SDPUtil.find_lines(this.session, 'a=group:');\n for (i = 0; i < lines.length; i++) {\n tmp = lines[i].split(' ');\n var semantics = tmp.shift().substr(8);\n elem.c('group', {xmlns: 'urn:xmpp:jingle:apps:grouping:0', semantics:semantics});\n for (j = 0; j < tmp.length; j++) {\n elem.c('content', {name: tmp[j]}).up();\n }\n elem.up();\n }\n }\n for (i = 0; i < this.media.length; i++) {\n mline = SDPUtil.parse_mline(this.media[i].split('\\r\\n')[0]);\n if (!(mline.media === 'audio' ||\n mline.media === 'video' ||\n mline.media === 'application'))\n {\n continue;\n }\n if (SDPUtil.find_line(this.media[i], 'a=ssrc:')) {\n ssrc = SDPUtil.find_line(this.media[i], 'a=ssrc:').substring(7).split(' ')[0]; // take the first\n } else {\n ssrc = false;\n }\n\n elem.c('content', {creator: thecreator, name: mline.media});\n if (SDPUtil.find_line(this.media[i], 'a=mid:')) {\n // prefer identifier from a=mid if present\n var mid = SDPUtil.parse_mid(SDPUtil.find_line(this.media[i], 'a=mid:'));\n elem.attrs({ name: mid });\n }\n\n if (SDPUtil.find_line(this.media[i], 'a=rtpmap:').length) {\n elem.c('description',\n {xmlns: 'urn:xmpp:jingle:apps:rtp:1',\n media: mline.media });\n if (ssrc) {\n elem.attrs({ssrc: ssrc});\n }\n for (j = 0; j < mline.fmt.length; j++) {\n rtpmap = SDPUtil.find_line(this.media[i], 'a=rtpmap:' + mline.fmt[j]);\n elem.c('payload-type', SDPUtil.parse_rtpmap(rtpmap));\n // put any 'a=fmtp:' + mline.fmt[j] lines into \n if (SDPUtil.find_line(this.media[i], 'a=fmtp:' + mline.fmt[j])) {\n tmp = SDPUtil.parse_fmtp(SDPUtil.find_line(this.media[i], 'a=fmtp:' + mline.fmt[j]));\n for (k = 0; k < tmp.length; k++) {\n elem.c('parameter', tmp[k]).up();\n }\n }\n this.rtcpFbToJingle(i, elem, mline.fmt[j]); // XEP-0293 -- map a=rtcp-fb\n\n elem.up();\n }\n if (SDPUtil.find_line(this.media[i], 'a=crypto:', this.session)) {\n elem.c('encryption', {required: 1});\n var crypto = SDPUtil.find_lines(this.media[i], 'a=crypto:', this.session);\n crypto.forEach(function(line) {\n elem.c('crypto', SDPUtil.parse_crypto(line)).up();\n });\n elem.up(); // end of encryption\n }\n\n if (ssrc) {\n // new style mapping\n elem.c('source', { ssrc: ssrc, xmlns: 'urn:xmpp:jingle:apps:rtp:ssma:0' });\n // FIXME: group by ssrc and support multiple different ssrcs\n var ssrclines = SDPUtil.find_lines(this.media[i], 'a=ssrc:');\n if(ssrclines.length > 0) {\n ssrclines.forEach(function (line) {\n var idx = line.indexOf(' ');\n var linessrc = line.substr(0, idx).substr(7);\n if (linessrc != ssrc) {\n elem.up();\n ssrc = linessrc;\n elem.c('source', { ssrc: ssrc, xmlns: 'urn:xmpp:jingle:apps:rtp:ssma:0' });\n }\n var kv = line.substr(idx + 1);\n elem.c('parameter');\n if (kv.indexOf(':') == -1) {\n elem.attrs({ name: kv });\n } else {\n var k = kv.split(':', 2)[0];\n elem.attrs({ name: k });\n\n var v = kv.split(':', 2)[1];\n v = SDPUtil.filter_special_chars(v);\n elem.attrs({ value: v });\n }\n elem.up();\n });\n } else {\n elem.up();\n elem.c('source', { ssrc: ssrc, xmlns: 'urn:xmpp:jingle:apps:rtp:ssma:0' });\n elem.c('parameter');\n elem.attrs({name: \"cname\", value:Math.random().toString(36).substring(7)});\n elem.up();\n var msid = null;\n if(mline.media == \"audio\")\n {\n msid = APP.RTC.localAudio._getId();\n }\n else\n {\n msid = APP.RTC.localVideo._getId();\n }\n if(msid != null)\n {\n msid = SDPUtil.filter_special_chars(msid);\n elem.c('parameter');\n elem.attrs({name: \"msid\", value:msid});\n elem.up();\n elem.c('parameter');\n elem.attrs({name: \"mslabel\", value:msid});\n elem.up();\n elem.c('parameter');\n elem.attrs({name: \"label\", value:msid});\n elem.up();\n }\n }\n elem.up();\n\n // XEP-0339 handle ssrc-group attributes\n var ssrc_group_lines = SDPUtil.find_lines(this.media[i], 'a=ssrc-group:');\n ssrc_group_lines.forEach(function(line) {\n var idx = line.indexOf(' ');\n var semantics = line.substr(0, idx).substr(13);\n var ssrcs = line.substr(14 + semantics.length).split(' ');\n if (ssrcs.length) {\n elem.c('ssrc-group', { semantics: semantics, xmlns: 'urn:xmpp:jingle:apps:rtp:ssma:0' });\n ssrcs.forEach(function(ssrc) {\n elem.c('source', { ssrc: ssrc })\n .up();\n });\n elem.up();\n }\n });\n }\n\n if (SDPUtil.find_line(this.media[i], 'a=rtcp-mux')) {\n elem.c('rtcp-mux').up();\n }\n\n // XEP-0293 -- map a=rtcp-fb:*\n this.rtcpFbToJingle(i, elem, '*');\n\n // XEP-0294\n if (SDPUtil.find_line(this.media[i], 'a=extmap:')) {\n lines = SDPUtil.find_lines(this.media[i], 'a=extmap:');\n for (j = 0; j < lines.length; j++) {\n tmp = SDPUtil.parse_extmap(lines[j]);\n elem.c('rtp-hdrext', { xmlns: 'urn:xmpp:jingle:apps:rtp:rtp-hdrext:0',\n uri: tmp.uri,\n id: tmp.value });\n if (tmp.hasOwnProperty('direction')) {\n switch (tmp.direction) {\n case 'sendonly':\n elem.attrs({senders: 'responder'});\n break;\n case 'recvonly':\n elem.attrs({senders: 'initiator'});\n break;\n case 'sendrecv':\n elem.attrs({senders: 'both'});\n break;\n case 'inactive':\n elem.attrs({senders: 'none'});\n break;\n }\n }\n // TODO: handle params\n elem.up();\n }\n }\n elem.up(); // end of description\n }\n\n // map ice-ufrag/pwd, dtls fingerprint, candidates\n this.transportToJingle(i, elem);\n\n if (SDPUtil.find_line(this.media[i], 'a=sendrecv', this.session)) {\n elem.attrs({senders: 'both'});\n } else if (SDPUtil.find_line(this.media[i], 'a=sendonly', this.session)) {\n elem.attrs({senders: 'initiator'});\n } else if (SDPUtil.find_line(this.media[i], 'a=recvonly', this.session)) {\n elem.attrs({senders: 'responder'});\n } else if (SDPUtil.find_line(this.media[i], 'a=inactive', this.session)) {\n elem.attrs({senders: 'none'});\n }\n if (mline.port == '0') {\n // estos hack to reject an m-line\n elem.attrs({senders: 'rejected'});\n }\n elem.up(); // end of content\n }\n elem.up();\n return elem;\n};\n\nSDP.prototype.transportToJingle = function (mediaindex, elem) {\n var tmp, sctpmap, sctpAttrs, fingerprints;\n var self = this;\n elem.c('transport');\n\n // XEP-0343 DTLS/SCTP\n if (SDPUtil.find_line(this.media[mediaindex], 'a=sctpmap:').length)\n {\n sctpmap = SDPUtil.find_line(\n this.media[mediaindex], 'a=sctpmap:', self.session);\n if (sctpmap)\n {\n sctpAttrs = SDPUtil.parse_sctpmap(sctpmap);\n elem.c('sctpmap',\n {\n xmlns: 'urn:xmpp:jingle:transports:dtls-sctp:1',\n number: sctpAttrs[0], /* SCTP port */\n protocol: sctpAttrs[1] /* protocol */\n });\n // Optional stream count attribute\n if (sctpAttrs.length > 2)\n elem.attrs({ streams: sctpAttrs[2]});\n elem.up();\n }\n }\n // XEP-0320\n fingerprints = SDPUtil.find_lines(this.media[mediaindex], 'a=fingerprint:', this.session);\n fingerprints.forEach(function(line) {\n tmp = SDPUtil.parse_fingerprint(line);\n tmp.xmlns = 'urn:xmpp:jingle:apps:dtls:0';\n elem.c('fingerprint').t(tmp.fingerprint);\n delete tmp.fingerprint;\n line = SDPUtil.find_line(self.media[mediaindex], 'a=setup:', self.session);\n if (line) {\n tmp.setup = line.substr(8);\n }\n elem.attrs(tmp);\n elem.up(); // end of fingerprint\n });\n tmp = SDPUtil.iceparams(this.media[mediaindex], this.session);\n if (tmp) {\n tmp.xmlns = 'urn:xmpp:jingle:transports:ice-udp:1';\n elem.attrs(tmp);\n // XEP-0176\n if (SDPUtil.find_line(this.media[mediaindex], 'a=candidate:', this.session)) { // add any a=candidate lines\n var lines = SDPUtil.find_lines(this.media[mediaindex], 'a=candidate:', this.session);\n lines.forEach(function (line) {\n var candidate = SDPUtil.candidateToJingle(line);\n var protocol = (candidate &&\n typeof candidate.protocol === 'string')\n ? candidate.protocol.toLowerCase() : '';\n if ((self.removeTcpCandidates && protocol === 'tcp') ||\n (self.removeUdpCandidates && protocol === 'udp')) {\n return;\n }\n elem.c('candidate', candidate).up();\n });\n }\n }\n elem.up(); // end of transport\n}\n\nSDP.prototype.rtcpFbToJingle = function (mediaindex, elem, payloadtype) { // XEP-0293\n var lines = SDPUtil.find_lines(this.media[mediaindex], 'a=rtcp-fb:' + payloadtype);\n lines.forEach(function (line) {\n var tmp = SDPUtil.parse_rtcpfb(line);\n if (tmp.type == 'trr-int') {\n elem.c('rtcp-fb-trr-int', {xmlns: 'urn:xmpp:jingle:apps:rtp:rtcp-fb:0', value: tmp.params[0]});\n elem.up();\n } else {\n elem.c('rtcp-fb', {xmlns: 'urn:xmpp:jingle:apps:rtp:rtcp-fb:0', type: tmp.type});\n if (tmp.params.length > 0) {\n elem.attrs({'subtype': tmp.params[0]});\n }\n elem.up();\n }\n });\n};\n\nSDP.prototype.rtcpFbFromJingle = function (elem, payloadtype) { // XEP-0293\n var media = '';\n var tmp = elem.find('>rtcp-fb-trr-int[xmlns=\"urn:xmpp:jingle:apps:rtp:rtcp-fb:0\"]');\n if (tmp.length) {\n media += 'a=rtcp-fb:' + '*' + ' ' + 'trr-int' + ' ';\n if (tmp.attr('value')) {\n media += tmp.attr('value');\n } else {\n media += '0';\n }\n media += '\\r\\n';\n }\n tmp = elem.find('>rtcp-fb[xmlns=\"urn:xmpp:jingle:apps:rtp:rtcp-fb:0\"]');\n tmp.each(function () {\n media += 'a=rtcp-fb:' + payloadtype + ' ' + $(this).attr('type');\n if ($(this).attr('subtype')) {\n media += ' ' + $(this).attr('subtype');\n }\n media += '\\r\\n';\n });\n return media;\n};\n\n// construct an SDP from a jingle stanza\nSDP.prototype.fromJingle = function (jingle) {\n var self = this;\n this.raw = 'v=0\\r\\n' +\n 'o=- 1923518516 2 IN IP4 0.0.0.0\\r\\n' +// FIXME\n 's=-\\r\\n' +\n 't=0 0\\r\\n';\n // http://tools.ietf.org/html/draft-ietf-mmusic-sdp-bundle-negotiation-04#section-8\n if ($(jingle).find('>group[xmlns=\"urn:xmpp:jingle:apps:grouping:0\"]').length) {\n $(jingle).find('>group[xmlns=\"urn:xmpp:jingle:apps:grouping:0\"]').each(function (idx, group) {\n var contents = $(group).find('>content').map(function (idx, content) {\n return content.getAttribute('name');\n }).get();\n if (contents.length > 0) {\n self.raw += 'a=group:' + (group.getAttribute('semantics') || group.getAttribute('type')) + ' ' + contents.join(' ') + '\\r\\n';\n }\n });\n }\n\n this.session = this.raw;\n jingle.find('>content').each(function () {\n var m = self.jingle2media($(this));\n self.media.push(m);\n });\n\n // reconstruct msid-semantic -- apparently not necessary\n /*\n var msid = SDPUtil.parse_ssrc(this.raw);\n if (msid.hasOwnProperty('mslabel')) {\n this.session += \"a=msid-semantic: WMS \" + msid.mslabel + \"\\r\\n\";\n }\n */\n\n this.raw = this.session + this.media.join('');\n};\n\n// translate a jingle content element into an an SDP media part\nSDP.prototype.jingle2media = function (content) {\n var media = '',\n desc = content.find('description'),\n ssrc = desc.attr('ssrc'),\n self = this,\n tmp;\n var sctp = content.find(\n '>transport>sctpmap[xmlns=\"urn:xmpp:jingle:transports:dtls-sctp:1\"]');\n\n tmp = { media: desc.attr('media') };\n tmp.port = '1';\n if (content.attr('senders') == 'rejected') {\n // estos hack to reject an m-line.\n tmp.port = '0';\n }\n if (content.find('>transport>fingerprint').length || desc.find('encryption').length) {\n if (sctp.length)\n tmp.proto = 'DTLS/SCTP';\n else\n tmp.proto = 'RTP/SAVPF';\n } else {\n tmp.proto = 'RTP/AVPF';\n }\n if (!sctp.length) {\n tmp.fmt = desc.find('payload-type').map(\n function () { return this.getAttribute('id'); }).get();\n media += SDPUtil.build_mline(tmp) + '\\r\\n';\n } else {\n media += 'm=application 1 DTLS/SCTP ' + sctp.attr('number') + '\\r\\n';\n media += 'a=sctpmap:' + sctp.attr('number') +\n ' ' + sctp.attr('protocol');\n\n var streamCount = sctp.attr('streams');\n if (streamCount)\n media += ' ' + streamCount + '\\r\\n';\n else\n media += '\\r\\n';\n }\n\n media += 'c=IN IP4 0.0.0.0\\r\\n';\n if (!sctp.length)\n media += 'a=rtcp:1 IN IP4 0.0.0.0\\r\\n';\n tmp = content.find('>transport[xmlns=\"urn:xmpp:jingle:transports:ice-udp:1\"]');\n if (tmp.length) {\n if (tmp.attr('ufrag')) {\n media += SDPUtil.build_iceufrag(tmp.attr('ufrag')) + '\\r\\n';\n }\n if (tmp.attr('pwd')) {\n media += SDPUtil.build_icepwd(tmp.attr('pwd')) + '\\r\\n';\n }\n tmp.find('>fingerprint').each(function () {\n // FIXME: check namespace at some point\n media += 'a=fingerprint:' + this.getAttribute('hash');\n media += ' ' + $(this).text();\n media += '\\r\\n';\n if (this.getAttribute('setup')) {\n media += 'a=setup:' + this.getAttribute('setup') + '\\r\\n';\n }\n });\n }\n switch (content.attr('senders')) {\n case 'initiator':\n media += 'a=sendonly\\r\\n';\n break;\n case 'responder':\n media += 'a=recvonly\\r\\n';\n break;\n case 'none':\n media += 'a=inactive\\r\\n';\n break;\n case 'both':\n media += 'a=sendrecv\\r\\n';\n break;\n }\n media += 'a=mid:' + content.attr('name') + '\\r\\n';\n\n // \n // see http://code.google.com/p/libjingle/issues/detail?id=309 -- no spec though\n // and http://mail.jabber.org/pipermail/jingle/2011-December/001761.html\n if (desc.find('rtcp-mux').length) {\n media += 'a=rtcp-mux\\r\\n';\n }\n\n if (desc.find('encryption').length) {\n desc.find('encryption>crypto').each(function () {\n media += 'a=crypto:' + this.getAttribute('tag');\n media += ' ' + this.getAttribute('crypto-suite');\n media += ' ' + this.getAttribute('key-params');\n if (this.getAttribute('session-params')) {\n media += ' ' + this.getAttribute('session-params');\n }\n media += '\\r\\n';\n });\n }\n desc.find('payload-type').each(function () {\n media += SDPUtil.build_rtpmap(this) + '\\r\\n';\n if ($(this).find('>parameter').length) {\n media += 'a=fmtp:' + this.getAttribute('id') + ' ';\n media += $(this).find('parameter').map(function () {\n return (this.getAttribute('name')\n ? (this.getAttribute('name') + '=') : '') +\n this.getAttribute('value');\n }).get().join('; ');\n media += '\\r\\n';\n }\n // xep-0293\n media += self.rtcpFbFromJingle($(this), this.getAttribute('id'));\n });\n\n // xep-0293\n media += self.rtcpFbFromJingle(desc, '*');\n\n // xep-0294\n tmp = desc.find('>rtp-hdrext[xmlns=\"urn:xmpp:jingle:apps:rtp:rtp-hdrext:0\"]');\n tmp.each(function () {\n media += 'a=extmap:' + this.getAttribute('id') + ' ' + this.getAttribute('uri') + '\\r\\n';\n });\n\n content.find('>transport[xmlns=\"urn:xmpp:jingle:transports:ice-udp:1\"]>candidate').each(function () {\n var protocol = this.getAttribute('protocol');\n protocol = (typeof protocol === 'string') ? protocol.toLowerCase(): '';\n\n if ((self.removeTcpCandidates && protocol === 'tcp') ||\n (self.removeUdpCandidates && protocol === 'udp')) {\n return;\n }\n\n media += SDPUtil.candidateFromJingle(this);\n });\n\n // XEP-0339 handle ssrc-group attributes\n content.find('description>ssrc-group[xmlns=\"urn:xmpp:jingle:apps:rtp:ssma:0\"]').each(function() {\n var semantics = this.getAttribute('semantics');\n var ssrcs = $(this).find('>source').map(function() {\n return this.getAttribute('ssrc');\n }).get();\n\n if (ssrcs.length) {\n media += 'a=ssrc-group:' + semantics + ' ' + ssrcs.join(' ') + '\\r\\n';\n }\n });\n\n tmp = content.find('description>source[xmlns=\"urn:xmpp:jingle:apps:rtp:ssma:0\"]');\n tmp.each(function () {\n var ssrc = this.getAttribute('ssrc');\n $(this).find('>parameter').each(function () {\n var name = this.getAttribute('name');\n var value = this.getAttribute('value');\n value = SDPUtil.filter_special_chars(value);\n media += 'a=ssrc:' + ssrc + ' ' + name;\n if (value && value.length)\n media += ':' + value;\n media += '\\r\\n';\n });\n });\n\n return media;\n};\n\n\nmodule.exports = SDP;\n", + "var SDPUtil = require(\"./SDPUtil\");\n\nfunction SDPDiffer(mySDP, otherSDP)\n{\n this.mySDP = mySDP;\n this.otherSDP = otherSDP;\n}\n\n/**\n * Returns map of MediaChannel that contains media contained in\n * 'mySDP', but not contained in 'otherSdp'. Mapped by channel idx.\n */\nSDPDiffer.prototype.getNewMedia = function() {\n\n // this could be useful in Array.prototype.\n function arrayEquals(array) {\n // if the other array is a falsy value, return\n if (!array)\n return false;\n\n // compare lengths - can save a lot of time\n if (this.length != array.length)\n return false;\n\n for (var i = 0, l=this.length; i < l; i++) {\n // Check if we have nested arrays\n if (this[i] instanceof Array && array[i] instanceof Array) {\n // recurse into the nested arrays\n if (!this[i].equals(array[i]))\n return false;\n }\n else if (this[i] != array[i]) {\n // Warning - two different object instances will never be\n // equal: {x:20} != {x:20}\n return false;\n }\n }\n return true;\n }\n\n var myMedias = this.mySDP.getMediaSsrcMap();\n var othersMedias = this.otherSDP.getMediaSsrcMap();\n var newMedia = {};\n Object.keys(othersMedias).forEach(function(othersMediaIdx) {\n var myMedia = myMedias[othersMediaIdx];\n var othersMedia = othersMedias[othersMediaIdx];\n if(!myMedia && othersMedia) {\n // Add whole channel\n newMedia[othersMediaIdx] = othersMedia;\n return;\n }\n // Look for new ssrcs across the channel\n Object.keys(othersMedia.ssrcs).forEach(function(ssrc) {\n if(Object.keys(myMedia.ssrcs).indexOf(ssrc) === -1) {\n // Allocate channel if we've found ssrc that doesn't exist in\n // our channel\n if(!newMedia[othersMediaIdx]){\n newMedia[othersMediaIdx] = {\n mediaindex: othersMedia.mediaindex,\n mid: othersMedia.mid,\n ssrcs: {},\n ssrcGroups: []\n };\n }\n newMedia[othersMediaIdx].ssrcs[ssrc] = othersMedia.ssrcs[ssrc];\n }\n });\n\n // Look for new ssrc groups across the channels\n othersMedia.ssrcGroups.forEach(function(otherSsrcGroup){\n\n // try to match the other ssrc-group with an ssrc-group of ours\n var matched = false;\n for (var i = 0; i < myMedia.ssrcGroups.length; i++) {\n var mySsrcGroup = myMedia.ssrcGroups[i];\n if (otherSsrcGroup.semantics == mySsrcGroup.semantics &&\n arrayEquals.apply(otherSsrcGroup.ssrcs,\n [mySsrcGroup.ssrcs])) {\n\n matched = true;\n break;\n }\n }\n\n if (!matched) {\n // Allocate channel if we've found an ssrc-group that doesn't\n // exist in our channel\n\n if(!newMedia[othersMediaIdx]){\n newMedia[othersMediaIdx] = {\n mediaindex: othersMedia.mediaindex,\n mid: othersMedia.mid,\n ssrcs: {},\n ssrcGroups: []\n };\n }\n newMedia[othersMediaIdx].ssrcGroups.push(otherSsrcGroup);\n }\n });\n });\n return newMedia;\n};\n\n/**\n * TODO: document!\n */\nSDPDiffer.prototype.toJingle = function(modify) {\n var sdpMediaSsrcs = this.getNewMedia();\n\n var modified = false;\n Object.keys(sdpMediaSsrcs).forEach(function(mediaindex){\n modified = true;\n var media = sdpMediaSsrcs[mediaindex];\n modify.c('content', {name: media.mid});\n\n modify.c('description',\n {xmlns:'urn:xmpp:jingle:apps:rtp:1', media: media.mid});\n // FIXME: not completely sure this operates on blocks and / or handles\n // different ssrcs correctly\n // generate sources from lines\n Object.keys(media.ssrcs).forEach(function(ssrcNum) {\n var mediaSsrc = media.ssrcs[ssrcNum];\n modify.c('source', { xmlns: 'urn:xmpp:jingle:apps:rtp:ssma:0' });\n modify.attrs({ssrc: mediaSsrc.ssrc});\n // iterate over ssrc lines\n mediaSsrc.lines.forEach(function (line) {\n var idx = line.indexOf(' ');\n var kv = line.substr(idx + 1);\n modify.c('parameter');\n if (kv.indexOf(':') == -1) {\n modify.attrs({ name: kv });\n } else {\n var nv = kv.split(':', 2);\n var name = nv[0];\n var value = SDPUtil.filter_special_chars(nv[1]);\n modify.attrs({ name: name });\n modify.attrs({ value: value });\n }\n modify.up(); // end of parameter\n });\n modify.up(); // end of source\n });\n\n // generate source groups from lines\n media.ssrcGroups.forEach(function(ssrcGroup) {\n if (ssrcGroup.ssrcs.length) {\n\n modify.c('ssrc-group', {\n semantics: ssrcGroup.semantics,\n xmlns: 'urn:xmpp:jingle:apps:rtp:ssma:0'\n });\n\n ssrcGroup.ssrcs.forEach(function (ssrc) {\n modify.c('source', { ssrc: ssrc })\n .up(); // end of source\n });\n modify.up(); // end of ssrc-group\n }\n });\n\n modify.up(); // end of description\n modify.up(); // end of content\n });\n\n return modified;\n};\n\nmodule.exports = SDPDiffer;", + "var logger = require(\"jitsi-meet-logger\").getLogger(__filename);\nvar RTCBrowserType = require(\"../RTC/RTCBrowserType\");\n\n\nSDPUtil = {\n filter_special_chars: function (text) {\n return text.replace(/[\\\\\\/\\{,\\}\\+]/g, \"\");\n },\n iceparams: function (mediadesc, sessiondesc) {\n var data = null;\n if (SDPUtil.find_line(mediadesc, 'a=ice-ufrag:', sessiondesc) &&\n SDPUtil.find_line(mediadesc, 'a=ice-pwd:', sessiondesc)) {\n data = {\n ufrag: SDPUtil.parse_iceufrag(SDPUtil.find_line(mediadesc, 'a=ice-ufrag:', sessiondesc)),\n pwd: SDPUtil.parse_icepwd(SDPUtil.find_line(mediadesc, 'a=ice-pwd:', sessiondesc))\n };\n }\n return data;\n },\n parse_iceufrag: function (line) {\n return line.substring(12);\n },\n build_iceufrag: function (frag) {\n return 'a=ice-ufrag:' + frag;\n },\n parse_icepwd: function (line) {\n return line.substring(10);\n },\n build_icepwd: function (pwd) {\n return 'a=ice-pwd:' + pwd;\n },\n parse_mid: function (line) {\n return line.substring(6);\n },\n parse_mline: function (line) {\n var parts = line.substring(2).split(' '),\n data = {};\n data.media = parts.shift();\n data.port = parts.shift();\n data.proto = parts.shift();\n if (parts[parts.length - 1] === '') { // trailing whitespace\n parts.pop();\n }\n data.fmt = parts;\n return data;\n },\n build_mline: function (mline) {\n return 'm=' + mline.media + ' ' + mline.port + ' ' + mline.proto + ' ' + mline.fmt.join(' ');\n },\n parse_rtpmap: function (line) {\n var parts = line.substring(9).split(' '),\n data = {};\n data.id = parts.shift();\n parts = parts[0].split('/');\n data.name = parts.shift();\n data.clockrate = parts.shift();\n data.channels = parts.length ? parts.shift() : '1';\n return data;\n },\n /**\n * Parses SDP line \"a=sctpmap:...\" and extracts SCTP port from it.\n * @param line eg. \"a=sctpmap:5000 webrtc-datachannel\"\n * @returns [SCTP port number, protocol, streams]\n */\n parse_sctpmap: function (line)\n {\n var parts = line.substring(10).split(' ');\n var sctpPort = parts[0];\n var protocol = parts[1];\n // Stream count is optional\n var streamCount = parts.length > 2 ? parts[2] : null;\n return [sctpPort, protocol, streamCount];// SCTP port\n },\n build_rtpmap: function (el) {\n var line = 'a=rtpmap:' + el.getAttribute('id') + ' ' + el.getAttribute('name') + '/' + el.getAttribute('clockrate');\n if (el.getAttribute('channels') && el.getAttribute('channels') != '1') {\n line += '/' + el.getAttribute('channels');\n }\n return line;\n },\n parse_crypto: function (line) {\n var parts = line.substring(9).split(' '),\n data = {};\n data.tag = parts.shift();\n data['crypto-suite'] = parts.shift();\n data['key-params'] = parts.shift();\n if (parts.length) {\n data['session-params'] = parts.join(' ');\n }\n return data;\n },\n parse_fingerprint: function (line) { // RFC 4572\n var parts = line.substring(14).split(' '),\n data = {};\n data.hash = parts.shift();\n data.fingerprint = parts.shift();\n // TODO assert that fingerprint satisfies 2UHEX *(\":\" 2UHEX) ?\n return data;\n },\n parse_fmtp: function (line) {\n var parts = line.split(' '),\n i, key, value,\n data = [];\n parts.shift();\n parts = parts.join(' ').split(';');\n for (i = 0; i < parts.length; i++) {\n key = parts[i].split('=')[0];\n while (key.length && key[0] == ' ') {\n key = key.substring(1);\n }\n value = parts[i].split('=')[1];\n if (key && value) {\n data.push({name: key, value: value});\n } else if (key) {\n // rfc 4733 (DTMF) style stuff\n data.push({name: '', value: key});\n }\n }\n return data;\n },\n parse_icecandidate: function (line) {\n var candidate = {},\n elems = line.split(' ');\n candidate.foundation = elems[0].substring(12);\n candidate.component = elems[1];\n candidate.protocol = elems[2].toLowerCase();\n candidate.priority = elems[3];\n candidate.ip = elems[4];\n candidate.port = elems[5];\n // elems[6] => \"typ\"\n candidate.type = elems[7];\n candidate.generation = 0; // default value, may be overwritten below\n for (var i = 8; i < elems.length; i += 2) {\n switch (elems[i]) {\n case 'raddr':\n candidate['rel-addr'] = elems[i + 1];\n break;\n case 'rport':\n candidate['rel-port'] = elems[i + 1];\n break;\n case 'generation':\n candidate.generation = elems[i + 1];\n break;\n case 'tcptype':\n candidate.tcptype = elems[i + 1];\n break;\n default: // TODO\n logger.log('parse_icecandidate not translating \"' + elems[i] + '\" = \"' + elems[i + 1] + '\"');\n }\n }\n candidate.network = '1';\n candidate.id = Math.random().toString(36).substr(2, 10); // not applicable to SDP -- FIXME: should be unique, not just random\n return candidate;\n },\n build_icecandidate: function (cand) {\n var line = ['a=candidate:' + cand.foundation, cand.component, cand.protocol, cand.priority, cand.ip, cand.port, 'typ', cand.type].join(' ');\n line += ' ';\n switch (cand.type) {\n case 'srflx':\n case 'prflx':\n case 'relay':\n if (cand.hasOwnAttribute('rel-addr') && cand.hasOwnAttribute('rel-port')) {\n line += 'raddr';\n line += ' ';\n line += cand['rel-addr'];\n line += ' ';\n line += 'rport';\n line += ' ';\n line += cand['rel-port'];\n line += ' ';\n }\n break;\n }\n if (cand.hasOwnAttribute('tcptype')) {\n line += 'tcptype';\n line += ' ';\n line += cand.tcptype;\n line += ' ';\n }\n line += 'generation';\n line += ' ';\n line += cand.hasOwnAttribute('generation') ? cand.generation : '0';\n return line;\n },\n parse_ssrc: function (desc) {\n // proprietary mapping of a=ssrc lines\n // TODO: see \"Jingle RTP Source Description\" by Juberti and P. Thatcher on google docs\n // and parse according to that\n var lines = desc.split('\\r\\n'),\n data = {};\n for (var i = 0; i < lines.length; i++) {\n if (lines[i].substring(0, 7) == 'a=ssrc:') {\n var idx = lines[i].indexOf(' ');\n data[lines[i].substr(idx + 1).split(':', 2)[0]] = lines[i].substr(idx + 1).split(':', 2)[1];\n }\n }\n return data;\n },\n parse_rtcpfb: function (line) {\n var parts = line.substr(10).split(' ');\n var data = {};\n data.pt = parts.shift();\n data.type = parts.shift();\n data.params = parts;\n return data;\n },\n parse_extmap: function (line) {\n var parts = line.substr(9).split(' ');\n var data = {};\n data.value = parts.shift();\n if (data.value.indexOf('/') != -1) {\n data.direction = data.value.substr(data.value.indexOf('/') + 1);\n data.value = data.value.substr(0, data.value.indexOf('/'));\n } else {\n data.direction = 'both';\n }\n data.uri = parts.shift();\n data.params = parts;\n return data;\n },\n find_line: function (haystack, needle, sessionpart) {\n var lines = haystack.split('\\r\\n');\n for (var i = 0; i < lines.length; i++) {\n if (lines[i].substring(0, needle.length) == needle) {\n return lines[i];\n }\n }\n if (!sessionpart) {\n return false;\n }\n // search session part\n lines = sessionpart.split('\\r\\n');\n for (var j = 0; j < lines.length; j++) {\n if (lines[j].substring(0, needle.length) == needle) {\n return lines[j];\n }\n }\n return false;\n },\n find_lines: function (haystack, needle, sessionpart) {\n var lines = haystack.split('\\r\\n'),\n needles = [];\n for (var i = 0; i < lines.length; i++) {\n if (lines[i].substring(0, needle.length) == needle)\n needles.push(lines[i]);\n }\n if (needles.length || !sessionpart) {\n return needles;\n }\n // search session part\n lines = sessionpart.split('\\r\\n');\n for (var j = 0; j < lines.length; j++) {\n if (lines[j].substring(0, needle.length) == needle) {\n needles.push(lines[j]);\n }\n }\n return needles;\n },\n candidateToJingle: function (line) {\n // a=candidate:2979166662 1 udp 2113937151 192.168.2.100 57698 typ host generation 0\n // \n if (line.indexOf('candidate:') === 0) {\n line = 'a=' + line;\n } else if (line.substring(0, 12) != 'a=candidate:') {\n logger.log('parseCandidate called with a line that is not a candidate line');\n logger.log(line);\n return null;\n }\n if (line.substring(line.length - 2) == '\\r\\n') // chomp it\n line = line.substring(0, line.length - 2);\n var candidate = {},\n elems = line.split(' '),\n i;\n if (elems[6] != 'typ') {\n logger.log('did not find typ in the right place');\n logger.log(line);\n return null;\n }\n candidate.foundation = elems[0].substring(12);\n candidate.component = elems[1];\n candidate.protocol = elems[2].toLowerCase();\n candidate.priority = elems[3];\n candidate.ip = elems[4];\n candidate.port = elems[5];\n // elems[6] => \"typ\"\n candidate.type = elems[7];\n\n candidate.generation = '0'; // default, may be overwritten below\n for (i = 8; i < elems.length; i += 2) {\n switch (elems[i]) {\n case 'raddr':\n candidate['rel-addr'] = elems[i + 1];\n break;\n case 'rport':\n candidate['rel-port'] = elems[i + 1];\n break;\n case 'generation':\n candidate.generation = elems[i + 1];\n break;\n case 'tcptype':\n candidate.tcptype = elems[i + 1];\n break;\n default: // TODO\n logger.log('not translating \"' + elems[i] + '\" = \"' + elems[i + 1] + '\"');\n }\n }\n candidate.network = '1';\n candidate.id = Math.random().toString(36).substr(2, 10); // not applicable to SDP -- FIXME: should be unique, not just random\n return candidate;\n },\n candidateFromJingle: function (cand) {\n var line = 'a=candidate:';\n line += cand.getAttribute('foundation');\n line += ' ';\n line += cand.getAttribute('component');\n line += ' ';\n\n var protocol = cand.getAttribute('protocol');\n // use tcp candidates for FF\n if (RTCBrowserType.isFirefox() && protocol.toLowerCase() == 'ssltcp') {\n protocol = 'tcp';\n }\n\n line += protocol; //.toUpperCase(); // chrome M23 doesn't like this\n line += ' ';\n line += cand.getAttribute('priority');\n line += ' ';\n line += cand.getAttribute('ip');\n line += ' ';\n line += cand.getAttribute('port');\n line += ' ';\n line += 'typ';\n line += ' ' + cand.getAttribute('type');\n line += ' ';\n switch (cand.getAttribute('type')) {\n case 'srflx':\n case 'prflx':\n case 'relay':\n if (cand.getAttribute('rel-addr') && cand.getAttribute('rel-port')) {\n line += 'raddr';\n line += ' ';\n line += cand.getAttribute('rel-addr');\n line += ' ';\n line += 'rport';\n line += ' ';\n line += cand.getAttribute('rel-port');\n line += ' ';\n }\n break;\n }\n if (protocol.toLowerCase() == 'tcp') {\n line += 'tcptype';\n line += ' ';\n line += cand.getAttribute('tcptype');\n line += ' ';\n }\n line += 'generation';\n line += ' ';\n line += cand.getAttribute('generation') || '0';\n return line + '\\r\\n';\n }\n};\n\nmodule.exports = SDPUtil;\n", + "/* global $ */\nvar RTC = require('../RTC/RTC');\n\nvar logger = require(\"jitsi-meet-logger\").getLogger(__filename);\nvar RTCBrowserType = require(\"../RTC/RTCBrowserType.js\");\nvar XMPPEvents = require(\"../../service/xmpp/XMPPEvents\");\nvar SSRCReplacement = require(\"./LocalSSRCReplacement\");\n\nfunction TraceablePeerConnection(ice_config, constraints, session) {\n var self = this;\n this.session = session;\n var RTCPeerConnectionType = null;\n if (RTCBrowserType.isFirefox()) {\n RTCPeerConnectionType = mozRTCPeerConnection;\n } else if (RTCBrowserType.isTemasysPluginUsed()) {\n RTCPeerConnectionType = RTCPeerConnection;\n } else {\n RTCPeerConnectionType = webkitRTCPeerConnection;\n }\n this.peerconnection = new RTCPeerConnectionType(ice_config, constraints);\n this.updateLog = [];\n this.stats = {};\n this.statsinterval = null;\n this.maxstats = 0; // limit to 300 values, i.e. 5 minutes; set to 0 to disable\n var Interop = require('sdp-interop').Interop;\n this.interop = new Interop();\n var Simulcast = require('sdp-simulcast');\n this.simulcast = new Simulcast({numOfLayers: 3, explodeRemoteSimulcast: false});\n\n // override as desired\n this.trace = function (what, info) {\n /*logger.warn('WTRACE', what, info);\n if (info && RTCBrowserType.isIExplorer()) {\n if (info.length > 1024) {\n logger.warn('WTRACE', what, info.substr(1024));\n }\n if (info.length > 2048) {\n logger.warn('WTRACE', what, info.substr(2048));\n }\n }*/\n self.updateLog.push({\n time: new Date(),\n type: what,\n value: info || \"\"\n });\n };\n this.onicecandidate = null;\n this.peerconnection.onicecandidate = function (event) {\n // FIXME: this causes stack overflow with Temasys Plugin\n if (!RTCBrowserType.isTemasysPluginUsed())\n self.trace('onicecandidate', JSON.stringify(event.candidate, null, ' '));\n if (self.onicecandidate !== null) {\n self.onicecandidate(event);\n }\n };\n this.onaddstream = null;\n this.peerconnection.onaddstream = function (event) {\n self.trace('onaddstream', event.stream.id);\n if (self.onaddstream !== null) {\n self.onaddstream(event);\n }\n };\n this.onremovestream = null;\n this.peerconnection.onremovestream = function (event) {\n self.trace('onremovestream', event.stream.id);\n if (self.onremovestream !== null) {\n self.onremovestream(event);\n }\n };\n this.onsignalingstatechange = null;\n this.peerconnection.onsignalingstatechange = function (event) {\n self.trace('onsignalingstatechange', self.signalingState);\n if (self.onsignalingstatechange !== null) {\n self.onsignalingstatechange(event);\n }\n };\n this.oniceconnectionstatechange = null;\n this.peerconnection.oniceconnectionstatechange = function (event) {\n self.trace('oniceconnectionstatechange', self.iceConnectionState);\n if (self.oniceconnectionstatechange !== null) {\n self.oniceconnectionstatechange(event);\n }\n };\n this.onnegotiationneeded = null;\n this.peerconnection.onnegotiationneeded = function (event) {\n self.trace('onnegotiationneeded');\n if (self.onnegotiationneeded !== null) {\n self.onnegotiationneeded(event);\n }\n };\n self.ondatachannel = null;\n this.peerconnection.ondatachannel = function (event) {\n self.trace('ondatachannel', event);\n if (self.ondatachannel !== null) {\n self.ondatachannel(event);\n }\n };\n // XXX: do all non-firefox browsers which we support also support this?\n if (!RTCBrowserType.isFirefox() && this.maxstats) {\n this.statsinterval = window.setInterval(function() {\n self.peerconnection.getStats(function(stats) {\n var results = stats.result();\n var now = new Date();\n for (var i = 0; i < results.length; ++i) {\n results[i].names().forEach(function (name) {\n var id = results[i].id + '-' + name;\n if (!self.stats[id]) {\n self.stats[id] = {\n startTime: now,\n endTime: now,\n values: [],\n times: []\n };\n }\n self.stats[id].values.push(results[i].stat(name));\n self.stats[id].times.push(now.getTime());\n if (self.stats[id].values.length > self.maxstats) {\n self.stats[id].values.shift();\n self.stats[id].times.shift();\n }\n self.stats[id].endTime = now;\n });\n }\n });\n\n }, 1000);\n }\n}\n\n/**\n * Returns a string representation of a SessionDescription object.\n */\nvar dumpSDP = function(description) {\n if (typeof description === 'undefined' || description == null) {\n return '';\n }\n\n return 'type: ' + description.type + '\\r\\n' + description.sdp;\n};\n\n/**\n * Takes a SessionDescription object and returns a \"normalized\" version.\n * Currently it only takes care of ordering the a=ssrc lines.\n */\nvar normalizePlanB = function(desc) {\n if (typeof desc !== 'object' || desc === null ||\n typeof desc.sdp !== 'string') {\n logger.warn('An empty description was passed as an argument.');\n return desc;\n }\n\n var transform = require('sdp-transform');\n var session = transform.parse(desc.sdp);\n\n if (typeof session !== 'undefined' && typeof session.media !== 'undefined' &&\n Array.isArray(session.media)) {\n session.media.forEach(function (mLine) {\n\n // Chrome appears to be picky about the order in which a=ssrc lines\n // are listed in an m-line when rtx is enabled (and thus there are\n // a=ssrc-group lines with FID semantics). Specifically if we have\n // \"a=ssrc-group:FID S1 S2\" and the \"a=ssrc:S2\" lines appear before\n // the \"a=ssrc:S1\" lines, SRD fails.\n // So, put SSRC which appear as the first SSRC in an FID ssrc-group\n // first.\n var firstSsrcs = [];\n var newSsrcLines = [];\n\n if (typeof mLine.ssrcGroups !== 'undefined' && Array.isArray(mLine.ssrcGroups)) {\n mLine.ssrcGroups.forEach(function (group) {\n if (typeof group.semantics !== 'undefined' &&\n group.semantics === 'FID') {\n if (typeof group.ssrcs !== 'undefined') {\n firstSsrcs.push(Number(group.ssrcs.split(' ')[0]));\n }\n }\n });\n }\n\n if (typeof mLine.ssrcs !== 'undefined' && Array.isArray(mLine.ssrcs)) {\n var i;\n for (i = 0; i Plan B\n // transformation.\n desc = SSRCReplacement.mungeLocalVideoSSRC(desc);\n\n this.trace('getLocalDescription::preTransform', dumpSDP(desc));\n\n // if we're running on FF, transform to Plan B first.\n if (RTCBrowserType.usesUnifiedPlan()) {\n desc = this.interop.toPlanB(desc);\n this.trace('getLocalDescription::postTransform (Plan B)', dumpSDP(desc));\n }\n return desc;\n },\n remoteDescription: function() {\n var desc = this.peerconnection.remoteDescription;\n this.trace('getRemoteDescription::preTransform', dumpSDP(desc));\n\n // if we're running on FF, transform to Plan B first.\n if (RTCBrowserType.usesUnifiedPlan()) {\n desc = this.interop.toPlanB(desc);\n this.trace('getRemoteDescription::postTransform (Plan B)', dumpSDP(desc));\n }\n return desc;\n }\n};\nObject.keys(getters).forEach(function (prop) {\n Object.defineProperty(\n TraceablePeerConnection.prototype,\n prop, {\n get: getters[prop]\n }\n );\n});\n\nTraceablePeerConnection.prototype.addStream = function (stream) {\n this.trace('addStream', stream.id);\n try\n {\n this.peerconnection.addStream(stream);\n }\n catch (e)\n {\n logger.error(e);\n }\n};\n\nTraceablePeerConnection.prototype.removeStream = function (stream, stopStreams) {\n this.trace('removeStream', stream.id);\n if(stopStreams) {\n RTC.stopMediaStream(stream);\n }\n\n try {\n // FF doesn't support this yet.\n if (this.peerconnection.removeStream)\n this.peerconnection.removeStream(stream);\n } catch (e) {\n logger.error(e);\n }\n};\n\nTraceablePeerConnection.prototype.createDataChannel = function (label, opts) {\n this.trace('createDataChannel', label, opts);\n return this.peerconnection.createDataChannel(label, opts);\n};\n\nTraceablePeerConnection.prototype.setLocalDescription\n = function (description, successCallback, failureCallback) {\n this.trace('setLocalDescription::preTransform', dumpSDP(description));\n // if we're running on FF, transform to Plan A first.\n if (RTCBrowserType.usesUnifiedPlan()) {\n description = this.interop.toUnifiedPlan(description);\n this.trace('setLocalDescription::postTransform (Plan A)', dumpSDP(description));\n }\n\n var self = this;\n this.peerconnection.setLocalDescription(description,\n function () {\n self.trace('setLocalDescriptionOnSuccess');\n successCallback();\n },\n function (err) {\n self.trace('setLocalDescriptionOnFailure', err);\n failureCallback(err);\n }\n );\n /*\n if (this.statsinterval === null && this.maxstats > 0) {\n // start gathering stats\n }\n */\n};\n\nTraceablePeerConnection.prototype.setRemoteDescription\n = function (description, successCallback, failureCallback) {\n this.trace('setRemoteDescription::preTransform', dumpSDP(description));\n // TODO the focus should squeze or explode the remote simulcast\n description = this.simulcast.mungeRemoteDescription(description);\n this.trace('setRemoteDescription::postTransform (simulcast)', dumpSDP(description));\n\n // if we're running on FF, transform to Plan A first.\n if (RTCBrowserType.usesUnifiedPlan()) {\n description = this.interop.toUnifiedPlan(description);\n this.trace('setRemoteDescription::postTransform (Plan A)', dumpSDP(description));\n }\n\n if (RTCBrowserType.usesPlanB()) {\n description = normalizePlanB(description);\n }\n\n var self = this;\n this.peerconnection.setRemoteDescription(description,\n function () {\n self.trace('setRemoteDescriptionOnSuccess');\n successCallback();\n },\n function (err) {\n self.trace('setRemoteDescriptionOnFailure', err);\n failureCallback(err);\n }\n );\n /*\n if (this.statsinterval === null && this.maxstats > 0) {\n // start gathering stats\n }\n */\n};\n\nTraceablePeerConnection.prototype.close = function () {\n this.trace('stop');\n if (this.statsinterval !== null) {\n window.clearInterval(this.statsinterval);\n this.statsinterval = null;\n }\n this.peerconnection.close();\n};\n\nTraceablePeerConnection.prototype.createOffer\n = function (successCallback, failureCallback, constraints) {\n var self = this;\n this.trace('createOffer', JSON.stringify(constraints, null, ' '));\n this.peerconnection.createOffer(\n function (offer) {\n self.trace('createOfferOnSuccess::preTransform', dumpSDP(offer));\n // NOTE this is not tested because in meet the focus generates the\n // offer.\n\n // if we're running on FF, transform to Plan B first.\n if (RTCBrowserType.usesUnifiedPlan()) {\n offer = self.interop.toPlanB(offer);\n self.trace('createOfferOnSuccess::postTransform (Plan B)', dumpSDP(offer));\n }\n\n offer = SSRCReplacement.mungeLocalVideoSSRC(offer);\n\n if (self.session.room.options.enableSimulcast && self.simulcast.isSupported()) {\n offer = self.simulcast.mungeLocalDescription(offer);\n self.trace('createOfferOnSuccess::postTransform (simulcast)', dumpSDP(offer));\n }\n successCallback(offer);\n },\n function(err) {\n self.trace('createOfferOnFailure', err);\n failureCallback(err);\n },\n constraints\n );\n};\n\nTraceablePeerConnection.prototype.createAnswer\n = function (successCallback, failureCallback, constraints) {\n var self = this;\n this.trace('createAnswer', JSON.stringify(constraints, null, ' '));\n this.peerconnection.createAnswer(\n function (answer) {\n self.trace('createAnswerOnSuccess::preTransform', dumpSDP(answer));\n // if we're running on FF, transform to Plan A first.\n if (RTCBrowserType.usesUnifiedPlan()) {\n answer = self.interop.toPlanB(answer);\n self.trace('createAnswerOnSuccess::postTransform (Plan B)', dumpSDP(answer));\n }\n\n // munge local video SSRC\n answer = SSRCReplacement.mungeLocalVideoSSRC(answer);\n\n if (self.session.room.options.enableSimulcast && self.simulcast.isSupported()) {\n answer = self.simulcast.mungeLocalDescription(answer);\n self.trace('createAnswerOnSuccess::postTransform (simulcast)', dumpSDP(answer));\n }\n successCallback(answer);\n },\n function(err) {\n self.trace('createAnswerOnFailure', err);\n failureCallback(err);\n },\n constraints\n );\n};\n\nTraceablePeerConnection.prototype.addIceCandidate\n = function (candidate, successCallback, failureCallback) {\n //var self = this;\n this.trace('addIceCandidate', JSON.stringify(candidate, null, ' '));\n this.peerconnection.addIceCandidate(candidate);\n /* maybe later\n this.peerconnection.addIceCandidate(candidate,\n function () {\n self.trace('addIceCandidateOnSuccess');\n successCallback();\n },\n function (err) {\n self.trace('addIceCandidateOnFailure', err);\n failureCallback(err);\n }\n );\n */\n};\n\nTraceablePeerConnection.prototype.getStats = function(callback, errback) {\n // TODO: Is this the correct way to handle Opera, Temasys?\n if (RTCBrowserType.isFirefox()) {\n // ignore for now...\n if(!errback)\n errback = function () {};\n this.peerconnection.getStats(null, callback, errback);\n } else {\n this.peerconnection.getStats(callback);\n }\n};\n\nmodule.exports = TraceablePeerConnection;\n", + "/* global $, $iq, Promise, Strophe */\n\nvar logger = require(\"jitsi-meet-logger\").getLogger(__filename);\nvar XMPPEvents = require(\"../../service/xmpp/XMPPEvents\");\nvar Settings = require(\"../settings/Settings\");\n\nvar AuthenticationEvents\n = require(\"../../service/authentication/AuthenticationEvents\");\n\nfunction createExpBackoffTimer(step) {\n var count = 1;\n return function (reset) {\n // Reset call\n if (reset) {\n count = 1;\n return;\n }\n // Calculate next timeout\n var timeout = Math.pow(2, count - 1);\n count += 1;\n return timeout * step;\n };\n}\n\n\n\n\n\nfunction Moderator(roomName, xmpp, emitter) {\n this.roomName = roomName;\n this.xmppService = xmpp;\n this.getNextTimeout = createExpBackoffTimer(1000);\n this.getNextErrorTimeout = createExpBackoffTimer(1000);\n // External authentication stuff\n this.externalAuthEnabled = false;\n this.settings = new Settings(roomName);\n // Sip gateway can be enabled by configuring Jigasi host in config.js or\n // it will be enabled automatically if focus detects the component through\n // service discovery.\n this.sipGatewayEnabled = this.xmppService.options.hosts &&\n this.xmppService.options.hosts.call_control !== undefined;\n\n this.eventEmitter = emitter;\n\n this.connection = this.xmppService.connection;\n this.focusUserJid;\n //FIXME:\n // Message listener that talks to POPUP window\n function listener(event) {\n if (event.data && event.data.sessionId) {\n if (event.origin !== window.location.origin) {\n logger.warn(\"Ignoring sessionId from different origin: \" +\n event.origin);\n return;\n }\n localStorage.setItem('sessionId', event.data.sessionId);\n // After popup is closed we will authenticate\n }\n }\n // Register\n if (window.addEventListener) {\n window.addEventListener(\"message\", listener, false);\n } else {\n window.attachEvent(\"onmessage\", listener);\n }\n}\n\nModerator.prototype.isExternalAuthEnabled = function () {\n return this.externalAuthEnabled;\n};\n\nModerator.prototype.isSipGatewayEnabled = function () {\n return this.sipGatewayEnabled;\n};\n\n\nModerator.prototype.onMucMemberLeft = function (jid) {\n logger.info(\"Someone left is it focus ? \" + jid);\n var resource = Strophe.getResourceFromJid(jid);\n if (resource === 'focus' && !this.xmppService.sessionTerminated) {\n logger.info(\n \"Focus has left the room - leaving conference\");\n //hangUp();\n // We'd rather reload to have everything re-initialized\n //FIXME: show some message before reload\n this.eventEmitter.emit(XMPPEvents.FOCUS_LEFT);\n }\n};\n\n\nModerator.prototype.setFocusUserJid = function (focusJid) {\n if (!this.focusUserJid) {\n this.focusUserJid = focusJid;\n logger.info(\"Focus jid set to: \" + this.focusUserJid);\n }\n};\n\n\nModerator.prototype.getFocusUserJid = function () {\n return this.focusUserJid;\n};\n\nModerator.prototype.getFocusComponent = function () {\n // Get focus component address\n var focusComponent = this.xmppService.options.hosts.focus;\n // If not specified use default: 'focus.domain'\n if (!focusComponent) {\n focusComponent = 'focus.' + this.xmppService.options.hosts.domain;\n }\n return focusComponent;\n};\n\nModerator.prototype.createConferenceIq = function () {\n // Generate create conference IQ\n var elem = $iq({to: this.getFocusComponent(), type: 'set'});\n\n // Session Id used for authentication\n var sessionId = localStorage.getItem('sessionId');\n var machineUID = this.settings.getSettings().uid;\n\n logger.info(\n \"Session ID: \" + sessionId + \" machine UID: \" + machineUID);\n\n elem.c('conference', {\n xmlns: 'http://jitsi.org/protocol/focus',\n room: this.roomName,\n 'machine-uid': machineUID\n });\n\n if (sessionId) {\n elem.attrs({ 'session-id': sessionId});\n }\n if (this.xmppService.options.hosts.bridge !== undefined) {\n elem.c(\n 'property', {\n name: 'bridge',\n value: this.xmppService.options.hosts.bridge\n }).up();\n }\n if (this.xmppService.options.enforcedBridge !== undefined) {\n elem.c(\n 'property', {\n name: 'enforcedBridge',\n value: this.xmppService.options.enforcedBridge\n }).up();\n }\n // Tell the focus we have Jigasi configured\n if (this.xmppService.options.hosts.call_control !== undefined) {\n elem.c(\n 'property', {\n name: 'call_control',\n value: this.xmppService.options.hosts.call_control\n }).up();\n }\n if (this.xmppService.options.channelLastN !== undefined) {\n elem.c(\n 'property', {\n name: 'channelLastN',\n value: this.xmppService.options.channelLastN\n }).up();\n }\n if (this.xmppService.options.adaptiveLastN !== undefined) {\n elem.c(\n 'property', {\n name: 'adaptiveLastN',\n value: this.xmppService.options.adaptiveLastN\n }).up();\n }\n if (this.xmppService.options.adaptiveSimulcast !== undefined) {\n elem.c(\n 'property', {\n name: 'adaptiveSimulcast',\n value: this.xmppService.options.adaptiveSimulcast\n }).up();\n }\n if (this.xmppService.options.openSctp !== undefined) {\n elem.c(\n 'property', {\n name: 'openSctp',\n value: this.xmppService.options.openSctp\n }).up();\n }\n if (this.xmppService.options.startAudioMuted !== undefined)\n {\n elem.c(\n 'property', {\n name: 'startAudioMuted',\n value: this.xmppService.options.startAudioMuted\n }).up();\n }\n if (this.xmppService.options.startVideoMuted !== undefined)\n {\n elem.c(\n 'property', {\n name: 'startVideoMuted',\n value: this.xmppService.options.startVideoMuted\n }).up();\n }\n elem.c(\n 'property', {\n name: 'simulcastMode',\n value: 'rewriting'\n }).up();\n elem.up();\n return elem;\n};\n\n\nModerator.prototype.parseSessionId = function (resultIq) {\n var sessionId = $(resultIq).find('conference').attr('session-id');\n if (sessionId) {\n logger.info('Received sessionId: ' + sessionId);\n localStorage.setItem('sessionId', sessionId);\n }\n};\n\nModerator.prototype.parseConfigOptions = function (resultIq) {\n\n this.setFocusUserJid(\n $(resultIq).find('conference').attr('focusjid'));\n\n var authenticationEnabled\n = $(resultIq).find(\n '>conference>property' +\n '[name=\\'authentication\\'][value=\\'true\\']').length > 0;\n\n logger.info(\"Authentication enabled: \" + authenticationEnabled);\n\n this.externalAuthEnabled = $(resultIq).find(\n '>conference>property' +\n '[name=\\'externalAuth\\'][value=\\'true\\']').length > 0;\n\n console.info(\n 'External authentication enabled: ' + this.externalAuthEnabled);\n\n if (!this.externalAuthEnabled) {\n // We expect to receive sessionId in 'internal' authentication mode\n this.parseSessionId(resultIq);\n }\n\n var authIdentity = $(resultIq).find('>conference').attr('identity');\n\n this.eventEmitter.emit(AuthenticationEvents.IDENTITY_UPDATED,\n authenticationEnabled, authIdentity);\n\n // Check if focus has auto-detected Jigasi component(this will be also\n // included if we have passed our host from the config)\n if ($(resultIq).find(\n '>conference>property' +\n '[name=\\'sipGatewayEnabled\\'][value=\\'true\\']').length) {\n this.sipGatewayEnabled = true;\n }\n\n logger.info(\"Sip gateway enabled: \" + this.sipGatewayEnabled);\n};\n\n// FIXME = we need to show the fact that we're waiting for the focus\n// to the user(or that focus is not available)\nModerator.prototype.allocateConferenceFocus = function (callback) {\n // Try to use focus user JID from the config\n this.setFocusUserJid(this.xmppService.options.focusUserJid);\n // Send create conference IQ\n var iq = this.createConferenceIq();\n var self = this;\n this.connection.sendIQ(\n iq,\n function (result) {\n\n // Setup config options\n self.parseConfigOptions(result);\n\n if ('true' === $(result).find('conference').attr('ready')) {\n // Reset both timers\n self.getNextTimeout(true);\n self.getNextErrorTimeout(true);\n // Exec callback\n callback();\n } else {\n var waitMs = self.getNextTimeout();\n logger.info(\"Waiting for the focus... \" + waitMs);\n // Reset error timeout\n self.getNextErrorTimeout(true);\n window.setTimeout(\n function () {\n self.allocateConferenceFocus(callback);\n }, waitMs);\n }\n },\n function (error) {\n // Invalid session ? remove and try again\n // without session ID to get a new one\n var invalidSession\n = $(error).find('>error>session-invalid').length;\n if (invalidSession) {\n logger.info(\"Session expired! - removing\");\n localStorage.removeItem(\"sessionId\");\n }\n if ($(error).find('>error>graceful-shutdown').length) {\n self.eventEmitter.emit(XMPPEvents.GRACEFUL_SHUTDOWN);\n return;\n }\n // Check for error returned by the reservation system\n var reservationErr = $(error).find('>error>reservation-error');\n if (reservationErr.length) {\n // Trigger error event\n var errorCode = reservationErr.attr('error-code');\n var errorMsg;\n if ($(error).find('>error>text')) {\n errorMsg = $(error).find('>error>text').text();\n }\n self.eventEmitter.emit(\n XMPPEvents.RESERVATION_ERROR, errorCode, errorMsg);\n return;\n }\n // Not authorized to create new room\n if ($(error).find('>error>not-authorized').length) {\n logger.warn(\"Unauthorized to start the conference\", error);\n var toDomain\n = Strophe.getDomainFromJid(error.getAttribute('to'));\n if (toDomain !==\n this.xmppService.options.hosts.anonymousdomain) {\n //FIXME: \"is external\" should come either from\n // the focus or config.js\n self.externalAuthEnabled = true;\n }\n self.eventEmitter.emit(\n XMPPEvents.AUTHENTICATION_REQUIRED,\n function () {\n self.allocateConferenceFocus(\n callback);\n });\n return;\n }\n var waitMs = self.getNextErrorTimeout();\n logger.error(\"Focus error, retry after \" + waitMs, error);\n // Show message\n var focusComponent = self.getFocusComponent();\n var retrySec = waitMs / 1000;\n //FIXME: message is duplicated ?\n // Do not show in case of session invalid\n // which means just a retry\n if (!invalidSession) {\n self.eventEmitter.emit(XMPPEvents.FOCUS_DISCONNECTED,\n focusComponent, retrySec);\n }\n // Reset response timeout\n self.getNextTimeout(true);\n window.setTimeout(\n function () {\n self.allocateConferenceFocus(callback);\n }, waitMs);\n }\n );\n};\n\nModerator.prototype.authenticate = function () {\n var self = this;\n return new Promise(function (resolve, reject) {\n self.connection.sendIQ(\n self.createConferenceIq(),\n function (result) {\n self.parseSessionId(result);\n resolve();\n }, function (error) {\n var code = $(error).find('>error').attr('code');\n reject(error, code);\n }\n );\n });\n};\n\nModerator.prototype.getLoginUrl = function (urlCallback, failureCallback) {\n var iq = $iq({to: this.getFocusComponent(), type: 'get'});\n iq.c('login-url', {\n xmlns: 'http://jitsi.org/protocol/focus',\n room: this.roomName,\n 'machine-uid': this.settings.getSettings().uid\n });\n this.connection.sendIQ(\n iq,\n function (result) {\n var url = $(result).find('login-url').attr('url');\n url = url = decodeURIComponent(url);\n if (url) {\n logger.info(\"Got auth url: \" + url);\n urlCallback(url);\n } else {\n logger.error(\n \"Failed to get auth url from the focus\", result);\n failureCallback(result);\n }\n },\n function (error) {\n logger.error(\"Get auth url error\", error);\n failureCallback(error);\n }\n );\n};\n\nModerator.prototype.getPopupLoginUrl = function (urlCallback, failureCallback) {\n var iq = $iq({to: this.getFocusComponent(), type: 'get'});\n iq.c('login-url', {\n xmlns: 'http://jitsi.org/protocol/focus',\n room: this.roomName,\n 'machine-uid': this.settings.getSettings().uid,\n popup: true\n });\n this.connection.sendIQ(\n iq,\n function (result) {\n var url = $(result).find('login-url').attr('url');\n url = url = decodeURIComponent(url);\n if (url) {\n logger.info(\"Got POPUP auth url: \" + url);\n urlCallback(url);\n } else {\n logger.error(\n \"Failed to get POPUP auth url from the focus\", result);\n failureCallback(result);\n }\n },\n function (error) {\n logger.error('Get POPUP auth url error', error);\n failureCallback(error);\n }\n );\n};\n\nModerator.prototype.logout = function (callback) {\n var iq = $iq({to: this.getFocusComponent(), type: 'set'});\n var sessionId = localStorage.getItem('sessionId');\n if (!sessionId) {\n callback();\n return;\n }\n iq.c('logout', {\n xmlns: 'http://jitsi.org/protocol/focus',\n 'session-id': sessionId\n });\n this.connection.sendIQ(\n iq,\n function (result) {\n var logoutUrl = $(result).find('logout').attr('logout-url');\n if (logoutUrl) {\n logoutUrl = decodeURIComponent(logoutUrl);\n }\n logger.info(\"Log out OK, url: \" + logoutUrl, result);\n localStorage.removeItem('sessionId');\n callback(logoutUrl);\n },\n function (error) {\n logger.error(\"Logout error\", error);\n }\n );\n};\n\nmodule.exports = Moderator;\n", + "/* global $, $iq, config, connection, focusMucJid, messageHandler,\n Toolbar, Util, Promise */\nvar XMPPEvents = require(\"../../service/XMPP/XMPPEvents\");\nvar logger = require(\"jitsi-meet-logger\").getLogger(__filename);\n\nfunction Recording(ee, connection, focusMucJid) {\n this.eventEmitter = ee;\n this.connection = connection;\n this.state = \"off\";\n this.focusMucJid = focusMucJid;\n this.url = null;\n this._isSupported = false;\n}\n\nRecording.prototype.handleJibriPresence = function (jibri) {\n var attributes = jibri.attributes;\n if(!attributes)\n return;\n\n this._isSupported =\n (attributes.status && attributes.status !== \"undefined\");\n if(this._isSupported) {\n this.url = attributes.url || null;\n this.state = attributes.status || \"off\";\n }\n this.eventEmitter.emit(XMPPEvents.RECORDING_STATE_CHANGED);\n};\n\nRecording.prototype.setRecording = function (state, streamId, followEntity,\n callback, errCallback){\n if (state == this.state){\n return;\n }\n\n // FIXME jibri does not accept IQ without 'url' attribute set ?\n\n var iq = $iq({to: this.focusMucJid, type: 'set'})\n .c('jibri', {\n \"xmlns\": 'http://jitsi.org/protocol/jibri',\n \"action\": (state === 'on') ? 'start' : 'stop',\n \"streamid\": streamId,\n \"follow-entity\": followEntity\n }).up();\n\n logger.log('Set jibri recording: '+state, iq.nodeTree);\n console.log(iq.nodeTree);\n this.connection.sendIQ(\n iq,\n function (result) {\n callback($(result).find('jibri').attr('state'),\n $(result).find('jibri').attr('url'));\n },\n function (error) {\n logger.log('Failed to start recording, error: ', error);\n errCallback(error);\n });\n};\n\nRecording.prototype.toggleRecording = function (token, followEntity) {\n var self = this;\n return new Promise(function(resolve, reject) {\n if (!token) {\n reject(new Error(\"No token passed!\"));\n logger.error(\"No token passed!\");\n return;\n }\n if(self.state === \"on\") {\n reject(new Error(\"Recording is already started!\"));\n logger.error(\"Recording is already started!\");\n return;\n }\n\n var oldState = self.state;\n var newState = (oldState === 'off' || !oldState) ? 'on' : 'off';\n\n self.setRecording(newState,\n token, followEntity,\n function (state, url) {\n logger.log(\"New recording state: \", state);\n if (state && state !== oldState) {\n self.state = state;\n self.url = url;\n resolve();\n } else {\n reject(new Error(\"State not changed!\"));\n }\n },\n function (error) {\n reject(error);\n }\n );\n });\n};\n\n/**\n * Returns true if the recording is supproted and false if not.\n */\nRecording.prototype.isSupported = function () {\n return this._isSupported;\n};\n\n/**\n * Returns null if the recording is not supported, \"on\" if the recording started\n * and \"off\" if the recording is not started.\n */\nRecording.prototype.getState = function () {\n return this.state;\n};\n\n/**\n * Returns the url of the recorded video.\n */\nRecording.prototype.getURL = function () {\n return this.url;\n};\n\nmodule.exports = Recording;\n", + "/* jshint -W117 */\n/* a simple MUC connection plugin\n * can only handle a single MUC room\n */\n\nvar logger = require(\"jitsi-meet-logger\").getLogger(__filename);\nvar ChatRoom = require(\"./ChatRoom\");\n\nmodule.exports = function(XMPP) {\n Strophe.addConnectionPlugin('emuc', {\n connection: null,\n rooms: {},//map with the rooms\n init: function (conn) {\n this.connection = conn;\n // add handlers (just once)\n this.connection.addHandler(this.onPresence.bind(this), null, 'presence', null, null, null, null);\n this.connection.addHandler(this.onPresenceUnavailable.bind(this), null, 'presence', 'unavailable', null);\n this.connection.addHandler(this.onPresenceError.bind(this), null, 'presence', 'error', null);\n this.connection.addHandler(this.onMessage.bind(this), null, 'message', null, null);\n },\n createRoom: function (jid, password, options) {\n var roomJid = Strophe.getBareJidFromJid(jid);\n if (this.rooms[roomJid]) {\n logger.error(\"You are already in the room!\");\n return;\n }\n this.rooms[roomJid] = new ChatRoom(this.connection, jid, password, XMPP, options);\n return this.rooms[roomJid];\n },\n doLeave: function (jid) {\n this.rooms[jid].doLeave();\n delete this.rooms[jid];\n },\n onPresence: function (pres) {\n var from = pres.getAttribute('from');\n\n // What is this for? A workaround for something?\n if (pres.getAttribute('type')) {\n return true;\n }\n\n var room = this.rooms[Strophe.getBareJidFromJid(from)];\n if(!room)\n return;\n\n // Parse status.\n if ($(pres).find('>x[xmlns=\"http://jabber.org/protocol/muc#user\"]>status[code=\"201\"]').length) {\n room.createNonAnonymousRoom();\n }\n\n room.onPresence(pres);\n\n return true;\n },\n onPresenceUnavailable: function (pres) {\n var from = pres.getAttribute('from');\n var room = this.rooms[Strophe.getBareJidFromJid(from)];\n if(!room)\n return;\n\n room.onPresenceUnavailable(pres, from);\n return true;\n },\n onPresenceError: function (pres) {\n var from = pres.getAttribute('from');\n var room = this.rooms[Strophe.getBareJidFromJid(from)];\n if(!room)\n return;\n\n room.onPresenceError(pres, from);\n return true;\n },\n onMessage: function (msg) {\n // FIXME: this is a hack. but jingle on muc makes nickchanges hard\n var from = msg.getAttribute('from');\n var room = this.rooms[Strophe.getBareJidFromJid(from)];\n if(!room)\n return;\n\n room.onMessage(msg, from);\n return true;\n },\n\n setJingleSession: function (from, session) {\n var room = this.rooms[Strophe.getBareJidFromJid(from)];\n if(!room)\n return;\n\n room.setJingleSession(session);\n }\n });\n};\n\n", + "/* jshint -W117 */\n\n\nvar logger = require(\"jitsi-meet-logger\").getLogger(__filename);\nvar JingleSession = require(\"./JingleSessionPC\");\nvar XMPPEvents = require(\"../../service/xmpp/XMPPEvents\");\nvar RTCBrowserType = require(\"../RTC/RTCBrowserType\");\n\n\nmodule.exports = function(XMPP, eventEmitter) {\n Strophe.addConnectionPlugin('jingle', {\n connection: null,\n sessions: {},\n jid2session: {},\n ice_config: {iceServers: []},\n media_constraints: {\n mandatory: {\n 'OfferToReceiveAudio': true,\n 'OfferToReceiveVideo': true\n }\n // MozDontOfferDataChannel: true when this is firefox\n },\n init: function (conn) {\n this.connection = conn;\n if (this.connection.disco) {\n // http://xmpp.org/extensions/xep-0167.html#support\n // http://xmpp.org/extensions/xep-0176.html#support\n this.connection.disco.addFeature('urn:xmpp:jingle:1');\n this.connection.disco.addFeature('urn:xmpp:jingle:apps:rtp:1');\n this.connection.disco.addFeature('urn:xmpp:jingle:transports:ice-udp:1');\n this.connection.disco.addFeature('urn:xmpp:jingle:apps:dtls:0');\n this.connection.disco.addFeature('urn:xmpp:jingle:transports:dtls-sctp:1');\n this.connection.disco.addFeature('urn:xmpp:jingle:apps:rtp:audio');\n this.connection.disco.addFeature('urn:xmpp:jingle:apps:rtp:video');\n\n if (RTCBrowserType.isChrome() || RTCBrowserType.isOpera()\n || RTCBrowserType.isTemasysPluginUsed()) {\n this.connection.disco.addFeature('urn:ietf:rfc:4588');\n }\n\n // this is dealt with by SDP O/A so we don't need to announce this\n //this.connection.disco.addFeature('urn:xmpp:jingle:apps:rtp:rtcp-fb:0'); // XEP-0293\n //this.connection.disco.addFeature('urn:xmpp:jingle:apps:rtp:rtp-hdrext:0'); // XEP-0294\n\n this.connection.disco.addFeature('urn:ietf:rfc:5761'); // rtcp-mux\n this.connection.disco.addFeature('urn:ietf:rfc:5888'); // a=group, e.g. bundle\n\n //this.connection.disco.addFeature('urn:ietf:rfc:5576'); // a=ssrc\n }\n this.connection.addHandler(this.onJingle.bind(this), 'urn:xmpp:jingle:1', 'iq', 'set', null, null);\n },\n onJingle: function (iq) {\n var sid = $(iq).find('jingle').attr('sid');\n var action = $(iq).find('jingle').attr('action');\n var fromJid = iq.getAttribute('from');\n // send ack first\n var ack = $iq({type: 'result',\n to: fromJid,\n id: iq.getAttribute('id')\n });\n logger.log('on jingle ' + action + ' from ' + fromJid, iq);\n var sess = this.sessions[sid];\n if ('session-initiate' != action) {\n if (sess === null) {\n ack.type = 'error';\n ack.c('error', {type: 'cancel'})\n .c('item-not-found', {xmlns: 'urn:ietf:params:xml:ns:xmpp-stanzas'}).up()\n .c('unknown-session', {xmlns: 'urn:xmpp:jingle:errors:1'});\n this.connection.send(ack);\n return true;\n }\n // local jid is not checked\n if (fromJid != sess.peerjid) {\n logger.warn('jid mismatch for session id', sid, fromJid, sess.peerjid);\n ack.type = 'error';\n ack.c('error', {type: 'cancel'})\n .c('item-not-found', {xmlns: 'urn:ietf:params:xml:ns:xmpp-stanzas'}).up()\n .c('unknown-session', {xmlns: 'urn:xmpp:jingle:errors:1'});\n this.connection.send(ack);\n return true;\n }\n } else if (sess !== undefined) {\n // existing session with same session id\n // this might be out-of-order if the sess.peerjid is the same as from\n ack.type = 'error';\n ack.c('error', {type: 'cancel'})\n .c('service-unavailable', {xmlns: 'urn:ietf:params:xml:ns:xmpp-stanzas'}).up();\n logger.warn('duplicate session id', sid);\n this.connection.send(ack);\n return true;\n }\n // FIXME: check for a defined action\n this.connection.send(ack);\n // see http://xmpp.org/extensions/xep-0166.html#concepts-session\n switch (action) {\n case 'session-initiate':\n console.log(\"(TIME) received session-initiate:\\t\",\n window.performance.now());\n var startMuted = $(iq).find('jingle>startmuted');\n if (startMuted && startMuted.length > 0) {\n var audioMuted = startMuted.attr(\"audio\");\n var videoMuted = startMuted.attr(\"video\");\n eventEmitter.emit(XMPPEvents.START_MUTED_FROM_FOCUS,\n audioMuted === \"true\", videoMuted === \"true\");\n }\n sess = new JingleSession(\n $(iq).attr('to'), $(iq).find('jingle').attr('sid'),\n this.connection, XMPP);\n // configure session\n\n var fromBareJid = Strophe.getBareJidFromJid(fromJid);\n this.connection.emuc.setJingleSession(fromBareJid, sess);\n\n sess.media_constraints = this.media_constraints;\n sess.ice_config = this.ice_config;\n\n sess.initialize(fromJid, false);\n eventEmitter.emit(XMPPEvents.CALL_INCOMING, sess);\n // FIXME: setRemoteDescription should only be done when this call is to be accepted\n sess.setOffer($(iq).find('>jingle'));\n\n this.sessions[sess.sid] = sess;\n this.jid2session[sess.peerjid] = sess;\n\n // the callback should either\n // .sendAnswer and .accept\n // or .sendTerminate -- not necessarily synchronous\n\n sess.sendAnswer();\n sess.accept();\n break;\n case 'session-accept':\n sess.setAnswer($(iq).find('>jingle'));\n sess.accept();\n break;\n case 'session-terminate':\n // If this is not the focus sending the terminate, we have\n // nothing more to do here.\n if (Object.keys(this.sessions).length < 1\n || !(this.sessions[Object.keys(this.sessions)[0]]\n instanceof JingleSession))\n {\n break;\n }\n logger.log('terminating...', sess.sid);\n sess.terminate();\n this.terminate(sess.sid);\n if ($(iq).find('>jingle>reason').length) {\n $(document).trigger('callterminated.jingle', [\n sess.sid,\n sess.peerjid,\n $(iq).find('>jingle>reason>:first')[0].tagName,\n $(iq).find('>jingle>reason>text').text()\n ]);\n } else {\n $(document).trigger('callterminated.jingle',\n [sess.sid, sess.peerjid]);\n }\n break;\n case 'transport-info':\n sess.addIceCandidate($(iq).find('>jingle>content'));\n break;\n case 'session-info':\n var affected;\n if ($(iq).find('>jingle>ringing[xmlns=\"urn:xmpp:jingle:apps:rtp:info:1\"]').length) {\n $(document).trigger('ringing.jingle', [sess.sid]);\n } else if ($(iq).find('>jingle>mute[xmlns=\"urn:xmpp:jingle:apps:rtp:info:1\"]').length) {\n affected = $(iq).find('>jingle>mute[xmlns=\"urn:xmpp:jingle:apps:rtp:info:1\"]').attr('name');\n $(document).trigger('mute.jingle', [sess.sid, affected]);\n } else if ($(iq).find('>jingle>unmute[xmlns=\"urn:xmpp:jingle:apps:rtp:info:1\"]').length) {\n affected = $(iq).find('>jingle>unmute[xmlns=\"urn:xmpp:jingle:apps:rtp:info:1\"]').attr('name');\n $(document).trigger('unmute.jingle', [sess.sid, affected]);\n }\n break;\n case 'addsource': // FIXME: proprietary, un-jingleish\n case 'source-add': // FIXME: proprietary\n sess.addSource($(iq).find('>jingle>content'));\n break;\n case 'removesource': // FIXME: proprietary, un-jingleish\n case 'source-remove': // FIXME: proprietary\n sess.removeSource($(iq).find('>jingle>content'));\n break;\n default:\n logger.warn('jingle action not implemented', action);\n break;\n }\n return true;\n },\n terminate: function (sid, reason, text) { // terminate by sessionid (or all sessions)\n if (sid === null || sid === undefined) {\n for (sid in this.sessions) {\n if (this.sessions[sid].state != 'ended') {\n this.sessions[sid].sendTerminate(reason || (!this.sessions[sid].active()) ? 'cancel' : null, text);\n this.sessions[sid].terminate();\n }\n delete this.jid2session[this.sessions[sid].peerjid];\n delete this.sessions[sid];\n }\n } else if (this.sessions.hasOwnProperty(sid)) {\n if (this.sessions[sid].state != 'ended') {\n this.sessions[sid].sendTerminate(reason || (!this.sessions[sid].active()) ? 'cancel' : null, text);\n this.sessions[sid].terminate();\n }\n delete this.jid2session[this.sessions[sid].peerjid];\n delete this.sessions[sid];\n }\n },\n getStunAndTurnCredentials: function () {\n // get stun and turn configuration from server via xep-0215\n // uses time-limited credentials as described in\n // http://tools.ietf.org/html/draft-uberti-behave-turn-rest-00\n //\n // see https://code.google.com/p/prosody-modules/source/browse/mod_turncredentials/mod_turncredentials.lua\n // for a prosody module which implements this\n //\n // currently, this doesn't work with updateIce and therefore credentials with a long\n // validity have to be fetched before creating the peerconnection\n // TODO: implement refresh via updateIce as described in\n // https://code.google.com/p/webrtc/issues/detail?id=1650\n var self = this;\n this.connection.sendIQ(\n $iq({type: 'get', to: this.connection.domain})\n .c('services', {xmlns: 'urn:xmpp:extdisco:1'}).c('service', {host: 'turn.' + this.connection.domain}),\n function (res) {\n var iceservers = [];\n $(res).find('>services>service').each(function (idx, el) {\n el = $(el);\n var dict = {};\n var type = el.attr('type');\n switch (type) {\n case 'stun':\n dict.url = 'stun:' + el.attr('host');\n if (el.attr('port')) {\n dict.url += ':' + el.attr('port');\n }\n iceservers.push(dict);\n break;\n case 'turn':\n case 'turns':\n dict.url = type + ':';\n if (el.attr('username')) { // https://code.google.com/p/webrtc/issues/detail?id=1508\n if (navigator.userAgent.match(/Chrom(e|ium)\\/([0-9]+)\\./) && parseInt(navigator.userAgent.match(/Chrom(e|ium)\\/([0-9]+)\\./)[2], 10) < 28) {\n dict.url += el.attr('username') + '@';\n } else {\n dict.username = el.attr('username'); // only works in M28\n }\n }\n dict.url += el.attr('host');\n if (el.attr('port') && el.attr('port') != '3478') {\n dict.url += ':' + el.attr('port');\n }\n if (el.attr('transport') && el.attr('transport') != 'udp') {\n dict.url += '?transport=' + el.attr('transport');\n }\n if (el.attr('password')) {\n dict.credential = el.attr('password');\n }\n iceservers.push(dict);\n break;\n }\n });\n self.ice_config.iceServers = iceservers;\n },\n function (err) {\n logger.warn('getting turn credentials failed', err);\n logger.warn('is mod_turncredentials or similar installed?');\n }\n );\n // implement push?\n },\n\n /**\n * Returns the data saved in 'updateLog' in a format to be logged.\n */\n getLog: function () {\n var data = {};\n var self = this;\n Object.keys(this.sessions).forEach(function (sid) {\n var session = self.sessions[sid];\n if (session.peerconnection && session.peerconnection.updateLog) {\n // FIXME: should probably be a .dump call\n data[\"jingle_\" + session.sid] = {\n updateLog: session.peerconnection.updateLog,\n stats: session.peerconnection.stats,\n url: window.location.href\n };\n }\n });\n return data;\n }\n });\n};\n\n", + "/* global Strophe */\nmodule.exports = function () {\n\n Strophe.addConnectionPlugin('logger', {\n // logs raw stanzas and makes them available for download as JSON\n connection: null,\n log: [],\n init: function (conn) {\n this.connection = conn;\n this.connection.rawInput = this.log_incoming.bind(this);\n this.connection.rawOutput = this.log_outgoing.bind(this);\n },\n log_incoming: function (stanza) {\n this.log.push([new Date().getTime(), 'incoming', stanza]);\n },\n log_outgoing: function (stanza) {\n this.log.push([new Date().getTime(), 'outgoing', stanza]);\n }\n });\n};", + "/* global $, $iq, Strophe */\n\nvar logger = require(\"jitsi-meet-logger\").getLogger(__filename);\n\nvar XMPPEvents = require(\"../../service/xmpp/XMPPEvents\");\n\n/**\n * Ping every 20 sec\n */\nvar PING_INTERVAL = 20000;\n\n/**\n * Ping timeout error after 15 sec of waiting.\n */\nvar PING_TIMEOUT = 15000;\n\n/**\n * Will close the connection after 3 consecutive ping errors.\n */\nvar PING_THRESHOLD = 3;\n\n/**\n * XEP-0199 ping plugin.\n *\n * Registers \"urn:xmpp:ping\" namespace under Strophe.NS.PING.\n */\nmodule.exports = function (XMPP, eventEmitter) {\n Strophe.addConnectionPlugin('ping', {\n\n connection: null,\n\n failedPings: 0,\n\n /**\n * Initializes the plugin. Method called by Strophe.\n * @param connection Strophe connection instance.\n */\n init: function (connection) {\n this.connection = connection;\n Strophe.addNamespace('PING', \"urn:xmpp:ping\");\n },\n\n /**\n * Sends \"ping\" to given jid\n * @param jid the JID to which ping request will be sent.\n * @param success callback called on success.\n * @param error callback called on error.\n * @param timeout ms how long are we going to wait for the response. On\n * timeout error callback is called with undefined error\n * argument.\n */\n ping: function (jid, success, error, timeout) {\n var iq = $iq({type: 'get', to: jid});\n iq.c('ping', {xmlns: Strophe.NS.PING});\n this.connection.sendIQ(iq, success, error, timeout);\n },\n\n /**\n * Checks if given jid has XEP-0199 ping support.\n * @param jid the JID to be checked for ping support.\n * @param callback function with boolean argument which will be\n * true if XEP-0199 ping is supported by given jid\n */\n hasPingSupport: function (jid, callback) {\n this.connection.disco.info(\n jid, null,\n function (result) {\n var ping = $(result).find('>>feature[var=\"urn:xmpp:ping\"]');\n callback(ping.length > 0);\n },\n function (error) {\n logger.error(\"Ping feature discovery error\", error);\n callback(false);\n }\n );\n },\n\n /**\n * Starts to send ping in given interval to specified remote JID.\n * This plugin supports only one such task and stopInterval\n * must be called before starting a new one.\n * @param remoteJid remote JID to which ping requests will be sent to.\n * @param interval task interval in ms.\n */\n startInterval: function (remoteJid, interval) {\n if (this.intervalId) {\n logger.error(\"Ping task scheduled already\");\n return;\n }\n if (!interval)\n interval = PING_INTERVAL;\n var self = this;\n this.intervalId = window.setInterval(function () {\n self.ping(remoteJid,\n function (result) {\n // Ping OK\n self.failedPings = 0;\n },\n function (error) {\n self.failedPings += 1;\n logger.error(\n \"Ping \" + (error ? \"error\" : \"timeout\"), error);\n if (self.failedPings >= PING_THRESHOLD) {\n self.connection.disconnect();\n }\n }, PING_TIMEOUT);\n }, interval);\n logger.info(\"XMPP pings will be sent every \" + interval + \" ms\");\n },\n\n /**\n * Stops current \"ping\" interval task.\n */\n stopInterval: function () {\n if (this.intervalId) {\n window.clearInterval(this.intervalId);\n this.intervalId = null;\n this.failedPings = 0;\n logger.info(\"Ping interval cleared\");\n }\n }\n });\n};\n", + "/* jshint -W117 */\nvar logger = require(\"jitsi-meet-logger\").getLogger(__filename);\n\nmodule.exports = function() {\n Strophe.addConnectionPlugin('rayo',\n {\n RAYO_XMLNS: 'urn:xmpp:rayo:1',\n connection: null,\n init: function (conn) {\n this.connection = conn;\n if (this.connection.disco) {\n this.connection.disco.addFeature('urn:xmpp:rayo:client:1');\n }\n\n this.connection.addHandler(\n this.onRayo.bind(this), this.RAYO_XMLNS, 'iq', 'set',\n null, null);\n },\n onRayo: function (iq) {\n logger.info(\"Rayo IQ\", iq);\n },\n dial: function (to, from, roomName, roomPass, focusMucJid) {\n var self = this;\n return new Promise(function (resolve, reject) {\n if(!focusMucJid) {\n reject(new Error(\"Internal error!\"));\n return;\n }\n var req = $iq(\n {\n type: 'set',\n to: focusMucJid\n }\n );\n req.c('dial',\n {\n xmlns: self.RAYO_XMLNS,\n to: to,\n from: from\n });\n req.c('header',\n {\n name: 'JvbRoomName',\n value: roomName\n }).up();\n\n if (roomPass !== null && roomPass.length) {\n\n req.c('header',\n {\n name: 'JvbRoomPassword',\n value: roomPass\n }).up();\n }\n\n self.connection.sendIQ(\n req,\n function (result) {\n logger.info('Dial result ', result);\n\n var resource = $(result).find('ref').attr('uri');\n self.call_resource =\n resource.substr('xmpp:'.length);\n logger.info(\n \"Received call resource: \" +\n self.call_resource);\n resolve();\n },\n function (error) {\n logger.info('Dial error ', error);\n reject(error);\n }\n );\n });\n },\n hangup: function () {\n var self = this;\n return new Promise(function (resolve, reject) {\n if (!self.call_resource) {\n reject(new Error(\"No call in progress\"));\n logger.warn(\"No call in progress\");\n return;\n }\n\n var req = $iq(\n {\n type: 'set',\n to: self.call_resource\n }\n );\n req.c('hangup',\n {\n xmlns: self.RAYO_XMLNS\n });\n\n self.connection.sendIQ(\n req,\n function (result) {\n logger.info('Hangup result ', result);\n self.call_resource = null;\n resolve();\n },\n function (error) {\n logger.info('Hangup error ', error);\n self.call_resource = null;\n reject(new Error('Hangup error '));\n }\n );\n });\n }\n }\n );\n};\n", + "/* global Strophe */\n/**\n * Strophe logger implementation. Logs from level WARN and above.\n */\nvar logger = require(\"jitsi-meet-logger\").getLogger(__filename);\n\nmodule.exports = function () {\n\n Strophe.log = function (level, msg) {\n switch (level) {\n case Strophe.LogLevel.WARN:\n logger.warn(\"Strophe: \" + msg);\n break;\n case Strophe.LogLevel.ERROR:\n case Strophe.LogLevel.FATAL:\n logger.error(\"Strophe: \" + msg);\n break;\n }\n };\n\n Strophe.getStatusString = function (status) {\n switch (status) {\n case Strophe.Status.ERROR:\n return \"ERROR\";\n case Strophe.Status.CONNECTING:\n return \"CONNECTING\";\n case Strophe.Status.CONNFAIL:\n return \"CONNFAIL\";\n case Strophe.Status.AUTHENTICATING:\n return \"AUTHENTICATING\";\n case Strophe.Status.AUTHFAIL:\n return \"AUTHFAIL\";\n case Strophe.Status.CONNECTED:\n return \"CONNECTED\";\n case Strophe.Status.DISCONNECTED:\n return \"DISCONNECTED\";\n case Strophe.Status.DISCONNECTING:\n return \"DISCONNECTING\";\n case Strophe.Status.ATTACHED:\n return \"ATTACHED\";\n default:\n return \"unknown\";\n }\n };\n};\n", + "/* global $, APP, config, Strophe*/\n\nvar logger = require(\"jitsi-meet-logger\").getLogger(__filename);\nvar EventEmitter = require(\"events\");\nvar Pako = require(\"pako\");\nvar RTCEvents = require(\"../../service/RTC/RTCEvents\");\nvar XMPPEvents = require(\"../../service/xmpp/XMPPEvents\");\nvar JitsiConnectionErrors = require(\"../../JitsiConnectionErrors\");\nvar JitsiConnectionEvents = require(\"../../JitsiConnectionEvents\");\nvar RTC = require(\"../RTC/RTC\");\n\nvar authenticatedUser = false;\n\nfunction createConnection(bosh) {\n bosh = bosh || '/http-bind';\n\n // Append token as URL param\n if (this.token) {\n bosh += bosh.indexOf('?') == -1 ?\n '?token=' + this.token : '&token=' + this.token;\n }\n\n return new Strophe.Connection(bosh);\n};\n\n\n\n//!!!!!!!!!! FIXME: ...\nfunction initStrophePlugins(XMPP)\n{\n require(\"./strophe.emuc\")(XMPP);\n require(\"./strophe.jingle\")(XMPP, XMPP.eventEmitter);\n// require(\"./strophe.moderate\")(XMPP, eventEmitter);\n require(\"./strophe.util\")();\n require(\"./strophe.ping\")(XMPP, XMPP.eventEmitter);\n require(\"./strophe.rayo\")();\n require(\"./strophe.logger\")();\n}\n\n//!!!!!!!!!! FIXME: ...\n///**\n// * If given localStream is video one this method will advertise it's\n// * video type in MUC presence.\n// * @param localStream new or modified LocalStream.\n// */\n//function broadcastLocalVideoType(localStream) {\n// if (localStream.videoType)\n// XMPP.addToPresence('videoType', localStream.videoType);\n//}\n//\n//function registerListeners() {\n// RTC.addStreamListener(\n// broadcastLocalVideoType,\n// StreamEventTypes.EVENT_TYPE_LOCAL_CHANGED\n// );\n// RTC.addListener(RTCEvents.AVAILABLE_DEVICES_CHANGED, function (devices) {\n// XMPP.addToPresence(\"devices\", devices);\n// });\n//}\n\nfunction XMPP(options) {\n this.eventEmitter = new EventEmitter();\n this.connection = null;\n this.disconnectInProgress = false;\n\n this.forceMuted = false;\n this.options = options;\n initStrophePlugins(this);\n// registerListeners();\n\n this.connection = createConnection(options.bosh);\n}\n\n\nXMPP.prototype.getConnection = function(){ return connection; };\n\nXMPP.prototype._connect = function (jid, password) {\n\n var self = this;\n // connection.connect() starts the connection process.\n //\n // As the connection process proceeds, the user supplied callback will\n // be triggered multiple times with status updates. The callback should\n // take two arguments - the status code and the error condition.\n //\n // The status code will be one of the values in the Strophe.Status\n // constants. The error condition will be one of the conditions defined\n // in RFC 3920 or the condition ‘strophe-parsererror’.\n //\n // The Parameters wait, hold and route are optional and only relevant\n // for BOSH connections. Please see XEP 124 for a more detailed\n // explanation of the optional parameters.\n //\n // Connection status constants for use by the connection handler\n // callback.\n //\n // Status.ERROR - An error has occurred (websockets specific)\n // Status.CONNECTING - The connection is currently being made\n // Status.CONNFAIL - The connection attempt failed\n // Status.AUTHENTICATING - The connection is authenticating\n // Status.AUTHFAIL - The authentication attempt failed\n // Status.CONNECTED - The connection has succeeded\n // Status.DISCONNECTED - The connection has been terminated\n // Status.DISCONNECTING - The connection is currently being terminated\n // Status.ATTACHED - The connection has been attached\n\n var anonymousConnectionFailed = false;\n var connectionFailed = false;\n var lastErrorMsg;\n this.connection.connect(jid, password, function (status, msg) {\n logger.log(\"(TIME) Strophe \" + Strophe.getStatusString(status) +\n (msg ? \"[\" + msg + \"]\" : \"\") + \"\\t:\" + window.performance.now());\n if (status === Strophe.Status.CONNECTED) {\n if (self.options.useStunTurn) {\n self.connection.jingle.getStunAndTurnCredentials();\n }\n\n\n logger.info(\"My Jabber ID: \" + self.connection.jid);\n\n // Schedule ping ?\n var pingJid = self.connection.domain;\n self.connection.ping.hasPingSupport(\n pingJid,\n function (hasPing) {\n if (hasPing)\n self.connection.ping.startInterval(pingJid);\n else\n logger.warn(\"Ping NOT supported by \" + pingJid);\n }\n );\n\n if (password)\n authenticatedUser = true;\n if (self.connection && self.connection.connected &&\n Strophe.getResourceFromJid(self.connection.jid)) {\n // .connected is true while connecting?\n// self.connection.send($pres());\n self.eventEmitter.emit(JitsiConnectionEvents.CONNECTION_ESTABLISHED,\n Strophe.getResourceFromJid(self.connection.jid));\n }\n } else if (status === Strophe.Status.CONNFAIL) {\n if (msg === 'x-strophe-bad-non-anon-jid') {\n anonymousConnectionFailed = true;\n }\n else\n {\n connectionFailed = true;\n }\n lastErrorMsg = msg;\n } else if (status === Strophe.Status.DISCONNECTED) {\n // Stop ping interval\n self.connection.ping.stopInterval();\n self.disconnectInProgress = false;\n if (anonymousConnectionFailed) {\n // prompt user for username and password\n self.eventEmitter.emit(JitsiConnectionEvents.CONNECTION_FAILED,\n JitsiConnectionErrors.PASSWORD_REQUIRED);\n } else if(connectionFailed) {\n self.eventEmitter.emit(JitsiConnectionEvents.CONNECTION_FAILED,\n JitsiConnectionErrors.OTHER_ERROR,\n msg ? msg : lastErrorMsg);\n } else {\n self.eventEmitter.emit(JitsiConnectionEvents.CONNECTION_DISCONNECTED,\n msg ? msg : lastErrorMsg);\n }\n } else if (status === Strophe.Status.AUTHFAIL) {\n // wrong password or username, prompt user\n self.eventEmitter.emit(JitsiConnectionEvents.CONNECTION_FAILED,\n JitsiConnectionErrors.PASSWORD_REQUIRED);\n\n }\n });\n}\n\nXMPP.prototype.connect = function (jid, password) {\n if(!jid) {\n var configDomain = this.options.hosts.anonymousdomain || this.options.hosts.domain;\n // Force authenticated domain if room is appended with '?login=true'\n if (this.options.hosts.anonymousdomain &&\n window.location.search.indexOf(\"login=true\") !== -1) {\n configDomain = this.options.hosts.domain;\n }\n jid = configDomain || window.location.hostname;\n }\n return this._connect(jid, password);\n};\n\nXMPP.prototype.createRoom = function (roomName, options) {\n var roomjid = roomName + '@' + this.options.hosts.muc;\n\n if (options.useNicks) {\n if (options.nick) {\n roomjid += '/' + options.nick;\n } else {\n roomjid += '/' + Strophe.getNodeFromJid(this.connection.jid);\n }\n } else {\n var tmpJid = Strophe.getNodeFromJid(this.connection.jid);\n\n if(!authenticatedUser)\n tmpJid = tmpJid.substr(0, 8);\n\n roomjid += '/' + tmpJid;\n }\n\n return this.connection.emuc.createRoom(roomjid, null, options);\n}\n\nXMPP.prototype.addListener = function(type, listener) {\n this.eventEmitter.on(type, listener);\n};\n\nXMPP.prototype.removeListener = function (type, listener) {\n this.eventEmitter.removeListener(type, listener);\n};\n\n//FIXME: this should work with the room\nXMPP.prototype.leaveRoom = function (jid) {\n var handler = this.connection.jingle.jid2session[jid];\n if (handler && handler.peerconnection) {\n // FIXME: probably removing streams is not required and close() should\n // be enough\n if (RTC.localAudio) {\n handler.peerconnection.removeStream(\n RTC.localAudio.getOriginalStream(), true);\n }\n if (RTC.localVideo) {\n handler.peerconnection.removeStream(\n RTC.localVideo.getOriginalStream(), true);\n }\n handler.peerconnection.close();\n }\n this.eventEmitter.emit(XMPPEvents.DISPOSE_CONFERENCE);\n this.connection.emuc.doLeave(jid);\n};\n\n/**\n * Sends 'data' as a log message to the focus. Returns true iff a message\n * was sent.\n * @param data\n * @returns {boolean} true iff a message was sent.\n */\nXMPP.prototype.sendLogs = function (data) {\n if(!this.connection.emuc.focusMucJid)\n return false;\n\n var deflate = true;\n\n var content = JSON.stringify(data);\n if (deflate) {\n content = String.fromCharCode.apply(null, Pako.deflateRaw(content));\n }\n content = Base64.encode(content);\n // XEP-0337-ish\n var message = $msg({to: this.connection.emuc.focusMucJid, type: 'normal'});\n message.c('log', { xmlns: 'urn:xmpp:eventlog',\n id: 'PeerConnectionStats'});\n message.c('message').t(content).up();\n if (deflate) {\n message.c('tag', {name: \"deflated\", value: \"true\"}).up();\n }\n message.up();\n\n this.connection.send(message);\n return true;\n};\n\n// Gets the logs from strophe.jingle.\nXMPP.prototype.getJingleLog = function () {\n return this.connection.jingle ? this.connection.jingle.getLog() : {};\n};\n\n// Gets the logs from strophe.\nXMPP.prototype.getXmppLog = function () {\n return this.connection.logger ? this.connection.logger.log : null;\n};\n\n\nXMPP.prototype.dial = function (to, from, roomName,roomPass) {\n this.connection.rayo.dial(to, from, roomName,roomPass);\n};\n\nXMPP.prototype.setMute = function (jid, mute) {\n this.connection.moderate.setMute(jid, mute);\n};\n\nXMPP.prototype.eject = function (jid) {\n this.connection.moderate.eject(jid);\n};\n\nXMPP.prototype.getSessions = function () {\n return this.connection.jingle.sessions;\n};\n\nXMPP.prototype.disconnect = function () {\n if (this.disconnectInProgress || !this.connection || !this.connection.connected)\n {\n this.eventEmitter.emit(JitsiConnectionEvents.WRONG_STATE);\n return;\n }\n\n this.disconnectInProgress = true;\n\n this.connection.disconnect();\n};\n\n/**\n * Gets the SSRC of local media stream.\n * @param mediaType the media type that tells whether we want to get\n * the SSRC of local audio or video stream.\n * @returns {*} the SSRC number for local media stream or null if\n * not available.\n */\nXMPP.prototype.getLocalSSRC = function (mediaType) {\n if (this.connection.jingle.activecall &&\n this.connection.jingle.activecall.peerconnection) {\n return this.connection.jingle.activecall.getLocalSSRC(mediaType);\n } else {\n return null;\n }\n};\n\nmodule.exports = XMPP;\n", + "/*!\n * async\n * https://github.com/caolan/async\n *\n * Copyright 2010-2014 Caolan McMahon\n * Released under the MIT license\n */\n/*jshint onevar: false, indent:4 */\n/*global setImmediate: false, setTimeout: false, console: false */\n(function () {\n\n var async = {};\n\n // global on the server, window in the browser\n var root, previous_async;\n\n root = this;\n if (root != null) {\n previous_async = root.async;\n }\n\n async.noConflict = function () {\n root.async = previous_async;\n return async;\n };\n\n function only_once(fn) {\n var called = false;\n return function() {\n if (called) throw new Error(\"Callback was already called.\");\n called = true;\n fn.apply(root, arguments);\n }\n }\n\n //// cross-browser compatiblity functions ////\n\n var _toString = Object.prototype.toString;\n\n var _isArray = Array.isArray || function (obj) {\n return _toString.call(obj) === '[object Array]';\n };\n\n var _each = function (arr, iterator) {\n if (arr.forEach) {\n return arr.forEach(iterator);\n }\n for (var i = 0; i < arr.length; i += 1) {\n iterator(arr[i], i, arr);\n }\n };\n\n var _map = function (arr, iterator) {\n if (arr.map) {\n return arr.map(iterator);\n }\n var results = [];\n _each(arr, function (x, i, a) {\n results.push(iterator(x, i, a));\n });\n return results;\n };\n\n var _reduce = function (arr, iterator, memo) {\n if (arr.reduce) {\n return arr.reduce(iterator, memo);\n }\n _each(arr, function (x, i, a) {\n memo = iterator(memo, x, i, a);\n });\n return memo;\n };\n\n var _keys = function (obj) {\n if (Object.keys) {\n return Object.keys(obj);\n }\n var keys = [];\n for (var k in obj) {\n if (obj.hasOwnProperty(k)) {\n keys.push(k);\n }\n }\n return keys;\n };\n\n //// exported async module functions ////\n\n //// nextTick implementation with browser-compatible fallback ////\n if (typeof process === 'undefined' || !(process.nextTick)) {\n if (typeof setImmediate === 'function') {\n async.nextTick = function (fn) {\n // not a direct alias for IE10 compatibility\n setImmediate(fn);\n };\n async.setImmediate = async.nextTick;\n }\n else {\n async.nextTick = function (fn) {\n setTimeout(fn, 0);\n };\n async.setImmediate = async.nextTick;\n }\n }\n else {\n async.nextTick = process.nextTick;\n if (typeof setImmediate !== 'undefined') {\n async.setImmediate = function (fn) {\n // not a direct alias for IE10 compatibility\n setImmediate(fn);\n };\n }\n else {\n async.setImmediate = async.nextTick;\n }\n }\n\n async.each = function (arr, iterator, callback) {\n callback = callback || function () {};\n if (!arr.length) {\n return callback();\n }\n var completed = 0;\n _each(arr, function (x) {\n iterator(x, only_once(done) );\n });\n function done(err) {\n if (err) {\n callback(err);\n callback = function () {};\n }\n else {\n completed += 1;\n if (completed >= arr.length) {\n callback();\n }\n }\n }\n };\n async.forEach = async.each;\n\n async.eachSeries = function (arr, iterator, callback) {\n callback = callback || function () {};\n if (!arr.length) {\n return callback();\n }\n var completed = 0;\n var iterate = function () {\n iterator(arr[completed], function (err) {\n if (err) {\n callback(err);\n callback = function () {};\n }\n else {\n completed += 1;\n if (completed >= arr.length) {\n callback();\n }\n else {\n iterate();\n }\n }\n });\n };\n iterate();\n };\n async.forEachSeries = async.eachSeries;\n\n async.eachLimit = function (arr, limit, iterator, callback) {\n var fn = _eachLimit(limit);\n fn.apply(null, [arr, iterator, callback]);\n };\n async.forEachLimit = async.eachLimit;\n\n var _eachLimit = function (limit) {\n\n return function (arr, iterator, callback) {\n callback = callback || function () {};\n if (!arr.length || limit <= 0) {\n return callback();\n }\n var completed = 0;\n var started = 0;\n var running = 0;\n\n (function replenish () {\n if (completed >= arr.length) {\n return callback();\n }\n\n while (running < limit && started < arr.length) {\n started += 1;\n running += 1;\n iterator(arr[started - 1], function (err) {\n if (err) {\n callback(err);\n callback = function () {};\n }\n else {\n completed += 1;\n running -= 1;\n if (completed >= arr.length) {\n callback();\n }\n else {\n replenish();\n }\n }\n });\n }\n })();\n };\n };\n\n\n var doParallel = function (fn) {\n return function () {\n var args = Array.prototype.slice.call(arguments);\n return fn.apply(null, [async.each].concat(args));\n };\n };\n var doParallelLimit = function(limit, fn) {\n return function () {\n var args = Array.prototype.slice.call(arguments);\n return fn.apply(null, [_eachLimit(limit)].concat(args));\n };\n };\n var doSeries = function (fn) {\n return function () {\n var args = Array.prototype.slice.call(arguments);\n return fn.apply(null, [async.eachSeries].concat(args));\n };\n };\n\n\n var _asyncMap = function (eachfn, arr, iterator, callback) {\n arr = _map(arr, function (x, i) {\n return {index: i, value: x};\n });\n if (!callback) {\n eachfn(arr, function (x, callback) {\n iterator(x.value, function (err) {\n callback(err);\n });\n });\n } else {\n var results = [];\n eachfn(arr, function (x, callback) {\n iterator(x.value, function (err, v) {\n results[x.index] = v;\n callback(err);\n });\n }, function (err) {\n callback(err, results);\n });\n }\n };\n async.map = doParallel(_asyncMap);\n async.mapSeries = doSeries(_asyncMap);\n async.mapLimit = function (arr, limit, iterator, callback) {\n return _mapLimit(limit)(arr, iterator, callback);\n };\n\n var _mapLimit = function(limit) {\n return doParallelLimit(limit, _asyncMap);\n };\n\n // reduce only has a series version, as doing reduce in parallel won't\n // work in many situations.\n async.reduce = function (arr, memo, iterator, callback) {\n async.eachSeries(arr, function (x, callback) {\n iterator(memo, x, function (err, v) {\n memo = v;\n callback(err);\n });\n }, function (err) {\n callback(err, memo);\n });\n };\n // inject alias\n async.inject = async.reduce;\n // foldl alias\n async.foldl = async.reduce;\n\n async.reduceRight = function (arr, memo, iterator, callback) {\n var reversed = _map(arr, function (x) {\n return x;\n }).reverse();\n async.reduce(reversed, memo, iterator, callback);\n };\n // foldr alias\n async.foldr = async.reduceRight;\n\n var _filter = function (eachfn, arr, iterator, callback) {\n var results = [];\n arr = _map(arr, function (x, i) {\n return {index: i, value: x};\n });\n eachfn(arr, function (x, callback) {\n iterator(x.value, function (v) {\n if (v) {\n results.push(x);\n }\n callback();\n });\n }, function (err) {\n callback(_map(results.sort(function (a, b) {\n return a.index - b.index;\n }), function (x) {\n return x.value;\n }));\n });\n };\n async.filter = doParallel(_filter);\n async.filterSeries = doSeries(_filter);\n // select alias\n async.select = async.filter;\n async.selectSeries = async.filterSeries;\n\n var _reject = function (eachfn, arr, iterator, callback) {\n var results = [];\n arr = _map(arr, function (x, i) {\n return {index: i, value: x};\n });\n eachfn(arr, function (x, callback) {\n iterator(x.value, function (v) {\n if (!v) {\n results.push(x);\n }\n callback();\n });\n }, function (err) {\n callback(_map(results.sort(function (a, b) {\n return a.index - b.index;\n }), function (x) {\n return x.value;\n }));\n });\n };\n async.reject = doParallel(_reject);\n async.rejectSeries = doSeries(_reject);\n\n var _detect = function (eachfn, arr, iterator, main_callback) {\n eachfn(arr, function (x, callback) {\n iterator(x, function (result) {\n if (result) {\n main_callback(x);\n main_callback = function () {};\n }\n else {\n callback();\n }\n });\n }, function (err) {\n main_callback();\n });\n };\n async.detect = doParallel(_detect);\n async.detectSeries = doSeries(_detect);\n\n async.some = function (arr, iterator, main_callback) {\n async.each(arr, function (x, callback) {\n iterator(x, function (v) {\n if (v) {\n main_callback(true);\n main_callback = function () {};\n }\n callback();\n });\n }, function (err) {\n main_callback(false);\n });\n };\n // any alias\n async.any = async.some;\n\n async.every = function (arr, iterator, main_callback) {\n async.each(arr, function (x, callback) {\n iterator(x, function (v) {\n if (!v) {\n main_callback(false);\n main_callback = function () {};\n }\n callback();\n });\n }, function (err) {\n main_callback(true);\n });\n };\n // all alias\n async.all = async.every;\n\n async.sortBy = function (arr, iterator, callback) {\n async.map(arr, function (x, callback) {\n iterator(x, function (err, criteria) {\n if (err) {\n callback(err);\n }\n else {\n callback(null, {value: x, criteria: criteria});\n }\n });\n }, function (err, results) {\n if (err) {\n return callback(err);\n }\n else {\n var fn = function (left, right) {\n var a = left.criteria, b = right.criteria;\n return a < b ? -1 : a > b ? 1 : 0;\n };\n callback(null, _map(results.sort(fn), function (x) {\n return x.value;\n }));\n }\n });\n };\n\n async.auto = function (tasks, callback) {\n callback = callback || function () {};\n var keys = _keys(tasks);\n var remainingTasks = keys.length\n if (!remainingTasks) {\n return callback();\n }\n\n var results = {};\n\n var listeners = [];\n var addListener = function (fn) {\n listeners.unshift(fn);\n };\n var removeListener = function (fn) {\n for (var i = 0; i < listeners.length; i += 1) {\n if (listeners[i] === fn) {\n listeners.splice(i, 1);\n return;\n }\n }\n };\n var taskComplete = function () {\n remainingTasks--\n _each(listeners.slice(0), function (fn) {\n fn();\n });\n };\n\n addListener(function () {\n if (!remainingTasks) {\n var theCallback = callback;\n // prevent final callback from calling itself if it errors\n callback = function () {};\n\n theCallback(null, results);\n }\n });\n\n _each(keys, function (k) {\n var task = _isArray(tasks[k]) ? tasks[k]: [tasks[k]];\n var taskCallback = function (err) {\n var args = Array.prototype.slice.call(arguments, 1);\n if (args.length <= 1) {\n args = args[0];\n }\n if (err) {\n var safeResults = {};\n _each(_keys(results), function(rkey) {\n safeResults[rkey] = results[rkey];\n });\n safeResults[k] = args;\n callback(err, safeResults);\n // stop subsequent errors hitting callback multiple times\n callback = function () {};\n }\n else {\n results[k] = args;\n async.setImmediate(taskComplete);\n }\n };\n var requires = task.slice(0, Math.abs(task.length - 1)) || [];\n var ready = function () {\n return _reduce(requires, function (a, x) {\n return (a && results.hasOwnProperty(x));\n }, true) && !results.hasOwnProperty(k);\n };\n if (ready()) {\n task[task.length - 1](taskCallback, results);\n }\n else {\n var listener = function () {\n if (ready()) {\n removeListener(listener);\n task[task.length - 1](taskCallback, results);\n }\n };\n addListener(listener);\n }\n });\n };\n\n async.retry = function(times, task, callback) {\n var DEFAULT_TIMES = 5;\n var attempts = [];\n // Use defaults if times not passed\n if (typeof times === 'function') {\n callback = task;\n task = times;\n times = DEFAULT_TIMES;\n }\n // Make sure times is a number\n times = parseInt(times, 10) || DEFAULT_TIMES;\n var wrappedTask = function(wrappedCallback, wrappedResults) {\n var retryAttempt = function(task, finalAttempt) {\n return function(seriesCallback) {\n task(function(err, result){\n seriesCallback(!err || finalAttempt, {err: err, result: result});\n }, wrappedResults);\n };\n };\n while (times) {\n attempts.push(retryAttempt(task, !(times-=1)));\n }\n async.series(attempts, function(done, data){\n data = data[data.length - 1];\n (wrappedCallback || callback)(data.err, data.result);\n });\n }\n // If a callback is passed, run this as a controll flow\n return callback ? wrappedTask() : wrappedTask\n };\n\n async.waterfall = function (tasks, callback) {\n callback = callback || function () {};\n if (!_isArray(tasks)) {\n var err = new Error('First argument to waterfall must be an array of functions');\n return callback(err);\n }\n if (!tasks.length) {\n return callback();\n }\n var wrapIterator = function (iterator) {\n return function (err) {\n if (err) {\n callback.apply(null, arguments);\n callback = function () {};\n }\n else {\n var args = Array.prototype.slice.call(arguments, 1);\n var next = iterator.next();\n if (next) {\n args.push(wrapIterator(next));\n }\n else {\n args.push(callback);\n }\n async.setImmediate(function () {\n iterator.apply(null, args);\n });\n }\n };\n };\n wrapIterator(async.iterator(tasks))();\n };\n\n var _parallel = function(eachfn, tasks, callback) {\n callback = callback || function () {};\n if (_isArray(tasks)) {\n eachfn.map(tasks, function (fn, callback) {\n if (fn) {\n fn(function (err) {\n var args = Array.prototype.slice.call(arguments, 1);\n if (args.length <= 1) {\n args = args[0];\n }\n callback.call(null, err, args);\n });\n }\n }, callback);\n }\n else {\n var results = {};\n eachfn.each(_keys(tasks), function (k, callback) {\n tasks[k](function (err) {\n var args = Array.prototype.slice.call(arguments, 1);\n if (args.length <= 1) {\n args = args[0];\n }\n results[k] = args;\n callback(err);\n });\n }, function (err) {\n callback(err, results);\n });\n }\n };\n\n async.parallel = function (tasks, callback) {\n _parallel({ map: async.map, each: async.each }, tasks, callback);\n };\n\n async.parallelLimit = function(tasks, limit, callback) {\n _parallel({ map: _mapLimit(limit), each: _eachLimit(limit) }, tasks, callback);\n };\n\n async.series = function (tasks, callback) {\n callback = callback || function () {};\n if (_isArray(tasks)) {\n async.mapSeries(tasks, function (fn, callback) {\n if (fn) {\n fn(function (err) {\n var args = Array.prototype.slice.call(arguments, 1);\n if (args.length <= 1) {\n args = args[0];\n }\n callback.call(null, err, args);\n });\n }\n }, callback);\n }\n else {\n var results = {};\n async.eachSeries(_keys(tasks), function (k, callback) {\n tasks[k](function (err) {\n var args = Array.prototype.slice.call(arguments, 1);\n if (args.length <= 1) {\n args = args[0];\n }\n results[k] = args;\n callback(err);\n });\n }, function (err) {\n callback(err, results);\n });\n }\n };\n\n async.iterator = function (tasks) {\n var makeCallback = function (index) {\n var fn = function () {\n if (tasks.length) {\n tasks[index].apply(null, arguments);\n }\n return fn.next();\n };\n fn.next = function () {\n return (index < tasks.length - 1) ? makeCallback(index + 1): null;\n };\n return fn;\n };\n return makeCallback(0);\n };\n\n async.apply = function (fn) {\n var args = Array.prototype.slice.call(arguments, 1);\n return function () {\n return fn.apply(\n null, args.concat(Array.prototype.slice.call(arguments))\n );\n };\n };\n\n var _concat = function (eachfn, arr, fn, callback) {\n var r = [];\n eachfn(arr, function (x, cb) {\n fn(x, function (err, y) {\n r = r.concat(y || []);\n cb(err);\n });\n }, function (err) {\n callback(err, r);\n });\n };\n async.concat = doParallel(_concat);\n async.concatSeries = doSeries(_concat);\n\n async.whilst = function (test, iterator, callback) {\n if (test()) {\n iterator(function (err) {\n if (err) {\n return callback(err);\n }\n async.whilst(test, iterator, callback);\n });\n }\n else {\n callback();\n }\n };\n\n async.doWhilst = function (iterator, test, callback) {\n iterator(function (err) {\n if (err) {\n return callback(err);\n }\n var args = Array.prototype.slice.call(arguments, 1);\n if (test.apply(null, args)) {\n async.doWhilst(iterator, test, callback);\n }\n else {\n callback();\n }\n });\n };\n\n async.until = function (test, iterator, callback) {\n if (!test()) {\n iterator(function (err) {\n if (err) {\n return callback(err);\n }\n async.until(test, iterator, callback);\n });\n }\n else {\n callback();\n }\n };\n\n async.doUntil = function (iterator, test, callback) {\n iterator(function (err) {\n if (err) {\n return callback(err);\n }\n var args = Array.prototype.slice.call(arguments, 1);\n if (!test.apply(null, args)) {\n async.doUntil(iterator, test, callback);\n }\n else {\n callback();\n }\n });\n };\n\n async.queue = function (worker, concurrency) {\n if (concurrency === undefined) {\n concurrency = 1;\n }\n function _insert(q, data, pos, callback) {\n if (!q.started){\n q.started = true;\n }\n if (!_isArray(data)) {\n data = [data];\n }\n if(data.length == 0) {\n // call drain immediately if there are no tasks\n return async.setImmediate(function() {\n if (q.drain) {\n q.drain();\n }\n });\n }\n _each(data, function(task) {\n var item = {\n data: task,\n callback: typeof callback === 'function' ? callback : null\n };\n\n if (pos) {\n q.tasks.unshift(item);\n } else {\n q.tasks.push(item);\n }\n\n if (q.saturated && q.tasks.length === q.concurrency) {\n q.saturated();\n }\n async.setImmediate(q.process);\n });\n }\n\n var workers = 0;\n var q = {\n tasks: [],\n concurrency: concurrency,\n saturated: null,\n empty: null,\n drain: null,\n started: false,\n paused: false,\n push: function (data, callback) {\n _insert(q, data, false, callback);\n },\n kill: function () {\n q.drain = null;\n q.tasks = [];\n },\n unshift: function (data, callback) {\n _insert(q, data, true, callback);\n },\n process: function () {\n if (!q.paused && workers < q.concurrency && q.tasks.length) {\n var task = q.tasks.shift();\n if (q.empty && q.tasks.length === 0) {\n q.empty();\n }\n workers += 1;\n var next = function () {\n workers -= 1;\n if (task.callback) {\n task.callback.apply(task, arguments);\n }\n if (q.drain && q.tasks.length + workers === 0) {\n q.drain();\n }\n q.process();\n };\n var cb = only_once(next);\n worker(task.data, cb);\n }\n },\n length: function () {\n return q.tasks.length;\n },\n running: function () {\n return workers;\n },\n idle: function() {\n return q.tasks.length + workers === 0;\n },\n pause: function () {\n if (q.paused === true) { return; }\n q.paused = true;\n q.process();\n },\n resume: function () {\n if (q.paused === false) { return; }\n q.paused = false;\n q.process();\n }\n };\n return q;\n };\n \n async.priorityQueue = function (worker, concurrency) {\n \n function _compareTasks(a, b){\n return a.priority - b.priority;\n };\n \n function _binarySearch(sequence, item, compare) {\n var beg = -1,\n end = sequence.length - 1;\n while (beg < end) {\n var mid = beg + ((end - beg + 1) >>> 1);\n if (compare(item, sequence[mid]) >= 0) {\n beg = mid;\n } else {\n end = mid - 1;\n }\n }\n return beg;\n }\n \n function _insert(q, data, priority, callback) {\n if (!q.started){\n q.started = true;\n }\n if (!_isArray(data)) {\n data = [data];\n }\n if(data.length == 0) {\n // call drain immediately if there are no tasks\n return async.setImmediate(function() {\n if (q.drain) {\n q.drain();\n }\n });\n }\n _each(data, function(task) {\n var item = {\n data: task,\n priority: priority,\n callback: typeof callback === 'function' ? callback : null\n };\n \n q.tasks.splice(_binarySearch(q.tasks, item, _compareTasks) + 1, 0, item);\n\n if (q.saturated && q.tasks.length === q.concurrency) {\n q.saturated();\n }\n async.setImmediate(q.process);\n });\n }\n \n // Start with a normal queue\n var q = async.queue(worker, concurrency);\n \n // Override push to accept second parameter representing priority\n q.push = function (data, priority, callback) {\n _insert(q, data, priority, callback);\n };\n \n // Remove unshift function\n delete q.unshift;\n\n return q;\n };\n\n async.cargo = function (worker, payload) {\n var working = false,\n tasks = [];\n\n var cargo = {\n tasks: tasks,\n payload: payload,\n saturated: null,\n empty: null,\n drain: null,\n drained: true,\n push: function (data, callback) {\n if (!_isArray(data)) {\n data = [data];\n }\n _each(data, function(task) {\n tasks.push({\n data: task,\n callback: typeof callback === 'function' ? callback : null\n });\n cargo.drained = false;\n if (cargo.saturated && tasks.length === payload) {\n cargo.saturated();\n }\n });\n async.setImmediate(cargo.process);\n },\n process: function process() {\n if (working) return;\n if (tasks.length === 0) {\n if(cargo.drain && !cargo.drained) cargo.drain();\n cargo.drained = true;\n return;\n }\n\n var ts = typeof payload === 'number'\n ? tasks.splice(0, payload)\n : tasks.splice(0, tasks.length);\n\n var ds = _map(ts, function (task) {\n return task.data;\n });\n\n if(cargo.empty) cargo.empty();\n working = true;\n worker(ds, function () {\n working = false;\n\n var args = arguments;\n _each(ts, function (data) {\n if (data.callback) {\n data.callback.apply(null, args);\n }\n });\n\n process();\n });\n },\n length: function () {\n return tasks.length;\n },\n running: function () {\n return working;\n }\n };\n return cargo;\n };\n\n var _console_fn = function (name) {\n return function (fn) {\n var args = Array.prototype.slice.call(arguments, 1);\n fn.apply(null, args.concat([function (err) {\n var args = Array.prototype.slice.call(arguments, 1);\n if (typeof console !== 'undefined') {\n if (err) {\n if (console.error) {\n console.error(err);\n }\n }\n else if (console[name]) {\n _each(args, function (x) {\n console[name](x);\n });\n }\n }\n }]));\n };\n };\n async.log = _console_fn('log');\n async.dir = _console_fn('dir');\n /*async.info = _console_fn('info');\n async.warn = _console_fn('warn');\n async.error = _console_fn('error');*/\n\n async.memoize = function (fn, hasher) {\n var memo = {};\n var queues = {};\n hasher = hasher || function (x) {\n return x;\n };\n var memoized = function () {\n var args = Array.prototype.slice.call(arguments);\n var callback = args.pop();\n var key = hasher.apply(null, args);\n if (key in memo) {\n async.nextTick(function () {\n callback.apply(null, memo[key]);\n });\n }\n else if (key in queues) {\n queues[key].push(callback);\n }\n else {\n queues[key] = [callback];\n fn.apply(null, args.concat([function () {\n memo[key] = arguments;\n var q = queues[key];\n delete queues[key];\n for (var i = 0, l = q.length; i < l; i++) {\n q[i].apply(null, arguments);\n }\n }]));\n }\n };\n memoized.memo = memo;\n memoized.unmemoized = fn;\n return memoized;\n };\n\n async.unmemoize = function (fn) {\n return function () {\n return (fn.unmemoized || fn).apply(null, arguments);\n };\n };\n\n async.times = function (count, iterator, callback) {\n var counter = [];\n for (var i = 0; i < count; i++) {\n counter.push(i);\n }\n return async.map(counter, iterator, callback);\n };\n\n async.timesSeries = function (count, iterator, callback) {\n var counter = [];\n for (var i = 0; i < count; i++) {\n counter.push(i);\n }\n return async.mapSeries(counter, iterator, callback);\n };\n\n async.seq = function (/* functions... */) {\n var fns = arguments;\n return function () {\n var that = this;\n var args = Array.prototype.slice.call(arguments);\n var callback = args.pop();\n async.reduce(fns, args, function (newargs, fn, cb) {\n fn.apply(that, newargs.concat([function () {\n var err = arguments[0];\n var nextargs = Array.prototype.slice.call(arguments, 1);\n cb(err, nextargs);\n }]))\n },\n function (err, results) {\n callback.apply(that, [err].concat(results));\n });\n };\n };\n\n async.compose = function (/* functions... */) {\n return async.seq.apply(null, Array.prototype.reverse.call(arguments));\n };\n\n var _applyEach = function (eachfn, fns /*args...*/) {\n var go = function () {\n var that = this;\n var args = Array.prototype.slice.call(arguments);\n var callback = args.pop();\n return eachfn(fns, function (fn, cb) {\n fn.apply(that, args.concat([cb]));\n },\n callback);\n };\n if (arguments.length > 2) {\n var args = Array.prototype.slice.call(arguments, 2);\n return go.apply(this, args);\n }\n else {\n return go;\n }\n };\n async.applyEach = doParallel(_applyEach);\n async.applyEachSeries = doSeries(_applyEach);\n\n async.forever = function (fn, callback) {\n function next(err) {\n if (err) {\n if (callback) {\n return callback(err);\n }\n throw err;\n }\n fn(next);\n }\n next();\n };\n\n // Node.js\n if (typeof module !== 'undefined' && module.exports) {\n module.exports = async;\n }\n // AMD / RequireJS\n else if (typeof define !== 'undefined' && define.amd) {\n define([], function () {\n return async;\n });\n }\n // included directly via