mirror of
https://github.com/DOI-DO/j40-cejst-2.git
synced 2025-02-23 01:54:18 -08:00
1 line
No EOL
3.4 MiB
1 line
No EOL
3.4 MiB
(self.webpackChunkjustice40_tool=self.webpackChunkjustice40_tool||[]).push([[281],{2846:function(__unused_webpack_module,exports){eval("/*! ieee754. BSD-3-Clause License. Feross Aboukhadijeh <https://feross.org/opensource> */\nexports.read = function (buffer, offset, isLE, mLen, nBytes) {\n var e, m;\n var eLen = nBytes * 8 - mLen - 1;\n var eMax = (1 << eLen) - 1;\n var eBias = eMax >> 1;\n var nBits = -7;\n var i = isLE ? nBytes - 1 : 0;\n var d = isLE ? -1 : 1;\n var s = buffer[offset + i];\n i += d;\n e = s & (1 << -nBits) - 1;\n s >>= -nBits;\n nBits += eLen;\n\n for (; nBits > 0; e = e * 256 + buffer[offset + i], i += d, nBits -= 8) {}\n\n m = e & (1 << -nBits) - 1;\n e >>= -nBits;\n nBits += mLen;\n\n for (; nBits > 0; m = m * 256 + buffer[offset + i], i += d, nBits -= 8) {}\n\n if (e === 0) {\n e = 1 - eBias;\n } else if (e === eMax) {\n return m ? NaN : (s ? -1 : 1) * Infinity;\n } else {\n m = m + Math.pow(2, mLen);\n e = e - eBias;\n }\n\n return (s ? -1 : 1) * m * Math.pow(2, e - mLen);\n};\n\nexports.write = function (buffer, value, offset, isLE, mLen, nBytes) {\n var e, m, c;\n var eLen = nBytes * 8 - mLen - 1;\n var eMax = (1 << eLen) - 1;\n var eBias = eMax >> 1;\n var rt = mLen === 23 ? Math.pow(2, -24) - Math.pow(2, -77) : 0;\n var i = isLE ? 0 : nBytes - 1;\n var d = isLE ? 1 : -1;\n var s = value < 0 || value === 0 && 1 / value < 0 ? 1 : 0;\n value = Math.abs(value);\n\n if (isNaN(value) || value === Infinity) {\n m = isNaN(value) ? 1 : 0;\n e = eMax;\n } else {\n e = Math.floor(Math.log(value) / Math.LN2);\n\n if (value * (c = Math.pow(2, -e)) < 1) {\n e--;\n c *= 2;\n }\n\n if (e + eBias >= 1) {\n value += rt / c;\n } else {\n value += rt * Math.pow(2, 1 - eBias);\n }\n\n if (value * c >= 2) {\n e++;\n c /= 2;\n }\n\n if (e + eBias >= eMax) {\n m = 0;\n e = eMax;\n } else if (e + eBias >= 1) {\n m = (value * c - 1) * Math.pow(2, mLen);\n e = e + eBias;\n } else {\n m = value * Math.pow(2, eBias - 1) * Math.pow(2, mLen);\n e = 0;\n }\n }\n\n for (; mLen >= 8; buffer[offset + i] = m & 0xff, i += d, m /= 256, mLen -= 8) {}\n\n e = e << mLen | m;\n eLen += mLen;\n\n for (; eLen > 0; buffer[offset + i] = e & 0xff, i += d, e /= 256, eLen -= 8) {}\n\n buffer[offset + i - d] |= s * 128;\n};//# sourceURL=[module]\n//# sourceMappingURL=data:application/json;charset=utf-8;base64,eyJ2ZXJzaW9uIjozLCJzb3VyY2VzIjpbIndlYnBhY2s6Ly9qdXN0aWNlNDAtdG9vbC8uL25vZGVfbW9kdWxlcy9pZWVlNzU0L2luZGV4LmpzPzBiNzkiXSwibmFtZXMiOltdLCJtYXBwaW5ncyI6IkFBQUE7QUFDQSxZQUFZO0FBQ1o7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQUVBLFFBQVEsV0FBVzs7QUFFbkI7QUFDQTtBQUNBOztBQUVBLFFBQVEsV0FBVzs7QUFFbkI7QUFDQTtBQUNBLEdBQUc7QUFDSDtBQUNBLEdBQUc7QUFDSDtBQUNBO0FBQ0E7O0FBRUE7QUFDQTs7QUFFQSxhQUFhO0FBQ2I7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBLEdBQUc7QUFDSDs7QUFFQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0EsS0FBSztBQUNMO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0EsS0FBSztBQUNMO0FBQ0E7QUFDQSxLQUFLO0FBQ0w7QUFDQTtBQUNBO0FBQ0E7O0FBRUEsUUFBUSxXQUFXOztBQUVuQjtBQUNBOztBQUVBLFFBQVEsVUFBVTs7QUFFbEI7QUFDQSIsImZpbGUiOiIyODQ2LmpzIiwic291cmNlc0NvbnRlbnQiOlsiLyohIGllZWU3NTQuIEJTRC0zLUNsYXVzZSBMaWNlbnNlLiBGZXJvc3MgQWJvdWtoYWRpamVoIDxodHRwczovL2Zlcm9zcy5vcmcvb3BlbnNvdXJjZT4gKi9cbmV4cG9ydHMucmVhZCA9IGZ1bmN0aW9uIChidWZmZXIsIG9mZnNldCwgaXNMRSwgbUxlbiwgbkJ5dGVzKSB7XG4gIHZhciBlLCBtO1xuICB2YXIgZUxlbiA9IG5CeXRlcyAqIDggLSBtTGVuIC0gMTtcbiAgdmFyIGVNYXggPSAoMSA8PCBlTGVuKSAtIDE7XG4gIHZhciBlQmlhcyA9IGVNYXggPj4gMTtcbiAgdmFyIG5CaXRzID0gLTc7XG4gIHZhciBpID0gaXNMRSA/IG5CeXRlcyAtIDEgOiAwO1xuICB2YXIgZCA9IGlzTEUgPyAtMSA6IDE7XG4gIHZhciBzID0gYnVmZmVyW29mZnNldCArIGldO1xuICBpICs9IGQ7XG4gIGUgPSBzICYgKDEgPDwgLW5CaXRzKSAtIDE7XG4gIHMgPj49IC1uQml0cztcbiAgbkJpdHMgKz0gZUxlbjtcblxuICBmb3IgKDsgbkJpdHMgPiAwOyBlID0gZSAqIDI1NiArIGJ1ZmZlcltvZmZzZXQgKyBpXSwgaSArPSBkLCBuQml0cyAtPSA4KSB7fVxuXG4gIG0gPSBlICYgKDEgPDwgLW5CaXRzKSAtIDE7XG4gIGUgPj49IC1uQml0cztcbiAgbkJpdHMgKz0gbUxlbjtcblxuICBmb3IgKDsgbkJpdHMgPiAwOyBtID0gbSAqIDI1NiArIGJ1ZmZlcltvZmZzZXQgKyBpXSwgaSArPSBkLCBuQml0cyAtPSA4KSB7fVxuXG4gIGlmIChlID09PSAwKSB7XG4gICAgZSA9IDEgLSBlQmlhcztcbiAgfSBlbHNlIGlmIChlID09PSBlTWF4KSB7XG4gICAgcmV0dXJuIG0gPyBOYU4gOiAocyA/IC0xIDogMSkgKiBJbmZpbml0eTtcbiAgfSBlbHNlIHtcbiAgICBtID0gbSArIE1hdGgucG93KDIsIG1MZW4pO1xuICAgIGUgPSBlIC0gZUJpYXM7XG4gIH1cblxuICByZXR1cm4gKHMgPyAtMSA6IDEpICogbSAqIE1hdGgucG93KDIsIGUgLSBtTGVuKTtcbn07XG5cbmV4cG9ydHMud3JpdGUgPSBmdW5jdGlvbiAoYnVmZmVyLCB2YWx1ZSwgb2Zmc2V0LCBpc0xFLCBtTGVuLCBuQnl0ZXMpIHtcbiAgdmFyIGUsIG0sIGM7XG4gIHZhciBlTGVuID0gbkJ5dGVzICogOCAtIG1MZW4gLSAxO1xuICB2YXIgZU1heCA9ICgxIDw8IGVMZW4pIC0gMTtcbiAgdmFyIGVCaWFzID0gZU1heCA+PiAxO1xuICB2YXIgcnQgPSBtTGVuID09PSAyMyA/IE1hdGgucG93KDIsIC0yNCkgLSBNYXRoLnBvdygyLCAtNzcpIDogMDtcbiAgdmFyIGkgPSBpc0xFID8gMCA6IG5CeXRlcyAtIDE7XG4gIHZhciBkID0gaXNMRSA/IDEgOiAtMTtcbiAgdmFyIHMgPSB2YWx1ZSA8IDAgfHwgdmFsdWUgPT09IDAgJiYgMSAvIHZhbHVlIDwgMCA/IDEgOiAwO1xuICB2YWx1ZSA9IE1hdGguYWJzKHZhbHVlKTtcblxuICBpZiAoaXNOYU4odmFsdWUpIHx8IHZhbHVlID09PSBJbmZpbml0eSkge1xuICAgIG0gPSBpc05hTih2YWx1ZSkgPyAxIDogMDtcbiAgICBlID0gZU1heDtcbiAgfSBlbHNlIHtcbiAgICBlID0gTWF0aC5mbG9vcihNYXRoLmxvZyh2YWx1ZSkgLyBNYXRoLkxOMik7XG5cbiAgICBpZiAodmFsdWUgKiAoYyA9IE1hdGgucG93KDIsIC1lKSkgPCAxKSB7XG4gICAgICBlLS07XG4gICAgICBjICo9IDI7XG4gICAgfVxuXG4gICAgaWYgKGUgKyBlQmlhcyA+PSAxKSB7XG4gICAgICB2YWx1ZSArPSBydCAvIGM7XG4gICAgfSBlbHNlIHtcbiAgICAgIHZhbHVlICs9IHJ0ICogTWF0aC5wb3coMiwgMSAtIGVCaWFzKTtcbiAgICB9XG5cbiAgICBpZiAodmFsdWUgKiBjID49IDIpIHtcbiAgICAgIGUrKztcbiAgICAgIGMgLz0gMjtcbiAgICB9XG5cbiAgICBpZiAoZSArIGVCaWFzID49IGVNYXgpIHtcbiAgICAgIG0gPSAwO1xuICAgICAgZSA9IGVNYXg7XG4gICAgfSBlbHNlIGlmIChlICsgZUJpYXMgPj0gMSkge1xuICAgICAgbSA9ICh2YWx1ZSAqIGMgLSAxKSAqIE1hdGgucG93KDIsIG1MZW4pO1xuICAgICAgZSA9IGUgKyBlQmlhcztcbiAgICB9IGVsc2Uge1xuICAgICAgbSA9IHZhbHVlICogTWF0aC5wb3coMiwgZUJpYXMgLSAxKSAqIE1hdGgucG93KDIsIG1MZW4pO1xuICAgICAgZSA9IDA7XG4gICAgfVxuICB9XG5cbiAgZm9yICg7IG1MZW4gPj0gODsgYnVmZmVyW29mZnNldCArIGldID0gbSAmIDB4ZmYsIGkgKz0gZCwgbSAvPSAyNTYsIG1MZW4gLT0gOCkge31cblxuICBlID0gZSA8PCBtTGVuIHwgbTtcbiAgZUxlbiArPSBtTGVuO1xuXG4gIGZvciAoOyBlTGVuID4gMDsgYnVmZmVyW29mZnNldCArIGldID0gZSAmIDB4ZmYsIGkgKz0gZCwgZSAvPSAyNTYsIGVMZW4gLT0gOCkge31cblxuICBidWZmZXJbb2Zmc2V0ICsgaSAtIGRdIHw9IHMgKiAxMjg7XG59OyJdLCJzb3VyY2VSb290IjoiIn0=\n//# sourceURL=webpack-internal:///2846\n")},4362:function(module,__unused_webpack_exports,__webpack_require__){"use strict";eval("\n\nmodule.exports = Pbf;\n\nvar ieee754 = __webpack_require__(2846);\n\nfunction Pbf(buf) {\n this.buf = ArrayBuffer.isView && ArrayBuffer.isView(buf) ? buf : new Uint8Array(buf || 0);\n this.pos = 0;\n this.type = 0;\n this.length = this.buf.length;\n}\n\nPbf.Varint = 0; // varint: int32, int64, uint32, uint64, sint32, sint64, bool, enum\n\nPbf.Fixed64 = 1; // 64-bit: double, fixed64, sfixed64\n\nPbf.Bytes = 2; // length-delimited: string, bytes, embedded messages, packed repeated fields\n\nPbf.Fixed32 = 5; // 32-bit: float, fixed32, sfixed32\n\nvar SHIFT_LEFT_32 = (1 << 16) * (1 << 16),\n SHIFT_RIGHT_32 = 1 / SHIFT_LEFT_32; // Threshold chosen based on both benchmarking and knowledge about browser string\n// data structures (which currently switch structure types at 12 bytes or more)\n\nvar TEXT_DECODER_MIN_LENGTH = 12;\nvar utf8TextDecoder = typeof TextDecoder === 'undefined' ? null : new TextDecoder('utf8');\nPbf.prototype = {\n destroy: function destroy() {\n this.buf = null;\n },\n // === READING =================================================================\n readFields: function readFields(readField, result, end) {\n end = end || this.length;\n\n while (this.pos < end) {\n var val = this.readVarint(),\n tag = val >> 3,\n startPos = this.pos;\n this.type = val & 0x7;\n readField(tag, result, this);\n if (this.pos === startPos) this.skip(val);\n }\n\n return result;\n },\n readMessage: function readMessage(readField, result) {\n return this.readFields(readField, result, this.readVarint() + this.pos);\n },\n readFixed32: function readFixed32() {\n var val = readUInt32(this.buf, this.pos);\n this.pos += 4;\n return val;\n },\n readSFixed32: function readSFixed32() {\n var val = readInt32(this.buf, this.pos);\n this.pos += 4;\n return val;\n },\n // 64-bit int handling is based on github.com/dpw/node-buffer-more-ints (MIT-licensed)\n readFixed64: function readFixed64() {\n var val = readUInt32(this.buf, this.pos) + readUInt32(this.buf, this.pos + 4) * SHIFT_LEFT_32;\n this.pos += 8;\n return val;\n },\n readSFixed64: function readSFixed64() {\n var val = readUInt32(this.buf, this.pos) + readInt32(this.buf, this.pos + 4) * SHIFT_LEFT_32;\n this.pos += 8;\n return val;\n },\n readFloat: function readFloat() {\n var val = ieee754.read(this.buf, this.pos, true, 23, 4);\n this.pos += 4;\n return val;\n },\n readDouble: function readDouble() {\n var val = ieee754.read(this.buf, this.pos, true, 52, 8);\n this.pos += 8;\n return val;\n },\n readVarint: function readVarint(isSigned) {\n var buf = this.buf,\n val,\n b;\n b = buf[this.pos++];\n val = b & 0x7f;\n if (b < 0x80) return val;\n b = buf[this.pos++];\n val |= (b & 0x7f) << 7;\n if (b < 0x80) return val;\n b = buf[this.pos++];\n val |= (b & 0x7f) << 14;\n if (b < 0x80) return val;\n b = buf[this.pos++];\n val |= (b & 0x7f) << 21;\n if (b < 0x80) return val;\n b = buf[this.pos];\n val |= (b & 0x0f) << 28;\n return readVarintRemainder(val, isSigned, this);\n },\n readVarint64: function readVarint64() {\n // for compatibility with v2.0.1\n return this.readVarint(true);\n },\n readSVarint: function readSVarint() {\n var num = this.readVarint();\n return num % 2 === 1 ? (num + 1) / -2 : num / 2; // zigzag encoding\n },\n readBoolean: function readBoolean() {\n return Boolean(this.readVarint());\n },\n readString: function readString() {\n var end = this.readVarint() + this.pos;\n var pos = this.pos;\n this.pos = end;\n\n if (end - pos >= TEXT_DECODER_MIN_LENGTH && utf8TextDecoder) {\n // longer strings are fast with the built-in browser TextDecoder API\n return readUtf8TextDecoder(this.buf, pos, end);\n } // short strings are fast with our custom implementation\n\n\n return readUtf8(this.buf, pos, end);\n },\n readBytes: function readBytes() {\n var end = this.readVarint() + this.pos,\n buffer = this.buf.subarray(this.pos, end);\n this.pos = end;\n return buffer;\n },\n // verbose for performance reasons; doesn't affect gzipped size\n readPackedVarint: function readPackedVarint(arr, isSigned) {\n if (this.type !== Pbf.Bytes) return arr.push(this.readVarint(isSigned));\n var end = readPackedEnd(this);\n arr = arr || [];\n\n while (this.pos < end) {\n arr.push(this.readVarint(isSigned));\n }\n\n return arr;\n },\n readPackedSVarint: function readPackedSVarint(arr) {\n if (this.type !== Pbf.Bytes) return arr.push(this.readSVarint());\n var end = readPackedEnd(this);\n arr = arr || [];\n\n while (this.pos < end) {\n arr.push(this.readSVarint());\n }\n\n return arr;\n },\n readPackedBoolean: function readPackedBoolean(arr) {\n if (this.type !== Pbf.Bytes) return arr.push(this.readBoolean());\n var end = readPackedEnd(this);\n arr = arr || [];\n\n while (this.pos < end) {\n arr.push(this.readBoolean());\n }\n\n return arr;\n },\n readPackedFloat: function readPackedFloat(arr) {\n if (this.type !== Pbf.Bytes) return arr.push(this.readFloat());\n var end = readPackedEnd(this);\n arr = arr || [];\n\n while (this.pos < end) {\n arr.push(this.readFloat());\n }\n\n return arr;\n },\n readPackedDouble: function readPackedDouble(arr) {\n if (this.type !== Pbf.Bytes) return arr.push(this.readDouble());\n var end = readPackedEnd(this);\n arr = arr || [];\n\n while (this.pos < end) {\n arr.push(this.readDouble());\n }\n\n return arr;\n },\n readPackedFixed32: function readPackedFixed32(arr) {\n if (this.type !== Pbf.Bytes) return arr.push(this.readFixed32());\n var end = readPackedEnd(this);\n arr = arr || [];\n\n while (this.pos < end) {\n arr.push(this.readFixed32());\n }\n\n return arr;\n },\n readPackedSFixed32: function readPackedSFixed32(arr) {\n if (this.type !== Pbf.Bytes) return arr.push(this.readSFixed32());\n var end = readPackedEnd(this);\n arr = arr || [];\n\n while (this.pos < end) {\n arr.push(this.readSFixed32());\n }\n\n return arr;\n },\n readPackedFixed64: function readPackedFixed64(arr) {\n if (this.type !== Pbf.Bytes) return arr.push(this.readFixed64());\n var end = readPackedEnd(this);\n arr = arr || [];\n\n while (this.pos < end) {\n arr.push(this.readFixed64());\n }\n\n return arr;\n },\n readPackedSFixed64: function readPackedSFixed64(arr) {\n if (this.type !== Pbf.Bytes) return arr.push(this.readSFixed64());\n var end = readPackedEnd(this);\n arr = arr || [];\n\n while (this.pos < end) {\n arr.push(this.readSFixed64());\n }\n\n return arr;\n },\n skip: function skip(val) {\n var type = val & 0x7;\n if (type === Pbf.Varint) while (this.buf[this.pos++] > 0x7f) {} else if (type === Pbf.Bytes) this.pos = this.readVarint() + this.pos;else if (type === Pbf.Fixed32) this.pos += 4;else if (type === Pbf.Fixed64) this.pos += 8;else throw new Error('Unimplemented type: ' + type);\n },\n // === WRITING =================================================================\n writeTag: function writeTag(tag, type) {\n this.writeVarint(tag << 3 | type);\n },\n realloc: function realloc(min) {\n var length = this.length || 16;\n\n while (length < this.pos + min) {\n length *= 2;\n }\n\n if (length !== this.length) {\n var buf = new Uint8Array(length);\n buf.set(this.buf);\n this.buf = buf;\n this.length = length;\n }\n },\n finish: function finish() {\n this.length = this.pos;\n this.pos = 0;\n return this.buf.subarray(0, this.length);\n },\n writeFixed32: function writeFixed32(val) {\n this.realloc(4);\n writeInt32(this.buf, val, this.pos);\n this.pos += 4;\n },\n writeSFixed32: function writeSFixed32(val) {\n this.realloc(4);\n writeInt32(this.buf, val, this.pos);\n this.pos += 4;\n },\n writeFixed64: function writeFixed64(val) {\n this.realloc(8);\n writeInt32(this.buf, val & -1, this.pos);\n writeInt32(this.buf, Math.floor(val * SHIFT_RIGHT_32), this.pos + 4);\n this.pos += 8;\n },\n writeSFixed64: function writeSFixed64(val) {\n this.realloc(8);\n writeInt32(this.buf, val & -1, this.pos);\n writeInt32(this.buf, Math.floor(val * SHIFT_RIGHT_32), this.pos + 4);\n this.pos += 8;\n },\n writeVarint: function writeVarint(val) {\n val = +val || 0;\n\n if (val > 0xfffffff || val < 0) {\n writeBigVarint(val, this);\n return;\n }\n\n this.realloc(4);\n this.buf[this.pos++] = val & 0x7f | (val > 0x7f ? 0x80 : 0);\n if (val <= 0x7f) return;\n this.buf[this.pos++] = (val >>>= 7) & 0x7f | (val > 0x7f ? 0x80 : 0);\n if (val <= 0x7f) return;\n this.buf[this.pos++] = (val >>>= 7) & 0x7f | (val > 0x7f ? 0x80 : 0);\n if (val <= 0x7f) return;\n this.buf[this.pos++] = val >>> 7 & 0x7f;\n },\n writeSVarint: function writeSVarint(val) {\n this.writeVarint(val < 0 ? -val * 2 - 1 : val * 2);\n },\n writeBoolean: function writeBoolean(val) {\n this.writeVarint(Boolean(val));\n },\n writeString: function writeString(str) {\n str = String(str);\n this.realloc(str.length * 4);\n this.pos++; // reserve 1 byte for short string length\n\n var startPos = this.pos; // write the string directly to the buffer and see how much was written\n\n this.pos = writeUtf8(this.buf, str, this.pos);\n var len = this.pos - startPos;\n if (len >= 0x80) makeRoomForExtraLength(startPos, len, this); // finally, write the message length in the reserved place and restore the position\n\n this.pos = startPos - 1;\n this.writeVarint(len);\n this.pos += len;\n },\n writeFloat: function writeFloat(val) {\n this.realloc(4);\n ieee754.write(this.buf, val, this.pos, true, 23, 4);\n this.pos += 4;\n },\n writeDouble: function writeDouble(val) {\n this.realloc(8);\n ieee754.write(this.buf, val, this.pos, true, 52, 8);\n this.pos += 8;\n },\n writeBytes: function writeBytes(buffer) {\n var len = buffer.length;\n this.writeVarint(len);\n this.realloc(len);\n\n for (var i = 0; i < len; i++) {\n this.buf[this.pos++] = buffer[i];\n }\n },\n writeRawMessage: function writeRawMessage(fn, obj) {\n this.pos++; // reserve 1 byte for short message length\n // write the message directly to the buffer and see how much was written\n\n var startPos = this.pos;\n fn(obj, this);\n var len = this.pos - startPos;\n if (len >= 0x80) makeRoomForExtraLength(startPos, len, this); // finally, write the message length in the reserved place and restore the position\n\n this.pos = startPos - 1;\n this.writeVarint(len);\n this.pos += len;\n },\n writeMessage: function writeMessage(tag, fn, obj) {\n this.writeTag(tag, Pbf.Bytes);\n this.writeRawMessage(fn, obj);\n },\n writePackedVarint: function writePackedVarint(tag, arr) {\n if (arr.length) this.writeMessage(tag, _writePackedVarint, arr);\n },\n writePackedSVarint: function writePackedSVarint(tag, arr) {\n if (arr.length) this.writeMessage(tag, _writePackedSVarint, arr);\n },\n writePackedBoolean: function writePackedBoolean(tag, arr) {\n if (arr.length) this.writeMessage(tag, _writePackedBoolean, arr);\n },\n writePackedFloat: function writePackedFloat(tag, arr) {\n if (arr.length) this.writeMessage(tag, _writePackedFloat, arr);\n },\n writePackedDouble: function writePackedDouble(tag, arr) {\n if (arr.length) this.writeMessage(tag, _writePackedDouble, arr);\n },\n writePackedFixed32: function writePackedFixed32(tag, arr) {\n if (arr.length) this.writeMessage(tag, _writePackedFixed, arr);\n },\n writePackedSFixed32: function writePackedSFixed32(tag, arr) {\n if (arr.length) this.writeMessage(tag, _writePackedSFixed, arr);\n },\n writePackedFixed64: function writePackedFixed64(tag, arr) {\n if (arr.length) this.writeMessage(tag, _writePackedFixed2, arr);\n },\n writePackedSFixed64: function writePackedSFixed64(tag, arr) {\n if (arr.length) this.writeMessage(tag, _writePackedSFixed2, arr);\n },\n writeBytesField: function writeBytesField(tag, buffer) {\n this.writeTag(tag, Pbf.Bytes);\n this.writeBytes(buffer);\n },\n writeFixed32Field: function writeFixed32Field(tag, val) {\n this.writeTag(tag, Pbf.Fixed32);\n this.writeFixed32(val);\n },\n writeSFixed32Field: function writeSFixed32Field(tag, val) {\n this.writeTag(tag, Pbf.Fixed32);\n this.writeSFixed32(val);\n },\n writeFixed64Field: function writeFixed64Field(tag, val) {\n this.writeTag(tag, Pbf.Fixed64);\n this.writeFixed64(val);\n },\n writeSFixed64Field: function writeSFixed64Field(tag, val) {\n this.writeTag(tag, Pbf.Fixed64);\n this.writeSFixed64(val);\n },\n writeVarintField: function writeVarintField(tag, val) {\n this.writeTag(tag, Pbf.Varint);\n this.writeVarint(val);\n },\n writeSVarintField: function writeSVarintField(tag, val) {\n this.writeTag(tag, Pbf.Varint);\n this.writeSVarint(val);\n },\n writeStringField: function writeStringField(tag, str) {\n this.writeTag(tag, Pbf.Bytes);\n this.writeString(str);\n },\n writeFloatField: function writeFloatField(tag, val) {\n this.writeTag(tag, Pbf.Fixed32);\n this.writeFloat(val);\n },\n writeDoubleField: function writeDoubleField(tag, val) {\n this.writeTag(tag, Pbf.Fixed64);\n this.writeDouble(val);\n },\n writeBooleanField: function writeBooleanField(tag, val) {\n this.writeVarintField(tag, Boolean(val));\n }\n};\n\nfunction readVarintRemainder(l, s, p) {\n var buf = p.buf,\n h,\n b;\n b = buf[p.pos++];\n h = (b & 0x70) >> 4;\n if (b < 0x80) return toNum(l, h, s);\n b = buf[p.pos++];\n h |= (b & 0x7f) << 3;\n if (b < 0x80) return toNum(l, h, s);\n b = buf[p.pos++];\n h |= (b & 0x7f) << 10;\n if (b < 0x80) return toNum(l, h, s);\n b = buf[p.pos++];\n h |= (b & 0x7f) << 17;\n if (b < 0x80) return toNum(l, h, s);\n b = buf[p.pos++];\n h |= (b & 0x7f) << 24;\n if (b < 0x80) return toNum(l, h, s);\n b = buf[p.pos++];\n h |= (b & 0x01) << 31;\n if (b < 0x80) return toNum(l, h, s);\n throw new Error('Expected varint not more than 10 bytes');\n}\n\nfunction readPackedEnd(pbf) {\n return pbf.type === Pbf.Bytes ? pbf.readVarint() + pbf.pos : pbf.pos + 1;\n}\n\nfunction toNum(low, high, isSigned) {\n if (isSigned) {\n return high * 0x100000000 + (low >>> 0);\n }\n\n return (high >>> 0) * 0x100000000 + (low >>> 0);\n}\n\nfunction writeBigVarint(val, pbf) {\n var low, high;\n\n if (val >= 0) {\n low = val % 0x100000000 | 0;\n high = val / 0x100000000 | 0;\n } else {\n low = ~(-val % 0x100000000);\n high = ~(-val / 0x100000000);\n\n if (low ^ 0xffffffff) {\n low = low + 1 | 0;\n } else {\n low = 0;\n high = high + 1 | 0;\n }\n }\n\n if (val >= 0x10000000000000000 || val < -0x10000000000000000) {\n throw new Error('Given varint doesn\\'t fit into 10 bytes');\n }\n\n pbf.realloc(10);\n writeBigVarintLow(low, high, pbf);\n writeBigVarintHigh(high, pbf);\n}\n\nfunction writeBigVarintLow(low, high, pbf) {\n pbf.buf[pbf.pos++] = low & 0x7f | 0x80;\n low >>>= 7;\n pbf.buf[pbf.pos++] = low & 0x7f | 0x80;\n low >>>= 7;\n pbf.buf[pbf.pos++] = low & 0x7f | 0x80;\n low >>>= 7;\n pbf.buf[pbf.pos++] = low & 0x7f | 0x80;\n low >>>= 7;\n pbf.buf[pbf.pos] = low & 0x7f;\n}\n\nfunction writeBigVarintHigh(high, pbf) {\n var lsb = (high & 0x07) << 4;\n pbf.buf[pbf.pos++] |= lsb | ((high >>>= 3) ? 0x80 : 0);\n if (!high) return;\n pbf.buf[pbf.pos++] = high & 0x7f | ((high >>>= 7) ? 0x80 : 0);\n if (!high) return;\n pbf.buf[pbf.pos++] = high & 0x7f | ((high >>>= 7) ? 0x80 : 0);\n if (!high) return;\n pbf.buf[pbf.pos++] = high & 0x7f | ((high >>>= 7) ? 0x80 : 0);\n if (!high) return;\n pbf.buf[pbf.pos++] = high & 0x7f | ((high >>>= 7) ? 0x80 : 0);\n if (!high) return;\n pbf.buf[pbf.pos++] = high & 0x7f;\n}\n\nfunction makeRoomForExtraLength(startPos, len, pbf) {\n var extraLen = len <= 0x3fff ? 1 : len <= 0x1fffff ? 2 : len <= 0xfffffff ? 3 : Math.floor(Math.log(len) / (Math.LN2 * 7)); // if 1 byte isn't enough for encoding message length, shift the data to the right\n\n pbf.realloc(extraLen);\n\n for (var i = pbf.pos - 1; i >= startPos; i--) {\n pbf.buf[i + extraLen] = pbf.buf[i];\n }\n}\n\nfunction _writePackedVarint(arr, pbf) {\n for (var i = 0; i < arr.length; i++) {\n pbf.writeVarint(arr[i]);\n }\n}\n\nfunction _writePackedSVarint(arr, pbf) {\n for (var i = 0; i < arr.length; i++) {\n pbf.writeSVarint(arr[i]);\n }\n}\n\nfunction _writePackedFloat(arr, pbf) {\n for (var i = 0; i < arr.length; i++) {\n pbf.writeFloat(arr[i]);\n }\n}\n\nfunction _writePackedDouble(arr, pbf) {\n for (var i = 0; i < arr.length; i++) {\n pbf.writeDouble(arr[i]);\n }\n}\n\nfunction _writePackedBoolean(arr, pbf) {\n for (var i = 0; i < arr.length; i++) {\n pbf.writeBoolean(arr[i]);\n }\n}\n\nfunction _writePackedFixed(arr, pbf) {\n for (var i = 0; i < arr.length; i++) {\n pbf.writeFixed32(arr[i]);\n }\n}\n\nfunction _writePackedSFixed(arr, pbf) {\n for (var i = 0; i < arr.length; i++) {\n pbf.writeSFixed32(arr[i]);\n }\n}\n\nfunction _writePackedFixed2(arr, pbf) {\n for (var i = 0; i < arr.length; i++) {\n pbf.writeFixed64(arr[i]);\n }\n}\n\nfunction _writePackedSFixed2(arr, pbf) {\n for (var i = 0; i < arr.length; i++) {\n pbf.writeSFixed64(arr[i]);\n }\n} // Buffer code below from https://github.com/feross/buffer, MIT-licensed\n\n\nfunction readUInt32(buf, pos) {\n return (buf[pos] | buf[pos + 1] << 8 | buf[pos + 2] << 16) + buf[pos + 3] * 0x1000000;\n}\n\nfunction writeInt32(buf, val, pos) {\n buf[pos] = val;\n buf[pos + 1] = val >>> 8;\n buf[pos + 2] = val >>> 16;\n buf[pos + 3] = val >>> 24;\n}\n\nfunction readInt32(buf, pos) {\n return (buf[pos] | buf[pos + 1] << 8 | buf[pos + 2] << 16) + (buf[pos + 3] << 24);\n}\n\nfunction readUtf8(buf, pos, end) {\n var str = '';\n var i = pos;\n\n while (i < end) {\n var b0 = buf[i];\n var c = null; // codepoint\n\n var bytesPerSequence = b0 > 0xEF ? 4 : b0 > 0xDF ? 3 : b0 > 0xBF ? 2 : 1;\n if (i + bytesPerSequence > end) break;\n var b1, b2, b3;\n\n if (bytesPerSequence === 1) {\n if (b0 < 0x80) {\n c = b0;\n }\n } else if (bytesPerSequence === 2) {\n b1 = buf[i + 1];\n\n if ((b1 & 0xC0) === 0x80) {\n c = (b0 & 0x1F) << 0x6 | b1 & 0x3F;\n\n if (c <= 0x7F) {\n c = null;\n }\n }\n } else if (bytesPerSequence === 3) {\n b1 = buf[i + 1];\n b2 = buf[i + 2];\n\n if ((b1 & 0xC0) === 0x80 && (b2 & 0xC0) === 0x80) {\n c = (b0 & 0xF) << 0xC | (b1 & 0x3F) << 0x6 | b2 & 0x3F;\n\n if (c <= 0x7FF || c >= 0xD800 && c <= 0xDFFF) {\n c = null;\n }\n }\n } else if (bytesPerSequence === 4) {\n b1 = buf[i + 1];\n b2 = buf[i + 2];\n b3 = buf[i + 3];\n\n if ((b1 & 0xC0) === 0x80 && (b2 & 0xC0) === 0x80 && (b3 & 0xC0) === 0x80) {\n c = (b0 & 0xF) << 0x12 | (b1 & 0x3F) << 0xC | (b2 & 0x3F) << 0x6 | b3 & 0x3F;\n\n if (c <= 0xFFFF || c >= 0x110000) {\n c = null;\n }\n }\n }\n\n if (c === null) {\n c = 0xFFFD;\n bytesPerSequence = 1;\n } else if (c > 0xFFFF) {\n c -= 0x10000;\n str += String.fromCharCode(c >>> 10 & 0x3FF | 0xD800);\n c = 0xDC00 | c & 0x3FF;\n }\n\n str += String.fromCharCode(c);\n i += bytesPerSequence;\n }\n\n return str;\n}\n\nfunction readUtf8TextDecoder(buf, pos, end) {\n return utf8TextDecoder.decode(buf.subarray(pos, end));\n}\n\nfunction writeUtf8(buf, str, pos) {\n for (var i = 0, c, lead; i < str.length; i++) {\n c = str.charCodeAt(i); // code point\n\n if (c > 0xD7FF && c < 0xE000) {\n if (lead) {\n if (c < 0xDC00) {\n buf[pos++] = 0xEF;\n buf[pos++] = 0xBF;\n buf[pos++] = 0xBD;\n lead = c;\n continue;\n } else {\n c = lead - 0xD800 << 10 | c - 0xDC00 | 0x10000;\n lead = null;\n }\n } else {\n if (c > 0xDBFF || i + 1 === str.length) {\n buf[pos++] = 0xEF;\n buf[pos++] = 0xBF;\n buf[pos++] = 0xBD;\n } else {\n lead = c;\n }\n\n continue;\n }\n } else if (lead) {\n buf[pos++] = 0xEF;\n buf[pos++] = 0xBF;\n buf[pos++] = 0xBD;\n lead = null;\n }\n\n if (c < 0x80) {\n buf[pos++] = c;\n } else {\n if (c < 0x800) {\n buf[pos++] = c >> 0x6 | 0xC0;\n } else {\n if (c < 0x10000) {\n buf[pos++] = c >> 0xC | 0xE0;\n } else {\n buf[pos++] = c >> 0x12 | 0xF0;\n buf[pos++] = c >> 0xC & 0x3F | 0x80;\n }\n\n buf[pos++] = c >> 0x6 & 0x3F | 0x80;\n }\n\n buf[pos++] = c & 0x3F | 0x80;\n }\n }\n\n return pos;\n}//# sourceURL=[module]\n//# sourceMappingURL=data:application/json;charset=utf-8;base64,eyJ2ZXJzaW9uIjozLCJzb3VyY2VzIjpbIndlYnBhY2s6Ly9qdXN0aWNlNDAtdG9vbC8uL25vZGVfbW9kdWxlcy9wYmYvaW5kZXguanM/NmVmZCJdLCJuYW1lcyI6W10sIm1hcHBpbmdzIjoiQUFBYTs7QUFFYjs7QUFFQSxjQUFjLG1CQUFPLENBQUMsSUFBUzs7QUFFL0I7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQUVBLGVBQWU7O0FBRWYsZ0JBQWdCOztBQUVoQixjQUFjOztBQUVkLGdCQUFnQjs7QUFFaEI7QUFDQSx1Q0FBdUM7QUFDdkM7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBLEdBQUc7QUFDSDtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBLEdBQUc7QUFDSDtBQUNBO0FBQ0EsR0FBRztBQUNIO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsR0FBRztBQUNIO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsR0FBRztBQUNIO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQSxHQUFHO0FBQ0g7QUFDQTtBQUNBO0FBQ0E7QUFDQSxHQUFHO0FBQ0g7QUFDQTtBQUNBO0FBQ0E7QUFDQSxHQUFHO0FBQ0g7QUFDQTtBQUNBO0FBQ0E7QUFDQSxHQUFHO0FBQ0g7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQSxHQUFHO0FBQ0g7QUFDQTtBQUNBO0FBQ0EsR0FBRztBQUNIO0FBQ0E7QUFDQSxvREFBb0Q7QUFDcEQsR0FBRztBQUNIO0FBQ0E7QUFDQSxHQUFHO0FBQ0g7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0EsS0FBSzs7O0FBR0w7QUFDQSxHQUFHO0FBQ0g7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBLEdBQUc7QUFDSCxxQ0FBcUM7QUFDckM7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBOztBQUVBO0FBQ0EsR0FBRztBQUNIO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBLEdBQUc7QUFDSDtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQSxHQUFHO0FBQ0g7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBOztBQUVBO0FBQ0EsR0FBRztBQUNIO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBLEdBQUc7QUFDSDtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQSxHQUFHO0FBQ0g7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBOztBQUVBO0FBQ0EsR0FBRztBQUNIO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBLEdBQUc7QUFDSDtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQSxHQUFHO0FBQ0g7QUFDQTtBQUNBLG1FQUFtRSxzRUFBc0UsNkNBQTZDLDZDQUE2QztBQUNuTyxHQUFHO0FBQ0g7QUFDQTtBQUNBO0FBQ0EsR0FBRztBQUNIO0FBQ0E7O0FBRUE7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBLEdBQUc7QUFDSDtBQUNBO0FBQ0E7QUFDQTtBQUNBLEdBQUc7QUFDSDtBQUNBO0FBQ0E7QUFDQTtBQUNBLEdBQUc7QUFDSDtBQUNBO0FBQ0E7QUFDQTtBQUNBLEdBQUc7QUFDSDtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsR0FBRztBQUNIO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQSxHQUFHO0FBQ0g7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsR0FBRztBQUNIO0FBQ0E7QUFDQSxHQUFHO0FBQ0g7QUFDQTtBQUNBLEdBQUc7QUFDSDtBQUNBO0FBQ0E7QUFDQSxlQUFlOztBQUVmLDRCQUE0Qjs7QUFFNUI7QUFDQTtBQUNBLGlFQUFpRTs7QUFFakU7QUFDQTtBQUNBO0FBQ0EsR0FBRztBQUNIO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsR0FBRztBQUNIO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsR0FBRztBQUNIO0FBQ0E7QUFDQTtBQUNBOztBQUVBLG1CQUFtQixTQUFTO0FBQzVCO0FBQ0E7QUFDQSxHQUFHO0FBQ0g7QUFDQSxlQUFlO0FBQ2Y7O0FBRUE7QUFDQTtBQUNBO0FBQ0EsaUVBQWlFOztBQUVqRTtBQUNBO0FBQ0E7QUFDQSxHQUFHO0FBQ0g7QUFDQTtBQUNBO0FBQ0EsR0FBRztBQUNIO0FBQ0E7QUFDQSxHQUFHO0FBQ0g7QUFDQTtBQUNBLEdBQUc7QUFDSDtBQUNBO0FBQ0EsR0FBRztBQUNIO0FBQ0E7QUFDQSxHQUFHO0FBQ0g7QUFDQTtBQUNBLEdBQUc7QUFDSDtBQUNBO0FBQ0EsR0FBRztBQUNIO0FBQ0E7QUFDQSxHQUFHO0FBQ0g7QUFDQTtBQUNBLEdBQUc7QUFDSDtBQUNBO0FBQ0EsR0FBRztBQUNIO0FBQ0E7QUFDQTtBQUNBLEdBQUc7QUFDSDtBQUNBO0FBQ0E7QUFDQSxHQUFHO0FBQ0g7QUFDQTtBQUNBO0FBQ0EsR0FBRztBQUNIO0FBQ0E7QUFDQTtBQUNBLEdBQUc7QUFDSDtBQUNBO0FBQ0E7QUFDQSxHQUFHO0FBQ0g7QUFDQTtBQUNBO0FBQ0EsR0FBRztBQUNIO0FBQ0E7QUFDQTtBQUNBLEdBQUc7QUFDSDtBQUNBO0FBQ0E7QUFDQSxHQUFHO0FBQ0g7QUFDQTtBQUNBO0FBQ0EsR0FBRztBQUNIO0FBQ0E7QUFDQTtBQUNBLEdBQUc7QUFDSDtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7O0FBRUE7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQSxHQUFHO0FBQ0g7QUFDQTs7QUFFQTtBQUNBO0FBQ0EsS0FBSztBQUNMO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQSw2SEFBNkg7O0FBRTdIOztBQUVBLDJCQUEyQixlQUFlO0FBQzFDO0FBQ0E7QUFDQTs7QUFFQTtBQUNBLGlCQUFpQixnQkFBZ0I7QUFDakM7QUFDQTtBQUNBOztBQUVBO0FBQ0EsaUJBQWlCLGdCQUFnQjtBQUNqQztBQUNBO0FBQ0E7O0FBRUE7QUFDQSxpQkFBaUIsZ0JBQWdCO0FBQ2pDO0FBQ0E7QUFDQTs7QUFFQTtBQUNBLGlCQUFpQixnQkFBZ0I7QUFDakM7QUFDQTtBQUNBOztBQUVBO0FBQ0EsaUJBQWlCLGdCQUFnQjtBQUNqQztBQUNBO0FBQ0E7O0FBRUE7QUFDQSxpQkFBaUIsZ0JBQWdCO0FBQ2pDO0FBQ0E7QUFDQTs7QUFFQTtBQUNBLGlCQUFpQixnQkFBZ0I7QUFDakM7QUFDQTtBQUNBOztBQUVBO0FBQ0EsaUJBQWlCLGdCQUFnQjtBQUNqQztBQUNBO0FBQ0E7O0FBRUE7QUFDQSxpQkFBaUIsZ0JBQWdCO0FBQ2pDO0FBQ0E7QUFDQSxDQUFDOzs7QUFHRDtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBLGlCQUFpQjs7QUFFakI7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsS0FBSztBQUNMOztBQUVBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQSxLQUFLO0FBQ0w7QUFDQTs7QUFFQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsS0FBSztBQUNMO0FBQ0E7QUFDQTs7QUFFQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0EsS0FBSztBQUNMO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBLDBCQUEwQixnQkFBZ0I7QUFDMUMsMEJBQTBCOztBQUUxQjtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsU0FBUztBQUNUO0FBQ0E7QUFDQTtBQUNBLE9BQU87QUFDUDtBQUNBO0FBQ0E7QUFDQTtBQUNBLFNBQVM7QUFDVDtBQUNBOztBQUVBO0FBQ0E7QUFDQSxLQUFLO0FBQ0w7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0EsS0FBSztBQUNMO0FBQ0E7QUFDQSxPQUFPO0FBQ1A7QUFDQTtBQUNBLFNBQVM7QUFDVDtBQUNBO0FBQ0E7O0FBRUE7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQSIsImZpbGUiOiI0MzYyLmpzIiwic291cmNlc0NvbnRlbnQiOlsiJ3VzZSBzdHJpY3QnO1xuXG5tb2R1bGUuZXhwb3J0cyA9IFBiZjtcblxudmFyIGllZWU3NTQgPSByZXF1aXJlKCdpZWVlNzU0Jyk7XG5cbmZ1bmN0aW9uIFBiZihidWYpIHtcbiAgdGhpcy5idWYgPSBBcnJheUJ1ZmZlci5pc1ZpZXcgJiYgQXJyYXlCdWZmZXIuaXNWaWV3KGJ1ZikgPyBidWYgOiBuZXcgVWludDhBcnJheShidWYgfHwgMCk7XG4gIHRoaXMucG9zID0gMDtcbiAgdGhpcy50eXBlID0gMDtcbiAgdGhpcy5sZW5ndGggPSB0aGlzLmJ1Zi5sZW5ndGg7XG59XG5cblBiZi5WYXJpbnQgPSAwOyAvLyB2YXJpbnQ6IGludDMyLCBpbnQ2NCwgdWludDMyLCB1aW50NjQsIHNpbnQzMiwgc2ludDY0LCBib29sLCBlbnVtXG5cblBiZi5GaXhlZDY0ID0gMTsgLy8gNjQtYml0OiBkb3VibGUsIGZpeGVkNjQsIHNmaXhlZDY0XG5cblBiZi5CeXRlcyA9IDI7IC8vIGxlbmd0aC1kZWxpbWl0ZWQ6IHN0cmluZywgYnl0ZXMsIGVtYmVkZGVkIG1lc3NhZ2VzLCBwYWNrZWQgcmVwZWF0ZWQgZmllbGRzXG5cblBiZi5GaXhlZDMyID0gNTsgLy8gMzItYml0OiBmbG9hdCwgZml4ZWQzMiwgc2ZpeGVkMzJcblxudmFyIFNISUZUX0xFRlRfMzIgPSAoMSA8PCAxNikgKiAoMSA8PCAxNiksXG4gICAgU0hJRlRfUklHSFRfMzIgPSAxIC8gU0hJRlRfTEVGVF8zMjsgLy8gVGhyZXNob2xkIGNob3NlbiBiYXNlZCBvbiBib3RoIGJlbmNobWFya2luZyBhbmQga25vd2xlZGdlIGFib3V0IGJyb3dzZXIgc3RyaW5nXG4vLyBkYXRhIHN0cnVjdHVyZXMgKHdoaWNoIGN1cnJlbnRseSBzd2l0Y2ggc3RydWN0dXJlIHR5cGVzIGF0IDEyIGJ5dGVzIG9yIG1vcmUpXG5cbnZhciBURVhUX0RFQ09ERVJfTUlOX0xFTkdUSCA9IDEyO1xudmFyIHV0ZjhUZXh0RGVjb2RlciA9IHR5cGVvZiBUZXh0RGVjb2RlciA9PT0gJ3VuZGVmaW5lZCcgPyBudWxsIDogbmV3IFRleHREZWNvZGVyKCd1dGY4Jyk7XG5QYmYucHJvdG90eXBlID0ge1xuICBkZXN0cm95OiBmdW5jdGlvbiBkZXN0cm95KCkge1xuICAgIHRoaXMuYnVmID0gbnVsbDtcbiAgfSxcbiAgLy8gPT09IFJFQURJTkcgPT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT1cbiAgcmVhZEZpZWxkczogZnVuY3Rpb24gcmVhZEZpZWxkcyhyZWFkRmllbGQsIHJlc3VsdCwgZW5kKSB7XG4gICAgZW5kID0gZW5kIHx8IHRoaXMubGVuZ3RoO1xuXG4gICAgd2hpbGUgKHRoaXMucG9zIDwgZW5kKSB7XG4gICAgICB2YXIgdmFsID0gdGhpcy5yZWFkVmFyaW50KCksXG4gICAgICAgICAgdGFnID0gdmFsID4+IDMsXG4gICAgICAgICAgc3RhcnRQb3MgPSB0aGlzLnBvcztcbiAgICAgIHRoaXMudHlwZSA9IHZhbCAmIDB4NztcbiAgICAgIHJlYWRGaWVsZCh0YWcsIHJlc3VsdCwgdGhpcyk7XG4gICAgICBpZiAodGhpcy5wb3MgPT09IHN0YXJ0UG9zKSB0aGlzLnNraXAodmFsKTtcbiAgICB9XG5cbiAgICByZXR1cm4gcmVzdWx0O1xuICB9LFxuICByZWFkTWVzc2FnZTogZnVuY3Rpb24gcmVhZE1lc3NhZ2UocmVhZEZpZWxkLCByZXN1bHQpIHtcbiAgICByZXR1cm4gdGhpcy5yZWFkRmllbGRzKHJlYWRGaWVsZCwgcmVzdWx0LCB0aGlzLnJlYWRWYXJpbnQoKSArIHRoaXMucG9zKTtcbiAgfSxcbiAgcmVhZEZpeGVkMzI6IGZ1bmN0aW9uIHJlYWRGaXhlZDMyKCkge1xuICAgIHZhciB2YWwgPSByZWFkVUludDMyKHRoaXMuYnVmLCB0aGlzLnBvcyk7XG4gICAgdGhpcy5wb3MgKz0gNDtcbiAgICByZXR1cm4gdmFsO1xuICB9LFxuICByZWFkU0ZpeGVkMzI6IGZ1bmN0aW9uIHJlYWRTRml4ZWQzMigpIHtcbiAgICB2YXIgdmFsID0gcmVhZEludDMyKHRoaXMuYnVmLCB0aGlzLnBvcyk7XG4gICAgdGhpcy5wb3MgKz0gNDtcbiAgICByZXR1cm4gdmFsO1xuICB9LFxuICAvLyA2NC1iaXQgaW50IGhhbmRsaW5nIGlzIGJhc2VkIG9uIGdpdGh1Yi5jb20vZHB3L25vZGUtYnVmZmVyLW1vcmUtaW50cyAoTUlULWxpY2Vuc2VkKVxuICByZWFkRml4ZWQ2NDogZnVuY3Rpb24gcmVhZEZpeGVkNjQoKSB7XG4gICAgdmFyIHZhbCA9IHJlYWRVSW50MzIodGhpcy5idWYsIHRoaXMucG9zKSArIHJlYWRVSW50MzIodGhpcy5idWYsIHRoaXMucG9zICsgNCkgKiBTSElGVF9MRUZUXzMyO1xuICAgIHRoaXMucG9zICs9IDg7XG4gICAgcmV0dXJuIHZhbDtcbiAgfSxcbiAgcmVhZFNGaXhlZDY0OiBmdW5jdGlvbiByZWFkU0ZpeGVkNjQoKSB7XG4gICAgdmFyIHZhbCA9IHJlYWRVSW50MzIodGhpcy5idWYsIHRoaXMucG9zKSArIHJlYWRJbnQzMih0aGlzLmJ1ZiwgdGhpcy5wb3MgKyA0KSAqIFNISUZUX0xFRlRfMzI7XG4gICAgdGhpcy5wb3MgKz0gODtcbiAgICByZXR1cm4gdmFsO1xuICB9LFxuICByZWFkRmxvYXQ6IGZ1bmN0aW9uIHJlYWRGbG9hdCgpIHtcbiAgICB2YXIgdmFsID0gaWVlZTc1NC5yZWFkKHRoaXMuYnVmLCB0aGlzLnBvcywgdHJ1ZSwgMjMsIDQpO1xuICAgIHRoaXMucG9zICs9IDQ7XG4gICAgcmV0dXJuIHZhbDtcbiAgfSxcbiAgcmVhZERvdWJsZTogZnVuY3Rpb24gcmVhZERvdWJsZSgpIHtcbiAgICB2YXIgdmFsID0gaWVlZTc1NC5yZWFkKHRoaXMuYnVmLCB0aGlzLnBvcywgdHJ1ZSwgNTIsIDgpO1xuICAgIHRoaXMucG9zICs9IDg7XG4gICAgcmV0dXJuIHZhbDtcbiAgfSxcbiAgcmVhZFZhcmludDogZnVuY3Rpb24gcmVhZFZhcmludChpc1NpZ25lZCkge1xuICAgIHZhciBidWYgPSB0aGlzLmJ1ZixcbiAgICAgICAgdmFsLFxuICAgICAgICBiO1xuICAgIGIgPSBidWZbdGhpcy5wb3MrK107XG4gICAgdmFsID0gYiAmIDB4N2Y7XG4gICAgaWYgKGIgPCAweDgwKSByZXR1cm4gdmFsO1xuICAgIGIgPSBidWZbdGhpcy5wb3MrK107XG4gICAgdmFsIHw9IChiICYgMHg3ZikgPDwgNztcbiAgICBpZiAoYiA8IDB4ODApIHJldHVybiB2YWw7XG4gICAgYiA9IGJ1Zlt0aGlzLnBvcysrXTtcbiAgICB2YWwgfD0gKGIgJiAweDdmKSA8PCAxNDtcbiAgICBpZiAoYiA8IDB4ODApIHJldHVybiB2YWw7XG4gICAgYiA9IGJ1Zlt0aGlzLnBvcysrXTtcbiAgICB2YWwgfD0gKGIgJiAweDdmKSA8PCAyMTtcbiAgICBpZiAoYiA8IDB4ODApIHJldHVybiB2YWw7XG4gICAgYiA9IGJ1Zlt0aGlzLnBvc107XG4gICAgdmFsIHw9IChiICYgMHgwZikgPDwgMjg7XG4gICAgcmV0dXJuIHJlYWRWYXJpbnRSZW1haW5kZXIodmFsLCBpc1NpZ25lZCwgdGhpcyk7XG4gIH0sXG4gIHJlYWRWYXJpbnQ2NDogZnVuY3Rpb24gcmVhZFZhcmludDY0KCkge1xuICAgIC8vIGZvciBjb21wYXRpYmlsaXR5IHdpdGggdjIuMC4xXG4gICAgcmV0dXJuIHRoaXMucmVhZFZhcmludCh0cnVlKTtcbiAgfSxcbiAgcmVhZFNWYXJpbnQ6IGZ1bmN0aW9uIHJlYWRTVmFyaW50KCkge1xuICAgIHZhciBudW0gPSB0aGlzLnJlYWRWYXJpbnQoKTtcbiAgICByZXR1cm4gbnVtICUgMiA9PT0gMSA/IChudW0gKyAxKSAvIC0yIDogbnVtIC8gMjsgLy8gemlnemFnIGVuY29kaW5nXG4gIH0sXG4gIHJlYWRCb29sZWFuOiBmdW5jdGlvbiByZWFkQm9vbGVhbigpIHtcbiAgICByZXR1cm4gQm9vbGVhbih0aGlzLnJlYWRWYXJpbnQoKSk7XG4gIH0sXG4gIHJlYWRTdHJpbmc6IGZ1bmN0aW9uIHJlYWRTdHJpbmcoKSB7XG4gICAgdmFyIGVuZCA9IHRoaXMucmVhZFZhcmludCgpICsgdGhpcy5wb3M7XG4gICAgdmFyIHBvcyA9IHRoaXMucG9zO1xuICAgIHRoaXMucG9zID0gZW5kO1xuXG4gICAgaWYgKGVuZCAtIHBvcyA+PSBURVhUX0RFQ09ERVJfTUlOX0xFTkdUSCAmJiB1dGY4VGV4dERlY29kZXIpIHtcbiAgICAgIC8vIGxvbmdlciBzdHJpbmdzIGFyZSBmYXN0IHdpdGggdGhlIGJ1aWx0LWluIGJyb3dzZXIgVGV4dERlY29kZXIgQVBJXG4gICAgICByZXR1cm4gcmVhZFV0ZjhUZXh0RGVjb2Rlcih0aGlzLmJ1ZiwgcG9zLCBlbmQpO1xuICAgIH0gLy8gc2hvcnQgc3RyaW5ncyBhcmUgZmFzdCB3aXRoIG91ciBjdXN0b20gaW1wbGVtZW50YXRpb25cblxuXG4gICAgcmV0dXJuIHJlYWRVdGY4KHRoaXMuYnVmLCBwb3MsIGVuZCk7XG4gIH0sXG4gIHJlYWRCeXRlczogZnVuY3Rpb24gcmVhZEJ5dGVzKCkge1xuICAgIHZhciBlbmQgPSB0aGlzLnJlYWRWYXJpbnQoKSArIHRoaXMucG9zLFxuICAgICAgICBidWZmZXIgPSB0aGlzLmJ1Zi5zdWJhcnJheSh0aGlzLnBvcywgZW5kKTtcbiAgICB0aGlzLnBvcyA9IGVuZDtcbiAgICByZXR1cm4gYnVmZmVyO1xuICB9LFxuICAvLyB2ZXJib3NlIGZvciBwZXJmb3JtYW5jZSByZWFzb25zOyBkb2Vzbid0IGFmZmVjdCBnemlwcGVkIHNpemVcbiAgcmVhZFBhY2tlZFZhcmludDogZnVuY3Rpb24gcmVhZFBhY2tlZFZhcmludChhcnIsIGlzU2lnbmVkKSB7XG4gICAgaWYgKHRoaXMudHlwZSAhPT0gUGJmLkJ5dGVzKSByZXR1cm4gYXJyLnB1c2godGhpcy5yZWFkVmFyaW50KGlzU2lnbmVkKSk7XG4gICAgdmFyIGVuZCA9IHJlYWRQYWNrZWRFbmQodGhpcyk7XG4gICAgYXJyID0gYXJyIHx8IFtdO1xuXG4gICAgd2hpbGUgKHRoaXMucG9zIDwgZW5kKSB7XG4gICAgICBhcnIucHVzaCh0aGlzLnJlYWRWYXJpbnQoaXNTaWduZWQpKTtcbiAgICB9XG5cbiAgICByZXR1cm4gYXJyO1xuICB9LFxuICByZWFkUGFja2VkU1ZhcmludDogZnVuY3Rpb24gcmVhZFBhY2tlZFNWYXJpbnQoYXJyKSB7XG4gICAgaWYgKHRoaXMudHlwZSAhPT0gUGJmLkJ5dGVzKSByZXR1cm4gYXJyLnB1c2godGhpcy5yZWFkU1ZhcmludCgpKTtcbiAgICB2YXIgZW5kID0gcmVhZFBhY2tlZEVuZCh0aGlzKTtcbiAgICBhcnIgPSBhcnIgfHwgW107XG5cbiAgICB3aGlsZSAodGhpcy5wb3MgPCBlbmQpIHtcbiAgICAgIGFyci5wdXNoKHRoaXMucmVhZFNWYXJpbnQoKSk7XG4gICAgfVxuXG4gICAgcmV0dXJuIGFycjtcbiAgfSxcbiAgcmVhZFBhY2tlZEJvb2xlYW46IGZ1bmN0aW9uIHJlYWRQYWNrZWRCb29sZWFuKGFycikge1xuICAgIGlmICh0aGlzLnR5cGUgIT09IFBiZi5CeXRlcykgcmV0dXJuIGFyci5wdXNoKHRoaXMucmVhZEJvb2xlYW4oKSk7XG4gICAgdmFyIGVuZCA9IHJlYWRQYWNrZWRFbmQodGhpcyk7XG4gICAgYXJyID0gYXJyIHx8IFtdO1xuXG4gICAgd2hpbGUgKHRoaXMucG9zIDwgZW5kKSB7XG4gICAgICBhcnIucHVzaCh0aGlzLnJlYWRCb29sZWFuKCkpO1xuICAgIH1cblxuICAgIHJldHVybiBhcnI7XG4gIH0sXG4gIHJlYWRQYWNrZWRGbG9hdDogZnVuY3Rpb24gcmVhZFBhY2tlZEZsb2F0KGFycikge1xuICAgIGlmICh0aGlzLnR5cGUgIT09IFBiZi5CeXRlcykgcmV0dXJuIGFyci5wdXNoKHRoaXMucmVhZEZsb2F0KCkpO1xuICAgIHZhciBlbmQgPSByZWFkUGFja2VkRW5kKHRoaXMpO1xuICAgIGFyciA9IGFyciB8fCBbXTtcblxuICAgIHdoaWxlICh0aGlzLnBvcyA8IGVuZCkge1xuICAgICAgYXJyLnB1c2godGhpcy5yZWFkRmxvYXQoKSk7XG4gICAgfVxuXG4gICAgcmV0dXJuIGFycjtcbiAgfSxcbiAgcmVhZFBhY2tlZERvdWJsZTogZnVuY3Rpb24gcmVhZFBhY2tlZERvdWJsZShhcnIpIHtcbiAgICBpZiAodGhpcy50eXBlICE9PSBQYmYuQnl0ZXMpIHJldHVybiBhcnIucHVzaCh0aGlzLnJlYWREb3VibGUoKSk7XG4gICAgdmFyIGVuZCA9IHJlYWRQYWNrZWRFbmQodGhpcyk7XG4gICAgYXJyID0gYXJyIHx8IFtdO1xuXG4gICAgd2hpbGUgKHRoaXMucG9zIDwgZW5kKSB7XG4gICAgICBhcnIucHVzaCh0aGlzLnJlYWREb3VibGUoKSk7XG4gICAgfVxuXG4gICAgcmV0dXJuIGFycjtcbiAgfSxcbiAgcmVhZFBhY2tlZEZpeGVkMzI6IGZ1bmN0aW9uIHJlYWRQYWNrZWRGaXhlZDMyKGFycikge1xuICAgIGlmICh0aGlzLnR5cGUgIT09IFBiZi5CeXRlcykgcmV0dXJuIGFyci5wdXNoKHRoaXMucmVhZEZpeGVkMzIoKSk7XG4gICAgdmFyIGVuZCA9IHJlYWRQYWNrZWRFbmQodGhpcyk7XG4gICAgYXJyID0gYXJyIHx8IFtdO1xuXG4gICAgd2hpbGUgKHRoaXMucG9zIDwgZW5kKSB7XG4gICAgICBhcnIucHVzaCh0aGlzLnJlYWRGaXhlZDMyKCkpO1xuICAgIH1cblxuICAgIHJldHVybiBhcnI7XG4gIH0sXG4gIHJlYWRQYWNrZWRTRml4ZWQzMjogZnVuY3Rpb24gcmVhZFBhY2tlZFNGaXhlZDMyKGFycikge1xuICAgIGlmICh0aGlzLnR5cGUgIT09IFBiZi5CeXRlcykgcmV0dXJuIGFyci5wdXNoKHRoaXMucmVhZFNGaXhlZDMyKCkpO1xuICAgIHZhciBlbmQgPSByZWFkUGFja2VkRW5kKHRoaXMpO1xuICAgIGFyciA9IGFyciB8fCBbXTtcblxuICAgIHdoaWxlICh0aGlzLnBvcyA8IGVuZCkge1xuICAgICAgYXJyLnB1c2godGhpcy5yZWFkU0ZpeGVkMzIoKSk7XG4gICAgfVxuXG4gICAgcmV0dXJuIGFycjtcbiAgfSxcbiAgcmVhZFBhY2tlZEZpeGVkNjQ6IGZ1bmN0aW9uIHJlYWRQYWNrZWRGaXhlZDY0KGFycikge1xuICAgIGlmICh0aGlzLnR5cGUgIT09IFBiZi5CeXRlcykgcmV0dXJuIGFyci5wdXNoKHRoaXMucmVhZEZpeGVkNjQoKSk7XG4gICAgdmFyIGVuZCA9IHJlYWRQYWNrZWRFbmQodGhpcyk7XG4gICAgYXJyID0gYXJyIHx8IFtdO1xuXG4gICAgd2hpbGUgKHRoaXMucG9zIDwgZW5kKSB7XG4gICAgICBhcnIucHVzaCh0aGlzLnJlYWRGaXhlZDY0KCkpO1xuICAgIH1cblxuICAgIHJldHVybiBhcnI7XG4gIH0sXG4gIHJlYWRQYWNrZWRTRml4ZWQ2NDogZnVuY3Rpb24gcmVhZFBhY2tlZFNGaXhlZDY0KGFycikge1xuICAgIGlmICh0aGlzLnR5cGUgIT09IFBiZi5CeXRlcykgcmV0dXJuIGFyci5wdXNoKHRoaXMucmVhZFNGaXhlZDY0KCkpO1xuICAgIHZhciBlbmQgPSByZWFkUGFja2VkRW5kKHRoaXMpO1xuICAgIGFyciA9IGFyciB8fCBbXTtcblxuICAgIHdoaWxlICh0aGlzLnBvcyA8IGVuZCkge1xuICAgICAgYXJyLnB1c2godGhpcy5yZWFkU0ZpeGVkNjQoKSk7XG4gICAgfVxuXG4gICAgcmV0dXJuIGFycjtcbiAgfSxcbiAgc2tpcDogZnVuY3Rpb24gc2tpcCh2YWwpIHtcbiAgICB2YXIgdHlwZSA9IHZhbCAmIDB4NztcbiAgICBpZiAodHlwZSA9PT0gUGJmLlZhcmludCkgd2hpbGUgKHRoaXMuYnVmW3RoaXMucG9zKytdID4gMHg3Zikge30gZWxzZSBpZiAodHlwZSA9PT0gUGJmLkJ5dGVzKSB0aGlzLnBvcyA9IHRoaXMucmVhZFZhcmludCgpICsgdGhpcy5wb3M7ZWxzZSBpZiAodHlwZSA9PT0gUGJmLkZpeGVkMzIpIHRoaXMucG9zICs9IDQ7ZWxzZSBpZiAodHlwZSA9PT0gUGJmLkZpeGVkNjQpIHRoaXMucG9zICs9IDg7ZWxzZSB0aHJvdyBuZXcgRXJyb3IoJ1VuaW1wbGVtZW50ZWQgdHlwZTogJyArIHR5cGUpO1xuICB9LFxuICAvLyA9PT0gV1JJVElORyA9PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PVxuICB3cml0ZVRhZzogZnVuY3Rpb24gd3JpdGVUYWcodGFnLCB0eXBlKSB7XG4gICAgdGhpcy53cml0ZVZhcmludCh0YWcgPDwgMyB8IHR5cGUpO1xuICB9LFxuICByZWFsbG9jOiBmdW5jdGlvbiByZWFsbG9jKG1pbikge1xuICAgIHZhciBsZW5ndGggPSB0aGlzLmxlbmd0aCB8fCAxNjtcblxuICAgIHdoaWxlIChsZW5ndGggPCB0aGlzLnBvcyArIG1pbikge1xuICAgICAgbGVuZ3RoICo9IDI7XG4gICAgfVxuXG4gICAgaWYgKGxlbmd0aCAhPT0gdGhpcy5sZW5ndGgpIHtcbiAgICAgIHZhciBidWYgPSBuZXcgVWludDhBcnJheShsZW5ndGgpO1xuICAgICAgYnVmLnNldCh0aGlzLmJ1Zik7XG4gICAgICB0aGlzLmJ1ZiA9IGJ1ZjtcbiAgICAgIHRoaXMubGVuZ3RoID0gbGVuZ3RoO1xuICAgIH1cbiAgfSxcbiAgZmluaXNoOiBmdW5jdGlvbiBmaW5pc2goKSB7XG4gICAgdGhpcy5sZW5ndGggPSB0aGlzLnBvcztcbiAgICB0aGlzLnBvcyA9IDA7XG4gICAgcmV0dXJuIHRoaXMuYnVmLnN1YmFycmF5KDAsIHRoaXMubGVuZ3RoKTtcbiAgfSxcbiAgd3JpdGVGaXhlZDMyOiBmdW5jdGlvbiB3cml0ZUZpeGVkMzIodmFsKSB7XG4gICAgdGhpcy5yZWFsbG9jKDQpO1xuICAgIHdyaXRlSW50MzIodGhpcy5idWYsIHZhbCwgdGhpcy5wb3MpO1xuICAgIHRoaXMucG9zICs9IDQ7XG4gIH0sXG4gIHdyaXRlU0ZpeGVkMzI6IGZ1bmN0aW9uIHdyaXRlU0ZpeGVkMzIodmFsKSB7XG4gICAgdGhpcy5yZWFsbG9jKDQpO1xuICAgIHdyaXRlSW50MzIodGhpcy5idWYsIHZhbCwgdGhpcy5wb3MpO1xuICAgIHRoaXMucG9zICs9IDQ7XG4gIH0sXG4gIHdyaXRlRml4ZWQ2NDogZnVuY3Rpb24gd3JpdGVGaXhlZDY0KHZhbCkge1xuICAgIHRoaXMucmVhbGxvYyg4KTtcbiAgICB3cml0ZUludDMyKHRoaXMuYnVmLCB2YWwgJiAtMSwgdGhpcy5wb3MpO1xuICAgIHdyaXRlSW50MzIodGhpcy5idWYsIE1hdGguZmxvb3IodmFsICogU0hJRlRfUklHSFRfMzIpLCB0aGlzLnBvcyArIDQpO1xuICAgIHRoaXMucG9zICs9IDg7XG4gIH0sXG4gIHdyaXRlU0ZpeGVkNjQ6IGZ1bmN0aW9uIHdyaXRlU0ZpeGVkNjQodmFsKSB7XG4gICAgdGhpcy5yZWFsbG9jKDgpO1xuICAgIHdyaXRlSW50MzIodGhpcy5idWYsIHZhbCAmIC0xLCB0aGlzLnBvcyk7XG4gICAgd3JpdGVJbnQzMih0aGlzLmJ1ZiwgTWF0aC5mbG9vcih2YWwgKiBTSElGVF9SSUdIVF8zMiksIHRoaXMucG9zICsgNCk7XG4gICAgdGhpcy5wb3MgKz0gODtcbiAgfSxcbiAgd3JpdGVWYXJpbnQ6IGZ1bmN0aW9uIHdyaXRlVmFyaW50KHZhbCkge1xuICAgIHZhbCA9ICt2YWwgfHwgMDtcblxuICAgIGlmICh2YWwgPiAweGZmZmZmZmYgfHwgdmFsIDwgMCkge1xuICAgICAgd3JpdGVCaWdWYXJpbnQodmFsLCB0aGlzKTtcbiAgICAgIHJldHVybjtcbiAgICB9XG5cbiAgICB0aGlzLnJlYWxsb2MoNCk7XG4gICAgdGhpcy5idWZbdGhpcy5wb3MrK10gPSB2YWwgJiAweDdmIHwgKHZhbCA+IDB4N2YgPyAweDgwIDogMCk7XG4gICAgaWYgKHZhbCA8PSAweDdmKSByZXR1cm47XG4gICAgdGhpcy5idWZbdGhpcy5wb3MrK10gPSAodmFsID4+Pj0gNykgJiAweDdmIHwgKHZhbCA+IDB4N2YgPyAweDgwIDogMCk7XG4gICAgaWYgKHZhbCA8PSAweDdmKSByZXR1cm47XG4gICAgdGhpcy5idWZbdGhpcy5wb3MrK10gPSAodmFsID4+Pj0gNykgJiAweDdmIHwgKHZhbCA+IDB4N2YgPyAweDgwIDogMCk7XG4gICAgaWYgKHZhbCA8PSAweDdmKSByZXR1cm47XG4gICAgdGhpcy5idWZbdGhpcy5wb3MrK10gPSB2YWwgPj4+IDcgJiAweDdmO1xuICB9LFxuICB3cml0ZVNWYXJpbnQ6IGZ1bmN0aW9uIHdyaXRlU1ZhcmludCh2YWwpIHtcbiAgICB0aGlzLndyaXRlVmFyaW50KHZhbCA8IDAgPyAtdmFsICogMiAtIDEgOiB2YWwgKiAyKTtcbiAgfSxcbiAgd3JpdGVCb29sZWFuOiBmdW5jdGlvbiB3cml0ZUJvb2xlYW4odmFsKSB7XG4gICAgdGhpcy53cml0ZVZhcmludChCb29sZWFuKHZhbCkpO1xuICB9LFxuICB3cml0ZVN0cmluZzogZnVuY3Rpb24gd3JpdGVTdHJpbmcoc3RyKSB7XG4gICAgc3RyID0gU3RyaW5nKHN0cik7XG4gICAgdGhpcy5yZWFsbG9jKHN0ci5sZW5ndGggKiA0KTtcbiAgICB0aGlzLnBvcysrOyAvLyByZXNlcnZlIDEgYnl0ZSBmb3Igc2hvcnQgc3RyaW5nIGxlbmd0aFxuXG4gICAgdmFyIHN0YXJ0UG9zID0gdGhpcy5wb3M7IC8vIHdyaXRlIHRoZSBzdHJpbmcgZGlyZWN0bHkgdG8gdGhlIGJ1ZmZlciBhbmQgc2VlIGhvdyBtdWNoIHdhcyB3cml0dGVuXG5cbiAgICB0aGlzLnBvcyA9IHdyaXRlVXRmOCh0aGlzLmJ1Ziwgc3RyLCB0aGlzLnBvcyk7XG4gICAgdmFyIGxlbiA9IHRoaXMucG9zIC0gc3RhcnRQb3M7XG4gICAgaWYgKGxlbiA+PSAweDgwKSBtYWtlUm9vbUZvckV4dHJhTGVuZ3RoKHN0YXJ0UG9zLCBsZW4sIHRoaXMpOyAvLyBmaW5hbGx5LCB3cml0ZSB0aGUgbWVzc2FnZSBsZW5ndGggaW4gdGhlIHJlc2VydmVkIHBsYWNlIGFuZCByZXN0b3JlIHRoZSBwb3NpdGlvblxuXG4gICAgdGhpcy5wb3MgPSBzdGFydFBvcyAtIDE7XG4gICAgdGhpcy53cml0ZVZhcmludChsZW4pO1xuICAgIHRoaXMucG9zICs9IGxlbjtcbiAgfSxcbiAgd3JpdGVGbG9hdDogZnVuY3Rpb24gd3JpdGVGbG9hdCh2YWwpIHtcbiAgICB0aGlzLnJlYWxsb2MoNCk7XG4gICAgaWVlZTc1NC53cml0ZSh0aGlzLmJ1ZiwgdmFsLCB0aGlzLnBvcywgdHJ1ZSwgMjMsIDQpO1xuICAgIHRoaXMucG9zICs9IDQ7XG4gIH0sXG4gIHdyaXRlRG91YmxlOiBmdW5jdGlvbiB3cml0ZURvdWJsZSh2YWwpIHtcbiAgICB0aGlzLnJlYWxsb2MoOCk7XG4gICAgaWVlZTc1NC53cml0ZSh0aGlzLmJ1ZiwgdmFsLCB0aGlzLnBvcywgdHJ1ZSwgNTIsIDgpO1xuICAgIHRoaXMucG9zICs9IDg7XG4gIH0sXG4gIHdyaXRlQnl0ZXM6IGZ1bmN0aW9uIHdyaXRlQnl0ZXMoYnVmZmVyKSB7XG4gICAgdmFyIGxlbiA9IGJ1ZmZlci5sZW5ndGg7XG4gICAgdGhpcy53cml0ZVZhcmludChsZW4pO1xuICAgIHRoaXMucmVhbGxvYyhsZW4pO1xuXG4gICAgZm9yICh2YXIgaSA9IDA7IGkgPCBsZW47IGkrKykge1xuICAgICAgdGhpcy5idWZbdGhpcy5wb3MrK10gPSBidWZmZXJbaV07XG4gICAgfVxuICB9LFxuICB3cml0ZVJhd01lc3NhZ2U6IGZ1bmN0aW9uIHdyaXRlUmF3TWVzc2FnZShmbiwgb2JqKSB7XG4gICAgdGhpcy5wb3MrKzsgLy8gcmVzZXJ2ZSAxIGJ5dGUgZm9yIHNob3J0IG1lc3NhZ2UgbGVuZ3RoXG4gICAgLy8gd3JpdGUgdGhlIG1lc3NhZ2UgZGlyZWN0bHkgdG8gdGhlIGJ1ZmZlciBhbmQgc2VlIGhvdyBtdWNoIHdhcyB3cml0dGVuXG5cbiAgICB2YXIgc3RhcnRQb3MgPSB0aGlzLnBvcztcbiAgICBmbihvYmosIHRoaXMpO1xuICAgIHZhciBsZW4gPSB0aGlzLnBvcyAtIHN0YXJ0UG9zO1xuICAgIGlmIChsZW4gPj0gMHg4MCkgbWFrZVJvb21Gb3JFeHRyYUxlbmd0aChzdGFydFBvcywgbGVuLCB0aGlzKTsgLy8gZmluYWxseSwgd3JpdGUgdGhlIG1lc3NhZ2UgbGVuZ3RoIGluIHRoZSByZXNlcnZlZCBwbGFjZSBhbmQgcmVzdG9yZSB0aGUgcG9zaXRpb25cblxuICAgIHRoaXMucG9zID0gc3RhcnRQb3MgLSAxO1xuICAgIHRoaXMud3JpdGVWYXJpbnQobGVuKTtcbiAgICB0aGlzLnBvcyArPSBsZW47XG4gIH0sXG4gIHdyaXRlTWVzc2FnZTogZnVuY3Rpb24gd3JpdGVNZXNzYWdlKHRhZywgZm4sIG9iaikge1xuICAgIHRoaXMud3JpdGVUYWcodGFnLCBQYmYuQnl0ZXMpO1xuICAgIHRoaXMud3JpdGVSYXdNZXNzYWdlKGZuLCBvYmopO1xuICB9LFxuICB3cml0ZVBhY2tlZFZhcmludDogZnVuY3Rpb24gd3JpdGVQYWNrZWRWYXJpbnQodGFnLCBhcnIpIHtcbiAgICBpZiAoYXJyLmxlbmd0aCkgdGhpcy53cml0ZU1lc3NhZ2UodGFnLCBfd3JpdGVQYWNrZWRWYXJpbnQsIGFycik7XG4gIH0sXG4gIHdyaXRlUGFja2VkU1ZhcmludDogZnVuY3Rpb24gd3JpdGVQYWNrZWRTVmFyaW50KHRhZywgYXJyKSB7XG4gICAgaWYgKGFyci5sZW5ndGgpIHRoaXMud3JpdGVNZXNzYWdlKHRhZywgX3dyaXRlUGFja2VkU1ZhcmludCwgYXJyKTtcbiAgfSxcbiAgd3JpdGVQYWNrZWRCb29sZWFuOiBmdW5jdGlvbiB3cml0ZVBhY2tlZEJvb2xlYW4odGFnLCBhcnIpIHtcbiAgICBpZiAoYXJyLmxlbmd0aCkgdGhpcy53cml0ZU1lc3NhZ2UodGFnLCBfd3JpdGVQYWNrZWRCb29sZWFuLCBhcnIpO1xuICB9LFxuICB3cml0ZVBhY2tlZEZsb2F0OiBmdW5jdGlvbiB3cml0ZVBhY2tlZEZsb2F0KHRhZywgYXJyKSB7XG4gICAgaWYgKGFyci5sZW5ndGgpIHRoaXMud3JpdGVNZXNzYWdlKHRhZywgX3dyaXRlUGFja2VkRmxvYXQsIGFycik7XG4gIH0sXG4gIHdyaXRlUGFja2VkRG91YmxlOiBmdW5jdGlvbiB3cml0ZVBhY2tlZERvdWJsZSh0YWcsIGFycikge1xuICAgIGlmIChhcnIubGVuZ3RoKSB0aGlzLndyaXRlTWVzc2FnZSh0YWcsIF93cml0ZVBhY2tlZERvdWJsZSwgYXJyKTtcbiAgfSxcbiAgd3JpdGVQYWNrZWRGaXhlZDMyOiBmdW5jdGlvbiB3cml0ZVBhY2tlZEZpeGVkMzIodGFnLCBhcnIpIHtcbiAgICBpZiAoYXJyLmxlbmd0aCkgdGhpcy53cml0ZU1lc3NhZ2UodGFnLCBfd3JpdGVQYWNrZWRGaXhlZCwgYXJyKTtcbiAgfSxcbiAgd3JpdGVQYWNrZWRTRml4ZWQzMjogZnVuY3Rpb24gd3JpdGVQYWNrZWRTRml4ZWQzMih0YWcsIGFycikge1xuICAgIGlmIChhcnIubGVuZ3RoKSB0aGlzLndyaXRlTWVzc2FnZSh0YWcsIF93cml0ZVBhY2tlZFNGaXhlZCwgYXJyKTtcbiAgfSxcbiAgd3JpdGVQYWNrZWRGaXhlZDY0OiBmdW5jdGlvbiB3cml0ZVBhY2tlZEZpeGVkNjQodGFnLCBhcnIpIHtcbiAgICBpZiAoYXJyLmxlbmd0aCkgdGhpcy53cml0ZU1lc3NhZ2UodGFnLCBfd3JpdGVQYWNrZWRGaXhlZDIsIGFycik7XG4gIH0sXG4gIHdyaXRlUGFja2VkU0ZpeGVkNjQ6IGZ1bmN0aW9uIHdyaXRlUGFja2VkU0ZpeGVkNjQodGFnLCBhcnIpIHtcbiAgICBpZiAoYXJyLmxlbmd0aCkgdGhpcy53cml0ZU1lc3NhZ2UodGFnLCBfd3JpdGVQYWNrZWRTRml4ZWQyLCBhcnIpO1xuICB9LFxuICB3cml0ZUJ5dGVzRmllbGQ6IGZ1bmN0aW9uIHdyaXRlQnl0ZXNGaWVsZCh0YWcsIGJ1ZmZlcikge1xuICAgIHRoaXMud3JpdGVUYWcodGFnLCBQYmYuQnl0ZXMpO1xuICAgIHRoaXMud3JpdGVCeXRlcyhidWZmZXIpO1xuICB9LFxuICB3cml0ZUZpeGVkMzJGaWVsZDogZnVuY3Rpb24gd3JpdGVGaXhlZDMyRmllbGQodGFnLCB2YWwpIHtcbiAgICB0aGlzLndyaXRlVGFnKHRhZywgUGJmLkZpeGVkMzIpO1xuICAgIHRoaXMud3JpdGVGaXhlZDMyKHZhbCk7XG4gIH0sXG4gIHdyaXRlU0ZpeGVkMzJGaWVsZDogZnVuY3Rpb24gd3JpdGVTRml4ZWQzMkZpZWxkKHRhZywgdmFsKSB7XG4gICAgdGhpcy53cml0ZVRhZyh0YWcsIFBiZi5GaXhlZDMyKTtcbiAgICB0aGlzLndyaXRlU0ZpeGVkMzIodmFsKTtcbiAgfSxcbiAgd3JpdGVGaXhlZDY0RmllbGQ6IGZ1bmN0aW9uIHdyaXRlRml4ZWQ2NEZpZWxkKHRhZywgdmFsKSB7XG4gICAgdGhpcy53cml0ZVRhZyh0YWcsIFBiZi5GaXhlZDY0KTtcbiAgICB0aGlzLndyaXRlRml4ZWQ2NCh2YWwpO1xuICB9LFxuICB3cml0ZVNGaXhlZDY0RmllbGQ6IGZ1bmN0aW9uIHdyaXRlU0ZpeGVkNjRGaWVsZCh0YWcsIHZhbCkge1xuICAgIHRoaXMud3JpdGVUYWcodGFnLCBQYmYuRml4ZWQ2NCk7XG4gICAgdGhpcy53cml0ZVNGaXhlZDY0KHZhbCk7XG4gIH0sXG4gIHdyaXRlVmFyaW50RmllbGQ6IGZ1bmN0aW9uIHdyaXRlVmFyaW50RmllbGQodGFnLCB2YWwpIHtcbiAgICB0aGlzLndyaXRlVGFnKHRhZywgUGJmLlZhcmludCk7XG4gICAgdGhpcy53cml0ZVZhcmludCh2YWwpO1xuICB9LFxuICB3cml0ZVNWYXJpbnRGaWVsZDogZnVuY3Rpb24gd3JpdGVTVmFyaW50RmllbGQodGFnLCB2YWwpIHtcbiAgICB0aGlzLndyaXRlVGFnKHRhZywgUGJmLlZhcmludCk7XG4gICAgdGhpcy53cml0ZVNWYXJpbnQodmFsKTtcbiAgfSxcbiAgd3JpdGVTdHJpbmdGaWVsZDogZnVuY3Rpb24gd3JpdGVTdHJpbmdGaWVsZCh0YWcsIHN0cikge1xuICAgIHRoaXMud3JpdGVUYWcodGFnLCBQYmYuQnl0ZXMpO1xuICAgIHRoaXMud3JpdGVTdHJpbmcoc3RyKTtcbiAgfSxcbiAgd3JpdGVGbG9hdEZpZWxkOiBmdW5jdGlvbiB3cml0ZUZsb2F0RmllbGQodGFnLCB2YWwpIHtcbiAgICB0aGlzLndyaXRlVGFnKHRhZywgUGJmLkZpeGVkMzIpO1xuICAgIHRoaXMud3JpdGVGbG9hdCh2YWwpO1xuICB9LFxuICB3cml0ZURvdWJsZUZpZWxkOiBmdW5jdGlvbiB3cml0ZURvdWJsZUZpZWxkKHRhZywgdmFsKSB7XG4gICAgdGhpcy53cml0ZVRhZyh0YWcsIFBiZi5GaXhlZDY0KTtcbiAgICB0aGlzLndyaXRlRG91YmxlKHZhbCk7XG4gIH0sXG4gIHdyaXRlQm9vbGVhbkZpZWxkOiBmdW5jdGlvbiB3cml0ZUJvb2xlYW5GaWVsZCh0YWcsIHZhbCkge1xuICAgIHRoaXMud3JpdGVWYXJpbnRGaWVsZCh0YWcsIEJvb2xlYW4odmFsKSk7XG4gIH1cbn07XG5cbmZ1bmN0aW9uIHJlYWRWYXJpbnRSZW1haW5kZXIobCwgcywgcCkge1xuICB2YXIgYnVmID0gcC5idWYsXG4gICAgICBoLFxuICAgICAgYjtcbiAgYiA9IGJ1ZltwLnBvcysrXTtcbiAgaCA9IChiICYgMHg3MCkgPj4gNDtcbiAgaWYgKGIgPCAweDgwKSByZXR1cm4gdG9OdW0obCwgaCwgcyk7XG4gIGIgPSBidWZbcC5wb3MrK107XG4gIGggfD0gKGIgJiAweDdmKSA8PCAzO1xuICBpZiAoYiA8IDB4ODApIHJldHVybiB0b051bShsLCBoLCBzKTtcbiAgYiA9IGJ1ZltwLnBvcysrXTtcbiAgaCB8PSAoYiAmIDB4N2YpIDw8IDEwO1xuICBpZiAoYiA8IDB4ODApIHJldHVybiB0b051bShsLCBoLCBzKTtcbiAgYiA9IGJ1ZltwLnBvcysrXTtcbiAgaCB8PSAoYiAmIDB4N2YpIDw8IDE3O1xuICBpZiAoYiA8IDB4ODApIHJldHVybiB0b051bShsLCBoLCBzKTtcbiAgYiA9IGJ1ZltwLnBvcysrXTtcbiAgaCB8PSAoYiAmIDB4N2YpIDw8IDI0O1xuICBpZiAoYiA8IDB4ODApIHJldHVybiB0b051bShsLCBoLCBzKTtcbiAgYiA9IGJ1ZltwLnBvcysrXTtcbiAgaCB8PSAoYiAmIDB4MDEpIDw8IDMxO1xuICBpZiAoYiA8IDB4ODApIHJldHVybiB0b051bShsLCBoLCBzKTtcbiAgdGhyb3cgbmV3IEVycm9yKCdFeHBlY3RlZCB2YXJpbnQgbm90IG1vcmUgdGhhbiAxMCBieXRlcycpO1xufVxuXG5mdW5jdGlvbiByZWFkUGFja2VkRW5kKHBiZikge1xuICByZXR1cm4gcGJmLnR5cGUgPT09IFBiZi5CeXRlcyA/IHBiZi5yZWFkVmFyaW50KCkgKyBwYmYucG9zIDogcGJmLnBvcyArIDE7XG59XG5cbmZ1bmN0aW9uIHRvTnVtKGxvdywgaGlnaCwgaXNTaWduZWQpIHtcbiAgaWYgKGlzU2lnbmVkKSB7XG4gICAgcmV0dXJuIGhpZ2ggKiAweDEwMDAwMDAwMCArIChsb3cgPj4+IDApO1xuICB9XG5cbiAgcmV0dXJuIChoaWdoID4+PiAwKSAqIDB4MTAwMDAwMDAwICsgKGxvdyA+Pj4gMCk7XG59XG5cbmZ1bmN0aW9uIHdyaXRlQmlnVmFyaW50KHZhbCwgcGJmKSB7XG4gIHZhciBsb3csIGhpZ2g7XG5cbiAgaWYgKHZhbCA+PSAwKSB7XG4gICAgbG93ID0gdmFsICUgMHgxMDAwMDAwMDAgfCAwO1xuICAgIGhpZ2ggPSB2YWwgLyAweDEwMDAwMDAwMCB8IDA7XG4gIH0gZWxzZSB7XG4gICAgbG93ID0gfigtdmFsICUgMHgxMDAwMDAwMDApO1xuICAgIGhpZ2ggPSB+KC12YWwgLyAweDEwMDAwMDAwMCk7XG5cbiAgICBpZiAobG93IF4gMHhmZmZmZmZmZikge1xuICAgICAgbG93ID0gbG93ICsgMSB8IDA7XG4gICAgfSBlbHNlIHtcbiAgICAgIGxvdyA9IDA7XG4gICAgICBoaWdoID0gaGlnaCArIDEgfCAwO1xuICAgIH1cbiAgfVxuXG4gIGlmICh2YWwgPj0gMHgxMDAwMDAwMDAwMDAwMDAwMCB8fCB2YWwgPCAtMHgxMDAwMDAwMDAwMDAwMDAwMCkge1xuICAgIHRocm93IG5ldyBFcnJvcignR2l2ZW4gdmFyaW50IGRvZXNuXFwndCBmaXQgaW50byAxMCBieXRlcycpO1xuICB9XG5cbiAgcGJmLnJlYWxsb2MoMTApO1xuICB3cml0ZUJpZ1ZhcmludExvdyhsb3csIGhpZ2gsIHBiZik7XG4gIHdyaXRlQmlnVmFyaW50SGlnaChoaWdoLCBwYmYpO1xufVxuXG5mdW5jdGlvbiB3cml0ZUJpZ1ZhcmludExvdyhsb3csIGhpZ2gsIHBiZikge1xuICBwYmYuYnVmW3BiZi5wb3MrK10gPSBsb3cgJiAweDdmIHwgMHg4MDtcbiAgbG93ID4+Pj0gNztcbiAgcGJmLmJ1ZltwYmYucG9zKytdID0gbG93ICYgMHg3ZiB8IDB4ODA7XG4gIGxvdyA+Pj49IDc7XG4gIHBiZi5idWZbcGJmLnBvcysrXSA9IGxvdyAmIDB4N2YgfCAweDgwO1xuICBsb3cgPj4+PSA3O1xuICBwYmYuYnVmW3BiZi5wb3MrK10gPSBsb3cgJiAweDdmIHwgMHg4MDtcbiAgbG93ID4+Pj0gNztcbiAgcGJmLmJ1ZltwYmYucG9zXSA9IGxvdyAmIDB4N2Y7XG59XG5cbmZ1bmN0aW9uIHdyaXRlQmlnVmFyaW50SGlnaChoaWdoLCBwYmYpIHtcbiAgdmFyIGxzYiA9IChoaWdoICYgMHgwNykgPDwgNDtcbiAgcGJmLmJ1ZltwYmYucG9zKytdIHw9IGxzYiB8ICgoaGlnaCA+Pj49IDMpID8gMHg4MCA6IDApO1xuICBpZiAoIWhpZ2gpIHJldHVybjtcbiAgcGJmLmJ1ZltwYmYucG9zKytdID0gaGlnaCAmIDB4N2YgfCAoKGhpZ2ggPj4+PSA3KSA/IDB4ODAgOiAwKTtcbiAgaWYgKCFoaWdoKSByZXR1cm47XG4gIHBiZi5idWZbcGJmLnBvcysrXSA9IGhpZ2ggJiAweDdmIHwgKChoaWdoID4+Pj0gNykgPyAweDgwIDogMCk7XG4gIGlmICghaGlnaCkgcmV0dXJuO1xuICBwYmYuYnVmW3BiZi5wb3MrK10gPSBoaWdoICYgMHg3ZiB8ICgoaGlnaCA+Pj49IDcpID8gMHg4MCA6IDApO1xuICBpZiAoIWhpZ2gpIHJldHVybjtcbiAgcGJmLmJ1ZltwYmYucG9zKytdID0gaGlnaCAmIDB4N2YgfCAoKGhpZ2ggPj4+PSA3KSA/IDB4ODAgOiAwKTtcbiAgaWYgKCFoaWdoKSByZXR1cm47XG4gIHBiZi5idWZbcGJmLnBvcysrXSA9IGhpZ2ggJiAweDdmO1xufVxuXG5mdW5jdGlvbiBtYWtlUm9vbUZvckV4dHJhTGVuZ3RoKHN0YXJ0UG9zLCBsZW4sIHBiZikge1xuICB2YXIgZXh0cmFMZW4gPSBsZW4gPD0gMHgzZmZmID8gMSA6IGxlbiA8PSAweDFmZmZmZiA/IDIgOiBsZW4gPD0gMHhmZmZmZmZmID8gMyA6IE1hdGguZmxvb3IoTWF0aC5sb2cobGVuKSAvIChNYXRoLkxOMiAqIDcpKTsgLy8gaWYgMSBieXRlIGlzbid0IGVub3VnaCBmb3IgZW5jb2RpbmcgbWVzc2FnZSBsZW5ndGgsIHNoaWZ0IHRoZSBkYXRhIHRvIHRoZSByaWdodFxuXG4gIHBiZi5yZWFsbG9jKGV4dHJhTGVuKTtcblxuICBmb3IgKHZhciBpID0gcGJmLnBvcyAtIDE7IGkgPj0gc3RhcnRQb3M7IGktLSkge1xuICAgIHBiZi5idWZbaSArIGV4dHJhTGVuXSA9IHBiZi5idWZbaV07XG4gIH1cbn1cblxuZnVuY3Rpb24gX3dyaXRlUGFja2VkVmFyaW50KGFyciwgcGJmKSB7XG4gIGZvciAodmFyIGkgPSAwOyBpIDwgYXJyLmxlbmd0aDsgaSsrKSB7XG4gICAgcGJmLndyaXRlVmFyaW50KGFycltpXSk7XG4gIH1cbn1cblxuZnVuY3Rpb24gX3dyaXRlUGFja2VkU1ZhcmludChhcnIsIHBiZikge1xuICBmb3IgKHZhciBpID0gMDsgaSA8IGFyci5sZW5ndGg7IGkrKykge1xuICAgIHBiZi53cml0ZVNWYXJpbnQoYXJyW2ldKTtcbiAgfVxufVxuXG5mdW5jdGlvbiBfd3JpdGVQYWNrZWRGbG9hdChhcnIsIHBiZikge1xuICBmb3IgKHZhciBpID0gMDsgaSA8IGFyci5sZW5ndGg7IGkrKykge1xuICAgIHBiZi53cml0ZUZsb2F0KGFycltpXSk7XG4gIH1cbn1cblxuZnVuY3Rpb24gX3dyaXRlUGFja2VkRG91YmxlKGFyciwgcGJmKSB7XG4gIGZvciAodmFyIGkgPSAwOyBpIDwgYXJyLmxlbmd0aDsgaSsrKSB7XG4gICAgcGJmLndyaXRlRG91YmxlKGFycltpXSk7XG4gIH1cbn1cblxuZnVuY3Rpb24gX3dyaXRlUGFja2VkQm9vbGVhbihhcnIsIHBiZikge1xuICBmb3IgKHZhciBpID0gMDsgaSA8IGFyci5sZW5ndGg7IGkrKykge1xuICAgIHBiZi53cml0ZUJvb2xlYW4oYXJyW2ldKTtcbiAgfVxufVxuXG5mdW5jdGlvbiBfd3JpdGVQYWNrZWRGaXhlZChhcnIsIHBiZikge1xuICBmb3IgKHZhciBpID0gMDsgaSA8IGFyci5sZW5ndGg7IGkrKykge1xuICAgIHBiZi53cml0ZUZpeGVkMzIoYXJyW2ldKTtcbiAgfVxufVxuXG5mdW5jdGlvbiBfd3JpdGVQYWNrZWRTRml4ZWQoYXJyLCBwYmYpIHtcbiAgZm9yICh2YXIgaSA9IDA7IGkgPCBhcnIubGVuZ3RoOyBpKyspIHtcbiAgICBwYmYud3JpdGVTRml4ZWQzMihhcnJbaV0pO1xuICB9XG59XG5cbmZ1bmN0aW9uIF93cml0ZVBhY2tlZEZpeGVkMihhcnIsIHBiZikge1xuICBmb3IgKHZhciBpID0gMDsgaSA8IGFyci5sZW5ndGg7IGkrKykge1xuICAgIHBiZi53cml0ZUZpeGVkNjQoYXJyW2ldKTtcbiAgfVxufVxuXG5mdW5jdGlvbiBfd3JpdGVQYWNrZWRTRml4ZWQyKGFyciwgcGJmKSB7XG4gIGZvciAodmFyIGkgPSAwOyBpIDwgYXJyLmxlbmd0aDsgaSsrKSB7XG4gICAgcGJmLndyaXRlU0ZpeGVkNjQoYXJyW2ldKTtcbiAgfVxufSAvLyBCdWZmZXIgY29kZSBiZWxvdyBmcm9tIGh0dHBzOi8vZ2l0aHViLmNvbS9mZXJvc3MvYnVmZmVyLCBNSVQtbGljZW5zZWRcblxuXG5mdW5jdGlvbiByZWFkVUludDMyKGJ1ZiwgcG9zKSB7XG4gIHJldHVybiAoYnVmW3Bvc10gfCBidWZbcG9zICsgMV0gPDwgOCB8IGJ1Zltwb3MgKyAyXSA8PCAxNikgKyBidWZbcG9zICsgM10gKiAweDEwMDAwMDA7XG59XG5cbmZ1bmN0aW9uIHdyaXRlSW50MzIoYnVmLCB2YWwsIHBvcykge1xuICBidWZbcG9zXSA9IHZhbDtcbiAgYnVmW3BvcyArIDFdID0gdmFsID4+PiA4O1xuICBidWZbcG9zICsgMl0gPSB2YWwgPj4+IDE2O1xuICBidWZbcG9zICsgM10gPSB2YWwgPj4+IDI0O1xufVxuXG5mdW5jdGlvbiByZWFkSW50MzIoYnVmLCBwb3MpIHtcbiAgcmV0dXJuIChidWZbcG9zXSB8IGJ1Zltwb3MgKyAxXSA8PCA4IHwgYnVmW3BvcyArIDJdIDw8IDE2KSArIChidWZbcG9zICsgM10gPDwgMjQpO1xufVxuXG5mdW5jdGlvbiByZWFkVXRmOChidWYsIHBvcywgZW5kKSB7XG4gIHZhciBzdHIgPSAnJztcbiAgdmFyIGkgPSBwb3M7XG5cbiAgd2hpbGUgKGkgPCBlbmQpIHtcbiAgICB2YXIgYjAgPSBidWZbaV07XG4gICAgdmFyIGMgPSBudWxsOyAvLyBjb2RlcG9pbnRcblxuICAgIHZhciBieXRlc1BlclNlcXVlbmNlID0gYjAgPiAweEVGID8gNCA6IGIwID4gMHhERiA/IDMgOiBiMCA+IDB4QkYgPyAyIDogMTtcbiAgICBpZiAoaSArIGJ5dGVzUGVyU2VxdWVuY2UgPiBlbmQpIGJyZWFrO1xuICAgIHZhciBiMSwgYjIsIGIzO1xuXG4gICAgaWYgKGJ5dGVzUGVyU2VxdWVuY2UgPT09IDEpIHtcbiAgICAgIGlmIChiMCA8IDB4ODApIHtcbiAgICAgICAgYyA9IGIwO1xuICAgICAgfVxuICAgIH0gZWxzZSBpZiAoYnl0ZXNQZXJTZXF1ZW5jZSA9PT0gMikge1xuICAgICAgYjEgPSBidWZbaSArIDFdO1xuXG4gICAgICBpZiAoKGIxICYgMHhDMCkgPT09IDB4ODApIHtcbiAgICAgICAgYyA9IChiMCAmIDB4MUYpIDw8IDB4NiB8IGIxICYgMHgzRjtcblxuICAgICAgICBpZiAoYyA8PSAweDdGKSB7XG4gICAgICAgICAgYyA9IG51bGw7XG4gICAgICAgIH1cbiAgICAgIH1cbiAgICB9IGVsc2UgaWYgKGJ5dGVzUGVyU2VxdWVuY2UgPT09IDMpIHtcbiAgICAgIGIxID0gYnVmW2kgKyAxXTtcbiAgICAgIGIyID0gYnVmW2kgKyAyXTtcblxuICAgICAgaWYgKChiMSAmIDB4QzApID09PSAweDgwICYmIChiMiAmIDB4QzApID09PSAweDgwKSB7XG4gICAgICAgIGMgPSAoYjAgJiAweEYpIDw8IDB4QyB8IChiMSAmIDB4M0YpIDw8IDB4NiB8IGIyICYgMHgzRjtcblxuICAgICAgICBpZiAoYyA8PSAweDdGRiB8fCBjID49IDB4RDgwMCAmJiBjIDw9IDB4REZGRikge1xuICAgICAgICAgIGMgPSBudWxsO1xuICAgICAgICB9XG4gICAgICB9XG4gICAgfSBlbHNlIGlmIChieXRlc1BlclNlcXVlbmNlID09PSA0KSB7XG4gICAgICBiMSA9IGJ1ZltpICsgMV07XG4gICAgICBiMiA9IGJ1ZltpICsgMl07XG4gICAgICBiMyA9IGJ1ZltpICsgM107XG5cbiAgICAgIGlmICgoYjEgJiAweEMwKSA9PT0gMHg4MCAmJiAoYjIgJiAweEMwKSA9PT0gMHg4MCAmJiAoYjMgJiAweEMwKSA9PT0gMHg4MCkge1xuICAgICAgICBjID0gKGIwICYgMHhGKSA8PCAweDEyIHwgKGIxICYgMHgzRikgPDwgMHhDIHwgKGIyICYgMHgzRikgPDwgMHg2IHwgYjMgJiAweDNGO1xuXG4gICAgICAgIGlmIChjIDw9IDB4RkZGRiB8fCBjID49IDB4MTEwMDAwKSB7XG4gICAgICAgICAgYyA9IG51bGw7XG4gICAgICAgIH1cbiAgICAgIH1cbiAgICB9XG5cbiAgICBpZiAoYyA9PT0gbnVsbCkge1xuICAgICAgYyA9IDB4RkZGRDtcbiAgICAgIGJ5dGVzUGVyU2VxdWVuY2UgPSAxO1xuICAgIH0gZWxzZSBpZiAoYyA+IDB4RkZGRikge1xuICAgICAgYyAtPSAweDEwMDAwO1xuICAgICAgc3RyICs9IFN0cmluZy5mcm9tQ2hhckNvZGUoYyA+Pj4gMTAgJiAweDNGRiB8IDB4RDgwMCk7XG4gICAgICBjID0gMHhEQzAwIHwgYyAmIDB4M0ZGO1xuICAgIH1cblxuICAgIHN0ciArPSBTdHJpbmcuZnJvbUNoYXJDb2RlKGMpO1xuICAgIGkgKz0gYnl0ZXNQZXJTZXF1ZW5jZTtcbiAgfVxuXG4gIHJldHVybiBzdHI7XG59XG5cbmZ1bmN0aW9uIHJlYWRVdGY4VGV4dERlY29kZXIoYnVmLCBwb3MsIGVuZCkge1xuICByZXR1cm4gdXRmOFRleHREZWNvZGVyLmRlY29kZShidWYuc3ViYXJyYXkocG9zLCBlbmQpKTtcbn1cblxuZnVuY3Rpb24gd3JpdGVVdGY4KGJ1Ziwgc3RyLCBwb3MpIHtcbiAgZm9yICh2YXIgaSA9IDAsIGMsIGxlYWQ7IGkgPCBzdHIubGVuZ3RoOyBpKyspIHtcbiAgICBjID0gc3RyLmNoYXJDb2RlQXQoaSk7IC8vIGNvZGUgcG9pbnRcblxuICAgIGlmIChjID4gMHhEN0ZGICYmIGMgPCAweEUwMDApIHtcbiAgICAgIGlmIChsZWFkKSB7XG4gICAgICAgIGlmIChjIDwgMHhEQzAwKSB7XG4gICAgICAgICAgYnVmW3BvcysrXSA9IDB4RUY7XG4gICAgICAgICAgYnVmW3BvcysrXSA9IDB4QkY7XG4gICAgICAgICAgYnVmW3BvcysrXSA9IDB4QkQ7XG4gICAgICAgICAgbGVhZCA9IGM7XG4gICAgICAgICAgY29udGludWU7XG4gICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgYyA9IGxlYWQgLSAweEQ4MDAgPDwgMTAgfCBjIC0gMHhEQzAwIHwgMHgxMDAwMDtcbiAgICAgICAgICBsZWFkID0gbnVsbDtcbiAgICAgICAgfVxuICAgICAgfSBlbHNlIHtcbiAgICAgICAgaWYgKGMgPiAweERCRkYgfHwgaSArIDEgPT09IHN0ci5sZW5ndGgpIHtcbiAgICAgICAgICBidWZbcG9zKytdID0gMHhFRjtcbiAgICAgICAgICBidWZbcG9zKytdID0gMHhCRjtcbiAgICAgICAgICBidWZbcG9zKytdID0gMHhCRDtcbiAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICBsZWFkID0gYztcbiAgICAgICAgfVxuXG4gICAgICAgIGNvbnRpbnVlO1xuICAgICAgfVxuICAgIH0gZWxzZSBpZiAobGVhZCkge1xuICAgICAgYnVmW3BvcysrXSA9IDB4RUY7XG4gICAgICBidWZbcG9zKytdID0gMHhCRjtcbiAgICAgIGJ1Zltwb3MrK10gPSAweEJEO1xuICAgICAgbGVhZCA9IG51bGw7XG4gICAgfVxuXG4gICAgaWYgKGMgPCAweDgwKSB7XG4gICAgICBidWZbcG9zKytdID0gYztcbiAgICB9IGVsc2Uge1xuICAgICAgaWYgKGMgPCAweDgwMCkge1xuICAgICAgICBidWZbcG9zKytdID0gYyA+PiAweDYgfCAweEMwO1xuICAgICAgfSBlbHNlIHtcbiAgICAgICAgaWYgKGMgPCAweDEwMDAwKSB7XG4gICAgICAgICAgYnVmW3BvcysrXSA9IGMgPj4gMHhDIHwgMHhFMDtcbiAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICBidWZbcG9zKytdID0gYyA+PiAweDEyIHwgMHhGMDtcbiAgICAgICAgICBidWZbcG9zKytdID0gYyA+PiAweEMgJiAweDNGIHwgMHg4MDtcbiAgICAgICAgfVxuXG4gICAgICAgIGJ1Zltwb3MrK10gPSBjID4+IDB4NiAmIDB4M0YgfCAweDgwO1xuICAgICAgfVxuXG4gICAgICBidWZbcG9zKytdID0gYyAmIDB4M0YgfCAweDgwO1xuICAgIH1cbiAgfVxuXG4gIHJldHVybiBwb3M7XG59Il0sInNvdXJjZVJvb3QiOiIifQ==\n//# sourceURL=webpack-internal:///4362\n")},5792:function(module){eval('!function (t, i) {\n true ? module.exports = i() : 0;\n}(this, function () {\n "use strict";\n\n function t(t, r, e, a, h) {\n !function t(n, r, e, a, h) {\n for (; a > e;) {\n if (a - e > 600) {\n var o = a - e + 1,\n s = r - e + 1,\n l = Math.log(o),\n f = .5 * Math.exp(2 * l / 3),\n u = .5 * Math.sqrt(l * f * (o - f) / o) * (s - o / 2 < 0 ? -1 : 1),\n m = Math.max(e, Math.floor(r - s * f / o + u)),\n c = Math.min(a, Math.floor(r + (o - s) * f / o + u));\n t(n, r, m, c, h);\n }\n\n var p = n[r],\n d = e,\n x = a;\n\n for (i(n, e, r), h(n[a], p) > 0 && i(n, e, a); d < x;) {\n for (i(n, d, x), d++, x--; h(n[d], p) < 0;) {\n d++;\n }\n\n for (; h(n[x], p) > 0;) {\n x--;\n }\n }\n\n 0 === h(n[e], p) ? i(n, e, x) : i(n, ++x, a), x <= r && (e = x + 1), r <= x && (a = x - 1);\n }\n }(t, r, e || 0, a || t.length - 1, h || n);\n }\n\n function i(t, i, n) {\n var r = t[i];\n t[i] = t[n], t[n] = r;\n }\n\n function n(t, i) {\n return t < i ? -1 : t > i ? 1 : 0;\n }\n\n var r = function r(t) {\n void 0 === t && (t = 9), this._maxEntries = Math.max(4, t), this._minEntries = Math.max(2, Math.ceil(.4 * this._maxEntries)), this.clear();\n };\n\n function e(t, i, n) {\n if (!n) return i.indexOf(t);\n\n for (var r = 0; r < i.length; r++) {\n if (n(t, i[r])) return r;\n }\n\n return -1;\n }\n\n function a(t, i) {\n h(t, 0, t.children.length, i, t);\n }\n\n function h(t, i, n, r, e) {\n e || (e = p(null)), e.minX = 1 / 0, e.minY = 1 / 0, e.maxX = -1 / 0, e.maxY = -1 / 0;\n\n for (var a = i; a < n; a++) {\n var h = t.children[a];\n o(e, t.leaf ? r(h) : h);\n }\n\n return e;\n }\n\n function o(t, i) {\n return t.minX = Math.min(t.minX, i.minX), t.minY = Math.min(t.minY, i.minY), t.maxX = Math.max(t.maxX, i.maxX), t.maxY = Math.max(t.maxY, i.maxY), t;\n }\n\n function s(t, i) {\n return t.minX - i.minX;\n }\n\n function l(t, i) {\n return t.minY - i.minY;\n }\n\n function f(t) {\n return (t.maxX - t.minX) * (t.maxY - t.minY);\n }\n\n function u(t) {\n return t.maxX - t.minX + (t.maxY - t.minY);\n }\n\n function m(t, i) {\n return t.minX <= i.minX && t.minY <= i.minY && i.maxX <= t.maxX && i.maxY <= t.maxY;\n }\n\n function c(t, i) {\n return i.minX <= t.maxX && i.minY <= t.maxY && i.maxX >= t.minX && i.maxY >= t.minY;\n }\n\n function p(t) {\n return {\n children: t,\n height: 1,\n leaf: !0,\n minX: 1 / 0,\n minY: 1 / 0,\n maxX: -1 / 0,\n maxY: -1 / 0\n };\n }\n\n function d(i, n, r, e, a) {\n for (var h = [n, r]; h.length;) {\n if (!((r = h.pop()) - (n = h.pop()) <= e)) {\n var o = n + Math.ceil((r - n) / e / 2) * e;\n t(i, o, n, r, a), h.push(n, o, o, r);\n }\n }\n }\n\n return r.prototype.all = function () {\n return this._all(this.data, []);\n }, r.prototype.search = function (t) {\n var i = this.data,\n n = [];\n if (!c(t, i)) return n;\n\n for (var r = this.toBBox, e = []; i;) {\n for (var a = 0; a < i.children.length; a++) {\n var h = i.children[a],\n o = i.leaf ? r(h) : h;\n c(t, o) && (i.leaf ? n.push(h) : m(t, o) ? this._all(h, n) : e.push(h));\n }\n\n i = e.pop();\n }\n\n return n;\n }, r.prototype.collides = function (t) {\n var i = this.data;\n if (!c(t, i)) return !1;\n\n for (var n = []; i;) {\n for (var r = 0; r < i.children.length; r++) {\n var e = i.children[r],\n a = i.leaf ? this.toBBox(e) : e;\n\n if (c(t, a)) {\n if (i.leaf || m(t, a)) return !0;\n n.push(e);\n }\n }\n\n i = n.pop();\n }\n\n return !1;\n }, r.prototype.load = function (t) {\n if (!t || !t.length) return this;\n\n if (t.length < this._minEntries) {\n for (var i = 0; i < t.length; i++) {\n this.insert(t[i]);\n }\n\n return this;\n }\n\n var n = this._build(t.slice(), 0, t.length - 1, 0);\n\n if (this.data.children.length) {\n if (this.data.height === n.height) this._splitRoot(this.data, n);else {\n if (this.data.height < n.height) {\n var r = this.data;\n this.data = n, n = r;\n }\n\n this._insert(n, this.data.height - n.height - 1, !0);\n }\n } else this.data = n;\n return this;\n }, r.prototype.insert = function (t) {\n return t && this._insert(t, this.data.height - 1), this;\n }, r.prototype.clear = function () {\n return this.data = p([]), this;\n }, r.prototype.remove = function (t, i) {\n if (!t) return this;\n\n for (var n, r, a, h = this.data, o = this.toBBox(t), s = [], l = []; h || s.length;) {\n if (h || (h = s.pop(), r = s[s.length - 1], n = l.pop(), a = !0), h.leaf) {\n var f = e(t, h.children, i);\n if (-1 !== f) return h.children.splice(f, 1), s.push(h), this._condense(s), this;\n }\n\n a || h.leaf || !m(h, o) ? r ? (n++, h = r.children[n], a = !1) : h = null : (s.push(h), l.push(n), n = 0, r = h, h = h.children[0]);\n }\n\n return this;\n }, r.prototype.toBBox = function (t) {\n return t;\n }, r.prototype.compareMinX = function (t, i) {\n return t.minX - i.minX;\n }, r.prototype.compareMinY = function (t, i) {\n return t.minY - i.minY;\n }, r.prototype.toJSON = function () {\n return this.data;\n }, r.prototype.fromJSON = function (t) {\n return this.data = t, this;\n }, r.prototype._all = function (t, i) {\n for (var n = []; t;) {\n t.leaf ? i.push.apply(i, t.children) : n.push.apply(n, t.children), t = n.pop();\n }\n\n return i;\n }, r.prototype._build = function (t, i, n, r) {\n var e,\n h = n - i + 1,\n o = this._maxEntries;\n if (h <= o) return a(e = p(t.slice(i, n + 1)), this.toBBox), e;\n r || (r = Math.ceil(Math.log(h) / Math.log(o)), o = Math.ceil(h / Math.pow(o, r - 1))), (e = p([])).leaf = !1, e.height = r;\n var s = Math.ceil(h / o),\n l = s * Math.ceil(Math.sqrt(o));\n d(t, i, n, l, this.compareMinX);\n\n for (var f = i; f <= n; f += l) {\n var u = Math.min(f + l - 1, n);\n d(t, f, u, s, this.compareMinY);\n\n for (var m = f; m <= u; m += s) {\n var c = Math.min(m + s - 1, u);\n e.children.push(this._build(t, m, c, r - 1));\n }\n }\n\n return a(e, this.toBBox), e;\n }, r.prototype._chooseSubtree = function (t, i, n, r) {\n for (; r.push(i), !i.leaf && r.length - 1 !== n;) {\n for (var e = 1 / 0, a = 1 / 0, h = void 0, o = 0; o < i.children.length; o++) {\n var s = i.children[o],\n l = f(s),\n u = (m = t, c = s, (Math.max(c.maxX, m.maxX) - Math.min(c.minX, m.minX)) * (Math.max(c.maxY, m.maxY) - Math.min(c.minY, m.minY)) - l);\n u < a ? (a = u, e = l < e ? l : e, h = s) : u === a && l < e && (e = l, h = s);\n }\n\n i = h || i.children[0];\n }\n\n var m, c;\n return i;\n }, r.prototype._insert = function (t, i, n) {\n var r = n ? t : this.toBBox(t),\n e = [],\n a = this._chooseSubtree(r, this.data, i, e);\n\n for (a.children.push(t), o(a, r); i >= 0 && e[i].children.length > this._maxEntries;) {\n this._split(e, i), i--;\n }\n\n this._adjustParentBBoxes(r, e, i);\n }, r.prototype._split = function (t, i) {\n var n = t[i],\n r = n.children.length,\n e = this._minEntries;\n\n this._chooseSplitAxis(n, e, r);\n\n var h = this._chooseSplitIndex(n, e, r),\n o = p(n.children.splice(h, n.children.length - h));\n\n o.height = n.height, o.leaf = n.leaf, a(n, this.toBBox), a(o, this.toBBox), i ? t[i - 1].children.push(o) : this._splitRoot(n, o);\n }, r.prototype._splitRoot = function (t, i) {\n this.data = p([t, i]), this.data.height = t.height + 1, this.data.leaf = !1, a(this.data, this.toBBox);\n }, r.prototype._chooseSplitIndex = function (t, i, n) {\n for (var r, e, a, o, s, l, u, m = 1 / 0, c = 1 / 0, p = i; p <= n - i; p++) {\n var d = h(t, 0, p, this.toBBox),\n x = h(t, p, n, this.toBBox),\n v = (e = d, a = x, o = void 0, s = void 0, l = void 0, u = void 0, o = Math.max(e.minX, a.minX), s = Math.max(e.minY, a.minY), l = Math.min(e.maxX, a.maxX), u = Math.min(e.maxY, a.maxY), Math.max(0, l - o) * Math.max(0, u - s)),\n M = f(d) + f(x);\n v < m ? (m = v, r = p, c = M < c ? M : c) : v === m && M < c && (c = M, r = p);\n }\n\n return r || n - i;\n }, r.prototype._chooseSplitAxis = function (t, i, n) {\n var r = t.leaf ? this.compareMinX : s,\n e = t.leaf ? this.compareMinY : l;\n this._allDistMargin(t, i, n, r) < this._allDistMargin(t, i, n, e) && t.children.sort(r);\n }, r.prototype._allDistMargin = function (t, i, n, r) {\n t.children.sort(r);\n\n for (var e = this.toBBox, a = h(t, 0, i, e), s = h(t, n - i, n, e), l = u(a) + u(s), f = i; f < n - i; f++) {\n var m = t.children[f];\n o(a, t.leaf ? e(m) : m), l += u(a);\n }\n\n for (var c = n - i - 1; c >= i; c--) {\n var p = t.children[c];\n o(s, t.leaf ? e(p) : p), l += u(s);\n }\n\n return l;\n }, r.prototype._adjustParentBBoxes = function (t, i, n) {\n for (var r = n; r >= 0; r--) {\n o(i[r], t);\n }\n }, r.prototype._condense = function (t) {\n for (var i = t.length - 1, n = void 0; i >= 0; i--) {\n 0 === t[i].children.length ? i > 0 ? (n = t[i - 1].children).splice(n.indexOf(t[i]), 1) : this.clear() : a(t[i], this.toBBox);\n }\n }, r;\n});//# sourceURL=[module]\n//# sourceMappingURL=data:application/json;charset=utf-8;base64,eyJ2ZXJzaW9uIjozLCJzb3VyY2VzIjpbIndlYnBhY2s6Ly9qdXN0aWNlNDAtdG9vbC8uL25vZGVfbW9kdWxlcy9yYnVzaC9yYnVzaC5taW4uanM/NzliYyJdLCJuYW1lcyI6W10sIm1hcHBpbmdzIjoiQUFBQTtBQUNBLEVBQUUsS0FBMEQsMEJBQTBCLENBQW1GO0FBQ3pLLENBQUM7QUFDRDs7QUFFQTtBQUNBO0FBQ0EsWUFBWSxPQUFPO0FBQ25CO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTs7QUFFQSxzREFBc0QsT0FBTztBQUM3RCxvQ0FBb0MsZ0JBQWdCO0FBQ3BEO0FBQ0E7O0FBRUEsZ0JBQWdCLGdCQUFnQjtBQUNoQztBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBLEtBQUs7QUFDTDs7QUFFQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBOztBQUVBO0FBQ0E7O0FBRUEsbUJBQW1CLGNBQWM7QUFDakM7QUFDQTs7QUFFQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBOztBQUVBLG1CQUFtQixPQUFPO0FBQzFCO0FBQ0E7QUFDQTs7QUFFQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0Esd0JBQXdCLFVBQVU7QUFDbEM7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQSxHQUFHO0FBQ0g7QUFDQTtBQUNBOztBQUVBLHFDQUFxQyxHQUFHO0FBQ3hDLHFCQUFxQix1QkFBdUI7QUFDNUM7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTs7QUFFQTtBQUNBLEdBQUc7QUFDSDtBQUNBOztBQUVBLG9CQUFvQixHQUFHO0FBQ3ZCLHFCQUFxQix1QkFBdUI7QUFDNUM7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7O0FBRUE7QUFDQSxHQUFHO0FBQ0g7O0FBRUE7QUFDQSxxQkFBcUIsY0FBYztBQUNuQztBQUNBOztBQUVBO0FBQ0E7O0FBRUE7O0FBRUE7QUFDQSx1RUFBdUU7QUFDdkU7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBLEtBQUs7QUFDTDtBQUNBLEdBQUc7QUFDSDtBQUNBLEdBQUc7QUFDSDtBQUNBLEdBQUc7QUFDSDs7QUFFQSx3RUFBd0UsZUFBZTtBQUN2RjtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBOztBQUVBO0FBQ0EsR0FBRztBQUNIO0FBQ0EsR0FBRztBQUNIO0FBQ0EsR0FBRztBQUNIO0FBQ0EsR0FBRztBQUNIO0FBQ0EsR0FBRztBQUNIO0FBQ0EsR0FBRztBQUNILG9CQUFvQixHQUFHO0FBQ3ZCO0FBQ0E7O0FBRUE7QUFDQSxHQUFHO0FBQ0g7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQSxtQkFBbUIsUUFBUTtBQUMzQjtBQUNBOztBQUVBLHFCQUFxQixRQUFRO0FBQzdCO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0EsR0FBRztBQUNILFVBQVUsMENBQTBDO0FBQ3BELHVEQUF1RCx1QkFBdUI7QUFDOUU7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBOztBQUVBO0FBQ0E7QUFDQSxHQUFHO0FBQ0g7QUFDQTtBQUNBOztBQUVBLHFDQUFxQyxtREFBbUQ7QUFDeEY7QUFDQTs7QUFFQTtBQUNBLEdBQUc7QUFDSDtBQUNBO0FBQ0E7O0FBRUE7O0FBRUE7QUFDQTs7QUFFQTtBQUNBLEdBQUc7QUFDSDtBQUNBLEdBQUc7QUFDSCw4REFBOEQsWUFBWTtBQUMxRTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQSxHQUFHO0FBQ0g7QUFDQTtBQUNBO0FBQ0EsR0FBRztBQUNIOztBQUVBLCtGQUErRixXQUFXO0FBQzFHO0FBQ0E7QUFDQTs7QUFFQSwyQkFBMkIsUUFBUTtBQUNuQztBQUNBO0FBQ0E7O0FBRUE7QUFDQSxHQUFHO0FBQ0gsbUJBQW1CLFFBQVE7QUFDM0I7QUFDQTtBQUNBLEdBQUc7QUFDSCwwQ0FBMEMsUUFBUTtBQUNsRDtBQUNBO0FBQ0EsR0FBRztBQUNILENBQUMiLCJmaWxlIjoiNTc5Mi5qcyIsInNvdXJjZXNDb250ZW50IjpbIiFmdW5jdGlvbiAodCwgaSkge1xuICBcIm9iamVjdFwiID09IHR5cGVvZiBleHBvcnRzICYmIFwidW5kZWZpbmVkXCIgIT0gdHlwZW9mIG1vZHVsZSA/IG1vZHVsZS5leHBvcnRzID0gaSgpIDogXCJmdW5jdGlvblwiID09IHR5cGVvZiBkZWZpbmUgJiYgZGVmaW5lLmFtZCA/IGRlZmluZShpKSA6ICh0ID0gdCB8fCBzZWxmKS5SQnVzaCA9IGkoKTtcbn0odGhpcywgZnVuY3Rpb24gKCkge1xuICBcInVzZSBzdHJpY3RcIjtcblxuICBmdW5jdGlvbiB0KHQsIHIsIGUsIGEsIGgpIHtcbiAgICAhZnVuY3Rpb24gdChuLCByLCBlLCBhLCBoKSB7XG4gICAgICBmb3IgKDsgYSA+IGU7KSB7XG4gICAgICAgIGlmIChhIC0gZSA+IDYwMCkge1xuICAgICAgICAgIHZhciBvID0gYSAtIGUgKyAxLFxuICAgICAgICAgICAgICBzID0gciAtIGUgKyAxLFxuICAgICAgICAgICAgICBsID0gTWF0aC5sb2cobyksXG4gICAgICAgICAgICAgIGYgPSAuNSAqIE1hdGguZXhwKDIgKiBsIC8gMyksXG4gICAgICAgICAgICAgIHUgPSAuNSAqIE1hdGguc3FydChsICogZiAqIChvIC0gZikgLyBvKSAqIChzIC0gbyAvIDIgPCAwID8gLTEgOiAxKSxcbiAgICAgICAgICAgICAgbSA9IE1hdGgubWF4KGUsIE1hdGguZmxvb3IociAtIHMgKiBmIC8gbyArIHUpKSxcbiAgICAgICAgICAgICAgYyA9IE1hdGgubWluKGEsIE1hdGguZmxvb3IociArIChvIC0gcykgKiBmIC8gbyArIHUpKTtcbiAgICAgICAgICB0KG4sIHIsIG0sIGMsIGgpO1xuICAgICAgICB9XG5cbiAgICAgICAgdmFyIHAgPSBuW3JdLFxuICAgICAgICAgICAgZCA9IGUsXG4gICAgICAgICAgICB4ID0gYTtcblxuICAgICAgICBmb3IgKGkobiwgZSwgciksIGgoblthXSwgcCkgPiAwICYmIGkobiwgZSwgYSk7IGQgPCB4Oykge1xuICAgICAgICAgIGZvciAoaShuLCBkLCB4KSwgZCsrLCB4LS07IGgobltkXSwgcCkgPCAwOykge1xuICAgICAgICAgICAgZCsrO1xuICAgICAgICAgIH1cblxuICAgICAgICAgIGZvciAoOyBoKG5beF0sIHApID4gMDspIHtcbiAgICAgICAgICAgIHgtLTtcbiAgICAgICAgICB9XG4gICAgICAgIH1cblxuICAgICAgICAwID09PSBoKG5bZV0sIHApID8gaShuLCBlLCB4KSA6IGkobiwgKyt4LCBhKSwgeCA8PSByICYmIChlID0geCArIDEpLCByIDw9IHggJiYgKGEgPSB4IC0gMSk7XG4gICAgICB9XG4gICAgfSh0LCByLCBlIHx8IDAsIGEgfHwgdC5sZW5ndGggLSAxLCBoIHx8IG4pO1xuICB9XG5cbiAgZnVuY3Rpb24gaSh0LCBpLCBuKSB7XG4gICAgdmFyIHIgPSB0W2ldO1xuICAgIHRbaV0gPSB0W25dLCB0W25dID0gcjtcbiAgfVxuXG4gIGZ1bmN0aW9uIG4odCwgaSkge1xuICAgIHJldHVybiB0IDwgaSA/IC0xIDogdCA+IGkgPyAxIDogMDtcbiAgfVxuXG4gIHZhciByID0gZnVuY3Rpb24gcih0KSB7XG4gICAgdm9pZCAwID09PSB0ICYmICh0ID0gOSksIHRoaXMuX21heEVudHJpZXMgPSBNYXRoLm1heCg0LCB0KSwgdGhpcy5fbWluRW50cmllcyA9IE1hdGgubWF4KDIsIE1hdGguY2VpbCguNCAqIHRoaXMuX21heEVudHJpZXMpKSwgdGhpcy5jbGVhcigpO1xuICB9O1xuXG4gIGZ1bmN0aW9uIGUodCwgaSwgbikge1xuICAgIGlmICghbikgcmV0dXJuIGkuaW5kZXhPZih0KTtcblxuICAgIGZvciAodmFyIHIgPSAwOyByIDwgaS5sZW5ndGg7IHIrKykge1xuICAgICAgaWYgKG4odCwgaVtyXSkpIHJldHVybiByO1xuICAgIH1cblxuICAgIHJldHVybiAtMTtcbiAgfVxuXG4gIGZ1bmN0aW9uIGEodCwgaSkge1xuICAgIGgodCwgMCwgdC5jaGlsZHJlbi5sZW5ndGgsIGksIHQpO1xuICB9XG5cbiAgZnVuY3Rpb24gaCh0LCBpLCBuLCByLCBlKSB7XG4gICAgZSB8fCAoZSA9IHAobnVsbCkpLCBlLm1pblggPSAxIC8gMCwgZS5taW5ZID0gMSAvIDAsIGUubWF4WCA9IC0xIC8gMCwgZS5tYXhZID0gLTEgLyAwO1xuXG4gICAgZm9yICh2YXIgYSA9IGk7IGEgPCBuOyBhKyspIHtcbiAgICAgIHZhciBoID0gdC5jaGlsZHJlblthXTtcbiAgICAgIG8oZSwgdC5sZWFmID8gcihoKSA6IGgpO1xuICAgIH1cblxuICAgIHJldHVybiBlO1xuICB9XG5cbiAgZnVuY3Rpb24gbyh0LCBpKSB7XG4gICAgcmV0dXJuIHQubWluWCA9IE1hdGgubWluKHQubWluWCwgaS5taW5YKSwgdC5taW5ZID0gTWF0aC5taW4odC5taW5ZLCBpLm1pblkpLCB0Lm1heFggPSBNYXRoLm1heCh0Lm1heFgsIGkubWF4WCksIHQubWF4WSA9IE1hdGgubWF4KHQubWF4WSwgaS5tYXhZKSwgdDtcbiAgfVxuXG4gIGZ1bmN0aW9uIHModCwgaSkge1xuICAgIHJldHVybiB0Lm1pblggLSBpLm1pblg7XG4gIH1cblxuICBmdW5jdGlvbiBsKHQsIGkpIHtcbiAgICByZXR1cm4gdC5taW5ZIC0gaS5taW5ZO1xuICB9XG5cbiAgZnVuY3Rpb24gZih0KSB7XG4gICAgcmV0dXJuICh0Lm1heFggLSB0Lm1pblgpICogKHQubWF4WSAtIHQubWluWSk7XG4gIH1cblxuICBmdW5jdGlvbiB1KHQpIHtcbiAgICByZXR1cm4gdC5tYXhYIC0gdC5taW5YICsgKHQubWF4WSAtIHQubWluWSk7XG4gIH1cblxuICBmdW5jdGlvbiBtKHQsIGkpIHtcbiAgICByZXR1cm4gdC5taW5YIDw9IGkubWluWCAmJiB0Lm1pblkgPD0gaS5taW5ZICYmIGkubWF4WCA8PSB0Lm1heFggJiYgaS5tYXhZIDw9IHQubWF4WTtcbiAgfVxuXG4gIGZ1bmN0aW9uIGModCwgaSkge1xuICAgIHJldHVybiBpLm1pblggPD0gdC5tYXhYICYmIGkubWluWSA8PSB0Lm1heFkgJiYgaS5tYXhYID49IHQubWluWCAmJiBpLm1heFkgPj0gdC5taW5ZO1xuICB9XG5cbiAgZnVuY3Rpb24gcCh0KSB7XG4gICAgcmV0dXJuIHtcbiAgICAgIGNoaWxkcmVuOiB0LFxuICAgICAgaGVpZ2h0OiAxLFxuICAgICAgbGVhZjogITAsXG4gICAgICBtaW5YOiAxIC8gMCxcbiAgICAgIG1pblk6IDEgLyAwLFxuICAgICAgbWF4WDogLTEgLyAwLFxuICAgICAgbWF4WTogLTEgLyAwXG4gICAgfTtcbiAgfVxuXG4gIGZ1bmN0aW9uIGQoaSwgbiwgciwgZSwgYSkge1xuICAgIGZvciAodmFyIGggPSBbbiwgcl07IGgubGVuZ3RoOykge1xuICAgICAgaWYgKCEoKHIgPSBoLnBvcCgpKSAtIChuID0gaC5wb3AoKSkgPD0gZSkpIHtcbiAgICAgICAgdmFyIG8gPSBuICsgTWF0aC5jZWlsKChyIC0gbikgLyBlIC8gMikgKiBlO1xuICAgICAgICB0KGksIG8sIG4sIHIsIGEpLCBoLnB1c2gobiwgbywgbywgcik7XG4gICAgICB9XG4gICAgfVxuICB9XG5cbiAgcmV0dXJuIHIucHJvdG90eXBlLmFsbCA9IGZ1bmN0aW9uICgpIHtcbiAgICByZXR1cm4gdGhpcy5fYWxsKHRoaXMuZGF0YSwgW10pO1xuICB9LCByLnByb3RvdHlwZS5zZWFyY2ggPSBmdW5jdGlvbiAodCkge1xuICAgIHZhciBpID0gdGhpcy5kYXRhLFxuICAgICAgICBuID0gW107XG4gICAgaWYgKCFjKHQsIGkpKSByZXR1cm4gbjtcblxuICAgIGZvciAodmFyIHIgPSB0aGlzLnRvQkJveCwgZSA9IFtdOyBpOykge1xuICAgICAgZm9yICh2YXIgYSA9IDA7IGEgPCBpLmNoaWxkcmVuLmxlbmd0aDsgYSsrKSB7XG4gICAgICAgIHZhciBoID0gaS5jaGlsZHJlblthXSxcbiAgICAgICAgICAgIG8gPSBpLmxlYWYgPyByKGgpIDogaDtcbiAgICAgICAgYyh0LCBvKSAmJiAoaS5sZWFmID8gbi5wdXNoKGgpIDogbSh0LCBvKSA/IHRoaXMuX2FsbChoLCBuKSA6IGUucHVzaChoKSk7XG4gICAgICB9XG5cbiAgICAgIGkgPSBlLnBvcCgpO1xuICAgIH1cblxuICAgIHJldHVybiBuO1xuICB9LCByLnByb3RvdHlwZS5jb2xsaWRlcyA9IGZ1bmN0aW9uICh0KSB7XG4gICAgdmFyIGkgPSB0aGlzLmRhdGE7XG4gICAgaWYgKCFjKHQsIGkpKSByZXR1cm4gITE7XG5cbiAgICBmb3IgKHZhciBuID0gW107IGk7KSB7XG4gICAgICBmb3IgKHZhciByID0gMDsgciA8IGkuY2hpbGRyZW4ubGVuZ3RoOyByKyspIHtcbiAgICAgICAgdmFyIGUgPSBpLmNoaWxkcmVuW3JdLFxuICAgICAgICAgICAgYSA9IGkubGVhZiA/IHRoaXMudG9CQm94KGUpIDogZTtcblxuICAgICAgICBpZiAoYyh0LCBhKSkge1xuICAgICAgICAgIGlmIChpLmxlYWYgfHwgbSh0LCBhKSkgcmV0dXJuICEwO1xuICAgICAgICAgIG4ucHVzaChlKTtcbiAgICAgICAgfVxuICAgICAgfVxuXG4gICAgICBpID0gbi5wb3AoKTtcbiAgICB9XG5cbiAgICByZXR1cm4gITE7XG4gIH0sIHIucHJvdG90eXBlLmxvYWQgPSBmdW5jdGlvbiAodCkge1xuICAgIGlmICghdCB8fCAhdC5sZW5ndGgpIHJldHVybiB0aGlzO1xuXG4gICAgaWYgKHQubGVuZ3RoIDwgdGhpcy5fbWluRW50cmllcykge1xuICAgICAgZm9yICh2YXIgaSA9IDA7IGkgPCB0Lmxlbmd0aDsgaSsrKSB7XG4gICAgICAgIHRoaXMuaW5zZXJ0KHRbaV0pO1xuICAgICAgfVxuXG4gICAgICByZXR1cm4gdGhpcztcbiAgICB9XG5cbiAgICB2YXIgbiA9IHRoaXMuX2J1aWxkKHQuc2xpY2UoKSwgMCwgdC5sZW5ndGggLSAxLCAwKTtcblxuICAgIGlmICh0aGlzLmRhdGEuY2hpbGRyZW4ubGVuZ3RoKSB7XG4gICAgICBpZiAodGhpcy5kYXRhLmhlaWdodCA9PT0gbi5oZWlnaHQpIHRoaXMuX3NwbGl0Um9vdCh0aGlzLmRhdGEsIG4pO2Vsc2Uge1xuICAgICAgICBpZiAodGhpcy5kYXRhLmhlaWdodCA8IG4uaGVpZ2h0KSB7XG4gICAgICAgICAgdmFyIHIgPSB0aGlzLmRhdGE7XG4gICAgICAgICAgdGhpcy5kYXRhID0gbiwgbiA9IHI7XG4gICAgICAgIH1cblxuICAgICAgICB0aGlzLl9pbnNlcnQobiwgdGhpcy5kYXRhLmhlaWdodCAtIG4uaGVpZ2h0IC0gMSwgITApO1xuICAgICAgfVxuICAgIH0gZWxzZSB0aGlzLmRhdGEgPSBuO1xuICAgIHJldHVybiB0aGlzO1xuICB9LCByLnByb3RvdHlwZS5pbnNlcnQgPSBmdW5jdGlvbiAodCkge1xuICAgIHJldHVybiB0ICYmIHRoaXMuX2luc2VydCh0LCB0aGlzLmRhdGEuaGVpZ2h0IC0gMSksIHRoaXM7XG4gIH0sIHIucHJvdG90eXBlLmNsZWFyID0gZnVuY3Rpb24gKCkge1xuICAgIHJldHVybiB0aGlzLmRhdGEgPSBwKFtdKSwgdGhpcztcbiAgfSwgci5wcm90b3R5cGUucmVtb3ZlID0gZnVuY3Rpb24gKHQsIGkpIHtcbiAgICBpZiAoIXQpIHJldHVybiB0aGlzO1xuXG4gICAgZm9yICh2YXIgbiwgciwgYSwgaCA9IHRoaXMuZGF0YSwgbyA9IHRoaXMudG9CQm94KHQpLCBzID0gW10sIGwgPSBbXTsgaCB8fCBzLmxlbmd0aDspIHtcbiAgICAgIGlmIChoIHx8IChoID0gcy5wb3AoKSwgciA9IHNbcy5sZW5ndGggLSAxXSwgbiA9IGwucG9wKCksIGEgPSAhMCksIGgubGVhZikge1xuICAgICAgICB2YXIgZiA9IGUodCwgaC5jaGlsZHJlbiwgaSk7XG4gICAgICAgIGlmICgtMSAhPT0gZikgcmV0dXJuIGguY2hpbGRyZW4uc3BsaWNlKGYsIDEpLCBzLnB1c2goaCksIHRoaXMuX2NvbmRlbnNlKHMpLCB0aGlzO1xuICAgICAgfVxuXG4gICAgICBhIHx8IGgubGVhZiB8fCAhbShoLCBvKSA/IHIgPyAobisrLCBoID0gci5jaGlsZHJlbltuXSwgYSA9ICExKSA6IGggPSBudWxsIDogKHMucHVzaChoKSwgbC5wdXNoKG4pLCBuID0gMCwgciA9IGgsIGggPSBoLmNoaWxkcmVuWzBdKTtcbiAgICB9XG5cbiAgICByZXR1cm4gdGhpcztcbiAgfSwgci5wcm90b3R5cGUudG9CQm94ID0gZnVuY3Rpb24gKHQpIHtcbiAgICByZXR1cm4gdDtcbiAgfSwgci5wcm90b3R5cGUuY29tcGFyZU1pblggPSBmdW5jdGlvbiAodCwgaSkge1xuICAgIHJldHVybiB0Lm1pblggLSBpLm1pblg7XG4gIH0sIHIucHJvdG90eXBlLmNvbXBhcmVNaW5ZID0gZnVuY3Rpb24gKHQsIGkpIHtcbiAgICByZXR1cm4gdC5taW5ZIC0gaS5taW5ZO1xuICB9LCByLnByb3RvdHlwZS50b0pTT04gPSBmdW5jdGlvbiAoKSB7XG4gICAgcmV0dXJuIHRoaXMuZGF0YTtcbiAgfSwgci5wcm90b3R5cGUuZnJvbUpTT04gPSBmdW5jdGlvbiAodCkge1xuICAgIHJldHVybiB0aGlzLmRhdGEgPSB0LCB0aGlzO1xuICB9LCByLnByb3RvdHlwZS5fYWxsID0gZnVuY3Rpb24gKHQsIGkpIHtcbiAgICBmb3IgKHZhciBuID0gW107IHQ7KSB7XG4gICAgICB0LmxlYWYgPyBpLnB1c2guYXBwbHkoaSwgdC5jaGlsZHJlbikgOiBuLnB1c2guYXBwbHkobiwgdC5jaGlsZHJlbiksIHQgPSBuLnBvcCgpO1xuICAgIH1cblxuICAgIHJldHVybiBpO1xuICB9LCByLnByb3RvdHlwZS5fYnVpbGQgPSBmdW5jdGlvbiAodCwgaSwgbiwgcikge1xuICAgIHZhciBlLFxuICAgICAgICBoID0gbiAtIGkgKyAxLFxuICAgICAgICBvID0gdGhpcy5fbWF4RW50cmllcztcbiAgICBpZiAoaCA8PSBvKSByZXR1cm4gYShlID0gcCh0LnNsaWNlKGksIG4gKyAxKSksIHRoaXMudG9CQm94KSwgZTtcbiAgICByIHx8IChyID0gTWF0aC5jZWlsKE1hdGgubG9nKGgpIC8gTWF0aC5sb2cobykpLCBvID0gTWF0aC5jZWlsKGggLyBNYXRoLnBvdyhvLCByIC0gMSkpKSwgKGUgPSBwKFtdKSkubGVhZiA9ICExLCBlLmhlaWdodCA9IHI7XG4gICAgdmFyIHMgPSBNYXRoLmNlaWwoaCAvIG8pLFxuICAgICAgICBsID0gcyAqIE1hdGguY2VpbChNYXRoLnNxcnQobykpO1xuICAgIGQodCwgaSwgbiwgbCwgdGhpcy5jb21wYXJlTWluWCk7XG5cbiAgICBmb3IgKHZhciBmID0gaTsgZiA8PSBuOyBmICs9IGwpIHtcbiAgICAgIHZhciB1ID0gTWF0aC5taW4oZiArIGwgLSAxLCBuKTtcbiAgICAgIGQodCwgZiwgdSwgcywgdGhpcy5jb21wYXJlTWluWSk7XG5cbiAgICAgIGZvciAodmFyIG0gPSBmOyBtIDw9IHU7IG0gKz0gcykge1xuICAgICAgICB2YXIgYyA9IE1hdGgubWluKG0gKyBzIC0gMSwgdSk7XG4gICAgICAgIGUuY2hpbGRyZW4ucHVzaCh0aGlzLl9idWlsZCh0LCBtLCBjLCByIC0gMSkpO1xuICAgICAgfVxuICAgIH1cblxuICAgIHJldHVybiBhKGUsIHRoaXMudG9CQm94KSwgZTtcbiAgfSwgci5wcm90b3R5cGUuX2Nob29zZVN1YnRyZWUgPSBmdW5jdGlvbiAodCwgaSwgbiwgcikge1xuICAgIGZvciAoOyByLnB1c2goaSksICFpLmxlYWYgJiYgci5sZW5ndGggLSAxICE9PSBuOykge1xuICAgICAgZm9yICh2YXIgZSA9IDEgLyAwLCBhID0gMSAvIDAsIGggPSB2b2lkIDAsIG8gPSAwOyBvIDwgaS5jaGlsZHJlbi5sZW5ndGg7IG8rKykge1xuICAgICAgICB2YXIgcyA9IGkuY2hpbGRyZW5bb10sXG4gICAgICAgICAgICBsID0gZihzKSxcbiAgICAgICAgICAgIHUgPSAobSA9IHQsIGMgPSBzLCAoTWF0aC5tYXgoYy5tYXhYLCBtLm1heFgpIC0gTWF0aC5taW4oYy5taW5YLCBtLm1pblgpKSAqIChNYXRoLm1heChjLm1heFksIG0ubWF4WSkgLSBNYXRoLm1pbihjLm1pblksIG0ubWluWSkpIC0gbCk7XG4gICAgICAgIHUgPCBhID8gKGEgPSB1LCBlID0gbCA8IGUgPyBsIDogZSwgaCA9IHMpIDogdSA9PT0gYSAmJiBsIDwgZSAmJiAoZSA9IGwsIGggPSBzKTtcbiAgICAgIH1cblxuICAgICAgaSA9IGggfHwgaS5jaGlsZHJlblswXTtcbiAgICB9XG5cbiAgICB2YXIgbSwgYztcbiAgICByZXR1cm4gaTtcbiAgfSwgci5wcm90b3R5cGUuX2luc2VydCA9IGZ1bmN0aW9uICh0LCBpLCBuKSB7XG4gICAgdmFyIHIgPSBuID8gdCA6IHRoaXMudG9CQm94KHQpLFxuICAgICAgICBlID0gW10sXG4gICAgICAgIGEgPSB0aGlzLl9jaG9vc2VTdWJ0cmVlKHIsIHRoaXMuZGF0YSwgaSwgZSk7XG5cbiAgICBmb3IgKGEuY2hpbGRyZW4ucHVzaCh0KSwgbyhhLCByKTsgaSA+PSAwICYmIGVbaV0uY2hpbGRyZW4ubGVuZ3RoID4gdGhpcy5fbWF4RW50cmllczspIHtcbiAgICAgIHRoaXMuX3NwbGl0KGUsIGkpLCBpLS07XG4gICAgfVxuXG4gICAgdGhpcy5fYWRqdXN0UGFyZW50QkJveGVzKHIsIGUsIGkpO1xuICB9LCByLnByb3RvdHlwZS5fc3BsaXQgPSBmdW5jdGlvbiAodCwgaSkge1xuICAgIHZhciBuID0gdFtpXSxcbiAgICAgICAgciA9IG4uY2hpbGRyZW4ubGVuZ3RoLFxuICAgICAgICBlID0gdGhpcy5fbWluRW50cmllcztcblxuICAgIHRoaXMuX2Nob29zZVNwbGl0QXhpcyhuLCBlLCByKTtcblxuICAgIHZhciBoID0gdGhpcy5fY2hvb3NlU3BsaXRJbmRleChuLCBlLCByKSxcbiAgICAgICAgbyA9IHAobi5jaGlsZHJlbi5zcGxpY2UoaCwgbi5jaGlsZHJlbi5sZW5ndGggLSBoKSk7XG5cbiAgICBvLmhlaWdodCA9IG4uaGVpZ2h0LCBvLmxlYWYgPSBuLmxlYWYsIGEobiwgdGhpcy50b0JCb3gpLCBhKG8sIHRoaXMudG9CQm94KSwgaSA/IHRbaSAtIDFdLmNoaWxkcmVuLnB1c2gobykgOiB0aGlzLl9zcGxpdFJvb3Qobiwgbyk7XG4gIH0sIHIucHJvdG90eXBlLl9zcGxpdFJvb3QgPSBmdW5jdGlvbiAodCwgaSkge1xuICAgIHRoaXMuZGF0YSA9IHAoW3QsIGldKSwgdGhpcy5kYXRhLmhlaWdodCA9IHQuaGVpZ2h0ICsgMSwgdGhpcy5kYXRhLmxlYWYgPSAhMSwgYSh0aGlzLmRhdGEsIHRoaXMudG9CQm94KTtcbiAgfSwgci5wcm90b3R5cGUuX2Nob29zZVNwbGl0SW5kZXggPSBmdW5jdGlvbiAodCwgaSwgbikge1xuICAgIGZvciAodmFyIHIsIGUsIGEsIG8sIHMsIGwsIHUsIG0gPSAxIC8gMCwgYyA9IDEgLyAwLCBwID0gaTsgcCA8PSBuIC0gaTsgcCsrKSB7XG4gICAgICB2YXIgZCA9IGgodCwgMCwgcCwgdGhpcy50b0JCb3gpLFxuICAgICAgICAgIHggPSBoKHQsIHAsIG4sIHRoaXMudG9CQm94KSxcbiAgICAgICAgICB2ID0gKGUgPSBkLCBhID0geCwgbyA9IHZvaWQgMCwgcyA9IHZvaWQgMCwgbCA9IHZvaWQgMCwgdSA9IHZvaWQgMCwgbyA9IE1hdGgubWF4KGUubWluWCwgYS5taW5YKSwgcyA9IE1hdGgubWF4KGUubWluWSwgYS5taW5ZKSwgbCA9IE1hdGgubWluKGUubWF4WCwgYS5tYXhYKSwgdSA9IE1hdGgubWluKGUubWF4WSwgYS5tYXhZKSwgTWF0aC5tYXgoMCwgbCAtIG8pICogTWF0aC5tYXgoMCwgdSAtIHMpKSxcbiAgICAgICAgICBNID0gZihkKSArIGYoeCk7XG4gICAgICB2IDwgbSA/IChtID0gdiwgciA9IHAsIGMgPSBNIDwgYyA/IE0gOiBjKSA6IHYgPT09IG0gJiYgTSA8IGMgJiYgKGMgPSBNLCByID0gcCk7XG4gICAgfVxuXG4gICAgcmV0dXJuIHIgfHwgbiAtIGk7XG4gIH0sIHIucHJvdG90eXBlLl9jaG9vc2VTcGxpdEF4aXMgPSBmdW5jdGlvbiAodCwgaSwgbikge1xuICAgIHZhciByID0gdC5sZWFmID8gdGhpcy5jb21wYXJlTWluWCA6IHMsXG4gICAgICAgIGUgPSB0LmxlYWYgPyB0aGlzLmNvbXBhcmVNaW5ZIDogbDtcbiAgICB0aGlzLl9hbGxEaXN0TWFyZ2luKHQsIGksIG4sIHIpIDwgdGhpcy5fYWxsRGlzdE1hcmdpbih0LCBpLCBuLCBlKSAmJiB0LmNoaWxkcmVuLnNvcnQocik7XG4gIH0sIHIucHJvdG90eXBlLl9hbGxEaXN0TWFyZ2luID0gZnVuY3Rpb24gKHQsIGksIG4sIHIpIHtcbiAgICB0LmNoaWxkcmVuLnNvcnQocik7XG5cbiAgICBmb3IgKHZhciBlID0gdGhpcy50b0JCb3gsIGEgPSBoKHQsIDAsIGksIGUpLCBzID0gaCh0LCBuIC0gaSwgbiwgZSksIGwgPSB1KGEpICsgdShzKSwgZiA9IGk7IGYgPCBuIC0gaTsgZisrKSB7XG4gICAgICB2YXIgbSA9IHQuY2hpbGRyZW5bZl07XG4gICAgICBvKGEsIHQubGVhZiA/IGUobSkgOiBtKSwgbCArPSB1KGEpO1xuICAgIH1cblxuICAgIGZvciAodmFyIGMgPSBuIC0gaSAtIDE7IGMgPj0gaTsgYy0tKSB7XG4gICAgICB2YXIgcCA9IHQuY2hpbGRyZW5bY107XG4gICAgICBvKHMsIHQubGVhZiA/IGUocCkgOiBwKSwgbCArPSB1KHMpO1xuICAgIH1cblxuICAgIHJldHVybiBsO1xuICB9LCByLnByb3RvdHlwZS5fYWRqdXN0UGFyZW50QkJveGVzID0gZnVuY3Rpb24gKHQsIGksIG4pIHtcbiAgICBmb3IgKHZhciByID0gbjsgciA+PSAwOyByLS0pIHtcbiAgICAgIG8oaVtyXSwgdCk7XG4gICAgfVxuICB9LCByLnByb3RvdHlwZS5fY29uZGVuc2UgPSBmdW5jdGlvbiAodCkge1xuICAgIGZvciAodmFyIGkgPSB0Lmxlbmd0aCAtIDEsIG4gPSB2b2lkIDA7IGkgPj0gMDsgaS0tKSB7XG4gICAgICAwID09PSB0W2ldLmNoaWxkcmVuLmxlbmd0aCA/IGkgPiAwID8gKG4gPSB0W2kgLSAxXS5jaGlsZHJlbikuc3BsaWNlKG4uaW5kZXhPZih0W2ldKSwgMSkgOiB0aGlzLmNsZWFyKCkgOiBhKHRbaV0sIHRoaXMudG9CQm94KTtcbiAgICB9XG4gIH0sIHI7XG59KTsiXSwic291cmNlUm9vdCI6IiJ9\n//# sourceURL=webpack-internal:///5792\n')},9682:function(__unused_webpack_module,__webpack_exports__,__webpack_require__){"use strict";eval('// ESM COMPAT FLAG\n__webpack_require__.r(__webpack_exports__);\n\n// EXPORTS\n__webpack_require__.d(__webpack_exports__, {\n "default": function() { return /* binding */ cejst; }\n});\n\n// EXTERNAL MODULE: ./node_modules/react/index.js\nvar react = __webpack_require__(7294);\n// EXTERNAL MODULE: ./src/components/layout.tsx + 8 modules\nvar layout = __webpack_require__(6515);\n;// CONCATENATED MODULE: ./node_modules/ol/Disposable.js\n/**\n * @module ol/Disposable\n */\n\n/**\n * @classdesc\n * Objects that need to clean up after themselves.\n */\nvar Disposable =\n/** @class */\nfunction () {\n function Disposable() {\n /**\n * The object has already been disposed.\n * @type {boolean}\n * @protected\n */\n this.disposed = false;\n }\n /**\n * Clean up.\n */\n\n\n Disposable.prototype.dispose = function () {\n if (!this.disposed) {\n this.disposed = true;\n this.disposeInternal();\n }\n };\n /**\n * Extension point for disposable objects.\n * @protected\n */\n\n\n Disposable.prototype.disposeInternal = function () {};\n\n return Disposable;\n}();\n\n/* harmony default export */ var ol_Disposable = (Disposable);\n;// CONCATENATED MODULE: ./node_modules/ol/array.js\n/**\n * @module ol/array\n */\n\n/**\n * Performs a binary search on the provided sorted list and returns the index of the item if found. If it can\'t be found it\'ll return -1.\n * https://github.com/darkskyapp/binary-search\n *\n * @param {Array<*>} haystack Items to search through.\n * @param {*} needle The item to look for.\n * @param {Function=} opt_comparator Comparator function.\n * @return {number} The index of the item if found, -1 if not.\n */\nfunction binarySearch(haystack, needle, opt_comparator) {\n var mid, cmp;\n var comparator = opt_comparator || numberSafeCompareFunction;\n var low = 0;\n var high = haystack.length;\n var found = false;\n\n while (low < high) {\n /* Note that "(low + high) >>> 1" may overflow, and results in a typecast\n * to double (which gives the wrong results). */\n mid = low + (high - low >> 1);\n cmp = +comparator(haystack[mid], needle);\n\n if (cmp < 0.0) {\n /* Too low. */\n low = mid + 1;\n } else {\n /* Key found or too high */\n high = mid;\n found = !cmp;\n }\n }\n /* Key not found. */\n\n\n return found ? low : ~low;\n}\n/**\n * Compare function for array sort that is safe for numbers.\n * @param {*} a The first object to be compared.\n * @param {*} b The second object to be compared.\n * @return {number} A negative number, zero, or a positive number as the first\n * argument is less than, equal to, or greater than the second.\n */\n\nfunction numberSafeCompareFunction(a, b) {\n return a > b ? 1 : a < b ? -1 : 0;\n}\n/**\n * Whether the array contains the given object.\n * @param {Array<*>} arr The array to test for the presence of the element.\n * @param {*} obj The object for which to test.\n * @return {boolean} The object is in the array.\n */\n\nfunction includes(arr, obj) {\n return arr.indexOf(obj) >= 0;\n}\n/**\n * @param {Array<number>} arr Array.\n * @param {number} target Target.\n * @param {number} direction 0 means return the nearest, > 0\n * means return the largest nearest, < 0 means return the\n * smallest nearest.\n * @return {number} Index.\n */\n\nfunction linearFindNearest(arr, target, direction) {\n var n = arr.length;\n\n if (arr[0] <= target) {\n return 0;\n } else if (target <= arr[n - 1]) {\n return n - 1;\n } else {\n var i = void 0;\n\n if (direction > 0) {\n for (i = 1; i < n; ++i) {\n if (arr[i] < target) {\n return i - 1;\n }\n }\n } else if (direction < 0) {\n for (i = 1; i < n; ++i) {\n if (arr[i] <= target) {\n return i;\n }\n }\n } else {\n for (i = 1; i < n; ++i) {\n if (arr[i] == target) {\n return i;\n } else if (arr[i] < target) {\n if (arr[i - 1] - target < target - arr[i]) {\n return i - 1;\n } else {\n return i;\n }\n }\n }\n }\n\n return n - 1;\n }\n}\n/**\n * @param {Array<*>} arr Array.\n * @param {number} begin Begin index.\n * @param {number} end End index.\n */\n\nfunction reverseSubArray(arr, begin, end) {\n while (begin < end) {\n var tmp = arr[begin];\n arr[begin] = arr[end];\n arr[end] = tmp;\n ++begin;\n --end;\n }\n}\n/**\n * @param {Array<VALUE>} arr The array to modify.\n * @param {!Array<VALUE>|VALUE} data The elements or arrays of elements to add to arr.\n * @template VALUE\n */\n\nfunction array_extend(arr, data) {\n var extension = Array.isArray(data) ? data : [data];\n var length = extension.length;\n\n for (var i = 0; i < length; i++) {\n arr[arr.length] = extension[i];\n }\n}\n/**\n * @param {Array<VALUE>} arr The array to modify.\n * @param {VALUE} obj The element to remove.\n * @template VALUE\n * @return {boolean} If the element was removed.\n */\n\nfunction remove(arr, obj) {\n var i = arr.indexOf(obj);\n var found = i > -1;\n\n if (found) {\n arr.splice(i, 1);\n }\n\n return found;\n}\n/**\n * @param {Array<VALUE>} arr The array to search in.\n * @param {function(VALUE, number, ?) : boolean} func The function to compare.\n * @template VALUE\n * @return {VALUE|null} The element found or null.\n */\n\nfunction find(arr, func) {\n var length = arr.length >>> 0;\n var value;\n\n for (var i = 0; i < length; i++) {\n value = arr[i];\n\n if (func(value, i, arr)) {\n return value;\n }\n }\n\n return null;\n}\n/**\n * @param {Array|Uint8ClampedArray} arr1 The first array to compare.\n * @param {Array|Uint8ClampedArray} arr2 The second array to compare.\n * @return {boolean} Whether the two arrays are equal.\n */\n\nfunction equals(arr1, arr2) {\n var len1 = arr1.length;\n\n if (len1 !== arr2.length) {\n return false;\n }\n\n for (var i = 0; i < len1; i++) {\n if (arr1[i] !== arr2[i]) {\n return false;\n }\n }\n\n return true;\n}\n/**\n * Sort the passed array such that the relative order of equal elements is preverved.\n * See https://en.wikipedia.org/wiki/Sorting_algorithm#Stability for details.\n * @param {Array<*>} arr The array to sort (modifies original).\n * @param {!function(*, *): number} compareFnc Comparison function.\n * @api\n */\n\nfunction stableSort(arr, compareFnc) {\n var length = arr.length;\n var tmp = Array(arr.length);\n var i;\n\n for (i = 0; i < length; i++) {\n tmp[i] = {\n index: i,\n value: arr[i]\n };\n }\n\n tmp.sort(function (a, b) {\n return compareFnc(a.value, b.value) || a.index - b.index;\n });\n\n for (i = 0; i < arr.length; i++) {\n arr[i] = tmp[i].value;\n }\n}\n/**\n * @param {Array<*>} arr The array to search in.\n * @param {Function} func Comparison function.\n * @return {number} Return index.\n */\n\nfunction findIndex(arr, func) {\n var index;\n var found = !arr.every(function (el, idx) {\n index = idx;\n return !func(el, idx, arr);\n });\n return found ? index : -1;\n}\n/**\n * @param {Array<*>} arr The array to test.\n * @param {Function=} opt_func Comparison function.\n * @param {boolean=} opt_strict Strictly sorted (default false).\n * @return {boolean} Return index.\n */\n\nfunction isSorted(arr, opt_func, opt_strict) {\n var compare = opt_func || numberSafeCompareFunction;\n return arr.every(function (currentVal, index) {\n if (index === 0) {\n return true;\n }\n\n var res = compare(arr[index - 1], currentVal);\n return !(res > 0 || opt_strict && res === 0);\n });\n}\n;// CONCATENATED MODULE: ./node_modules/ol/functions.js\n/**\n * @module ol/functions\n */\n\n/**\n * Always returns true.\n * @returns {boolean} true.\n */\n\nfunction TRUE() {\n return true;\n}\n/**\n * Always returns false.\n * @returns {boolean} false.\n */\n\nfunction functions_FALSE() {\n return false;\n}\n/**\n * A reusable function, used e.g. as a default for callbacks.\n *\n * @return {void} Nothing.\n */\n\nfunction VOID() {}\n/**\n * Wrap a function in another function that remembers the last return. If the\n * returned function is called twice in a row with the same arguments and the same\n * this object, it will return the value from the first call in the second call.\n *\n * @param {function(...any): ReturnType} fn The function to memoize.\n * @return {function(...any): ReturnType} The memoized function.\n * @template ReturnType\n */\n\nfunction memoizeOne(fn) {\n var called = false;\n /** @type {ReturnType} */\n\n var lastResult;\n /** @type {Array<any>} */\n\n var lastArgs;\n var lastThis;\n return function () {\n var nextArgs = Array.prototype.slice.call(arguments);\n\n if (!called || this !== lastThis || !equals(nextArgs, lastArgs)) {\n called = true;\n lastThis = this;\n lastArgs = nextArgs;\n lastResult = fn.apply(this, arguments);\n }\n\n return lastResult;\n };\n}\n;// CONCATENATED MODULE: ./node_modules/ol/util.js\n/**\n * @module ol/util\n */\n\n/**\n * @return {?} Any return.\n */\nfunction util_abstract() {\n return (\n /** @type {?} */\n function () {\n throw new Error(\'Unimplemented abstract method.\');\n }()\n );\n}\n/**\n * Counter for getUid.\n * @type {number}\n * @private\n */\n\nvar uidCounter_ = 0;\n/**\n * Gets a unique ID for an object. This mutates the object so that further calls\n * with the same object as a parameter returns the same value. Unique IDs are generated\n * as a strictly increasing sequence. Adapted from goog.getUid.\n *\n * @param {Object} obj The object to get the unique ID for.\n * @return {string} The unique ID for the object.\n * @api\n */\n\nfunction util_getUid(obj) {\n return obj.ol_uid || (obj.ol_uid = String(++uidCounter_));\n}\n/**\n * OpenLayers version.\n * @type {string}\n */\n\nvar VERSION = \'6.5.0\';\n;// CONCATENATED MODULE: ./node_modules/ol/AssertionError.js\nvar __extends = undefined && undefined.__extends || function () {\n var _extendStatics = function extendStatics(d, b) {\n _extendStatics = Object.setPrototypeOf || {\n __proto__: []\n } instanceof Array && function (d, b) {\n d.__proto__ = b;\n } || function (d, b) {\n for (var p in b) {\n if (Object.prototype.hasOwnProperty.call(b, p)) d[p] = b[p];\n }\n };\n\n return _extendStatics(d, b);\n };\n\n return function (d, b) {\n _extendStatics(d, b);\n\n function __() {\n this.constructor = d;\n }\n\n d.prototype = b === null ? Object.create(b) : (__.prototype = b.prototype, new __());\n };\n}();\n/**\n * @module ol/AssertionError\n */\n\n\n\n/**\n * Error object thrown when an assertion failed. This is an ECMA-262 Error,\n * extended with a `code` property.\n * See https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Error.\n */\n\nvar AssertionError =\n/** @class */\nfunction (_super) {\n __extends(AssertionError, _super);\n /**\n * @param {number} code Error code.\n */\n\n\n function AssertionError(code) {\n var _this = this;\n\n var path = VERSION === \'latest\' ? VERSION : \'v\' + VERSION.split(\'-\')[0];\n var message = \'Assertion failed. See https://openlayers.org/en/\' + path + \'/doc/errors/#\' + code + \' for details.\';\n _this = _super.call(this, message) || this;\n /**\n * Error code. The meaning of the code can be found on\n * https://openlayers.org/en/latest/doc/errors/ (replace `latest` with\n * the version found in the OpenLayers script\'s header comment if a version\n * other than the latest is used).\n * @type {number}\n * @api\n */\n\n _this.code = code;\n /**\n * @type {string}\n */\n\n _this.name = \'AssertionError\'; // Re-assign message, see https://github.com/Rich-Harris/buble/issues/40\n\n _this.message = message;\n return _this;\n }\n\n return AssertionError;\n}(Error);\n\n/* harmony default export */ var ol_AssertionError = (AssertionError);\n;// CONCATENATED MODULE: ./node_modules/ol/asserts.js\n/**\n * @module ol/asserts\n */\n\n/**\n * @param {*} assertion Assertion we expected to be truthy.\n * @param {number} errorCode Error code.\n */\n\nfunction asserts_assert(assertion, errorCode) {\n if (!assertion) {\n throw new ol_AssertionError(errorCode);\n }\n}\n;// CONCATENATED MODULE: ./node_modules/ol/transform.js\n/**\n * @module ol/transform\n */\n\n/**\n * An array representing an affine 2d transformation for use with\n * {@link module:ol/transform} functions. The array has 6 elements.\n * @typedef {!Array<number>} Transform\n * @api\n */\n\n/**\n * Collection of affine 2d transformation functions. The functions work on an\n * array of 6 elements. The element order is compatible with the [SVGMatrix\n * interface](https://developer.mozilla.org/en-US/docs/Web/API/SVGMatrix) and is\n * a subset (elements a to f) of a 3×3 matrix:\n * ```\n * [ a c e ]\n * [ b d f ]\n * [ 0 0 1 ]\n * ```\n */\n\n/**\n * @private\n * @type {Transform}\n */\n\nvar tmp_ = new Array(6);\n/**\n * Create an identity transform.\n * @return {!Transform} Identity transform.\n */\n\nfunction create() {\n return [1, 0, 0, 1, 0, 0];\n}\n/**\n * Resets the given transform to an identity transform.\n * @param {!Transform} transform Transform.\n * @return {!Transform} Transform.\n */\n\nfunction transform_reset(transform) {\n return set(transform, 1, 0, 0, 1, 0, 0);\n}\n/**\n * Multiply the underlying matrices of two transforms and return the result in\n * the first transform.\n * @param {!Transform} transform1 Transform parameters of matrix 1.\n * @param {!Transform} transform2 Transform parameters of matrix 2.\n * @return {!Transform} transform1 multiplied with transform2.\n */\n\nfunction multiply(transform1, transform2) {\n var a1 = transform1[0];\n var b1 = transform1[1];\n var c1 = transform1[2];\n var d1 = transform1[3];\n var e1 = transform1[4];\n var f1 = transform1[5];\n var a2 = transform2[0];\n var b2 = transform2[1];\n var c2 = transform2[2];\n var d2 = transform2[3];\n var e2 = transform2[4];\n var f2 = transform2[5];\n transform1[0] = a1 * a2 + c1 * b2;\n transform1[1] = b1 * a2 + d1 * b2;\n transform1[2] = a1 * c2 + c1 * d2;\n transform1[3] = b1 * c2 + d1 * d2;\n transform1[4] = a1 * e2 + c1 * f2 + e1;\n transform1[5] = b1 * e2 + d1 * f2 + f1;\n return transform1;\n}\n/**\n * Set the transform components a-f on a given transform.\n * @param {!Transform} transform Transform.\n * @param {number} a The a component of the transform.\n * @param {number} b The b component of the transform.\n * @param {number} c The c component of the transform.\n * @param {number} d The d component of the transform.\n * @param {number} e The e component of the transform.\n * @param {number} f The f component of the transform.\n * @return {!Transform} Matrix with transform applied.\n */\n\nfunction set(transform, a, b, c, d, e, f) {\n transform[0] = a;\n transform[1] = b;\n transform[2] = c;\n transform[3] = d;\n transform[4] = e;\n transform[5] = f;\n return transform;\n}\n/**\n * Set transform on one matrix from another matrix.\n * @param {!Transform} transform1 Matrix to set transform to.\n * @param {!Transform} transform2 Matrix to set transform from.\n * @return {!Transform} transform1 with transform from transform2 applied.\n */\n\nfunction setFromArray(transform1, transform2) {\n transform1[0] = transform2[0];\n transform1[1] = transform2[1];\n transform1[2] = transform2[2];\n transform1[3] = transform2[3];\n transform1[4] = transform2[4];\n transform1[5] = transform2[5];\n return transform1;\n}\n/**\n * Transforms the given coordinate with the given transform returning the\n * resulting, transformed coordinate. The coordinate will be modified in-place.\n *\n * @param {Transform} transform The transformation.\n * @param {import("./coordinate.js").Coordinate|import("./pixel.js").Pixel} coordinate The coordinate to transform.\n * @return {import("./coordinate.js").Coordinate|import("./pixel.js").Pixel} return coordinate so that operations can be\n * chained together.\n */\n\nfunction apply(transform, coordinate) {\n var x = coordinate[0];\n var y = coordinate[1];\n coordinate[0] = transform[0] * x + transform[2] * y + transform[4];\n coordinate[1] = transform[1] * x + transform[3] * y + transform[5];\n return coordinate;\n}\n/**\n * Applies rotation to the given transform.\n * @param {!Transform} transform Transform.\n * @param {number} angle Angle in radians.\n * @return {!Transform} The rotated transform.\n */\n\nfunction rotate(transform, angle) {\n var cos = Math.cos(angle);\n var sin = Math.sin(angle);\n return multiply(transform, set(tmp_, cos, sin, -sin, cos, 0, 0));\n}\n/**\n * Applies scale to a given transform.\n * @param {!Transform} transform Transform.\n * @param {number} x Scale factor x.\n * @param {number} y Scale factor y.\n * @return {!Transform} The scaled transform.\n */\n\nfunction scale(transform, x, y) {\n return multiply(transform, set(tmp_, x, 0, 0, y, 0, 0));\n}\n/**\n * Creates a scale transform.\n * @param {!Transform} target Transform to overwrite.\n * @param {number} x Scale factor x.\n * @param {number} y Scale factor y.\n * @return {!Transform} The scale transform.\n */\n\nfunction makeScale(target, x, y) {\n return set(target, x, 0, 0, y, 0, 0);\n}\n/**\n * Applies translation to the given transform.\n * @param {!Transform} transform Transform.\n * @param {number} dx Translation x.\n * @param {number} dy Translation y.\n * @return {!Transform} The translated transform.\n */\n\nfunction translate(transform, dx, dy) {\n return multiply(transform, set(tmp_, 1, 0, 0, 1, dx, dy));\n}\n/**\n * Creates a composite transform given an initial translation, scale, rotation, and\n * final translation (in that order only, not commutative).\n * @param {!Transform} transform The transform (will be modified in place).\n * @param {number} dx1 Initial translation x.\n * @param {number} dy1 Initial translation y.\n * @param {number} sx Scale factor x.\n * @param {number} sy Scale factor y.\n * @param {number} angle Rotation (in counter-clockwise radians).\n * @param {number} dx2 Final translation x.\n * @param {number} dy2 Final translation y.\n * @return {!Transform} The composite transform.\n */\n\nfunction compose(transform, dx1, dy1, sx, sy, angle, dx2, dy2) {\n var sin = Math.sin(angle);\n var cos = Math.cos(angle);\n transform[0] = sx * cos;\n transform[1] = sy * sin;\n transform[2] = -sx * sin;\n transform[3] = sy * cos;\n transform[4] = dx2 * sx * cos - dy2 * sx * sin + dx1;\n transform[5] = dx2 * sy * sin + dy2 * sy * cos + dy1;\n return transform;\n}\n/**\n * Creates a composite transform given an initial translation, scale, rotation, and\n * final translation (in that order only, not commutative). The resulting transform\n * string can be applied as `transform` porperty of an HTMLElement\'s style.\n * @param {number} dx1 Initial translation x.\n * @param {number} dy1 Initial translation y.\n * @param {number} sx Scale factor x.\n * @param {number} sy Scale factor y.\n * @param {number} angle Rotation (in counter-clockwise radians).\n * @param {number} dx2 Final translation x.\n * @param {number} dy2 Final translation y.\n * @return {string} The composite css transform.\n * @api\n */\n\nfunction composeCssTransform(dx1, dy1, sx, sy, angle, dx2, dy2) {\n return transform_toString(compose(create(), dx1, dy1, sx, sy, angle, dx2, dy2));\n}\n/**\n * Invert the given transform.\n * @param {!Transform} source The source transform to invert.\n * @return {!Transform} The inverted (source) transform.\n */\n\nfunction invert(source) {\n return makeInverse(source, source);\n}\n/**\n * Invert the given transform.\n * @param {!Transform} target Transform to be set as the inverse of\n * the source transform.\n * @param {!Transform} source The source transform to invert.\n * @return {!Transform} The inverted (target) transform.\n */\n\nfunction makeInverse(target, source) {\n var det = determinant(source);\n asserts_assert(det !== 0, 32); // Transformation matrix cannot be inverted\n\n var a = source[0];\n var b = source[1];\n var c = source[2];\n var d = source[3];\n var e = source[4];\n var f = source[5];\n target[0] = d / det;\n target[1] = -b / det;\n target[2] = -c / det;\n target[3] = a / det;\n target[4] = (c * f - d * e) / det;\n target[5] = -(a * f - b * e) / det;\n return target;\n}\n/**\n * Returns the determinant of the given matrix.\n * @param {!Transform} mat Matrix.\n * @return {number} Determinant.\n */\n\nfunction determinant(mat) {\n return mat[0] * mat[3] - mat[1] * mat[2];\n}\n/**\n * A string version of the transform. This can be used\n * for CSS transforms.\n * @param {!Transform} mat Matrix.\n * @return {string} The transform as a string.\n */\n\nfunction transform_toString(mat) {\n return \'matrix(\' + mat.join(\', \') + \')\';\n}\n;// CONCATENATED MODULE: ./node_modules/ol/extent/Corner.js\n/**\n * @module ol/extent/Corner\n */\n\n/**\n * Extent corner.\n * @enum {string}\n */\n/* harmony default export */ var Corner = ({\n BOTTOM_LEFT: \'bottom-left\',\n BOTTOM_RIGHT: \'bottom-right\',\n TOP_LEFT: \'top-left\',\n TOP_RIGHT: \'top-right\'\n});\n;// CONCATENATED MODULE: ./node_modules/ol/extent/Relationship.js\n/**\n * @module ol/extent/Relationship\n */\n\n/**\n * Relationship to an extent.\n * @enum {number}\n */\n/* harmony default export */ var Relationship = ({\n UNKNOWN: 0,\n INTERSECTING: 1,\n ABOVE: 2,\n RIGHT: 4,\n BELOW: 8,\n LEFT: 16\n});\n;// CONCATENATED MODULE: ./node_modules/ol/extent.js\n/**\n * @module ol/extent\n */\n\n\n\n/**\n * An array of numbers representing an extent: `[minx, miny, maxx, maxy]`.\n * @typedef {Array<number>} Extent\n * @api\n */\n\n/**\n * Build an extent that includes all given coordinates.\n *\n * @param {Array<import("./coordinate.js").Coordinate>} coordinates Coordinates.\n * @return {Extent} Bounding extent.\n * @api\n */\n\nfunction boundingExtent(coordinates) {\n var extent = createEmpty();\n\n for (var i = 0, ii = coordinates.length; i < ii; ++i) {\n extendCoordinate(extent, coordinates[i]);\n }\n\n return extent;\n}\n/**\n * @param {Array<number>} xs Xs.\n * @param {Array<number>} ys Ys.\n * @param {Extent=} opt_extent Destination extent.\n * @private\n * @return {Extent} Extent.\n */\n\nfunction _boundingExtentXYs(xs, ys, opt_extent) {\n var minX = Math.min.apply(null, xs);\n var minY = Math.min.apply(null, ys);\n var maxX = Math.max.apply(null, xs);\n var maxY = Math.max.apply(null, ys);\n return createOrUpdate(minX, minY, maxX, maxY, opt_extent);\n}\n/**\n * Return extent increased by the provided value.\n * @param {Extent} extent Extent.\n * @param {number} value The amount by which the extent should be buffered.\n * @param {Extent=} opt_extent Extent.\n * @return {Extent} Extent.\n * @api\n */\n\n\nfunction buffer(extent, value, opt_extent) {\n if (opt_extent) {\n opt_extent[0] = extent[0] - value;\n opt_extent[1] = extent[1] - value;\n opt_extent[2] = extent[2] + value;\n opt_extent[3] = extent[3] + value;\n return opt_extent;\n } else {\n return [extent[0] - value, extent[1] - value, extent[2] + value, extent[3] + value];\n }\n}\n/**\n * Creates a clone of an extent.\n *\n * @param {Extent} extent Extent to clone.\n * @param {Extent=} opt_extent Extent.\n * @return {Extent} The clone.\n */\n\nfunction clone(extent, opt_extent) {\n if (opt_extent) {\n opt_extent[0] = extent[0];\n opt_extent[1] = extent[1];\n opt_extent[2] = extent[2];\n opt_extent[3] = extent[3];\n return opt_extent;\n } else {\n return extent.slice();\n }\n}\n/**\n * @param {Extent} extent Extent.\n * @param {number} x X.\n * @param {number} y Y.\n * @return {number} Closest squared distance.\n */\n\nfunction closestSquaredDistanceXY(extent, x, y) {\n var dx, dy;\n\n if (x < extent[0]) {\n dx = extent[0] - x;\n } else if (extent[2] < x) {\n dx = x - extent[2];\n } else {\n dx = 0;\n }\n\n if (y < extent[1]) {\n dy = extent[1] - y;\n } else if (extent[3] < y) {\n dy = y - extent[3];\n } else {\n dy = 0;\n }\n\n return dx * dx + dy * dy;\n}\n/**\n * Check if the passed coordinate is contained or on the edge of the extent.\n *\n * @param {Extent} extent Extent.\n * @param {import("./coordinate.js").Coordinate} coordinate Coordinate.\n * @return {boolean} The coordinate is contained in the extent.\n * @api\n */\n\nfunction containsCoordinate(extent, coordinate) {\n return containsXY(extent, coordinate[0], coordinate[1]);\n}\n/**\n * Check if one extent contains another.\n *\n * An extent is deemed contained if it lies completely within the other extent,\n * including if they share one or more edges.\n *\n * @param {Extent} extent1 Extent 1.\n * @param {Extent} extent2 Extent 2.\n * @return {boolean} The second extent is contained by or on the edge of the\n * first.\n * @api\n */\n\nfunction containsExtent(extent1, extent2) {\n return extent1[0] <= extent2[0] && extent2[2] <= extent1[2] && extent1[1] <= extent2[1] && extent2[3] <= extent1[3];\n}\n/**\n * Check if the passed coordinate is contained or on the edge of the extent.\n *\n * @param {Extent} extent Extent.\n * @param {number} x X coordinate.\n * @param {number} y Y coordinate.\n * @return {boolean} The x, y values are contained in the extent.\n * @api\n */\n\nfunction containsXY(extent, x, y) {\n return extent[0] <= x && x <= extent[2] && extent[1] <= y && y <= extent[3];\n}\n/**\n * Get the relationship between a coordinate and extent.\n * @param {Extent} extent The extent.\n * @param {import("./coordinate.js").Coordinate} coordinate The coordinate.\n * @return {import("./extent/Relationship.js").default} The relationship (bitwise compare with\n * import("./extent/Relationship.js").Relationship).\n */\n\nfunction coordinateRelationship(extent, coordinate) {\n var minX = extent[0];\n var minY = extent[1];\n var maxX = extent[2];\n var maxY = extent[3];\n var x = coordinate[0];\n var y = coordinate[1];\n var relationship = Relationship.UNKNOWN;\n\n if (x < minX) {\n relationship = relationship | Relationship.LEFT;\n } else if (x > maxX) {\n relationship = relationship | Relationship.RIGHT;\n }\n\n if (y < minY) {\n relationship = relationship | Relationship.BELOW;\n } else if (y > maxY) {\n relationship = relationship | Relationship.ABOVE;\n }\n\n if (relationship === Relationship.UNKNOWN) {\n relationship = Relationship.INTERSECTING;\n }\n\n return relationship;\n}\n/**\n * Create an empty extent.\n * @return {Extent} Empty extent.\n * @api\n */\n\nfunction createEmpty() {\n return [Infinity, Infinity, -Infinity, -Infinity];\n}\n/**\n * Create a new extent or update the provided extent.\n * @param {number} minX Minimum X.\n * @param {number} minY Minimum Y.\n * @param {number} maxX Maximum X.\n * @param {number} maxY Maximum Y.\n * @param {Extent=} opt_extent Destination extent.\n * @return {Extent} Extent.\n */\n\nfunction createOrUpdate(minX, minY, maxX, maxY, opt_extent) {\n if (opt_extent) {\n opt_extent[0] = minX;\n opt_extent[1] = minY;\n opt_extent[2] = maxX;\n opt_extent[3] = maxY;\n return opt_extent;\n } else {\n return [minX, minY, maxX, maxY];\n }\n}\n/**\n * Create a new empty extent or make the provided one empty.\n * @param {Extent=} opt_extent Extent.\n * @return {Extent} Extent.\n */\n\nfunction createOrUpdateEmpty(opt_extent) {\n return createOrUpdate(Infinity, Infinity, -Infinity, -Infinity, opt_extent);\n}\n/**\n * @param {import("./coordinate.js").Coordinate} coordinate Coordinate.\n * @param {Extent=} opt_extent Extent.\n * @return {Extent} Extent.\n */\n\nfunction createOrUpdateFromCoordinate(coordinate, opt_extent) {\n var x = coordinate[0];\n var y = coordinate[1];\n return createOrUpdate(x, y, x, y, opt_extent);\n}\n/**\n * @param {Array<import("./coordinate.js").Coordinate>} coordinates Coordinates.\n * @param {Extent=} opt_extent Extent.\n * @return {Extent} Extent.\n */\n\nfunction createOrUpdateFromCoordinates(coordinates, opt_extent) {\n var extent = createOrUpdateEmpty(opt_extent);\n return extendCoordinates(extent, coordinates);\n}\n/**\n * @param {Array<number>} flatCoordinates Flat coordinates.\n * @param {number} offset Offset.\n * @param {number} end End.\n * @param {number} stride Stride.\n * @param {Extent=} opt_extent Extent.\n * @return {Extent} Extent.\n */\n\nfunction createOrUpdateFromFlatCoordinates(flatCoordinates, offset, end, stride, opt_extent) {\n var extent = createOrUpdateEmpty(opt_extent);\n return extendFlatCoordinates(extent, flatCoordinates, offset, end, stride);\n}\n/**\n * @param {Array<Array<import("./coordinate.js").Coordinate>>} rings Rings.\n * @param {Extent=} opt_extent Extent.\n * @return {Extent} Extent.\n */\n\nfunction createOrUpdateFromRings(rings, opt_extent) {\n var extent = createOrUpdateEmpty(opt_extent);\n return extendRings(extent, rings);\n}\n/**\n * Determine if two extents are equivalent.\n * @param {Extent} extent1 Extent 1.\n * @param {Extent} extent2 Extent 2.\n * @return {boolean} The two extents are equivalent.\n * @api\n */\n\nfunction extent_equals(extent1, extent2) {\n return extent1[0] == extent2[0] && extent1[2] == extent2[2] && extent1[1] == extent2[1] && extent1[3] == extent2[3];\n}\n/**\n * Determine if two extents are approximately equivalent.\n * @param {Extent} extent1 Extent 1.\n * @param {Extent} extent2 Extent 2.\n * @param {number} tolerance Tolerance in extent coordinate units.\n * @return {boolean} The two extents differ by less than the tolerance.\n */\n\nfunction approximatelyEquals(extent1, extent2, tolerance) {\n return Math.abs(extent1[0] - extent2[0]) < tolerance && Math.abs(extent1[2] - extent2[2]) < tolerance && Math.abs(extent1[1] - extent2[1]) < tolerance && Math.abs(extent1[3] - extent2[3]) < tolerance;\n}\n/**\n * Modify an extent to include another extent.\n * @param {Extent} extent1 The extent to be modified.\n * @param {Extent} extent2 The extent that will be included in the first.\n * @return {Extent} A reference to the first (extended) extent.\n * @api\n */\n\nfunction extent_extend(extent1, extent2) {\n if (extent2[0] < extent1[0]) {\n extent1[0] = extent2[0];\n }\n\n if (extent2[2] > extent1[2]) {\n extent1[2] = extent2[2];\n }\n\n if (extent2[1] < extent1[1]) {\n extent1[1] = extent2[1];\n }\n\n if (extent2[3] > extent1[3]) {\n extent1[3] = extent2[3];\n }\n\n return extent1;\n}\n/**\n * @param {Extent} extent Extent.\n * @param {import("./coordinate.js").Coordinate} coordinate Coordinate.\n */\n\nfunction extendCoordinate(extent, coordinate) {\n if (coordinate[0] < extent[0]) {\n extent[0] = coordinate[0];\n }\n\n if (coordinate[0] > extent[2]) {\n extent[2] = coordinate[0];\n }\n\n if (coordinate[1] < extent[1]) {\n extent[1] = coordinate[1];\n }\n\n if (coordinate[1] > extent[3]) {\n extent[3] = coordinate[1];\n }\n}\n/**\n * @param {Extent} extent Extent.\n * @param {Array<import("./coordinate.js").Coordinate>} coordinates Coordinates.\n * @return {Extent} Extent.\n */\n\nfunction extendCoordinates(extent, coordinates) {\n for (var i = 0, ii = coordinates.length; i < ii; ++i) {\n extendCoordinate(extent, coordinates[i]);\n }\n\n return extent;\n}\n/**\n * @param {Extent} extent Extent.\n * @param {Array<number>} flatCoordinates Flat coordinates.\n * @param {number} offset Offset.\n * @param {number} end End.\n * @param {number} stride Stride.\n * @return {Extent} Extent.\n */\n\nfunction extendFlatCoordinates(extent, flatCoordinates, offset, end, stride) {\n for (; offset < end; offset += stride) {\n extendXY(extent, flatCoordinates[offset], flatCoordinates[offset + 1]);\n }\n\n return extent;\n}\n/**\n * @param {Extent} extent Extent.\n * @param {Array<Array<import("./coordinate.js").Coordinate>>} rings Rings.\n * @return {Extent} Extent.\n */\n\nfunction extendRings(extent, rings) {\n for (var i = 0, ii = rings.length; i < ii; ++i) {\n extendCoordinates(extent, rings[i]);\n }\n\n return extent;\n}\n/**\n * @param {Extent} extent Extent.\n * @param {number} x X.\n * @param {number} y Y.\n */\n\nfunction extendXY(extent, x, y) {\n extent[0] = Math.min(extent[0], x);\n extent[1] = Math.min(extent[1], y);\n extent[2] = Math.max(extent[2], x);\n extent[3] = Math.max(extent[3], y);\n}\n/**\n * This function calls `callback` for each corner of the extent. If the\n * callback returns a truthy value the function returns that value\n * immediately. Otherwise the function returns `false`.\n * @param {Extent} extent Extent.\n * @param {function(import("./coordinate.js").Coordinate): S} callback Callback.\n * @return {S|boolean} Value.\n * @template S\n */\n\nfunction forEachCorner(extent, callback) {\n var val;\n val = callback(getBottomLeft(extent));\n\n if (val) {\n return val;\n }\n\n val = callback(getBottomRight(extent));\n\n if (val) {\n return val;\n }\n\n val = callback(getTopRight(extent));\n\n if (val) {\n return val;\n }\n\n val = callback(getTopLeft(extent));\n\n if (val) {\n return val;\n }\n\n return false;\n}\n/**\n * Get the size of an extent.\n * @param {Extent} extent Extent.\n * @return {number} Area.\n * @api\n */\n\nfunction getArea(extent) {\n var area = 0;\n\n if (!extent_isEmpty(extent)) {\n area = extent_getWidth(extent) * getHeight(extent);\n }\n\n return area;\n}\n/**\n * Get the bottom left coordinate of an extent.\n * @param {Extent} extent Extent.\n * @return {import("./coordinate.js").Coordinate} Bottom left coordinate.\n * @api\n */\n\nfunction getBottomLeft(extent) {\n return [extent[0], extent[1]];\n}\n/**\n * Get the bottom right coordinate of an extent.\n * @param {Extent} extent Extent.\n * @return {import("./coordinate.js").Coordinate} Bottom right coordinate.\n * @api\n */\n\nfunction getBottomRight(extent) {\n return [extent[2], extent[1]];\n}\n/**\n * Get the center coordinate of an extent.\n * @param {Extent} extent Extent.\n * @return {import("./coordinate.js").Coordinate} Center.\n * @api\n */\n\nfunction getCenter(extent) {\n return [(extent[0] + extent[2]) / 2, (extent[1] + extent[3]) / 2];\n}\n/**\n * Get a corner coordinate of an extent.\n * @param {Extent} extent Extent.\n * @param {import("./extent/Corner.js").default} corner Corner.\n * @return {import("./coordinate.js").Coordinate} Corner coordinate.\n */\n\nfunction getCorner(extent, corner) {\n var coordinate;\n\n if (corner === Corner.BOTTOM_LEFT) {\n coordinate = getBottomLeft(extent);\n } else if (corner === Corner.BOTTOM_RIGHT) {\n coordinate = getBottomRight(extent);\n } else if (corner === Corner.TOP_LEFT) {\n coordinate = getTopLeft(extent);\n } else if (corner === Corner.TOP_RIGHT) {\n coordinate = getTopRight(extent);\n } else {\n asserts_assert(false, 13); // Invalid corner\n }\n\n return coordinate;\n}\n/**\n * @param {Extent} extent1 Extent 1.\n * @param {Extent} extent2 Extent 2.\n * @return {number} Enlarged area.\n */\n\nfunction getEnlargedArea(extent1, extent2) {\n var minX = Math.min(extent1[0], extent2[0]);\n var minY = Math.min(extent1[1], extent2[1]);\n var maxX = Math.max(extent1[2], extent2[2]);\n var maxY = Math.max(extent1[3], extent2[3]);\n return (maxX - minX) * (maxY - minY);\n}\n/**\n * @param {import("./coordinate.js").Coordinate} center Center.\n * @param {number} resolution Resolution.\n * @param {number} rotation Rotation.\n * @param {import("./size.js").Size} size Size.\n * @param {Extent=} opt_extent Destination extent.\n * @return {Extent} Extent.\n */\n\nfunction getForViewAndSize(center, resolution, rotation, size, opt_extent) {\n var dx = resolution * size[0] / 2;\n var dy = resolution * size[1] / 2;\n var cosRotation = Math.cos(rotation);\n var sinRotation = Math.sin(rotation);\n var xCos = dx * cosRotation;\n var xSin = dx * sinRotation;\n var yCos = dy * cosRotation;\n var ySin = dy * sinRotation;\n var x = center[0];\n var y = center[1];\n var x0 = x - xCos + ySin;\n var x1 = x - xCos - ySin;\n var x2 = x + xCos - ySin;\n var x3 = x + xCos + ySin;\n var y0 = y - xSin - yCos;\n var y1 = y - xSin + yCos;\n var y2 = y + xSin + yCos;\n var y3 = y + xSin - yCos;\n return createOrUpdate(Math.min(x0, x1, x2, x3), Math.min(y0, y1, y2, y3), Math.max(x0, x1, x2, x3), Math.max(y0, y1, y2, y3), opt_extent);\n}\n/**\n * Get the height of an extent.\n * @param {Extent} extent Extent.\n * @return {number} Height.\n * @api\n */\n\nfunction getHeight(extent) {\n return extent[3] - extent[1];\n}\n/**\n * @param {Extent} extent1 Extent 1.\n * @param {Extent} extent2 Extent 2.\n * @return {number} Intersection area.\n */\n\nfunction getIntersectionArea(extent1, extent2) {\n var intersection = getIntersection(extent1, extent2);\n return getArea(intersection);\n}\n/**\n * Get the intersection of two extents.\n * @param {Extent} extent1 Extent 1.\n * @param {Extent} extent2 Extent 2.\n * @param {Extent=} opt_extent Optional extent to populate with intersection.\n * @return {Extent} Intersecting extent.\n * @api\n */\n\nfunction getIntersection(extent1, extent2, opt_extent) {\n var intersection = opt_extent ? opt_extent : createEmpty();\n\n if (intersects(extent1, extent2)) {\n if (extent1[0] > extent2[0]) {\n intersection[0] = extent1[0];\n } else {\n intersection[0] = extent2[0];\n }\n\n if (extent1[1] > extent2[1]) {\n intersection[1] = extent1[1];\n } else {\n intersection[1] = extent2[1];\n }\n\n if (extent1[2] < extent2[2]) {\n intersection[2] = extent1[2];\n } else {\n intersection[2] = extent2[2];\n }\n\n if (extent1[3] < extent2[3]) {\n intersection[3] = extent1[3];\n } else {\n intersection[3] = extent2[3];\n }\n } else {\n createOrUpdateEmpty(intersection);\n }\n\n return intersection;\n}\n/**\n * @param {Extent} extent Extent.\n * @return {number} Margin.\n */\n\nfunction getMargin(extent) {\n return extent_getWidth(extent) + getHeight(extent);\n}\n/**\n * Get the size (width, height) of an extent.\n * @param {Extent} extent The extent.\n * @return {import("./size.js").Size} The extent size.\n * @api\n */\n\nfunction getSize(extent) {\n return [extent[2] - extent[0], extent[3] - extent[1]];\n}\n/**\n * Get the top left coordinate of an extent.\n * @param {Extent} extent Extent.\n * @return {import("./coordinate.js").Coordinate} Top left coordinate.\n * @api\n */\n\nfunction getTopLeft(extent) {\n return [extent[0], extent[3]];\n}\n/**\n * Get the top right coordinate of an extent.\n * @param {Extent} extent Extent.\n * @return {import("./coordinate.js").Coordinate} Top right coordinate.\n * @api\n */\n\nfunction getTopRight(extent) {\n return [extent[2], extent[3]];\n}\n/**\n * Get the width of an extent.\n * @param {Extent} extent Extent.\n * @return {number} Width.\n * @api\n */\n\nfunction extent_getWidth(extent) {\n return extent[2] - extent[0];\n}\n/**\n * Determine if one extent intersects another.\n * @param {Extent} extent1 Extent 1.\n * @param {Extent} extent2 Extent.\n * @return {boolean} The two extents intersect.\n * @api\n */\n\nfunction intersects(extent1, extent2) {\n return extent1[0] <= extent2[2] && extent1[2] >= extent2[0] && extent1[1] <= extent2[3] && extent1[3] >= extent2[1];\n}\n/**\n * Determine if an extent is empty.\n * @param {Extent} extent Extent.\n * @return {boolean} Is empty.\n * @api\n */\n\nfunction extent_isEmpty(extent) {\n return extent[2] < extent[0] || extent[3] < extent[1];\n}\n/**\n * @param {Extent} extent Extent.\n * @param {Extent=} opt_extent Extent.\n * @return {Extent} Extent.\n */\n\nfunction returnOrUpdate(extent, opt_extent) {\n if (opt_extent) {\n opt_extent[0] = extent[0];\n opt_extent[1] = extent[1];\n opt_extent[2] = extent[2];\n opt_extent[3] = extent[3];\n return opt_extent;\n } else {\n return extent;\n }\n}\n/**\n * @param {Extent} extent Extent.\n * @param {number} value Value.\n */\n\nfunction scaleFromCenter(extent, value) {\n var deltaX = (extent[2] - extent[0]) / 2 * (value - 1);\n var deltaY = (extent[3] - extent[1]) / 2 * (value - 1);\n extent[0] -= deltaX;\n extent[2] += deltaX;\n extent[1] -= deltaY;\n extent[3] += deltaY;\n}\n/**\n * Determine if the segment between two coordinates intersects (crosses,\n * touches, or is contained by) the provided extent.\n * @param {Extent} extent The extent.\n * @param {import("./coordinate.js").Coordinate} start Segment start coordinate.\n * @param {import("./coordinate.js").Coordinate} end Segment end coordinate.\n * @return {boolean} The segment intersects the extent.\n */\n\nfunction intersectsSegment(extent, start, end) {\n var intersects = false;\n var startRel = coordinateRelationship(extent, start);\n var endRel = coordinateRelationship(extent, end);\n\n if (startRel === Relationship.INTERSECTING || endRel === Relationship.INTERSECTING) {\n intersects = true;\n } else {\n var minX = extent[0];\n var minY = extent[1];\n var maxX = extent[2];\n var maxY = extent[3];\n var startX = start[0];\n var startY = start[1];\n var endX = end[0];\n var endY = end[1];\n var slope = (endY - startY) / (endX - startX);\n var x = void 0,\n y = void 0;\n\n if (!!(endRel & Relationship.ABOVE) && !(startRel & Relationship.ABOVE)) {\n // potentially intersects top\n x = endX - (endY - maxY) / slope;\n intersects = x >= minX && x <= maxX;\n }\n\n if (!intersects && !!(endRel & Relationship.RIGHT) && !(startRel & Relationship.RIGHT)) {\n // potentially intersects right\n y = endY - (endX - maxX) * slope;\n intersects = y >= minY && y <= maxY;\n }\n\n if (!intersects && !!(endRel & Relationship.BELOW) && !(startRel & Relationship.BELOW)) {\n // potentially intersects bottom\n x = endX - (endY - minY) / slope;\n intersects = x >= minX && x <= maxX;\n }\n\n if (!intersects && !!(endRel & Relationship.LEFT) && !(startRel & Relationship.LEFT)) {\n // potentially intersects left\n y = endY - (endX - minX) * slope;\n intersects = y >= minY && y <= maxY;\n }\n }\n\n return intersects;\n}\n/**\n * Apply a transform function to the extent.\n * @param {Extent} extent Extent.\n * @param {import("./proj.js").TransformFunction} transformFn Transform function.\n * Called with `[minX, minY, maxX, maxY]` extent coordinates.\n * @param {Extent=} opt_extent Destination extent.\n * @param {number=} opt_stops Number of stops per side used for the transform.\n * By default only the corners are used.\n * @return {Extent} Extent.\n * @api\n */\n\nfunction applyTransform(extent, transformFn, opt_extent, opt_stops) {\n var coordinates = [];\n\n if (opt_stops > 1) {\n var width = extent[2] - extent[0];\n var height = extent[3] - extent[1];\n\n for (var i = 0; i < opt_stops; ++i) {\n coordinates.push(extent[0] + width * i / opt_stops, extent[1], extent[2], extent[1] + height * i / opt_stops, extent[2] - width * i / opt_stops, extent[3], extent[0], extent[3] - height * i / opt_stops);\n }\n } else {\n coordinates = [extent[0], extent[1], extent[2], extent[1], extent[2], extent[3], extent[0], extent[3]];\n }\n\n transformFn(coordinates, coordinates, 2);\n var xs = [];\n var ys = [];\n\n for (var i = 0, l = coordinates.length; i < l; i += 2) {\n xs.push(coordinates[i]);\n ys.push(coordinates[i + 1]);\n }\n\n return _boundingExtentXYs(xs, ys, opt_extent);\n}\n/**\n * Modifies the provided extent in-place to be within the real world\n * extent.\n *\n * @param {Extent} extent Extent.\n * @param {import("./proj/Projection.js").default} projection Projection\n * @return {Extent} The extent within the real world extent.\n */\n\nfunction wrapX(extent, projection) {\n var projectionExtent = projection.getExtent();\n var center = getCenter(extent);\n\n if (projection.canWrapX() && (center[0] < projectionExtent[0] || center[0] >= projectionExtent[2])) {\n var worldWidth = extent_getWidth(projectionExtent);\n var worldsAway = Math.floor((center[0] - projectionExtent[0]) / worldWidth);\n var offset = worldsAway * worldWidth;\n extent[0] -= offset;\n extent[2] -= offset;\n }\n\n return extent;\n}\n;// CONCATENATED MODULE: ./node_modules/ol/math.js\n/**\n * @module ol/math\n */\n\n/**\n * Takes a number and clamps it to within the provided bounds.\n * @param {number} value The input number.\n * @param {number} min The minimum value to return.\n * @param {number} max The maximum value to return.\n * @return {number} The input number if it is within bounds, or the nearest\n * number within the bounds.\n */\nfunction math_clamp(value, min, max) {\n return Math.min(Math.max(value, min), max);\n}\n/**\n * Return the hyperbolic cosine of a given number. The method will use the\n * native `Math.cosh` function if it is available, otherwise the hyperbolic\n * cosine will be calculated via the reference implementation of the Mozilla\n * developer network.\n *\n * @param {number} x X.\n * @return {number} Hyperbolic cosine of x.\n */\n\nvar cosh = function () {\n // Wrapped in a iife, to save the overhead of checking for the native\n // implementation on every invocation.\n var cosh;\n\n if (\'cosh\' in Math) {\n // The environment supports the native Math.cosh function, use it…\n cosh = Math.cosh;\n } else {\n // … else, use the reference implementation of MDN:\n cosh = function cosh(x) {\n var y =\n /** @type {Math} */\n Math.exp(x);\n return (y + 1 / y) / 2;\n };\n }\n\n return cosh;\n}();\n/**\n * Return the base 2 logarithm of a given number. The method will use the\n * native `Math.log2` function if it is available, otherwise the base 2\n * logarithm will be calculated via the reference implementation of the\n * Mozilla developer network.\n *\n * @param {number} x X.\n * @return {number} Base 2 logarithm of x.\n */\n\nvar log2 = function () {\n // Wrapped in a iife, to save the overhead of checking for the native\n // implementation on every invocation.\n var log2;\n\n if (\'log2\' in Math) {\n // The environment supports the native Math.log2 function, use it…\n log2 = Math.log2;\n } else {\n // … else, use the reference implementation of MDN:\n log2 = function log2(x) {\n return Math.log(x) * Math.LOG2E;\n };\n }\n\n return log2;\n}();\n/**\n * Returns the square of the closest distance between the point (x, y) and the\n * line segment (x1, y1) to (x2, y2).\n * @param {number} x X.\n * @param {number} y Y.\n * @param {number} x1 X1.\n * @param {number} y1 Y1.\n * @param {number} x2 X2.\n * @param {number} y2 Y2.\n * @return {number} Squared distance.\n */\n\nfunction squaredSegmentDistance(x, y, x1, y1, x2, y2) {\n var dx = x2 - x1;\n var dy = y2 - y1;\n\n if (dx !== 0 || dy !== 0) {\n var t = ((x - x1) * dx + (y - y1) * dy) / (dx * dx + dy * dy);\n\n if (t > 1) {\n x1 = x2;\n y1 = y2;\n } else if (t > 0) {\n x1 += dx * t;\n y1 += dy * t;\n }\n }\n\n return math_squaredDistance(x, y, x1, y1);\n}\n/**\n * Returns the square of the distance between the points (x1, y1) and (x2, y2).\n * @param {number} x1 X1.\n * @param {number} y1 Y1.\n * @param {number} x2 X2.\n * @param {number} y2 Y2.\n * @return {number} Squared distance.\n */\n\nfunction math_squaredDistance(x1, y1, x2, y2) {\n var dx = x2 - x1;\n var dy = y2 - y1;\n return dx * dx + dy * dy;\n}\n/**\n * Solves system of linear equations using Gaussian elimination method.\n *\n * @param {Array<Array<number>>} mat Augmented matrix (n x n + 1 column)\n * in row-major order.\n * @return {Array<number>} The resulting vector.\n */\n\nfunction solveLinearSystem(mat) {\n var n = mat.length;\n\n for (var i = 0; i < n; i++) {\n // Find max in the i-th column (ignoring i - 1 first rows)\n var maxRow = i;\n var maxEl = Math.abs(mat[i][i]);\n\n for (var r = i + 1; r < n; r++) {\n var absValue = Math.abs(mat[r][i]);\n\n if (absValue > maxEl) {\n maxEl = absValue;\n maxRow = r;\n }\n }\n\n if (maxEl === 0) {\n return null; // matrix is singular\n } // Swap max row with i-th (current) row\n\n\n var tmp = mat[maxRow];\n mat[maxRow] = mat[i];\n mat[i] = tmp; // Subtract the i-th row to make all the remaining rows 0 in the i-th column\n\n for (var j = i + 1; j < n; j++) {\n var coef = -mat[j][i] / mat[i][i];\n\n for (var k = i; k < n + 1; k++) {\n if (i == k) {\n mat[j][k] = 0;\n } else {\n mat[j][k] += coef * mat[i][k];\n }\n }\n }\n } // Solve Ax=b for upper triangular matrix A (mat)\n\n\n var x = new Array(n);\n\n for (var l = n - 1; l >= 0; l--) {\n x[l] = mat[l][n] / mat[l][l];\n\n for (var m = l - 1; m >= 0; m--) {\n mat[m][n] -= mat[m][l] * x[l];\n }\n }\n\n return x;\n}\n/**\n * Converts radians to to degrees.\n *\n * @param {number} angleInRadians Angle in radians.\n * @return {number} Angle in degrees.\n */\n\nfunction math_toDegrees(angleInRadians) {\n return angleInRadians * 180 / Math.PI;\n}\n/**\n * Converts degrees to radians.\n *\n * @param {number} angleInDegrees Angle in degrees.\n * @return {number} Angle in radians.\n */\n\nfunction math_toRadians(angleInDegrees) {\n return angleInDegrees * Math.PI / 180;\n}\n/**\n * Returns the modulo of a / b, depending on the sign of b.\n *\n * @param {number} a Dividend.\n * @param {number} b Divisor.\n * @return {number} Modulo.\n */\n\nfunction math_modulo(a, b) {\n var r = a % b;\n return r * b < 0 ? r + b : r;\n}\n/**\n * Calculates the linearly interpolated value of x between a and b.\n *\n * @param {number} a Number\n * @param {number} b Number\n * @param {number} x Value to be interpolated.\n * @return {number} Interpolated value.\n */\n\nfunction lerp(a, b, x) {\n return a + x * (b - a);\n}\n;// CONCATENATED MODULE: ./node_modules/ol/color.js\n/**\n * @module ol/color\n */\n\n\n/**\n * A color represented as a short array [red, green, blue, alpha].\n * red, green, and blue should be integers in the range 0..255 inclusive.\n * alpha should be a float in the range 0..1 inclusive. If no alpha value is\n * given then `1` will be used.\n * @typedef {Array<number>} Color\n * @api\n */\n\n/**\n * This RegExp matches # followed by 3, 4, 6, or 8 hex digits.\n * @const\n * @type {RegExp}\n * @private\n */\n\nvar HEX_COLOR_RE_ = /^#([a-f0-9]{3}|[a-f0-9]{4}(?:[a-f0-9]{2}){0,2})$/i;\n/**\n * Regular expression for matching potential named color style strings.\n * @const\n * @type {RegExp}\n * @private\n */\n\nvar NAMED_COLOR_RE_ = /^([a-z]*)$|^hsla?\\(.*\\)$/i;\n/**\n * Return the color as an rgba string.\n * @param {Color|string} color Color.\n * @return {string} Rgba string.\n * @api\n */\n\nfunction asString(color) {\n if (typeof color === \'string\') {\n return color;\n } else {\n return color_toString(color);\n }\n}\n/**\n * Return named color as an rgba string.\n * @param {string} color Named color.\n * @return {string} Rgb string.\n */\n\nfunction fromNamed(color) {\n var el = document.createElement(\'div\');\n el.style.color = color;\n\n if (el.style.color !== \'\') {\n document.body.appendChild(el);\n var rgb = getComputedStyle(el).color;\n document.body.removeChild(el);\n return rgb;\n } else {\n return \'\';\n }\n}\n/**\n * @param {string} s String.\n * @return {Color} Color.\n */\n\n\nvar fromString = function () {\n // We maintain a small cache of parsed strings. To provide cheap LRU-like\n // semantics, whenever the cache grows too large we simply delete an\n // arbitrary 25% of the entries.\n\n /**\n * @const\n * @type {number}\n */\n var MAX_CACHE_SIZE = 1024;\n /**\n * @type {Object<string, Color>}\n */\n\n var cache = {};\n /**\n * @type {number}\n */\n\n var cacheSize = 0;\n return (\n /**\n * @param {string} s String.\n * @return {Color} Color.\n */\n function (s) {\n var color;\n\n if (cache.hasOwnProperty(s)) {\n color = cache[s];\n } else {\n if (cacheSize >= MAX_CACHE_SIZE) {\n var i = 0;\n\n for (var key in cache) {\n if ((i++ & 3) === 0) {\n delete cache[key];\n --cacheSize;\n }\n }\n }\n\n color = fromStringInternal_(s);\n cache[s] = color;\n ++cacheSize;\n }\n\n return color;\n }\n );\n}();\n/**\n * Return the color as an array. This function maintains a cache of calculated\n * arrays which means the result should not be modified.\n * @param {Color|string} color Color.\n * @return {Color} Color.\n * @api\n */\n\nfunction asArray(color) {\n if (Array.isArray(color)) {\n return color;\n } else {\n return fromString(color);\n }\n}\n/**\n * @param {string} s String.\n * @private\n * @return {Color} Color.\n */\n\nfunction fromStringInternal_(s) {\n var r, g, b, a, color;\n\n if (NAMED_COLOR_RE_.exec(s)) {\n s = fromNamed(s);\n }\n\n if (HEX_COLOR_RE_.exec(s)) {\n // hex\n var n = s.length - 1; // number of hex digits\n\n var d = // number of digits per channel\n void 0; // number of digits per channel\n\n if (n <= 4) {\n d = 1;\n } else {\n d = 2;\n }\n\n var hasAlpha = n === 4 || n === 8;\n r = parseInt(s.substr(1 + 0 * d, d), 16);\n g = parseInt(s.substr(1 + 1 * d, d), 16);\n b = parseInt(s.substr(1 + 2 * d, d), 16);\n\n if (hasAlpha) {\n a = parseInt(s.substr(1 + 3 * d, d), 16);\n } else {\n a = 255;\n }\n\n if (d == 1) {\n r = (r << 4) + r;\n g = (g << 4) + g;\n b = (b << 4) + b;\n\n if (hasAlpha) {\n a = (a << 4) + a;\n }\n }\n\n color = [r, g, b, a / 255];\n } else if (s.indexOf(\'rgba(\') == 0) {\n // rgba()\n color = s.slice(5, -1).split(\',\').map(Number);\n normalize(color);\n } else if (s.indexOf(\'rgb(\') == 0) {\n // rgb()\n color = s.slice(4, -1).split(\',\').map(Number);\n color.push(1);\n normalize(color);\n } else {\n asserts_assert(false, 14); // Invalid color\n }\n\n return color;\n}\n/**\n * TODO this function is only used in the test, we probably shouldn\'t export it\n * @param {Color} color Color.\n * @return {Color} Clamped color.\n */\n\n\nfunction normalize(color) {\n color[0] = math_clamp(color[0] + 0.5 | 0, 0, 255);\n color[1] = math_clamp(color[1] + 0.5 | 0, 0, 255);\n color[2] = math_clamp(color[2] + 0.5 | 0, 0, 255);\n color[3] = math_clamp(color[3], 0, 1);\n return color;\n}\n/**\n * @param {Color} color Color.\n * @return {string} String.\n */\n\nfunction color_toString(color) {\n var r = color[0];\n\n if (r != (r | 0)) {\n r = r + 0.5 | 0;\n }\n\n var g = color[1];\n\n if (g != (g | 0)) {\n g = g + 0.5 | 0;\n }\n\n var b = color[2];\n\n if (b != (b | 0)) {\n b = b + 0.5 | 0;\n }\n\n var a = color[3] === undefined ? 1 : color[3];\n return \'rgba(\' + r + \',\' + g + \',\' + b + \',\' + a + \')\';\n}\n/**\n * @param {string} s String.\n * @return {boolean} Whether the string is actually a valid color\n */\n\nfunction isStringColor(s) {\n if (NAMED_COLOR_RE_.test(s)) {\n s = fromNamed(s);\n }\n\n return HEX_COLOR_RE_.test(s) || s.indexOf(\'rgba(\') === 0 || s.indexOf(\'rgb(\') === 0;\n}\n;// CONCATENATED MODULE: ./node_modules/ol/style/IconImageCache.js\n/**\n * @module ol/style/IconImageCache\n */\n\n/**\n * @classdesc\n * Singleton class. Available through {@link module:ol/style/IconImageCache~shared}.\n */\n\nvar IconImageCache =\n/** @class */\nfunction () {\n function IconImageCache() {\n /**\n * @type {!Object<string, import("./IconImage.js").default>}\n * @private\n */\n this.cache_ = {};\n /**\n * @type {number}\n * @private\n */\n\n this.cacheSize_ = 0;\n /**\n * @type {number}\n * @private\n */\n\n this.maxCacheSize_ = 32;\n }\n /**\n * FIXME empty description for jsdoc\n */\n\n\n IconImageCache.prototype.clear = function () {\n this.cache_ = {};\n this.cacheSize_ = 0;\n };\n /**\n * @return {boolean} Can expire cache.\n */\n\n\n IconImageCache.prototype.canExpireCache = function () {\n return this.cacheSize_ > this.maxCacheSize_;\n };\n /**\n * FIXME empty description for jsdoc\n */\n\n\n IconImageCache.prototype.expire = function () {\n if (this.canExpireCache()) {\n var i = 0;\n\n for (var key in this.cache_) {\n var iconImage = this.cache_[key];\n\n if ((i++ & 3) === 0 && !iconImage.hasListener()) {\n delete this.cache_[key];\n --this.cacheSize_;\n }\n }\n }\n };\n /**\n * @param {string} src Src.\n * @param {?string} crossOrigin Cross origin.\n * @param {import("../color.js").Color} color Color.\n * @return {import("./IconImage.js").default} Icon image.\n */\n\n\n IconImageCache.prototype.get = function (src, crossOrigin, color) {\n var key = getKey(src, crossOrigin, color);\n return key in this.cache_ ? this.cache_[key] : null;\n };\n /**\n * @param {string} src Src.\n * @param {?string} crossOrigin Cross origin.\n * @param {import("../color.js").Color} color Color.\n * @param {import("./IconImage.js").default} iconImage Icon image.\n */\n\n\n IconImageCache.prototype.set = function (src, crossOrigin, color, iconImage) {\n var key = getKey(src, crossOrigin, color);\n this.cache_[key] = iconImage;\n ++this.cacheSize_;\n };\n /**\n * Set the cache size of the icon cache. Default is `32`. Change this value when\n * your map uses more than 32 different icon images and you are not caching icon\n * styles on the application level.\n * @param {number} maxCacheSize Cache max size.\n * @api\n */\n\n\n IconImageCache.prototype.setSize = function (maxCacheSize) {\n this.maxCacheSize_ = maxCacheSize;\n this.expire();\n };\n\n return IconImageCache;\n}();\n/**\n * @param {string} src Src.\n * @param {?string} crossOrigin Cross origin.\n * @param {import("../color.js").Color} color Color.\n * @return {string} Cache key.\n */\n\n\nfunction getKey(src, crossOrigin, color) {\n var colorString = color ? asString(color) : \'null\';\n return crossOrigin + \':\' + src + \':\' + colorString;\n}\n\n/* harmony default export */ var style_IconImageCache = ((/* unused pure expression or super */ null && (IconImageCache)));\n/**\n * The {@link module:ol/style/IconImageCache~IconImageCache} for\n * {@link module:ol/style/Icon~Icon} images.\n * @api\n */\n\nvar shared = new IconImageCache();\n;// CONCATENATED MODULE: ./node_modules/ol/events/Event.js\n/**\n * @module ol/events/Event\n */\n\n/**\n * @classdesc\n * Stripped down implementation of the W3C DOM Level 2 Event interface.\n * See https://www.w3.org/TR/DOM-Level-2-Events/events.html#Events-interface.\n *\n * This implementation only provides `type` and `target` properties, and\n * `stopPropagation` and `preventDefault` methods. It is meant as base class\n * for higher level events defined in the library, and works with\n * {@link module:ol/events/Target~Target}.\n */\nvar BaseEvent =\n/** @class */\nfunction () {\n /**\n * @param {string} type Type.\n */\n function BaseEvent(type) {\n /**\n * @type {boolean}\n */\n this.propagationStopped;\n /**\n * The event type.\n * @type {string}\n * @api\n */\n\n this.type = type;\n /**\n * The event target.\n * @type {Object}\n * @api\n */\n\n this.target = null;\n }\n /**\n * Stop event propagation.\n * @api\n */\n\n\n BaseEvent.prototype.preventDefault = function () {\n this.propagationStopped = true;\n };\n /**\n * Stop event propagation.\n * @api\n */\n\n\n BaseEvent.prototype.stopPropagation = function () {\n this.propagationStopped = true;\n };\n\n return BaseEvent;\n}();\n/**\n * @param {Event|import("./Event.js").default} evt Event\n */\n\n\nfunction stopPropagation(evt) {\n evt.stopPropagation();\n}\n/**\n * @param {Event|import("./Event.js").default} evt Event\n */\n\nfunction preventDefault(evt) {\n evt.preventDefault();\n}\n/* harmony default export */ var Event = (BaseEvent);\n;// CONCATENATED MODULE: ./node_modules/ol/ObjectEventType.js\n/**\n * @module ol/ObjectEventType\n */\n\n/**\n * @enum {string}\n */\n/* harmony default export */ var ObjectEventType = ({\n /**\n * Triggered when a property is changed.\n * @event module:ol/Object.ObjectEvent#propertychange\n * @api\n */\n PROPERTYCHANGE: \'propertychange\'\n});\n;// CONCATENATED MODULE: ./node_modules/ol/obj.js\n/**\n * @module ol/obj\n */\n\n/**\n * Polyfill for Object.assign(). Assigns enumerable and own properties from\n * one or more source objects to a target object.\n * See https://developer.mozilla.org/en/docs/Web/JavaScript/Reference/Global_Objects/Object/assign.\n *\n * @param {!Object} target The target object.\n * @param {...Object} var_sources The source object(s).\n * @return {!Object} The modified target object.\n */\nvar obj_assign = typeof Object.assign === \'function\' ? Object.assign : function (target, var_sources) {\n if (target === undefined || target === null) {\n throw new TypeError(\'Cannot convert undefined or null to object\');\n }\n\n var output = Object(target);\n\n for (var i = 1, ii = arguments.length; i < ii; ++i) {\n var source = arguments[i];\n\n if (source !== undefined && source !== null) {\n for (var key in source) {\n if (source.hasOwnProperty(key)) {\n output[key] = source[key];\n }\n }\n }\n }\n\n return output;\n};\n/**\n * Removes all properties from an object.\n * @param {Object} object The object to clear.\n */\n\nfunction clear(object) {\n for (var property in object) {\n delete object[property];\n }\n}\n/**\n * Polyfill for Object.values(). Get an array of property values from an object.\n * See https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Object/values\n *\n * @param {!Object<K,V>} object The object from which to get the values.\n * @return {!Array<V>} The property values.\n * @template K,V\n */\n\nvar getValues = typeof Object.values === \'function\' ? Object.values : function (object) {\n var values = [];\n\n for (var property in object) {\n values.push(object[property]);\n }\n\n return values;\n};\n/**\n * Determine if an object has any properties.\n * @param {Object} object The object to check.\n * @return {boolean} The object is empty.\n */\n\nfunction obj_isEmpty(object) {\n var property;\n\n for (property in object) {\n return false;\n }\n\n return !property;\n}\n;// CONCATENATED MODULE: ./node_modules/ol/events/Target.js\nvar Target_extends = undefined && undefined.__extends || function () {\n var _extendStatics = function extendStatics(d, b) {\n _extendStatics = Object.setPrototypeOf || {\n __proto__: []\n } instanceof Array && function (d, b) {\n d.__proto__ = b;\n } || function (d, b) {\n for (var p in b) {\n if (Object.prototype.hasOwnProperty.call(b, p)) d[p] = b[p];\n }\n };\n\n return _extendStatics(d, b);\n };\n\n return function (d, b) {\n _extendStatics(d, b);\n\n function __() {\n this.constructor = d;\n }\n\n d.prototype = b === null ? Object.create(b) : (__.prototype = b.prototype, new __());\n };\n}();\n/**\n * @module ol/events/Target\n */\n\n\n\n\n\n\n/**\n * @typedef {EventTarget|Target} EventTargetLike\n */\n\n/**\n * @classdesc\n * A simplified implementation of the W3C DOM Level 2 EventTarget interface.\n * See https://www.w3.org/TR/2000/REC-DOM-Level-2-Events-20001113/events.html#Events-EventTarget.\n *\n * There are two important simplifications compared to the specification:\n *\n * 1. The handling of `useCapture` in `addEventListener` and\n * `removeEventListener`. There is no real capture model.\n * 2. The handling of `stopPropagation` and `preventDefault` on `dispatchEvent`.\n * There is no event target hierarchy. When a listener calls\n * `stopPropagation` or `preventDefault` on an event object, it means that no\n * more listeners after this one will be called. Same as when the listener\n * returns false.\n */\n\nvar Target =\n/** @class */\nfunction (_super) {\n Target_extends(Target, _super);\n /**\n * @param {*=} opt_target Default event target for dispatched events.\n */\n\n\n function Target(opt_target) {\n var _this = _super.call(this) || this;\n /**\n * @private\n * @type {*}\n */\n\n\n _this.eventTarget_ = opt_target;\n /**\n * @private\n * @type {Object<string, number>}\n */\n\n _this.pendingRemovals_ = null;\n /**\n * @private\n * @type {Object<string, number>}\n */\n\n _this.dispatching_ = null;\n /**\n * @private\n * @type {Object<string, Array<import("../events.js").Listener>>}\n */\n\n _this.listeners_ = null;\n return _this;\n }\n /**\n * @param {string} type Type.\n * @param {import("../events.js").Listener} listener Listener.\n */\n\n\n Target.prototype.addEventListener = function (type, listener) {\n if (!type || !listener) {\n return;\n }\n\n var listeners = this.listeners_ || (this.listeners_ = {});\n var listenersForType = listeners[type] || (listeners[type] = []);\n\n if (listenersForType.indexOf(listener) === -1) {\n listenersForType.push(listener);\n }\n };\n /**\n * Dispatches an event and calls all listeners listening for events\n * of this type. The event parameter can either be a string or an\n * Object with a `type` property.\n *\n * @param {import("./Event.js").default|string} event Event object.\n * @return {boolean|undefined} `false` if anyone called preventDefault on the\n * event object or if any of the listeners returned false.\n * @api\n */\n\n\n Target.prototype.dispatchEvent = function (event) {\n /** @type {import("./Event.js").default|Event} */\n var evt = typeof event === \'string\' ? new Event(event) : event;\n var type = evt.type;\n\n if (!evt.target) {\n evt.target = this.eventTarget_ || this;\n }\n\n var listeners = this.listeners_ && this.listeners_[type];\n var propagate;\n\n if (listeners) {\n var dispatching = this.dispatching_ || (this.dispatching_ = {});\n var pendingRemovals = this.pendingRemovals_ || (this.pendingRemovals_ = {});\n\n if (!(type in dispatching)) {\n dispatching[type] = 0;\n pendingRemovals[type] = 0;\n }\n\n ++dispatching[type];\n\n for (var i = 0, ii = listeners.length; i < ii; ++i) {\n if (\'handleEvent\' in listeners[i]) {\n propagate =\n /** @type {import("../events.js").ListenerObject} */\n listeners[i].handleEvent(evt);\n } else {\n propagate =\n /** @type {import("../events.js").ListenerFunction} */\n listeners[i].call(this, evt);\n }\n\n if (propagate === false || evt.propagationStopped) {\n propagate = false;\n break;\n }\n }\n\n --dispatching[type];\n\n if (dispatching[type] === 0) {\n var pr = pendingRemovals[type];\n delete pendingRemovals[type];\n\n while (pr--) {\n this.removeEventListener(type, VOID);\n }\n\n delete dispatching[type];\n }\n\n return propagate;\n }\n };\n /**\n * Clean up.\n */\n\n\n Target.prototype.disposeInternal = function () {\n this.listeners_ && clear(this.listeners_);\n };\n /**\n * Get the listeners for a specified event type. Listeners are returned in the\n * order that they will be called in.\n *\n * @param {string} type Type.\n * @return {Array<import("../events.js").Listener>|undefined} Listeners.\n */\n\n\n Target.prototype.getListeners = function (type) {\n return this.listeners_ && this.listeners_[type] || undefined;\n };\n /**\n * @param {string=} opt_type Type. If not provided,\n * `true` will be returned if this event target has any listeners.\n * @return {boolean} Has listeners.\n */\n\n\n Target.prototype.hasListener = function (opt_type) {\n if (!this.listeners_) {\n return false;\n }\n\n return opt_type ? opt_type in this.listeners_ : Object.keys(this.listeners_).length > 0;\n };\n /**\n * @param {string} type Type.\n * @param {import("../events.js").Listener} listener Listener.\n */\n\n\n Target.prototype.removeEventListener = function (type, listener) {\n var listeners = this.listeners_ && this.listeners_[type];\n\n if (listeners) {\n var index = listeners.indexOf(listener);\n\n if (index !== -1) {\n if (this.pendingRemovals_ && type in this.pendingRemovals_) {\n // make listener a no-op, and remove later in #dispatchEvent()\n listeners[index] = VOID;\n ++this.pendingRemovals_[type];\n } else {\n listeners.splice(index, 1);\n\n if (listeners.length === 0) {\n delete this.listeners_[type];\n }\n }\n }\n }\n };\n\n return Target;\n}(ol_Disposable);\n\n/* harmony default export */ var events_Target = (Target);\n;// CONCATENATED MODULE: ./node_modules/ol/events/EventType.js\n/**\n * @module ol/events/EventType\n */\n\n/**\n * @enum {string}\n * @const\n */\n/* harmony default export */ var EventType = ({\n /**\n * Generic change event. Triggered when the revision counter is increased.\n * @event module:ol/events/Event~BaseEvent#change\n * @api\n */\n CHANGE: \'change\',\n\n /**\n * Generic error event. Triggered when an error occurs.\n * @event module:ol/events/Event~BaseEvent#error\n * @api\n */\n ERROR: \'error\',\n BLUR: \'blur\',\n CLEAR: \'clear\',\n CONTEXTMENU: \'contextmenu\',\n CLICK: \'click\',\n DBLCLICK: \'dblclick\',\n DRAGENTER: \'dragenter\',\n DRAGOVER: \'dragover\',\n DROP: \'drop\',\n FOCUS: \'focus\',\n KEYDOWN: \'keydown\',\n KEYPRESS: \'keypress\',\n LOAD: \'load\',\n RESIZE: \'resize\',\n TOUCHMOVE: \'touchmove\',\n WHEEL: \'wheel\'\n});\n;// CONCATENATED MODULE: ./node_modules/ol/events.js\n/**\n * @module ol/events\n */\n\n/**\n * Key to use with {@link module:ol/Observable~Observable#unByKey}.\n * @typedef {Object} EventsKey\n * @property {ListenerFunction} listener\n * @property {import("./events/Target.js").EventTargetLike} target\n * @property {string} type\n * @api\n */\n\n/**\n * Listener function. This function is called with an event object as argument.\n * When the function returns `false`, event propagation will stop.\n *\n * @typedef {function((Event|import("./events/Event.js").default)): (void|boolean)} ListenerFunction\n * @api\n */\n\n/**\n * @typedef {Object} ListenerObject\n * @property {ListenerFunction} handleEvent\n */\n\n/**\n * @typedef {ListenerFunction|ListenerObject} Listener\n */\n\n/**\n * Registers an event listener on an event target. Inspired by\n * https://google.github.io/closure-library/api/source/closure/goog/events/events.js.src.html\n *\n * This function efficiently binds a `listener` to a `this` object, and returns\n * a key for use with {@link module:ol/events~unlistenByKey}.\n *\n * @param {import("./events/Target.js").EventTargetLike} target Event target.\n * @param {string} type Event type.\n * @param {ListenerFunction} listener Listener.\n * @param {Object=} opt_this Object referenced by the `this` keyword in the\n * listener. Default is the `target`.\n * @param {boolean=} opt_once If true, add the listener as one-off listener.\n * @return {EventsKey} Unique key for the listener.\n */\n\nfunction listen(target, type, _listener, opt_this, opt_once) {\n if (opt_this && opt_this !== target) {\n _listener = _listener.bind(opt_this);\n }\n\n if (opt_once) {\n var originalListener_1 = _listener;\n\n _listener = function listener() {\n target.removeEventListener(type, _listener);\n originalListener_1.apply(this, arguments);\n };\n }\n\n var eventsKey = {\n target: target,\n type: type,\n listener: _listener\n };\n target.addEventListener(type, _listener);\n return eventsKey;\n}\n/**\n * Registers a one-off event listener on an event target. Inspired by\n * https://google.github.io/closure-library/api/source/closure/goog/events/events.js.src.html\n *\n * This function efficiently binds a `listener` as self-unregistering listener\n * to a `this` object, and returns a key for use with\n * {@link module:ol/events~unlistenByKey} in case the listener needs to be\n * unregistered before it is called.\n *\n * When {@link module:ol/events~listen} is called with the same arguments after this\n * function, the self-unregistering listener will be turned into a permanent\n * listener.\n *\n * @param {import("./events/Target.js").EventTargetLike} target Event target.\n * @param {string} type Event type.\n * @param {ListenerFunction} listener Listener.\n * @param {Object=} opt_this Object referenced by the `this` keyword in the\n * listener. Default is the `target`.\n * @return {EventsKey} Key for unlistenByKey.\n */\n\nfunction listenOnce(target, type, listener, opt_this) {\n return listen(target, type, listener, opt_this, true);\n}\n/**\n * Unregisters event listeners on an event target. Inspired by\n * https://google.github.io/closure-library/api/source/closure/goog/events/events.js.src.html\n *\n * The argument passed to this function is the key returned from\n * {@link module:ol/events~listen} or {@link module:ol/events~listenOnce}.\n *\n * @param {EventsKey} key The key.\n */\n\nfunction unlistenByKey(key) {\n if (key && key.target) {\n key.target.removeEventListener(key.type, key.listener);\n clear(key);\n }\n}\n;// CONCATENATED MODULE: ./node_modules/ol/Observable.js\nvar Observable_extends = undefined && undefined.__extends || function () {\n var _extendStatics = function extendStatics(d, b) {\n _extendStatics = Object.setPrototypeOf || {\n __proto__: []\n } instanceof Array && function (d, b) {\n d.__proto__ = b;\n } || function (d, b) {\n for (var p in b) {\n if (Object.prototype.hasOwnProperty.call(b, p)) d[p] = b[p];\n }\n };\n\n return _extendStatics(d, b);\n };\n\n return function (d, b) {\n _extendStatics(d, b);\n\n function __() {\n this.constructor = d;\n }\n\n d.prototype = b === null ? Object.create(b) : (__.prototype = b.prototype, new __());\n };\n}();\n/**\n * @module ol/Observable\n */\n\n\n\n\n\n/**\n * @classdesc\n * Abstract base class; normally only used for creating subclasses and not\n * instantiated in apps.\n * An event target providing convenient methods for listener registration\n * and unregistration. A generic `change` event is always available through\n * {@link module:ol/Observable~Observable#changed}.\n *\n * @fires import("./events/Event.js").default\n * @api\n */\n\nvar Observable =\n/** @class */\nfunction (_super) {\n Observable_extends(Observable, _super);\n\n function Observable() {\n var _this = _super.call(this) || this;\n /**\n * @private\n * @type {number}\n */\n\n\n _this.revision_ = 0;\n return _this;\n }\n /**\n * Increases the revision counter and dispatches a \'change\' event.\n * @api\n */\n\n\n Observable.prototype.changed = function () {\n ++this.revision_;\n this.dispatchEvent(EventType.CHANGE);\n };\n /**\n * Get the version number for this object. Each time the object is modified,\n * its version number will be incremented.\n * @return {number} Revision.\n * @api\n */\n\n\n Observable.prototype.getRevision = function () {\n return this.revision_;\n };\n /**\n * Listen for a certain type of event.\n * @param {string|Array<string>} type The event type or array of event types.\n * @param {function(?): ?} listener The listener function.\n * @return {import("./events.js").EventsKey|Array<import("./events.js").EventsKey>} Unique key for the listener. If\n * called with an array of event types as the first argument, the return\n * will be an array of keys.\n * @api\n */\n\n\n Observable.prototype.on = function (type, listener) {\n if (Array.isArray(type)) {\n var len = type.length;\n var keys = new Array(len);\n\n for (var i = 0; i < len; ++i) {\n keys[i] = listen(this, type[i], listener);\n }\n\n return keys;\n } else {\n return listen(this,\n /** @type {string} */\n type, listener);\n }\n };\n /**\n * Listen once for a certain type of event.\n * @param {string|Array<string>} type The event type or array of event types.\n * @param {function(?): ?} listener The listener function.\n * @return {import("./events.js").EventsKey|Array<import("./events.js").EventsKey>} Unique key for the listener. If\n * called with an array of event types as the first argument, the return\n * will be an array of keys.\n * @api\n */\n\n\n Observable.prototype.once = function (type, listener) {\n var key;\n\n if (Array.isArray(type)) {\n var len = type.length;\n key = new Array(len);\n\n for (var i = 0; i < len; ++i) {\n key[i] = listenOnce(this, type[i], listener);\n }\n } else {\n key = listenOnce(this,\n /** @type {string} */\n type, listener);\n }\n /** @type {Object} */\n\n\n listener.ol_key = key;\n return key;\n };\n /**\n * Unlisten for a certain type of event.\n * @param {string|Array<string>} type The event type or array of event types.\n * @param {function(?): ?} listener The listener function.\n * @api\n */\n\n\n Observable.prototype.un = function (type, listener) {\n var key =\n /** @type {Object} */\n listener.ol_key;\n\n if (key) {\n unByKey(key);\n } else if (Array.isArray(type)) {\n for (var i = 0, ii = type.length; i < ii; ++i) {\n this.removeEventListener(type[i], listener);\n }\n } else {\n this.removeEventListener(type, listener);\n }\n };\n\n return Observable;\n}(events_Target);\n/**\n * Removes an event listener using the key returned by `on()` or `once()`.\n * @param {import("./events.js").EventsKey|Array<import("./events.js").EventsKey>} key The key returned by `on()`\n * or `once()` (or an array of keys).\n * @api\n */\n\n\nfunction unByKey(key) {\n if (Array.isArray(key)) {\n for (var i = 0, ii = key.length; i < ii; ++i) {\n unlistenByKey(key[i]);\n }\n } else {\n unlistenByKey(\n /** @type {import("./events.js").EventsKey} */\n key);\n }\n}\n/* harmony default export */ var ol_Observable = (Observable);\n;// CONCATENATED MODULE: ./node_modules/ol/Object.js\nvar Object_extends = undefined && undefined.__extends || function () {\n var _extendStatics = function extendStatics(d, b) {\n _extendStatics = Object.setPrototypeOf || {\n __proto__: []\n } instanceof Array && function (d, b) {\n d.__proto__ = b;\n } || function (d, b) {\n for (var p in b) {\n if (Object.prototype.hasOwnProperty.call(b, p)) d[p] = b[p];\n }\n };\n\n return _extendStatics(d, b);\n };\n\n return function (d, b) {\n _extendStatics(d, b);\n\n function __() {\n this.constructor = d;\n }\n\n d.prototype = b === null ? Object.create(b) : (__.prototype = b.prototype, new __());\n };\n}();\n/**\n * @module ol/Object\n */\n\n\n\n\n\n\n\n/**\n * @classdesc\n * Events emitted by {@link module:ol/Object~BaseObject} instances are instances of this type.\n */\n\nvar ObjectEvent =\n/** @class */\nfunction (_super) {\n Object_extends(ObjectEvent, _super);\n /**\n * @param {string} type The event type.\n * @param {string} key The property name.\n * @param {*} oldValue The old value for `key`.\n */\n\n\n function ObjectEvent(type, key, oldValue) {\n var _this = _super.call(this, type) || this;\n /**\n * The name of the property whose value is changing.\n * @type {string}\n * @api\n */\n\n\n _this.key = key;\n /**\n * The old value. To get the new value use `e.target.get(e.key)` where\n * `e` is the event object.\n * @type {*}\n * @api\n */\n\n _this.oldValue = oldValue;\n return _this;\n }\n\n return ObjectEvent;\n}(Event);\n\n\n/**\n * @classdesc\n * Abstract base class; normally only used for creating subclasses and not\n * instantiated in apps.\n * Most non-trivial classes inherit from this.\n *\n * This extends {@link module:ol/Observable} with observable\n * properties, where each property is observable as well as the object as a\n * whole.\n *\n * Classes that inherit from this have pre-defined properties, to which you can\n * add your owns. The pre-defined properties are listed in this documentation as\n * \'Observable Properties\', and have their own accessors; for example,\n * {@link module:ol/Map~Map} has a `target` property, accessed with\n * `getTarget()` and changed with `setTarget()`. Not all properties are however\n * settable. There are also general-purpose accessors `get()` and `set()`. For\n * example, `get(\'target\')` is equivalent to `getTarget()`.\n *\n * The `set` accessors trigger a change event, and you can monitor this by\n * registering a listener. For example, {@link module:ol/View~View} has a\n * `center` property, so `view.on(\'change:center\', function(evt) {...});` would\n * call the function whenever the value of the center property changes. Within\n * the function, `evt.target` would be the view, so `evt.target.getCenter()`\n * would return the new center.\n *\n * You can add your own observable properties with\n * `object.set(\'prop\', \'value\')`, and retrieve that with `object.get(\'prop\')`.\n * You can listen for changes on that property value with\n * `object.on(\'change:prop\', listener)`. You can get a list of all\n * properties with {@link module:ol/Object~BaseObject#getProperties}.\n *\n * Note that the observable properties are separate from standard JS properties.\n * You can, for example, give your map object a title with\n * `map.title=\'New title\'` and with `map.set(\'title\', \'Another title\')`. The\n * first will be a `hasOwnProperty`; the second will appear in\n * `getProperties()`. Only the second is observable.\n *\n * Properties can be deleted by using the unset method. E.g.\n * object.unset(\'foo\').\n *\n * @fires ObjectEvent\n * @api\n */\n\nvar BaseObject =\n/** @class */\nfunction (_super) {\n Object_extends(BaseObject, _super);\n /**\n * @param {Object<string, *>=} opt_values An object with key-value pairs.\n */\n\n\n function BaseObject(opt_values) {\n var _this = _super.call(this) || this; // Call {@link module:ol/util~getUid} to ensure that the order of objects\' ids is\n // the same as the order in which they were created. This also helps to\n // ensure that object properties are always added in the same order, which\n // helps many JavaScript engines generate faster code.\n\n\n util_getUid(_this);\n /**\n * @private\n * @type {Object<string, *>}\n */\n\n _this.values_ = null;\n\n if (opt_values !== undefined) {\n _this.setProperties(opt_values);\n }\n\n return _this;\n }\n /**\n * Gets a value.\n * @param {string} key Key name.\n * @return {*} Value.\n * @api\n */\n\n\n BaseObject.prototype.get = function (key) {\n var value;\n\n if (this.values_ && this.values_.hasOwnProperty(key)) {\n value = this.values_[key];\n }\n\n return value;\n };\n /**\n * Get a list of object property names.\n * @return {Array<string>} List of property names.\n * @api\n */\n\n\n BaseObject.prototype.getKeys = function () {\n return this.values_ && Object.keys(this.values_) || [];\n };\n /**\n * Get an object of all property names and values.\n * @return {Object<string, *>} Object.\n * @api\n */\n\n\n BaseObject.prototype.getProperties = function () {\n return this.values_ && obj_assign({}, this.values_) || {};\n };\n /**\n * @return {boolean} The object has properties.\n */\n\n\n BaseObject.prototype.hasProperties = function () {\n return !!this.values_;\n };\n /**\n * @param {string} key Key name.\n * @param {*} oldValue Old value.\n */\n\n\n BaseObject.prototype.notify = function (key, oldValue) {\n var eventType;\n eventType = getChangeEventType(key);\n this.dispatchEvent(new ObjectEvent(eventType, key, oldValue));\n eventType = ObjectEventType.PROPERTYCHANGE;\n this.dispatchEvent(new ObjectEvent(eventType, key, oldValue));\n };\n /**\n * Sets a value.\n * @param {string} key Key name.\n * @param {*} value Value.\n * @param {boolean=} opt_silent Update without triggering an event.\n * @api\n */\n\n\n BaseObject.prototype.set = function (key, value, opt_silent) {\n var values = this.values_ || (this.values_ = {});\n\n if (opt_silent) {\n values[key] = value;\n } else {\n var oldValue = values[key];\n values[key] = value;\n\n if (oldValue !== value) {\n this.notify(key, oldValue);\n }\n }\n };\n /**\n * Sets a collection of key-value pairs. Note that this changes any existing\n * properties and adds new ones (it does not remove any existing properties).\n * @param {Object<string, *>} values Values.\n * @param {boolean=} opt_silent Update without triggering an event.\n * @api\n */\n\n\n BaseObject.prototype.setProperties = function (values, opt_silent) {\n for (var key in values) {\n this.set(key, values[key], opt_silent);\n }\n };\n /**\n * Apply any properties from another object without triggering events.\n * @param {BaseObject} source The source object.\n * @protected\n */\n\n\n BaseObject.prototype.applyProperties = function (source) {\n if (!source.values_) {\n return;\n }\n\n obj_assign(this.values_ || (this.values_ = {}), source.values_);\n };\n /**\n * Unsets a property.\n * @param {string} key Key name.\n * @param {boolean=} opt_silent Unset without triggering an event.\n * @api\n */\n\n\n BaseObject.prototype.unset = function (key, opt_silent) {\n if (this.values_ && key in this.values_) {\n var oldValue = this.values_[key];\n delete this.values_[key];\n\n if (obj_isEmpty(this.values_)) {\n this.values_ = null;\n }\n\n if (!opt_silent) {\n this.notify(key, oldValue);\n }\n }\n };\n\n return BaseObject;\n}(ol_Observable);\n/**\n * @type {Object<string, string>}\n */\n\n\nvar changeEventTypeCache = {};\n/**\n * @param {string} key Key name.\n * @return {string} Change name.\n */\n\nfunction getChangeEventType(key) {\n return changeEventTypeCache.hasOwnProperty(key) ? changeEventTypeCache[key] : changeEventTypeCache[key] = \'change:\' + key;\n}\n/* harmony default export */ var ol_Object = (BaseObject);\n;// CONCATENATED MODULE: ./node_modules/ol/layer/Property.js\n/**\n * @module ol/layer/Property\n */\n\n/**\n * @enum {string}\n */\n/* harmony default export */ var Property = ({\n OPACITY: \'opacity\',\n VISIBLE: \'visible\',\n EXTENT: \'extent\',\n Z_INDEX: \'zIndex\',\n MAX_RESOLUTION: \'maxResolution\',\n MIN_RESOLUTION: \'minResolution\',\n MAX_ZOOM: \'maxZoom\',\n MIN_ZOOM: \'minZoom\',\n SOURCE: \'source\'\n});\n;// CONCATENATED MODULE: ./node_modules/ol/layer/Base.js\nvar Base_extends = undefined && undefined.__extends || function () {\n var _extendStatics = function extendStatics(d, b) {\n _extendStatics = Object.setPrototypeOf || {\n __proto__: []\n } instanceof Array && function (d, b) {\n d.__proto__ = b;\n } || function (d, b) {\n for (var p in b) {\n if (Object.prototype.hasOwnProperty.call(b, p)) d[p] = b[p];\n }\n };\n\n return _extendStatics(d, b);\n };\n\n return function (d, b) {\n _extendStatics(d, b);\n\n function __() {\n this.constructor = d;\n }\n\n d.prototype = b === null ? Object.create(b) : (__.prototype = b.prototype, new __());\n };\n}();\n/**\n * @module ol/layer/Base\n */\n\n\n\n\n\n\n\n\n/**\n * @typedef {Object} Options\n * @property {string} [className=\'ol-layer\'] A CSS class name to set to the layer element.\n * @property {number} [opacity=1] Opacity (0, 1).\n * @property {boolean} [visible=true] Visibility.\n * @property {import("../extent.js").Extent} [extent] The bounding extent for layer rendering. The layer will not be\n * rendered outside of this extent.\n * @property {number} [zIndex] The z-index for layer rendering. At rendering time, the layers\n * will be ordered, first by Z-index and then by position. When `undefined`, a `zIndex` of 0 is assumed\n * for layers that are added to the map\'s `layers` collection, or `Infinity` when the layer\'s `setMap()`\n * method was used.\n * @property {number} [minResolution] The minimum resolution (inclusive) at which this layer will be\n * visible.\n * @property {number} [maxResolution] The maximum resolution (exclusive) below which this layer will\n * be visible.\n * @property {number} [minZoom] The minimum view zoom level (exclusive) above which this layer will be\n * visible.\n * @property {number} [maxZoom] The maximum view zoom level (inclusive) at which this layer will\n * be visible.\n */\n\n/**\n * @classdesc\n * Abstract base class; normally only used for creating subclasses and not\n * instantiated in apps.\n * Note that with {@link module:ol/layer/Base} and all its subclasses, any property set in\n * the options is set as a {@link module:ol/Object} property on the layer object, so\n * is observable, and has get/set accessors.\n *\n * @api\n */\n\nvar BaseLayer =\n/** @class */\nfunction (_super) {\n Base_extends(BaseLayer, _super);\n /**\n * @param {Options} options Layer options.\n */\n\n\n function BaseLayer(options) {\n var _this = _super.call(this) || this;\n /**\n * @type {Object<string, *>}\n */\n\n\n var properties = obj_assign({}, options);\n properties[Property.OPACITY] = options.opacity !== undefined ? options.opacity : 1;\n asserts_assert(typeof properties[Property.OPACITY] === \'number\', 64); // Layer opacity must be a number\n\n properties[Property.VISIBLE] = options.visible !== undefined ? options.visible : true;\n properties[Property.Z_INDEX] = options.zIndex;\n properties[Property.MAX_RESOLUTION] = options.maxResolution !== undefined ? options.maxResolution : Infinity;\n properties[Property.MIN_RESOLUTION] = options.minResolution !== undefined ? options.minResolution : 0;\n properties[Property.MIN_ZOOM] = options.minZoom !== undefined ? options.minZoom : -Infinity;\n properties[Property.MAX_ZOOM] = options.maxZoom !== undefined ? options.maxZoom : Infinity;\n /**\n * @type {string}\n * @private\n */\n\n _this.className_ = properties.className !== undefined ? options.className : \'ol-layer\';\n delete properties.className;\n\n _this.setProperties(properties);\n /**\n * @type {import("./Layer.js").State}\n * @private\n */\n\n\n _this.state_ = null;\n return _this;\n }\n /**\n * @return {string} CSS class name.\n */\n\n\n BaseLayer.prototype.getClassName = function () {\n return this.className_;\n };\n /**\n * This method is not meant to be called by layers or layer renderers because the state\n * is incorrect if the layer is included in a layer group.\n *\n * @param {boolean=} opt_managed Layer is managed.\n * @return {import("./Layer.js").State} Layer state.\n */\n\n\n BaseLayer.prototype.getLayerState = function (opt_managed) {\n /** @type {import("./Layer.js").State} */\n var state = this.state_ ||\n /** @type {?} */\n {\n layer: this,\n managed: opt_managed === undefined ? true : opt_managed\n };\n var zIndex = this.getZIndex();\n state.opacity = math_clamp(Math.round(this.getOpacity() * 100) / 100, 0, 1);\n state.sourceState = this.getSourceState();\n state.visible = this.getVisible();\n state.extent = this.getExtent();\n state.zIndex = zIndex !== undefined ? zIndex : state.managed === false ? Infinity : 0;\n state.maxResolution = this.getMaxResolution();\n state.minResolution = Math.max(this.getMinResolution(), 0);\n state.minZoom = this.getMinZoom();\n state.maxZoom = this.getMaxZoom();\n this.state_ = state;\n return state;\n };\n /**\n * @abstract\n * @param {Array<import("./Layer.js").default>=} opt_array Array of layers (to be\n * modified in place).\n * @return {Array<import("./Layer.js").default>} Array of layers.\n */\n\n\n BaseLayer.prototype.getLayersArray = function (opt_array) {\n return util_abstract();\n };\n /**\n * @abstract\n * @param {Array<import("./Layer.js").State>=} opt_states Optional list of layer\n * states (to be modified in place).\n * @return {Array<import("./Layer.js").State>} List of layer states.\n */\n\n\n BaseLayer.prototype.getLayerStatesArray = function (opt_states) {\n return util_abstract();\n };\n /**\n * Return the {@link module:ol/extent~Extent extent} of the layer or `undefined` if it\n * will be visible regardless of extent.\n * @return {import("../extent.js").Extent|undefined} The layer extent.\n * @observable\n * @api\n */\n\n\n BaseLayer.prototype.getExtent = function () {\n return (\n /** @type {import("../extent.js").Extent|undefined} */\n this.get(Property.EXTENT)\n );\n };\n /**\n * Return the maximum resolution of the layer.\n * @return {number} The maximum resolution of the layer.\n * @observable\n * @api\n */\n\n\n BaseLayer.prototype.getMaxResolution = function () {\n return (\n /** @type {number} */\n this.get(Property.MAX_RESOLUTION)\n );\n };\n /**\n * Return the minimum resolution of the layer.\n * @return {number} The minimum resolution of the layer.\n * @observable\n * @api\n */\n\n\n BaseLayer.prototype.getMinResolution = function () {\n return (\n /** @type {number} */\n this.get(Property.MIN_RESOLUTION)\n );\n };\n /**\n * Return the minimum zoom level of the layer.\n * @return {number} The minimum zoom level of the layer.\n * @observable\n * @api\n */\n\n\n BaseLayer.prototype.getMinZoom = function () {\n return (\n /** @type {number} */\n this.get(Property.MIN_ZOOM)\n );\n };\n /**\n * Return the maximum zoom level of the layer.\n * @return {number} The maximum zoom level of the layer.\n * @observable\n * @api\n */\n\n\n BaseLayer.prototype.getMaxZoom = function () {\n return (\n /** @type {number} */\n this.get(Property.MAX_ZOOM)\n );\n };\n /**\n * Return the opacity of the layer (between 0 and 1).\n * @return {number} The opacity of the layer.\n * @observable\n * @api\n */\n\n\n BaseLayer.prototype.getOpacity = function () {\n return (\n /** @type {number} */\n this.get(Property.OPACITY)\n );\n };\n /**\n * @abstract\n * @return {import("../source/State.js").default} Source state.\n */\n\n\n BaseLayer.prototype.getSourceState = function () {\n return util_abstract();\n };\n /**\n * Return the visibility of the layer (`true` or `false`).\n * @return {boolean} The visibility of the layer.\n * @observable\n * @api\n */\n\n\n BaseLayer.prototype.getVisible = function () {\n return (\n /** @type {boolean} */\n this.get(Property.VISIBLE)\n );\n };\n /**\n * Return the Z-index of the layer, which is used to order layers before\n * rendering. The default Z-index is 0.\n * @return {number} The Z-index of the layer.\n * @observable\n * @api\n */\n\n\n BaseLayer.prototype.getZIndex = function () {\n return (\n /** @type {number} */\n this.get(Property.Z_INDEX)\n );\n };\n /**\n * Set the extent at which the layer is visible. If `undefined`, the layer\n * will be visible at all extents.\n * @param {import("../extent.js").Extent|undefined} extent The extent of the layer.\n * @observable\n * @api\n */\n\n\n BaseLayer.prototype.setExtent = function (extent) {\n this.set(Property.EXTENT, extent);\n };\n /**\n * Set the maximum resolution at which the layer is visible.\n * @param {number} maxResolution The maximum resolution of the layer.\n * @observable\n * @api\n */\n\n\n BaseLayer.prototype.setMaxResolution = function (maxResolution) {\n this.set(Property.MAX_RESOLUTION, maxResolution);\n };\n /**\n * Set the minimum resolution at which the layer is visible.\n * @param {number} minResolution The minimum resolution of the layer.\n * @observable\n * @api\n */\n\n\n BaseLayer.prototype.setMinResolution = function (minResolution) {\n this.set(Property.MIN_RESOLUTION, minResolution);\n };\n /**\n * Set the maximum zoom (exclusive) at which the layer is visible.\n * Note that the zoom levels for layer visibility are based on the\n * view zoom level, which may be different from a tile source zoom level.\n * @param {number} maxZoom The maximum zoom of the layer.\n * @observable\n * @api\n */\n\n\n BaseLayer.prototype.setMaxZoom = function (maxZoom) {\n this.set(Property.MAX_ZOOM, maxZoom);\n };\n /**\n * Set the minimum zoom (inclusive) at which the layer is visible.\n * Note that the zoom levels for layer visibility are based on the\n * view zoom level, which may be different from a tile source zoom level.\n * @param {number} minZoom The minimum zoom of the layer.\n * @observable\n * @api\n */\n\n\n BaseLayer.prototype.setMinZoom = function (minZoom) {\n this.set(Property.MIN_ZOOM, minZoom);\n };\n /**\n * Set the opacity of the layer, allowed values range from 0 to 1.\n * @param {number} opacity The opacity of the layer.\n * @observable\n * @api\n */\n\n\n BaseLayer.prototype.setOpacity = function (opacity) {\n asserts_assert(typeof opacity === \'number\', 64); // Layer opacity must be a number\n\n this.set(Property.OPACITY, opacity);\n };\n /**\n * Set the visibility of the layer (`true` or `false`).\n * @param {boolean} visible The visibility of the layer.\n * @observable\n * @api\n */\n\n\n BaseLayer.prototype.setVisible = function (visible) {\n this.set(Property.VISIBLE, visible);\n };\n /**\n * Set Z-index of the layer, which is used to order layers before rendering.\n * The default Z-index is 0.\n * @param {number} zindex The z-index of the layer.\n * @observable\n * @api\n */\n\n\n BaseLayer.prototype.setZIndex = function (zindex) {\n this.set(Property.Z_INDEX, zindex);\n };\n /**\n * Clean up.\n */\n\n\n BaseLayer.prototype.disposeInternal = function () {\n if (this.state_) {\n this.state_.layer = null;\n this.state_ = null;\n }\n\n _super.prototype.disposeInternal.call(this);\n };\n\n return BaseLayer;\n}(ol_Object);\n\n/* harmony default export */ var Base = (BaseLayer);\n;// CONCATENATED MODULE: ./node_modules/ol/render/EventType.js\n/**\n * @module ol/render/EventType\n */\n\n/**\n * @enum {string}\n */\n/* harmony default export */ var render_EventType = ({\n /**\n * Triggered before a layer is rendered.\n * @event module:ol/render/Event~RenderEvent#prerender\n * @api\n */\n PRERENDER: \'prerender\',\n\n /**\n * Triggered after a layer is rendered.\n * @event module:ol/render/Event~RenderEvent#postrender\n * @api\n */\n POSTRENDER: \'postrender\',\n\n /**\n * Triggered before layers are rendered.\n * The event object will not have a `context` set.\n * @event module:ol/render/Event~RenderEvent#precompose\n * @api\n */\n PRECOMPOSE: \'precompose\',\n\n /**\n * Triggered after all layers are rendered.\n * The event object will not have a `context` set.\n * @event module:ol/render/Event~RenderEvent#postcompose\n * @api\n */\n POSTCOMPOSE: \'postcompose\',\n\n /**\n * Triggered when rendering is complete, i.e. all sources and tiles have\n * finished loading for the current viewport, and all tiles are faded in.\n * The event object will not have a `context` set.\n * @event module:ol/render/Event~RenderEvent#rendercomplete\n * @api\n */\n RENDERCOMPLETE: \'rendercomplete\'\n});\n;// CONCATENATED MODULE: ./node_modules/ol/source/State.js\n/**\n * @module ol/source/State\n */\n\n/**\n * @enum {string}\n * State of the source, one of \'undefined\', \'loading\', \'ready\' or \'error\'.\n */\n/* harmony default export */ var State = ({\n UNDEFINED: \'undefined\',\n LOADING: \'loading\',\n READY: \'ready\',\n ERROR: \'error\'\n});\n;// CONCATENATED MODULE: ./node_modules/ol/layer/Layer.js\nvar Layer_extends = undefined && undefined.__extends || function () {\n var _extendStatics = function extendStatics(d, b) {\n _extendStatics = Object.setPrototypeOf || {\n __proto__: []\n } instanceof Array && function (d, b) {\n d.__proto__ = b;\n } || function (d, b) {\n for (var p in b) {\n if (Object.prototype.hasOwnProperty.call(b, p)) d[p] = b[p];\n }\n };\n\n return _extendStatics(d, b);\n };\n\n return function (d, b) {\n _extendStatics(d, b);\n\n function __() {\n this.constructor = d;\n }\n\n d.prototype = b === null ? Object.create(b) : (__.prototype = b.prototype, new __());\n };\n}();\n/**\n * @module ol/layer/Layer\n */\n\n\n\n\n\n\n\n\n\n\n\n/**\n * @typedef {function(import("../PluggableMap.js").FrameState):HTMLElement} RenderFunction\n */\n\n/**\n * @typedef {Object} Options\n * @property {string} [className=\'ol-layer\'] A CSS class name to set to the layer element.\n * @property {number} [opacity=1] Opacity (0, 1).\n * @property {boolean} [visible=true] Visibility.\n * @property {import("../extent.js").Extent} [extent] The bounding extent for layer rendering. The layer will not be\n * rendered outside of this extent.\n * @property {number} [zIndex] The z-index for layer rendering. At rendering time, the layers\n * will be ordered, first by Z-index and then by position. When `undefined`, a `zIndex` of 0 is assumed\n * for layers that are added to the map\'s `layers` collection, or `Infinity` when the layer\'s `setMap()`\n * method was used.\n * @property {number} [minResolution] The minimum resolution (inclusive) at which this layer will be\n * visible.\n * @property {number} [maxResolution] The maximum resolution (exclusive) below which this layer will\n * be visible.\n * @property {number} [minZoom] The minimum view zoom level (exclusive) above which this layer will be\n * visible.\n * @property {number} [maxZoom] The maximum view zoom level (inclusive) at which this layer will\n * be visible.\n * @property {import("../source/Source.js").default} [source] Source for this layer. If not provided to the constructor,\n * the source can be set by calling {@link module:ol/layer/Layer#setSource layer.setSource(source)} after\n * construction.\n * @property {import("../PluggableMap.js").default} [map] Map.\n * @property {RenderFunction} [render] Render function. Takes the frame state as input and is expected to return an\n * HTML element. Will overwrite the default rendering for the layer.\n */\n\n/**\n * @typedef {Object} State\n * @property {import("./Layer.js").default} layer\n * @property {number} opacity Opacity, the value is rounded to two digits to appear after the decimal point.\n * @property {import("../source/State.js").default} sourceState\n * @property {boolean} visible\n * @property {boolean} managed\n * @property {import("../extent.js").Extent} [extent]\n * @property {number} zIndex\n * @property {number} maxResolution\n * @property {number} minResolution\n * @property {number} minZoom\n * @property {number} maxZoom\n */\n\n/**\n * @classdesc\n * Base class from which all layer types are derived. This should only be instantiated\n * in the case where a custom layer is be added to the map with a custom `render` function.\n * Such a function can be specified in the `options` object, and is expected to return an HTML element.\n *\n * A visual representation of raster or vector map data.\n * Layers group together those properties that pertain to how the data is to be\n * displayed, irrespective of the source of that data.\n *\n * Layers are usually added to a map with {@link module:ol/Map#addLayer}. Components\n * like {@link module:ol/interaction/Select~Select} use unmanaged layers\n * internally. These unmanaged layers are associated with the map using\n * {@link module:ol/layer/Layer~Layer#setMap} instead.\n *\n * A generic `change` event is fired when the state of the source changes.\n *\n * Please note that for performance reasons several layers might get rendered to\n * the same HTML element, which will cause {@link module:ol/Map~Map#forEachLayerAtPixel} to\n * give false positives. To avoid this, apply different `className` properties to the\n * layers at creation time.\n *\n * @fires import("../render/Event.js").RenderEvent#prerender\n * @fires import("../render/Event.js").RenderEvent#postrender\n *\n * @template {import("../source/Source.js").default} SourceType\n * @api\n */\n\nvar Layer =\n/** @class */\nfunction (_super) {\n Layer_extends(Layer, _super);\n /**\n * @param {Options} options Layer options.\n */\n\n\n function Layer(options) {\n var _this = this;\n\n var baseOptions = obj_assign({}, options);\n delete baseOptions.source;\n _this = _super.call(this, baseOptions) || this;\n /**\n * @private\n * @type {?import("../events.js").EventsKey}\n */\n\n _this.mapPrecomposeKey_ = null;\n /**\n * @private\n * @type {?import("../events.js").EventsKey}\n */\n\n _this.mapRenderKey_ = null;\n /**\n * @private\n * @type {?import("../events.js").EventsKey}\n */\n\n _this.sourceChangeKey_ = null;\n /**\n * @private\n * @type {import("../renderer/Layer.js").default}\n */\n\n _this.renderer_ = null; // Overwrite default render method with a custom one\n\n if (options.render) {\n _this.render = options.render;\n }\n\n if (options.map) {\n _this.setMap(options.map);\n }\n\n _this.addEventListener(getChangeEventType(Property.SOURCE), _this.handleSourcePropertyChange_);\n\n var source = options.source ?\n /** @type {SourceType} */\n options.source : null;\n\n _this.setSource(source);\n\n return _this;\n }\n /**\n * @param {Array<import("./Layer.js").default>=} opt_array Array of layers (to be modified in place).\n * @return {Array<import("./Layer.js").default>} Array of layers.\n */\n\n\n Layer.prototype.getLayersArray = function (opt_array) {\n var array = opt_array ? opt_array : [];\n array.push(this);\n return array;\n };\n /**\n * @param {Array<import("./Layer.js").State>=} opt_states Optional list of layer states (to be modified in place).\n * @return {Array<import("./Layer.js").State>} List of layer states.\n */\n\n\n Layer.prototype.getLayerStatesArray = function (opt_states) {\n var states = opt_states ? opt_states : [];\n states.push(this.getLayerState());\n return states;\n };\n /**\n * Get the layer source.\n * @return {SourceType} The layer source (or `null` if not yet set).\n * @observable\n * @api\n */\n\n\n Layer.prototype.getSource = function () {\n return (\n /** @type {SourceType} */\n this.get(Property.SOURCE) || null\n );\n };\n /**\n * @return {import("../source/State.js").default} Source state.\n */\n\n\n Layer.prototype.getSourceState = function () {\n var source = this.getSource();\n return !source ? State.UNDEFINED : source.getState();\n };\n /**\n * @private\n */\n\n\n Layer.prototype.handleSourceChange_ = function () {\n this.changed();\n };\n /**\n * @private\n */\n\n\n Layer.prototype.handleSourcePropertyChange_ = function () {\n if (this.sourceChangeKey_) {\n unlistenByKey(this.sourceChangeKey_);\n this.sourceChangeKey_ = null;\n }\n\n var source = this.getSource();\n\n if (source) {\n this.sourceChangeKey_ = listen(source, EventType.CHANGE, this.handleSourceChange_, this);\n }\n\n this.changed();\n };\n /**\n * @param {import("../pixel").Pixel} pixel Pixel.\n * @return {Promise<Array<import("../Feature").default>>} Promise that resolves with\n * an array of features.\n */\n\n\n Layer.prototype.getFeatures = function (pixel) {\n return this.renderer_.getFeatures(pixel);\n };\n /**\n * In charge to manage the rendering of the layer. One layer type is\n * bounded with one layer renderer.\n * @param {?import("../PluggableMap.js").FrameState} frameState Frame state.\n * @param {HTMLElement} target Target which the renderer may (but need not) use\n * for rendering its content.\n * @return {HTMLElement} The rendered element.\n */\n\n\n Layer.prototype.render = function (frameState, target) {\n var layerRenderer = this.getRenderer();\n\n if (layerRenderer.prepareFrame(frameState)) {\n return layerRenderer.renderFrame(frameState, target);\n }\n };\n /**\n * Sets the layer to be rendered on top of other layers on a map. The map will\n * not manage this layer in its layers collection, and the callback in\n * {@link module:ol/Map#forEachLayerAtPixel} will receive `null` as layer. This\n * is useful for temporary layers. To remove an unmanaged layer from the map,\n * use `#setMap(null)`.\n *\n * To add the layer to a map and have it managed by the map, use\n * {@link module:ol/Map#addLayer} instead.\n * @param {import("../PluggableMap.js").default} map Map.\n * @api\n */\n\n\n Layer.prototype.setMap = function (map) {\n if (this.mapPrecomposeKey_) {\n unlistenByKey(this.mapPrecomposeKey_);\n this.mapPrecomposeKey_ = null;\n }\n\n if (!map) {\n this.changed();\n }\n\n if (this.mapRenderKey_) {\n unlistenByKey(this.mapRenderKey_);\n this.mapRenderKey_ = null;\n }\n\n if (map) {\n this.mapPrecomposeKey_ = listen(map, render_EventType.PRECOMPOSE, function (evt) {\n var renderEvent =\n /** @type {import("../render/Event.js").default} */\n evt;\n var layerStatesArray = renderEvent.frameState.layerStatesArray;\n var layerState = this.getLayerState(false); // A layer can only be added to the map once. Use either `layer.setMap()` or `map.addLayer()`, not both.\n\n asserts_assert(!layerStatesArray.some(function (arrayLayerState) {\n return arrayLayerState.layer === layerState.layer;\n }), 67);\n layerStatesArray.push(layerState);\n }, this);\n this.mapRenderKey_ = listen(this, EventType.CHANGE, map.render, map);\n this.changed();\n }\n };\n /**\n * Set the layer source.\n * @param {SourceType} source The layer source.\n * @observable\n * @api\n */\n\n\n Layer.prototype.setSource = function (source) {\n this.set(Property.SOURCE, source);\n };\n /**\n * Get the renderer for this layer.\n * @return {import("../renderer/Layer.js").default} The layer renderer.\n */\n\n\n Layer.prototype.getRenderer = function () {\n if (!this.renderer_) {\n this.renderer_ = this.createRenderer();\n }\n\n return this.renderer_;\n };\n /**\n * @return {boolean} The layer has a renderer.\n */\n\n\n Layer.prototype.hasRenderer = function () {\n return !!this.renderer_;\n };\n /**\n * Create a renderer for this layer.\n * @return {import("../renderer/Layer.js").default} A layer renderer.\n * @protected\n */\n\n\n Layer.prototype.createRenderer = function () {\n return null;\n };\n /**\n * Clean up.\n */\n\n\n Layer.prototype.disposeInternal = function () {\n this.setSource(null);\n\n _super.prototype.disposeInternal.call(this);\n };\n\n return Layer;\n}(Base);\n/**\n * Return `true` if the layer is visible and if the provided view state\n * has resolution and zoom levels that are in range of the layer\'s min/max.\n * @param {State} layerState Layer state.\n * @param {import("../View.js").State} viewState View state.\n * @return {boolean} The layer is visible at the given view state.\n */\n\n\nfunction inView(layerState, viewState) {\n if (!layerState.visible) {\n return false;\n }\n\n var resolution = viewState.resolution;\n\n if (resolution < layerState.minResolution || resolution >= layerState.maxResolution) {\n return false;\n }\n\n var zoom = viewState.zoom;\n return zoom > layerState.minZoom && zoom <= layerState.maxZoom;\n}\n/* harmony default export */ var layer_Layer = (Layer);\n;// CONCATENATED MODULE: ./node_modules/ol/coordinate.js\n/**\n * @module ol/coordinate\n */\n\n\n\n/**\n * An array of numbers representing an xy coordinate. Example: `[16, 48]`.\n * @typedef {Array<number>} Coordinate\n * @api\n */\n\n/**\n * A function that takes a {@link module:ol/coordinate~Coordinate} and\n * transforms it into a `{string}`.\n *\n * @typedef {function((Coordinate|undefined)): string} CoordinateFormat\n * @api\n */\n\n/**\n * Add `delta` to `coordinate`. `coordinate` is modified in place and returned\n * by the function.\n *\n * Example:\n *\n * import {add} from \'ol/coordinate\';\n *\n * var coord = [7.85, 47.983333];\n * add(coord, [-2, 4]);\n * // coord is now [5.85, 51.983333]\n *\n * @param {Coordinate} coordinate Coordinate.\n * @param {Coordinate} delta Delta.\n * @return {Coordinate} The input coordinate adjusted by\n * the given delta.\n * @api\n */\n\nfunction add(coordinate, delta) {\n coordinate[0] += +delta[0];\n coordinate[1] += +delta[1];\n return coordinate;\n}\n/**\n * Calculates the point closest to the passed coordinate on the passed circle.\n *\n * @param {Coordinate} coordinate The coordinate.\n * @param {import("./geom/Circle.js").default} circle The circle.\n * @return {Coordinate} Closest point on the circumference.\n */\n\nfunction closestOnCircle(coordinate, circle) {\n var r = circle.getRadius();\n var center = circle.getCenter();\n var x0 = center[0];\n var y0 = center[1];\n var x1 = coordinate[0];\n var y1 = coordinate[1];\n var dx = x1 - x0;\n var dy = y1 - y0;\n\n if (dx === 0 && dy === 0) {\n dx = 1;\n }\n\n var d = Math.sqrt(dx * dx + dy * dy);\n var x = x0 + r * dx / d;\n var y = y0 + r * dy / d;\n return [x, y];\n}\n/**\n * Calculates the point closest to the passed coordinate on the passed segment.\n * This is the foot of the perpendicular of the coordinate to the segment when\n * the foot is on the segment, or the closest segment coordinate when the foot\n * is outside the segment.\n *\n * @param {Coordinate} coordinate The coordinate.\n * @param {Array<Coordinate>} segment The two coordinates\n * of the segment.\n * @return {Coordinate} The foot of the perpendicular of\n * the coordinate to the segment.\n */\n\nfunction closestOnSegment(coordinate, segment) {\n var x0 = coordinate[0];\n var y0 = coordinate[1];\n var start = segment[0];\n var end = segment[1];\n var x1 = start[0];\n var y1 = start[1];\n var x2 = end[0];\n var y2 = end[1];\n var dx = x2 - x1;\n var dy = y2 - y1;\n var along = dx === 0 && dy === 0 ? 0 : (dx * (x0 - x1) + dy * (y0 - y1)) / (dx * dx + dy * dy || 0);\n var x, y;\n\n if (along <= 0) {\n x = x1;\n y = y1;\n } else if (along >= 1) {\n x = x2;\n y = y2;\n } else {\n x = x1 + along * dx;\n y = y1 + along * dy;\n }\n\n return [x, y];\n}\n/**\n * Returns a {@link module:ol/coordinate~CoordinateFormat} function that can be\n * used to format\n * a {Coordinate} to a string.\n *\n * Example without specifying the fractional digits:\n *\n * import {createStringXY} from \'ol/coordinate\';\n *\n * var coord = [7.85, 47.983333];\n * var stringifyFunc = createStringXY();\n * var out = stringifyFunc(coord);\n * // out is now \'8, 48\'\n *\n * Example with explicitly specifying 2 fractional digits:\n *\n * import {createStringXY} from \'ol/coordinate\';\n *\n * var coord = [7.85, 47.983333];\n * var stringifyFunc = createStringXY(2);\n * var out = stringifyFunc(coord);\n * // out is now \'7.85, 47.98\'\n *\n * @param {number=} opt_fractionDigits The number of digits to include\n * after the decimal point. Default is `0`.\n * @return {CoordinateFormat} Coordinate format.\n * @api\n */\n\nfunction createStringXY(opt_fractionDigits) {\n return (\n /**\n * @param {Coordinate} coordinate Coordinate.\n * @return {string} String XY.\n */\n function (coordinate) {\n return toStringXY(coordinate, opt_fractionDigits);\n }\n );\n}\n/**\n * @param {string} hemispheres Hemispheres.\n * @param {number} degrees Degrees.\n * @param {number=} opt_fractionDigits The number of digits to include\n * after the decimal point. Default is `0`.\n * @return {string} String.\n */\n\nfunction degreesToStringHDMS(hemispheres, degrees, opt_fractionDigits) {\n var normalizedDegrees = modulo(degrees + 180, 360) - 180;\n var x = Math.abs(3600 * normalizedDegrees);\n var dflPrecision = opt_fractionDigits || 0;\n var precision = Math.pow(10, dflPrecision);\n var deg = Math.floor(x / 3600);\n var min = Math.floor((x - deg * 3600) / 60);\n var sec = x - deg * 3600 - min * 60;\n sec = Math.ceil(sec * precision) / precision;\n\n if (sec >= 60) {\n sec = 0;\n min += 1;\n }\n\n if (min >= 60) {\n min = 0;\n deg += 1;\n }\n\n return deg + "\\xB0 " + padNumber(min, 2) + "\\u2032 " + padNumber(sec, 2, dflPrecision) + "\\u2033" + (normalizedDegrees == 0 ? \'\' : \' \' + hemispheres.charAt(normalizedDegrees < 0 ? 1 : 0));\n}\n/**\n * Transforms the given {@link module:ol/coordinate~Coordinate} to a string\n * using the given string template. The strings `{x}` and `{y}` in the template\n * will be replaced with the first and second coordinate values respectively.\n *\n * Example without specifying the fractional digits:\n *\n * import {format} from \'ol/coordinate\';\n *\n * var coord = [7.85, 47.983333];\n * var template = \'Coordinate is ({x}|{y}).\';\n * var out = format(coord, template);\n * // out is now \'Coordinate is (8|48).\'\n *\n * Example explicitly specifying the fractional digits:\n *\n * import {format} from \'ol/coordinate\';\n *\n * var coord = [7.85, 47.983333];\n * var template = \'Coordinate is ({x}|{y}).\';\n * var out = format(coord, template, 2);\n * // out is now \'Coordinate is (7.85|47.98).\'\n *\n * @param {Coordinate} coordinate Coordinate.\n * @param {string} template A template string with `{x}` and `{y}` placeholders\n * that will be replaced by first and second coordinate values.\n * @param {number=} opt_fractionDigits The number of digits to include\n * after the decimal point. Default is `0`.\n * @return {string} Formatted coordinate.\n * @api\n */\n\nfunction format(coordinate, template, opt_fractionDigits) {\n if (coordinate) {\n return template.replace(\'{x}\', coordinate[0].toFixed(opt_fractionDigits)).replace(\'{y}\', coordinate[1].toFixed(opt_fractionDigits));\n } else {\n return \'\';\n }\n}\n/**\n * @param {Coordinate} coordinate1 First coordinate.\n * @param {Coordinate} coordinate2 Second coordinate.\n * @return {boolean} The two coordinates are equal.\n */\n\nfunction coordinate_equals(coordinate1, coordinate2) {\n var equals = true;\n\n for (var i = coordinate1.length - 1; i >= 0; --i) {\n if (coordinate1[i] != coordinate2[i]) {\n equals = false;\n break;\n }\n }\n\n return equals;\n}\n/**\n * Rotate `coordinate` by `angle`. `coordinate` is modified in place and\n * returned by the function.\n *\n * Example:\n *\n * import {rotate} from \'ol/coordinate\';\n *\n * var coord = [7.85, 47.983333];\n * var rotateRadians = Math.PI / 2; // 90 degrees\n * rotate(coord, rotateRadians);\n * // coord is now [-47.983333, 7.85]\n *\n * @param {Coordinate} coordinate Coordinate.\n * @param {number} angle Angle in radian.\n * @return {Coordinate} Coordinate.\n * @api\n */\n\nfunction coordinate_rotate(coordinate, angle) {\n var cosAngle = Math.cos(angle);\n var sinAngle = Math.sin(angle);\n var x = coordinate[0] * cosAngle - coordinate[1] * sinAngle;\n var y = coordinate[1] * cosAngle + coordinate[0] * sinAngle;\n coordinate[0] = x;\n coordinate[1] = y;\n return coordinate;\n}\n/**\n * Scale `coordinate` by `scale`. `coordinate` is modified in place and returned\n * by the function.\n *\n * Example:\n *\n * import {scale as scaleCoordinate} from \'ol/coordinate\';\n *\n * var coord = [7.85, 47.983333];\n * var scale = 1.2;\n * scaleCoordinate(coord, scale);\n * // coord is now [9.42, 57.5799996]\n *\n * @param {Coordinate} coordinate Coordinate.\n * @param {number} scale Scale factor.\n * @return {Coordinate} Coordinate.\n */\n\nfunction coordinate_scale(coordinate, scale) {\n coordinate[0] *= scale;\n coordinate[1] *= scale;\n return coordinate;\n}\n/**\n * @param {Coordinate} coord1 First coordinate.\n * @param {Coordinate} coord2 Second coordinate.\n * @return {number} Squared distance between coord1 and coord2.\n */\n\nfunction coordinate_squaredDistance(coord1, coord2) {\n var dx = coord1[0] - coord2[0];\n var dy = coord1[1] - coord2[1];\n return dx * dx + dy * dy;\n}\n/**\n * @param {Coordinate} coord1 First coordinate.\n * @param {Coordinate} coord2 Second coordinate.\n * @return {number} Distance between coord1 and coord2.\n */\n\nfunction distance(coord1, coord2) {\n return Math.sqrt(coordinate_squaredDistance(coord1, coord2));\n}\n/**\n * Calculate the squared distance from a coordinate to a line segment.\n *\n * @param {Coordinate} coordinate Coordinate of the point.\n * @param {Array<Coordinate>} segment Line segment (2\n * coordinates).\n * @return {number} Squared distance from the point to the line segment.\n */\n\nfunction squaredDistanceToSegment(coordinate, segment) {\n return coordinate_squaredDistance(coordinate, closestOnSegment(coordinate, segment));\n}\n/**\n * Format a geographic coordinate with the hemisphere, degrees, minutes, and\n * seconds.\n *\n * Example without specifying fractional digits:\n *\n * import {toStringHDMS} from \'ol/coordinate\';\n *\n * var coord = [7.85, 47.983333];\n * var out = toStringHDMS(coord);\n * // out is now \'47° 58′ 60″ N 7° 50′ 60″ E\'\n *\n * Example explicitly specifying 1 fractional digit:\n *\n * import {toStringHDMS} from \'ol/coordinate\';\n *\n * var coord = [7.85, 47.983333];\n * var out = toStringHDMS(coord, 1);\n * // out is now \'47° 58′ 60.0″ N 7° 50′ 60.0″ E\'\n *\n * @param {Coordinate} coordinate Coordinate.\n * @param {number=} opt_fractionDigits The number of digits to include\n * after the decimal point. Default is `0`.\n * @return {string} Hemisphere, degrees, minutes and seconds.\n * @api\n */\n\nfunction toStringHDMS(coordinate, opt_fractionDigits) {\n if (coordinate) {\n return degreesToStringHDMS(\'NS\', coordinate[1], opt_fractionDigits) + \' \' + degreesToStringHDMS(\'EW\', coordinate[0], opt_fractionDigits);\n } else {\n return \'\';\n }\n}\n/**\n * Format a coordinate as a comma delimited string.\n *\n * Example without specifying fractional digits:\n *\n * import {toStringXY} from \'ol/coordinate\';\n *\n * var coord = [7.85, 47.983333];\n * var out = toStringXY(coord);\n * // out is now \'8, 48\'\n *\n * Example explicitly specifying 1 fractional digit:\n *\n * import {toStringXY} from \'ol/coordinate\';\n *\n * var coord = [7.85, 47.983333];\n * var out = toStringXY(coord, 1);\n * // out is now \'7.8, 48.0\'\n *\n * @param {Coordinate} coordinate Coordinate.\n * @param {number=} opt_fractionDigits The number of digits to include\n * after the decimal point. Default is `0`.\n * @return {string} XY.\n * @api\n */\n\nfunction toStringXY(coordinate, opt_fractionDigits) {\n return format(coordinate, \'{x}, {y}\', opt_fractionDigits);\n}\n/**\n * Modifies the provided coordinate in-place to be within the real world\n * extent. The lower projection extent boundary is inclusive, the upper one\n * exclusive.\n *\n * @param {Coordinate} coordinate Coordinate.\n * @param {import("./proj/Projection.js").default} projection Projection.\n * @return {Coordinate} The coordinate within the real world extent.\n */\n\nfunction coordinate_wrapX(coordinate, projection) {\n if (projection.canWrapX()) {\n var worldWidth = extent_getWidth(projection.getExtent());\n var worldsAway = coordinate_getWorldsAway(coordinate, projection, worldWidth);\n\n if (worldsAway) {\n coordinate[0] -= worldsAway * worldWidth;\n }\n }\n\n return coordinate;\n}\n/**\n * @param {Coordinate} coordinate Coordinate.\n * @param {import("./proj/Projection.js").default} projection Projection.\n * @param {number=} opt_sourceExtentWidth Width of the source extent.\n * @return {number} Offset in world widths.\n */\n\nfunction coordinate_getWorldsAway(coordinate, projection, opt_sourceExtentWidth) {\n var projectionExtent = projection.getExtent();\n var worldsAway = 0;\n\n if (projection.canWrapX() && (coordinate[0] < projectionExtent[0] || coordinate[0] > projectionExtent[2])) {\n var sourceExtentWidth = opt_sourceExtentWidth || extent_getWidth(projectionExtent);\n worldsAway = Math.floor((coordinate[0] - projectionExtent[0]) / sourceExtentWidth);\n }\n\n return worldsAway;\n}\n;// CONCATENATED MODULE: ./node_modules/ol/renderer/Map.js\nvar Map_extends = undefined && undefined.__extends || function () {\n var _extendStatics = function extendStatics(d, b) {\n _extendStatics = Object.setPrototypeOf || {\n __proto__: []\n } instanceof Array && function (d, b) {\n d.__proto__ = b;\n } || function (d, b) {\n for (var p in b) {\n if (Object.prototype.hasOwnProperty.call(b, p)) d[p] = b[p];\n }\n };\n\n return _extendStatics(d, b);\n };\n\n return function (d, b) {\n _extendStatics(d, b);\n\n function __() {\n this.constructor = d;\n }\n\n d.prototype = b === null ? Object.create(b) : (__.prototype = b.prototype, new __());\n };\n}();\n/**\n * @module ol/renderer/Map\n */\n\n\n\n\n\n\n\n\n\n\n/**\n * @typedef HitMatch\n * @property {import("../Feature.js").FeatureLike} feature\n * @property {import("../layer/Layer.js").default} layer\n * @property {import("../geom/SimpleGeometry.js").default} geometry\n * @property {number} distanceSq\n * @property {import("./vector.js").FeatureCallback<T>} callback\n * @template T\n */\n\n/**\n * @abstract\n */\n\nvar MapRenderer =\n/** @class */\nfunction (_super) {\n Map_extends(MapRenderer, _super);\n /**\n * @param {import("../PluggableMap.js").default} map Map.\n */\n\n\n function MapRenderer(map) {\n var _this = _super.call(this) || this;\n /**\n * @private\n * @type {import("../PluggableMap.js").default}\n */\n\n\n _this.map_ = map;\n return _this;\n }\n /**\n * @abstract\n * @param {import("../render/EventType.js").default} type Event type.\n * @param {import("../PluggableMap.js").FrameState} frameState Frame state.\n */\n\n\n MapRenderer.prototype.dispatchRenderEvent = function (type, frameState) {\n util_abstract();\n };\n /**\n * @param {import("../PluggableMap.js").FrameState} frameState FrameState.\n * @protected\n */\n\n\n MapRenderer.prototype.calculateMatrices2D = function (frameState) {\n var viewState = frameState.viewState;\n var coordinateToPixelTransform = frameState.coordinateToPixelTransform;\n var pixelToCoordinateTransform = frameState.pixelToCoordinateTransform;\n compose(coordinateToPixelTransform, frameState.size[0] / 2, frameState.size[1] / 2, 1 / viewState.resolution, -1 / viewState.resolution, -viewState.rotation, -viewState.center[0], -viewState.center[1]);\n makeInverse(pixelToCoordinateTransform, coordinateToPixelTransform);\n };\n /**\n * @param {import("../coordinate.js").Coordinate} coordinate Coordinate.\n * @param {import("../PluggableMap.js").FrameState} frameState FrameState.\n * @param {number} hitTolerance Hit tolerance in pixels.\n * @param {boolean} checkWrapped Check for wrapped geometries.\n * @param {import("./vector.js").FeatureCallback<T>} callback Feature callback.\n * @param {S} thisArg Value to use as `this` when executing `callback`.\n * @param {function(this: U, import("../layer/Layer.js").default): boolean} layerFilter Layer filter\n * function, only layers which are visible and for which this function\n * returns `true` will be tested for features. By default, all visible\n * layers will be tested.\n * @param {U} thisArg2 Value to use as `this` when executing `layerFilter`.\n * @return {T|undefined} Callback result.\n * @template S,T,U\n */\n\n\n MapRenderer.prototype.forEachFeatureAtCoordinate = function (coordinate, frameState, hitTolerance, checkWrapped, callback, thisArg, layerFilter, thisArg2) {\n var result;\n var viewState = frameState.viewState;\n /**\n * @param {boolean} managed Managed layer.\n * @param {import("../Feature.js").FeatureLike} feature Feature.\n * @param {import("../layer/Layer.js").default} layer Layer.\n * @param {import("../geom/Geometry.js").default} geometry Geometry.\n * @return {T|undefined} Callback result.\n */\n\n function forEachFeatureAtCoordinate(managed, feature, layer, geometry) {\n return callback.call(thisArg, feature, managed ? layer : null, geometry);\n }\n\n var projection = viewState.projection;\n var translatedCoordinate = coordinate_wrapX(coordinate.slice(), projection);\n var offsets = [[0, 0]];\n\n if (projection.canWrapX() && checkWrapped) {\n var projectionExtent = projection.getExtent();\n var worldWidth = extent_getWidth(projectionExtent);\n offsets.push([-worldWidth, 0], [worldWidth, 0]);\n }\n\n var layerStates = frameState.layerStatesArray;\n var numLayers = layerStates.length;\n var matches =\n /** @type {Array<HitMatch<T>>} */\n [];\n var tmpCoord = [];\n\n for (var i = 0; i < offsets.length; i++) {\n for (var j = numLayers - 1; j >= 0; --j) {\n var layerState = layerStates[j];\n var layer = layerState.layer;\n\n if (layer.hasRenderer() && inView(layerState, viewState) && layerFilter.call(thisArg2, layer)) {\n var layerRenderer = layer.getRenderer();\n var source = layer.getSource();\n\n if (layerRenderer && source) {\n var coordinates = source.getWrapX() ? translatedCoordinate : coordinate;\n var callback_1 = forEachFeatureAtCoordinate.bind(null, layerState.managed);\n tmpCoord[0] = coordinates[0] + offsets[i][0];\n tmpCoord[1] = coordinates[1] + offsets[i][1];\n result = layerRenderer.forEachFeatureAtCoordinate(tmpCoord, frameState, hitTolerance, callback_1, matches);\n }\n\n if (result) {\n return result;\n }\n }\n }\n }\n\n if (matches.length === 0) {\n return undefined;\n }\n\n var order = 1 / matches.length;\n matches.forEach(function (m, i) {\n return m.distanceSq += i * order;\n });\n matches.sort(function (a, b) {\n return a.distanceSq - b.distanceSq;\n });\n matches.some(function (m) {\n return result = m.callback(m.feature, m.layer, m.geometry);\n });\n return result;\n };\n /**\n * @abstract\n * @param {import("../pixel.js").Pixel} pixel Pixel.\n * @param {import("../PluggableMap.js").FrameState} frameState FrameState.\n * @param {number} hitTolerance Hit tolerance in pixels.\n * @param {function(import("../layer/Layer.js").default, (Uint8ClampedArray|Uint8Array)): T} callback Layer\n * callback.\n * @param {function(import("../layer/Layer.js").default): boolean} layerFilter Layer filter\n * function, only layers which are visible and for which this function\n * returns `true` will be tested for features. By default, all visible\n * layers will be tested.\n * @return {T|undefined} Callback result.\n * @template T\n */\n\n\n MapRenderer.prototype.forEachLayerAtPixel = function (pixel, frameState, hitTolerance, callback, layerFilter) {\n return util_abstract();\n };\n /**\n * @param {import("../coordinate.js").Coordinate} coordinate Coordinate.\n * @param {import("../PluggableMap.js").FrameState} frameState FrameState.\n * @param {number} hitTolerance Hit tolerance in pixels.\n * @param {boolean} checkWrapped Check for wrapped geometries.\n * @param {function(this: U, import("../layer/Layer.js").default): boolean} layerFilter Layer filter\n * function, only layers which are visible and for which this function\n * returns `true` will be tested for features. By default, all visible\n * layers will be tested.\n * @param {U} thisArg Value to use as `this` when executing `layerFilter`.\n * @return {boolean} Is there a feature at the given coordinate?\n * @template U\n */\n\n\n MapRenderer.prototype.hasFeatureAtCoordinate = function (coordinate, frameState, hitTolerance, checkWrapped, layerFilter, thisArg) {\n var hasFeature = this.forEachFeatureAtCoordinate(coordinate, frameState, hitTolerance, checkWrapped, TRUE, this, layerFilter, thisArg);\n return hasFeature !== undefined;\n };\n /**\n * @return {import("../PluggableMap.js").default} Map.\n */\n\n\n MapRenderer.prototype.getMap = function () {\n return this.map_;\n };\n /**\n * Render.\n * @abstract\n * @param {?import("../PluggableMap.js").FrameState} frameState Frame state.\n */\n\n\n MapRenderer.prototype.renderFrame = function (frameState) {\n util_abstract();\n };\n /**\n * @param {import("../PluggableMap.js").FrameState} frameState Frame state.\n * @protected\n */\n\n\n MapRenderer.prototype.scheduleExpireIconCache = function (frameState) {\n if (shared.canExpireCache()) {\n frameState.postRenderFunctions.push(expireIconCache);\n }\n };\n\n return MapRenderer;\n}(ol_Disposable);\n/**\n * @param {import("../PluggableMap.js").default} map Map.\n * @param {import("../PluggableMap.js").FrameState} frameState Frame state.\n */\n\n\nfunction expireIconCache(map, frameState) {\n shared.expire();\n}\n\n/* harmony default export */ var Map = (MapRenderer);\n;// CONCATENATED MODULE: ./node_modules/ol/render/Event.js\n/**\n * @module ol/render/Event\n */\nvar Event_extends = undefined && undefined.__extends || function () {\n var _extendStatics = function extendStatics(d, b) {\n _extendStatics = Object.setPrototypeOf || {\n __proto__: []\n } instanceof Array && function (d, b) {\n d.__proto__ = b;\n } || function (d, b) {\n for (var p in b) {\n if (Object.prototype.hasOwnProperty.call(b, p)) d[p] = b[p];\n }\n };\n\n return _extendStatics(d, b);\n };\n\n return function (d, b) {\n _extendStatics(d, b);\n\n function __() {\n this.constructor = d;\n }\n\n d.prototype = b === null ? Object.create(b) : (__.prototype = b.prototype, new __());\n };\n}();\n\n\n\nvar RenderEvent =\n/** @class */\nfunction (_super) {\n Event_extends(RenderEvent, _super);\n /**\n * @param {import("./EventType.js").default} type Type.\n * @param {import("../transform.js").Transform=} opt_inversePixelTransform Transform for\n * CSS pixels to rendered pixels.\n * @param {import("../PluggableMap.js").FrameState=} opt_frameState Frame state.\n * @param {?CanvasRenderingContext2D=} opt_context Context.\n */\n\n\n function RenderEvent(type, opt_inversePixelTransform, opt_frameState, opt_context) {\n var _this = _super.call(this, type) || this;\n /**\n * Transform from CSS pixels (relative to the top-left corner of the map viewport)\n * to rendered pixels on this event\'s `context`. Only available when a Canvas renderer is used, null otherwise.\n * @type {import("../transform.js").Transform|undefined}\n * @api\n */\n\n\n _this.inversePixelTransform = opt_inversePixelTransform;\n /**\n * An object representing the current render frame state.\n * @type {import("../PluggableMap.js").FrameState|undefined}\n * @api\n */\n\n _this.frameState = opt_frameState;\n /**\n * Canvas context. Not available when the event is dispatched by the map. Only available\n * when a Canvas renderer is used, null otherwise.\n * @type {CanvasRenderingContext2D|null|undefined}\n * @api\n */\n\n _this.context = opt_context;\n return _this;\n }\n\n return RenderEvent;\n}(Event);\n\n/* harmony default export */ var render_Event = (RenderEvent);\n;// CONCATENATED MODULE: ./node_modules/ol/css.js\n/**\n * @module ol/css\n */\n\n/**\n * @typedef {Object} FontParameters\n * @property {string} style\n * @property {string} variant\n * @property {string} weight\n * @property {string} size\n * @property {string} lineHeight\n * @property {string} family\n * @property {Array<string>} families\n */\n\n/**\n * The CSS class for hidden feature.\n *\n * @const\n * @type {string}\n */\nvar CLASS_HIDDEN = \'ol-hidden\';\n/**\n * The CSS class that we\'ll give the DOM elements to have them selectable.\n *\n * @const\n * @type {string}\n */\n\nvar CLASS_SELECTABLE = \'ol-selectable\';\n/**\n * The CSS class that we\'ll give the DOM elements to have them unselectable.\n *\n * @const\n * @type {string}\n */\n\nvar CLASS_UNSELECTABLE = \'ol-unselectable\';\n/**\n * The CSS class for unsupported feature.\n *\n * @const\n * @type {string}\n */\n\nvar CLASS_UNSUPPORTED = \'ol-unsupported\';\n/**\n * The CSS class for controls.\n *\n * @const\n * @type {string}\n */\n\nvar CLASS_CONTROL = \'ol-control\';\n/**\n * The CSS class that we\'ll give the DOM elements that are collapsed, i.e.\n * to those elements which usually can be expanded.\n *\n * @const\n * @type {string}\n */\n\nvar CLASS_COLLAPSED = \'ol-collapsed\';\n/**\n * From http://stackoverflow.com/questions/10135697/regex-to-parse-any-css-font\n * @type {RegExp}\n */\n\nvar fontRegEx = new RegExp([\'^\\\\s*(?=(?:(?:[-a-z]+\\\\s*){0,2}(italic|oblique))?)\', \'(?=(?:(?:[-a-z]+\\\\s*){0,2}(small-caps))?)\', \'(?=(?:(?:[-a-z]+\\\\s*){0,2}(bold(?:er)?|lighter|[1-9]00 ))?)\', \'(?:(?:normal|\\\\1|\\\\2|\\\\3)\\\\s*){0,3}((?:xx?-)?\', \'(?:small|large)|medium|smaller|larger|[\\\\.\\\\d]+(?:\\\\%|in|[cem]m|ex|p[ctx]))\', \'(?:\\\\s*\\\\/\\\\s*(normal|[\\\\.\\\\d]+(?:\\\\%|in|[cem]m|ex|p[ctx])?))\', \'?\\\\s*([-,\\\\"\\\\\\\'\\\\sa-z]+?)\\\\s*$\'].join(\'\'), \'i\');\nvar fontRegExMatchIndex = [\'style\', \'variant\', \'weight\', \'size\', \'lineHeight\', \'family\'];\n/**\n * Get the list of font families from a font spec. Note that this doesn\'t work\n * for font families that have commas in them.\n * @param {string} fontSpec The CSS font property.\n * @return {FontParameters} The font parameters (or null if the input spec is invalid).\n */\n\nvar getFontParameters = function getFontParameters(fontSpec) {\n var match = fontSpec.match(fontRegEx);\n\n if (!match) {\n return null;\n }\n\n var style =\n /** @type {FontParameters} */\n {\n lineHeight: \'normal\',\n size: \'1.2em\',\n style: \'normal\',\n weight: \'normal\',\n variant: \'normal\'\n };\n\n for (var i = 0, ii = fontRegExMatchIndex.length; i < ii; ++i) {\n var value = match[i + 1];\n\n if (value !== undefined) {\n style[fontRegExMatchIndex[i]] = value;\n }\n }\n\n style.families = style.family.split(/,\\s?/);\n return style;\n};\n;// CONCATENATED MODULE: ./node_modules/ol/has.js\n/**\n * @module ol/has\n */\nvar ua = typeof navigator !== \'undefined\' && typeof navigator.userAgent !== \'undefined\' ? navigator.userAgent.toLowerCase() : \'\';\n/**\n * User agent string says we are dealing with Firefox as browser.\n * @type {boolean}\n */\n\nvar FIREFOX = ua.indexOf(\'firefox\') !== -1;\n/**\n * User agent string says we are dealing with Safari as browser.\n * @type {boolean}\n */\n\nvar SAFARI = ua.indexOf(\'safari\') !== -1 && ua.indexOf(\'chrom\') == -1;\n/**\n * User agent string says we are dealing with a WebKit engine.\n * @type {boolean}\n */\n\nvar WEBKIT = ua.indexOf(\'webkit\') !== -1 && ua.indexOf(\'edge\') == -1;\n/**\n * User agent string says we are dealing with a Mac as platform.\n * @type {boolean}\n */\n\nvar has_MAC = ua.indexOf(\'macintosh\') !== -1;\n/**\n * The ratio between physical pixels and device-independent pixels\n * (dips) on the device (`window.devicePixelRatio`).\n * @const\n * @type {number}\n * @api\n */\n\nvar DEVICE_PIXEL_RATIO = typeof devicePixelRatio !== \'undefined\' ? devicePixelRatio : 1;\n/**\n * The execution context is a worker with OffscreenCanvas available.\n * @const\n * @type {boolean}\n */\n\nvar WORKER_OFFSCREEN_CANVAS = typeof WorkerGlobalScope !== \'undefined\' && typeof OffscreenCanvas !== \'undefined\' && self instanceof WorkerGlobalScope; //eslint-disable-line\n\n/**\n * Image.prototype.decode() is supported.\n * @type {boolean}\n */\n\nvar IMAGE_DECODE = typeof Image !== \'undefined\' && Image.prototype.decode;\n/**\n * @type {boolean}\n */\n\nvar PASSIVE_EVENT_LISTENERS = function () {\n var passive = false;\n\n try {\n var options = Object.defineProperty({}, \'passive\', {\n get: function get() {\n passive = true;\n }\n });\n window.addEventListener(\'_\', null, options);\n window.removeEventListener(\'_\', null, options);\n } catch (error) {// passive not supported\n }\n\n return passive;\n}();\n;// CONCATENATED MODULE: ./node_modules/ol/dom.js\n\n/**\n * @module ol/dom\n */\n//FIXME Move this function to the canvas module\n\n/**\n * Create an html canvas element and returns its 2d context.\n * @param {number=} opt_width Canvas width.\n * @param {number=} opt_height Canvas height.\n * @param {Array<HTMLCanvasElement>=} opt_canvasPool Canvas pool to take existing canvas from.\n * @return {CanvasRenderingContext2D} The context.\n */\n\nfunction createCanvasContext2D(opt_width, opt_height, opt_canvasPool) {\n var canvas = opt_canvasPool && opt_canvasPool.length ? opt_canvasPool.shift() : WORKER_OFFSCREEN_CANVAS ? new OffscreenCanvas(opt_width || 300, opt_height || 300) : document.createElement(\'canvas\');\n\n if (opt_width) {\n canvas.width = opt_width;\n }\n\n if (opt_height) {\n canvas.height = opt_height;\n } //FIXME Allow OffscreenCanvasRenderingContext2D as return type\n\n\n return (\n /** @type {CanvasRenderingContext2D} */\n canvas.getContext(\'2d\')\n );\n}\n/**\n * Get the current computed width for the given element including margin,\n * padding and border.\n * Equivalent to jQuery\'s `$(el).outerWidth(true)`.\n * @param {!HTMLElement} element Element.\n * @return {number} The width.\n */\n\nfunction dom_outerWidth(element) {\n var width = element.offsetWidth;\n var style = getComputedStyle(element);\n width += parseInt(style.marginLeft, 10) + parseInt(style.marginRight, 10);\n return width;\n}\n/**\n * Get the current computed height for the given element including margin,\n * padding and border.\n * Equivalent to jQuery\'s `$(el).outerHeight(true)`.\n * @param {!HTMLElement} element Element.\n * @return {number} The height.\n */\n\nfunction dom_outerHeight(element) {\n var height = element.offsetHeight;\n var style = getComputedStyle(element);\n height += parseInt(style.marginTop, 10) + parseInt(style.marginBottom, 10);\n return height;\n}\n/**\n * @param {Node} newNode Node to replace old node\n * @param {Node} oldNode The node to be replaced\n */\n\nfunction replaceNode(newNode, oldNode) {\n var parent = oldNode.parentNode;\n\n if (parent) {\n parent.replaceChild(newNode, oldNode);\n }\n}\n/**\n * @param {Node} node The node to remove.\n * @returns {Node} The node that was removed or null.\n */\n\nfunction removeNode(node) {\n return node && node.parentNode ? node.parentNode.removeChild(node) : null;\n}\n/**\n * @param {Node} node The node to remove the children from.\n */\n\nfunction removeChildren(node) {\n while (node.lastChild) {\n node.removeChild(node.lastChild);\n }\n}\n/**\n * Transform the children of a parent node so they match the\n * provided list of children. This function aims to efficiently\n * remove, add, and reorder child nodes while maintaining a simple\n * implementation (it is not guaranteed to minimize DOM operations).\n * @param {Node} node The parent node whose children need reworking.\n * @param {Array<Node>} children The desired children.\n */\n\nfunction replaceChildren(node, children) {\n var oldChildren = node.childNodes;\n\n for (var i = 0; true; ++i) {\n var oldChild = oldChildren[i];\n var newChild = children[i]; // check if our work is done\n\n if (!oldChild && !newChild) {\n break;\n } // check if children match\n\n\n if (oldChild === newChild) {\n continue;\n } // check if a new child needs to be added\n\n\n if (!oldChild) {\n node.appendChild(newChild);\n continue;\n } // check if an old child needs to be removed\n\n\n if (!newChild) {\n node.removeChild(oldChild);\n --i;\n continue;\n } // reorder\n\n\n node.insertBefore(newChild, oldChild);\n }\n}\n;// CONCATENATED MODULE: ./node_modules/ol/render/canvas.js\n/**\n * @module ol/render/canvas\n */\n\n\n\n\n\n\n\n/**\n * @typedef {Object} FillState\n * @property {import("../colorlike.js").ColorLike} fillStyle\n */\n\n/**\n * @typedef Label\n * @property {number} width\n * @property {number} height\n * @property {Array<string|number>} contextInstructions\n */\n\n/**\n * @typedef {Object} FillStrokeState\n * @property {import("../colorlike.js").ColorLike} [currentFillStyle]\n * @property {import("../colorlike.js").ColorLike} [currentStrokeStyle]\n * @property {CanvasLineCap} [currentLineCap]\n * @property {Array<number>} currentLineDash\n * @property {number} [currentLineDashOffset]\n * @property {CanvasLineJoin} [currentLineJoin]\n * @property {number} [currentLineWidth]\n * @property {number} [currentMiterLimit]\n * @property {number} [lastStroke]\n * @property {import("../colorlike.js").ColorLike} [fillStyle]\n * @property {import("../colorlike.js").ColorLike} [strokeStyle]\n * @property {CanvasLineCap} [lineCap]\n * @property {Array<number>} lineDash\n * @property {number} [lineDashOffset]\n * @property {CanvasLineJoin} [lineJoin]\n * @property {number} [lineWidth]\n * @property {number} [miterLimit]\n */\n\n/**\n * @typedef {Object} StrokeState\n * @property {CanvasLineCap} lineCap\n * @property {Array<number>} lineDash\n * @property {number} lineDashOffset\n * @property {CanvasLineJoin} lineJoin\n * @property {number} lineWidth\n * @property {number} miterLimit\n * @property {import("../colorlike.js").ColorLike} strokeStyle\n */\n\n/**\n * @typedef {Object} TextState\n * @property {string} font\n * @property {string} [textAlign]\n * @property {string} textBaseline\n * @property {string} [placement]\n * @property {number} [maxAngle]\n * @property {boolean} [overflow]\n * @property {import("../style/Fill.js").default} [backgroundFill]\n * @property {import("../style/Stroke.js").default} [backgroundStroke]\n * @property {import("../size.js").Size} [scale]\n * @property {Array<number>} [padding]\n */\n\n/**\n * @typedef {Object} SerializableInstructions\n * @property {Array<*>} instructions The rendering instructions.\n * @property {Array<*>} hitDetectionInstructions The rendering hit detection instructions.\n * @property {Array<number>} coordinates The array of all coordinates.\n * @property {!Object<string, TextState>} [textStates] The text states (decluttering).\n * @property {!Object<string, FillState>} [fillStates] The fill states (decluttering).\n * @property {!Object<string, StrokeState>} [strokeStates] The stroke states (decluttering).\n */\n\n/**\n * @typedef {Object<number, import("./canvas/Executor.js").ReplayImageOrLabelArgs>} DeclutterImageWithText\n */\n\n/**\n * @const\n * @type {string}\n */\n\nvar defaultFont = \'10px sans-serif\';\n/**\n * @const\n * @type {import("../colorlike.js").ColorLike}\n */\n\nvar defaultFillStyle = \'#000\';\n/**\n * @const\n * @type {CanvasLineCap}\n */\n\nvar defaultLineCap = \'round\';\n/**\n * @const\n * @type {Array<number>}\n */\n\nvar defaultLineDash = [];\n/**\n * @const\n * @type {number}\n */\n\nvar defaultLineDashOffset = 0;\n/**\n * @const\n * @type {CanvasLineJoin}\n */\n\nvar defaultLineJoin = \'round\';\n/**\n * @const\n * @type {number}\n */\n\nvar defaultMiterLimit = 10;\n/**\n * @const\n * @type {import("../colorlike.js").ColorLike}\n */\n\nvar defaultStrokeStyle = \'#000\';\n/**\n * @const\n * @type {string}\n */\n\nvar defaultTextAlign = \'center\';\n/**\n * @const\n * @type {string}\n */\n\nvar defaultTextBaseline = \'middle\';\n/**\n * @const\n * @type {Array<number>}\n */\n\nvar defaultPadding = [0, 0, 0, 0];\n/**\n * @const\n * @type {number}\n */\n\nvar defaultLineWidth = 1;\n/**\n * @type {BaseObject}\n */\n\nvar checkedFonts = new ol_Object();\n/**\n * The label cache for text rendering. To change the default cache size of 2048\n * entries, use {@link module:ol/structs/LRUCache#setSize}.\n * Deprecated - there is no label cache any more.\n * @type {?}\n * @api\n * @deprecated\n */\n\nvar labelCache = new events_Target();\n\nlabelCache.setSize = function () {\n console.warn(\'labelCache is deprecated.\'); //eslint-disable-line\n};\n/**\n * @type {CanvasRenderingContext2D}\n */\n\n\nvar measureContext = null;\n/**\n * @type {string}\n */\n\nvar measureFont;\n/**\n * @type {!Object<string, number>}\n */\n\nvar textHeights = {};\n/**\n * Clears the label cache when a font becomes available.\n * @param {string} fontSpec CSS font spec.\n */\n\nvar registerFont = function () {\n var retries = 100;\n var size = \'32px \';\n var referenceFonts = [\'monospace\', \'serif\'];\n var len = referenceFonts.length;\n var text = "wmytzilWMYTZIL@#/&?$%10\\uF013";\n var interval, referenceWidth;\n /**\n * @param {string} fontStyle Css font-style\n * @param {string} fontWeight Css font-weight\n * @param {*} fontFamily Css font-family\n * @return {boolean} Font with style and weight is available\n */\n\n function isAvailable(fontStyle, fontWeight, fontFamily) {\n var available = true;\n\n for (var i = 0; i < len; ++i) {\n var referenceFont = referenceFonts[i];\n referenceWidth = measureTextWidth(fontStyle + \' \' + fontWeight + \' \' + size + referenceFont, text);\n\n if (fontFamily != referenceFont) {\n var width = measureTextWidth(fontStyle + \' \' + fontWeight + \' \' + size + fontFamily + \',\' + referenceFont, text); // If width and referenceWidth are the same, then the fallback was used\n // instead of the font we wanted, so the font is not available.\n\n available = available && width != referenceWidth;\n }\n }\n\n if (available) {\n return true;\n }\n\n return false;\n }\n\n function check() {\n var done = true;\n var fonts = checkedFonts.getKeys();\n\n for (var i = 0, ii = fonts.length; i < ii; ++i) {\n var font = fonts[i];\n\n if (checkedFonts.get(font) < retries) {\n if (isAvailable.apply(this, font.split(\'\\n\'))) {\n clear(textHeights); // Make sure that loaded fonts are picked up by Safari\n\n measureContext = null;\n measureFont = undefined;\n checkedFonts.set(font, retries);\n } else {\n checkedFonts.set(font, checkedFonts.get(font) + 1, true);\n done = false;\n }\n }\n }\n\n if (done) {\n clearInterval(interval);\n interval = undefined;\n }\n }\n\n return function (fontSpec) {\n var font = getFontParameters(fontSpec);\n\n if (!font) {\n return;\n }\n\n var families = font.families;\n\n for (var i = 0, ii = families.length; i < ii; ++i) {\n var family = families[i];\n var key = font.style + \'\\n\' + font.weight + \'\\n\' + family;\n\n if (checkedFonts.get(key) === undefined) {\n checkedFonts.set(key, retries, true);\n\n if (!isAvailable(font.style, font.weight, family)) {\n checkedFonts.set(key, 0, true);\n\n if (interval === undefined) {\n interval = setInterval(check, 32);\n }\n }\n }\n }\n };\n}();\n/**\n * @param {string} font Font to use for measuring.\n * @return {import("../size.js").Size} Measurement.\n */\n\nvar measureTextHeight = function () {\n /**\n * @type {HTMLDivElement}\n */\n var div;\n return function (fontSpec) {\n var height = textHeights[fontSpec];\n\n if (height == undefined) {\n if (WORKER_OFFSCREEN_CANVAS) {\n var font = getFontParameters(fontSpec);\n var metrics = measureText(fontSpec, \'Žg\');\n var lineHeight = isNaN(Number(font.lineHeight)) ? 1.2 : Number(font.lineHeight);\n height = lineHeight * (metrics.actualBoundingBoxAscent + metrics.actualBoundingBoxDescent);\n } else {\n if (!div) {\n div = document.createElement(\'div\');\n div.innerHTML = \'M\';\n div.style.margin = \'0 !important\';\n div.style.padding = \'0 !important\';\n div.style.position = \'absolute !important\';\n div.style.left = \'-99999px !important\';\n }\n\n div.style.font = fontSpec;\n document.body.appendChild(div);\n height = div.offsetHeight;\n document.body.removeChild(div);\n }\n\n textHeights[fontSpec] = height;\n }\n\n return height;\n };\n}();\n/**\n * @param {string} font Font.\n * @param {string} text Text.\n * @return {TextMetrics} Text metrics.\n */\n\nfunction measureText(font, text) {\n if (!measureContext) {\n measureContext = createCanvasContext2D(1, 1);\n }\n\n if (font != measureFont) {\n measureContext.font = font;\n measureFont = measureContext.font;\n }\n\n return measureContext.measureText(text);\n}\n/**\n * @param {string} font Font.\n * @param {string} text Text.\n * @return {number} Width.\n */\n\n\nfunction measureTextWidth(font, text) {\n return measureText(font, text).width;\n}\n/**\n * Measure text width using a cache.\n * @param {string} font The font.\n * @param {string} text The text to measure.\n * @param {Object<string, number>} cache A lookup of cached widths by text.\n * @returns {number} The text width.\n */\n\nfunction measureAndCacheTextWidth(font, text, cache) {\n if (text in cache) {\n return cache[text];\n }\n\n var width = measureTextWidth(font, text);\n cache[text] = width;\n return width;\n}\n/**\n * @param {string} font Font to use for measuring.\n * @param {Array<string>} lines Lines to measure.\n * @param {Array<number>} widths Array will be populated with the widths of\n * each line.\n * @return {number} Width of the whole text.\n */\n\nfunction measureTextWidths(font, lines, widths) {\n var numLines = lines.length;\n var width = 0;\n\n for (var i = 0; i < numLines; ++i) {\n var currentWidth = measureTextWidth(font, lines[i]);\n width = Math.max(width, currentWidth);\n widths.push(currentWidth);\n }\n\n return width;\n}\n/**\n * @param {CanvasRenderingContext2D} context Context.\n * @param {number} rotation Rotation.\n * @param {number} offsetX X offset.\n * @param {number} offsetY Y offset.\n */\n\nfunction rotateAtOffset(context, rotation, offsetX, offsetY) {\n if (rotation !== 0) {\n context.translate(offsetX, offsetY);\n context.rotate(rotation);\n context.translate(-offsetX, -offsetY);\n }\n}\n/**\n * @param {CanvasRenderingContext2D} context Context.\n * @param {import("../transform.js").Transform|null} transform Transform.\n * @param {number} opacity Opacity.\n * @param {Label|HTMLCanvasElement|HTMLImageElement|HTMLVideoElement} labelOrImage Label.\n * @param {number} originX Origin X.\n * @param {number} originY Origin Y.\n * @param {number} w Width.\n * @param {number} h Height.\n * @param {number} x X.\n * @param {number} y Y.\n * @param {import("../size.js").Size} scale Scale.\n */\n\nfunction drawImageOrLabel(context, transform, opacity, labelOrImage, originX, originY, w, h, x, y, scale) {\n context.save();\n\n if (opacity !== 1) {\n context.globalAlpha *= opacity;\n }\n\n if (transform) {\n context.setTransform.apply(context, transform);\n }\n\n if (\n /** @type {*} */\n labelOrImage.contextInstructions) {\n // label\n context.translate(x, y);\n context.scale(scale[0], scale[1]);\n executeLabelInstructions(\n /** @type {Label} */\n labelOrImage, context);\n } else if (scale[0] < 0 || scale[1] < 0) {\n // flipped image\n context.translate(x, y);\n context.scale(scale[0], scale[1]);\n context.drawImage(\n /** @type {HTMLCanvasElement|HTMLImageElement|HTMLVideoElement} */\n labelOrImage, originX, originY, w, h, 0, 0, w, h);\n } else {\n // if image not flipped translate and scale can be avoided\n context.drawImage(\n /** @type {HTMLCanvasElement|HTMLImageElement|HTMLVideoElement} */\n labelOrImage, originX, originY, w, h, x, y, w * scale[0], h * scale[1]);\n }\n\n context.restore();\n}\n/**\n * @param {Label} label Label.\n * @param {CanvasRenderingContext2D} context Context.\n */\n\nfunction executeLabelInstructions(label, context) {\n var contextInstructions = label.contextInstructions;\n\n for (var i = 0, ii = contextInstructions.length; i < ii; i += 2) {\n if (Array.isArray(contextInstructions[i + 1])) {\n context[contextInstructions[i]].apply(context, contextInstructions[i + 1]);\n } else {\n context[contextInstructions[i]] = contextInstructions[i + 1];\n }\n }\n}\n/**\n * @type {HTMLCanvasElement}\n * @private\n */\n\n\nvar createTransformStringCanvas = null;\n/**\n * @param {import("../transform.js").Transform} transform Transform.\n * @return {string} CSS transform.\n */\n\nfunction createTransformString(transform) {\n if (WORKER_OFFSCREEN_CANVAS) {\n return transform_toString(transform);\n } else {\n if (!createTransformStringCanvas) {\n createTransformStringCanvas = createCanvasContext2D(1, 1).canvas;\n }\n\n createTransformStringCanvas.style.transform = transform_toString(transform);\n return createTransformStringCanvas.style.transform;\n }\n}\n;// CONCATENATED MODULE: ./node_modules/ol/renderer/Composite.js\nvar Composite_extends = undefined && undefined.__extends || function () {\n var _extendStatics = function extendStatics(d, b) {\n _extendStatics = Object.setPrototypeOf || {\n __proto__: []\n } instanceof Array && function (d, b) {\n d.__proto__ = b;\n } || function (d, b) {\n for (var p in b) {\n if (Object.prototype.hasOwnProperty.call(b, p)) d[p] = b[p];\n }\n };\n\n return _extendStatics(d, b);\n };\n\n return function (d, b) {\n _extendStatics(d, b);\n\n function __() {\n this.constructor = d;\n }\n\n d.prototype = b === null ? Object.create(b) : (__.prototype = b.prototype, new __());\n };\n}();\n/**\n * @module ol/renderer/Composite\n */\n\n\n\n\n\n\n\n\n\n\n\n\n/**\n * @classdesc\n * Canvas map renderer.\n * @api\n */\n\nvar CompositeMapRenderer =\n/** @class */\nfunction (_super) {\n Composite_extends(CompositeMapRenderer, _super);\n /**\n * @param {import("../PluggableMap.js").default} map Map.\n */\n\n\n function CompositeMapRenderer(map) {\n var _this = _super.call(this, map) || this;\n /**\n * @type {import("../events.js").EventsKey}\n */\n\n\n _this.fontChangeListenerKey_ = listen(checkedFonts, ObjectEventType.PROPERTYCHANGE, map.redrawText.bind(map));\n /**\n * @private\n * @type {HTMLDivElement}\n */\n\n _this.element_ = document.createElement(\'div\');\n var style = _this.element_.style;\n style.position = \'absolute\';\n style.width = \'100%\';\n style.height = \'100%\';\n style.zIndex = \'0\';\n _this.element_.className = CLASS_UNSELECTABLE + \' ol-layers\';\n var container = map.getViewport();\n container.insertBefore(_this.element_, container.firstChild || null);\n /**\n * @private\n * @type {Array<HTMLElement>}\n */\n\n _this.children_ = [];\n /**\n * @private\n * @type {boolean}\n */\n\n _this.renderedVisible_ = true;\n return _this;\n }\n /**\n * @param {import("../render/EventType.js").default} type Event type.\n * @param {import("../PluggableMap.js").FrameState} frameState Frame state.\n */\n\n\n CompositeMapRenderer.prototype.dispatchRenderEvent = function (type, frameState) {\n var map = this.getMap();\n\n if (map.hasListener(type)) {\n var event_1 = new render_Event(type, undefined, frameState);\n map.dispatchEvent(event_1);\n }\n };\n\n CompositeMapRenderer.prototype.disposeInternal = function () {\n unlistenByKey(this.fontChangeListenerKey_);\n this.element_.parentNode.removeChild(this.element_);\n\n _super.prototype.disposeInternal.call(this);\n };\n /**\n * Render.\n * @param {?import("../PluggableMap.js").FrameState} frameState Frame state.\n */\n\n\n CompositeMapRenderer.prototype.renderFrame = function (frameState) {\n if (!frameState) {\n if (this.renderedVisible_) {\n this.element_.style.display = \'none\';\n this.renderedVisible_ = false;\n }\n\n return;\n }\n\n this.calculateMatrices2D(frameState);\n this.dispatchRenderEvent(render_EventType.PRECOMPOSE, frameState);\n var layerStatesArray = frameState.layerStatesArray.sort(function (a, b) {\n return a.zIndex - b.zIndex;\n });\n var viewState = frameState.viewState;\n this.children_.length = 0;\n /**\n * @type {Array<import("../layer/BaseVector.js").default>}\n */\n\n var declutterLayers = [];\n var previousElement = null;\n\n for (var i = 0, ii = layerStatesArray.length; i < ii; ++i) {\n var layerState = layerStatesArray[i];\n frameState.layerIndex = i;\n\n if (!inView(layerState, viewState) || layerState.sourceState != State.READY && layerState.sourceState != State.UNDEFINED) {\n continue;\n }\n\n var layer = layerState.layer;\n var element = layer.render(frameState, previousElement);\n\n if (!element) {\n continue;\n }\n\n if (element !== previousElement) {\n this.children_.push(element);\n previousElement = element;\n }\n\n if (\'getDeclutter\' in layer) {\n declutterLayers.push(layer);\n }\n }\n\n for (var i = declutterLayers.length - 1; i >= 0; --i) {\n declutterLayers[i].renderDeclutter(frameState);\n }\n\n replaceChildren(this.element_, this.children_);\n this.dispatchRenderEvent(render_EventType.POSTCOMPOSE, frameState);\n\n if (!this.renderedVisible_) {\n this.element_.style.display = \'\';\n this.renderedVisible_ = true;\n }\n\n this.scheduleExpireIconCache(frameState);\n };\n /**\n * @param {import("../pixel.js").Pixel} pixel Pixel.\n * @param {import("../PluggableMap.js").FrameState} frameState FrameState.\n * @param {number} hitTolerance Hit tolerance in pixels.\n * @param {function(import("../layer/Layer.js").default, (Uint8ClampedArray|Uint8Array)): T} callback Layer\n * callback.\n * @param {function(import("../layer/Layer.js").default): boolean} layerFilter Layer filter\n * function, only layers which are visible and for which this function\n * returns `true` will be tested for features. By default, all visible\n * layers will be tested.\n * @return {T|undefined} Callback result.\n * @template T\n */\n\n\n CompositeMapRenderer.prototype.forEachLayerAtPixel = function (pixel, frameState, hitTolerance, callback, layerFilter) {\n var viewState = frameState.viewState;\n var layerStates = frameState.layerStatesArray;\n var numLayers = layerStates.length;\n\n for (var i = numLayers - 1; i >= 0; --i) {\n var layerState = layerStates[i];\n var layer = layerState.layer;\n\n if (layer.hasRenderer() && inView(layerState, viewState) && layerFilter(layer)) {\n var layerRenderer = layer.getRenderer();\n var data = layerRenderer.getDataAtPixel(pixel, frameState, hitTolerance);\n\n if (data) {\n var result = callback(layer, data);\n\n if (result) {\n return result;\n }\n }\n }\n }\n\n return undefined;\n };\n\n return CompositeMapRenderer;\n}(Map);\n\n/* harmony default export */ var Composite = (CompositeMapRenderer);\n;// CONCATENATED MODULE: ./node_modules/ol/CollectionEventType.js\n/**\n * @module ol/CollectionEventType\n */\n\n/**\n * @enum {string}\n */\n/* harmony default export */ var CollectionEventType = ({\n /**\n * Triggered when an item is added to the collection.\n * @event module:ol/Collection.CollectionEvent#add\n * @api\n */\n ADD: \'add\',\n\n /**\n * Triggered when an item is removed from the collection.\n * @event module:ol/Collection.CollectionEvent#remove\n * @api\n */\n REMOVE: \'remove\'\n});\n;// CONCATENATED MODULE: ./node_modules/ol/Collection.js\nvar Collection_extends = undefined && undefined.__extends || function () {\n var _extendStatics = function extendStatics(d, b) {\n _extendStatics = Object.setPrototypeOf || {\n __proto__: []\n } instanceof Array && function (d, b) {\n d.__proto__ = b;\n } || function (d, b) {\n for (var p in b) {\n if (Object.prototype.hasOwnProperty.call(b, p)) d[p] = b[p];\n }\n };\n\n return _extendStatics(d, b);\n };\n\n return function (d, b) {\n _extendStatics(d, b);\n\n function __() {\n this.constructor = d;\n }\n\n d.prototype = b === null ? Object.create(b) : (__.prototype = b.prototype, new __());\n };\n}();\n/**\n * @module ol/Collection\n */\n\n\n\n\n\n\n/**\n * @enum {string}\n * @private\n */\n\nvar Collection_Property = {\n LENGTH: \'length\'\n};\n/**\n * @classdesc\n * Events emitted by {@link module:ol/Collection~Collection} instances are instances of this\n * type.\n */\n\nvar CollectionEvent =\n/** @class */\nfunction (_super) {\n Collection_extends(CollectionEvent, _super);\n /**\n * @param {import("./CollectionEventType.js").default} type Type.\n * @param {*=} opt_element Element.\n * @param {number=} opt_index The index of the added or removed element.\n */\n\n\n function CollectionEvent(type, opt_element, opt_index) {\n var _this = _super.call(this, type) || this;\n /**\n * The element that is added to or removed from the collection.\n * @type {*}\n * @api\n */\n\n\n _this.element = opt_element;\n /**\n * The index of the added or removed element.\n * @type {number}\n * @api\n */\n\n _this.index = opt_index;\n return _this;\n }\n\n return CollectionEvent;\n}(Event);\n\n\n/**\n * @typedef {Object} Options\n * @property {boolean} [unique=false] Disallow the same item from being added to\n * the collection twice.\n */\n\n/**\n * @classdesc\n * An expanded version of standard JS Array, adding convenience methods for\n * manipulation. Add and remove changes to the Collection trigger a Collection\n * event. Note that this does not cover changes to the objects _within_ the\n * Collection; they trigger events on the appropriate object, not on the\n * Collection as a whole.\n *\n * @fires CollectionEvent\n *\n * @template T\n * @api\n */\n\nvar Collection =\n/** @class */\nfunction (_super) {\n Collection_extends(Collection, _super);\n /**\n * @param {Array<T>=} opt_array Array.\n * @param {Options=} opt_options Collection options.\n */\n\n\n function Collection(opt_array, opt_options) {\n var _this = _super.call(this) || this;\n\n var options = opt_options || {};\n /**\n * @private\n * @type {boolean}\n */\n\n _this.unique_ = !!options.unique;\n /**\n * @private\n * @type {!Array<T>}\n */\n\n _this.array_ = opt_array ? opt_array : [];\n\n if (_this.unique_) {\n for (var i = 0, ii = _this.array_.length; i < ii; ++i) {\n _this.assertUnique_(_this.array_[i], i);\n }\n }\n\n _this.updateLength_();\n\n return _this;\n }\n /**\n * Remove all elements from the collection.\n * @api\n */\n\n\n Collection.prototype.clear = function () {\n while (this.getLength() > 0) {\n this.pop();\n }\n };\n /**\n * Add elements to the collection. This pushes each item in the provided array\n * to the end of the collection.\n * @param {!Array<T>} arr Array.\n * @return {Collection<T>} This collection.\n * @api\n */\n\n\n Collection.prototype.extend = function (arr) {\n for (var i = 0, ii = arr.length; i < ii; ++i) {\n this.push(arr[i]);\n }\n\n return this;\n };\n /**\n * Iterate over each element, calling the provided callback.\n * @param {function(T, number, Array<T>): *} f The function to call\n * for every element. This function takes 3 arguments (the element, the\n * index and the array). The return value is ignored.\n * @api\n */\n\n\n Collection.prototype.forEach = function (f) {\n var array = this.array_;\n\n for (var i = 0, ii = array.length; i < ii; ++i) {\n f(array[i], i, array);\n }\n };\n /**\n * Get a reference to the underlying Array object. Warning: if the array\n * is mutated, no events will be dispatched by the collection, and the\n * collection\'s "length" property won\'t be in sync with the actual length\n * of the array.\n * @return {!Array<T>} Array.\n * @api\n */\n\n\n Collection.prototype.getArray = function () {\n return this.array_;\n };\n /**\n * Get the element at the provided index.\n * @param {number} index Index.\n * @return {T} Element.\n * @api\n */\n\n\n Collection.prototype.item = function (index) {\n return this.array_[index];\n };\n /**\n * Get the length of this collection.\n * @return {number} The length of the array.\n * @observable\n * @api\n */\n\n\n Collection.prototype.getLength = function () {\n return this.get(Collection_Property.LENGTH);\n };\n /**\n * Insert an element at the provided index.\n * @param {number} index Index.\n * @param {T} elem Element.\n * @api\n */\n\n\n Collection.prototype.insertAt = function (index, elem) {\n if (this.unique_) {\n this.assertUnique_(elem);\n }\n\n this.array_.splice(index, 0, elem);\n this.updateLength_();\n this.dispatchEvent(new CollectionEvent(CollectionEventType.ADD, elem, index));\n };\n /**\n * Remove the last element of the collection and return it.\n * Return `undefined` if the collection is empty.\n * @return {T|undefined} Element.\n * @api\n */\n\n\n Collection.prototype.pop = function () {\n return this.removeAt(this.getLength() - 1);\n };\n /**\n * Insert the provided element at the end of the collection.\n * @param {T} elem Element.\n * @return {number} New length of the collection.\n * @api\n */\n\n\n Collection.prototype.push = function (elem) {\n if (this.unique_) {\n this.assertUnique_(elem);\n }\n\n var n = this.getLength();\n this.insertAt(n, elem);\n return this.getLength();\n };\n /**\n * Remove the first occurrence of an element from the collection.\n * @param {T} elem Element.\n * @return {T|undefined} The removed element or undefined if none found.\n * @api\n */\n\n\n Collection.prototype.remove = function (elem) {\n var arr = this.array_;\n\n for (var i = 0, ii = arr.length; i < ii; ++i) {\n if (arr[i] === elem) {\n return this.removeAt(i);\n }\n }\n\n return undefined;\n };\n /**\n * Remove the element at the provided index and return it.\n * Return `undefined` if the collection does not contain this index.\n * @param {number} index Index.\n * @return {T|undefined} Value.\n * @api\n */\n\n\n Collection.prototype.removeAt = function (index) {\n var prev = this.array_[index];\n this.array_.splice(index, 1);\n this.updateLength_();\n this.dispatchEvent(new CollectionEvent(CollectionEventType.REMOVE, prev, index));\n return prev;\n };\n /**\n * Set the element at the provided index.\n * @param {number} index Index.\n * @param {T} elem Element.\n * @api\n */\n\n\n Collection.prototype.setAt = function (index, elem) {\n var n = this.getLength();\n\n if (index < n) {\n if (this.unique_) {\n this.assertUnique_(elem, index);\n }\n\n var prev = this.array_[index];\n this.array_[index] = elem;\n this.dispatchEvent(new CollectionEvent(CollectionEventType.REMOVE, prev, index));\n this.dispatchEvent(new CollectionEvent(CollectionEventType.ADD, elem, index));\n } else {\n for (var j = n; j < index; ++j) {\n this.insertAt(j, undefined);\n }\n\n this.insertAt(index, elem);\n }\n };\n /**\n * @private\n */\n\n\n Collection.prototype.updateLength_ = function () {\n this.set(Collection_Property.LENGTH, this.array_.length);\n };\n /**\n * @private\n * @param {T} elem Element.\n * @param {number=} opt_except Optional index to ignore.\n */\n\n\n Collection.prototype.assertUnique_ = function (elem, opt_except) {\n for (var i = 0, ii = this.array_.length; i < ii; ++i) {\n if (this.array_[i] === elem && i !== opt_except) {\n throw new ol_AssertionError(58);\n }\n }\n };\n\n return Collection;\n}(ol_Object);\n\n/* harmony default export */ var ol_Collection = (Collection);\n;// CONCATENATED MODULE: ./node_modules/ol/layer/Group.js\nvar Group_extends = undefined && undefined.__extends || function () {\n var _extendStatics = function extendStatics(d, b) {\n _extendStatics = Object.setPrototypeOf || {\n __proto__: []\n } instanceof Array && function (d, b) {\n d.__proto__ = b;\n } || function (d, b) {\n for (var p in b) {\n if (Object.prototype.hasOwnProperty.call(b, p)) d[p] = b[p];\n }\n };\n\n return _extendStatics(d, b);\n };\n\n return function (d, b) {\n _extendStatics(d, b);\n\n function __() {\n this.constructor = d;\n }\n\n d.prototype = b === null ? Object.create(b) : (__.prototype = b.prototype, new __());\n };\n}();\n/**\n * @module ol/layer/Group\n */\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n/**\n * @typedef {Object} Options\n * @property {number} [opacity=1] Opacity (0, 1).\n * @property {boolean} [visible=true] Visibility.\n * @property {import("../extent.js").Extent} [extent] The bounding extent for layer rendering. The layer will not be\n * rendered outside of this extent.\n * @property {number} [zIndex] The z-index for layer rendering. At rendering time, the layers\n * will be ordered, first by Z-index and then by position. When `undefined`, a `zIndex` of 0 is assumed\n * for layers that are added to the map\'s `layers` collection, or `Infinity` when the layer\'s `setMap()`\n * method was used.\n * @property {number} [minResolution] The minimum resolution (inclusive) at which this layer will be\n * visible.\n * @property {number} [maxResolution] The maximum resolution (exclusive) below which this layer will\n * be visible.\n * @property {number} [minZoom] The minimum view zoom level (exclusive) above which this layer will be\n * visible.\n * @property {number} [maxZoom] The maximum view zoom level (inclusive) at which this layer will\n * be visible.\n * @property {number} [minZoom] The minimum view zoom level (exclusive) above which this layer will be\n * visible.\n * @property {number} [maxZoom] The maximum view zoom level (inclusive) at which this layer will\n * be visible.\n * @property {Array<import("./Base.js").default>|import("../Collection.js").default<import("./Base.js").default>} [layers] Child layers.\n */\n\n/**\n * @enum {string}\n * @private\n */\n\nvar Group_Property = {\n LAYERS: \'layers\'\n};\n/**\n * @classdesc\n * A {@link module:ol/Collection~Collection} of layers that are handled together.\n *\n * A generic `change` event is triggered when the group/Collection changes.\n *\n * @api\n */\n\nvar LayerGroup =\n/** @class */\nfunction (_super) {\n Group_extends(LayerGroup, _super);\n /**\n * @param {Options=} opt_options Layer options.\n */\n\n\n function LayerGroup(opt_options) {\n var _this = this;\n\n var options = opt_options || {};\n var baseOptions =\n /** @type {Options} */\n obj_assign({}, options);\n delete baseOptions.layers;\n var layers = options.layers;\n _this = _super.call(this, baseOptions) || this;\n /**\n * @private\n * @type {Array<import("../events.js").EventsKey>}\n */\n\n _this.layersListenerKeys_ = [];\n /**\n * @private\n * @type {Object<string, Array<import("../events.js").EventsKey>>}\n */\n\n _this.listenerKeys_ = {};\n\n _this.addEventListener(getChangeEventType(Group_Property.LAYERS), _this.handleLayersChanged_);\n\n if (layers) {\n if (Array.isArray(layers)) {\n layers = new ol_Collection(layers.slice(), {\n unique: true\n });\n } else {\n asserts_assert(typeof\n /** @type {?} */\n layers.getArray === \'function\', 43); // Expected `layers` to be an array or a `Collection`\n }\n } else {\n layers = new ol_Collection(undefined, {\n unique: true\n });\n }\n\n _this.setLayers(layers);\n\n return _this;\n }\n /**\n * @private\n */\n\n\n LayerGroup.prototype.handleLayerChange_ = function () {\n this.changed();\n };\n /**\n * @private\n */\n\n\n LayerGroup.prototype.handleLayersChanged_ = function () {\n this.layersListenerKeys_.forEach(unlistenByKey);\n this.layersListenerKeys_.length = 0;\n var layers = this.getLayers();\n this.layersListenerKeys_.push(listen(layers, CollectionEventType.ADD, this.handleLayersAdd_, this), listen(layers, CollectionEventType.REMOVE, this.handleLayersRemove_, this));\n\n for (var id in this.listenerKeys_) {\n this.listenerKeys_[id].forEach(unlistenByKey);\n }\n\n clear(this.listenerKeys_);\n var layersArray = layers.getArray();\n\n for (var i = 0, ii = layersArray.length; i < ii; i++) {\n var layer = layersArray[i];\n this.listenerKeys_[util_getUid(layer)] = [listen(layer, ObjectEventType.PROPERTYCHANGE, this.handleLayerChange_, this), listen(layer, EventType.CHANGE, this.handleLayerChange_, this)];\n }\n\n this.changed();\n };\n /**\n * @param {import("../Collection.js").CollectionEvent} collectionEvent CollectionEvent.\n * @private\n */\n\n\n LayerGroup.prototype.handleLayersAdd_ = function (collectionEvent) {\n var layer =\n /** @type {import("./Base.js").default} */\n collectionEvent.element;\n this.listenerKeys_[util_getUid(layer)] = [listen(layer, ObjectEventType.PROPERTYCHANGE, this.handleLayerChange_, this), listen(layer, EventType.CHANGE, this.handleLayerChange_, this)];\n this.changed();\n };\n /**\n * @param {import("../Collection.js").CollectionEvent} collectionEvent CollectionEvent.\n * @private\n */\n\n\n LayerGroup.prototype.handleLayersRemove_ = function (collectionEvent) {\n var layer =\n /** @type {import("./Base.js").default} */\n collectionEvent.element;\n var key = util_getUid(layer);\n this.listenerKeys_[key].forEach(unlistenByKey);\n delete this.listenerKeys_[key];\n this.changed();\n };\n /**\n * Returns the {@link module:ol/Collection collection} of {@link module:ol/layer/Layer~Layer layers}\n * in this group.\n * @return {!import("../Collection.js").default<import("./Base.js").default>} Collection of\n * {@link module:ol/layer/Base layers} that are part of this group.\n * @observable\n * @api\n */\n\n\n LayerGroup.prototype.getLayers = function () {\n return (\n /** @type {!import("../Collection.js").default<import("./Base.js").default>} */\n this.get(Group_Property.LAYERS)\n );\n };\n /**\n * Set the {@link module:ol/Collection collection} of {@link module:ol/layer/Layer~Layer layers}\n * in this group.\n * @param {!import("../Collection.js").default<import("./Base.js").default>} layers Collection of\n * {@link module:ol/layer/Base layers} that are part of this group.\n * @observable\n * @api\n */\n\n\n LayerGroup.prototype.setLayers = function (layers) {\n this.set(Group_Property.LAYERS, layers);\n };\n /**\n * @param {Array<import("./Layer.js").default>=} opt_array Array of layers (to be modified in place).\n * @return {Array<import("./Layer.js").default>} Array of layers.\n */\n\n\n LayerGroup.prototype.getLayersArray = function (opt_array) {\n var array = opt_array !== undefined ? opt_array : [];\n this.getLayers().forEach(function (layer) {\n layer.getLayersArray(array);\n });\n return array;\n };\n /**\n * @param {Array<import("./Layer.js").State>=} opt_states Optional list of layer states (to be modified in place).\n * @return {Array<import("./Layer.js").State>} List of layer states.\n */\n\n\n LayerGroup.prototype.getLayerStatesArray = function (opt_states) {\n var states = opt_states !== undefined ? opt_states : [];\n var pos = states.length;\n this.getLayers().forEach(function (layer) {\n layer.getLayerStatesArray(states);\n });\n var ownLayerState = this.getLayerState();\n\n for (var i = pos, ii = states.length; i < ii; i++) {\n var layerState = states[i];\n layerState.opacity *= ownLayerState.opacity;\n layerState.visible = layerState.visible && ownLayerState.visible;\n layerState.maxResolution = Math.min(layerState.maxResolution, ownLayerState.maxResolution);\n layerState.minResolution = Math.max(layerState.minResolution, ownLayerState.minResolution);\n layerState.minZoom = Math.max(layerState.minZoom, ownLayerState.minZoom);\n layerState.maxZoom = Math.min(layerState.maxZoom, ownLayerState.maxZoom);\n\n if (ownLayerState.extent !== undefined) {\n if (layerState.extent !== undefined) {\n layerState.extent = getIntersection(layerState.extent, ownLayerState.extent);\n } else {\n layerState.extent = ownLayerState.extent;\n }\n }\n }\n\n return states;\n };\n /**\n * @return {import("../source/State.js").default} Source state.\n */\n\n\n LayerGroup.prototype.getSourceState = function () {\n return State.READY;\n };\n\n return LayerGroup;\n}(Base);\n\n/* harmony default export */ var Group = (LayerGroup);\n;// CONCATENATED MODULE: ./node_modules/ol/MapEvent.js\nvar MapEvent_extends = undefined && undefined.__extends || function () {\n var _extendStatics = function extendStatics(d, b) {\n _extendStatics = Object.setPrototypeOf || {\n __proto__: []\n } instanceof Array && function (d, b) {\n d.__proto__ = b;\n } || function (d, b) {\n for (var p in b) {\n if (Object.prototype.hasOwnProperty.call(b, p)) d[p] = b[p];\n }\n };\n\n return _extendStatics(d, b);\n };\n\n return function (d, b) {\n _extendStatics(d, b);\n\n function __() {\n this.constructor = d;\n }\n\n d.prototype = b === null ? Object.create(b) : (__.prototype = b.prototype, new __());\n };\n}();\n/**\n * @module ol/MapEvent\n */\n\n\n\n/**\n * @classdesc\n * Events emitted as map events are instances of this type.\n * See {@link module:ol/PluggableMap~PluggableMap} for which events trigger a map event.\n */\n\nvar MapEvent =\n/** @class */\nfunction (_super) {\n MapEvent_extends(MapEvent, _super);\n /**\n * @param {string} type Event type.\n * @param {import("./PluggableMap.js").default} map Map.\n * @param {?import("./PluggableMap.js").FrameState=} opt_frameState Frame state.\n */\n\n\n function MapEvent(type, map, opt_frameState) {\n var _this = _super.call(this, type) || this;\n /**\n * The map where the event occurred.\n * @type {import("./PluggableMap.js").default}\n * @api\n */\n\n\n _this.map = map;\n /**\n * The frame state at the time of the event.\n * @type {?import("./PluggableMap.js").FrameState}\n * @api\n */\n\n _this.frameState = opt_frameState !== undefined ? opt_frameState : null;\n return _this;\n }\n\n return MapEvent;\n}(Event);\n\n/* harmony default export */ var ol_MapEvent = (MapEvent);\n;// CONCATENATED MODULE: ./node_modules/ol/MapBrowserEvent.js\nvar MapBrowserEvent_extends = undefined && undefined.__extends || function () {\n var _extendStatics = function extendStatics(d, b) {\n _extendStatics = Object.setPrototypeOf || {\n __proto__: []\n } instanceof Array && function (d, b) {\n d.__proto__ = b;\n } || function (d, b) {\n for (var p in b) {\n if (Object.prototype.hasOwnProperty.call(b, p)) d[p] = b[p];\n }\n };\n\n return _extendStatics(d, b);\n };\n\n return function (d, b) {\n _extendStatics(d, b);\n\n function __() {\n this.constructor = d;\n }\n\n d.prototype = b === null ? Object.create(b) : (__.prototype = b.prototype, new __());\n };\n}();\n/**\n * @module ol/MapBrowserEvent\n */\n\n\n\n/**\n * @classdesc\n * Events emitted as map browser events are instances of this type.\n * See {@link module:ol/PluggableMap~PluggableMap} for which events trigger a map browser event.\n * @template {UIEvent} EVENT\n */\n\nvar MapBrowserEvent =\n/** @class */\nfunction (_super) {\n MapBrowserEvent_extends(MapBrowserEvent, _super);\n /**\n * @param {string} type Event type.\n * @param {import("./PluggableMap.js").default} map Map.\n * @param {EVENT} originalEvent Original event.\n * @param {boolean=} opt_dragging Is the map currently being dragged?\n * @param {?import("./PluggableMap.js").FrameState=} opt_frameState Frame state.\n */\n\n\n function MapBrowserEvent(type, map, originalEvent, opt_dragging, opt_frameState) {\n var _this = _super.call(this, type, map, opt_frameState) || this;\n /**\n * The original browser event.\n * @const\n * @type {EVENT}\n * @api\n */\n\n\n _this.originalEvent = originalEvent;\n /**\n * The map pixel relative to the viewport corresponding to the original browser event.\n * @type {?import("./pixel.js").Pixel}\n */\n\n _this.pixel_ = null;\n /**\n * The coordinate in the user projection corresponding to the original browser event.\n * @type {?import("./coordinate.js").Coordinate}\n */\n\n _this.coordinate_ = null;\n /**\n * Indicates if the map is currently being dragged. Only set for\n * `POINTERDRAG` and `POINTERMOVE` events. Default is `false`.\n *\n * @type {boolean}\n * @api\n */\n\n _this.dragging = opt_dragging !== undefined ? opt_dragging : false;\n return _this;\n }\n\n Object.defineProperty(MapBrowserEvent.prototype, "pixel", {\n /**\n * The map pixel relative to the viewport corresponding to the original event.\n * @type {import("./pixel.js").Pixel}\n * @api\n */\n get: function get() {\n if (!this.pixel_) {\n this.pixel_ = this.map.getEventPixel(this.originalEvent);\n }\n\n return this.pixel_;\n },\n set: function set(pixel) {\n this.pixel_ = pixel;\n },\n enumerable: false,\n configurable: true\n });\n Object.defineProperty(MapBrowserEvent.prototype, "coordinate", {\n /**\n * The coordinate corresponding to the original browser event. This will be in the user\n * projection if one is set. Otherwise it will be in the view projection.\n * @type {import("./coordinate.js").Coordinate}\n * @api\n */\n get: function get() {\n if (!this.coordinate_) {\n this.coordinate_ = this.map.getCoordinateFromPixel(this.pixel);\n }\n\n return this.coordinate_;\n },\n set: function set(coordinate) {\n this.coordinate_ = coordinate;\n },\n enumerable: false,\n configurable: true\n });\n /**\n * Prevents the default browser action.\n * See https://developer.mozilla.org/en-US/docs/Web/API/event.preventDefault.\n * @api\n */\n\n MapBrowserEvent.prototype.preventDefault = function () {\n _super.prototype.preventDefault.call(this);\n\n this.originalEvent.preventDefault();\n };\n /**\n * Prevents further propagation of the current event.\n * See https://developer.mozilla.org/en-US/docs/Web/API/event.stopPropagation.\n * @api\n */\n\n\n MapBrowserEvent.prototype.stopPropagation = function () {\n _super.prototype.stopPropagation.call(this);\n\n this.originalEvent.stopPropagation();\n };\n\n return MapBrowserEvent;\n}(ol_MapEvent);\n\n/* harmony default export */ var ol_MapBrowserEvent = (MapBrowserEvent);\n;// CONCATENATED MODULE: ./node_modules/ol/MapBrowserEventType.js\n/**\n * @module ol/MapBrowserEventType\n */\n\n/**\n * Constants for event names.\n * @enum {string}\n */\n\n/* harmony default export */ var ol_MapBrowserEventType = ({\n /**\n * A true single click with no dragging and no double click. Note that this\n * event is delayed by 250 ms to ensure that it is not a double click.\n * @event module:ol/MapBrowserEvent~MapBrowserEvent#singleclick\n * @api\n */\n SINGLECLICK: \'singleclick\',\n\n /**\n * A click with no dragging. A double click will fire two of this.\n * @event module:ol/MapBrowserEvent~MapBrowserEvent#click\n * @api\n */\n CLICK: EventType.CLICK,\n\n /**\n * A true double click, with no dragging.\n * @event module:ol/MapBrowserEvent~MapBrowserEvent#dblclick\n * @api\n */\n DBLCLICK: EventType.DBLCLICK,\n\n /**\n * Triggered when a pointer is dragged.\n * @event module:ol/MapBrowserEvent~MapBrowserEvent#pointerdrag\n * @api\n */\n POINTERDRAG: \'pointerdrag\',\n\n /**\n * Triggered when a pointer is moved. Note that on touch devices this is\n * triggered when the map is panned, so is not the same as mousemove.\n * @event module:ol/MapBrowserEvent~MapBrowserEvent#pointermove\n * @api\n */\n POINTERMOVE: \'pointermove\',\n POINTERDOWN: \'pointerdown\',\n POINTERUP: \'pointerup\',\n POINTEROVER: \'pointerover\',\n POINTEROUT: \'pointerout\',\n POINTERENTER: \'pointerenter\',\n POINTERLEAVE: \'pointerleave\',\n POINTERCANCEL: \'pointercancel\'\n});\n;// CONCATENATED MODULE: ./node_modules/ol/pointer/EventType.js\n/**\n * @module ol/pointer/EventType\n */\n\n/**\n * Constants for event names.\n * @enum {string}\n */\n/* harmony default export */ var pointer_EventType = ({\n POINTERMOVE: \'pointermove\',\n POINTERDOWN: \'pointerdown\',\n POINTERUP: \'pointerup\',\n POINTEROVER: \'pointerover\',\n POINTEROUT: \'pointerout\',\n POINTERENTER: \'pointerenter\',\n POINTERLEAVE: \'pointerleave\',\n POINTERCANCEL: \'pointercancel\'\n});\n;// CONCATENATED MODULE: ./node_modules/ol/MapBrowserEventHandler.js\n/**\n * @module ol/MapBrowserEventHandler\n */\nvar MapBrowserEventHandler_extends = undefined && undefined.__extends || function () {\n var _extendStatics = function extendStatics(d, b) {\n _extendStatics = Object.setPrototypeOf || {\n __proto__: []\n } instanceof Array && function (d, b) {\n d.__proto__ = b;\n } || function (d, b) {\n for (var p in b) {\n if (Object.prototype.hasOwnProperty.call(b, p)) d[p] = b[p];\n }\n };\n\n return _extendStatics(d, b);\n };\n\n return function (d, b) {\n _extendStatics(d, b);\n\n function __() {\n this.constructor = d;\n }\n\n d.prototype = b === null ? Object.create(b) : (__.prototype = b.prototype, new __());\n };\n}();\n\n\n\n\n\n\n\n\n\nvar MapBrowserEventHandler =\n/** @class */\nfunction (_super) {\n MapBrowserEventHandler_extends(MapBrowserEventHandler, _super);\n /**\n * @param {import("./PluggableMap.js").default} map The map with the viewport to listen to events on.\n * @param {number=} moveTolerance The minimal distance the pointer must travel to trigger a move.\n */\n\n\n function MapBrowserEventHandler(map, moveTolerance) {\n var _this = _super.call(this, map) || this;\n /**\n * This is the element that we will listen to the real events on.\n * @type {import("./PluggableMap.js").default}\n * @private\n */\n\n\n _this.map_ = map;\n /**\n * @type {any}\n * @private\n */\n\n _this.clickTimeoutId_;\n /**\n * Emulate dblclick and singleclick. Will be true when only one pointer is active.\n * @type {boolean}\n */\n\n _this.emulateClicks_ = false;\n /**\n * @type {boolean}\n * @private\n */\n\n _this.dragging_ = false;\n /**\n * @type {!Array<import("./events.js").EventsKey>}\n * @private\n */\n\n _this.dragListenerKeys_ = [];\n /**\n * @type {number}\n * @private\n */\n\n _this.moveTolerance_ = moveTolerance ? moveTolerance * DEVICE_PIXEL_RATIO : DEVICE_PIXEL_RATIO;\n /**\n * The most recent "down" type event (or null if none have occurred).\n * Set on pointerdown.\n * @type {PointerEvent}\n * @private\n */\n\n _this.down_ = null;\n\n var element = _this.map_.getViewport();\n /**\n * @type {number}\n * @private\n */\n\n\n _this.activePointers_ = 0;\n /**\n * @type {!Object<number, boolean>}\n * @private\n */\n\n _this.trackedTouches_ = {};\n _this.element_ = element;\n /**\n * @type {?import("./events.js").EventsKey}\n * @private\n */\n\n _this.pointerdownListenerKey_ = listen(element, pointer_EventType.POINTERDOWN, _this.handlePointerDown_, _this);\n /**\n * @type {PointerEvent}\n * @private\n */\n\n _this.originalPointerMoveEvent_;\n /**\n * @type {?import("./events.js").EventsKey}\n * @private\n */\n\n _this.relayedListenerKey_ = listen(element, pointer_EventType.POINTERMOVE, _this.relayEvent_, _this);\n /**\n * @private\n */\n\n _this.boundHandleTouchMove_ = _this.handleTouchMove_.bind(_this);\n\n _this.element_.addEventListener(EventType.TOUCHMOVE, _this.boundHandleTouchMove_, PASSIVE_EVENT_LISTENERS ? {\n passive: false\n } : false);\n\n return _this;\n }\n /**\n * @param {PointerEvent} pointerEvent Pointer\n * event.\n * @private\n */\n\n\n MapBrowserEventHandler.prototype.emulateClick_ = function (pointerEvent) {\n var newEvent = new ol_MapBrowserEvent(ol_MapBrowserEventType.CLICK, this.map_, pointerEvent);\n this.dispatchEvent(newEvent);\n\n if (this.clickTimeoutId_ !== undefined) {\n // double-click\n clearTimeout(this.clickTimeoutId_);\n this.clickTimeoutId_ = undefined;\n newEvent = new ol_MapBrowserEvent(ol_MapBrowserEventType.DBLCLICK, this.map_, pointerEvent);\n this.dispatchEvent(newEvent);\n } else {\n // click\n this.clickTimeoutId_ = setTimeout(\n /** @this {MapBrowserEventHandler} */\n function () {\n this.clickTimeoutId_ = undefined;\n var newEvent = new ol_MapBrowserEvent(ol_MapBrowserEventType.SINGLECLICK, this.map_, pointerEvent);\n this.dispatchEvent(newEvent);\n }.bind(this), 250);\n }\n };\n /**\n * Keeps track on how many pointers are currently active.\n *\n * @param {PointerEvent} pointerEvent Pointer\n * event.\n * @private\n */\n\n\n MapBrowserEventHandler.prototype.updateActivePointers_ = function (pointerEvent) {\n var event = pointerEvent;\n\n if (event.type == ol_MapBrowserEventType.POINTERUP || event.type == ol_MapBrowserEventType.POINTERCANCEL) {\n delete this.trackedTouches_[event.pointerId];\n } else if (event.type == ol_MapBrowserEventType.POINTERDOWN) {\n this.trackedTouches_[event.pointerId] = true;\n }\n\n this.activePointers_ = Object.keys(this.trackedTouches_).length;\n };\n /**\n * @param {PointerEvent} pointerEvent Pointer\n * event.\n * @private\n */\n\n\n MapBrowserEventHandler.prototype.handlePointerUp_ = function (pointerEvent) {\n this.updateActivePointers_(pointerEvent);\n var newEvent = new ol_MapBrowserEvent(ol_MapBrowserEventType.POINTERUP, this.map_, pointerEvent);\n this.dispatchEvent(newEvent); // We emulate click events on left mouse button click, touch contact, and pen\n // contact. isMouseActionButton returns true in these cases (evt.button is set\n // to 0).\n // See http://www.w3.org/TR/pointerevents/#button-states\n // We only fire click, singleclick, and doubleclick if nobody has called\n // event.stopPropagation() or event.preventDefault().\n\n if (this.emulateClicks_ && !newEvent.propagationStopped && !this.dragging_ && this.isMouseActionButton_(pointerEvent)) {\n this.emulateClick_(this.down_);\n }\n\n if (this.activePointers_ === 0) {\n this.dragListenerKeys_.forEach(unlistenByKey);\n this.dragListenerKeys_.length = 0;\n this.dragging_ = false;\n this.down_ = null;\n }\n };\n /**\n * @param {PointerEvent} pointerEvent Pointer\n * event.\n * @return {boolean} If the left mouse button was pressed.\n * @private\n */\n\n\n MapBrowserEventHandler.prototype.isMouseActionButton_ = function (pointerEvent) {\n return pointerEvent.button === 0;\n };\n /**\n * @param {PointerEvent} pointerEvent Pointer\n * event.\n * @private\n */\n\n\n MapBrowserEventHandler.prototype.handlePointerDown_ = function (pointerEvent) {\n this.emulateClicks_ = this.activePointers_ === 0;\n this.updateActivePointers_(pointerEvent);\n var newEvent = new ol_MapBrowserEvent(ol_MapBrowserEventType.POINTERDOWN, this.map_, pointerEvent);\n this.dispatchEvent(newEvent);\n this.down_ = pointerEvent;\n\n if (this.dragListenerKeys_.length === 0) {\n var doc = this.map_.getOwnerDocument();\n this.dragListenerKeys_.push(listen(doc, ol_MapBrowserEventType.POINTERMOVE, this.handlePointerMove_, this), listen(doc, ol_MapBrowserEventType.POINTERUP, this.handlePointerUp_, this),\n /* Note that the listener for `pointercancel is set up on\n * `pointerEventHandler_` and not `documentPointerEventHandler_` like\n * the `pointerup` and `pointermove` listeners.\n *\n * The reason for this is the following: `TouchSource.vacuumTouches_()`\n * issues `pointercancel` events, when there was no `touchend` for a\n * `touchstart`. Now, let\'s say a first `touchstart` is registered on\n * `pointerEventHandler_`. The `documentPointerEventHandler_` is set up.\n * But `documentPointerEventHandler_` doesn\'t know about the first\n * `touchstart`. If there is no `touchend` for the `touchstart`, we can\n * only receive a `touchcancel` from `pointerEventHandler_`, because it is\n * only registered there.\n */\n listen(this.element_, ol_MapBrowserEventType.POINTERCANCEL, this.handlePointerUp_, this));\n\n if (this.element_.getRootNode && this.element_.getRootNode() !== doc) {\n this.dragListenerKeys_.push(listen(this.element_.getRootNode(), ol_MapBrowserEventType.POINTERUP, this.handlePointerUp_, this));\n }\n }\n };\n /**\n * @param {PointerEvent} pointerEvent Pointer\n * event.\n * @private\n */\n\n\n MapBrowserEventHandler.prototype.handlePointerMove_ = function (pointerEvent) {\n // Between pointerdown and pointerup, pointermove events are triggered.\n // To avoid a \'false\' touchmove event to be dispatched, we test if the pointer\n // moved a significant distance.\n if (this.isMoving_(pointerEvent)) {\n this.dragging_ = true;\n var newEvent = new ol_MapBrowserEvent(ol_MapBrowserEventType.POINTERDRAG, this.map_, pointerEvent, this.dragging_);\n this.dispatchEvent(newEvent);\n }\n };\n /**\n * Wrap and relay a pointer event. Note that this requires that the type\n * string for the MapBrowserEvent matches the PointerEvent type.\n * @param {PointerEvent} pointerEvent Pointer\n * event.\n * @private\n */\n\n\n MapBrowserEventHandler.prototype.relayEvent_ = function (pointerEvent) {\n this.originalPointerMoveEvent_ = pointerEvent;\n var dragging = !!(this.down_ && this.isMoving_(pointerEvent));\n this.dispatchEvent(new ol_MapBrowserEvent(pointerEvent.type, this.map_, pointerEvent, dragging));\n };\n /**\n * Flexible handling of a `touch-action: none` css equivalent: because calling\n * `preventDefault()` on a `pointermove` event does not stop native page scrolling\n * and zooming, we also listen for `touchmove` and call `preventDefault()` on it\n * when an interaction (currently `DragPan` handles the event.\n * @param {TouchEvent} event Event.\n * @private\n */\n\n\n MapBrowserEventHandler.prototype.handleTouchMove_ = function (event) {\n // Due to https://github.com/mpizenberg/elm-pep/issues/2, `this.originalPointerMoveEvent_`\n // may not be initialized yet when we get here on a platform without native pointer events.\n if (!this.originalPointerMoveEvent_ || this.originalPointerMoveEvent_.defaultPrevented) {\n event.preventDefault();\n }\n };\n /**\n * @param {PointerEvent} pointerEvent Pointer\n * event.\n * @return {boolean} Is moving.\n * @private\n */\n\n\n MapBrowserEventHandler.prototype.isMoving_ = function (pointerEvent) {\n return this.dragging_ || Math.abs(pointerEvent.clientX - this.down_.clientX) > this.moveTolerance_ || Math.abs(pointerEvent.clientY - this.down_.clientY) > this.moveTolerance_;\n };\n /**\n * Clean up.\n */\n\n\n MapBrowserEventHandler.prototype.disposeInternal = function () {\n if (this.relayedListenerKey_) {\n unlistenByKey(this.relayedListenerKey_);\n this.relayedListenerKey_ = null;\n }\n\n this.element_.removeEventListener(EventType.TOUCHMOVE, this.boundHandleTouchMove_);\n\n if (this.pointerdownListenerKey_) {\n unlistenByKey(this.pointerdownListenerKey_);\n this.pointerdownListenerKey_ = null;\n }\n\n this.dragListenerKeys_.forEach(unlistenByKey);\n this.dragListenerKeys_.length = 0;\n this.element_ = null;\n\n _super.prototype.disposeInternal.call(this);\n };\n\n return MapBrowserEventHandler;\n}(events_Target);\n\n/* harmony default export */ var ol_MapBrowserEventHandler = (MapBrowserEventHandler);\n;// CONCATENATED MODULE: ./node_modules/ol/MapEventType.js\n/**\n * @module ol/MapEventType\n */\n\n/**\n * @enum {string}\n */\n/* harmony default export */ var MapEventType = ({\n /**\n * Triggered after a map frame is rendered.\n * @event module:ol/MapEvent~MapEvent#postrender\n * @api\n */\n POSTRENDER: \'postrender\',\n\n /**\n * Triggered when the map starts moving.\n * @event module:ol/MapEvent~MapEvent#movestart\n * @api\n */\n MOVESTART: \'movestart\',\n\n /**\n * Triggered after the map is moved.\n * @event module:ol/MapEvent~MapEvent#moveend\n * @api\n */\n MOVEEND: \'moveend\'\n});\n;// CONCATENATED MODULE: ./node_modules/ol/MapProperty.js\n/**\n * @module ol/MapProperty\n */\n\n/**\n * @enum {string}\n */\n/* harmony default export */ var MapProperty = ({\n LAYERGROUP: \'layergroup\',\n SIZE: \'size\',\n TARGET: \'target\',\n VIEW: \'view\'\n});\n;// CONCATENATED MODULE: ./node_modules/ol/structs/PriorityQueue.js\n/**\n * @module ol/structs/PriorityQueue\n */\n\n\n/**\n * @type {number}\n */\n\nvar DROP = Infinity;\n/**\n * @classdesc\n * Priority queue.\n *\n * The implementation is inspired from the Closure Library\'s Heap class and\n * Python\'s heapq module.\n *\n * See http://closure-library.googlecode.com/svn/docs/closure_goog_structs_heap.js.source.html\n * and http://hg.python.org/cpython/file/2.7/Lib/heapq.py.\n *\n * @template T\n */\n\nvar PriorityQueue =\n/** @class */\nfunction () {\n /**\n * @param {function(T): number} priorityFunction Priority function.\n * @param {function(T): string} keyFunction Key function.\n */\n function PriorityQueue(priorityFunction, keyFunction) {\n /**\n * @type {function(T): number}\n * @private\n */\n this.priorityFunction_ = priorityFunction;\n /**\n * @type {function(T): string}\n * @private\n */\n\n this.keyFunction_ = keyFunction;\n /**\n * @type {Array<T>}\n * @private\n */\n\n this.elements_ = [];\n /**\n * @type {Array<number>}\n * @private\n */\n\n this.priorities_ = [];\n /**\n * @type {!Object<string, boolean>}\n * @private\n */\n\n this.queuedElements_ = {};\n }\n /**\n * FIXME empty description for jsdoc\n */\n\n\n PriorityQueue.prototype.clear = function () {\n this.elements_.length = 0;\n this.priorities_.length = 0;\n clear(this.queuedElements_);\n };\n /**\n * Remove and return the highest-priority element. O(log N).\n * @return {T} Element.\n */\n\n\n PriorityQueue.prototype.dequeue = function () {\n var elements = this.elements_;\n var priorities = this.priorities_;\n var element = elements[0];\n\n if (elements.length == 1) {\n elements.length = 0;\n priorities.length = 0;\n } else {\n elements[0] = elements.pop();\n priorities[0] = priorities.pop();\n this.siftUp_(0);\n }\n\n var elementKey = this.keyFunction_(element);\n delete this.queuedElements_[elementKey];\n return element;\n };\n /**\n * Enqueue an element. O(log N).\n * @param {T} element Element.\n * @return {boolean} The element was added to the queue.\n */\n\n\n PriorityQueue.prototype.enqueue = function (element) {\n asserts_assert(!(this.keyFunction_(element) in this.queuedElements_), 31); // Tried to enqueue an `element` that was already added to the queue\n\n var priority = this.priorityFunction_(element);\n\n if (priority != DROP) {\n this.elements_.push(element);\n this.priorities_.push(priority);\n this.queuedElements_[this.keyFunction_(element)] = true;\n this.siftDown_(0, this.elements_.length - 1);\n return true;\n }\n\n return false;\n };\n /**\n * @return {number} Count.\n */\n\n\n PriorityQueue.prototype.getCount = function () {\n return this.elements_.length;\n };\n /**\n * Gets the index of the left child of the node at the given index.\n * @param {number} index The index of the node to get the left child for.\n * @return {number} The index of the left child.\n * @private\n */\n\n\n PriorityQueue.prototype.getLeftChildIndex_ = function (index) {\n return index * 2 + 1;\n };\n /**\n * Gets the index of the right child of the node at the given index.\n * @param {number} index The index of the node to get the right child for.\n * @return {number} The index of the right child.\n * @private\n */\n\n\n PriorityQueue.prototype.getRightChildIndex_ = function (index) {\n return index * 2 + 2;\n };\n /**\n * Gets the index of the parent of the node at the given index.\n * @param {number} index The index of the node to get the parent for.\n * @return {number} The index of the parent.\n * @private\n */\n\n\n PriorityQueue.prototype.getParentIndex_ = function (index) {\n return index - 1 >> 1;\n };\n /**\n * Make this a heap. O(N).\n * @private\n */\n\n\n PriorityQueue.prototype.heapify_ = function () {\n var i;\n\n for (i = (this.elements_.length >> 1) - 1; i >= 0; i--) {\n this.siftUp_(i);\n }\n };\n /**\n * @return {boolean} Is empty.\n */\n\n\n PriorityQueue.prototype.isEmpty = function () {\n return this.elements_.length === 0;\n };\n /**\n * @param {string} key Key.\n * @return {boolean} Is key queued.\n */\n\n\n PriorityQueue.prototype.isKeyQueued = function (key) {\n return key in this.queuedElements_;\n };\n /**\n * @param {T} element Element.\n * @return {boolean} Is queued.\n */\n\n\n PriorityQueue.prototype.isQueued = function (element) {\n return this.isKeyQueued(this.keyFunction_(element));\n };\n /**\n * @param {number} index The index of the node to move down.\n * @private\n */\n\n\n PriorityQueue.prototype.siftUp_ = function (index) {\n var elements = this.elements_;\n var priorities = this.priorities_;\n var count = elements.length;\n var element = elements[index];\n var priority = priorities[index];\n var startIndex = index;\n\n while (index < count >> 1) {\n var lIndex = this.getLeftChildIndex_(index);\n var rIndex = this.getRightChildIndex_(index);\n var smallerChildIndex = rIndex < count && priorities[rIndex] < priorities[lIndex] ? rIndex : lIndex;\n elements[index] = elements[smallerChildIndex];\n priorities[index] = priorities[smallerChildIndex];\n index = smallerChildIndex;\n }\n\n elements[index] = element;\n priorities[index] = priority;\n this.siftDown_(startIndex, index);\n };\n /**\n * @param {number} startIndex The index of the root.\n * @param {number} index The index of the node to move up.\n * @private\n */\n\n\n PriorityQueue.prototype.siftDown_ = function (startIndex, index) {\n var elements = this.elements_;\n var priorities = this.priorities_;\n var element = elements[index];\n var priority = priorities[index];\n\n while (index > startIndex) {\n var parentIndex = this.getParentIndex_(index);\n\n if (priorities[parentIndex] > priority) {\n elements[index] = elements[parentIndex];\n priorities[index] = priorities[parentIndex];\n index = parentIndex;\n } else {\n break;\n }\n }\n\n elements[index] = element;\n priorities[index] = priority;\n };\n /**\n * FIXME empty description for jsdoc\n */\n\n\n PriorityQueue.prototype.reprioritize = function () {\n var priorityFunction = this.priorityFunction_;\n var elements = this.elements_;\n var priorities = this.priorities_;\n var index = 0;\n var n = elements.length;\n var element, i, priority;\n\n for (i = 0; i < n; ++i) {\n element = elements[i];\n priority = priorityFunction(element);\n\n if (priority == DROP) {\n delete this.queuedElements_[this.keyFunction_(element)];\n } else {\n priorities[index] = priority;\n elements[index++] = element;\n }\n }\n\n elements.length = index;\n priorities.length = index;\n this.heapify_();\n };\n\n return PriorityQueue;\n}();\n\n/* harmony default export */ var structs_PriorityQueue = (PriorityQueue);\n;// CONCATENATED MODULE: ./node_modules/ol/TileState.js\n/**\n * @module ol/TileState\n */\n\n/**\n * @enum {number}\n */\n/* harmony default export */ var TileState = ({\n IDLE: 0,\n LOADING: 1,\n LOADED: 2,\n\n /**\n * Indicates that tile loading failed\n * @type {number}\n */\n ERROR: 3,\n EMPTY: 4\n});\n;// CONCATENATED MODULE: ./node_modules/ol/TileQueue.js\nvar TileQueue_extends = undefined && undefined.__extends || function () {\n var _extendStatics = function extendStatics(d, b) {\n _extendStatics = Object.setPrototypeOf || {\n __proto__: []\n } instanceof Array && function (d, b) {\n d.__proto__ = b;\n } || function (d, b) {\n for (var p in b) {\n if (Object.prototype.hasOwnProperty.call(b, p)) d[p] = b[p];\n }\n };\n\n return _extendStatics(d, b);\n };\n\n return function (d, b) {\n _extendStatics(d, b);\n\n function __() {\n this.constructor = d;\n }\n\n d.prototype = b === null ? Object.create(b) : (__.prototype = b.prototype, new __());\n };\n}();\n/**\n * @module ol/TileQueue\n */\n\n\n\n\n\n/**\n * @typedef {function(import("./Tile.js").default, string, import("./coordinate.js").Coordinate, number): number} PriorityFunction\n */\n\nvar TileQueue =\n/** @class */\nfunction (_super) {\n TileQueue_extends(TileQueue, _super);\n /**\n * @param {PriorityFunction} tilePriorityFunction Tile priority function.\n * @param {function(): ?} tileChangeCallback Function called on each tile change event.\n */\n\n\n function TileQueue(tilePriorityFunction, tileChangeCallback) {\n var _this = _super.call(this,\n /**\n * @param {Array} element Element.\n * @return {number} Priority.\n */\n function (element) {\n return tilePriorityFunction.apply(null, element);\n },\n /**\n * @param {Array} element Element.\n * @return {string} Key.\n */\n function (element) {\n return (\n /** @type {import("./Tile.js").default} */\n element[0].getKey()\n );\n }) || this;\n /** @private */\n\n\n _this.boundHandleTileChange_ = _this.handleTileChange.bind(_this);\n /**\n * @private\n * @type {function(): ?}\n */\n\n _this.tileChangeCallback_ = tileChangeCallback;\n /**\n * @private\n * @type {number}\n */\n\n _this.tilesLoading_ = 0;\n /**\n * @private\n * @type {!Object<string,boolean>}\n */\n\n _this.tilesLoadingKeys_ = {};\n return _this;\n }\n /**\n * @param {Array} element Element.\n * @return {boolean} The element was added to the queue.\n */\n\n\n TileQueue.prototype.enqueue = function (element) {\n var added = _super.prototype.enqueue.call(this, element);\n\n if (added) {\n var tile = element[0];\n tile.addEventListener(EventType.CHANGE, this.boundHandleTileChange_);\n }\n\n return added;\n };\n /**\n * @return {number} Number of tiles loading.\n */\n\n\n TileQueue.prototype.getTilesLoading = function () {\n return this.tilesLoading_;\n };\n /**\n * @param {import("./events/Event.js").default} event Event.\n * @protected\n */\n\n\n TileQueue.prototype.handleTileChange = function (event) {\n var tile =\n /** @type {import("./Tile.js").default} */\n event.target;\n var state = tile.getState();\n\n if (tile.hifi && state === TileState.LOADED || state === TileState.ERROR || state === TileState.EMPTY) {\n tile.removeEventListener(EventType.CHANGE, this.boundHandleTileChange_);\n var tileKey = tile.getKey();\n\n if (tileKey in this.tilesLoadingKeys_) {\n delete this.tilesLoadingKeys_[tileKey];\n --this.tilesLoading_;\n }\n\n this.tileChangeCallback_();\n }\n };\n /**\n * @param {number} maxTotalLoading Maximum number tiles to load simultaneously.\n * @param {number} maxNewLoads Maximum number of new tiles to load.\n */\n\n\n TileQueue.prototype.loadMoreTiles = function (maxTotalLoading, maxNewLoads) {\n var newLoads = 0;\n var state, tile, tileKey;\n\n while (this.tilesLoading_ < maxTotalLoading && newLoads < maxNewLoads && this.getCount() > 0) {\n tile =\n /** @type {import("./Tile.js").default} */\n this.dequeue()[0];\n tileKey = tile.getKey();\n state = tile.getState();\n\n if (state === TileState.IDLE && !(tileKey in this.tilesLoadingKeys_)) {\n this.tilesLoadingKeys_[tileKey] = true;\n ++this.tilesLoading_;\n ++newLoads;\n tile.load();\n }\n }\n };\n\n return TileQueue;\n}(structs_PriorityQueue);\n\n/* harmony default export */ var ol_TileQueue = (TileQueue);\n/**\n * @param {import(\'./PluggableMap.js\').FrameState} frameState Frame state.\n * @param {import("./Tile.js").default} tile Tile.\n * @param {string} tileSourceKey Tile source key.\n * @param {import("./coordinate.js").Coordinate} tileCenter Tile center.\n * @param {number} tileResolution Tile resolution.\n * @return {number} Tile priority.\n */\n\nfunction getTilePriority(frameState, tile, tileSourceKey, tileCenter, tileResolution) {\n // Filter out tiles at higher zoom levels than the current zoom level, or that\n // are outside the visible extent.\n if (!frameState || !(tileSourceKey in frameState.wantedTiles)) {\n return DROP;\n }\n\n if (!frameState.wantedTiles[tileSourceKey][tile.getKey()]) {\n return DROP;\n } // Prioritize the highest zoom level tiles closest to the focus.\n // Tiles at higher zoom levels are prioritized using Math.log(tileResolution).\n // Within a zoom level, tiles are prioritized by the distance in pixels between\n // the center of the tile and the center of the viewport. The factor of 65536\n // means that the prioritization should behave as desired for tiles up to\n // 65536 * Math.log(2) = 45426 pixels from the focus.\n\n\n var center = frameState.viewState.center;\n var deltaX = tileCenter[0] - center[0];\n var deltaY = tileCenter[1] - center[1];\n return 65536 * Math.log(tileResolution) + Math.sqrt(deltaX * deltaX + deltaY * deltaY) / tileResolution;\n}\n;// CONCATENATED MODULE: ./node_modules/ol/geom/GeometryType.js\n/**\n * @module ol/geom/GeometryType\n */\n\n/**\n * The geometry type. One of `\'Point\'`, `\'LineString\'`, `\'LinearRing\'`,\n * `\'Polygon\'`, `\'MultiPoint\'`, `\'MultiLineString\'`, `\'MultiPolygon\'`,\n * `\'GeometryCollection\'`, `\'Circle\'`.\n * @enum {string}\n */\n/* harmony default export */ var geom_GeometryType = ({\n POINT: \'Point\',\n LINE_STRING: \'LineString\',\n LINEAR_RING: \'LinearRing\',\n POLYGON: \'Polygon\',\n MULTI_POINT: \'MultiPoint\',\n MULTI_LINE_STRING: \'MultiLineString\',\n MULTI_POLYGON: \'MultiPolygon\',\n GEOMETRY_COLLECTION: \'GeometryCollection\',\n CIRCLE: \'Circle\'\n});\n;// CONCATENATED MODULE: ./node_modules/ol/proj/Units.js\n/**\n * @module ol/proj/Units\n */\n\n/**\n * Projection units: `\'degrees\'`, `\'ft\'`, `\'m\'`, `\'pixels\'`, `\'tile-pixels\'` or\n * `\'us-ft\'`.\n * @enum {string}\n */\nvar Units = {\n /**\n * Degrees\n * @api\n */\n DEGREES: \'degrees\',\n\n /**\n * Feet\n * @api\n */\n FEET: \'ft\',\n\n /**\n * Meters\n * @api\n */\n METERS: \'m\',\n\n /**\n * Pixels\n * @api\n */\n PIXELS: \'pixels\',\n\n /**\n * Tile Pixels\n * @api\n */\n TILE_PIXELS: \'tile-pixels\',\n\n /**\n * US Feet\n * @api\n */\n USFEET: \'us-ft\'\n};\n/**\n * Meters per unit lookup table.\n * @const\n * @type {Object<Units, number>}\n * @api\n */\n\nvar METERS_PER_UNIT = {}; // use the radius of the Normal sphere\n\nMETERS_PER_UNIT[Units.DEGREES] = 2 * Math.PI * 6370997 / 360;\nMETERS_PER_UNIT[Units.FEET] = 0.3048;\nMETERS_PER_UNIT[Units.METERS] = 1;\nMETERS_PER_UNIT[Units.USFEET] = 1200 / 3937;\n/* harmony default export */ var proj_Units = (Units);\n;// CONCATENATED MODULE: ./node_modules/ol/ViewHint.js\n/**\n * @module ol/ViewHint\n */\n\n/**\n * @enum {number}\n */\n/* harmony default export */ var ViewHint = ({\n ANIMATING: 0,\n INTERACTING: 1\n});\n;// CONCATENATED MODULE: ./node_modules/ol/ViewProperty.js\n/**\n * @module ol/ViewProperty\n */\n\n/**\n * @enum {string}\n */\n/* harmony default export */ var ViewProperty = ({\n CENTER: \'center\',\n RESOLUTION: \'resolution\',\n ROTATION: \'rotation\'\n});\n;// CONCATENATED MODULE: ./node_modules/ol/tilegrid/common.js\n/**\n * @module ol/tilegrid/common\n */\n\n/**\n * Default maximum zoom for default tile grids.\n * @type {number}\n */\nvar DEFAULT_MAX_ZOOM = 42;\n/**\n * Default tile size.\n * @type {number}\n */\n\nvar DEFAULT_TILE_SIZE = 256;\n;// CONCATENATED MODULE: ./node_modules/ol/proj/Projection.js\n/**\n * @module ol/proj/Projection\n */\n\n/**\n * @typedef {Object} Options\n * @property {string} code The SRS identifier code, e.g. `EPSG:4326`.\n * @property {import("./Units.js").default|string} [units] Units. Required unless a\n * proj4 projection is defined for `code`.\n * @property {import("../extent.js").Extent} [extent] The validity extent for the SRS.\n * @property {string} [axisOrientation=\'enu\'] The axis orientation as specified in Proj4.\n * @property {boolean} [global=false] Whether the projection is valid for the whole globe.\n * @property {number} [metersPerUnit] The meters per unit for the SRS.\n * If not provided, the `units` are used to get the meters per unit from the {@link module:ol/proj/Units~METERS_PER_UNIT}\n * lookup table.\n * @property {import("../extent.js").Extent} [worldExtent] The world extent for the SRS.\n * @property {function(number, import("../coordinate.js").Coordinate):number} [getPointResolution]\n * Function to determine resolution at a point. The function is called with a\n * `{number}` view resolution and an `{import("../coordinate.js").Coordinate}` as arguments, and returns\n * the `{number}` resolution in projection units at the passed coordinate. If this is `undefined`,\n * the default {@link module:ol/proj#getPointResolution} function will be used.\n */\n\n/**\n * @classdesc\n * Projection definition class. One of these is created for each projection\n * supported in the application and stored in the {@link module:ol/proj} namespace.\n * You can use these in applications, but this is not required, as API params\n * and options use {@link module:ol/proj~ProjectionLike} which means the simple string\n * code will suffice.\n *\n * You can use {@link module:ol/proj~get} to retrieve the object for a particular\n * projection.\n *\n * The library includes definitions for `EPSG:4326` and `EPSG:3857`, together\n * with the following aliases:\n * * `EPSG:4326`: CRS:84, urn:ogc:def:crs:EPSG:6.6:4326,\n * urn:ogc:def:crs:OGC:1.3:CRS84, urn:ogc:def:crs:OGC:2:84,\n * http://www.opengis.net/gml/srs/epsg.xml#4326,\n * urn:x-ogc:def:crs:EPSG:4326\n * * `EPSG:3857`: EPSG:102100, EPSG:102113, EPSG:900913,\n * urn:ogc:def:crs:EPSG:6.18:3:3857,\n * http://www.opengis.net/gml/srs/epsg.xml#3857\n *\n * If you use [proj4js](https://github.com/proj4js/proj4js), aliases can\n * be added using `proj4.defs()`. After all required projection definitions are\n * added, call the {@link module:ol/proj/proj4~register} function.\n *\n * @api\n */\n\nvar Projection =\n/** @class */\nfunction () {\n /**\n * @param {Options} options Projection options.\n */\n function Projection(options) {\n /**\n * @private\n * @type {string}\n */\n this.code_ = options.code;\n /**\n * Units of projected coordinates. When set to `TILE_PIXELS`, a\n * `this.extent_` and `this.worldExtent_` must be configured properly for each\n * tile.\n * @private\n * @type {import("./Units.js").default}\n */\n\n this.units_ =\n /** @type {import("./Units.js").default} */\n options.units;\n /**\n * Validity extent of the projection in projected coordinates. For projections\n * with `TILE_PIXELS` units, this is the extent of the tile in\n * tile pixel space.\n * @private\n * @type {import("../extent.js").Extent}\n */\n\n this.extent_ = options.extent !== undefined ? options.extent : null;\n /**\n * Extent of the world in EPSG:4326. For projections with\n * `TILE_PIXELS` units, this is the extent of the tile in\n * projected coordinate space.\n * @private\n * @type {import("../extent.js").Extent}\n */\n\n this.worldExtent_ = options.worldExtent !== undefined ? options.worldExtent : null;\n /**\n * @private\n * @type {string}\n */\n\n this.axisOrientation_ = options.axisOrientation !== undefined ? options.axisOrientation : \'enu\';\n /**\n * @private\n * @type {boolean}\n */\n\n this.global_ = options.global !== undefined ? options.global : false;\n /**\n * @private\n * @type {boolean}\n */\n\n this.canWrapX_ = !!(this.global_ && this.extent_);\n /**\n * @private\n * @type {function(number, import("../coordinate.js").Coordinate):number|undefined}\n */\n\n this.getPointResolutionFunc_ = options.getPointResolution;\n /**\n * @private\n * @type {import("../tilegrid/TileGrid.js").default}\n */\n\n this.defaultTileGrid_ = null;\n /**\n * @private\n * @type {number|undefined}\n */\n\n this.metersPerUnit_ = options.metersPerUnit;\n }\n /**\n * @return {boolean} The projection is suitable for wrapping the x-axis\n */\n\n\n Projection.prototype.canWrapX = function () {\n return this.canWrapX_;\n };\n /**\n * Get the code for this projection, e.g. \'EPSG:4326\'.\n * @return {string} Code.\n * @api\n */\n\n\n Projection.prototype.getCode = function () {\n return this.code_;\n };\n /**\n * Get the validity extent for this projection.\n * @return {import("../extent.js").Extent} Extent.\n * @api\n */\n\n\n Projection.prototype.getExtent = function () {\n return this.extent_;\n };\n /**\n * Get the units of this projection.\n * @return {import("./Units.js").default} Units.\n * @api\n */\n\n\n Projection.prototype.getUnits = function () {\n return this.units_;\n };\n /**\n * Get the amount of meters per unit of this projection. If the projection is\n * not configured with `metersPerUnit` or a units identifier, the return is\n * `undefined`.\n * @return {number|undefined} Meters.\n * @api\n */\n\n\n Projection.prototype.getMetersPerUnit = function () {\n return this.metersPerUnit_ || METERS_PER_UNIT[this.units_];\n };\n /**\n * Get the world extent for this projection.\n * @return {import("../extent.js").Extent} Extent.\n * @api\n */\n\n\n Projection.prototype.getWorldExtent = function () {\n return this.worldExtent_;\n };\n /**\n * Get the axis orientation of this projection.\n * Example values are:\n * enu - the default easting, northing, elevation.\n * neu - northing, easting, up - useful for "lat/long" geographic coordinates,\n * or south orientated transverse mercator.\n * wnu - westing, northing, up - some planetary coordinate systems have\n * "west positive" coordinate systems\n * @return {string} Axis orientation.\n * @api\n */\n\n\n Projection.prototype.getAxisOrientation = function () {\n return this.axisOrientation_;\n };\n /**\n * Is this projection a global projection which spans the whole world?\n * @return {boolean} Whether the projection is global.\n * @api\n */\n\n\n Projection.prototype.isGlobal = function () {\n return this.global_;\n };\n /**\n * Set if the projection is a global projection which spans the whole world\n * @param {boolean} global Whether the projection is global.\n * @api\n */\n\n\n Projection.prototype.setGlobal = function (global) {\n this.global_ = global;\n this.canWrapX_ = !!(global && this.extent_);\n };\n /**\n * @return {import("../tilegrid/TileGrid.js").default} The default tile grid.\n */\n\n\n Projection.prototype.getDefaultTileGrid = function () {\n return this.defaultTileGrid_;\n };\n /**\n * @param {import("../tilegrid/TileGrid.js").default} tileGrid The default tile grid.\n */\n\n\n Projection.prototype.setDefaultTileGrid = function (tileGrid) {\n this.defaultTileGrid_ = tileGrid;\n };\n /**\n * Set the validity extent for this projection.\n * @param {import("../extent.js").Extent} extent Extent.\n * @api\n */\n\n\n Projection.prototype.setExtent = function (extent) {\n this.extent_ = extent;\n this.canWrapX_ = !!(this.global_ && extent);\n };\n /**\n * Set the world extent for this projection.\n * @param {import("../extent.js").Extent} worldExtent World extent\n * [minlon, minlat, maxlon, maxlat].\n * @api\n */\n\n\n Projection.prototype.setWorldExtent = function (worldExtent) {\n this.worldExtent_ = worldExtent;\n };\n /**\n * Set the getPointResolution function (see {@link module:ol/proj~getPointResolution}\n * for this projection.\n * @param {function(number, import("../coordinate.js").Coordinate):number} func Function\n * @api\n */\n\n\n Projection.prototype.setGetPointResolution = function (func) {\n this.getPointResolutionFunc_ = func;\n };\n /**\n * Get the custom point resolution function for this projection (if set).\n * @return {function(number, import("../coordinate.js").Coordinate):number|undefined} The custom point\n * resolution function (if set).\n */\n\n\n Projection.prototype.getPointResolutionFunc = function () {\n return this.getPointResolutionFunc_;\n };\n\n return Projection;\n}();\n\n/* harmony default export */ var proj_Projection = (Projection);\n;// CONCATENATED MODULE: ./node_modules/ol/proj/epsg3857.js\nvar epsg3857_extends = undefined && undefined.__extends || function () {\n var _extendStatics = function extendStatics(d, b) {\n _extendStatics = Object.setPrototypeOf || {\n __proto__: []\n } instanceof Array && function (d, b) {\n d.__proto__ = b;\n } || function (d, b) {\n for (var p in b) {\n if (Object.prototype.hasOwnProperty.call(b, p)) d[p] = b[p];\n }\n };\n\n return _extendStatics(d, b);\n };\n\n return function (d, b) {\n _extendStatics(d, b);\n\n function __() {\n this.constructor = d;\n }\n\n d.prototype = b === null ? Object.create(b) : (__.prototype = b.prototype, new __());\n };\n}();\n/**\n * @module ol/proj/epsg3857\n */\n\n\n\n\n\n/**\n * Radius of WGS84 sphere\n *\n * @const\n * @type {number}\n */\n\nvar RADIUS = 6378137;\n/**\n * @const\n * @type {number}\n */\n\nvar HALF_SIZE = Math.PI * RADIUS;\n/**\n * @const\n * @type {import("../extent.js").Extent}\n */\n\nvar EXTENT = [-HALF_SIZE, -HALF_SIZE, HALF_SIZE, HALF_SIZE];\n/**\n * @const\n * @type {import("../extent.js").Extent}\n */\n\nvar WORLD_EXTENT = [-180, -85, 180, 85];\n/**\n * Maximum safe value in y direction\n * @const\n * @type {number}\n */\n\nvar MAX_SAFE_Y = RADIUS * Math.log(Math.tan(Math.PI / 2));\n/**\n * @classdesc\n * Projection object for web/spherical Mercator (EPSG:3857).\n */\n\nvar EPSG3857Projection =\n/** @class */\nfunction (_super) {\n epsg3857_extends(EPSG3857Projection, _super);\n /**\n * @param {string} code Code.\n */\n\n\n function EPSG3857Projection(code) {\n return _super.call(this, {\n code: code,\n units: proj_Units.METERS,\n extent: EXTENT,\n global: true,\n worldExtent: WORLD_EXTENT,\n getPointResolution: function getPointResolution(resolution, point) {\n return resolution / cosh(point[1] / RADIUS);\n }\n }) || this;\n }\n\n return EPSG3857Projection;\n}(proj_Projection);\n/**\n * Projections equal to EPSG:3857.\n *\n * @const\n * @type {Array<import("./Projection.js").default>}\n */\n\n\nvar PROJECTIONS = [new EPSG3857Projection(\'EPSG:3857\'), new EPSG3857Projection(\'EPSG:102100\'), new EPSG3857Projection(\'EPSG:102113\'), new EPSG3857Projection(\'EPSG:900913\'), new EPSG3857Projection(\'http://www.opengis.net/gml/srs/epsg.xml#3857\')];\n/**\n * Transformation from EPSG:4326 to EPSG:3857.\n *\n * @param {Array<number>} input Input array of coordinate values.\n * @param {Array<number>=} opt_output Output array of coordinate values.\n * @param {number=} opt_dimension Dimension (default is `2`).\n * @return {Array<number>} Output array of coordinate values.\n */\n\nfunction fromEPSG4326(input, opt_output, opt_dimension) {\n var length = input.length;\n var dimension = opt_dimension > 1 ? opt_dimension : 2;\n var output = opt_output;\n\n if (output === undefined) {\n if (dimension > 2) {\n // preserve values beyond second dimension\n output = input.slice();\n } else {\n output = new Array(length);\n }\n }\n\n for (var i = 0; i < length; i += dimension) {\n output[i] = HALF_SIZE * input[i] / 180;\n var y = RADIUS * Math.log(Math.tan(Math.PI * (+input[i + 1] + 90) / 360));\n\n if (y > MAX_SAFE_Y) {\n y = MAX_SAFE_Y;\n } else if (y < -MAX_SAFE_Y) {\n y = -MAX_SAFE_Y;\n }\n\n output[i + 1] = y;\n }\n\n return output;\n}\n/**\n * Transformation from EPSG:3857 to EPSG:4326.\n *\n * @param {Array<number>} input Input array of coordinate values.\n * @param {Array<number>=} opt_output Output array of coordinate values.\n * @param {number=} opt_dimension Dimension (default is `2`).\n * @return {Array<number>} Output array of coordinate values.\n */\n\nfunction toEPSG4326(input, opt_output, opt_dimension) {\n var length = input.length;\n var dimension = opt_dimension > 1 ? opt_dimension : 2;\n var output = opt_output;\n\n if (output === undefined) {\n if (dimension > 2) {\n // preserve values beyond second dimension\n output = input.slice();\n } else {\n output = new Array(length);\n }\n }\n\n for (var i = 0; i < length; i += dimension) {\n output[i] = 180 * input[i] / HALF_SIZE;\n output[i + 1] = 360 * Math.atan(Math.exp(input[i + 1] / RADIUS)) / Math.PI - 90;\n }\n\n return output;\n}\n;// CONCATENATED MODULE: ./node_modules/ol/proj/epsg4326.js\nvar epsg4326_extends = undefined && undefined.__extends || function () {\n var _extendStatics = function extendStatics(d, b) {\n _extendStatics = Object.setPrototypeOf || {\n __proto__: []\n } instanceof Array && function (d, b) {\n d.__proto__ = b;\n } || function (d, b) {\n for (var p in b) {\n if (Object.prototype.hasOwnProperty.call(b, p)) d[p] = b[p];\n }\n };\n\n return _extendStatics(d, b);\n };\n\n return function (d, b) {\n _extendStatics(d, b);\n\n function __() {\n this.constructor = d;\n }\n\n d.prototype = b === null ? Object.create(b) : (__.prototype = b.prototype, new __());\n };\n}();\n/**\n * @module ol/proj/epsg4326\n */\n\n\n\n\n/**\n * Semi-major radius of the WGS84 ellipsoid.\n *\n * @const\n * @type {number}\n */\n\nvar epsg4326_RADIUS = 6378137;\n/**\n * Extent of the EPSG:4326 projection which is the whole world.\n *\n * @const\n * @type {import("../extent.js").Extent}\n */\n\nvar epsg4326_EXTENT = [-180, -90, 180, 90];\n/**\n * @const\n * @type {number}\n */\n\nvar epsg4326_METERS_PER_UNIT = Math.PI * epsg4326_RADIUS / 180;\n/**\n * @classdesc\n * Projection object for WGS84 geographic coordinates (EPSG:4326).\n *\n * Note that OpenLayers does not strictly comply with the EPSG definition.\n * The EPSG registry defines 4326 as a CRS for Latitude,Longitude (y,x).\n * OpenLayers treats EPSG:4326 as a pseudo-projection, with x,y coordinates.\n */\n\nvar EPSG4326Projection =\n/** @class */\nfunction (_super) {\n epsg4326_extends(EPSG4326Projection, _super);\n /**\n * @param {string} code Code.\n * @param {string=} opt_axisOrientation Axis orientation.\n */\n\n\n function EPSG4326Projection(code, opt_axisOrientation) {\n return _super.call(this, {\n code: code,\n units: proj_Units.DEGREES,\n extent: epsg4326_EXTENT,\n axisOrientation: opt_axisOrientation,\n global: true,\n metersPerUnit: epsg4326_METERS_PER_UNIT,\n worldExtent: epsg4326_EXTENT\n }) || this;\n }\n\n return EPSG4326Projection;\n}(proj_Projection);\n/**\n * Projections equal to EPSG:4326.\n *\n * @const\n * @type {Array<import("./Projection.js").default>}\n */\n\n\nvar epsg4326_PROJECTIONS = [new EPSG4326Projection(\'CRS:84\'), new EPSG4326Projection(\'EPSG:4326\', \'neu\'), new EPSG4326Projection(\'urn:ogc:def:crs:OGC:1.3:CRS84\'), new EPSG4326Projection(\'urn:ogc:def:crs:OGC:2:84\'), new EPSG4326Projection(\'http://www.opengis.net/gml/srs/epsg.xml#4326\', \'neu\')];\n;// CONCATENATED MODULE: ./node_modules/ol/proj/projections.js\n/**\n * @module ol/proj/projections\n */\n\n/**\n * @type {Object<string, import("./Projection.js").default>}\n */\nvar cache = {};\n/**\n * Clear the projections cache.\n */\n\nfunction projections_clear() {\n cache = {};\n}\n/**\n * Get a cached projection by code.\n * @param {string} code The code for the projection.\n * @return {import("./Projection.js").default} The projection (if cached).\n */\n\nfunction get(code) {\n return cache[code] || cache[code.replace(/urn:(x-)?ogc:def:crs:EPSG:(.*:)?(\\w+)$/, \'EPSG:$3\')] || null;\n}\n/**\n * Add a projection to the cache.\n * @param {string} code The projection code.\n * @param {import("./Projection.js").default} projection The projection to cache.\n */\n\nfunction projections_add(code, projection) {\n cache[code] = projection;\n}\n;// CONCATENATED MODULE: ./node_modules/ol/proj/transforms.js\n/**\n * @module ol/proj/transforms\n */\n\n/**\n * @private\n * @type {!Object<string, Object<string, import("../proj.js").TransformFunction>>}\n */\n\nvar transforms = {};\n/**\n * Clear the transform cache.\n */\n\nfunction transforms_clear() {\n transforms = {};\n}\n/**\n * Registers a conversion function to convert coordinates from the source\n * projection to the destination projection.\n *\n * @param {import("./Projection.js").default} source Source.\n * @param {import("./Projection.js").default} destination Destination.\n * @param {import("../proj.js").TransformFunction} transformFn Transform.\n */\n\nfunction transforms_add(source, destination, transformFn) {\n var sourceCode = source.getCode();\n var destinationCode = destination.getCode();\n\n if (!(sourceCode in transforms)) {\n transforms[sourceCode] = {};\n }\n\n transforms[sourceCode][destinationCode] = transformFn;\n}\n/**\n * Unregisters the conversion function to convert coordinates from the source\n * projection to the destination projection. This method is used to clean up\n * cached transforms during testing.\n *\n * @param {import("./Projection.js").default} source Source projection.\n * @param {import("./Projection.js").default} destination Destination projection.\n * @return {import("../proj.js").TransformFunction} transformFn The unregistered transform.\n */\n\nfunction transforms_remove(source, destination) {\n var sourceCode = source.getCode();\n var destinationCode = destination.getCode();\n var transform = transforms[sourceCode][destinationCode];\n delete transforms[sourceCode][destinationCode];\n\n if (isEmpty(transforms[sourceCode])) {\n delete transforms[sourceCode];\n }\n\n return transform;\n}\n/**\n * Get a transform given a source code and a destination code.\n * @param {string} sourceCode The code for the source projection.\n * @param {string} destinationCode The code for the destination projection.\n * @return {import("../proj.js").TransformFunction|undefined} The transform function (if found).\n */\n\nfunction transforms_get(sourceCode, destinationCode) {\n var transform;\n\n if (sourceCode in transforms && destinationCode in transforms[sourceCode]) {\n transform = transforms[sourceCode][destinationCode];\n }\n\n return transform;\n}\n;// CONCATENATED MODULE: ./node_modules/ol/sphere.js\n/**\n * @module ol/sphere\n */\n\n\n/**\n * Object literal with options for the {@link getLength} or {@link getArea}\n * functions.\n * @typedef {Object} SphereMetricOptions\n * @property {import("./proj.js").ProjectionLike} [projection=\'EPSG:3857\']\n * Projection of the geometry. By default, the geometry is assumed to be in\n * Web Mercator.\n * @property {number} [radius=6371008.8] Sphere radius. By default, the\n * [mean Earth radius](https://en.wikipedia.org/wiki/Earth_radius#Mean_radius)\n * for the WGS84 ellipsoid is used.\n */\n\n/**\n * The mean Earth radius (1/3 * (2a + b)) for the WGS84 ellipsoid.\n * https://en.wikipedia.org/wiki/Earth_radius#Mean_radius\n * @type {number}\n */\n\nvar DEFAULT_RADIUS = 6371008.8;\n/**\n * Get the great circle distance (in meters) between two geographic coordinates.\n * @param {Array} c1 Starting coordinate.\n * @param {Array} c2 Ending coordinate.\n * @param {number=} opt_radius The sphere radius to use. Defaults to the Earth\'s\n * mean radius using the WGS84 ellipsoid.\n * @return {number} The great circle distance between the points (in meters).\n * @api\n */\n\nfunction getDistance(c1, c2, opt_radius) {\n var radius = opt_radius || DEFAULT_RADIUS;\n var lat1 = math_toRadians(c1[1]);\n var lat2 = math_toRadians(c2[1]);\n var deltaLatBy2 = (lat2 - lat1) / 2;\n var deltaLonBy2 = math_toRadians(c2[0] - c1[0]) / 2;\n var a = Math.sin(deltaLatBy2) * Math.sin(deltaLatBy2) + Math.sin(deltaLonBy2) * Math.sin(deltaLonBy2) * Math.cos(lat1) * Math.cos(lat2);\n return 2 * radius * Math.atan2(Math.sqrt(a), Math.sqrt(1 - a));\n}\n/**\n * Get the cumulative great circle length of linestring coordinates (geographic).\n * @param {Array} coordinates Linestring coordinates.\n * @param {number} radius The sphere radius to use.\n * @return {number} The length (in meters).\n */\n\nfunction getLengthInternal(coordinates, radius) {\n var length = 0;\n\n for (var i = 0, ii = coordinates.length; i < ii - 1; ++i) {\n length += getDistance(coordinates[i], coordinates[i + 1], radius);\n }\n\n return length;\n}\n/**\n * Get the spherical length of a geometry. This length is the sum of the\n * great circle distances between coordinates. For polygons, the length is\n * the sum of all rings. For points, the length is zero. For multi-part\n * geometries, the length is the sum of the length of each part.\n * @param {import("./geom/Geometry.js").default} geometry A geometry.\n * @param {SphereMetricOptions=} opt_options Options for the\n * length calculation. By default, geometries are assumed to be in \'EPSG:3857\'.\n * You can change this by providing a `projection` option.\n * @return {number} The spherical length (in meters).\n * @api\n */\n\n\nfunction getLength(geometry, opt_options) {\n var options = opt_options || {};\n var radius = options.radius || DEFAULT_RADIUS;\n var projection = options.projection || \'EPSG:3857\';\n var type = geometry.getType();\n\n if (type !== GeometryType.GEOMETRY_COLLECTION) {\n geometry = geometry.clone().transform(projection, \'EPSG:4326\');\n }\n\n var length = 0;\n var coordinates, coords, i, ii, j, jj;\n\n switch (type) {\n case GeometryType.POINT:\n case GeometryType.MULTI_POINT:\n {\n break;\n }\n\n case GeometryType.LINE_STRING:\n case GeometryType.LINEAR_RING:\n {\n coordinates =\n /** @type {import("./geom/SimpleGeometry.js").default} */\n geometry.getCoordinates();\n length = getLengthInternal(coordinates, radius);\n break;\n }\n\n case GeometryType.MULTI_LINE_STRING:\n case GeometryType.POLYGON:\n {\n coordinates =\n /** @type {import("./geom/SimpleGeometry.js").default} */\n geometry.getCoordinates();\n\n for (i = 0, ii = coordinates.length; i < ii; ++i) {\n length += getLengthInternal(coordinates[i], radius);\n }\n\n break;\n }\n\n case GeometryType.MULTI_POLYGON:\n {\n coordinates =\n /** @type {import("./geom/SimpleGeometry.js").default} */\n geometry.getCoordinates();\n\n for (i = 0, ii = coordinates.length; i < ii; ++i) {\n coords = coordinates[i];\n\n for (j = 0, jj = coords.length; j < jj; ++j) {\n length += getLengthInternal(coords[j], radius);\n }\n }\n\n break;\n }\n\n case GeometryType.GEOMETRY_COLLECTION:\n {\n var geometries =\n /** @type {import("./geom/GeometryCollection.js").default} */\n geometry.getGeometries();\n\n for (i = 0, ii = geometries.length; i < ii; ++i) {\n length += getLength(geometries[i], opt_options);\n }\n\n break;\n }\n\n default:\n {\n throw new Error(\'Unsupported geometry type: \' + type);\n }\n }\n\n return length;\n}\n/**\n * Returns the spherical area for a list of coordinates.\n *\n * [Reference](https://trs-new.jpl.nasa.gov/handle/2014/40409)\n * Robert. G. Chamberlain and William H. Duquette, "Some Algorithms for\n * Polygons on a Sphere", JPL Publication 07-03, Jet Propulsion\n * Laboratory, Pasadena, CA, June 2007\n *\n * @param {Array<import("./coordinate.js").Coordinate>} coordinates List of coordinates of a linear\n * ring. If the ring is oriented clockwise, the area will be positive,\n * otherwise it will be negative.\n * @param {number} radius The sphere radius.\n * @return {number} Area (in square meters).\n */\n\nfunction getAreaInternal(coordinates, radius) {\n var area = 0;\n var len = coordinates.length;\n var x1 = coordinates[len - 1][0];\n var y1 = coordinates[len - 1][1];\n\n for (var i = 0; i < len; i++) {\n var x2 = coordinates[i][0];\n var y2 = coordinates[i][1];\n area += toRadians(x2 - x1) * (2 + Math.sin(toRadians(y1)) + Math.sin(toRadians(y2)));\n x1 = x2;\n y1 = y2;\n }\n\n return area * radius * radius / 2.0;\n}\n/**\n * Get the spherical area of a geometry. This is the area (in meters) assuming\n * that polygon edges are segments of great circles on a sphere.\n * @param {import("./geom/Geometry.js").default} geometry A geometry.\n * @param {SphereMetricOptions=} opt_options Options for the area\n * calculation. By default, geometries are assumed to be in \'EPSG:3857\'.\n * You can change this by providing a `projection` option.\n * @return {number} The spherical area (in square meters).\n * @api\n */\n\n\nfunction sphere_getArea(geometry, opt_options) {\n var options = opt_options || {};\n var radius = options.radius || DEFAULT_RADIUS;\n var projection = options.projection || \'EPSG:3857\';\n var type = geometry.getType();\n\n if (type !== GeometryType.GEOMETRY_COLLECTION) {\n geometry = geometry.clone().transform(projection, \'EPSG:4326\');\n }\n\n var area = 0;\n var coordinates, coords, i, ii, j, jj;\n\n switch (type) {\n case GeometryType.POINT:\n case GeometryType.MULTI_POINT:\n case GeometryType.LINE_STRING:\n case GeometryType.MULTI_LINE_STRING:\n case GeometryType.LINEAR_RING:\n {\n break;\n }\n\n case GeometryType.POLYGON:\n {\n coordinates =\n /** @type {import("./geom/Polygon.js").default} */\n geometry.getCoordinates();\n area = Math.abs(getAreaInternal(coordinates[0], radius));\n\n for (i = 1, ii = coordinates.length; i < ii; ++i) {\n area -= Math.abs(getAreaInternal(coordinates[i], radius));\n }\n\n break;\n }\n\n case GeometryType.MULTI_POLYGON:\n {\n coordinates =\n /** @type {import("./geom/SimpleGeometry.js").default} */\n geometry.getCoordinates();\n\n for (i = 0, ii = coordinates.length; i < ii; ++i) {\n coords = coordinates[i];\n area += Math.abs(getAreaInternal(coords[0], radius));\n\n for (j = 1, jj = coords.length; j < jj; ++j) {\n area -= Math.abs(getAreaInternal(coords[j], radius));\n }\n }\n\n break;\n }\n\n case GeometryType.GEOMETRY_COLLECTION:\n {\n var geometries =\n /** @type {import("./geom/GeometryCollection.js").default} */\n geometry.getGeometries();\n\n for (i = 0, ii = geometries.length; i < ii; ++i) {\n area += sphere_getArea(geometries[i], opt_options);\n }\n\n break;\n }\n\n default:\n {\n throw new Error(\'Unsupported geometry type: \' + type);\n }\n }\n\n return area;\n}\n/**\n * Returns the coordinate at the given distance and bearing from `c1`.\n *\n * @param {import("./coordinate.js").Coordinate} c1 The origin point (`[lon, lat]` in degrees).\n * @param {number} distance The great-circle distance between the origin\n * point and the target point.\n * @param {number} bearing The bearing (in radians).\n * @param {number=} opt_radius The sphere radius to use. Defaults to the Earth\'s\n * mean radius using the WGS84 ellipsoid.\n * @return {import("./coordinate.js").Coordinate} The target point.\n */\n\nfunction offset(c1, distance, bearing, opt_radius) {\n var radius = opt_radius || DEFAULT_RADIUS;\n var lat1 = toRadians(c1[1]);\n var lon1 = toRadians(c1[0]);\n var dByR = distance / radius;\n var lat = Math.asin(Math.sin(lat1) * Math.cos(dByR) + Math.cos(lat1) * Math.sin(dByR) * Math.cos(bearing));\n var lon = lon1 + Math.atan2(Math.sin(bearing) * Math.sin(dByR) * Math.cos(lat1), Math.cos(dByR) - Math.sin(lat1) * Math.sin(lat));\n return [toDegrees(lon), toDegrees(lat)];\n}\n;// CONCATENATED MODULE: ./node_modules/ol/proj.js\n/**\n * @module ol/proj\n */\n\n/**\n * The ol/proj module stores:\n * * a list of {@link module:ol/proj/Projection}\n * objects, one for each projection supported by the application\n * * a list of transform functions needed to convert coordinates in one projection\n * into another.\n *\n * The static functions are the methods used to maintain these.\n * Each transform function can handle not only simple coordinate pairs, but also\n * large arrays of coordinates such as vector geometries.\n *\n * When loaded, the library adds projection objects for EPSG:4326 (WGS84\n * geographic coordinates) and EPSG:3857 (Web or Spherical Mercator, as used\n * for example by Bing Maps or OpenStreetMap), together with the relevant\n * transform functions.\n *\n * Additional transforms may be added by using the http://proj4js.org/\n * library (version 2.2 or later). You can use the full build supplied by\n * Proj4js, or create a custom build to support those projections you need; see\n * the Proj4js website for how to do this. You also need the Proj4js definitions\n * for the required projections. These definitions can be obtained from\n * https://epsg.io/, and are a JS function, so can be loaded in a script\n * tag (as in the examples) or pasted into your application.\n *\n * After all required projection definitions are added to proj4\'s registry (by\n * using `proj4.defs()`), simply call `register(proj4)` from the `ol/proj/proj4`\n * package. Existing transforms are not changed by this function. See\n * examples/wms-image-custom-proj for an example of this.\n *\n * Additional projection definitions can be registered with `proj4.defs()` any\n * time. Just make sure to call `register(proj4)` again; for example, with user-supplied data where you don\'t\n * know in advance what projections are needed, you can initially load minimal\n * support and then load whichever are requested.\n *\n * Note that Proj4js does not support projection extents. If you want to add\n * one for creating default tile grids, you can add it after the Projection\n * object has been created with `setExtent`, for example,\n * `get(\'EPSG:1234\').setExtent(extent)`.\n *\n * In addition to Proj4js support, any transform functions can be added with\n * {@link module:ol/proj~addCoordinateTransforms}. To use this, you must first create\n * a {@link module:ol/proj/Projection} object for the new projection and add it with\n * {@link module:ol/proj~addProjection}. You can then add the forward and inverse\n * functions with {@link module:ol/proj~addCoordinateTransforms}. See\n * examples/wms-custom-proj for an example of this.\n *\n * Note that if no transforms are needed and you only need to define the\n * projection, just add a {@link module:ol/proj/Projection} with\n * {@link module:ol/proj~addProjection}. See examples/wms-no-proj for an example of\n * this.\n */\n\n\n\n\n\n\n\n\n\n\n/**\n * A projection as {@link module:ol/proj/Projection}, SRS identifier\n * string or undefined.\n * @typedef {Projection|string|undefined} ProjectionLike\n * @api\n */\n\n/**\n * A transform function accepts an array of input coordinate values, an optional\n * output array, and an optional dimension (default should be 2). The function\n * transforms the input coordinate values, populates the output array, and\n * returns the output array.\n *\n * @typedef {function(Array<number>, Array<number>=, number=): Array<number>} TransformFunction\n * @api\n */\n\n\n\n/**\n * @param {Array<number>} input Input coordinate array.\n * @param {Array<number>=} opt_output Output array of coordinate values.\n * @param {number=} opt_dimension Dimension.\n * @return {Array<number>} Output coordinate array (new array, same coordinate\n * values).\n */\n\nfunction cloneTransform(input, opt_output, opt_dimension) {\n var output;\n\n if (opt_output !== undefined) {\n for (var i = 0, ii = input.length; i < ii; ++i) {\n opt_output[i] = input[i];\n }\n\n output = opt_output;\n } else {\n output = input.slice();\n }\n\n return output;\n}\n/**\n * @param {Array<number>} input Input coordinate array.\n * @param {Array<number>=} opt_output Output array of coordinate values.\n * @param {number=} opt_dimension Dimension.\n * @return {Array<number>} Input coordinate array (same array as input).\n */\n\nfunction identityTransform(input, opt_output, opt_dimension) {\n if (opt_output !== undefined && input !== opt_output) {\n for (var i = 0, ii = input.length; i < ii; ++i) {\n opt_output[i] = input[i];\n }\n\n input = opt_output;\n }\n\n return input;\n}\n/**\n * Add a Projection object to the list of supported projections that can be\n * looked up by their code.\n *\n * @param {Projection} projection Projection instance.\n * @api\n */\n\nfunction addProjection(projection) {\n projections_add(projection.getCode(), projection);\n transforms_add(projection, projection, cloneTransform);\n}\n/**\n * @param {Array<Projection>} projections Projections.\n */\n\nfunction addProjections(projections) {\n projections.forEach(addProjection);\n}\n/**\n * Fetches a Projection object for the code specified.\n *\n * @param {ProjectionLike} projectionLike Either a code string which is\n * a combination of authority and identifier such as "EPSG:4326", or an\n * existing projection object, or undefined.\n * @return {Projection} Projection object, or null if not in list.\n * @api\n */\n\nfunction proj_get(projectionLike) {\n return typeof projectionLike === \'string\' ? get(\n /** @type {string} */\n projectionLike) :\n /** @type {Projection} */\n projectionLike || null;\n}\n/**\n * Get the resolution of the point in degrees or distance units.\n * For projections with degrees as the unit this will simply return the\n * provided resolution. For other projections the point resolution is\n * by default estimated by transforming the \'point\' pixel to EPSG:4326,\n * measuring its width and height on the normal sphere,\n * and taking the average of the width and height.\n * A custom function can be provided for a specific projection, either\n * by setting the `getPointResolution` option in the\n * {@link module:ol/proj/Projection~Projection} constructor or by using\n * {@link module:ol/proj/Projection~Projection#setGetPointResolution} to change an existing\n * projection object.\n * @param {ProjectionLike} projection The projection.\n * @param {number} resolution Nominal resolution in projection units.\n * @param {import("./coordinate.js").Coordinate} point Point to find adjusted resolution at.\n * @param {import("./proj/Units.js").default=} opt_units Units to get the point resolution in.\n * Default is the projection\'s units.\n * @return {number} Point resolution.\n * @api\n */\n\nfunction getPointResolution(projection, resolution, point, opt_units) {\n projection = proj_get(projection);\n var pointResolution;\n var getter = projection.getPointResolutionFunc();\n\n if (getter) {\n pointResolution = getter(resolution, point);\n\n if (opt_units && opt_units !== projection.getUnits()) {\n var metersPerUnit = projection.getMetersPerUnit();\n\n if (metersPerUnit) {\n pointResolution = pointResolution * metersPerUnit / METERS_PER_UNIT[opt_units];\n }\n }\n } else {\n var units = projection.getUnits();\n\n if (units == proj_Units.DEGREES && !opt_units || opt_units == proj_Units.DEGREES) {\n pointResolution = resolution;\n } else {\n // Estimate point resolution by transforming the center pixel to EPSG:4326,\n // measuring its width and height on the normal sphere, and taking the\n // average of the width and height.\n var toEPSG4326_1 = getTransformFromProjections(projection, proj_get(\'EPSG:4326\'));\n\n if (toEPSG4326_1 === identityTransform && units !== proj_Units.DEGREES) {\n // no transform is available\n pointResolution = resolution * projection.getMetersPerUnit();\n } else {\n var vertices = [point[0] - resolution / 2, point[1], point[0] + resolution / 2, point[1], point[0], point[1] - resolution / 2, point[0], point[1] + resolution / 2];\n vertices = toEPSG4326_1(vertices, vertices, 2);\n var width = getDistance(vertices.slice(0, 2), vertices.slice(2, 4));\n var height = getDistance(vertices.slice(4, 6), vertices.slice(6, 8));\n pointResolution = (width + height) / 2;\n }\n\n var metersPerUnit = opt_units ? METERS_PER_UNIT[opt_units] : projection.getMetersPerUnit();\n\n if (metersPerUnit !== undefined) {\n pointResolution /= metersPerUnit;\n }\n }\n }\n\n return pointResolution;\n}\n/**\n * Registers transformation functions that don\'t alter coordinates. Those allow\n * to transform between projections with equal meaning.\n *\n * @param {Array<Projection>} projections Projections.\n * @api\n */\n\nfunction addEquivalentProjections(projections) {\n addProjections(projections);\n projections.forEach(function (source) {\n projections.forEach(function (destination) {\n if (source !== destination) {\n transforms_add(source, destination, cloneTransform);\n }\n });\n });\n}\n/**\n * Registers transformation functions to convert coordinates in any projection\n * in projection1 to any projection in projection2.\n *\n * @param {Array<Projection>} projections1 Projections with equal\n * meaning.\n * @param {Array<Projection>} projections2 Projections with equal\n * meaning.\n * @param {TransformFunction} forwardTransform Transformation from any\n * projection in projection1 to any projection in projection2.\n * @param {TransformFunction} inverseTransform Transform from any projection\n * in projection2 to any projection in projection1..\n */\n\nfunction addEquivalentTransforms(projections1, projections2, forwardTransform, inverseTransform) {\n projections1.forEach(function (projection1) {\n projections2.forEach(function (projection2) {\n transforms_add(projection1, projection2, forwardTransform);\n transforms_add(projection2, projection1, inverseTransform);\n });\n });\n}\n/**\n * Clear all cached projections and transforms.\n */\n\nfunction clearAllProjections() {\n clearProj();\n clearTransformFuncs();\n}\n/**\n * @param {Projection|string|undefined} projection Projection.\n * @param {string} defaultCode Default code.\n * @return {Projection} Projection.\n */\n\nfunction createProjection(projection, defaultCode) {\n if (!projection) {\n return proj_get(defaultCode);\n } else if (typeof projection === \'string\') {\n return proj_get(projection);\n } else {\n return (\n /** @type {Projection} */\n projection\n );\n }\n}\n/**\n * Creates a {@link module:ol/proj~TransformFunction} from a simple 2D coordinate transform\n * function.\n * @param {function(import("./coordinate.js").Coordinate): import("./coordinate.js").Coordinate} coordTransform Coordinate\n * transform.\n * @return {TransformFunction} Transform function.\n */\n\nfunction createTransformFromCoordinateTransform(coordTransform) {\n return (\n /**\n * @param {Array<number>} input Input.\n * @param {Array<number>=} opt_output Output.\n * @param {number=} opt_dimension Dimension.\n * @return {Array<number>} Output.\n */\n function (input, opt_output, opt_dimension) {\n var length = input.length;\n var dimension = opt_dimension !== undefined ? opt_dimension : 2;\n var output = opt_output !== undefined ? opt_output : new Array(length);\n\n for (var i = 0; i < length; i += dimension) {\n var point = coordTransform([input[i], input[i + 1]]);\n output[i] = point[0];\n output[i + 1] = point[1];\n\n for (var j = dimension - 1; j >= 2; --j) {\n output[i + j] = input[i + j];\n }\n }\n\n return output;\n }\n );\n}\n/**\n * Registers coordinate transform functions to convert coordinates between the\n * source projection and the destination projection.\n * The forward and inverse functions convert coordinate pairs; this function\n * converts these into the functions used internally which also handle\n * extents and coordinate arrays.\n *\n * @param {ProjectionLike} source Source projection.\n * @param {ProjectionLike} destination Destination projection.\n * @param {function(import("./coordinate.js").Coordinate): import("./coordinate.js").Coordinate} forward The forward transform\n * function (that is, from the source projection to the destination\n * projection) that takes a {@link module:ol/coordinate~Coordinate} as argument and returns\n * the transformed {@link module:ol/coordinate~Coordinate}.\n * @param {function(import("./coordinate.js").Coordinate): import("./coordinate.js").Coordinate} inverse The inverse transform\n * function (that is, from the destination projection to the source\n * projection) that takes a {@link module:ol/coordinate~Coordinate} as argument and returns\n * the transformed {@link module:ol/coordinate~Coordinate}.\n * @api\n */\n\nfunction addCoordinateTransforms(source, destination, forward, inverse) {\n var sourceProj = proj_get(source);\n var destProj = proj_get(destination);\n addTransformFunc(sourceProj, destProj, createTransformFromCoordinateTransform(forward));\n addTransformFunc(destProj, sourceProj, createTransformFromCoordinateTransform(inverse));\n}\n/**\n * Transforms a coordinate from longitude/latitude to a different projection.\n * @param {import("./coordinate.js").Coordinate} coordinate Coordinate as longitude and latitude, i.e.\n * an array with longitude as 1st and latitude as 2nd element.\n * @param {ProjectionLike=} opt_projection Target projection. The\n * default is Web Mercator, i.e. \'EPSG:3857\'.\n * @return {import("./coordinate.js").Coordinate} Coordinate projected to the target projection.\n * @api\n */\n\nfunction fromLonLat(coordinate, opt_projection) {\n return transform(coordinate, \'EPSG:4326\', opt_projection !== undefined ? opt_projection : \'EPSG:3857\');\n}\n/**\n * Transforms a coordinate to longitude/latitude.\n * @param {import("./coordinate.js").Coordinate} coordinate Projected coordinate.\n * @param {ProjectionLike=} opt_projection Projection of the coordinate.\n * The default is Web Mercator, i.e. \'EPSG:3857\'.\n * @return {import("./coordinate.js").Coordinate} Coordinate as longitude and latitude, i.e. an array\n * with longitude as 1st and latitude as 2nd element.\n * @api\n */\n\nfunction toLonLat(coordinate, opt_projection) {\n var lonLat = transform(coordinate, opt_projection !== undefined ? opt_projection : \'EPSG:3857\', \'EPSG:4326\');\n var lon = lonLat[0];\n\n if (lon < -180 || lon > 180) {\n lonLat[0] = modulo(lon + 180, 360) - 180;\n }\n\n return lonLat;\n}\n/**\n * Checks if two projections are the same, that is every coordinate in one\n * projection does represent the same geographic point as the same coordinate in\n * the other projection.\n *\n * @param {Projection} projection1 Projection 1.\n * @param {Projection} projection2 Projection 2.\n * @return {boolean} Equivalent.\n * @api\n */\n\nfunction equivalent(projection1, projection2) {\n if (projection1 === projection2) {\n return true;\n }\n\n var equalUnits = projection1.getUnits() === projection2.getUnits();\n\n if (projection1.getCode() === projection2.getCode()) {\n return equalUnits;\n } else {\n var transformFunc = getTransformFromProjections(projection1, projection2);\n return transformFunc === cloneTransform && equalUnits;\n }\n}\n/**\n * Searches in the list of transform functions for the function for converting\n * coordinates from the source projection to the destination projection.\n *\n * @param {Projection} sourceProjection Source Projection object.\n * @param {Projection} destinationProjection Destination Projection\n * object.\n * @return {TransformFunction} Transform function.\n */\n\nfunction getTransformFromProjections(sourceProjection, destinationProjection) {\n var sourceCode = sourceProjection.getCode();\n var destinationCode = destinationProjection.getCode();\n var transformFunc = transforms_get(sourceCode, destinationCode);\n\n if (!transformFunc) {\n transformFunc = identityTransform;\n }\n\n return transformFunc;\n}\n/**\n * Given the projection-like objects, searches for a transformation\n * function to convert a coordinates array from the source projection to the\n * destination projection.\n *\n * @param {ProjectionLike} source Source.\n * @param {ProjectionLike} destination Destination.\n * @return {TransformFunction} Transform function.\n * @api\n */\n\nfunction getTransform(source, destination) {\n var sourceProjection = proj_get(source);\n var destinationProjection = proj_get(destination);\n return getTransformFromProjections(sourceProjection, destinationProjection);\n}\n/**\n * Transforms a coordinate from source projection to destination projection.\n * This returns a new coordinate (and does not modify the original).\n *\n * See {@link module:ol/proj~transformExtent} for extent transformation.\n * See the transform method of {@link module:ol/geom/Geometry~Geometry} and its\n * subclasses for geometry transforms.\n *\n * @param {import("./coordinate.js").Coordinate} coordinate Coordinate.\n * @param {ProjectionLike} source Source projection-like.\n * @param {ProjectionLike} destination Destination projection-like.\n * @return {import("./coordinate.js").Coordinate} Coordinate.\n * @api\n */\n\nfunction transform(coordinate, source, destination) {\n var transformFunc = getTransform(source, destination);\n return transformFunc(coordinate, undefined, coordinate.length);\n}\n/**\n * Transforms an extent from source projection to destination projection. This\n * returns a new extent (and does not modify the original).\n *\n * @param {import("./extent.js").Extent} extent The extent to transform.\n * @param {ProjectionLike} source Source projection-like.\n * @param {ProjectionLike} destination Destination projection-like.\n * @param {number=} opt_stops Number of stops per side used for the transform.\n * By default only the corners are used.\n * @return {import("./extent.js").Extent} The transformed extent.\n * @api\n */\n\nfunction proj_transformExtent(extent, source, destination, opt_stops) {\n var transformFunc = getTransform(source, destination);\n return applyTransform(extent, transformFunc, undefined, opt_stops);\n}\n/**\n * Transforms the given point to the destination projection.\n *\n * @param {import("./coordinate.js").Coordinate} point Point.\n * @param {Projection} sourceProjection Source projection.\n * @param {Projection} destinationProjection Destination projection.\n * @return {import("./coordinate.js").Coordinate} Point.\n */\n\nfunction transformWithProjections(point, sourceProjection, destinationProjection) {\n var transformFunc = getTransformFromProjections(sourceProjection, destinationProjection);\n return transformFunc(point);\n}\n/**\n * @type {?Projection}\n */\n\nvar userProjection = null;\n/**\n * Set the projection for coordinates supplied from and returned by API methods.\n * Note that this method is not yet a part of the stable API. Support for user\n * projections is not yet complete and should be considered experimental.\n * @param {ProjectionLike} projection The user projection.\n */\n\nfunction setUserProjection(projection) {\n userProjection = proj_get(projection);\n}\n/**\n * Clear the user projection if set. Note that this method is not yet a part of\n * the stable API. Support for user projections is not yet complete and should\n * be considered experimental.\n */\n\nfunction clearUserProjection() {\n userProjection = null;\n}\n/**\n * Get the projection for coordinates supplied from and returned by API methods.\n * Note that this method is not yet a part of the stable API. Support for user\n * projections is not yet complete and should be considered experimental.\n * @returns {?Projection} The user projection (or null if not set).\n */\n\nfunction getUserProjection() {\n return userProjection;\n}\n/**\n * Use geographic coordinates (WGS-84 datum) in API methods. Note that this\n * method is not yet a part of the stable API. Support for user projections is\n * not yet complete and should be considered experimental.\n */\n\nfunction useGeographic() {\n setUserProjection(\'EPSG:4326\');\n}\n/**\n * Return a coordinate transformed into the user projection. If no user projection\n * is set, the original coordinate is returned.\n * @param {Array<number>} coordinate Input coordinate.\n * @param {ProjectionLike} sourceProjection The input coordinate projection.\n * @returns {Array<number>} The input coordinate in the user projection.\n */\n\nfunction toUserCoordinate(coordinate, sourceProjection) {\n if (!userProjection) {\n return coordinate;\n }\n\n return transform(coordinate, sourceProjection, userProjection);\n}\n/**\n * Return a coordinate transformed from the user projection. If no user projection\n * is set, the original coordinate is returned.\n * @param {Array<number>} coordinate Input coordinate.\n * @param {ProjectionLike} destProjection The destination projection.\n * @returns {Array<number>} The input coordinate transformed.\n */\n\nfunction fromUserCoordinate(coordinate, destProjection) {\n if (!userProjection) {\n return coordinate;\n }\n\n return transform(coordinate, userProjection, destProjection);\n}\n/**\n * Return an extent transformed into the user projection. If no user projection\n * is set, the original extent is returned.\n * @param {import("./extent.js").Extent} extent Input extent.\n * @param {ProjectionLike} sourceProjection The input extent projection.\n * @returns {import("./extent.js").Extent} The input extent in the user projection.\n */\n\nfunction toUserExtent(extent, sourceProjection) {\n if (!userProjection) {\n return extent;\n }\n\n return proj_transformExtent(extent, sourceProjection, userProjection);\n}\n/**\n * Return an extent transformed from the user projection. If no user projection\n * is set, the original extent is returned.\n * @param {import("./extent.js").Extent} extent Input extent.\n * @param {ProjectionLike} destProjection The destination projection.\n * @returns {import("./extent.js").Extent} The input extent transformed.\n */\n\nfunction fromUserExtent(extent, destProjection) {\n if (!userProjection) {\n return extent;\n }\n\n return proj_transformExtent(extent, userProjection, destProjection);\n}\n/**\n * Creates a safe coordinate transform function from a coordinate transform function.\n * "Safe" means that it can handle wrapping of x-coordinates for global projections,\n * and that coordinates exceeding the source projection validity extent\'s range will be\n * clamped to the validity range.\n * @param {Projection} sourceProj Source projection.\n * @param {Projection} destProj Destination projection.\n * @param {function(import("./coordinate.js").Coordinate): import("./coordinate.js").Coordinate} transform Transform function (source to destiation).\n * @return {function(import("./coordinate.js").Coordinate): import("./coordinate.js").Coordinate} Safe transform function (source to destiation).\n */\n\nfunction createSafeCoordinateTransform(sourceProj, destProj, transform) {\n return function (coord) {\n var sourceX = coord[0];\n var sourceY = coord[1];\n var transformed, worldsAway;\n\n if (sourceProj.canWrapX()) {\n var sourceExtent = sourceProj.getExtent();\n var sourceExtentWidth = getWidth(sourceExtent);\n worldsAway = getWorldsAway(coord, sourceProj, sourceExtentWidth);\n\n if (worldsAway) {\n // Move x to the real world\n sourceX = sourceX - worldsAway * sourceExtentWidth;\n }\n\n sourceX = clamp(sourceX, sourceExtent[0], sourceExtent[2]);\n sourceY = clamp(sourceY, sourceExtent[1], sourceExtent[3]);\n transformed = transform([sourceX, sourceY]);\n } else {\n transformed = transform(coord);\n }\n\n if (worldsAway && destProj.canWrapX()) {\n // Move transformed coordinate back to the offset world\n transformed[0] += worldsAway * getWidth(destProj.getExtent());\n }\n\n return transformed;\n };\n}\n/**\n * Add transforms to and from EPSG:4326 and EPSG:3857. This function is called\n * by when this module is executed and should only need to be called again after\n * `clearAllProjections()` is called (e.g. in tests).\n */\n\nfunction addCommon() {\n // Add transformations that don\'t alter coordinates to convert within set of\n // projections with equal meaning.\n addEquivalentProjections(PROJECTIONS);\n addEquivalentProjections(epsg4326_PROJECTIONS); // Add transformations to convert EPSG:4326 like coordinates to EPSG:3857 like\n // coordinates and back.\n\n addEquivalentTransforms(epsg4326_PROJECTIONS, PROJECTIONS, fromEPSG4326, toEPSG4326);\n}\naddCommon();\n;// CONCATENATED MODULE: ./node_modules/ol/centerconstraint.js\n/**\n * @module ol/centerconstraint\n */\n\n/**\n * @typedef {function((import("./coordinate.js").Coordinate|undefined), number, import("./size.js").Size, boolean=, Array<number>=): (import("./coordinate.js").Coordinate|undefined)} Type\n */\n\n/**\n * @param {import("./extent.js").Extent} extent Extent.\n * @param {boolean} onlyCenter If true, the constraint will only apply to the view center.\n * @param {boolean} smooth If true, the view will be able to go slightly out of the given extent\n * (only during interaction and animation).\n * @return {Type} The constraint.\n */\n\nfunction createExtent(extent, onlyCenter, smooth) {\n return (\n /**\n * @param {import("./coordinate.js").Coordinate|undefined} center Center.\n * @param {number} resolution Resolution.\n * @param {import("./size.js").Size} size Viewport size; unused if `onlyCenter` was specified.\n * @param {boolean=} opt_isMoving True if an interaction or animation is in progress.\n * @param {Array<number>=} opt_centerShift Shift between map center and viewport center.\n * @return {import("./coordinate.js").Coordinate|undefined} Center.\n */\n function (center, resolution, size, opt_isMoving, opt_centerShift) {\n if (center) {\n var viewWidth = onlyCenter ? 0 : size[0] * resolution;\n var viewHeight = onlyCenter ? 0 : size[1] * resolution;\n var shiftX = opt_centerShift ? opt_centerShift[0] : 0;\n var shiftY = opt_centerShift ? opt_centerShift[1] : 0;\n var minX = extent[0] + viewWidth / 2 + shiftX;\n var maxX = extent[2] - viewWidth / 2 + shiftX;\n var minY = extent[1] + viewHeight / 2 + shiftY;\n var maxY = extent[3] - viewHeight / 2 + shiftY; // note: when zooming out of bounds, min and max values for x and y may\n // end up inverted (min > max); this has to be accounted for\n\n if (minX > maxX) {\n minX = (maxX + minX) / 2;\n maxX = minX;\n }\n\n if (minY > maxY) {\n minY = (maxY + minY) / 2;\n maxY = minY;\n }\n\n var x = math_clamp(center[0], minX, maxX);\n var y = math_clamp(center[1], minY, maxY);\n var ratio = 30 * resolution; // during an interaction, allow some overscroll\n\n if (opt_isMoving && smooth) {\n x += -ratio * Math.log(1 + Math.max(0, minX - center[0]) / ratio) + ratio * Math.log(1 + Math.max(0, center[0] - maxX) / ratio);\n y += -ratio * Math.log(1 + Math.max(0, minY - center[1]) / ratio) + ratio * Math.log(1 + Math.max(0, center[1] - maxY) / ratio);\n }\n\n return [x, y];\n } else {\n return undefined;\n }\n }\n );\n}\n/**\n * @param {import("./coordinate.js").Coordinate=} center Center.\n * @return {import("./coordinate.js").Coordinate|undefined} Center.\n */\n\nfunction none(center) {\n return center;\n}\n;// CONCATENATED MODULE: ./node_modules/ol/resolutionconstraint.js\n/**\n * @module ol/resolutionconstraint\n */\n\n\n\n/**\n * @typedef {function((number|undefined), number, import("./size.js").Size, boolean=): (number|undefined)} Type\n */\n\n/**\n * Returns a modified resolution taking into account the viewport size and maximum\n * allowed extent.\n * @param {number} resolution Resolution\n * @param {import("./extent.js").Extent} maxExtent Maximum allowed extent.\n * @param {import("./size.js").Size} viewportSize Viewport size.\n * @param {boolean} showFullExtent Whether to show the full extent.\n * @return {number} Capped resolution.\n */\n\nfunction getViewportClampedResolution(resolution, maxExtent, viewportSize, showFullExtent) {\n var xResolution = extent_getWidth(maxExtent) / viewportSize[0];\n var yResolution = getHeight(maxExtent) / viewportSize[1];\n\n if (showFullExtent) {\n return Math.min(resolution, Math.max(xResolution, yResolution));\n }\n\n return Math.min(resolution, Math.min(xResolution, yResolution));\n}\n/**\n * Returns a modified resolution to be between maxResolution and minResolution while\n * still allowing the value to be slightly out of bounds.\n * Note: the computation is based on the logarithm function (ln):\n * - at 1, ln(x) is 0\n * - above 1, ln(x) keeps increasing but at a much slower pace than x\n * The final result is clamped to prevent getting too far away from bounds.\n * @param {number} resolution Resolution.\n * @param {number} maxResolution Max resolution.\n * @param {number} minResolution Min resolution.\n * @return {number} Smoothed resolution.\n */\n\n\nfunction getSmoothClampedResolution(resolution, maxResolution, minResolution) {\n var result = Math.min(resolution, maxResolution);\n var ratio = 50;\n result *= Math.log(1 + ratio * Math.max(0, resolution / maxResolution - 1)) / ratio + 1;\n\n if (minResolution) {\n result = Math.max(result, minResolution);\n result /= Math.log(1 + ratio * Math.max(0, minResolution / resolution - 1)) / ratio + 1;\n }\n\n return math_clamp(result, minResolution / 2, maxResolution * 2);\n}\n/**\n * @param {Array<number>} resolutions Resolutions.\n * @param {boolean=} opt_smooth If true, the view will be able to slightly exceed resolution limits. Default: true.\n * @param {import("./extent.js").Extent=} opt_maxExtent Maximum allowed extent.\n * @param {boolean=} opt_showFullExtent If true, allows us to show the full extent. Default: false.\n * @return {Type} Zoom function.\n */\n\n\nfunction createSnapToResolutions(resolutions, opt_smooth, opt_maxExtent, opt_showFullExtent) {\n return (\n /**\n * @param {number|undefined} resolution Resolution.\n * @param {number} direction Direction.\n * @param {import("./size.js").Size} size Viewport size.\n * @param {boolean=} opt_isMoving True if an interaction or animation is in progress.\n * @return {number|undefined} Resolution.\n */\n function (resolution, direction, size, opt_isMoving) {\n if (resolution !== undefined) {\n var maxResolution = resolutions[0];\n var minResolution = resolutions[resolutions.length - 1];\n var cappedMaxRes = opt_maxExtent ? getViewportClampedResolution(maxResolution, opt_maxExtent, size, opt_showFullExtent) : maxResolution; // during interacting or animating, allow intermediary values\n\n if (opt_isMoving) {\n var smooth = opt_smooth !== undefined ? opt_smooth : true;\n\n if (!smooth) {\n return math_clamp(resolution, minResolution, cappedMaxRes);\n }\n\n return getSmoothClampedResolution(resolution, cappedMaxRes, minResolution);\n }\n\n var capped = Math.min(cappedMaxRes, resolution);\n var z = Math.floor(linearFindNearest(resolutions, capped, direction));\n\n if (resolutions[z] > cappedMaxRes && z < resolutions.length - 1) {\n return resolutions[z + 1];\n }\n\n return resolutions[z];\n } else {\n return undefined;\n }\n }\n );\n}\n/**\n * @param {number} power Power.\n * @param {number} maxResolution Maximum resolution.\n * @param {number=} opt_minResolution Minimum resolution.\n * @param {boolean=} opt_smooth If true, the view will be able to slightly exceed resolution limits. Default: true.\n * @param {import("./extent.js").Extent=} opt_maxExtent Maximum allowed extent.\n * @param {boolean=} opt_showFullExtent If true, allows us to show the full extent. Default: false.\n * @return {Type} Zoom function.\n */\n\nfunction createSnapToPower(power, maxResolution, opt_minResolution, opt_smooth, opt_maxExtent, opt_showFullExtent) {\n return (\n /**\n * @param {number|undefined} resolution Resolution.\n * @param {number} direction Direction.\n * @param {import("./size.js").Size} size Viewport size.\n * @param {boolean=} opt_isMoving True if an interaction or animation is in progress.\n * @return {number|undefined} Resolution.\n */\n function (resolution, direction, size, opt_isMoving) {\n if (resolution !== undefined) {\n var cappedMaxRes = opt_maxExtent ? getViewportClampedResolution(maxResolution, opt_maxExtent, size, opt_showFullExtent) : maxResolution;\n var minResolution = opt_minResolution !== undefined ? opt_minResolution : 0; // during interacting or animating, allow intermediary values\n\n if (opt_isMoving) {\n var smooth = opt_smooth !== undefined ? opt_smooth : true;\n\n if (!smooth) {\n return math_clamp(resolution, minResolution, cappedMaxRes);\n }\n\n return getSmoothClampedResolution(resolution, cappedMaxRes, minResolution);\n }\n\n var tolerance = 1e-9;\n var minZoomLevel = Math.ceil(Math.log(maxResolution / cappedMaxRes) / Math.log(power) - tolerance);\n var offset = -direction * (0.5 - tolerance) + 0.5;\n var capped = Math.min(cappedMaxRes, resolution);\n var cappedZoomLevel = Math.floor(Math.log(maxResolution / capped) / Math.log(power) + offset);\n var zoomLevel = Math.max(minZoomLevel, cappedZoomLevel);\n var newResolution = maxResolution / Math.pow(power, zoomLevel);\n return math_clamp(newResolution, minResolution, cappedMaxRes);\n } else {\n return undefined;\n }\n }\n );\n}\n/**\n * @param {number} maxResolution Max resolution.\n * @param {number} minResolution Min resolution.\n * @param {boolean=} opt_smooth If true, the view will be able to slightly exceed resolution limits. Default: true.\n * @param {import("./extent.js").Extent=} opt_maxExtent Maximum allowed extent.\n * @param {boolean=} opt_showFullExtent If true, allows us to show the full extent. Default: false.\n * @return {Type} Zoom function.\n */\n\nfunction createMinMaxResolution(maxResolution, minResolution, opt_smooth, opt_maxExtent, opt_showFullExtent) {\n return (\n /**\n * @param {number|undefined} resolution Resolution.\n * @param {number} direction Direction.\n * @param {import("./size.js").Size} size Viewport size.\n * @param {boolean=} opt_isMoving True if an interaction or animation is in progress.\n * @return {number|undefined} Resolution.\n */\n function (resolution, direction, size, opt_isMoving) {\n if (resolution !== undefined) {\n var cappedMaxRes = opt_maxExtent ? getViewportClampedResolution(maxResolution, opt_maxExtent, size, opt_showFullExtent) : maxResolution;\n var smooth = opt_smooth !== undefined ? opt_smooth : true;\n\n if (!smooth || !opt_isMoving) {\n return math_clamp(resolution, minResolution, cappedMaxRes);\n }\n\n return getSmoothClampedResolution(resolution, cappedMaxRes, minResolution);\n } else {\n return undefined;\n }\n }\n );\n}\n;// CONCATENATED MODULE: ./node_modules/ol/rotationconstraint.js\n/**\n * @module ol/rotationconstraint\n */\n\n/**\n * @typedef {function((number|undefined), boolean=): (number|undefined)} Type\n */\n\n/**\n * @param {number|undefined} rotation Rotation.\n * @return {number|undefined} Rotation.\n */\n\nfunction disable(rotation) {\n if (rotation !== undefined) {\n return 0;\n } else {\n return undefined;\n }\n}\n/**\n * @param {number|undefined} rotation Rotation.\n * @return {number|undefined} Rotation.\n */\n\nfunction rotationconstraint_none(rotation) {\n if (rotation !== undefined) {\n return rotation;\n } else {\n return undefined;\n }\n}\n/**\n * @param {number} n N.\n * @return {Type} Rotation constraint.\n */\n\nfunction createSnapToN(n) {\n var theta = 2 * Math.PI / n;\n return (\n /**\n * @param {number|undefined} rotation Rotation.\n * @param {boolean=} opt_isMoving True if an interaction or animation is in progress.\n * @return {number|undefined} Rotation.\n */\n function (rotation, opt_isMoving) {\n if (opt_isMoving) {\n return rotation;\n }\n\n if (rotation !== undefined) {\n rotation = Math.floor(rotation / theta + 0.5) * theta;\n return rotation;\n } else {\n return undefined;\n }\n }\n );\n}\n/**\n * @param {number=} opt_tolerance Tolerance.\n * @return {Type} Rotation constraint.\n */\n\nfunction createSnapToZero(opt_tolerance) {\n var tolerance = opt_tolerance || math_toRadians(5);\n return (\n /**\n * @param {number|undefined} rotation Rotation.\n * @param {boolean=} opt_isMoving True if an interaction or animation is in progress.\n * @return {number|undefined} Rotation.\n */\n function (rotation, opt_isMoving) {\n if (opt_isMoving) {\n return rotation;\n }\n\n if (rotation !== undefined) {\n if (Math.abs(rotation) <= tolerance) {\n return 0;\n } else {\n return rotation;\n }\n } else {\n return undefined;\n }\n }\n );\n}\n;// CONCATENATED MODULE: ./node_modules/ol/easing.js\n/**\n * @module ol/easing\n */\n\n/**\n * Start slow and speed up.\n * @param {number} t Input between 0 and 1.\n * @return {number} Output between 0 and 1.\n * @api\n */\nfunction easeIn(t) {\n return Math.pow(t, 3);\n}\n/**\n * Start fast and slow down.\n * @param {number} t Input between 0 and 1.\n * @return {number} Output between 0 and 1.\n * @api\n */\n\nfunction easeOut(t) {\n return 1 - easeIn(1 - t);\n}\n/**\n * Start slow, speed up, and then slow down again.\n * @param {number} t Input between 0 and 1.\n * @return {number} Output between 0 and 1.\n * @api\n */\n\nfunction inAndOut(t) {\n return 3 * t * t - 2 * t * t * t;\n}\n/**\n * Maintain a constant speed over time.\n * @param {number} t Input between 0 and 1.\n * @return {number} Output between 0 and 1.\n * @api\n */\n\nfunction linear(t) {\n return t;\n}\n/**\n * Start slow, speed up, and at the very end slow down again. This has the\n * same general behavior as {@link module:ol/easing~inAndOut}, but the final\n * slowdown is delayed.\n * @param {number} t Input between 0 and 1.\n * @return {number} Output between 0 and 1.\n * @api\n */\n\nfunction upAndDown(t) {\n if (t < 0.5) {\n return inAndOut(2 * t);\n } else {\n return 1 - inAndOut(2 * (t - 0.5));\n }\n}\n;// CONCATENATED MODULE: ./node_modules/ol/geom/GeometryLayout.js\n/**\n * @module ol/geom/GeometryLayout\n */\n\n/**\n * The coordinate layout for geometries, indicating whether a 3rd or 4th z (\'Z\')\n * or measure (\'M\') coordinate is available. Supported values are `\'XY\'`,\n * `\'XYZ\'`, `\'XYM\'`, `\'XYZM\'`.\n * @enum {string}\n */\n/* harmony default export */ var geom_GeometryLayout = ({\n XY: \'XY\',\n XYZ: \'XYZ\',\n XYM: \'XYM\',\n XYZM: \'XYZM\'\n});\n;// CONCATENATED MODULE: ./node_modules/ol/geom/flat/transform.js\n/**\n * @module ol/geom/flat/transform\n */\n\n/**\n * @param {Array<number>} flatCoordinates Flat coordinates.\n * @param {number} offset Offset.\n * @param {number} end End.\n * @param {number} stride Stride.\n * @param {import("../../transform.js").Transform} transform Transform.\n * @param {Array<number>=} opt_dest Destination.\n * @return {Array<number>} Transformed coordinates.\n */\nfunction transform2D(flatCoordinates, offset, end, stride, transform, opt_dest) {\n var dest = opt_dest ? opt_dest : [];\n var i = 0;\n\n for (var j = offset; j < end; j += stride) {\n var x = flatCoordinates[j];\n var y = flatCoordinates[j + 1];\n dest[i++] = transform[0] * x + transform[2] * y + transform[4];\n dest[i++] = transform[1] * x + transform[3] * y + transform[5];\n }\n\n if (opt_dest && dest.length != i) {\n dest.length = i;\n }\n\n return dest;\n}\n/**\n * @param {Array<number>} flatCoordinates Flat coordinates.\n * @param {number} offset Offset.\n * @param {number} end End.\n * @param {number} stride Stride.\n * @param {number} angle Angle.\n * @param {Array<number>} anchor Rotation anchor point.\n * @param {Array<number>=} opt_dest Destination.\n * @return {Array<number>} Transformed coordinates.\n */\n\nfunction transform_rotate(flatCoordinates, offset, end, stride, angle, anchor, opt_dest) {\n var dest = opt_dest ? opt_dest : [];\n var cos = Math.cos(angle);\n var sin = Math.sin(angle);\n var anchorX = anchor[0];\n var anchorY = anchor[1];\n var i = 0;\n\n for (var j = offset; j < end; j += stride) {\n var deltaX = flatCoordinates[j] - anchorX;\n var deltaY = flatCoordinates[j + 1] - anchorY;\n dest[i++] = anchorX + deltaX * cos - deltaY * sin;\n dest[i++] = anchorY + deltaX * sin + deltaY * cos;\n\n for (var k = j + 2; k < j + stride; ++k) {\n dest[i++] = flatCoordinates[k];\n }\n }\n\n if (opt_dest && dest.length != i) {\n dest.length = i;\n }\n\n return dest;\n}\n/**\n * Scale the coordinates.\n * @param {Array<number>} flatCoordinates Flat coordinates.\n * @param {number} offset Offset.\n * @param {number} end End.\n * @param {number} stride Stride.\n * @param {number} sx Scale factor in the x-direction.\n * @param {number} sy Scale factor in the y-direction.\n * @param {Array<number>} anchor Scale anchor point.\n * @param {Array<number>=} opt_dest Destination.\n * @return {Array<number>} Transformed coordinates.\n */\n\nfunction transform_scale(flatCoordinates, offset, end, stride, sx, sy, anchor, opt_dest) {\n var dest = opt_dest ? opt_dest : [];\n var anchorX = anchor[0];\n var anchorY = anchor[1];\n var i = 0;\n\n for (var j = offset; j < end; j += stride) {\n var deltaX = flatCoordinates[j] - anchorX;\n var deltaY = flatCoordinates[j + 1] - anchorY;\n dest[i++] = anchorX + sx * deltaX;\n dest[i++] = anchorY + sy * deltaY;\n\n for (var k = j + 2; k < j + stride; ++k) {\n dest[i++] = flatCoordinates[k];\n }\n }\n\n if (opt_dest && dest.length != i) {\n dest.length = i;\n }\n\n return dest;\n}\n/**\n * @param {Array<number>} flatCoordinates Flat coordinates.\n * @param {number} offset Offset.\n * @param {number} end End.\n * @param {number} stride Stride.\n * @param {number} deltaX Delta X.\n * @param {number} deltaY Delta Y.\n * @param {Array<number>=} opt_dest Destination.\n * @return {Array<number>} Transformed coordinates.\n */\n\nfunction transform_translate(flatCoordinates, offset, end, stride, deltaX, deltaY, opt_dest) {\n var dest = opt_dest ? opt_dest : [];\n var i = 0;\n\n for (var j = offset; j < end; j += stride) {\n dest[i++] = flatCoordinates[j] + deltaX;\n dest[i++] = flatCoordinates[j + 1] + deltaY;\n\n for (var k = j + 2; k < j + stride; ++k) {\n dest[i++] = flatCoordinates[k];\n }\n }\n\n if (opt_dest && dest.length != i) {\n dest.length = i;\n }\n\n return dest;\n}\n;// CONCATENATED MODULE: ./node_modules/ol/geom/Geometry.js\nvar Geometry_extends = undefined && undefined.__extends || function () {\n var _extendStatics = function extendStatics(d, b) {\n _extendStatics = Object.setPrototypeOf || {\n __proto__: []\n } instanceof Array && function (d, b) {\n d.__proto__ = b;\n } || function (d, b) {\n for (var p in b) {\n if (Object.prototype.hasOwnProperty.call(b, p)) d[p] = b[p];\n }\n };\n\n return _extendStatics(d, b);\n };\n\n return function (d, b) {\n _extendStatics(d, b);\n\n function __() {\n this.constructor = d;\n }\n\n d.prototype = b === null ? Object.create(b) : (__.prototype = b.prototype, new __());\n };\n}();\n/**\n * @module ol/geom/Geometry\n */\n\n\n\n\n\n\n\n\n\n\n/**\n * @type {import("../transform.js").Transform}\n */\n\nvar tmpTransform = create();\n/**\n * @classdesc\n * Abstract base class; normally only used for creating subclasses and not\n * instantiated in apps.\n * Base class for vector geometries.\n *\n * To get notified of changes to the geometry, register a listener for the\n * generic `change` event on your geometry instance.\n *\n * @abstract\n * @api\n */\n\nvar Geometry =\n/** @class */\nfunction (_super) {\n Geometry_extends(Geometry, _super);\n\n function Geometry() {\n var _this = _super.call(this) || this;\n /**\n * @private\n * @type {import("../extent.js").Extent}\n */\n\n\n _this.extent_ = createEmpty();\n /**\n * @private\n * @type {number}\n */\n\n _this.extentRevision_ = -1;\n /**\n * @protected\n * @type {number}\n */\n\n _this.simplifiedGeometryMaxMinSquaredTolerance = 0;\n /**\n * @protected\n * @type {number}\n */\n\n _this.simplifiedGeometryRevision = 0;\n /**\n * Get a transformed and simplified version of the geometry.\n * @abstract\n * @param {number} revision The geometry revision.\n * @param {number} squaredTolerance Squared tolerance.\n * @param {import("../proj.js").TransformFunction} [opt_transform] Optional transform function.\n * @return {Geometry} Simplified geometry.\n */\n\n _this.simplifyTransformedInternal = memoizeOne(function (revision, squaredTolerance, opt_transform) {\n if (!opt_transform) {\n return this.getSimplifiedGeometry(squaredTolerance);\n }\n\n var clone = this.clone();\n clone.applyTransform(opt_transform);\n return clone.getSimplifiedGeometry(squaredTolerance);\n });\n return _this;\n }\n /**\n * Get a transformed and simplified version of the geometry.\n * @abstract\n * @param {number} squaredTolerance Squared tolerance.\n * @param {import("../proj.js").TransformFunction} [opt_transform] Optional transform function.\n * @return {Geometry} Simplified geometry.\n */\n\n\n Geometry.prototype.simplifyTransformed = function (squaredTolerance, opt_transform) {\n return this.simplifyTransformedInternal(this.getRevision(), squaredTolerance, opt_transform);\n };\n /**\n * Make a complete copy of the geometry.\n * @abstract\n * @return {!Geometry} Clone.\n */\n\n\n Geometry.prototype.clone = function () {\n return util_abstract();\n };\n /**\n * @abstract\n * @param {number} x X.\n * @param {number} y Y.\n * @param {import("../coordinate.js").Coordinate} closestPoint Closest point.\n * @param {number} minSquaredDistance Minimum squared distance.\n * @return {number} Minimum squared distance.\n */\n\n\n Geometry.prototype.closestPointXY = function (x, y, closestPoint, minSquaredDistance) {\n return util_abstract();\n };\n /**\n * @param {number} x X.\n * @param {number} y Y.\n * @return {boolean} Contains (x, y).\n */\n\n\n Geometry.prototype.containsXY = function (x, y) {\n var coord = this.getClosestPoint([x, y]);\n return coord[0] === x && coord[1] === y;\n };\n /**\n * Return the closest point of the geometry to the passed point as\n * {@link module:ol/coordinate~Coordinate coordinate}.\n * @param {import("../coordinate.js").Coordinate} point Point.\n * @param {import("../coordinate.js").Coordinate=} opt_closestPoint Closest point.\n * @return {import("../coordinate.js").Coordinate} Closest point.\n * @api\n */\n\n\n Geometry.prototype.getClosestPoint = function (point, opt_closestPoint) {\n var closestPoint = opt_closestPoint ? opt_closestPoint : [NaN, NaN];\n this.closestPointXY(point[0], point[1], closestPoint, Infinity);\n return closestPoint;\n };\n /**\n * Returns true if this geometry includes the specified coordinate. If the\n * coordinate is on the boundary of the geometry, returns false.\n * @param {import("../coordinate.js").Coordinate} coordinate Coordinate.\n * @return {boolean} Contains coordinate.\n * @api\n */\n\n\n Geometry.prototype.intersectsCoordinate = function (coordinate) {\n return this.containsXY(coordinate[0], coordinate[1]);\n };\n /**\n * @abstract\n * @param {import("../extent.js").Extent} extent Extent.\n * @protected\n * @return {import("../extent.js").Extent} extent Extent.\n */\n\n\n Geometry.prototype.computeExtent = function (extent) {\n return util_abstract();\n };\n /**\n * Get the extent of the geometry.\n * @param {import("../extent.js").Extent=} opt_extent Extent.\n * @return {import("../extent.js").Extent} extent Extent.\n * @api\n */\n\n\n Geometry.prototype.getExtent = function (opt_extent) {\n if (this.extentRevision_ != this.getRevision()) {\n var extent = this.computeExtent(this.extent_);\n\n if (isNaN(extent[0]) || isNaN(extent[1])) {\n createOrUpdateEmpty(extent);\n }\n\n this.extentRevision_ = this.getRevision();\n }\n\n return returnOrUpdate(this.extent_, opt_extent);\n };\n /**\n * Rotate the geometry around a given coordinate. This modifies the geometry\n * coordinates in place.\n * @abstract\n * @param {number} angle Rotation angle in radians.\n * @param {import("../coordinate.js").Coordinate} anchor The rotation center.\n * @api\n */\n\n\n Geometry.prototype.rotate = function (angle, anchor) {\n util_abstract();\n };\n /**\n * Scale the geometry (with an optional origin). This modifies the geometry\n * coordinates in place.\n * @abstract\n * @param {number} sx The scaling factor in the x-direction.\n * @param {number=} opt_sy The scaling factor in the y-direction (defaults to sx).\n * @param {import("../coordinate.js").Coordinate=} opt_anchor The scale origin (defaults to the center\n * of the geometry extent).\n * @api\n */\n\n\n Geometry.prototype.scale = function (sx, opt_sy, opt_anchor) {\n util_abstract();\n };\n /**\n * Create a simplified version of this geometry. For linestrings, this uses\n * the [Douglas Peucker](https://en.wikipedia.org/wiki/Ramer-Douglas-Peucker_algorithm)\n * algorithm. For polygons, a quantization-based\n * simplification is used to preserve topology.\n * @param {number} tolerance The tolerance distance for simplification.\n * @return {Geometry} A new, simplified version of the original geometry.\n * @api\n */\n\n\n Geometry.prototype.simplify = function (tolerance) {\n return this.getSimplifiedGeometry(tolerance * tolerance);\n };\n /**\n * Create a simplified version of this geometry using the Douglas Peucker\n * algorithm.\n * See https://en.wikipedia.org/wiki/Ramer-Douglas-Peucker_algorithm.\n * @abstract\n * @param {number} squaredTolerance Squared tolerance.\n * @return {Geometry} Simplified geometry.\n */\n\n\n Geometry.prototype.getSimplifiedGeometry = function (squaredTolerance) {\n return util_abstract();\n };\n /**\n * Get the type of this geometry.\n * @abstract\n * @return {import("./GeometryType.js").default} Geometry type.\n */\n\n\n Geometry.prototype.getType = function () {\n return util_abstract();\n };\n /**\n * Apply a transform function to the coordinates of the geometry.\n * The geometry is modified in place.\n * If you do not want the geometry modified in place, first `clone()` it and\n * then use this function on the clone.\n * @abstract\n * @param {import("../proj.js").TransformFunction} transformFn Transform function.\n * Called with a flat array of geometry coordinates.\n */\n\n\n Geometry.prototype.applyTransform = function (transformFn) {\n util_abstract();\n };\n /**\n * Test if the geometry and the passed extent intersect.\n * @abstract\n * @param {import("../extent.js").Extent} extent Extent.\n * @return {boolean} `true` if the geometry and the extent intersect.\n */\n\n\n Geometry.prototype.intersectsExtent = function (extent) {\n return util_abstract();\n };\n /**\n * Translate the geometry. This modifies the geometry coordinates in place. If\n * instead you want a new geometry, first `clone()` this geometry.\n * @abstract\n * @param {number} deltaX Delta X.\n * @param {number} deltaY Delta Y.\n * @api\n */\n\n\n Geometry.prototype.translate = function (deltaX, deltaY) {\n util_abstract();\n };\n /**\n * Transform each coordinate of the geometry from one coordinate reference\n * system to another. The geometry is modified in place.\n * For example, a line will be transformed to a line and a circle to a circle.\n * If you do not want the geometry modified in place, first `clone()` it and\n * then use this function on the clone.\n *\n * @param {import("../proj.js").ProjectionLike} source The current projection. Can be a\n * string identifier or a {@link module:ol/proj/Projection~Projection} object.\n * @param {import("../proj.js").ProjectionLike} destination The desired projection. Can be a\n * string identifier or a {@link module:ol/proj/Projection~Projection} object.\n * @return {Geometry} This geometry. Note that original geometry is\n * modified in place.\n * @api\n */\n\n\n Geometry.prototype.transform = function (source, destination) {\n /** @type {import("../proj/Projection.js").default} */\n var sourceProj = proj_get(source);\n var transformFn = sourceProj.getUnits() == proj_Units.TILE_PIXELS ? function (inCoordinates, outCoordinates, stride) {\n var pixelExtent = sourceProj.getExtent();\n var projectedExtent = sourceProj.getWorldExtent();\n var scale = getHeight(projectedExtent) / getHeight(pixelExtent);\n compose(tmpTransform, projectedExtent[0], projectedExtent[3], scale, -scale, 0, 0, 0);\n transform2D(inCoordinates, 0, inCoordinates.length, stride, tmpTransform, outCoordinates);\n return getTransform(sourceProj, destination)(inCoordinates, outCoordinates, stride);\n } : getTransform(sourceProj, destination);\n this.applyTransform(transformFn);\n return this;\n };\n\n return Geometry;\n}(ol_Object);\n\n/* harmony default export */ var geom_Geometry = (Geometry);\n;// CONCATENATED MODULE: ./node_modules/ol/geom/SimpleGeometry.js\nvar SimpleGeometry_extends = undefined && undefined.__extends || function () {\n var _extendStatics = function extendStatics(d, b) {\n _extendStatics = Object.setPrototypeOf || {\n __proto__: []\n } instanceof Array && function (d, b) {\n d.__proto__ = b;\n } || function (d, b) {\n for (var p in b) {\n if (Object.prototype.hasOwnProperty.call(b, p)) d[p] = b[p];\n }\n };\n\n return _extendStatics(d, b);\n };\n\n return function (d, b) {\n _extendStatics(d, b);\n\n function __() {\n this.constructor = d;\n }\n\n d.prototype = b === null ? Object.create(b) : (__.prototype = b.prototype, new __());\n };\n}();\n/**\n * @module ol/geom/SimpleGeometry\n */\n\n\n\n\n\n\n\n/**\n * @classdesc\n * Abstract base class; only used for creating subclasses; do not instantiate\n * in apps, as cannot be rendered.\n *\n * @abstract\n * @api\n */\n\nvar SimpleGeometry =\n/** @class */\nfunction (_super) {\n SimpleGeometry_extends(SimpleGeometry, _super);\n\n function SimpleGeometry() {\n var _this = _super.call(this) || this;\n /**\n * @protected\n * @type {import("./GeometryLayout.js").default}\n */\n\n\n _this.layout = geom_GeometryLayout.XY;\n /**\n * @protected\n * @type {number}\n */\n\n _this.stride = 2;\n /**\n * @protected\n * @type {Array<number>}\n */\n\n _this.flatCoordinates = null;\n return _this;\n }\n /**\n * @param {import("../extent.js").Extent} extent Extent.\n * @protected\n * @return {import("../extent.js").Extent} extent Extent.\n */\n\n\n SimpleGeometry.prototype.computeExtent = function (extent) {\n return createOrUpdateFromFlatCoordinates(this.flatCoordinates, 0, this.flatCoordinates.length, this.stride, extent);\n };\n /**\n * @abstract\n * @return {Array<*>} Coordinates.\n */\n\n\n SimpleGeometry.prototype.getCoordinates = function () {\n return util_abstract();\n };\n /**\n * Return the first coordinate of the geometry.\n * @return {import("../coordinate.js").Coordinate} First coordinate.\n * @api\n */\n\n\n SimpleGeometry.prototype.getFirstCoordinate = function () {\n return this.flatCoordinates.slice(0, this.stride);\n };\n /**\n * @return {Array<number>} Flat coordinates.\n */\n\n\n SimpleGeometry.prototype.getFlatCoordinates = function () {\n return this.flatCoordinates;\n };\n /**\n * Return the last coordinate of the geometry.\n * @return {import("../coordinate.js").Coordinate} Last point.\n * @api\n */\n\n\n SimpleGeometry.prototype.getLastCoordinate = function () {\n return this.flatCoordinates.slice(this.flatCoordinates.length - this.stride);\n };\n /**\n * Return the {@link module:ol/geom/GeometryLayout layout} of the geometry.\n * @return {import("./GeometryLayout.js").default} Layout.\n * @api\n */\n\n\n SimpleGeometry.prototype.getLayout = function () {\n return this.layout;\n };\n /**\n * Create a simplified version of this geometry using the Douglas Peucker algorithm.\n * @param {number} squaredTolerance Squared tolerance.\n * @return {SimpleGeometry} Simplified geometry.\n */\n\n\n SimpleGeometry.prototype.getSimplifiedGeometry = function (squaredTolerance) {\n if (this.simplifiedGeometryRevision !== this.getRevision()) {\n this.simplifiedGeometryMaxMinSquaredTolerance = 0;\n this.simplifiedGeometryRevision = this.getRevision();\n } // If squaredTolerance is negative or if we know that simplification will not\n // have any effect then just return this.\n\n\n if (squaredTolerance < 0 || this.simplifiedGeometryMaxMinSquaredTolerance !== 0 && squaredTolerance <= this.simplifiedGeometryMaxMinSquaredTolerance) {\n return this;\n }\n\n var simplifiedGeometry = this.getSimplifiedGeometryInternal(squaredTolerance);\n var simplifiedFlatCoordinates = simplifiedGeometry.getFlatCoordinates();\n\n if (simplifiedFlatCoordinates.length < this.flatCoordinates.length) {\n return simplifiedGeometry;\n } else {\n // Simplification did not actually remove any coordinates. We now know\n // that any calls to getSimplifiedGeometry with a squaredTolerance less\n // than or equal to the current squaredTolerance will also not have any\n // effect. This allows us to short circuit simplification (saving CPU\n // cycles) and prevents the cache of simplified geometries from filling\n // up with useless identical copies of this geometry (saving memory).\n this.simplifiedGeometryMaxMinSquaredTolerance = squaredTolerance;\n return this;\n }\n };\n /**\n * @param {number} squaredTolerance Squared tolerance.\n * @return {SimpleGeometry} Simplified geometry.\n * @protected\n */\n\n\n SimpleGeometry.prototype.getSimplifiedGeometryInternal = function (squaredTolerance) {\n return this;\n };\n /**\n * @return {number} Stride.\n */\n\n\n SimpleGeometry.prototype.getStride = function () {\n return this.stride;\n };\n /**\n * @param {import("./GeometryLayout.js").default} layout Layout.\n * @param {Array<number>} flatCoordinates Flat coordinates.\n */\n\n\n SimpleGeometry.prototype.setFlatCoordinates = function (layout, flatCoordinates) {\n this.stride = getStrideForLayout(layout);\n this.layout = layout;\n this.flatCoordinates = flatCoordinates;\n };\n /**\n * @abstract\n * @param {!Array<*>} coordinates Coordinates.\n * @param {import("./GeometryLayout.js").default=} opt_layout Layout.\n */\n\n\n SimpleGeometry.prototype.setCoordinates = function (coordinates, opt_layout) {\n util_abstract();\n };\n /**\n * @param {import("./GeometryLayout.js").default|undefined} layout Layout.\n * @param {Array<*>} coordinates Coordinates.\n * @param {number} nesting Nesting.\n * @protected\n */\n\n\n SimpleGeometry.prototype.setLayout = function (layout, coordinates, nesting) {\n /** @type {number} */\n var stride;\n\n if (layout) {\n stride = getStrideForLayout(layout);\n } else {\n for (var i = 0; i < nesting; ++i) {\n if (coordinates.length === 0) {\n this.layout = geom_GeometryLayout.XY;\n this.stride = 2;\n return;\n } else {\n coordinates =\n /** @type {Array} */\n coordinates[0];\n }\n }\n\n stride = coordinates.length;\n layout = getLayoutForStride(stride);\n }\n\n this.layout = layout;\n this.stride = stride;\n };\n /**\n * Apply a transform function to the coordinates of the geometry.\n * The geometry is modified in place.\n * If you do not want the geometry modified in place, first `clone()` it and\n * then use this function on the clone.\n * @param {import("../proj.js").TransformFunction} transformFn Transform function.\n * Called with a flat array of geometry coordinates.\n * @api\n */\n\n\n SimpleGeometry.prototype.applyTransform = function (transformFn) {\n if (this.flatCoordinates) {\n transformFn(this.flatCoordinates, this.flatCoordinates, this.stride);\n this.changed();\n }\n };\n /**\n * Rotate the geometry around a given coordinate. This modifies the geometry\n * coordinates in place.\n * @param {number} angle Rotation angle in counter-clockwise radians.\n * @param {import("../coordinate.js").Coordinate} anchor The rotation center.\n * @api\n */\n\n\n SimpleGeometry.prototype.rotate = function (angle, anchor) {\n var flatCoordinates = this.getFlatCoordinates();\n\n if (flatCoordinates) {\n var stride = this.getStride();\n transform_rotate(flatCoordinates, 0, flatCoordinates.length, stride, angle, anchor, flatCoordinates);\n this.changed();\n }\n };\n /**\n * Scale the geometry (with an optional origin). This modifies the geometry\n * coordinates in place.\n * @param {number} sx The scaling factor in the x-direction.\n * @param {number=} opt_sy The scaling factor in the y-direction (defaults to sx).\n * @param {import("../coordinate.js").Coordinate=} opt_anchor The scale origin (defaults to the center\n * of the geometry extent).\n * @api\n */\n\n\n SimpleGeometry.prototype.scale = function (sx, opt_sy, opt_anchor) {\n var sy = opt_sy;\n\n if (sy === undefined) {\n sy = sx;\n }\n\n var anchor = opt_anchor;\n\n if (!anchor) {\n anchor = getCenter(this.getExtent());\n }\n\n var flatCoordinates = this.getFlatCoordinates();\n\n if (flatCoordinates) {\n var stride = this.getStride();\n transform_scale(flatCoordinates, 0, flatCoordinates.length, stride, sx, sy, anchor, flatCoordinates);\n this.changed();\n }\n };\n /**\n * Translate the geometry. This modifies the geometry coordinates in place. If\n * instead you want a new geometry, first `clone()` this geometry.\n * @param {number} deltaX Delta X.\n * @param {number} deltaY Delta Y.\n * @api\n */\n\n\n SimpleGeometry.prototype.translate = function (deltaX, deltaY) {\n var flatCoordinates = this.getFlatCoordinates();\n\n if (flatCoordinates) {\n var stride = this.getStride();\n transform_translate(flatCoordinates, 0, flatCoordinates.length, stride, deltaX, deltaY, flatCoordinates);\n this.changed();\n }\n };\n\n return SimpleGeometry;\n}(geom_Geometry);\n/**\n * @param {number} stride Stride.\n * @return {import("./GeometryLayout.js").default} layout Layout.\n */\n\n\nfunction getLayoutForStride(stride) {\n var layout;\n\n if (stride == 2) {\n layout = geom_GeometryLayout.XY;\n } else if (stride == 3) {\n layout = geom_GeometryLayout.XYZ;\n } else if (stride == 4) {\n layout = geom_GeometryLayout.XYZM;\n }\n\n return (\n /** @type {import("./GeometryLayout.js").default} */\n layout\n );\n}\n/**\n * @param {import("./GeometryLayout.js").default} layout Layout.\n * @return {number} Stride.\n */\n\n\nfunction getStrideForLayout(layout) {\n var stride;\n\n if (layout == geom_GeometryLayout.XY) {\n stride = 2;\n } else if (layout == geom_GeometryLayout.XYZ || layout == geom_GeometryLayout.XYM) {\n stride = 3;\n } else if (layout == geom_GeometryLayout.XYZM) {\n stride = 4;\n }\n\n return (\n /** @type {number} */\n stride\n );\n}\n/**\n * @param {SimpleGeometry} simpleGeometry Simple geometry.\n * @param {import("../transform.js").Transform} transform Transform.\n * @param {Array<number>=} opt_dest Destination.\n * @return {Array<number>} Transformed flat coordinates.\n */\n\nfunction transformGeom2D(simpleGeometry, transform, opt_dest) {\n var flatCoordinates = simpleGeometry.getFlatCoordinates();\n\n if (!flatCoordinates) {\n return null;\n } else {\n var stride = simpleGeometry.getStride();\n return transform2D(flatCoordinates, 0, flatCoordinates.length, stride, transform, opt_dest);\n }\n}\n/* harmony default export */ var geom_SimpleGeometry = (SimpleGeometry);\n;// CONCATENATED MODULE: ./node_modules/ol/geom/flat/closest.js\n/**\n * @module ol/geom/flat/closest\n */\n\n/**\n * Returns the point on the 2D line segment flatCoordinates[offset1] to\n * flatCoordinates[offset2] that is closest to the point (x, y). Extra\n * dimensions are linearly interpolated.\n * @param {Array<number>} flatCoordinates Flat coordinates.\n * @param {number} offset1 Offset 1.\n * @param {number} offset2 Offset 2.\n * @param {number} stride Stride.\n * @param {number} x X.\n * @param {number} y Y.\n * @param {Array<number>} closestPoint Closest point.\n */\n\nfunction assignClosest(flatCoordinates, offset1, offset2, stride, x, y, closestPoint) {\n var x1 = flatCoordinates[offset1];\n var y1 = flatCoordinates[offset1 + 1];\n var dx = flatCoordinates[offset2] - x1;\n var dy = flatCoordinates[offset2 + 1] - y1;\n var offset;\n\n if (dx === 0 && dy === 0) {\n offset = offset1;\n } else {\n var t = ((x - x1) * dx + (y - y1) * dy) / (dx * dx + dy * dy);\n\n if (t > 1) {\n offset = offset2;\n } else if (t > 0) {\n for (var i = 0; i < stride; ++i) {\n closestPoint[i] = lerp(flatCoordinates[offset1 + i], flatCoordinates[offset2 + i], t);\n }\n\n closestPoint.length = stride;\n return;\n } else {\n offset = offset1;\n }\n }\n\n for (var i = 0; i < stride; ++i) {\n closestPoint[i] = flatCoordinates[offset + i];\n }\n\n closestPoint.length = stride;\n}\n/**\n * Return the squared of the largest distance between any pair of consecutive\n * coordinates.\n * @param {Array<number>} flatCoordinates Flat coordinates.\n * @param {number} offset Offset.\n * @param {number} end End.\n * @param {number} stride Stride.\n * @param {number} max Max squared delta.\n * @return {number} Max squared delta.\n */\n\n\nfunction maxSquaredDelta(flatCoordinates, offset, end, stride, max) {\n var x1 = flatCoordinates[offset];\n var y1 = flatCoordinates[offset + 1];\n\n for (offset += stride; offset < end; offset += stride) {\n var x2 = flatCoordinates[offset];\n var y2 = flatCoordinates[offset + 1];\n var squaredDelta = math_squaredDistance(x1, y1, x2, y2);\n\n if (squaredDelta > max) {\n max = squaredDelta;\n }\n\n x1 = x2;\n y1 = y2;\n }\n\n return max;\n}\n/**\n * @param {Array<number>} flatCoordinates Flat coordinates.\n * @param {number} offset Offset.\n * @param {Array<number>} ends Ends.\n * @param {number} stride Stride.\n * @param {number} max Max squared delta.\n * @return {number} Max squared delta.\n */\n\nfunction arrayMaxSquaredDelta(flatCoordinates, offset, ends, stride, max) {\n for (var i = 0, ii = ends.length; i < ii; ++i) {\n var end = ends[i];\n max = maxSquaredDelta(flatCoordinates, offset, end, stride, max);\n offset = end;\n }\n\n return max;\n}\n/**\n * @param {Array<number>} flatCoordinates Flat coordinates.\n * @param {number} offset Offset.\n * @param {Array<Array<number>>} endss Endss.\n * @param {number} stride Stride.\n * @param {number} max Max squared delta.\n * @return {number} Max squared delta.\n */\n\nfunction multiArrayMaxSquaredDelta(flatCoordinates, offset, endss, stride, max) {\n for (var i = 0, ii = endss.length; i < ii; ++i) {\n var ends = endss[i];\n max = arrayMaxSquaredDelta(flatCoordinates, offset, ends, stride, max);\n offset = ends[ends.length - 1];\n }\n\n return max;\n}\n/**\n * @param {Array<number>} flatCoordinates Flat coordinates.\n * @param {number} offset Offset.\n * @param {number} end End.\n * @param {number} stride Stride.\n * @param {number} maxDelta Max delta.\n * @param {boolean} isRing Is ring.\n * @param {number} x X.\n * @param {number} y Y.\n * @param {Array<number>} closestPoint Closest point.\n * @param {number} minSquaredDistance Minimum squared distance.\n * @param {Array<number>=} opt_tmpPoint Temporary point object.\n * @return {number} Minimum squared distance.\n */\n\nfunction assignClosestPoint(flatCoordinates, offset, end, stride, maxDelta, isRing, x, y, closestPoint, minSquaredDistance, opt_tmpPoint) {\n if (offset == end) {\n return minSquaredDistance;\n }\n\n var i, squaredDistance;\n\n if (maxDelta === 0) {\n // All points are identical, so just test the first point.\n squaredDistance = math_squaredDistance(x, y, flatCoordinates[offset], flatCoordinates[offset + 1]);\n\n if (squaredDistance < minSquaredDistance) {\n for (i = 0; i < stride; ++i) {\n closestPoint[i] = flatCoordinates[offset + i];\n }\n\n closestPoint.length = stride;\n return squaredDistance;\n } else {\n return minSquaredDistance;\n }\n }\n\n var tmpPoint = opt_tmpPoint ? opt_tmpPoint : [NaN, NaN];\n var index = offset + stride;\n\n while (index < end) {\n assignClosest(flatCoordinates, index - stride, index, stride, x, y, tmpPoint);\n squaredDistance = math_squaredDistance(x, y, tmpPoint[0], tmpPoint[1]);\n\n if (squaredDistance < minSquaredDistance) {\n minSquaredDistance = squaredDistance;\n\n for (i = 0; i < stride; ++i) {\n closestPoint[i] = tmpPoint[i];\n }\n\n closestPoint.length = stride;\n index += stride;\n } else {\n // Skip ahead multiple points, because we know that all the skipped\n // points cannot be any closer than the closest point we have found so\n // far. We know this because we know how close the current point is, how\n // close the closest point we have found so far is, and the maximum\n // distance between consecutive points. For example, if we\'re currently\n // at distance 10, the best we\'ve found so far is 3, and that the maximum\n // distance between consecutive points is 2, then we\'ll need to skip at\n // least (10 - 3) / 2 == 3 (rounded down) points to have any chance of\n // finding a closer point. We use Math.max(..., 1) to ensure that we\n // always advance at least one point, to avoid an infinite loop.\n index += stride * Math.max((Math.sqrt(squaredDistance) - Math.sqrt(minSquaredDistance)) / maxDelta | 0, 1);\n }\n }\n\n if (isRing) {\n // Check the closing segment.\n assignClosest(flatCoordinates, end - stride, offset, stride, x, y, tmpPoint);\n squaredDistance = math_squaredDistance(x, y, tmpPoint[0], tmpPoint[1]);\n\n if (squaredDistance < minSquaredDistance) {\n minSquaredDistance = squaredDistance;\n\n for (i = 0; i < stride; ++i) {\n closestPoint[i] = tmpPoint[i];\n }\n\n closestPoint.length = stride;\n }\n }\n\n return minSquaredDistance;\n}\n/**\n * @param {Array<number>} flatCoordinates Flat coordinates.\n * @param {number} offset Offset.\n * @param {Array<number>} ends Ends.\n * @param {number} stride Stride.\n * @param {number} maxDelta Max delta.\n * @param {boolean} isRing Is ring.\n * @param {number} x X.\n * @param {number} y Y.\n * @param {Array<number>} closestPoint Closest point.\n * @param {number} minSquaredDistance Minimum squared distance.\n * @param {Array<number>=} opt_tmpPoint Temporary point object.\n * @return {number} Minimum squared distance.\n */\n\nfunction assignClosestArrayPoint(flatCoordinates, offset, ends, stride, maxDelta, isRing, x, y, closestPoint, minSquaredDistance, opt_tmpPoint) {\n var tmpPoint = opt_tmpPoint ? opt_tmpPoint : [NaN, NaN];\n\n for (var i = 0, ii = ends.length; i < ii; ++i) {\n var end = ends[i];\n minSquaredDistance = assignClosestPoint(flatCoordinates, offset, end, stride, maxDelta, isRing, x, y, closestPoint, minSquaredDistance, tmpPoint);\n offset = end;\n }\n\n return minSquaredDistance;\n}\n/**\n * @param {Array<number>} flatCoordinates Flat coordinates.\n * @param {number} offset Offset.\n * @param {Array<Array<number>>} endss Endss.\n * @param {number} stride Stride.\n * @param {number} maxDelta Max delta.\n * @param {boolean} isRing Is ring.\n * @param {number} x X.\n * @param {number} y Y.\n * @param {Array<number>} closestPoint Closest point.\n * @param {number} minSquaredDistance Minimum squared distance.\n * @param {Array<number>=} opt_tmpPoint Temporary point object.\n * @return {number} Minimum squared distance.\n */\n\nfunction assignClosestMultiArrayPoint(flatCoordinates, offset, endss, stride, maxDelta, isRing, x, y, closestPoint, minSquaredDistance, opt_tmpPoint) {\n var tmpPoint = opt_tmpPoint ? opt_tmpPoint : [NaN, NaN];\n\n for (var i = 0, ii = endss.length; i < ii; ++i) {\n var ends = endss[i];\n minSquaredDistance = assignClosestArrayPoint(flatCoordinates, offset, ends, stride, maxDelta, isRing, x, y, closestPoint, minSquaredDistance, tmpPoint);\n offset = ends[ends.length - 1];\n }\n\n return minSquaredDistance;\n}\n;// CONCATENATED MODULE: ./node_modules/ol/geom/flat/deflate.js\n/**\n * @module ol/geom/flat/deflate\n */\n\n/**\n * @param {Array<number>} flatCoordinates Flat coordinates.\n * @param {number} offset Offset.\n * @param {import("../../coordinate.js").Coordinate} coordinate Coordinate.\n * @param {number} stride Stride.\n * @return {number} offset Offset.\n */\nfunction deflateCoordinate(flatCoordinates, offset, coordinate, stride) {\n for (var i = 0, ii = coordinate.length; i < ii; ++i) {\n flatCoordinates[offset++] = coordinate[i];\n }\n\n return offset;\n}\n/**\n * @param {Array<number>} flatCoordinates Flat coordinates.\n * @param {number} offset Offset.\n * @param {Array<import("../../coordinate.js").Coordinate>} coordinates Coordinates.\n * @param {number} stride Stride.\n * @return {number} offset Offset.\n */\n\nfunction deflateCoordinates(flatCoordinates, offset, coordinates, stride) {\n for (var i = 0, ii = coordinates.length; i < ii; ++i) {\n var coordinate = coordinates[i];\n\n for (var j = 0; j < stride; ++j) {\n flatCoordinates[offset++] = coordinate[j];\n }\n }\n\n return offset;\n}\n/**\n * @param {Array<number>} flatCoordinates Flat coordinates.\n * @param {number} offset Offset.\n * @param {Array<Array<import("../../coordinate.js").Coordinate>>} coordinatess Coordinatess.\n * @param {number} stride Stride.\n * @param {Array<number>=} opt_ends Ends.\n * @return {Array<number>} Ends.\n */\n\nfunction deflateCoordinatesArray(flatCoordinates, offset, coordinatess, stride, opt_ends) {\n var ends = opt_ends ? opt_ends : [];\n var i = 0;\n\n for (var j = 0, jj = coordinatess.length; j < jj; ++j) {\n var end = deflateCoordinates(flatCoordinates, offset, coordinatess[j], stride);\n ends[i++] = end;\n offset = end;\n }\n\n ends.length = i;\n return ends;\n}\n/**\n * @param {Array<number>} flatCoordinates Flat coordinates.\n * @param {number} offset Offset.\n * @param {Array<Array<Array<import("../../coordinate.js").Coordinate>>>} coordinatesss Coordinatesss.\n * @param {number} stride Stride.\n * @param {Array<Array<number>>=} opt_endss Endss.\n * @return {Array<Array<number>>} Endss.\n */\n\nfunction deflateMultiCoordinatesArray(flatCoordinates, offset, coordinatesss, stride, opt_endss) {\n var endss = opt_endss ? opt_endss : [];\n var i = 0;\n\n for (var j = 0, jj = coordinatesss.length; j < jj; ++j) {\n var ends = deflateCoordinatesArray(flatCoordinates, offset, coordinatesss[j], stride, endss[i]);\n endss[i++] = ends;\n offset = ends[ends.length - 1];\n }\n\n endss.length = i;\n return endss;\n}\n;// CONCATENATED MODULE: ./node_modules/ol/geom/flat/simplify.js\n/**\n * @module ol/geom/flat/simplify\n */\n// Based on simplify-js https://github.com/mourner/simplify-js\n// Copyright (c) 2012, Vladimir Agafonkin\n// All rights reserved.\n//\n// Redistribution and use in source and binary forms, with or without\n// modification, are permitted provided that the following conditions are met:\n//\n// 1. Redistributions of source code must retain the above copyright notice,\n// this list of conditions and the following disclaimer.\n//\n// 2. Redistributions in binary form must reproduce the above copyright\n// notice, this list of conditions and the following disclaimer in the\n// documentation and/or other materials provided with the distribution.\n//\n// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"\n// AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE\n// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE\n// ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE\n// LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR\n// CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF\n// SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS\n// INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN\n// CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)\n// ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE\n// POSSIBILITY OF SUCH DAMAGE.\n\n/**\n * @param {Array<number>} flatCoordinates Flat coordinates.\n * @param {number} offset Offset.\n * @param {number} end End.\n * @param {number} stride Stride.\n * @param {number} squaredTolerance Squared tolerance.\n * @param {boolean} highQuality Highest quality.\n * @param {Array<number>=} opt_simplifiedFlatCoordinates Simplified flat\n * coordinates.\n * @return {Array<number>} Simplified line string.\n */\n\nfunction simplifyLineString(flatCoordinates, offset, end, stride, squaredTolerance, highQuality, opt_simplifiedFlatCoordinates) {\n var simplifiedFlatCoordinates = opt_simplifiedFlatCoordinates !== undefined ? opt_simplifiedFlatCoordinates : [];\n\n if (!highQuality) {\n end = radialDistance(flatCoordinates, offset, end, stride, squaredTolerance, simplifiedFlatCoordinates, 0);\n flatCoordinates = simplifiedFlatCoordinates;\n offset = 0;\n stride = 2;\n }\n\n simplifiedFlatCoordinates.length = douglasPeucker(flatCoordinates, offset, end, stride, squaredTolerance, simplifiedFlatCoordinates, 0);\n return simplifiedFlatCoordinates;\n}\n/**\n * @param {Array<number>} flatCoordinates Flat coordinates.\n * @param {number} offset Offset.\n * @param {number} end End.\n * @param {number} stride Stride.\n * @param {number} squaredTolerance Squared tolerance.\n * @param {Array<number>} simplifiedFlatCoordinates Simplified flat\n * coordinates.\n * @param {number} simplifiedOffset Simplified offset.\n * @return {number} Simplified offset.\n */\n\nfunction douglasPeucker(flatCoordinates, offset, end, stride, squaredTolerance, simplifiedFlatCoordinates, simplifiedOffset) {\n var n = (end - offset) / stride;\n\n if (n < 3) {\n for (; offset < end; offset += stride) {\n simplifiedFlatCoordinates[simplifiedOffset++] = flatCoordinates[offset];\n simplifiedFlatCoordinates[simplifiedOffset++] = flatCoordinates[offset + 1];\n }\n\n return simplifiedOffset;\n }\n /** @type {Array<number>} */\n\n\n var markers = new Array(n);\n markers[0] = 1;\n markers[n - 1] = 1;\n /** @type {Array<number>} */\n\n var stack = [offset, end - stride];\n var index = 0;\n\n while (stack.length > 0) {\n var last = stack.pop();\n var first = stack.pop();\n var maxSquaredDistance = 0;\n var x1 = flatCoordinates[first];\n var y1 = flatCoordinates[first + 1];\n var x2 = flatCoordinates[last];\n var y2 = flatCoordinates[last + 1];\n\n for (var i = first + stride; i < last; i += stride) {\n var x = flatCoordinates[i];\n var y = flatCoordinates[i + 1];\n var squaredDistance_1 = squaredSegmentDistance(x, y, x1, y1, x2, y2);\n\n if (squaredDistance_1 > maxSquaredDistance) {\n index = i;\n maxSquaredDistance = squaredDistance_1;\n }\n }\n\n if (maxSquaredDistance > squaredTolerance) {\n markers[(index - offset) / stride] = 1;\n\n if (first + stride < index) {\n stack.push(first, index);\n }\n\n if (index + stride < last) {\n stack.push(index, last);\n }\n }\n }\n\n for (var i = 0; i < n; ++i) {\n if (markers[i]) {\n simplifiedFlatCoordinates[simplifiedOffset++] = flatCoordinates[offset + i * stride];\n simplifiedFlatCoordinates[simplifiedOffset++] = flatCoordinates[offset + i * stride + 1];\n }\n }\n\n return simplifiedOffset;\n}\n/**\n * @param {Array<number>} flatCoordinates Flat coordinates.\n * @param {number} offset Offset.\n * @param {Array<number>} ends Ends.\n * @param {number} stride Stride.\n * @param {number} squaredTolerance Squared tolerance.\n * @param {Array<number>} simplifiedFlatCoordinates Simplified flat\n * coordinates.\n * @param {number} simplifiedOffset Simplified offset.\n * @param {Array<number>} simplifiedEnds Simplified ends.\n * @return {number} Simplified offset.\n */\n\nfunction douglasPeuckerArray(flatCoordinates, offset, ends, stride, squaredTolerance, simplifiedFlatCoordinates, simplifiedOffset, simplifiedEnds) {\n for (var i = 0, ii = ends.length; i < ii; ++i) {\n var end = ends[i];\n simplifiedOffset = douglasPeucker(flatCoordinates, offset, end, stride, squaredTolerance, simplifiedFlatCoordinates, simplifiedOffset);\n simplifiedEnds.push(simplifiedOffset);\n offset = end;\n }\n\n return simplifiedOffset;\n}\n/**\n * @param {Array<number>} flatCoordinates Flat coordinates.\n * @param {number} offset Offset.\n * @param {Array<Array<number>>} endss Endss.\n * @param {number} stride Stride.\n * @param {number} squaredTolerance Squared tolerance.\n * @param {Array<number>} simplifiedFlatCoordinates Simplified flat\n * coordinates.\n * @param {number} simplifiedOffset Simplified offset.\n * @param {Array<Array<number>>} simplifiedEndss Simplified endss.\n * @return {number} Simplified offset.\n */\n\nfunction douglasPeuckerMultiArray(flatCoordinates, offset, endss, stride, squaredTolerance, simplifiedFlatCoordinates, simplifiedOffset, simplifiedEndss) {\n for (var i = 0, ii = endss.length; i < ii; ++i) {\n var ends = endss[i];\n var simplifiedEnds = [];\n simplifiedOffset = douglasPeuckerArray(flatCoordinates, offset, ends, stride, squaredTolerance, simplifiedFlatCoordinates, simplifiedOffset, simplifiedEnds);\n simplifiedEndss.push(simplifiedEnds);\n offset = ends[ends.length - 1];\n }\n\n return simplifiedOffset;\n}\n/**\n * @param {Array<number>} flatCoordinates Flat coordinates.\n * @param {number} offset Offset.\n * @param {number} end End.\n * @param {number} stride Stride.\n * @param {number} squaredTolerance Squared tolerance.\n * @param {Array<number>} simplifiedFlatCoordinates Simplified flat\n * coordinates.\n * @param {number} simplifiedOffset Simplified offset.\n * @return {number} Simplified offset.\n */\n\nfunction radialDistance(flatCoordinates, offset, end, stride, squaredTolerance, simplifiedFlatCoordinates, simplifiedOffset) {\n if (end <= offset + stride) {\n // zero or one point, no simplification possible, so copy and return\n for (; offset < end; offset += stride) {\n simplifiedFlatCoordinates[simplifiedOffset++] = flatCoordinates[offset];\n simplifiedFlatCoordinates[simplifiedOffset++] = flatCoordinates[offset + 1];\n }\n\n return simplifiedOffset;\n }\n\n var x1 = flatCoordinates[offset];\n var y1 = flatCoordinates[offset + 1]; // copy first point\n\n simplifiedFlatCoordinates[simplifiedOffset++] = x1;\n simplifiedFlatCoordinates[simplifiedOffset++] = y1;\n var x2 = x1;\n var y2 = y1;\n\n for (offset += stride; offset < end; offset += stride) {\n x2 = flatCoordinates[offset];\n y2 = flatCoordinates[offset + 1];\n\n if (squaredDistance(x1, y1, x2, y2) > squaredTolerance) {\n // copy point at offset\n simplifiedFlatCoordinates[simplifiedOffset++] = x2;\n simplifiedFlatCoordinates[simplifiedOffset++] = y2;\n x1 = x2;\n y1 = y2;\n }\n }\n\n if (x2 != x1 || y2 != y1) {\n // copy last point\n simplifiedFlatCoordinates[simplifiedOffset++] = x2;\n simplifiedFlatCoordinates[simplifiedOffset++] = y2;\n }\n\n return simplifiedOffset;\n}\n/**\n * @param {number} value Value.\n * @param {number} tolerance Tolerance.\n * @return {number} Rounded value.\n */\n\nfunction snap(value, tolerance) {\n return tolerance * Math.round(value / tolerance);\n}\n/**\n * Simplifies a line string using an algorithm designed by Tim Schaub.\n * Coordinates are snapped to the nearest value in a virtual grid and\n * consecutive duplicate coordinates are discarded. This effectively preserves\n * topology as the simplification of any subsection of a line string is\n * independent of the rest of the line string. This means that, for examples,\n * the common edge between two polygons will be simplified to the same line\n * string independently in both polygons. This implementation uses a single\n * pass over the coordinates and eliminates intermediate collinear points.\n * @param {Array<number>} flatCoordinates Flat coordinates.\n * @param {number} offset Offset.\n * @param {number} end End.\n * @param {number} stride Stride.\n * @param {number} tolerance Tolerance.\n * @param {Array<number>} simplifiedFlatCoordinates Simplified flat\n * coordinates.\n * @param {number} simplifiedOffset Simplified offset.\n * @return {number} Simplified offset.\n */\n\nfunction quantize(flatCoordinates, offset, end, stride, tolerance, simplifiedFlatCoordinates, simplifiedOffset) {\n // do nothing if the line is empty\n if (offset == end) {\n return simplifiedOffset;\n } // snap the first coordinate (P1)\n\n\n var x1 = snap(flatCoordinates[offset], tolerance);\n var y1 = snap(flatCoordinates[offset + 1], tolerance);\n offset += stride; // add the first coordinate to the output\n\n simplifiedFlatCoordinates[simplifiedOffset++] = x1;\n simplifiedFlatCoordinates[simplifiedOffset++] = y1; // find the next coordinate that does not snap to the same value as the first\n // coordinate (P2)\n\n var x2, y2;\n\n do {\n x2 = snap(flatCoordinates[offset], tolerance);\n y2 = snap(flatCoordinates[offset + 1], tolerance);\n offset += stride;\n\n if (offset == end) {\n // all coordinates snap to the same value, the line collapses to a point\n // push the last snapped value anyway to ensure that the output contains\n // at least two points\n // FIXME should we really return at least two points anyway?\n simplifiedFlatCoordinates[simplifiedOffset++] = x2;\n simplifiedFlatCoordinates[simplifiedOffset++] = y2;\n return simplifiedOffset;\n }\n } while (x2 == x1 && y2 == y1);\n\n while (offset < end) {\n // snap the next coordinate (P3)\n var x3 = snap(flatCoordinates[offset], tolerance);\n var y3 = snap(flatCoordinates[offset + 1], tolerance);\n offset += stride; // skip P3 if it is equal to P2\n\n if (x3 == x2 && y3 == y2) {\n continue;\n } // calculate the delta between P1 and P2\n\n\n var dx1 = x2 - x1;\n var dy1 = y2 - y1; // calculate the delta between P3 and P1\n\n var dx2 = x3 - x1;\n var dy2 = y3 - y1; // if P1, P2, and P3 are colinear and P3 is further from P1 than P2 is from\n // P1 in the same direction then P2 is on the straight line between P1 and\n // P3\n\n if (dx1 * dy2 == dy1 * dx2 && (dx1 < 0 && dx2 < dx1 || dx1 == dx2 || dx1 > 0 && dx2 > dx1) && (dy1 < 0 && dy2 < dy1 || dy1 == dy2 || dy1 > 0 && dy2 > dy1)) {\n // discard P2 and set P2 = P3\n x2 = x3;\n y2 = y3;\n continue;\n } // either P1, P2, and P3 are not colinear, or they are colinear but P3 is\n // between P3 and P1 or on the opposite half of the line to P2. add P2,\n // and continue with P1 = P2 and P2 = P3\n\n\n simplifiedFlatCoordinates[simplifiedOffset++] = x2;\n simplifiedFlatCoordinates[simplifiedOffset++] = y2;\n x1 = x2;\n y1 = y2;\n x2 = x3;\n y2 = y3;\n } // add the last point (P2)\n\n\n simplifiedFlatCoordinates[simplifiedOffset++] = x2;\n simplifiedFlatCoordinates[simplifiedOffset++] = y2;\n return simplifiedOffset;\n}\n/**\n * @param {Array<number>} flatCoordinates Flat coordinates.\n * @param {number} offset Offset.\n * @param {Array<number>} ends Ends.\n * @param {number} stride Stride.\n * @param {number} tolerance Tolerance.\n * @param {Array<number>} simplifiedFlatCoordinates Simplified flat\n * coordinates.\n * @param {number} simplifiedOffset Simplified offset.\n * @param {Array<number>} simplifiedEnds Simplified ends.\n * @return {number} Simplified offset.\n */\n\nfunction quantizeArray(flatCoordinates, offset, ends, stride, tolerance, simplifiedFlatCoordinates, simplifiedOffset, simplifiedEnds) {\n for (var i = 0, ii = ends.length; i < ii; ++i) {\n var end = ends[i];\n simplifiedOffset = quantize(flatCoordinates, offset, end, stride, tolerance, simplifiedFlatCoordinates, simplifiedOffset);\n simplifiedEnds.push(simplifiedOffset);\n offset = end;\n }\n\n return simplifiedOffset;\n}\n/**\n * @param {Array<number>} flatCoordinates Flat coordinates.\n * @param {number} offset Offset.\n * @param {Array<Array<number>>} endss Endss.\n * @param {number} stride Stride.\n * @param {number} tolerance Tolerance.\n * @param {Array<number>} simplifiedFlatCoordinates Simplified flat\n * coordinates.\n * @param {number} simplifiedOffset Simplified offset.\n * @param {Array<Array<number>>} simplifiedEndss Simplified endss.\n * @return {number} Simplified offset.\n */\n\nfunction quantizeMultiArray(flatCoordinates, offset, endss, stride, tolerance, simplifiedFlatCoordinates, simplifiedOffset, simplifiedEndss) {\n for (var i = 0, ii = endss.length; i < ii; ++i) {\n var ends = endss[i];\n var simplifiedEnds = [];\n simplifiedOffset = quantizeArray(flatCoordinates, offset, ends, stride, tolerance, simplifiedFlatCoordinates, simplifiedOffset, simplifiedEnds);\n simplifiedEndss.push(simplifiedEnds);\n offset = ends[ends.length - 1];\n }\n\n return simplifiedOffset;\n}\n;// CONCATENATED MODULE: ./node_modules/ol/geom/flat/inflate.js\n/**\n * @module ol/geom/flat/inflate\n */\n\n/**\n * @param {Array<number>} flatCoordinates Flat coordinates.\n * @param {number} offset Offset.\n * @param {number} end End.\n * @param {number} stride Stride.\n * @param {Array<import("../../coordinate.js").Coordinate>=} opt_coordinates Coordinates.\n * @return {Array<import("../../coordinate.js").Coordinate>} Coordinates.\n */\nfunction inflateCoordinates(flatCoordinates, offset, end, stride, opt_coordinates) {\n var coordinates = opt_coordinates !== undefined ? opt_coordinates : [];\n var i = 0;\n\n for (var j = offset; j < end; j += stride) {\n coordinates[i++] = flatCoordinates.slice(j, j + stride);\n }\n\n coordinates.length = i;\n return coordinates;\n}\n/**\n * @param {Array<number>} flatCoordinates Flat coordinates.\n * @param {number} offset Offset.\n * @param {Array<number>} ends Ends.\n * @param {number} stride Stride.\n * @param {Array<Array<import("../../coordinate.js").Coordinate>>=} opt_coordinatess Coordinatess.\n * @return {Array<Array<import("../../coordinate.js").Coordinate>>} Coordinatess.\n */\n\nfunction inflateCoordinatesArray(flatCoordinates, offset, ends, stride, opt_coordinatess) {\n var coordinatess = opt_coordinatess !== undefined ? opt_coordinatess : [];\n var i = 0;\n\n for (var j = 0, jj = ends.length; j < jj; ++j) {\n var end = ends[j];\n coordinatess[i++] = inflateCoordinates(flatCoordinates, offset, end, stride, coordinatess[i]);\n offset = end;\n }\n\n coordinatess.length = i;\n return coordinatess;\n}\n/**\n * @param {Array<number>} flatCoordinates Flat coordinates.\n * @param {number} offset Offset.\n * @param {Array<Array<number>>} endss Endss.\n * @param {number} stride Stride.\n * @param {Array<Array<Array<import("../../coordinate.js").Coordinate>>>=} opt_coordinatesss\n * Coordinatesss.\n * @return {Array<Array<Array<import("../../coordinate.js").Coordinate>>>} Coordinatesss.\n */\n\nfunction inflateMultiCoordinatesArray(flatCoordinates, offset, endss, stride, opt_coordinatesss) {\n var coordinatesss = opt_coordinatesss !== undefined ? opt_coordinatesss : [];\n var i = 0;\n\n for (var j = 0, jj = endss.length; j < jj; ++j) {\n var ends = endss[j];\n coordinatesss[i++] = inflateCoordinatesArray(flatCoordinates, offset, ends, stride, coordinatesss[i]);\n offset = ends[ends.length - 1];\n }\n\n coordinatesss.length = i;\n return coordinatesss;\n}\n;// CONCATENATED MODULE: ./node_modules/ol/geom/flat/area.js\n/**\n * @module ol/geom/flat/area\n */\n\n/**\n * @param {Array<number>} flatCoordinates Flat coordinates.\n * @param {number} offset Offset.\n * @param {number} end End.\n * @param {number} stride Stride.\n * @return {number} Area.\n */\nfunction linearRing(flatCoordinates, offset, end, stride) {\n var twiceArea = 0;\n var x1 = flatCoordinates[end - stride];\n var y1 = flatCoordinates[end - stride + 1];\n\n for (; offset < end; offset += stride) {\n var x2 = flatCoordinates[offset];\n var y2 = flatCoordinates[offset + 1];\n twiceArea += y1 * x2 - x1 * y2;\n x1 = x2;\n y1 = y2;\n }\n\n return twiceArea / 2;\n}\n/**\n * @param {Array<number>} flatCoordinates Flat coordinates.\n * @param {number} offset Offset.\n * @param {Array<number>} ends Ends.\n * @param {number} stride Stride.\n * @return {number} Area.\n */\n\nfunction linearRings(flatCoordinates, offset, ends, stride) {\n var area = 0;\n\n for (var i = 0, ii = ends.length; i < ii; ++i) {\n var end = ends[i];\n area += linearRing(flatCoordinates, offset, end, stride);\n offset = end;\n }\n\n return area;\n}\n/**\n * @param {Array<number>} flatCoordinates Flat coordinates.\n * @param {number} offset Offset.\n * @param {Array<Array<number>>} endss Endss.\n * @param {number} stride Stride.\n * @return {number} Area.\n */\n\nfunction linearRingss(flatCoordinates, offset, endss, stride) {\n var area = 0;\n\n for (var i = 0, ii = endss.length; i < ii; ++i) {\n var ends = endss[i];\n area += linearRings(flatCoordinates, offset, ends, stride);\n offset = ends[ends.length - 1];\n }\n\n return area;\n}\n;// CONCATENATED MODULE: ./node_modules/ol/geom/LinearRing.js\nvar LinearRing_extends = undefined && undefined.__extends || function () {\n var _extendStatics = function extendStatics(d, b) {\n _extendStatics = Object.setPrototypeOf || {\n __proto__: []\n } instanceof Array && function (d, b) {\n d.__proto__ = b;\n } || function (d, b) {\n for (var p in b) {\n if (Object.prototype.hasOwnProperty.call(b, p)) d[p] = b[p];\n }\n };\n\n return _extendStatics(d, b);\n };\n\n return function (d, b) {\n _extendStatics(d, b);\n\n function __() {\n this.constructor = d;\n }\n\n d.prototype = b === null ? Object.create(b) : (__.prototype = b.prototype, new __());\n };\n}();\n/**\n * @module ol/geom/LinearRing\n */\n\n\n\n\n\n\n\n\n\n\n\n/**\n * @classdesc\n * Linear ring geometry. Only used as part of polygon; cannot be rendered\n * on its own.\n *\n * @api\n */\n\nvar LinearRing =\n/** @class */\nfunction (_super) {\n LinearRing_extends(LinearRing, _super);\n /**\n * @param {Array<import("../coordinate.js").Coordinate>|Array<number>} coordinates Coordinates.\n * For internal use, flat coordinates in combination with `opt_layout` are also accepted.\n * @param {import("./GeometryLayout.js").default=} opt_layout Layout.\n */\n\n\n function LinearRing(coordinates, opt_layout) {\n var _this = _super.call(this) || this;\n /**\n * @private\n * @type {number}\n */\n\n\n _this.maxDelta_ = -1;\n /**\n * @private\n * @type {number}\n */\n\n _this.maxDeltaRevision_ = -1;\n\n if (opt_layout !== undefined && !Array.isArray(coordinates[0])) {\n _this.setFlatCoordinates(opt_layout,\n /** @type {Array<number>} */\n coordinates);\n } else {\n _this.setCoordinates(\n /** @type {Array<import("../coordinate.js").Coordinate>} */\n coordinates, opt_layout);\n }\n\n return _this;\n }\n /**\n * Make a complete copy of the geometry.\n * @return {!LinearRing} Clone.\n * @api\n */\n\n\n LinearRing.prototype.clone = function () {\n return new LinearRing(this.flatCoordinates.slice(), this.layout);\n };\n /**\n * @param {number} x X.\n * @param {number} y Y.\n * @param {import("../coordinate.js").Coordinate} closestPoint Closest point.\n * @param {number} minSquaredDistance Minimum squared distance.\n * @return {number} Minimum squared distance.\n */\n\n\n LinearRing.prototype.closestPointXY = function (x, y, closestPoint, minSquaredDistance) {\n if (minSquaredDistance < closestSquaredDistanceXY(this.getExtent(), x, y)) {\n return minSquaredDistance;\n }\n\n if (this.maxDeltaRevision_ != this.getRevision()) {\n this.maxDelta_ = Math.sqrt(maxSquaredDelta(this.flatCoordinates, 0, this.flatCoordinates.length, this.stride, 0));\n this.maxDeltaRevision_ = this.getRevision();\n }\n\n return assignClosestPoint(this.flatCoordinates, 0, this.flatCoordinates.length, this.stride, this.maxDelta_, true, x, y, closestPoint, minSquaredDistance);\n };\n /**\n * Return the area of the linear ring on projected plane.\n * @return {number} Area (on projected plane).\n * @api\n */\n\n\n LinearRing.prototype.getArea = function () {\n return linearRing(this.flatCoordinates, 0, this.flatCoordinates.length, this.stride);\n };\n /**\n * Return the coordinates of the linear ring.\n * @return {Array<import("../coordinate.js").Coordinate>} Coordinates.\n * @api\n */\n\n\n LinearRing.prototype.getCoordinates = function () {\n return inflateCoordinates(this.flatCoordinates, 0, this.flatCoordinates.length, this.stride);\n };\n /**\n * @param {number} squaredTolerance Squared tolerance.\n * @return {LinearRing} Simplified LinearRing.\n * @protected\n */\n\n\n LinearRing.prototype.getSimplifiedGeometryInternal = function (squaredTolerance) {\n var simplifiedFlatCoordinates = [];\n simplifiedFlatCoordinates.length = douglasPeucker(this.flatCoordinates, 0, this.flatCoordinates.length, this.stride, squaredTolerance, simplifiedFlatCoordinates, 0);\n return new LinearRing(simplifiedFlatCoordinates, geom_GeometryLayout.XY);\n };\n /**\n * Get the type of this geometry.\n * @return {import("./GeometryType.js").default} Geometry type.\n * @api\n */\n\n\n LinearRing.prototype.getType = function () {\n return geom_GeometryType.LINEAR_RING;\n };\n /**\n * Test if the geometry and the passed extent intersect.\n * @param {import("../extent.js").Extent} extent Extent.\n * @return {boolean} `true` if the geometry and the extent intersect.\n * @api\n */\n\n\n LinearRing.prototype.intersectsExtent = function (extent) {\n return false;\n };\n /**\n * Set the coordinates of the linear ring.\n * @param {!Array<import("../coordinate.js").Coordinate>} coordinates Coordinates.\n * @param {import("./GeometryLayout.js").default=} opt_layout Layout.\n * @api\n */\n\n\n LinearRing.prototype.setCoordinates = function (coordinates, opt_layout) {\n this.setLayout(opt_layout, coordinates, 1);\n\n if (!this.flatCoordinates) {\n this.flatCoordinates = [];\n }\n\n this.flatCoordinates.length = deflateCoordinates(this.flatCoordinates, 0, coordinates, this.stride);\n this.changed();\n };\n\n return LinearRing;\n}(geom_SimpleGeometry);\n\n/* harmony default export */ var geom_LinearRing = (LinearRing);\n;// CONCATENATED MODULE: ./node_modules/ol/geom/Point.js\nvar Point_extends = undefined && undefined.__extends || function () {\n var _extendStatics = function extendStatics(d, b) {\n _extendStatics = Object.setPrototypeOf || {\n __proto__: []\n } instanceof Array && function (d, b) {\n d.__proto__ = b;\n } || function (d, b) {\n for (var p in b) {\n if (Object.prototype.hasOwnProperty.call(b, p)) d[p] = b[p];\n }\n };\n\n return _extendStatics(d, b);\n };\n\n return function (d, b) {\n _extendStatics(d, b);\n\n function __() {\n this.constructor = d;\n }\n\n d.prototype = b === null ? Object.create(b) : (__.prototype = b.prototype, new __());\n };\n}();\n/**\n * @module ol/geom/Point\n */\n\n\n\n\n\n\n\n/**\n * @classdesc\n * Point geometry.\n *\n * @api\n */\n\nvar Point =\n/** @class */\nfunction (_super) {\n Point_extends(Point, _super);\n /**\n * @param {import("../coordinate.js").Coordinate} coordinates Coordinates.\n * @param {import("./GeometryLayout.js").default=} opt_layout Layout.\n */\n\n\n function Point(coordinates, opt_layout) {\n var _this = _super.call(this) || this;\n\n _this.setCoordinates(coordinates, opt_layout);\n\n return _this;\n }\n /**\n * Make a complete copy of the geometry.\n * @return {!Point} Clone.\n * @api\n */\n\n\n Point.prototype.clone = function () {\n var point = new Point(this.flatCoordinates.slice(), this.layout);\n point.applyProperties(this);\n return point;\n };\n /**\n * @param {number} x X.\n * @param {number} y Y.\n * @param {import("../coordinate.js").Coordinate} closestPoint Closest point.\n * @param {number} minSquaredDistance Minimum squared distance.\n * @return {number} Minimum squared distance.\n */\n\n\n Point.prototype.closestPointXY = function (x, y, closestPoint, minSquaredDistance) {\n var flatCoordinates = this.flatCoordinates;\n var squaredDistance = math_squaredDistance(x, y, flatCoordinates[0], flatCoordinates[1]);\n\n if (squaredDistance < minSquaredDistance) {\n var stride = this.stride;\n\n for (var i = 0; i < stride; ++i) {\n closestPoint[i] = flatCoordinates[i];\n }\n\n closestPoint.length = stride;\n return squaredDistance;\n } else {\n return minSquaredDistance;\n }\n };\n /**\n * Return the coordinate of the point.\n * @return {import("../coordinate.js").Coordinate} Coordinates.\n * @api\n */\n\n\n Point.prototype.getCoordinates = function () {\n return !this.flatCoordinates ? [] : this.flatCoordinates.slice();\n };\n /**\n * @param {import("../extent.js").Extent} extent Extent.\n * @protected\n * @return {import("../extent.js").Extent} extent Extent.\n */\n\n\n Point.prototype.computeExtent = function (extent) {\n return createOrUpdateFromCoordinate(this.flatCoordinates, extent);\n };\n /**\n * Get the type of this geometry.\n * @return {import("./GeometryType.js").default} Geometry type.\n * @api\n */\n\n\n Point.prototype.getType = function () {\n return geom_GeometryType.POINT;\n };\n /**\n * Test if the geometry and the passed extent intersect.\n * @param {import("../extent.js").Extent} extent Extent.\n * @return {boolean} `true` if the geometry and the extent intersect.\n * @api\n */\n\n\n Point.prototype.intersectsExtent = function (extent) {\n return containsXY(extent, this.flatCoordinates[0], this.flatCoordinates[1]);\n };\n /**\n * @param {!Array<*>} coordinates Coordinates.\n * @param {import("./GeometryLayout.js").default=} opt_layout Layout.\n * @api\n */\n\n\n Point.prototype.setCoordinates = function (coordinates, opt_layout) {\n this.setLayout(opt_layout, coordinates, 0);\n\n if (!this.flatCoordinates) {\n this.flatCoordinates = [];\n }\n\n this.flatCoordinates.length = deflateCoordinate(this.flatCoordinates, 0, coordinates, this.stride);\n this.changed();\n };\n\n return Point;\n}(geom_SimpleGeometry);\n\n/* harmony default export */ var geom_Point = (Point);\n;// CONCATENATED MODULE: ./node_modules/ol/geom/flat/contains.js\n/**\n * @module ol/geom/flat/contains\n */\n\n/**\n * @param {Array<number>} flatCoordinates Flat coordinates.\n * @param {number} offset Offset.\n * @param {number} end End.\n * @param {number} stride Stride.\n * @param {import("../../extent.js").Extent} extent Extent.\n * @return {boolean} Contains extent.\n */\n\nfunction linearRingContainsExtent(flatCoordinates, offset, end, stride, extent) {\n var outside = forEachCorner(extent,\n /**\n * @param {import("../../coordinate.js").Coordinate} coordinate Coordinate.\n * @return {boolean} Contains (x, y).\n */\n function (coordinate) {\n return !linearRingContainsXY(flatCoordinates, offset, end, stride, coordinate[0], coordinate[1]);\n });\n return !outside;\n}\n/**\n * @param {Array<number>} flatCoordinates Flat coordinates.\n * @param {number} offset Offset.\n * @param {number} end End.\n * @param {number} stride Stride.\n * @param {number} x X.\n * @param {number} y Y.\n * @return {boolean} Contains (x, y).\n */\n\nfunction linearRingContainsXY(flatCoordinates, offset, end, stride, x, y) {\n // http://geomalgorithms.com/a03-_inclusion.html\n // Copyright 2000 softSurfer, 2012 Dan Sunday\n // This code may be freely used and modified for any purpose\n // providing that this copyright notice is included with it.\n // SoftSurfer makes no warranty for this code, and cannot be held\n // liable for any real or imagined damage resulting from its use.\n // Users of this code must verify correctness for their application.\n var wn = 0;\n var x1 = flatCoordinates[end - stride];\n var y1 = flatCoordinates[end - stride + 1];\n\n for (; offset < end; offset += stride) {\n var x2 = flatCoordinates[offset];\n var y2 = flatCoordinates[offset + 1];\n\n if (y1 <= y) {\n if (y2 > y && (x2 - x1) * (y - y1) - (x - x1) * (y2 - y1) > 0) {\n wn++;\n }\n } else if (y2 <= y && (x2 - x1) * (y - y1) - (x - x1) * (y2 - y1) < 0) {\n wn--;\n }\n\n x1 = x2;\n y1 = y2;\n }\n\n return wn !== 0;\n}\n/**\n * @param {Array<number>} flatCoordinates Flat coordinates.\n * @param {number} offset Offset.\n * @param {Array<number>} ends Ends.\n * @param {number} stride Stride.\n * @param {number} x X.\n * @param {number} y Y.\n * @return {boolean} Contains (x, y).\n */\n\nfunction linearRingsContainsXY(flatCoordinates, offset, ends, stride, x, y) {\n if (ends.length === 0) {\n return false;\n }\n\n if (!linearRingContainsXY(flatCoordinates, offset, ends[0], stride, x, y)) {\n return false;\n }\n\n for (var i = 1, ii = ends.length; i < ii; ++i) {\n if (linearRingContainsXY(flatCoordinates, ends[i - 1], ends[i], stride, x, y)) {\n return false;\n }\n }\n\n return true;\n}\n/**\n * @param {Array<number>} flatCoordinates Flat coordinates.\n * @param {number} offset Offset.\n * @param {Array<Array<number>>} endss Endss.\n * @param {number} stride Stride.\n * @param {number} x X.\n * @param {number} y Y.\n * @return {boolean} Contains (x, y).\n */\n\nfunction linearRingssContainsXY(flatCoordinates, offset, endss, stride, x, y) {\n if (endss.length === 0) {\n return false;\n }\n\n for (var i = 0, ii = endss.length; i < ii; ++i) {\n var ends = endss[i];\n\n if (linearRingsContainsXY(flatCoordinates, offset, ends, stride, x, y)) {\n return true;\n }\n\n offset = ends[ends.length - 1];\n }\n\n return false;\n}\n;// CONCATENATED MODULE: ./node_modules/ol/geom/flat/interiorpoint.js\n/**\n * @module ol/geom/flat/interiorpoint\n */\n\n\n/**\n * Calculates a point that is likely to lie in the interior of the linear rings.\n * Inspired by JTS\'s com.vividsolutions.jts.geom.Geometry#getInteriorPoint.\n * @param {Array<number>} flatCoordinates Flat coordinates.\n * @param {number} offset Offset.\n * @param {Array<number>} ends Ends.\n * @param {number} stride Stride.\n * @param {Array<number>} flatCenters Flat centers.\n * @param {number} flatCentersOffset Flat center offset.\n * @param {Array<number>=} opt_dest Destination.\n * @return {Array<number>} Destination point as XYM coordinate, where M is the\n * length of the horizontal intersection that the point belongs to.\n */\n\nfunction getInteriorPointOfArray(flatCoordinates, offset, ends, stride, flatCenters, flatCentersOffset, opt_dest) {\n var i, ii, x, x1, x2, y1, y2;\n var y = flatCenters[flatCentersOffset + 1];\n /** @type {Array<number>} */\n\n var intersections = []; // Calculate intersections with the horizontal line\n\n for (var r = 0, rr = ends.length; r < rr; ++r) {\n var end = ends[r];\n x1 = flatCoordinates[end - stride];\n y1 = flatCoordinates[end - stride + 1];\n\n for (i = offset; i < end; i += stride) {\n x2 = flatCoordinates[i];\n y2 = flatCoordinates[i + 1];\n\n if (y <= y1 && y2 <= y || y1 <= y && y <= y2) {\n x = (y - y1) / (y2 - y1) * (x2 - x1) + x1;\n intersections.push(x);\n }\n\n x1 = x2;\n y1 = y2;\n }\n } // Find the longest segment of the horizontal line that has its center point\n // inside the linear ring.\n\n\n var pointX = NaN;\n var maxSegmentLength = -Infinity;\n intersections.sort(numberSafeCompareFunction);\n x1 = intersections[0];\n\n for (i = 1, ii = intersections.length; i < ii; ++i) {\n x2 = intersections[i];\n var segmentLength = Math.abs(x2 - x1);\n\n if (segmentLength > maxSegmentLength) {\n x = (x1 + x2) / 2;\n\n if (linearRingsContainsXY(flatCoordinates, offset, ends, stride, x, y)) {\n pointX = x;\n maxSegmentLength = segmentLength;\n }\n }\n\n x1 = x2;\n }\n\n if (isNaN(pointX)) {\n // There is no horizontal line that has its center point inside the linear\n // ring. Use the center of the the linear ring\'s extent.\n pointX = flatCenters[flatCentersOffset];\n }\n\n if (opt_dest) {\n opt_dest.push(pointX, y, maxSegmentLength);\n return opt_dest;\n } else {\n return [pointX, y, maxSegmentLength];\n }\n}\n/**\n * @param {Array<number>} flatCoordinates Flat coordinates.\n * @param {number} offset Offset.\n * @param {Array<Array<number>>} endss Endss.\n * @param {number} stride Stride.\n * @param {Array<number>} flatCenters Flat centers.\n * @return {Array<number>} Interior points as XYM coordinates, where M is the\n * length of the horizontal intersection that the point belongs to.\n */\n\nfunction getInteriorPointsOfMultiArray(flatCoordinates, offset, endss, stride, flatCenters) {\n var interiorPoints = [];\n\n for (var i = 0, ii = endss.length; i < ii; ++i) {\n var ends = endss[i];\n interiorPoints = getInteriorPointOfArray(flatCoordinates, offset, ends, stride, flatCenters, 2 * i, interiorPoints);\n offset = ends[ends.length - 1];\n }\n\n return interiorPoints;\n}\n;// CONCATENATED MODULE: ./node_modules/ol/geom/flat/segments.js\n/**\n * @module ol/geom/flat/segments\n */\n\n/**\n * This function calls `callback` for each segment of the flat coordinates\n * array. If the callback returns a truthy value the function returns that\n * value immediately. Otherwise the function returns `false`.\n * @param {Array<number>} flatCoordinates Flat coordinates.\n * @param {number} offset Offset.\n * @param {number} end End.\n * @param {number} stride Stride.\n * @param {function(import("../../coordinate.js").Coordinate, import("../../coordinate.js").Coordinate): T} callback Function\n * called for each segment.\n * @return {T|boolean} Value.\n * @template T\n */\nfunction forEach(flatCoordinates, offset, end, stride, callback) {\n var point1 = [flatCoordinates[offset], flatCoordinates[offset + 1]];\n var point2 = [];\n var ret;\n\n for (; offset + stride < end; offset += stride) {\n point2[0] = flatCoordinates[offset + stride];\n point2[1] = flatCoordinates[offset + stride + 1];\n ret = callback(point1, point2);\n\n if (ret) {\n return ret;\n }\n\n point1[0] = point2[0];\n point1[1] = point2[1];\n }\n\n return false;\n}\n;// CONCATENATED MODULE: ./node_modules/ol/geom/flat/intersectsextent.js\n/**\n * @module ol/geom/flat/intersectsextent\n */\n\n\n\n/**\n * @param {Array<number>} flatCoordinates Flat coordinates.\n * @param {number} offset Offset.\n * @param {number} end End.\n * @param {number} stride Stride.\n * @param {import("../../extent.js").Extent} extent Extent.\n * @return {boolean} True if the geometry and the extent intersect.\n */\n\nfunction intersectsLineString(flatCoordinates, offset, end, stride, extent) {\n var coordinatesExtent = extendFlatCoordinates(createEmpty(), flatCoordinates, offset, end, stride);\n\n if (!intersects(extent, coordinatesExtent)) {\n return false;\n }\n\n if (containsExtent(extent, coordinatesExtent)) {\n return true;\n }\n\n if (coordinatesExtent[0] >= extent[0] && coordinatesExtent[2] <= extent[2]) {\n return true;\n }\n\n if (coordinatesExtent[1] >= extent[1] && coordinatesExtent[3] <= extent[3]) {\n return true;\n }\n\n return forEach(flatCoordinates, offset, end, stride,\n /**\n * @param {import("../../coordinate.js").Coordinate} point1 Start point.\n * @param {import("../../coordinate.js").Coordinate} point2 End point.\n * @return {boolean} `true` if the segment and the extent intersect,\n * `false` otherwise.\n */\n function (point1, point2) {\n return intersectsSegment(extent, point1, point2);\n });\n}\n/**\n * @param {Array<number>} flatCoordinates Flat coordinates.\n * @param {number} offset Offset.\n * @param {Array<number>} ends Ends.\n * @param {number} stride Stride.\n * @param {import("../../extent.js").Extent} extent Extent.\n * @return {boolean} True if the geometry and the extent intersect.\n */\n\nfunction intersectsLineStringArray(flatCoordinates, offset, ends, stride, extent) {\n for (var i = 0, ii = ends.length; i < ii; ++i) {\n if (intersectsLineString(flatCoordinates, offset, ends[i], stride, extent)) {\n return true;\n }\n\n offset = ends[i];\n }\n\n return false;\n}\n/**\n * @param {Array<number>} flatCoordinates Flat coordinates.\n * @param {number} offset Offset.\n * @param {number} end End.\n * @param {number} stride Stride.\n * @param {import("../../extent.js").Extent} extent Extent.\n * @return {boolean} True if the geometry and the extent intersect.\n */\n\nfunction intersectsLinearRing(flatCoordinates, offset, end, stride, extent) {\n if (intersectsLineString(flatCoordinates, offset, end, stride, extent)) {\n return true;\n }\n\n if (linearRingContainsXY(flatCoordinates, offset, end, stride, extent[0], extent[1])) {\n return true;\n }\n\n if (linearRingContainsXY(flatCoordinates, offset, end, stride, extent[0], extent[3])) {\n return true;\n }\n\n if (linearRingContainsXY(flatCoordinates, offset, end, stride, extent[2], extent[1])) {\n return true;\n }\n\n if (linearRingContainsXY(flatCoordinates, offset, end, stride, extent[2], extent[3])) {\n return true;\n }\n\n return false;\n}\n/**\n * @param {Array<number>} flatCoordinates Flat coordinates.\n * @param {number} offset Offset.\n * @param {Array<number>} ends Ends.\n * @param {number} stride Stride.\n * @param {import("../../extent.js").Extent} extent Extent.\n * @return {boolean} True if the geometry and the extent intersect.\n */\n\nfunction intersectsLinearRingArray(flatCoordinates, offset, ends, stride, extent) {\n if (!intersectsLinearRing(flatCoordinates, offset, ends[0], stride, extent)) {\n return false;\n }\n\n if (ends.length === 1) {\n return true;\n }\n\n for (var i = 1, ii = ends.length; i < ii; ++i) {\n if (linearRingContainsExtent(flatCoordinates, ends[i - 1], ends[i], stride, extent)) {\n if (!intersectsLineString(flatCoordinates, ends[i - 1], ends[i], stride, extent)) {\n return false;\n }\n }\n }\n\n return true;\n}\n/**\n * @param {Array<number>} flatCoordinates Flat coordinates.\n * @param {number} offset Offset.\n * @param {Array<Array<number>>} endss Endss.\n * @param {number} stride Stride.\n * @param {import("../../extent.js").Extent} extent Extent.\n * @return {boolean} True if the geometry and the extent intersect.\n */\n\nfunction intersectsLinearRingMultiArray(flatCoordinates, offset, endss, stride, extent) {\n for (var i = 0, ii = endss.length; i < ii; ++i) {\n var ends = endss[i];\n\n if (intersectsLinearRingArray(flatCoordinates, offset, ends, stride, extent)) {\n return true;\n }\n\n offset = ends[ends.length - 1];\n }\n\n return false;\n}\n;// CONCATENATED MODULE: ./node_modules/ol/geom/flat/reverse.js\n/**\n * @module ol/geom/flat/reverse\n */\n\n/**\n * @param {Array<number>} flatCoordinates Flat coordinates.\n * @param {number} offset Offset.\n * @param {number} end End.\n * @param {number} stride Stride.\n */\nfunction coordinates(flatCoordinates, offset, end, stride) {\n while (offset < end - stride) {\n for (var i = 0; i < stride; ++i) {\n var tmp = flatCoordinates[offset + i];\n flatCoordinates[offset + i] = flatCoordinates[end - stride + i];\n flatCoordinates[end - stride + i] = tmp;\n }\n\n offset += stride;\n end -= stride;\n }\n}\n;// CONCATENATED MODULE: ./node_modules/ol/geom/flat/orient.js\n/**\n * @module ol/geom/flat/orient\n */\n\n/**\n * Is the linear ring oriented clockwise in a coordinate system with a bottom-left\n * coordinate origin? For a coordinate system with a top-left coordinate origin,\n * the ring\'s orientation is clockwise when this function returns false.\n * @param {Array<number>} flatCoordinates Flat coordinates.\n * @param {number} offset Offset.\n * @param {number} end End.\n * @param {number} stride Stride.\n * @return {boolean} Is clockwise.\n */\n\nfunction linearRingIsClockwise(flatCoordinates, offset, end, stride) {\n // http://tinyurl.com/clockwise-method\n // https://github.com/OSGeo/gdal/blob/trunk/gdal/ogr/ogrlinearring.cpp\n var edge = 0;\n var x1 = flatCoordinates[end - stride];\n var y1 = flatCoordinates[end - stride + 1];\n\n for (; offset < end; offset += stride) {\n var x2 = flatCoordinates[offset];\n var y2 = flatCoordinates[offset + 1];\n edge += (x2 - x1) * (y2 + y1);\n x1 = x2;\n y1 = y2;\n }\n\n return edge === 0 ? undefined : edge > 0;\n}\n/**\n * Determines if linear rings are oriented. By default, left-hand orientation\n * is tested (first ring must be clockwise, remaining rings counter-clockwise).\n * To test for right-hand orientation, use the `opt_right` argument.\n *\n * @param {Array<number>} flatCoordinates Flat coordinates.\n * @param {number} offset Offset.\n * @param {Array<number>} ends Array of end indexes.\n * @param {number} stride Stride.\n * @param {boolean=} opt_right Test for right-hand orientation\n * (counter-clockwise exterior ring and clockwise interior rings).\n * @return {boolean} Rings are correctly oriented.\n */\n\nfunction linearRingsAreOriented(flatCoordinates, offset, ends, stride, opt_right) {\n var right = opt_right !== undefined ? opt_right : false;\n\n for (var i = 0, ii = ends.length; i < ii; ++i) {\n var end = ends[i];\n var isClockwise = linearRingIsClockwise(flatCoordinates, offset, end, stride);\n\n if (i === 0) {\n if (right && isClockwise || !right && !isClockwise) {\n return false;\n }\n } else {\n if (right && !isClockwise || !right && isClockwise) {\n return false;\n }\n }\n\n offset = end;\n }\n\n return true;\n}\n/**\n * Determines if linear rings are oriented. By default, left-hand orientation\n * is tested (first ring must be clockwise, remaining rings counter-clockwise).\n * To test for right-hand orientation, use the `opt_right` argument.\n *\n * @param {Array<number>} flatCoordinates Flat coordinates.\n * @param {number} offset Offset.\n * @param {Array<Array<number>>} endss Array of array of end indexes.\n * @param {number} stride Stride.\n * @param {boolean=} opt_right Test for right-hand orientation\n * (counter-clockwise exterior ring and clockwise interior rings).\n * @return {boolean} Rings are correctly oriented.\n */\n\nfunction linearRingssAreOriented(flatCoordinates, offset, endss, stride, opt_right) {\n for (var i = 0, ii = endss.length; i < ii; ++i) {\n var ends = endss[i];\n\n if (!linearRingsAreOriented(flatCoordinates, offset, ends, stride, opt_right)) {\n return false;\n }\n\n if (ends.length) {\n offset = ends[ends.length - 1];\n }\n }\n\n return true;\n}\n/**\n * Orient coordinates in a flat array of linear rings. By default, rings\n * are oriented following the left-hand rule (clockwise for exterior and\n * counter-clockwise for interior rings). To orient according to the\n * right-hand rule, use the `opt_right` argument.\n *\n * @param {Array<number>} flatCoordinates Flat coordinates.\n * @param {number} offset Offset.\n * @param {Array<number>} ends Ends.\n * @param {number} stride Stride.\n * @param {boolean=} opt_right Follow the right-hand rule for orientation.\n * @return {number} End.\n */\n\nfunction orientLinearRings(flatCoordinates, offset, ends, stride, opt_right) {\n var right = opt_right !== undefined ? opt_right : false;\n\n for (var i = 0, ii = ends.length; i < ii; ++i) {\n var end = ends[i];\n var isClockwise = linearRingIsClockwise(flatCoordinates, offset, end, stride);\n var reverse = i === 0 ? right && isClockwise || !right && !isClockwise : right && !isClockwise || !right && isClockwise;\n\n if (reverse) {\n coordinates(flatCoordinates, offset, end, stride);\n }\n\n offset = end;\n }\n\n return offset;\n}\n/**\n * Orient coordinates in a flat array of linear rings. By default, rings\n * are oriented following the left-hand rule (clockwise for exterior and\n * counter-clockwise for interior rings). To orient according to the\n * right-hand rule, use the `opt_right` argument.\n *\n * @param {Array<number>} flatCoordinates Flat coordinates.\n * @param {number} offset Offset.\n * @param {Array<Array<number>>} endss Array of array of end indexes.\n * @param {number} stride Stride.\n * @param {boolean=} opt_right Follow the right-hand rule for orientation.\n * @return {number} End.\n */\n\nfunction orientLinearRingsArray(flatCoordinates, offset, endss, stride, opt_right) {\n for (var i = 0, ii = endss.length; i < ii; ++i) {\n offset = orientLinearRings(flatCoordinates, offset, endss[i], stride, opt_right);\n }\n\n return offset;\n}\n;// CONCATENATED MODULE: ./node_modules/ol/geom/Polygon.js\nvar Polygon_extends = undefined && undefined.__extends || function () {\n var _extendStatics = function extendStatics(d, b) {\n _extendStatics = Object.setPrototypeOf || {\n __proto__: []\n } instanceof Array && function (d, b) {\n d.__proto__ = b;\n } || function (d, b) {\n for (var p in b) {\n if (Object.prototype.hasOwnProperty.call(b, p)) d[p] = b[p];\n }\n };\n\n return _extendStatics(d, b);\n };\n\n return function (d, b) {\n _extendStatics(d, b);\n\n function __() {\n this.constructor = d;\n }\n\n d.prototype = b === null ? Object.create(b) : (__.prototype = b.prototype, new __());\n };\n}();\n/**\n * @module ol/geom/Polygon\n */\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n/**\n * @classdesc\n * Polygon geometry.\n *\n * @api\n */\n\nvar Polygon =\n/** @class */\nfunction (_super) {\n Polygon_extends(Polygon, _super);\n /**\n * @param {!Array<Array<import("../coordinate.js").Coordinate>>|!Array<number>} coordinates\n * Array of linear rings that define the polygon. The first linear ring of the\n * array defines the outer-boundary or surface of the polygon. Each subsequent\n * linear ring defines a hole in the surface of the polygon. A linear ring is\n * an array of vertices\' coordinates where the first coordinate and the last are\n * equivalent. (For internal use, flat coordinates in combination with\n * `opt_layout` and `opt_ends` are also accepted.)\n * @param {import("./GeometryLayout.js").default=} opt_layout Layout.\n * @param {Array<number>=} opt_ends Ends (for internal use with flat coordinates).\n */\n\n\n function Polygon(coordinates, opt_layout, opt_ends) {\n var _this = _super.call(this) || this;\n /**\n * @type {Array<number>}\n * @private\n */\n\n\n _this.ends_ = [];\n /**\n * @private\n * @type {number}\n */\n\n _this.flatInteriorPointRevision_ = -1;\n /**\n * @private\n * @type {import("../coordinate.js").Coordinate}\n */\n\n _this.flatInteriorPoint_ = null;\n /**\n * @private\n * @type {number}\n */\n\n _this.maxDelta_ = -1;\n /**\n * @private\n * @type {number}\n */\n\n _this.maxDeltaRevision_ = -1;\n /**\n * @private\n * @type {number}\n */\n\n _this.orientedRevision_ = -1;\n /**\n * @private\n * @type {Array<number>}\n */\n\n _this.orientedFlatCoordinates_ = null;\n\n if (opt_layout !== undefined && opt_ends) {\n _this.setFlatCoordinates(opt_layout,\n /** @type {Array<number>} */\n coordinates);\n\n _this.ends_ = opt_ends;\n } else {\n _this.setCoordinates(\n /** @type {Array<Array<import("../coordinate.js").Coordinate>>} */\n coordinates, opt_layout);\n }\n\n return _this;\n }\n /**\n * Append the passed linear ring to this polygon.\n * @param {LinearRing} linearRing Linear ring.\n * @api\n */\n\n\n Polygon.prototype.appendLinearRing = function (linearRing) {\n if (!this.flatCoordinates) {\n this.flatCoordinates = linearRing.getFlatCoordinates().slice();\n } else {\n array_extend(this.flatCoordinates, linearRing.getFlatCoordinates());\n }\n\n this.ends_.push(this.flatCoordinates.length);\n this.changed();\n };\n /**\n * Make a complete copy of the geometry.\n * @return {!Polygon} Clone.\n * @api\n */\n\n\n Polygon.prototype.clone = function () {\n var polygon = new Polygon(this.flatCoordinates.slice(), this.layout, this.ends_.slice());\n polygon.applyProperties(this);\n return polygon;\n };\n /**\n * @param {number} x X.\n * @param {number} y Y.\n * @param {import("../coordinate.js").Coordinate} closestPoint Closest point.\n * @param {number} minSquaredDistance Minimum squared distance.\n * @return {number} Minimum squared distance.\n */\n\n\n Polygon.prototype.closestPointXY = function (x, y, closestPoint, minSquaredDistance) {\n if (minSquaredDistance < closestSquaredDistanceXY(this.getExtent(), x, y)) {\n return minSquaredDistance;\n }\n\n if (this.maxDeltaRevision_ != this.getRevision()) {\n this.maxDelta_ = Math.sqrt(arrayMaxSquaredDelta(this.flatCoordinates, 0, this.ends_, this.stride, 0));\n this.maxDeltaRevision_ = this.getRevision();\n }\n\n return assignClosestArrayPoint(this.flatCoordinates, 0, this.ends_, this.stride, this.maxDelta_, true, x, y, closestPoint, minSquaredDistance);\n };\n /**\n * @param {number} x X.\n * @param {number} y Y.\n * @return {boolean} Contains (x, y).\n */\n\n\n Polygon.prototype.containsXY = function (x, y) {\n return linearRingsContainsXY(this.getOrientedFlatCoordinates(), 0, this.ends_, this.stride, x, y);\n };\n /**\n * Return the area of the polygon on projected plane.\n * @return {number} Area (on projected plane).\n * @api\n */\n\n\n Polygon.prototype.getArea = function () {\n return linearRings(this.getOrientedFlatCoordinates(), 0, this.ends_, this.stride);\n };\n /**\n * Get the coordinate array for this geometry. This array has the structure\n * of a GeoJSON coordinate array for polygons.\n *\n * @param {boolean=} opt_right Orient coordinates according to the right-hand\n * rule (counter-clockwise for exterior and clockwise for interior rings).\n * If `false`, coordinates will be oriented according to the left-hand rule\n * (clockwise for exterior and counter-clockwise for interior rings).\n * By default, coordinate orientation will depend on how the geometry was\n * constructed.\n * @return {Array<Array<import("../coordinate.js").Coordinate>>} Coordinates.\n * @api\n */\n\n\n Polygon.prototype.getCoordinates = function (opt_right) {\n var flatCoordinates;\n\n if (opt_right !== undefined) {\n flatCoordinates = this.getOrientedFlatCoordinates().slice();\n orientLinearRings(flatCoordinates, 0, this.ends_, this.stride, opt_right);\n } else {\n flatCoordinates = this.flatCoordinates;\n }\n\n return inflateCoordinatesArray(flatCoordinates, 0, this.ends_, this.stride);\n };\n /**\n * @return {Array<number>} Ends.\n */\n\n\n Polygon.prototype.getEnds = function () {\n return this.ends_;\n };\n /**\n * @return {Array<number>} Interior point.\n */\n\n\n Polygon.prototype.getFlatInteriorPoint = function () {\n if (this.flatInteriorPointRevision_ != this.getRevision()) {\n var flatCenter = getCenter(this.getExtent());\n this.flatInteriorPoint_ = getInteriorPointOfArray(this.getOrientedFlatCoordinates(), 0, this.ends_, this.stride, flatCenter, 0);\n this.flatInteriorPointRevision_ = this.getRevision();\n }\n\n return this.flatInteriorPoint_;\n };\n /**\n * Return an interior point of the polygon.\n * @return {Point} Interior point as XYM coordinate, where M is the\n * length of the horizontal intersection that the point belongs to.\n * @api\n */\n\n\n Polygon.prototype.getInteriorPoint = function () {\n return new geom_Point(this.getFlatInteriorPoint(), geom_GeometryLayout.XYM);\n };\n /**\n * Return the number of rings of the polygon, this includes the exterior\n * ring and any interior rings.\n *\n * @return {number} Number of rings.\n * @api\n */\n\n\n Polygon.prototype.getLinearRingCount = function () {\n return this.ends_.length;\n };\n /**\n * Return the Nth linear ring of the polygon geometry. Return `null` if the\n * given index is out of range.\n * The exterior linear ring is available at index `0` and the interior rings\n * at index `1` and beyond.\n *\n * @param {number} index Index.\n * @return {LinearRing} Linear ring.\n * @api\n */\n\n\n Polygon.prototype.getLinearRing = function (index) {\n if (index < 0 || this.ends_.length <= index) {\n return null;\n }\n\n return new geom_LinearRing(this.flatCoordinates.slice(index === 0 ? 0 : this.ends_[index - 1], this.ends_[index]), this.layout);\n };\n /**\n * Return the linear rings of the polygon.\n * @return {Array<LinearRing>} Linear rings.\n * @api\n */\n\n\n Polygon.prototype.getLinearRings = function () {\n var layout = this.layout;\n var flatCoordinates = this.flatCoordinates;\n var ends = this.ends_;\n var linearRings = [];\n var offset = 0;\n\n for (var i = 0, ii = ends.length; i < ii; ++i) {\n var end = ends[i];\n var linearRing = new geom_LinearRing(flatCoordinates.slice(offset, end), layout);\n linearRings.push(linearRing);\n offset = end;\n }\n\n return linearRings;\n };\n /**\n * @return {Array<number>} Oriented flat coordinates.\n */\n\n\n Polygon.prototype.getOrientedFlatCoordinates = function () {\n if (this.orientedRevision_ != this.getRevision()) {\n var flatCoordinates = this.flatCoordinates;\n\n if (linearRingsAreOriented(flatCoordinates, 0, this.ends_, this.stride)) {\n this.orientedFlatCoordinates_ = flatCoordinates;\n } else {\n this.orientedFlatCoordinates_ = flatCoordinates.slice();\n this.orientedFlatCoordinates_.length = orientLinearRings(this.orientedFlatCoordinates_, 0, this.ends_, this.stride);\n }\n\n this.orientedRevision_ = this.getRevision();\n }\n\n return this.orientedFlatCoordinates_;\n };\n /**\n * @param {number} squaredTolerance Squared tolerance.\n * @return {Polygon} Simplified Polygon.\n * @protected\n */\n\n\n Polygon.prototype.getSimplifiedGeometryInternal = function (squaredTolerance) {\n var simplifiedFlatCoordinates = [];\n var simplifiedEnds = [];\n simplifiedFlatCoordinates.length = quantizeArray(this.flatCoordinates, 0, this.ends_, this.stride, Math.sqrt(squaredTolerance), simplifiedFlatCoordinates, 0, simplifiedEnds);\n return new Polygon(simplifiedFlatCoordinates, geom_GeometryLayout.XY, simplifiedEnds);\n };\n /**\n * Get the type of this geometry.\n * @return {import("./GeometryType.js").default} Geometry type.\n * @api\n */\n\n\n Polygon.prototype.getType = function () {\n return geom_GeometryType.POLYGON;\n };\n /**\n * Test if the geometry and the passed extent intersect.\n * @param {import("../extent.js").Extent} extent Extent.\n * @return {boolean} `true` if the geometry and the extent intersect.\n * @api\n */\n\n\n Polygon.prototype.intersectsExtent = function (extent) {\n return intersectsLinearRingArray(this.getOrientedFlatCoordinates(), 0, this.ends_, this.stride, extent);\n };\n /**\n * Set the coordinates of the polygon.\n * @param {!Array<Array<import("../coordinate.js").Coordinate>>} coordinates Coordinates.\n * @param {import("./GeometryLayout.js").default=} opt_layout Layout.\n * @api\n */\n\n\n Polygon.prototype.setCoordinates = function (coordinates, opt_layout) {\n this.setLayout(opt_layout, coordinates, 2);\n\n if (!this.flatCoordinates) {\n this.flatCoordinates = [];\n }\n\n var ends = deflateCoordinatesArray(this.flatCoordinates, 0, coordinates, this.stride, this.ends_);\n this.flatCoordinates.length = ends.length === 0 ? 0 : ends[ends.length - 1];\n this.changed();\n };\n\n return Polygon;\n}(geom_SimpleGeometry);\n\n/* harmony default export */ var geom_Polygon = (Polygon);\n/**\n * Create an approximation of a circle on the surface of a sphere.\n * @param {import("../coordinate.js").Coordinate} center Center (`[lon, lat]` in degrees).\n * @param {number} radius The great-circle distance from the center to\n * the polygon vertices.\n * @param {number=} opt_n Optional number of vertices for the resulting\n * polygon. Default is `32`.\n * @param {number=} opt_sphereRadius Optional radius for the sphere (defaults to\n * the Earth\'s mean radius using the WGS84 ellipsoid).\n * @return {Polygon} The "circular" polygon.\n * @api\n */\n\nfunction circular(center, radius, opt_n, opt_sphereRadius) {\n var n = opt_n ? opt_n : 32;\n /** @type {Array<number>} */\n\n var flatCoordinates = [];\n\n for (var i = 0; i < n; ++i) {\n extend(flatCoordinates, sphereOffset(center, radius, 2 * Math.PI * i / n, opt_sphereRadius));\n }\n\n flatCoordinates.push(flatCoordinates[0], flatCoordinates[1]);\n return new Polygon(flatCoordinates, GeometryLayout.XY, [flatCoordinates.length]);\n}\n/**\n * Create a polygon from an extent. The layout used is `XY`.\n * @param {import("../extent.js").Extent} extent The extent.\n * @return {Polygon} The polygon.\n * @api\n */\n\nfunction fromExtent(extent) {\n var minX = extent[0];\n var minY = extent[1];\n var maxX = extent[2];\n var maxY = extent[3];\n var flatCoordinates = [minX, minY, minX, maxY, maxX, maxY, maxX, minY, minX, minY];\n return new Polygon(flatCoordinates, geom_GeometryLayout.XY, [flatCoordinates.length]);\n}\n/**\n * Create a regular polygon from a circle.\n * @param {import("./Circle.js").default} circle Circle geometry.\n * @param {number=} opt_sides Number of sides of the polygon. Default is 32.\n * @param {number=} opt_angle Start angle for the first vertex of the polygon in\n * counter-clockwise radians. 0 means East. Default is 0.\n * @return {Polygon} Polygon geometry.\n * @api\n */\n\nfunction fromCircle(circle, opt_sides, opt_angle) {\n var sides = opt_sides ? opt_sides : 32;\n var stride = circle.getStride();\n var layout = circle.getLayout();\n var center = circle.getCenter();\n var arrayLength = stride * (sides + 1);\n var flatCoordinates = new Array(arrayLength);\n\n for (var i = 0; i < arrayLength; i += stride) {\n flatCoordinates[i] = 0;\n flatCoordinates[i + 1] = 0;\n\n for (var j = 2; j < stride; j++) {\n flatCoordinates[i + j] = center[j];\n }\n }\n\n var ends = [flatCoordinates.length];\n var polygon = new Polygon(flatCoordinates, layout, ends);\n makeRegular(polygon, center, circle.getRadius(), opt_angle);\n return polygon;\n}\n/**\n * Modify the coordinates of a polygon to make it a regular polygon.\n * @param {Polygon} polygon Polygon geometry.\n * @param {import("../coordinate.js").Coordinate} center Center of the regular polygon.\n * @param {number} radius Radius of the regular polygon.\n * @param {number=} opt_angle Start angle for the first vertex of the polygon in\n * counter-clockwise radians. 0 means East. Default is 0.\n */\n\nfunction makeRegular(polygon, center, radius, opt_angle) {\n var flatCoordinates = polygon.getFlatCoordinates();\n var stride = polygon.getStride();\n var sides = flatCoordinates.length / stride - 1;\n var startAngle = opt_angle ? opt_angle : 0;\n\n for (var i = 0; i <= sides; ++i) {\n var offset = i * stride;\n var angle = startAngle + modulo(i, sides) * 2 * Math.PI / sides;\n flatCoordinates[offset] = center[0] + radius * Math.cos(angle);\n flatCoordinates[offset + 1] = center[1] + radius * Math.sin(angle);\n }\n\n polygon.changed();\n}\n;// CONCATENATED MODULE: ./node_modules/ol/View.js\nvar View_extends = undefined && undefined.__extends || function () {\n var _extendStatics = function extendStatics(d, b) {\n _extendStatics = Object.setPrototypeOf || {\n __proto__: []\n } instanceof Array && function (d, b) {\n d.__proto__ = b;\n } || function (d, b) {\n for (var p in b) {\n if (Object.prototype.hasOwnProperty.call(b, p)) d[p] = b[p];\n }\n };\n\n return _extendStatics(d, b);\n };\n\n return function (d, b) {\n _extendStatics(d, b);\n\n function __() {\n this.constructor = d;\n }\n\n d.prototype = b === null ? Object.create(b) : (__.prototype = b.prototype, new __());\n };\n}();\n/**\n * @module ol/View\n */\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n/**\n * An animation configuration\n *\n * @typedef {Object} Animation\n * @property {import("./coordinate.js").Coordinate} [sourceCenter]\n * @property {import("./coordinate.js").Coordinate} [targetCenter]\n * @property {number} [sourceResolution]\n * @property {number} [targetResolution]\n * @property {number} [sourceRotation]\n * @property {number} [targetRotation]\n * @property {import("./coordinate.js").Coordinate} [anchor]\n * @property {number} start\n * @property {number} duration\n * @property {boolean} complete\n * @property {function(number):number} easing\n * @property {function(boolean):void} callback\n */\n\n/**\n * @typedef {Object} Constraints\n * @property {import("./centerconstraint.js").Type} center\n * @property {import("./resolutionconstraint.js").Type} resolution\n * @property {import("./rotationconstraint.js").Type} rotation\n */\n\n/**\n * @typedef {Object} FitOptions\n * @property {import("./size.js").Size} [size] The size in pixels of the box to fit\n * the extent into. Default is the current size of the first map in the DOM that\n * uses this view, or `[100, 100]` if no such map is found.\n * @property {!Array<number>} [padding=[0, 0, 0, 0]] Padding (in pixels) to be\n * cleared inside the view. Values in the array are top, right, bottom and left\n * padding.\n * @property {boolean} [nearest=false] If the view `constrainResolution` option is `true`,\n * get the nearest extent instead of the closest that actually fits the view.\n * @property {number} [minResolution=0] Minimum resolution that we zoom to.\n * @property {number} [maxZoom] Maximum zoom level that we zoom to. If\n * `minResolution` is given, this property is ignored.\n * @property {number} [duration] The duration of the animation in milliseconds.\n * By default, there is no animation to the target extent.\n * @property {function(number):number} [easing] The easing function used during\n * the animation (defaults to {@link module:ol/easing~inAndOut}).\n * The function will be called for each frame with a number representing a\n * fraction of the animation\'s duration. The function should return a number\n * between 0 and 1 representing the progress toward the destination state.\n * @property {function(boolean):void} [callback] Function called when the view is in\n * its final position. The callback will be called with `true` if the animation\n * series completed on its own or `false` if it was cancelled.\n */\n\n/**\n * @typedef {Object} ViewOptions\n * @property {import("./coordinate.js").Coordinate} [center] The initial center for\n * the view. If a user projection is not set, the coordinate system for the center is\n * specified with the `projection` option. Layer sources will not be fetched if this\n * is not set, but the center can be set later with {@link #setCenter}.\n * @property {boolean|number} [constrainRotation=true] Rotation constraint.\n * `false` means no constraint. `true` means no constraint, but snap to zero\n * near zero. A number constrains the rotation to that number of values. For\n * example, `4` will constrain the rotation to 0, 90, 180, and 270 degrees.\n * @property {boolean} [enableRotation=true] Enable rotation.\n * If `false`, a rotation constraint that always sets the rotation to zero is\n * used. The `constrainRotation` option has no effect if `enableRotation` is\n * `false`.\n * @property {import("./extent.js").Extent} [extent] The extent that constrains the\n * view, in other words, nothing outside of this extent can be visible on the map.\n * @property {boolean} [constrainOnlyCenter=false] If true, the extent\n * constraint will only apply to the view center and not the whole extent.\n * @property {boolean} [smoothExtentConstraint=true] If true, the extent\n * constraint will be applied smoothly, i.e. allow the view to go slightly outside\n * of the given `extent`.\n * @property {number} [maxResolution] The maximum resolution used to determine\n * the resolution constraint. It is used together with `minResolution` (or\n * `maxZoom`) and `zoomFactor`. If unspecified it is calculated in such a way\n * that the projection\'s validity extent fits in a 256x256 px tile. If the\n * projection is Spherical Mercator (the default) then `maxResolution` defaults\n * to `40075016.68557849 / 256 = 156543.03392804097`.\n * @property {number} [minResolution] The minimum resolution used to determine\n * the resolution constraint. It is used together with `maxResolution` (or\n * `minZoom`) and `zoomFactor`. If unspecified it is calculated assuming 29\n * zoom levels (with a factor of 2). If the projection is Spherical Mercator\n * (the default) then `minResolution` defaults to\n * `40075016.68557849 / 256 / Math.pow(2, 28) = 0.0005831682455839253`.\n * @property {number} [maxZoom=28] The maximum zoom level used to determine the\n * resolution constraint. It is used together with `minZoom` (or\n * `maxResolution`) and `zoomFactor`. Note that if `minResolution` is also\n * provided, it is given precedence over `maxZoom`.\n * @property {number} [minZoom=0] The minimum zoom level used to determine the\n * resolution constraint. It is used together with `maxZoom` (or\n * `minResolution`) and `zoomFactor`. Note that if `maxResolution` is also\n * provided, it is given precedence over `minZoom`.\n * @property {boolean} [multiWorld=false] If `false` the view is constrained so\n * only one world is visible, and you cannot pan off the edge. If `true` the map\n * may show multiple worlds at low zoom levels. Only used if the `projection` is\n * global. Note that if `extent` is also provided it is given precedence.\n * @property {boolean} [constrainResolution=false] If true, the view will always\n * animate to the closest zoom level after an interaction; false means\n * intermediary zoom levels are allowed.\n * @property {boolean} [smoothResolutionConstraint=true] If true, the resolution\n * min/max values will be applied smoothly, i. e. allow the view to exceed slightly\n * the given resolution or zoom bounds.\n * @property {boolean} [showFullExtent=false] Allow the view to be zoomed out to\n * show the full configured extent. By default, when a view is configured with an\n * extent, users will not be able to zoom out so the viewport exceeds the extent in\n * either dimension. This means the full extent may not be visible if the viewport\n * is taller or wider than the aspect ratio of the configured extent. If\n * showFullExtent is true, the user will be able to zoom out so that the viewport\n * exceeds the height or width of the configured extent, but not both, allowing the\n * full extent to be shown.\n * @property {import("./proj.js").ProjectionLike} [projection=\'EPSG:3857\'] The\n * projection. The default is Spherical Mercator.\n * @property {number} [resolution] The initial resolution for the view. The\n * units are `projection` units per pixel (e.g. meters per pixel). An\n * alternative to setting this is to set `zoom`. Layer sources will not be\n * fetched if neither this nor `zoom` are defined, but they can be set later\n * with {@link #setZoom} or {@link #setResolution}.\n * @property {Array<number>} [resolutions] Resolutions to determine the\n * resolution constraint. If set the `maxResolution`, `minResolution`,\n * `minZoom`, `maxZoom`, and `zoomFactor` options are ignored.\n * @property {number} [rotation=0] The initial rotation for the view in radians\n * (positive rotation clockwise, 0 means North).\n * @property {number} [zoom] Only used if `resolution` is not defined. Zoom\n * level used to calculate the initial resolution for the view.\n * @property {number} [zoomFactor=2] The zoom factor used to compute the\n * corresponding resolution.\n * @property {!Array<number>} [padding=[0, 0, 0, 0]] Padding (in css pixels).\n * If the map viewport is partially covered with other content (overlays) along\n * its edges, this setting allows to shift the center of the viewport away from\n * that content. The order of the values is top, right, bottom, left.\n */\n\n/**\n * @typedef {Object} AnimationOptions\n * @property {import("./coordinate.js").Coordinate} [center] The center of the view at the end of\n * the animation.\n * @property {number} [zoom] The zoom level of the view at the end of the\n * animation. This takes precedence over `resolution`.\n * @property {number} [resolution] The resolution of the view at the end\n * of the animation. If `zoom` is also provided, this option will be ignored.\n * @property {number} [rotation] The rotation of the view at the end of\n * the animation.\n * @property {import("./coordinate.js").Coordinate} [anchor] Optional anchor to remain fixed\n * during a rotation or resolution animation.\n * @property {number} [duration=1000] The duration of the animation in milliseconds.\n * @property {function(number):number} [easing] The easing function used\n * during the animation (defaults to {@link module:ol/easing~inAndOut}).\n * The function will be called for each frame with a number representing a\n * fraction of the animation\'s duration. The function should return a number\n * between 0 and 1 representing the progress toward the destination state.\n */\n\n/**\n * @typedef {Object} State\n * @property {import("./coordinate.js").Coordinate} center\n * @property {import("./proj/Projection.js").default} projection\n * @property {number} resolution\n * @property {number} rotation\n * @property {number} zoom\n */\n\n/**\n * Default min zoom level for the map view.\n * @type {number}\n */\n\nvar DEFAULT_MIN_ZOOM = 0;\n/**\n * @classdesc\n * A View object represents a simple 2D view of the map.\n *\n * This is the object to act upon to change the center, resolution,\n * and rotation of the map.\n *\n * A View has a `projection`. The projection determines the\n * coordinate system of the center, and its units determine the units of the\n * resolution (projection units per pixel). The default projection is\n * Spherical Mercator (EPSG:3857).\n *\n * ### The view states\n *\n * A View is determined by three states: `center`, `resolution`,\n * and `rotation`. Each state has a corresponding getter and setter, e.g.\n * `getCenter` and `setCenter` for the `center` state.\n *\n * The `zoom` state is actually not saved on the view: all computations\n * internally use the `resolution` state. Still, the `setZoom` and `getZoom`\n * methods are available, as well as `getResolutionForZoom` and\n * `getZoomForResolution` to switch from one system to the other.\n *\n * ### The constraints\n *\n * `setCenter`, `setResolution` and `setRotation` can be used to change the\n * states of the view, but any constraint defined in the constructor will\n * be applied along the way.\n *\n * A View object can have a *resolution constraint*, a *rotation constraint*\n * and a *center constraint*.\n *\n * The *resolution constraint* typically restricts min/max values and\n * snaps to specific resolutions. It is determined by the following\n * options: `resolutions`, `maxResolution`, `maxZoom` and `zoomFactor`.\n * If `resolutions` is set, the other three options are ignored. See\n * documentation for each option for more information. By default, the view\n * only has a min/max restriction and allow intermediary zoom levels when\n * pinch-zooming for example.\n *\n * The *rotation constraint* snaps to specific angles. It is determined\n * by the following options: `enableRotation` and `constrainRotation`.\n * By default rotation is allowed and its value is snapped to zero when approaching the\n * horizontal.\n *\n * The *center constraint* is determined by the `extent` option. By\n * default the view center is not constrained at all.\n *\n * ### Changing the view state\n *\n * It is important to note that `setZoom`, `setResolution`, `setCenter` and\n * `setRotation` are subject to the above mentioned constraints. As such, it\n * may sometimes not be possible to know in advance the resulting state of the\n * View. For example, calling `setResolution(10)` does not guarantee that\n * `getResolution()` will return `10`.\n *\n * A consequence of this is that, when applying a delta on the view state, one\n * should use `adjustCenter`, `adjustRotation`, `adjustZoom` and `adjustResolution`\n * rather than the corresponding setters. This will let view do its internal\n * computations. Besides, the `adjust*` methods also take an `opt_anchor`\n * argument which allows specifying an origin for the transformation.\n *\n * ### Interacting with the view\n *\n * View constraints are usually only applied when the view is *at rest*, meaning that\n * no interaction or animation is ongoing. As such, if the user puts the view in a\n * state that is not equivalent to a constrained one (e.g. rotating the view when\n * the snap angle is 0), an animation will be triggered at the interaction end to\n * put back the view to a stable state;\n *\n * @api\n */\n\nvar View =\n/** @class */\nfunction (_super) {\n View_extends(View, _super);\n /**\n * @param {ViewOptions=} opt_options View options.\n */\n\n\n function View(opt_options) {\n var _this = _super.call(this) || this;\n\n var options = obj_assign({}, opt_options);\n /**\n * @private\n * @type {Array<number>}\n */\n\n _this.hints_ = [0, 0];\n /**\n * @private\n * @type {Array<Array<Animation>>}\n */\n\n _this.animations_ = [];\n /**\n * @private\n * @type {number|undefined}\n */\n\n _this.updateAnimationKey_;\n /**\n * @private\n * @const\n * @type {import("./proj/Projection.js").default}\n */\n\n _this.projection_ = createProjection(options.projection, \'EPSG:3857\');\n /**\n * @private\n * @type {import("./size.js").Size}\n */\n\n _this.viewportSize_ = [100, 100];\n /**\n * @private\n * @type {import("./coordinate.js").Coordinate|undefined}\n */\n\n _this.targetCenter_ = null;\n /**\n * @private\n * @type {number|undefined}\n */\n\n _this.targetResolution_;\n /**\n * @private\n * @type {number|undefined}\n */\n\n _this.targetRotation_;\n /**\n * @private\n * @type {import("./coordinate.js").Coordinate|undefined}\n */\n\n _this.cancelAnchor_ = undefined;\n\n if (options.center) {\n options.center = fromUserCoordinate(options.center, _this.projection_);\n }\n\n if (options.extent) {\n options.extent = fromUserExtent(options.extent, _this.projection_);\n }\n\n _this.applyOptions_(options);\n\n return _this;\n }\n /**\n * Set up the view with the given options.\n * @param {ViewOptions} options View options.\n */\n\n\n View.prototype.applyOptions_ = function (options) {\n /**\n * @type {Object<string, *>}\n */\n var properties = {};\n var resolutionConstraintInfo = createResolutionConstraint(options);\n /**\n * @private\n * @type {number}\n */\n\n this.maxResolution_ = resolutionConstraintInfo.maxResolution;\n /**\n * @private\n * @type {number}\n */\n\n this.minResolution_ = resolutionConstraintInfo.minResolution;\n /**\n * @private\n * @type {number}\n */\n\n this.zoomFactor_ = resolutionConstraintInfo.zoomFactor;\n /**\n * @private\n * @type {Array<number>|undefined}\n */\n\n this.resolutions_ = options.resolutions;\n /**\n * Padding (in css pixels).\n * If the map viewport is partially covered with other content (overlays) along\n * its edges, this setting allows to shift the center of the viewport away from that\n * content. The order of the values in the array is top, right, bottom, left.\n * The default is no padding, which is equivalent to `[0, 0, 0, 0]`.\n * @type {Array<number>|undefined}\n * @api\n */\n\n this.padding = options.padding;\n /**\n * @private\n * @type {number}\n */\n\n this.minZoom_ = resolutionConstraintInfo.minZoom;\n var centerConstraint = createCenterConstraint(options);\n var resolutionConstraint = resolutionConstraintInfo.constraint;\n var rotationConstraint = createRotationConstraint(options);\n /**\n * @private\n * @type {Constraints}\n */\n\n this.constraints_ = {\n center: centerConstraint,\n resolution: resolutionConstraint,\n rotation: rotationConstraint\n };\n this.setRotation(options.rotation !== undefined ? options.rotation : 0);\n this.setCenterInternal(options.center !== undefined ? options.center : null);\n\n if (options.resolution !== undefined) {\n this.setResolution(options.resolution);\n } else if (options.zoom !== undefined) {\n this.setZoom(options.zoom);\n }\n\n this.setProperties(properties);\n /**\n * @private\n * @type {ViewOptions}\n */\n\n this.options_ = options;\n };\n /**\n * Get an updated version of the view options used to construct the view. The\n * current resolution (or zoom), center, and rotation are applied to any stored\n * options. The provided options can be used to apply new min/max zoom or\n * resolution limits.\n * @param {ViewOptions} newOptions New options to be applied.\n * @return {ViewOptions} New options updated with the current view state.\n */\n\n\n View.prototype.getUpdatedOptions_ = function (newOptions) {\n var options = obj_assign({}, this.options_); // preserve resolution (or zoom)\n\n if (options.resolution !== undefined) {\n options.resolution = this.getResolution();\n } else {\n options.zoom = this.getZoom();\n } // preserve center\n\n\n options.center = this.getCenterInternal(); // preserve rotation\n\n options.rotation = this.getRotation();\n return obj_assign({}, options, newOptions);\n };\n /**\n * Animate the view. The view\'s center, zoom (or resolution), and rotation\n * can be animated for smooth transitions between view states. For example,\n * to animate the view to a new zoom level:\n *\n * view.animate({zoom: view.getZoom() + 1});\n *\n * By default, the animation lasts one second and uses in-and-out easing. You\n * can customize this behavior by including `duration` (in milliseconds) and\n * `easing` options (see {@link module:ol/easing}).\n *\n * To chain together multiple animations, call the method with multiple\n * animation objects. For example, to first zoom and then pan:\n *\n * view.animate({zoom: 10}, {center: [0, 0]});\n *\n * If you provide a function as the last argument to the animate method, it\n * will get called at the end of an animation series. The callback will be\n * called with `true` if the animation series completed on its own or `false`\n * if it was cancelled.\n *\n * Animations are cancelled by user interactions (e.g. dragging the map) or by\n * calling `view.setCenter()`, `view.setResolution()`, or `view.setRotation()`\n * (or another method that calls one of these).\n *\n * @param {...(AnimationOptions|function(boolean): void)} var_args Animation\n * options. Multiple animations can be run in series by passing multiple\n * options objects. To run multiple animations in parallel, call the method\n * multiple times. An optional callback can be provided as a final\n * argument. The callback will be called with a boolean indicating whether\n * the animation completed without being cancelled.\n * @api\n */\n\n\n View.prototype.animate = function (var_args) {\n if (this.isDef() && !this.getAnimating()) {\n this.resolveConstraints(0);\n }\n\n var args = new Array(arguments.length);\n\n for (var i = 0; i < args.length; ++i) {\n var options = arguments[i];\n\n if (options.center) {\n options = obj_assign({}, options);\n options.center = fromUserCoordinate(options.center, this.getProjection());\n }\n\n if (options.anchor) {\n options = obj_assign({}, options);\n options.anchor = fromUserCoordinate(options.anchor, this.getProjection());\n }\n\n args[i] = options;\n }\n\n this.animateInternal.apply(this, args);\n };\n /**\n * @param {...(AnimationOptions|function(boolean): void)} var_args Animation options.\n */\n\n\n View.prototype.animateInternal = function (var_args) {\n var animationCount = arguments.length;\n var callback;\n\n if (animationCount > 1 && typeof arguments[animationCount - 1] === \'function\') {\n callback = arguments[animationCount - 1];\n --animationCount;\n }\n\n if (!this.isDef()) {\n // if view properties are not yet set, shortcut to the final state\n var state = arguments[animationCount - 1];\n\n if (state.center) {\n this.setCenterInternal(state.center);\n }\n\n if (state.zoom !== undefined) {\n this.setZoom(state.zoom);\n }\n\n if (state.rotation !== undefined) {\n this.setRotation(state.rotation);\n }\n\n if (callback) {\n animationCallback(callback, true);\n }\n\n return;\n }\n\n var start = Date.now();\n var center = this.targetCenter_.slice();\n var resolution = this.targetResolution_;\n var rotation = this.targetRotation_;\n var series = [];\n\n for (var i = 0; i < animationCount; ++i) {\n var options =\n /** @type {AnimationOptions} */\n arguments[i];\n var animation = {\n start: start,\n complete: false,\n anchor: options.anchor,\n duration: options.duration !== undefined ? options.duration : 1000,\n easing: options.easing || inAndOut,\n callback: callback\n };\n\n if (options.center) {\n animation.sourceCenter = center;\n animation.targetCenter = options.center.slice();\n center = animation.targetCenter;\n }\n\n if (options.zoom !== undefined) {\n animation.sourceResolution = resolution;\n animation.targetResolution = this.getResolutionForZoom(options.zoom);\n resolution = animation.targetResolution;\n } else if (options.resolution) {\n animation.sourceResolution = resolution;\n animation.targetResolution = options.resolution;\n resolution = animation.targetResolution;\n }\n\n if (options.rotation !== undefined) {\n animation.sourceRotation = rotation;\n var delta = math_modulo(options.rotation - rotation + Math.PI, 2 * Math.PI) - Math.PI;\n animation.targetRotation = rotation + delta;\n rotation = animation.targetRotation;\n } // check if animation is a no-op\n\n\n if (isNoopAnimation(animation)) {\n animation.complete = true; // we still push it onto the series for callback handling\n } else {\n start += animation.duration;\n }\n\n series.push(animation);\n }\n\n this.animations_.push(series);\n this.setHint(ViewHint.ANIMATING, 1);\n this.updateAnimations_();\n };\n /**\n * Determine if the view is being animated.\n * @return {boolean} The view is being animated.\n * @api\n */\n\n\n View.prototype.getAnimating = function () {\n return this.hints_[ViewHint.ANIMATING] > 0;\n };\n /**\n * Determine if the user is interacting with the view, such as panning or zooming.\n * @return {boolean} The view is being interacted with.\n * @api\n */\n\n\n View.prototype.getInteracting = function () {\n return this.hints_[ViewHint.INTERACTING] > 0;\n };\n /**\n * Cancel any ongoing animations.\n * @api\n */\n\n\n View.prototype.cancelAnimations = function () {\n this.setHint(ViewHint.ANIMATING, -this.hints_[ViewHint.ANIMATING]);\n var anchor;\n\n for (var i = 0, ii = this.animations_.length; i < ii; ++i) {\n var series = this.animations_[i];\n\n if (series[0].callback) {\n animationCallback(series[0].callback, false);\n }\n\n if (!anchor) {\n for (var j = 0, jj = series.length; j < jj; ++j) {\n var animation = series[j];\n\n if (!animation.complete) {\n anchor = animation.anchor;\n break;\n }\n }\n }\n }\n\n this.animations_.length = 0;\n this.cancelAnchor_ = anchor;\n };\n /**\n * Update all animations.\n */\n\n\n View.prototype.updateAnimations_ = function () {\n if (this.updateAnimationKey_ !== undefined) {\n cancelAnimationFrame(this.updateAnimationKey_);\n this.updateAnimationKey_ = undefined;\n }\n\n if (!this.getAnimating()) {\n return;\n }\n\n var now = Date.now();\n var more = false;\n\n for (var i = this.animations_.length - 1; i >= 0; --i) {\n var series = this.animations_[i];\n var seriesComplete = true;\n\n for (var j = 0, jj = series.length; j < jj; ++j) {\n var animation = series[j];\n\n if (animation.complete) {\n continue;\n }\n\n var elapsed = now - animation.start;\n var fraction = animation.duration > 0 ? elapsed / animation.duration : 1;\n\n if (fraction >= 1) {\n animation.complete = true;\n fraction = 1;\n } else {\n seriesComplete = false;\n }\n\n var progress = animation.easing(fraction);\n\n if (animation.sourceCenter) {\n var x0 = animation.sourceCenter[0];\n var y0 = animation.sourceCenter[1];\n var x1 = animation.targetCenter[0];\n var y1 = animation.targetCenter[1];\n var x = x0 + progress * (x1 - x0);\n var y = y0 + progress * (y1 - y0);\n this.targetCenter_ = [x, y];\n }\n\n if (animation.sourceResolution && animation.targetResolution) {\n var resolution = progress === 1 ? animation.targetResolution : animation.sourceResolution + progress * (animation.targetResolution - animation.sourceResolution);\n\n if (animation.anchor) {\n var size = this.getViewportSize_(this.getRotation());\n var constrainedResolution = this.constraints_.resolution(resolution, 0, size, true);\n this.targetCenter_ = this.calculateCenterZoom(constrainedResolution, animation.anchor);\n }\n\n this.targetResolution_ = resolution;\n this.applyTargetState_(true);\n }\n\n if (animation.sourceRotation !== undefined && animation.targetRotation !== undefined) {\n var rotation = progress === 1 ? math_modulo(animation.targetRotation + Math.PI, 2 * Math.PI) - Math.PI : animation.sourceRotation + progress * (animation.targetRotation - animation.sourceRotation);\n\n if (animation.anchor) {\n var constrainedRotation = this.constraints_.rotation(rotation, true);\n this.targetCenter_ = this.calculateCenterRotate(constrainedRotation, animation.anchor);\n }\n\n this.targetRotation_ = rotation;\n }\n\n this.applyTargetState_(true);\n more = true;\n\n if (!animation.complete) {\n break;\n }\n }\n\n if (seriesComplete) {\n this.animations_[i] = null;\n this.setHint(ViewHint.ANIMATING, -1);\n var callback = series[0].callback;\n\n if (callback) {\n animationCallback(callback, true);\n }\n }\n } // prune completed series\n\n\n this.animations_ = this.animations_.filter(Boolean);\n\n if (more && this.updateAnimationKey_ === undefined) {\n this.updateAnimationKey_ = requestAnimationFrame(this.updateAnimations_.bind(this));\n }\n };\n /**\n * @param {number} rotation Target rotation.\n * @param {import("./coordinate.js").Coordinate} anchor Rotation anchor.\n * @return {import("./coordinate.js").Coordinate|undefined} Center for rotation and anchor.\n */\n\n\n View.prototype.calculateCenterRotate = function (rotation, anchor) {\n var center;\n var currentCenter = this.getCenterInternal();\n\n if (currentCenter !== undefined) {\n center = [currentCenter[0] - anchor[0], currentCenter[1] - anchor[1]];\n coordinate_rotate(center, rotation - this.getRotation());\n add(center, anchor);\n }\n\n return center;\n };\n /**\n * @param {number} resolution Target resolution.\n * @param {import("./coordinate.js").Coordinate} anchor Zoom anchor.\n * @return {import("./coordinate.js").Coordinate|undefined} Center for resolution and anchor.\n */\n\n\n View.prototype.calculateCenterZoom = function (resolution, anchor) {\n var center;\n var currentCenter = this.getCenterInternal();\n var currentResolution = this.getResolution();\n\n if (currentCenter !== undefined && currentResolution !== undefined) {\n var x = anchor[0] - resolution * (anchor[0] - currentCenter[0]) / currentResolution;\n var y = anchor[1] - resolution * (anchor[1] - currentCenter[1]) / currentResolution;\n center = [x, y];\n }\n\n return center;\n };\n /**\n * Returns the current viewport size.\n * @private\n * @param {number=} opt_rotation Take into account the rotation of the viewport when giving the size\n * @return {import("./size.js").Size} Viewport size or `[100, 100]` when no viewport is found.\n */\n\n\n View.prototype.getViewportSize_ = function (opt_rotation) {\n var size = this.viewportSize_;\n\n if (opt_rotation) {\n var w = size[0];\n var h = size[1];\n return [Math.abs(w * Math.cos(opt_rotation)) + Math.abs(h * Math.sin(opt_rotation)), Math.abs(w * Math.sin(opt_rotation)) + Math.abs(h * Math.cos(opt_rotation))];\n } else {\n return size;\n }\n };\n /**\n * Stores the viewport size on the view. The viewport size is not read every time from the DOM\n * to avoid performance hit and layout reflow.\n * This should be done on map size change.\n * Note: the constraints are not resolved during an animation to avoid stopping it\n * @param {import("./size.js").Size=} opt_size Viewport size; if undefined, [100, 100] is assumed\n */\n\n\n View.prototype.setViewportSize = function (opt_size) {\n this.viewportSize_ = Array.isArray(opt_size) ? opt_size.slice() : [100, 100];\n\n if (!this.getAnimating()) {\n this.resolveConstraints(0);\n }\n };\n /**\n * Get the view center.\n * @return {import("./coordinate.js").Coordinate|undefined} The center of the view.\n * @observable\n * @api\n */\n\n\n View.prototype.getCenter = function () {\n var center = this.getCenterInternal();\n\n if (!center) {\n return center;\n }\n\n return toUserCoordinate(center, this.getProjection());\n };\n /**\n * Get the view center without transforming to user projection.\n * @return {import("./coordinate.js").Coordinate|undefined} The center of the view.\n */\n\n\n View.prototype.getCenterInternal = function () {\n return (\n /** @type {import("./coordinate.js").Coordinate|undefined} */\n this.get(ViewProperty.CENTER)\n );\n };\n /**\n * @return {Constraints} Constraints.\n */\n\n\n View.prototype.getConstraints = function () {\n return this.constraints_;\n };\n /**\n * @return {boolean} Resolution constraint is set\n */\n\n\n View.prototype.getConstrainResolution = function () {\n return this.options_.constrainResolution;\n };\n /**\n * @param {Array<number>=} opt_hints Destination array.\n * @return {Array<number>} Hint.\n */\n\n\n View.prototype.getHints = function (opt_hints) {\n if (opt_hints !== undefined) {\n opt_hints[0] = this.hints_[0];\n opt_hints[1] = this.hints_[1];\n return opt_hints;\n } else {\n return this.hints_.slice();\n }\n };\n /**\n * Calculate the extent for the current view state and the passed size.\n * The size is the pixel dimensions of the box into which the calculated extent\n * should fit. In most cases you want to get the extent of the entire map,\n * that is `map.getSize()`.\n * @param {import("./size.js").Size=} opt_size Box pixel size. If not provided, the size\n * of the map that uses this view will be used.\n * @return {import("./extent.js").Extent} Extent.\n * @api\n */\n\n\n View.prototype.calculateExtent = function (opt_size) {\n var extent = this.calculateExtentInternal(opt_size);\n return toUserExtent(extent, this.getProjection());\n };\n /**\n * @param {import("./size.js").Size=} opt_size Box pixel size. If not provided,\n * the map\'s last known viewport size will be used.\n * @return {import("./extent.js").Extent} Extent.\n */\n\n\n View.prototype.calculateExtentInternal = function (opt_size) {\n var size = opt_size || this.getViewportSize_();\n var center =\n /** @type {!import("./coordinate.js").Coordinate} */\n this.getCenterInternal();\n asserts_assert(center, 1); // The view center is not defined\n\n var resolution =\n /** @type {!number} */\n this.getResolution();\n asserts_assert(resolution !== undefined, 2); // The view resolution is not defined\n\n var rotation =\n /** @type {!number} */\n this.getRotation();\n asserts_assert(rotation !== undefined, 3); // The view rotation is not defined\n\n return getForViewAndSize(center, resolution, rotation, size);\n };\n /**\n * Get the maximum resolution of the view.\n * @return {number} The maximum resolution of the view.\n * @api\n */\n\n\n View.prototype.getMaxResolution = function () {\n return this.maxResolution_;\n };\n /**\n * Get the minimum resolution of the view.\n * @return {number} The minimum resolution of the view.\n * @api\n */\n\n\n View.prototype.getMinResolution = function () {\n return this.minResolution_;\n };\n /**\n * Get the maximum zoom level for the view.\n * @return {number} The maximum zoom level.\n * @api\n */\n\n\n View.prototype.getMaxZoom = function () {\n return (\n /** @type {number} */\n this.getZoomForResolution(this.minResolution_)\n );\n };\n /**\n * Set a new maximum zoom level for the view.\n * @param {number} zoom The maximum zoom level.\n * @api\n */\n\n\n View.prototype.setMaxZoom = function (zoom) {\n this.applyOptions_(this.getUpdatedOptions_({\n maxZoom: zoom\n }));\n };\n /**\n * Get the minimum zoom level for the view.\n * @return {number} The minimum zoom level.\n * @api\n */\n\n\n View.prototype.getMinZoom = function () {\n return (\n /** @type {number} */\n this.getZoomForResolution(this.maxResolution_)\n );\n };\n /**\n * Set a new minimum zoom level for the view.\n * @param {number} zoom The minimum zoom level.\n * @api\n */\n\n\n View.prototype.setMinZoom = function (zoom) {\n this.applyOptions_(this.getUpdatedOptions_({\n minZoom: zoom\n }));\n };\n /**\n * Set whether the view shoud allow intermediary zoom levels.\n * @param {boolean} enabled Whether the resolution is constrained.\n * @api\n */\n\n\n View.prototype.setConstrainResolution = function (enabled) {\n this.applyOptions_(this.getUpdatedOptions_({\n constrainResolution: enabled\n }));\n };\n /**\n * Get the view projection.\n * @return {import("./proj/Projection.js").default} The projection of the view.\n * @api\n */\n\n\n View.prototype.getProjection = function () {\n return this.projection_;\n };\n /**\n * Get the view resolution.\n * @return {number|undefined} The resolution of the view.\n * @observable\n * @api\n */\n\n\n View.prototype.getResolution = function () {\n return (\n /** @type {number|undefined} */\n this.get(ViewProperty.RESOLUTION)\n );\n };\n /**\n * Get the resolutions for the view. This returns the array of resolutions\n * passed to the constructor of the View, or undefined if none were given.\n * @return {Array<number>|undefined} The resolutions of the view.\n * @api\n */\n\n\n View.prototype.getResolutions = function () {\n return this.resolutions_;\n };\n /**\n * Get the resolution for a provided extent (in map units) and size (in pixels).\n * @param {import("./extent.js").Extent} extent Extent.\n * @param {import("./size.js").Size=} opt_size Box pixel size.\n * @return {number} The resolution at which the provided extent will render at\n * the given size.\n * @api\n */\n\n\n View.prototype.getResolutionForExtent = function (extent, opt_size) {\n return this.getResolutionForExtentInternal(fromUserExtent(extent, this.getProjection()), opt_size);\n };\n /**\n * Get the resolution for a provided extent (in map units) and size (in pixels).\n * @param {import("./extent.js").Extent} extent Extent.\n * @param {import("./size.js").Size=} opt_size Box pixel size.\n * @return {number} The resolution at which the provided extent will render at\n * the given size.\n */\n\n\n View.prototype.getResolutionForExtentInternal = function (extent, opt_size) {\n var size = opt_size || this.getViewportSize_();\n var xResolution = extent_getWidth(extent) / size[0];\n var yResolution = getHeight(extent) / size[1];\n return Math.max(xResolution, yResolution);\n };\n /**\n * Return a function that returns a value between 0 and 1 for a\n * resolution. Exponential scaling is assumed.\n * @param {number=} opt_power Power.\n * @return {function(number): number} Resolution for value function.\n */\n\n\n View.prototype.getResolutionForValueFunction = function (opt_power) {\n var power = opt_power || 2;\n var maxResolution = this.getConstrainedResolution(this.maxResolution_);\n var minResolution = this.minResolution_;\n var max = Math.log(maxResolution / minResolution) / Math.log(power);\n return (\n /**\n * @param {number} value Value.\n * @return {number} Resolution.\n */\n function (value) {\n var resolution = maxResolution / Math.pow(power, value * max);\n return resolution;\n }\n );\n };\n /**\n * Get the view rotation.\n * @return {number} The rotation of the view in radians.\n * @observable\n * @api\n */\n\n\n View.prototype.getRotation = function () {\n return (\n /** @type {number} */\n this.get(ViewProperty.ROTATION)\n );\n };\n /**\n * Return a function that returns a resolution for a value between\n * 0 and 1. Exponential scaling is assumed.\n * @param {number=} opt_power Power.\n * @return {function(number): number} Value for resolution function.\n */\n\n\n View.prototype.getValueForResolutionFunction = function (opt_power) {\n var logPower = Math.log(opt_power || 2);\n var maxResolution = this.getConstrainedResolution(this.maxResolution_);\n var minResolution = this.minResolution_;\n var max = Math.log(maxResolution / minResolution) / logPower;\n return (\n /**\n * @param {number} resolution Resolution.\n * @return {number} Value.\n */\n function (resolution) {\n var value = Math.log(maxResolution / resolution) / logPower / max;\n return value;\n }\n );\n };\n /**\n * Returns the size of the viewport minus padding.\n * @private\n * @param {number=} opt_rotation Take into account the rotation of the viewport when giving the size\n * @return {import("./size.js").Size} Viewport size reduced by the padding.\n */\n\n\n View.prototype.getViewportSizeMinusPadding_ = function (opt_rotation) {\n var size = this.getViewportSize_(opt_rotation);\n var padding = this.padding;\n\n if (padding) {\n size = [size[0] - padding[1] - padding[3], size[1] - padding[0] - padding[2]];\n }\n\n return size;\n };\n /**\n * @return {State} View state.\n */\n\n\n View.prototype.getState = function () {\n var projection = this.getProjection();\n var resolution =\n /** @type {number} */\n this.getResolution();\n var rotation = this.getRotation();\n var center =\n /** @type {import("./coordinate.js").Coordinate} */\n this.getCenterInternal();\n var padding = this.padding;\n\n if (padding) {\n var reducedSize = this.getViewportSizeMinusPadding_();\n center = calculateCenterOn(center, this.getViewportSize_(), [reducedSize[0] / 2 + padding[3], reducedSize[1] / 2 + padding[0]], resolution, rotation);\n }\n\n return {\n center: center.slice(0),\n projection: projection !== undefined ? projection : null,\n resolution: resolution,\n rotation: rotation,\n zoom: this.getZoom()\n };\n };\n /**\n * Get the current zoom level. This method may return non-integer zoom levels\n * if the view does not constrain the resolution, or if an interaction or\n * animation is underway.\n * @return {number|undefined} Zoom.\n * @api\n */\n\n\n View.prototype.getZoom = function () {\n var zoom;\n var resolution = this.getResolution();\n\n if (resolution !== undefined) {\n zoom = this.getZoomForResolution(resolution);\n }\n\n return zoom;\n };\n /**\n * Get the zoom level for a resolution.\n * @param {number} resolution The resolution.\n * @return {number|undefined} The zoom level for the provided resolution.\n * @api\n */\n\n\n View.prototype.getZoomForResolution = function (resolution) {\n var offset = this.minZoom_ || 0;\n var max, zoomFactor;\n\n if (this.resolutions_) {\n var nearest = linearFindNearest(this.resolutions_, resolution, 1);\n offset = nearest;\n max = this.resolutions_[nearest];\n\n if (nearest == this.resolutions_.length - 1) {\n zoomFactor = 2;\n } else {\n zoomFactor = max / this.resolutions_[nearest + 1];\n }\n } else {\n max = this.maxResolution_;\n zoomFactor = this.zoomFactor_;\n }\n\n return offset + Math.log(max / resolution) / Math.log(zoomFactor);\n };\n /**\n * Get the resolution for a zoom level.\n * @param {number} zoom Zoom level.\n * @return {number} The view resolution for the provided zoom level.\n * @api\n */\n\n\n View.prototype.getResolutionForZoom = function (zoom) {\n if (this.resolutions_) {\n if (this.resolutions_.length <= 1) {\n return 0;\n }\n\n var baseLevel = math_clamp(Math.floor(zoom), 0, this.resolutions_.length - 2);\n var zoomFactor = this.resolutions_[baseLevel] / this.resolutions_[baseLevel + 1];\n return this.resolutions_[baseLevel] / Math.pow(zoomFactor, math_clamp(zoom - baseLevel, 0, 1));\n } else {\n return this.maxResolution_ / Math.pow(this.zoomFactor_, zoom - this.minZoom_);\n }\n };\n /**\n * Fit the given geometry or extent based on the given map size and border.\n * The size is pixel dimensions of the box to fit the extent into.\n * In most cases you will want to use the map size, that is `map.getSize()`.\n * Takes care of the map angle.\n * @param {import("./geom/SimpleGeometry.js").default|import("./extent.js").Extent} geometryOrExtent The geometry or\n * extent to fit the view to.\n * @param {FitOptions=} opt_options Options.\n * @api\n */\n\n\n View.prototype.fit = function (geometryOrExtent, opt_options) {\n /** @type {import("./geom/SimpleGeometry.js").default} */\n var geometry;\n asserts_assert(Array.isArray(geometryOrExtent) || typeof\n /** @type {?} */\n geometryOrExtent.getSimplifiedGeometry === \'function\', 24); // Invalid extent or geometry provided as `geometry`\n\n if (Array.isArray(geometryOrExtent)) {\n asserts_assert(!extent_isEmpty(geometryOrExtent), 25); // Cannot fit empty extent provided as `geometry`\n\n var extent = fromUserExtent(geometryOrExtent, this.getProjection());\n geometry = fromExtent(extent);\n } else if (geometryOrExtent.getType() === geom_GeometryType.CIRCLE) {\n var extent = fromUserExtent(geometryOrExtent.getExtent(), this.getProjection());\n geometry = fromExtent(extent);\n geometry.rotate(this.getRotation(), getCenter(extent));\n } else {\n var userProjection = getUserProjection();\n\n if (userProjection) {\n geometry =\n /** @type {import("./geom/SimpleGeometry.js").default} */\n geometryOrExtent.clone().transform(userProjection, this.getProjection());\n } else {\n geometry = geometryOrExtent;\n }\n }\n\n this.fitInternal(geometry, opt_options);\n };\n /**\n * @param {import("./geom/SimpleGeometry.js").default} geometry The geometry.\n * @param {FitOptions=} opt_options Options.\n */\n\n\n View.prototype.fitInternal = function (geometry, opt_options) {\n var options = opt_options || {};\n var size = options.size;\n\n if (!size) {\n size = this.getViewportSizeMinusPadding_();\n }\n\n var padding = options.padding !== undefined ? options.padding : [0, 0, 0, 0];\n var nearest = options.nearest !== undefined ? options.nearest : false;\n var minResolution;\n\n if (options.minResolution !== undefined) {\n minResolution = options.minResolution;\n } else if (options.maxZoom !== undefined) {\n minResolution = this.getResolutionForZoom(options.maxZoom);\n } else {\n minResolution = 0;\n }\n\n var coords = geometry.getFlatCoordinates(); // calculate rotated extent\n\n var rotation = this.getRotation();\n var cosAngle = Math.cos(-rotation);\n var sinAngle = Math.sin(-rotation);\n var minRotX = +Infinity;\n var minRotY = +Infinity;\n var maxRotX = -Infinity;\n var maxRotY = -Infinity;\n var stride = geometry.getStride();\n\n for (var i = 0, ii = coords.length; i < ii; i += stride) {\n var rotX = coords[i] * cosAngle - coords[i + 1] * sinAngle;\n var rotY = coords[i] * sinAngle + coords[i + 1] * cosAngle;\n minRotX = Math.min(minRotX, rotX);\n minRotY = Math.min(minRotY, rotY);\n maxRotX = Math.max(maxRotX, rotX);\n maxRotY = Math.max(maxRotY, rotY);\n } // calculate resolution\n\n\n var resolution = this.getResolutionForExtentInternal([minRotX, minRotY, maxRotX, maxRotY], [size[0] - padding[1] - padding[3], size[1] - padding[0] - padding[2]]);\n resolution = isNaN(resolution) ? minResolution : Math.max(resolution, minResolution);\n resolution = this.getConstrainedResolution(resolution, nearest ? 0 : 1); // calculate center\n\n sinAngle = -sinAngle; // go back to original rotation\n\n var centerRotX = (minRotX + maxRotX) / 2;\n var centerRotY = (minRotY + maxRotY) / 2;\n centerRotX += (padding[1] - padding[3]) / 2 * resolution;\n centerRotY += (padding[0] - padding[2]) / 2 * resolution;\n var centerX = centerRotX * cosAngle - centerRotY * sinAngle;\n var centerY = centerRotY * cosAngle + centerRotX * sinAngle;\n var center = this.getConstrainedCenter([centerX, centerY], resolution);\n var callback = options.callback ? options.callback : VOID;\n\n if (options.duration !== undefined) {\n this.animateInternal({\n resolution: resolution,\n center: center,\n duration: options.duration,\n easing: options.easing\n }, callback);\n } else {\n this.targetResolution_ = resolution;\n this.targetCenter_ = center;\n this.applyTargetState_(false, true);\n animationCallback(callback, true);\n }\n };\n /**\n * Center on coordinate and view position.\n * @param {import("./coordinate.js").Coordinate} coordinate Coordinate.\n * @param {import("./size.js").Size} size Box pixel size.\n * @param {import("./pixel.js").Pixel} position Position on the view to center on.\n * @api\n */\n\n\n View.prototype.centerOn = function (coordinate, size, position) {\n this.centerOnInternal(fromUserCoordinate(coordinate, this.getProjection()), size, position);\n };\n /**\n * @param {import("./coordinate.js").Coordinate} coordinate Coordinate.\n * @param {import("./size.js").Size} size Box pixel size.\n * @param {import("./pixel.js").Pixel} position Position on the view to center on.\n */\n\n\n View.prototype.centerOnInternal = function (coordinate, size, position) {\n this.setCenterInternal(calculateCenterOn(coordinate, size, position, this.getResolution(), this.getRotation()));\n };\n /**\n * Calculates the shift between map and viewport center.\n * @param {import("./coordinate.js").Coordinate} center Center.\n * @param {number} resolution Resolution.\n * @param {number} rotation Rotation.\n * @param {import("./size.js").Size} size Size.\n * @return {Array<number>|undefined} Center shift.\n */\n\n\n View.prototype.calculateCenterShift = function (center, resolution, rotation, size) {\n var centerShift;\n var padding = this.padding;\n\n if (padding && center) {\n var reducedSize = this.getViewportSizeMinusPadding_(-rotation);\n var shiftedCenter = calculateCenterOn(center, size, [reducedSize[0] / 2 + padding[3], reducedSize[1] / 2 + padding[0]], resolution, rotation);\n centerShift = [center[0] - shiftedCenter[0], center[1] - shiftedCenter[1]];\n }\n\n return centerShift;\n };\n /**\n * @return {boolean} Is defined.\n */\n\n\n View.prototype.isDef = function () {\n return !!this.getCenterInternal() && this.getResolution() !== undefined;\n };\n /**\n * Adds relative coordinates to the center of the view. Any extent constraint will apply.\n * @param {import("./coordinate.js").Coordinate} deltaCoordinates Relative value to add.\n * @api\n */\n\n\n View.prototype.adjustCenter = function (deltaCoordinates) {\n var center = toUserCoordinate(this.targetCenter_, this.getProjection());\n this.setCenter([center[0] + deltaCoordinates[0], center[1] + deltaCoordinates[1]]);\n };\n /**\n * Adds relative coordinates to the center of the view. Any extent constraint will apply.\n * @param {import("./coordinate.js").Coordinate} deltaCoordinates Relative value to add.\n */\n\n\n View.prototype.adjustCenterInternal = function (deltaCoordinates) {\n var center = this.targetCenter_;\n this.setCenterInternal([center[0] + deltaCoordinates[0], center[1] + deltaCoordinates[1]]);\n };\n /**\n * Multiply the view resolution by a ratio, optionally using an anchor. Any resolution\n * constraint will apply.\n * @param {number} ratio The ratio to apply on the view resolution.\n * @param {import("./coordinate.js").Coordinate=} opt_anchor The origin of the transformation.\n * @api\n */\n\n\n View.prototype.adjustResolution = function (ratio, opt_anchor) {\n var anchor = opt_anchor && fromUserCoordinate(opt_anchor, this.getProjection());\n this.adjustResolutionInternal(ratio, anchor);\n };\n /**\n * Multiply the view resolution by a ratio, optionally using an anchor. Any resolution\n * constraint will apply.\n * @param {number} ratio The ratio to apply on the view resolution.\n * @param {import("./coordinate.js").Coordinate=} opt_anchor The origin of the transformation.\n */\n\n\n View.prototype.adjustResolutionInternal = function (ratio, opt_anchor) {\n var isMoving = this.getAnimating() || this.getInteracting();\n var size = this.getViewportSize_(this.getRotation());\n var newResolution = this.constraints_.resolution(this.targetResolution_ * ratio, 0, size, isMoving);\n\n if (opt_anchor) {\n this.targetCenter_ = this.calculateCenterZoom(newResolution, opt_anchor);\n }\n\n this.targetResolution_ *= ratio;\n this.applyTargetState_();\n };\n /**\n * Adds a value to the view zoom level, optionally using an anchor. Any resolution\n * constraint will apply.\n * @param {number} delta Relative value to add to the zoom level.\n * @param {import("./coordinate.js").Coordinate=} opt_anchor The origin of the transformation.\n * @api\n */\n\n\n View.prototype.adjustZoom = function (delta, opt_anchor) {\n this.adjustResolution(Math.pow(this.zoomFactor_, -delta), opt_anchor);\n };\n /**\n * Adds a value to the view rotation, optionally using an anchor. Any rotation\n * constraint will apply.\n * @param {number} delta Relative value to add to the zoom rotation, in radians.\n * @param {import("./coordinate.js").Coordinate=} opt_anchor The rotation center.\n * @api\n */\n\n\n View.prototype.adjustRotation = function (delta, opt_anchor) {\n if (opt_anchor) {\n opt_anchor = fromUserCoordinate(opt_anchor, this.getProjection());\n }\n\n this.adjustRotationInternal(delta, opt_anchor);\n };\n /**\n * @param {number} delta Relative value to add to the zoom rotation, in radians.\n * @param {import("./coordinate.js").Coordinate=} opt_anchor The rotation center.\n */\n\n\n View.prototype.adjustRotationInternal = function (delta, opt_anchor) {\n var isMoving = this.getAnimating() || this.getInteracting();\n var newRotation = this.constraints_.rotation(this.targetRotation_ + delta, isMoving);\n\n if (opt_anchor) {\n this.targetCenter_ = this.calculateCenterRotate(newRotation, opt_anchor);\n }\n\n this.targetRotation_ += delta;\n this.applyTargetState_();\n };\n /**\n * Set the center of the current view. Any extent constraint will apply.\n * @param {import("./coordinate.js").Coordinate|undefined} center The center of the view.\n * @observable\n * @api\n */\n\n\n View.prototype.setCenter = function (center) {\n this.setCenterInternal(fromUserCoordinate(center, this.getProjection()));\n };\n /**\n * Set the center using the view projection (not the user projection).\n * @param {import("./coordinate.js").Coordinate|undefined} center The center of the view.\n */\n\n\n View.prototype.setCenterInternal = function (center) {\n this.targetCenter_ = center;\n this.applyTargetState_();\n };\n /**\n * @param {import("./ViewHint.js").default} hint Hint.\n * @param {number} delta Delta.\n * @return {number} New value.\n */\n\n\n View.prototype.setHint = function (hint, delta) {\n this.hints_[hint] += delta;\n this.changed();\n return this.hints_[hint];\n };\n /**\n * Set the resolution for this view. Any resolution constraint will apply.\n * @param {number|undefined} resolution The resolution of the view.\n * @observable\n * @api\n */\n\n\n View.prototype.setResolution = function (resolution) {\n this.targetResolution_ = resolution;\n this.applyTargetState_();\n };\n /**\n * Set the rotation for this view. Any rotation constraint will apply.\n * @param {number} rotation The rotation of the view in radians.\n * @observable\n * @api\n */\n\n\n View.prototype.setRotation = function (rotation) {\n this.targetRotation_ = rotation;\n this.applyTargetState_();\n };\n /**\n * Zoom to a specific zoom level. Any resolution constrain will apply.\n * @param {number} zoom Zoom level.\n * @api\n */\n\n\n View.prototype.setZoom = function (zoom) {\n this.setResolution(this.getResolutionForZoom(zoom));\n };\n /**\n * Recompute rotation/resolution/center based on target values.\n * Note: we have to compute rotation first, then resolution and center considering that\n * parameters can influence one another in case a view extent constraint is present.\n * @param {boolean=} opt_doNotCancelAnims Do not cancel animations.\n * @param {boolean=} opt_forceMoving Apply constraints as if the view is moving.\n * @private\n */\n\n\n View.prototype.applyTargetState_ = function (opt_doNotCancelAnims, opt_forceMoving) {\n var isMoving = this.getAnimating() || this.getInteracting() || opt_forceMoving; // compute rotation\n\n var newRotation = this.constraints_.rotation(this.targetRotation_, isMoving);\n var size = this.getViewportSize_(newRotation);\n var newResolution = this.constraints_.resolution(this.targetResolution_, 0, size, isMoving);\n var newCenter = this.constraints_.center(this.targetCenter_, newResolution, size, isMoving, this.calculateCenterShift(this.targetCenter_, newResolution, newRotation, size));\n\n if (this.get(ViewProperty.ROTATION) !== newRotation) {\n this.set(ViewProperty.ROTATION, newRotation);\n }\n\n if (this.get(ViewProperty.RESOLUTION) !== newResolution) {\n this.set(ViewProperty.RESOLUTION, newResolution);\n }\n\n if (!this.get(ViewProperty.CENTER) || !coordinate_equals(this.get(ViewProperty.CENTER), newCenter)) {\n this.set(ViewProperty.CENTER, newCenter);\n }\n\n if (this.getAnimating() && !opt_doNotCancelAnims) {\n this.cancelAnimations();\n }\n\n this.cancelAnchor_ = undefined;\n };\n /**\n * If any constraints need to be applied, an animation will be triggered.\n * This is typically done on interaction end.\n * Note: calling this with a duration of 0 will apply the constrained values straight away,\n * without animation.\n * @param {number=} opt_duration The animation duration in ms.\n * @param {number=} opt_resolutionDirection Which direction to zoom.\n * @param {import("./coordinate.js").Coordinate=} opt_anchor The origin of the transformation.\n */\n\n\n View.prototype.resolveConstraints = function (opt_duration, opt_resolutionDirection, opt_anchor) {\n var duration = opt_duration !== undefined ? opt_duration : 200;\n var direction = opt_resolutionDirection || 0;\n var newRotation = this.constraints_.rotation(this.targetRotation_);\n var size = this.getViewportSize_(newRotation);\n var newResolution = this.constraints_.resolution(this.targetResolution_, direction, size);\n var newCenter = this.constraints_.center(this.targetCenter_, newResolution, size, false, this.calculateCenterShift(this.targetCenter_, newResolution, newRotation, size));\n\n if (duration === 0 && !this.cancelAnchor_) {\n this.targetResolution_ = newResolution;\n this.targetRotation_ = newRotation;\n this.targetCenter_ = newCenter;\n this.applyTargetState_();\n return;\n }\n\n var anchor = opt_anchor || (duration === 0 ? this.cancelAnchor_ : undefined);\n this.cancelAnchor_ = undefined;\n\n if (this.getResolution() !== newResolution || this.getRotation() !== newRotation || !this.getCenterInternal() || !coordinate_equals(this.getCenterInternal(), newCenter)) {\n if (this.getAnimating()) {\n this.cancelAnimations();\n }\n\n this.animateInternal({\n rotation: newRotation,\n center: newCenter,\n resolution: newResolution,\n duration: duration,\n easing: easeOut,\n anchor: anchor\n });\n }\n };\n /**\n * Notify the View that an interaction has started.\n * The view state will be resolved to a stable one if needed\n * (depending on its constraints).\n * @api\n */\n\n\n View.prototype.beginInteraction = function () {\n this.resolveConstraints(0);\n this.setHint(ViewHint.INTERACTING, 1);\n };\n /**\n * Notify the View that an interaction has ended. The view state will be resolved\n * to a stable one if needed (depending on its constraints).\n * @param {number=} opt_duration Animation duration in ms.\n * @param {number=} opt_resolutionDirection Which direction to zoom.\n * @param {import("./coordinate.js").Coordinate=} opt_anchor The origin of the transformation.\n * @api\n */\n\n\n View.prototype.endInteraction = function (opt_duration, opt_resolutionDirection, opt_anchor) {\n var anchor = opt_anchor && fromUserCoordinate(opt_anchor, this.getProjection());\n this.endInteractionInternal(opt_duration, opt_resolutionDirection, anchor);\n };\n /**\n * Notify the View that an interaction has ended. The view state will be resolved\n * to a stable one if needed (depending on its constraints).\n * @param {number=} opt_duration Animation duration in ms.\n * @param {number=} opt_resolutionDirection Which direction to zoom.\n * @param {import("./coordinate.js").Coordinate=} opt_anchor The origin of the transformation.\n */\n\n\n View.prototype.endInteractionInternal = function (opt_duration, opt_resolutionDirection, opt_anchor) {\n this.setHint(ViewHint.INTERACTING, -1);\n this.resolveConstraints(opt_duration, opt_resolutionDirection, opt_anchor);\n };\n /**\n * Get a valid position for the view center according to the current constraints.\n * @param {import("./coordinate.js").Coordinate|undefined} targetCenter Target center position.\n * @param {number=} opt_targetResolution Target resolution. If not supplied, the current one will be used.\n * This is useful to guess a valid center position at a different zoom level.\n * @return {import("./coordinate.js").Coordinate|undefined} Valid center position.\n */\n\n\n View.prototype.getConstrainedCenter = function (targetCenter, opt_targetResolution) {\n var size = this.getViewportSize_(this.getRotation());\n return this.constraints_.center(targetCenter, opt_targetResolution || this.getResolution(), size);\n };\n /**\n * Get a valid zoom level according to the current view constraints.\n * @param {number|undefined} targetZoom Target zoom.\n * @param {number=} [opt_direction=0] Indicate which resolution should be used\n * by a renderer if the view resolution does not match any resolution of the tile source.\n * If 0, the nearest resolution will be used. If 1, the nearest lower resolution\n * will be used. If -1, the nearest higher resolution will be used.\n * @return {number|undefined} Valid zoom level.\n */\n\n\n View.prototype.getConstrainedZoom = function (targetZoom, opt_direction) {\n var targetRes = this.getResolutionForZoom(targetZoom);\n return this.getZoomForResolution(this.getConstrainedResolution(targetRes, opt_direction));\n };\n /**\n * Get a valid resolution according to the current view constraints.\n * @param {number|undefined} targetResolution Target resolution.\n * @param {number=} [opt_direction=0] Indicate which resolution should be used\n * by a renderer if the view resolution does not match any resolution of the tile source.\n * If 0, the nearest resolution will be used. If 1, the nearest lower resolution\n * will be used. If -1, the nearest higher resolution will be used.\n * @return {number|undefined} Valid resolution.\n */\n\n\n View.prototype.getConstrainedResolution = function (targetResolution, opt_direction) {\n var direction = opt_direction || 0;\n var size = this.getViewportSize_(this.getRotation());\n return this.constraints_.resolution(targetResolution, direction, size);\n };\n\n return View;\n}(ol_Object);\n/**\n * @param {Function} callback Callback.\n * @param {*} returnValue Return value.\n */\n\n\nfunction animationCallback(callback, returnValue) {\n setTimeout(function () {\n callback(returnValue);\n }, 0);\n}\n/**\n * @param {ViewOptions} options View options.\n * @return {import("./centerconstraint.js").Type} The constraint.\n */\n\n\nfunction createCenterConstraint(options) {\n if (options.extent !== undefined) {\n var smooth = options.smoothExtentConstraint !== undefined ? options.smoothExtentConstraint : true;\n return createExtent(options.extent, options.constrainOnlyCenter, smooth);\n }\n\n var projection = createProjection(options.projection, \'EPSG:3857\');\n\n if (options.multiWorld !== true && projection.isGlobal()) {\n var extent = projection.getExtent().slice();\n extent[0] = -Infinity;\n extent[2] = Infinity;\n return createExtent(extent, false, false);\n }\n\n return none;\n}\n/**\n * @param {ViewOptions} options View options.\n * @return {{constraint: import("./resolutionconstraint.js").Type, maxResolution: number,\n * minResolution: number, minZoom: number, zoomFactor: number}} The constraint.\n */\n\nfunction createResolutionConstraint(options) {\n var resolutionConstraint;\n var maxResolution;\n var minResolution; // TODO: move these to be ol constants\n // see https://github.com/openlayers/openlayers/issues/2076\n\n var defaultMaxZoom = 28;\n var defaultZoomFactor = 2;\n var minZoom = options.minZoom !== undefined ? options.minZoom : DEFAULT_MIN_ZOOM;\n var maxZoom = options.maxZoom !== undefined ? options.maxZoom : defaultMaxZoom;\n var zoomFactor = options.zoomFactor !== undefined ? options.zoomFactor : defaultZoomFactor;\n var multiWorld = options.multiWorld !== undefined ? options.multiWorld : false;\n var smooth = options.smoothResolutionConstraint !== undefined ? options.smoothResolutionConstraint : true;\n var showFullExtent = options.showFullExtent !== undefined ? options.showFullExtent : false;\n var projection = createProjection(options.projection, \'EPSG:3857\');\n var projExtent = projection.getExtent();\n var constrainOnlyCenter = options.constrainOnlyCenter;\n var extent = options.extent;\n\n if (!multiWorld && !extent && projection.isGlobal()) {\n constrainOnlyCenter = false;\n extent = projExtent;\n }\n\n if (options.resolutions !== undefined) {\n var resolutions = options.resolutions;\n maxResolution = resolutions[minZoom];\n minResolution = resolutions[maxZoom] !== undefined ? resolutions[maxZoom] : resolutions[resolutions.length - 1];\n\n if (options.constrainResolution) {\n resolutionConstraint = createSnapToResolutions(resolutions, smooth, !constrainOnlyCenter && extent, showFullExtent);\n } else {\n resolutionConstraint = createMinMaxResolution(maxResolution, minResolution, smooth, !constrainOnlyCenter && extent, showFullExtent);\n }\n } else {\n // calculate the default min and max resolution\n var size = !projExtent ? // use an extent that can fit the whole world if need be\n 360 * METERS_PER_UNIT[proj_Units.DEGREES] / projection.getMetersPerUnit() : Math.max(extent_getWidth(projExtent), getHeight(projExtent));\n var defaultMaxResolution = size / DEFAULT_TILE_SIZE / Math.pow(defaultZoomFactor, DEFAULT_MIN_ZOOM);\n var defaultMinResolution = defaultMaxResolution / Math.pow(defaultZoomFactor, defaultMaxZoom - DEFAULT_MIN_ZOOM); // user provided maxResolution takes precedence\n\n maxResolution = options.maxResolution;\n\n if (maxResolution !== undefined) {\n minZoom = 0;\n } else {\n maxResolution = defaultMaxResolution / Math.pow(zoomFactor, minZoom);\n } // user provided minResolution takes precedence\n\n\n minResolution = options.minResolution;\n\n if (minResolution === undefined) {\n if (options.maxZoom !== undefined) {\n if (options.maxResolution !== undefined) {\n minResolution = maxResolution / Math.pow(zoomFactor, maxZoom);\n } else {\n minResolution = defaultMaxResolution / Math.pow(zoomFactor, maxZoom);\n }\n } else {\n minResolution = defaultMinResolution;\n }\n } // given discrete zoom levels, minResolution may be different than provided\n\n\n maxZoom = minZoom + Math.floor(Math.log(maxResolution / minResolution) / Math.log(zoomFactor));\n minResolution = maxResolution / Math.pow(zoomFactor, maxZoom - minZoom);\n\n if (options.constrainResolution) {\n resolutionConstraint = createSnapToPower(zoomFactor, maxResolution, minResolution, smooth, !constrainOnlyCenter && extent, showFullExtent);\n } else {\n resolutionConstraint = createMinMaxResolution(maxResolution, minResolution, smooth, !constrainOnlyCenter && extent, showFullExtent);\n }\n }\n\n return {\n constraint: resolutionConstraint,\n maxResolution: maxResolution,\n minResolution: minResolution,\n minZoom: minZoom,\n zoomFactor: zoomFactor\n };\n}\n/**\n * @param {ViewOptions} options View options.\n * @return {import("./rotationconstraint.js").Type} Rotation constraint.\n */\n\nfunction createRotationConstraint(options) {\n var enableRotation = options.enableRotation !== undefined ? options.enableRotation : true;\n\n if (enableRotation) {\n var constrainRotation = options.constrainRotation;\n\n if (constrainRotation === undefined || constrainRotation === true) {\n return createSnapToZero();\n } else if (constrainRotation === false) {\n return rotationconstraint_none;\n } else if (typeof constrainRotation === \'number\') {\n return createSnapToN(constrainRotation);\n } else {\n return rotationconstraint_none;\n }\n } else {\n return disable;\n }\n}\n/**\n * Determine if an animation involves no view change.\n * @param {Animation} animation The animation.\n * @return {boolean} The animation involves no view change.\n */\n\nfunction isNoopAnimation(animation) {\n if (animation.sourceCenter && animation.targetCenter) {\n if (!coordinate_equals(animation.sourceCenter, animation.targetCenter)) {\n return false;\n }\n }\n\n if (animation.sourceResolution !== animation.targetResolution) {\n return false;\n }\n\n if (animation.sourceRotation !== animation.targetRotation) {\n return false;\n }\n\n return true;\n}\n/**\n * @param {import("./coordinate.js").Coordinate} coordinate Coordinate.\n * @param {import("./size.js").Size} size Box pixel size.\n * @param {import("./pixel.js").Pixel} position Position on the view to center on.\n * @param {number} resolution Resolution.\n * @param {number} rotation Rotation.\n * @return {import("./coordinate.js").Coordinate} Shifted center.\n */\n\nfunction calculateCenterOn(coordinate, size, position, resolution, rotation) {\n // calculate rotated position\n var cosAngle = Math.cos(-rotation);\n var sinAngle = Math.sin(-rotation);\n var rotX = coordinate[0] * cosAngle - coordinate[1] * sinAngle;\n var rotY = coordinate[1] * cosAngle + coordinate[0] * sinAngle;\n rotX += (size[0] / 2 - position[0]) * resolution;\n rotY += (position[1] - size[1] / 2) * resolution; // go back to original angle\n\n sinAngle = -sinAngle; // go back to original rotation\n\n var centerX = rotX * cosAngle - rotY * sinAngle;\n var centerY = rotY * cosAngle + rotX * sinAngle;\n return [centerX, centerY];\n}\n\n/* harmony default export */ var ol_View = (View);\n;// CONCATENATED MODULE: ./node_modules/ol/size.js\n/**\n * @module ol/size\n */\n\n/**\n * An array of numbers representing a size: `[width, height]`.\n * @typedef {Array<number>} Size\n * @api\n */\n\n/**\n * Returns a buffered size.\n * @param {Size} size Size.\n * @param {number} num The amount by which to buffer.\n * @param {Size=} opt_size Optional reusable size array.\n * @return {Size} The buffered size.\n */\nfunction size_buffer(size, num, opt_size) {\n if (opt_size === undefined) {\n opt_size = [0, 0];\n }\n\n opt_size[0] = size[0] + 2 * num;\n opt_size[1] = size[1] + 2 * num;\n return opt_size;\n}\n/**\n * Determines if a size has a positive area.\n * @param {Size} size The size to test.\n * @return {boolean} The size has a positive area.\n */\n\nfunction hasArea(size) {\n return size[0] > 0 && size[1] > 0;\n}\n/**\n * Returns a size scaled by a ratio. The result will be an array of integers.\n * @param {Size} size Size.\n * @param {number} ratio Ratio.\n * @param {Size=} opt_size Optional reusable size array.\n * @return {Size} The scaled size.\n */\n\nfunction size_scale(size, ratio, opt_size) {\n if (opt_size === undefined) {\n opt_size = [0, 0];\n }\n\n opt_size[0] = size[0] * ratio + 0.5 | 0;\n opt_size[1] = size[1] * ratio + 0.5 | 0;\n return opt_size;\n}\n/**\n * Returns an `Size` array for the passed in number (meaning: square) or\n * `Size` array.\n * (meaning: non-square),\n * @param {number|Size} size Width and height.\n * @param {Size=} opt_size Optional reusable size array.\n * @return {Size} Size.\n * @api\n */\n\nfunction toSize(size, opt_size) {\n if (Array.isArray(size)) {\n return size;\n } else {\n if (opt_size === undefined) {\n opt_size = [size, size];\n } else {\n opt_size[0] = size;\n opt_size[1] = size;\n }\n\n return opt_size;\n }\n}\n;// CONCATENATED MODULE: ./node_modules/ol/PluggableMap.js\nvar PluggableMap_extends = undefined && undefined.__extends || function () {\n var _extendStatics = function extendStatics(d, b) {\n _extendStatics = Object.setPrototypeOf || {\n __proto__: []\n } instanceof Array && function (d, b) {\n d.__proto__ = b;\n } || function (d, b) {\n for (var p in b) {\n if (Object.prototype.hasOwnProperty.call(b, p)) d[p] = b[p];\n }\n };\n\n return _extendStatics(d, b);\n };\n\n return function (d, b) {\n _extendStatics(d, b);\n\n function __() {\n this.constructor = d;\n }\n\n d.prototype = b === null ? Object.create(b) : (__.prototype = b.prototype, new __());\n };\n}();\n/**\n * @module ol/PluggableMap\n */\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n/**\n * State of the current frame. Only `pixelRatio`, `time` and `viewState` should\n * be used in applications.\n * @typedef {Object} FrameState\n * @property {number} pixelRatio The pixel ratio of the frame.\n * @property {number} time The time when rendering of the frame was requested.\n * @property {import("./View.js").State} viewState The state of the current view.\n * @property {boolean} animate\n * @property {import("./transform.js").Transform} coordinateToPixelTransform\n * @property {import("rbush").default} declutterTree\n * @property {null|import("./extent.js").Extent} extent\n * @property {number} index\n * @property {Array<import("./layer/Layer.js").State>} layerStatesArray\n * @property {number} layerIndex\n * @property {import("./transform.js").Transform} pixelToCoordinateTransform\n * @property {Array<PostRenderFunction>} postRenderFunctions\n * @property {import("./size.js").Size} size\n * @property {TileQueue} tileQueue\n * @property {!Object<string, Object<string, boolean>>} usedTiles\n * @property {Array<number>} viewHints\n * @property {!Object<string, Object<string, boolean>>} wantedTiles\n */\n\n/**\n * @typedef {function(PluggableMap, ?FrameState): any} PostRenderFunction\n */\n\n/**\n * @typedef {Object} AtPixelOptions\n * @property {undefined|function(import("./layer/Layer.js").default): boolean} [layerFilter] Layer filter\n * function. The filter function will receive one argument, the\n * {@link module:ol/layer/Layer layer-candidate} and it should return a boolean value.\n * Only layers which are visible and for which this function returns `true`\n * will be tested for features. By default, all visible layers will be tested.\n * @property {number} [hitTolerance=0] Hit-detection tolerance in css pixels. Pixels\n * inside the radius around the given position will be checked for features.\n * @property {boolean} [checkWrapped=true] Check-Wrapped Will check for for wrapped geometries inside the range of\n * +/- 1 world width. Works only if a projection is used that can be wrapped.\n */\n\n/**\n * @typedef {Object} MapOptionsInternal\n * @property {Collection<import("./control/Control.js").default>} [controls]\n * @property {Collection<import("./interaction/Interaction.js").default>} [interactions]\n * @property {HTMLElement|Document} keyboardEventTarget\n * @property {Collection<import("./Overlay.js").default>} overlays\n * @property {Object<string, *>} values\n */\n\n/**\n * Object literal with config options for the map.\n * @typedef {Object} MapOptions\n * @property {Collection<import("./control/Control.js").default>|Array<import("./control/Control.js").default>} [controls]\n * Controls initially added to the map. If not specified,\n * {@link module:ol/control~defaults} is used.\n * @property {number} [pixelRatio=window.devicePixelRatio] The ratio between\n * physical pixels and device-independent pixels (dips) on the device.\n * @property {Collection<import("./interaction/Interaction.js").default>|Array<import("./interaction/Interaction.js").default>} [interactions]\n * Interactions that are initially added to the map. If not specified,\n * {@link module:ol/interaction~defaults} is used.\n * @property {HTMLElement|Document|string} [keyboardEventTarget] The element to\n * listen to keyboard events on. This determines when the `KeyboardPan` and\n * `KeyboardZoom` interactions trigger. For example, if this option is set to\n * `document` the keyboard interactions will always trigger. If this option is\n * not specified, the element the library listens to keyboard events on is the\n * map target (i.e. the user-provided div for the map). If this is not\n * `document`, the target element needs to be focused for key events to be\n * emitted, requiring that the target element has a `tabindex` attribute.\n * @property {Array<import("./layer/Base.js").default>|Collection<import("./layer/Base.js").default>|LayerGroup} [layers]\n * Layers. If this is not defined, a map with no layers will be rendered. Note\n * that layers are rendered in the order supplied, so if you want, for example,\n * a vector layer to appear on top of a tile layer, it must come after the tile\n * layer.\n * @property {number} [maxTilesLoading=16] Maximum number tiles to load\n * simultaneously.\n * @property {number} [moveTolerance=1] The minimum distance in pixels the\n * cursor must move to be detected as a map move event instead of a click.\n * Increasing this value can make it easier to click on the map.\n * @property {Collection<import("./Overlay.js").default>|Array<import("./Overlay.js").default>} [overlays]\n * Overlays initially added to the map. By default, no overlays are added.\n * @property {HTMLElement|string} [target] The container for the map, either the\n * element itself or the `id` of the element. If not specified at construction\n * time, {@link module:ol/Map~Map#setTarget} must be called for the map to be\n * rendered. If passed by element, the container can be in a secondary document.\n * @property {View} [view] The map\'s view. No layer sources will be\n * fetched unless this is specified at construction time or through\n * {@link module:ol/Map~Map#setView}.\n */\n\n/**\n * @fires import("./MapBrowserEvent.js").MapBrowserEvent\n * @fires import("./MapEvent.js").MapEvent\n * @fires import("./render/Event.js").default#precompose\n * @fires import("./render/Event.js").default#postcompose\n * @fires import("./render/Event.js").default#rendercomplete\n * @api\n */\n\nvar PluggableMap =\n/** @class */\nfunction (_super) {\n PluggableMap_extends(PluggableMap, _super);\n /**\n * @param {MapOptions} options Map options.\n */\n\n\n function PluggableMap(options) {\n var _this = _super.call(this) || this;\n\n var optionsInternal = createOptionsInternal(options);\n /** @private */\n\n _this.boundHandleBrowserEvent_ = _this.handleBrowserEvent.bind(_this);\n /**\n * @type {number}\n * @private\n */\n\n _this.maxTilesLoading_ = options.maxTilesLoading !== undefined ? options.maxTilesLoading : 16;\n /**\n * @private\n * @type {number}\n */\n\n _this.pixelRatio_ = options.pixelRatio !== undefined ? options.pixelRatio : DEVICE_PIXEL_RATIO;\n /**\n * @private\n * @type {*}\n */\n\n _this.postRenderTimeoutHandle_;\n /**\n * @private\n * @type {number|undefined}\n */\n\n _this.animationDelayKey_;\n /**\n * @private\n */\n\n _this.animationDelay_ =\n /** @this {PluggableMap} */\n function () {\n this.animationDelayKey_ = undefined;\n this.renderFrame_(Date.now());\n }.bind(_this);\n /**\n * @private\n * @type {import("./transform.js").Transform}\n */\n\n\n _this.coordinateToPixelTransform_ = create();\n /**\n * @private\n * @type {import("./transform.js").Transform}\n */\n\n _this.pixelToCoordinateTransform_ = create();\n /**\n * @private\n * @type {number}\n */\n\n _this.frameIndex_ = 0;\n /**\n * @private\n * @type {?FrameState}\n */\n\n _this.frameState_ = null;\n /**\n * The extent at the previous \'moveend\' event.\n * @private\n * @type {import("./extent.js").Extent}\n */\n\n _this.previousExtent_ = null;\n /**\n * @private\n * @type {?import("./events.js").EventsKey}\n */\n\n _this.viewPropertyListenerKey_ = null;\n /**\n * @private\n * @type {?import("./events.js").EventsKey}\n */\n\n _this.viewChangeListenerKey_ = null;\n /**\n * @private\n * @type {?Array<import("./events.js").EventsKey>}\n */\n\n _this.layerGroupPropertyListenerKeys_ = null;\n /**\n * @private\n * @type {!HTMLElement}\n */\n\n _this.viewport_ = document.createElement(\'div\');\n _this.viewport_.className = \'ol-viewport\' + (\'ontouchstart\' in window ? \' ol-touch\' : \'\');\n _this.viewport_.style.position = \'relative\';\n _this.viewport_.style.overflow = \'hidden\';\n _this.viewport_.style.width = \'100%\';\n _this.viewport_.style.height = \'100%\';\n /**\n * @private\n * @type {!HTMLElement}\n */\n\n _this.overlayContainer_ = document.createElement(\'div\');\n _this.overlayContainer_.style.position = \'absolute\';\n _this.overlayContainer_.style.zIndex = \'0\';\n _this.overlayContainer_.style.width = \'100%\';\n _this.overlayContainer_.style.height = \'100%\';\n _this.overlayContainer_.style.pointerEvents = \'none\';\n _this.overlayContainer_.className = \'ol-overlaycontainer\';\n\n _this.viewport_.appendChild(_this.overlayContainer_);\n /**\n * @private\n * @type {!HTMLElement}\n */\n\n\n _this.overlayContainerStopEvent_ = document.createElement(\'div\');\n _this.overlayContainerStopEvent_.style.position = \'absolute\';\n _this.overlayContainerStopEvent_.style.zIndex = \'0\';\n _this.overlayContainerStopEvent_.style.width = \'100%\';\n _this.overlayContainerStopEvent_.style.height = \'100%\';\n _this.overlayContainerStopEvent_.style.pointerEvents = \'none\';\n _this.overlayContainerStopEvent_.className = \'ol-overlaycontainer-stopevent\';\n\n _this.viewport_.appendChild(_this.overlayContainerStopEvent_);\n /**\n * @private\n * @type {MapBrowserEventHandler}\n */\n\n\n _this.mapBrowserEventHandler_ = null;\n /**\n * @private\n * @type {number}\n */\n\n _this.moveTolerance_ = options.moveTolerance;\n /**\n * @private\n * @type {HTMLElement|Document}\n */\n\n _this.keyboardEventTarget_ = optionsInternal.keyboardEventTarget;\n /**\n * @private\n * @type {?Array<import("./events.js").EventsKey>}\n */\n\n _this.keyHandlerKeys_ = null;\n /**\n * @type {Collection<import("./control/Control.js").default>}\n * @protected\n */\n\n _this.controls = optionsInternal.controls || new ol_Collection();\n /**\n * @type {Collection<import("./interaction/Interaction.js").default>}\n * @protected\n */\n\n _this.interactions = optionsInternal.interactions || new ol_Collection();\n /**\n * @type {Collection<import("./Overlay.js").default>}\n * @private\n */\n\n _this.overlays_ = optionsInternal.overlays;\n /**\n * A lookup of overlays by id.\n * @private\n * @type {Object<string, import("./Overlay.js").default>}\n */\n\n _this.overlayIdIndex_ = {};\n /**\n * @type {import("./renderer/Map.js").default}\n * @private\n */\n\n _this.renderer_ = null;\n /**\n * @type {undefined|function(Event): void}\n * @private\n */\n\n _this.handleResize_;\n /**\n * @private\n * @type {!Array<PostRenderFunction>}\n */\n\n _this.postRenderFunctions_ = [];\n /**\n * @private\n * @type {TileQueue}\n */\n\n _this.tileQueue_ = new ol_TileQueue(_this.getTilePriority.bind(_this), _this.handleTileChange_.bind(_this));\n\n _this.addEventListener(getChangeEventType(MapProperty.LAYERGROUP), _this.handleLayerGroupChanged_);\n\n _this.addEventListener(getChangeEventType(MapProperty.VIEW), _this.handleViewChanged_);\n\n _this.addEventListener(getChangeEventType(MapProperty.SIZE), _this.handleSizeChanged_);\n\n _this.addEventListener(getChangeEventType(MapProperty.TARGET), _this.handleTargetChanged_); // setProperties will trigger the rendering of the map if the map\n // is "defined" already.\n\n\n _this.setProperties(optionsInternal.values);\n\n _this.controls.forEach(\n /**\n * @param {import("./control/Control.js").default} control Control.\n * @this {PluggableMap}\n */\n function (control) {\n control.setMap(this);\n }.bind(_this));\n\n _this.controls.addEventListener(CollectionEventType.ADD,\n /**\n * @param {import("./Collection.js").CollectionEvent} event CollectionEvent.\n */\n function (event) {\n event.element.setMap(this);\n }.bind(_this));\n\n _this.controls.addEventListener(CollectionEventType.REMOVE,\n /**\n * @param {import("./Collection.js").CollectionEvent} event CollectionEvent.\n */\n function (event) {\n event.element.setMap(null);\n }.bind(_this));\n\n _this.interactions.forEach(\n /**\n * @param {import("./interaction/Interaction.js").default} interaction Interaction.\n * @this {PluggableMap}\n */\n function (interaction) {\n interaction.setMap(this);\n }.bind(_this));\n\n _this.interactions.addEventListener(CollectionEventType.ADD,\n /**\n * @param {import("./Collection.js").CollectionEvent} event CollectionEvent.\n */\n function (event) {\n event.element.setMap(this);\n }.bind(_this));\n\n _this.interactions.addEventListener(CollectionEventType.REMOVE,\n /**\n * @param {import("./Collection.js").CollectionEvent} event CollectionEvent.\n */\n function (event) {\n event.element.setMap(null);\n }.bind(_this));\n\n _this.overlays_.forEach(_this.addOverlayInternal_.bind(_this));\n\n _this.overlays_.addEventListener(CollectionEventType.ADD,\n /**\n * @param {import("./Collection.js").CollectionEvent} event CollectionEvent.\n */\n function (event) {\n this.addOverlayInternal_(\n /** @type {import("./Overlay.js").default} */\n event.element);\n }.bind(_this));\n\n _this.overlays_.addEventListener(CollectionEventType.REMOVE,\n /**\n * @param {import("./Collection.js").CollectionEvent} event CollectionEvent.\n */\n function (event) {\n var overlay =\n /** @type {import("./Overlay.js").default} */\n event.element;\n var id = overlay.getId();\n\n if (id !== undefined) {\n delete this.overlayIdIndex_[id.toString()];\n }\n\n event.element.setMap(null);\n }.bind(_this));\n\n return _this;\n }\n /**\n * @abstract\n * @return {import("./renderer/Map.js").default} The map renderer\n */\n\n\n PluggableMap.prototype.createRenderer = function () {\n throw new Error(\'Use a map type that has a createRenderer method\');\n };\n /**\n * Add the given control to the map.\n * @param {import("./control/Control.js").default} control Control.\n * @api\n */\n\n\n PluggableMap.prototype.addControl = function (control) {\n this.getControls().push(control);\n };\n /**\n * Add the given interaction to the map. If you want to add an interaction\n * at another point of the collection use `getInteraction()` and the methods\n * available on {@link module:ol/Collection~Collection}. This can be used to\n * stop the event propagation from the handleEvent function. The interactions\n * get to handle the events in the reverse order of this collection.\n * @param {import("./interaction/Interaction.js").default} interaction Interaction to add.\n * @api\n */\n\n\n PluggableMap.prototype.addInteraction = function (interaction) {\n this.getInteractions().push(interaction);\n };\n /**\n * Adds the given layer to the top of this map. If you want to add a layer\n * elsewhere in the stack, use `getLayers()` and the methods available on\n * {@link module:ol/Collection~Collection}.\n * @param {import("./layer/Base.js").default} layer Layer.\n * @api\n */\n\n\n PluggableMap.prototype.addLayer = function (layer) {\n var layers = this.getLayerGroup().getLayers();\n layers.push(layer);\n };\n /**\n * Add the given overlay to the map.\n * @param {import("./Overlay.js").default} overlay Overlay.\n * @api\n */\n\n\n PluggableMap.prototype.addOverlay = function (overlay) {\n this.getOverlays().push(overlay);\n };\n /**\n * This deals with map\'s overlay collection changes.\n * @param {import("./Overlay.js").default} overlay Overlay.\n * @private\n */\n\n\n PluggableMap.prototype.addOverlayInternal_ = function (overlay) {\n var id = overlay.getId();\n\n if (id !== undefined) {\n this.overlayIdIndex_[id.toString()] = overlay;\n }\n\n overlay.setMap(this);\n };\n /**\n *\n * Clean up.\n */\n\n\n PluggableMap.prototype.disposeInternal = function () {\n this.setTarget(null);\n\n _super.prototype.disposeInternal.call(this);\n };\n /**\n * Detect features that intersect a pixel on the viewport, and execute a\n * callback with each intersecting feature. Layers included in the detection can\n * be configured through the `layerFilter` option in `opt_options`.\n * @param {import("./pixel.js").Pixel} pixel Pixel.\n * @param {function(import("./Feature.js").FeatureLike, import("./layer/Layer.js").default, import("./geom/SimpleGeometry.js").default): T} callback Feature callback. The callback will be\n * called with two arguments. The first argument is one\n * {@link module:ol/Feature feature} or\n * {@link module:ol/render/Feature render feature} at the pixel, the second is\n * the {@link module:ol/layer/Layer layer} of the feature and will be null for\n * unmanaged layers. To stop detection, callback functions can return a\n * truthy value.\n * @param {AtPixelOptions=} opt_options Optional options.\n * @return {T|undefined} Callback result, i.e. the return value of last\n * callback execution, or the first truthy callback return value.\n * @template S,T\n * @api\n */\n\n\n PluggableMap.prototype.forEachFeatureAtPixel = function (pixel, callback, opt_options) {\n if (!this.frameState_) {\n return;\n }\n\n var coordinate = this.getCoordinateFromPixelInternal(pixel);\n opt_options = opt_options !== undefined ? opt_options : {};\n var hitTolerance = opt_options.hitTolerance !== undefined ? opt_options.hitTolerance : 0;\n var layerFilter = opt_options.layerFilter !== undefined ? opt_options.layerFilter : TRUE;\n var checkWrapped = opt_options.checkWrapped !== false;\n return this.renderer_.forEachFeatureAtCoordinate(coordinate, this.frameState_, hitTolerance, checkWrapped, callback, null, layerFilter, null);\n };\n /**\n * Get all features that intersect a pixel on the viewport.\n * @param {import("./pixel.js").Pixel} pixel Pixel.\n * @param {AtPixelOptions=} opt_options Optional options.\n * @return {Array<import("./Feature.js").FeatureLike>} The detected features or\n * an empty array if none were found.\n * @api\n */\n\n\n PluggableMap.prototype.getFeaturesAtPixel = function (pixel, opt_options) {\n var features = [];\n this.forEachFeatureAtPixel(pixel, function (feature) {\n features.push(feature);\n }, opt_options);\n return features;\n };\n /**\n * Detect layers that have a color value at a pixel on the viewport, and\n * execute a callback with each matching layer. Layers included in the\n * detection can be configured through `opt_layerFilter`.\n *\n * Note: this may give false positives unless the map layers have had different `className`\n * properties assigned to them.\n *\n * @param {import("./pixel.js").Pixel} pixel Pixel.\n * @param {function(this: S, import("./layer/Layer.js").default, (Uint8ClampedArray|Uint8Array)): T} callback\n * Layer callback. This callback will receive two arguments: first is the\n * {@link module:ol/layer/Layer layer}, second argument is an array representing\n * [R, G, B, A] pixel values (0 - 255) and will be `null` for layer types\n * that do not currently support this argument. To stop detection, callback\n * functions can return a truthy value.\n * @param {AtPixelOptions=} opt_options Configuration options.\n * @return {T|undefined} Callback result, i.e. the return value of last\n * callback execution, or the first truthy callback return value.\n * @template S,T\n * @api\n */\n\n\n PluggableMap.prototype.forEachLayerAtPixel = function (pixel, callback, opt_options) {\n if (!this.frameState_) {\n return;\n }\n\n var options = opt_options || {};\n var hitTolerance = options.hitTolerance !== undefined ? options.hitTolerance : 0;\n var layerFilter = options.layerFilter || TRUE;\n return this.renderer_.forEachLayerAtPixel(pixel, this.frameState_, hitTolerance, callback, layerFilter);\n };\n /**\n * Detect if features intersect a pixel on the viewport. Layers included in the\n * detection can be configured through `opt_layerFilter`.\n * @param {import("./pixel.js").Pixel} pixel Pixel.\n * @param {AtPixelOptions=} opt_options Optional options.\n * @return {boolean} Is there a feature at the given pixel?\n * @api\n */\n\n\n PluggableMap.prototype.hasFeatureAtPixel = function (pixel, opt_options) {\n if (!this.frameState_) {\n return false;\n }\n\n var coordinate = this.getCoordinateFromPixelInternal(pixel);\n opt_options = opt_options !== undefined ? opt_options : {};\n var layerFilter = opt_options.layerFilter !== undefined ? opt_options.layerFilter : TRUE;\n var hitTolerance = opt_options.hitTolerance !== undefined ? opt_options.hitTolerance : 0;\n var checkWrapped = opt_options.checkWrapped !== false;\n return this.renderer_.hasFeatureAtCoordinate(coordinate, this.frameState_, hitTolerance, checkWrapped, layerFilter, null);\n };\n /**\n * Returns the coordinate in user projection for a browser event.\n * @param {MouseEvent} event Event.\n * @return {import("./coordinate.js").Coordinate} Coordinate.\n * @api\n */\n\n\n PluggableMap.prototype.getEventCoordinate = function (event) {\n return this.getCoordinateFromPixel(this.getEventPixel(event));\n };\n /**\n * Returns the coordinate in view projection for a browser event.\n * @param {MouseEvent} event Event.\n * @return {import("./coordinate.js").Coordinate} Coordinate.\n */\n\n\n PluggableMap.prototype.getEventCoordinateInternal = function (event) {\n return this.getCoordinateFromPixelInternal(this.getEventPixel(event));\n };\n /**\n * Returns the map pixel position for a browser event relative to the viewport.\n * @param {UIEvent} event Event.\n * @return {import("./pixel.js").Pixel} Pixel.\n * @api\n */\n\n\n PluggableMap.prototype.getEventPixel = function (event) {\n var viewportPosition = this.viewport_.getBoundingClientRect();\n var eventPosition = //FIXME Are we really calling this with a TouchEvent anywhere?\n \'changedTouches\' in event ?\n /** @type {TouchEvent} */\n event.changedTouches[0] :\n /** @type {MouseEvent} */\n event;\n return [eventPosition.clientX - viewportPosition.left, eventPosition.clientY - viewportPosition.top];\n };\n /**\n * Get the target in which this map is rendered.\n * Note that this returns what is entered as an option or in setTarget:\n * if that was an element, it returns an element; if a string, it returns that.\n * @return {HTMLElement|string|undefined} The Element or id of the Element that the\n * map is rendered in.\n * @observable\n * @api\n */\n\n\n PluggableMap.prototype.getTarget = function () {\n return (\n /** @type {HTMLElement|string|undefined} */\n this.get(MapProperty.TARGET)\n );\n };\n /**\n * Get the DOM element into which this map is rendered. In contrast to\n * `getTarget` this method always return an `Element`, or `null` if the\n * map has no target.\n * @return {HTMLElement} The element that the map is rendered in.\n * @api\n */\n\n\n PluggableMap.prototype.getTargetElement = function () {\n var target = this.getTarget();\n\n if (target !== undefined) {\n return typeof target === \'string\' ? document.getElementById(target) : target;\n } else {\n return null;\n }\n };\n /**\n * Get the coordinate for a given pixel. This returns a coordinate in the\n * user projection.\n * @param {import("./pixel.js").Pixel} pixel Pixel position in the map viewport.\n * @return {import("./coordinate.js").Coordinate} The coordinate for the pixel position.\n * @api\n */\n\n\n PluggableMap.prototype.getCoordinateFromPixel = function (pixel) {\n return toUserCoordinate(this.getCoordinateFromPixelInternal(pixel), this.getView().getProjection());\n };\n /**\n * Get the coordinate for a given pixel. This returns a coordinate in the\n * map view projection.\n * @param {import("./pixel.js").Pixel} pixel Pixel position in the map viewport.\n * @return {import("./coordinate.js").Coordinate} The coordinate for the pixel position.\n */\n\n\n PluggableMap.prototype.getCoordinateFromPixelInternal = function (pixel) {\n var frameState = this.frameState_;\n\n if (!frameState) {\n return null;\n } else {\n return apply(frameState.pixelToCoordinateTransform, pixel.slice());\n }\n };\n /**\n * Get the map controls. Modifying this collection changes the controls\n * associated with the map.\n * @return {Collection<import("./control/Control.js").default>} Controls.\n * @api\n */\n\n\n PluggableMap.prototype.getControls = function () {\n return this.controls;\n };\n /**\n * Get the map overlays. Modifying this collection changes the overlays\n * associated with the map.\n * @return {Collection<import("./Overlay.js").default>} Overlays.\n * @api\n */\n\n\n PluggableMap.prototype.getOverlays = function () {\n return this.overlays_;\n };\n /**\n * Get an overlay by its identifier (the value returned by overlay.getId()).\n * Note that the index treats string and numeric identifiers as the same. So\n * `map.getOverlayById(2)` will return an overlay with id `\'2\'` or `2`.\n * @param {string|number} id Overlay identifier.\n * @return {import("./Overlay.js").default} Overlay.\n * @api\n */\n\n\n PluggableMap.prototype.getOverlayById = function (id) {\n var overlay = this.overlayIdIndex_[id.toString()];\n return overlay !== undefined ? overlay : null;\n };\n /**\n * Get the map interactions. Modifying this collection changes the interactions\n * associated with the map.\n *\n * Interactions are used for e.g. pan, zoom and rotate.\n * @return {Collection<import("./interaction/Interaction.js").default>} Interactions.\n * @api\n */\n\n\n PluggableMap.prototype.getInteractions = function () {\n return this.interactions;\n };\n /**\n * Get the layergroup associated with this map.\n * @return {LayerGroup} A layer group containing the layers in this map.\n * @observable\n * @api\n */\n\n\n PluggableMap.prototype.getLayerGroup = function () {\n return (\n /** @type {LayerGroup} */\n this.get(MapProperty.LAYERGROUP)\n );\n };\n /**\n * Get the collection of layers associated with this map.\n * @return {!Collection<import("./layer/Base.js").default>} Layers.\n * @api\n */\n\n\n PluggableMap.prototype.getLayers = function () {\n var layers = this.getLayerGroup().getLayers();\n return layers;\n };\n /**\n * @return {boolean} Layers have sources that are still loading.\n */\n\n\n PluggableMap.prototype.getLoading = function () {\n var layerStatesArray = this.getLayerGroup().getLayerStatesArray();\n\n for (var i = 0, ii = layerStatesArray.length; i < ii; ++i) {\n var layer = layerStatesArray[i].layer;\n var source =\n /** @type {import("./layer/Layer.js").default} */\n layer.getSource();\n\n if (source && source.loading) {\n return true;\n }\n }\n\n return false;\n };\n /**\n * Get the pixel for a coordinate. This takes a coordinate in the user\n * projection and returns the corresponding pixel.\n * @param {import("./coordinate.js").Coordinate} coordinate A map coordinate.\n * @return {import("./pixel.js").Pixel} A pixel position in the map viewport.\n * @api\n */\n\n\n PluggableMap.prototype.getPixelFromCoordinate = function (coordinate) {\n var viewCoordinate = fromUserCoordinate(coordinate, this.getView().getProjection());\n return this.getPixelFromCoordinateInternal(viewCoordinate);\n };\n /**\n * Get the pixel for a coordinate. This takes a coordinate in the map view\n * projection and returns the corresponding pixel.\n * @param {import("./coordinate.js").Coordinate} coordinate A map coordinate.\n * @return {import("./pixel.js").Pixel} A pixel position in the map viewport.\n */\n\n\n PluggableMap.prototype.getPixelFromCoordinateInternal = function (coordinate) {\n var frameState = this.frameState_;\n\n if (!frameState) {\n return null;\n } else {\n return apply(frameState.coordinateToPixelTransform, coordinate.slice(0, 2));\n }\n };\n /**\n * Get the map renderer.\n * @return {import("./renderer/Map.js").default} Renderer\n */\n\n\n PluggableMap.prototype.getRenderer = function () {\n return this.renderer_;\n };\n /**\n * Get the size of this map.\n * @return {import("./size.js").Size|undefined} The size in pixels of the map in the DOM.\n * @observable\n * @api\n */\n\n\n PluggableMap.prototype.getSize = function () {\n return (\n /** @type {import("./size.js").Size|undefined} */\n this.get(MapProperty.SIZE)\n );\n };\n /**\n * Get the view associated with this map. A view manages properties such as\n * center and resolution.\n * @return {View} The view that controls this map.\n * @observable\n * @api\n */\n\n\n PluggableMap.prototype.getView = function () {\n return (\n /** @type {View} */\n this.get(MapProperty.VIEW)\n );\n };\n /**\n * Get the element that serves as the map viewport.\n * @return {HTMLElement} Viewport.\n * @api\n */\n\n\n PluggableMap.prototype.getViewport = function () {\n return this.viewport_;\n };\n /**\n * Get the element that serves as the container for overlays. Elements added to\n * this container will let mousedown and touchstart events through to the map,\n * so clicks and gestures on an overlay will trigger {@link module:ol/MapBrowserEvent~MapBrowserEvent}\n * events.\n * @return {!HTMLElement} The map\'s overlay container.\n */\n\n\n PluggableMap.prototype.getOverlayContainer = function () {\n return this.overlayContainer_;\n };\n /**\n * Get the element that serves as a container for overlays that don\'t allow\n * event propagation. Elements added to this container won\'t let mousedown and\n * touchstart events through to the map, so clicks and gestures on an overlay\n * don\'t trigger any {@link module:ol/MapBrowserEvent~MapBrowserEvent}.\n * @return {!HTMLElement} The map\'s overlay container that stops events.\n */\n\n\n PluggableMap.prototype.getOverlayContainerStopEvent = function () {\n return this.overlayContainerStopEvent_;\n };\n /**\n * @return {!Document} The document where the map is displayed.\n */\n\n\n PluggableMap.prototype.getOwnerDocument = function () {\n return this.getTargetElement() ? this.getTargetElement().ownerDocument : document;\n };\n /**\n * @param {import("./Tile.js").default} tile Tile.\n * @param {string} tileSourceKey Tile source key.\n * @param {import("./coordinate.js").Coordinate} tileCenter Tile center.\n * @param {number} tileResolution Tile resolution.\n * @return {number} Tile priority.\n */\n\n\n PluggableMap.prototype.getTilePriority = function (tile, tileSourceKey, tileCenter, tileResolution) {\n return getTilePriority(this.frameState_, tile, tileSourceKey, tileCenter, tileResolution);\n };\n /**\n * @param {UIEvent} browserEvent Browser event.\n * @param {string=} opt_type Type.\n */\n\n\n PluggableMap.prototype.handleBrowserEvent = function (browserEvent, opt_type) {\n var type = opt_type || browserEvent.type;\n var mapBrowserEvent = new ol_MapBrowserEvent(type, this, browserEvent);\n this.handleMapBrowserEvent(mapBrowserEvent);\n };\n /**\n * @param {MapBrowserEvent} mapBrowserEvent The event to handle.\n */\n\n\n PluggableMap.prototype.handleMapBrowserEvent = function (mapBrowserEvent) {\n if (!this.frameState_) {\n // With no view defined, we cannot translate pixels into geographical\n // coordinates so interactions cannot be used.\n return;\n }\n\n var originalEvent =\n /** @type {PointerEvent} */\n mapBrowserEvent.originalEvent;\n var eventType = originalEvent.type;\n\n if (eventType === pointer_EventType.POINTERDOWN || eventType === EventType.WHEEL || eventType === EventType.KEYDOWN) {\n var doc = this.getOwnerDocument();\n var rootNode = this.viewport_.getRootNode ? this.viewport_.getRootNode() : doc;\n var target = \'host\' in rootNode // ShadowRoot\n ?\n /** @type {ShadowRoot} */\n rootNode.elementFromPoint(originalEvent.clientX, originalEvent.clientY) :\n /** @type {Node} */\n originalEvent.target;\n\n if ( // Abort if the target is a child of the container for elements whose events are not meant\n // to be handled by map interactions.\n this.overlayContainerStopEvent_.contains(target) || // Abort if the event target is a child of the container that is no longer in the page.\n // It\'s possible for the target to no longer be in the page if it has been removed in an\n // event listener, this might happen in a Control that recreates it\'s content based on\n // user interaction either manually or via a render in something like https://reactjs.org/\n !(rootNode === doc ? doc.documentElement : rootNode).contains(target)) {\n return;\n }\n }\n\n mapBrowserEvent.frameState = this.frameState_;\n\n if (this.dispatchEvent(mapBrowserEvent) !== false) {\n var interactionsArray = this.getInteractions().getArray().slice();\n\n for (var i = interactionsArray.length - 1; i >= 0; i--) {\n var interaction = interactionsArray[i];\n\n if (interaction.getMap() !== this || !interaction.getActive() || !this.getTargetElement()) {\n continue;\n }\n\n var cont = interaction.handleEvent(mapBrowserEvent);\n\n if (!cont || mapBrowserEvent.propagationStopped) {\n break;\n }\n }\n }\n };\n /**\n * @protected\n */\n\n\n PluggableMap.prototype.handlePostRender = function () {\n var frameState = this.frameState_; // Manage the tile queue\n // Image loads are expensive and a limited resource, so try to use them\n // efficiently:\n // * When the view is static we allow a large number of parallel tile loads\n // to complete the frame as quickly as possible.\n // * When animating or interacting, image loads can cause janks, so we reduce\n // the maximum number of loads per frame and limit the number of parallel\n // tile loads to remain reactive to view changes and to reduce the chance of\n // loading tiles that will quickly disappear from view.\n\n var tileQueue = this.tileQueue_;\n\n if (!tileQueue.isEmpty()) {\n var maxTotalLoading = this.maxTilesLoading_;\n var maxNewLoads = maxTotalLoading;\n\n if (frameState) {\n var hints = frameState.viewHints;\n\n if (hints[ViewHint.ANIMATING] || hints[ViewHint.INTERACTING]) {\n var lowOnFrameBudget = !IMAGE_DECODE && Date.now() - frameState.time > 8;\n maxTotalLoading = lowOnFrameBudget ? 0 : 8;\n maxNewLoads = lowOnFrameBudget ? 0 : 2;\n }\n }\n\n if (tileQueue.getTilesLoading() < maxTotalLoading) {\n tileQueue.reprioritize(); // FIXME only call if view has changed\n\n tileQueue.loadMoreTiles(maxTotalLoading, maxNewLoads);\n }\n }\n\n if (frameState && this.hasListener(render_EventType.RENDERCOMPLETE) && !frameState.animate && !this.tileQueue_.getTilesLoading() && !this.getLoading()) {\n this.renderer_.dispatchRenderEvent(render_EventType.RENDERCOMPLETE, frameState);\n }\n\n var postRenderFunctions = this.postRenderFunctions_;\n\n for (var i = 0, ii = postRenderFunctions.length; i < ii; ++i) {\n postRenderFunctions[i](this, frameState);\n }\n\n postRenderFunctions.length = 0;\n };\n /**\n * @private\n */\n\n\n PluggableMap.prototype.handleSizeChanged_ = function () {\n if (this.getView() && !this.getView().getAnimating()) {\n this.getView().resolveConstraints(0);\n }\n\n this.render();\n };\n /**\n * @private\n */\n\n\n PluggableMap.prototype.handleTargetChanged_ = function () {\n // target may be undefined, null, a string or an Element.\n // If it\'s a string we convert it to an Element before proceeding.\n // If it\'s not now an Element we remove the viewport from the DOM.\n // If it\'s an Element we append the viewport element to it.\n var targetElement;\n\n if (this.getTarget()) {\n targetElement = this.getTargetElement();\n }\n\n if (this.mapBrowserEventHandler_) {\n for (var i = 0, ii = this.keyHandlerKeys_.length; i < ii; ++i) {\n unlistenByKey(this.keyHandlerKeys_[i]);\n }\n\n this.keyHandlerKeys_ = null;\n this.viewport_.removeEventListener(EventType.CONTEXTMENU, this.boundHandleBrowserEvent_);\n this.viewport_.removeEventListener(EventType.WHEEL, this.boundHandleBrowserEvent_);\n\n if (this.handleResize_ !== undefined) {\n removeEventListener(EventType.RESIZE, this.handleResize_, false);\n this.handleResize_ = undefined;\n }\n\n this.mapBrowserEventHandler_.dispose();\n this.mapBrowserEventHandler_ = null;\n removeNode(this.viewport_);\n }\n\n if (!targetElement) {\n if (this.renderer_) {\n clearTimeout(this.postRenderTimeoutHandle_);\n this.postRenderTimeoutHandle_ = undefined;\n this.postRenderFunctions_.length = 0;\n this.renderer_.dispose();\n this.renderer_ = null;\n }\n\n if (this.animationDelayKey_) {\n cancelAnimationFrame(this.animationDelayKey_);\n this.animationDelayKey_ = undefined;\n }\n } else {\n targetElement.appendChild(this.viewport_);\n\n if (!this.renderer_) {\n this.renderer_ = this.createRenderer();\n }\n\n this.mapBrowserEventHandler_ = new ol_MapBrowserEventHandler(this, this.moveTolerance_);\n\n for (var key in ol_MapBrowserEventType) {\n this.mapBrowserEventHandler_.addEventListener(ol_MapBrowserEventType[key], this.handleMapBrowserEvent.bind(this));\n }\n\n this.viewport_.addEventListener(EventType.CONTEXTMENU, this.boundHandleBrowserEvent_, false);\n this.viewport_.addEventListener(EventType.WHEEL, this.boundHandleBrowserEvent_, PASSIVE_EVENT_LISTENERS ? {\n passive: false\n } : false);\n var keyboardEventTarget = !this.keyboardEventTarget_ ? targetElement : this.keyboardEventTarget_;\n this.keyHandlerKeys_ = [listen(keyboardEventTarget, EventType.KEYDOWN, this.handleBrowserEvent, this), listen(keyboardEventTarget, EventType.KEYPRESS, this.handleBrowserEvent, this)];\n\n if (!this.handleResize_) {\n this.handleResize_ = this.updateSize.bind(this);\n window.addEventListener(EventType.RESIZE, this.handleResize_, false);\n }\n }\n\n this.updateSize(); // updateSize calls setSize, so no need to call this.render\n // ourselves here.\n };\n /**\n * @private\n */\n\n\n PluggableMap.prototype.handleTileChange_ = function () {\n this.render();\n };\n /**\n * @private\n */\n\n\n PluggableMap.prototype.handleViewPropertyChanged_ = function () {\n this.render();\n };\n /**\n * @private\n */\n\n\n PluggableMap.prototype.handleViewChanged_ = function () {\n if (this.viewPropertyListenerKey_) {\n unlistenByKey(this.viewPropertyListenerKey_);\n this.viewPropertyListenerKey_ = null;\n }\n\n if (this.viewChangeListenerKey_) {\n unlistenByKey(this.viewChangeListenerKey_);\n this.viewChangeListenerKey_ = null;\n }\n\n var view = this.getView();\n\n if (view) {\n this.updateViewportSize_();\n this.viewPropertyListenerKey_ = listen(view, ObjectEventType.PROPERTYCHANGE, this.handleViewPropertyChanged_, this);\n this.viewChangeListenerKey_ = listen(view, EventType.CHANGE, this.handleViewPropertyChanged_, this);\n view.resolveConstraints(0);\n }\n\n this.render();\n };\n /**\n * @private\n */\n\n\n PluggableMap.prototype.handleLayerGroupChanged_ = function () {\n if (this.layerGroupPropertyListenerKeys_) {\n this.layerGroupPropertyListenerKeys_.forEach(unlistenByKey);\n this.layerGroupPropertyListenerKeys_ = null;\n }\n\n var layerGroup = this.getLayerGroup();\n\n if (layerGroup) {\n this.layerGroupPropertyListenerKeys_ = [listen(layerGroup, ObjectEventType.PROPERTYCHANGE, this.render, this), listen(layerGroup, EventType.CHANGE, this.render, this)];\n }\n\n this.render();\n };\n /**\n * @return {boolean} Is rendered.\n */\n\n\n PluggableMap.prototype.isRendered = function () {\n return !!this.frameState_;\n };\n /**\n * Requests an immediate render in a synchronous manner.\n * @api\n */\n\n\n PluggableMap.prototype.renderSync = function () {\n if (this.animationDelayKey_) {\n cancelAnimationFrame(this.animationDelayKey_);\n }\n\n this.animationDelay_();\n };\n /**\n * Redraws all text after new fonts have loaded\n */\n\n\n PluggableMap.prototype.redrawText = function () {\n var layerStates = this.getLayerGroup().getLayerStatesArray();\n\n for (var i = 0, ii = layerStates.length; i < ii; ++i) {\n var layer = layerStates[i].layer;\n\n if (layer.hasRenderer()) {\n layer.getRenderer().handleFontsChanged();\n }\n }\n };\n /**\n * Request a map rendering (at the next animation frame).\n * @api\n */\n\n\n PluggableMap.prototype.render = function () {\n if (this.renderer_ && this.animationDelayKey_ === undefined) {\n this.animationDelayKey_ = requestAnimationFrame(this.animationDelay_);\n }\n };\n /**\n * Remove the given control from the map.\n * @param {import("./control/Control.js").default} control Control.\n * @return {import("./control/Control.js").default|undefined} The removed control (or undefined\n * if the control was not found).\n * @api\n */\n\n\n PluggableMap.prototype.removeControl = function (control) {\n return this.getControls().remove(control);\n };\n /**\n * Remove the given interaction from the map.\n * @param {import("./interaction/Interaction.js").default} interaction Interaction to remove.\n * @return {import("./interaction/Interaction.js").default|undefined} The removed interaction (or\n * undefined if the interaction was not found).\n * @api\n */\n\n\n PluggableMap.prototype.removeInteraction = function (interaction) {\n return this.getInteractions().remove(interaction);\n };\n /**\n * Removes the given layer from the map.\n * @param {import("./layer/Base.js").default} layer Layer.\n * @return {import("./layer/Base.js").default|undefined} The removed layer (or undefined if the\n * layer was not found).\n * @api\n */\n\n\n PluggableMap.prototype.removeLayer = function (layer) {\n var layers = this.getLayerGroup().getLayers();\n return layers.remove(layer);\n };\n /**\n * Remove the given overlay from the map.\n * @param {import("./Overlay.js").default} overlay Overlay.\n * @return {import("./Overlay.js").default|undefined} The removed overlay (or undefined\n * if the overlay was not found).\n * @api\n */\n\n\n PluggableMap.prototype.removeOverlay = function (overlay) {\n return this.getOverlays().remove(overlay);\n };\n /**\n * @param {number} time Time.\n * @private\n */\n\n\n PluggableMap.prototype.renderFrame_ = function (time) {\n var _this = this;\n\n var size = this.getSize();\n var view = this.getView();\n var previousFrameState = this.frameState_;\n /** @type {?FrameState} */\n\n var frameState = null;\n\n if (size !== undefined && hasArea(size) && view && view.isDef()) {\n var viewHints = view.getHints(this.frameState_ ? this.frameState_.viewHints : undefined);\n var viewState = view.getState();\n frameState = {\n animate: false,\n coordinateToPixelTransform: this.coordinateToPixelTransform_,\n declutterTree: null,\n extent: getForViewAndSize(viewState.center, viewState.resolution, viewState.rotation, size),\n index: this.frameIndex_++,\n layerIndex: 0,\n layerStatesArray: this.getLayerGroup().getLayerStatesArray(),\n pixelRatio: this.pixelRatio_,\n pixelToCoordinateTransform: this.pixelToCoordinateTransform_,\n postRenderFunctions: [],\n size: size,\n tileQueue: this.tileQueue_,\n time: time,\n usedTiles: {},\n viewState: viewState,\n viewHints: viewHints,\n wantedTiles: {}\n };\n }\n\n this.frameState_ = frameState;\n this.renderer_.renderFrame(frameState);\n\n if (frameState) {\n if (frameState.animate) {\n this.render();\n }\n\n Array.prototype.push.apply(this.postRenderFunctions_, frameState.postRenderFunctions);\n\n if (previousFrameState) {\n var moveStart = !this.previousExtent_ || !extent_isEmpty(this.previousExtent_) && !extent_equals(frameState.extent, this.previousExtent_);\n\n if (moveStart) {\n this.dispatchEvent(new ol_MapEvent(MapEventType.MOVESTART, this, previousFrameState));\n this.previousExtent_ = createOrUpdateEmpty(this.previousExtent_);\n }\n }\n\n var idle = this.previousExtent_ && !frameState.viewHints[ViewHint.ANIMATING] && !frameState.viewHints[ViewHint.INTERACTING] && !extent_equals(frameState.extent, this.previousExtent_);\n\n if (idle) {\n this.dispatchEvent(new ol_MapEvent(MapEventType.MOVEEND, this, frameState));\n clone(frameState.extent, this.previousExtent_);\n }\n }\n\n this.dispatchEvent(new ol_MapEvent(MapEventType.POSTRENDER, this, frameState));\n\n if (!this.postRenderTimeoutHandle_) {\n this.postRenderTimeoutHandle_ = setTimeout(function () {\n _this.postRenderTimeoutHandle_ = undefined;\n\n _this.handlePostRender();\n }, 0);\n }\n };\n /**\n * Sets the layergroup of this map.\n * @param {LayerGroup} layerGroup A layer group containing the layers in this map.\n * @observable\n * @api\n */\n\n\n PluggableMap.prototype.setLayerGroup = function (layerGroup) {\n this.set(MapProperty.LAYERGROUP, layerGroup);\n };\n /**\n * Set the size of this map.\n * @param {import("./size.js").Size|undefined} size The size in pixels of the map in the DOM.\n * @observable\n * @api\n */\n\n\n PluggableMap.prototype.setSize = function (size) {\n this.set(MapProperty.SIZE, size);\n };\n /**\n * Set the target element to render this map into.\n * @param {HTMLElement|string|undefined} target The Element or id of the Element\n * that the map is rendered in.\n * @observable\n * @api\n */\n\n\n PluggableMap.prototype.setTarget = function (target) {\n this.set(MapProperty.TARGET, target);\n };\n /**\n * Set the view for this map.\n * @param {View} view The view that controls this map.\n * @observable\n * @api\n */\n\n\n PluggableMap.prototype.setView = function (view) {\n this.set(MapProperty.VIEW, view);\n };\n /**\n * Force a recalculation of the map viewport size. This should be called when\n * third-party code changes the size of the map viewport.\n * @api\n */\n\n\n PluggableMap.prototype.updateSize = function () {\n var targetElement = this.getTargetElement();\n\n if (!targetElement) {\n this.setSize(undefined);\n } else {\n var computedStyle = getComputedStyle(targetElement);\n this.setSize([targetElement.offsetWidth - parseFloat(computedStyle[\'borderLeftWidth\']) - parseFloat(computedStyle[\'paddingLeft\']) - parseFloat(computedStyle[\'paddingRight\']) - parseFloat(computedStyle[\'borderRightWidth\']), targetElement.offsetHeight - parseFloat(computedStyle[\'borderTopWidth\']) - parseFloat(computedStyle[\'paddingTop\']) - parseFloat(computedStyle[\'paddingBottom\']) - parseFloat(computedStyle[\'borderBottomWidth\'])]);\n }\n\n this.updateViewportSize_();\n };\n /**\n * Recomputes the viewport size and save it on the view object (if any)\n * @private\n */\n\n\n PluggableMap.prototype.updateViewportSize_ = function () {\n var view = this.getView();\n\n if (view) {\n var size = undefined;\n var computedStyle = getComputedStyle(this.viewport_);\n\n if (computedStyle.width && computedStyle.height) {\n size = [parseInt(computedStyle.width, 10), parseInt(computedStyle.height, 10)];\n }\n\n view.setViewportSize(size);\n }\n };\n\n return PluggableMap;\n}(ol_Object);\n/**\n * @param {MapOptions} options Map options.\n * @return {MapOptionsInternal} Internal map options.\n */\n\n\nfunction createOptionsInternal(options) {\n /**\n * @type {HTMLElement|Document}\n */\n var keyboardEventTarget = null;\n\n if (options.keyboardEventTarget !== undefined) {\n keyboardEventTarget = typeof options.keyboardEventTarget === \'string\' ? document.getElementById(options.keyboardEventTarget) : options.keyboardEventTarget;\n }\n /**\n * @type {Object<string, *>}\n */\n\n\n var values = {};\n var layerGroup = options.layers && typeof\n /** @type {?} */\n options.layers.getLayers === \'function\' ?\n /** @type {LayerGroup} */\n options.layers : new Group({\n layers:\n /** @type {Collection} */\n options.layers\n });\n values[MapProperty.LAYERGROUP] = layerGroup;\n values[MapProperty.TARGET] = options.target;\n values[MapProperty.VIEW] = options.view !== undefined ? options.view : new ol_View();\n var controls;\n\n if (options.controls !== undefined) {\n if (Array.isArray(options.controls)) {\n controls = new ol_Collection(options.controls.slice());\n } else {\n asserts_assert(typeof\n /** @type {?} */\n options.controls.getArray === \'function\', 47); // Expected `controls` to be an array or an `import("./Collection.js").Collection`\n\n controls =\n /** @type {Collection} */\n options.controls;\n }\n }\n\n var interactions;\n\n if (options.interactions !== undefined) {\n if (Array.isArray(options.interactions)) {\n interactions = new ol_Collection(options.interactions.slice());\n } else {\n asserts_assert(typeof\n /** @type {?} */\n options.interactions.getArray === \'function\', 48); // Expected `interactions` to be an array or an `import("./Collection.js").Collection`\n\n interactions =\n /** @type {Collection} */\n options.interactions;\n }\n }\n\n var overlays;\n\n if (options.overlays !== undefined) {\n if (Array.isArray(options.overlays)) {\n overlays = new ol_Collection(options.overlays.slice());\n } else {\n asserts_assert(typeof\n /** @type {?} */\n options.overlays.getArray === \'function\', 49); // Expected `overlays` to be an array or an `import("./Collection.js").Collection`\n\n overlays = options.overlays;\n }\n } else {\n overlays = new ol_Collection();\n }\n\n return {\n controls: controls,\n interactions: interactions,\n keyboardEventTarget: keyboardEventTarget,\n overlays: overlays,\n values: values\n };\n}\n\n/* harmony default export */ var ol_PluggableMap = (PluggableMap);\n;// CONCATENATED MODULE: ./node_modules/ol/control/Control.js\nvar Control_extends = undefined && undefined.__extends || function () {\n var _extendStatics = function extendStatics(d, b) {\n _extendStatics = Object.setPrototypeOf || {\n __proto__: []\n } instanceof Array && function (d, b) {\n d.__proto__ = b;\n } || function (d, b) {\n for (var p in b) {\n if (Object.prototype.hasOwnProperty.call(b, p)) d[p] = b[p];\n }\n };\n\n return _extendStatics(d, b);\n };\n\n return function (d, b) {\n _extendStatics(d, b);\n\n function __() {\n this.constructor = d;\n }\n\n d.prototype = b === null ? Object.create(b) : (__.prototype = b.prototype, new __());\n };\n}();\n/**\n * @module ol/control/Control\n */\n\n\n\n\n\n\n\n/**\n * @typedef {Object} Options\n * @property {HTMLElement} [element] The element is the control\'s\n * container element. This only needs to be specified if you\'re developing\n * a custom control.\n * @property {function(import("../MapEvent.js").default):void} [render] Function called when\n * the control should be re-rendered. This is called in a `requestAnimationFrame`\n * callback.\n * @property {HTMLElement|string} [target] Specify a target if you want\n * the control to be rendered outside of the map\'s viewport.\n */\n\n/**\n * @classdesc\n * A control is a visible widget with a DOM element in a fixed position on the\n * screen. They can involve user input (buttons), or be informational only;\n * the position is determined using CSS. By default these are placed in the\n * container with CSS class name `ol-overlaycontainer-stopevent`, but can use\n * any outside DOM element.\n *\n * This is the base class for controls. You can use it for simple custom\n * controls by creating the element with listeners, creating an instance:\n * ```js\n * var myControl = new Control({element: myElement});\n * ```\n * and then adding this to the map.\n *\n * The main advantage of having this as a control rather than a simple separate\n * DOM element is that preventing propagation is handled for you. Controls\n * will also be objects in a {@link module:ol/Collection~Collection}, so you can use their methods.\n *\n * You can also extend this base for your own control class. See\n * examples/custom-controls for an example of how to do this.\n *\n * @api\n */\n\nvar Control =\n/** @class */\nfunction (_super) {\n Control_extends(Control, _super);\n /**\n * @param {Options} options Control options.\n */\n\n\n function Control(options) {\n var _this = _super.call(this) || this;\n\n var element = options.element;\n\n if (element && !options.target && !element.style.pointerEvents) {\n element.style.pointerEvents = \'auto\';\n }\n /**\n * @protected\n * @type {HTMLElement}\n */\n\n\n _this.element = element ? element : null;\n /**\n * @private\n * @type {HTMLElement}\n */\n\n _this.target_ = null;\n /**\n * @private\n * @type {import("../PluggableMap.js").default}\n */\n\n _this.map_ = null;\n /**\n * @protected\n * @type {!Array<import("../events.js").EventsKey>}\n */\n\n _this.listenerKeys = [];\n\n if (options.render) {\n _this.render = options.render;\n }\n\n if (options.target) {\n _this.setTarget(options.target);\n }\n\n return _this;\n }\n /**\n * Clean up.\n */\n\n\n Control.prototype.disposeInternal = function () {\n removeNode(this.element);\n\n _super.prototype.disposeInternal.call(this);\n };\n /**\n * Get the map associated with this control.\n * @return {import("../PluggableMap.js").default} Map.\n * @api\n */\n\n\n Control.prototype.getMap = function () {\n return this.map_;\n };\n /**\n * Remove the control from its current map and attach it to the new map.\n * Subclasses may set up event handlers to get notified about changes to\n * the map here.\n * @param {import("../PluggableMap.js").default} map Map.\n * @api\n */\n\n\n Control.prototype.setMap = function (map) {\n if (this.map_) {\n removeNode(this.element);\n }\n\n for (var i = 0, ii = this.listenerKeys.length; i < ii; ++i) {\n unlistenByKey(this.listenerKeys[i]);\n }\n\n this.listenerKeys.length = 0;\n this.map_ = map;\n\n if (this.map_) {\n var target = this.target_ ? this.target_ : map.getOverlayContainerStopEvent();\n target.appendChild(this.element);\n\n if (this.render !== VOID) {\n this.listenerKeys.push(listen(map, MapEventType.POSTRENDER, this.render, this));\n }\n\n map.render();\n }\n };\n /**\n * Renders the control.\n * @param {import("../MapEvent.js").default} mapEvent Map event.\n * @api\n */\n\n\n Control.prototype.render = function (mapEvent) {};\n /**\n * This function is used to set a target element for the control. It has no\n * effect if it is called after the control has been added to the map (i.e.\n * after `setMap` is called on the control). If no `target` is set in the\n * options passed to the control constructor and if `setTarget` is not called\n * then the control is added to the map\'s overlay container.\n * @param {HTMLElement|string} target Target.\n * @api\n */\n\n\n Control.prototype.setTarget = function (target) {\n this.target_ = typeof target === \'string\' ? document.getElementById(target) : target;\n };\n\n return Control;\n}(ol_Object);\n\n/* harmony default export */ var control_Control = (Control);\n;// CONCATENATED MODULE: ./node_modules/ol/control/Attribution.js\nvar Attribution_extends = undefined && undefined.__extends || function () {\n var _extendStatics = function extendStatics(d, b) {\n _extendStatics = Object.setPrototypeOf || {\n __proto__: []\n } instanceof Array && function (d, b) {\n d.__proto__ = b;\n } || function (d, b) {\n for (var p in b) {\n if (Object.prototype.hasOwnProperty.call(b, p)) d[p] = b[p];\n }\n };\n\n return _extendStatics(d, b);\n };\n\n return function (d, b) {\n _extendStatics(d, b);\n\n function __() {\n this.constructor = d;\n }\n\n d.prototype = b === null ? Object.create(b) : (__.prototype = b.prototype, new __());\n };\n}();\n/**\n * @module ol/control/Attribution\n */\n\n\n\n\n\n\n\n\n/**\n * @typedef {Object} Options\n * @property {string} [className=\'ol-attribution\'] CSS class name.\n * @property {HTMLElement|string} [target] Specify a target if you\n * want the control to be rendered outside of the map\'s\n * viewport.\n * @property {boolean} [collapsible] Specify if attributions can\n * be collapsed. If not specified, sources control this behavior with their\n * `attributionsCollapsible` setting.\n * @property {boolean} [collapsed=true] Specify if attributions should\n * be collapsed at startup.\n * @property {string} [tipLabel=\'Attributions\'] Text label to use for the button tip.\n * @property {string} [label=\'i\'] Text label to use for the\n * collapsed attributions button.\n * Instead of text, also an element (e.g. a `span` element) can be used.\n * @property {string} [expandClassName=className + \'-expand\'] CSS class name for the\n * collapsed attributions button.\n * @property {string|HTMLElement} [collapseLabel=\'»\'] Text label to use\n * for the expanded attributions button.\n * Instead of text, also an element (e.g. a `span` element) can be used.\n * @property {string} [collapseClassName=className + \'-collapse\'] CSS class name for the\n * expanded attributions button.\n * @property {function(import("../MapEvent.js").default):void} [render] Function called when\n * the control should be re-rendered. This is called in a `requestAnimationFrame`\n * callback.\n */\n\n/**\n * @classdesc\n * Control to show all the attributions associated with the layer sources\n * in the map. This control is one of the default controls included in maps.\n * By default it will show in the bottom right portion of the map, but this can\n * be changed by using a css selector for `.ol-attribution`.\n *\n * @api\n */\n\nvar Attribution =\n/** @class */\nfunction (_super) {\n Attribution_extends(Attribution, _super);\n /**\n * @param {Options=} opt_options Attribution options.\n */\n\n\n function Attribution(opt_options) {\n var _this = this;\n\n var options = opt_options ? opt_options : {};\n _this = _super.call(this, {\n element: document.createElement(\'div\'),\n render: options.render,\n target: options.target\n }) || this;\n /**\n * @private\n * @type {HTMLElement}\n */\n\n _this.ulElement_ = document.createElement(\'ul\');\n /**\n * @private\n * @type {boolean}\n */\n\n _this.collapsed_ = options.collapsed !== undefined ? options.collapsed : true;\n /**\n * @private\n * @type {boolean}\n */\n\n _this.userCollapsed_ = _this.collapsed_;\n /**\n * @private\n * @type {boolean}\n */\n\n _this.overrideCollapsible_ = options.collapsible !== undefined;\n /**\n * @private\n * @type {boolean}\n */\n\n _this.collapsible_ = options.collapsible !== undefined ? options.collapsible : true;\n\n if (!_this.collapsible_) {\n _this.collapsed_ = false;\n }\n\n var className = options.className !== undefined ? options.className : \'ol-attribution\';\n var tipLabel = options.tipLabel !== undefined ? options.tipLabel : \'Attributions\';\n var expandClassName = options.expandClassName !== undefined ? options.expandClassName : className + \'-expand\';\n var collapseLabel = options.collapseLabel !== undefined ? options.collapseLabel : "\\xBB";\n var collapseClassName = options.collapseClassName !== undefined ? options.collapseClassName : className + \'-collpase\';\n\n if (typeof collapseLabel === \'string\') {\n /**\n * @private\n * @type {HTMLElement}\n */\n _this.collapseLabel_ = document.createElement(\'span\');\n _this.collapseLabel_.textContent = collapseLabel;\n _this.collapseLabel_.className = collapseClassName;\n } else {\n _this.collapseLabel_ = collapseLabel;\n }\n\n var label = options.label !== undefined ? options.label : \'i\';\n\n if (typeof label === \'string\') {\n /**\n * @private\n * @type {HTMLElement}\n */\n _this.label_ = document.createElement(\'span\');\n _this.label_.textContent = label;\n _this.label_.className = expandClassName;\n } else {\n _this.label_ = label;\n }\n\n var activeLabel = _this.collapsible_ && !_this.collapsed_ ? _this.collapseLabel_ : _this.label_;\n var button = document.createElement(\'button\');\n button.setAttribute(\'type\', \'button\');\n button.title = tipLabel;\n button.appendChild(activeLabel);\n button.addEventListener(EventType.CLICK, _this.handleClick_.bind(_this), false);\n var cssClasses = className + \' \' + CLASS_UNSELECTABLE + \' \' + CLASS_CONTROL + (_this.collapsed_ && _this.collapsible_ ? \' \' + CLASS_COLLAPSED : \'\') + (_this.collapsible_ ? \'\' : \' ol-uncollapsible\');\n var element = _this.element;\n element.className = cssClasses;\n element.appendChild(_this.ulElement_);\n element.appendChild(button);\n /**\n * A list of currently rendered resolutions.\n * @type {Array<string>}\n * @private\n */\n\n _this.renderedAttributions_ = [];\n /**\n * @private\n * @type {boolean}\n */\n\n _this.renderedVisible_ = true;\n return _this;\n }\n /**\n * Collect a list of visible attributions and set the collapsible state.\n * @param {import("../PluggableMap.js").FrameState} frameState Frame state.\n * @return {Array<string>} Attributions.\n * @private\n */\n\n\n Attribution.prototype.collectSourceAttributions_ = function (frameState) {\n /**\n * Used to determine if an attribution already exists.\n * @type {!Object<string, boolean>}\n */\n var lookup = {};\n /**\n * A list of visible attributions.\n * @type {Array<string>}\n */\n\n var visibleAttributions = [];\n var collapsible = true;\n var layerStatesArray = frameState.layerStatesArray;\n\n for (var i = 0, ii = layerStatesArray.length; i < ii; ++i) {\n var layerState = layerStatesArray[i];\n\n if (!inView(layerState, frameState.viewState)) {\n continue;\n }\n\n var source =\n /** @type {import("../layer/Layer.js").default} */\n layerState.layer.getSource();\n\n if (!source) {\n continue;\n }\n\n var attributionGetter = source.getAttributions();\n\n if (!attributionGetter) {\n continue;\n }\n\n var attributions = attributionGetter(frameState);\n\n if (!attributions) {\n continue;\n }\n\n collapsible = collapsible && source.getAttributionsCollapsible() !== false;\n\n if (Array.isArray(attributions)) {\n for (var j = 0, jj = attributions.length; j < jj; ++j) {\n if (!(attributions[j] in lookup)) {\n visibleAttributions.push(attributions[j]);\n lookup[attributions[j]] = true;\n }\n }\n } else {\n if (!(attributions in lookup)) {\n visibleAttributions.push(attributions);\n lookup[attributions] = true;\n }\n }\n }\n\n if (!this.overrideCollapsible_) {\n this.setCollapsible(collapsible);\n }\n\n return visibleAttributions;\n };\n /**\n * @private\n * @param {?import("../PluggableMap.js").FrameState} frameState Frame state.\n */\n\n\n Attribution.prototype.updateElement_ = function (frameState) {\n if (!frameState) {\n if (this.renderedVisible_) {\n this.element.style.display = \'none\';\n this.renderedVisible_ = false;\n }\n\n return;\n }\n\n var attributions = this.collectSourceAttributions_(frameState);\n var visible = attributions.length > 0;\n\n if (this.renderedVisible_ != visible) {\n this.element.style.display = visible ? \'\' : \'none\';\n this.renderedVisible_ = visible;\n }\n\n if (equals(attributions, this.renderedAttributions_)) {\n return;\n }\n\n removeChildren(this.ulElement_); // append the attributions\n\n for (var i = 0, ii = attributions.length; i < ii; ++i) {\n var element = document.createElement(\'li\');\n element.innerHTML = attributions[i];\n this.ulElement_.appendChild(element);\n }\n\n this.renderedAttributions_ = attributions;\n };\n /**\n * @param {MouseEvent} event The event to handle\n * @private\n */\n\n\n Attribution.prototype.handleClick_ = function (event) {\n event.preventDefault();\n this.handleToggle_();\n this.userCollapsed_ = this.collapsed_;\n };\n /**\n * @private\n */\n\n\n Attribution.prototype.handleToggle_ = function () {\n this.element.classList.toggle(CLASS_COLLAPSED);\n\n if (this.collapsed_) {\n replaceNode(this.collapseLabel_, this.label_);\n } else {\n replaceNode(this.label_, this.collapseLabel_);\n }\n\n this.collapsed_ = !this.collapsed_;\n };\n /**\n * Return `true` if the attribution is collapsible, `false` otherwise.\n * @return {boolean} True if the widget is collapsible.\n * @api\n */\n\n\n Attribution.prototype.getCollapsible = function () {\n return this.collapsible_;\n };\n /**\n * Set whether the attribution should be collapsible.\n * @param {boolean} collapsible True if the widget is collapsible.\n * @api\n */\n\n\n Attribution.prototype.setCollapsible = function (collapsible) {\n if (this.collapsible_ === collapsible) {\n return;\n }\n\n this.collapsible_ = collapsible;\n this.element.classList.toggle(\'ol-uncollapsible\');\n\n if (this.userCollapsed_) {\n this.handleToggle_();\n }\n };\n /**\n * Collapse or expand the attribution according to the passed parameter. Will\n * not do anything if the attribution isn\'t collapsible or if the current\n * collapsed state is already the one requested.\n * @param {boolean} collapsed True if the widget is collapsed.\n * @api\n */\n\n\n Attribution.prototype.setCollapsed = function (collapsed) {\n this.userCollapsed_ = collapsed;\n\n if (!this.collapsible_ || this.collapsed_ === collapsed) {\n return;\n }\n\n this.handleToggle_();\n };\n /**\n * Return `true` when the attribution is currently collapsed or `false`\n * otherwise.\n * @return {boolean} True if the widget is collapsed.\n * @api\n */\n\n\n Attribution.prototype.getCollapsed = function () {\n return this.collapsed_;\n };\n /**\n * Update the attribution element.\n * @param {import("../MapEvent.js").default} mapEvent Map event.\n * @override\n */\n\n\n Attribution.prototype.render = function (mapEvent) {\n this.updateElement_(mapEvent.frameState);\n };\n\n return Attribution;\n}(control_Control);\n\n/* harmony default export */ var control_Attribution = (Attribution);\n;// CONCATENATED MODULE: ./node_modules/ol/control/Rotate.js\nvar Rotate_extends = undefined && undefined.__extends || function () {\n var _extendStatics = function extendStatics(d, b) {\n _extendStatics = Object.setPrototypeOf || {\n __proto__: []\n } instanceof Array && function (d, b) {\n d.__proto__ = b;\n } || function (d, b) {\n for (var p in b) {\n if (Object.prototype.hasOwnProperty.call(b, p)) d[p] = b[p];\n }\n };\n\n return _extendStatics(d, b);\n };\n\n return function (d, b) {\n _extendStatics(d, b);\n\n function __() {\n this.constructor = d;\n }\n\n d.prototype = b === null ? Object.create(b) : (__.prototype = b.prototype, new __());\n };\n}();\n/**\n * @module ol/control/Rotate\n */\n\n\n\n\n\n\n/**\n * @typedef {Object} Options\n * @property {string} [className=\'ol-rotate\'] CSS class name.\n * @property {string|HTMLElement} [label=\'⇧\'] Text label to use for the rotate button.\n * Instead of text, also an element (e.g. a `span` element) can be used.\n * @property {string} [tipLabel=\'Reset rotation\'] Text label to use for the rotate tip.\n * @property {string} [compassClassName=\'ol-compass\'] CSS class name for the compass.\n * @property {number} [duration=250] Animation duration in milliseconds.\n * @property {boolean} [autoHide=true] Hide the control when rotation is 0.\n * @property {function(import("../MapEvent.js").default):void} [render] Function called when the control should\n * be re-rendered. This is called in a `requestAnimationFrame` callback.\n * @property {function():void} [resetNorth] Function called when the control is clicked.\n * This will override the default `resetNorth`.\n * @property {HTMLElement|string} [target] Specify a target if you want the control to be\n * rendered outside of the map\'s viewport.\n */\n\n/**\n * @classdesc\n * A button control to reset rotation to 0.\n * To style this control use css selector `.ol-rotate`. A `.ol-hidden` css\n * selector is added to the button when the rotation is 0.\n *\n * @api\n */\n\nvar Rotate =\n/** @class */\nfunction (_super) {\n Rotate_extends(Rotate, _super);\n /**\n * @param {Options=} opt_options Rotate options.\n */\n\n\n function Rotate(opt_options) {\n var _this = this;\n\n var options = opt_options ? opt_options : {};\n _this = _super.call(this, {\n element: document.createElement(\'div\'),\n render: options.render,\n target: options.target\n }) || this;\n var className = options.className !== undefined ? options.className : \'ol-rotate\';\n var label = options.label !== undefined ? options.label : "\\u21E7";\n var compassClassName = options.compassClassName !== undefined ? options.compassClassName : \'ol-compass\';\n /**\n * @type {HTMLElement}\n * @private\n */\n\n _this.label_ = null;\n\n if (typeof label === \'string\') {\n _this.label_ = document.createElement(\'span\');\n _this.label_.className = compassClassName;\n _this.label_.textContent = label;\n } else {\n _this.label_ = label;\n\n _this.label_.classList.add(compassClassName);\n }\n\n var tipLabel = options.tipLabel ? options.tipLabel : \'Reset rotation\';\n var button = document.createElement(\'button\');\n button.className = className + \'-reset\';\n button.setAttribute(\'type\', \'button\');\n button.title = tipLabel;\n button.appendChild(_this.label_);\n button.addEventListener(EventType.CLICK, _this.handleClick_.bind(_this), false);\n var cssClasses = className + \' \' + CLASS_UNSELECTABLE + \' \' + CLASS_CONTROL;\n var element = _this.element;\n element.className = cssClasses;\n element.appendChild(button);\n _this.callResetNorth_ = options.resetNorth ? options.resetNorth : undefined;\n /**\n * @type {number}\n * @private\n */\n\n _this.duration_ = options.duration !== undefined ? options.duration : 250;\n /**\n * @type {boolean}\n * @private\n */\n\n _this.autoHide_ = options.autoHide !== undefined ? options.autoHide : true;\n /**\n * @private\n * @type {number|undefined}\n */\n\n _this.rotation_ = undefined;\n\n if (_this.autoHide_) {\n _this.element.classList.add(CLASS_HIDDEN);\n }\n\n return _this;\n }\n /**\n * @param {MouseEvent} event The event to handle\n * @private\n */\n\n\n Rotate.prototype.handleClick_ = function (event) {\n event.preventDefault();\n\n if (this.callResetNorth_ !== undefined) {\n this.callResetNorth_();\n } else {\n this.resetNorth_();\n }\n };\n /**\n * @private\n */\n\n\n Rotate.prototype.resetNorth_ = function () {\n var map = this.getMap();\n var view = map.getView();\n\n if (!view) {\n // the map does not have a view, so we can\'t act\n // upon it\n return;\n }\n\n var rotation = view.getRotation();\n\n if (rotation !== undefined) {\n if (this.duration_ > 0 && rotation % (2 * Math.PI) !== 0) {\n view.animate({\n rotation: 0,\n duration: this.duration_,\n easing: easeOut\n });\n } else {\n view.setRotation(0);\n }\n }\n };\n /**\n * Update the rotate control element.\n * @param {import("../MapEvent.js").default} mapEvent Map event.\n * @override\n */\n\n\n Rotate.prototype.render = function (mapEvent) {\n var frameState = mapEvent.frameState;\n\n if (!frameState) {\n return;\n }\n\n var rotation = frameState.viewState.rotation;\n\n if (rotation != this.rotation_) {\n var transform = \'rotate(\' + rotation + \'rad)\';\n\n if (this.autoHide_) {\n var contains = this.element.classList.contains(CLASS_HIDDEN);\n\n if (!contains && rotation === 0) {\n this.element.classList.add(CLASS_HIDDEN);\n } else if (contains && rotation !== 0) {\n this.element.classList.remove(CLASS_HIDDEN);\n }\n }\n\n this.label_.style.transform = transform;\n }\n\n this.rotation_ = rotation;\n };\n\n return Rotate;\n}(control_Control);\n\n/* harmony default export */ var control_Rotate = (Rotate);\n;// CONCATENATED MODULE: ./node_modules/ol/control/Zoom.js\nvar Zoom_extends = undefined && undefined.__extends || function () {\n var _extendStatics = function extendStatics(d, b) {\n _extendStatics = Object.setPrototypeOf || {\n __proto__: []\n } instanceof Array && function (d, b) {\n d.__proto__ = b;\n } || function (d, b) {\n for (var p in b) {\n if (Object.prototype.hasOwnProperty.call(b, p)) d[p] = b[p];\n }\n };\n\n return _extendStatics(d, b);\n };\n\n return function (d, b) {\n _extendStatics(d, b);\n\n function __() {\n this.constructor = d;\n }\n\n d.prototype = b === null ? Object.create(b) : (__.prototype = b.prototype, new __());\n };\n}();\n/**\n * @module ol/control/Zoom\n */\n\n\n\n\n\n\n/**\n * @typedef {Object} Options\n * @property {number} [duration=250] Animation duration in milliseconds.\n * @property {string} [className=\'ol-zoom\'] CSS class name.\n * @property {string} [zoomInClassName=className + \'-in\'] CSS class name for the zoom-in button.\n * @property {string} [zoomOutClassName=className + \'-out\'] CSS class name for the zoom-out button.\n * @property {string|HTMLElement} [zoomInLabel=\'+\'] Text label to use for the zoom-in\n * button. Instead of text, also an element (e.g. a `span` element) can be used.\n * @property {string|HTMLElement} [zoomOutLabel=\'-\'] Text label to use for the zoom-out button.\n * Instead of text, also an element (e.g. a `span` element) can be used.\n * @property {string} [zoomInTipLabel=\'Zoom in\'] Text label to use for the button tip.\n * @property {string} [zoomOutTipLabel=\'Zoom out\'] Text label to use for the button tip.\n * @property {number} [delta=1] The zoom delta applied on each click.\n * @property {HTMLElement|string} [target] Specify a target if you want the control to be\n * rendered outside of the map\'s viewport.\n */\n\n/**\n * @classdesc\n * A control with 2 buttons, one for zoom in and one for zoom out.\n * This control is one of the default controls of a map. To style this control\n * use css selectors `.ol-zoom-in` and `.ol-zoom-out`.\n *\n * @api\n */\n\nvar Zoom =\n/** @class */\nfunction (_super) {\n Zoom_extends(Zoom, _super);\n /**\n * @param {Options=} opt_options Zoom options.\n */\n\n\n function Zoom(opt_options) {\n var _this = this;\n\n var options = opt_options ? opt_options : {};\n _this = _super.call(this, {\n element: document.createElement(\'div\'),\n target: options.target\n }) || this;\n var className = options.className !== undefined ? options.className : \'ol-zoom\';\n var delta = options.delta !== undefined ? options.delta : 1;\n var zoomInClassName = options.zoomInClassName !== undefined ? options.zoomInClassName : className + \'-in\';\n var zoomOutClassName = options.zoomOutClassName !== undefined ? options.zoomOutClassName : className + \'-out\';\n var zoomInLabel = options.zoomInLabel !== undefined ? options.zoomInLabel : \'+\';\n var zoomOutLabel = options.zoomOutLabel !== undefined ? options.zoomOutLabel : "\\u2212";\n var zoomInTipLabel = options.zoomInTipLabel !== undefined ? options.zoomInTipLabel : \'Zoom in\';\n var zoomOutTipLabel = options.zoomOutTipLabel !== undefined ? options.zoomOutTipLabel : \'Zoom out\';\n var inElement = document.createElement(\'button\');\n inElement.className = zoomInClassName;\n inElement.setAttribute(\'type\', \'button\');\n inElement.title = zoomInTipLabel;\n inElement.appendChild(typeof zoomInLabel === \'string\' ? document.createTextNode(zoomInLabel) : zoomInLabel);\n inElement.addEventListener(EventType.CLICK, _this.handleClick_.bind(_this, delta), false);\n var outElement = document.createElement(\'button\');\n outElement.className = zoomOutClassName;\n outElement.setAttribute(\'type\', \'button\');\n outElement.title = zoomOutTipLabel;\n outElement.appendChild(typeof zoomOutLabel === \'string\' ? document.createTextNode(zoomOutLabel) : zoomOutLabel);\n outElement.addEventListener(EventType.CLICK, _this.handleClick_.bind(_this, -delta), false);\n var cssClasses = className + \' \' + CLASS_UNSELECTABLE + \' \' + CLASS_CONTROL;\n var element = _this.element;\n element.className = cssClasses;\n element.appendChild(inElement);\n element.appendChild(outElement);\n /**\n * @type {number}\n * @private\n */\n\n _this.duration_ = options.duration !== undefined ? options.duration : 250;\n return _this;\n }\n /**\n * @param {number} delta Zoom delta.\n * @param {MouseEvent} event The event to handle\n * @private\n */\n\n\n Zoom.prototype.handleClick_ = function (delta, event) {\n event.preventDefault();\n this.zoomByDelta_(delta);\n };\n /**\n * @param {number} delta Zoom delta.\n * @private\n */\n\n\n Zoom.prototype.zoomByDelta_ = function (delta) {\n var map = this.getMap();\n var view = map.getView();\n\n if (!view) {\n // the map does not have a view, so we can\'t act\n // upon it\n return;\n }\n\n var currentZoom = view.getZoom();\n\n if (currentZoom !== undefined) {\n var newZoom = view.getConstrainedZoom(currentZoom + delta);\n\n if (this.duration_ > 0) {\n if (view.getAnimating()) {\n view.cancelAnimations();\n }\n\n view.animate({\n zoom: newZoom,\n duration: this.duration_,\n easing: easeOut\n });\n } else {\n view.setZoom(newZoom);\n }\n }\n };\n\n return Zoom;\n}(control_Control);\n\n/* harmony default export */ var control_Zoom = (Zoom);\n;// CONCATENATED MODULE: ./node_modules/ol/control.js\n/**\n * @module ol/control\n */\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n/**\n * @typedef {Object} DefaultsOptions\n * @property {boolean} [attribution=true] Include\n * {@link module:ol/control/Attribution~Attribution}.\n * @property {import("./control/Attribution.js").Options} [attributionOptions]\n * Options for {@link module:ol/control/Attribution~Attribution}.\n * @property {boolean} [rotate=true] Include\n * {@link module:ol/control/Rotate~Rotate}.\n * @property {import("./control/Rotate.js").Options} [rotateOptions] Options\n * for {@link module:ol/control/Rotate~Rotate}.\n * @property {boolean} [zoom] Include {@link module:ol/control/Zoom~Zoom}.\n * @property {import("./control/Zoom.js").Options} [zoomOptions] Options for\n * {@link module:ol/control/Zoom~Zoom}.\n * @api\n */\n\n/**\n * Set of controls included in maps by default. Unless configured otherwise,\n * this returns a collection containing an instance of each of the following\n * controls:\n * * {@link module:ol/control/Zoom~Zoom}\n * * {@link module:ol/control/Rotate~Rotate}\n * * {@link module:ol/control/Attribution~Attribution}\n *\n * @param {DefaultsOptions=} opt_options\n * Defaults options.\n * @return {Collection<import("./control/Control.js").default>}\n * Controls.\n * @api\n */\n\nfunction defaults(opt_options) {\n var options = opt_options ? opt_options : {};\n var controls = new ol_Collection();\n var zoomControl = options.zoom !== undefined ? options.zoom : true;\n\n if (zoomControl) {\n controls.push(new control_Zoom(options.zoomOptions));\n }\n\n var rotateControl = options.rotate !== undefined ? options.rotate : true;\n\n if (rotateControl) {\n controls.push(new control_Rotate(options.rotateOptions));\n }\n\n var attributionControl = options.attribution !== undefined ? options.attribution : true;\n\n if (attributionControl) {\n controls.push(new control_Attribution(options.attributionOptions));\n }\n\n return controls;\n}\n;// CONCATENATED MODULE: ./node_modules/ol/interaction/Property.js\n/**\n * @module ol/interaction/Property\n */\n\n/**\n * @enum {string}\n */\n/* harmony default export */ var interaction_Property = ({\n ACTIVE: \'active\'\n});\n;// CONCATENATED MODULE: ./node_modules/ol/interaction/Interaction.js\nvar Interaction_extends = undefined && undefined.__extends || function () {\n var _extendStatics = function extendStatics(d, b) {\n _extendStatics = Object.setPrototypeOf || {\n __proto__: []\n } instanceof Array && function (d, b) {\n d.__proto__ = b;\n } || function (d, b) {\n for (var p in b) {\n if (Object.prototype.hasOwnProperty.call(b, p)) d[p] = b[p];\n }\n };\n\n return _extendStatics(d, b);\n };\n\n return function (d, b) {\n _extendStatics(d, b);\n\n function __() {\n this.constructor = d;\n }\n\n d.prototype = b === null ? Object.create(b) : (__.prototype = b.prototype, new __());\n };\n}();\n/**\n * @module ol/interaction/Interaction\n */\n\n\n\n\n\n/**\n * Object literal with config options for interactions.\n * @typedef {Object} InteractionOptions\n * @property {function(import("../MapBrowserEvent.js").default):boolean} handleEvent\n * Method called by the map to notify the interaction that a browser event was\n * dispatched to the map. If the function returns a falsy value, propagation of\n * the event to other interactions in the map\'s interactions chain will be\n * prevented (this includes functions with no explicit return). The interactions\n * are traversed in reverse order of the interactions collection of the map.\n */\n\n/**\n * @classdesc\n * Abstract base class; normally only used for creating subclasses and not\n * instantiated in apps.\n * User actions that change the state of the map. Some are similar to controls,\n * but are not associated with a DOM element.\n * For example, {@link module:ol/interaction/KeyboardZoom~KeyboardZoom} is\n * functionally the same as {@link module:ol/control/Zoom~Zoom}, but triggered\n * by a keyboard event not a button element event.\n * Although interactions do not have a DOM element, some of them do render\n * vectors and so are visible on the screen.\n * @api\n */\n\nvar Interaction =\n/** @class */\nfunction (_super) {\n Interaction_extends(Interaction, _super);\n /**\n * @param {InteractionOptions=} opt_options Options.\n */\n\n\n function Interaction(opt_options) {\n var _this = _super.call(this) || this;\n\n if (opt_options && opt_options.handleEvent) {\n _this.handleEvent = opt_options.handleEvent;\n }\n /**\n * @private\n * @type {import("../PluggableMap.js").default}\n */\n\n\n _this.map_ = null;\n\n _this.setActive(true);\n\n return _this;\n }\n /**\n * Return whether the interaction is currently active.\n * @return {boolean} `true` if the interaction is active, `false` otherwise.\n * @observable\n * @api\n */\n\n\n Interaction.prototype.getActive = function () {\n return (\n /** @type {boolean} */\n this.get(interaction_Property.ACTIVE)\n );\n };\n /**\n * Get the map associated with this interaction.\n * @return {import("../PluggableMap.js").default} Map.\n * @api\n */\n\n\n Interaction.prototype.getMap = function () {\n return this.map_;\n };\n /**\n * Handles the {@link module:ol/MapBrowserEvent map browser event}.\n * @param {import("../MapBrowserEvent.js").default} mapBrowserEvent Map browser event.\n * @return {boolean} `false` to stop event propagation.\n * @api\n */\n\n\n Interaction.prototype.handleEvent = function (mapBrowserEvent) {\n return true;\n };\n /**\n * Activate or deactivate the interaction.\n * @param {boolean} active Active.\n * @observable\n * @api\n */\n\n\n Interaction.prototype.setActive = function (active) {\n this.set(interaction_Property.ACTIVE, active);\n };\n /**\n * Remove the interaction from its current map and attach it to the new map.\n * Subclasses may set up event handlers to get notified about changes to\n * the map here.\n * @param {import("../PluggableMap.js").default} map Map.\n */\n\n\n Interaction.prototype.setMap = function (map) {\n this.map_ = map;\n };\n\n return Interaction;\n}(ol_Object);\n/**\n * @param {import("../View.js").default} view View.\n * @param {import("../coordinate.js").Coordinate} delta Delta.\n * @param {number=} opt_duration Duration.\n */\n\n\nfunction pan(view, delta, opt_duration) {\n var currentCenter = view.getCenterInternal();\n\n if (currentCenter) {\n var center = [currentCenter[0] + delta[0], currentCenter[1] + delta[1]];\n view.animateInternal({\n duration: opt_duration !== undefined ? opt_duration : 250,\n easing: linear,\n center: view.getConstrainedCenter(center)\n });\n }\n}\n/**\n * @param {import("../View.js").default} view View.\n * @param {number} delta Delta from previous zoom level.\n * @param {import("../coordinate.js").Coordinate=} opt_anchor Anchor coordinate in the user projection.\n * @param {number=} opt_duration Duration.\n */\n\nfunction zoomByDelta(view, delta, opt_anchor, opt_duration) {\n var currentZoom = view.getZoom();\n\n if (currentZoom === undefined) {\n return;\n }\n\n var newZoom = view.getConstrainedZoom(currentZoom + delta);\n var newResolution = view.getResolutionForZoom(newZoom);\n\n if (view.getAnimating()) {\n view.cancelAnimations();\n }\n\n view.animate({\n resolution: newResolution,\n anchor: opt_anchor,\n duration: opt_duration !== undefined ? opt_duration : 250,\n easing: easeOut\n });\n}\n/* harmony default export */ var interaction_Interaction = (Interaction);\n;// CONCATENATED MODULE: ./node_modules/ol/interaction/DoubleClickZoom.js\nvar DoubleClickZoom_extends = undefined && undefined.__extends || function () {\n var _extendStatics = function extendStatics(d, b) {\n _extendStatics = Object.setPrototypeOf || {\n __proto__: []\n } instanceof Array && function (d, b) {\n d.__proto__ = b;\n } || function (d, b) {\n for (var p in b) {\n if (Object.prototype.hasOwnProperty.call(b, p)) d[p] = b[p];\n }\n };\n\n return _extendStatics(d, b);\n };\n\n return function (d, b) {\n _extendStatics(d, b);\n\n function __() {\n this.constructor = d;\n }\n\n d.prototype = b === null ? Object.create(b) : (__.prototype = b.prototype, new __());\n };\n}();\n/**\n * @module ol/interaction/DoubleClickZoom\n */\n\n\n\n\n/**\n * @typedef {Object} Options\n * @property {number} [duration=250] Animation duration in milliseconds.\n * @property {number} [delta=1] The zoom delta applied on each double click.\n */\n\n/**\n * @classdesc\n * Allows the user to zoom by double-clicking on the map.\n * @api\n */\n\nvar DoubleClickZoom =\n/** @class */\nfunction (_super) {\n DoubleClickZoom_extends(DoubleClickZoom, _super);\n /**\n * @param {Options=} opt_options Options.\n */\n\n\n function DoubleClickZoom(opt_options) {\n var _this = _super.call(this) || this;\n\n var options = opt_options ? opt_options : {};\n /**\n * @private\n * @type {number}\n */\n\n _this.delta_ = options.delta ? options.delta : 1;\n /**\n * @private\n * @type {number}\n */\n\n _this.duration_ = options.duration !== undefined ? options.duration : 250;\n return _this;\n }\n /**\n * Handles the {@link module:ol/MapBrowserEvent map browser event} (if it was a\n * doubleclick) and eventually zooms the map.\n * @param {import("../MapBrowserEvent.js").default} mapBrowserEvent Map browser event.\n * @return {boolean} `false` to stop event propagation.\n */\n\n\n DoubleClickZoom.prototype.handleEvent = function (mapBrowserEvent) {\n var stopEvent = false;\n\n if (mapBrowserEvent.type == ol_MapBrowserEventType.DBLCLICK) {\n var browserEvent =\n /** @type {MouseEvent} */\n mapBrowserEvent.originalEvent;\n var map = mapBrowserEvent.map;\n var anchor = mapBrowserEvent.coordinate;\n var delta = browserEvent.shiftKey ? -this.delta_ : this.delta_;\n var view = map.getView();\n zoomByDelta(view, delta, anchor, this.duration_);\n browserEvent.preventDefault();\n stopEvent = true;\n }\n\n return !stopEvent;\n };\n\n return DoubleClickZoom;\n}(interaction_Interaction);\n\n/* harmony default export */ var interaction_DoubleClickZoom = (DoubleClickZoom);\n;// CONCATENATED MODULE: ./node_modules/ol/interaction/Pointer.js\nvar Pointer_extends = undefined && undefined.__extends || function () {\n var _extendStatics = function extendStatics(d, b) {\n _extendStatics = Object.setPrototypeOf || {\n __proto__: []\n } instanceof Array && function (d, b) {\n d.__proto__ = b;\n } || function (d, b) {\n for (var p in b) {\n if (Object.prototype.hasOwnProperty.call(b, p)) d[p] = b[p];\n }\n };\n\n return _extendStatics(d, b);\n };\n\n return function (d, b) {\n _extendStatics(d, b);\n\n function __() {\n this.constructor = d;\n }\n\n d.prototype = b === null ? Object.create(b) : (__.prototype = b.prototype, new __());\n };\n}();\n/**\n * @module ol/interaction/Pointer\n */\n\n\n\n\n\n/**\n * @typedef {Object} Options\n * @property {function(import("../MapBrowserEvent.js").default):boolean} [handleDownEvent]\n * Function handling "down" events. If the function returns `true` then a drag\n * sequence is started.\n * @property {function(import("../MapBrowserEvent.js").default):void} [handleDragEvent]\n * Function handling "drag" events. This function is called on "move" events\n * during a drag sequence.\n * @property {function(import("../MapBrowserEvent.js").default):boolean} [handleEvent]\n * Method called by the map to notify the interaction that a browser event was\n * dispatched to the map. The function may return `false` to prevent the\n * propagation of the event to other interactions in the map\'s interactions\n * chain.\n * @property {function(import("../MapBrowserEvent.js").default):void} [handleMoveEvent]\n * Function handling "move" events. This function is called on "move" events.\n * This functions is also called during a drag sequence, so during a drag\n * sequence both the `handleDragEvent` function and this function are called.\n * If `handleDownEvent` is defined and it returns true this function will not\n * be called during a drag sequence.\n * @property {function(import("../MapBrowserEvent.js").default):boolean} [handleUpEvent]\n * Function handling "up" events. If the function returns `false` then the\n * current drag sequence is stopped.\n * @property {function(boolean):boolean} [stopDown]\n * Should the down event be propagated to other interactions, or should be\n * stopped?\n */\n\n/**\n * @classdesc\n * Base class that calls user-defined functions on `down`, `move` and `up`\n * events. This class also manages "drag sequences".\n *\n * When the `handleDownEvent` user function returns `true` a drag sequence is\n * started. During a drag sequence the `handleDragEvent` user function is\n * called on `move` events. The drag sequence ends when the `handleUpEvent`\n * user function is called and returns `false`.\n * @api\n */\n\nvar PointerInteraction =\n/** @class */\nfunction (_super) {\n Pointer_extends(PointerInteraction, _super);\n /**\n * @param {Options=} opt_options Options.\n */\n\n\n function PointerInteraction(opt_options) {\n var _this = this;\n\n var options = opt_options ? opt_options : {};\n _this = _super.call(this,\n /** @type {import("./Interaction.js").InteractionOptions} */\n options) || this;\n\n if (options.handleDownEvent) {\n _this.handleDownEvent = options.handleDownEvent;\n }\n\n if (options.handleDragEvent) {\n _this.handleDragEvent = options.handleDragEvent;\n }\n\n if (options.handleMoveEvent) {\n _this.handleMoveEvent = options.handleMoveEvent;\n }\n\n if (options.handleUpEvent) {\n _this.handleUpEvent = options.handleUpEvent;\n }\n\n if (options.stopDown) {\n _this.stopDown = options.stopDown;\n }\n /**\n * @type {boolean}\n * @protected\n */\n\n\n _this.handlingDownUpSequence = false;\n /**\n * @type {!Object<string, PointerEvent>}\n * @private\n */\n\n _this.trackedPointers_ = {};\n /**\n * @type {Array<PointerEvent>}\n * @protected\n */\n\n _this.targetPointers = [];\n return _this;\n }\n /**\n * Returns the current number of pointers involved in the interaction,\n * e.g. `2` when two fingers are used.\n * @return {number} The number of pointers.\n * @api\n */\n\n\n PointerInteraction.prototype.getPointerCount = function () {\n return this.targetPointers.length;\n };\n /**\n * Handle pointer down events.\n * @param {import("../MapBrowserEvent.js").default} mapBrowserEvent Event.\n * @return {boolean} If the event was consumed.\n * @protected\n */\n\n\n PointerInteraction.prototype.handleDownEvent = function (mapBrowserEvent) {\n return false;\n };\n /**\n * Handle pointer drag events.\n * @param {import("../MapBrowserEvent.js").default} mapBrowserEvent Event.\n * @protected\n */\n\n\n PointerInteraction.prototype.handleDragEvent = function (mapBrowserEvent) {};\n /**\n * Handles the {@link module:ol/MapBrowserEvent map browser event} and may call into\n * other functions, if event sequences like e.g. \'drag\' or \'down-up\' etc. are\n * detected.\n * @param {import("../MapBrowserEvent.js").default} mapBrowserEvent Map browser event.\n * @return {boolean} `false` to stop event propagation.\n * @api\n */\n\n\n PointerInteraction.prototype.handleEvent = function (mapBrowserEvent) {\n if (!mapBrowserEvent.originalEvent) {\n return true;\n }\n\n var stopEvent = false;\n this.updateTrackedPointers_(mapBrowserEvent);\n\n if (this.handlingDownUpSequence) {\n if (mapBrowserEvent.type == ol_MapBrowserEventType.POINTERDRAG) {\n this.handleDragEvent(mapBrowserEvent); // prevent page scrolling during dragging\n\n mapBrowserEvent.originalEvent.preventDefault();\n } else if (mapBrowserEvent.type == ol_MapBrowserEventType.POINTERUP) {\n var handledUp = this.handleUpEvent(mapBrowserEvent);\n this.handlingDownUpSequence = handledUp && this.targetPointers.length > 0;\n }\n } else {\n if (mapBrowserEvent.type == ol_MapBrowserEventType.POINTERDOWN) {\n var handled = this.handleDownEvent(mapBrowserEvent);\n this.handlingDownUpSequence = handled;\n stopEvent = this.stopDown(handled);\n } else if (mapBrowserEvent.type == ol_MapBrowserEventType.POINTERMOVE) {\n this.handleMoveEvent(mapBrowserEvent);\n }\n }\n\n return !stopEvent;\n };\n /**\n * Handle pointer move events.\n * @param {import("../MapBrowserEvent.js").default} mapBrowserEvent Event.\n * @protected\n */\n\n\n PointerInteraction.prototype.handleMoveEvent = function (mapBrowserEvent) {};\n /**\n * Handle pointer up events.\n * @param {import("../MapBrowserEvent.js").default} mapBrowserEvent Event.\n * @return {boolean} If the event was consumed.\n * @protected\n */\n\n\n PointerInteraction.prototype.handleUpEvent = function (mapBrowserEvent) {\n return false;\n };\n /**\n * This function is used to determine if "down" events should be propagated\n * to other interactions or should be stopped.\n * @param {boolean} handled Was the event handled by the interaction?\n * @return {boolean} Should the `down` event be stopped?\n */\n\n\n PointerInteraction.prototype.stopDown = function (handled) {\n return handled;\n };\n /**\n * @param {import("../MapBrowserEvent.js").default} mapBrowserEvent Event.\n * @private\n */\n\n\n PointerInteraction.prototype.updateTrackedPointers_ = function (mapBrowserEvent) {\n if (isPointerDraggingEvent(mapBrowserEvent)) {\n var event_1 = mapBrowserEvent.originalEvent;\n var id = event_1.pointerId.toString();\n\n if (mapBrowserEvent.type == ol_MapBrowserEventType.POINTERUP) {\n delete this.trackedPointers_[id];\n } else if (mapBrowserEvent.type == ol_MapBrowserEventType.POINTERDOWN) {\n this.trackedPointers_[id] = event_1;\n } else if (id in this.trackedPointers_) {\n // update only when there was a pointerdown event for this pointer\n this.trackedPointers_[id] = event_1;\n }\n\n this.targetPointers = getValues(this.trackedPointers_);\n }\n };\n\n return PointerInteraction;\n}(interaction_Interaction);\n/**\n * @param {Array<PointerEvent>} pointerEvents List of events.\n * @return {import("../pixel.js").Pixel} Centroid pixel.\n */\n\n\nfunction Pointer_centroid(pointerEvents) {\n var length = pointerEvents.length;\n var clientX = 0;\n var clientY = 0;\n\n for (var i = 0; i < length; i++) {\n clientX += pointerEvents[i].clientX;\n clientY += pointerEvents[i].clientY;\n }\n\n return [clientX / length, clientY / length];\n}\n/**\n * @param {import("../MapBrowserEvent.js").default} mapBrowserEvent Event.\n * @return {boolean} Whether the event is a pointerdown, pointerdrag\n * or pointerup event.\n */\n\nfunction isPointerDraggingEvent(mapBrowserEvent) {\n var type = mapBrowserEvent.type;\n return type === ol_MapBrowserEventType.POINTERDOWN || type === ol_MapBrowserEventType.POINTERDRAG || type === ol_MapBrowserEventType.POINTERUP;\n}\n\n/* harmony default export */ var Pointer = (PointerInteraction);\n;// CONCATENATED MODULE: ./node_modules/ol/events/condition.js\n/**\n * @module ol/events/condition\n */\n\n\n\n\n/**\n * A function that takes an {@link module:ol/MapBrowserEvent} and returns a\n * `{boolean}`. If the condition is met, true should be returned.\n *\n * @typedef {function(this: ?, import("../MapBrowserEvent.js").default): boolean} Condition\n */\n\n/**\n * Creates a condition function that passes when all provided conditions pass.\n * @param {...Condition} var_args Conditions to check.\n * @return {Condition} Condition function.\n */\n\nfunction condition_all(var_args) {\n var conditions = arguments;\n /**\n * @param {import("../MapBrowserEvent.js").default} event Event.\n * @return {boolean} All conditions passed.\n */\n\n return function (event) {\n var pass = true;\n\n for (var i = 0, ii = conditions.length; i < ii; ++i) {\n pass = pass && conditions[i](event);\n\n if (!pass) {\n break;\n }\n }\n\n return pass;\n };\n}\n/**\n * Return `true` if only the alt-key is pressed, `false` otherwise (e.g. when\n * additionally the shift-key is pressed).\n *\n * @param {import("../MapBrowserEvent.js").default} mapBrowserEvent Map browser event.\n * @return {boolean} True if only the alt key is pressed.\n * @api\n */\n\nvar altKeyOnly = function altKeyOnly(mapBrowserEvent) {\n var originalEvent =\n /** @type {KeyboardEvent|MouseEvent|TouchEvent} */\n mapBrowserEvent.originalEvent;\n return originalEvent.altKey && !(originalEvent.metaKey || originalEvent.ctrlKey) && !originalEvent.shiftKey;\n};\n/**\n * Return `true` if only the alt-key and shift-key is pressed, `false` otherwise\n * (e.g. when additionally the platform-modifier-key is pressed).\n *\n * @param {import("../MapBrowserEvent.js").default} mapBrowserEvent Map browser event.\n * @return {boolean} True if only the alt and shift keys are pressed.\n * @api\n */\n\nvar altShiftKeysOnly = function altShiftKeysOnly(mapBrowserEvent) {\n var originalEvent =\n /** @type {KeyboardEvent|MouseEvent|TouchEvent} */\n mapBrowserEvent.originalEvent;\n return originalEvent.altKey && !(originalEvent.metaKey || originalEvent.ctrlKey) && originalEvent.shiftKey;\n};\n/**\n * Return `true` if the map has the focus. This condition requires a map target\n * element with a `tabindex` attribute, e.g. `<div id="map" tabindex="1">`.\n *\n * @param {import("../MapBrowserEvent.js").default} event Map browser event.\n * @return {boolean} The map has the focus.\n * @api\n */\n\nvar condition_focus = function focus(event) {\n return event.target.getTargetElement().contains(document.activeElement);\n};\n/**\n * Return `true` if the map has the focus or no \'tabindex\' attribute set.\n *\n * @param {import("../MapBrowserEvent.js").default} event Map browser event.\n * @return {boolean} The map container has the focus or no \'tabindex\' attribute.\n */\n\nvar focusWithTabindex = function focusWithTabindex(event) {\n return event.map.getTargetElement().hasAttribute(\'tabindex\') ? condition_focus(event) : true;\n};\n/**\n * Return always true.\n *\n * @param {import("../MapBrowserEvent.js").default} mapBrowserEvent Map browser event.\n * @return {boolean} True.\n * @api\n */\n\nvar always = TRUE;\n/**\n * Return `true` if the event is a `click` event, `false` otherwise.\n *\n * @param {import("../MapBrowserEvent.js").default} mapBrowserEvent Map browser event.\n * @return {boolean} True if the event is a map `click` event.\n * @api\n */\n\nvar click = function click(mapBrowserEvent) {\n return mapBrowserEvent.type == MapBrowserEventType.CLICK;\n};\n/**\n * Return `true` if the event has an "action"-producing mouse button.\n *\n * By definition, this includes left-click on windows/linux, and left-click\n * without the ctrl key on Macs.\n *\n * @param {import("../MapBrowserEvent.js").default} mapBrowserEvent Map browser event.\n * @return {boolean} The result.\n */\n\nvar mouseActionButton = function mouseActionButton(mapBrowserEvent) {\n var originalEvent =\n /** @type {MouseEvent} */\n mapBrowserEvent.originalEvent;\n return originalEvent.button == 0 && !(WEBKIT && has_MAC && originalEvent.ctrlKey);\n};\n/**\n * Return always false.\n *\n * @param {import("../MapBrowserEvent.js").default} mapBrowserEvent Map browser event.\n * @return {boolean} False.\n * @api\n */\n\nvar never = (/* unused pure expression or super */ null && (FALSE));\n/**\n * Return `true` if the browser event is a `pointermove` event, `false`\n * otherwise.\n *\n * @param {import("../MapBrowserEvent.js").default} mapBrowserEvent Map browser event.\n * @return {boolean} True if the browser event is a `pointermove` event.\n * @api\n */\n\nvar pointerMove = function pointerMove(mapBrowserEvent) {\n return mapBrowserEvent.type == \'pointermove\';\n};\n/**\n * Return `true` if the event is a map `singleclick` event, `false` otherwise.\n *\n * @param {import("../MapBrowserEvent.js").default} mapBrowserEvent Map browser event.\n * @return {boolean} True if the event is a map `singleclick` event.\n * @api\n */\n\nvar singleClick = function singleClick(mapBrowserEvent) {\n return mapBrowserEvent.type == MapBrowserEventType.SINGLECLICK;\n};\n/**\n * Return `true` if the event is a map `dblclick` event, `false` otherwise.\n *\n * @param {import("../MapBrowserEvent.js").default} mapBrowserEvent Map browser event.\n * @return {boolean} True if the event is a map `dblclick` event.\n * @api\n */\n\nvar doubleClick = function doubleClick(mapBrowserEvent) {\n return mapBrowserEvent.type == MapBrowserEventType.DBLCLICK;\n};\n/**\n * Return `true` if no modifier key (alt-, shift- or platform-modifier-key) is\n * pressed.\n *\n * @param {import("../MapBrowserEvent.js").default} mapBrowserEvent Map browser event.\n * @return {boolean} True only if there no modifier keys are pressed.\n * @api\n */\n\nvar noModifierKeys = function noModifierKeys(mapBrowserEvent) {\n var originalEvent =\n /** @type {KeyboardEvent|MouseEvent|TouchEvent} */\n mapBrowserEvent.originalEvent;\n return !originalEvent.altKey && !(originalEvent.metaKey || originalEvent.ctrlKey) && !originalEvent.shiftKey;\n};\n/**\n * Return `true` if only the platform-modifier-key (the meta-key on Mac,\n * ctrl-key otherwise) is pressed, `false` otherwise (e.g. when additionally\n * the shift-key is pressed).\n *\n * @param {import("../MapBrowserEvent.js").default} mapBrowserEvent Map browser event.\n * @return {boolean} True if only the platform modifier key is pressed.\n * @api\n */\n\nvar platformModifierKeyOnly = function platformModifierKeyOnly(mapBrowserEvent) {\n var originalEvent =\n /** @type {KeyboardEvent|MouseEvent|TouchEvent} */\n mapBrowserEvent.originalEvent;\n return !originalEvent.altKey && (MAC ? originalEvent.metaKey : originalEvent.ctrlKey) && !originalEvent.shiftKey;\n};\n/**\n * Return `true` if only the shift-key is pressed, `false` otherwise (e.g. when\n * additionally the alt-key is pressed).\n *\n * @param {import("../MapBrowserEvent.js").default} mapBrowserEvent Map browser event.\n * @return {boolean} True if only the shift key is pressed.\n * @api\n */\n\nvar shiftKeyOnly = function shiftKeyOnly(mapBrowserEvent) {\n var originalEvent =\n /** @type {KeyboardEvent|MouseEvent|TouchEvent} */\n mapBrowserEvent.originalEvent;\n return !originalEvent.altKey && !(originalEvent.metaKey || originalEvent.ctrlKey) && originalEvent.shiftKey;\n};\n/**\n * Return `true` if the target element is not editable, i.e. not a `<input>`-,\n * `<select>`- or `<textarea>`-element, `false` otherwise.\n *\n * @param {import("../MapBrowserEvent.js").default} mapBrowserEvent Map browser event.\n * @return {boolean} True only if the target element is not editable.\n * @api\n */\n\nvar targetNotEditable = function targetNotEditable(mapBrowserEvent) {\n var originalEvent =\n /** @type {KeyboardEvent|MouseEvent|TouchEvent} */\n mapBrowserEvent.originalEvent;\n var tagName =\n /** @type {Element} */\n originalEvent.target.tagName;\n return tagName !== \'INPUT\' && tagName !== \'SELECT\' && tagName !== \'TEXTAREA\';\n};\n/**\n * Return `true` if the event originates from a mouse device.\n *\n * @param {import("../MapBrowserEvent.js").default} mapBrowserEvent Map browser event.\n * @return {boolean} True if the event originates from a mouse device.\n * @api\n */\n\nvar mouseOnly = function mouseOnly(mapBrowserEvent) {\n var pointerEvent =\n /** @type {import("../MapBrowserEvent").default} */\n mapBrowserEvent.originalEvent;\n asserts_assert(pointerEvent !== undefined, 56); // mapBrowserEvent must originate from a pointer event\n // see http://www.w3.org/TR/pointerevents/#widl-PointerEvent-pointerType\n\n return pointerEvent.pointerType == \'mouse\';\n};\n/**\n * Return `true` if the event originates from a touchable device.\n *\n * @param {import("../MapBrowserEvent.js").default} mapBrowserEvent Map browser event.\n * @return {boolean} True if the event originates from a touchable device.\n * @api\n */\n\nvar touchOnly = function touchOnly(mapBrowserEvent) {\n var pointerEvt =\n /** @type {import("../MapBrowserEvent").default} */\n mapBrowserEvent.originalEvent;\n assert(pointerEvt !== undefined, 56); // mapBrowserEvent must originate from a pointer event\n // see http://www.w3.org/TR/pointerevents/#widl-PointerEvent-pointerType\n\n return pointerEvt.pointerType === \'touch\';\n};\n/**\n * Return `true` if the event originates from a digital pen.\n *\n * @param {import("../MapBrowserEvent.js").default} mapBrowserEvent Map browser event.\n * @return {boolean} True if the event originates from a digital pen.\n * @api\n */\n\nvar penOnly = function penOnly(mapBrowserEvent) {\n var pointerEvt =\n /** @type {import("../MapBrowserEvent").default} */\n mapBrowserEvent.originalEvent;\n assert(pointerEvt !== undefined, 56); // mapBrowserEvent must originate from a pointer event\n // see http://www.w3.org/TR/pointerevents/#widl-PointerEvent-pointerType\n\n return pointerEvt.pointerType === \'pen\';\n};\n/**\n * Return `true` if the event originates from a primary pointer in\n * contact with the surface or if the left mouse button is pressed.\n * See http://www.w3.org/TR/pointerevents/#button-states.\n *\n * @param {import("../MapBrowserEvent.js").default} mapBrowserEvent Map browser event.\n * @return {boolean} True if the event originates from a primary pointer.\n * @api\n */\n\nvar primaryAction = function primaryAction(mapBrowserEvent) {\n var pointerEvent =\n /** @type {import("../MapBrowserEvent").default} */\n mapBrowserEvent.originalEvent;\n asserts_assert(pointerEvent !== undefined, 56); // mapBrowserEvent must originate from a pointer event\n\n return pointerEvent.isPrimary && pointerEvent.button === 0;\n};\n;// CONCATENATED MODULE: ./node_modules/ol/interaction/DragPan.js\nvar DragPan_extends = undefined && undefined.__extends || function () {\n var _extendStatics = function extendStatics(d, b) {\n _extendStatics = Object.setPrototypeOf || {\n __proto__: []\n } instanceof Array && function (d, b) {\n d.__proto__ = b;\n } || function (d, b) {\n for (var p in b) {\n if (Object.prototype.hasOwnProperty.call(b, p)) d[p] = b[p];\n }\n };\n\n return _extendStatics(d, b);\n };\n\n return function (d, b) {\n _extendStatics(d, b);\n\n function __() {\n this.constructor = d;\n }\n\n d.prototype = b === null ? Object.create(b) : (__.prototype = b.prototype, new __());\n };\n}();\n/**\n * @module ol/interaction/DragPan\n */\n\n\n\n\n\n\n\n/**\n * @typedef {Object} Options\n * @property {import("../events/condition.js").Condition} [condition] A function that takes an {@link module:ol/MapBrowserEvent~MapBrowserEvent} and returns a boolean\n * to indicate whether that event should be handled.\n * Default is {@link module:ol/events/condition~noModifierKeys} and {@link module:ol/events/condition~primaryAction}.\n * @property {boolean} [onFocusOnly=false] When the map\'s target has a `tabindex` attribute set,\n * the interaction will only handle events when the map has the focus.\n * @property {import("../Kinetic.js").default} [kinetic] Kinetic inertia to apply to the pan.\n */\n\n/**\n * @classdesc\n * Allows the user to pan the map by dragging the map.\n * @api\n */\n\nvar DragPan =\n/** @class */\nfunction (_super) {\n DragPan_extends(DragPan, _super);\n /**\n * @param {Options=} opt_options Options.\n */\n\n\n function DragPan(opt_options) {\n var _this = _super.call(this, {\n stopDown: functions_FALSE\n }) || this;\n\n var options = opt_options ? opt_options : {};\n /**\n * @private\n * @type {import("../Kinetic.js").default|undefined}\n */\n\n _this.kinetic_ = options.kinetic;\n /**\n * @type {import("../pixel.js").Pixel}\n */\n\n _this.lastCentroid = null;\n /**\n * @type {number}\n */\n\n _this.lastPointersCount_;\n /**\n * @type {boolean}\n */\n\n _this.panning_ = false;\n var condition = options.condition ? options.condition : condition_all(noModifierKeys, primaryAction);\n /**\n * @private\n * @type {import("../events/condition.js").Condition}\n */\n\n _this.condition_ = options.onFocusOnly ? condition_all(focusWithTabindex, condition) : condition;\n /**\n * @private\n * @type {boolean}\n */\n\n _this.noKinetic_ = false;\n return _this;\n }\n /**\n * Handle pointer drag events.\n * @param {import("../MapBrowserEvent.js").default} mapBrowserEvent Event.\n */\n\n\n DragPan.prototype.handleDragEvent = function (mapBrowserEvent) {\n if (!this.panning_) {\n this.panning_ = true;\n this.getMap().getView().beginInteraction();\n }\n\n var targetPointers = this.targetPointers;\n var centroid = Pointer_centroid(targetPointers);\n\n if (targetPointers.length == this.lastPointersCount_) {\n if (this.kinetic_) {\n this.kinetic_.update(centroid[0], centroid[1]);\n }\n\n if (this.lastCentroid) {\n var delta = [this.lastCentroid[0] - centroid[0], centroid[1] - this.lastCentroid[1]];\n var map = mapBrowserEvent.map;\n var view = map.getView();\n coordinate_scale(delta, view.getResolution());\n coordinate_rotate(delta, view.getRotation());\n view.adjustCenterInternal(delta);\n }\n } else if (this.kinetic_) {\n // reset so we don\'t overestimate the kinetic energy after\n // after one finger down, tiny drag, second finger down\n this.kinetic_.begin();\n }\n\n this.lastCentroid = centroid;\n this.lastPointersCount_ = targetPointers.length;\n mapBrowserEvent.originalEvent.preventDefault();\n };\n /**\n * Handle pointer up events.\n * @param {import("../MapBrowserEvent.js").default} mapBrowserEvent Event.\n * @return {boolean} If the event was consumed.\n */\n\n\n DragPan.prototype.handleUpEvent = function (mapBrowserEvent) {\n var map = mapBrowserEvent.map;\n var view = map.getView();\n\n if (this.targetPointers.length === 0) {\n if (!this.noKinetic_ && this.kinetic_ && this.kinetic_.end()) {\n var distance = this.kinetic_.getDistance();\n var angle = this.kinetic_.getAngle();\n var center = view.getCenterInternal();\n var centerpx = map.getPixelFromCoordinateInternal(center);\n var dest = map.getCoordinateFromPixelInternal([centerpx[0] - distance * Math.cos(angle), centerpx[1] - distance * Math.sin(angle)]);\n view.animateInternal({\n center: view.getConstrainedCenter(dest),\n duration: 500,\n easing: easeOut\n });\n }\n\n if (this.panning_) {\n this.panning_ = false;\n view.endInteraction();\n }\n\n return false;\n } else {\n if (this.kinetic_) {\n // reset so we don\'t overestimate the kinetic energy after\n // after one finger up, tiny drag, second finger up\n this.kinetic_.begin();\n }\n\n this.lastCentroid = null;\n return true;\n }\n };\n /**\n * Handle pointer down events.\n * @param {import("../MapBrowserEvent.js").default} mapBrowserEvent Event.\n * @return {boolean} If the event was consumed.\n */\n\n\n DragPan.prototype.handleDownEvent = function (mapBrowserEvent) {\n if (this.targetPointers.length > 0 && this.condition_(mapBrowserEvent)) {\n var map = mapBrowserEvent.map;\n var view = map.getView();\n this.lastCentroid = null; // stop any current animation\n\n if (view.getAnimating()) {\n view.cancelAnimations();\n }\n\n if (this.kinetic_) {\n this.kinetic_.begin();\n } // No kinetic as soon as more than one pointer on the screen is\n // detected. This is to prevent nasty pans after pinch.\n\n\n this.noKinetic_ = this.targetPointers.length > 1;\n return true;\n } else {\n return false;\n }\n };\n\n return DragPan;\n}(Pointer);\n\n/* harmony default export */ var interaction_DragPan = (DragPan);\n;// CONCATENATED MODULE: ./node_modules/ol/interaction/DragRotate.js\nvar DragRotate_extends = undefined && undefined.__extends || function () {\n var _extendStatics = function extendStatics(d, b) {\n _extendStatics = Object.setPrototypeOf || {\n __proto__: []\n } instanceof Array && function (d, b) {\n d.__proto__ = b;\n } || function (d, b) {\n for (var p in b) {\n if (Object.prototype.hasOwnProperty.call(b, p)) d[p] = b[p];\n }\n };\n\n return _extendStatics(d, b);\n };\n\n return function (d, b) {\n _extendStatics(d, b);\n\n function __() {\n this.constructor = d;\n }\n\n d.prototype = b === null ? Object.create(b) : (__.prototype = b.prototype, new __());\n };\n}();\n/**\n * @module ol/interaction/DragRotate\n */\n\n\n\n\n\n\n/**\n * @typedef {Object} Options\n * @property {import("../events/condition.js").Condition} [condition] A function that takes an\n * {@link module:ol/MapBrowserEvent~MapBrowserEvent} and returns a boolean\n * to indicate whether that event should be handled.\n * Default is {@link module:ol/events/condition~altShiftKeysOnly}.\n * @property {number} [duration=250] Animation duration in milliseconds.\n */\n\n/**\n * @classdesc\n * Allows the user to rotate the map by clicking and dragging on the map,\n * normally combined with an {@link module:ol/events/condition} that limits\n * it to when the alt and shift keys are held down.\n *\n * This interaction is only supported for mouse devices.\n * @api\n */\n\nvar DragRotate =\n/** @class */\nfunction (_super) {\n DragRotate_extends(DragRotate, _super);\n /**\n * @param {Options=} opt_options Options.\n */\n\n\n function DragRotate(opt_options) {\n var _this = this;\n\n var options = opt_options ? opt_options : {};\n _this = _super.call(this, {\n stopDown: functions_FALSE\n }) || this;\n /**\n * @private\n * @type {import("../events/condition.js").Condition}\n */\n\n _this.condition_ = options.condition ? options.condition : altShiftKeysOnly;\n /**\n * @private\n * @type {number|undefined}\n */\n\n _this.lastAngle_ = undefined;\n /**\n * @private\n * @type {number}\n */\n\n _this.duration_ = options.duration !== undefined ? options.duration : 250;\n return _this;\n }\n /**\n * Handle pointer drag events.\n * @param {import("../MapBrowserEvent.js").default} mapBrowserEvent Event.\n */\n\n\n DragRotate.prototype.handleDragEvent = function (mapBrowserEvent) {\n if (!mouseOnly(mapBrowserEvent)) {\n return;\n }\n\n var map = mapBrowserEvent.map;\n var view = map.getView();\n\n if (view.getConstraints().rotation === disable) {\n return;\n }\n\n var size = map.getSize();\n var offset = mapBrowserEvent.pixel;\n var theta = Math.atan2(size[1] / 2 - offset[1], offset[0] - size[0] / 2);\n\n if (this.lastAngle_ !== undefined) {\n var delta = theta - this.lastAngle_;\n view.adjustRotationInternal(-delta);\n }\n\n this.lastAngle_ = theta;\n };\n /**\n * Handle pointer up events.\n * @param {import("../MapBrowserEvent.js").default} mapBrowserEvent Event.\n * @return {boolean} If the event was consumed.\n */\n\n\n DragRotate.prototype.handleUpEvent = function (mapBrowserEvent) {\n if (!mouseOnly(mapBrowserEvent)) {\n return true;\n }\n\n var map = mapBrowserEvent.map;\n var view = map.getView();\n view.endInteraction(this.duration_);\n return false;\n };\n /**\n * Handle pointer down events.\n * @param {import("../MapBrowserEvent.js").default} mapBrowserEvent Event.\n * @return {boolean} If the event was consumed.\n */\n\n\n DragRotate.prototype.handleDownEvent = function (mapBrowserEvent) {\n if (!mouseOnly(mapBrowserEvent)) {\n return false;\n }\n\n if (mouseActionButton(mapBrowserEvent) && this.condition_(mapBrowserEvent)) {\n var map = mapBrowserEvent.map;\n map.getView().beginInteraction();\n this.lastAngle_ = undefined;\n return true;\n } else {\n return false;\n }\n };\n\n return DragRotate;\n}(Pointer);\n\n/* harmony default export */ var interaction_DragRotate = (DragRotate);\n;// CONCATENATED MODULE: ./node_modules/ol/render/Box.js\n/**\n * @module ol/render/Box\n */\nvar Box_extends = undefined && undefined.__extends || function () {\n var _extendStatics = function extendStatics(d, b) {\n _extendStatics = Object.setPrototypeOf || {\n __proto__: []\n } instanceof Array && function (d, b) {\n d.__proto__ = b;\n } || function (d, b) {\n for (var p in b) {\n if (Object.prototype.hasOwnProperty.call(b, p)) d[p] = b[p];\n }\n };\n\n return _extendStatics(d, b);\n };\n\n return function (d, b) {\n _extendStatics(d, b);\n\n function __() {\n this.constructor = d;\n }\n\n d.prototype = b === null ? Object.create(b) : (__.prototype = b.prototype, new __());\n };\n}();\n\n\n\n\nvar RenderBox =\n/** @class */\nfunction (_super) {\n Box_extends(RenderBox, _super);\n /**\n * @param {string} className CSS class name.\n */\n\n\n function RenderBox(className) {\n var _this = _super.call(this) || this;\n /**\n * @type {import("../geom/Polygon.js").default}\n * @private\n */\n\n\n _this.geometry_ = null;\n /**\n * @type {HTMLDivElement}\n * @private\n */\n\n _this.element_ = document.createElement(\'div\');\n _this.element_.style.position = \'absolute\';\n _this.element_.style.pointerEvents = \'auto\';\n _this.element_.className = \'ol-box \' + className;\n /**\n * @private\n * @type {import("../PluggableMap.js").default}\n */\n\n _this.map_ = null;\n /**\n * @private\n * @type {import("../pixel.js").Pixel}\n */\n\n _this.startPixel_ = null;\n /**\n * @private\n * @type {import("../pixel.js").Pixel}\n */\n\n _this.endPixel_ = null;\n return _this;\n }\n /**\n * Clean up.\n */\n\n\n RenderBox.prototype.disposeInternal = function () {\n this.setMap(null);\n };\n /**\n * @private\n */\n\n\n RenderBox.prototype.render_ = function () {\n var startPixel = this.startPixel_;\n var endPixel = this.endPixel_;\n var px = \'px\';\n var style = this.element_.style;\n style.left = Math.min(startPixel[0], endPixel[0]) + px;\n style.top = Math.min(startPixel[1], endPixel[1]) + px;\n style.width = Math.abs(endPixel[0] - startPixel[0]) + px;\n style.height = Math.abs(endPixel[1] - startPixel[1]) + px;\n };\n /**\n * @param {import("../PluggableMap.js").default} map Map.\n */\n\n\n RenderBox.prototype.setMap = function (map) {\n if (this.map_) {\n this.map_.getOverlayContainer().removeChild(this.element_);\n var style = this.element_.style;\n style.left = \'inherit\';\n style.top = \'inherit\';\n style.width = \'inherit\';\n style.height = \'inherit\';\n }\n\n this.map_ = map;\n\n if (this.map_) {\n this.map_.getOverlayContainer().appendChild(this.element_);\n }\n };\n /**\n * @param {import("../pixel.js").Pixel} startPixel Start pixel.\n * @param {import("../pixel.js").Pixel} endPixel End pixel.\n */\n\n\n RenderBox.prototype.setPixels = function (startPixel, endPixel) {\n this.startPixel_ = startPixel;\n this.endPixel_ = endPixel;\n this.createOrUpdateGeometry();\n this.render_();\n };\n /**\n * Creates or updates the cached geometry.\n */\n\n\n RenderBox.prototype.createOrUpdateGeometry = function () {\n var startPixel = this.startPixel_;\n var endPixel = this.endPixel_;\n var pixels = [startPixel, [startPixel[0], endPixel[1]], endPixel, [endPixel[0], startPixel[1]]];\n var coordinates = pixels.map(this.map_.getCoordinateFromPixelInternal, this.map_); // close the polygon\n\n coordinates[4] = coordinates[0].slice();\n\n if (!this.geometry_) {\n this.geometry_ = new geom_Polygon([coordinates]);\n } else {\n this.geometry_.setCoordinates([coordinates]);\n }\n };\n /**\n * @return {import("../geom/Polygon.js").default} Geometry.\n */\n\n\n RenderBox.prototype.getGeometry = function () {\n return this.geometry_;\n };\n\n return RenderBox;\n}(ol_Disposable);\n\n/* harmony default export */ var Box = (RenderBox);\n;// CONCATENATED MODULE: ./node_modules/ol/interaction/DragBox.js\nvar DragBox_extends = undefined && undefined.__extends || function () {\n var _extendStatics = function extendStatics(d, b) {\n _extendStatics = Object.setPrototypeOf || {\n __proto__: []\n } instanceof Array && function (d, b) {\n d.__proto__ = b;\n } || function (d, b) {\n for (var p in b) {\n if (Object.prototype.hasOwnProperty.call(b, p)) d[p] = b[p];\n }\n };\n\n return _extendStatics(d, b);\n };\n\n return function (d, b) {\n _extendStatics(d, b);\n\n function __() {\n this.constructor = d;\n }\n\n d.prototype = b === null ? Object.create(b) : (__.prototype = b.prototype, new __());\n };\n}();\n/**\n * @module ol/interaction/DragBox\n */\n// FIXME draw drag box\n\n\n\n\n\n\n/**\n * A function that takes a {@link module:ol/MapBrowserEvent} and two\n * {@link module:ol/pixel~Pixel}s and returns a `{boolean}`. If the condition is met,\n * true should be returned.\n * @typedef {function(this: ?, import("../MapBrowserEvent.js").default, import("../pixel.js").Pixel, import("../pixel.js").Pixel):boolean} EndCondition\n */\n\n/**\n * @typedef {Object} Options\n * @property {string} [className=\'ol-dragbox\'] CSS class name for styling the box.\n * @property {import("../events/condition.js").Condition} [condition] A function that takes an {@link module:ol/MapBrowserEvent~MapBrowserEvent} and returns a boolean\n * to indicate whether that event should be handled.\n * Default is {@link ol/events/condition~mouseActionButton}.\n * @property {number} [minArea=64] The minimum area of the box in pixel, this value is used by the default\n * `boxEndCondition` function.\n * @property {EndCondition} [boxEndCondition] A function that takes a {@link module:ol/MapBrowserEvent~MapBrowserEvent} and two\n * {@link module:ol/pixel~Pixel}s to indicate whether a `boxend` event should be fired.\n * Default is `true` if the area of the box is bigger than the `minArea` option.\n * @property {function(this:DragBox, import("../MapBrowserEvent.js").default):void} [onBoxEnd] Code to execute just\n * before `boxend` is fired.\n */\n\n/**\n * @enum {string}\n */\n\nvar DragBoxEventType = {\n /**\n * Triggered upon drag box start.\n * @event DragBoxEvent#boxstart\n * @api\n */\n BOXSTART: \'boxstart\',\n\n /**\n * Triggered on drag when box is active.\n * @event DragBoxEvent#boxdrag\n * @api\n */\n BOXDRAG: \'boxdrag\',\n\n /**\n * Triggered upon drag box end.\n * @event DragBoxEvent#boxend\n * @api\n */\n BOXEND: \'boxend\',\n\n /**\n * Triggered upon drag box canceled.\n * @event DragBoxEvent#boxcancel\n * @api\n */\n BOXCANCEL: \'boxcancel\'\n};\n/**\n * @classdesc\n * Events emitted by {@link module:ol/interaction/DragBox~DragBox} instances are instances of\n * this type.\n */\n\nvar DragBoxEvent =\n/** @class */\nfunction (_super) {\n DragBox_extends(DragBoxEvent, _super);\n /**\n * @param {string} type The event type.\n * @param {import("../coordinate.js").Coordinate} coordinate The event coordinate.\n * @param {import("../MapBrowserEvent.js").default} mapBrowserEvent Originating event.\n */\n\n\n function DragBoxEvent(type, coordinate, mapBrowserEvent) {\n var _this = _super.call(this, type) || this;\n /**\n * The coordinate of the drag event.\n * @const\n * @type {import("../coordinate.js").Coordinate}\n * @api\n */\n\n\n _this.coordinate = coordinate;\n /**\n * @const\n * @type {import("../MapBrowserEvent.js").default}\n * @api\n */\n\n _this.mapBrowserEvent = mapBrowserEvent;\n return _this;\n }\n\n return DragBoxEvent;\n}(Event);\n\n\n/**\n * @classdesc\n * Allows the user to draw a vector box by clicking and dragging on the map,\n * normally combined with an {@link module:ol/events/condition} that limits\n * it to when the shift or other key is held down. This is used, for example,\n * for zooming to a specific area of the map\n * (see {@link module:ol/interaction/DragZoom~DragZoom} and\n * {@link module:ol/interaction/DragRotateAndZoom}).\n *\n * @fires DragBoxEvent\n * @api\n */\n\nvar DragBox =\n/** @class */\nfunction (_super) {\n DragBox_extends(DragBox, _super);\n /**\n * @param {Options=} opt_options Options.\n */\n\n\n function DragBox(opt_options) {\n var _this = _super.call(this) || this;\n\n var options = opt_options ? opt_options : {};\n /**\n * @type {import("../render/Box.js").default}\n * @private\n */\n\n _this.box_ = new Box(options.className || \'ol-dragbox\');\n /**\n * @type {number}\n * @private\n */\n\n _this.minArea_ = options.minArea !== undefined ? options.minArea : 64;\n\n if (options.onBoxEnd) {\n _this.onBoxEnd = options.onBoxEnd;\n }\n /**\n * @type {import("../pixel.js").Pixel}\n * @private\n */\n\n\n _this.startPixel_ = null;\n /**\n * @private\n * @type {import("../events/condition.js").Condition}\n */\n\n _this.condition_ = options.condition ? options.condition : mouseActionButton;\n /**\n * @private\n * @type {EndCondition}\n */\n\n _this.boxEndCondition_ = options.boxEndCondition ? options.boxEndCondition : _this.defaultBoxEndCondition;\n return _this;\n }\n /**\n * The default condition for determining whether the boxend event\n * should fire.\n * @param {import("../MapBrowserEvent.js").default} mapBrowserEvent The originating MapBrowserEvent\n * leading to the box end.\n * @param {import("../pixel.js").Pixel} startPixel The starting pixel of the box.\n * @param {import("../pixel.js").Pixel} endPixel The end pixel of the box.\n * @return {boolean} Whether or not the boxend condition should be fired.\n */\n\n\n DragBox.prototype.defaultBoxEndCondition = function (mapBrowserEvent, startPixel, endPixel) {\n var width = endPixel[0] - startPixel[0];\n var height = endPixel[1] - startPixel[1];\n return width * width + height * height >= this.minArea_;\n };\n /**\n * Returns geometry of last drawn box.\n * @return {import("../geom/Polygon.js").default} Geometry.\n * @api\n */\n\n\n DragBox.prototype.getGeometry = function () {\n return this.box_.getGeometry();\n };\n /**\n * Handle pointer drag events.\n * @param {import("../MapBrowserEvent.js").default} mapBrowserEvent Event.\n */\n\n\n DragBox.prototype.handleDragEvent = function (mapBrowserEvent) {\n this.box_.setPixels(this.startPixel_, mapBrowserEvent.pixel);\n this.dispatchEvent(new DragBoxEvent(DragBoxEventType.BOXDRAG, mapBrowserEvent.coordinate, mapBrowserEvent));\n };\n /**\n * Handle pointer up events.\n * @param {import("../MapBrowserEvent.js").default} mapBrowserEvent Event.\n * @return {boolean} If the event was consumed.\n */\n\n\n DragBox.prototype.handleUpEvent = function (mapBrowserEvent) {\n this.box_.setMap(null);\n var completeBox = this.boxEndCondition_(mapBrowserEvent, this.startPixel_, mapBrowserEvent.pixel);\n\n if (completeBox) {\n this.onBoxEnd(mapBrowserEvent);\n }\n\n this.dispatchEvent(new DragBoxEvent(completeBox ? DragBoxEventType.BOXEND : DragBoxEventType.BOXCANCEL, mapBrowserEvent.coordinate, mapBrowserEvent));\n return false;\n };\n /**\n * Handle pointer down events.\n * @param {import("../MapBrowserEvent.js").default} mapBrowserEvent Event.\n * @return {boolean} If the event was consumed.\n */\n\n\n DragBox.prototype.handleDownEvent = function (mapBrowserEvent) {\n if (this.condition_(mapBrowserEvent)) {\n this.startPixel_ = mapBrowserEvent.pixel;\n this.box_.setMap(mapBrowserEvent.map);\n this.box_.setPixels(this.startPixel_, this.startPixel_);\n this.dispatchEvent(new DragBoxEvent(DragBoxEventType.BOXSTART, mapBrowserEvent.coordinate, mapBrowserEvent));\n return true;\n } else {\n return false;\n }\n };\n /**\n * Function to execute just before `onboxend` is fired\n * @param {import("../MapBrowserEvent.js").default} event Event.\n */\n\n\n DragBox.prototype.onBoxEnd = function (event) {};\n\n return DragBox;\n}(Pointer);\n\n/* harmony default export */ var interaction_DragBox = (DragBox);\n;// CONCATENATED MODULE: ./node_modules/ol/interaction/DragZoom.js\nvar DragZoom_extends = undefined && undefined.__extends || function () {\n var _extendStatics = function extendStatics(d, b) {\n _extendStatics = Object.setPrototypeOf || {\n __proto__: []\n } instanceof Array && function (d, b) {\n d.__proto__ = b;\n } || function (d, b) {\n for (var p in b) {\n if (Object.prototype.hasOwnProperty.call(b, p)) d[p] = b[p];\n }\n };\n\n return _extendStatics(d, b);\n };\n\n return function (d, b) {\n _extendStatics(d, b);\n\n function __() {\n this.constructor = d;\n }\n\n d.prototype = b === null ? Object.create(b) : (__.prototype = b.prototype, new __());\n };\n}();\n/**\n * @module ol/interaction/DragZoom\n */\n\n\n\n\n\n\n/**\n * @typedef {Object} Options\n * @property {string} [className=\'ol-dragzoom\'] CSS class name for styling the\n * box.\n * @property {import("../events/condition.js").Condition} [condition] A function that\n * takes an {@link module:ol/MapBrowserEvent~MapBrowserEvent} and returns a\n * boolean to indicate whether that event should be handled.\n * Default is {@link module:ol/events/condition~shiftKeyOnly}.\n * @property {number} [duration=200] Animation duration in milliseconds.\n * @property {boolean} [out=false] Use interaction for zooming out.\n * @property {number} [minArea=64] The minimum area of the box in pixel, this value is used by the parent default\n * `boxEndCondition` function.\n */\n\n/**\n * @classdesc\n * Allows the user to zoom the map by clicking and dragging on the map,\n * normally combined with an {@link module:ol/events/condition} that limits\n * it to when a key, shift by default, is held down.\n *\n * To change the style of the box, use CSS and the `.ol-dragzoom` selector, or\n * your custom one configured with `className`.\n * @api\n */\n\nvar DragZoom =\n/** @class */\nfunction (_super) {\n DragZoom_extends(DragZoom, _super);\n /**\n * @param {Options=} opt_options Options.\n */\n\n\n function DragZoom(opt_options) {\n var _this = this;\n\n var options = opt_options ? opt_options : {};\n var condition = options.condition ? options.condition : shiftKeyOnly;\n _this = _super.call(this, {\n condition: condition,\n className: options.className || \'ol-dragzoom\',\n minArea: options.minArea\n }) || this;\n /**\n * @private\n * @type {number}\n */\n\n _this.duration_ = options.duration !== undefined ? options.duration : 200;\n /**\n * @private\n * @type {boolean}\n */\n\n _this.out_ = options.out !== undefined ? options.out : false;\n return _this;\n }\n /**\n * Function to execute just before `onboxend` is fired\n * @param {import("../MapBrowserEvent.js").default} event Event.\n */\n\n\n DragZoom.prototype.onBoxEnd = function (event) {\n var map = this.getMap();\n var view =\n /** @type {!import("../View.js").default} */\n map.getView();\n var size =\n /** @type {!import("../size.js").Size} */\n map.getSize();\n var extent = this.getGeometry().getExtent();\n\n if (this.out_) {\n var mapExtent = view.calculateExtentInternal(size);\n var boxPixelExtent = createOrUpdateFromCoordinates([map.getPixelFromCoordinateInternal(getBottomLeft(extent)), map.getPixelFromCoordinateInternal(getTopRight(extent))]);\n var factor = view.getResolutionForExtentInternal(boxPixelExtent, size);\n scaleFromCenter(mapExtent, 1 / factor);\n extent = mapExtent;\n }\n\n var resolution = view.getConstrainedResolution(view.getResolutionForExtentInternal(extent, size));\n var center = view.getConstrainedCenter(getCenter(extent), resolution);\n view.animateInternal({\n resolution: resolution,\n center: center,\n duration: this.duration_,\n easing: easeOut\n });\n };\n\n return DragZoom;\n}(interaction_DragBox);\n\n/* harmony default export */ var interaction_DragZoom = (DragZoom);\n;// CONCATENATED MODULE: ./node_modules/ol/events/KeyCode.js\n/**\n * @module ol/events/KeyCode\n */\n\n/**\n * @enum {number}\n * @const\n */\n/* harmony default export */ var KeyCode = ({\n LEFT: 37,\n UP: 38,\n RIGHT: 39,\n DOWN: 40\n});\n;// CONCATENATED MODULE: ./node_modules/ol/interaction/KeyboardPan.js\nvar KeyboardPan_extends = undefined && undefined.__extends || function () {\n var _extendStatics = function extendStatics(d, b) {\n _extendStatics = Object.setPrototypeOf || {\n __proto__: []\n } instanceof Array && function (d, b) {\n d.__proto__ = b;\n } || function (d, b) {\n for (var p in b) {\n if (Object.prototype.hasOwnProperty.call(b, p)) d[p] = b[p];\n }\n };\n\n return _extendStatics(d, b);\n };\n\n return function (d, b) {\n _extendStatics(d, b);\n\n function __() {\n this.constructor = d;\n }\n\n d.prototype = b === null ? Object.create(b) : (__.prototype = b.prototype, new __());\n };\n}();\n/**\n * @module ol/interaction/KeyboardPan\n */\n\n\n\n\n\n\n\n/**\n * @typedef {Object} Options\n * @property {import("../events/condition.js").Condition} [condition] A function that\n * takes an {@link module:ol/MapBrowserEvent~MapBrowserEvent} and returns a\n * boolean to indicate whether that event should be handled. Default is\n * {@link module:ol/events/condition~noModifierKeys} and\n * {@link module:ol/events/condition~targetNotEditable}.\n * @property {number} [duration=100] Animation duration in milliseconds.\n * @property {number} [pixelDelta=128] The amount of pixels to pan on each key\n * press.\n */\n\n/**\n * @classdesc\n * Allows the user to pan the map using keyboard arrows.\n * Note that, although this interaction is by default included in maps,\n * the keys can only be used when browser focus is on the element to which\n * the keyboard events are attached. By default, this is the map div,\n * though you can change this with the `keyboardEventTarget` in\n * {@link module:ol/Map~Map}. `document` never loses focus but, for any other\n * element, focus will have to be on, and returned to, this element if the keys\n * are to function.\n * See also {@link module:ol/interaction/KeyboardZoom~KeyboardZoom}.\n * @api\n */\n\nvar KeyboardPan =\n/** @class */\nfunction (_super) {\n KeyboardPan_extends(KeyboardPan, _super);\n /**\n * @param {Options=} opt_options Options.\n */\n\n\n function KeyboardPan(opt_options) {\n var _this = _super.call(this) || this;\n\n var options = opt_options || {};\n /**\n * @private\n * @param {import("../MapBrowserEvent.js").default} mapBrowserEvent Browser event.\n * @return {boolean} Combined condition result.\n */\n\n _this.defaultCondition_ = function (mapBrowserEvent) {\n return noModifierKeys(mapBrowserEvent) && targetNotEditable(mapBrowserEvent);\n };\n /**\n * @private\n * @type {import("../events/condition.js").Condition}\n */\n\n\n _this.condition_ = options.condition !== undefined ? options.condition : _this.defaultCondition_;\n /**\n * @private\n * @type {number}\n */\n\n _this.duration_ = options.duration !== undefined ? options.duration : 100;\n /**\n * @private\n * @type {number}\n */\n\n _this.pixelDelta_ = options.pixelDelta !== undefined ? options.pixelDelta : 128;\n return _this;\n }\n /**\n * Handles the {@link module:ol/MapBrowserEvent map browser event} if it was a\n * `KeyEvent`, and decides the direction to pan to (if an arrow key was\n * pressed).\n * @param {import("../MapBrowserEvent.js").default} mapBrowserEvent Map browser event.\n * @return {boolean} `false` to stop event propagation.\n * @this {KeyboardPan}\n */\n\n\n KeyboardPan.prototype.handleEvent = function (mapBrowserEvent) {\n var stopEvent = false;\n\n if (mapBrowserEvent.type == EventType.KEYDOWN) {\n var keyEvent =\n /** @type {KeyboardEvent} */\n mapBrowserEvent.originalEvent;\n var keyCode = keyEvent.keyCode;\n\n if (this.condition_(mapBrowserEvent) && (keyCode == KeyCode.DOWN || keyCode == KeyCode.LEFT || keyCode == KeyCode.RIGHT || keyCode == KeyCode.UP)) {\n var map = mapBrowserEvent.map;\n var view = map.getView();\n var mapUnitsDelta = view.getResolution() * this.pixelDelta_;\n var deltaX = 0,\n deltaY = 0;\n\n if (keyCode == KeyCode.DOWN) {\n deltaY = -mapUnitsDelta;\n } else if (keyCode == KeyCode.LEFT) {\n deltaX = -mapUnitsDelta;\n } else if (keyCode == KeyCode.RIGHT) {\n deltaX = mapUnitsDelta;\n } else {\n deltaY = mapUnitsDelta;\n }\n\n var delta = [deltaX, deltaY];\n coordinate_rotate(delta, view.getRotation());\n pan(view, delta, this.duration_);\n keyEvent.preventDefault();\n stopEvent = true;\n }\n }\n\n return !stopEvent;\n };\n\n return KeyboardPan;\n}(interaction_Interaction);\n\n/* harmony default export */ var interaction_KeyboardPan = (KeyboardPan);\n;// CONCATENATED MODULE: ./node_modules/ol/interaction/KeyboardZoom.js\nvar KeyboardZoom_extends = undefined && undefined.__extends || function () {\n var _extendStatics = function extendStatics(d, b) {\n _extendStatics = Object.setPrototypeOf || {\n __proto__: []\n } instanceof Array && function (d, b) {\n d.__proto__ = b;\n } || function (d, b) {\n for (var p in b) {\n if (Object.prototype.hasOwnProperty.call(b, p)) d[p] = b[p];\n }\n };\n\n return _extendStatics(d, b);\n };\n\n return function (d, b) {\n _extendStatics(d, b);\n\n function __() {\n this.constructor = d;\n }\n\n d.prototype = b === null ? Object.create(b) : (__.prototype = b.prototype, new __());\n };\n}();\n/**\n * @module ol/interaction/KeyboardZoom\n */\n\n\n\n\n\n/**\n * @typedef {Object} Options\n * @property {number} [duration=100] Animation duration in milliseconds.\n * @property {import("../events/condition.js").Condition} [condition] A function that\n * takes an {@link module:ol/MapBrowserEvent~MapBrowserEvent} and returns a\n * boolean to indicate whether that event should be handled. Default is\n * {@link module:ol/events/condition~targetNotEditable}.\n * @property {number} [delta=1] The zoom level delta on each key press.\n */\n\n/**\n * @classdesc\n * Allows the user to zoom the map using keyboard + and -.\n * Note that, although this interaction is by default included in maps,\n * the keys can only be used when browser focus is on the element to which\n * the keyboard events are attached. By default, this is the map div,\n * though you can change this with the `keyboardEventTarget` in\n * {@link module:ol/Map~Map}. `document` never loses focus but, for any other\n * element, focus will have to be on, and returned to, this element if the keys\n * are to function.\n * See also {@link module:ol/interaction/KeyboardPan~KeyboardPan}.\n * @api\n */\n\nvar KeyboardZoom =\n/** @class */\nfunction (_super) {\n KeyboardZoom_extends(KeyboardZoom, _super);\n /**\n * @param {Options=} opt_options Options.\n */\n\n\n function KeyboardZoom(opt_options) {\n var _this = _super.call(this) || this;\n\n var options = opt_options ? opt_options : {};\n /**\n * @private\n * @type {import("../events/condition.js").Condition}\n */\n\n _this.condition_ = options.condition ? options.condition : targetNotEditable;\n /**\n * @private\n * @type {number}\n */\n\n _this.delta_ = options.delta ? options.delta : 1;\n /**\n * @private\n * @type {number}\n */\n\n _this.duration_ = options.duration !== undefined ? options.duration : 100;\n return _this;\n }\n /**\n * Handles the {@link module:ol/MapBrowserEvent map browser event} if it was a\n * `KeyEvent`, and decides whether to zoom in or out (depending on whether the\n * key pressed was \'+\' or \'-\').\n * @param {import("../MapBrowserEvent.js").default} mapBrowserEvent Map browser event.\n * @return {boolean} `false` to stop event propagation.\n * @this {KeyboardZoom}\n */\n\n\n KeyboardZoom.prototype.handleEvent = function (mapBrowserEvent) {\n var stopEvent = false;\n\n if (mapBrowserEvent.type == EventType.KEYDOWN || mapBrowserEvent.type == EventType.KEYPRESS) {\n var keyEvent =\n /** @type {KeyboardEvent} */\n mapBrowserEvent.originalEvent;\n var charCode = keyEvent.charCode;\n\n if (this.condition_(mapBrowserEvent) && (charCode == \'+\'.charCodeAt(0) || charCode == \'-\'.charCodeAt(0))) {\n var map = mapBrowserEvent.map;\n var delta = charCode == \'+\'.charCodeAt(0) ? this.delta_ : -this.delta_;\n var view = map.getView();\n zoomByDelta(view, delta, undefined, this.duration_);\n keyEvent.preventDefault();\n stopEvent = true;\n }\n }\n\n return !stopEvent;\n };\n\n return KeyboardZoom;\n}(interaction_Interaction);\n\n/* harmony default export */ var interaction_KeyboardZoom = (KeyboardZoom);\n;// CONCATENATED MODULE: ./node_modules/ol/Kinetic.js\n/**\n * @module ol/Kinetic\n */\n\n/**\n * @classdesc\n * Implementation of inertial deceleration for map movement.\n *\n * @api\n */\nvar Kinetic =\n/** @class */\nfunction () {\n /**\n * @param {number} decay Rate of decay (must be negative).\n * @param {number} minVelocity Minimum velocity (pixels/millisecond).\n * @param {number} delay Delay to consider to calculate the kinetic\n * initial values (milliseconds).\n */\n function Kinetic(decay, minVelocity, delay) {\n /**\n * @private\n * @type {number}\n */\n this.decay_ = decay;\n /**\n * @private\n * @type {number}\n */\n\n this.minVelocity_ = minVelocity;\n /**\n * @private\n * @type {number}\n */\n\n this.delay_ = delay;\n /**\n * @private\n * @type {Array<number>}\n */\n\n this.points_ = [];\n /**\n * @private\n * @type {number}\n */\n\n this.angle_ = 0;\n /**\n * @private\n * @type {number}\n */\n\n this.initialVelocity_ = 0;\n }\n /**\n * FIXME empty description for jsdoc\n */\n\n\n Kinetic.prototype.begin = function () {\n this.points_.length = 0;\n this.angle_ = 0;\n this.initialVelocity_ = 0;\n };\n /**\n * @param {number} x X.\n * @param {number} y Y.\n */\n\n\n Kinetic.prototype.update = function (x, y) {\n this.points_.push(x, y, Date.now());\n };\n /**\n * @return {boolean} Whether we should do kinetic animation.\n */\n\n\n Kinetic.prototype.end = function () {\n if (this.points_.length < 6) {\n // at least 2 points are required (i.e. there must be at least 6 elements\n // in the array)\n return false;\n }\n\n var delay = Date.now() - this.delay_;\n var lastIndex = this.points_.length - 3;\n\n if (this.points_[lastIndex + 2] < delay) {\n // the last tracked point is too old, which means that the user stopped\n // panning before releasing the map\n return false;\n } // get the first point which still falls into the delay time\n\n\n var firstIndex = lastIndex - 3;\n\n while (firstIndex > 0 && this.points_[firstIndex + 2] > delay) {\n firstIndex -= 3;\n }\n\n var duration = this.points_[lastIndex + 2] - this.points_[firstIndex + 2]; // we don\'t want a duration of 0 (divide by zero)\n // we also make sure the user panned for a duration of at least one frame\n // (1/60s) to compute sane displacement values\n\n if (duration < 1000 / 60) {\n return false;\n }\n\n var dx = this.points_[lastIndex] - this.points_[firstIndex];\n var dy = this.points_[lastIndex + 1] - this.points_[firstIndex + 1];\n this.angle_ = Math.atan2(dy, dx);\n this.initialVelocity_ = Math.sqrt(dx * dx + dy * dy) / duration;\n return this.initialVelocity_ > this.minVelocity_;\n };\n /**\n * @return {number} Total distance travelled (pixels).\n */\n\n\n Kinetic.prototype.getDistance = function () {\n return (this.minVelocity_ - this.initialVelocity_) / this.decay_;\n };\n /**\n * @return {number} Angle of the kinetic panning animation (radians).\n */\n\n\n Kinetic.prototype.getAngle = function () {\n return this.angle_;\n };\n\n return Kinetic;\n}();\n\n/* harmony default export */ var ol_Kinetic = (Kinetic);\n;// CONCATENATED MODULE: ./node_modules/ol/interaction/MouseWheelZoom.js\nvar MouseWheelZoom_extends = undefined && undefined.__extends || function () {\n var _extendStatics = function extendStatics(d, b) {\n _extendStatics = Object.setPrototypeOf || {\n __proto__: []\n } instanceof Array && function (d, b) {\n d.__proto__ = b;\n } || function (d, b) {\n for (var p in b) {\n if (Object.prototype.hasOwnProperty.call(b, p)) d[p] = b[p];\n }\n };\n\n return _extendStatics(d, b);\n };\n\n return function (d, b) {\n _extendStatics(d, b);\n\n function __() {\n this.constructor = d;\n }\n\n d.prototype = b === null ? Object.create(b) : (__.prototype = b.prototype, new __());\n };\n}();\n/**\n * @module ol/interaction/MouseWheelZoom\n */\n\n\n\n\n\n\n\n/**\n * @enum {string}\n */\n\nvar Mode = {\n TRACKPAD: \'trackpad\',\n WHEEL: \'wheel\'\n};\n/**\n * @typedef {Object} Options\n * @property {import("../events/condition.js").Condition} [condition] A function that\n * takes an {@link module:ol/MapBrowserEvent~MapBrowserEvent} and returns a\n * boolean to indicate whether that event should be handled. Default is\n * {@link module:ol/events/condition~always}.\n * @property {boolean} [onFocusOnly=false] When the map\'s target has a `tabindex` attribute set,\n * the interaction will only handle events when the map has the focus.\n * @property {number} [maxDelta=1] Maximum mouse wheel delta.\n * @property {number} [duration=250] Animation duration in milliseconds.\n * @property {number} [timeout=80] Mouse wheel timeout duration in milliseconds.\n * @property {boolean} [useAnchor=true] Enable zooming using the mouse\'s\n * location as the anchor. When set to `false`, zooming in and out will zoom to\n * the center of the screen instead of zooming on the mouse\'s location.\n * @property {boolean} [constrainResolution=false] If true, the mouse wheel zoom\n * event will always animate to the closest zoom level after an interaction;\n * false means intermediary zoom levels are allowed.\n */\n\n/**\n * @classdesc\n * Allows the user to zoom the map by scrolling the mouse wheel.\n * @api\n */\n\nvar MouseWheelZoom =\n/** @class */\nfunction (_super) {\n MouseWheelZoom_extends(MouseWheelZoom, _super);\n /**\n * @param {Options=} opt_options Options.\n */\n\n\n function MouseWheelZoom(opt_options) {\n var _this = this;\n\n var options = opt_options ? opt_options : {};\n _this = _super.call(this,\n /** @type {import("./Interaction.js").InteractionOptions} */\n options) || this;\n /**\n * @private\n * @type {number}\n */\n\n _this.totalDelta_ = 0;\n /**\n * @private\n * @type {number}\n */\n\n _this.lastDelta_ = 0;\n /**\n * @private\n * @type {number}\n */\n\n _this.maxDelta_ = options.maxDelta !== undefined ? options.maxDelta : 1;\n /**\n * @private\n * @type {number}\n */\n\n _this.duration_ = options.duration !== undefined ? options.duration : 250;\n /**\n * @private\n * @type {number}\n */\n\n _this.timeout_ = options.timeout !== undefined ? options.timeout : 80;\n /**\n * @private\n * @type {boolean}\n */\n\n _this.useAnchor_ = options.useAnchor !== undefined ? options.useAnchor : true;\n /**\n * @private\n * @type {boolean}\n */\n\n _this.constrainResolution_ = options.constrainResolution !== undefined ? options.constrainResolution : false;\n var condition = options.condition ? options.condition : always;\n /**\n * @private\n * @type {import("../events/condition.js").Condition}\n */\n\n _this.condition_ = options.onFocusOnly ? condition_all(focusWithTabindex, condition) : condition;\n /**\n * @private\n * @type {?import("../coordinate.js").Coordinate}\n */\n\n _this.lastAnchor_ = null;\n /**\n * @private\n * @type {number|undefined}\n */\n\n _this.startTime_ = undefined;\n /**\n * @private\n * @type {?}\n */\n\n _this.timeoutId_;\n /**\n * @private\n * @type {Mode|undefined}\n */\n\n _this.mode_ = undefined;\n /**\n * Trackpad events separated by this delay will be considered separate\n * interactions.\n * @type {number}\n */\n\n _this.trackpadEventGap_ = 400;\n /**\n * @type {?}\n */\n\n _this.trackpadTimeoutId_;\n /**\n * The number of delta values per zoom level\n * @private\n * @type {number}\n */\n\n _this.deltaPerZoom_ = 300;\n return _this;\n }\n /**\n * @private\n */\n\n\n MouseWheelZoom.prototype.endInteraction_ = function () {\n this.trackpadTimeoutId_ = undefined;\n var view = this.getMap().getView();\n view.endInteraction(undefined, this.lastDelta_ ? this.lastDelta_ > 0 ? 1 : -1 : 0, this.lastAnchor_);\n };\n /**\n * Handles the {@link module:ol/MapBrowserEvent map browser event} (if it was a mousewheel-event) and eventually\n * zooms the map.\n * @param {import("../MapBrowserEvent.js").default} mapBrowserEvent Map browser event.\n * @return {boolean} `false` to stop event propagation.\n */\n\n\n MouseWheelZoom.prototype.handleEvent = function (mapBrowserEvent) {\n if (!this.condition_(mapBrowserEvent)) {\n return true;\n }\n\n var type = mapBrowserEvent.type;\n\n if (type !== EventType.WHEEL) {\n return true;\n }\n\n var map = mapBrowserEvent.map;\n var wheelEvent =\n /** @type {WheelEvent} */\n mapBrowserEvent.originalEvent;\n wheelEvent.preventDefault();\n\n if (this.useAnchor_) {\n this.lastAnchor_ = mapBrowserEvent.coordinate;\n } // Delta normalisation inspired by\n // https://github.com/mapbox/mapbox-gl-js/blob/001c7b9/js/ui/handler/scroll_zoom.js\n\n\n var delta;\n\n if (mapBrowserEvent.type == EventType.WHEEL) {\n delta = wheelEvent.deltaY;\n\n if (FIREFOX && wheelEvent.deltaMode === WheelEvent.DOM_DELTA_PIXEL) {\n delta /= DEVICE_PIXEL_RATIO;\n }\n\n if (wheelEvent.deltaMode === WheelEvent.DOM_DELTA_LINE) {\n delta *= 40;\n }\n }\n\n if (delta === 0) {\n return false;\n } else {\n this.lastDelta_ = delta;\n }\n\n var now = Date.now();\n\n if (this.startTime_ === undefined) {\n this.startTime_ = now;\n }\n\n if (!this.mode_ || now - this.startTime_ > this.trackpadEventGap_) {\n this.mode_ = Math.abs(delta) < 4 ? Mode.TRACKPAD : Mode.WHEEL;\n }\n\n var view = map.getView();\n\n if (this.mode_ === Mode.TRACKPAD && !(view.getConstrainResolution() || this.constrainResolution_)) {\n if (this.trackpadTimeoutId_) {\n clearTimeout(this.trackpadTimeoutId_);\n } else {\n if (view.getAnimating()) {\n view.cancelAnimations();\n }\n\n view.beginInteraction();\n }\n\n this.trackpadTimeoutId_ = setTimeout(this.endInteraction_.bind(this), this.timeout_);\n view.adjustZoom(-delta / this.deltaPerZoom_, this.lastAnchor_);\n this.startTime_ = now;\n return false;\n }\n\n this.totalDelta_ += delta;\n var timeLeft = Math.max(this.timeout_ - (now - this.startTime_), 0);\n clearTimeout(this.timeoutId_);\n this.timeoutId_ = setTimeout(this.handleWheelZoom_.bind(this, map), timeLeft);\n return false;\n };\n /**\n * @private\n * @param {import("../PluggableMap.js").default} map Map.\n */\n\n\n MouseWheelZoom.prototype.handleWheelZoom_ = function (map) {\n var view = map.getView();\n\n if (view.getAnimating()) {\n view.cancelAnimations();\n }\n\n var delta = -math_clamp(this.totalDelta_, -this.maxDelta_ * this.deltaPerZoom_, this.maxDelta_ * this.deltaPerZoom_) / this.deltaPerZoom_;\n\n if (view.getConstrainResolution() || this.constrainResolution_) {\n // view has a zoom constraint, zoom by 1\n delta = delta ? delta > 0 ? 1 : -1 : 0;\n }\n\n zoomByDelta(view, delta, this.lastAnchor_, this.duration_);\n this.mode_ = undefined;\n this.totalDelta_ = 0;\n this.lastAnchor_ = null;\n this.startTime_ = undefined;\n this.timeoutId_ = undefined;\n };\n /**\n * Enable or disable using the mouse\'s location as an anchor when zooming\n * @param {boolean} useAnchor true to zoom to the mouse\'s location, false\n * to zoom to the center of the map\n * @api\n */\n\n\n MouseWheelZoom.prototype.setMouseAnchor = function (useAnchor) {\n this.useAnchor_ = useAnchor;\n\n if (!useAnchor) {\n this.lastAnchor_ = null;\n }\n };\n\n return MouseWheelZoom;\n}(interaction_Interaction);\n\n/* harmony default export */ var interaction_MouseWheelZoom = (MouseWheelZoom);\n;// CONCATENATED MODULE: ./node_modules/ol/interaction/PinchRotate.js\nvar PinchRotate_extends = undefined && undefined.__extends || function () {\n var _extendStatics = function extendStatics(d, b) {\n _extendStatics = Object.setPrototypeOf || {\n __proto__: []\n } instanceof Array && function (d, b) {\n d.__proto__ = b;\n } || function (d, b) {\n for (var p in b) {\n if (Object.prototype.hasOwnProperty.call(b, p)) d[p] = b[p];\n }\n };\n\n return _extendStatics(d, b);\n };\n\n return function (d, b) {\n _extendStatics(d, b);\n\n function __() {\n this.constructor = d;\n }\n\n d.prototype = b === null ? Object.create(b) : (__.prototype = b.prototype, new __());\n };\n}();\n/**\n * @module ol/interaction/PinchRotate\n */\n\n\n\n\n\n/**\n * @typedef {Object} Options\n * @property {number} [duration=250] The duration of the animation in\n * milliseconds.\n * @property {number} [threshold=0.3] Minimal angle in radians to start a rotation.\n */\n\n/**\n * @classdesc\n * Allows the user to rotate the map by twisting with two fingers\n * on a touch screen.\n * @api\n */\n\nvar PinchRotate =\n/** @class */\nfunction (_super) {\n PinchRotate_extends(PinchRotate, _super);\n /**\n * @param {Options=} opt_options Options.\n */\n\n\n function PinchRotate(opt_options) {\n var _this = this;\n\n var options = opt_options ? opt_options : {};\n var pointerOptions =\n /** @type {import("./Pointer.js").Options} */\n options;\n\n if (!pointerOptions.stopDown) {\n pointerOptions.stopDown = functions_FALSE;\n }\n\n _this = _super.call(this, pointerOptions) || this;\n /**\n * @private\n * @type {import("../coordinate.js").Coordinate}\n */\n\n _this.anchor_ = null;\n /**\n * @private\n * @type {number|undefined}\n */\n\n _this.lastAngle_ = undefined;\n /**\n * @private\n * @type {boolean}\n */\n\n _this.rotating_ = false;\n /**\n * @private\n * @type {number}\n */\n\n _this.rotationDelta_ = 0.0;\n /**\n * @private\n * @type {number}\n */\n\n _this.threshold_ = options.threshold !== undefined ? options.threshold : 0.3;\n /**\n * @private\n * @type {number}\n */\n\n _this.duration_ = options.duration !== undefined ? options.duration : 250;\n return _this;\n }\n /**\n * Handle pointer drag events.\n * @param {import("../MapBrowserEvent.js").default} mapBrowserEvent Event.\n */\n\n\n PinchRotate.prototype.handleDragEvent = function (mapBrowserEvent) {\n var rotationDelta = 0.0;\n var touch0 = this.targetPointers[0];\n var touch1 = this.targetPointers[1]; // angle between touches\n\n var angle = Math.atan2(touch1.clientY - touch0.clientY, touch1.clientX - touch0.clientX);\n\n if (this.lastAngle_ !== undefined) {\n var delta = angle - this.lastAngle_;\n this.rotationDelta_ += delta;\n\n if (!this.rotating_ && Math.abs(this.rotationDelta_) > this.threshold_) {\n this.rotating_ = true;\n }\n\n rotationDelta = delta;\n }\n\n this.lastAngle_ = angle;\n var map = mapBrowserEvent.map;\n var view = map.getView();\n\n if (view.getConstraints().rotation === disable) {\n return;\n } // rotate anchor point.\n // FIXME: should be the intersection point between the lines:\n // touch0,touch1 and previousTouch0,previousTouch1\n\n\n var viewportPosition = map.getViewport().getBoundingClientRect();\n var centroid = Pointer_centroid(this.targetPointers);\n centroid[0] -= viewportPosition.left;\n centroid[1] -= viewportPosition.top;\n this.anchor_ = map.getCoordinateFromPixelInternal(centroid); // rotate\n\n if (this.rotating_) {\n map.render();\n view.adjustRotationInternal(rotationDelta, this.anchor_);\n }\n };\n /**\n * Handle pointer up events.\n * @param {import("../MapBrowserEvent.js").default} mapBrowserEvent Event.\n * @return {boolean} If the event was consumed.\n */\n\n\n PinchRotate.prototype.handleUpEvent = function (mapBrowserEvent) {\n if (this.targetPointers.length < 2) {\n var map = mapBrowserEvent.map;\n var view = map.getView();\n view.endInteraction(this.duration_);\n return false;\n } else {\n return true;\n }\n };\n /**\n * Handle pointer down events.\n * @param {import("../MapBrowserEvent.js").default} mapBrowserEvent Event.\n * @return {boolean} If the event was consumed.\n */\n\n\n PinchRotate.prototype.handleDownEvent = function (mapBrowserEvent) {\n if (this.targetPointers.length >= 2) {\n var map = mapBrowserEvent.map;\n this.anchor_ = null;\n this.lastAngle_ = undefined;\n this.rotating_ = false;\n this.rotationDelta_ = 0.0;\n\n if (!this.handlingDownUpSequence) {\n map.getView().beginInteraction();\n }\n\n return true;\n } else {\n return false;\n }\n };\n\n return PinchRotate;\n}(Pointer);\n\n/* harmony default export */ var interaction_PinchRotate = (PinchRotate);\n;// CONCATENATED MODULE: ./node_modules/ol/interaction/PinchZoom.js\nvar PinchZoom_extends = undefined && undefined.__extends || function () {\n var _extendStatics = function extendStatics(d, b) {\n _extendStatics = Object.setPrototypeOf || {\n __proto__: []\n } instanceof Array && function (d, b) {\n d.__proto__ = b;\n } || function (d, b) {\n for (var p in b) {\n if (Object.prototype.hasOwnProperty.call(b, p)) d[p] = b[p];\n }\n };\n\n return _extendStatics(d, b);\n };\n\n return function (d, b) {\n _extendStatics(d, b);\n\n function __() {\n this.constructor = d;\n }\n\n d.prototype = b === null ? Object.create(b) : (__.prototype = b.prototype, new __());\n };\n}();\n/**\n * @module ol/interaction/PinchZoom\n */\n\n\n\n\n/**\n * @typedef {Object} Options\n * @property {number} [duration=400] Animation duration in milliseconds.\n */\n\n/**\n * @classdesc\n * Allows the user to zoom the map by pinching with two fingers\n * on a touch screen.\n * @api\n */\n\nvar PinchZoom =\n/** @class */\nfunction (_super) {\n PinchZoom_extends(PinchZoom, _super);\n /**\n * @param {Options=} opt_options Options.\n */\n\n\n function PinchZoom(opt_options) {\n var _this = this;\n\n var options = opt_options ? opt_options : {};\n var pointerOptions =\n /** @type {import("./Pointer.js").Options} */\n options;\n\n if (!pointerOptions.stopDown) {\n pointerOptions.stopDown = functions_FALSE;\n }\n\n _this = _super.call(this, pointerOptions) || this;\n /**\n * @private\n * @type {import("../coordinate.js").Coordinate}\n */\n\n _this.anchor_ = null;\n /**\n * @private\n * @type {number}\n */\n\n _this.duration_ = options.duration !== undefined ? options.duration : 400;\n /**\n * @private\n * @type {number|undefined}\n */\n\n _this.lastDistance_ = undefined;\n /**\n * @private\n * @type {number}\n */\n\n _this.lastScaleDelta_ = 1;\n return _this;\n }\n /**\n * Handle pointer drag events.\n * @param {import("../MapBrowserEvent.js").default} mapBrowserEvent Event.\n */\n\n\n PinchZoom.prototype.handleDragEvent = function (mapBrowserEvent) {\n var scaleDelta = 1.0;\n var touch0 = this.targetPointers[0];\n var touch1 = this.targetPointers[1];\n var dx = touch0.clientX - touch1.clientX;\n var dy = touch0.clientY - touch1.clientY; // distance between touches\n\n var distance = Math.sqrt(dx * dx + dy * dy);\n\n if (this.lastDistance_ !== undefined) {\n scaleDelta = this.lastDistance_ / distance;\n }\n\n this.lastDistance_ = distance;\n var map = mapBrowserEvent.map;\n var view = map.getView();\n\n if (scaleDelta != 1.0) {\n this.lastScaleDelta_ = scaleDelta;\n } // scale anchor point.\n\n\n var viewportPosition = map.getViewport().getBoundingClientRect();\n var centroid = Pointer_centroid(this.targetPointers);\n centroid[0] -= viewportPosition.left;\n centroid[1] -= viewportPosition.top;\n this.anchor_ = map.getCoordinateFromPixelInternal(centroid); // scale, bypass the resolution constraint\n\n map.render();\n view.adjustResolutionInternal(scaleDelta, this.anchor_);\n };\n /**\n * Handle pointer up events.\n * @param {import("../MapBrowserEvent.js").default} mapBrowserEvent Event.\n * @return {boolean} If the event was consumed.\n */\n\n\n PinchZoom.prototype.handleUpEvent = function (mapBrowserEvent) {\n if (this.targetPointers.length < 2) {\n var map = mapBrowserEvent.map;\n var view = map.getView();\n var direction = this.lastScaleDelta_ > 1 ? 1 : -1;\n view.endInteraction(this.duration_, direction);\n return false;\n } else {\n return true;\n }\n };\n /**\n * Handle pointer down events.\n * @param {import("../MapBrowserEvent.js").default} mapBrowserEvent Event.\n * @return {boolean} If the event was consumed.\n */\n\n\n PinchZoom.prototype.handleDownEvent = function (mapBrowserEvent) {\n if (this.targetPointers.length >= 2) {\n var map = mapBrowserEvent.map;\n this.anchor_ = null;\n this.lastDistance_ = undefined;\n this.lastScaleDelta_ = 1;\n\n if (!this.handlingDownUpSequence) {\n map.getView().beginInteraction();\n }\n\n return true;\n } else {\n return false;\n }\n };\n\n return PinchZoom;\n}(Pointer);\n\n/* harmony default export */ var interaction_PinchZoom = (PinchZoom);\n;// CONCATENATED MODULE: ./node_modules/ol/interaction.js\n/**\n * @module ol/interaction\n */\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n/**\n * @typedef {Object} DefaultsOptions\n * @property {boolean} [altShiftDragRotate=true] Whether Alt-Shift-drag rotate is\n * desired.\n * @property {boolean} [onFocusOnly=false] Interact only when the map has the\n * focus. This affects the `MouseWheelZoom` and `DragPan` interactions and is\n * useful when page scroll is desired for maps that do not have the browser\'s\n * focus.\n * @property {boolean} [doubleClickZoom=true] Whether double click zoom is\n * desired.\n * @property {boolean} [keyboard=true] Whether keyboard interaction is desired.\n * @property {boolean} [mouseWheelZoom=true] Whether mousewheel zoom is desired.\n * @property {boolean} [shiftDragZoom=true] Whether Shift-drag zoom is desired.\n * @property {boolean} [dragPan=true] Whether drag pan is desired.\n * @property {boolean} [pinchRotate=true] Whether pinch rotate is desired.\n * @property {boolean} [pinchZoom=true] Whether pinch zoom is desired.\n * @property {number} [zoomDelta] Zoom level delta when using keyboard or double click zoom.\n * @property {number} [zoomDuration] Duration of the zoom animation in\n * milliseconds.\n */\n\n/**\n * Set of interactions included in maps by default. Specific interactions can be\n * excluded by setting the appropriate option to false in the constructor\n * options, but the order of the interactions is fixed. If you want to specify\n * a different order for interactions, you will need to create your own\n * {@link module:ol/interaction/Interaction} instances and insert\n * them into a {@link module:ol/Collection} in the order you want\n * before creating your {@link module:ol/Map~Map} instance. Changing the order can\n * be of interest if the event propagation needs to be stopped at a point.\n * The default set of interactions, in sequence, is:\n * * {@link module:ol/interaction/DragRotate~DragRotate}\n * * {@link module:ol/interaction/DoubleClickZoom~DoubleClickZoom}\n * * {@link module:ol/interaction/DragPan~DragPan}\n * * {@link module:ol/interaction/PinchRotate~PinchRotate}\n * * {@link module:ol/interaction/PinchZoom~PinchZoom}\n * * {@link module:ol/interaction/KeyboardPan~KeyboardPan}\n * * {@link module:ol/interaction/KeyboardZoom~KeyboardZoom}\n * * {@link module:ol/interaction/MouseWheelZoom~MouseWheelZoom}\n * * {@link module:ol/interaction/DragZoom~DragZoom}\n *\n * @param {DefaultsOptions=} opt_options Defaults options.\n * @return {import("./Collection.js").default<import("./interaction/Interaction.js").default>}\n * A collection of interactions to be used with the {@link module:ol/Map~Map}\n * constructor\'s `interactions` option.\n * @api\n */\n\nfunction interaction_defaults(opt_options) {\n var options = opt_options ? opt_options : {};\n var interactions = new ol_Collection();\n var kinetic = new ol_Kinetic(-0.005, 0.05, 100);\n var altShiftDragRotate = options.altShiftDragRotate !== undefined ? options.altShiftDragRotate : true;\n\n if (altShiftDragRotate) {\n interactions.push(new interaction_DragRotate());\n }\n\n var doubleClickZoom = options.doubleClickZoom !== undefined ? options.doubleClickZoom : true;\n\n if (doubleClickZoom) {\n interactions.push(new interaction_DoubleClickZoom({\n delta: options.zoomDelta,\n duration: options.zoomDuration\n }));\n }\n\n var dragPan = options.dragPan !== undefined ? options.dragPan : true;\n\n if (dragPan) {\n interactions.push(new interaction_DragPan({\n onFocusOnly: options.onFocusOnly,\n kinetic: kinetic\n }));\n }\n\n var pinchRotate = options.pinchRotate !== undefined ? options.pinchRotate : true;\n\n if (pinchRotate) {\n interactions.push(new interaction_PinchRotate());\n }\n\n var pinchZoom = options.pinchZoom !== undefined ? options.pinchZoom : true;\n\n if (pinchZoom) {\n interactions.push(new interaction_PinchZoom({\n duration: options.zoomDuration\n }));\n }\n\n var keyboard = options.keyboard !== undefined ? options.keyboard : true;\n\n if (keyboard) {\n interactions.push(new interaction_KeyboardPan());\n interactions.push(new interaction_KeyboardZoom({\n delta: options.zoomDelta,\n duration: options.zoomDuration\n }));\n }\n\n var mouseWheelZoom = options.mouseWheelZoom !== undefined ? options.mouseWheelZoom : true;\n\n if (mouseWheelZoom) {\n interactions.push(new interaction_MouseWheelZoom({\n onFocusOnly: options.onFocusOnly,\n duration: options.zoomDuration\n }));\n }\n\n var shiftDragZoom = options.shiftDragZoom !== undefined ? options.shiftDragZoom : true;\n\n if (shiftDragZoom) {\n interactions.push(new interaction_DragZoom({\n duration: options.zoomDuration\n }));\n }\n\n return interactions;\n}\n;// CONCATENATED MODULE: ./node_modules/ol/Map.js\nvar ol_Map_extends = undefined && undefined.__extends || function () {\n var _extendStatics = function extendStatics(d, b) {\n _extendStatics = Object.setPrototypeOf || {\n __proto__: []\n } instanceof Array && function (d, b) {\n d.__proto__ = b;\n } || function (d, b) {\n for (var p in b) {\n if (Object.prototype.hasOwnProperty.call(b, p)) d[p] = b[p];\n }\n };\n\n return _extendStatics(d, b);\n };\n\n return function (d, b) {\n _extendStatics(d, b);\n\n function __() {\n this.constructor = d;\n }\n\n d.prototype = b === null ? Object.create(b) : (__.prototype = b.prototype, new __());\n };\n}();\n/**\n * @module ol/Map\n */\n\n\n\n\n\n\n\n/**\n * @classdesc\n * The map is the core component of OpenLayers. For a map to render, a view,\n * one or more layers, and a target container are needed:\n *\n * import Map from \'ol/Map\';\n * import View from \'ol/View\';\n * import TileLayer from \'ol/layer/Tile\';\n * import OSM from \'ol/source/OSM\';\n *\n * var map = new Map({\n * view: new View({\n * center: [0, 0],\n * zoom: 1\n * }),\n * layers: [\n * new TileLayer({\n * source: new OSM()\n * })\n * ],\n * target: \'map\'\n * });\n *\n * The above snippet creates a map using a {@link module:ol/layer/Tile} to\n * display {@link module:ol/source/OSM~OSM} OSM data and render it to a DOM\n * element with the id `map`.\n *\n * The constructor places a viewport container (with CSS class name\n * `ol-viewport`) in the target element (see `getViewport()`), and then two\n * further elements within the viewport: one with CSS class name\n * `ol-overlaycontainer-stopevent` for controls and some overlays, and one with\n * CSS class name `ol-overlaycontainer` for other overlays (see the `stopEvent`\n * option of {@link module:ol/Overlay~Overlay} for the difference). The map\n * itself is placed in a further element within the viewport.\n *\n * Layers are stored as a {@link module:ol/Collection~Collection} in\n * layerGroups. A top-level group is provided by the library. This is what is\n * accessed by `getLayerGroup` and `setLayerGroup`. Layers entered in the\n * options are added to this group, and `addLayer` and `removeLayer` change the\n * layer collection in the group. `getLayers` is a convenience function for\n * `getLayerGroup().getLayers()`. Note that {@link module:ol/layer/Group~Group}\n * is a subclass of {@link module:ol/layer/Base}, so layers entered in the\n * options or added with `addLayer` can be groups, which can contain further\n * groups, and so on.\n *\n * @api\n */\n\nvar Map_Map =\n/** @class */\nfunction (_super) {\n ol_Map_extends(Map, _super);\n /**\n * @param {import("./PluggableMap.js").MapOptions} options Map options.\n */\n\n\n function Map(options) {\n var _this = this;\n\n options = obj_assign({}, options);\n\n if (!options.controls) {\n options.controls = defaults();\n }\n\n if (!options.interactions) {\n options.interactions = interaction_defaults({\n onFocusOnly: true\n });\n }\n\n _this = _super.call(this, options) || this;\n return _this;\n }\n\n Map.prototype.createRenderer = function () {\n return new Composite(this);\n };\n\n return Map;\n}(ol_PluggableMap);\n\n/* harmony default export */ var ol_Map = (Map_Map);\n;// CONCATENATED MODULE: ./node_modules/ol/layer/TileProperty.js\n/**\n * @module ol/layer/TileProperty\n */\n\n/**\n * @enum {string}\n */\n/* harmony default export */ var TileProperty = ({\n PRELOAD: \'preload\',\n USE_INTERIM_TILES_ON_ERROR: \'useInterimTilesOnError\'\n});\n;// CONCATENATED MODULE: ./node_modules/ol/layer/BaseTile.js\nvar BaseTile_extends = undefined && undefined.__extends || function () {\n var _extendStatics = function extendStatics(d, b) {\n _extendStatics = Object.setPrototypeOf || {\n __proto__: []\n } instanceof Array && function (d, b) {\n d.__proto__ = b;\n } || function (d, b) {\n for (var p in b) {\n if (Object.prototype.hasOwnProperty.call(b, p)) d[p] = b[p];\n }\n };\n\n return _extendStatics(d, b);\n };\n\n return function (d, b) {\n _extendStatics(d, b);\n\n function __() {\n this.constructor = d;\n }\n\n d.prototype = b === null ? Object.create(b) : (__.prototype = b.prototype, new __());\n };\n}();\n/**\n * @module ol/layer/BaseTile\n */\n\n\n\n\n\n/**\n * @typedef {Object} Options\n * @property {string} [className=\'ol-layer\'] A CSS class name to set to the layer element.\n * @property {number} [opacity=1] Opacity (0, 1).\n * @property {boolean} [visible=true] Visibility.\n * @property {import("../extent.js").Extent} [extent] The bounding extent for layer rendering. The layer will not be\n * rendered outside of this extent.\n * @property {number} [zIndex] The z-index for layer rendering. At rendering time, the layers\n * will be ordered, first by Z-index and then by position. When `undefined`, a `zIndex` of 0 is assumed\n * for layers that are added to the map\'s `layers` collection, or `Infinity` when the layer\'s `setMap()`\n * method was used.\n * @property {number} [minResolution] The minimum resolution (inclusive) at which this layer will be\n * visible.\n * @property {number} [maxResolution] The maximum resolution (exclusive) below which this layer will\n * be visible.\n * @property {number} [minZoom] The minimum view zoom level (exclusive) above which this layer will be\n * visible.\n * @property {number} [maxZoom] The maximum view zoom level (inclusive) at which this layer will\n * be visible.\n * @property {number} [preload=0] Preload. Load low-resolution tiles up to `preload` levels. `0`\n * means no preloading.\n * @property {import("../source/Tile.js").default} [source] Source for this layer.\n * @property {import("../PluggableMap.js").default} [map] Sets the layer as overlay on a map. The map will not manage\n * this layer in its layers collection, and the layer will be rendered on top. This is useful for\n * temporary layers. The standard way to add a layer to a map and have it managed by the map is to\n * use {@link module:ol/Map#addLayer}.\n * @property {boolean} [useInterimTilesOnError=true] Use interim tiles on error.\n */\n\n/**\n * @classdesc\n * For layer sources that provide pre-rendered, tiled images in grids that are\n * organized by zoom levels for specific resolutions.\n * Note that any property set in the options is set as a {@link module:ol/Object~BaseObject}\n * property on the layer object; for example, setting `title: \'My Title\'` in the\n * options means that `title` is observable, and has get/set accessors.\n *\n * @extends {Layer<import("../source/Tile.js").default>}\n * @api\n */\n\nvar BaseTileLayer =\n/** @class */\nfunction (_super) {\n BaseTile_extends(BaseTileLayer, _super);\n /**\n * @param {Options=} opt_options Tile layer options.\n */\n\n\n function BaseTileLayer(opt_options) {\n var _this = this;\n\n var options = opt_options ? opt_options : {};\n var baseOptions = obj_assign({}, options);\n delete baseOptions.preload;\n delete baseOptions.useInterimTilesOnError;\n _this = _super.call(this, baseOptions) || this;\n\n _this.setPreload(options.preload !== undefined ? options.preload : 0);\n\n _this.setUseInterimTilesOnError(options.useInterimTilesOnError !== undefined ? options.useInterimTilesOnError : true);\n\n return _this;\n }\n /**\n * Return the level as number to which we will preload tiles up to.\n * @return {number} The level to preload tiles up to.\n * @observable\n * @api\n */\n\n\n BaseTileLayer.prototype.getPreload = function () {\n return (\n /** @type {number} */\n this.get(TileProperty.PRELOAD)\n );\n };\n /**\n * Set the level as number to which we will preload tiles up to.\n * @param {number} preload The level to preload tiles up to.\n * @observable\n * @api\n */\n\n\n BaseTileLayer.prototype.setPreload = function (preload) {\n this.set(TileProperty.PRELOAD, preload);\n };\n /**\n * Whether we use interim tiles on error.\n * @return {boolean} Use interim tiles on error.\n * @observable\n * @api\n */\n\n\n BaseTileLayer.prototype.getUseInterimTilesOnError = function () {\n return (\n /** @type {boolean} */\n this.get(TileProperty.USE_INTERIM_TILES_ON_ERROR)\n );\n };\n /**\n * Set whether we use interim tiles on error.\n * @param {boolean} useInterimTilesOnError Use interim tiles on error.\n * @observable\n * @api\n */\n\n\n BaseTileLayer.prototype.setUseInterimTilesOnError = function (useInterimTilesOnError) {\n this.set(TileProperty.USE_INTERIM_TILES_ON_ERROR, useInterimTilesOnError);\n };\n\n return BaseTileLayer;\n}(layer_Layer);\n\n/* harmony default export */ var BaseTile = (BaseTileLayer);\n;// CONCATENATED MODULE: ./node_modules/ol/ImageState.js\n/**\n * @module ol/ImageState\n */\n\n/**\n * @enum {number}\n */\n/* harmony default export */ var ImageState = ({\n IDLE: 0,\n LOADING: 1,\n LOADED: 2,\n ERROR: 3,\n EMPTY: 4\n});\n;// CONCATENATED MODULE: ./node_modules/ol/renderer/Layer.js\nvar renderer_Layer_extends = undefined && undefined.__extends || function () {\n var _extendStatics = function extendStatics(d, b) {\n _extendStatics = Object.setPrototypeOf || {\n __proto__: []\n } instanceof Array && function (d, b) {\n d.__proto__ = b;\n } || function (d, b) {\n for (var p in b) {\n if (Object.prototype.hasOwnProperty.call(b, p)) d[p] = b[p];\n }\n };\n\n return _extendStatics(d, b);\n };\n\n return function (d, b) {\n _extendStatics(d, b);\n\n function __() {\n this.constructor = d;\n }\n\n d.prototype = b === null ? Object.create(b) : (__.prototype = b.prototype, new __());\n };\n}();\n/**\n * @module ol/renderer/Layer\n */\n\n\n\n\n\n\n\n/**\n * @template {import("../layer/Layer.js").default} LayerType\n */\n\nvar LayerRenderer =\n/** @class */\nfunction (_super) {\n renderer_Layer_extends(LayerRenderer, _super);\n /**\n * @param {LayerType} layer Layer.\n */\n\n\n function LayerRenderer(layer) {\n var _this = _super.call(this) || this;\n /** @private */\n\n\n _this.boundHandleImageChange_ = _this.handleImageChange_.bind(_this);\n /**\n * @protected\n * @type {LayerType}\n */\n\n _this.layer_ = layer;\n /**\n * @type {import("../render/canvas/ExecutorGroup").default}\n */\n\n _this.declutterExecutorGroup = null;\n return _this;\n }\n /**\n * Asynchronous layer level hit detection.\n * @param {import("../pixel.js").Pixel} pixel Pixel.\n * @return {Promise<Array<import("../Feature").default>>} Promise that resolves with\n * an array of features.\n */\n\n\n LayerRenderer.prototype.getFeatures = function (pixel) {\n return util_abstract();\n };\n /**\n * Determine whether render should be called.\n * @abstract\n * @param {import("../PluggableMap.js").FrameState} frameState Frame state.\n * @return {boolean} Layer is ready to be rendered.\n */\n\n\n LayerRenderer.prototype.prepareFrame = function (frameState) {\n return util_abstract();\n };\n /**\n * Render the layer.\n * @abstract\n * @param {import("../PluggableMap.js").FrameState} frameState Frame state.\n * @param {HTMLElement} target Target that may be used to render content to.\n * @return {HTMLElement} The rendered element.\n */\n\n\n LayerRenderer.prototype.renderFrame = function (frameState, target) {\n return util_abstract();\n };\n /**\n * @param {Object<number, Object<string, import("../Tile.js").default>>} tiles Lookup of loaded tiles by zoom level.\n * @param {number} zoom Zoom level.\n * @param {import("../Tile.js").default} tile Tile.\n * @return {boolean|void} If `false`, the tile will not be considered loaded.\n */\n\n\n LayerRenderer.prototype.loadedTileCallback = function (tiles, zoom, tile) {\n if (!tiles[zoom]) {\n tiles[zoom] = {};\n }\n\n tiles[zoom][tile.tileCoord.toString()] = tile;\n return undefined;\n };\n /**\n * Create a function that adds loaded tiles to the tile lookup.\n * @param {import("../source/Tile.js").default} source Tile source.\n * @param {import("../proj/Projection.js").default} projection Projection of the tiles.\n * @param {Object<number, Object<string, import("../Tile.js").default>>} tiles Lookup of loaded tiles by zoom level.\n * @return {function(number, import("../TileRange.js").default):boolean} A function that can be\n * called with a zoom level and a tile range to add loaded tiles to the lookup.\n * @protected\n */\n\n\n LayerRenderer.prototype.createLoadedTileFinder = function (source, projection, tiles) {\n return (\n /**\n * @param {number} zoom Zoom level.\n * @param {import("../TileRange.js").default} tileRange Tile range.\n * @return {boolean} The tile range is fully loaded.\n * @this {LayerRenderer}\n */\n function (zoom, tileRange) {\n var callback = this.loadedTileCallback.bind(this, tiles, zoom);\n return source.forEachLoadedTile(projection, zoom, tileRange, callback);\n }.bind(this)\n );\n };\n /**\n * @abstract\n * @param {import("../coordinate.js").Coordinate} coordinate Coordinate.\n * @param {import("../PluggableMap.js").FrameState} frameState Frame state.\n * @param {number} hitTolerance Hit tolerance in pixels.\n * @param {import("./vector.js").FeatureCallback<T>} callback Feature callback.\n * @param {Array<import("./Map.js").HitMatch<T>>} matches The hit detected matches with tolerance.\n * @return {T|undefined} Callback result.\n * @template T\n */\n\n\n LayerRenderer.prototype.forEachFeatureAtCoordinate = function (coordinate, frameState, hitTolerance, callback, matches) {\n return undefined;\n };\n /**\n * @abstract\n * @param {import("../pixel.js").Pixel} pixel Pixel.\n * @param {import("../PluggableMap.js").FrameState} frameState FrameState.\n * @param {number} hitTolerance Hit tolerance in pixels.\n * @return {Uint8ClampedArray|Uint8Array} The result. If there is no data at the pixel\n * location, null will be returned. If there is data, but pixel values cannot be\n * returned, and empty array will be returned.\n */\n\n\n LayerRenderer.prototype.getDataAtPixel = function (pixel, frameState, hitTolerance) {\n return util_abstract();\n };\n /**\n * @return {LayerType} Layer.\n */\n\n\n LayerRenderer.prototype.getLayer = function () {\n return this.layer_;\n };\n /**\n * Perform action necessary to get the layer rendered after new fonts have loaded\n * @abstract\n */\n\n\n LayerRenderer.prototype.handleFontsChanged = function () {};\n /**\n * Handle changes in image state.\n * @param {import("../events/Event.js").default} event Image change event.\n * @private\n */\n\n\n LayerRenderer.prototype.handleImageChange_ = function (event) {\n var image =\n /** @type {import("../Image.js").default} */\n event.target;\n\n if (image.getState() === ImageState.LOADED) {\n this.renderIfReadyAndVisible();\n }\n };\n /**\n * Load the image if not already loaded, and register the image change\n * listener if needed.\n * @param {import("../ImageBase.js").default} image Image.\n * @return {boolean} `true` if the image is already loaded, `false` otherwise.\n * @protected\n */\n\n\n LayerRenderer.prototype.loadImage = function (image) {\n var imageState = image.getState();\n\n if (imageState != ImageState.LOADED && imageState != ImageState.ERROR) {\n image.addEventListener(EventType.CHANGE, this.boundHandleImageChange_);\n }\n\n if (imageState == ImageState.IDLE) {\n image.load();\n imageState = image.getState();\n }\n\n return imageState == ImageState.LOADED;\n };\n /**\n * @protected\n */\n\n\n LayerRenderer.prototype.renderIfReadyAndVisible = function () {\n var layer = this.getLayer();\n\n if (layer.getVisible() && layer.getSourceState() == State.READY) {\n layer.changed();\n }\n };\n\n return LayerRenderer;\n}(ol_Observable);\n\n/* harmony default export */ var renderer_Layer = (LayerRenderer);\n;// CONCATENATED MODULE: ./node_modules/ol/renderer/canvas/Layer.js\nvar canvas_Layer_extends = undefined && undefined.__extends || function () {\n var _extendStatics = function extendStatics(d, b) {\n _extendStatics = Object.setPrototypeOf || {\n __proto__: []\n } instanceof Array && function (d, b) {\n d.__proto__ = b;\n } || function (d, b) {\n for (var p in b) {\n if (Object.prototype.hasOwnProperty.call(b, p)) d[p] = b[p];\n }\n };\n\n return _extendStatics(d, b);\n };\n\n return function (d, b) {\n _extendStatics(d, b);\n\n function __() {\n this.constructor = d;\n }\n\n d.prototype = b === null ? Object.create(b) : (__.prototype = b.prototype, new __());\n };\n}();\n/**\n * @module ol/renderer/canvas/Layer\n */\n\n\n\n\n\n\n\n\n\n/**\n * @abstract\n * @template {import("../../layer/Layer.js").default} LayerType\n */\n\nvar CanvasLayerRenderer =\n/** @class */\nfunction (_super) {\n canvas_Layer_extends(CanvasLayerRenderer, _super);\n /**\n * @param {LayerType} layer Layer.\n */\n\n\n function CanvasLayerRenderer(layer) {\n var _this = _super.call(this, layer) || this;\n /**\n * @protected\n * @type {HTMLElement}\n */\n\n\n _this.container = null;\n /**\n * @protected\n * @type {number}\n */\n\n _this.renderedResolution;\n /**\n * A temporary transform. The values in this transform should only be used in a\n * function that sets the values.\n * @protected\n * @type {import("../../transform.js").Transform}\n */\n\n _this.tempTransform = create();\n /**\n * The transform for rendered pixels to viewport CSS pixels. This transform must\n * be set when rendering a frame and may be used by other functions after rendering.\n * @protected\n * @type {import("../../transform.js").Transform}\n */\n\n _this.pixelTransform = create();\n /**\n * The transform for viewport CSS pixels to rendered pixels. This transform must\n * be set when rendering a frame and may be used by other functions after rendering.\n * @protected\n * @type {import("../../transform.js").Transform}\n */\n\n _this.inversePixelTransform = create();\n /**\n * @type {CanvasRenderingContext2D}\n */\n\n _this.context = null;\n /**\n * @type {boolean}\n */\n\n _this.containerReused = false;\n return _this;\n }\n /**\n * Get a rendering container from an existing target, if compatible.\n * @param {HTMLElement} target Potential render target.\n * @param {string} transform CSS Transform.\n * @param {number} opacity Opacity.\n */\n\n\n CanvasLayerRenderer.prototype.useContainer = function (target, transform, opacity) {\n var layerClassName = this.getLayer().getClassName();\n var container, context;\n\n if (target && target.style.opacity === \'\' && target.className === layerClassName) {\n var canvas = target.firstElementChild;\n\n if (canvas instanceof HTMLCanvasElement) {\n context = canvas.getContext(\'2d\');\n }\n }\n\n if (context && (context.canvas.width === 0 || context.canvas.style.transform === transform)) {\n // Container of the previous layer renderer can be used.\n this.container = target;\n this.context = context;\n this.containerReused = true;\n } else if (this.containerReused) {\n // Previously reused container cannot be used any more.\n this.container = null;\n this.context = null;\n this.containerReused = false;\n }\n\n if (!this.container) {\n container = document.createElement(\'div\');\n container.className = layerClassName;\n var style = container.style;\n style.position = \'absolute\';\n style.width = \'100%\';\n style.height = \'100%\';\n context = createCanvasContext2D();\n var canvas = context.canvas;\n container.appendChild(canvas);\n style = canvas.style;\n style.position = \'absolute\';\n style.left = \'0\';\n style.transformOrigin = \'top left\';\n this.container = container;\n this.context = context;\n }\n };\n /**\n * @param {CanvasRenderingContext2D} context Context.\n * @param {import("../../PluggableMap.js").FrameState} frameState Frame state.\n * @param {import("../../extent.js").Extent} extent Clip extent.\n * @protected\n */\n\n\n CanvasLayerRenderer.prototype.clip = function (context, frameState, extent) {\n var pixelRatio = frameState.pixelRatio;\n var halfWidth = frameState.size[0] * pixelRatio / 2;\n var halfHeight = frameState.size[1] * pixelRatio / 2;\n var rotation = frameState.viewState.rotation;\n var topLeft = getTopLeft(extent);\n var topRight = getTopRight(extent);\n var bottomRight = getBottomRight(extent);\n var bottomLeft = getBottomLeft(extent);\n apply(frameState.coordinateToPixelTransform, topLeft);\n apply(frameState.coordinateToPixelTransform, topRight);\n apply(frameState.coordinateToPixelTransform, bottomRight);\n apply(frameState.coordinateToPixelTransform, bottomLeft);\n context.save();\n rotateAtOffset(context, -rotation, halfWidth, halfHeight);\n context.beginPath();\n context.moveTo(topLeft[0] * pixelRatio, topLeft[1] * pixelRatio);\n context.lineTo(topRight[0] * pixelRatio, topRight[1] * pixelRatio);\n context.lineTo(bottomRight[0] * pixelRatio, bottomRight[1] * pixelRatio);\n context.lineTo(bottomLeft[0] * pixelRatio, bottomLeft[1] * pixelRatio);\n context.clip();\n rotateAtOffset(context, rotation, halfWidth, halfHeight);\n };\n /**\n * @param {CanvasRenderingContext2D} context Context.\n * @param {import("../../PluggableMap.js").FrameState} frameState Frame state.\n * @param {import("../../extent.js").Extent} extent Clip extent.\n * @protected\n */\n\n\n CanvasLayerRenderer.prototype.clipUnrotated = function (context, frameState, extent) {\n var topLeft = getTopLeft(extent);\n var topRight = getTopRight(extent);\n var bottomRight = getBottomRight(extent);\n var bottomLeft = getBottomLeft(extent);\n apply(frameState.coordinateToPixelTransform, topLeft);\n apply(frameState.coordinateToPixelTransform, topRight);\n apply(frameState.coordinateToPixelTransform, bottomRight);\n apply(frameState.coordinateToPixelTransform, bottomLeft);\n var inverted = this.inversePixelTransform;\n apply(inverted, topLeft);\n apply(inverted, topRight);\n apply(inverted, bottomRight);\n apply(inverted, bottomLeft);\n context.save();\n context.beginPath();\n context.moveTo(Math.round(topLeft[0]), Math.round(topLeft[1]));\n context.lineTo(Math.round(topRight[0]), Math.round(topRight[1]));\n context.lineTo(Math.round(bottomRight[0]), Math.round(bottomRight[1]));\n context.lineTo(Math.round(bottomLeft[0]), Math.round(bottomLeft[1]));\n context.clip();\n };\n /**\n * @param {import("../../render/EventType.js").default} type Event type.\n * @param {CanvasRenderingContext2D} context Context.\n * @param {import("../../PluggableMap.js").FrameState} frameState Frame state.\n * @private\n */\n\n\n CanvasLayerRenderer.prototype.dispatchRenderEvent_ = function (type, context, frameState) {\n var layer = this.getLayer();\n\n if (layer.hasListener(type)) {\n var event_1 = new render_Event(type, this.inversePixelTransform, frameState, context);\n layer.dispatchEvent(event_1);\n }\n };\n /**\n * @param {CanvasRenderingContext2D} context Context.\n * @param {import("../../PluggableMap.js").FrameState} frameState Frame state.\n * @protected\n */\n\n\n CanvasLayerRenderer.prototype.preRender = function (context, frameState) {\n this.dispatchRenderEvent_(render_EventType.PRERENDER, context, frameState);\n };\n /**\n * @param {CanvasRenderingContext2D} context Context.\n * @param {import("../../PluggableMap.js").FrameState} frameState Frame state.\n * @protected\n */\n\n\n CanvasLayerRenderer.prototype.postRender = function (context, frameState) {\n this.dispatchRenderEvent_(render_EventType.POSTRENDER, context, frameState);\n };\n /**\n * Creates a transform for rendering to an element that will be rotated after rendering.\n * @param {import("../../coordinate.js").Coordinate} center Center.\n * @param {number} resolution Resolution.\n * @param {number} rotation Rotation.\n * @param {number} pixelRatio Pixel ratio.\n * @param {number} width Width of the rendered element (in pixels).\n * @param {number} height Height of the rendered element (in pixels).\n * @param {number} offsetX Offset on the x-axis in view coordinates.\n * @protected\n * @return {!import("../../transform.js").Transform} Transform.\n */\n\n\n CanvasLayerRenderer.prototype.getRenderTransform = function (center, resolution, rotation, pixelRatio, width, height, offsetX) {\n var dx1 = width / 2;\n var dy1 = height / 2;\n var sx = pixelRatio / resolution;\n var sy = -sx;\n var dx2 = -center[0] + offsetX;\n var dy2 = -center[1];\n return compose(this.tempTransform, dx1, dy1, sx, sy, -rotation, dx2, dy2);\n };\n /**\n * @param {import("../../pixel.js").Pixel} pixel Pixel.\n * @param {import("../../PluggableMap.js").FrameState} frameState FrameState.\n * @param {number} hitTolerance Hit tolerance in pixels.\n * @return {Uint8ClampedArray|Uint8Array} The result. If there is no data at the pixel\n * location, null will be returned. If there is data, but pixel values cannot be\n * returned, and empty array will be returned.\n */\n\n\n CanvasLayerRenderer.prototype.getDataAtPixel = function (pixel, frameState, hitTolerance) {\n var renderPixel = apply(this.inversePixelTransform, pixel.slice());\n var context = this.context;\n var layer = this.getLayer();\n var layerExtent = layer.getExtent();\n\n if (layerExtent) {\n var renderCoordinate = apply(frameState.pixelToCoordinateTransform, pixel.slice());\n /** get only data inside of the layer extent */\n\n if (!containsCoordinate(layerExtent, renderCoordinate)) {\n return null;\n }\n }\n\n var data;\n\n try {\n var x = Math.round(renderPixel[0]);\n var y = Math.round(renderPixel[1]);\n var newCanvas = document.createElement(\'canvas\');\n var newContext = newCanvas.getContext(\'2d\');\n newCanvas.width = 1;\n newCanvas.height = 1;\n newContext.clearRect(0, 0, 1, 1);\n newContext.drawImage(context.canvas, x, y, 1, 1, 0, 0, 1, 1);\n data = newContext.getImageData(0, 0, 1, 1).data;\n } catch (err) {\n if (err.name === \'SecurityError\') {\n // tainted canvas, we assume there is data at the given pixel (although there might not be)\n return new Uint8Array();\n }\n\n return data;\n }\n\n if (data[3] === 0) {\n return null;\n }\n\n return data;\n };\n\n return CanvasLayerRenderer;\n}(renderer_Layer);\n\n/* harmony default export */ var canvas_Layer = (CanvasLayerRenderer);\n;// CONCATENATED MODULE: ./node_modules/ol/TileRange.js\n/**\n * @module ol/TileRange\n */\n\n/**\n * A representation of a contiguous block of tiles. A tile range is specified\n * by its min/max tile coordinates and is inclusive of coordinates.\n */\nvar TileRange =\n/** @class */\nfunction () {\n /**\n * @param {number} minX Minimum X.\n * @param {number} maxX Maximum X.\n * @param {number} minY Minimum Y.\n * @param {number} maxY Maximum Y.\n */\n function TileRange(minX, maxX, minY, maxY) {\n /**\n * @type {number}\n */\n this.minX = minX;\n /**\n * @type {number}\n */\n\n this.maxX = maxX;\n /**\n * @type {number}\n */\n\n this.minY = minY;\n /**\n * @type {number}\n */\n\n this.maxY = maxY;\n }\n /**\n * @param {import("./tilecoord.js").TileCoord} tileCoord Tile coordinate.\n * @return {boolean} Contains tile coordinate.\n */\n\n\n TileRange.prototype.contains = function (tileCoord) {\n return this.containsXY(tileCoord[1], tileCoord[2]);\n };\n /**\n * @param {TileRange} tileRange Tile range.\n * @return {boolean} Contains.\n */\n\n\n TileRange.prototype.containsTileRange = function (tileRange) {\n return this.minX <= tileRange.minX && tileRange.maxX <= this.maxX && this.minY <= tileRange.minY && tileRange.maxY <= this.maxY;\n };\n /**\n * @param {number} x Tile coordinate x.\n * @param {number} y Tile coordinate y.\n * @return {boolean} Contains coordinate.\n */\n\n\n TileRange.prototype.containsXY = function (x, y) {\n return this.minX <= x && x <= this.maxX && this.minY <= y && y <= this.maxY;\n };\n /**\n * @param {TileRange} tileRange Tile range.\n * @return {boolean} Equals.\n */\n\n\n TileRange.prototype.equals = function (tileRange) {\n return this.minX == tileRange.minX && this.minY == tileRange.minY && this.maxX == tileRange.maxX && this.maxY == tileRange.maxY;\n };\n /**\n * @param {TileRange} tileRange Tile range.\n */\n\n\n TileRange.prototype.extend = function (tileRange) {\n if (tileRange.minX < this.minX) {\n this.minX = tileRange.minX;\n }\n\n if (tileRange.maxX > this.maxX) {\n this.maxX = tileRange.maxX;\n }\n\n if (tileRange.minY < this.minY) {\n this.minY = tileRange.minY;\n }\n\n if (tileRange.maxY > this.maxY) {\n this.maxY = tileRange.maxY;\n }\n };\n /**\n * @return {number} Height.\n */\n\n\n TileRange.prototype.getHeight = function () {\n return this.maxY - this.minY + 1;\n };\n /**\n * @return {import("./size.js").Size} Size.\n */\n\n\n TileRange.prototype.getSize = function () {\n return [this.getWidth(), this.getHeight()];\n };\n /**\n * @return {number} Width.\n */\n\n\n TileRange.prototype.getWidth = function () {\n return this.maxX - this.minX + 1;\n };\n /**\n * @param {TileRange} tileRange Tile range.\n * @return {boolean} Intersects.\n */\n\n\n TileRange.prototype.intersects = function (tileRange) {\n return this.minX <= tileRange.maxX && this.maxX >= tileRange.minX && this.minY <= tileRange.maxY && this.maxY >= tileRange.minY;\n };\n\n return TileRange;\n}();\n/**\n * @param {number} minX Minimum X.\n * @param {number} maxX Maximum X.\n * @param {number} minY Minimum Y.\n * @param {number} maxY Maximum Y.\n * @param {TileRange=} tileRange TileRange.\n * @return {TileRange} Tile range.\n */\n\n\nfunction TileRange_createOrUpdate(minX, maxX, minY, maxY, tileRange) {\n if (tileRange !== undefined) {\n tileRange.minX = minX;\n tileRange.maxX = maxX;\n tileRange.minY = minY;\n tileRange.maxY = maxY;\n return tileRange;\n } else {\n return new TileRange(minX, maxX, minY, maxY);\n }\n}\n/* harmony default export */ var ol_TileRange = (TileRange);\n;// CONCATENATED MODULE: ./node_modules/ol/renderer/canvas/TileLayer.js\nvar TileLayer_extends = undefined && undefined.__extends || function () {\n var _extendStatics = function extendStatics(d, b) {\n _extendStatics = Object.setPrototypeOf || {\n __proto__: []\n } instanceof Array && function (d, b) {\n d.__proto__ = b;\n } || function (d, b) {\n for (var p in b) {\n if (Object.prototype.hasOwnProperty.call(b, p)) d[p] = b[p];\n }\n };\n\n return _extendStatics(d, b);\n };\n\n return function (d, b) {\n _extendStatics(d, b);\n\n function __() {\n this.constructor = d;\n }\n\n d.prototype = b === null ? Object.create(b) : (__.prototype = b.prototype, new __());\n };\n}();\n/**\n * @module ol/renderer/canvas/TileLayer\n */\n\n\n\n\n\n\n\n\n\n\n\n\n/**\n * @classdesc\n * Canvas renderer for tile layers.\n * @api\n */\n\nvar CanvasTileLayerRenderer =\n/** @class */\nfunction (_super) {\n TileLayer_extends(CanvasTileLayerRenderer, _super);\n /**\n * @param {import("../../layer/Tile.js").default|import("../../layer/VectorTile.js").default} tileLayer Tile layer.\n */\n\n\n function CanvasTileLayerRenderer(tileLayer) {\n var _this = _super.call(this, tileLayer) || this;\n /**\n * Rendered extent has changed since the previous `renderFrame()` call\n * @type {boolean}\n */\n\n\n _this.extentChanged = true;\n /**\n * @private\n * @type {?import("../../extent.js").Extent}\n */\n\n _this.renderedExtent_ = null;\n /**\n * @protected\n * @type {number}\n */\n\n _this.renderedPixelRatio;\n /**\n * @protected\n * @type {import("../../proj/Projection.js").default}\n */\n\n _this.renderedProjection = null;\n /**\n * @protected\n * @type {number}\n */\n\n _this.renderedRevision;\n /**\n * @protected\n * @type {!Array<import("../../Tile.js").default>}\n */\n\n _this.renderedTiles = [];\n /**\n * @private\n * @type {boolean}\n */\n\n _this.newTiles_ = false;\n /**\n * @protected\n * @type {import("../../extent.js").Extent}\n */\n\n _this.tmpExtent = createEmpty();\n /**\n * @private\n * @type {import("../../TileRange.js").default}\n */\n\n _this.tmpTileRange_ = new ol_TileRange(0, 0, 0, 0);\n return _this;\n }\n /**\n * @protected\n * @param {import("../../Tile.js").default} tile Tile.\n * @return {boolean} Tile is drawable.\n */\n\n\n CanvasTileLayerRenderer.prototype.isDrawableTile = function (tile) {\n var tileLayer = this.getLayer();\n var tileState = tile.getState();\n var useInterimTilesOnError = tileLayer.getUseInterimTilesOnError();\n return tileState == TileState.LOADED || tileState == TileState.EMPTY || tileState == TileState.ERROR && !useInterimTilesOnError;\n };\n /**\n * @param {number} z Tile coordinate z.\n * @param {number} x Tile coordinate x.\n * @param {number} y Tile coordinate y.\n * @param {import("../../PluggableMap.js").FrameState} frameState Frame state.\n * @return {!import("../../Tile.js").default} Tile.\n */\n\n\n CanvasTileLayerRenderer.prototype.getTile = function (z, x, y, frameState) {\n var pixelRatio = frameState.pixelRatio;\n var projection = frameState.viewState.projection;\n var tileLayer = this.getLayer();\n var tileSource = tileLayer.getSource();\n var tile = tileSource.getTile(z, x, y, pixelRatio, projection);\n\n if (tile.getState() == TileState.ERROR) {\n if (!tileLayer.getUseInterimTilesOnError()) {\n // When useInterimTilesOnError is false, we consider the error tile as loaded.\n tile.setState(TileState.LOADED);\n } else if (tileLayer.getPreload() > 0) {\n // Preloaded tiles for lower resolutions might have finished loading.\n this.newTiles_ = true;\n }\n }\n\n if (!this.isDrawableTile(tile)) {\n tile = tile.getInterimTile();\n }\n\n return tile;\n };\n /**\n * @param {Object<number, Object<string, import("../../Tile.js").default>>} tiles Lookup of loaded tiles by zoom level.\n * @param {number} zoom Zoom level.\n * @param {import("../../Tile.js").default} tile Tile.\n * @return {boolean|void} If `false`, the tile will not be considered loaded.\n */\n\n\n CanvasTileLayerRenderer.prototype.loadedTileCallback = function (tiles, zoom, tile) {\n if (this.isDrawableTile(tile)) {\n return _super.prototype.loadedTileCallback.call(this, tiles, zoom, tile);\n }\n\n return false;\n };\n /**\n * Determine whether render should be called.\n * @param {import("../../PluggableMap.js").FrameState} frameState Frame state.\n * @return {boolean} Layer is ready to be rendered.\n */\n\n\n CanvasTileLayerRenderer.prototype.prepareFrame = function (frameState) {\n return !!this.getLayer().getSource();\n };\n /**\n * Render the layer.\n * @param {import("../../PluggableMap.js").FrameState} frameState Frame state.\n * @param {HTMLElement} target Target that may be used to render content to.\n * @return {HTMLElement} The rendered element.\n */\n\n\n CanvasTileLayerRenderer.prototype.renderFrame = function (frameState, target) {\n var layerState = frameState.layerStatesArray[frameState.layerIndex];\n var viewState = frameState.viewState;\n var projection = viewState.projection;\n var viewResolution = viewState.resolution;\n var viewCenter = viewState.center;\n var rotation = viewState.rotation;\n var pixelRatio = frameState.pixelRatio;\n var tileLayer = this.getLayer();\n var tileSource = tileLayer.getSource();\n var sourceRevision = tileSource.getRevision();\n var tileGrid = tileSource.getTileGridForProjection(projection);\n var z = tileGrid.getZForResolution(viewResolution, tileSource.zDirection);\n var tileResolution = tileGrid.getResolution(z);\n var extent = frameState.extent;\n var layerExtent = layerState.extent && fromUserExtent(layerState.extent, projection);\n\n if (layerExtent) {\n extent = getIntersection(extent, fromUserExtent(layerState.extent, projection));\n }\n\n var tilePixelRatio = tileSource.getTilePixelRatio(pixelRatio); // desired dimensions of the canvas in pixels\n\n var width = Math.round(frameState.size[0] * tilePixelRatio);\n var height = Math.round(frameState.size[1] * tilePixelRatio);\n\n if (rotation) {\n var size = Math.round(Math.sqrt(width * width + height * height));\n width = size;\n height = size;\n }\n\n var dx = tileResolution * width / 2 / tilePixelRatio;\n var dy = tileResolution * height / 2 / tilePixelRatio;\n var canvasExtent = [viewCenter[0] - dx, viewCenter[1] - dy, viewCenter[0] + dx, viewCenter[1] + dy];\n var tileRange = tileGrid.getTileRangeForExtentAndZ(extent, z);\n /**\n * @type {Object<number, Object<string, import("../../Tile.js").default>>}\n */\n\n var tilesToDrawByZ = {};\n tilesToDrawByZ[z] = {};\n var findLoadedTiles = this.createLoadedTileFinder(tileSource, projection, tilesToDrawByZ);\n var tmpExtent = this.tmpExtent;\n var tmpTileRange = this.tmpTileRange_;\n this.newTiles_ = false;\n\n for (var x = tileRange.minX; x <= tileRange.maxX; ++x) {\n for (var y = tileRange.minY; y <= tileRange.maxY; ++y) {\n var tile = this.getTile(z, x, y, frameState);\n\n if (this.isDrawableTile(tile)) {\n var uid = util_getUid(this);\n\n if (tile.getState() == TileState.LOADED) {\n tilesToDrawByZ[z][tile.tileCoord.toString()] = tile;\n var inTransition = tile.inTransition(uid);\n\n if (!this.newTiles_ && (inTransition || this.renderedTiles.indexOf(tile) === -1)) {\n this.newTiles_ = true;\n }\n }\n\n if (tile.getAlpha(uid, frameState.time) === 1) {\n // don\'t look for alt tiles if alpha is 1\n continue;\n }\n }\n\n var childTileRange = tileGrid.getTileCoordChildTileRange(tile.tileCoord, tmpTileRange, tmpExtent);\n var covered = false;\n\n if (childTileRange) {\n covered = findLoadedTiles(z + 1, childTileRange);\n }\n\n if (!covered) {\n tileGrid.forEachTileCoordParentTileRange(tile.tileCoord, findLoadedTiles, tmpTileRange, tmpExtent);\n }\n }\n }\n\n var canvasScale = tileResolution / viewResolution; // set forward and inverse pixel transforms\n\n compose(this.pixelTransform, frameState.size[0] / 2, frameState.size[1] / 2, 1 / tilePixelRatio, 1 / tilePixelRatio, rotation, -width / 2, -height / 2);\n var canvasTransform = createTransformString(this.pixelTransform);\n this.useContainer(target, canvasTransform, layerState.opacity);\n var context = this.context;\n var canvas = context.canvas;\n makeInverse(this.inversePixelTransform, this.pixelTransform); // set scale transform for calculating tile positions on the canvas\n\n compose(this.tempTransform, width / 2, height / 2, canvasScale, canvasScale, 0, -width / 2, -height / 2);\n\n if (canvas.width != width || canvas.height != height) {\n canvas.width = width;\n canvas.height = height;\n } else if (!this.containerReused) {\n context.clearRect(0, 0, width, height);\n }\n\n if (layerExtent) {\n this.clipUnrotated(context, frameState, layerExtent);\n }\n\n obj_assign(context, tileSource.getContextOptions());\n this.preRender(context, frameState);\n this.renderedTiles.length = 0;\n /** @type {Array<number>} */\n\n var zs = Object.keys(tilesToDrawByZ).map(Number);\n zs.sort(numberSafeCompareFunction);\n var clips, clipZs, currentClip;\n\n if (layerState.opacity === 1 && (!this.containerReused || tileSource.getOpaque(frameState.viewState.projection))) {\n zs = zs.reverse();\n } else {\n clips = [];\n clipZs = [];\n }\n\n for (var i = zs.length - 1; i >= 0; --i) {\n var currentZ = zs[i];\n var currentTilePixelSize = tileSource.getTilePixelSize(currentZ, pixelRatio, projection);\n var currentResolution = tileGrid.getResolution(currentZ);\n var currentScale = currentResolution / tileResolution;\n var dx_1 = currentTilePixelSize[0] * currentScale * canvasScale;\n var dy_1 = currentTilePixelSize[1] * currentScale * canvasScale;\n var originTileCoord = tileGrid.getTileCoordForCoordAndZ(getTopLeft(canvasExtent), currentZ);\n var originTileExtent = tileGrid.getTileCoordExtent(originTileCoord);\n var origin_1 = apply(this.tempTransform, [tilePixelRatio * (originTileExtent[0] - canvasExtent[0]) / tileResolution, tilePixelRatio * (canvasExtent[3] - originTileExtent[3]) / tileResolution]);\n var tileGutter = tilePixelRatio * tileSource.getGutterForProjection(projection);\n var tilesToDraw = tilesToDrawByZ[currentZ];\n\n for (var tileCoordKey in tilesToDraw) {\n var tile =\n /** @type {import("../../ImageTile.js").default} */\n tilesToDraw[tileCoordKey];\n var tileCoord = tile.tileCoord; // Calculate integer positions and sizes so that tiles align\n\n var floatX = origin_1[0] - (originTileCoord[1] - tileCoord[1]) * dx_1;\n var nextX = Math.round(floatX + dx_1);\n var floatY = origin_1[1] - (originTileCoord[2] - tileCoord[2]) * dy_1;\n var nextY = Math.round(floatY + dy_1);\n var x = Math.round(floatX);\n var y = Math.round(floatY);\n var w = nextX - x;\n var h = nextY - y;\n var transition = z === currentZ;\n var inTransition = transition && tile.getAlpha(util_getUid(this), frameState.time) !== 1;\n\n if (!inTransition) {\n if (clips) {\n // Clip mask for regions in this tile that already filled by a higher z tile\n context.save();\n currentClip = [x, y, x + w, y, x + w, y + h, x, y + h];\n\n for (var i_1 = 0, ii = clips.length; i_1 < ii; ++i_1) {\n if (z !== currentZ && currentZ < clipZs[i_1]) {\n var clip = clips[i_1];\n context.beginPath(); // counter-clockwise (outer ring) for current tile\n\n context.moveTo(currentClip[0], currentClip[1]);\n context.lineTo(currentClip[2], currentClip[3]);\n context.lineTo(currentClip[4], currentClip[5]);\n context.lineTo(currentClip[6], currentClip[7]); // clockwise (inner ring) for higher z tile\n\n context.moveTo(clip[6], clip[7]);\n context.lineTo(clip[4], clip[5]);\n context.lineTo(clip[2], clip[3]);\n context.lineTo(clip[0], clip[1]);\n context.clip();\n }\n }\n\n clips.push(currentClip);\n clipZs.push(currentZ);\n } else {\n context.clearRect(x, y, w, h);\n }\n }\n\n this.drawTileImage(tile, frameState, x, y, w, h, tileGutter, transition, layerState.opacity);\n\n if (clips && !inTransition) {\n context.restore();\n }\n\n this.renderedTiles.push(tile);\n this.updateUsedTiles(frameState.usedTiles, tileSource, tile);\n }\n }\n\n this.renderedRevision = sourceRevision;\n this.renderedResolution = tileResolution;\n this.extentChanged = !this.renderedExtent_ || !extent_equals(this.renderedExtent_, canvasExtent);\n this.renderedExtent_ = canvasExtent;\n this.renderedPixelRatio = pixelRatio;\n this.renderedProjection = projection;\n this.manageTilePyramid(frameState, tileSource, tileGrid, pixelRatio, projection, extent, z, tileLayer.getPreload());\n this.scheduleExpireCache(frameState, tileSource);\n this.postRender(context, frameState);\n\n if (layerState.extent) {\n context.restore();\n }\n\n if (canvasTransform !== canvas.style.transform) {\n canvas.style.transform = canvasTransform;\n }\n\n return this.container;\n };\n /**\n * @param {import("../../ImageTile.js").default} tile Tile.\n * @param {import("../../PluggableMap.js").FrameState} frameState Frame state.\n * @param {number} x Left of the tile.\n * @param {number} y Top of the tile.\n * @param {number} w Width of the tile.\n * @param {number} h Height of the tile.\n * @param {number} gutter Tile gutter.\n * @param {boolean} transition Apply an alpha transition.\n * @param {number} opacity Opacity.\n */\n\n\n CanvasTileLayerRenderer.prototype.drawTileImage = function (tile, frameState, x, y, w, h, gutter, transition, opacity) {\n var image = this.getTileImage(tile);\n\n if (!image) {\n return;\n }\n\n var uid = util_getUid(this);\n var tileAlpha = transition ? tile.getAlpha(uid, frameState.time) : 1;\n var alpha = opacity * tileAlpha;\n var alphaChanged = alpha !== this.context.globalAlpha;\n\n if (alphaChanged) {\n this.context.save();\n this.context.globalAlpha = alpha;\n }\n\n this.context.drawImage(image, gutter, gutter, image.width - 2 * gutter, image.height - 2 * gutter, x, y, w, h);\n\n if (alphaChanged) {\n this.context.restore();\n }\n\n if (tileAlpha !== 1) {\n frameState.animate = true;\n } else if (transition) {\n tile.endTransition(uid);\n }\n };\n /**\n * @return {HTMLCanvasElement} Image\n */\n\n\n CanvasTileLayerRenderer.prototype.getImage = function () {\n var context = this.context;\n return context ? context.canvas : null;\n };\n /**\n * Get the image from a tile.\n * @param {import("../../ImageTile.js").default} tile Tile.\n * @return {HTMLCanvasElement|HTMLImageElement|HTMLVideoElement} Image.\n * @protected\n */\n\n\n CanvasTileLayerRenderer.prototype.getTileImage = function (tile) {\n return tile.getImage();\n };\n /**\n * @param {import("../../PluggableMap.js").FrameState} frameState Frame state.\n * @param {import("../../source/Tile.js").default} tileSource Tile source.\n * @protected\n */\n\n\n CanvasTileLayerRenderer.prototype.scheduleExpireCache = function (frameState, tileSource) {\n if (tileSource.canExpireCache()) {\n /**\n * @param {import("../../source/Tile.js").default} tileSource Tile source.\n * @param {import("../../PluggableMap.js").default} map Map.\n * @param {import("../../PluggableMap.js").FrameState} frameState Frame state.\n */\n var postRenderFunction = function (tileSource, map, frameState) {\n var tileSourceKey = util_getUid(tileSource);\n\n if (tileSourceKey in frameState.usedTiles) {\n tileSource.expireCache(frameState.viewState.projection, frameState.usedTiles[tileSourceKey]);\n }\n }.bind(null, tileSource);\n\n frameState.postRenderFunctions.push(\n /** @type {import("../../PluggableMap.js").PostRenderFunction} */\n postRenderFunction);\n }\n };\n /**\n * @param {!Object<string, !Object<string, boolean>>} usedTiles Used tiles.\n * @param {import("../../source/Tile.js").default} tileSource Tile source.\n * @param {import(\'../../Tile.js\').default} tile Tile.\n * @protected\n */\n\n\n CanvasTileLayerRenderer.prototype.updateUsedTiles = function (usedTiles, tileSource, tile) {\n // FIXME should we use tilesToDrawByZ instead?\n var tileSourceKey = util_getUid(tileSource);\n\n if (!(tileSourceKey in usedTiles)) {\n usedTiles[tileSourceKey] = {};\n }\n\n usedTiles[tileSourceKey][tile.getKey()] = true;\n };\n /**\n * Manage tile pyramid.\n * This function performs a number of functions related to the tiles at the\n * current zoom and lower zoom levels:\n * - registers idle tiles in frameState.wantedTiles so that they are not\n * discarded by the tile queue\n * - enqueues missing tiles\n * @param {import("../../PluggableMap.js").FrameState} frameState Frame state.\n * @param {import("../../source/Tile.js").default} tileSource Tile source.\n * @param {import("../../tilegrid/TileGrid.js").default} tileGrid Tile grid.\n * @param {number} pixelRatio Pixel ratio.\n * @param {import("../../proj/Projection.js").default} projection Projection.\n * @param {import("../../extent.js").Extent} extent Extent.\n * @param {number} currentZ Current Z.\n * @param {number} preload Load low resolution tiles up to \'preload\' levels.\n * @param {function(import("../../Tile.js").default)=} opt_tileCallback Tile callback.\n * @protected\n */\n\n\n CanvasTileLayerRenderer.prototype.manageTilePyramid = function (frameState, tileSource, tileGrid, pixelRatio, projection, extent, currentZ, preload, opt_tileCallback) {\n var tileSourceKey = util_getUid(tileSource);\n\n if (!(tileSourceKey in frameState.wantedTiles)) {\n frameState.wantedTiles[tileSourceKey] = {};\n }\n\n var wantedTiles = frameState.wantedTiles[tileSourceKey];\n var tileQueue = frameState.tileQueue;\n var minZoom = tileGrid.getMinZoom();\n var tileCount = 0;\n var tile, tileRange, tileResolution, x, y, z;\n\n for (z = minZoom; z <= currentZ; ++z) {\n tileRange = tileGrid.getTileRangeForExtentAndZ(extent, z, tileRange);\n tileResolution = tileGrid.getResolution(z);\n\n for (x = tileRange.minX; x <= tileRange.maxX; ++x) {\n for (y = tileRange.minY; y <= tileRange.maxY; ++y) {\n if (currentZ - z <= preload) {\n ++tileCount;\n tile = tileSource.getTile(z, x, y, pixelRatio, projection);\n\n if (tile.getState() == TileState.IDLE) {\n wantedTiles[tile.getKey()] = true;\n\n if (!tileQueue.isKeyQueued(tile.getKey())) {\n tileQueue.enqueue([tile, tileSourceKey, tileGrid.getTileCoordCenter(tile.tileCoord), tileResolution]);\n }\n }\n\n if (opt_tileCallback !== undefined) {\n opt_tileCallback(tile);\n }\n } else {\n tileSource.useTile(z, x, y, projection);\n }\n }\n }\n }\n\n tileSource.updateCacheSize(tileCount, projection);\n };\n\n return CanvasTileLayerRenderer;\n}(canvas_Layer);\n/**\n * @function\n * @return {import("../../layer/Tile.js").default|import("../../layer/VectorTile.js").default}\n */\n\n\nCanvasTileLayerRenderer.prototype.getLayer;\n/* harmony default export */ var canvas_TileLayer = (CanvasTileLayerRenderer);\n;// CONCATENATED MODULE: ./node_modules/ol/layer/Tile.js\nvar Tile_extends = undefined && undefined.__extends || function () {\n var _extendStatics = function extendStatics(d, b) {\n _extendStatics = Object.setPrototypeOf || {\n __proto__: []\n } instanceof Array && function (d, b) {\n d.__proto__ = b;\n } || function (d, b) {\n for (var p in b) {\n if (Object.prototype.hasOwnProperty.call(b, p)) d[p] = b[p];\n }\n };\n\n return _extendStatics(d, b);\n };\n\n return function (d, b) {\n _extendStatics(d, b);\n\n function __() {\n this.constructor = d;\n }\n\n d.prototype = b === null ? Object.create(b) : (__.prototype = b.prototype, new __());\n };\n}();\n/**\n * @module ol/layer/Tile\n */\n\n\n\n\n/**\n * @classdesc\n * For layer sources that provide pre-rendered, tiled images in grids that are\n * organized by zoom levels for specific resolutions.\n * Note that any property set in the options is set as a {@link module:ol/Object~BaseObject}\n * property on the layer object; for example, setting `title: \'My Title\'` in the\n * options means that `title` is observable, and has get/set accessors.\n *\n * @api\n */\n\nvar TileLayer =\n/** @class */\nfunction (_super) {\n Tile_extends(TileLayer, _super);\n /**\n * @param {import("./BaseTile.js").Options=} opt_options Tile layer options.\n */\n\n\n function TileLayer(opt_options) {\n return _super.call(this, opt_options) || this;\n }\n /**\n * Create a renderer for this layer.\n * @return {import("../renderer/Layer.js").default} A layer renderer.\n * @protected\n */\n\n\n TileLayer.prototype.createRenderer = function () {\n return new canvas_TileLayer(this);\n };\n\n return TileLayer;\n}(BaseTile);\n\n/* harmony default export */ var Tile = (TileLayer);\n;// CONCATENATED MODULE: ./node_modules/ol/Tile.js\nvar ol_Tile_extends = undefined && undefined.__extends || function () {\n var _extendStatics = function extendStatics(d, b) {\n _extendStatics = Object.setPrototypeOf || {\n __proto__: []\n } instanceof Array && function (d, b) {\n d.__proto__ = b;\n } || function (d, b) {\n for (var p in b) {\n if (Object.prototype.hasOwnProperty.call(b, p)) d[p] = b[p];\n }\n };\n\n return _extendStatics(d, b);\n };\n\n return function (d, b) {\n _extendStatics(d, b);\n\n function __() {\n this.constructor = d;\n }\n\n d.prototype = b === null ? Object.create(b) : (__.prototype = b.prototype, new __());\n };\n}();\n/**\n * @module ol/Tile\n */\n\n\n\n\n\n\n\n/**\n * A function that takes an {@link module:ol/Tile} for the tile and a\n * `{string}` for the url as arguments. The default is\n * ```js\n * source.setTileLoadFunction(function(tile, src) {\n * tile.getImage().src = src;\n * });\n * ```\n * For more fine grained control, the load function can use fetch or XMLHttpRequest and involve\n * error handling:\n *\n * ```js\n * import TileState from \'ol/TileState\';\n *\n * source.setTileLoadFunction(function(tile, src) {\n * var xhr = new XMLHttpRequest();\n * xhr.responseType = \'blob\';\n * xhr.addEventListener(\'loadend\', function (evt) {\n * var data = this.response;\n * if (data !== undefined) {\n * tile.getImage().src = URL.createObjectURL(data);\n * } else {\n * tile.setState(TileState.ERROR);\n * }\n * });\n * xhr.addEventListener(\'error\', function () {\n * tile.setState(TileState.ERROR);\n * });\n * xhr.open(\'GET\', src);\n * xhr.send();\n * });\n * ```\n *\n * @typedef {function(Tile, string): void} LoadFunction\n * @api\n */\n\n/**\n * {@link module:ol/source/Tile~Tile} sources use a function of this type to get\n * the url that provides a tile for a given tile coordinate.\n *\n * This function takes an {@link module:ol/tilecoord~TileCoord} for the tile\n * coordinate, a `{number}` representing the pixel ratio and a\n * {@link module:ol/proj/Projection} for the projection as arguments\n * and returns a `{string}` representing the tile URL, or undefined if no tile\n * should be requested for the passed tile coordinate.\n *\n * @typedef {function(import("./tilecoord.js").TileCoord, number,\n * import("./proj/Projection.js").default): (string|undefined)} UrlFunction\n * @api\n */\n\n/**\n * @typedef {Object} Options\n * @property {number} [transition=250] A duration for tile opacity\n * transitions in milliseconds. A duration of 0 disables the opacity transition.\n * @api\n */\n\n/**\n * @classdesc\n * Base class for tiles.\n *\n * @abstract\n */\n\nvar Tile_Tile =\n/** @class */\nfunction (_super) {\n ol_Tile_extends(Tile, _super);\n /**\n * @param {import("./tilecoord.js").TileCoord} tileCoord Tile coordinate.\n * @param {import("./TileState.js").default} state State.\n * @param {Options=} opt_options Tile options.\n */\n\n\n function Tile(tileCoord, state, opt_options) {\n var _this = _super.call(this) || this;\n\n var options = opt_options ? opt_options : {};\n /**\n * @type {import("./tilecoord.js").TileCoord}\n */\n\n _this.tileCoord = tileCoord;\n /**\n * @protected\n * @type {import("./TileState.js").default}\n */\n\n _this.state = state;\n /**\n * An "interim" tile for this tile. The interim tile may be used while this\n * one is loading, for "smooth" transitions when changing params/dimensions\n * on the source.\n * @type {Tile}\n */\n\n _this.interimTile = null;\n /**\n * The tile is available at the highest possible resolution. Subclasses can\n * set this to `false` initially. Tile load listeners will not be\n * unregistered before this is set to `true` and a `#changed()` is called.\n * @type {boolean}\n */\n\n _this.hifi = true;\n /**\n * A key assigned to the tile. This is used by the tile source to determine\n * if this tile can effectively be used, or if a new tile should be created\n * and this one be used as an interim tile for this new tile.\n * @type {string}\n */\n\n _this.key = \'\';\n /**\n * The duration for the opacity transition.\n * @type {number}\n */\n\n _this.transition_ = options.transition === undefined ? 250 : options.transition;\n /**\n * Lookup of start times for rendering transitions. If the start time is\n * equal to -1, the transition is complete.\n * @type {Object<string, number>}\n */\n\n _this.transitionStarts_ = {};\n return _this;\n }\n /**\n * @protected\n */\n\n\n Tile.prototype.changed = function () {\n this.dispatchEvent(EventType.CHANGE);\n };\n /**\n * Called by the tile cache when the tile is removed from the cache due to expiry\n */\n\n\n Tile.prototype.release = function () {};\n /**\n * @return {string} Key.\n */\n\n\n Tile.prototype.getKey = function () {\n return this.key + \'/\' + this.tileCoord;\n };\n /**\n * Get the interim tile most suitable for rendering using the chain of interim\n * tiles. This corresponds to the most recent tile that has been loaded, if no\n * such tile exists, the original tile is returned.\n * @return {!Tile} Best tile for rendering.\n */\n\n\n Tile.prototype.getInterimTile = function () {\n if (!this.interimTile) {\n //empty chain\n return this;\n }\n\n var tile = this.interimTile; // find the first loaded tile and return it. Since the chain is sorted in\n // decreasing order of creation time, there is no need to search the remainder\n // of the list (all those tiles correspond to older requests and will be\n // cleaned up by refreshInterimChain)\n\n do {\n if (tile.getState() == TileState.LOADED) {\n // Show tile immediately instead of fading it in after loading, because\n // the interim tile is in place already\n this.transition_ = 0;\n return tile;\n }\n\n tile = tile.interimTile;\n } while (tile); // we can not find a better tile\n\n\n return this;\n };\n /**\n * Goes through the chain of interim tiles and discards sections of the chain\n * that are no longer relevant.\n */\n\n\n Tile.prototype.refreshInterimChain = function () {\n if (!this.interimTile) {\n return;\n }\n\n var tile = this.interimTile;\n var prev =\n /** @type {Tile} */\n this;\n\n do {\n if (tile.getState() == TileState.LOADED) {\n //we have a loaded tile, we can discard the rest of the list\n //we would could abort any LOADING tile request\n //older than this tile (i.e. any LOADING tile following this entry in the chain)\n tile.interimTile = null;\n break;\n } else if (tile.getState() == TileState.LOADING) {\n //keep this LOADING tile any loaded tiles later in the chain are\n //older than this tile, so we\'re still interested in the request\n prev = tile;\n } else if (tile.getState() == TileState.IDLE) {\n //the head of the list is the most current tile, we don\'t need\n //to start any other requests for this chain\n prev.interimTile = tile.interimTile;\n } else {\n prev = tile;\n }\n\n tile = prev.interimTile;\n } while (tile);\n };\n /**\n * Get the tile coordinate for this tile.\n * @return {import("./tilecoord.js").TileCoord} The tile coordinate.\n * @api\n */\n\n\n Tile.prototype.getTileCoord = function () {\n return this.tileCoord;\n };\n /**\n * @return {import("./TileState.js").default} State.\n */\n\n\n Tile.prototype.getState = function () {\n return this.state;\n };\n /**\n * Sets the state of this tile. If you write your own {@link module:ol/Tile~LoadFunction tileLoadFunction} ,\n * it is important to set the state correctly to {@link module:ol/TileState~ERROR}\n * when the tile cannot be loaded. Otherwise the tile cannot be removed from\n * the tile queue and will block other requests.\n * @param {import("./TileState.js").default} state State.\n * @api\n */\n\n\n Tile.prototype.setState = function (state) {\n if (this.state !== TileState.ERROR && this.state > state) {\n throw new Error(\'Tile load sequence violation\');\n }\n\n this.state = state;\n this.changed();\n };\n /**\n * Load the image or retry if loading previously failed.\n * Loading is taken care of by the tile queue, and calling this method is\n * only needed for preloading or for reloading in case of an error.\n * @abstract\n * @api\n */\n\n\n Tile.prototype.load = function () {\n util_abstract();\n };\n /**\n * Get the alpha value for rendering.\n * @param {string} id An id for the renderer.\n * @param {number} time The render frame time.\n * @return {number} A number between 0 and 1.\n */\n\n\n Tile.prototype.getAlpha = function (id, time) {\n if (!this.transition_) {\n return 1;\n }\n\n var start = this.transitionStarts_[id];\n\n if (!start) {\n start = time;\n this.transitionStarts_[id] = start;\n } else if (start === -1) {\n return 1;\n }\n\n var delta = time - start + 1000 / 60; // avoid rendering at 0\n\n if (delta >= this.transition_) {\n return 1;\n }\n\n return easeIn(delta / this.transition_);\n };\n /**\n * Determine if a tile is in an alpha transition. A tile is considered in\n * transition if tile.getAlpha() has not yet been called or has been called\n * and returned 1.\n * @param {string} id An id for the renderer.\n * @return {boolean} The tile is in transition.\n */\n\n\n Tile.prototype.inTransition = function (id) {\n if (!this.transition_) {\n return false;\n }\n\n return this.transitionStarts_[id] !== -1;\n };\n /**\n * Mark a transition as complete.\n * @param {string} id An id for the renderer.\n */\n\n\n Tile.prototype.endTransition = function (id) {\n if (this.transition_) {\n this.transitionStarts_[id] = -1;\n }\n };\n\n return Tile;\n}(events_Target);\n\n/* harmony default export */ var ol_Tile = (Tile_Tile);\n;// CONCATENATED MODULE: ./node_modules/ol/VectorTile.js\nvar VectorTile_extends = undefined && undefined.__extends || function () {\n var _extendStatics = function extendStatics(d, b) {\n _extendStatics = Object.setPrototypeOf || {\n __proto__: []\n } instanceof Array && function (d, b) {\n d.__proto__ = b;\n } || function (d, b) {\n for (var p in b) {\n if (Object.prototype.hasOwnProperty.call(b, p)) d[p] = b[p];\n }\n };\n\n return _extendStatics(d, b);\n };\n\n return function (d, b) {\n _extendStatics(d, b);\n\n function __() {\n this.constructor = d;\n }\n\n d.prototype = b === null ? Object.create(b) : (__.prototype = b.prototype, new __());\n };\n}();\n/**\n * @module ol/VectorTile\n */\n\n\n\n\n\nvar VectorTile =\n/** @class */\nfunction (_super) {\n VectorTile_extends(VectorTile, _super);\n /**\n * @param {import("./tilecoord.js").TileCoord} tileCoord Tile coordinate.\n * @param {import("./TileState.js").default} state State.\n * @param {string} src Data source url.\n * @param {import("./format/Feature.js").default} format Feature format.\n * @param {import("./Tile.js").LoadFunction} tileLoadFunction Tile load function.\n * @param {import("./Tile.js").Options=} opt_options Tile options.\n */\n\n\n function VectorTile(tileCoord, state, src, format, tileLoadFunction, opt_options) {\n var _this = _super.call(this, tileCoord, state, opt_options) || this;\n /**\n * Extent of this tile; set by the source.\n * @type {import("./extent.js").Extent}\n */\n\n\n _this.extent = null;\n /**\n * @private\n * @type {import("./format/Feature.js").default}\n */\n\n _this.format_ = format;\n /**\n * @private\n * @type {Array<import("./Feature.js").default>}\n */\n\n _this.features_ = null;\n /**\n * @private\n * @type {import("./featureloader.js").FeatureLoader}\n */\n\n _this.loader_;\n /**\n * Feature projection of this tile; set by the source.\n * @type {import("./proj/Projection.js").default}\n */\n\n _this.projection = null;\n /**\n * Resolution of this tile; set by the source.\n * @type {number}\n */\n\n _this.resolution;\n /**\n * @private\n * @type {import("./Tile.js").LoadFunction}\n */\n\n _this.tileLoadFunction_ = tileLoadFunction;\n /**\n * @private\n * @type {string}\n */\n\n _this.url_ = src;\n _this.key = src;\n return _this;\n }\n /**\n * Get the feature format assigned for reading this tile\'s features.\n * @return {import("./format/Feature.js").default} Feature format.\n * @api\n */\n\n\n VectorTile.prototype.getFormat = function () {\n return this.format_;\n };\n /**\n * Get the features for this tile. Geometries will be in the view projection.\n * @return {Array<import("./Feature.js").FeatureLike>} Features.\n * @api\n */\n\n\n VectorTile.prototype.getFeatures = function () {\n return this.features_;\n };\n /**\n * Load not yet loaded URI.\n */\n\n\n VectorTile.prototype.load = function () {\n if (this.state == TileState.IDLE) {\n this.setState(TileState.LOADING);\n this.tileLoadFunction_(this, this.url_);\n\n if (this.loader_) {\n this.loader_(this.extent, this.resolution, this.projection);\n }\n }\n };\n /**\n * Handler for successful tile load.\n * @param {Array<import("./Feature.js").default>} features The loaded features.\n * @param {import("./proj/Projection.js").default} dataProjection Data projection.\n */\n\n\n VectorTile.prototype.onLoad = function (features, dataProjection) {\n this.setFeatures(features);\n };\n /**\n * Handler for tile load errors.\n */\n\n\n VectorTile.prototype.onError = function () {\n this.setState(TileState.ERROR);\n };\n /**\n * Function for use in an {@link module:ol/source/VectorTile~VectorTile}\'s `tileLoadFunction`.\n * Sets the features for the tile.\n * @param {Array<import("./Feature.js").default>} features Features.\n * @api\n */\n\n\n VectorTile.prototype.setFeatures = function (features) {\n this.features_ = features;\n this.setState(TileState.LOADED);\n };\n /**\n * Set the feature loader for reading this tile\'s features.\n * @param {import("./featureloader.js").FeatureLoader} loader Feature loader.\n * @api\n */\n\n\n VectorTile.prototype.setLoader = function (loader) {\n this.loader_ = loader;\n };\n\n return VectorTile;\n}(ol_Tile);\n\n/* harmony default export */ var ol_VectorTile = (VectorTile);\n;// CONCATENATED MODULE: ./node_modules/ol/structs/LRUCache.js\n/**\n * @module ol/structs/LRUCache\n */\n\n/**\n * @typedef {Object} Entry\n * @property {string} key_\n * @property {Object} newer\n * @property {Object} older\n * @property {*} value_\n */\n\n/**\n * @classdesc\n * Implements a Least-Recently-Used cache where the keys do not conflict with\n * Object\'s properties (e.g. \'hasOwnProperty\' is not allowed as a key). Expiring\n * items from the cache is the responsibility of the user.\n *\n * @fires import("../events/Event.js").default\n * @template T\n */\n\nvar LRUCache =\n/** @class */\nfunction () {\n /**\n * @param {number=} opt_highWaterMark High water mark.\n */\n function LRUCache(opt_highWaterMark) {\n /**\n * Desired max cache size after expireCache(). If set to 0, no cache entries\n * will be pruned at all.\n * @type {number}\n */\n this.highWaterMark = opt_highWaterMark !== undefined ? opt_highWaterMark : 2048;\n /**\n * @private\n * @type {number}\n */\n\n this.count_ = 0;\n /**\n * @private\n * @type {!Object<string, Entry>}\n */\n\n this.entries_ = {};\n /**\n * @private\n * @type {?Entry}\n */\n\n this.oldest_ = null;\n /**\n * @private\n * @type {?Entry}\n */\n\n this.newest_ = null;\n }\n /**\n * @return {boolean} Can expire cache.\n */\n\n\n LRUCache.prototype.canExpireCache = function () {\n return this.highWaterMark > 0 && this.getCount() > this.highWaterMark;\n };\n /**\n * FIXME empty description for jsdoc\n */\n\n\n LRUCache.prototype.clear = function () {\n this.count_ = 0;\n this.entries_ = {};\n this.oldest_ = null;\n this.newest_ = null;\n };\n /**\n * @param {string} key Key.\n * @return {boolean} Contains key.\n */\n\n\n LRUCache.prototype.containsKey = function (key) {\n return this.entries_.hasOwnProperty(key);\n };\n /**\n * @param {function(T, string, LRUCache<T>): ?} f The function\n * to call for every entry from the oldest to the newer. This function takes\n * 3 arguments (the entry value, the entry key and the LRUCache object).\n * The return value is ignored.\n */\n\n\n LRUCache.prototype.forEach = function (f) {\n var entry = this.oldest_;\n\n while (entry) {\n f(entry.value_, entry.key_, this);\n entry = entry.newer;\n }\n };\n /**\n * @param {string} key Key.\n * @param {*=} opt_options Options (reserverd for subclasses).\n * @return {T} Value.\n */\n\n\n LRUCache.prototype.get = function (key, opt_options) {\n var entry = this.entries_[key];\n asserts_assert(entry !== undefined, 15); // Tried to get a value for a key that does not exist in the cache\n\n if (entry === this.newest_) {\n return entry.value_;\n } else if (entry === this.oldest_) {\n this.oldest_ =\n /** @type {Entry} */\n this.oldest_.newer;\n this.oldest_.older = null;\n } else {\n entry.newer.older = entry.older;\n entry.older.newer = entry.newer;\n }\n\n entry.newer = null;\n entry.older = this.newest_;\n this.newest_.newer = entry;\n this.newest_ = entry;\n return entry.value_;\n };\n /**\n * Remove an entry from the cache.\n * @param {string} key The entry key.\n * @return {T} The removed entry.\n */\n\n\n LRUCache.prototype.remove = function (key) {\n var entry = this.entries_[key];\n asserts_assert(entry !== undefined, 15); // Tried to get a value for a key that does not exist in the cache\n\n if (entry === this.newest_) {\n this.newest_ =\n /** @type {Entry} */\n entry.older;\n\n if (this.newest_) {\n this.newest_.newer = null;\n }\n } else if (entry === this.oldest_) {\n this.oldest_ =\n /** @type {Entry} */\n entry.newer;\n\n if (this.oldest_) {\n this.oldest_.older = null;\n }\n } else {\n entry.newer.older = entry.older;\n entry.older.newer = entry.newer;\n }\n\n delete this.entries_[key];\n --this.count_;\n return entry.value_;\n };\n /**\n * @return {number} Count.\n */\n\n\n LRUCache.prototype.getCount = function () {\n return this.count_;\n };\n /**\n * @return {Array<string>} Keys.\n */\n\n\n LRUCache.prototype.getKeys = function () {\n var keys = new Array(this.count_);\n var i = 0;\n var entry;\n\n for (entry = this.newest_; entry; entry = entry.older) {\n keys[i++] = entry.key_;\n }\n\n return keys;\n };\n /**\n * @return {Array<T>} Values.\n */\n\n\n LRUCache.prototype.getValues = function () {\n var values = new Array(this.count_);\n var i = 0;\n var entry;\n\n for (entry = this.newest_; entry; entry = entry.older) {\n values[i++] = entry.value_;\n }\n\n return values;\n };\n /**\n * @return {T} Last value.\n */\n\n\n LRUCache.prototype.peekLast = function () {\n return this.oldest_.value_;\n };\n /**\n * @return {string} Last key.\n */\n\n\n LRUCache.prototype.peekLastKey = function () {\n return this.oldest_.key_;\n };\n /**\n * Get the key of the newest item in the cache. Throws if the cache is empty.\n * @return {string} The newest key.\n */\n\n\n LRUCache.prototype.peekFirstKey = function () {\n return this.newest_.key_;\n };\n /**\n * @return {T} value Value.\n */\n\n\n LRUCache.prototype.pop = function () {\n var entry = this.oldest_;\n delete this.entries_[entry.key_];\n\n if (entry.newer) {\n entry.newer.older = null;\n }\n\n this.oldest_ =\n /** @type {Entry} */\n entry.newer;\n\n if (!this.oldest_) {\n this.newest_ = null;\n }\n\n --this.count_;\n return entry.value_;\n };\n /**\n * @param {string} key Key.\n * @param {T} value Value.\n */\n\n\n LRUCache.prototype.replace = function (key, value) {\n this.get(key); // update `newest_`\n\n this.entries_[key].value_ = value;\n };\n /**\n * @param {string} key Key.\n * @param {T} value Value.\n */\n\n\n LRUCache.prototype.set = function (key, value) {\n asserts_assert(!(key in this.entries_), 16); // Tried to set a value for a key that is used already\n\n var entry = {\n key_: key,\n newer: null,\n older: this.newest_,\n value_: value\n };\n\n if (!this.newest_) {\n this.oldest_ = entry;\n } else {\n this.newest_.newer = entry;\n }\n\n this.newest_ = entry;\n this.entries_[key] = entry;\n ++this.count_;\n };\n /**\n * Set a maximum number of entries for the cache.\n * @param {number} size Cache size.\n * @api\n */\n\n\n LRUCache.prototype.setSize = function (size) {\n this.highWaterMark = size;\n };\n\n return LRUCache;\n}();\n\n/* harmony default export */ var structs_LRUCache = (LRUCache);\n;// CONCATENATED MODULE: ./node_modules/ol/tilecoord.js\n/**\n * @module ol/tilecoord\n */\n\n/**\n * An array of three numbers representing the location of a tile in a tile\n * grid. The order is `z` (zoom level), `x` (column), and `y` (row).\n * @typedef {Array<number>} TileCoord\n * @api\n */\n\n/**\n * @param {number} z Z.\n * @param {number} x X.\n * @param {number} y Y.\n * @param {TileCoord=} opt_tileCoord Tile coordinate.\n * @return {TileCoord} Tile coordinate.\n */\nfunction tilecoord_createOrUpdate(z, x, y, opt_tileCoord) {\n if (opt_tileCoord !== undefined) {\n opt_tileCoord[0] = z;\n opt_tileCoord[1] = x;\n opt_tileCoord[2] = y;\n return opt_tileCoord;\n } else {\n return [z, x, y];\n }\n}\n/**\n * @param {number} z Z.\n * @param {number} x X.\n * @param {number} y Y.\n * @return {string} Key.\n */\n\nfunction getKeyZXY(z, x, y) {\n return z + \'/\' + x + \'/\' + y;\n}\n/**\n * Get the key for a tile coord.\n * @param {TileCoord} tileCoord The tile coord.\n * @return {string} Key.\n */\n\nfunction tilecoord_getKey(tileCoord) {\n return getKeyZXY(tileCoord[0], tileCoord[1], tileCoord[2]);\n}\n/**\n * Get a tile coord given a key.\n * @param {string} key The tile coord key.\n * @return {TileCoord} The tile coord.\n */\n\nfunction fromKey(key) {\n return key.split(\'/\').map(Number);\n}\n/**\n * @param {TileCoord} tileCoord Tile coord.\n * @return {number} Hash.\n */\n\nfunction hash(tileCoord) {\n return (tileCoord[1] << tileCoord[0]) + tileCoord[2];\n}\n/**\n * @param {TileCoord} tileCoord Tile coordinate.\n * @param {!import("./tilegrid/TileGrid.js").default} tileGrid Tile grid.\n * @return {boolean} Tile coordinate is within extent and zoom level range.\n */\n\nfunction withinExtentAndZ(tileCoord, tileGrid) {\n var z = tileCoord[0];\n var x = tileCoord[1];\n var y = tileCoord[2];\n\n if (tileGrid.getMinZoom() > z || z > tileGrid.getMaxZoom()) {\n return false;\n }\n\n var tileRange = tileGrid.getFullTileRange(z);\n\n if (!tileRange) {\n return true;\n } else {\n return tileRange.containsXY(x, y);\n }\n}\n;// CONCATENATED MODULE: ./node_modules/ol/TileCache.js\nvar TileCache_extends = undefined && undefined.__extends || function () {\n var _extendStatics = function extendStatics(d, b) {\n _extendStatics = Object.setPrototypeOf || {\n __proto__: []\n } instanceof Array && function (d, b) {\n d.__proto__ = b;\n } || function (d, b) {\n for (var p in b) {\n if (Object.prototype.hasOwnProperty.call(b, p)) d[p] = b[p];\n }\n };\n\n return _extendStatics(d, b);\n };\n\n return function (d, b) {\n _extendStatics(d, b);\n\n function __() {\n this.constructor = d;\n }\n\n d.prototype = b === null ? Object.create(b) : (__.prototype = b.prototype, new __());\n };\n}();\n/**\n * @module ol/TileCache\n */\n\n\n\n\n\nvar TileCache =\n/** @class */\nfunction (_super) {\n TileCache_extends(TileCache, _super);\n\n function TileCache() {\n return _super !== null && _super.apply(this, arguments) || this;\n }\n /**\n * @param {!Object<string, boolean>} usedTiles Used tiles.\n */\n\n\n TileCache.prototype.expireCache = function (usedTiles) {\n while (this.canExpireCache()) {\n var tile = this.peekLast();\n\n if (tile.getKey() in usedTiles) {\n break;\n } else {\n this.pop().release();\n }\n }\n };\n /**\n * Prune all tiles from the cache that don\'t have the same z as the newest tile.\n */\n\n\n TileCache.prototype.pruneExceptNewestZ = function () {\n if (this.getCount() === 0) {\n return;\n }\n\n var key = this.peekFirstKey();\n var tileCoord = fromKey(key);\n var z = tileCoord[0];\n this.forEach(function (tile) {\n if (tile.tileCoord[0] !== z) {\n this.remove(tilecoord_getKey(tile.tileCoord));\n tile.release();\n }\n }.bind(this));\n };\n\n return TileCache;\n}(structs_LRUCache);\n\n/* harmony default export */ var ol_TileCache = (TileCache);\n;// CONCATENATED MODULE: ./node_modules/ol/source/TileEventType.js\n/**\n * @module ol/source/TileEventType\n */\n\n/**\n * @enum {string}\n */\n/* harmony default export */ var TileEventType = ({\n /**\n * Triggered when a tile starts loading.\n * @event module:ol/source/Tile.TileSourceEvent#tileloadstart\n * @api\n */\n TILELOADSTART: \'tileloadstart\',\n\n /**\n * Triggered when a tile finishes loading, either when its data is loaded,\n * or when loading was aborted because the tile is no longer needed.\n * @event module:ol/source/Tile.TileSourceEvent#tileloadend\n * @api\n */\n TILELOADEND: \'tileloadend\',\n\n /**\n * Triggered if tile loading results in an error.\n * @event module:ol/source/Tile.TileSourceEvent#tileloaderror\n * @api\n */\n TILELOADERROR: \'tileloaderror\'\n});\n;// CONCATENATED MODULE: ./node_modules/ol/source/Source.js\nvar Source_extends = undefined && undefined.__extends || function () {\n var _extendStatics = function extendStatics(d, b) {\n _extendStatics = Object.setPrototypeOf || {\n __proto__: []\n } instanceof Array && function (d, b) {\n d.__proto__ = b;\n } || function (d, b) {\n for (var p in b) {\n if (Object.prototype.hasOwnProperty.call(b, p)) d[p] = b[p];\n }\n };\n\n return _extendStatics(d, b);\n };\n\n return function (d, b) {\n _extendStatics(d, b);\n\n function __() {\n this.constructor = d;\n }\n\n d.prototype = b === null ? Object.create(b) : (__.prototype = b.prototype, new __());\n };\n}();\n/**\n * @module ol/source/Source\n */\n\n\n\n\n\n\n/**\n * A function that returns a string or an array of strings representing source\n * attributions.\n *\n * @typedef {function(import("../PluggableMap.js").FrameState): (string|Array<string>)} Attribution\n */\n\n/**\n * A type that can be used to provide attribution information for data sources.\n *\n * It represents either\n * * a simple string (e.g. `\'© Acme Inc.\'`)\n * * an array of simple strings (e.g. `[\'© Acme Inc.\', \'© Bacme Inc.\']`)\n * * a function that returns a string or array of strings ({@link module:ol/source/Source~Attribution})\n *\n * @typedef {string|Array<string>|Attribution} AttributionLike\n */\n\n/**\n * @typedef {Object} Options\n * @property {AttributionLike} [attributions]\n * @property {boolean} [attributionsCollapsible=true] Attributions are collapsible.\n * @property {import("../proj.js").ProjectionLike} [projection] Projection. Default is the view projection.\n * @property {import("./State.js").default} [state=\'ready\']\n * @property {boolean} [wrapX=false]\n */\n\n/**\n * @classdesc\n * Abstract base class; normally only used for creating subclasses and not\n * instantiated in apps.\n * Base class for {@link module:ol/layer/Layer~Layer} sources.\n *\n * A generic `change` event is triggered when the state of the source changes.\n * @abstract\n * @api\n */\n\nvar Source =\n/** @class */\nfunction (_super) {\n Source_extends(Source, _super);\n /**\n * @param {Options} options Source options.\n */\n\n\n function Source(options) {\n var _this = _super.call(this) || this;\n /**\n * @private\n * @type {import("../proj/Projection.js").default}\n */\n\n\n _this.projection_ = proj_get(options.projection);\n /**\n * @private\n * @type {?Attribution}\n */\n\n _this.attributions_ = adaptAttributions(options.attributions);\n /**\n * @private\n * @type {boolean}\n */\n\n _this.attributionsCollapsible_ = options.attributionsCollapsible !== undefined ? options.attributionsCollapsible : true;\n /**\n * This source is currently loading data. Sources that defer loading to the\n * map\'s tile queue never set this to `true`.\n * @type {boolean}\n */\n\n _this.loading = false;\n /**\n * @private\n * @type {import("./State.js").default}\n */\n\n _this.state_ = options.state !== undefined ? options.state : State.READY;\n /**\n * @private\n * @type {boolean}\n */\n\n _this.wrapX_ = options.wrapX !== undefined ? options.wrapX : false;\n return _this;\n }\n /**\n * Get the attribution function for the source.\n * @return {?Attribution} Attribution function.\n */\n\n\n Source.prototype.getAttributions = function () {\n return this.attributions_;\n };\n /**\n * @return {boolean} Attributions are collapsible.\n */\n\n\n Source.prototype.getAttributionsCollapsible = function () {\n return this.attributionsCollapsible_;\n };\n /**\n * Get the projection of the source.\n * @return {import("../proj/Projection.js").default} Projection.\n * @api\n */\n\n\n Source.prototype.getProjection = function () {\n return this.projection_;\n };\n /**\n * @abstract\n * @return {Array<number>|undefined} Resolutions.\n */\n\n\n Source.prototype.getResolutions = function () {\n return util_abstract();\n };\n /**\n * Get the state of the source, see {@link module:ol/source/State~State} for possible states.\n * @return {import("./State.js").default} State.\n * @api\n */\n\n\n Source.prototype.getState = function () {\n return this.state_;\n };\n /**\n * @return {boolean|undefined} Wrap X.\n */\n\n\n Source.prototype.getWrapX = function () {\n return this.wrapX_;\n };\n /**\n * @return {Object|undefined} Context options.\n */\n\n\n Source.prototype.getContextOptions = function () {\n return undefined;\n };\n /**\n * Refreshes the source. The source will be cleared, and data from the server will be reloaded.\n * @api\n */\n\n\n Source.prototype.refresh = function () {\n this.changed();\n };\n /**\n * Set the attributions of the source.\n * @param {AttributionLike|undefined} attributions Attributions.\n * Can be passed as `string`, `Array<string>`, {@link module:ol/source/Source~Attribution},\n * or `undefined`.\n * @api\n */\n\n\n Source.prototype.setAttributions = function (attributions) {\n this.attributions_ = adaptAttributions(attributions);\n this.changed();\n };\n /**\n * Set the state of the source.\n * @param {import("./State.js").default} state State.\n */\n\n\n Source.prototype.setState = function (state) {\n this.state_ = state;\n this.changed();\n };\n\n return Source;\n}(ol_Object);\n/**\n * Turns the attributions option into an attributions function.\n * @param {AttributionLike|undefined} attributionLike The attribution option.\n * @return {?Attribution} An attribution function (or null).\n */\n\n\nfunction adaptAttributions(attributionLike) {\n if (!attributionLike) {\n return null;\n }\n\n if (Array.isArray(attributionLike)) {\n return function (frameState) {\n return attributionLike;\n };\n }\n\n if (typeof attributionLike === \'function\') {\n return attributionLike;\n }\n\n return function (frameState) {\n return [attributionLike];\n };\n}\n\n/* harmony default export */ var source_Source = (Source);\n;// CONCATENATED MODULE: ./node_modules/ol/tilegrid/TileGrid.js\n/**\n * @module ol/tilegrid/TileGrid\n */\n\n\n\n\n\n\n\n\n/**\n * @private\n * @type {import("../tilecoord.js").TileCoord}\n */\n\nvar tmpTileCoord = [0, 0, 0];\n/**\n * @typedef {Object} Options\n * @property {import("../extent.js").Extent} [extent] Extent for the tile grid. No tiles outside this\n * extent will be requested by {@link module:ol/source/Tile} sources. When no `origin` or\n * `origins` are configured, the `origin` will be set to the top-left corner of the extent.\n * @property {number} [minZoom=0] Minimum zoom.\n * @property {import("../coordinate.js").Coordinate} [origin] The tile grid origin, i.e. where the `x`\n * and `y` axes meet (`[z, 0, 0]`). Tile coordinates increase left to right and downwards. If not\n * specified, `extent` or `origins` must be provided.\n * @property {Array<import("../coordinate.js").Coordinate>} [origins] Tile grid origins, i.e. where\n * the `x` and `y` axes meet (`[z, 0, 0]`), for each zoom level. If given, the array length\n * should match the length of the `resolutions` array, i.e. each resolution can have a different\n * origin. Tile coordinates increase left to right and downwards. If not specified, `extent` or\n * `origin` must be provided.\n * @property {!Array<number>} resolutions Resolutions. The array index of each resolution needs\n * to match the zoom level. This means that even if a `minZoom` is configured, the resolutions\n * array will have a length of `maxZoom + 1`.\n * @property {Array<import("../size.js").Size>} [sizes] Number of tile rows and columns\n * of the grid for each zoom level. If specified the values\n * define each zoom level\'s extent together with the `origin` or `origins`.\n * A grid `extent` can be configured in addition, and will further limit the extent\n * for which tile requests are made by sources. If the bottom-left corner of\n * an extent is used as `origin` or `origins`, then the `y` value must be\n * negative because OpenLayers tile coordinates use the top left as the origin.\n * @property {number|import("../size.js").Size} [tileSize] Tile size.\n * Default is `[256, 256]`.\n * @property {Array<import("../size.js").Size>} [tileSizes] Tile sizes. If given, the array length\n * should match the length of the `resolutions` array, i.e. each resolution can have a different\n * tile size.\n */\n\n/**\n * @classdesc\n * Base class for setting the grid pattern for sources accessing tiled-image\n * servers.\n * @api\n */\n\nvar TileGrid =\n/** @class */\nfunction () {\n /**\n * @param {Options} options Tile grid options.\n */\n function TileGrid(options) {\n /**\n * @protected\n * @type {number}\n */\n this.minZoom = options.minZoom !== undefined ? options.minZoom : 0;\n /**\n * @private\n * @type {!Array<number>}\n */\n\n this.resolutions_ = options.resolutions;\n asserts_assert(isSorted(this.resolutions_, function (a, b) {\n return b - a;\n }, true), 17); // `resolutions` must be sorted in descending order\n // check if we\'ve got a consistent zoom factor and origin\n\n var zoomFactor;\n\n if (!options.origins) {\n for (var i = 0, ii = this.resolutions_.length - 1; i < ii; ++i) {\n if (!zoomFactor) {\n zoomFactor = this.resolutions_[i] / this.resolutions_[i + 1];\n } else {\n if (this.resolutions_[i] / this.resolutions_[i + 1] !== zoomFactor) {\n zoomFactor = undefined;\n break;\n }\n }\n }\n }\n /**\n * @private\n * @type {number|undefined}\n */\n\n\n this.zoomFactor_ = zoomFactor;\n /**\n * @protected\n * @type {number}\n */\n\n this.maxZoom = this.resolutions_.length - 1;\n /**\n * @private\n * @type {import("../coordinate.js").Coordinate}\n */\n\n this.origin_ = options.origin !== undefined ? options.origin : null;\n /**\n * @private\n * @type {Array<import("../coordinate.js").Coordinate>}\n */\n\n this.origins_ = null;\n\n if (options.origins !== undefined) {\n this.origins_ = options.origins;\n asserts_assert(this.origins_.length == this.resolutions_.length, 20); // Number of `origins` and `resolutions` must be equal\n }\n\n var extent = options.extent;\n\n if (extent !== undefined && !this.origin_ && !this.origins_) {\n this.origin_ = getTopLeft(extent);\n }\n\n asserts_assert(!this.origin_ && this.origins_ || this.origin_ && !this.origins_, 18); // Either `origin` or `origins` must be configured, never both\n\n /**\n * @private\n * @type {Array<number|import("../size.js").Size>}\n */\n\n this.tileSizes_ = null;\n\n if (options.tileSizes !== undefined) {\n this.tileSizes_ = options.tileSizes;\n asserts_assert(this.tileSizes_.length == this.resolutions_.length, 19); // Number of `tileSizes` and `resolutions` must be equal\n }\n /**\n * @private\n * @type {number|import("../size.js").Size}\n */\n\n\n this.tileSize_ = options.tileSize !== undefined ? options.tileSize : !this.tileSizes_ ? DEFAULT_TILE_SIZE : null;\n asserts_assert(!this.tileSize_ && this.tileSizes_ || this.tileSize_ && !this.tileSizes_, 22); // Either `tileSize` or `tileSizes` must be configured, never both\n\n /**\n * @private\n * @type {import("../extent.js").Extent}\n */\n\n this.extent_ = extent !== undefined ? extent : null;\n /**\n * @private\n * @type {Array<import("../TileRange.js").default>}\n */\n\n this.fullTileRanges_ = null;\n /**\n * @private\n * @type {import("../size.js").Size}\n */\n\n this.tmpSize_ = [0, 0];\n\n if (options.sizes !== undefined) {\n this.fullTileRanges_ = options.sizes.map(function (size, z) {\n var tileRange = new ol_TileRange(Math.min(0, size[0]), Math.max(size[0] - 1, -1), Math.min(0, size[1]), Math.max(size[1] - 1, -1));\n\n if (extent) {\n var restrictedTileRange = this.getTileRangeForExtentAndZ(extent, z);\n tileRange.minX = Math.max(restrictedTileRange.minX, tileRange.minX);\n tileRange.maxX = Math.min(restrictedTileRange.maxX, tileRange.maxX);\n tileRange.minY = Math.max(restrictedTileRange.minY, tileRange.minY);\n tileRange.maxY = Math.min(restrictedTileRange.maxY, tileRange.maxY);\n }\n\n return tileRange;\n }, this);\n } else if (extent) {\n this.calculateTileRanges_(extent);\n }\n }\n /**\n * Call a function with each tile coordinate for a given extent and zoom level.\n *\n * @param {import("../extent.js").Extent} extent Extent.\n * @param {number} zoom Integer zoom level.\n * @param {function(import("../tilecoord.js").TileCoord): void} callback Function called with each tile coordinate.\n * @api\n */\n\n\n TileGrid.prototype.forEachTileCoord = function (extent, zoom, callback) {\n var tileRange = this.getTileRangeForExtentAndZ(extent, zoom);\n\n for (var i = tileRange.minX, ii = tileRange.maxX; i <= ii; ++i) {\n for (var j = tileRange.minY, jj = tileRange.maxY; j <= jj; ++j) {\n callback([zoom, i, j]);\n }\n }\n };\n /**\n * @param {import("../tilecoord.js").TileCoord} tileCoord Tile coordinate.\n * @param {function(number, import("../TileRange.js").default): boolean} callback Callback.\n * @param {import("../TileRange.js").default=} opt_tileRange Temporary import("../TileRange.js").default object.\n * @param {import("../extent.js").Extent=} opt_extent Temporary import("../extent.js").Extent object.\n * @return {boolean} Callback succeeded.\n */\n\n\n TileGrid.prototype.forEachTileCoordParentTileRange = function (tileCoord, callback, opt_tileRange, opt_extent) {\n var tileRange, x, y;\n var tileCoordExtent = null;\n var z = tileCoord[0] - 1;\n\n if (this.zoomFactor_ === 2) {\n x = tileCoord[1];\n y = tileCoord[2];\n } else {\n tileCoordExtent = this.getTileCoordExtent(tileCoord, opt_extent);\n }\n\n while (z >= this.minZoom) {\n if (this.zoomFactor_ === 2) {\n x = Math.floor(x / 2);\n y = Math.floor(y / 2);\n tileRange = TileRange_createOrUpdate(x, x, y, y, opt_tileRange);\n } else {\n tileRange = this.getTileRangeForExtentAndZ(tileCoordExtent, z, opt_tileRange);\n }\n\n if (callback(z, tileRange)) {\n return true;\n }\n\n --z;\n }\n\n return false;\n };\n /**\n * Get the extent for this tile grid, if it was configured.\n * @return {import("../extent.js").Extent} Extent.\n * @api\n */\n\n\n TileGrid.prototype.getExtent = function () {\n return this.extent_;\n };\n /**\n * Get the maximum zoom level for the grid.\n * @return {number} Max zoom.\n * @api\n */\n\n\n TileGrid.prototype.getMaxZoom = function () {\n return this.maxZoom;\n };\n /**\n * Get the minimum zoom level for the grid.\n * @return {number} Min zoom.\n * @api\n */\n\n\n TileGrid.prototype.getMinZoom = function () {\n return this.minZoom;\n };\n /**\n * Get the origin for the grid at the given zoom level.\n * @param {number} z Integer zoom level.\n * @return {import("../coordinate.js").Coordinate} Origin.\n * @api\n */\n\n\n TileGrid.prototype.getOrigin = function (z) {\n if (this.origin_) {\n return this.origin_;\n } else {\n return this.origins_[z];\n }\n };\n /**\n * Get the resolution for the given zoom level.\n * @param {number} z Integer zoom level.\n * @return {number} Resolution.\n * @api\n */\n\n\n TileGrid.prototype.getResolution = function (z) {\n return this.resolutions_[z];\n };\n /**\n * Get the list of resolutions for the tile grid.\n * @return {Array<number>} Resolutions.\n * @api\n */\n\n\n TileGrid.prototype.getResolutions = function () {\n return this.resolutions_;\n };\n /**\n * @param {import("../tilecoord.js").TileCoord} tileCoord Tile coordinate.\n * @param {import("../TileRange.js").default=} opt_tileRange Temporary import("../TileRange.js").default object.\n * @param {import("../extent.js").Extent=} opt_extent Temporary import("../extent.js").Extent object.\n * @return {import("../TileRange.js").default} Tile range.\n */\n\n\n TileGrid.prototype.getTileCoordChildTileRange = function (tileCoord, opt_tileRange, opt_extent) {\n if (tileCoord[0] < this.maxZoom) {\n if (this.zoomFactor_ === 2) {\n var minX = tileCoord[1] * 2;\n var minY = tileCoord[2] * 2;\n return TileRange_createOrUpdate(minX, minX + 1, minY, minY + 1, opt_tileRange);\n }\n\n var tileCoordExtent = this.getTileCoordExtent(tileCoord, opt_extent);\n return this.getTileRangeForExtentAndZ(tileCoordExtent, tileCoord[0] + 1, opt_tileRange);\n }\n\n return null;\n };\n /**\n * Get the extent for a tile range.\n * @param {number} z Integer zoom level.\n * @param {import("../TileRange.js").default} tileRange Tile range.\n * @param {import("../extent.js").Extent=} opt_extent Temporary import("../extent.js").Extent object.\n * @return {import("../extent.js").Extent} Extent.\n */\n\n\n TileGrid.prototype.getTileRangeExtent = function (z, tileRange, opt_extent) {\n var origin = this.getOrigin(z);\n var resolution = this.getResolution(z);\n var tileSize = toSize(this.getTileSize(z), this.tmpSize_);\n var minX = origin[0] + tileRange.minX * tileSize[0] * resolution;\n var maxX = origin[0] + (tileRange.maxX + 1) * tileSize[0] * resolution;\n var minY = origin[1] + tileRange.minY * tileSize[1] * resolution;\n var maxY = origin[1] + (tileRange.maxY + 1) * tileSize[1] * resolution;\n return createOrUpdate(minX, minY, maxX, maxY, opt_extent);\n };\n /**\n * Get a tile range for the given extent and integer zoom level.\n * @param {import("../extent.js").Extent} extent Extent.\n * @param {number} z Integer zoom level.\n * @param {import("../TileRange.js").default=} opt_tileRange Temporary tile range object.\n * @return {import("../TileRange.js").default} Tile range.\n */\n\n\n TileGrid.prototype.getTileRangeForExtentAndZ = function (extent, z, opt_tileRange) {\n var tileCoord = tmpTileCoord;\n this.getTileCoordForXYAndZ_(extent[0], extent[3], z, false, tileCoord);\n var minX = tileCoord[1];\n var minY = tileCoord[2];\n this.getTileCoordForXYAndZ_(extent[2], extent[1], z, true, tileCoord);\n return TileRange_createOrUpdate(minX, tileCoord[1], minY, tileCoord[2], opt_tileRange);\n };\n /**\n * @param {import("../tilecoord.js").TileCoord} tileCoord Tile coordinate.\n * @return {import("../coordinate.js").Coordinate} Tile center.\n */\n\n\n TileGrid.prototype.getTileCoordCenter = function (tileCoord) {\n var origin = this.getOrigin(tileCoord[0]);\n var resolution = this.getResolution(tileCoord[0]);\n var tileSize = toSize(this.getTileSize(tileCoord[0]), this.tmpSize_);\n return [origin[0] + (tileCoord[1] + 0.5) * tileSize[0] * resolution, origin[1] - (tileCoord[2] + 0.5) * tileSize[1] * resolution];\n };\n /**\n * Get the extent of a tile coordinate.\n *\n * @param {import("../tilecoord.js").TileCoord} tileCoord Tile coordinate.\n * @param {import("../extent.js").Extent=} opt_extent Temporary extent object.\n * @return {import("../extent.js").Extent} Extent.\n * @api\n */\n\n\n TileGrid.prototype.getTileCoordExtent = function (tileCoord, opt_extent) {\n var origin = this.getOrigin(tileCoord[0]);\n var resolution = this.getResolution(tileCoord[0]);\n var tileSize = toSize(this.getTileSize(tileCoord[0]), this.tmpSize_);\n var minX = origin[0] + tileCoord[1] * tileSize[0] * resolution;\n var minY = origin[1] - (tileCoord[2] + 1) * tileSize[1] * resolution;\n var maxX = minX + tileSize[0] * resolution;\n var maxY = minY + tileSize[1] * resolution;\n return createOrUpdate(minX, minY, maxX, maxY, opt_extent);\n };\n /**\n * Get the tile coordinate for the given map coordinate and resolution. This\n * method considers that coordinates that intersect tile boundaries should be\n * assigned the higher tile coordinate.\n *\n * @param {import("../coordinate.js").Coordinate} coordinate Coordinate.\n * @param {number} resolution Resolution.\n * @param {import("../tilecoord.js").TileCoord=} opt_tileCoord Destination import("../tilecoord.js").TileCoord object.\n * @return {import("../tilecoord.js").TileCoord} Tile coordinate.\n * @api\n */\n\n\n TileGrid.prototype.getTileCoordForCoordAndResolution = function (coordinate, resolution, opt_tileCoord) {\n return this.getTileCoordForXYAndResolution_(coordinate[0], coordinate[1], resolution, false, opt_tileCoord);\n };\n /**\n * Note that this method should not be called for resolutions that correspond\n * to an integer zoom level. Instead call the `getTileCoordForXYAndZ_` method.\n * @param {number} x X.\n * @param {number} y Y.\n * @param {number} resolution Resolution (for a non-integer zoom level).\n * @param {boolean} reverseIntersectionPolicy Instead of letting edge\n * intersections go to the higher tile coordinate, let edge intersections\n * go to the lower tile coordinate.\n * @param {import("../tilecoord.js").TileCoord=} opt_tileCoord Temporary import("../tilecoord.js").TileCoord object.\n * @return {import("../tilecoord.js").TileCoord} Tile coordinate.\n * @private\n */\n\n\n TileGrid.prototype.getTileCoordForXYAndResolution_ = function (x, y, resolution, reverseIntersectionPolicy, opt_tileCoord) {\n var z = this.getZForResolution(resolution);\n var scale = resolution / this.getResolution(z);\n var origin = this.getOrigin(z);\n var tileSize = toSize(this.getTileSize(z), this.tmpSize_);\n var adjustX = reverseIntersectionPolicy ? 0.5 : 0;\n var adjustY = reverseIntersectionPolicy ? 0.5 : 0;\n var xFromOrigin = Math.floor((x - origin[0]) / resolution + adjustX);\n var yFromOrigin = Math.floor((origin[1] - y) / resolution + adjustY);\n var tileCoordX = scale * xFromOrigin / tileSize[0];\n var tileCoordY = scale * yFromOrigin / tileSize[1];\n\n if (reverseIntersectionPolicy) {\n tileCoordX = Math.ceil(tileCoordX) - 1;\n tileCoordY = Math.ceil(tileCoordY) - 1;\n } else {\n tileCoordX = Math.floor(tileCoordX);\n tileCoordY = Math.floor(tileCoordY);\n }\n\n return tilecoord_createOrUpdate(z, tileCoordX, tileCoordY, opt_tileCoord);\n };\n /**\n * Although there is repetition between this method and `getTileCoordForXYAndResolution_`,\n * they should have separate implementations. This method is for integer zoom\n * levels. The other method should only be called for resolutions corresponding\n * to non-integer zoom levels.\n * @param {number} x Map x coordinate.\n * @param {number} y Map y coordinate.\n * @param {number} z Integer zoom level.\n * @param {boolean} reverseIntersectionPolicy Instead of letting edge\n * intersections go to the higher tile coordinate, let edge intersections\n * go to the lower tile coordinate.\n * @param {import("../tilecoord.js").TileCoord=} opt_tileCoord Temporary import("../tilecoord.js").TileCoord object.\n * @return {import("../tilecoord.js").TileCoord} Tile coordinate.\n * @private\n */\n\n\n TileGrid.prototype.getTileCoordForXYAndZ_ = function (x, y, z, reverseIntersectionPolicy, opt_tileCoord) {\n var origin = this.getOrigin(z);\n var resolution = this.getResolution(z);\n var tileSize = toSize(this.getTileSize(z), this.tmpSize_);\n var adjustX = reverseIntersectionPolicy ? 0.5 : 0;\n var adjustY = reverseIntersectionPolicy ? 0.5 : 0;\n var xFromOrigin = Math.floor((x - origin[0]) / resolution + adjustX);\n var yFromOrigin = Math.floor((origin[1] - y) / resolution + adjustY);\n var tileCoordX = xFromOrigin / tileSize[0];\n var tileCoordY = yFromOrigin / tileSize[1];\n\n if (reverseIntersectionPolicy) {\n tileCoordX = Math.ceil(tileCoordX) - 1;\n tileCoordY = Math.ceil(tileCoordY) - 1;\n } else {\n tileCoordX = Math.floor(tileCoordX);\n tileCoordY = Math.floor(tileCoordY);\n }\n\n return tilecoord_createOrUpdate(z, tileCoordX, tileCoordY, opt_tileCoord);\n };\n /**\n * Get a tile coordinate given a map coordinate and zoom level.\n * @param {import("../coordinate.js").Coordinate} coordinate Coordinate.\n * @param {number} z Zoom level.\n * @param {import("../tilecoord.js").TileCoord=} opt_tileCoord Destination import("../tilecoord.js").TileCoord object.\n * @return {import("../tilecoord.js").TileCoord} Tile coordinate.\n * @api\n */\n\n\n TileGrid.prototype.getTileCoordForCoordAndZ = function (coordinate, z, opt_tileCoord) {\n return this.getTileCoordForXYAndZ_(coordinate[0], coordinate[1], z, false, opt_tileCoord);\n };\n /**\n * @param {import("../tilecoord.js").TileCoord} tileCoord Tile coordinate.\n * @return {number} Tile resolution.\n */\n\n\n TileGrid.prototype.getTileCoordResolution = function (tileCoord) {\n return this.resolutions_[tileCoord[0]];\n };\n /**\n * Get the tile size for a zoom level. The type of the return value matches the\n * `tileSize` or `tileSizes` that the tile grid was configured with. To always\n * get an `import("../size.js").Size`, run the result through `import("../size.js").Size.toSize()`.\n * @param {number} z Z.\n * @return {number|import("../size.js").Size} Tile size.\n * @api\n */\n\n\n TileGrid.prototype.getTileSize = function (z) {\n if (this.tileSize_) {\n return this.tileSize_;\n } else {\n return this.tileSizes_[z];\n }\n };\n /**\n * @param {number} z Zoom level.\n * @return {import("../TileRange.js").default} Extent tile range for the specified zoom level.\n */\n\n\n TileGrid.prototype.getFullTileRange = function (z) {\n if (!this.fullTileRanges_) {\n return this.extent_ ? this.getTileRangeForExtentAndZ(this.extent_, z) : null;\n } else {\n return this.fullTileRanges_[z];\n }\n };\n /**\n * @param {number} resolution Resolution.\n * @param {number=} opt_direction If 0, the nearest resolution will be used.\n * If 1, the nearest lower resolution will be used. If -1, the nearest\n * higher resolution will be used. Default is 0.\n * @return {number} Z.\n * @api\n */\n\n\n TileGrid.prototype.getZForResolution = function (resolution, opt_direction) {\n var z = linearFindNearest(this.resolutions_, resolution, opt_direction || 0);\n return math_clamp(z, this.minZoom, this.maxZoom);\n };\n /**\n * @param {!import("../extent.js").Extent} extent Extent for this tile grid.\n * @private\n */\n\n\n TileGrid.prototype.calculateTileRanges_ = function (extent) {\n var length = this.resolutions_.length;\n var fullTileRanges = new Array(length);\n\n for (var z = this.minZoom; z < length; ++z) {\n fullTileRanges[z] = this.getTileRangeForExtentAndZ(extent, z);\n }\n\n this.fullTileRanges_ = fullTileRanges;\n };\n\n return TileGrid;\n}();\n\n/* harmony default export */ var tilegrid_TileGrid = (TileGrid);\n;// CONCATENATED MODULE: ./node_modules/ol/tilegrid.js\n/**\n * @module ol/tilegrid\n */\n\n\n\n\n\n\n\n/**\n * @param {import("./proj/Projection.js").default} projection Projection.\n * @return {!TileGrid} Default tile grid for the\n * passed projection.\n */\n\nfunction getForProjection(projection) {\n var tileGrid = projection.getDefaultTileGrid();\n\n if (!tileGrid) {\n tileGrid = createForProjection(projection);\n projection.setDefaultTileGrid(tileGrid);\n }\n\n return tileGrid;\n}\n/**\n * @param {TileGrid} tileGrid Tile grid.\n * @param {import("./tilecoord.js").TileCoord} tileCoord Tile coordinate.\n * @param {import("./proj/Projection.js").default} projection Projection.\n * @return {import("./tilecoord.js").TileCoord} Tile coordinate.\n */\n\nfunction tilegrid_wrapX(tileGrid, tileCoord, projection) {\n var z = tileCoord[0];\n var center = tileGrid.getTileCoordCenter(tileCoord);\n var projectionExtent = extentFromProjection(projection);\n\n if (!containsCoordinate(projectionExtent, center)) {\n var worldWidth = extent_getWidth(projectionExtent);\n var worldsAway = Math.ceil((projectionExtent[0] - center[0]) / worldWidth);\n center[0] += worldWidth * worldsAway;\n return tileGrid.getTileCoordForCoordAndZ(center, z);\n } else {\n return tileCoord;\n }\n}\n/**\n * @param {import("./extent.js").Extent} extent Extent.\n * @param {number=} opt_maxZoom Maximum zoom level (default is\n * DEFAULT_MAX_ZOOM).\n * @param {number|import("./size.js").Size=} opt_tileSize Tile size (default uses\n * DEFAULT_TILE_SIZE).\n * @param {import("./extent/Corner.js").default=} opt_corner Extent corner (default is `\'top-left\'`).\n * @return {!TileGrid} TileGrid instance.\n */\n\nfunction createForExtent(extent, opt_maxZoom, opt_tileSize, opt_corner) {\n var corner = opt_corner !== undefined ? opt_corner : Corner.TOP_LEFT;\n var resolutions = resolutionsFromExtent(extent, opt_maxZoom, opt_tileSize);\n return new tilegrid_TileGrid({\n extent: extent,\n origin: getCorner(extent, corner),\n resolutions: resolutions,\n tileSize: opt_tileSize\n });\n}\n/**\n * @typedef {Object} XYZOptions\n * @property {import("./extent.js").Extent} [extent] Extent for the tile grid. The origin for an XYZ tile grid is the\n * top-left corner of the extent. If `maxResolution` is not provided the zero level of the grid is defined by the resolution\n * at which one tile fits in the provided extent. If not provided, the extent of the EPSG:3857 projection is used.\n * @property {number} [maxResolution] Resolution at level zero.\n * @property {number} [maxZoom] Maximum zoom. The default is `42`. This determines the number of levels\n * in the grid set. For example, a `maxZoom` of 21 means there are 22 levels in the grid set.\n * @property {number} [minZoom=0] Minimum zoom.\n * @property {number|import("./size.js").Size} [tileSize=[256, 256]] Tile size in pixels.\n */\n\n/**\n * Creates a tile grid with a standard XYZ tiling scheme.\n * @param {XYZOptions=} opt_options Tile grid options.\n * @return {!TileGrid} Tile grid instance.\n * @api\n */\n\nfunction createXYZ(opt_options) {\n var xyzOptions = opt_options || {};\n var extent = xyzOptions.extent || proj_get(\'EPSG:3857\').getExtent();\n var gridOptions = {\n extent: extent,\n minZoom: xyzOptions.minZoom,\n tileSize: xyzOptions.tileSize,\n resolutions: resolutionsFromExtent(extent, xyzOptions.maxZoom, xyzOptions.tileSize, xyzOptions.maxResolution)\n };\n return new tilegrid_TileGrid(gridOptions);\n}\n/**\n * Create a resolutions array from an extent. A zoom factor of 2 is assumed.\n * @param {import("./extent.js").Extent} extent Extent.\n * @param {number=} opt_maxZoom Maximum zoom level (default is\n * DEFAULT_MAX_ZOOM).\n * @param {number|import("./size.js").Size=} opt_tileSize Tile size (default uses\n * DEFAULT_TILE_SIZE).\n * @param {number=} opt_maxResolution Resolution at level zero.\n * @return {!Array<number>} Resolutions array.\n */\n\nfunction resolutionsFromExtent(extent, opt_maxZoom, opt_tileSize, opt_maxResolution) {\n var maxZoom = opt_maxZoom !== undefined ? opt_maxZoom : DEFAULT_MAX_ZOOM;\n var height = getHeight(extent);\n var width = extent_getWidth(extent);\n var tileSize = toSize(opt_tileSize !== undefined ? opt_tileSize : DEFAULT_TILE_SIZE);\n var maxResolution = opt_maxResolution > 0 ? opt_maxResolution : Math.max(width / tileSize[0], height / tileSize[1]);\n var length = maxZoom + 1;\n var resolutions = new Array(length);\n\n for (var z = 0; z < length; ++z) {\n resolutions[z] = maxResolution / Math.pow(2, z);\n }\n\n return resolutions;\n}\n/**\n * @param {import("./proj.js").ProjectionLike} projection Projection.\n * @param {number=} opt_maxZoom Maximum zoom level (default is\n * DEFAULT_MAX_ZOOM).\n * @param {number|import("./size.js").Size=} opt_tileSize Tile size (default uses\n * DEFAULT_TILE_SIZE).\n * @param {import("./extent/Corner.js").default=} opt_corner Extent corner (default is `\'top-left\'`).\n * @return {!TileGrid} TileGrid instance.\n */\n\n\nfunction createForProjection(projection, opt_maxZoom, opt_tileSize, opt_corner) {\n var extent = extentFromProjection(projection);\n return createForExtent(extent, opt_maxZoom, opt_tileSize, opt_corner);\n}\n/**\n * Generate a tile grid extent from a projection. If the projection has an\n * extent, it is used. If not, a global extent is assumed.\n * @param {import("./proj.js").ProjectionLike} projection Projection.\n * @return {import("./extent.js").Extent} Extent.\n */\n\nfunction extentFromProjection(projection) {\n projection = proj_get(projection);\n var extent = projection.getExtent();\n\n if (!extent) {\n var half = 180 * METERS_PER_UNIT[proj_Units.DEGREES] / projection.getMetersPerUnit();\n extent = createOrUpdate(-half, -half, half, half);\n }\n\n return extent;\n}\n;// CONCATENATED MODULE: ./node_modules/ol/source/Tile.js\nvar source_Tile_extends = undefined && undefined.__extends || function () {\n var _extendStatics = function extendStatics(d, b) {\n _extendStatics = Object.setPrototypeOf || {\n __proto__: []\n } instanceof Array && function (d, b) {\n d.__proto__ = b;\n } || function (d, b) {\n for (var p in b) {\n if (Object.prototype.hasOwnProperty.call(b, p)) d[p] = b[p];\n }\n };\n\n return _extendStatics(d, b);\n };\n\n return function (d, b) {\n _extendStatics(d, b);\n\n function __() {\n this.constructor = d;\n }\n\n d.prototype = b === null ? Object.create(b) : (__.prototype = b.prototype, new __());\n };\n}();\n/**\n * @module ol/source/Tile\n */\n\n\n\n\n\n\n\n\n\n\n\n\n/**\n * @typedef {Object} Options\n * @property {import("./Source.js").AttributionLike} [attributions]\n * @property {boolean} [attributionsCollapsible=true] Attributions are collapsible.\n * @property {number} [cacheSize]\n * @property {boolean} [opaque=false] Whether the layer is opaque.\n * @property {number} [tilePixelRatio]\n * @property {import("../proj.js").ProjectionLike} [projection]\n * @property {import("./State.js").default} [state]\n * @property {import("../tilegrid/TileGrid.js").default} [tileGrid]\n * @property {boolean} [wrapX=true]\n * @property {number} [transition]\n * @property {string} [key]\n * @property {number} [zDirection=0]\n */\n\n/**\n * @classdesc\n * Abstract base class; normally only used for creating subclasses and not\n * instantiated in apps.\n * Base class for sources providing images divided into a tile grid.\n * @abstract\n * @api\n */\n\nvar TileSource =\n/** @class */\nfunction (_super) {\n source_Tile_extends(TileSource, _super);\n /**\n * @param {Options} options SourceTile source options.\n */\n\n\n function TileSource(options) {\n var _this = _super.call(this, {\n attributions: options.attributions,\n attributionsCollapsible: options.attributionsCollapsible,\n projection: options.projection,\n state: options.state,\n wrapX: options.wrapX\n }) || this;\n /**\n * @private\n * @type {boolean}\n */\n\n\n _this.opaque_ = options.opaque !== undefined ? options.opaque : false;\n /**\n * @private\n * @type {number}\n */\n\n _this.tilePixelRatio_ = options.tilePixelRatio !== undefined ? options.tilePixelRatio : 1;\n /**\n * @protected\n * @type {import("../tilegrid/TileGrid.js").default}\n */\n\n _this.tileGrid = options.tileGrid !== undefined ? options.tileGrid : null;\n var tileSize = [256, 256];\n var tileGrid = options.tileGrid;\n\n if (tileGrid) {\n toSize(tileGrid.getTileSize(tileGrid.getMinZoom()), tileSize);\n }\n /**\n * @protected\n * @type {import("../TileCache.js").default}\n */\n\n\n _this.tileCache = new ol_TileCache(options.cacheSize || 0);\n /**\n * @protected\n * @type {import("../size.js").Size}\n */\n\n _this.tmpSize = [0, 0];\n /**\n * @private\n * @type {string}\n */\n\n _this.key_ = options.key || \'\';\n /**\n * @protected\n * @type {import("../Tile.js").Options}\n */\n\n _this.tileOptions = {\n transition: options.transition\n };\n /**\n * zDirection hint, read by the renderer. Indicates which resolution should be used\n * by a renderer if the views resolution does not match any resolution of the tile source.\n * If 0, the nearest resolution will be used. If 1, the nearest lower resolution\n * will be used. If -1, the nearest higher resolution will be used.\n * @type {number}\n */\n\n _this.zDirection = options.zDirection ? options.zDirection : 0;\n return _this;\n }\n /**\n * @return {boolean} Can expire cache.\n */\n\n\n TileSource.prototype.canExpireCache = function () {\n return this.tileCache.canExpireCache();\n };\n /**\n * @param {import("../proj/Projection.js").default} projection Projection.\n * @param {!Object<string, boolean>} usedTiles Used tiles.\n */\n\n\n TileSource.prototype.expireCache = function (projection, usedTiles) {\n var tileCache = this.getTileCacheForProjection(projection);\n\n if (tileCache) {\n tileCache.expireCache(usedTiles);\n }\n };\n /**\n * @param {import("../proj/Projection.js").default} projection Projection.\n * @param {number} z Zoom level.\n * @param {import("../TileRange.js").default} tileRange Tile range.\n * @param {function(import("../Tile.js").default):(boolean|void)} callback Called with each\n * loaded tile. If the callback returns `false`, the tile will not be\n * considered loaded.\n * @return {boolean} The tile range is fully covered with loaded tiles.\n */\n\n\n TileSource.prototype.forEachLoadedTile = function (projection, z, tileRange, callback) {\n var tileCache = this.getTileCacheForProjection(projection);\n\n if (!tileCache) {\n return false;\n }\n\n var covered = true;\n var tile, tileCoordKey, loaded;\n\n for (var x = tileRange.minX; x <= tileRange.maxX; ++x) {\n for (var y = tileRange.minY; y <= tileRange.maxY; ++y) {\n tileCoordKey = getKeyZXY(z, x, y);\n loaded = false;\n\n if (tileCache.containsKey(tileCoordKey)) {\n tile =\n /** @type {!import("../Tile.js").default} */\n tileCache.get(tileCoordKey);\n loaded = tile.getState() === TileState.LOADED;\n\n if (loaded) {\n loaded = callback(tile) !== false;\n }\n }\n\n if (!loaded) {\n covered = false;\n }\n }\n }\n\n return covered;\n };\n /**\n * @param {import("../proj/Projection.js").default} projection Projection.\n * @return {number} Gutter.\n */\n\n\n TileSource.prototype.getGutterForProjection = function (projection) {\n return 0;\n };\n /**\n * Return the key to be used for all tiles in the source.\n * @return {string} The key for all tiles.\n * @protected\n */\n\n\n TileSource.prototype.getKey = function () {\n return this.key_;\n };\n /**\n * Set the value to be used as the key for all tiles in the source.\n * @param {string} key The key for tiles.\n * @protected\n */\n\n\n TileSource.prototype.setKey = function (key) {\n if (this.key_ !== key) {\n this.key_ = key;\n this.changed();\n }\n };\n /**\n * @param {import("../proj/Projection.js").default} projection Projection.\n * @return {boolean} Opaque.\n */\n\n\n TileSource.prototype.getOpaque = function (projection) {\n return this.opaque_;\n };\n /**\n * @return {Array<number>} Resolutions.\n */\n\n\n TileSource.prototype.getResolutions = function () {\n return this.tileGrid.getResolutions();\n };\n /**\n * @abstract\n * @param {number} z Tile coordinate z.\n * @param {number} x Tile coordinate x.\n * @param {number} y Tile coordinate y.\n * @param {number} pixelRatio Pixel ratio.\n * @param {import("../proj/Projection.js").default} projection Projection.\n * @return {!import("../Tile.js").default} Tile.\n */\n\n\n TileSource.prototype.getTile = function (z, x, y, pixelRatio, projection) {\n return util_abstract();\n };\n /**\n * Return the tile grid of the tile source.\n * @return {import("../tilegrid/TileGrid.js").default} Tile grid.\n * @api\n */\n\n\n TileSource.prototype.getTileGrid = function () {\n return this.tileGrid;\n };\n /**\n * @param {import("../proj/Projection.js").default} projection Projection.\n * @return {!import("../tilegrid/TileGrid.js").default} Tile grid.\n */\n\n\n TileSource.prototype.getTileGridForProjection = function (projection) {\n if (!this.tileGrid) {\n return getForProjection(projection);\n } else {\n return this.tileGrid;\n }\n };\n /**\n * @param {import("../proj/Projection.js").default} projection Projection.\n * @return {import("../TileCache.js").default} Tile cache.\n * @protected\n */\n\n\n TileSource.prototype.getTileCacheForProjection = function (projection) {\n asserts_assert(equivalent(this.getProjection(), projection), 68 // A VectorTile source can only be rendered if it has a projection compatible with the view projection.\n );\n return this.tileCache;\n };\n /**\n * Get the tile pixel ratio for this source. Subclasses may override this\n * method, which is meant to return a supported pixel ratio that matches the\n * provided `pixelRatio` as close as possible.\n * @param {number} pixelRatio Pixel ratio.\n * @return {number} Tile pixel ratio.\n */\n\n\n TileSource.prototype.getTilePixelRatio = function (pixelRatio) {\n return this.tilePixelRatio_;\n };\n /**\n * @param {number} z Z.\n * @param {number} pixelRatio Pixel ratio.\n * @param {import("../proj/Projection.js").default} projection Projection.\n * @return {import("../size.js").Size} Tile size.\n */\n\n\n TileSource.prototype.getTilePixelSize = function (z, pixelRatio, projection) {\n var tileGrid = this.getTileGridForProjection(projection);\n var tilePixelRatio = this.getTilePixelRatio(pixelRatio);\n var tileSize = toSize(tileGrid.getTileSize(z), this.tmpSize);\n\n if (tilePixelRatio == 1) {\n return tileSize;\n } else {\n return size_scale(tileSize, tilePixelRatio, this.tmpSize);\n }\n };\n /**\n * Returns a tile coordinate wrapped around the x-axis. When the tile coordinate\n * is outside the resolution and extent range of the tile grid, `null` will be\n * returned.\n * @param {import("../tilecoord.js").TileCoord} tileCoord Tile coordinate.\n * @param {import("../proj/Projection.js").default=} opt_projection Projection.\n * @return {import("../tilecoord.js").TileCoord} Tile coordinate to be passed to the tileUrlFunction or\n * null if no tile URL should be created for the passed `tileCoord`.\n */\n\n\n TileSource.prototype.getTileCoordForTileUrlFunction = function (tileCoord, opt_projection) {\n var projection = opt_projection !== undefined ? opt_projection : this.getProjection();\n var tileGrid = this.getTileGridForProjection(projection);\n\n if (this.getWrapX() && projection.isGlobal()) {\n tileCoord = tilegrid_wrapX(tileGrid, tileCoord, projection);\n }\n\n return withinExtentAndZ(tileCoord, tileGrid) ? tileCoord : null;\n };\n /**\n * Remove all cached tiles from the source. The next render cycle will fetch new tiles.\n * @api\n */\n\n\n TileSource.prototype.clear = function () {\n this.tileCache.clear();\n };\n\n TileSource.prototype.refresh = function () {\n this.clear();\n\n _super.prototype.refresh.call(this);\n };\n /**\n * Increases the cache size if needed\n * @param {number} tileCount Minimum number of tiles needed.\n * @param {import("../proj/Projection.js").default} projection Projection.\n */\n\n\n TileSource.prototype.updateCacheSize = function (tileCount, projection) {\n var tileCache = this.getTileCacheForProjection(projection);\n\n if (tileCount > tileCache.highWaterMark) {\n tileCache.highWaterMark = tileCount;\n }\n };\n /**\n * Marks a tile coord as being used, without triggering a load.\n * @abstract\n * @param {number} z Tile coordinate z.\n * @param {number} x Tile coordinate x.\n * @param {number} y Tile coordinate y.\n * @param {import("../proj/Projection.js").default} projection Projection.\n */\n\n\n TileSource.prototype.useTile = function (z, x, y, projection) {};\n\n return TileSource;\n}(source_Source);\n/**\n * @classdesc\n * Events emitted by {@link module:ol/source/Tile~TileSource} instances are instances of this\n * type.\n */\n\n\nvar TileSourceEvent =\n/** @class */\nfunction (_super) {\n source_Tile_extends(TileSourceEvent, _super);\n /**\n * @param {string} type Type.\n * @param {import("../Tile.js").default} tile The tile.\n */\n\n\n function TileSourceEvent(type, tile) {\n var _this = _super.call(this, type) || this;\n /**\n * The tile related to the event.\n * @type {import("../Tile.js").default}\n * @api\n */\n\n\n _this.tile = tile;\n return _this;\n }\n\n return TileSourceEvent;\n}(Event);\n\n\n/* harmony default export */ var source_Tile = (TileSource);\n;// CONCATENATED MODULE: ./node_modules/ol/tileurlfunction.js\n/**\n * @module ol/tileurlfunction\n */\n\n\n\n/**\n * @param {string} template Template.\n * @param {import("./tilegrid/TileGrid.js").default} tileGrid Tile grid.\n * @return {import("./Tile.js").UrlFunction} Tile URL function.\n */\n\nfunction createFromTemplate(template, tileGrid) {\n var zRegEx = /\\{z\\}/g;\n var xRegEx = /\\{x\\}/g;\n var yRegEx = /\\{y\\}/g;\n var dashYRegEx = /\\{-y\\}/g;\n return (\n /**\n * @param {import("./tilecoord.js").TileCoord} tileCoord Tile Coordinate.\n * @param {number} pixelRatio Pixel ratio.\n * @param {import("./proj/Projection.js").default} projection Projection.\n * @return {string|undefined} Tile URL.\n */\n function (tileCoord, pixelRatio, projection) {\n if (!tileCoord) {\n return undefined;\n } else {\n return template.replace(zRegEx, tileCoord[0].toString()).replace(xRegEx, tileCoord[1].toString()).replace(yRegEx, tileCoord[2].toString()).replace(dashYRegEx, function () {\n var z = tileCoord[0];\n var range = tileGrid.getFullTileRange(z);\n asserts_assert(range, 55); // The {-y} placeholder requires a tile grid with extent\n\n var y = range.getHeight() - tileCoord[2] - 1;\n return y.toString();\n });\n }\n }\n );\n}\n/**\n * @param {Array<string>} templates Templates.\n * @param {import("./tilegrid/TileGrid.js").default} tileGrid Tile grid.\n * @return {import("./Tile.js").UrlFunction} Tile URL function.\n */\n\nfunction createFromTemplates(templates, tileGrid) {\n var len = templates.length;\n var tileUrlFunctions = new Array(len);\n\n for (var i = 0; i < len; ++i) {\n tileUrlFunctions[i] = createFromTemplate(templates[i], tileGrid);\n }\n\n return createFromTileUrlFunctions(tileUrlFunctions);\n}\n/**\n * @param {Array<import("./Tile.js").UrlFunction>} tileUrlFunctions Tile URL Functions.\n * @return {import("./Tile.js").UrlFunction} Tile URL function.\n */\n\nfunction createFromTileUrlFunctions(tileUrlFunctions) {\n if (tileUrlFunctions.length === 1) {\n return tileUrlFunctions[0];\n }\n\n return (\n /**\n * @param {import("./tilecoord.js").TileCoord} tileCoord Tile Coordinate.\n * @param {number} pixelRatio Pixel ratio.\n * @param {import("./proj/Projection.js").default} projection Projection.\n * @return {string|undefined} Tile URL.\n */\n function (tileCoord, pixelRatio, projection) {\n if (!tileCoord) {\n return undefined;\n } else {\n var h = hash(tileCoord);\n var index = math_modulo(h, tileUrlFunctions.length);\n return tileUrlFunctions[index](tileCoord, pixelRatio, projection);\n }\n }\n );\n}\n/**\n * @param {import("./tilecoord.js").TileCoord} tileCoord Tile coordinate.\n * @param {number} pixelRatio Pixel ratio.\n * @param {import("./proj/Projection.js").default} projection Projection.\n * @return {string|undefined} Tile URL.\n */\n\nfunction nullTileUrlFunction(tileCoord, pixelRatio, projection) {\n return undefined;\n}\n/**\n * @param {string} url URL.\n * @return {Array<string>} Array of urls.\n */\n\nfunction expandUrl(url) {\n var urls = [];\n var match = /\\{([a-z])-([a-z])\\}/.exec(url);\n\n if (match) {\n // char range\n var startCharCode = match[1].charCodeAt(0);\n var stopCharCode = match[2].charCodeAt(0);\n var charCode = void 0;\n\n for (charCode = startCharCode; charCode <= stopCharCode; ++charCode) {\n urls.push(url.replace(match[0], String.fromCharCode(charCode)));\n }\n\n return urls;\n }\n\n match = /\\{(\\d+)-(\\d+)\\}/.exec(url);\n\n if (match) {\n // number range\n var stop_1 = parseInt(match[2], 10);\n\n for (var i = parseInt(match[1], 10); i <= stop_1; i++) {\n urls.push(url.replace(match[0], i.toString()));\n }\n\n return urls;\n }\n\n urls.push(url);\n return urls;\n}\n;// CONCATENATED MODULE: ./node_modules/ol/source/UrlTile.js\nvar UrlTile_extends = undefined && undefined.__extends || function () {\n var _extendStatics = function extendStatics(d, b) {\n _extendStatics = Object.setPrototypeOf || {\n __proto__: []\n } instanceof Array && function (d, b) {\n d.__proto__ = b;\n } || function (d, b) {\n for (var p in b) {\n if (Object.prototype.hasOwnProperty.call(b, p)) d[p] = b[p];\n }\n };\n\n return _extendStatics(d, b);\n };\n\n return function (d, b) {\n _extendStatics(d, b);\n\n function __() {\n this.constructor = d;\n }\n\n d.prototype = b === null ? Object.create(b) : (__.prototype = b.prototype, new __());\n };\n}();\n/**\n * @module ol/source/UrlTile\n */\n\n\n\n\n\n\n\n\n/**\n * @typedef {Object} Options\n * @property {import("./Source.js").AttributionLike} [attributions]\n * @property {boolean} [attributionsCollapsible=true] Attributions are collapsible.\n * @property {number} [cacheSize]\n * @property {boolean} [opaque=false] Whether the layer is opaque.\n * @property {import("../proj.js").ProjectionLike} [projection]\n * @property {import("./State.js").default} [state]\n * @property {import("../tilegrid/TileGrid.js").default} [tileGrid]\n * @property {import("../Tile.js").LoadFunction} tileLoadFunction\n * @property {number} [tilePixelRatio]\n * @property {import("../Tile.js").UrlFunction} [tileUrlFunction]\n * @property {string} [url]\n * @property {Array<string>} [urls]\n * @property {boolean} [wrapX=true]\n * @property {number} [transition]\n * @property {string} [key]\n * @property {number} [zDirection=0]\n */\n\n/**\n * @classdesc\n * Base class for sources providing tiles divided into a tile grid over http.\n *\n * @fires import("./Tile.js").TileSourceEvent\n */\n\nvar UrlTile =\n/** @class */\nfunction (_super) {\n UrlTile_extends(UrlTile, _super);\n /**\n * @param {Options} options Image tile options.\n */\n\n\n function UrlTile(options) {\n var _this = _super.call(this, {\n attributions: options.attributions,\n cacheSize: options.cacheSize,\n opaque: options.opaque,\n projection: options.projection,\n state: options.state,\n tileGrid: options.tileGrid,\n tilePixelRatio: options.tilePixelRatio,\n wrapX: options.wrapX,\n transition: options.transition,\n key: options.key,\n attributionsCollapsible: options.attributionsCollapsible,\n zDirection: options.zDirection\n }) || this;\n /**\n * @private\n * @type {boolean}\n */\n\n\n _this.generateTileUrlFunction_ = _this.tileUrlFunction === UrlTile.prototype.tileUrlFunction;\n /**\n * @protected\n * @type {import("../Tile.js").LoadFunction}\n */\n\n _this.tileLoadFunction = options.tileLoadFunction;\n\n if (options.tileUrlFunction) {\n _this.tileUrlFunction = options.tileUrlFunction;\n }\n /**\n * @protected\n * @type {!Array<string>|null}\n */\n\n\n _this.urls = null;\n\n if (options.urls) {\n _this.setUrls(options.urls);\n } else if (options.url) {\n _this.setUrl(options.url);\n }\n /**\n * @private\n * @type {!Object<string, boolean>}\n */\n\n\n _this.tileLoadingKeys_ = {};\n return _this;\n }\n /**\n * Return the tile load function of the source.\n * @return {import("../Tile.js").LoadFunction} TileLoadFunction\n * @api\n */\n\n\n UrlTile.prototype.getTileLoadFunction = function () {\n return this.tileLoadFunction;\n };\n /**\n * Return the tile URL function of the source.\n * @return {import("../Tile.js").UrlFunction} TileUrlFunction\n * @api\n */\n\n\n UrlTile.prototype.getTileUrlFunction = function () {\n return Object.getPrototypeOf(this).tileUrlFunction === this.tileUrlFunction ? this.tileUrlFunction.bind(this) : this.tileUrlFunction;\n };\n /**\n * Return the URLs used for this source.\n * When a tileUrlFunction is used instead of url or urls,\n * null will be returned.\n * @return {!Array<string>|null} URLs.\n * @api\n */\n\n\n UrlTile.prototype.getUrls = function () {\n return this.urls;\n };\n /**\n * Handle tile change events.\n * @param {import("../events/Event.js").default} event Event.\n * @protected\n */\n\n\n UrlTile.prototype.handleTileChange = function (event) {\n var tile =\n /** @type {import("../Tile.js").default} */\n event.target;\n var uid = util_getUid(tile);\n var tileState = tile.getState();\n var type;\n\n if (tileState == TileState.LOADING) {\n this.tileLoadingKeys_[uid] = true;\n type = TileEventType.TILELOADSTART;\n } else if (uid in this.tileLoadingKeys_) {\n delete this.tileLoadingKeys_[uid];\n type = tileState == TileState.ERROR ? TileEventType.TILELOADERROR : tileState == TileState.LOADED ? TileEventType.TILELOADEND : undefined;\n }\n\n if (type != undefined) {\n this.dispatchEvent(new TileSourceEvent(type, tile));\n }\n };\n /**\n * Set the tile load function of the source.\n * @param {import("../Tile.js").LoadFunction} tileLoadFunction Tile load function.\n * @api\n */\n\n\n UrlTile.prototype.setTileLoadFunction = function (tileLoadFunction) {\n this.tileCache.clear();\n this.tileLoadFunction = tileLoadFunction;\n this.changed();\n };\n /**\n * Set the tile URL function of the source.\n * @param {import("../Tile.js").UrlFunction} tileUrlFunction Tile URL function.\n * @param {string=} key Optional new tile key for the source.\n * @api\n */\n\n\n UrlTile.prototype.setTileUrlFunction = function (tileUrlFunction, key) {\n this.tileUrlFunction = tileUrlFunction;\n this.tileCache.pruneExceptNewestZ();\n\n if (typeof key !== \'undefined\') {\n this.setKey(key);\n } else {\n this.changed();\n }\n };\n /**\n * Set the URL to use for requests.\n * @param {string} url URL.\n * @api\n */\n\n\n UrlTile.prototype.setUrl = function (url) {\n var urls = expandUrl(url);\n this.urls = urls;\n this.setUrls(urls);\n };\n /**\n * Set the URLs to use for requests.\n * @param {Array<string>} urls URLs.\n * @api\n */\n\n\n UrlTile.prototype.setUrls = function (urls) {\n this.urls = urls;\n var key = urls.join(\'\\n\');\n\n if (this.generateTileUrlFunction_) {\n this.setTileUrlFunction(createFromTemplates(urls, this.tileGrid), key);\n } else {\n this.setKey(key);\n }\n };\n /**\n * @param {import("../tilecoord.js").TileCoord} tileCoord Tile coordinate.\n * @param {number} pixelRatio Pixel ratio.\n * @param {import("../proj/Projection.js").default} projection Projection.\n * @return {string|undefined} Tile URL.\n */\n\n\n UrlTile.prototype.tileUrlFunction = function (tileCoord, pixelRatio, projection) {\n return undefined;\n };\n /**\n * Marks a tile coord as being used, without triggering a load.\n * @param {number} z Tile coordinate z.\n * @param {number} x Tile coordinate x.\n * @param {number} y Tile coordinate y.\n */\n\n\n UrlTile.prototype.useTile = function (z, x, y) {\n var tileCoordKey = getKeyZXY(z, x, y);\n\n if (this.tileCache.containsKey(tileCoordKey)) {\n this.tileCache.get(tileCoordKey);\n }\n };\n\n return UrlTile;\n}(source_Tile);\n\n/* harmony default export */ var source_UrlTile = (UrlTile);\n;// CONCATENATED MODULE: ./node_modules/ol/VectorRenderTile.js\nvar VectorRenderTile_extends = undefined && undefined.__extends || function () {\n var _extendStatics = function extendStatics(d, b) {\n _extendStatics = Object.setPrototypeOf || {\n __proto__: []\n } instanceof Array && function (d, b) {\n d.__proto__ = b;\n } || function (d, b) {\n for (var p in b) {\n if (Object.prototype.hasOwnProperty.call(b, p)) d[p] = b[p];\n }\n };\n\n return _extendStatics(d, b);\n };\n\n return function (d, b) {\n _extendStatics(d, b);\n\n function __() {\n this.constructor = d;\n }\n\n d.prototype = b === null ? Object.create(b) : (__.prototype = b.prototype, new __());\n };\n}();\n/**\n * @module ol/VectorRenderTile\n */\n\n\n\n\n\n/**\n * @typedef {Object} ReplayState\n * @property {boolean} dirty\n * @property {null|import("./render.js").OrderFunction} renderedRenderOrder\n * @property {number} renderedTileRevision\n * @property {number} renderedResolution\n * @property {number} renderedRevision\n * @property {number} renderedZ\n * @property {number} renderedTileResolution\n * @property {number} renderedTileZ\n */\n\n/**\n * @type {Array<HTMLCanvasElement>}\n */\n\nvar canvasPool = [];\n\nvar VectorRenderTile =\n/** @class */\nfunction (_super) {\n VectorRenderTile_extends(VectorRenderTile, _super);\n /**\n * @param {import("./tilecoord.js").TileCoord} tileCoord Tile coordinate.\n * @param {import("./TileState.js").default} state State.\n * @param {import("./tilecoord.js").TileCoord} urlTileCoord Wrapped tile coordinate for source urls.\n * @param {function(VectorRenderTile):Array<import("./VectorTile").default>} getSourceTiles Function\n * to get source tiles for this tile.\n */\n\n\n function VectorRenderTile(tileCoord, state, urlTileCoord, getSourceTiles) {\n var _this = _super.call(this, tileCoord, state, {\n transition: 0\n }) || this;\n /**\n * @private\n * @type {!Object<string, CanvasRenderingContext2D>}\n */\n\n\n _this.context_ = {};\n /**\n * Executor groups by layer uid. Entries are read/written by the renderer.\n * @type {Object<string, Array<import("./render/canvas/ExecutorGroup.js").default>>}\n */\n\n _this.executorGroups = {};\n /**\n * Executor groups for decluttering, by layer uid. Entries are read/written by the renderer.\n * @type {Object<string, Array<import("./render/canvas/ExecutorGroup.js").default>>}\n */\n\n _this.declutterExecutorGroups = {};\n /**\n * Number of loading source tiles. Read/written by the source.\n * @type {number}\n */\n\n _this.loadingSourceTiles = 0;\n /**\n * Tile keys of error source tiles. Read/written by the source.\n * @type {Object<string, boolean>}\n */\n\n _this.errorSourceTileKeys = {};\n /**\n * @type {Object<number, ImageData>}\n */\n\n _this.hitDetectionImageData = {};\n /**\n * @private\n * @type {!Object<string, ReplayState>}\n */\n\n _this.replayState_ = {};\n /**\n * @type {Array<import("./VectorTile.js").default>}\n */\n\n _this.sourceTiles = null;\n /**\n * @type {number}\n */\n\n _this.wantedResolution;\n /**\n * @type {!function():Array<import("./VectorTile.js").default>}\n */\n\n _this.getSourceTiles = getSourceTiles.bind(undefined, _this);\n /**\n * z of the source tiles of the last getSourceTiles call.\n * @type {number}\n */\n\n _this.sourceZ = -1;\n /**\n * True when all tiles for this tile\'s nominal resolution are available.\n * @type {boolean}\n */\n\n _this.hifi = false;\n /**\n * @type {import("./tilecoord.js").TileCoord}\n */\n\n _this.wrappedTileCoord = urlTileCoord;\n return _this;\n }\n /**\n * @param {import("./layer/Layer.js").default} layer Layer.\n * @return {CanvasRenderingContext2D} The rendering context.\n */\n\n\n VectorRenderTile.prototype.getContext = function (layer) {\n var key = util_getUid(layer);\n\n if (!(key in this.context_)) {\n this.context_[key] = createCanvasContext2D(1, 1, canvasPool);\n }\n\n return this.context_[key];\n };\n /**\n * @param {import("./layer/Layer.js").default} layer Layer.\n * @return {boolean} Tile has a rendering context for the given layer.\n */\n\n\n VectorRenderTile.prototype.hasContext = function (layer) {\n return util_getUid(layer) in this.context_;\n };\n /**\n * Get the Canvas for this tile.\n * @param {import("./layer/Layer.js").default} layer Layer.\n * @return {HTMLCanvasElement} Canvas.\n */\n\n\n VectorRenderTile.prototype.getImage = function (layer) {\n return this.hasContext(layer) ? this.getContext(layer).canvas : null;\n };\n /**\n * @param {import("./layer/Layer.js").default} layer Layer.\n * @return {ReplayState} The replay state.\n */\n\n\n VectorRenderTile.prototype.getReplayState = function (layer) {\n var key = util_getUid(layer);\n\n if (!(key in this.replayState_)) {\n this.replayState_[key] = {\n dirty: false,\n renderedRenderOrder: null,\n renderedResolution: NaN,\n renderedRevision: -1,\n renderedTileResolution: NaN,\n renderedTileRevision: -1,\n renderedZ: -1,\n renderedTileZ: -1\n };\n }\n\n return this.replayState_[key];\n };\n /**\n * Load the tile.\n */\n\n\n VectorRenderTile.prototype.load = function () {\n this.getSourceTiles();\n };\n /**\n * Remove from the cache due to expiry\n */\n\n\n VectorRenderTile.prototype.release = function () {\n for (var key in this.context_) {\n canvasPool.push(this.context_[key].canvas);\n delete this.context_[key];\n }\n\n _super.prototype.release.call(this);\n };\n\n return VectorRenderTile;\n}(ol_Tile);\n\n/* harmony default export */ var ol_VectorRenderTile = (VectorRenderTile);\n;// CONCATENATED MODULE: ./node_modules/ol/format/FormatType.js\n/**\n * @module ol/format/FormatType\n */\n\n/**\n * @enum {string}\n */\n/* harmony default export */ var FormatType = ({\n ARRAY_BUFFER: \'arraybuffer\',\n JSON: \'json\',\n TEXT: \'text\',\n XML: \'xml\'\n});\n;// CONCATENATED MODULE: ./node_modules/ol/featureloader.js\n/**\n * @module ol/featureloader\n */\n\n\n/**\n *\n * @type {boolean}\n * @private\n */\n\nvar withCredentials = false;\n/**\n * {@link module:ol/source/Vector} sources use a function of this type to\n * load features.\n *\n * This function takes an {@link module:ol/extent~Extent} representing the area to be loaded,\n * a `{number}` representing the resolution (map units per pixel), an\n * {@link module:ol/proj/Projection} for the projection and success and failure callbacks as\n * arguments. `this` within the function is bound to the\n * {@link module:ol/source/Vector} it\'s called from.\n *\n * The function is responsible for loading the features and adding them to the\n * source.\n * @typedef {function(this:(import("./source/Vector").default|import("./VectorTile.js").default),\n * import("./extent.js").Extent,\n * number,\n * import("./proj/Projection.js").default,\n * function(Array<import("./Feature.js").default>): void=,\n * function(): void=): void} FeatureLoader\n * @api\n */\n\n/**\n * {@link module:ol/source/Vector} sources use a function of this type to\n * get the url to load features from.\n *\n * This function takes an {@link module:ol/extent~Extent} representing the area\n * to be loaded, a `{number}` representing the resolution (map units per pixel)\n * and an {@link module:ol/proj/Projection} for the projection as\n * arguments and returns a `{string}` representing the URL.\n * @typedef {function(import("./extent.js").Extent, number, import("./proj/Projection.js").default): string} FeatureUrlFunction\n * @api\n */\n\n/**\n * @param {string|FeatureUrlFunction} url Feature URL service.\n * @param {import("./format/Feature.js").default} format Feature format.\n * @param {import("./extent.js").Extent} extent Extent.\n * @param {number} resolution Resolution.\n * @param {import("./proj/Projection.js").default} projection Projection.\n * @param {function(Array<import("./Feature.js").default>, import("./proj/Projection.js").default): void} success Success\n * Function called with the loaded features and optionally with the data projection.\n * @param {function(): void} failure Failure\n * Function called when loading failed.\n */\n\nfunction loadFeaturesXhr(url, format, extent, resolution, projection, success, failure) {\n var xhr = new XMLHttpRequest();\n xhr.open(\'GET\', typeof url === \'function\' ? url(extent, resolution, projection) : url, true);\n\n if (format.getType() == FormatType.ARRAY_BUFFER) {\n xhr.responseType = \'arraybuffer\';\n }\n\n xhr.withCredentials = withCredentials;\n /**\n * @param {Event} event Event.\n * @private\n */\n\n xhr.onload = function (event) {\n // status will be 0 for file:// urls\n if (!xhr.status || xhr.status >= 200 && xhr.status < 300) {\n var type = format.getType();\n /** @type {Document|Node|Object|string|undefined} */\n\n var source = void 0;\n\n if (type == FormatType.JSON || type == FormatType.TEXT) {\n source = xhr.responseText;\n } else if (type == FormatType.XML) {\n source = xhr.responseXML;\n\n if (!source) {\n source = new DOMParser().parseFromString(xhr.responseText, \'application/xml\');\n }\n } else if (type == FormatType.ARRAY_BUFFER) {\n source =\n /** @type {ArrayBuffer} */\n xhr.response;\n }\n\n if (source) {\n success(\n /** @type {Array<import("./Feature.js").default>} */\n format.readFeatures(source, {\n extent: extent,\n featureProjection: projection\n }), format.readProjection(source));\n } else {\n failure();\n }\n } else {\n failure();\n }\n };\n /**\n * @private\n */\n\n\n xhr.onerror = failure;\n xhr.send();\n}\n/**\n * Create an XHR feature loader for a `url` and `format`. The feature loader\n * loads features (with XHR), parses the features, and adds them to the\n * vector source.\n * @param {string|FeatureUrlFunction} url Feature URL service.\n * @param {import("./format/Feature.js").default} format Feature format.\n * @return {FeatureLoader} The feature loader.\n * @api\n */\n\nfunction xhr(url, format) {\n /**\n * @param {import("./extent.js").Extent} extent Extent.\n * @param {number} resolution Resolution.\n * @param {import("./proj/Projection.js").default} projection Projection.\n * @param {function(): void=} success Success\n * Function called when loading succeeded.\n * @param {function(): void=} failure Failure\n * Function called when loading failed.\n * @this {import("./source/Vector").default}\n */\n return function (extent, resolution, projection, success, failure) {\n var source =\n /** @type {import("./source/Vector").default} */\n this;\n loadFeaturesXhr(url, format, extent, resolution, projection,\n /**\n * @param {Array<import("./Feature.js").default>} features The loaded features.\n * @param {import("./proj/Projection.js").default} dataProjection Data\n * projection.\n */\n function (features, dataProjection) {\n if (success !== undefined) {\n success(features);\n }\n\n source.addFeatures(features);\n },\n /* FIXME handle error */\n failure ? failure : VOID);\n };\n}\n/**\n * Setter for the withCredentials configuration for the XHR.\n *\n * @param {boolean} xhrWithCredentials The value of withCredentials to set.\n * Compare https://developer.mozilla.org/en-US/docs/Web/API/XMLHttpRequest/\n * @api\n */\n\nfunction setWithCredentials(xhrWithCredentials) {\n withCredentials = xhrWithCredentials;\n}\n;// CONCATENATED MODULE: ./node_modules/ol/source/VectorTile.js\n/**\n * @module ol/source/VectorTile\n */\nvar source_VectorTile_extends = undefined && undefined.__extends || function () {\n var _extendStatics = function extendStatics(d, b) {\n _extendStatics = Object.setPrototypeOf || {\n __proto__: []\n } instanceof Array && function (d, b) {\n d.__proto__ = b;\n } || function (d, b) {\n for (var p in b) {\n if (Object.prototype.hasOwnProperty.call(b, p)) d[p] = b[p];\n }\n };\n\n return _extendStatics(d, b);\n };\n\n return function (d, b) {\n _extendStatics(d, b);\n\n function __() {\n this.constructor = d;\n }\n\n d.prototype = b === null ? Object.create(b) : (__.prototype = b.prototype, new __());\n };\n}();\n\n\n\n\n\n\n\n\n\n\n\n\n\n/**\n * @typedef {Object} Options\n * @property {import("./Source.js").AttributionLike} [attributions] Attributions.\n * @property {boolean} [attributionsCollapsible=true] Attributions are collapsible.\n * @property {number} [cacheSize] Initial tile cache size. Will auto-grow to hold at least twice the number of tiles in the viewport.\n * @property {import("../extent.js").Extent} [extent]\n * @property {import("../format/Feature.js").default} [format] Feature format for tiles. Used and required by the default.\n * @property {boolean} [overlaps=true] This source may have overlapping geometries. Setting this\n * to `false` (e.g. for sources with polygons that represent administrative\n * boundaries or TopoJSON sources) allows the renderer to optimise fill and\n * stroke operations.\n * @property {import("../proj.js").ProjectionLike} [projection=\'EPSG:3857\'] Projection of the tile grid.\n * @property {import("./State.js").default} [state] Source state.\n * @property {typeof import("../VectorTile.js").default} [tileClass] Class used to instantiate image tiles.\n * Default is {@link module:ol/VectorTile}.\n * @property {number} [maxZoom=22] Optional max zoom level. Not used if `tileGrid` is provided.\n * @property {number} [minZoom] Optional min zoom level. Not used if `tileGrid` is provided.\n * @property {number|import("../size.js").Size} [tileSize=512] Optional tile size. Not used if `tileGrid` is provided.\n * @property {number} [maxResolution] Optional tile grid resolution at level zero. Not used if `tileGrid` is provided.\n * @property {import("../tilegrid/TileGrid.js").default} [tileGrid] Tile grid.\n * @property {import("../Tile.js").LoadFunction} [tileLoadFunction]\n * Optional function to load a tile given a URL. Could look like this for pbf tiles:\n * ```js\n * function(tile, url) {\n * tile.setLoader(function(extent, resolution, projection) {\n * fetch(url).then(function(response) {\n * response.arrayBuffer().then(function(data) {\n * const format = tile.getFormat() // ol/format/MVT configured as source format\n * const features = format.readFeatures(data, {\n * extent: extent,\n * featureProjection: projection\n * });\n * tile.setFeatures(features);\n * });\n * });\n * });\n * }\n * ```\n * If you do not need extent, resolution and projection to get the features for a tile (e.g.\n * for GeoJSON tiles), your `tileLoadFunction` does not need a `setLoader()` call. Only make sure\n * to call `setFeatures()` on the tile:\n * ```js\n * const format = new GeoJSON({featureProjection: map.getView().getProjection()});\n * async function tileLoadFunction(tile, url) {\n * const response = await fetch(url);\n * const data = await response.json();\n * tile.setFeatures(format.readFeatures(data));\n * }\n * ```\n * @property {import("../Tile.js").UrlFunction} [tileUrlFunction] Optional function to get tile URL given a tile coordinate and the projection.\n * @property {string} [url] URL template. Must include `{x}`, `{y}` or `{-y}`, and `{z}` placeholders.\n * A `{?-?}` template pattern, for example `subdomain{a-f}.domain.com`, may be\n * used instead of defining each one separately in the `urls` option.\n * @property {number} [transition] A duration for tile opacity\n * transitions in milliseconds. A duration of 0 disables the opacity transition.\n * @property {Array<string>} [urls] An array of URL templates.\n * @property {boolean} [wrapX=true] Whether to wrap the world horizontally.\n * When set to `false`, only one world\n * will be rendered. When set to `true`, tiles will be wrapped horizontally to\n * render multiple worlds.\n * @property {number} [zDirection=1] Indicate which resolution should be used\n * by a renderer if the view resolution does not match any resolution of the tile source.\n * If 0, the nearest resolution will be used. If 1, the nearest lower resolution\n * will be used. If -1, the nearest higher resolution will be used.\n */\n\n/**\n * @classdesc\n * Class for layer sources providing vector data divided into a tile grid, to be\n * used with {@link module:ol/layer/VectorTile~VectorTile}. Although this source receives tiles\n * with vector features from the server, it is not meant for feature editing.\n * Features are optimized for rendering, their geometries are clipped at or near\n * tile boundaries and simplified for a view resolution. See\n * {@link module:ol/source/Vector} for vector sources that are suitable for feature\n * editing.\n *\n * @fires import("./Tile.js").TileSourceEvent\n * @api\n */\n\nvar VectorTile_VectorTile =\n/** @class */\nfunction (_super) {\n source_VectorTile_extends(VectorTile, _super);\n /**\n * @param {!Options} options Vector tile options.\n */\n\n\n function VectorTile(options) {\n var _this = this;\n\n var projection = options.projection || \'EPSG:3857\';\n var extent = options.extent || extentFromProjection(projection);\n var tileGrid = options.tileGrid || createXYZ({\n extent: extent,\n maxResolution: options.maxResolution,\n maxZoom: options.maxZoom !== undefined ? options.maxZoom : 22,\n minZoom: options.minZoom,\n tileSize: options.tileSize || 512\n });\n _this = _super.call(this, {\n attributions: options.attributions,\n attributionsCollapsible: options.attributionsCollapsible,\n cacheSize: options.cacheSize,\n opaque: false,\n projection: projection,\n state: options.state,\n tileGrid: tileGrid,\n tileLoadFunction: options.tileLoadFunction ? options.tileLoadFunction : defaultLoadFunction,\n tileUrlFunction: options.tileUrlFunction,\n url: options.url,\n urls: options.urls,\n wrapX: options.wrapX === undefined ? true : options.wrapX,\n transition: options.transition,\n zDirection: options.zDirection === undefined ? 1 : options.zDirection\n }) || this;\n /**\n * @private\n * @type {import("../format/Feature.js").default}\n */\n\n _this.format_ = options.format ? options.format : null;\n /**\n * @type {Object<string, import("./VectorTile").default>}\n */\n\n _this.loadingTiles_ = {};\n /**\n * @private\n * @type {TileCache}\n */\n\n _this.sourceTileCache = new ol_TileCache(_this.tileCache.highWaterMark);\n /**\n * @private\n * @type {boolean}\n */\n\n _this.overlaps_ = options.overlaps == undefined ? true : options.overlaps;\n /**\n * @protected\n * @type {typeof import("../VectorTile.js").default}\n */\n\n _this.tileClass = options.tileClass ? options.tileClass : ol_VectorTile;\n /**\n * @private\n * @type {Object<string, import("../tilegrid/TileGrid.js").default>}\n */\n\n _this.tileGrids_ = {};\n return _this;\n }\n /**\n * Get features whose bounding box intersects the provided extent. Only features for cached\n * tiles for the last rendered zoom level are available in the source. So this method is only\n * suitable for requesting tiles for extents that are currently rendered.\n *\n * Features are returned in random tile order and as they are included in the tiles. This means\n * they can be clipped, duplicated across tiles, and simplified to the render resolution.\n *\n * @param {import("../extent.js").Extent} extent Extent.\n * @return {Array<import("../Feature.js").FeatureLike>} Features.\n * @api\n */\n\n\n VectorTile.prototype.getFeaturesInExtent = function (extent) {\n var features = [];\n var tileCache = this.tileCache;\n\n if (tileCache.getCount() === 0) {\n return features;\n }\n\n var z = fromKey(tileCache.peekFirstKey())[0];\n var tileGrid = this.tileGrid;\n tileCache.forEach(function (tile) {\n if (tile.tileCoord[0] !== z || tile.getState() !== TileState.LOADED) {\n return;\n }\n\n var sourceTiles = tile.getSourceTiles();\n\n for (var i = 0, ii = sourceTiles.length; i < ii; ++i) {\n var sourceTile = sourceTiles[i];\n var tileCoord = sourceTile.tileCoord;\n\n if (intersects(extent, tileGrid.getTileCoordExtent(tileCoord))) {\n var tileFeatures = sourceTile.getFeatures();\n\n if (tileFeatures) {\n for (var j = 0, jj = tileFeatures.length; j < jj; ++j) {\n var candidate = tileFeatures[j];\n var geometry = candidate.getGeometry();\n\n if (intersects(extent, geometry.getExtent())) {\n features.push(candidate);\n }\n }\n }\n }\n }\n });\n return features;\n };\n /**\n * @return {boolean} The source can have overlapping geometries.\n */\n\n\n VectorTile.prototype.getOverlaps = function () {\n return this.overlaps_;\n };\n /**\n * clear {@link module:ol/TileCache~TileCache} and delete all source tiles\n * @api\n */\n\n\n VectorTile.prototype.clear = function () {\n this.tileCache.clear();\n this.sourceTileCache.clear();\n };\n /**\n * @param {import("../proj/Projection.js").default} projection Projection.\n * @param {!Object<string, boolean>} usedTiles Used tiles.\n */\n\n\n VectorTile.prototype.expireCache = function (projection, usedTiles) {\n _super.prototype.expireCache.call(this, projection, usedTiles);\n\n this.sourceTileCache.expireCache({});\n };\n /**\n * @param {number} pixelRatio Pixel ratio.\n * @param {import("../proj/Projection").default} projection Projection.\n * @param {VectorRenderTile} tile Vector image tile.\n * @return {Array<import("../VectorTile").default>} Tile keys.\n */\n\n\n VectorTile.prototype.getSourceTiles = function (pixelRatio, projection, tile) {\n var urlTileCoord = tile.wrappedTileCoord;\n var tileGrid = this.getTileGridForProjection(projection);\n var extent = tileGrid.getTileCoordExtent(urlTileCoord);\n var z = urlTileCoord[0];\n var resolution = tileGrid.getResolution(z); // make extent 1 pixel smaller so we don\'t load tiles for < 0.5 pixel render space\n\n buffer(extent, -resolution, extent);\n var sourceTileGrid = this.tileGrid;\n var sourceExtent = sourceTileGrid.getExtent();\n\n if (sourceExtent) {\n getIntersection(extent, sourceExtent, extent);\n }\n\n var sourceZ = sourceTileGrid.getZForResolution(resolution, 1);\n var minZoom = sourceTileGrid.getMinZoom();\n var previousSourceTiles = tile.sourceTiles;\n var sourceTiles, covered, loadedZ;\n\n if (previousSourceTiles && previousSourceTiles.length > 0 && previousSourceTiles[0].tileCoord[0] === sourceZ) {\n sourceTiles = previousSourceTiles;\n covered = true;\n loadedZ = sourceZ;\n } else {\n sourceTiles = [];\n loadedZ = sourceZ + 1;\n\n do {\n --loadedZ;\n covered = true;\n sourceTileGrid.forEachTileCoord(extent, loadedZ, function (sourceTileCoord) {\n var tileUrl = this.tileUrlFunction(sourceTileCoord, pixelRatio, projection);\n var sourceTile;\n\n if (tileUrl !== undefined) {\n if (this.sourceTileCache.containsKey(tileUrl)) {\n sourceTile = this.sourceTileCache.get(tileUrl);\n var state = sourceTile.getState();\n\n if (state === TileState.LOADED || state === TileState.ERROR || state === TileState.EMPTY) {\n sourceTiles.push(sourceTile);\n return;\n }\n } else if (loadedZ === sourceZ) {\n sourceTile = new this.tileClass(sourceTileCoord, TileState.IDLE, tileUrl, this.format_, this.tileLoadFunction);\n sourceTile.extent = sourceTileGrid.getTileCoordExtent(sourceTileCoord);\n sourceTile.projection = projection;\n sourceTile.resolution = sourceTileGrid.getResolution(sourceTileCoord[0]);\n this.sourceTileCache.set(tileUrl, sourceTile);\n sourceTile.addEventListener(EventType.CHANGE, this.handleTileChange.bind(this));\n sourceTile.load();\n }\n }\n\n covered = covered && sourceTile && sourceTile.getState() === TileState.LOADED;\n\n if (!sourceTile) {\n return;\n }\n\n if (sourceTile.getState() !== TileState.EMPTY && tile.getState() === TileState.IDLE) {\n tile.loadingSourceTiles++;\n sourceTile.addEventListener(EventType.CHANGE, function listenChange() {\n var state = sourceTile.getState();\n var sourceTileKey = sourceTile.getKey();\n\n if (state === TileState.LOADED || state === TileState.ERROR) {\n if (state === TileState.LOADED) {\n sourceTile.removeEventListener(EventType.CHANGE, listenChange);\n tile.loadingSourceTiles--;\n delete tile.errorSourceTileKeys[sourceTileKey];\n } else if (state === TileState.ERROR) {\n tile.errorSourceTileKeys[sourceTileKey] = true;\n }\n\n var errorTileCount = Object.keys(tile.errorSourceTileKeys).length;\n\n if (tile.loadingSourceTiles - errorTileCount === 0) {\n tile.hifi = errorTileCount === 0;\n tile.sourceZ = sourceZ;\n tile.setState(TileState.LOADED);\n }\n }\n });\n }\n }.bind(this));\n\n if (!covered) {\n sourceTiles.length = 0;\n }\n } while (!covered && loadedZ > minZoom);\n }\n\n if (tile.getState() === TileState.IDLE) {\n tile.setState(TileState.LOADING);\n }\n\n if (covered) {\n tile.hifi = sourceZ === loadedZ;\n tile.sourceZ = loadedZ;\n\n if (tile.getState() < TileState.LOADED) {\n tile.setState(TileState.LOADED);\n } else if (!previousSourceTiles || !equals(sourceTiles, previousSourceTiles)) {\n tile.sourceTiles = sourceTiles;\n }\n }\n\n return sourceTiles;\n };\n /**\n * @param {number} z Tile coordinate z.\n * @param {number} x Tile coordinate x.\n * @param {number} y Tile coordinate y.\n * @param {number} pixelRatio Pixel ratio.\n * @param {import("../proj/Projection.js").default} projection Projection.\n * @return {!VectorRenderTile} Tile.\n */\n\n\n VectorTile.prototype.getTile = function (z, x, y, pixelRatio, projection) {\n var coordKey = getKeyZXY(z, x, y);\n var key = this.getKey();\n var tile;\n\n if (this.tileCache.containsKey(coordKey)) {\n tile = this.tileCache.get(coordKey);\n\n if (tile.key === key) {\n return tile;\n }\n }\n\n var tileCoord = [z, x, y];\n var urlTileCoord = this.getTileCoordForTileUrlFunction(tileCoord, projection);\n var sourceExtent = this.getTileGrid().getExtent();\n var tileGrid = this.getTileGridForProjection(projection);\n\n if (urlTileCoord && sourceExtent) {\n var tileExtent = tileGrid.getTileCoordExtent(urlTileCoord); // make extent 1 pixel smaller so we don\'t load tiles for < 0.5 pixel render space\n\n buffer(tileExtent, -tileGrid.getResolution(z), tileExtent);\n\n if (!intersects(sourceExtent, tileExtent)) {\n urlTileCoord = null;\n }\n }\n\n var empty = true;\n\n if (urlTileCoord !== null) {\n var sourceTileGrid = this.tileGrid;\n var resolution = tileGrid.getResolution(z);\n var sourceZ = sourceTileGrid.getZForResolution(resolution, 1); // make extent 1 pixel smaller so we don\'t load tiles for < 0.5 pixel render space\n\n var extent = tileGrid.getTileCoordExtent(urlTileCoord);\n buffer(extent, -resolution, extent);\n sourceTileGrid.forEachTileCoord(extent, sourceZ, function (sourceTileCoord) {\n empty = empty && !this.tileUrlFunction(sourceTileCoord, pixelRatio, projection);\n }.bind(this));\n }\n\n var newTile = new ol_VectorRenderTile(tileCoord, empty ? TileState.EMPTY : TileState.IDLE, urlTileCoord, this.getSourceTiles.bind(this, pixelRatio, projection));\n newTile.key = key;\n\n if (tile) {\n newTile.interimTile = tile;\n newTile.refreshInterimChain();\n this.tileCache.replace(coordKey, newTile);\n } else {\n this.tileCache.set(coordKey, newTile);\n }\n\n return newTile;\n };\n /**\n * @param {import("../proj/Projection.js").default} projection Projection.\n * @return {!import("../tilegrid/TileGrid.js").default} Tile grid.\n */\n\n\n VectorTile.prototype.getTileGridForProjection = function (projection) {\n var code = projection.getCode();\n var tileGrid = this.tileGrids_[code];\n\n if (!tileGrid) {\n // A tile grid that matches the tile size of the source tile grid is more\n // likely to have 1:1 relationships between source tiles and rendered tiles.\n var sourceTileGrid = this.tileGrid;\n tileGrid = createForProjection(projection, undefined, sourceTileGrid ? sourceTileGrid.getTileSize(sourceTileGrid.getMinZoom()) : undefined);\n this.tileGrids_[code] = tileGrid;\n }\n\n return tileGrid;\n };\n /**\n * Get the tile pixel ratio for this source.\n * @param {number} pixelRatio Pixel ratio.\n * @return {number} Tile pixel ratio.\n */\n\n\n VectorTile.prototype.getTilePixelRatio = function (pixelRatio) {\n return pixelRatio;\n };\n /**\n * @param {number} z Z.\n * @param {number} pixelRatio Pixel ratio.\n * @param {import("../proj/Projection.js").default} projection Projection.\n * @return {import("../size.js").Size} Tile size.\n */\n\n\n VectorTile.prototype.getTilePixelSize = function (z, pixelRatio, projection) {\n var tileGrid = this.getTileGridForProjection(projection);\n var tileSize = toSize(tileGrid.getTileSize(z), this.tmpSize);\n return [Math.round(tileSize[0] * pixelRatio), Math.round(tileSize[1] * pixelRatio)];\n };\n /**\n * Increases the cache size if needed\n * @param {number} tileCount Minimum number of tiles needed.\n * @param {import("../proj/Projection.js").default} projection Projection.\n */\n\n\n VectorTile.prototype.updateCacheSize = function (tileCount, projection) {\n _super.prototype.updateCacheSize.call(this, tileCount * 2, projection);\n };\n\n return VectorTile;\n}(source_UrlTile);\n\n/* harmony default export */ var source_VectorTile = (VectorTile_VectorTile);\n/**\n * Sets the loader for a tile.\n * @param {import("../VectorTile.js").default} tile Vector tile.\n * @param {string} url URL.\n */\n\nfunction defaultLoadFunction(tile, url) {\n tile.setLoader(\n /**\n * @param {import("../extent.js").Extent} extent Extent.\n * @param {number} resolution Resolution.\n * @param {import("../proj/Projection.js").default} projection Projection.\n */\n function (extent, resolution, projection) {\n loadFeaturesXhr(url, tile.getFormat(), extent, resolution, projection, tile.onLoad.bind(tile), tile.onError.bind(tile));\n });\n}\n// EXTERNAL MODULE: ./node_modules/rbush/rbush.min.js\nvar rbush_min = __webpack_require__(5792);\nvar rbush_min_default = /*#__PURE__*/__webpack_require__.n(rbush_min);\n;// CONCATENATED MODULE: ./node_modules/ol/style/Image.js\n/**\n * @module ol/style/Image\n */\n\n\n/**\n * @typedef {Object} Options\n * @property {number} opacity\n * @property {boolean} rotateWithView\n * @property {number} rotation\n * @property {number|import("../size.js").Size} scale\n * @property {Array<number>} displacement\n */\n\n/**\n * @classdesc\n * A base class used for creating subclasses and not instantiated in\n * apps. Base class for {@link module:ol/style/Icon~Icon}, {@link module:ol/style/Circle~CircleStyle} and\n * {@link module:ol/style/RegularShape~RegularShape}.\n * @abstract\n * @api\n */\n\nvar ImageStyle =\n/** @class */\nfunction () {\n /**\n * @param {Options} options Options.\n */\n function ImageStyle(options) {\n /**\n * @private\n * @type {number}\n */\n this.opacity_ = options.opacity;\n /**\n * @private\n * @type {boolean}\n */\n\n this.rotateWithView_ = options.rotateWithView;\n /**\n * @private\n * @type {number}\n */\n\n this.rotation_ = options.rotation;\n /**\n * @private\n * @type {number|import("../size.js").Size}\n */\n\n this.scale_ = options.scale;\n /**\n * @private\n * @type {import("../size.js").Size}\n */\n\n this.scaleArray_ = toSize(options.scale);\n /**\n * @private\n * @type {Array<number>}\n */\n\n this.displacement_ = options.displacement;\n }\n /**\n * Clones the style.\n * @return {ImageStyle} The cloned style.\n * @api\n */\n\n\n ImageStyle.prototype.clone = function () {\n var scale = this.getScale();\n return new ImageStyle({\n opacity: this.getOpacity(),\n scale: Array.isArray(scale) ? scale.slice() : scale,\n rotation: this.getRotation(),\n rotateWithView: this.getRotateWithView(),\n displacement: this.getDisplacement().slice()\n });\n };\n /**\n * Get the symbolizer opacity.\n * @return {number} Opacity.\n * @api\n */\n\n\n ImageStyle.prototype.getOpacity = function () {\n return this.opacity_;\n };\n /**\n * Determine whether the symbolizer rotates with the map.\n * @return {boolean} Rotate with map.\n * @api\n */\n\n\n ImageStyle.prototype.getRotateWithView = function () {\n return this.rotateWithView_;\n };\n /**\n * Get the symoblizer rotation.\n * @return {number} Rotation.\n * @api\n */\n\n\n ImageStyle.prototype.getRotation = function () {\n return this.rotation_;\n };\n /**\n * Get the symbolizer scale.\n * @return {number|import("../size.js").Size} Scale.\n * @api\n */\n\n\n ImageStyle.prototype.getScale = function () {\n return this.scale_;\n };\n /**\n * Get the symbolizer scale array.\n * @return {import("../size.js").Size} Scale array.\n */\n\n\n ImageStyle.prototype.getScaleArray = function () {\n return this.scaleArray_;\n };\n /**\n * Get the displacement of the shape\n * @return {Array<number>} Shape\'s center displacement\n * @api\n */\n\n\n ImageStyle.prototype.getDisplacement = function () {\n return this.displacement_;\n };\n /**\n * Get the anchor point in pixels. The anchor determines the center point for the\n * symbolizer.\n * @abstract\n * @return {Array<number>} Anchor.\n */\n\n\n ImageStyle.prototype.getAnchor = function () {\n return util_abstract();\n };\n /**\n * Get the image element for the symbolizer.\n * @abstract\n * @param {number} pixelRatio Pixel ratio.\n * @return {HTMLCanvasElement|HTMLVideoElement|HTMLImageElement} Image element.\n */\n\n\n ImageStyle.prototype.getImage = function (pixelRatio) {\n return util_abstract();\n };\n /**\n * @abstract\n * @return {HTMLCanvasElement|HTMLVideoElement|HTMLImageElement} Image element.\n */\n\n\n ImageStyle.prototype.getHitDetectionImage = function () {\n return util_abstract();\n };\n /*\n * Get the image pixel ratio.\n * @param {number} pixelRatio Pixel ratio.\n * */\n\n\n ImageStyle.prototype.getPixelRatio = function (pixelRatio) {\n return 1;\n };\n /**\n * @abstract\n * @return {import("../ImageState.js").default} Image state.\n */\n\n\n ImageStyle.prototype.getImageState = function () {\n return util_abstract();\n };\n /**\n * @abstract\n * @return {import("../size.js").Size} Image size.\n */\n\n\n ImageStyle.prototype.getImageSize = function () {\n return util_abstract();\n };\n /**\n * @abstract\n * @return {import("../size.js").Size} Size of the hit-detection image.\n */\n\n\n ImageStyle.prototype.getHitDetectionImageSize = function () {\n return util_abstract();\n };\n /**\n * Get the origin of the symbolizer.\n * @abstract\n * @return {Array<number>} Origin.\n */\n\n\n ImageStyle.prototype.getOrigin = function () {\n return util_abstract();\n };\n /**\n * Get the size of the symbolizer (in pixels).\n * @abstract\n * @return {import("../size.js").Size} Size.\n */\n\n\n ImageStyle.prototype.getSize = function () {\n return util_abstract();\n };\n /**\n * Set the opacity.\n *\n * @param {number} opacity Opacity.\n * @api\n */\n\n\n ImageStyle.prototype.setOpacity = function (opacity) {\n this.opacity_ = opacity;\n };\n /**\n * Set whether to rotate the style with the view.\n *\n * @param {boolean} rotateWithView Rotate with map.\n * @api\n */\n\n\n ImageStyle.prototype.setRotateWithView = function (rotateWithView) {\n this.rotateWithView_ = rotateWithView;\n };\n /**\n * Set the rotation.\n *\n * @param {number} rotation Rotation.\n * @api\n */\n\n\n ImageStyle.prototype.setRotation = function (rotation) {\n this.rotation_ = rotation;\n };\n /**\n * Set the scale.\n *\n * @param {number|import("../size.js").Size} scale Scale.\n * @api\n */\n\n\n ImageStyle.prototype.setScale = function (scale) {\n this.scale_ = scale;\n this.scaleArray_ = toSize(scale);\n };\n /**\n * @abstract\n * @param {function(import("../events/Event.js").default): void} listener Listener function.\n */\n\n\n ImageStyle.prototype.listenImageChange = function (listener) {\n util_abstract();\n };\n /**\n * Load not yet loaded URI.\n * @abstract\n */\n\n\n ImageStyle.prototype.load = function () {\n util_abstract();\n };\n /**\n * @abstract\n * @param {function(import("../events/Event.js").default): void} listener Listener function.\n */\n\n\n ImageStyle.prototype.unlistenImageChange = function (listener) {\n util_abstract();\n };\n\n return ImageStyle;\n}();\n\n/* harmony default export */ var style_Image = (ImageStyle);\n;// CONCATENATED MODULE: ./node_modules/ol/colorlike.js\n/**\n * @module ol/colorlike\n */\n\n/**\n * A type accepted by CanvasRenderingContext2D.fillStyle\n * or CanvasRenderingContext2D.strokeStyle.\n * Represents a color, pattern, or gradient. The origin for patterns and\n * gradients as fill style is an increment of 512 css pixels from map coordinate\n * `[0, 0]`. For seamless repeat patterns, width and height of the pattern image\n * must be a factor of two (2, 4, 8, ..., 512).\n *\n * @typedef {string|CanvasPattern|CanvasGradient} ColorLike\n * @api\n */\n\n/**\n * @param {import("./color.js").Color|ColorLike} color Color.\n * @return {ColorLike} The color as an {@link ol/colorlike~ColorLike}.\n * @api\n */\n\nfunction asColorLike(color) {\n if (Array.isArray(color)) {\n return color_toString(color);\n } else {\n return color;\n }\n}\n;// CONCATENATED MODULE: ./node_modules/ol/style/RegularShape.js\n/**\n * @module ol/style/RegularShape\n */\nvar RegularShape_extends = undefined && undefined.__extends || function () {\n var _extendStatics = function extendStatics(d, b) {\n _extendStatics = Object.setPrototypeOf || {\n __proto__: []\n } instanceof Array && function (d, b) {\n d.__proto__ = b;\n } || function (d, b) {\n for (var p in b) {\n if (Object.prototype.hasOwnProperty.call(b, p)) d[p] = b[p];\n }\n };\n\n return _extendStatics(d, b);\n };\n\n return function (d, b) {\n _extendStatics(d, b);\n\n function __() {\n this.constructor = d;\n }\n\n d.prototype = b === null ? Object.create(b) : (__.prototype = b.prototype, new __());\n };\n}();\n\n\n\n\n\n\n\n/**\n * Specify radius for regular polygons, or radius1 and radius2 for stars.\n * @typedef {Object} Options\n * @property {import("./Fill.js").default} [fill] Fill style.\n * @property {number} points Number of points for stars and regular polygons. In case of a polygon, the number of points\n * is the number of sides.\n * @property {number} [radius] Radius of a regular polygon.\n * @property {number} [radius1] Outer radius of a star.\n * @property {number} [radius2] Inner radius of a star.\n * @property {number} [angle=0] Shape\'s angle in radians. A value of 0 will have one of the shape\'s point facing up.\n * @property {Array<number>} [displacement=[0,0]] Displacement of the shape\n * @property {import("./Stroke.js").default} [stroke] Stroke style.\n * @property {number} [rotation=0] Rotation in radians (positive rotation clockwise).\n * @property {boolean} [rotateWithView=false] Whether to rotate the shape with the view.\n * @property {number|import("../size.js").Size} [scale=1] Scale. Unless two dimensional scaling is required a better\n * result may be obtained with appropriate settings for `radius`, `radius1` and `radius2`.\n */\n\n/**\n * @typedef {Object} RenderOptions\n * @property {import("../colorlike.js").ColorLike} [strokeStyle]\n * @property {number} strokeWidth\n * @property {number} size\n * @property {CanvasLineCap} lineCap\n * @property {Array<number>} lineDash\n * @property {number} lineDashOffset\n * @property {CanvasLineJoin} lineJoin\n * @property {number} miterLimit\n */\n\n/**\n * @classdesc\n * Set regular shape style for vector features. The resulting shape will be\n * a regular polygon when `radius` is provided, or a star when `radius1` and\n * `radius2` are provided.\n * @api\n */\n\nvar RegularShape =\n/** @class */\nfunction (_super) {\n RegularShape_extends(RegularShape, _super);\n /**\n * @param {Options} options Options.\n */\n\n\n function RegularShape(options) {\n var _this = this;\n /**\n * @type {boolean}\n */\n\n\n var rotateWithView = options.rotateWithView !== undefined ? options.rotateWithView : false;\n _this = _super.call(this, {\n opacity: 1,\n rotateWithView: rotateWithView,\n rotation: options.rotation !== undefined ? options.rotation : 0,\n scale: options.scale !== undefined ? options.scale : 1,\n displacement: options.displacement !== undefined ? options.displacement : [0, 0]\n }) || this;\n /**\n * @private\n * @type {Object<number, HTMLCanvasElement>}\n */\n\n _this.canvas_ = {};\n /**\n * @private\n * @type {HTMLCanvasElement}\n */\n\n _this.hitDetectionCanvas_ = null;\n /**\n * @private\n * @type {import("./Fill.js").default}\n */\n\n _this.fill_ = options.fill !== undefined ? options.fill : null;\n /**\n * @private\n * @type {Array<number>}\n */\n\n _this.origin_ = [0, 0];\n /**\n * @private\n * @type {number}\n */\n\n _this.points_ = options.points;\n /**\n * @protected\n * @type {number}\n */\n\n _this.radius_ = options.radius !== undefined ? options.radius : options.radius1;\n /**\n * @private\n * @type {number|undefined}\n */\n\n _this.radius2_ = options.radius2;\n /**\n * @private\n * @type {number}\n */\n\n _this.angle_ = options.angle !== undefined ? options.angle : 0;\n /**\n * @private\n * @type {import("./Stroke.js").default}\n */\n\n _this.stroke_ = options.stroke !== undefined ? options.stroke : null;\n /**\n * @private\n * @type {Array<number>}\n */\n\n _this.anchor_ = null;\n /**\n * @private\n * @type {import("../size.js").Size}\n */\n\n _this.size_ = null;\n /**\n * @private\n * @type {import("../size.js").Size}\n */\n\n _this.imageSize_ = null;\n /**\n * @private\n * @type {import("../size.js").Size}\n */\n\n _this.hitDetectionImageSize_ = null;\n\n _this.render();\n\n return _this;\n }\n /**\n * Clones the style.\n * @return {RegularShape} The cloned style.\n * @api\n */\n\n\n RegularShape.prototype.clone = function () {\n var scale = this.getScale();\n var style = new RegularShape({\n fill: this.getFill() ? this.getFill().clone() : undefined,\n points: this.getPoints(),\n radius: this.getRadius(),\n radius2: this.getRadius2(),\n angle: this.getAngle(),\n stroke: this.getStroke() ? this.getStroke().clone() : undefined,\n rotation: this.getRotation(),\n rotateWithView: this.getRotateWithView(),\n scale: Array.isArray(scale) ? scale.slice() : scale,\n displacement: this.getDisplacement().slice()\n });\n style.setOpacity(this.getOpacity());\n return style;\n };\n /**\n * Get the anchor point in pixels. The anchor determines the center point for the\n * symbolizer.\n * @return {Array<number>} Anchor.\n * @api\n */\n\n\n RegularShape.prototype.getAnchor = function () {\n return this.anchor_;\n };\n /**\n * Get the angle used in generating the shape.\n * @return {number} Shape\'s rotation in radians.\n * @api\n */\n\n\n RegularShape.prototype.getAngle = function () {\n return this.angle_;\n };\n /**\n * Get the fill style for the shape.\n * @return {import("./Fill.js").default} Fill style.\n * @api\n */\n\n\n RegularShape.prototype.getFill = function () {\n return this.fill_;\n };\n /**\n * @return {HTMLCanvasElement} Image element.\n */\n\n\n RegularShape.prototype.getHitDetectionImage = function () {\n if (!this.hitDetectionCanvas_) {\n var renderOptions = this.createRenderOptions();\n this.createHitDetectionCanvas_(renderOptions);\n }\n\n return this.hitDetectionCanvas_;\n };\n /**\n * Get the image icon.\n * @param {number} pixelRatio Pixel ratio.\n * @return {HTMLCanvasElement} Image or Canvas element.\n * @api\n */\n\n\n RegularShape.prototype.getImage = function (pixelRatio) {\n if (!this.canvas_[pixelRatio || 1]) {\n var renderOptions = this.createRenderOptions();\n var context = createCanvasContext2D(renderOptions.size * pixelRatio || 1, renderOptions.size * pixelRatio || 1);\n this.draw_(renderOptions, context, 0, 0, pixelRatio || 1);\n this.canvas_[pixelRatio || 1] = context.canvas;\n }\n\n return this.canvas_[pixelRatio || 1];\n };\n /*\n * Get the image pixel ratio.\n * @param {number} pixelRatio Pixel ratio.\n * */\n\n\n RegularShape.prototype.getPixelRatio = function (pixelRatio) {\n return pixelRatio;\n };\n /**\n * @return {import("../size.js").Size} Image size.\n */\n\n\n RegularShape.prototype.getImageSize = function () {\n return this.imageSize_;\n };\n /**\n * @return {import("../size.js").Size} Size of the hit-detection image.\n */\n\n\n RegularShape.prototype.getHitDetectionImageSize = function () {\n return this.hitDetectionImageSize_;\n };\n /**\n * @return {import("../ImageState.js").default} Image state.\n */\n\n\n RegularShape.prototype.getImageState = function () {\n return ImageState.LOADED;\n };\n /**\n * Get the origin of the symbolizer.\n * @return {Array<number>} Origin.\n * @api\n */\n\n\n RegularShape.prototype.getOrigin = function () {\n return this.origin_;\n };\n /**\n * Get the number of points for generating the shape.\n * @return {number} Number of points for stars and regular polygons.\n * @api\n */\n\n\n RegularShape.prototype.getPoints = function () {\n return this.points_;\n };\n /**\n * Get the (primary) radius for the shape.\n * @return {number} Radius.\n * @api\n */\n\n\n RegularShape.prototype.getRadius = function () {\n return this.radius_;\n };\n /**\n * Get the secondary radius for the shape.\n * @return {number|undefined} Radius2.\n * @api\n */\n\n\n RegularShape.prototype.getRadius2 = function () {\n return this.radius2_;\n };\n /**\n * Get the size of the symbolizer (in pixels).\n * @return {import("../size.js").Size} Size.\n * @api\n */\n\n\n RegularShape.prototype.getSize = function () {\n return this.size_;\n };\n /**\n * Get the stroke style for the shape.\n * @return {import("./Stroke.js").default} Stroke style.\n * @api\n */\n\n\n RegularShape.prototype.getStroke = function () {\n return this.stroke_;\n };\n /**\n * @param {function(import("../events/Event.js").default): void} listener Listener function.\n */\n\n\n RegularShape.prototype.listenImageChange = function (listener) {};\n /**\n * Load not yet loaded URI.\n */\n\n\n RegularShape.prototype.load = function () {};\n /**\n * @param {function(import("../events/Event.js").default): void} listener Listener function.\n */\n\n\n RegularShape.prototype.unlistenImageChange = function (listener) {};\n /**\n * @returns {RenderOptions} The render options\n * @protected\n */\n\n\n RegularShape.prototype.createRenderOptions = function () {\n var lineCap = defaultLineCap;\n var lineJoin = defaultLineJoin;\n var miterLimit = 0;\n var lineDash = null;\n var lineDashOffset = 0;\n var strokeStyle;\n var strokeWidth = 0;\n\n if (this.stroke_) {\n strokeStyle = this.stroke_.getColor();\n\n if (strokeStyle === null) {\n strokeStyle = defaultStrokeStyle;\n }\n\n strokeStyle = asColorLike(strokeStyle);\n strokeWidth = this.stroke_.getWidth();\n\n if (strokeWidth === undefined) {\n strokeWidth = defaultLineWidth;\n }\n\n lineDash = this.stroke_.getLineDash();\n lineDashOffset = this.stroke_.getLineDashOffset();\n lineJoin = this.stroke_.getLineJoin();\n\n if (lineJoin === undefined) {\n lineJoin = defaultLineJoin;\n }\n\n lineCap = this.stroke_.getLineCap();\n\n if (lineCap === undefined) {\n lineCap = defaultLineCap;\n }\n\n miterLimit = this.stroke_.getMiterLimit();\n\n if (miterLimit === undefined) {\n miterLimit = defaultMiterLimit;\n }\n }\n\n var size = 2 * (this.radius_ + strokeWidth) + 1;\n return {\n strokeStyle: strokeStyle,\n strokeWidth: strokeWidth,\n size: size,\n lineCap: lineCap,\n lineDash: lineDash,\n lineDashOffset: lineDashOffset,\n lineJoin: lineJoin,\n miterLimit: miterLimit\n };\n };\n /**\n * @protected\n */\n\n\n RegularShape.prototype.render = function () {\n var renderOptions = this.createRenderOptions();\n var context = createCanvasContext2D(renderOptions.size, renderOptions.size);\n this.draw_(renderOptions, context, 0, 0, 1);\n this.canvas_ = {};\n this.canvas_[1] = context.canvas; // canvas.width and height are rounded to the closest integer\n\n var size = context.canvas.width;\n var imageSize = size;\n var displacement = this.getDisplacement();\n this.hitDetectionImageSize_ = [renderOptions.size, renderOptions.size];\n this.createHitDetectionCanvas_(renderOptions);\n this.anchor_ = [size / 2 - displacement[0], size / 2 + displacement[1]];\n this.size_ = [size, size];\n this.imageSize_ = [imageSize, imageSize];\n };\n /**\n * @private\n * @param {RenderOptions} renderOptions Render options.\n * @param {CanvasRenderingContext2D} context The rendering context.\n * @param {number} x The origin for the symbol (x).\n * @param {number} y The origin for the symbol (y).\n * @param {number} pixelRatio The pixel ratio.\n */\n\n\n RegularShape.prototype.draw_ = function (renderOptions, context, x, y, pixelRatio) {\n var i, angle0, radiusC; // reset transform\n\n context.setTransform(pixelRatio, 0, 0, pixelRatio, 0, 0); // then move to (x, y)\n\n context.translate(x, y);\n context.beginPath();\n var points = this.points_;\n\n if (points === Infinity) {\n context.arc(renderOptions.size / 2, renderOptions.size / 2, this.radius_, 0, 2 * Math.PI, true);\n } else {\n var radius2 = this.radius2_ !== undefined ? this.radius2_ : this.radius_;\n\n if (radius2 !== this.radius_) {\n points = 2 * points;\n }\n\n for (i = 0; i <= points; i++) {\n angle0 = i * 2 * Math.PI / points - Math.PI / 2 + this.angle_;\n radiusC = i % 2 === 0 ? this.radius_ : radius2;\n context.lineTo(renderOptions.size / 2 + radiusC * Math.cos(angle0), renderOptions.size / 2 + radiusC * Math.sin(angle0));\n }\n }\n\n if (this.fill_) {\n var color = this.fill_.getColor();\n\n if (color === null) {\n color = defaultFillStyle;\n }\n\n context.fillStyle = asColorLike(color);\n context.fill();\n }\n\n if (this.stroke_) {\n context.strokeStyle = renderOptions.strokeStyle;\n context.lineWidth = renderOptions.strokeWidth;\n\n if (context.setLineDash && renderOptions.lineDash) {\n context.setLineDash(renderOptions.lineDash);\n context.lineDashOffset = renderOptions.lineDashOffset;\n }\n\n context.lineCap = renderOptions.lineCap;\n context.lineJoin = renderOptions.lineJoin;\n context.miterLimit = renderOptions.miterLimit;\n context.stroke();\n }\n\n context.closePath();\n };\n /**\n * @private\n * @param {RenderOptions} renderOptions Render options.\n */\n\n\n RegularShape.prototype.createHitDetectionCanvas_ = function (renderOptions) {\n this.hitDetectionCanvas_ = this.getImage(1);\n\n if (this.fill_) {\n var color = this.fill_.getColor(); // determine if fill is transparent (or pattern or gradient)\n\n var opacity = 0;\n\n if (typeof color === \'string\') {\n color = asArray(color);\n }\n\n if (color === null) {\n opacity = 1;\n } else if (Array.isArray(color)) {\n opacity = color.length === 4 ? color[3] : 1;\n }\n\n if (opacity === 0) {\n // if a transparent fill style is set, create an extra hit-detection image\n // with a default fill style\n var context = createCanvasContext2D(renderOptions.size, renderOptions.size);\n this.hitDetectionCanvas_ = context.canvas;\n this.drawHitDetectionCanvas_(renderOptions, context, 0, 0);\n }\n }\n };\n /**\n * @private\n * @param {RenderOptions} renderOptions Render options.\n * @param {CanvasRenderingContext2D} context The context.\n * @param {number} x The origin for the symbol (x).\n * @param {number} y The origin for the symbol (y).\n */\n\n\n RegularShape.prototype.drawHitDetectionCanvas_ = function (renderOptions, context, x, y) {\n // move to (x, y)\n context.translate(x, y);\n context.beginPath();\n var points = this.points_;\n\n if (points === Infinity) {\n context.arc(renderOptions.size / 2, renderOptions.size / 2, this.radius_, 0, 2 * Math.PI, true);\n } else {\n var radius2 = this.radius2_ !== undefined ? this.radius2_ : this.radius_;\n\n if (radius2 !== this.radius_) {\n points = 2 * points;\n }\n\n var i = void 0,\n radiusC = void 0,\n angle0 = void 0;\n\n for (i = 0; i <= points; i++) {\n angle0 = i * 2 * Math.PI / points - Math.PI / 2 + this.angle_;\n radiusC = i % 2 === 0 ? this.radius_ : radius2;\n context.lineTo(renderOptions.size / 2 + radiusC * Math.cos(angle0), renderOptions.size / 2 + radiusC * Math.sin(angle0));\n }\n }\n\n context.fillStyle = defaultFillStyle;\n context.fill();\n\n if (this.stroke_) {\n context.strokeStyle = renderOptions.strokeStyle;\n context.lineWidth = renderOptions.strokeWidth;\n\n if (renderOptions.lineDash) {\n context.setLineDash(renderOptions.lineDash);\n context.lineDashOffset = renderOptions.lineDashOffset;\n }\n\n context.stroke();\n }\n\n context.closePath();\n };\n\n return RegularShape;\n}(style_Image);\n\n/* harmony default export */ var style_RegularShape = (RegularShape);\n;// CONCATENATED MODULE: ./node_modules/ol/style/Circle.js\n/**\n * @module ol/style/Circle\n */\nvar Circle_extends = undefined && undefined.__extends || function () {\n var _extendStatics = function extendStatics(d, b) {\n _extendStatics = Object.setPrototypeOf || {\n __proto__: []\n } instanceof Array && function (d, b) {\n d.__proto__ = b;\n } || function (d, b) {\n for (var p in b) {\n if (Object.prototype.hasOwnProperty.call(b, p)) d[p] = b[p];\n }\n };\n\n return _extendStatics(d, b);\n };\n\n return function (d, b) {\n _extendStatics(d, b);\n\n function __() {\n this.constructor = d;\n }\n\n d.prototype = b === null ? Object.create(b) : (__.prototype = b.prototype, new __());\n };\n}();\n\n\n/**\n * @typedef {Object} Options\n * @property {import("./Fill.js").default} [fill] Fill style.\n * @property {number} radius Circle radius.\n * @property {import("./Stroke.js").default} [stroke] Stroke style.\n * @property {Array<number>} [displacement=[0,0]] displacement\n * @property {number|import("../size.js").Size} [scale=1] Scale. A two dimensional scale will produce an ellipse.\n * Unless two dimensional scaling is required a better result may be obtained with an appropriate setting for `radius`.\n * @property {number} [rotation=0] Rotation in radians\n * (positive rotation clockwise, meaningful only when used in conjunction with a two dimensional scale).\n * @property {boolean} [rotateWithView=false] Whether to rotate the shape with the view\n * (meaningful only when used in conjunction with a two dimensional scale).\n */\n\n/**\n * @classdesc\n * Set circle style for vector features.\n * @api\n */\n\nvar Circle_CircleStyle =\n/** @class */\nfunction (_super) {\n Circle_extends(CircleStyle, _super);\n /**\n * @param {Options=} opt_options Options.\n */\n\n\n function CircleStyle(opt_options) {\n var _this = this;\n\n var options = opt_options ? opt_options : {};\n _this = _super.call(this, {\n points: Infinity,\n fill: options.fill,\n radius: options.radius,\n stroke: options.stroke,\n scale: options.scale !== undefined ? options.scale : 1,\n rotation: options.rotation !== undefined ? options.rotation : 0,\n rotateWithView: options.rotateWithView !== undefined ? options.rotateWithView : false,\n displacement: options.displacement !== undefined ? options.displacement : [0, 0]\n }) || this;\n return _this;\n }\n /**\n * Clones the style.\n * @return {CircleStyle} The cloned style.\n * @api\n */\n\n\n CircleStyle.prototype.clone = function () {\n var scale = this.getScale();\n var style = new CircleStyle({\n fill: this.getFill() ? this.getFill().clone() : undefined,\n stroke: this.getStroke() ? this.getStroke().clone() : undefined,\n radius: this.getRadius(),\n scale: Array.isArray(scale) ? scale.slice() : scale,\n rotation: this.getRotation(),\n rotateWithView: this.getRotateWithView(),\n displacement: this.getDisplacement().slice()\n });\n style.setOpacity(this.getOpacity());\n return style;\n };\n /**\n * Set the circle radius.\n *\n * @param {number} radius Circle radius.\n * @api\n */\n\n\n CircleStyle.prototype.setRadius = function (radius) {\n this.radius_ = radius;\n this.render();\n };\n\n return CircleStyle;\n}(style_RegularShape);\n\n/* harmony default export */ var Circle = (Circle_CircleStyle);\n;// CONCATENATED MODULE: ./node_modules/ol/style/Fill.js\n/**\n * @module ol/style/Fill\n */\n\n/**\n * @typedef {Object} Options\n * @property {import("../color.js").Color|import("../colorlike.js").ColorLike} [color=null] A color, gradient or pattern.\n * See {@link module:ol/color~Color} and {@link module:ol/colorlike~ColorLike} for possible formats.\n * Default null; if null, the Canvas/renderer default black will be used.\n */\n\n/**\n * @classdesc\n * Set fill style for vector features.\n * @api\n */\nvar Fill_Fill =\n/** @class */\nfunction () {\n /**\n * @param {Options=} opt_options Options.\n */\n function Fill(opt_options) {\n var options = opt_options || {};\n /**\n * @private\n * @type {import("../color.js").Color|import("../colorlike.js").ColorLike}\n */\n\n this.color_ = options.color !== undefined ? options.color : null;\n }\n /**\n * Clones the style. The color is not cloned if it is an {@link module:ol/colorlike~ColorLike}.\n * @return {Fill} The cloned style.\n * @api\n */\n\n\n Fill.prototype.clone = function () {\n var color = this.getColor();\n return new Fill({\n color: Array.isArray(color) ? color.slice() : color || undefined\n });\n };\n /**\n * Get the fill color.\n * @return {import("../color.js").Color|import("../colorlike.js").ColorLike} Color.\n * @api\n */\n\n\n Fill.prototype.getColor = function () {\n return this.color_;\n };\n /**\n * Set the color.\n *\n * @param {import("../color.js").Color|import("../colorlike.js").ColorLike} color Color.\n * @api\n */\n\n\n Fill.prototype.setColor = function (color) {\n this.color_ = color;\n };\n\n return Fill;\n}();\n\n/* harmony default export */ var style_Fill = (Fill_Fill);\n;// CONCATENATED MODULE: ./node_modules/ol/style/Stroke.js\n/**\n * @module ol/style/Stroke\n */\n\n/**\n * @typedef {Object} Options\n * @property {import("../color.js").Color|import("../colorlike.js").ColorLike} [color] A color, gradient or pattern.\n * See {@link module:ol/color~Color} and {@link module:ol/colorlike~ColorLike} for possible formats.\n * Default null; if null, the Canvas/renderer default black will be used.\n * @property {CanvasLineCap} [lineCap=\'round\'] Line cap style: `butt`, `round`, or `square`.\n * @property {CanvasLineJoin} [lineJoin=\'round\'] Line join style: `bevel`, `round`, or `miter`.\n * @property {Array<number>} [lineDash] Line dash pattern. Default is `null` (no dash).\n * Please note that Internet Explorer 10 and lower do not support the `setLineDash` method on\n * the `CanvasRenderingContext2D` and therefore this option will have no visual effect in these browsers.\n * @property {number} [lineDashOffset=0] Line dash offset.\n * @property {number} [miterLimit=10] Miter limit.\n * @property {number} [width] Width.\n */\n\n/**\n * @classdesc\n * Set stroke style for vector features.\n * Note that the defaults given are the Canvas defaults, which will be used if\n * option is not defined. The `get` functions return whatever was entered in\n * the options; they will not return the default.\n * @api\n */\nvar Stroke_Stroke =\n/** @class */\nfunction () {\n /**\n * @param {Options=} opt_options Options.\n */\n function Stroke(opt_options) {\n var options = opt_options || {};\n /**\n * @private\n * @type {import("../color.js").Color|import("../colorlike.js").ColorLike}\n */\n\n this.color_ = options.color !== undefined ? options.color : null;\n /**\n * @private\n * @type {CanvasLineCap|undefined}\n */\n\n this.lineCap_ = options.lineCap;\n /**\n * @private\n * @type {Array<number>}\n */\n\n this.lineDash_ = options.lineDash !== undefined ? options.lineDash : null;\n /**\n * @private\n * @type {number|undefined}\n */\n\n this.lineDashOffset_ = options.lineDashOffset;\n /**\n * @private\n * @type {CanvasLineJoin|undefined}\n */\n\n this.lineJoin_ = options.lineJoin;\n /**\n * @private\n * @type {number|undefined}\n */\n\n this.miterLimit_ = options.miterLimit;\n /**\n * @private\n * @type {number|undefined}\n */\n\n this.width_ = options.width;\n }\n /**\n * Clones the style.\n * @return {Stroke} The cloned style.\n * @api\n */\n\n\n Stroke.prototype.clone = function () {\n var color = this.getColor();\n return new Stroke({\n color: Array.isArray(color) ? color.slice() : color || undefined,\n lineCap: this.getLineCap(),\n lineDash: this.getLineDash() ? this.getLineDash().slice() : undefined,\n lineDashOffset: this.getLineDashOffset(),\n lineJoin: this.getLineJoin(),\n miterLimit: this.getMiterLimit(),\n width: this.getWidth()\n });\n };\n /**\n * Get the stroke color.\n * @return {import("../color.js").Color|import("../colorlike.js").ColorLike} Color.\n * @api\n */\n\n\n Stroke.prototype.getColor = function () {\n return this.color_;\n };\n /**\n * Get the line cap type for the stroke.\n * @return {CanvasLineCap|undefined} Line cap.\n * @api\n */\n\n\n Stroke.prototype.getLineCap = function () {\n return this.lineCap_;\n };\n /**\n * Get the line dash style for the stroke.\n * @return {Array<number>} Line dash.\n * @api\n */\n\n\n Stroke.prototype.getLineDash = function () {\n return this.lineDash_;\n };\n /**\n * Get the line dash offset for the stroke.\n * @return {number|undefined} Line dash offset.\n * @api\n */\n\n\n Stroke.prototype.getLineDashOffset = function () {\n return this.lineDashOffset_;\n };\n /**\n * Get the line join type for the stroke.\n * @return {CanvasLineJoin|undefined} Line join.\n * @api\n */\n\n\n Stroke.prototype.getLineJoin = function () {\n return this.lineJoin_;\n };\n /**\n * Get the miter limit for the stroke.\n * @return {number|undefined} Miter limit.\n * @api\n */\n\n\n Stroke.prototype.getMiterLimit = function () {\n return this.miterLimit_;\n };\n /**\n * Get the stroke width.\n * @return {number|undefined} Width.\n * @api\n */\n\n\n Stroke.prototype.getWidth = function () {\n return this.width_;\n };\n /**\n * Set the color.\n *\n * @param {import("../color.js").Color|import("../colorlike.js").ColorLike} color Color.\n * @api\n */\n\n\n Stroke.prototype.setColor = function (color) {\n this.color_ = color;\n };\n /**\n * Set the line cap.\n *\n * @param {CanvasLineCap|undefined} lineCap Line cap.\n * @api\n */\n\n\n Stroke.prototype.setLineCap = function (lineCap) {\n this.lineCap_ = lineCap;\n };\n /**\n * Set the line dash.\n *\n * Please note that Internet Explorer 10 and lower [do not support][mdn] the\n * `setLineDash` method on the `CanvasRenderingContext2D` and therefore this\n * property will have no visual effect in these browsers.\n *\n * [mdn]: https://developer.mozilla.org/en-US/docs/Web/API/CanvasRenderingContext2D/setLineDash#Browser_compatibility\n *\n * @param {Array<number>} lineDash Line dash.\n * @api\n */\n\n\n Stroke.prototype.setLineDash = function (lineDash) {\n this.lineDash_ = lineDash;\n };\n /**\n * Set the line dash offset.\n *\n * @param {number|undefined} lineDashOffset Line dash offset.\n * @api\n */\n\n\n Stroke.prototype.setLineDashOffset = function (lineDashOffset) {\n this.lineDashOffset_ = lineDashOffset;\n };\n /**\n * Set the line join.\n *\n * @param {CanvasLineJoin|undefined} lineJoin Line join.\n * @api\n */\n\n\n Stroke.prototype.setLineJoin = function (lineJoin) {\n this.lineJoin_ = lineJoin;\n };\n /**\n * Set the miter limit.\n *\n * @param {number|undefined} miterLimit Miter limit.\n * @api\n */\n\n\n Stroke.prototype.setMiterLimit = function (miterLimit) {\n this.miterLimit_ = miterLimit;\n };\n /**\n * Set the width.\n *\n * @param {number|undefined} width Width.\n * @api\n */\n\n\n Stroke.prototype.setWidth = function (width) {\n this.width_ = width;\n };\n\n return Stroke;\n}();\n\n/* harmony default export */ var style_Stroke = (Stroke_Stroke);\n;// CONCATENATED MODULE: ./node_modules/ol/style/Style.js\n/**\n * @module ol/style/Style\n */\n\n\n\n\n\n/**\n * A function that takes an {@link module:ol/Feature} and a `{number}`\n * representing the view\'s resolution. The function should return a\n * {@link module:ol/style/Style} or an array of them. This way e.g. a\n * vector layer can be styled. If the function returns `undefined`, the\n * feature will not be rendered.\n *\n * @typedef {function(import("../Feature.js").FeatureLike, number):(Style|Array<Style>|void)} StyleFunction\n */\n\n/**\n * A {@link Style}, an array of {@link Style}, or a {@link StyleFunction}.\n * @typedef {Style|Array<Style>|StyleFunction} StyleLike\n */\n\n/**\n * A function that takes an {@link module:ol/Feature} as argument and returns an\n * {@link module:ol/geom/Geometry} that will be rendered and styled for the feature.\n *\n * @typedef {function(import("../Feature.js").FeatureLike):\n * (import("../geom/Geometry.js").default|import("../render/Feature.js").default|undefined)} GeometryFunction\n */\n\n/**\n * Custom renderer function. Takes two arguments:\n *\n * 1. The pixel coordinates of the geometry in GeoJSON notation.\n * 2. The {@link module:ol/render~State} of the layer renderer.\n *\n * @typedef {function((import("../coordinate.js").Coordinate|Array<import("../coordinate.js").Coordinate>|Array<Array<import("../coordinate.js").Coordinate>>),import("../render.js").State): void}\n * RenderFunction\n */\n\n/**\n * @typedef {Object} Options\n * @property {string|import("../geom/Geometry.js").default|GeometryFunction} [geometry] Feature property or geometry\n * or function returning a geometry to render for this style.\n * @property {import("./Fill.js").default} [fill] Fill style.\n * @property {import("./Image.js").default} [image] Image style.\n * @property {RenderFunction} [renderer] Custom renderer. When configured, `fill`, `stroke` and `image` will be\n * ignored, and the provided function will be called with each render frame for each geometry.\n * @property {import("./Stroke.js").default} [stroke] Stroke style.\n * @property {import("./Text.js").default} [text] Text style.\n * @property {number} [zIndex] Z index.\n */\n\n/**\n * @classdesc\n * Container for vector feature rendering styles. Any changes made to the style\n * or its children through `set*()` methods will not take effect until the\n * feature or layer that uses the style is re-rendered.\n *\n * ## Feature styles\n *\n * If no style is defined, the following default style is used:\n * ```js\n * import {Fill, Stroke, Circle, Style} from \'ol/style\';\n *\n * var fill = new Fill({\n * color: \'rgba(255,255,255,0.4)\'\n * });\n * var stroke = new Stroke({\n * color: \'#3399CC\',\n * width: 1.25\n * });\n * var styles = [\n * new Style({\n * image: new Circle({\n * fill: fill,\n * stroke: stroke,\n * radius: 5\n * }),\n * fill: fill,\n * stroke: stroke\n * })\n * ];\n * ```\n *\n * A separate editing style has the following defaults:\n * ```js\n * import {Fill, Stroke, Circle, Style} from \'ol/style\';\n * import GeometryType from \'ol/geom/GeometryType\';\n *\n * var white = [255, 255, 255, 1];\n * var blue = [0, 153, 255, 1];\n * var width = 3;\n * styles[GeometryType.POLYGON] = [\n * new Style({\n * fill: new Fill({\n * color: [255, 255, 255, 0.5]\n * })\n * })\n * ];\n * styles[GeometryType.MULTI_POLYGON] =\n * styles[GeometryType.POLYGON];\n * styles[GeometryType.LINE_STRING] = [\n * new Style({\n * stroke: new Stroke({\n * color: white,\n * width: width + 2\n * })\n * }),\n * new Style({\n * stroke: new Stroke({\n * color: blue,\n * width: width\n * })\n * })\n * ];\n * styles[GeometryType.MULTI_LINE_STRING] =\n * styles[GeometryType.LINE_STRING];\n * styles[GeometryType.POINT] = [\n * new Style({\n * image: new Circle({\n * radius: width * 2,\n * fill: new Fill({\n * color: blue\n * }),\n * stroke: new Stroke({\n * color: white,\n * width: width / 2\n * })\n * }),\n * zIndex: Infinity\n * })\n * ];\n * styles[GeometryType.MULTI_POINT] =\n * styles[GeometryType.POINT];\n * styles[GeometryType.GEOMETRY_COLLECTION] =\n * styles[GeometryType.POLYGON].concat(\n * styles[GeometryType.LINE_STRING],\n * styles[GeometryType.POINT]\n * );\n * ```\n *\n * @api\n */\n\nvar Style =\n/** @class */\nfunction () {\n /**\n * @param {Options=} opt_options Style options.\n */\n function Style(opt_options) {\n var options = opt_options || {};\n /**\n * @private\n * @type {string|import("../geom/Geometry.js").default|GeometryFunction}\n */\n\n this.geometry_ = null;\n /**\n * @private\n * @type {!GeometryFunction}\n */\n\n this.geometryFunction_ = defaultGeometryFunction;\n\n if (options.geometry !== undefined) {\n this.setGeometry(options.geometry);\n }\n /**\n * @private\n * @type {import("./Fill.js").default}\n */\n\n\n this.fill_ = options.fill !== undefined ? options.fill : null;\n /**\n * @private\n * @type {import("./Image.js").default}\n */\n\n this.image_ = options.image !== undefined ? options.image : null;\n /**\n * @private\n * @type {RenderFunction|null}\n */\n\n this.renderer_ = options.renderer !== undefined ? options.renderer : null;\n /**\n * @private\n * @type {import("./Stroke.js").default}\n */\n\n this.stroke_ = options.stroke !== undefined ? options.stroke : null;\n /**\n * @private\n * @type {import("./Text.js").default}\n */\n\n this.text_ = options.text !== undefined ? options.text : null;\n /**\n * @private\n * @type {number|undefined}\n */\n\n this.zIndex_ = options.zIndex;\n }\n /**\n * Clones the style.\n * @return {Style} The cloned style.\n * @api\n */\n\n\n Style.prototype.clone = function () {\n var geometry = this.getGeometry();\n\n if (geometry && typeof geometry === \'object\') {\n geometry =\n /** @type {import("../geom/Geometry.js").default} */\n geometry.clone();\n }\n\n return new Style({\n geometry: geometry,\n fill: this.getFill() ? this.getFill().clone() : undefined,\n image: this.getImage() ? this.getImage().clone() : undefined,\n stroke: this.getStroke() ? this.getStroke().clone() : undefined,\n text: this.getText() ? this.getText().clone() : undefined,\n zIndex: this.getZIndex()\n });\n };\n /**\n * Get the custom renderer function that was configured with\n * {@link #setRenderer} or the `renderer` constructor option.\n * @return {RenderFunction|null} Custom renderer function.\n * @api\n */\n\n\n Style.prototype.getRenderer = function () {\n return this.renderer_;\n };\n /**\n * Sets a custom renderer function for this style. When set, `fill`, `stroke`\n * and `image` options of the style will be ignored.\n * @param {RenderFunction|null} renderer Custom renderer function.\n * @api\n */\n\n\n Style.prototype.setRenderer = function (renderer) {\n this.renderer_ = renderer;\n };\n /**\n * Get the geometry to be rendered.\n * @return {string|import("../geom/Geometry.js").default|GeometryFunction}\n * Feature property or geometry or function that returns the geometry that will\n * be rendered with this style.\n * @api\n */\n\n\n Style.prototype.getGeometry = function () {\n return this.geometry_;\n };\n /**\n * Get the function used to generate a geometry for rendering.\n * @return {!GeometryFunction} Function that is called with a feature\n * and returns the geometry to render instead of the feature\'s geometry.\n * @api\n */\n\n\n Style.prototype.getGeometryFunction = function () {\n return this.geometryFunction_;\n };\n /**\n * Get the fill style.\n * @return {import("./Fill.js").default} Fill style.\n * @api\n */\n\n\n Style.prototype.getFill = function () {\n return this.fill_;\n };\n /**\n * Set the fill style.\n * @param {import("./Fill.js").default} fill Fill style.\n * @api\n */\n\n\n Style.prototype.setFill = function (fill) {\n this.fill_ = fill;\n };\n /**\n * Get the image style.\n * @return {import("./Image.js").default} Image style.\n * @api\n */\n\n\n Style.prototype.getImage = function () {\n return this.image_;\n };\n /**\n * Set the image style.\n * @param {import("./Image.js").default} image Image style.\n * @api\n */\n\n\n Style.prototype.setImage = function (image) {\n this.image_ = image;\n };\n /**\n * Get the stroke style.\n * @return {import("./Stroke.js").default} Stroke style.\n * @api\n */\n\n\n Style.prototype.getStroke = function () {\n return this.stroke_;\n };\n /**\n * Set the stroke style.\n * @param {import("./Stroke.js").default} stroke Stroke style.\n * @api\n */\n\n\n Style.prototype.setStroke = function (stroke) {\n this.stroke_ = stroke;\n };\n /**\n * Get the text style.\n * @return {import("./Text.js").default} Text style.\n * @api\n */\n\n\n Style.prototype.getText = function () {\n return this.text_;\n };\n /**\n * Set the text style.\n * @param {import("./Text.js").default} text Text style.\n * @api\n */\n\n\n Style.prototype.setText = function (text) {\n this.text_ = text;\n };\n /**\n * Get the z-index for the style.\n * @return {number|undefined} ZIndex.\n * @api\n */\n\n\n Style.prototype.getZIndex = function () {\n return this.zIndex_;\n };\n /**\n * Set a geometry that is rendered instead of the feature\'s geometry.\n *\n * @param {string|import("../geom/Geometry.js").default|GeometryFunction} geometry\n * Feature property or geometry or function returning a geometry to render\n * for this style.\n * @api\n */\n\n\n Style.prototype.setGeometry = function (geometry) {\n if (typeof geometry === \'function\') {\n this.geometryFunction_ = geometry;\n } else if (typeof geometry === \'string\') {\n this.geometryFunction_ = function (feature) {\n return (\n /** @type {import("../geom/Geometry.js").default} */\n feature.get(geometry)\n );\n };\n } else if (!geometry) {\n this.geometryFunction_ = defaultGeometryFunction;\n } else if (geometry !== undefined) {\n this.geometryFunction_ = function () {\n return (\n /** @type {import("../geom/Geometry.js").default} */\n geometry\n );\n };\n }\n\n this.geometry_ = geometry;\n };\n /**\n * Set the z-index.\n *\n * @param {number|undefined} zIndex ZIndex.\n * @api\n */\n\n\n Style.prototype.setZIndex = function (zIndex) {\n this.zIndex_ = zIndex;\n };\n\n return Style;\n}();\n/**\n * Convert the provided object into a style function. Functions passed through\n * unchanged. Arrays of Style or single style objects wrapped in a\n * new style function.\n * @param {StyleFunction|Array<Style>|Style} obj\n * A style function, a single style, or an array of styles.\n * @return {StyleFunction} A style function.\n */\n\n\nfunction toFunction(obj) {\n var styleFunction;\n\n if (typeof obj === \'function\') {\n styleFunction = obj;\n } else {\n /**\n * @type {Array<Style>}\n */\n var styles_1;\n\n if (Array.isArray(obj)) {\n styles_1 = obj;\n } else {\n asserts_assert(typeof\n /** @type {?} */\n obj.getZIndex === \'function\', 41); // Expected an `Style` or an array of `Style`\n\n var style =\n /** @type {Style} */\n obj;\n styles_1 = [style];\n }\n\n styleFunction = function styleFunction() {\n return styles_1;\n };\n }\n\n return styleFunction;\n}\n/**\n * @type {Array<Style>}\n */\n\nvar defaultStyles = null;\n/**\n * @param {import("../Feature.js").FeatureLike} feature Feature.\n * @param {number} resolution Resolution.\n * @return {Array<Style>} Style.\n */\n\nfunction createDefaultStyle(feature, resolution) {\n // We don\'t use an immediately-invoked function\n // and a closure so we don\'t get an error at script evaluation time in\n // browsers that do not support Canvas. (import("./Circle.js").CircleStyle does\n // canvas.getContext(\'2d\') at construction time, which will cause an.error\n // in such browsers.)\n if (!defaultStyles) {\n var fill = new style_Fill({\n color: \'rgba(255,255,255,0.4)\'\n });\n var stroke = new style_Stroke({\n color: \'#3399CC\',\n width: 1.25\n });\n defaultStyles = [new Style({\n image: new Circle({\n fill: fill,\n stroke: stroke,\n radius: 5\n }),\n fill: fill,\n stroke: stroke\n })];\n }\n\n return defaultStyles;\n}\n/**\n * Default styles for editing features.\n * @return {Object<import("../geom/GeometryType.js").default, Array<Style>>} Styles\n */\n\nfunction createEditingStyle() {\n /** @type {Object<import("../geom/GeometryType.js").default, Array<Style>>} */\n var styles = {};\n var white = [255, 255, 255, 1];\n var blue = [0, 153, 255, 1];\n var width = 3;\n styles[GeometryType.POLYGON] = [new Style({\n fill: new Fill({\n color: [255, 255, 255, 0.5]\n })\n })];\n styles[GeometryType.MULTI_POLYGON] = styles[GeometryType.POLYGON];\n styles[GeometryType.LINE_STRING] = [new Style({\n stroke: new Stroke({\n color: white,\n width: width + 2\n })\n }), new Style({\n stroke: new Stroke({\n color: blue,\n width: width\n })\n })];\n styles[GeometryType.MULTI_LINE_STRING] = styles[GeometryType.LINE_STRING];\n styles[GeometryType.CIRCLE] = styles[GeometryType.POLYGON].concat(styles[GeometryType.LINE_STRING]);\n styles[GeometryType.POINT] = [new Style({\n image: new CircleStyle({\n radius: width * 2,\n fill: new Fill({\n color: blue\n }),\n stroke: new Stroke({\n color: white,\n width: width / 2\n })\n }),\n zIndex: Infinity\n })];\n styles[GeometryType.MULTI_POINT] = styles[GeometryType.POINT];\n styles[GeometryType.GEOMETRY_COLLECTION] = styles[GeometryType.POLYGON].concat(styles[GeometryType.LINE_STRING], styles[GeometryType.POINT]);\n return styles;\n}\n/**\n * Function that is called with a feature and returns its default geometry.\n * @param {import("../Feature.js").FeatureLike} feature Feature to get the geometry for.\n * @return {import("../geom/Geometry.js").default|import("../render/Feature.js").default|undefined} Geometry to render.\n */\n\nfunction defaultGeometryFunction(feature) {\n return feature.getGeometry();\n}\n\n/* harmony default export */ var style_Style = ((/* unused pure expression or super */ null && (Style)));\n;// CONCATENATED MODULE: ./node_modules/ol/layer/BaseVector.js\nvar BaseVector_extends = undefined && undefined.__extends || function () {\n var _extendStatics = function extendStatics(d, b) {\n _extendStatics = Object.setPrototypeOf || {\n __proto__: []\n } instanceof Array && function (d, b) {\n d.__proto__ = b;\n } || function (d, b) {\n for (var p in b) {\n if (Object.prototype.hasOwnProperty.call(b, p)) d[p] = b[p];\n }\n };\n\n return _extendStatics(d, b);\n };\n\n return function (d, b) {\n _extendStatics(d, b);\n\n function __() {\n this.constructor = d;\n }\n\n d.prototype = b === null ? Object.create(b) : (__.prototype = b.prototype, new __());\n };\n}();\n/**\n * @module ol/layer/BaseVector\n */\n\n\n\n\n\n\n/**\n * @typedef {Object} Options\n * @property {string} [className=\'ol-layer\'] A CSS class name to set to the layer element.\n * @property {number} [opacity=1] Opacity (0, 1).\n * @property {boolean} [visible=true] Visibility.\n * @property {import("../extent.js").Extent} [extent] The bounding extent for layer rendering. The layer will not be\n * rendered outside of this extent.\n * @property {number} [zIndex] The z-index for layer rendering. At rendering time, the layers\n * will be ordered, first by Z-index and then by position. When `undefined`, a `zIndex` of 0 is assumed\n * for layers that are added to the map\'s `layers` collection, or `Infinity` when the layer\'s `setMap()`\n * method was used.\n * @property {number} [minResolution] The minimum resolution (inclusive) at which this layer will be\n * visible.\n * @property {number} [maxResolution] The maximum resolution (exclusive) below which this layer will\n * be visible.\n * @property {number} [minZoom] The minimum view zoom level (exclusive) above which this layer will be\n * visible.\n * @property {number} [maxZoom] The maximum view zoom level (inclusive) at which this layer will\n * be visible.\n * @property {import("../render.js").OrderFunction} [renderOrder] Render order. Function to be used when sorting\n * features before rendering. By default features are drawn in the order that they are created. Use\n * `null` to avoid the sort, but get an undefined draw order.\n * @property {number} [renderBuffer=100] The buffer in pixels around the viewport extent used by the\n * renderer when getting features from the vector source for the rendering or hit-detection.\n * Recommended value: the size of the largest symbol, line width or label.\n * @property {import("../source/Vector.js").default} [source] Source.\n * @property {import("../PluggableMap.js").default} [map] Sets the layer as overlay on a map. The map will not manage\n * this layer in its layers collection, and the layer will be rendered on top. This is useful for\n * temporary layers. The standard way to add a layer to a map and have it managed by the map is to\n * use {@link module:ol/Map#addLayer}.\n * @property {boolean} [declutter=false] Declutter images and text. Decluttering is applied to all\n * image and text styles of all Vector and VectorTile layers that have set this to `true`. The priority\n * is defined by the z-index of the layer, the `zIndex` of the style and the render order of features.\n * Higher z-index means higher priority. Within the same z-index, a feature rendered before another has\n * higher priority.\n * @property {import("../style/Style.js").StyleLike|null} [style] Layer style. When set to `null`, only\n * features that have their own style will be rendered. See {@link module:ol/style} for default style\n * which will be used if this is not set.\n * @property {boolean} [updateWhileAnimating=false] When set to `true`, feature batches will\n * be recreated during animations. This means that no vectors will be shown clipped, but the\n * setting will have a performance impact for large amounts of vector data. When set to `false`,\n * batches will be recreated when no animation is active.\n * @property {boolean} [updateWhileInteracting=false] When set to `true`, feature batches will\n * be recreated during interactions. See also `updateWhileAnimating`.\n */\n\n/**\n * @enum {string}\n * @private\n */\n\nvar BaseVector_Property = {\n RENDER_ORDER: \'renderOrder\'\n};\n/**\n * @classdesc\n * Vector data that is rendered client-side.\n * Note that any property set in the options is set as a {@link module:ol/Object~BaseObject}\n * property on the layer object; for example, setting `title: \'My Title\'` in the\n * options means that `title` is observable, and has get/set accessors.\n *\n * @template {import("../source/Vector.js").default|import("../source/VectorTile.js").default} VectorSourceType\n * @extends {Layer<VectorSourceType>}\n * @api\n */\n\nvar BaseVectorLayer =\n/** @class */\nfunction (_super) {\n BaseVector_extends(BaseVectorLayer, _super);\n /**\n * @param {Options=} opt_options Options.\n */\n\n\n function BaseVectorLayer(opt_options) {\n var _this = this;\n\n var options = opt_options ? opt_options : {};\n var baseOptions = obj_assign({}, options);\n delete baseOptions.style;\n delete baseOptions.renderBuffer;\n delete baseOptions.updateWhileAnimating;\n delete baseOptions.updateWhileInteracting;\n _this = _super.call(this, baseOptions) || this;\n /**\n * @private\n * @type {boolean}\n */\n\n _this.declutter_ = options.declutter !== undefined ? options.declutter : false;\n /**\n * @type {number}\n * @private\n */\n\n _this.renderBuffer_ = options.renderBuffer !== undefined ? options.renderBuffer : 100;\n /**\n * User provided style.\n * @type {import("../style/Style.js").StyleLike}\n * @private\n */\n\n _this.style_ = null;\n /**\n * Style function for use within the library.\n * @type {import("../style/Style.js").StyleFunction|undefined}\n * @private\n */\n\n _this.styleFunction_ = undefined;\n\n _this.setStyle(options.style);\n /**\n * @type {boolean}\n * @private\n */\n\n\n _this.updateWhileAnimating_ = options.updateWhileAnimating !== undefined ? options.updateWhileAnimating : false;\n /**\n * @type {boolean}\n * @private\n */\n\n _this.updateWhileInteracting_ = options.updateWhileInteracting !== undefined ? options.updateWhileInteracting : false;\n return _this;\n }\n /**\n * @return {boolean} Declutter.\n */\n\n\n BaseVectorLayer.prototype.getDeclutter = function () {\n return this.declutter_;\n };\n /**\n * Get the topmost feature that intersects the given pixel on the viewport. Returns a promise\n * that resolves with an array of features. The array will either contain the topmost feature\n * when a hit was detected, or it will be empty.\n *\n * The hit detection algorithm used for this method is optimized for performance, but is less\n * accurate than the one used in {@link import("../PluggableMap.js").default#getFeaturesAtPixel}: Text\n * is not considered, and icons are only represented by their bounding box instead of the exact\n * image.\n *\n * @param {import("../pixel.js").Pixel} pixel Pixel.\n * @return {Promise<Array<import("../Feature").default>>} Promise that resolves with an array of features.\n * @api\n */\n\n\n BaseVectorLayer.prototype.getFeatures = function (pixel) {\n return _super.prototype.getFeatures.call(this, pixel);\n };\n /**\n * @return {number|undefined} Render buffer.\n */\n\n\n BaseVectorLayer.prototype.getRenderBuffer = function () {\n return this.renderBuffer_;\n };\n /**\n * @return {function(import("../Feature.js").default, import("../Feature.js").default): number|null|undefined} Render\n * order.\n */\n\n\n BaseVectorLayer.prototype.getRenderOrder = function () {\n return (\n /** @type {import("../render.js").OrderFunction|null|undefined} */\n this.get(BaseVector_Property.RENDER_ORDER)\n );\n };\n /**\n * Get the style for features. This returns whatever was passed to the `style`\n * option at construction or to the `setStyle` method.\n * @return {import("../style/Style.js").StyleLike|null|undefined} Layer style.\n * @api\n */\n\n\n BaseVectorLayer.prototype.getStyle = function () {\n return this.style_;\n };\n /**\n * Get the style function.\n * @return {import("../style/Style.js").StyleFunction|undefined} Layer style function.\n * @api\n */\n\n\n BaseVectorLayer.prototype.getStyleFunction = function () {\n return this.styleFunction_;\n };\n /**\n * @return {boolean} Whether the rendered layer should be updated while\n * animating.\n */\n\n\n BaseVectorLayer.prototype.getUpdateWhileAnimating = function () {\n return this.updateWhileAnimating_;\n };\n /**\n * @return {boolean} Whether the rendered layer should be updated while\n * interacting.\n */\n\n\n BaseVectorLayer.prototype.getUpdateWhileInteracting = function () {\n return this.updateWhileInteracting_;\n };\n /**\n * Render declutter items for this layer\n * @param {import("../PluggableMap.js").FrameState} frameState Frame state.\n */\n\n\n BaseVectorLayer.prototype.renderDeclutter = function (frameState) {\n if (!frameState.declutterTree) {\n frameState.declutterTree = new (rbush_min_default())(9);\n }\n /** @type {*} */\n\n\n this.getRenderer().renderDeclutter(frameState);\n };\n /**\n * @param {import("../render.js").OrderFunction|null|undefined} renderOrder\n * Render order.\n */\n\n\n BaseVectorLayer.prototype.setRenderOrder = function (renderOrder) {\n this.set(BaseVector_Property.RENDER_ORDER, renderOrder);\n };\n /**\n * Set the style for features. This can be a single style object, an array\n * of styles, or a function that takes a feature and resolution and returns\n * an array of styles. If set to `null`, the layer has no style (a `null` style),\n * so only features that have their own styles will be rendered in the layer. Call\n * `setStyle()` without arguments to reset to the default style. See\n * {@link module:ol/style} for information on the default style.\n * @param {(import("../style/Style.js").StyleLike|null)=} opt_style Layer style.\n * @api\n */\n\n\n BaseVectorLayer.prototype.setStyle = function (opt_style) {\n this.style_ = opt_style !== undefined ? opt_style : createDefaultStyle;\n this.styleFunction_ = opt_style === null ? undefined : toFunction(this.style_);\n this.changed();\n };\n\n return BaseVectorLayer;\n}(layer_Layer);\n\n/* harmony default export */ var BaseVector = (BaseVectorLayer);\n;// CONCATENATED MODULE: ./node_modules/ol/render/canvas/Instruction.js\n/**\n * @module ol/render/canvas/Instruction\n */\n\n/**\n * @enum {number}\n */\nvar Instruction = {\n BEGIN_GEOMETRY: 0,\n BEGIN_PATH: 1,\n CIRCLE: 2,\n CLOSE_PATH: 3,\n CUSTOM: 4,\n DRAW_CHARS: 5,\n DRAW_IMAGE: 6,\n END_GEOMETRY: 7,\n FILL: 8,\n MOVE_TO_LINE_TO: 9,\n SET_FILL_STYLE: 10,\n SET_STROKE_STYLE: 11,\n STROKE: 12\n};\n/**\n * @type {Array<Instruction>}\n */\n\nvar fillInstruction = [Instruction.FILL];\n/**\n * @type {Array<Instruction>}\n */\n\nvar strokeInstruction = [Instruction.STROKE];\n/**\n * @type {Array<Instruction>}\n */\n\nvar beginPathInstruction = [Instruction.BEGIN_PATH];\n/**\n * @type {Array<Instruction>}\n */\n\nvar closePathInstruction = [Instruction.CLOSE_PATH];\n/* harmony default export */ var canvas_Instruction = (Instruction);\n;// CONCATENATED MODULE: ./node_modules/ol/render/VectorContext.js\n/**\n * @module ol/render/VectorContext\n */\n\n/**\n * @classdesc\n * Context for drawing geometries. A vector context is available on render\n * events and does not need to be constructed directly.\n * @api\n */\nvar VectorContext =\n/** @class */\nfunction () {\n function VectorContext() {}\n /**\n * Render a geometry with a custom renderer.\n *\n * @param {import("../geom/SimpleGeometry.js").default} geometry Geometry.\n * @param {import("../Feature.js").FeatureLike} feature Feature.\n * @param {Function} renderer Renderer.\n */\n\n\n VectorContext.prototype.drawCustom = function (geometry, feature, renderer) {};\n /**\n * Render a geometry.\n *\n * @param {import("../geom/Geometry.js").default} geometry The geometry to render.\n */\n\n\n VectorContext.prototype.drawGeometry = function (geometry) {};\n /**\n * Set the rendering style.\n *\n * @param {import("../style/Style.js").default} style The rendering style.\n */\n\n\n VectorContext.prototype.setStyle = function (style) {};\n /**\n * @param {import("../geom/Circle.js").default} circleGeometry Circle geometry.\n * @param {import("../Feature.js").default} feature Feature.\n */\n\n\n VectorContext.prototype.drawCircle = function (circleGeometry, feature) {};\n /**\n * @param {import("../Feature.js").default} feature Feature.\n * @param {import("../style/Style.js").default} style Style.\n */\n\n\n VectorContext.prototype.drawFeature = function (feature, style) {};\n /**\n * @param {import("../geom/GeometryCollection.js").default} geometryCollectionGeometry Geometry collection.\n * @param {import("../Feature.js").default} feature Feature.\n */\n\n\n VectorContext.prototype.drawGeometryCollection = function (geometryCollectionGeometry, feature) {};\n /**\n * @param {import("../geom/LineString.js").default|import("./Feature.js").default} lineStringGeometry Line string geometry.\n * @param {import("../Feature.js").FeatureLike} feature Feature.\n */\n\n\n VectorContext.prototype.drawLineString = function (lineStringGeometry, feature) {};\n /**\n * @param {import("../geom/MultiLineString.js").default|import("./Feature.js").default} multiLineStringGeometry MultiLineString geometry.\n * @param {import("../Feature.js").FeatureLike} feature Feature.\n */\n\n\n VectorContext.prototype.drawMultiLineString = function (multiLineStringGeometry, feature) {};\n /**\n * @param {import("../geom/MultiPoint.js").default|import("./Feature.js").default} multiPointGeometry MultiPoint geometry.\n * @param {import("../Feature.js").FeatureLike} feature Feature.\n */\n\n\n VectorContext.prototype.drawMultiPoint = function (multiPointGeometry, feature) {};\n /**\n * @param {import("../geom/MultiPolygon.js").default} multiPolygonGeometry MultiPolygon geometry.\n * @param {import("../Feature.js").FeatureLike} feature Feature.\n */\n\n\n VectorContext.prototype.drawMultiPolygon = function (multiPolygonGeometry, feature) {};\n /**\n * @param {import("../geom/Point.js").default|import("./Feature.js").default} pointGeometry Point geometry.\n * @param {import("../Feature.js").FeatureLike} feature Feature.\n */\n\n\n VectorContext.prototype.drawPoint = function (pointGeometry, feature) {};\n /**\n * @param {import("../geom/Polygon.js").default|import("./Feature.js").default} polygonGeometry Polygon geometry.\n * @param {import("../Feature.js").FeatureLike} feature Feature.\n */\n\n\n VectorContext.prototype.drawPolygon = function (polygonGeometry, feature) {};\n /**\n * @param {import("../geom/SimpleGeometry.js").default|import("./Feature.js").default} geometry Geometry.\n * @param {import("../Feature.js").FeatureLike} feature Feature.\n */\n\n\n VectorContext.prototype.drawText = function (geometry, feature) {};\n /**\n * @param {import("../style/Fill.js").default} fillStyle Fill style.\n * @param {import("../style/Stroke.js").default} strokeStyle Stroke style.\n */\n\n\n VectorContext.prototype.setFillStrokeStyle = function (fillStyle, strokeStyle) {};\n /**\n * @param {import("../style/Image.js").default} imageStyle Image style.\n * @param {import("../render/canvas.js").DeclutterImageWithText=} opt_declutterImageWithText Shared data for combined decluttering with a text style.\n */\n\n\n VectorContext.prototype.setImageStyle = function (imageStyle, opt_declutterImageWithText) {};\n /**\n * @param {import("../style/Text.js").default} textStyle Text style.\n * @param {import("../render/canvas.js").DeclutterImageWithText=} opt_declutterImageWithText Shared data for combined decluttering with an image style.\n */\n\n\n VectorContext.prototype.setTextStyle = function (textStyle, opt_declutterImageWithText) {};\n\n return VectorContext;\n}();\n\n/* harmony default export */ var render_VectorContext = (VectorContext);\n;// CONCATENATED MODULE: ./node_modules/ol/render/canvas/Builder.js\nvar Builder_extends = undefined && undefined.__extends || function () {\n var _extendStatics = function extendStatics(d, b) {\n _extendStatics = Object.setPrototypeOf || {\n __proto__: []\n } instanceof Array && function (d, b) {\n d.__proto__ = b;\n } || function (d, b) {\n for (var p in b) {\n if (Object.prototype.hasOwnProperty.call(b, p)) d[p] = b[p];\n }\n };\n\n return _extendStatics(d, b);\n };\n\n return function (d, b) {\n _extendStatics(d, b);\n\n function __() {\n this.constructor = d;\n }\n\n d.prototype = b === null ? Object.create(b) : (__.prototype = b.prototype, new __());\n };\n}();\n/**\n * @module ol/render/canvas/Builder\n */\n\n\n\n\n\n\n\n\n\n\n\n\nvar CanvasBuilder =\n/** @class */\nfunction (_super) {\n Builder_extends(CanvasBuilder, _super);\n /**\n * @param {number} tolerance Tolerance.\n * @param {import("../../extent.js").Extent} maxExtent Maximum extent.\n * @param {number} resolution Resolution.\n * @param {number} pixelRatio Pixel ratio.\n */\n\n\n function CanvasBuilder(tolerance, maxExtent, resolution, pixelRatio) {\n var _this = _super.call(this) || this;\n /**\n * @protected\n * @type {number}\n */\n\n\n _this.tolerance = tolerance;\n /**\n * @protected\n * @const\n * @type {import("../../extent.js").Extent}\n */\n\n _this.maxExtent = maxExtent;\n /**\n * @protected\n * @type {number}\n */\n\n _this.pixelRatio = pixelRatio;\n /**\n * @protected\n * @type {number}\n */\n\n _this.maxLineWidth = 0;\n /**\n * @protected\n * @const\n * @type {number}\n */\n\n _this.resolution = resolution;\n /**\n * @private\n * @type {Array<*>}\n */\n\n _this.beginGeometryInstruction1_ = null;\n /**\n * @private\n * @type {Array<*>}\n */\n\n _this.beginGeometryInstruction2_ = null;\n /**\n * @private\n * @type {import("../../extent.js").Extent}\n */\n\n _this.bufferedMaxExtent_ = null;\n /**\n * @protected\n * @type {Array<*>}\n */\n\n _this.instructions = [];\n /**\n * @protected\n * @type {Array<number>}\n */\n\n _this.coordinates = [];\n /**\n * @private\n * @type {import("../../coordinate.js").Coordinate}\n */\n\n _this.tmpCoordinate_ = [];\n /**\n * @protected\n * @type {Array<*>}\n */\n\n _this.hitDetectionInstructions = [];\n /**\n * @protected\n * @type {import("../canvas.js").FillStrokeState}\n */\n\n _this.state =\n /** @type {import("../canvas.js").FillStrokeState} */\n {};\n return _this;\n }\n /**\n * @protected\n * @param {Array<number>} dashArray Dash array.\n * @return {Array<number>} Dash array with pixel ratio applied\n */\n\n\n CanvasBuilder.prototype.applyPixelRatio = function (dashArray) {\n var pixelRatio = this.pixelRatio;\n return pixelRatio == 1 ? dashArray : dashArray.map(function (dash) {\n return dash * pixelRatio;\n });\n };\n /**\n * @param {Array<number>} flatCoordinates Flat coordinates.\n * @param {number} stride Stride.\n * @protected\n * @return {number} My end\n */\n\n\n CanvasBuilder.prototype.appendFlatPointCoordinates = function (flatCoordinates, stride) {\n var extent = this.getBufferedMaxExtent();\n var tmpCoord = this.tmpCoordinate_;\n var coordinates = this.coordinates;\n var myEnd = coordinates.length;\n\n for (var i = 0, ii = flatCoordinates.length; i < ii; i += stride) {\n tmpCoord[0] = flatCoordinates[i];\n tmpCoord[1] = flatCoordinates[i + 1];\n\n if (containsCoordinate(extent, tmpCoord)) {\n coordinates[myEnd++] = tmpCoord[0];\n coordinates[myEnd++] = tmpCoord[1];\n }\n }\n\n return myEnd;\n };\n /**\n * @param {Array<number>} flatCoordinates Flat coordinates.\n * @param {number} offset Offset.\n * @param {number} end End.\n * @param {number} stride Stride.\n * @param {boolean} closed Last input coordinate equals first.\n * @param {boolean} skipFirst Skip first coordinate.\n * @protected\n * @return {number} My end.\n */\n\n\n CanvasBuilder.prototype.appendFlatLineCoordinates = function (flatCoordinates, offset, end, stride, closed, skipFirst) {\n var coordinates = this.coordinates;\n var myEnd = coordinates.length;\n var extent = this.getBufferedMaxExtent();\n\n if (skipFirst) {\n offset += stride;\n }\n\n var lastXCoord = flatCoordinates[offset];\n var lastYCoord = flatCoordinates[offset + 1];\n var nextCoord = this.tmpCoordinate_;\n var skipped = true;\n var i, lastRel, nextRel;\n\n for (i = offset + stride; i < end; i += stride) {\n nextCoord[0] = flatCoordinates[i];\n nextCoord[1] = flatCoordinates[i + 1];\n nextRel = coordinateRelationship(extent, nextCoord);\n\n if (nextRel !== lastRel) {\n if (skipped) {\n coordinates[myEnd++] = lastXCoord;\n coordinates[myEnd++] = lastYCoord;\n skipped = false;\n }\n\n coordinates[myEnd++] = nextCoord[0];\n coordinates[myEnd++] = nextCoord[1];\n } else if (nextRel === Relationship.INTERSECTING) {\n coordinates[myEnd++] = nextCoord[0];\n coordinates[myEnd++] = nextCoord[1];\n skipped = false;\n } else {\n skipped = true;\n }\n\n lastXCoord = nextCoord[0];\n lastYCoord = nextCoord[1];\n lastRel = nextRel;\n } // Last coordinate equals first or only one point to append:\n\n\n if (closed && skipped || i === offset + stride) {\n coordinates[myEnd++] = lastXCoord;\n coordinates[myEnd++] = lastYCoord;\n }\n\n return myEnd;\n };\n /**\n * @param {Array<number>} flatCoordinates Flat coordinates.\n * @param {number} offset Offset.\n * @param {Array<number>} ends Ends.\n * @param {number} stride Stride.\n * @param {Array<number>} builderEnds Builder ends.\n * @return {number} Offset.\n */\n\n\n CanvasBuilder.prototype.drawCustomCoordinates_ = function (flatCoordinates, offset, ends, stride, builderEnds) {\n for (var i = 0, ii = ends.length; i < ii; ++i) {\n var end = ends[i];\n var builderEnd = this.appendFlatLineCoordinates(flatCoordinates, offset, end, stride, false, false);\n builderEnds.push(builderEnd);\n offset = end;\n }\n\n return offset;\n };\n /**\n * @param {import("../../geom/SimpleGeometry.js").default} geometry Geometry.\n * @param {import("../../Feature.js").FeatureLike} feature Feature.\n * @param {Function} renderer Renderer.\n */\n\n\n CanvasBuilder.prototype.drawCustom = function (geometry, feature, renderer) {\n this.beginGeometry(geometry, feature);\n var type = geometry.getType();\n var stride = geometry.getStride();\n var builderBegin = this.coordinates.length;\n var flatCoordinates, builderEnd, builderEnds, builderEndss;\n var offset;\n\n if (type == geom_GeometryType.MULTI_POLYGON) {\n flatCoordinates =\n /** @type {import("../../geom/MultiPolygon.js").default} */\n geometry.getOrientedFlatCoordinates();\n builderEndss = [];\n var endss =\n /** @type {import("../../geom/MultiPolygon.js").default} */\n geometry.getEndss();\n offset = 0;\n\n for (var i = 0, ii = endss.length; i < ii; ++i) {\n var myEnds = [];\n offset = this.drawCustomCoordinates_(flatCoordinates, offset, endss[i], stride, myEnds);\n builderEndss.push(myEnds);\n }\n\n this.instructions.push([canvas_Instruction.CUSTOM, builderBegin, builderEndss, geometry, renderer, inflateMultiCoordinatesArray]);\n } else if (type == geom_GeometryType.POLYGON || type == geom_GeometryType.MULTI_LINE_STRING) {\n builderEnds = [];\n flatCoordinates = type == geom_GeometryType.POLYGON ?\n /** @type {import("../../geom/Polygon.js").default} */\n geometry.getOrientedFlatCoordinates() : geometry.getFlatCoordinates();\n offset = this.drawCustomCoordinates_(flatCoordinates, 0,\n /** @type {import("../../geom/Polygon.js").default|import("../../geom/MultiLineString.js").default} */\n geometry.getEnds(), stride, builderEnds);\n this.instructions.push([canvas_Instruction.CUSTOM, builderBegin, builderEnds, geometry, renderer, inflateCoordinatesArray]);\n } else if (type == geom_GeometryType.LINE_STRING || type == geom_GeometryType.CIRCLE) {\n flatCoordinates = geometry.getFlatCoordinates();\n builderEnd = this.appendFlatLineCoordinates(flatCoordinates, 0, flatCoordinates.length, stride, false, false);\n this.instructions.push([canvas_Instruction.CUSTOM, builderBegin, builderEnd, geometry, renderer, inflateCoordinates]);\n } else if (type == geom_GeometryType.MULTI_POINT) {\n flatCoordinates = geometry.getFlatCoordinates();\n builderEnd = this.appendFlatPointCoordinates(flatCoordinates, stride);\n\n if (builderEnd > builderBegin) {\n this.instructions.push([canvas_Instruction.CUSTOM, builderBegin, builderEnd, geometry, renderer, inflateCoordinates]);\n }\n } else if (type == geom_GeometryType.POINT) {\n flatCoordinates = geometry.getFlatCoordinates();\n this.coordinates.push(flatCoordinates[0], flatCoordinates[1]);\n builderEnd = this.coordinates.length;\n this.instructions.push([canvas_Instruction.CUSTOM, builderBegin, builderEnd, geometry, renderer]);\n }\n\n this.endGeometry(feature);\n };\n /**\n * @protected\n * @param {import("../../geom/Geometry").default|import("../Feature.js").default} geometry The geometry.\n * @param {import("../../Feature.js").FeatureLike} feature Feature.\n */\n\n\n CanvasBuilder.prototype.beginGeometry = function (geometry, feature) {\n this.beginGeometryInstruction1_ = [canvas_Instruction.BEGIN_GEOMETRY, feature, 0, geometry];\n this.instructions.push(this.beginGeometryInstruction1_);\n this.beginGeometryInstruction2_ = [canvas_Instruction.BEGIN_GEOMETRY, feature, 0, geometry];\n this.hitDetectionInstructions.push(this.beginGeometryInstruction2_);\n };\n /**\n * @return {import("../canvas.js").SerializableInstructions} the serializable instructions.\n */\n\n\n CanvasBuilder.prototype.finish = function () {\n return {\n instructions: this.instructions,\n hitDetectionInstructions: this.hitDetectionInstructions,\n coordinates: this.coordinates\n };\n };\n /**\n * Reverse the hit detection instructions.\n */\n\n\n CanvasBuilder.prototype.reverseHitDetectionInstructions = function () {\n var hitDetectionInstructions = this.hitDetectionInstructions; // step 1 - reverse array\n\n hitDetectionInstructions.reverse(); // step 2 - reverse instructions within geometry blocks\n\n var i;\n var n = hitDetectionInstructions.length;\n var instruction;\n var type;\n var begin = -1;\n\n for (i = 0; i < n; ++i) {\n instruction = hitDetectionInstructions[i];\n type =\n /** @type {import("./Instruction.js").default} */\n instruction[0];\n\n if (type == canvas_Instruction.END_GEOMETRY) {\n begin = i;\n } else if (type == canvas_Instruction.BEGIN_GEOMETRY) {\n instruction[2] = i;\n reverseSubArray(this.hitDetectionInstructions, begin, i);\n begin = -1;\n }\n }\n };\n /**\n * @param {import("../../style/Fill.js").default} fillStyle Fill style.\n * @param {import("../../style/Stroke.js").default} strokeStyle Stroke style.\n */\n\n\n CanvasBuilder.prototype.setFillStrokeStyle = function (fillStyle, strokeStyle) {\n var state = this.state;\n\n if (fillStyle) {\n var fillStyleColor = fillStyle.getColor();\n state.fillStyle = asColorLike(fillStyleColor ? fillStyleColor : defaultFillStyle);\n } else {\n state.fillStyle = undefined;\n }\n\n if (strokeStyle) {\n var strokeStyleColor = strokeStyle.getColor();\n state.strokeStyle = asColorLike(strokeStyleColor ? strokeStyleColor : defaultStrokeStyle);\n var strokeStyleLineCap = strokeStyle.getLineCap();\n state.lineCap = strokeStyleLineCap !== undefined ? strokeStyleLineCap : defaultLineCap;\n var strokeStyleLineDash = strokeStyle.getLineDash();\n state.lineDash = strokeStyleLineDash ? strokeStyleLineDash.slice() : defaultLineDash;\n var strokeStyleLineDashOffset = strokeStyle.getLineDashOffset();\n state.lineDashOffset = strokeStyleLineDashOffset ? strokeStyleLineDashOffset : defaultLineDashOffset;\n var strokeStyleLineJoin = strokeStyle.getLineJoin();\n state.lineJoin = strokeStyleLineJoin !== undefined ? strokeStyleLineJoin : defaultLineJoin;\n var strokeStyleWidth = strokeStyle.getWidth();\n state.lineWidth = strokeStyleWidth !== undefined ? strokeStyleWidth : defaultLineWidth;\n var strokeStyleMiterLimit = strokeStyle.getMiterLimit();\n state.miterLimit = strokeStyleMiterLimit !== undefined ? strokeStyleMiterLimit : defaultMiterLimit;\n\n if (state.lineWidth > this.maxLineWidth) {\n this.maxLineWidth = state.lineWidth; // invalidate the buffered max extent cache\n\n this.bufferedMaxExtent_ = null;\n }\n } else {\n state.strokeStyle = undefined;\n state.lineCap = undefined;\n state.lineDash = null;\n state.lineDashOffset = undefined;\n state.lineJoin = undefined;\n state.lineWidth = undefined;\n state.miterLimit = undefined;\n }\n };\n /**\n * @param {import("../canvas.js").FillStrokeState} state State.\n * @return {Array<*>} Fill instruction.\n */\n\n\n CanvasBuilder.prototype.createFill = function (state) {\n var fillStyle = state.fillStyle;\n /** @type {Array<*>} */\n\n var fillInstruction = [canvas_Instruction.SET_FILL_STYLE, fillStyle];\n\n if (typeof fillStyle !== \'string\') {\n // Fill is a pattern or gradient - align it!\n fillInstruction.push(true);\n }\n\n return fillInstruction;\n };\n /**\n * @param {import("../canvas.js").FillStrokeState} state State.\n */\n\n\n CanvasBuilder.prototype.applyStroke = function (state) {\n this.instructions.push(this.createStroke(state));\n };\n /**\n * @param {import("../canvas.js").FillStrokeState} state State.\n * @return {Array<*>} Stroke instruction.\n */\n\n\n CanvasBuilder.prototype.createStroke = function (state) {\n return [canvas_Instruction.SET_STROKE_STYLE, state.strokeStyle, state.lineWidth * this.pixelRatio, state.lineCap, state.lineJoin, state.miterLimit, this.applyPixelRatio(state.lineDash), state.lineDashOffset * this.pixelRatio];\n };\n /**\n * @param {import("../canvas.js").FillStrokeState} state State.\n * @param {function(this:CanvasBuilder, import("../canvas.js").FillStrokeState):Array<*>} createFill Create fill.\n */\n\n\n CanvasBuilder.prototype.updateFillStyle = function (state, createFill) {\n var fillStyle = state.fillStyle;\n\n if (typeof fillStyle !== \'string\' || state.currentFillStyle != fillStyle) {\n if (fillStyle !== undefined) {\n this.instructions.push(createFill.call(this, state));\n }\n\n state.currentFillStyle = fillStyle;\n }\n };\n /**\n * @param {import("../canvas.js").FillStrokeState} state State.\n * @param {function(this:CanvasBuilder, import("../canvas.js").FillStrokeState): void} applyStroke Apply stroke.\n */\n\n\n CanvasBuilder.prototype.updateStrokeStyle = function (state, applyStroke) {\n var strokeStyle = state.strokeStyle;\n var lineCap = state.lineCap;\n var lineDash = state.lineDash;\n var lineDashOffset = state.lineDashOffset;\n var lineJoin = state.lineJoin;\n var lineWidth = state.lineWidth;\n var miterLimit = state.miterLimit;\n\n if (state.currentStrokeStyle != strokeStyle || state.currentLineCap != lineCap || lineDash != state.currentLineDash && !equals(state.currentLineDash, lineDash) || state.currentLineDashOffset != lineDashOffset || state.currentLineJoin != lineJoin || state.currentLineWidth != lineWidth || state.currentMiterLimit != miterLimit) {\n if (strokeStyle !== undefined) {\n applyStroke.call(this, state);\n }\n\n state.currentStrokeStyle = strokeStyle;\n state.currentLineCap = lineCap;\n state.currentLineDash = lineDash;\n state.currentLineDashOffset = lineDashOffset;\n state.currentLineJoin = lineJoin;\n state.currentLineWidth = lineWidth;\n state.currentMiterLimit = miterLimit;\n }\n };\n /**\n * @param {import("../../Feature.js").FeatureLike} feature Feature.\n */\n\n\n CanvasBuilder.prototype.endGeometry = function (feature) {\n this.beginGeometryInstruction1_[2] = this.instructions.length;\n this.beginGeometryInstruction1_ = null;\n this.beginGeometryInstruction2_[2] = this.hitDetectionInstructions.length;\n this.beginGeometryInstruction2_ = null;\n var endGeometryInstruction = [canvas_Instruction.END_GEOMETRY, feature];\n this.instructions.push(endGeometryInstruction);\n this.hitDetectionInstructions.push(endGeometryInstruction);\n };\n /**\n * Get the buffered rendering extent. Rendering will be clipped to the extent\n * provided to the constructor. To account for symbolizers that may intersect\n * this extent, we calculate a buffered extent (e.g. based on stroke width).\n * @return {import("../../extent.js").Extent} The buffered rendering extent.\n * @protected\n */\n\n\n CanvasBuilder.prototype.getBufferedMaxExtent = function () {\n if (!this.bufferedMaxExtent_) {\n this.bufferedMaxExtent_ = clone(this.maxExtent);\n\n if (this.maxLineWidth > 0) {\n var width = this.resolution * (this.maxLineWidth + 1) / 2;\n buffer(this.bufferedMaxExtent_, width, this.bufferedMaxExtent_);\n }\n }\n\n return this.bufferedMaxExtent_;\n };\n\n return CanvasBuilder;\n}(render_VectorContext);\n\n/* harmony default export */ var Builder = (CanvasBuilder);\n;// CONCATENATED MODULE: ./node_modules/ol/render/canvas/ImageBuilder.js\nvar ImageBuilder_extends = undefined && undefined.__extends || function () {\n var _extendStatics = function extendStatics(d, b) {\n _extendStatics = Object.setPrototypeOf || {\n __proto__: []\n } instanceof Array && function (d, b) {\n d.__proto__ = b;\n } || function (d, b) {\n for (var p in b) {\n if (Object.prototype.hasOwnProperty.call(b, p)) d[p] = b[p];\n }\n };\n\n return _extendStatics(d, b);\n };\n\n return function (d, b) {\n _extendStatics(d, b);\n\n function __() {\n this.constructor = d;\n }\n\n d.prototype = b === null ? Object.create(b) : (__.prototype = b.prototype, new __());\n };\n}();\n/**\n * @module ol/render/canvas/ImageBuilder\n */\n\n\n\n\n\nvar CanvasImageBuilder =\n/** @class */\nfunction (_super) {\n ImageBuilder_extends(CanvasImageBuilder, _super);\n /**\n * @param {number} tolerance Tolerance.\n * @param {import("../../extent.js").Extent} maxExtent Maximum extent.\n * @param {number} resolution Resolution.\n * @param {number} pixelRatio Pixel ratio.\n */\n\n\n function CanvasImageBuilder(tolerance, maxExtent, resolution, pixelRatio) {\n var _this = _super.call(this, tolerance, maxExtent, resolution, pixelRatio) || this;\n /**\n * @private\n * @type {HTMLCanvasElement|HTMLVideoElement|HTMLImageElement}\n */\n\n\n _this.hitDetectionImage_ = null;\n /**\n * @private\n * @type {HTMLCanvasElement|HTMLVideoElement|HTMLImageElement}\n */\n\n _this.image_ = null;\n /**\n * @private\n * @type {number|undefined}\n */\n\n _this.imagePixelRatio_ = undefined;\n /**\n * @private\n * @type {number|undefined}\n */\n\n _this.anchorX_ = undefined;\n /**\n * @private\n * @type {number|undefined}\n */\n\n _this.anchorY_ = undefined;\n /**\n * @private\n * @type {number|undefined}\n */\n\n _this.height_ = undefined;\n /**\n * @private\n * @type {number|undefined}\n */\n\n _this.opacity_ = undefined;\n /**\n * @private\n * @type {number|undefined}\n */\n\n _this.originX_ = undefined;\n /**\n * @private\n * @type {number|undefined}\n */\n\n _this.originY_ = undefined;\n /**\n * @private\n * @type {boolean|undefined}\n */\n\n _this.rotateWithView_ = undefined;\n /**\n * @private\n * @type {number|undefined}\n */\n\n _this.rotation_ = undefined;\n /**\n * @private\n * @type {import("../../size.js").Size|undefined}\n */\n\n _this.scale_ = undefined;\n /**\n * @private\n * @type {number|undefined}\n */\n\n _this.width_ = undefined;\n /**\n * Data shared with a text builder for combined decluttering.\n * @private\n * @type {import("../canvas.js").DeclutterImageWithText}\n */\n\n _this.declutterImageWithText_ = undefined;\n return _this;\n }\n /**\n * @param {import("../../geom/Point.js").default|import("../Feature.js").default} pointGeometry Point geometry.\n * @param {import("../../Feature.js").FeatureLike} feature Feature.\n */\n\n\n CanvasImageBuilder.prototype.drawPoint = function (pointGeometry, feature) {\n if (!this.image_) {\n return;\n }\n\n this.beginGeometry(pointGeometry, feature);\n var flatCoordinates = pointGeometry.getFlatCoordinates();\n var stride = pointGeometry.getStride();\n var myBegin = this.coordinates.length;\n var myEnd = this.appendFlatPointCoordinates(flatCoordinates, stride);\n this.instructions.push([canvas_Instruction.DRAW_IMAGE, myBegin, myEnd, this.image_, // Remaining arguments to DRAW_IMAGE are in alphabetical order\n this.anchorX_ * this.imagePixelRatio_, this.anchorY_ * this.imagePixelRatio_, Math.ceil(this.height_ * this.imagePixelRatio_), this.opacity_, this.originX_, this.originY_, this.rotateWithView_, this.rotation_, [this.scale_[0] * this.pixelRatio / this.imagePixelRatio_, this.scale_[1] * this.pixelRatio / this.imagePixelRatio_], Math.ceil(this.width_ * this.imagePixelRatio_), this.declutterImageWithText_]);\n this.hitDetectionInstructions.push([canvas_Instruction.DRAW_IMAGE, myBegin, myEnd, this.hitDetectionImage_, // Remaining arguments to DRAW_IMAGE are in alphabetical order\n this.anchorX_, this.anchorY_, this.height_, this.opacity_, this.originX_, this.originY_, this.rotateWithView_, this.rotation_, this.scale_, this.width_, this.declutterImageWithText_]);\n this.endGeometry(feature);\n };\n /**\n * @param {import("../../geom/MultiPoint.js").default|import("../Feature.js").default} multiPointGeometry MultiPoint geometry.\n * @param {import("../../Feature.js").FeatureLike} feature Feature.\n */\n\n\n CanvasImageBuilder.prototype.drawMultiPoint = function (multiPointGeometry, feature) {\n if (!this.image_) {\n return;\n }\n\n this.beginGeometry(multiPointGeometry, feature);\n var flatCoordinates = multiPointGeometry.getFlatCoordinates();\n var stride = multiPointGeometry.getStride();\n var myBegin = this.coordinates.length;\n var myEnd = this.appendFlatPointCoordinates(flatCoordinates, stride);\n this.instructions.push([canvas_Instruction.DRAW_IMAGE, myBegin, myEnd, this.image_, // Remaining arguments to DRAW_IMAGE are in alphabetical order\n this.anchorX_ * this.imagePixelRatio_, this.anchorY_ * this.imagePixelRatio_, Math.ceil(this.height_ * this.imagePixelRatio_), this.opacity_, this.originX_, this.originY_, this.rotateWithView_, this.rotation_, [this.scale_[0] * this.pixelRatio / this.imagePixelRatio_, this.scale_[1] * this.pixelRatio / this.imagePixelRatio_], Math.ceil(this.width_ * this.imagePixelRatio_), this.declutterImageWithText_]);\n this.hitDetectionInstructions.push([canvas_Instruction.DRAW_IMAGE, myBegin, myEnd, this.hitDetectionImage_, // Remaining arguments to DRAW_IMAGE are in alphabetical order\n this.anchorX_, this.anchorY_, this.height_, this.opacity_, this.originX_, this.originY_, this.rotateWithView_, this.rotation_, this.scale_, this.width_, this.declutterImageWithText_]);\n this.endGeometry(feature);\n };\n /**\n * @return {import("../canvas.js").SerializableInstructions} the serializable instructions.\n */\n\n\n CanvasImageBuilder.prototype.finish = function () {\n this.reverseHitDetectionInstructions(); // FIXME this doesn\'t really protect us against further calls to draw*Geometry\n\n this.anchorX_ = undefined;\n this.anchorY_ = undefined;\n this.hitDetectionImage_ = null;\n this.image_ = null;\n this.imagePixelRatio_ = undefined;\n this.height_ = undefined;\n this.scale_ = undefined;\n this.opacity_ = undefined;\n this.originX_ = undefined;\n this.originY_ = undefined;\n this.rotateWithView_ = undefined;\n this.rotation_ = undefined;\n this.width_ = undefined;\n return _super.prototype.finish.call(this);\n };\n /**\n * @param {import("../../style/Image.js").default} imageStyle Image style.\n * @param {Object=} opt_sharedData Shared data.\n */\n\n\n CanvasImageBuilder.prototype.setImageStyle = function (imageStyle, opt_sharedData) {\n var anchor = imageStyle.getAnchor();\n var size = imageStyle.getSize();\n var hitDetectionImage = imageStyle.getHitDetectionImage();\n var image = imageStyle.getImage(this.pixelRatio);\n var origin = imageStyle.getOrigin();\n this.imagePixelRatio_ = imageStyle.getPixelRatio(this.pixelRatio);\n this.anchorX_ = anchor[0];\n this.anchorY_ = anchor[1];\n this.hitDetectionImage_ = hitDetectionImage;\n this.image_ = image;\n this.height_ = size[1];\n this.opacity_ = imageStyle.getOpacity();\n this.originX_ = origin[0];\n this.originY_ = origin[1];\n this.rotateWithView_ = imageStyle.getRotateWithView();\n this.rotation_ = imageStyle.getRotation();\n this.scale_ = imageStyle.getScaleArray();\n this.width_ = size[0];\n this.declutterImageWithText_ = opt_sharedData;\n };\n\n return CanvasImageBuilder;\n}(Builder);\n\n/* harmony default export */ var ImageBuilder = (CanvasImageBuilder);\n;// CONCATENATED MODULE: ./node_modules/ol/render/canvas/LineStringBuilder.js\nvar LineStringBuilder_extends = undefined && undefined.__extends || function () {\n var _extendStatics = function extendStatics(d, b) {\n _extendStatics = Object.setPrototypeOf || {\n __proto__: []\n } instanceof Array && function (d, b) {\n d.__proto__ = b;\n } || function (d, b) {\n for (var p in b) {\n if (Object.prototype.hasOwnProperty.call(b, p)) d[p] = b[p];\n }\n };\n\n return _extendStatics(d, b);\n };\n\n return function (d, b) {\n _extendStatics(d, b);\n\n function __() {\n this.constructor = d;\n }\n\n d.prototype = b === null ? Object.create(b) : (__.prototype = b.prototype, new __());\n };\n}();\n/**\n * @module ol/render/canvas/LineStringBuilder\n */\n\n\n\n\n\nvar CanvasLineStringBuilder =\n/** @class */\nfunction (_super) {\n LineStringBuilder_extends(CanvasLineStringBuilder, _super);\n /**\n * @param {number} tolerance Tolerance.\n * @param {import("../../extent.js").Extent} maxExtent Maximum extent.\n * @param {number} resolution Resolution.\n * @param {number} pixelRatio Pixel ratio.\n */\n\n\n function CanvasLineStringBuilder(tolerance, maxExtent, resolution, pixelRatio) {\n return _super.call(this, tolerance, maxExtent, resolution, pixelRatio) || this;\n }\n /**\n * @param {Array<number>} flatCoordinates Flat coordinates.\n * @param {number} offset Offset.\n * @param {number} end End.\n * @param {number} stride Stride.\n * @private\n * @return {number} end.\n */\n\n\n CanvasLineStringBuilder.prototype.drawFlatCoordinates_ = function (flatCoordinates, offset, end, stride) {\n var myBegin = this.coordinates.length;\n var myEnd = this.appendFlatLineCoordinates(flatCoordinates, offset, end, stride, false, false);\n var moveToLineToInstruction = [canvas_Instruction.MOVE_TO_LINE_TO, myBegin, myEnd];\n this.instructions.push(moveToLineToInstruction);\n this.hitDetectionInstructions.push(moveToLineToInstruction);\n return end;\n };\n /**\n * @param {import("../../geom/LineString.js").default|import("../Feature.js").default} lineStringGeometry Line string geometry.\n * @param {import("../../Feature.js").FeatureLike} feature Feature.\n */\n\n\n CanvasLineStringBuilder.prototype.drawLineString = function (lineStringGeometry, feature) {\n var state = this.state;\n var strokeStyle = state.strokeStyle;\n var lineWidth = state.lineWidth;\n\n if (strokeStyle === undefined || lineWidth === undefined) {\n return;\n }\n\n this.updateStrokeStyle(state, this.applyStroke);\n this.beginGeometry(lineStringGeometry, feature);\n this.hitDetectionInstructions.push([canvas_Instruction.SET_STROKE_STYLE, state.strokeStyle, state.lineWidth, state.lineCap, state.lineJoin, state.miterLimit, state.lineDash, state.lineDashOffset], beginPathInstruction);\n var flatCoordinates = lineStringGeometry.getFlatCoordinates();\n var stride = lineStringGeometry.getStride();\n this.drawFlatCoordinates_(flatCoordinates, 0, flatCoordinates.length, stride);\n this.hitDetectionInstructions.push(strokeInstruction);\n this.endGeometry(feature);\n };\n /**\n * @param {import("../../geom/MultiLineString.js").default|import("../Feature.js").default} multiLineStringGeometry MultiLineString geometry.\n * @param {import("../../Feature.js").FeatureLike} feature Feature.\n */\n\n\n CanvasLineStringBuilder.prototype.drawMultiLineString = function (multiLineStringGeometry, feature) {\n var state = this.state;\n var strokeStyle = state.strokeStyle;\n var lineWidth = state.lineWidth;\n\n if (strokeStyle === undefined || lineWidth === undefined) {\n return;\n }\n\n this.updateStrokeStyle(state, this.applyStroke);\n this.beginGeometry(multiLineStringGeometry, feature);\n this.hitDetectionInstructions.push([canvas_Instruction.SET_STROKE_STYLE, state.strokeStyle, state.lineWidth, state.lineCap, state.lineJoin, state.miterLimit, state.lineDash, state.lineDashOffset], beginPathInstruction);\n var ends = multiLineStringGeometry.getEnds();\n var flatCoordinates = multiLineStringGeometry.getFlatCoordinates();\n var stride = multiLineStringGeometry.getStride();\n var offset = 0;\n\n for (var i = 0, ii = ends.length; i < ii; ++i) {\n offset = this.drawFlatCoordinates_(flatCoordinates, offset,\n /** @type {number} */\n ends[i], stride);\n }\n\n this.hitDetectionInstructions.push(strokeInstruction);\n this.endGeometry(feature);\n };\n /**\n * @return {import("../canvas.js").SerializableInstructions} the serializable instructions.\n */\n\n\n CanvasLineStringBuilder.prototype.finish = function () {\n var state = this.state;\n\n if (state.lastStroke != undefined && state.lastStroke != this.coordinates.length) {\n this.instructions.push(strokeInstruction);\n }\n\n this.reverseHitDetectionInstructions();\n this.state = null;\n return _super.prototype.finish.call(this);\n };\n /**\n * @param {import("../canvas.js").FillStrokeState} state State.\n */\n\n\n CanvasLineStringBuilder.prototype.applyStroke = function (state) {\n if (state.lastStroke != undefined && state.lastStroke != this.coordinates.length) {\n this.instructions.push(strokeInstruction);\n state.lastStroke = this.coordinates.length;\n }\n\n state.lastStroke = 0;\n\n _super.prototype.applyStroke.call(this, state);\n\n this.instructions.push(beginPathInstruction);\n };\n\n return CanvasLineStringBuilder;\n}(Builder);\n\n/* harmony default export */ var LineStringBuilder = (CanvasLineStringBuilder);\n;// CONCATENATED MODULE: ./node_modules/ol/render/canvas/PolygonBuilder.js\nvar PolygonBuilder_extends = undefined && undefined.__extends || function () {\n var _extendStatics = function extendStatics(d, b) {\n _extendStatics = Object.setPrototypeOf || {\n __proto__: []\n } instanceof Array && function (d, b) {\n d.__proto__ = b;\n } || function (d, b) {\n for (var p in b) {\n if (Object.prototype.hasOwnProperty.call(b, p)) d[p] = b[p];\n }\n };\n\n return _extendStatics(d, b);\n };\n\n return function (d, b) {\n _extendStatics(d, b);\n\n function __() {\n this.constructor = d;\n }\n\n d.prototype = b === null ? Object.create(b) : (__.prototype = b.prototype, new __());\n };\n}();\n/**\n * @module ol/render/canvas/PolygonBuilder\n */\n\n\n\n\n\n\n\nvar CanvasPolygonBuilder =\n/** @class */\nfunction (_super) {\n PolygonBuilder_extends(CanvasPolygonBuilder, _super);\n /**\n * @param {number} tolerance Tolerance.\n * @param {import("../../extent.js").Extent} maxExtent Maximum extent.\n * @param {number} resolution Resolution.\n * @param {number} pixelRatio Pixel ratio.\n */\n\n\n function CanvasPolygonBuilder(tolerance, maxExtent, resolution, pixelRatio) {\n return _super.call(this, tolerance, maxExtent, resolution, pixelRatio) || this;\n }\n /**\n * @param {Array<number>} flatCoordinates Flat coordinates.\n * @param {number} offset Offset.\n * @param {Array<number>} ends Ends.\n * @param {number} stride Stride.\n * @private\n * @return {number} End.\n */\n\n\n CanvasPolygonBuilder.prototype.drawFlatCoordinatess_ = function (flatCoordinates, offset, ends, stride) {\n var state = this.state;\n var fill = state.fillStyle !== undefined;\n var stroke = state.strokeStyle !== undefined;\n var numEnds = ends.length;\n this.instructions.push(beginPathInstruction);\n this.hitDetectionInstructions.push(beginPathInstruction);\n\n for (var i = 0; i < numEnds; ++i) {\n var end = ends[i];\n var myBegin = this.coordinates.length;\n var myEnd = this.appendFlatLineCoordinates(flatCoordinates, offset, end, stride, true, !stroke);\n var moveToLineToInstruction = [canvas_Instruction.MOVE_TO_LINE_TO, myBegin, myEnd];\n this.instructions.push(moveToLineToInstruction);\n this.hitDetectionInstructions.push(moveToLineToInstruction);\n\n if (stroke) {\n // Performance optimization: only call closePath() when we have a stroke.\n // Otherwise the ring is closed already (see appendFlatLineCoordinates above).\n this.instructions.push(closePathInstruction);\n this.hitDetectionInstructions.push(closePathInstruction);\n }\n\n offset = end;\n }\n\n if (fill) {\n this.instructions.push(fillInstruction);\n this.hitDetectionInstructions.push(fillInstruction);\n }\n\n if (stroke) {\n this.instructions.push(strokeInstruction);\n this.hitDetectionInstructions.push(strokeInstruction);\n }\n\n return offset;\n };\n /**\n * @param {import("../../geom/Circle.js").default} circleGeometry Circle geometry.\n * @param {import("../../Feature.js").default} feature Feature.\n */\n\n\n CanvasPolygonBuilder.prototype.drawCircle = function (circleGeometry, feature) {\n var state = this.state;\n var fillStyle = state.fillStyle;\n var strokeStyle = state.strokeStyle;\n\n if (fillStyle === undefined && strokeStyle === undefined) {\n return;\n }\n\n this.setFillStrokeStyles_();\n this.beginGeometry(circleGeometry, feature);\n\n if (state.fillStyle !== undefined) {\n this.hitDetectionInstructions.push([canvas_Instruction.SET_FILL_STYLE, defaultFillStyle]);\n }\n\n if (state.strokeStyle !== undefined) {\n this.hitDetectionInstructions.push([canvas_Instruction.SET_STROKE_STYLE, state.strokeStyle, state.lineWidth, state.lineCap, state.lineJoin, state.miterLimit, state.lineDash, state.lineDashOffset]);\n }\n\n var flatCoordinates = circleGeometry.getFlatCoordinates();\n var stride = circleGeometry.getStride();\n var myBegin = this.coordinates.length;\n this.appendFlatLineCoordinates(flatCoordinates, 0, flatCoordinates.length, stride, false, false);\n var circleInstruction = [canvas_Instruction.CIRCLE, myBegin];\n this.instructions.push(beginPathInstruction, circleInstruction);\n this.hitDetectionInstructions.push(beginPathInstruction, circleInstruction);\n\n if (state.fillStyle !== undefined) {\n this.instructions.push(fillInstruction);\n this.hitDetectionInstructions.push(fillInstruction);\n }\n\n if (state.strokeStyle !== undefined) {\n this.instructions.push(strokeInstruction);\n this.hitDetectionInstructions.push(strokeInstruction);\n }\n\n this.endGeometry(feature);\n };\n /**\n * @param {import("../../geom/Polygon.js").default|import("../Feature.js").default} polygonGeometry Polygon geometry.\n * @param {import("../../Feature.js").FeatureLike} feature Feature.\n */\n\n\n CanvasPolygonBuilder.prototype.drawPolygon = function (polygonGeometry, feature) {\n var state = this.state;\n var fillStyle = state.fillStyle;\n var strokeStyle = state.strokeStyle;\n\n if (fillStyle === undefined && strokeStyle === undefined) {\n return;\n }\n\n this.setFillStrokeStyles_();\n this.beginGeometry(polygonGeometry, feature);\n\n if (state.fillStyle !== undefined) {\n this.hitDetectionInstructions.push([canvas_Instruction.SET_FILL_STYLE, defaultFillStyle]);\n }\n\n if (state.strokeStyle !== undefined) {\n this.hitDetectionInstructions.push([canvas_Instruction.SET_STROKE_STYLE, state.strokeStyle, state.lineWidth, state.lineCap, state.lineJoin, state.miterLimit, state.lineDash, state.lineDashOffset]);\n }\n\n var ends = polygonGeometry.getEnds();\n var flatCoordinates = polygonGeometry.getOrientedFlatCoordinates();\n var stride = polygonGeometry.getStride();\n this.drawFlatCoordinatess_(flatCoordinates, 0,\n /** @type {Array<number>} */\n ends, stride);\n this.endGeometry(feature);\n };\n /**\n * @param {import("../../geom/MultiPolygon.js").default} multiPolygonGeometry MultiPolygon geometry.\n * @param {import("../../Feature.js").FeatureLike} feature Feature.\n */\n\n\n CanvasPolygonBuilder.prototype.drawMultiPolygon = function (multiPolygonGeometry, feature) {\n var state = this.state;\n var fillStyle = state.fillStyle;\n var strokeStyle = state.strokeStyle;\n\n if (fillStyle === undefined && strokeStyle === undefined) {\n return;\n }\n\n this.setFillStrokeStyles_();\n this.beginGeometry(multiPolygonGeometry, feature);\n\n if (state.fillStyle !== undefined) {\n this.hitDetectionInstructions.push([canvas_Instruction.SET_FILL_STYLE, defaultFillStyle]);\n }\n\n if (state.strokeStyle !== undefined) {\n this.hitDetectionInstructions.push([canvas_Instruction.SET_STROKE_STYLE, state.strokeStyle, state.lineWidth, state.lineCap, state.lineJoin, state.miterLimit, state.lineDash, state.lineDashOffset]);\n }\n\n var endss = multiPolygonGeometry.getEndss();\n var flatCoordinates = multiPolygonGeometry.getOrientedFlatCoordinates();\n var stride = multiPolygonGeometry.getStride();\n var offset = 0;\n\n for (var i = 0, ii = endss.length; i < ii; ++i) {\n offset = this.drawFlatCoordinatess_(flatCoordinates, offset, endss[i], stride);\n }\n\n this.endGeometry(feature);\n };\n /**\n * @return {import("../canvas.js").SerializableInstructions} the serializable instructions.\n */\n\n\n CanvasPolygonBuilder.prototype.finish = function () {\n this.reverseHitDetectionInstructions();\n this.state = null; // We want to preserve topology when drawing polygons. Polygons are\n // simplified using quantization and point elimination. However, we might\n // have received a mix of quantized and non-quantized geometries, so ensure\n // that all are quantized by quantizing all coordinates in the batch.\n\n var tolerance = this.tolerance;\n\n if (tolerance !== 0) {\n var coordinates = this.coordinates;\n\n for (var i = 0, ii = coordinates.length; i < ii; ++i) {\n coordinates[i] = snap(coordinates[i], tolerance);\n }\n }\n\n return _super.prototype.finish.call(this);\n };\n /**\n * @private\n */\n\n\n CanvasPolygonBuilder.prototype.setFillStrokeStyles_ = function () {\n var state = this.state;\n var fillStyle = state.fillStyle;\n\n if (fillStyle !== undefined) {\n this.updateFillStyle(state, this.createFill);\n }\n\n if (state.strokeStyle !== undefined) {\n this.updateStrokeStyle(state, this.applyStroke);\n }\n };\n\n return CanvasPolygonBuilder;\n}(Builder);\n\n/* harmony default export */ var PolygonBuilder = (CanvasPolygonBuilder);\n;// CONCATENATED MODULE: ./node_modules/ol/style/TextPlacement.js\n/**\n * @module ol/style/TextPlacement\n */\n\n/**\n * Text placement. One of `\'point\'`, `\'line\'`. Default is `\'point\'`. Note that\n * `\'line\'` requires the underlying geometry to be a {@link module:ol/geom/LineString~LineString},\n * {@link module:ol/geom/Polygon~Polygon}, {@link module:ol/geom/MultiLineString~MultiLineString} or\n * {@link module:ol/geom/MultiPolygon~MultiPolygon}.\n * @enum {string}\n */\n/* harmony default export */ var TextPlacement = ({\n POINT: \'point\',\n LINE: \'line\'\n});\n;// CONCATENATED MODULE: ./node_modules/ol/geom/flat/straightchunk.js\n/**\n * @module ol/geom/flat/straightchunk\n */\n\n/**\n * @param {number} maxAngle Maximum acceptable angle delta between segments.\n * @param {Array<number>} flatCoordinates Flat coordinates.\n * @param {number} offset Offset.\n * @param {number} end End.\n * @param {number} stride Stride.\n * @return {Array<number>} Start and end of the first suitable chunk of the\n * given `flatCoordinates`.\n */\nfunction matchingChunk(maxAngle, flatCoordinates, offset, end, stride) {\n var chunkStart = offset;\n var chunkEnd = offset;\n var chunkM = 0;\n var m = 0;\n var start = offset;\n var acos, i, m12, m23, x1, y1, x12, y12, x23, y23;\n\n for (i = offset; i < end; i += stride) {\n var x2 = flatCoordinates[i];\n var y2 = flatCoordinates[i + 1];\n\n if (x1 !== undefined) {\n x23 = x2 - x1;\n y23 = y2 - y1;\n m23 = Math.sqrt(x23 * x23 + y23 * y23);\n\n if (x12 !== undefined) {\n m += m12;\n acos = Math.acos((x12 * x23 + y12 * y23) / (m12 * m23));\n\n if (acos > maxAngle) {\n if (m > chunkM) {\n chunkM = m;\n chunkStart = start;\n chunkEnd = i;\n }\n\n m = 0;\n start = i - stride;\n }\n }\n\n m12 = m23;\n x12 = x23;\n y12 = y23;\n }\n\n x1 = x2;\n y1 = y2;\n }\n\n m += m23;\n return m > chunkM ? [start, i] : [chunkStart, chunkEnd];\n}\n;// CONCATENATED MODULE: ./node_modules/ol/render/canvas/TextBuilder.js\nvar TextBuilder_extends = undefined && undefined.__extends || function () {\n var _extendStatics = function extendStatics(d, b) {\n _extendStatics = Object.setPrototypeOf || {\n __proto__: []\n } instanceof Array && function (d, b) {\n d.__proto__ = b;\n } || function (d, b) {\n for (var p in b) {\n if (Object.prototype.hasOwnProperty.call(b, p)) d[p] = b[p];\n }\n };\n\n return _extendStatics(d, b);\n };\n\n return function (d, b) {\n _extendStatics(d, b);\n\n function __() {\n this.constructor = d;\n }\n\n d.prototype = b === null ? Object.create(b) : (__.prototype = b.prototype, new __());\n };\n}();\n/**\n * @module ol/render/canvas/TextBuilder\n */\n\n\n\n\n\n\n\n\n\n\n\n/**\n * @const\n * @enum {number}\n */\n\nvar TEXT_ALIGN = {\n \'left\': 0,\n \'end\': 0,\n \'center\': 0.5,\n \'right\': 1,\n \'start\': 1,\n \'top\': 0,\n \'middle\': 0.5,\n \'hanging\': 0.2,\n \'alphabetic\': 0.8,\n \'ideographic\': 0.8,\n \'bottom\': 1\n};\n\nvar CanvasTextBuilder =\n/** @class */\nfunction (_super) {\n TextBuilder_extends(CanvasTextBuilder, _super);\n /**\n * @param {number} tolerance Tolerance.\n * @param {import("../../extent.js").Extent} maxExtent Maximum extent.\n * @param {number} resolution Resolution.\n * @param {number} pixelRatio Pixel ratio.\n */\n\n\n function CanvasTextBuilder(tolerance, maxExtent, resolution, pixelRatio) {\n var _this = _super.call(this, tolerance, maxExtent, resolution, pixelRatio) || this;\n /**\n * @private\n * @type {Array<HTMLCanvasElement>}\n */\n\n\n _this.labels_ = null;\n /**\n * @private\n * @type {string}\n */\n\n _this.text_ = \'\';\n /**\n * @private\n * @type {number}\n */\n\n _this.textOffsetX_ = 0;\n /**\n * @private\n * @type {number}\n */\n\n _this.textOffsetY_ = 0;\n /**\n * @private\n * @type {boolean|undefined}\n */\n\n _this.textRotateWithView_ = undefined;\n /**\n * @private\n * @type {number}\n */\n\n _this.textRotation_ = 0;\n /**\n * @private\n * @type {?import("../canvas.js").FillState}\n */\n\n _this.textFillState_ = null;\n /**\n * @type {!Object<string, import("../canvas.js").FillState>}\n */\n\n _this.fillStates = {};\n /**\n * @private\n * @type {?import("../canvas.js").StrokeState}\n */\n\n _this.textStrokeState_ = null;\n /**\n * @type {!Object<string, import("../canvas.js").StrokeState>}\n */\n\n _this.strokeStates = {};\n /**\n * @private\n * @type {import("../canvas.js").TextState}\n */\n\n _this.textState_ =\n /** @type {import("../canvas.js").TextState} */\n {};\n /**\n * @type {!Object<string, import("../canvas.js").TextState>}\n */\n\n _this.textStates = {};\n /**\n * @private\n * @type {string}\n */\n\n _this.textKey_ = \'\';\n /**\n * @private\n * @type {string}\n */\n\n _this.fillKey_ = \'\';\n /**\n * @private\n * @type {string}\n */\n\n _this.strokeKey_ = \'\';\n /**\n * Data shared with an image builder for combined decluttering.\n * @private\n * @type {import("../canvas.js").DeclutterImageWithText}\n */\n\n _this.declutterImageWithText_ = undefined;\n return _this;\n }\n /**\n * @return {import("../canvas.js").SerializableInstructions} the serializable instructions.\n */\n\n\n CanvasTextBuilder.prototype.finish = function () {\n var instructions = _super.prototype.finish.call(this);\n\n instructions.textStates = this.textStates;\n instructions.fillStates = this.fillStates;\n instructions.strokeStates = this.strokeStates;\n return instructions;\n };\n /**\n * @param {import("../../geom/SimpleGeometry.js").default|import("../Feature.js").default} geometry Geometry.\n * @param {import("../../Feature.js").FeatureLike} feature Feature.\n */\n\n\n CanvasTextBuilder.prototype.drawText = function (geometry, feature) {\n var fillState = this.textFillState_;\n var strokeState = this.textStrokeState_;\n var textState = this.textState_;\n\n if (this.text_ === \'\' || !textState || !fillState && !strokeState) {\n return;\n }\n\n var coordinates = this.coordinates;\n var begin = coordinates.length;\n var geometryType = geometry.getType();\n var flatCoordinates = null;\n var stride = geometry.getStride();\n\n if (textState.placement === TextPlacement.LINE && (geometryType == geom_GeometryType.LINE_STRING || geometryType == geom_GeometryType.MULTI_LINE_STRING || geometryType == geom_GeometryType.POLYGON || geometryType == geom_GeometryType.MULTI_POLYGON)) {\n if (!intersects(this.getBufferedMaxExtent(), geometry.getExtent())) {\n return;\n }\n\n var ends = void 0;\n flatCoordinates = geometry.getFlatCoordinates();\n\n if (geometryType == geom_GeometryType.LINE_STRING) {\n ends = [flatCoordinates.length];\n } else if (geometryType == geom_GeometryType.MULTI_LINE_STRING) {\n ends =\n /** @type {import("../../geom/MultiLineString.js").default} */\n geometry.getEnds();\n } else if (geometryType == geom_GeometryType.POLYGON) {\n ends =\n /** @type {import("../../geom/Polygon.js").default} */\n geometry.getEnds().slice(0, 1);\n } else if (geometryType == geom_GeometryType.MULTI_POLYGON) {\n var endss =\n /** @type {import("../../geom/MultiPolygon.js").default} */\n geometry.getEndss();\n ends = [];\n\n for (var i = 0, ii = endss.length; i < ii; ++i) {\n ends.push(endss[i][0]);\n }\n }\n\n this.beginGeometry(geometry, feature);\n var textAlign = textState.textAlign;\n var flatOffset = 0;\n var flatEnd = void 0;\n\n for (var o = 0, oo = ends.length; o < oo; ++o) {\n if (textAlign == undefined) {\n var range = matchingChunk(textState.maxAngle, flatCoordinates, flatOffset, ends[o], stride);\n flatOffset = range[0];\n flatEnd = range[1];\n } else {\n flatEnd = ends[o];\n }\n\n for (var i = flatOffset; i < flatEnd; i += stride) {\n coordinates.push(flatCoordinates[i], flatCoordinates[i + 1]);\n }\n\n var end = coordinates.length;\n flatOffset = ends[o];\n this.drawChars_(begin, end);\n begin = end;\n }\n\n this.endGeometry(feature);\n } else {\n var geometryWidths = textState.overflow ? null : [];\n\n switch (geometryType) {\n case geom_GeometryType.POINT:\n case geom_GeometryType.MULTI_POINT:\n flatCoordinates =\n /** @type {import("../../geom/MultiPoint.js").default} */\n geometry.getFlatCoordinates();\n break;\n\n case geom_GeometryType.LINE_STRING:\n flatCoordinates =\n /** @type {import("../../geom/LineString.js").default} */\n geometry.getFlatMidpoint();\n break;\n\n case geom_GeometryType.CIRCLE:\n flatCoordinates =\n /** @type {import("../../geom/Circle.js").default} */\n geometry.getCenter();\n break;\n\n case geom_GeometryType.MULTI_LINE_STRING:\n flatCoordinates =\n /** @type {import("../../geom/MultiLineString.js").default} */\n geometry.getFlatMidpoints();\n stride = 2;\n break;\n\n case geom_GeometryType.POLYGON:\n flatCoordinates =\n /** @type {import("../../geom/Polygon.js").default} */\n geometry.getFlatInteriorPoint();\n\n if (!textState.overflow) {\n geometryWidths.push(flatCoordinates[2] / this.resolution);\n }\n\n stride = 3;\n break;\n\n case geom_GeometryType.MULTI_POLYGON:\n var interiorPoints =\n /** @type {import("../../geom/MultiPolygon.js").default} */\n geometry.getFlatInteriorPoints();\n flatCoordinates = [];\n\n for (var i = 0, ii = interiorPoints.length; i < ii; i += 3) {\n if (!textState.overflow) {\n geometryWidths.push(interiorPoints[i + 2] / this.resolution);\n }\n\n flatCoordinates.push(interiorPoints[i], interiorPoints[i + 1]);\n }\n\n if (flatCoordinates.length === 0) {\n return;\n }\n\n stride = 2;\n break;\n\n default:\n }\n\n var end = this.appendFlatPointCoordinates(flatCoordinates, stride);\n\n if (end === begin) {\n return;\n }\n\n this.saveTextStates_();\n\n if (textState.backgroundFill || textState.backgroundStroke) {\n this.setFillStrokeStyle(textState.backgroundFill, textState.backgroundStroke);\n\n if (textState.backgroundFill) {\n this.updateFillStyle(this.state, this.createFill);\n this.hitDetectionInstructions.push(this.createFill(this.state));\n }\n\n if (textState.backgroundStroke) {\n this.updateStrokeStyle(this.state, this.applyStroke);\n this.hitDetectionInstructions.push(this.createStroke(this.state));\n }\n }\n\n this.beginGeometry(geometry, feature); // adjust padding for negative scale\n\n var padding = textState.padding;\n\n if (padding != defaultPadding && (textState.scale[0] < 0 || textState.scale[1] < 0)) {\n var p0 = textState.padding[0];\n var p1 = textState.padding[1];\n var p2 = textState.padding[2];\n var p3 = textState.padding[3];\n\n if (textState.scale[0] < 0) {\n p1 = -p1;\n p3 = -p3;\n }\n\n if (textState.scale[1] < 0) {\n p0 = -p0;\n p2 = -p2;\n }\n\n padding = [p0, p1, p2, p3];\n } // The image is unknown at this stage so we pass null; it will be computed at render time.\n // For clarity, we pass NaN for offsetX, offsetY, width and height, which will be computed at\n // render time.\n\n\n var pixelRatio_1 = this.pixelRatio;\n this.instructions.push([canvas_Instruction.DRAW_IMAGE, begin, end, null, NaN, NaN, NaN, 1, 0, 0, this.textRotateWithView_, this.textRotation_, [1, 1], NaN, this.declutterImageWithText_, padding == defaultPadding ? defaultPadding : padding.map(function (p) {\n return p * pixelRatio_1;\n }), !!textState.backgroundFill, !!textState.backgroundStroke, this.text_, this.textKey_, this.strokeKey_, this.fillKey_, this.textOffsetX_, this.textOffsetY_, geometryWidths]);\n var scale = 1 / pixelRatio_1;\n this.hitDetectionInstructions.push([canvas_Instruction.DRAW_IMAGE, begin, end, null, NaN, NaN, NaN, 1, 0, 0, this.textRotateWithView_, this.textRotation_, [scale, scale], NaN, this.declutterImageWithText_, padding, !!textState.backgroundFill, !!textState.backgroundStroke, this.text_, this.textKey_, this.strokeKey_, this.fillKey_, this.textOffsetX_, this.textOffsetY_, geometryWidths]);\n this.endGeometry(feature);\n }\n };\n /**\n * @private\n */\n\n\n CanvasTextBuilder.prototype.saveTextStates_ = function () {\n var strokeState = this.textStrokeState_;\n var textState = this.textState_;\n var fillState = this.textFillState_;\n var strokeKey = this.strokeKey_;\n\n if (strokeState) {\n if (!(strokeKey in this.strokeStates)) {\n this.strokeStates[strokeKey] = {\n strokeStyle: strokeState.strokeStyle,\n lineCap: strokeState.lineCap,\n lineDashOffset: strokeState.lineDashOffset,\n lineWidth: strokeState.lineWidth,\n lineJoin: strokeState.lineJoin,\n miterLimit: strokeState.miterLimit,\n lineDash: strokeState.lineDash\n };\n }\n }\n\n var textKey = this.textKey_;\n\n if (!(textKey in this.textStates)) {\n this.textStates[textKey] = {\n font: textState.font,\n textAlign: textState.textAlign || defaultTextAlign,\n textBaseline: textState.textBaseline || defaultTextBaseline,\n scale: textState.scale\n };\n }\n\n var fillKey = this.fillKey_;\n\n if (fillState) {\n if (!(fillKey in this.fillStates)) {\n this.fillStates[fillKey] = {\n fillStyle: fillState.fillStyle\n };\n }\n }\n };\n /**\n * @private\n * @param {number} begin Begin.\n * @param {number} end End.\n */\n\n\n CanvasTextBuilder.prototype.drawChars_ = function (begin, end) {\n var strokeState = this.textStrokeState_;\n var textState = this.textState_;\n var strokeKey = this.strokeKey_;\n var textKey = this.textKey_;\n var fillKey = this.fillKey_;\n this.saveTextStates_();\n var pixelRatio = this.pixelRatio;\n var baseline = TEXT_ALIGN[textState.textBaseline];\n var offsetY = this.textOffsetY_ * pixelRatio;\n var text = this.text_;\n var strokeWidth = strokeState ? strokeState.lineWidth * Math.abs(textState.scale[0]) / 2 : 0;\n this.instructions.push([canvas_Instruction.DRAW_CHARS, begin, end, baseline, textState.overflow, fillKey, textState.maxAngle, pixelRatio, offsetY, strokeKey, strokeWidth * pixelRatio, text, textKey, 1]);\n this.hitDetectionInstructions.push([canvas_Instruction.DRAW_CHARS, begin, end, baseline, textState.overflow, fillKey, textState.maxAngle, 1, offsetY, strokeKey, strokeWidth, text, textKey, 1 / pixelRatio]);\n };\n /**\n * @param {import("../../style/Text.js").default} textStyle Text style.\n * @param {Object=} opt_sharedData Shared data.\n */\n\n\n CanvasTextBuilder.prototype.setTextStyle = function (textStyle, opt_sharedData) {\n var textState, fillState, strokeState;\n\n if (!textStyle) {\n this.text_ = \'\';\n } else {\n var textFillStyle = textStyle.getFill();\n\n if (!textFillStyle) {\n fillState = null;\n this.textFillState_ = fillState;\n } else {\n fillState = this.textFillState_;\n\n if (!fillState) {\n fillState =\n /** @type {import("../canvas.js").FillState} */\n {};\n this.textFillState_ = fillState;\n }\n\n fillState.fillStyle = asColorLike(textFillStyle.getColor() || defaultFillStyle);\n }\n\n var textStrokeStyle = textStyle.getStroke();\n\n if (!textStrokeStyle) {\n strokeState = null;\n this.textStrokeState_ = strokeState;\n } else {\n strokeState = this.textStrokeState_;\n\n if (!strokeState) {\n strokeState =\n /** @type {import("../canvas.js").StrokeState} */\n {};\n this.textStrokeState_ = strokeState;\n }\n\n var lineDash = textStrokeStyle.getLineDash();\n var lineDashOffset = textStrokeStyle.getLineDashOffset();\n var lineWidth = textStrokeStyle.getWidth();\n var miterLimit = textStrokeStyle.getMiterLimit();\n strokeState.lineCap = textStrokeStyle.getLineCap() || defaultLineCap;\n strokeState.lineDash = lineDash ? lineDash.slice() : defaultLineDash;\n strokeState.lineDashOffset = lineDashOffset === undefined ? defaultLineDashOffset : lineDashOffset;\n strokeState.lineJoin = textStrokeStyle.getLineJoin() || defaultLineJoin;\n strokeState.lineWidth = lineWidth === undefined ? defaultLineWidth : lineWidth;\n strokeState.miterLimit = miterLimit === undefined ? defaultMiterLimit : miterLimit;\n strokeState.strokeStyle = asColorLike(textStrokeStyle.getColor() || defaultStrokeStyle);\n }\n\n textState = this.textState_;\n var font = textStyle.getFont() || defaultFont;\n registerFont(font);\n var textScale = textStyle.getScaleArray();\n textState.overflow = textStyle.getOverflow();\n textState.font = font;\n textState.maxAngle = textStyle.getMaxAngle();\n textState.placement = textStyle.getPlacement();\n textState.textAlign = textStyle.getTextAlign();\n textState.textBaseline = textStyle.getTextBaseline() || defaultTextBaseline;\n textState.backgroundFill = textStyle.getBackgroundFill();\n textState.backgroundStroke = textStyle.getBackgroundStroke();\n textState.padding = textStyle.getPadding() || defaultPadding;\n textState.scale = textScale === undefined ? [1, 1] : textScale;\n var textOffsetX = textStyle.getOffsetX();\n var textOffsetY = textStyle.getOffsetY();\n var textRotateWithView = textStyle.getRotateWithView();\n var textRotation = textStyle.getRotation();\n this.text_ = textStyle.getText() || \'\';\n this.textOffsetX_ = textOffsetX === undefined ? 0 : textOffsetX;\n this.textOffsetY_ = textOffsetY === undefined ? 0 : textOffsetY;\n this.textRotateWithView_ = textRotateWithView === undefined ? false : textRotateWithView;\n this.textRotation_ = textRotation === undefined ? 0 : textRotation;\n this.strokeKey_ = strokeState ? (typeof strokeState.strokeStyle == \'string\' ? strokeState.strokeStyle : util_getUid(strokeState.strokeStyle)) + strokeState.lineCap + strokeState.lineDashOffset + \'|\' + strokeState.lineWidth + strokeState.lineJoin + strokeState.miterLimit + \'[\' + strokeState.lineDash.join() + \']\' : \'\';\n this.textKey_ = textState.font + textState.scale + (textState.textAlign || \'?\') + (textState.textBaseline || \'?\');\n this.fillKey_ = fillState ? typeof fillState.fillStyle == \'string\' ? fillState.fillStyle : \'|\' + util_getUid(fillState.fillStyle) : \'\';\n }\n\n this.declutterImageWithText_ = opt_sharedData;\n };\n\n return CanvasTextBuilder;\n}(Builder);\n\n/* harmony default export */ var TextBuilder = (CanvasTextBuilder);\n;// CONCATENATED MODULE: ./node_modules/ol/render/canvas/BuilderGroup.js\n/**\n * @module ol/render/canvas/BuilderGroup\n */\n\n\n\n\n\n/**\n * @type {Object<import("./BuilderType").default, typeof Builder>}\n */\n\nvar BATCH_CONSTRUCTORS = {\n \'Circle\': PolygonBuilder,\n \'Default\': Builder,\n \'Image\': ImageBuilder,\n \'LineString\': LineStringBuilder,\n \'Polygon\': PolygonBuilder,\n \'Text\': TextBuilder\n};\n\nvar BuilderGroup =\n/** @class */\nfunction () {\n /**\n * @param {number} tolerance Tolerance.\n * @param {import("../../extent.js").Extent} maxExtent Max extent.\n * @param {number} resolution Resolution.\n * @param {number} pixelRatio Pixel ratio.\n */\n function BuilderGroup(tolerance, maxExtent, resolution, pixelRatio) {\n /**\n * @private\n * @type {number}\n */\n this.tolerance_ = tolerance;\n /**\n * @private\n * @type {import("../../extent.js").Extent}\n */\n\n this.maxExtent_ = maxExtent;\n /**\n * @private\n * @type {number}\n */\n\n this.pixelRatio_ = pixelRatio;\n /**\n * @private\n * @type {number}\n */\n\n this.resolution_ = resolution;\n /**\n * @private\n * @type {!Object<string, !Object<import("./BuilderType").default, Builder>>}\n */\n\n this.buildersByZIndex_ = {};\n }\n /**\n * @return {!Object<string, !Object<import("./BuilderType").default, import("./Builder.js").SerializableInstructions>>} The serializable instructions\n */\n\n\n BuilderGroup.prototype.finish = function () {\n var builderInstructions = {};\n\n for (var zKey in this.buildersByZIndex_) {\n builderInstructions[zKey] = builderInstructions[zKey] || {};\n var builders = this.buildersByZIndex_[zKey];\n\n for (var builderKey in builders) {\n var builderInstruction = builders[builderKey].finish();\n builderInstructions[zKey][builderKey] = builderInstruction;\n }\n }\n\n return builderInstructions;\n };\n /**\n * @param {number|undefined} zIndex Z index.\n * @param {import("./BuilderType.js").default} builderType Replay type.\n * @return {import("../VectorContext.js").default} Replay.\n */\n\n\n BuilderGroup.prototype.getBuilder = function (zIndex, builderType) {\n var zIndexKey = zIndex !== undefined ? zIndex.toString() : \'0\';\n var replays = this.buildersByZIndex_[zIndexKey];\n\n if (replays === undefined) {\n replays = {};\n this.buildersByZIndex_[zIndexKey] = replays;\n }\n\n var replay = replays[builderType];\n\n if (replay === undefined) {\n var Constructor = BATCH_CONSTRUCTORS[builderType];\n replay = new Constructor(this.tolerance_, this.maxExtent_, this.resolution_, this.pixelRatio_);\n replays[builderType] = replay;\n }\n\n return replay;\n };\n\n return BuilderGroup;\n}();\n\n/* harmony default export */ var canvas_BuilderGroup = (BuilderGroup);\n;// CONCATENATED MODULE: ./node_modules/ol/render/canvas/BuilderType.js\n/**\n * @module ol/render/canvas/BuilderType\n */\n\n/**\n * @enum {string}\n */\n/* harmony default export */ var BuilderType = ({\n CIRCLE: \'Circle\',\n DEFAULT: \'Default\',\n IMAGE: \'Image\',\n LINE_STRING: \'LineString\',\n POLYGON: \'Polygon\',\n TEXT: \'Text\'\n});\n;// CONCATENATED MODULE: ./node_modules/ol/geom/flat/textpath.js\n/**\n * @module ol/geom/flat/textpath\n */\n\n\n/**\n * @param {Array<number>} flatCoordinates Path to put text on.\n * @param {number} offset Start offset of the `flatCoordinates`.\n * @param {number} end End offset of the `flatCoordinates`.\n * @param {number} stride Stride.\n * @param {string} text Text to place on the path.\n * @param {number} startM m along the path where the text starts.\n * @param {number} maxAngle Max angle between adjacent chars in radians.\n * @param {number} scale The product of the text scale and the device pixel ratio.\n * @param {function(string, string, Object<string, number>):number} measureAndCacheTextWidth Measure and cache text width.\n * @param {string} font The font.\n * @param {Object<string, number>} cache A cache of measured widths.\n * @param {number} rotation Rotation to apply to the flatCoordinates to determine whether text needs to be reversed.\n * @return {Array<Array<*>>} The result array (or null if `maxAngle` was\n * exceeded). Entries of the array are x, y, anchorX, angle, chunk.\n */\n\nfunction drawTextOnPath(flatCoordinates, offset, end, stride, text, startM, maxAngle, scale, measureAndCacheTextWidth, font, cache, rotation) {\n var x2 = flatCoordinates[offset];\n var y2 = flatCoordinates[offset + 1];\n var x1 = 0;\n var y1 = 0;\n var segmentLength = 0;\n var segmentM = 0;\n\n function advance() {\n x1 = x2;\n y1 = y2;\n offset += stride;\n x2 = flatCoordinates[offset];\n y2 = flatCoordinates[offset + 1];\n segmentM += segmentLength;\n segmentLength = Math.sqrt((x2 - x1) * (x2 - x1) + (y2 - y1) * (y2 - y1));\n }\n\n do {\n advance();\n } while (offset < end - stride && segmentM + segmentLength < startM);\n\n var interpolate = (startM - segmentM) / segmentLength;\n var beginX = lerp(x1, x2, interpolate);\n var beginY = lerp(y1, y2, interpolate);\n var startOffset = offset - stride;\n var startLength = segmentM;\n var endM = startM + scale * measureAndCacheTextWidth(font, text, cache);\n\n while (offset < end - stride && segmentM + segmentLength < endM) {\n advance();\n }\n\n interpolate = (endM - segmentM) / segmentLength;\n var endX = lerp(x1, x2, interpolate);\n var endY = lerp(y1, y2, interpolate); // Keep text upright\n\n var reverse;\n\n if (rotation) {\n var flat = [beginX, beginY, endX, endY];\n transform_rotate(flat, 0, 4, 2, rotation, flat, flat);\n reverse = flat[0] > flat[2];\n } else {\n reverse = beginX > endX;\n }\n\n var PI = Math.PI;\n var result = [];\n var singleSegment = startOffset + stride === offset;\n offset = startOffset;\n segmentLength = 0;\n segmentM = startLength;\n x2 = flatCoordinates[offset];\n y2 = flatCoordinates[offset + 1]; // All on the same segment\n\n if (singleSegment) {\n advance();\n var previousAngle_1 = Math.atan2(y2 - y1, x2 - x1);\n\n if (reverse) {\n previousAngle_1 += previousAngle_1 > 0 ? -PI : PI;\n }\n\n var x = (endX + beginX) / 2;\n var y = (endY + beginY) / 2;\n result[0] = [x, y, (endM - startM) / 2, previousAngle_1, text];\n return result;\n }\n\n var previousAngle;\n\n for (var i = 0, ii = text.length; i < ii;) {\n advance();\n var angle = Math.atan2(y2 - y1, x2 - x1);\n\n if (reverse) {\n angle += angle > 0 ? -PI : PI;\n }\n\n if (previousAngle !== undefined) {\n var delta = angle - previousAngle;\n delta += delta > PI ? -2 * PI : delta < -PI ? 2 * PI : 0;\n\n if (Math.abs(delta) > maxAngle) {\n return null;\n }\n }\n\n previousAngle = angle;\n var iStart = i;\n var charLength = 0;\n\n for (; i < ii; ++i) {\n var index = reverse ? ii - i - 1 : i;\n var len = scale * measureAndCacheTextWidth(font, text[index], cache);\n\n if (offset + stride < end && segmentM + segmentLength < startM + charLength + len / 2) {\n break;\n }\n\n charLength += len;\n }\n\n if (i === iStart) {\n continue;\n }\n\n var chars = reverse ? text.substring(ii - iStart, ii - i) : text.substring(iStart, i);\n interpolate = (startM + charLength / 2 - segmentM) / segmentLength;\n var x = lerp(x1, x2, interpolate);\n var y = lerp(y1, y2, interpolate);\n result.push([x, y, charLength / 2, angle, chars]);\n startM += charLength;\n }\n\n return result;\n}\n;// CONCATENATED MODULE: ./node_modules/ol/geom/flat/length.js\n/**\n * @module ol/geom/flat/length\n */\n\n/**\n * @param {Array<number>} flatCoordinates Flat coordinates.\n * @param {number} offset Offset.\n * @param {number} end End.\n * @param {number} stride Stride.\n * @return {number} Length.\n */\nfunction lineStringLength(flatCoordinates, offset, end, stride) {\n var x1 = flatCoordinates[offset];\n var y1 = flatCoordinates[offset + 1];\n var length = 0;\n\n for (var i = offset + stride; i < end; i += stride) {\n var x2 = flatCoordinates[i];\n var y2 = flatCoordinates[i + 1];\n length += Math.sqrt((x2 - x1) * (x2 - x1) + (y2 - y1) * (y2 - y1));\n x1 = x2;\n y1 = y2;\n }\n\n return length;\n}\n/**\n * @param {Array<number>} flatCoordinates Flat coordinates.\n * @param {number} offset Offset.\n * @param {number} end End.\n * @param {number} stride Stride.\n * @return {number} Perimeter.\n */\n\nfunction linearRingLength(flatCoordinates, offset, end, stride) {\n var perimeter = lineStringLength(flatCoordinates, offset, end, stride);\n var dx = flatCoordinates[end - stride] - flatCoordinates[offset];\n var dy = flatCoordinates[end - stride + 1] - flatCoordinates[offset + 1];\n perimeter += Math.sqrt(dx * dx + dy * dy);\n return perimeter;\n}\n;// CONCATENATED MODULE: ./node_modules/ol/render/canvas/Executor.js\n/**\n * @module ol/render/canvas/Executor\n */\n\n\n\n\n\n\n\n\n\n\n\n/**\n * @typedef {Object} BBox\n * @property {number} minX\n * @property {number} minY\n * @property {number} maxX\n * @property {number} maxY\n * @property {*} value\n */\n\n/**\n * @typedef {Object} ImageOrLabelDimensions\n * @property {number} drawImageX\n * @property {number} drawImageY\n * @property {number} drawImageW\n * @property {number} drawImageH\n * @property {number} originX\n * @property {number} originY\n * @property {Array<number>} scale\n * @property {BBox} declutterBox\n * @property {import("../../transform.js").Transform} canvasTransform\n */\n\n/**\n * @typedef {{0: CanvasRenderingContext2D, 1: number, 2: import("../canvas.js").Label|HTMLImageElement|HTMLCanvasElement|HTMLVideoElement, 3: ImageOrLabelDimensions, 4: number, 5: Array<*>, 6: Array<*>}} ReplayImageOrLabelArgs\n */\n\n/**\n * @template T\n * @typedef {function(import("../../Feature.js").FeatureLike, import("../../geom/SimpleGeometry.js").default): T} FeatureCallback\n */\n\n/**\n * @type {import("../../extent.js").Extent}\n */\n\nvar tmpExtent = createEmpty();\n/** @type {import("../../coordinate.js").Coordinate} */\n\nvar p1 = [];\n/** @type {import("../../coordinate.js").Coordinate} */\n\nvar p2 = [];\n/** @type {import("../../coordinate.js").Coordinate} */\n\nvar p3 = [];\n/** @type {import("../../coordinate.js").Coordinate} */\n\nvar p4 = [];\n/**\n * @param {ReplayImageOrLabelArgs} replayImageOrLabelArgs Arguments to replayImageOrLabel\n * @return {BBox} Declutter bbox.\n */\n\nfunction getDeclutterBox(replayImageOrLabelArgs) {\n return replayImageOrLabelArgs[3].declutterBox;\n}\n\nvar rtlRegEx = new RegExp(\n/* eslint-disable prettier/prettier */\n\'[\' + String.fromCharCode(0x00591) + \'-\' + String.fromCharCode(0x008ff) + String.fromCharCode(0x0fb1d) + \'-\' + String.fromCharCode(0x0fdff) + String.fromCharCode(0x0fe70) + \'-\' + String.fromCharCode(0x0fefc) + String.fromCharCode(0x10800) + \'-\' + String.fromCharCode(0x10fff) + String.fromCharCode(0x1e800) + \'-\' + String.fromCharCode(0x1efff) + \']\'\n/* eslint-enable prettier/prettier */\n);\n/**\n * @param {string} text Text.\n * @param {string} align Alignment.\n * @return {number} Text alignment.\n */\n\nfunction horizontalTextAlign(text, align) {\n if ((align === \'start\' || align === \'end\') && !rtlRegEx.test(text)) {\n align = align === \'start\' ? \'left\' : \'right\';\n }\n\n return TEXT_ALIGN[align];\n}\n\nvar Executor =\n/** @class */\nfunction () {\n /**\n * @param {number} resolution Resolution.\n * @param {number} pixelRatio Pixel ratio.\n * @param {boolean} overlaps The replay can have overlapping geometries.\n * @param {import("../canvas.js").SerializableInstructions} instructions The serializable instructions\n * @param {import("../../size.js").Size} renderBuffer Render buffer (width/height) in pixels.\n */\n function Executor(resolution, pixelRatio, overlaps, instructions, renderBuffer) {\n /**\n * @protected\n * @type {boolean}\n */\n this.overlaps = overlaps;\n /**\n * @protected\n * @type {number}\n */\n\n this.pixelRatio = pixelRatio;\n /**\n * @protected\n * @const\n * @type {number}\n */\n\n this.resolution = resolution;\n /**\n * @private\n * @type {boolean}\n */\n\n this.alignFill_;\n /**\n * @protected\n * @type {Array<*>}\n */\n\n this.instructions = instructions.instructions;\n /**\n * @protected\n * @type {Array<number>}\n */\n\n this.coordinates = instructions.coordinates;\n /**\n * @private\n * @type {!Object<number,import("../../coordinate.js").Coordinate|Array<import("../../coordinate.js").Coordinate>|Array<Array<import("../../coordinate.js").Coordinate>>>}\n */\n\n this.coordinateCache_ = {};\n /**\n * @private\n * @type {import("../../size.js").Size}\n */\n\n this.renderBuffer_ = renderBuffer;\n /**\n * @private\n * @type {!import("../../transform.js").Transform}\n */\n\n this.renderedTransform_ = create();\n /**\n * @protected\n * @type {Array<*>}\n */\n\n this.hitDetectionInstructions = instructions.hitDetectionInstructions;\n /**\n * @private\n * @type {Array<number>}\n */\n\n this.pixelCoordinates_ = null;\n /**\n * @private\n * @type {number}\n */\n\n this.viewRotation_ = 0;\n /**\n * @type {!Object<string, import("../canvas.js").FillState>}\n */\n\n this.fillStates = instructions.fillStates || {};\n /**\n * @type {!Object<string, import("../canvas.js").StrokeState>}\n */\n\n this.strokeStates = instructions.strokeStates || {};\n /**\n * @type {!Object<string, import("../canvas.js").TextState>}\n */\n\n this.textStates = instructions.textStates || {};\n /**\n * @private\n * @type {Object<string, Object<string, number>>}\n */\n\n this.widths_ = {};\n /**\n * @private\n * @type {Object<string, import("../canvas.js").Label>}\n */\n\n this.labels_ = {};\n }\n /**\n * @param {string} text Text.\n * @param {string} textKey Text style key.\n * @param {string} fillKey Fill style key.\n * @param {string} strokeKey Stroke style key.\n * @return {import("../canvas.js").Label} Label.\n */\n\n\n Executor.prototype.createLabel = function (text, textKey, fillKey, strokeKey) {\n var key = text + textKey + fillKey + strokeKey;\n\n if (this.labels_[key]) {\n return this.labels_[key];\n }\n\n var strokeState = strokeKey ? this.strokeStates[strokeKey] : null;\n var fillState = fillKey ? this.fillStates[fillKey] : null;\n var textState = this.textStates[textKey];\n var pixelRatio = this.pixelRatio;\n var scale = [textState.scale[0] * pixelRatio, textState.scale[1] * pixelRatio];\n var align = horizontalTextAlign(text, textState.textAlign || defaultTextAlign);\n var strokeWidth = strokeKey && strokeState.lineWidth ? strokeState.lineWidth : 0;\n var lines = text.split(\'\\n\');\n var numLines = lines.length;\n var widths = [];\n var width = measureTextWidths(textState.font, lines, widths);\n var lineHeight = measureTextHeight(textState.font);\n var height = lineHeight * numLines;\n var renderWidth = width + strokeWidth;\n var contextInstructions = []; // make canvas 2 pixels wider to account for italic text width measurement errors\n\n var w = (renderWidth + 2) * scale[0];\n var h = (height + strokeWidth) * scale[1];\n /** @type {import("../canvas.js").Label} */\n\n var label = {\n width: w < 0 ? Math.floor(w) : Math.ceil(w),\n height: h < 0 ? Math.floor(h) : Math.ceil(h),\n contextInstructions: contextInstructions\n };\n\n if (scale[0] != 1 || scale[1] != 1) {\n contextInstructions.push(\'scale\', scale);\n }\n\n contextInstructions.push(\'font\', textState.font);\n\n if (strokeKey) {\n contextInstructions.push(\'strokeStyle\', strokeState.strokeStyle);\n contextInstructions.push(\'lineWidth\', strokeWidth);\n contextInstructions.push(\'lineCap\', strokeState.lineCap);\n contextInstructions.push(\'lineJoin\', strokeState.lineJoin);\n contextInstructions.push(\'miterLimit\', strokeState.miterLimit); // eslint-disable-next-line\n\n var Context = WORKER_OFFSCREEN_CANVAS ? OffscreenCanvasRenderingContext2D : CanvasRenderingContext2D;\n\n if (Context.prototype.setLineDash) {\n contextInstructions.push(\'setLineDash\', [strokeState.lineDash]);\n contextInstructions.push(\'lineDashOffset\', strokeState.lineDashOffset);\n }\n }\n\n if (fillKey) {\n contextInstructions.push(\'fillStyle\', fillState.fillStyle);\n }\n\n contextInstructions.push(\'textBaseline\', \'middle\');\n contextInstructions.push(\'textAlign\', \'center\');\n var leftRight = 0.5 - align;\n var x = align * renderWidth + leftRight * strokeWidth;\n var i;\n\n if (strokeKey) {\n for (i = 0; i < numLines; ++i) {\n contextInstructions.push(\'strokeText\', [lines[i], x + leftRight * widths[i], 0.5 * (strokeWidth + lineHeight) + i * lineHeight]);\n }\n }\n\n if (fillKey) {\n for (i = 0; i < numLines; ++i) {\n contextInstructions.push(\'fillText\', [lines[i], x + leftRight * widths[i], 0.5 * (strokeWidth + lineHeight) + i * lineHeight]);\n }\n }\n\n this.labels_[key] = label;\n return label;\n };\n /**\n * @param {CanvasRenderingContext2D} context Context.\n * @param {import("../../coordinate.js").Coordinate} p1 1st point of the background box.\n * @param {import("../../coordinate.js").Coordinate} p2 2nd point of the background box.\n * @param {import("../../coordinate.js").Coordinate} p3 3rd point of the background box.\n * @param {import("../../coordinate.js").Coordinate} p4 4th point of the background box.\n * @param {Array<*>} fillInstruction Fill instruction.\n * @param {Array<*>} strokeInstruction Stroke instruction.\n */\n\n\n Executor.prototype.replayTextBackground_ = function (context, p1, p2, p3, p4, fillInstruction, strokeInstruction) {\n context.beginPath();\n context.moveTo.apply(context, p1);\n context.lineTo.apply(context, p2);\n context.lineTo.apply(context, p3);\n context.lineTo.apply(context, p4);\n context.lineTo.apply(context, p1);\n\n if (fillInstruction) {\n this.alignFill_ =\n /** @type {boolean} */\n fillInstruction[2];\n this.fill_(context);\n }\n\n if (strokeInstruction) {\n this.setStrokeStyle_(context,\n /** @type {Array<*>} */\n strokeInstruction);\n context.stroke();\n }\n };\n /**\n * @private\n * @param {number} sheetWidth Width of the sprite sheet.\n * @param {number} sheetHeight Height of the sprite sheet.\n * @param {number} centerX X.\n * @param {number} centerY Y.\n * @param {number} width Width.\n * @param {number} height Height.\n * @param {number} anchorX Anchor X.\n * @param {number} anchorY Anchor Y.\n * @param {number} originX Origin X.\n * @param {number} originY Origin Y.\n * @param {number} rotation Rotation.\n * @param {import("../../size.js").Size} scale Scale.\n * @param {boolean} snapToPixel Snap to pixel.\n * @param {Array<number>} padding Padding.\n * @param {boolean} fillStroke Background fill or stroke.\n * @param {import("../../Feature.js").FeatureLike} feature Feature.\n * @return {ImageOrLabelDimensions} Dimensions for positioning and decluttering the image or label.\n */\n\n\n Executor.prototype.calculateImageOrLabelDimensions_ = function (sheetWidth, sheetHeight, centerX, centerY, width, height, anchorX, anchorY, originX, originY, rotation, scale, snapToPixel, padding, fillStroke, feature) {\n anchorX *= scale[0];\n anchorY *= scale[1];\n var x = centerX - anchorX;\n var y = centerY - anchorY;\n var w = width + originX > sheetWidth ? sheetWidth - originX : width;\n var h = height + originY > sheetHeight ? sheetHeight - originY : height;\n var boxW = padding[3] + w * scale[0] + padding[1];\n var boxH = padding[0] + h * scale[1] + padding[2];\n var boxX = x - padding[3];\n var boxY = y - padding[0];\n\n if (fillStroke || rotation !== 0) {\n p1[0] = boxX;\n p4[0] = boxX;\n p1[1] = boxY;\n p2[1] = boxY;\n p2[0] = boxX + boxW;\n p3[0] = p2[0];\n p3[1] = boxY + boxH;\n p4[1] = p3[1];\n }\n\n var transform;\n\n if (rotation !== 0) {\n transform = compose(create(), centerX, centerY, 1, 1, rotation, -centerX, -centerY);\n apply(transform, p1);\n apply(transform, p2);\n apply(transform, p3);\n apply(transform, p4);\n createOrUpdate(Math.min(p1[0], p2[0], p3[0], p4[0]), Math.min(p1[1], p2[1], p3[1], p4[1]), Math.max(p1[0], p2[0], p3[0], p4[0]), Math.max(p1[1], p2[1], p3[1], p4[1]), tmpExtent);\n } else {\n createOrUpdate(Math.min(boxX, boxX + boxW), Math.min(boxY, boxY + boxH), Math.max(boxX, boxX + boxW), Math.max(boxY, boxY + boxH), tmpExtent);\n }\n\n if (snapToPixel) {\n x = Math.round(x);\n y = Math.round(y);\n }\n\n return {\n drawImageX: x,\n drawImageY: y,\n drawImageW: w,\n drawImageH: h,\n originX: originX,\n originY: originY,\n declutterBox: {\n minX: tmpExtent[0],\n minY: tmpExtent[1],\n maxX: tmpExtent[2],\n maxY: tmpExtent[3],\n value: feature\n },\n canvasTransform: transform,\n scale: scale\n };\n };\n /**\n * @private\n * @param {CanvasRenderingContext2D} context Context.\n * @param {number} contextScale Scale of the context.\n * @param {import("../canvas.js").Label|HTMLImageElement|HTMLCanvasElement|HTMLVideoElement} imageOrLabel Image.\n * @param {ImageOrLabelDimensions} dimensions Dimensions.\n * @param {number} opacity Opacity.\n * @param {Array<*>} fillInstruction Fill instruction.\n * @param {Array<*>} strokeInstruction Stroke instruction.\n * @return {boolean} The image or label was rendered.\n */\n\n\n Executor.prototype.replayImageOrLabel_ = function (context, contextScale, imageOrLabel, dimensions, opacity, fillInstruction, strokeInstruction) {\n var fillStroke = !!(fillInstruction || strokeInstruction);\n var box = dimensions.declutterBox;\n var canvas = context.canvas;\n var strokePadding = strokeInstruction ? strokeInstruction[2] * dimensions.scale[0] / 2 : 0;\n var intersects = box.minX - strokePadding <= canvas.width / contextScale && box.maxX + strokePadding >= 0 && box.minY - strokePadding <= canvas.height / contextScale && box.maxY + strokePadding >= 0;\n\n if (intersects) {\n if (fillStroke) {\n this.replayTextBackground_(context, p1, p2, p3, p4,\n /** @type {Array<*>} */\n fillInstruction,\n /** @type {Array<*>} */\n strokeInstruction);\n }\n\n drawImageOrLabel(context, dimensions.canvasTransform, opacity, imageOrLabel, dimensions.originX, dimensions.originY, dimensions.drawImageW, dimensions.drawImageH, dimensions.drawImageX, dimensions.drawImageY, dimensions.scale);\n }\n\n return true;\n };\n /**\n * @private\n * @param {CanvasRenderingContext2D} context Context.\n */\n\n\n Executor.prototype.fill_ = function (context) {\n if (this.alignFill_) {\n var origin_1 = apply(this.renderedTransform_, [0, 0]);\n var repeatSize = 512 * this.pixelRatio;\n context.save();\n context.translate(origin_1[0] % repeatSize, origin_1[1] % repeatSize);\n context.rotate(this.viewRotation_);\n }\n\n context.fill();\n\n if (this.alignFill_) {\n context.restore();\n }\n };\n /**\n * @private\n * @param {CanvasRenderingContext2D} context Context.\n * @param {Array<*>} instruction Instruction.\n */\n\n\n Executor.prototype.setStrokeStyle_ = function (context, instruction) {\n context[\'strokeStyle\'] =\n /** @type {import("../../colorlike.js").ColorLike} */\n instruction[1];\n context.lineWidth =\n /** @type {number} */\n instruction[2];\n context.lineCap =\n /** @type {CanvasLineCap} */\n instruction[3];\n context.lineJoin =\n /** @type {CanvasLineJoin} */\n instruction[4];\n context.miterLimit =\n /** @type {number} */\n instruction[5];\n\n if (context.setLineDash) {\n context.lineDashOffset =\n /** @type {number} */\n instruction[7];\n context.setLineDash(\n /** @type {Array<number>} */\n instruction[6]);\n }\n };\n /**\n * @private\n * @param {string} text The text to draw.\n * @param {string} textKey The key of the text state.\n * @param {string} strokeKey The key for the stroke state.\n * @param {string} fillKey The key for the fill state.\n * @return {{label: import("../canvas.js").Label, anchorX: number, anchorY: number}} The text image and its anchor.\n */\n\n\n Executor.prototype.drawLabelWithPointPlacement_ = function (text, textKey, strokeKey, fillKey) {\n var textState = this.textStates[textKey];\n var label = this.createLabel(text, textKey, fillKey, strokeKey);\n var strokeState = this.strokeStates[strokeKey];\n var pixelRatio = this.pixelRatio;\n var align = horizontalTextAlign(text, textState.textAlign || defaultTextAlign);\n var baseline = TEXT_ALIGN[textState.textBaseline || defaultTextBaseline];\n var strokeWidth = strokeState && strokeState.lineWidth ? strokeState.lineWidth : 0; // Remove the 2 pixels we added in createLabel() for the anchor\n\n var width = label.width / pixelRatio - 2 * textState.scale[0];\n var anchorX = align * width + 2 * (0.5 - align) * strokeWidth;\n var anchorY = baseline * label.height / pixelRatio + 2 * (0.5 - baseline) * strokeWidth;\n return {\n label: label,\n anchorX: anchorX,\n anchorY: anchorY\n };\n };\n /**\n * @private\n * @param {CanvasRenderingContext2D} context Context.\n * @param {number} contextScale Scale of the context.\n * @param {import("../../transform.js").Transform} transform Transform.\n * @param {Array<*>} instructions Instructions array.\n * @param {boolean} snapToPixel Snap point symbols and text to integer pixels.\n * @param {FeatureCallback<T>=} opt_featureCallback Feature callback.\n * @param {import("../../extent.js").Extent=} opt_hitExtent Only check\n * features that intersect this extent.\n * @param {import("rbush").default=} opt_declutterTree Declutter tree.\n * @return {T|undefined} Callback result.\n * @template T\n */\n\n\n Executor.prototype.execute_ = function (context, contextScale, transform, instructions, snapToPixel, opt_featureCallback, opt_hitExtent, opt_declutterTree) {\n /** @type {Array<number>} */\n var pixelCoordinates;\n\n if (this.pixelCoordinates_ && equals(transform, this.renderedTransform_)) {\n pixelCoordinates = this.pixelCoordinates_;\n } else {\n if (!this.pixelCoordinates_) {\n this.pixelCoordinates_ = [];\n }\n\n pixelCoordinates = transform2D(this.coordinates, 0, this.coordinates.length, 2, transform, this.pixelCoordinates_);\n setFromArray(this.renderedTransform_, transform);\n }\n\n var i = 0; // instruction index\n\n var ii = instructions.length; // end of instructions\n\n var d = 0; // data index\n\n var dd; // end of per-instruction data\n\n var anchorX, anchorY, prevX, prevY, roundX, roundY, image, text, textKey, strokeKey, fillKey;\n var pendingFill = 0;\n var pendingStroke = 0;\n var lastFillInstruction = null;\n var lastStrokeInstruction = null;\n var coordinateCache = this.coordinateCache_;\n var viewRotation = this.viewRotation_;\n var viewRotationFromTransform = Math.round(Math.atan2(-transform[1], transform[0]) * 1e12) / 1e12;\n var state =\n /** @type {import("../../render.js").State} */\n {\n context: context,\n pixelRatio: this.pixelRatio,\n resolution: this.resolution,\n rotation: viewRotation\n }; // When the batch size gets too big, performance decreases. 200 is a good\n // balance between batch size and number of fill/stroke instructions.\n\n var batchSize = this.instructions != instructions || this.overlaps ? 0 : 200;\n var\n /** @type {import("../../Feature.js").FeatureLike} */\n feature;\n var x, y, currentGeometry;\n\n while (i < ii) {\n var instruction = instructions[i];\n var type =\n /** @type {import("./Instruction.js").default} */\n instruction[0];\n\n switch (type) {\n case canvas_Instruction.BEGIN_GEOMETRY:\n feature =\n /** @type {import("../../Feature.js").FeatureLike} */\n instruction[1];\n currentGeometry = instruction[3];\n\n if (!feature.getGeometry()) {\n i =\n /** @type {number} */\n instruction[2];\n } else if (opt_hitExtent !== undefined && !intersects(opt_hitExtent, currentGeometry.getExtent())) {\n i =\n /** @type {number} */\n instruction[2] + 1;\n } else {\n ++i;\n }\n\n break;\n\n case canvas_Instruction.BEGIN_PATH:\n if (pendingFill > batchSize) {\n this.fill_(context);\n pendingFill = 0;\n }\n\n if (pendingStroke > batchSize) {\n context.stroke();\n pendingStroke = 0;\n }\n\n if (!pendingFill && !pendingStroke) {\n context.beginPath();\n prevX = NaN;\n prevY = NaN;\n }\n\n ++i;\n break;\n\n case canvas_Instruction.CIRCLE:\n d =\n /** @type {number} */\n instruction[1];\n var x1 = pixelCoordinates[d];\n var y1 = pixelCoordinates[d + 1];\n var x2 = pixelCoordinates[d + 2];\n var y2 = pixelCoordinates[d + 3];\n var dx = x2 - x1;\n var dy = y2 - y1;\n var r = Math.sqrt(dx * dx + dy * dy);\n context.moveTo(x1 + r, y1);\n context.arc(x1, y1, r, 0, 2 * Math.PI, true);\n ++i;\n break;\n\n case canvas_Instruction.CLOSE_PATH:\n context.closePath();\n ++i;\n break;\n\n case canvas_Instruction.CUSTOM:\n d =\n /** @type {number} */\n instruction[1];\n dd = instruction[2];\n var geometry =\n /** @type {import("../../geom/SimpleGeometry.js").default} */\n instruction[3];\n var renderer = instruction[4];\n var fn = instruction.length == 6 ? instruction[5] : undefined;\n state.geometry = geometry;\n state.feature = feature;\n\n if (!(i in coordinateCache)) {\n coordinateCache[i] = [];\n }\n\n var coords = coordinateCache[i];\n\n if (fn) {\n fn(pixelCoordinates, d, dd, 2, coords);\n } else {\n coords[0] = pixelCoordinates[d];\n coords[1] = pixelCoordinates[d + 1];\n coords.length = 2;\n }\n\n renderer(coords, state);\n ++i;\n break;\n\n case canvas_Instruction.DRAW_IMAGE:\n d =\n /** @type {number} */\n instruction[1];\n dd =\n /** @type {number} */\n instruction[2];\n image =\n /** @type {HTMLCanvasElement|HTMLVideoElement|HTMLImageElement} */\n instruction[3]; // Remaining arguments in DRAW_IMAGE are in alphabetical order\n\n anchorX =\n /** @type {number} */\n instruction[4];\n anchorY =\n /** @type {number} */\n instruction[5];\n var height =\n /** @type {number} */\n instruction[6];\n var opacity =\n /** @type {number} */\n instruction[7];\n var originX =\n /** @type {number} */\n instruction[8];\n var originY =\n /** @type {number} */\n instruction[9];\n var rotateWithView =\n /** @type {boolean} */\n instruction[10];\n var rotation =\n /** @type {number} */\n instruction[11];\n var scale =\n /** @type {import("../../size.js").Size} */\n instruction[12];\n var width =\n /** @type {number} */\n instruction[13];\n var declutterImageWithText =\n /** @type {import("../canvas.js").DeclutterImageWithText} */\n instruction[14];\n\n if (!image && instruction.length >= 19) {\n // create label images\n text =\n /** @type {string} */\n instruction[18];\n textKey =\n /** @type {string} */\n instruction[19];\n strokeKey =\n /** @type {string} */\n instruction[20];\n fillKey =\n /** @type {string} */\n instruction[21];\n var labelWithAnchor = this.drawLabelWithPointPlacement_(text, textKey, strokeKey, fillKey);\n image = labelWithAnchor.label;\n instruction[3] = image;\n var textOffsetX =\n /** @type {number} */\n instruction[22];\n anchorX = (labelWithAnchor.anchorX - textOffsetX) * this.pixelRatio;\n instruction[4] = anchorX;\n var textOffsetY =\n /** @type {number} */\n instruction[23];\n anchorY = (labelWithAnchor.anchorY - textOffsetY) * this.pixelRatio;\n instruction[5] = anchorY;\n height = image.height;\n instruction[6] = height;\n width = image.width;\n instruction[13] = width;\n }\n\n var geometryWidths = void 0;\n\n if (instruction.length > 24) {\n geometryWidths =\n /** @type {number} */\n instruction[24];\n }\n\n var padding = void 0,\n backgroundFill = void 0,\n backgroundStroke = void 0;\n\n if (instruction.length > 16) {\n padding =\n /** @type {Array<number>} */\n instruction[15];\n backgroundFill =\n /** @type {boolean} */\n instruction[16];\n backgroundStroke =\n /** @type {boolean} */\n instruction[17];\n } else {\n padding = defaultPadding;\n backgroundFill = false;\n backgroundStroke = false;\n }\n\n if (rotateWithView && viewRotationFromTransform) {\n // Canvas is expected to be rotated to reverse view rotation.\n rotation += viewRotation;\n } else if (!rotateWithView && !viewRotationFromTransform) {\n // Canvas is not rotated, images need to be rotated back to be north-up.\n rotation -= viewRotation;\n }\n\n var widthIndex = 0;\n\n for (; d < dd; d += 2) {\n if (geometryWidths && geometryWidths[widthIndex++] < width / this.pixelRatio) {\n continue;\n }\n\n var dimensions = this.calculateImageOrLabelDimensions_(image.width, image.height, pixelCoordinates[d], pixelCoordinates[d + 1], width, height, anchorX, anchorY, originX, originY, rotation, scale, snapToPixel, padding, backgroundFill || backgroundStroke, feature);\n /** @type {ReplayImageOrLabelArgs} */\n\n var args = [context, contextScale, image, dimensions, opacity, backgroundFill ?\n /** @type {Array<*>} */\n lastFillInstruction : null, backgroundStroke ?\n /** @type {Array<*>} */\n lastStrokeInstruction : null];\n var imageArgs = void 0;\n var imageDeclutterBox = void 0;\n\n if (opt_declutterTree && declutterImageWithText) {\n if (!declutterImageWithText[d]) {\n // We now have the image for an image+text combination.\n declutterImageWithText[d] = args; // Don\'t render anything for now, wait for the text.\n\n continue;\n }\n\n imageArgs = declutterImageWithText[d];\n delete declutterImageWithText[d];\n imageDeclutterBox = getDeclutterBox(imageArgs);\n\n if (opt_declutterTree.collides(imageDeclutterBox)) {\n continue;\n }\n }\n\n if (opt_declutterTree && opt_declutterTree.collides(dimensions.declutterBox)) {\n continue;\n }\n\n if (imageArgs) {\n // We now have image and text for an image+text combination.\n if (opt_declutterTree) {\n opt_declutterTree.insert(imageDeclutterBox);\n } // Render the image before we render the text.\n\n\n this.replayImageOrLabel_.apply(this, imageArgs);\n }\n\n if (opt_declutterTree) {\n opt_declutterTree.insert(dimensions.declutterBox);\n }\n\n this.replayImageOrLabel_.apply(this, args);\n }\n\n ++i;\n break;\n\n case canvas_Instruction.DRAW_CHARS:\n var begin =\n /** @type {number} */\n instruction[1];\n var end =\n /** @type {number} */\n instruction[2];\n var baseline =\n /** @type {number} */\n instruction[3];\n var overflow =\n /** @type {number} */\n instruction[4];\n fillKey =\n /** @type {string} */\n instruction[5];\n var maxAngle =\n /** @type {number} */\n instruction[6];\n var measurePixelRatio =\n /** @type {number} */\n instruction[7];\n var offsetY =\n /** @type {number} */\n instruction[8];\n strokeKey =\n /** @type {string} */\n instruction[9];\n var strokeWidth =\n /** @type {number} */\n instruction[10];\n text =\n /** @type {string} */\n instruction[11];\n textKey =\n /** @type {string} */\n instruction[12];\n var pixelRatioScale = [\n /** @type {number} */\n instruction[13],\n /** @type {number} */\n instruction[13]];\n var textState = this.textStates[textKey];\n var font = textState.font;\n var textScale = [textState.scale[0] * measurePixelRatio, textState.scale[1] * measurePixelRatio];\n var cachedWidths = void 0;\n\n if (font in this.widths_) {\n cachedWidths = this.widths_[font];\n } else {\n cachedWidths = {};\n this.widths_[font] = cachedWidths;\n }\n\n var pathLength = lineStringLength(pixelCoordinates, begin, end, 2);\n var textLength = Math.abs(textScale[0]) * measureAndCacheTextWidth(font, text, cachedWidths);\n\n if (overflow || textLength <= pathLength) {\n var textAlign = this.textStates[textKey].textAlign;\n var startM = (pathLength - textLength) * TEXT_ALIGN[textAlign];\n var parts = drawTextOnPath(pixelCoordinates, begin, end, 2, text, startM, maxAngle, Math.abs(textScale[0]), measureAndCacheTextWidth, font, cachedWidths, viewRotationFromTransform ? 0 : this.viewRotation_);\n\n drawChars: if (parts) {\n /** @type {Array<ReplayImageOrLabelArgs>} */\n var replayImageOrLabelArgs = [];\n var c = void 0,\n cc = void 0,\n chars = void 0,\n label = void 0,\n part = void 0;\n\n if (strokeKey) {\n for (c = 0, cc = parts.length; c < cc; ++c) {\n part = parts[c]; // x, y, anchorX, rotation, chunk\n\n chars =\n /** @type {string} */\n part[4];\n label = this.createLabel(chars, textKey, \'\', strokeKey);\n anchorX =\n /** @type {number} */\n part[2] + (textScale[0] < 0 ? -strokeWidth : strokeWidth);\n anchorY = baseline * label.height + (0.5 - baseline) * 2 * strokeWidth * textScale[1] / textScale[0] - offsetY;\n var dimensions = this.calculateImageOrLabelDimensions_(label.width, label.height, part[0], part[1], label.width, label.height, anchorX, anchorY, 0, 0, part[3], pixelRatioScale, false, defaultPadding, false, feature);\n\n if (opt_declutterTree && opt_declutterTree.collides(dimensions.declutterBox)) {\n break drawChars;\n }\n\n replayImageOrLabelArgs.push([context, contextScale, label, dimensions, 1, null, null]);\n }\n }\n\n if (fillKey) {\n for (c = 0, cc = parts.length; c < cc; ++c) {\n part = parts[c]; // x, y, anchorX, rotation, chunk\n\n chars =\n /** @type {string} */\n part[4];\n label = this.createLabel(chars, textKey, fillKey, \'\');\n anchorX =\n /** @type {number} */\n part[2];\n anchorY = baseline * label.height - offsetY;\n var dimensions = this.calculateImageOrLabelDimensions_(label.width, label.height, part[0], part[1], label.width, label.height, anchorX, anchorY, 0, 0, part[3], pixelRatioScale, false, defaultPadding, false, feature);\n\n if (opt_declutterTree && opt_declutterTree.collides(dimensions.declutterBox)) {\n break drawChars;\n }\n\n replayImageOrLabelArgs.push([context, contextScale, label, dimensions, 1, null, null]);\n }\n }\n\n if (opt_declutterTree) {\n opt_declutterTree.load(replayImageOrLabelArgs.map(getDeclutterBox));\n }\n\n for (var i_1 = 0, ii_1 = replayImageOrLabelArgs.length; i_1 < ii_1; ++i_1) {\n this.replayImageOrLabel_.apply(this, replayImageOrLabelArgs[i_1]);\n }\n }\n }\n\n ++i;\n break;\n\n case canvas_Instruction.END_GEOMETRY:\n if (opt_featureCallback !== undefined) {\n feature =\n /** @type {import("../../Feature.js").FeatureLike} */\n instruction[1];\n var result = opt_featureCallback(feature, currentGeometry);\n\n if (result) {\n return result;\n }\n }\n\n ++i;\n break;\n\n case canvas_Instruction.FILL:\n if (batchSize) {\n pendingFill++;\n } else {\n this.fill_(context);\n }\n\n ++i;\n break;\n\n case canvas_Instruction.MOVE_TO_LINE_TO:\n d =\n /** @type {number} */\n instruction[1];\n dd =\n /** @type {number} */\n instruction[2];\n x = pixelCoordinates[d];\n y = pixelCoordinates[d + 1];\n roundX = x + 0.5 | 0;\n roundY = y + 0.5 | 0;\n\n if (roundX !== prevX || roundY !== prevY) {\n context.moveTo(x, y);\n prevX = roundX;\n prevY = roundY;\n }\n\n for (d += 2; d < dd; d += 2) {\n x = pixelCoordinates[d];\n y = pixelCoordinates[d + 1];\n roundX = x + 0.5 | 0;\n roundY = y + 0.5 | 0;\n\n if (d == dd - 2 || roundX !== prevX || roundY !== prevY) {\n context.lineTo(x, y);\n prevX = roundX;\n prevY = roundY;\n }\n }\n\n ++i;\n break;\n\n case canvas_Instruction.SET_FILL_STYLE:\n lastFillInstruction = instruction;\n this.alignFill_ = instruction[2];\n\n if (pendingFill) {\n this.fill_(context);\n pendingFill = 0;\n\n if (pendingStroke) {\n context.stroke();\n pendingStroke = 0;\n }\n }\n\n context.fillStyle =\n /** @type {import("../../colorlike.js").ColorLike} */\n instruction[1];\n ++i;\n break;\n\n case canvas_Instruction.SET_STROKE_STYLE:\n lastStrokeInstruction = instruction;\n\n if (pendingStroke) {\n context.stroke();\n pendingStroke = 0;\n }\n\n this.setStrokeStyle_(context,\n /** @type {Array<*>} */\n instruction);\n ++i;\n break;\n\n case canvas_Instruction.STROKE:\n if (batchSize) {\n pendingStroke++;\n } else {\n context.stroke();\n }\n\n ++i;\n break;\n\n default:\n ++i; // consume the instruction anyway, to avoid an infinite loop\n\n break;\n }\n }\n\n if (pendingFill) {\n this.fill_(context);\n }\n\n if (pendingStroke) {\n context.stroke();\n }\n\n return undefined;\n };\n /**\n * @param {CanvasRenderingContext2D} context Context.\n * @param {number} contextScale Scale of the context.\n * @param {import("../../transform.js").Transform} transform Transform.\n * @param {number} viewRotation View rotation.\n * @param {boolean} snapToPixel Snap point symbols and text to integer pixels.\n * @param {import("rbush").default=} opt_declutterTree Declutter tree.\n */\n\n\n Executor.prototype.execute = function (context, contextScale, transform, viewRotation, snapToPixel, opt_declutterTree) {\n this.viewRotation_ = viewRotation;\n this.execute_(context, contextScale, transform, this.instructions, snapToPixel, undefined, undefined, opt_declutterTree);\n };\n /**\n * @param {CanvasRenderingContext2D} context Context.\n * @param {import("../../transform.js").Transform} transform Transform.\n * @param {number} viewRotation View rotation.\n * @param {FeatureCallback<T>=} opt_featureCallback Feature callback.\n * @param {import("../../extent.js").Extent=} opt_hitExtent Only check\n * features that intersect this extent.\n * @return {T|undefined} Callback result.\n * @template T\n */\n\n\n Executor.prototype.executeHitDetection = function (context, transform, viewRotation, opt_featureCallback, opt_hitExtent) {\n this.viewRotation_ = viewRotation;\n return this.execute_(context, 1, transform, this.hitDetectionInstructions, true, opt_featureCallback, opt_hitExtent);\n };\n\n return Executor;\n}();\n\n/* harmony default export */ var canvas_Executor = (Executor);\n;// CONCATENATED MODULE: ./node_modules/ol/render/canvas/ExecutorGroup.js\n/**\n * @module ol/render/canvas/ExecutorGroup\n */\n\n\n\n\n\n\n\n\n/**\n * @const\n * @type {Array<import("./BuilderType.js").default>}\n */\n\nvar ORDER = [BuilderType.POLYGON, BuilderType.CIRCLE, BuilderType.LINE_STRING, BuilderType.IMAGE, BuilderType.TEXT, BuilderType.DEFAULT];\n\nvar ExecutorGroup =\n/** @class */\nfunction () {\n /**\n * @param {import("../../extent.js").Extent} maxExtent Max extent for clipping. When a\n * `maxExtent` was set on the Buillder for this executor group, the same `maxExtent`\n * should be set here, unless the target context does not exceet that extent (which\n * can be the case when rendering to tiles).\n * @param {number} resolution Resolution.\n * @param {number} pixelRatio Pixel ratio.\n * @param {boolean} overlaps The executor group can have overlapping geometries.\n * @param {!Object<string, !Object<import("./BuilderType.js").default, import("../canvas.js").SerializableInstructions>>} allInstructions\n * The serializable instructions.\n * @param {number=} opt_renderBuffer Optional rendering buffer.\n */\n function ExecutorGroup(maxExtent, resolution, pixelRatio, overlaps, allInstructions, opt_renderBuffer) {\n /**\n * @private\n * @type {import("../../extent.js").Extent}\n */\n this.maxExtent_ = maxExtent;\n /**\n * @private\n * @type {boolean}\n */\n\n this.overlaps_ = overlaps;\n /**\n * @private\n * @type {number}\n */\n\n this.pixelRatio_ = pixelRatio;\n /**\n * @private\n * @type {number}\n */\n\n this.resolution_ = resolution;\n /**\n * @private\n * @type {number|undefined}\n */\n\n this.renderBuffer_ = opt_renderBuffer;\n /**\n * @private\n * @type {!Object<string, !Object<import("./BuilderType.js").default, import("./Executor").default>>}\n */\n\n this.executorsByZIndex_ = {};\n /**\n * @private\n * @type {CanvasRenderingContext2D}\n */\n\n this.hitDetectionContext_ = null;\n /**\n * @private\n * @type {import("../../transform.js").Transform}\n */\n\n this.hitDetectionTransform_ = create();\n this.createExecutors_(allInstructions);\n }\n /**\n * @param {CanvasRenderingContext2D} context Context.\n * @param {import("../../transform.js").Transform} transform Transform.\n */\n\n\n ExecutorGroup.prototype.clip = function (context, transform) {\n var flatClipCoords = this.getClipCoords(transform);\n context.beginPath();\n context.moveTo(flatClipCoords[0], flatClipCoords[1]);\n context.lineTo(flatClipCoords[2], flatClipCoords[3]);\n context.lineTo(flatClipCoords[4], flatClipCoords[5]);\n context.lineTo(flatClipCoords[6], flatClipCoords[7]);\n context.clip();\n };\n /**\n * Create executors and populate them using the provided instructions.\n * @private\n * @param {!Object<string, !Object<import("./BuilderType.js").default, import("../canvas.js").SerializableInstructions>>} allInstructions The serializable instructions\n */\n\n\n ExecutorGroup.prototype.createExecutors_ = function (allInstructions) {\n for (var zIndex in allInstructions) {\n var executors = this.executorsByZIndex_[zIndex];\n\n if (executors === undefined) {\n executors = {};\n this.executorsByZIndex_[zIndex] = executors;\n }\n\n var instructionByZindex = allInstructions[zIndex];\n var renderBuffer = [this.renderBuffer_ || 0, this.renderBuffer_ || 0];\n\n for (var builderType in instructionByZindex) {\n var instructions = instructionByZindex[builderType];\n executors[builderType] = new canvas_Executor(this.resolution_, this.pixelRatio_, this.overlaps_, instructions, renderBuffer);\n }\n }\n };\n /**\n * @param {Array<import("./BuilderType.js").default>} executors Executors.\n * @return {boolean} Has executors of the provided types.\n */\n\n\n ExecutorGroup.prototype.hasExecutors = function (executors) {\n for (var zIndex in this.executorsByZIndex_) {\n var candidates = this.executorsByZIndex_[zIndex];\n\n for (var i = 0, ii = executors.length; i < ii; ++i) {\n if (executors[i] in candidates) {\n return true;\n }\n }\n }\n\n return false;\n };\n /**\n * @param {import("../../coordinate.js").Coordinate} coordinate Coordinate.\n * @param {number} resolution Resolution.\n * @param {number} rotation Rotation.\n * @param {number} hitTolerance Hit tolerance in pixels.\n * @param {function(import("../../Feature.js").FeatureLike, import("../../geom/SimpleGeometry.js").default, number): T} callback Feature callback.\n * @param {Array<import("../../Feature.js").FeatureLike>} declutteredFeatures Decluttered features.\n * @return {T|undefined} Callback result.\n * @template T\n */\n\n\n ExecutorGroup.prototype.forEachFeatureAtCoordinate = function (coordinate, resolution, rotation, hitTolerance, callback, declutteredFeatures) {\n hitTolerance = Math.round(hitTolerance);\n var contextSize = hitTolerance * 2 + 1;\n var transform = compose(this.hitDetectionTransform_, hitTolerance + 0.5, hitTolerance + 0.5, 1 / resolution, -1 / resolution, -rotation, -coordinate[0], -coordinate[1]);\n var newContext = !this.hitDetectionContext_;\n\n if (newContext) {\n this.hitDetectionContext_ = createCanvasContext2D(contextSize, contextSize);\n }\n\n var context = this.hitDetectionContext_;\n\n if (context.canvas.width !== contextSize || context.canvas.height !== contextSize) {\n context.canvas.width = contextSize;\n context.canvas.height = contextSize;\n } else if (!newContext) {\n context.clearRect(0, 0, contextSize, contextSize);\n }\n /**\n * @type {import("../../extent.js").Extent}\n */\n\n\n var hitExtent;\n\n if (this.renderBuffer_ !== undefined) {\n hitExtent = createEmpty();\n extendCoordinate(hitExtent, coordinate);\n buffer(hitExtent, resolution * (this.renderBuffer_ + hitTolerance), hitExtent);\n }\n\n var indexes = getPixelIndexArray(hitTolerance);\n var builderType;\n /**\n * @param {import("../../Feature.js").FeatureLike} feature Feature.\n * @param {import("../../geom/SimpleGeometry.js").default} geometry Geometry.\n * @return {T|undefined} Callback result.\n */\n\n function featureCallback(feature, geometry) {\n var imageData = context.getImageData(0, 0, contextSize, contextSize).data;\n\n for (var i_1 = 0, ii = indexes.length; i_1 < ii; i_1++) {\n if (imageData[indexes[i_1]] > 0) {\n if (!declutteredFeatures || builderType !== BuilderType.IMAGE && builderType !== BuilderType.TEXT || declutteredFeatures.indexOf(feature) !== -1) {\n var idx = (indexes[i_1] - 3) / 4;\n var x = hitTolerance - idx % contextSize;\n var y = hitTolerance - (idx / contextSize | 0);\n var result_1 = callback(feature, geometry, x * x + y * y);\n\n if (result_1) {\n return result_1;\n }\n }\n\n context.clearRect(0, 0, contextSize, contextSize);\n break;\n }\n }\n\n return undefined;\n }\n /** @type {Array<number>} */\n\n\n var zs = Object.keys(this.executorsByZIndex_).map(Number);\n zs.sort(numberSafeCompareFunction);\n var i, j, executors, executor, result;\n\n for (i = zs.length - 1; i >= 0; --i) {\n var zIndexKey = zs[i].toString();\n executors = this.executorsByZIndex_[zIndexKey];\n\n for (j = ORDER.length - 1; j >= 0; --j) {\n builderType = ORDER[j];\n executor = executors[builderType];\n\n if (executor !== undefined) {\n result = executor.executeHitDetection(context, transform, rotation, featureCallback, hitExtent);\n\n if (result) {\n return result;\n }\n }\n }\n }\n\n return undefined;\n };\n /**\n * @param {import("../../transform.js").Transform} transform Transform.\n * @return {Array<number>} Clip coordinates.\n */\n\n\n ExecutorGroup.prototype.getClipCoords = function (transform) {\n var maxExtent = this.maxExtent_;\n\n if (!maxExtent) {\n return null;\n }\n\n var minX = maxExtent[0];\n var minY = maxExtent[1];\n var maxX = maxExtent[2];\n var maxY = maxExtent[3];\n var flatClipCoords = [minX, minY, minX, maxY, maxX, maxY, maxX, minY];\n transform2D(flatClipCoords, 0, 8, 2, transform, flatClipCoords);\n return flatClipCoords;\n };\n /**\n * @return {boolean} Is empty.\n */\n\n\n ExecutorGroup.prototype.isEmpty = function () {\n return obj_isEmpty(this.executorsByZIndex_);\n };\n /**\n * @param {CanvasRenderingContext2D} context Context.\n * @param {number} contextScale Scale of the context.\n * @param {import("../../transform.js").Transform} transform Transform.\n * @param {number} viewRotation View rotation.\n * @param {boolean} snapToPixel Snap point symbols and test to integer pixel.\n * @param {Array<import("./BuilderType.js").default>=} opt_builderTypes Ordered replay types to replay.\n * Default is {@link module:ol/render/replay~ORDER}\n * @param {import("rbush").default=} opt_declutterTree Declutter tree.\n */\n\n\n ExecutorGroup.prototype.execute = function (context, contextScale, transform, viewRotation, snapToPixel, opt_builderTypes, opt_declutterTree) {\n /** @type {Array<number>} */\n var zs = Object.keys(this.executorsByZIndex_).map(Number);\n zs.sort(numberSafeCompareFunction); // setup clipping so that the parts of over-simplified geometries are not\n // visible outside the current extent when panning\n\n if (this.maxExtent_) {\n context.save();\n this.clip(context, transform);\n }\n\n var builderTypes = opt_builderTypes ? opt_builderTypes : ORDER;\n var i, ii, j, jj, replays, replay;\n\n if (opt_declutterTree) {\n zs.reverse();\n }\n\n for (i = 0, ii = zs.length; i < ii; ++i) {\n var zIndexKey = zs[i].toString();\n replays = this.executorsByZIndex_[zIndexKey];\n\n for (j = 0, jj = builderTypes.length; j < jj; ++j) {\n var builderType = builderTypes[j];\n replay = replays[builderType];\n\n if (replay !== undefined) {\n replay.execute(context, contextScale, transform, viewRotation, snapToPixel, opt_declutterTree);\n }\n }\n }\n\n if (this.maxExtent_) {\n context.restore();\n }\n };\n\n return ExecutorGroup;\n}();\n/**\n * This cache is used to store arrays of indexes for calculated pixel circles\n * to increase performance.\n * It is a static property to allow each Replaygroup to access it.\n * @type {Object<number, Array<number>>}\n */\n\n\nvar circlePixelIndexArrayCache = {};\n/**\n * This methods creates an array with indexes of all pixels within a circle,\n * ordered by how close they are to the center.\n * A cache is used to increase performance.\n * @param {number} radius Radius.\n * @returns {Array<number>} An array with indexes within a circle.\n */\n\nfunction getPixelIndexArray(radius) {\n if (circlePixelIndexArrayCache[radius] !== undefined) {\n return circlePixelIndexArrayCache[radius];\n }\n\n var size = radius * 2 + 1;\n var maxDistanceSq = radius * radius;\n var distances = new Array(maxDistanceSq + 1);\n\n for (var i = 0; i <= radius; ++i) {\n for (var j = 0; j <= radius; ++j) {\n var distanceSq = i * i + j * j;\n\n if (distanceSq > maxDistanceSq) {\n break;\n }\n\n var distance = distances[distanceSq];\n\n if (!distance) {\n distance = [];\n distances[distanceSq] = distance;\n }\n\n distance.push(((radius + i) * size + (radius + j)) * 4 + 3);\n\n if (i > 0) {\n distance.push(((radius - i) * size + (radius + j)) * 4 + 3);\n }\n\n if (j > 0) {\n distance.push(((radius + i) * size + (radius - j)) * 4 + 3);\n\n if (i > 0) {\n distance.push(((radius - i) * size + (radius - j)) * 4 + 3);\n }\n }\n }\n }\n\n var pixelIndex = [];\n\n for (var i = 0, ii = distances.length; i < ii; ++i) {\n if (distances[i]) {\n pixelIndex.push.apply(pixelIndex, distances[i]);\n }\n }\n\n circlePixelIndexArrayCache[radius] = pixelIndex;\n return pixelIndex;\n}\n/* harmony default export */ var canvas_ExecutorGroup = (ExecutorGroup);\n;// CONCATENATED MODULE: ./node_modules/ol/layer/VectorTileRenderType.js\n/**\n * @module ol/layer/VectorTileRenderType\n */\n\n/**\n * @enum {string}\n * Render mode for vector tiles:\n * * `\'image\'`: Vector tiles are rendered as images. Great performance, but\n * point symbols and texts are always rotated with the view and pixels are\n * scaled during zoom animations.\n * * `\'hybrid\'`: Polygon and line elements are rendered as images, so pixels\n * are scaled during zoom animations. Point symbols and texts are accurately\n * rendered as vectors and can stay upright on rotated views.\n * * `\'vector\'`: Everything is rendered as vectors. Use this mode for improved\n * performance on vector tile layers with only a few rendered features (e.g.\n * for highlighting a subset of features of another layer with the same\n * source).\n * @api\n */\n/* harmony default export */ var VectorTileRenderType = ({\n IMAGE: \'image\',\n HYBRID: \'hybrid\',\n VECTOR: \'vector\'\n});\n;// CONCATENATED MODULE: ./node_modules/ol/render/canvas/Immediate.js\n/**\n * @module ol/render/canvas/Immediate\n */\n// FIXME test, especially polygons with holes and multipolygons\n// FIXME need to handle large thick features (where pixel size matters)\n// FIXME add offset and end to ol/geom/flat/transform~transform2D?\nvar Immediate_extends = undefined && undefined.__extends || function () {\n var _extendStatics = function extendStatics(d, b) {\n _extendStatics = Object.setPrototypeOf || {\n __proto__: []\n } instanceof Array && function (d, b) {\n d.__proto__ = b;\n } || function (d, b) {\n for (var p in b) {\n if (Object.prototype.hasOwnProperty.call(b, p)) d[p] = b[p];\n }\n };\n\n return _extendStatics(d, b);\n };\n\n return function (d, b) {\n _extendStatics(d, b);\n\n function __() {\n this.constructor = d;\n }\n\n d.prototype = b === null ? Object.create(b) : (__.prototype = b.prototype, new __());\n };\n}();\n\n\n\n\n\n\n\n\n\n\n/**\n * @classdesc\n * A concrete subclass of {@link module:ol/render/VectorContext} that implements\n * direct rendering of features and geometries to an HTML5 Canvas context.\n * Instances of this class are created internally by the library and\n * provided to application code as vectorContext member of the\n * {@link module:ol/render/Event~RenderEvent} object associated with postcompose, precompose and\n * render events emitted by layers and maps.\n */\n\nvar CanvasImmediateRenderer =\n/** @class */\nfunction (_super) {\n Immediate_extends(CanvasImmediateRenderer, _super);\n /**\n * @param {CanvasRenderingContext2D} context Context.\n * @param {number} pixelRatio Pixel ratio.\n * @param {import("../../extent.js").Extent} extent Extent.\n * @param {import("../../transform.js").Transform} transform Transform.\n * @param {number} viewRotation View rotation.\n * @param {number=} opt_squaredTolerance Optional squared tolerance for simplification.\n * @param {import("../../proj.js").TransformFunction=} opt_userTransform Transform from user to view projection.\n */\n\n\n function CanvasImmediateRenderer(context, pixelRatio, extent, transform, viewRotation, opt_squaredTolerance, opt_userTransform) {\n var _this = _super.call(this) || this;\n /**\n * @private\n * @type {CanvasRenderingContext2D}\n */\n\n\n _this.context_ = context;\n /**\n * @private\n * @type {number}\n */\n\n _this.pixelRatio_ = pixelRatio;\n /**\n * @private\n * @type {import("../../extent.js").Extent}\n */\n\n _this.extent_ = extent;\n /**\n * @private\n * @type {import("../../transform.js").Transform}\n */\n\n _this.transform_ = transform;\n /**\n * @private\n * @type {number}\n */\n\n _this.viewRotation_ = viewRotation;\n /**\n * @private\n * @type {number}\n */\n\n _this.squaredTolerance_ = opt_squaredTolerance;\n /**\n * @private\n * @type {import("../../proj.js").TransformFunction}\n */\n\n _this.userTransform_ = opt_userTransform;\n /**\n * @private\n * @type {?import("../canvas.js").FillState}\n */\n\n _this.contextFillState_ = null;\n /**\n * @private\n * @type {?import("../canvas.js").StrokeState}\n */\n\n _this.contextStrokeState_ = null;\n /**\n * @private\n * @type {?import("../canvas.js").TextState}\n */\n\n _this.contextTextState_ = null;\n /**\n * @private\n * @type {?import("../canvas.js").FillState}\n */\n\n _this.fillState_ = null;\n /**\n * @private\n * @type {?import("../canvas.js").StrokeState}\n */\n\n _this.strokeState_ = null;\n /**\n * @private\n * @type {HTMLCanvasElement|HTMLVideoElement|HTMLImageElement}\n */\n\n _this.image_ = null;\n /**\n * @private\n * @type {number}\n */\n\n _this.imageAnchorX_ = 0;\n /**\n * @private\n * @type {number}\n */\n\n _this.imageAnchorY_ = 0;\n /**\n * @private\n * @type {number}\n */\n\n _this.imageHeight_ = 0;\n /**\n * @private\n * @type {number}\n */\n\n _this.imageOpacity_ = 0;\n /**\n * @private\n * @type {number}\n */\n\n _this.imageOriginX_ = 0;\n /**\n * @private\n * @type {number}\n */\n\n _this.imageOriginY_ = 0;\n /**\n * @private\n * @type {boolean}\n */\n\n _this.imageRotateWithView_ = false;\n /**\n * @private\n * @type {number}\n */\n\n _this.imageRotation_ = 0;\n /**\n * @private\n * @type {import("../../size.js").Size}\n */\n\n _this.imageScale_ = [0, 0];\n /**\n * @private\n * @type {number}\n */\n\n _this.imageWidth_ = 0;\n /**\n * @private\n * @type {string}\n */\n\n _this.text_ = \'\';\n /**\n * @private\n * @type {number}\n */\n\n _this.textOffsetX_ = 0;\n /**\n * @private\n * @type {number}\n */\n\n _this.textOffsetY_ = 0;\n /**\n * @private\n * @type {boolean}\n */\n\n _this.textRotateWithView_ = false;\n /**\n * @private\n * @type {number}\n */\n\n _this.textRotation_ = 0;\n /**\n * @private\n * @type {import("../../size.js").Size}\n */\n\n _this.textScale_ = [0, 0];\n /**\n * @private\n * @type {?import("../canvas.js").FillState}\n */\n\n _this.textFillState_ = null;\n /**\n * @private\n * @type {?import("../canvas.js").StrokeState}\n */\n\n _this.textStrokeState_ = null;\n /**\n * @private\n * @type {?import("../canvas.js").TextState}\n */\n\n _this.textState_ = null;\n /**\n * @private\n * @type {Array<number>}\n */\n\n _this.pixelCoordinates_ = [];\n /**\n * @private\n * @type {import("../../transform.js").Transform}\n */\n\n _this.tmpLocalTransform_ = create();\n return _this;\n }\n /**\n * @param {Array<number>} flatCoordinates Flat coordinates.\n * @param {number} offset Offset.\n * @param {number} end End.\n * @param {number} stride Stride.\n * @private\n */\n\n\n CanvasImmediateRenderer.prototype.drawImages_ = function (flatCoordinates, offset, end, stride) {\n if (!this.image_) {\n return;\n }\n\n var pixelCoordinates = transform2D(flatCoordinates, offset, end, 2, this.transform_, this.pixelCoordinates_);\n var context = this.context_;\n var localTransform = this.tmpLocalTransform_;\n var alpha = context.globalAlpha;\n\n if (this.imageOpacity_ != 1) {\n context.globalAlpha = alpha * this.imageOpacity_;\n }\n\n var rotation = this.imageRotation_;\n\n if (this.imageRotateWithView_) {\n rotation += this.viewRotation_;\n }\n\n for (var i = 0, ii = pixelCoordinates.length; i < ii; i += 2) {\n var x = pixelCoordinates[i] - this.imageAnchorX_;\n var y = pixelCoordinates[i + 1] - this.imageAnchorY_;\n\n if (rotation !== 0 || this.imageScale_[0] != 1 || this.imageScale_[1] != 1) {\n var centerX = x + this.imageAnchorX_;\n var centerY = y + this.imageAnchorY_;\n compose(localTransform, centerX, centerY, 1, 1, rotation, -centerX, -centerY);\n context.setTransform.apply(context, localTransform);\n context.translate(centerX, centerY);\n context.scale(this.imageScale_[0], this.imageScale_[1]);\n context.drawImage(this.image_, this.imageOriginX_, this.imageOriginY_, this.imageWidth_, this.imageHeight_, -this.imageAnchorX_, -this.imageAnchorY_, this.imageWidth_, this.imageHeight_);\n context.setTransform(1, 0, 0, 1, 0, 0);\n } else {\n context.drawImage(this.image_, this.imageOriginX_, this.imageOriginY_, this.imageWidth_, this.imageHeight_, x, y, this.imageWidth_, this.imageHeight_);\n }\n }\n\n if (this.imageOpacity_ != 1) {\n context.globalAlpha = alpha;\n }\n };\n /**\n * @param {Array<number>} flatCoordinates Flat coordinates.\n * @param {number} offset Offset.\n * @param {number} end End.\n * @param {number} stride Stride.\n * @private\n */\n\n\n CanvasImmediateRenderer.prototype.drawText_ = function (flatCoordinates, offset, end, stride) {\n if (!this.textState_ || this.text_ === \'\') {\n return;\n }\n\n if (this.textFillState_) {\n this.setContextFillState_(this.textFillState_);\n }\n\n if (this.textStrokeState_) {\n this.setContextStrokeState_(this.textStrokeState_);\n }\n\n this.setContextTextState_(this.textState_);\n var pixelCoordinates = transform2D(flatCoordinates, offset, end, stride, this.transform_, this.pixelCoordinates_);\n var context = this.context_;\n var rotation = this.textRotation_;\n\n if (this.textRotateWithView_) {\n rotation += this.viewRotation_;\n }\n\n for (; offset < end; offset += stride) {\n var x = pixelCoordinates[offset] + this.textOffsetX_;\n var y = pixelCoordinates[offset + 1] + this.textOffsetY_;\n\n if (rotation !== 0 || this.textScale_[0] != 1 || this.textScale_[1] != 1) {\n var localTransform = compose(this.tmpLocalTransform_, x, y, 1, 1, rotation, -x, -y);\n context.setTransform.apply(context, localTransform);\n context.translate(x, y);\n context.scale(this.textScale_[0], this.textScale_[1]);\n\n if (this.textStrokeState_) {\n context.strokeText(this.text_, 0, 0);\n }\n\n if (this.textFillState_) {\n context.fillText(this.text_, 0, 0);\n }\n\n context.setTransform(1, 0, 0, 1, 0, 0);\n } else {\n if (this.textStrokeState_) {\n context.strokeText(this.text_, x, y);\n }\n\n if (this.textFillState_) {\n context.fillText(this.text_, x, y);\n }\n }\n }\n };\n /**\n * @param {Array<number>} flatCoordinates Flat coordinates.\n * @param {number} offset Offset.\n * @param {number} end End.\n * @param {number} stride Stride.\n * @param {boolean} close Close.\n * @private\n * @return {number} end End.\n */\n\n\n CanvasImmediateRenderer.prototype.moveToLineTo_ = function (flatCoordinates, offset, end, stride, close) {\n var context = this.context_;\n var pixelCoordinates = transform2D(flatCoordinates, offset, end, stride, this.transform_, this.pixelCoordinates_);\n context.moveTo(pixelCoordinates[0], pixelCoordinates[1]);\n var length = pixelCoordinates.length;\n\n if (close) {\n length -= 2;\n }\n\n for (var i = 2; i < length; i += 2) {\n context.lineTo(pixelCoordinates[i], pixelCoordinates[i + 1]);\n }\n\n if (close) {\n context.closePath();\n }\n\n return end;\n };\n /**\n * @param {Array<number>} flatCoordinates Flat coordinates.\n * @param {number} offset Offset.\n * @param {Array<number>} ends Ends.\n * @param {number} stride Stride.\n * @private\n * @return {number} End.\n */\n\n\n CanvasImmediateRenderer.prototype.drawRings_ = function (flatCoordinates, offset, ends, stride) {\n for (var i = 0, ii = ends.length; i < ii; ++i) {\n offset = this.moveToLineTo_(flatCoordinates, offset, ends[i], stride, true);\n }\n\n return offset;\n };\n /**\n * Render a circle geometry into the canvas. Rendering is immediate and uses\n * the current fill and stroke styles.\n *\n * @param {import("../../geom/Circle.js").default} geometry Circle geometry.\n * @api\n */\n\n\n CanvasImmediateRenderer.prototype.drawCircle = function (geometry) {\n if (!intersects(this.extent_, geometry.getExtent())) {\n return;\n }\n\n if (this.fillState_ || this.strokeState_) {\n if (this.fillState_) {\n this.setContextFillState_(this.fillState_);\n }\n\n if (this.strokeState_) {\n this.setContextStrokeState_(this.strokeState_);\n }\n\n var pixelCoordinates = transformGeom2D(geometry, this.transform_, this.pixelCoordinates_);\n var dx = pixelCoordinates[2] - pixelCoordinates[0];\n var dy = pixelCoordinates[3] - pixelCoordinates[1];\n var radius = Math.sqrt(dx * dx + dy * dy);\n var context = this.context_;\n context.beginPath();\n context.arc(pixelCoordinates[0], pixelCoordinates[1], radius, 0, 2 * Math.PI);\n\n if (this.fillState_) {\n context.fill();\n }\n\n if (this.strokeState_) {\n context.stroke();\n }\n }\n\n if (this.text_ !== \'\') {\n this.drawText_(geometry.getCenter(), 0, 2, 2);\n }\n };\n /**\n * Set the rendering style. Note that since this is an immediate rendering API,\n * any `zIndex` on the provided style will be ignored.\n *\n * @param {import("../../style/Style.js").default} style The rendering style.\n * @api\n */\n\n\n CanvasImmediateRenderer.prototype.setStyle = function (style) {\n this.setFillStrokeStyle(style.getFill(), style.getStroke());\n this.setImageStyle(style.getImage());\n this.setTextStyle(style.getText());\n };\n /**\n * @param {import("../../transform.js").Transform} transform Transform.\n */\n\n\n CanvasImmediateRenderer.prototype.setTransform = function (transform) {\n this.transform_ = transform;\n };\n /**\n * Render a geometry into the canvas. Call\n * {@link module:ol/render/canvas/Immediate#setStyle} first to set the rendering style.\n *\n * @param {import("../../geom/Geometry.js").default|import("../Feature.js").default} geometry The geometry to render.\n * @api\n */\n\n\n CanvasImmediateRenderer.prototype.drawGeometry = function (geometry) {\n var type = geometry.getType();\n\n switch (type) {\n case geom_GeometryType.POINT:\n this.drawPoint(\n /** @type {import("../../geom/Point.js").default} */\n geometry);\n break;\n\n case geom_GeometryType.LINE_STRING:\n this.drawLineString(\n /** @type {import("../../geom/LineString.js").default} */\n geometry);\n break;\n\n case geom_GeometryType.POLYGON:\n this.drawPolygon(\n /** @type {import("../../geom/Polygon.js").default} */\n geometry);\n break;\n\n case geom_GeometryType.MULTI_POINT:\n this.drawMultiPoint(\n /** @type {import("../../geom/MultiPoint.js").default} */\n geometry);\n break;\n\n case geom_GeometryType.MULTI_LINE_STRING:\n this.drawMultiLineString(\n /** @type {import("../../geom/MultiLineString.js").default} */\n geometry);\n break;\n\n case geom_GeometryType.MULTI_POLYGON:\n this.drawMultiPolygon(\n /** @type {import("../../geom/MultiPolygon.js").default} */\n geometry);\n break;\n\n case geom_GeometryType.GEOMETRY_COLLECTION:\n this.drawGeometryCollection(\n /** @type {import("../../geom/GeometryCollection.js").default} */\n geometry);\n break;\n\n case geom_GeometryType.CIRCLE:\n this.drawCircle(\n /** @type {import("../../geom/Circle.js").default} */\n geometry);\n break;\n\n default:\n }\n };\n /**\n * Render a feature into the canvas. Note that any `zIndex` on the provided\n * style will be ignored - features are rendered immediately in the order that\n * this method is called. If you need `zIndex` support, you should be using an\n * {@link module:ol/layer/Vector~VectorLayer} instead.\n *\n * @param {import("../../Feature.js").default} feature Feature.\n * @param {import("../../style/Style.js").default} style Style.\n * @api\n */\n\n\n CanvasImmediateRenderer.prototype.drawFeature = function (feature, style) {\n var geometry = style.getGeometryFunction()(feature);\n\n if (!geometry || !intersects(this.extent_, geometry.getExtent())) {\n return;\n }\n\n this.setStyle(style);\n this.drawGeometry(geometry);\n };\n /**\n * Render a GeometryCollection to the canvas. Rendering is immediate and\n * uses the current styles appropriate for each geometry in the collection.\n *\n * @param {import("../../geom/GeometryCollection.js").default} geometry Geometry collection.\n */\n\n\n CanvasImmediateRenderer.prototype.drawGeometryCollection = function (geometry) {\n var geometries = geometry.getGeometriesArray();\n\n for (var i = 0, ii = geometries.length; i < ii; ++i) {\n this.drawGeometry(geometries[i]);\n }\n };\n /**\n * Render a Point geometry into the canvas. Rendering is immediate and uses\n * the current style.\n *\n * @param {import("../../geom/Point.js").default|import("../Feature.js").default} geometry Point geometry.\n */\n\n\n CanvasImmediateRenderer.prototype.drawPoint = function (geometry) {\n if (this.squaredTolerance_) {\n geometry =\n /** @type {import("../../geom/Point.js").default} */\n geometry.simplifyTransformed(this.squaredTolerance_, this.userTransform_);\n }\n\n var flatCoordinates = geometry.getFlatCoordinates();\n var stride = geometry.getStride();\n\n if (this.image_) {\n this.drawImages_(flatCoordinates, 0, flatCoordinates.length, stride);\n }\n\n if (this.text_ !== \'\') {\n this.drawText_(flatCoordinates, 0, flatCoordinates.length, stride);\n }\n };\n /**\n * Render a MultiPoint geometry into the canvas. Rendering is immediate and\n * uses the current style.\n *\n * @param {import("../../geom/MultiPoint.js").default|import("../Feature.js").default} geometry MultiPoint geometry.\n */\n\n\n CanvasImmediateRenderer.prototype.drawMultiPoint = function (geometry) {\n if (this.squaredTolerance_) {\n geometry =\n /** @type {import("../../geom/MultiPoint.js").default} */\n geometry.simplifyTransformed(this.squaredTolerance_, this.userTransform_);\n }\n\n var flatCoordinates = geometry.getFlatCoordinates();\n var stride = geometry.getStride();\n\n if (this.image_) {\n this.drawImages_(flatCoordinates, 0, flatCoordinates.length, stride);\n }\n\n if (this.text_ !== \'\') {\n this.drawText_(flatCoordinates, 0, flatCoordinates.length, stride);\n }\n };\n /**\n * Render a LineString into the canvas. Rendering is immediate and uses\n * the current style.\n *\n * @param {import("../../geom/LineString.js").default|import("../Feature.js").default} geometry LineString geometry.\n */\n\n\n CanvasImmediateRenderer.prototype.drawLineString = function (geometry) {\n if (this.squaredTolerance_) {\n geometry =\n /** @type {import("../../geom/LineString.js").default} */\n geometry.simplifyTransformed(this.squaredTolerance_, this.userTransform_);\n }\n\n if (!intersects(this.extent_, geometry.getExtent())) {\n return;\n }\n\n if (this.strokeState_) {\n this.setContextStrokeState_(this.strokeState_);\n var context = this.context_;\n var flatCoordinates = geometry.getFlatCoordinates();\n context.beginPath();\n this.moveToLineTo_(flatCoordinates, 0, flatCoordinates.length, geometry.getStride(), false);\n context.stroke();\n }\n\n if (this.text_ !== \'\') {\n var flatMidpoint = geometry.getFlatMidpoint();\n this.drawText_(flatMidpoint, 0, 2, 2);\n }\n };\n /**\n * Render a MultiLineString geometry into the canvas. Rendering is immediate\n * and uses the current style.\n *\n * @param {import("../../geom/MultiLineString.js").default|import("../Feature.js").default} geometry MultiLineString geometry.\n */\n\n\n CanvasImmediateRenderer.prototype.drawMultiLineString = function (geometry) {\n if (this.squaredTolerance_) {\n geometry =\n /** @type {import("../../geom/MultiLineString.js").default} */\n geometry.simplifyTransformed(this.squaredTolerance_, this.userTransform_);\n }\n\n var geometryExtent = geometry.getExtent();\n\n if (!intersects(this.extent_, geometryExtent)) {\n return;\n }\n\n if (this.strokeState_) {\n this.setContextStrokeState_(this.strokeState_);\n var context = this.context_;\n var flatCoordinates = geometry.getFlatCoordinates();\n var offset = 0;\n var ends =\n /** @type {Array<number>} */\n geometry.getEnds();\n var stride = geometry.getStride();\n context.beginPath();\n\n for (var i = 0, ii = ends.length; i < ii; ++i) {\n offset = this.moveToLineTo_(flatCoordinates, offset, ends[i], stride, false);\n }\n\n context.stroke();\n }\n\n if (this.text_ !== \'\') {\n var flatMidpoints = geometry.getFlatMidpoints();\n this.drawText_(flatMidpoints, 0, flatMidpoints.length, 2);\n }\n };\n /**\n * Render a Polygon geometry into the canvas. Rendering is immediate and uses\n * the current style.\n *\n * @param {import("../../geom/Polygon.js").default|import("../Feature.js").default} geometry Polygon geometry.\n */\n\n\n CanvasImmediateRenderer.prototype.drawPolygon = function (geometry) {\n if (this.squaredTolerance_) {\n geometry =\n /** @type {import("../../geom/Polygon.js").default} */\n geometry.simplifyTransformed(this.squaredTolerance_, this.userTransform_);\n }\n\n if (!intersects(this.extent_, geometry.getExtent())) {\n return;\n }\n\n if (this.strokeState_ || this.fillState_) {\n if (this.fillState_) {\n this.setContextFillState_(this.fillState_);\n }\n\n if (this.strokeState_) {\n this.setContextStrokeState_(this.strokeState_);\n }\n\n var context = this.context_;\n context.beginPath();\n this.drawRings_(geometry.getOrientedFlatCoordinates(), 0,\n /** @type {Array<number>} */\n geometry.getEnds(), geometry.getStride());\n\n if (this.fillState_) {\n context.fill();\n }\n\n if (this.strokeState_) {\n context.stroke();\n }\n }\n\n if (this.text_ !== \'\') {\n var flatInteriorPoint = geometry.getFlatInteriorPoint();\n this.drawText_(flatInteriorPoint, 0, 2, 2);\n }\n };\n /**\n * Render MultiPolygon geometry into the canvas. Rendering is immediate and\n * uses the current style.\n * @param {import("../../geom/MultiPolygon.js").default} geometry MultiPolygon geometry.\n */\n\n\n CanvasImmediateRenderer.prototype.drawMultiPolygon = function (geometry) {\n if (this.squaredTolerance_) {\n geometry =\n /** @type {import("../../geom/MultiPolygon.js").default} */\n geometry.simplifyTransformed(this.squaredTolerance_, this.userTransform_);\n }\n\n if (!intersects(this.extent_, geometry.getExtent())) {\n return;\n }\n\n if (this.strokeState_ || this.fillState_) {\n if (this.fillState_) {\n this.setContextFillState_(this.fillState_);\n }\n\n if (this.strokeState_) {\n this.setContextStrokeState_(this.strokeState_);\n }\n\n var context = this.context_;\n var flatCoordinates = geometry.getOrientedFlatCoordinates();\n var offset = 0;\n var endss = geometry.getEndss();\n var stride = geometry.getStride();\n context.beginPath();\n\n for (var i = 0, ii = endss.length; i < ii; ++i) {\n var ends = endss[i];\n offset = this.drawRings_(flatCoordinates, offset, ends, stride);\n }\n\n if (this.fillState_) {\n context.fill();\n }\n\n if (this.strokeState_) {\n context.stroke();\n }\n }\n\n if (this.text_ !== \'\') {\n var flatInteriorPoints = geometry.getFlatInteriorPoints();\n this.drawText_(flatInteriorPoints, 0, flatInteriorPoints.length, 2);\n }\n };\n /**\n * @param {import("../canvas.js").FillState} fillState Fill state.\n * @private\n */\n\n\n CanvasImmediateRenderer.prototype.setContextFillState_ = function (fillState) {\n var context = this.context_;\n var contextFillState = this.contextFillState_;\n\n if (!contextFillState) {\n context.fillStyle = fillState.fillStyle;\n this.contextFillState_ = {\n fillStyle: fillState.fillStyle\n };\n } else {\n if (contextFillState.fillStyle != fillState.fillStyle) {\n contextFillState.fillStyle = fillState.fillStyle;\n context.fillStyle = fillState.fillStyle;\n }\n }\n };\n /**\n * @param {import("../canvas.js").StrokeState} strokeState Stroke state.\n * @private\n */\n\n\n CanvasImmediateRenderer.prototype.setContextStrokeState_ = function (strokeState) {\n var context = this.context_;\n var contextStrokeState = this.contextStrokeState_;\n\n if (!contextStrokeState) {\n context.lineCap = strokeState.lineCap;\n\n if (context.setLineDash) {\n context.setLineDash(strokeState.lineDash);\n context.lineDashOffset = strokeState.lineDashOffset;\n }\n\n context.lineJoin = strokeState.lineJoin;\n context.lineWidth = strokeState.lineWidth;\n context.miterLimit = strokeState.miterLimit;\n context.strokeStyle = strokeState.strokeStyle;\n this.contextStrokeState_ = {\n lineCap: strokeState.lineCap,\n lineDash: strokeState.lineDash,\n lineDashOffset: strokeState.lineDashOffset,\n lineJoin: strokeState.lineJoin,\n lineWidth: strokeState.lineWidth,\n miterLimit: strokeState.miterLimit,\n strokeStyle: strokeState.strokeStyle\n };\n } else {\n if (contextStrokeState.lineCap != strokeState.lineCap) {\n contextStrokeState.lineCap = strokeState.lineCap;\n context.lineCap = strokeState.lineCap;\n }\n\n if (context.setLineDash) {\n if (!equals(contextStrokeState.lineDash, strokeState.lineDash)) {\n context.setLineDash(contextStrokeState.lineDash = strokeState.lineDash);\n }\n\n if (contextStrokeState.lineDashOffset != strokeState.lineDashOffset) {\n contextStrokeState.lineDashOffset = strokeState.lineDashOffset;\n context.lineDashOffset = strokeState.lineDashOffset;\n }\n }\n\n if (contextStrokeState.lineJoin != strokeState.lineJoin) {\n contextStrokeState.lineJoin = strokeState.lineJoin;\n context.lineJoin = strokeState.lineJoin;\n }\n\n if (contextStrokeState.lineWidth != strokeState.lineWidth) {\n contextStrokeState.lineWidth = strokeState.lineWidth;\n context.lineWidth = strokeState.lineWidth;\n }\n\n if (contextStrokeState.miterLimit != strokeState.miterLimit) {\n contextStrokeState.miterLimit = strokeState.miterLimit;\n context.miterLimit = strokeState.miterLimit;\n }\n\n if (contextStrokeState.strokeStyle != strokeState.strokeStyle) {\n contextStrokeState.strokeStyle = strokeState.strokeStyle;\n context.strokeStyle = strokeState.strokeStyle;\n }\n }\n };\n /**\n * @param {import("../canvas.js").TextState} textState Text state.\n * @private\n */\n\n\n CanvasImmediateRenderer.prototype.setContextTextState_ = function (textState) {\n var context = this.context_;\n var contextTextState = this.contextTextState_;\n var textAlign = textState.textAlign ? textState.textAlign : defaultTextAlign;\n\n if (!contextTextState) {\n context.font = textState.font;\n context.textAlign =\n /** @type {CanvasTextAlign} */\n textAlign;\n context.textBaseline =\n /** @type {CanvasTextBaseline} */\n textState.textBaseline;\n this.contextTextState_ = {\n font: textState.font,\n textAlign: textAlign,\n textBaseline: textState.textBaseline\n };\n } else {\n if (contextTextState.font != textState.font) {\n contextTextState.font = textState.font;\n context.font = textState.font;\n }\n\n if (contextTextState.textAlign != textAlign) {\n contextTextState.textAlign =\n /** @type {CanvasTextAlign} */\n textAlign;\n context.textAlign =\n /** @type {CanvasTextAlign} */\n textAlign;\n }\n\n if (contextTextState.textBaseline != textState.textBaseline) {\n contextTextState.textBaseline =\n /** @type {CanvasTextBaseline} */\n textState.textBaseline;\n context.textBaseline =\n /** @type {CanvasTextBaseline} */\n textState.textBaseline;\n }\n }\n };\n /**\n * Set the fill and stroke style for subsequent draw operations. To clear\n * either fill or stroke styles, pass null for the appropriate parameter.\n *\n * @param {import("../../style/Fill.js").default} fillStyle Fill style.\n * @param {import("../../style/Stroke.js").default} strokeStyle Stroke style.\n */\n\n\n CanvasImmediateRenderer.prototype.setFillStrokeStyle = function (fillStyle, strokeStyle) {\n if (!fillStyle) {\n this.fillState_ = null;\n } else {\n var fillStyleColor = fillStyle.getColor();\n this.fillState_ = {\n fillStyle: asColorLike(fillStyleColor ? fillStyleColor : defaultFillStyle)\n };\n }\n\n if (!strokeStyle) {\n this.strokeState_ = null;\n } else {\n var strokeStyleColor = strokeStyle.getColor();\n var strokeStyleLineCap = strokeStyle.getLineCap();\n var strokeStyleLineDash = strokeStyle.getLineDash();\n var strokeStyleLineDashOffset = strokeStyle.getLineDashOffset();\n var strokeStyleLineJoin = strokeStyle.getLineJoin();\n var strokeStyleWidth = strokeStyle.getWidth();\n var strokeStyleMiterLimit = strokeStyle.getMiterLimit();\n this.strokeState_ = {\n lineCap: strokeStyleLineCap !== undefined ? strokeStyleLineCap : defaultLineCap,\n lineDash: strokeStyleLineDash ? strokeStyleLineDash : defaultLineDash,\n lineDashOffset: strokeStyleLineDashOffset ? strokeStyleLineDashOffset : defaultLineDashOffset,\n lineJoin: strokeStyleLineJoin !== undefined ? strokeStyleLineJoin : defaultLineJoin,\n lineWidth: this.pixelRatio_ * (strokeStyleWidth !== undefined ? strokeStyleWidth : defaultLineWidth),\n miterLimit: strokeStyleMiterLimit !== undefined ? strokeStyleMiterLimit : defaultMiterLimit,\n strokeStyle: asColorLike(strokeStyleColor ? strokeStyleColor : defaultStrokeStyle)\n };\n }\n };\n /**\n * Set the image style for subsequent draw operations. Pass null to remove\n * the image style.\n *\n * @param {import("../../style/Image.js").default} imageStyle Image style.\n */\n\n\n CanvasImmediateRenderer.prototype.setImageStyle = function (imageStyle) {\n if (!imageStyle) {\n this.image_ = null;\n } else {\n var imageSize = imageStyle.getSize();\n\n if (!imageSize) {\n this.image_ = null;\n } else {\n var imageAnchor = imageStyle.getAnchor(); // FIXME pixel ratio\n\n var imageImage = imageStyle.getImage(1);\n var imageOrigin = imageStyle.getOrigin();\n var imageScale = imageStyle.getScaleArray();\n this.imageAnchorX_ = imageAnchor[0];\n this.imageAnchorY_ = imageAnchor[1];\n this.imageHeight_ = imageSize[1];\n this.image_ = imageImage;\n this.imageOpacity_ = imageStyle.getOpacity();\n this.imageOriginX_ = imageOrigin[0];\n this.imageOriginY_ = imageOrigin[1];\n this.imageRotateWithView_ = imageStyle.getRotateWithView();\n this.imageRotation_ = imageStyle.getRotation();\n this.imageScale_ = [this.pixelRatio_ * imageScale[0], this.pixelRatio_ * imageScale[1]];\n this.imageWidth_ = imageSize[0];\n }\n }\n };\n /**\n * Set the text style for subsequent draw operations. Pass null to\n * remove the text style.\n *\n * @param {import("../../style/Text.js").default} textStyle Text style.\n */\n\n\n CanvasImmediateRenderer.prototype.setTextStyle = function (textStyle) {\n if (!textStyle) {\n this.text_ = \'\';\n } else {\n var textFillStyle = textStyle.getFill();\n\n if (!textFillStyle) {\n this.textFillState_ = null;\n } else {\n var textFillStyleColor = textFillStyle.getColor();\n this.textFillState_ = {\n fillStyle: asColorLike(textFillStyleColor ? textFillStyleColor : defaultFillStyle)\n };\n }\n\n var textStrokeStyle = textStyle.getStroke();\n\n if (!textStrokeStyle) {\n this.textStrokeState_ = null;\n } else {\n var textStrokeStyleColor = textStrokeStyle.getColor();\n var textStrokeStyleLineCap = textStrokeStyle.getLineCap();\n var textStrokeStyleLineDash = textStrokeStyle.getLineDash();\n var textStrokeStyleLineDashOffset = textStrokeStyle.getLineDashOffset();\n var textStrokeStyleLineJoin = textStrokeStyle.getLineJoin();\n var textStrokeStyleWidth = textStrokeStyle.getWidth();\n var textStrokeStyleMiterLimit = textStrokeStyle.getMiterLimit();\n this.textStrokeState_ = {\n lineCap: textStrokeStyleLineCap !== undefined ? textStrokeStyleLineCap : defaultLineCap,\n lineDash: textStrokeStyleLineDash ? textStrokeStyleLineDash : defaultLineDash,\n lineDashOffset: textStrokeStyleLineDashOffset ? textStrokeStyleLineDashOffset : defaultLineDashOffset,\n lineJoin: textStrokeStyleLineJoin !== undefined ? textStrokeStyleLineJoin : defaultLineJoin,\n lineWidth: textStrokeStyleWidth !== undefined ? textStrokeStyleWidth : defaultLineWidth,\n miterLimit: textStrokeStyleMiterLimit !== undefined ? textStrokeStyleMiterLimit : defaultMiterLimit,\n strokeStyle: asColorLike(textStrokeStyleColor ? textStrokeStyleColor : defaultStrokeStyle)\n };\n }\n\n var textFont = textStyle.getFont();\n var textOffsetX = textStyle.getOffsetX();\n var textOffsetY = textStyle.getOffsetY();\n var textRotateWithView = textStyle.getRotateWithView();\n var textRotation = textStyle.getRotation();\n var textScale = textStyle.getScaleArray();\n var textText = textStyle.getText();\n var textTextAlign = textStyle.getTextAlign();\n var textTextBaseline = textStyle.getTextBaseline();\n this.textState_ = {\n font: textFont !== undefined ? textFont : defaultFont,\n textAlign: textTextAlign !== undefined ? textTextAlign : defaultTextAlign,\n textBaseline: textTextBaseline !== undefined ? textTextBaseline : defaultTextBaseline\n };\n this.text_ = textText !== undefined ? textText : \'\';\n this.textOffsetX_ = textOffsetX !== undefined ? this.pixelRatio_ * textOffsetX : 0;\n this.textOffsetY_ = textOffsetY !== undefined ? this.pixelRatio_ * textOffsetY : 0;\n this.textRotateWithView_ = textRotateWithView !== undefined ? textRotateWithView : false;\n this.textRotation_ = textRotation !== undefined ? textRotation : 0;\n this.textScale_ = [this.pixelRatio_ * textScale[0], this.pixelRatio_ * textScale[1]];\n }\n };\n\n return CanvasImmediateRenderer;\n}(render_VectorContext);\n\n/* harmony default export */ var Immediate = (CanvasImmediateRenderer);\n;// CONCATENATED MODULE: ./node_modules/ol/style/IconAnchorUnits.js\n/**\n * @module ol/style/IconAnchorUnits\n */\n\n/**\n * Icon anchor units. One of \'fraction\', \'pixels\'.\n * @enum {string}\n */\n/* harmony default export */ var IconAnchorUnits = ({\n /**\n * Anchor is a fraction\n * @api\n */\n FRACTION: \'fraction\',\n\n /**\n * Anchor is in pixels\n * @api\n */\n PIXELS: \'pixels\'\n});\n;// CONCATENATED MODULE: ./node_modules/ol/style/IconOrigin.js\n/**\n * @module ol/style/IconOrigin\n */\n\n/**\n * Icon origin. One of \'bottom-left\', \'bottom-right\', \'top-left\', \'top-right\'.\n * @enum {string}\n */\n/* harmony default export */ var IconOrigin = ({\n /**\n * Origin is at bottom left\n * @api\n */\n BOTTOM_LEFT: \'bottom-left\',\n\n /**\n * Origin is at bottom right\n * @api\n */\n BOTTOM_RIGHT: \'bottom-right\',\n\n /**\n * Origin is at top left\n * @api\n */\n TOP_LEFT: \'top-left\',\n\n /**\n * Origin is at top right\n * @api\n */\n TOP_RIGHT: \'top-right\'\n});\n;// CONCATENATED MODULE: ./node_modules/ol/ImageBase.js\nvar ImageBase_extends = undefined && undefined.__extends || function () {\n var _extendStatics = function extendStatics(d, b) {\n _extendStatics = Object.setPrototypeOf || {\n __proto__: []\n } instanceof Array && function (d, b) {\n d.__proto__ = b;\n } || function (d, b) {\n for (var p in b) {\n if (Object.prototype.hasOwnProperty.call(b, p)) d[p] = b[p];\n }\n };\n\n return _extendStatics(d, b);\n };\n\n return function (d, b) {\n _extendStatics(d, b);\n\n function __() {\n this.constructor = d;\n }\n\n d.prototype = b === null ? Object.create(b) : (__.prototype = b.prototype, new __());\n };\n}();\n/**\n * @module ol/ImageBase\n */\n\n\n\n\n\n/**\n * @abstract\n */\n\nvar ImageBase =\n/** @class */\nfunction (_super) {\n ImageBase_extends(ImageBase, _super);\n /**\n * @param {import("./extent.js").Extent} extent Extent.\n * @param {number|undefined} resolution Resolution.\n * @param {number} pixelRatio Pixel ratio.\n * @param {import("./ImageState.js").default} state State.\n */\n\n\n function ImageBase(extent, resolution, pixelRatio, state) {\n var _this = _super.call(this) || this;\n /**\n * @protected\n * @type {import("./extent.js").Extent}\n */\n\n\n _this.extent = extent;\n /**\n * @private\n * @type {number}\n */\n\n _this.pixelRatio_ = pixelRatio;\n /**\n * @protected\n * @type {number|undefined}\n */\n\n _this.resolution = resolution;\n /**\n * @protected\n * @type {import("./ImageState.js").default}\n */\n\n _this.state = state;\n return _this;\n }\n /**\n * @protected\n */\n\n\n ImageBase.prototype.changed = function () {\n this.dispatchEvent(EventType.CHANGE);\n };\n /**\n * @return {import("./extent.js").Extent} Extent.\n */\n\n\n ImageBase.prototype.getExtent = function () {\n return this.extent;\n };\n /**\n * @abstract\n * @return {HTMLCanvasElement|HTMLImageElement|HTMLVideoElement} Image.\n */\n\n\n ImageBase.prototype.getImage = function () {\n return util_abstract();\n };\n /**\n * @return {number} PixelRatio.\n */\n\n\n ImageBase.prototype.getPixelRatio = function () {\n return this.pixelRatio_;\n };\n /**\n * @return {number} Resolution.\n */\n\n\n ImageBase.prototype.getResolution = function () {\n return (\n /** @type {number} */\n this.resolution\n );\n };\n /**\n * @return {import("./ImageState.js").default} State.\n */\n\n\n ImageBase.prototype.getState = function () {\n return this.state;\n };\n /**\n * Load not yet loaded URI.\n * @abstract\n */\n\n\n ImageBase.prototype.load = function () {\n util_abstract();\n };\n\n return ImageBase;\n}(events_Target);\n\n/* harmony default export */ var ol_ImageBase = (ImageBase);\n;// CONCATENATED MODULE: ./node_modules/ol/Image.js\nvar Image_extends = undefined && undefined.__extends || function () {\n var _extendStatics = function extendStatics(d, b) {\n _extendStatics = Object.setPrototypeOf || {\n __proto__: []\n } instanceof Array && function (d, b) {\n d.__proto__ = b;\n } || function (d, b) {\n for (var p in b) {\n if (Object.prototype.hasOwnProperty.call(b, p)) d[p] = b[p];\n }\n };\n\n return _extendStatics(d, b);\n };\n\n return function (d, b) {\n _extendStatics(d, b);\n\n function __() {\n this.constructor = d;\n }\n\n d.prototype = b === null ? Object.create(b) : (__.prototype = b.prototype, new __());\n };\n}();\n/**\n * @module ol/Image\n */\n\n\n\n\n\n\n\n\n/**\n * A function that takes an {@link module:ol/Image~Image} for the image and a\n * `{string}` for the src as arguments. It is supposed to make it so the\n * underlying image {@link module:ol/Image~Image#getImage} is assigned the\n * content specified by the src. If not specified, the default is\n *\n * function(image, src) {\n * image.getImage().src = src;\n * }\n *\n * Providing a custom `imageLoadFunction` can be useful to load images with\n * post requests or - in general - through XHR requests, where the src of the\n * image element would be set to a data URI when the content is loaded.\n *\n * @typedef {function(ImageWrapper, string): void} LoadFunction\n * @api\n */\n\nvar ImageWrapper =\n/** @class */\nfunction (_super) {\n Image_extends(ImageWrapper, _super);\n /**\n * @param {import("./extent.js").Extent} extent Extent.\n * @param {number|undefined} resolution Resolution.\n * @param {number} pixelRatio Pixel ratio.\n * @param {string} src Image source URI.\n * @param {?string} crossOrigin Cross origin.\n * @param {LoadFunction} imageLoadFunction Image load function.\n */\n\n\n function ImageWrapper(extent, resolution, pixelRatio, src, crossOrigin, imageLoadFunction) {\n var _this = _super.call(this, extent, resolution, pixelRatio, ImageState.IDLE) || this;\n /**\n * @private\n * @type {string}\n */\n\n\n _this.src_ = src;\n /**\n * @private\n * @type {HTMLCanvasElement|HTMLImageElement|HTMLVideoElement}\n */\n\n _this.image_ = new Image();\n\n if (crossOrigin !== null) {\n _this.image_.crossOrigin = crossOrigin;\n }\n /**\n * @private\n * @type {?function():void}\n */\n\n\n _this.unlisten_ = null;\n /**\n * @protected\n * @type {import("./ImageState.js").default}\n */\n\n _this.state = ImageState.IDLE;\n /**\n * @private\n * @type {LoadFunction}\n */\n\n _this.imageLoadFunction_ = imageLoadFunction;\n return _this;\n }\n /**\n * @return {HTMLCanvasElement|HTMLImageElement|HTMLVideoElement} Image.\n * @api\n */\n\n\n ImageWrapper.prototype.getImage = function () {\n return this.image_;\n };\n /**\n * Tracks loading or read errors.\n *\n * @private\n */\n\n\n ImageWrapper.prototype.handleImageError_ = function () {\n this.state = ImageState.ERROR;\n this.unlistenImage_();\n this.changed();\n };\n /**\n * Tracks successful image load.\n *\n * @private\n */\n\n\n ImageWrapper.prototype.handleImageLoad_ = function () {\n if (this.resolution === undefined) {\n this.resolution = getHeight(this.extent) / this.image_.height;\n }\n\n this.state = ImageState.LOADED;\n this.unlistenImage_();\n this.changed();\n };\n /**\n * Load the image or retry if loading previously failed.\n * Loading is taken care of by the tile queue, and calling this method is\n * only needed for preloading or for reloading in case of an error.\n * @api\n */\n\n\n ImageWrapper.prototype.load = function () {\n if (this.state == ImageState.IDLE || this.state == ImageState.ERROR) {\n this.state = ImageState.LOADING;\n this.changed();\n this.imageLoadFunction_(this, this.src_);\n this.unlisten_ = listenImage(this.image_, this.handleImageLoad_.bind(this), this.handleImageError_.bind(this));\n }\n };\n /**\n * @param {HTMLCanvasElement|HTMLImageElement|HTMLVideoElement} image Image.\n */\n\n\n ImageWrapper.prototype.setImage = function (image) {\n this.image_ = image;\n };\n /**\n * Discards event handlers which listen for load completion or errors.\n *\n * @private\n */\n\n\n ImageWrapper.prototype.unlistenImage_ = function () {\n if (this.unlisten_) {\n this.unlisten_();\n this.unlisten_ = null;\n }\n };\n\n return ImageWrapper;\n}(ol_ImageBase);\n/**\n * @param {HTMLCanvasElement|HTMLImageElement|HTMLVideoElement} image Image element.\n * @param {function():any} loadHandler Load callback function.\n * @param {function():any} errorHandler Error callback function.\n * @return {function():void} Callback to stop listening.\n */\n\n\nfunction listenImage(image, loadHandler, errorHandler) {\n var img =\n /** @type {HTMLImageElement} */\n image;\n\n if (img.src && IMAGE_DECODE) {\n var promise = img.decode();\n var listening_1 = true;\n\n var unlisten = function unlisten() {\n listening_1 = false;\n };\n\n promise.then(function () {\n if (listening_1) {\n loadHandler();\n }\n }).catch(function (error) {\n if (listening_1) {\n // FIXME: Unconditionally call errorHandler() when this bug is fixed upstream:\n // https://bugs.webkit.org/show_bug.cgi?id=198527\n if (error.name === \'EncodingError\' && error.message === \'Invalid image type.\') {\n loadHandler();\n } else {\n errorHandler();\n }\n }\n });\n return unlisten;\n }\n\n var listenerKeys = [listenOnce(img, EventType.LOAD, loadHandler), listenOnce(img, EventType.ERROR, errorHandler)];\n return function unlisten() {\n listenerKeys.forEach(unlistenByKey);\n };\n}\n/* harmony default export */ var ol_Image = ((/* unused pure expression or super */ null && (ImageWrapper)));\n;// CONCATENATED MODULE: ./node_modules/ol/style/IconImage.js\n/**\n * @module ol/style/IconImage\n */\nvar IconImage_extends = undefined && undefined.__extends || function () {\n var _extendStatics = function extendStatics(d, b) {\n _extendStatics = Object.setPrototypeOf || {\n __proto__: []\n } instanceof Array && function (d, b) {\n d.__proto__ = b;\n } || function (d, b) {\n for (var p in b) {\n if (Object.prototype.hasOwnProperty.call(b, p)) d[p] = b[p];\n }\n };\n\n return _extendStatics(d, b);\n };\n\n return function (d, b) {\n _extendStatics(d, b);\n\n function __() {\n this.constructor = d;\n }\n\n d.prototype = b === null ? Object.create(b) : (__.prototype = b.prototype, new __());\n };\n}();\n\n\n\n\n\n\n\n\n/**\n * @type {CanvasRenderingContext2D}\n */\n\nvar taintedTestContext = null;\n\nvar IconImage =\n/** @class */\nfunction (_super) {\n IconImage_extends(IconImage, _super);\n /**\n * @param {HTMLImageElement|HTMLCanvasElement} image Image.\n * @param {string|undefined} src Src.\n * @param {import("../size.js").Size} size Size.\n * @param {?string} crossOrigin Cross origin.\n * @param {import("../ImageState.js").default} imageState Image state.\n * @param {import("../color.js").Color} color Color.\n */\n\n\n function IconImage(image, src, size, crossOrigin, imageState, color) {\n var _this = _super.call(this) || this;\n /**\n * @private\n * @type {HTMLImageElement|HTMLCanvasElement}\n */\n\n\n _this.hitDetectionImage_ = null;\n /**\n * @private\n * @type {HTMLImageElement|HTMLCanvasElement}\n */\n\n _this.image_ = !image ? new Image() : image;\n\n if (crossOrigin !== null) {\n /** @type {HTMLImageElement} */\n _this.image_.crossOrigin = crossOrigin;\n }\n /**\n * @private\n * @type {Object<number, HTMLCanvasElement>}\n */\n\n\n _this.canvas_ = {};\n /**\n * @private\n * @type {import("../color.js").Color}\n */\n\n _this.color_ = color;\n /**\n * @private\n * @type {?function():void}\n */\n\n _this.unlisten_ = null;\n /**\n * @private\n * @type {import("../ImageState.js").default}\n */\n\n _this.imageState_ = imageState;\n /**\n * @private\n * @type {import("../size.js").Size}\n */\n\n _this.size_ = size;\n /**\n * @private\n * @type {string|undefined}\n */\n\n _this.src_ = src;\n /**\n * @private\n */\n\n _this.tainted_;\n return _this;\n }\n /**\n * @private\n * @return {boolean} The image canvas is tainted.\n */\n\n\n IconImage.prototype.isTainted_ = function () {\n if (this.tainted_ === undefined && this.imageState_ === ImageState.LOADED) {\n if (!taintedTestContext) {\n taintedTestContext = createCanvasContext2D(1, 1);\n }\n\n taintedTestContext.drawImage(this.image_, 0, 0);\n\n try {\n taintedTestContext.getImageData(0, 0, 1, 1);\n this.tainted_ = false;\n } catch (e) {\n taintedTestContext = null;\n this.tainted_ = true;\n }\n }\n\n return this.tainted_ === true;\n };\n /**\n * @private\n */\n\n\n IconImage.prototype.dispatchChangeEvent_ = function () {\n this.dispatchEvent(EventType.CHANGE);\n };\n /**\n * @private\n */\n\n\n IconImage.prototype.handleImageError_ = function () {\n this.imageState_ = ImageState.ERROR;\n this.unlistenImage_();\n this.dispatchChangeEvent_();\n };\n /**\n * @private\n */\n\n\n IconImage.prototype.handleImageLoad_ = function () {\n this.imageState_ = ImageState.LOADED;\n\n if (this.size_) {\n this.image_.width = this.size_[0];\n this.image_.height = this.size_[1];\n } else {\n this.size_ = [this.image_.width, this.image_.height];\n }\n\n this.unlistenImage_();\n this.dispatchChangeEvent_();\n };\n /**\n * @param {number} pixelRatio Pixel ratio.\n * @return {HTMLImageElement|HTMLCanvasElement} Image or Canvas element.\n */\n\n\n IconImage.prototype.getImage = function (pixelRatio) {\n this.replaceColor_(pixelRatio);\n return this.canvas_[pixelRatio] ? this.canvas_[pixelRatio] : this.image_;\n };\n /**\n * @param {number} pixelRatio Pixel ratio.\n * @return {number} Image or Canvas element.\n */\n\n\n IconImage.prototype.getPixelRatio = function (pixelRatio) {\n this.replaceColor_(pixelRatio);\n return this.canvas_[pixelRatio] ? pixelRatio : 1;\n };\n /**\n * @return {import("../ImageState.js").default} Image state.\n */\n\n\n IconImage.prototype.getImageState = function () {\n return this.imageState_;\n };\n /**\n * @return {HTMLImageElement|HTMLCanvasElement} Image element.\n */\n\n\n IconImage.prototype.getHitDetectionImage = function () {\n if (!this.hitDetectionImage_) {\n if (this.isTainted_()) {\n var width = this.size_[0];\n var height = this.size_[1];\n var context = createCanvasContext2D(width, height);\n context.fillRect(0, 0, width, height);\n this.hitDetectionImage_ = context.canvas;\n } else {\n this.hitDetectionImage_ = this.image_;\n }\n }\n\n return this.hitDetectionImage_;\n };\n /**\n * Get the size of the icon (in pixels).\n * @return {import("../size.js").Size} Image size.\n */\n\n\n IconImage.prototype.getSize = function () {\n return this.size_;\n };\n /**\n * @return {string|undefined} Image src.\n */\n\n\n IconImage.prototype.getSrc = function () {\n return this.src_;\n };\n /**\n * Load not yet loaded URI.\n */\n\n\n IconImage.prototype.load = function () {\n if (this.imageState_ == ImageState.IDLE) {\n this.imageState_ = ImageState.LOADING;\n\n try {\n /** @type {HTMLImageElement} */\n this.image_.src = this.src_;\n } catch (e) {\n this.handleImageError_();\n }\n\n this.unlisten_ = listenImage(this.image_, this.handleImageLoad_.bind(this), this.handleImageError_.bind(this));\n }\n };\n /**\n * @param {number} pixelRatio Pixel ratio.\n * @private\n */\n\n\n IconImage.prototype.replaceColor_ = function (pixelRatio) {\n if (!this.color_ || this.canvas_[pixelRatio]) {\n return;\n }\n\n var canvas = document.createElement(\'canvas\');\n this.canvas_[pixelRatio] = canvas;\n canvas.width = Math.ceil(this.image_.width * pixelRatio);\n canvas.height = Math.ceil(this.image_.height * pixelRatio);\n var ctx = canvas.getContext(\'2d\');\n ctx.scale(pixelRatio, pixelRatio);\n ctx.drawImage(this.image_, 0, 0);\n ctx.globalCompositeOperation = \'multiply\'; // Internet Explorer 11 does not support the multiply operation.\n // If the canvas is tainted in Internet Explorer this still produces\n // a solid color image with the shape of the icon.\n\n if (ctx.globalCompositeOperation === \'multiply\' || this.isTainted_()) {\n ctx.fillStyle = asString(this.color_);\n ctx.fillRect(0, 0, canvas.width, canvas.height);\n ctx.globalCompositeOperation = \'destination-in\';\n ctx.drawImage(this.image_, 0, 0);\n } else {\n var imgData = ctx.getImageData(0, 0, canvas.width, canvas.height);\n var data = imgData.data;\n var r = this.color_[0] / 255.0;\n var g = this.color_[1] / 255.0;\n var b = this.color_[2] / 255.0;\n var a = this.color_[3];\n\n for (var i = 0, ii = data.length; i < ii; i += 4) {\n data[i] *= r;\n data[i + 1] *= g;\n data[i + 2] *= b;\n data[i + 3] *= a;\n }\n\n ctx.putImageData(imgData, 0, 0);\n }\n };\n /**\n * Discards event handlers which listen for load completion or errors.\n *\n * @private\n */\n\n\n IconImage.prototype.unlistenImage_ = function () {\n if (this.unlisten_) {\n this.unlisten_();\n this.unlisten_ = null;\n }\n };\n\n return IconImage;\n}(events_Target);\n/**\n * @param {HTMLImageElement|HTMLCanvasElement} image Image.\n * @param {string} src Src.\n * @param {import("../size.js").Size} size Size.\n * @param {?string} crossOrigin Cross origin.\n * @param {import("../ImageState.js").default} imageState Image state.\n * @param {import("../color.js").Color} color Color.\n * @return {IconImage} Icon image.\n */\n\n\nfunction IconImage_get(image, src, size, crossOrigin, imageState, color) {\n var iconImage = shared.get(src, crossOrigin, color);\n\n if (!iconImage) {\n iconImage = new IconImage(image, src, size, crossOrigin, imageState, color);\n shared.set(src, crossOrigin, color, iconImage);\n }\n\n return iconImage;\n}\n/* harmony default export */ var style_IconImage = ((/* unused pure expression or super */ null && (IconImage)));\n;// CONCATENATED MODULE: ./node_modules/ol/style/Icon.js\nvar Icon_extends = undefined && undefined.__extends || function () {\n var _extendStatics = function extendStatics(d, b) {\n _extendStatics = Object.setPrototypeOf || {\n __proto__: []\n } instanceof Array && function (d, b) {\n d.__proto__ = b;\n } || function (d, b) {\n for (var p in b) {\n if (Object.prototype.hasOwnProperty.call(b, p)) d[p] = b[p];\n }\n };\n\n return _extendStatics(d, b);\n };\n\n return function (d, b) {\n _extendStatics(d, b);\n\n function __() {\n this.constructor = d;\n }\n\n d.prototype = b === null ? Object.create(b) : (__.prototype = b.prototype, new __());\n };\n}();\n/**\n * @module ol/style/Icon\n */\n\n\n\n\n\n\n\n\n\n\n\n/**\n * @typedef {Object} Options\n * @property {Array<number>} [anchor=[0.5, 0.5]] Anchor. Default value is the icon center.\n * @property {import("./IconOrigin.js").default} [anchorOrigin=\'top-left\'] Origin of the anchor: `bottom-left`, `bottom-right`,\n * `top-left` or `top-right`.\n * @property {import("./IconAnchorUnits.js").default} [anchorXUnits=\'fraction\'] Units in which the anchor x value is\n * specified. A value of `\'fraction\'` indicates the x value is a fraction of the icon. A value of `\'pixels\'` indicates\n * the x value in pixels.\n * @property {import("./IconAnchorUnits.js").default} [anchorYUnits=\'fraction\'] Units in which the anchor y value is\n * specified. A value of `\'fraction\'` indicates the y value is a fraction of the icon. A value of `\'pixels\'` indicates\n * the y value in pixels.\n * @property {import("../color.js").Color|string} [color] Color to tint the icon. If not specified,\n * the icon will be left as is.\n * @property {null|string} [crossOrigin] The `crossOrigin` attribute for loaded images. Note that you must provide a\n * `crossOrigin` value if you want to access pixel data with the Canvas renderer.\n * See https://developer.mozilla.org/en-US/docs/Web/HTML/CORS_enabled_image for more detail.\n * @property {HTMLImageElement|HTMLCanvasElement} [img] Image object for the icon. If the `src` option is not provided then the\n * provided image must already be loaded. And in that case, it is required\n * to provide the size of the image, with the `imgSize` option.\n * @property {Array<number>} [offset=[0, 0]] Offset, which, together with the size and the offset origin, define the\n * sub-rectangle to use from the original icon image.\n * @property {Array<number>} [displacement=[0,0]] Displacement the icon\n * @property {import("./IconOrigin.js").default} [offsetOrigin=\'top-left\'] Origin of the offset: `bottom-left`, `bottom-right`,\n * `top-left` or `top-right`.\n * @property {number} [opacity=1] Opacity of the icon.\n * @property {number|import("../size.js").Size} [scale=1] Scale.\n * @property {boolean} [rotateWithView=false] Whether to rotate the icon with the view.\n * @property {number} [rotation=0] Rotation in radians (positive rotation clockwise).\n * @property {import("../size.js").Size} [size] Icon size in pixel. Can be used together with `offset` to define the\n * sub-rectangle to use from the origin (sprite) icon image.\n * @property {import("../size.js").Size} [imgSize] Image size in pixels. Only required if `img` is set and `src` is not, and\n * for SVG images in Internet Explorer 11. The provided `imgSize` needs to match the actual size of the image.\n * @property {string} [src] Image source URI.\n */\n\n/**\n * @classdesc\n * Set icon style for vector features.\n * @api\n */\n\nvar Icon =\n/** @class */\nfunction (_super) {\n Icon_extends(Icon, _super);\n /**\n * @param {Options=} opt_options Options.\n */\n\n\n function Icon(opt_options) {\n var _this = this;\n\n var options = opt_options || {};\n /**\n * @type {number}\n */\n\n var opacity = options.opacity !== undefined ? options.opacity : 1;\n /**\n * @type {number}\n */\n\n var rotation = options.rotation !== undefined ? options.rotation : 0;\n /**\n * @type {number|import("../size.js").Size}\n */\n\n var scale = options.scale !== undefined ? options.scale : 1;\n /**\n * @type {boolean}\n */\n\n var rotateWithView = options.rotateWithView !== undefined ? options.rotateWithView : false;\n _this = _super.call(this, {\n opacity: opacity,\n rotation: rotation,\n scale: scale,\n displacement: options.displacement !== undefined ? options.displacement : [0, 0],\n rotateWithView: rotateWithView\n }) || this;\n /**\n * @private\n * @type {Array<number>}\n */\n\n _this.anchor_ = options.anchor !== undefined ? options.anchor : [0.5, 0.5];\n /**\n * @private\n * @type {Array<number>}\n */\n\n _this.normalizedAnchor_ = null;\n /**\n * @private\n * @type {import("./IconOrigin.js").default}\n */\n\n _this.anchorOrigin_ = options.anchorOrigin !== undefined ? options.anchorOrigin : IconOrigin.TOP_LEFT;\n /**\n * @private\n * @type {import("./IconAnchorUnits.js").default}\n */\n\n _this.anchorXUnits_ = options.anchorXUnits !== undefined ? options.anchorXUnits : IconAnchorUnits.FRACTION;\n /**\n * @private\n * @type {import("./IconAnchorUnits.js").default}\n */\n\n _this.anchorYUnits_ = options.anchorYUnits !== undefined ? options.anchorYUnits : IconAnchorUnits.FRACTION;\n /**\n * @private\n * @type {?string}\n */\n\n _this.crossOrigin_ = options.crossOrigin !== undefined ? options.crossOrigin : null;\n /**\n * @type {HTMLImageElement|HTMLCanvasElement}\n */\n\n var image = options.img !== undefined ? options.img : null;\n /**\n * @type {import("../size.js").Size}\n */\n\n var imgSize = options.imgSize !== undefined ? options.imgSize : null;\n /**\n * @type {string|undefined}\n */\n\n var src = options.src;\n asserts_assert(!(src !== undefined && image), 4); // `image` and `src` cannot be provided at the same time\n\n asserts_assert(!image || image && imgSize, 5); // `imgSize` must be set when `image` is provided\n\n if ((src === undefined || src.length === 0) && image) {\n src =\n /** @type {HTMLImageElement} */\n image.src || util_getUid(image);\n }\n\n asserts_assert(src !== undefined && src.length > 0, 6); // A defined and non-empty `src` or `image` must be provided\n\n /**\n * @type {import("../ImageState.js").default}\n */\n\n var imageState = options.src !== undefined ? ImageState.IDLE : ImageState.LOADED;\n /**\n * @private\n * @type {import("../color.js").Color}\n */\n\n _this.color_ = options.color !== undefined ? asArray(options.color) : null;\n /**\n * @private\n * @type {import("./IconImage.js").default}\n */\n\n _this.iconImage_ = IconImage_get(image,\n /** @type {string} */\n src, imgSize, _this.crossOrigin_, imageState, _this.color_);\n /**\n * @private\n * @type {Array<number>}\n */\n\n _this.offset_ = options.offset !== undefined ? options.offset : [0, 0];\n /**\n * @private\n * @type {import("./IconOrigin.js").default}\n */\n\n _this.offsetOrigin_ = options.offsetOrigin !== undefined ? options.offsetOrigin : IconOrigin.TOP_LEFT;\n /**\n * @private\n * @type {Array<number>}\n */\n\n _this.origin_ = null;\n /**\n * @private\n * @type {import("../size.js").Size}\n */\n\n _this.size_ = options.size !== undefined ? options.size : null;\n return _this;\n }\n /**\n * Clones the style. The underlying Image/HTMLCanvasElement is not cloned.\n * @return {Icon} The cloned style.\n * @api\n */\n\n\n Icon.prototype.clone = function () {\n var scale = this.getScale();\n return new Icon({\n anchor: this.anchor_.slice(),\n anchorOrigin: this.anchorOrigin_,\n anchorXUnits: this.anchorXUnits_,\n anchorYUnits: this.anchorYUnits_,\n crossOrigin: this.crossOrigin_,\n color: this.color_ && this.color_.slice ? this.color_.slice() : this.color_ || undefined,\n src: this.getSrc(),\n offset: this.offset_.slice(),\n offsetOrigin: this.offsetOrigin_,\n size: this.size_ !== null ? this.size_.slice() : undefined,\n opacity: this.getOpacity(),\n scale: Array.isArray(scale) ? scale.slice() : scale,\n rotation: this.getRotation(),\n rotateWithView: this.getRotateWithView()\n });\n };\n /**\n * Get the anchor point in pixels. The anchor determines the center point for the\n * symbolizer.\n * @return {Array<number>} Anchor.\n * @api\n */\n\n\n Icon.prototype.getAnchor = function () {\n if (this.normalizedAnchor_) {\n return this.normalizedAnchor_;\n }\n\n var anchor = this.anchor_;\n var size = this.getSize();\n\n if (this.anchorXUnits_ == IconAnchorUnits.FRACTION || this.anchorYUnits_ == IconAnchorUnits.FRACTION) {\n if (!size) {\n return null;\n }\n\n anchor = this.anchor_.slice();\n\n if (this.anchorXUnits_ == IconAnchorUnits.FRACTION) {\n anchor[0] *= size[0];\n }\n\n if (this.anchorYUnits_ == IconAnchorUnits.FRACTION) {\n anchor[1] *= size[1];\n }\n }\n\n if (this.anchorOrigin_ != IconOrigin.TOP_LEFT) {\n if (!size) {\n return null;\n }\n\n if (anchor === this.anchor_) {\n anchor = this.anchor_.slice();\n }\n\n if (this.anchorOrigin_ == IconOrigin.TOP_RIGHT || this.anchorOrigin_ == IconOrigin.BOTTOM_RIGHT) {\n anchor[0] = -anchor[0] + size[0];\n }\n\n if (this.anchorOrigin_ == IconOrigin.BOTTOM_LEFT || this.anchorOrigin_ == IconOrigin.BOTTOM_RIGHT) {\n anchor[1] = -anchor[1] + size[1];\n }\n }\n\n this.normalizedAnchor_ = anchor;\n return this.normalizedAnchor_;\n };\n /**\n * Set the anchor point. The anchor determines the center point for the\n * symbolizer.\n *\n * @param {Array<number>} anchor Anchor.\n * @api\n */\n\n\n Icon.prototype.setAnchor = function (anchor) {\n this.anchor_ = anchor;\n this.normalizedAnchor_ = null;\n };\n /**\n * Get the icon color.\n * @return {import("../color.js").Color} Color.\n * @api\n */\n\n\n Icon.prototype.getColor = function () {\n return this.color_;\n };\n /**\n * Get the image icon.\n * @param {number} pixelRatio Pixel ratio.\n * @return {HTMLImageElement|HTMLCanvasElement} Image or Canvas element.\n * @api\n */\n\n\n Icon.prototype.getImage = function (pixelRatio) {\n return this.iconImage_.getImage(pixelRatio);\n };\n /**\n * Get the pixel ratio.\n * @param {number} pixelRatio Pixel ratio.\n * @return {number} The pixel ration of the image.\n * @api\n */\n\n\n Icon.prototype.getPixelRatio = function (pixelRatio) {\n return this.iconImage_.getPixelRatio(pixelRatio);\n };\n /**\n * @return {import("../size.js").Size} Image size.\n */\n\n\n Icon.prototype.getImageSize = function () {\n return this.iconImage_.getSize();\n };\n /**\n * @return {import("../size.js").Size} Size of the hit-detection image.\n */\n\n\n Icon.prototype.getHitDetectionImageSize = function () {\n return this.getImageSize();\n };\n /**\n * @return {import("../ImageState.js").default} Image state.\n */\n\n\n Icon.prototype.getImageState = function () {\n return this.iconImage_.getImageState();\n };\n /**\n * @return {HTMLImageElement|HTMLCanvasElement} Image element.\n */\n\n\n Icon.prototype.getHitDetectionImage = function () {\n return this.iconImage_.getHitDetectionImage();\n };\n /**\n * Get the origin of the symbolizer.\n * @return {Array<number>} Origin.\n * @api\n */\n\n\n Icon.prototype.getOrigin = function () {\n if (this.origin_) {\n return this.origin_;\n }\n\n var offset = this.offset_;\n var displacement = this.getDisplacement();\n\n if (this.offsetOrigin_ != IconOrigin.TOP_LEFT) {\n var size = this.getSize();\n var iconImageSize = this.iconImage_.getSize();\n\n if (!size || !iconImageSize) {\n return null;\n }\n\n offset = offset.slice();\n\n if (this.offsetOrigin_ == IconOrigin.TOP_RIGHT || this.offsetOrigin_ == IconOrigin.BOTTOM_RIGHT) {\n offset[0] = iconImageSize[0] - size[0] - offset[0];\n }\n\n if (this.offsetOrigin_ == IconOrigin.BOTTOM_LEFT || this.offsetOrigin_ == IconOrigin.BOTTOM_RIGHT) {\n offset[1] = iconImageSize[1] - size[1] - offset[1];\n }\n }\n\n offset[0] += displacement[0];\n offset[1] += displacement[1];\n this.origin_ = offset;\n return this.origin_;\n };\n /**\n * Get the image URL.\n * @return {string|undefined} Image src.\n * @api\n */\n\n\n Icon.prototype.getSrc = function () {\n return this.iconImage_.getSrc();\n };\n /**\n * Get the size of the icon (in pixels).\n * @return {import("../size.js").Size} Image size.\n * @api\n */\n\n\n Icon.prototype.getSize = function () {\n return !this.size_ ? this.iconImage_.getSize() : this.size_;\n };\n /**\n * @param {function(import("../events/Event.js").default): void} listener Listener function.\n */\n\n\n Icon.prototype.listenImageChange = function (listener) {\n this.iconImage_.addEventListener(EventType.CHANGE, listener);\n };\n /**\n * Load not yet loaded URI.\n * When rendering a feature with an icon style, the vector renderer will\n * automatically call this method. However, you might want to call this\n * method yourself for preloading or other purposes.\n * @api\n */\n\n\n Icon.prototype.load = function () {\n this.iconImage_.load();\n };\n /**\n * @param {function(import("../events/Event.js").default): void} listener Listener function.\n */\n\n\n Icon.prototype.unlistenImageChange = function (listener) {\n this.iconImage_.removeEventListener(EventType.CHANGE, listener);\n };\n\n return Icon;\n}(style_Image);\n\n/* harmony default export */ var style_Icon = (Icon);\n;// CONCATENATED MODULE: ./node_modules/ol/render/canvas/hitdetect.js\n/**\n * @module ol/render/canvas/hitdetect\n */\n\n\n\n\n\n\n\n/**\n * @param {import("../../size.js").Size} size Canvas size in css pixels.\n * @param {Array<import("../../transform.js").Transform>} transforms Transforms\n * for rendering features to all worlds of the viewport, from coordinates to css\n * pixels.\n * @param {Array<import("../../Feature.js").FeatureLike>} features\n * Features to consider for hit detection.\n * @param {import("../../style/Style.js").StyleFunction|undefined} styleFunction\n * Layer style function.\n * @param {import("../../extent.js").Extent} extent Extent.\n * @param {number} resolution Resolution.\n * @param {number} rotation Rotation.\n * @return {ImageData} Hit detection image data.\n */\n\nfunction createHitDetectionImageData(size, transforms, features, styleFunction, extent, resolution, rotation) {\n var width = size[0] / 2;\n var height = size[1] / 2;\n var context = createCanvasContext2D(width, height);\n context.imageSmoothingEnabled = false;\n var canvas = context.canvas;\n var renderer = new Immediate(context, 0.5, extent, null, rotation);\n var featureCount = features.length; // Stretch hit detection index to use the whole available color range\n\n var indexFactor = Math.floor((256 * 256 * 256 - 1) / featureCount);\n var featuresByZIndex = {};\n\n for (var i = 1; i <= featureCount; ++i) {\n var feature = features[i - 1];\n var featureStyleFunction = feature.getStyleFunction() || styleFunction;\n\n if (!styleFunction) {\n continue;\n }\n\n var styles = featureStyleFunction(feature, resolution);\n\n if (!styles) {\n continue;\n }\n\n if (!Array.isArray(styles)) {\n styles = [styles];\n }\n\n var index = i * indexFactor;\n var color = \'#\' + (\'000000\' + index.toString(16)).slice(-6);\n\n for (var j = 0, jj = styles.length; j < jj; ++j) {\n var originalStyle = styles[j];\n var style = originalStyle.clone();\n var fill = style.getFill();\n\n if (fill) {\n fill.setColor(color);\n }\n\n var stroke = style.getStroke();\n\n if (stroke) {\n stroke.setColor(color);\n }\n\n style.setText(undefined);\n var image = originalStyle.getImage();\n\n if (image) {\n var imgSize = image.getImageSize();\n\n if (!imgSize) {\n continue;\n }\n\n var canvas_1 = document.createElement(\'canvas\');\n canvas_1.width = imgSize[0];\n canvas_1.height = imgSize[1];\n var imgContext = canvas_1.getContext(\'2d\', {\n alpha: false\n });\n imgContext.fillStyle = color;\n var img = imgContext.canvas;\n imgContext.fillRect(0, 0, img.width, img.height);\n var width_1 = imgSize ? imgSize[0] : img.width;\n var height_1 = imgSize ? imgSize[1] : img.height;\n var iconContext = createCanvasContext2D(width_1, height_1);\n iconContext.drawImage(img, 0, 0);\n style.setImage(new style_Icon({\n img: img,\n imgSize: imgSize,\n anchor: image.getAnchor(),\n anchorXUnits: IconAnchorUnits.PIXELS,\n anchorYUnits: IconAnchorUnits.PIXELS,\n offset: image.getOrigin(),\n size: image.getSize(),\n opacity: image.getOpacity(),\n scale: image.getScale(),\n rotation: image.getRotation(),\n rotateWithView: image.getRotateWithView()\n }));\n }\n\n var zIndex = Number(style.getZIndex());\n var byGeometryType = featuresByZIndex[zIndex];\n\n if (!byGeometryType) {\n byGeometryType = {};\n featuresByZIndex[zIndex] = byGeometryType;\n byGeometryType[geom_GeometryType.POLYGON] = [];\n byGeometryType[geom_GeometryType.CIRCLE] = [];\n byGeometryType[geom_GeometryType.LINE_STRING] = [];\n byGeometryType[geom_GeometryType.POINT] = [];\n }\n\n var geometry = style.getGeometryFunction()(feature);\n\n if (geometry && intersects(extent, geometry.getExtent())) {\n byGeometryType[geometry.getType().replace(\'Multi\', \'\')].push(geometry, style);\n }\n }\n }\n\n var zIndexKeys = Object.keys(featuresByZIndex).map(Number).sort(numberSafeCompareFunction);\n\n for (var i = 0, ii = zIndexKeys.length; i < ii; ++i) {\n var byGeometryType = featuresByZIndex[zIndexKeys[i]];\n\n for (var type in byGeometryType) {\n var geomAndStyle = byGeometryType[type];\n\n for (var j = 0, jj = geomAndStyle.length; j < jj; j += 2) {\n renderer.setStyle(geomAndStyle[j + 1]);\n\n for (var k = 0, kk = transforms.length; k < kk; ++k) {\n renderer.setTransform(transforms[k]);\n renderer.drawGeometry(geomAndStyle[j]);\n }\n }\n }\n }\n\n return context.getImageData(0, 0, canvas.width, canvas.height);\n}\n/**\n * @param {import("../../pixel").Pixel} pixel Pixel coordinate on the hit\n * detection canvas in css pixels.\n * @param {Array<import("../../Feature").FeatureLike>} features Features. Has to\n * match the `features` array that was passed to `createHitDetectionImageData()`.\n * @param {ImageData} imageData Hit detection image data generated by\n * `createHitDetectionImageData()`.\n * @return {Array<import("../../Feature").FeatureLike>} features Features.\n */\n\nfunction hitDetect(pixel, features, imageData) {\n var resultFeatures = [];\n\n if (imageData) {\n var index = (Math.round(pixel[0] / 2) + Math.round(pixel[1] / 2) * imageData.width) * 4;\n var r = imageData.data[index];\n var g = imageData.data[index + 1];\n var b = imageData.data[index + 2];\n var i = b + 256 * (g + 256 * r);\n var indexFactor = Math.floor((256 * 256 * 256 - 1) / features.length);\n\n if (i && i % indexFactor === 0) {\n resultFeatures.push(features[i / indexFactor - 1]);\n }\n }\n\n return resultFeatures;\n}\n;// CONCATENATED MODULE: ./node_modules/ol/renderer/vector.js\n/**\n * @module ol/renderer/vector\n */\n\n\n\n\n/**\n * Feature callback. The callback will be called with three arguments. The first\n * argument is one {@link module:ol/Feature feature} or {@link module:ol/render/Feature render feature}\n * at the pixel, the second is the {@link module:ol/layer/Layer layer} of the feature and will be null for\n * unmanaged layers. The third is the {@link module:ol/geom/SimpleGeometry} of the feature. For features\n * with a GeometryCollection geometry, it will be the first detected geometry from the collection.\n * @template T\n * @typedef {function(import("../Feature.js").FeatureLike, import("../layer/Layer.js").default, import("../geom/SimpleGeometry.js").default): T} FeatureCallback\n */\n\n/**\n * Tolerance for geometry simplification in device pixels.\n * @type {number}\n */\n\nvar SIMPLIFY_TOLERANCE = 0.5;\n/**\n * @const\n * @type {Object<import("../geom/GeometryType.js").default,\n * function(import("../render/canvas/BuilderGroup.js").default, import("../geom/Geometry.js").default,\n * import("../style/Style.js").default, Object): void>}\n */\n\nvar GEOMETRY_RENDERERS = {\n \'Point\': renderPointGeometry,\n \'LineString\': renderLineStringGeometry,\n \'Polygon\': renderPolygonGeometry,\n \'MultiPoint\': renderMultiPointGeometry,\n \'MultiLineString\': renderMultiLineStringGeometry,\n \'MultiPolygon\': renderMultiPolygonGeometry,\n \'GeometryCollection\': renderGeometryCollectionGeometry,\n \'Circle\': renderCircleGeometry\n};\n/**\n * @param {import("../Feature.js").FeatureLike} feature1 Feature 1.\n * @param {import("../Feature.js").FeatureLike} feature2 Feature 2.\n * @return {number} Order.\n */\n\nfunction defaultOrder(feature1, feature2) {\n return parseInt(getUid(feature1), 10) - parseInt(getUid(feature2), 10);\n}\n/**\n * @param {number} resolution Resolution.\n * @param {number} pixelRatio Pixel ratio.\n * @return {number} Squared pixel tolerance.\n */\n\nfunction getSquaredTolerance(resolution, pixelRatio) {\n var tolerance = getTolerance(resolution, pixelRatio);\n return tolerance * tolerance;\n}\n/**\n * @param {number} resolution Resolution.\n * @param {number} pixelRatio Pixel ratio.\n * @return {number} Pixel tolerance.\n */\n\nfunction getTolerance(resolution, pixelRatio) {\n return SIMPLIFY_TOLERANCE * resolution / pixelRatio;\n}\n/**\n * @param {import("../render/canvas/BuilderGroup.js").default} builderGroup Builder group.\n * @param {import("../geom/Circle.js").default} geometry Geometry.\n * @param {import("../style/Style.js").default} style Style.\n * @param {import("../Feature.js").default} feature Feature.\n * @param {import("../render/canvas/BuilderGroup.js").default=} opt_declutterBuilderGroup Builder for decluttering.\n */\n\nfunction renderCircleGeometry(builderGroup, geometry, style, feature, opt_declutterBuilderGroup) {\n var fillStyle = style.getFill();\n var strokeStyle = style.getStroke();\n\n if (fillStyle || strokeStyle) {\n var circleReplay = builderGroup.getBuilder(style.getZIndex(), BuilderType.CIRCLE);\n circleReplay.setFillStrokeStyle(fillStyle, strokeStyle);\n circleReplay.drawCircle(geometry, feature);\n }\n\n var textStyle = style.getText();\n\n if (textStyle && textStyle.getText()) {\n var textReplay = (opt_declutterBuilderGroup || builderGroup).getBuilder(style.getZIndex(), BuilderType.TEXT);\n textReplay.setTextStyle(textStyle);\n textReplay.drawText(geometry, feature);\n }\n}\n/**\n * @param {import("../render/canvas/BuilderGroup.js").default} replayGroup Replay group.\n * @param {import("../Feature.js").FeatureLike} feature Feature.\n * @param {import("../style/Style.js").default} style Style.\n * @param {number} squaredTolerance Squared tolerance.\n * @param {function(import("../events/Event.js").default): void} listener Listener function.\n * @param {import("../proj.js").TransformFunction} [opt_transform] Transform from user to view projection.\n * @param {import("../render/canvas/BuilderGroup.js").default=} opt_declutterBuilderGroup Builder for decluttering.\n * @return {boolean} `true` if style is loading.\n */\n\n\nfunction renderFeature(replayGroup, feature, style, squaredTolerance, listener, opt_transform, opt_declutterBuilderGroup) {\n var loading = false;\n var imageStyle = style.getImage();\n\n if (imageStyle) {\n var imageState = imageStyle.getImageState();\n\n if (imageState == ImageState.LOADED || imageState == ImageState.ERROR) {\n imageStyle.unlistenImageChange(listener);\n } else {\n if (imageState == ImageState.IDLE) {\n imageStyle.load();\n }\n\n imageState = imageStyle.getImageState();\n imageStyle.listenImageChange(listener);\n loading = true;\n }\n }\n\n renderFeatureInternal(replayGroup, feature, style, squaredTolerance, opt_transform, opt_declutterBuilderGroup);\n return loading;\n}\n/**\n * @param {import("../render/canvas/BuilderGroup.js").default} replayGroup Replay group.\n * @param {import("../Feature.js").FeatureLike} feature Feature.\n * @param {import("../style/Style.js").default} style Style.\n * @param {number} squaredTolerance Squared tolerance.\n * @param {import("../proj.js").TransformFunction} [opt_transform] Optional transform function.\n * @param {import("../render/canvas/BuilderGroup.js").default=} opt_declutterBuilderGroup Builder for decluttering.\n */\n\nfunction renderFeatureInternal(replayGroup, feature, style, squaredTolerance, opt_transform, opt_declutterBuilderGroup) {\n var geometry = style.getGeometryFunction()(feature);\n\n if (!geometry) {\n return;\n }\n\n var simplifiedGeometry = geometry.simplifyTransformed(squaredTolerance, opt_transform);\n var renderer = style.getRenderer();\n\n if (renderer) {\n renderGeometry(replayGroup, simplifiedGeometry, style, feature);\n } else {\n var geometryRenderer = GEOMETRY_RENDERERS[simplifiedGeometry.getType()];\n geometryRenderer(replayGroup, simplifiedGeometry, style, feature, opt_declutterBuilderGroup);\n }\n}\n/**\n * @param {import("../render/canvas/BuilderGroup.js").default} replayGroup Replay group.\n * @param {import("../geom/Geometry.js").default|import("../render/Feature.js").default} geometry Geometry.\n * @param {import("../style/Style.js").default} style Style.\n * @param {import("../Feature.js").FeatureLike} feature Feature.\n */\n\n\nfunction renderGeometry(replayGroup, geometry, style, feature) {\n if (geometry.getType() == geom_GeometryType.GEOMETRY_COLLECTION) {\n var geometries =\n /** @type {import("../geom/GeometryCollection.js").default} */\n geometry.getGeometries();\n\n for (var i = 0, ii = geometries.length; i < ii; ++i) {\n renderGeometry(replayGroup, geometries[i], style, feature);\n }\n\n return;\n }\n\n var replay = replayGroup.getBuilder(style.getZIndex(), BuilderType.DEFAULT);\n replay.drawCustom(\n /** @type {import("../geom/SimpleGeometry.js").default} */\n geometry, feature, style.getRenderer());\n}\n/**\n * @param {import("../render/canvas/BuilderGroup.js").default} replayGroup Replay group.\n * @param {import("../geom/GeometryCollection.js").default} geometry Geometry.\n * @param {import("../style/Style.js").default} style Style.\n * @param {import("../Feature.js").default} feature Feature.\n * @param {import("../render/canvas/BuilderGroup.js").default=} opt_declutterBuilderGroup Builder for decluttering.\n */\n\n\nfunction renderGeometryCollectionGeometry(replayGroup, geometry, style, feature, opt_declutterBuilderGroup) {\n var geometries = geometry.getGeometriesArray();\n var i, ii;\n\n for (i = 0, ii = geometries.length; i < ii; ++i) {\n var geometryRenderer = GEOMETRY_RENDERERS[geometries[i].getType()];\n geometryRenderer(replayGroup, geometries[i], style, feature, opt_declutterBuilderGroup);\n }\n}\n/**\n * @param {import("../render/canvas/BuilderGroup.js").default} builderGroup Replay group.\n * @param {import("../geom/LineString.js").default|import("../render/Feature.js").default} geometry Geometry.\n * @param {import("../style/Style.js").default} style Style.\n * @param {import("../Feature.js").FeatureLike} feature Feature.\n * @param {import("../render/canvas/BuilderGroup.js").default=} opt_declutterBuilderGroup Builder for decluttering.\n */\n\n\nfunction renderLineStringGeometry(builderGroup, geometry, style, feature, opt_declutterBuilderGroup) {\n var strokeStyle = style.getStroke();\n\n if (strokeStyle) {\n var lineStringReplay = builderGroup.getBuilder(style.getZIndex(), BuilderType.LINE_STRING);\n lineStringReplay.setFillStrokeStyle(null, strokeStyle);\n lineStringReplay.drawLineString(geometry, feature);\n }\n\n var textStyle = style.getText();\n\n if (textStyle && textStyle.getText()) {\n var textReplay = (opt_declutterBuilderGroup || builderGroup).getBuilder(style.getZIndex(), BuilderType.TEXT);\n textReplay.setTextStyle(textStyle);\n textReplay.drawText(geometry, feature);\n }\n}\n/**\n * @param {import("../render/canvas/BuilderGroup.js").default} builderGroup Replay group.\n * @param {import("../geom/MultiLineString.js").default|import("../render/Feature.js").default} geometry Geometry.\n * @param {import("../style/Style.js").default} style Style.\n * @param {import("../Feature.js").FeatureLike} feature Feature.\n * @param {import("../render/canvas/BuilderGroup.js").default=} opt_declutterBuilderGroup Builder for decluttering.\n */\n\n\nfunction renderMultiLineStringGeometry(builderGroup, geometry, style, feature, opt_declutterBuilderGroup) {\n var strokeStyle = style.getStroke();\n\n if (strokeStyle) {\n var lineStringReplay = builderGroup.getBuilder(style.getZIndex(), BuilderType.LINE_STRING);\n lineStringReplay.setFillStrokeStyle(null, strokeStyle);\n lineStringReplay.drawMultiLineString(geometry, feature);\n }\n\n var textStyle = style.getText();\n\n if (textStyle && textStyle.getText()) {\n var textReplay = (opt_declutterBuilderGroup || builderGroup).getBuilder(style.getZIndex(), BuilderType.TEXT);\n textReplay.setTextStyle(textStyle);\n textReplay.drawText(geometry, feature);\n }\n}\n/**\n * @param {import("../render/canvas/BuilderGroup.js").default} builderGroup Replay group.\n * @param {import("../geom/MultiPolygon.js").default} geometry Geometry.\n * @param {import("../style/Style.js").default} style Style.\n * @param {import("../Feature.js").default} feature Feature.\n * @param {import("../render/canvas/BuilderGroup.js").default=} opt_declutterBuilderGroup Builder for decluttering.\n */\n\n\nfunction renderMultiPolygonGeometry(builderGroup, geometry, style, feature, opt_declutterBuilderGroup) {\n var fillStyle = style.getFill();\n var strokeStyle = style.getStroke();\n\n if (strokeStyle || fillStyle) {\n var polygonReplay = builderGroup.getBuilder(style.getZIndex(), BuilderType.POLYGON);\n polygonReplay.setFillStrokeStyle(fillStyle, strokeStyle);\n polygonReplay.drawMultiPolygon(geometry, feature);\n }\n\n var textStyle = style.getText();\n\n if (textStyle && textStyle.getText()) {\n var textReplay = (opt_declutterBuilderGroup || builderGroup).getBuilder(style.getZIndex(), BuilderType.TEXT);\n textReplay.setTextStyle(textStyle);\n textReplay.drawText(geometry, feature);\n }\n}\n/**\n * @param {import("../render/canvas/BuilderGroup.js").default} builderGroup Replay group.\n * @param {import("../geom/Point.js").default|import("../render/Feature.js").default} geometry Geometry.\n * @param {import("../style/Style.js").default} style Style.\n * @param {import("../Feature.js").FeatureLike} feature Feature.\n * @param {import("../render/canvas/BuilderGroup.js").default=} opt_declutterBuilderGroup Builder for decluttering.\n */\n\n\nfunction renderPointGeometry(builderGroup, geometry, style, feature, opt_declutterBuilderGroup) {\n var imageStyle = style.getImage();\n var textStyle = style.getText();\n /** @type {import("../render/canvas.js").DeclutterImageWithText} */\n\n var declutterImageWithText;\n\n if (opt_declutterBuilderGroup) {\n builderGroup = opt_declutterBuilderGroup;\n declutterImageWithText = imageStyle && textStyle && textStyle.getText() ? {} : undefined;\n }\n\n if (imageStyle) {\n if (imageStyle.getImageState() != ImageState.LOADED) {\n return;\n }\n\n var imageReplay = builderGroup.getBuilder(style.getZIndex(), BuilderType.IMAGE);\n imageReplay.setImageStyle(imageStyle, declutterImageWithText);\n imageReplay.drawPoint(geometry, feature);\n }\n\n if (textStyle && textStyle.getText()) {\n var textReplay = builderGroup.getBuilder(style.getZIndex(), BuilderType.TEXT);\n textReplay.setTextStyle(textStyle, declutterImageWithText);\n textReplay.drawText(geometry, feature);\n }\n}\n/**\n * @param {import("../render/canvas/BuilderGroup.js").default} builderGroup Replay group.\n * @param {import("../geom/MultiPoint.js").default|import("../render/Feature.js").default} geometry Geometry.\n * @param {import("../style/Style.js").default} style Style.\n * @param {import("../Feature.js").FeatureLike} feature Feature.\n * @param {import("../render/canvas/BuilderGroup.js").default=} opt_declutterBuilderGroup Builder for decluttering.\n */\n\n\nfunction renderMultiPointGeometry(builderGroup, geometry, style, feature, opt_declutterBuilderGroup) {\n var imageStyle = style.getImage();\n var textStyle = style.getText();\n /** @type {import("../render/canvas.js").DeclutterImageWithText} */\n\n var declutterImageWithText;\n\n if (opt_declutterBuilderGroup) {\n builderGroup = opt_declutterBuilderGroup;\n declutterImageWithText = imageStyle && textStyle && textStyle.getText() ? {} : undefined;\n }\n\n if (imageStyle) {\n if (imageStyle.getImageState() != ImageState.LOADED) {\n return;\n }\n\n var imageReplay = builderGroup.getBuilder(style.getZIndex(), BuilderType.IMAGE);\n imageReplay.setImageStyle(imageStyle, declutterImageWithText);\n imageReplay.drawMultiPoint(geometry, feature);\n }\n\n if (textStyle && textStyle.getText()) {\n var textReplay = (opt_declutterBuilderGroup || builderGroup).getBuilder(style.getZIndex(), BuilderType.TEXT);\n textReplay.setTextStyle(textStyle, declutterImageWithText);\n textReplay.drawText(geometry, feature);\n }\n}\n/**\n * @param {import("../render/canvas/BuilderGroup.js").default} builderGroup Replay group.\n * @param {import("../geom/Polygon.js").default|import("../render/Feature.js").default} geometry Geometry.\n * @param {import("../style/Style.js").default} style Style.\n * @param {import("../Feature.js").FeatureLike} feature Feature.\n * @param {import("../render/canvas/BuilderGroup.js").default=} opt_declutterBuilderGroup Builder for decluttering.\n */\n\n\nfunction renderPolygonGeometry(builderGroup, geometry, style, feature, opt_declutterBuilderGroup) {\n var fillStyle = style.getFill();\n var strokeStyle = style.getStroke();\n\n if (fillStyle || strokeStyle) {\n var polygonReplay = builderGroup.getBuilder(style.getZIndex(), BuilderType.POLYGON);\n polygonReplay.setFillStrokeStyle(fillStyle, strokeStyle);\n polygonReplay.drawPolygon(geometry, feature);\n }\n\n var textStyle = style.getText();\n\n if (textStyle && textStyle.getText()) {\n var textReplay = (opt_declutterBuilderGroup || builderGroup).getBuilder(style.getZIndex(), BuilderType.TEXT);\n textReplay.setTextStyle(textStyle);\n textReplay.drawText(geometry, feature);\n }\n}\n;// CONCATENATED MODULE: ./node_modules/ol/renderer/canvas/VectorTileLayer.js\nvar VectorTileLayer_extends = undefined && undefined.__extends || function () {\n var _extendStatics = function extendStatics(d, b) {\n _extendStatics = Object.setPrototypeOf || {\n __proto__: []\n } instanceof Array && function (d, b) {\n d.__proto__ = b;\n } || function (d, b) {\n for (var p in b) {\n if (Object.prototype.hasOwnProperty.call(b, p)) d[p] = b[p];\n }\n };\n\n return _extendStatics(d, b);\n };\n\n return function (d, b) {\n _extendStatics(d, b);\n\n function __() {\n this.constructor = d;\n }\n\n d.prototype = b === null ? Object.create(b) : (__.prototype = b.prototype, new __());\n };\n}();\n/**\n * @module ol/renderer/canvas/VectorTileLayer\n */\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n/**\n * @type {!Object<string, Array<import("../../render/canvas/BuilderType.js").default>>}\n */\n\nvar IMAGE_REPLAYS = {\n \'image\': [BuilderType.POLYGON, BuilderType.CIRCLE, BuilderType.LINE_STRING, BuilderType.IMAGE, BuilderType.TEXT],\n \'hybrid\': [BuilderType.POLYGON, BuilderType.LINE_STRING],\n \'vector\': []\n};\n/**\n * @type {!Object<string, Array<import("../../render/canvas/BuilderType.js").default>>}\n */\n\nvar VECTOR_REPLAYS = {\n \'image\': [BuilderType.DEFAULT],\n \'hybrid\': [BuilderType.IMAGE, BuilderType.TEXT, BuilderType.DEFAULT],\n \'vector\': [BuilderType.POLYGON, BuilderType.CIRCLE, BuilderType.LINE_STRING, BuilderType.IMAGE, BuilderType.TEXT, BuilderType.DEFAULT]\n};\n/**\n * @classdesc\n * Canvas renderer for vector tile layers.\n * @api\n */\n\nvar CanvasVectorTileLayerRenderer =\n/** @class */\nfunction (_super) {\n VectorTileLayer_extends(CanvasVectorTileLayerRenderer, _super);\n /**\n * @param {import("../../layer/VectorTile.js").default} layer VectorTile layer.\n */\n\n\n function CanvasVectorTileLayerRenderer(layer) {\n var _this = _super.call(this, layer) || this;\n /** @private */\n\n\n _this.boundHandleStyleImageChange_ = _this.handleStyleImageChange_.bind(_this);\n /**\n * @private\n * @type {boolean}\n */\n\n _this.dirty_ = false;\n /**\n * @private\n * @type {number}\n */\n\n _this.renderedLayerRevision_;\n /**\n * @private\n * @type {import("../../transform").Transform}\n */\n\n _this.renderedPixelToCoordinateTransform_ = null;\n /**\n * @private\n * @type {number}\n */\n\n _this.renderedRotation_;\n /**\n * @private\n * @type {!Object<string, import("../../VectorRenderTile.js").default>}\n */\n\n _this.renderTileImageQueue_ = {};\n /**\n * @type {Object<string, import("../../events.js").EventsKey>}\n */\n\n _this.tileListenerKeys_ = {};\n /**\n * @private\n * @type {import("../../transform.js").Transform}\n */\n\n _this.tmpTransform_ = create();\n return _this;\n }\n /**\n * @param {import("../../VectorRenderTile.js").default} tile Tile.\n * @param {number} pixelRatio Pixel ratio.\n * @param {import("../../proj/Projection").default} projection Projection.\n * @param {boolean} queue Queue tile for rendering.\n * @return {boolean|undefined} Tile needs to be rendered.\n */\n\n\n CanvasVectorTileLayerRenderer.prototype.prepareTile = function (tile, pixelRatio, projection, queue) {\n var render;\n var tileUid = util_getUid(tile);\n var state = tile.getState();\n\n if ((state === TileState.LOADED && tile.hifi || state === TileState.ERROR) && tileUid in this.tileListenerKeys_) {\n unlistenByKey(this.tileListenerKeys_[tileUid]);\n delete this.tileListenerKeys_[tileUid];\n }\n\n if (state === TileState.LOADED || state === TileState.ERROR) {\n this.updateExecutorGroup_(tile, pixelRatio, projection);\n\n if (this.tileImageNeedsRender_(tile, pixelRatio, projection)) {\n render = true;\n\n if (queue) {\n this.renderTileImageQueue_[tileUid] = tile;\n }\n }\n }\n\n return render;\n };\n /**\n * @param {number} z Tile coordinate z.\n * @param {number} x Tile coordinate x.\n * @param {number} y Tile coordinate y.\n * @param {import("../../PluggableMap.js").FrameState} frameState Frame state.\n * @return {!import("../../Tile.js").default} Tile.\n */\n\n\n CanvasVectorTileLayerRenderer.prototype.getTile = function (z, x, y, frameState) {\n var pixelRatio = frameState.pixelRatio;\n var viewState = frameState.viewState;\n var resolution = viewState.resolution;\n var projection = viewState.projection;\n var layer = this.getLayer();\n var tile = layer.getSource().getTile(z, x, y, pixelRatio, projection);\n\n if (tile.getState() < TileState.LOADED) {\n tile.wantedResolution = resolution;\n var tileUid = util_getUid(tile);\n\n if (!(tileUid in this.tileListenerKeys_)) {\n var listenerKey = listen(tile, EventType.CHANGE, this.prepareTile.bind(this, tile, pixelRatio, projection, true));\n this.tileListenerKeys_[tileUid] = listenerKey;\n }\n } else {\n var viewHints = frameState.viewHints;\n var hifi = !(viewHints[ViewHint.ANIMATING] || viewHints[ViewHint.INTERACTING]);\n\n if (hifi || !tile.wantedResolution) {\n tile.wantedResolution = resolution;\n }\n\n var render = this.prepareTile(tile, pixelRatio, projection, false);\n\n if (render && layer.getRenderMode() !== VectorTileRenderType.VECTOR) {\n this.renderTileImage_(tile, frameState);\n }\n }\n\n return _super.prototype.getTile.call(this, z, x, y, frameState);\n };\n /**\n * @param {import("../../VectorRenderTile.js").default} tile Tile.\n * @return {boolean} Tile is drawable.\n */\n\n\n CanvasVectorTileLayerRenderer.prototype.isDrawableTile = function (tile) {\n var layer = this.getLayer();\n return _super.prototype.isDrawableTile.call(this, tile) && (layer.getRenderMode() === VectorTileRenderType.VECTOR ? util_getUid(layer) in tile.executorGroups : tile.hasContext(layer));\n };\n /**\n * @inheritDoc\n */\n\n\n CanvasVectorTileLayerRenderer.prototype.getTileImage = function (tile) {\n return tile.getImage(this.getLayer());\n };\n /**\n * Determine whether render should be called.\n * @param {import("../../PluggableMap.js").FrameState} frameState Frame state.\n * @return {boolean} Layer is ready to be rendered.\n */\n\n\n CanvasVectorTileLayerRenderer.prototype.prepareFrame = function (frameState) {\n var layerRevision = this.getLayer().getRevision();\n\n if (this.renderedLayerRevision_ != layerRevision) {\n this.renderedTiles.length = 0;\n }\n\n this.renderedLayerRevision_ = layerRevision;\n return _super.prototype.prepareFrame.call(this, frameState);\n };\n /**\n * @param {import("../../VectorRenderTile.js").default} tile Tile.\n * @param {number} pixelRatio Pixel ratio.\n * @param {import("../../proj/Projection.js").default} projection Projection.\n * @private\n */\n\n\n CanvasVectorTileLayerRenderer.prototype.updateExecutorGroup_ = function (tile, pixelRatio, projection) {\n var layer =\n /** @type {import("../../layer/VectorTile.js").default} */\n this.getLayer();\n var revision = layer.getRevision();\n var renderOrder = layer.getRenderOrder() || null;\n var resolution = tile.wantedResolution;\n var builderState = tile.getReplayState(layer);\n\n if (!builderState.dirty && builderState.renderedResolution === resolution && builderState.renderedRevision == revision && builderState.renderedRenderOrder == renderOrder && builderState.renderedZ === tile.sourceZ) {\n return;\n }\n\n var source = layer.getSource();\n var declutter = layer.getDeclutter();\n var sourceTileGrid = source.getTileGrid();\n var tileGrid = source.getTileGridForProjection(projection);\n var tileExtent = tileGrid.getTileCoordExtent(tile.wrappedTileCoord);\n var sourceTiles = source.getSourceTiles(pixelRatio, projection, tile);\n var layerUid = util_getUid(layer);\n delete tile.hitDetectionImageData[layerUid];\n tile.executorGroups[layerUid] = [];\n\n if (declutter) {\n tile.declutterExecutorGroups[layerUid] = [];\n }\n\n var _loop_1 = function _loop_1(t, tt) {\n var sourceTile = sourceTiles[t];\n\n if (sourceTile.getState() != TileState.LOADED) {\n return "continue";\n }\n\n var sourceTileCoord = sourceTile.tileCoord;\n var sourceTileExtent = sourceTileGrid.getTileCoordExtent(sourceTileCoord);\n var sharedExtent = getIntersection(tileExtent, sourceTileExtent);\n var bufferedExtent = extent_equals(sourceTileExtent, sharedExtent) ? null : buffer(sharedExtent, layer.getRenderBuffer() * resolution, this_1.tmpExtent);\n builderState.dirty = false;\n var builderGroup = new canvas_BuilderGroup(0, sharedExtent, resolution, pixelRatio);\n var declutterBuilderGroup = declutter ? new canvas_BuilderGroup(0, sharedExtent, resolution, pixelRatio) : undefined;\n var squaredTolerance = getSquaredTolerance(resolution, pixelRatio);\n /**\n * @param {import("../../Feature.js").FeatureLike} feature Feature.\n * @this {CanvasVectorTileLayerRenderer}\n */\n\n var render = function render(feature) {\n var styles;\n var styleFunction = feature.getStyleFunction() || layer.getStyleFunction();\n\n if (styleFunction) {\n styles = styleFunction(feature, resolution);\n }\n\n if (styles) {\n var dirty = this.renderFeature(feature, squaredTolerance, styles, builderGroup, declutterBuilderGroup);\n this.dirty_ = this.dirty_ || dirty;\n builderState.dirty = builderState.dirty || dirty;\n }\n };\n\n var features = sourceTile.getFeatures();\n\n if (renderOrder && renderOrder !== builderState.renderedRenderOrder) {\n features.sort(renderOrder);\n }\n\n for (var i = 0, ii = features.length; i < ii; ++i) {\n var feature = features[i];\n\n if (!bufferedExtent || intersects(bufferedExtent, feature.getGeometry().getExtent())) {\n render.call(this_1, feature);\n }\n }\n\n var executorGroupInstructions = builderGroup.finish(); // no need to clip when the render tile is covered by a single source tile\n\n var replayExtent = layer.getRenderMode() !== VectorTileRenderType.VECTOR && declutter && sourceTiles.length === 1 ? null : sharedExtent;\n var renderingReplayGroup = new canvas_ExecutorGroup(replayExtent, resolution, pixelRatio, source.getOverlaps(), executorGroupInstructions, layer.getRenderBuffer());\n tile.executorGroups[layerUid].push(renderingReplayGroup);\n\n if (declutterBuilderGroup) {\n var declutterExecutorGroup = new canvas_ExecutorGroup(replayExtent, resolution, pixelRatio, source.getOverlaps(), declutterBuilderGroup.finish(), layer.getRenderBuffer());\n tile.declutterExecutorGroups[layerUid].push(declutterExecutorGroup);\n }\n };\n\n var this_1 = this;\n\n for (var t = 0, tt = sourceTiles.length; t < tt; ++t) {\n _loop_1(t, tt);\n }\n\n builderState.renderedRevision = revision;\n builderState.renderedZ = tile.sourceZ;\n builderState.renderedRenderOrder = renderOrder;\n builderState.renderedResolution = resolution;\n };\n /**\n * @param {import("../../coordinate.js").Coordinate} coordinate Coordinate.\n * @param {import("../../PluggableMap.js").FrameState} frameState Frame state.\n * @param {number} hitTolerance Hit tolerance in pixels.\n * @param {import("../vector.js").FeatureCallback<T>} callback Feature callback.\n * @param {Array<import("../Map.js").HitMatch<T>>} matches The hit detected matches with tolerance.\n * @return {T|undefined} Callback result.\n * @template T\n */\n\n\n CanvasVectorTileLayerRenderer.prototype.forEachFeatureAtCoordinate = function (coordinate, frameState, hitTolerance, callback, matches) {\n var resolution = frameState.viewState.resolution;\n var rotation = frameState.viewState.rotation;\n hitTolerance = hitTolerance == undefined ? 0 : hitTolerance;\n var layer = this.getLayer();\n var source = layer.getSource();\n var tileGrid = source.getTileGridForProjection(frameState.viewState.projection);\n var hitExtent = boundingExtent([coordinate]);\n buffer(hitExtent, resolution * hitTolerance, hitExtent);\n /** @type {!Object<string, import("../Map.js").HitMatch<T>|true>} */\n\n var features = {};\n /**\n * @param {import("../../Feature.js").FeatureLike} feature Feature.\n * @param {import("../../geom/SimpleGeometry.js").default} geometry Geometry.\n * @param {number} distanceSq The squared distance to the click position.\n * @return {T|undefined} Callback result.\n */\n\n var featureCallback = function featureCallback(feature, geometry, distanceSq) {\n var key = feature.getId();\n\n if (key === undefined) {\n key = util_getUid(feature);\n }\n\n var match = features[key];\n\n if (!match) {\n if (distanceSq === 0) {\n features[key] = true;\n return callback(feature, layer, geometry);\n }\n\n matches.push(features[key] = {\n feature: feature,\n layer: layer,\n geometry: geometry,\n distanceSq: distanceSq,\n callback: callback\n });\n } else if (match !== true && distanceSq < match.distanceSq) {\n if (distanceSq === 0) {\n features[key] = true;\n matches.splice(matches.lastIndexOf(match), 1);\n return callback(feature, layer, geometry);\n }\n\n match.geometry = geometry;\n match.distanceSq = distanceSq;\n }\n\n return undefined;\n };\n\n var renderedTiles =\n /** @type {Array<import("../../VectorRenderTile.js").default>} */\n this.renderedTiles;\n var found;\n\n var _loop_2 = function _loop_2(i, ii) {\n var tile = renderedTiles[i];\n var tileExtent = tileGrid.getTileCoordExtent(tile.wrappedTileCoord);\n\n if (!intersects(tileExtent, hitExtent)) {\n return "continue";\n }\n\n var layerUid = util_getUid(layer);\n var executorGroups = [tile.executorGroups[layerUid]];\n var declutterExecutorGroups = tile.declutterExecutorGroups[layerUid];\n\n if (declutterExecutorGroups) {\n executorGroups.push(declutterExecutorGroups);\n }\n\n executorGroups.some(function (executorGroups) {\n var declutteredFeatures = executorGroups === declutterExecutorGroups ? frameState.declutterTree.all().map(function (item) {\n return item.value;\n }) : null;\n\n for (var t = 0, tt = executorGroups.length; t < tt; ++t) {\n var executorGroup = executorGroups[t];\n found = executorGroup.forEachFeatureAtCoordinate(coordinate, resolution, rotation, hitTolerance, featureCallback, declutteredFeatures);\n\n if (found) {\n return true;\n }\n }\n });\n };\n\n for (var i = 0, ii = renderedTiles.length; !found && i < ii; ++i) {\n _loop_2(i, ii);\n }\n\n return found;\n };\n /**\n * Asynchronous layer level hit detection.\n * @param {import("../../pixel.js").Pixel} pixel Pixel.\n * @return {Promise<Array<import("../../Feature").default>>} Promise that resolves with an array of features.\n */\n\n\n CanvasVectorTileLayerRenderer.prototype.getFeatures = function (pixel) {\n return new Promise(function (resolve, reject) {\n var layer =\n /** @type {import("../../layer/VectorTile.js").default} */\n this.getLayer();\n var layerUid = util_getUid(layer);\n var source = layer.getSource();\n var projection = this.renderedProjection;\n var projectionExtent = projection.getExtent();\n var resolution = this.renderedResolution;\n var tileGrid = source.getTileGridForProjection(projection);\n var coordinate = apply(this.renderedPixelToCoordinateTransform_, pixel.slice());\n var tileCoord = tileGrid.getTileCoordForCoordAndResolution(coordinate, resolution);\n var tile;\n\n for (var i = 0, ii = this.renderedTiles.length; i < ii; ++i) {\n if (tileCoord.toString() === this.renderedTiles[i].tileCoord.toString()) {\n tile = this.renderedTiles[i];\n\n if (tile.getState() === TileState.LOADED && tile.hifi) {\n var extent_1 = tileGrid.getTileCoordExtent(tile.tileCoord);\n\n if (source.getWrapX() && projection.canWrapX() && !containsExtent(projectionExtent, extent_1)) {\n coordinate_wrapX(coordinate, projection);\n }\n\n break;\n }\n\n tile = undefined;\n }\n }\n\n if (!tile || tile.loadingSourceTiles > 0) {\n resolve([]);\n return;\n }\n\n var extent = tileGrid.getTileCoordExtent(tile.wrappedTileCoord);\n var corner = getTopLeft(extent);\n var tilePixel = [(coordinate[0] - corner[0]) / resolution, (corner[1] - coordinate[1]) / resolution];\n var features = tile.getSourceTiles().reduce(function (accumulator, sourceTile) {\n return accumulator.concat(sourceTile.getFeatures());\n }, []);\n var hitDetectionImageData = tile.hitDetectionImageData[layerUid];\n\n if (!hitDetectionImageData && !this.animatingOrInteracting_) {\n var tileSize = toSize(tileGrid.getTileSize(tileGrid.getZForResolution(resolution)));\n var size = [tileSize[0] / 2, tileSize[1] / 2];\n var rotation = this.renderedRotation_;\n var transforms = [this.getRenderTransform(tileGrid.getTileCoordCenter(tile.wrappedTileCoord), resolution, 0, 0.5, size[0], size[1], 0)];\n hitDetectionImageData = createHitDetectionImageData(tileSize, transforms, features, layer.getStyleFunction(), tileGrid.getTileCoordExtent(tile.wrappedTileCoord), tile.getReplayState(layer).renderedResolution, rotation);\n tile.hitDetectionImageData[layerUid] = hitDetectionImageData;\n }\n\n resolve(hitDetect(tilePixel, features, hitDetectionImageData));\n }.bind(this));\n };\n /**\n * Perform action necessary to get the layer rendered after new fonts have loaded\n */\n\n\n CanvasVectorTileLayerRenderer.prototype.handleFontsChanged = function () {\n clear(this.renderTileImageQueue_);\n var layer = this.getLayer();\n\n if (layer.getVisible() && this.renderedLayerRevision_ !== undefined) {\n layer.changed();\n }\n };\n /**\n * Handle changes in image style state.\n * @param {import("../../events/Event.js").default} event Image style change event.\n * @private\n */\n\n\n CanvasVectorTileLayerRenderer.prototype.handleStyleImageChange_ = function (event) {\n this.renderIfReadyAndVisible();\n };\n /**\n * Render declutter items for this layer\n * @param {import("../../PluggableMap.js").FrameState} frameState Frame state.\n */\n\n\n CanvasVectorTileLayerRenderer.prototype.renderDeclutter = function (frameState) {\n var viewHints = frameState.viewHints;\n var hifi = !(viewHints[ViewHint.ANIMATING] || viewHints[ViewHint.INTERACTING]);\n var tiles =\n /** @type {Array<import("../../VectorRenderTile.js").default>} */\n this.renderedTiles;\n\n for (var i = 0, ii = tiles.length; i < ii; ++i) {\n var tile = tiles[i];\n var declutterExecutorGroups = tile.declutterExecutorGroups[util_getUid(this.getLayer())];\n\n if (declutterExecutorGroups) {\n for (var j = declutterExecutorGroups.length - 1; j >= 0; --j) {\n declutterExecutorGroups[j].execute(this.context, 1, this.getTileRenderTransform(tile, frameState), frameState.viewState.rotation, hifi, undefined, frameState.declutterTree);\n }\n }\n }\n };\n\n CanvasVectorTileLayerRenderer.prototype.getTileRenderTransform = function (tile, frameState) {\n var pixelRatio = frameState.pixelRatio;\n var viewState = frameState.viewState;\n var center = viewState.center;\n var resolution = viewState.resolution;\n var rotation = viewState.rotation;\n var size = frameState.size;\n var width = Math.round(size[0] * pixelRatio);\n var height = Math.round(size[1] * pixelRatio);\n var source = this.getLayer().getSource();\n var tileGrid = source.getTileGridForProjection(frameState.viewState.projection);\n var tileCoord = tile.tileCoord;\n var tileExtent = tileGrid.getTileCoordExtent(tile.wrappedTileCoord);\n var worldOffset = tileGrid.getTileCoordExtent(tileCoord, this.tmpExtent)[0] - tileExtent[0];\n var transform = multiply(scale(this.inversePixelTransform.slice(), 1 / pixelRatio, 1 / pixelRatio), this.getRenderTransform(center, resolution, rotation, pixelRatio, width, height, worldOffset));\n return transform;\n };\n /**\n * Render the layer.\n * @param {import("../../PluggableMap.js").FrameState} frameState Frame state.\n * @param {HTMLElement} target Target that may be used to render content to.\n * @return {HTMLElement} The rendered element.\n */\n\n\n CanvasVectorTileLayerRenderer.prototype.renderFrame = function (frameState, target) {\n var viewHints = frameState.viewHints;\n var hifi = !(viewHints[ViewHint.ANIMATING] || viewHints[ViewHint.INTERACTING]);\n this.renderQueuedTileImages_(hifi, frameState);\n\n _super.prototype.renderFrame.call(this, frameState, target);\n\n this.renderedPixelToCoordinateTransform_ = frameState.pixelToCoordinateTransform.slice();\n this.renderedRotation_ = frameState.viewState.rotation;\n var layer =\n /** @type {import("../../layer/VectorTile.js").default} */\n this.getLayer();\n var renderMode = layer.getRenderMode();\n\n if (renderMode === VectorTileRenderType.IMAGE) {\n return this.container;\n }\n\n var source = layer.getSource(); // Unqueue tiles from the image queue when we don\'t need any more\n\n var usedTiles = frameState.usedTiles[util_getUid(source)];\n\n for (var tileUid in this.renderTileImageQueue_) {\n if (!usedTiles || !(tileUid in usedTiles)) {\n delete this.renderTileImageQueue_[tileUid];\n }\n }\n\n var context = this.context;\n var replayTypes = VECTOR_REPLAYS[renderMode];\n var viewState = frameState.viewState;\n var rotation = viewState.rotation;\n var tiles = this.renderedTiles;\n var clips = [];\n var clipZs = [];\n\n for (var i = tiles.length - 1; i >= 0; --i) {\n var tile =\n /** @type {import("../../VectorRenderTile.js").default} */\n tiles[i];\n var transform = this.getTileRenderTransform(tile, frameState);\n var executorGroups = tile.executorGroups[util_getUid(layer)];\n var clipped = false;\n\n for (var t = 0, tt = executorGroups.length; t < tt; ++t) {\n var executorGroup = executorGroups[t];\n\n if (!executorGroup.hasExecutors(replayTypes)) {\n // sourceTile has no instructions of the types we want to render\n continue;\n }\n\n var currentZ = tile.tileCoord[0];\n var currentClip = void 0;\n\n if (!clipped) {\n currentClip = executorGroup.getClipCoords(transform);\n\n if (currentClip) {\n context.save(); // Create a clip mask for regions in this low resolution tile that are\n // already filled by a higher resolution tile\n\n for (var j = 0, jj = clips.length; j < jj; ++j) {\n var clip = clips[j];\n\n if (currentZ < clipZs[j]) {\n context.beginPath(); // counter-clockwise (outer ring) for current tile\n\n context.moveTo(currentClip[0], currentClip[1]);\n context.lineTo(currentClip[2], currentClip[3]);\n context.lineTo(currentClip[4], currentClip[5]);\n context.lineTo(currentClip[6], currentClip[7]); // clockwise (inner ring) for higher resolution tile\n\n context.moveTo(clip[6], clip[7]);\n context.lineTo(clip[4], clip[5]);\n context.lineTo(clip[2], clip[3]);\n context.lineTo(clip[0], clip[1]);\n context.clip();\n }\n }\n }\n }\n\n executorGroup.execute(context, 1, transform, rotation, hifi, replayTypes);\n\n if (!clipped && currentClip) {\n context.restore();\n clips.push(currentClip);\n clipZs.push(currentZ);\n clipped = true;\n }\n }\n }\n\n return this.container;\n };\n /**\n * @param {boolean} hifi We have time to render a high fidelity map image.\n * @param {import(\'../../PluggableMap.js\').FrameState} frameState Frame state.\n */\n\n\n CanvasVectorTileLayerRenderer.prototype.renderQueuedTileImages_ = function (hifi, frameState) {\n // When we don\'t have time to render hifi, only render tiles until we have used up\n // half of the frame budget of 16 ms\n for (var uid in this.renderTileImageQueue_) {\n if (!hifi && Date.now() - frameState.time > 8) {\n frameState.animate = true;\n break;\n }\n\n var tile = this.renderTileImageQueue_[uid];\n delete this.renderTileImageQueue_[uid];\n this.renderTileImage_(tile, frameState);\n }\n };\n /**\n * @param {import("../../Feature.js").FeatureLike} feature Feature.\n * @param {number} squaredTolerance Squared tolerance.\n * @param {import("../../style/Style.js").default|Array<import("../../style/Style.js").default>} styles The style or array of styles.\n * @param {import("../../render/canvas/BuilderGroup.js").default} builderGroup Replay group.\n * @param {import("../../render/canvas/BuilderGroup.js").default=} opt_declutterBuilderGroup Builder group for decluttering.\n * @return {boolean} `true` if an image is loading.\n */\n\n\n CanvasVectorTileLayerRenderer.prototype.renderFeature = function (feature, squaredTolerance, styles, builderGroup, opt_declutterBuilderGroup) {\n if (!styles) {\n return false;\n }\n\n var loading = false;\n\n if (Array.isArray(styles)) {\n for (var i = 0, ii = styles.length; i < ii; ++i) {\n loading = renderFeature(builderGroup, feature, styles[i], squaredTolerance, this.boundHandleStyleImageChange_, undefined, opt_declutterBuilderGroup) || loading;\n }\n } else {\n loading = renderFeature(builderGroup, feature, styles, squaredTolerance, this.boundHandleStyleImageChange_, undefined, opt_declutterBuilderGroup);\n }\n\n return loading;\n };\n /**\n * @param {import("../../VectorRenderTile.js").default} tile Tile.\n * @param {number} pixelRatio Pixel ratio.\n * @param {import("../../proj/Projection.js").default} projection Projection.\n * @return {boolean} A new tile image was rendered.\n * @private\n */\n\n\n CanvasVectorTileLayerRenderer.prototype.tileImageNeedsRender_ = function (tile, pixelRatio, projection) {\n var layer =\n /** @type {import("../../layer/VectorTile.js").default} */\n this.getLayer();\n var replayState = tile.getReplayState(layer);\n var revision = layer.getRevision();\n var sourceZ = tile.sourceZ;\n var resolution = tile.wantedResolution;\n return replayState.renderedTileResolution !== resolution || replayState.renderedTileRevision !== revision || replayState.renderedTileZ !== sourceZ;\n };\n /**\n * @param {import("../../VectorRenderTile.js").default} tile Tile.\n * @param {import("../../PluggableMap").FrameState} frameState Frame state.\n * @private\n */\n\n\n CanvasVectorTileLayerRenderer.prototype.renderTileImage_ = function (tile, frameState) {\n var layer =\n /** @type {import("../../layer/VectorTile.js").default} */\n this.getLayer();\n var replayState = tile.getReplayState(layer);\n var revision = layer.getRevision();\n var executorGroups = tile.executorGroups[util_getUid(layer)];\n replayState.renderedTileRevision = revision;\n replayState.renderedTileZ = tile.sourceZ;\n var tileCoord = tile.wrappedTileCoord;\n var z = tileCoord[0];\n var source = layer.getSource();\n var pixelRatio = frameState.pixelRatio;\n var viewState = frameState.viewState;\n var projection = viewState.projection;\n var tileGrid = source.getTileGridForProjection(projection);\n var tileResolution = tileGrid.getResolution(tile.tileCoord[0]);\n var renderPixelRatio = frameState.pixelRatio / tile.wantedResolution * tileResolution;\n var resolution = tileGrid.getResolution(z);\n var context = tile.getContext(layer); // Increase tile size when overzooming for low pixel ratio, to avoid blurry tiles\n\n pixelRatio = Math.round(Math.max(pixelRatio, renderPixelRatio / pixelRatio));\n var size = source.getTilePixelSize(z, pixelRatio, projection);\n context.canvas.width = size[0];\n context.canvas.height = size[1];\n var renderScale = pixelRatio / renderPixelRatio;\n\n if (renderScale !== 1) {\n var canvasTransform = transform_reset(this.tmpTransform_);\n scale(canvasTransform, renderScale, renderScale);\n context.setTransform.apply(context, canvasTransform);\n }\n\n var tileExtent = tileGrid.getTileCoordExtent(tileCoord, this.tmpExtent);\n var pixelScale = renderPixelRatio / resolution;\n var transform = transform_reset(this.tmpTransform_);\n scale(transform, pixelScale, -pixelScale);\n translate(transform, -tileExtent[0], -tileExtent[3]);\n\n for (var i = 0, ii = executorGroups.length; i < ii; ++i) {\n var executorGroup = executorGroups[i];\n executorGroup.execute(context, renderScale, transform, 0, true, IMAGE_REPLAYS[layer.getRenderMode()]);\n }\n\n replayState.renderedTileResolution = tile.wantedResolution;\n };\n\n return CanvasVectorTileLayerRenderer;\n}(canvas_TileLayer);\n\n/* harmony default export */ var canvas_VectorTileLayer = (CanvasVectorTileLayerRenderer);\n;// CONCATENATED MODULE: ./node_modules/ol/layer/VectorTile.js\nvar layer_VectorTile_extends = undefined && undefined.__extends || function () {\n var _extendStatics = function extendStatics(d, b) {\n _extendStatics = Object.setPrototypeOf || {\n __proto__: []\n } instanceof Array && function (d, b) {\n d.__proto__ = b;\n } || function (d, b) {\n for (var p in b) {\n if (Object.prototype.hasOwnProperty.call(b, p)) d[p] = b[p];\n }\n };\n\n return _extendStatics(d, b);\n };\n\n return function (d, b) {\n _extendStatics(d, b);\n\n function __() {\n this.constructor = d;\n }\n\n d.prototype = b === null ? Object.create(b) : (__.prototype = b.prototype, new __());\n };\n}();\n/**\n * @module ol/layer/VectorTile\n */\n\n\n\n\n\n\n\n\n/**\n * @typedef {Object} Options\n * @property {string} [className=\'ol-layer\'] A CSS class name to set to the layer element.\n * @property {number} [opacity=1] Opacity (0, 1).\n * @property {boolean} [visible=true] Visibility.\n * @property {import("../extent.js").Extent} [extent] The bounding extent for layer rendering. The layer will not be\n * rendered outside of this extent.\n * @property {number} [zIndex] The z-index for layer rendering. At rendering time, the layers\n * will be ordered, first by Z-index and then by position. When `undefined`, a `zIndex` of 0 is assumed\n * for layers that are added to the map\'s `layers` collection, or `Infinity` when the layer\'s `setMap()`\n * method was used.\n * @property {number} [minResolution] The minimum resolution (inclusive) at which this layer will be\n * visible.\n * @property {number} [maxResolution] The maximum resolution (exclusive) below which this layer will\n * be visible.\n * @property {number} [minZoom] The minimum view zoom level (exclusive) above which this layer will be\n * visible.\n * @property {number} [maxZoom] The maximum view zoom level (inclusive) at which this layer will\n * be visible.\n * @property {import("../render.js").OrderFunction} [renderOrder] Render order. Function to be used when sorting\n * features before rendering. By default features are drawn in the order that they are created. Use\n * `null` to avoid the sort, but get an undefined draw order.\n * @property {number} [renderBuffer=100] The buffer in pixels around the tile extent used by the\n * renderer when getting features from the vector tile for the rendering or hit-detection.\n * Recommended value: Vector tiles are usually generated with a buffer, so this value should match\n * the largest possible buffer of the used tiles. It should be at least the size of the largest\n * point symbol or line width.\n * @property {import("./VectorTileRenderType.js").default|string} [renderMode=\'hybrid\'] Render mode for vector tiles:\n * * `\'image\'`: Vector tiles are rendered as images. Only available when `declutter` is set to `false` (default).\n * Otherwise, `\'hybrid\'` mode will used instead. Great performance, but point symbols and texts\n * are always rotated with the view and pixels are scaled during zoom animations. Labels and point symbols will\n * get cut off at tile boundaries.\n * * `\'hybrid\'`: Polygon and line elements are rendered as images, so pixels are scaled during zoom\n * animations. Point symbols and texts are accurately rendered as vectors and can stay upright on\n * rotated views.\n * * `\'vector\'`: Everything is rendered as vectors. Use this mode for improved performance on vector\n * tile layers with only a few rendered features (e.g. for highlighting a subset of features of\n * another layer with the same source).\n * @property {import("../source/VectorTile.js").default} [source] Source.\n * @property {import("../PluggableMap.js").default} [map] Sets the layer as overlay on a map. The map will not manage\n * this layer in its layers collection, and the layer will be rendered on top. This is useful for\n * temporary layers. The standard way to add a layer to a map and have it managed by the map is to\n * use {@link module:ol/Map#addLayer}.\n * @property {boolean} [declutter=false] Declutter images and text. Decluttering is applied to all\n * image and text styles of all Vector and VectorTile layers that have set this to `true`. The priority\n * is defined by the z-index of the layer, the `zIndex` of the style and the render order of features.\n * Higher z-index means higher priority. Within the same z-index, a feature rendered before another has\n * higher priority.\n * @property {import("../style/Style.js").StyleLike} [style] Layer style. See\n * {@link module:ol/style} for default style which will be used if this is not defined.\n * @property {boolean} [updateWhileAnimating=false] When set to `true`, feature batches will be\n * recreated during animations. This means that no vectors will be shown clipped, but the setting\n * will have a performance impact for large amounts of vector data. When set to `false`, batches\n * will be recreated when no animation is active.\n * @property {boolean} [updateWhileInteracting=false] When set to `true`, feature batches will be\n * recreated during interactions. See also `updateWhileAnimating`.\n * @property {number} [preload=0] Preload. Load low-resolution tiles up to `preload` levels. `0`\n * means no preloading.\n * @property {boolean} [useInterimTilesOnError=true] Use interim tiles on error.\n */\n\n/**\n * @classdesc\n * Layer for vector tile data that is rendered client-side.\n * Note that any property set in the options is set as a {@link module:ol/Object~BaseObject}\n * property on the layer object; for example, setting `title: \'My Title\'` in the\n * options means that `title` is observable, and has get/set accessors.\n *\n * @param {Options=} opt_options Options.\n * @extends {BaseVectorLayer<import("../source/VectorTile.js").default>}\n * @api\n */\n\nvar VectorTileLayer =\n/** @class */\nfunction (_super) {\n layer_VectorTile_extends(VectorTileLayer, _super);\n /**\n * @param {Options=} opt_options Options.\n */\n\n\n function VectorTileLayer(opt_options) {\n var _this = this;\n\n var options = opt_options ? opt_options : {};\n var baseOptions =\n /** @type {Object} */\n obj_assign({}, options);\n delete baseOptions.preload;\n delete baseOptions.useInterimTilesOnError;\n _this = _super.call(this,\n /** @type {import("./BaseVector.js").Options} */\n baseOptions) || this;\n var renderMode = options.renderMode || VectorTileRenderType.HYBRID;\n asserts_assert(renderMode == undefined || renderMode == VectorTileRenderType.IMAGE || renderMode == VectorTileRenderType.HYBRID || renderMode == VectorTileRenderType.VECTOR, 28); // `renderMode` must be `\'image\'`, `\'hybrid\'` or `\'vector\'`.\n\n /**\n * @private\n * @type {import("./VectorTileRenderType.js").default}\n */\n\n _this.renderMode_ = renderMode;\n\n _this.setPreload(options.preload ? options.preload : 0);\n\n _this.setUseInterimTilesOnError(options.useInterimTilesOnError !== undefined ? options.useInterimTilesOnError : true);\n\n return _this;\n }\n /**\n * Create a renderer for this layer.\n * @return {import("../renderer/Layer.js").default} A layer renderer.\n * @protected\n */\n\n\n VectorTileLayer.prototype.createRenderer = function () {\n return new canvas_VectorTileLayer(this);\n };\n /**\n * Get the topmost feature that intersects the given pixel on the viewport. Returns a promise\n * that resolves with an array of features. The array will either contain the topmost feature\n * when a hit was detected, or it will be empty.\n *\n * The hit detection algorithm used for this method is optimized for performance, but is less\n * accurate than the one used in {@link import("../PluggableMap.js").default#getFeaturesAtPixel}: Text\n * is not considered, and icons are only represented by their bounding box instead of the exact\n * image.\n *\n * @param {import("../pixel.js").Pixel} pixel Pixel.\n * @return {Promise<Array<import("../Feature").default>>} Promise that resolves with an array of features.\n * @api\n */\n\n\n VectorTileLayer.prototype.getFeatures = function (pixel) {\n return _super.prototype.getFeatures.call(this, pixel);\n };\n /**\n * @return {import("./VectorTileRenderType.js").default} The render mode.\n */\n\n\n VectorTileLayer.prototype.getRenderMode = function () {\n return this.renderMode_;\n };\n /**\n * Return the level as number to which we will preload tiles up to.\n * @return {number} The level to preload tiles up to.\n * @observable\n * @api\n */\n\n\n VectorTileLayer.prototype.getPreload = function () {\n return (\n /** @type {number} */\n this.get(TileProperty.PRELOAD)\n );\n };\n /**\n * Whether we use interim tiles on error.\n * @return {boolean} Use interim tiles on error.\n * @observable\n * @api\n */\n\n\n VectorTileLayer.prototype.getUseInterimTilesOnError = function () {\n return (\n /** @type {boolean} */\n this.get(TileProperty.USE_INTERIM_TILES_ON_ERROR)\n );\n };\n /**\n * Set the level as number to which we will preload tiles up to.\n * @param {number} preload The level to preload tiles up to.\n * @observable\n * @api\n */\n\n\n VectorTileLayer.prototype.setPreload = function (preload) {\n this.set(TileProperty.PRELOAD, preload);\n };\n /**\n * Set whether we use interim tiles on error.\n * @param {boolean} useInterimTilesOnError Use interim tiles on error.\n * @observable\n * @api\n */\n\n\n VectorTileLayer.prototype.setUseInterimTilesOnError = function (useInterimTilesOnError) {\n this.set(TileProperty.USE_INTERIM_TILES_ON_ERROR, useInterimTilesOnError);\n };\n\n return VectorTileLayer;\n}(BaseVector);\n\n/* harmony default export */ var layer_VectorTile = (VectorTileLayer);\n;// CONCATENATED MODULE: ./node_modules/ol/format/Feature.js\n/**\n * @module ol/format/Feature\n */\n\n\n\n\n/**\n * @typedef {Object} ReadOptions\n * @property {import("../proj.js").ProjectionLike} [dataProjection] Projection of the data we are reading.\n * If not provided, the projection will be derived from the data (where possible) or\n * the `dataProjection` of the format is assigned (where set). If the projection\n * can not be derived from the data and if no `dataProjection` is set for a format,\n * the features will not be reprojected.\n * @property {import("../extent.js").Extent} [extent] Tile extent in map units of the tile being read.\n * This is only required when reading data with tile pixels as geometry units. When configured,\n * a `dataProjection` with `TILE_PIXELS` as `units` and the tile\'s pixel extent as `extent` needs to be\n * provided.\n * @property {import("../proj.js").ProjectionLike} [featureProjection] Projection of the feature geometries\n * created by the format reader. If not provided, features will be returned in the\n * `dataProjection`.\n */\n\n/**\n * @typedef {Object} WriteOptions\n * @property {import("../proj.js").ProjectionLike} [dataProjection] Projection of the data we are writing.\n * If not provided, the `dataProjection` of the format is assigned (where set).\n * If no `dataProjection` is set for a format, the features will be returned\n * in the `featureProjection`.\n * @property {import("../proj.js").ProjectionLike} [featureProjection] Projection of the feature geometries\n * that will be serialized by the format writer. If not provided, geometries are assumed\n * to be in the `dataProjection` if that is set; in other words, they are not transformed.\n * @property {boolean} [rightHanded] When writing geometries, follow the right-hand\n * rule for linear ring orientation. This means that polygons will have counter-clockwise\n * exterior rings and clockwise interior rings. By default, coordinates are serialized\n * as they are provided at construction. If `true`, the right-hand rule will\n * be applied. If `false`, the left-hand rule will be applied (clockwise for\n * exterior and counter-clockwise for interior rings). Note that not all\n * formats support this. The GeoJSON format does use this property when writing\n * geometries.\n * @property {number} [decimals] Maximum number of decimal places for coordinates.\n * Coordinates are stored internally as floats, but floating-point arithmetic can create\n * coordinates with a large number of decimal places, not generally wanted on output.\n * Set a number here to round coordinates. Can also be used to ensure that\n * coordinates read in can be written back out with the same number of decimals.\n * Default is no rounding.\n */\n\n/**\n * @classdesc\n * Abstract base class; normally only used for creating subclasses and not\n * instantiated in apps.\n * Base class for feature formats.\n * {@link module:ol/format/Feature~FeatureFormat} subclasses provide the ability to decode and encode\n * {@link module:ol/Feature~Feature} objects from a variety of commonly used geospatial\n * file formats. See the documentation for each format for more details.\n *\n * @abstract\n * @api\n */\n\nvar FeatureFormat =\n/** @class */\nfunction () {\n function FeatureFormat() {\n /**\n * @protected\n * @type {import("../proj/Projection.js").default}\n */\n this.dataProjection = null;\n /**\n * @protected\n * @type {import("../proj/Projection.js").default}\n */\n\n this.defaultFeatureProjection = null;\n }\n /**\n * Adds the data projection to the read options.\n * @param {Document|Element|Object|string} source Source.\n * @param {ReadOptions=} opt_options Options.\n * @return {ReadOptions|undefined} Options.\n * @protected\n */\n\n\n FeatureFormat.prototype.getReadOptions = function (source, opt_options) {\n var options;\n\n if (opt_options) {\n var dataProjection = opt_options.dataProjection ? proj_get(opt_options.dataProjection) : this.readProjection(source);\n\n if (opt_options.extent && dataProjection && dataProjection.getUnits() === proj_Units.TILE_PIXELS) {\n dataProjection = proj_get(dataProjection);\n dataProjection.setWorldExtent(opt_options.extent);\n }\n\n options = {\n dataProjection: dataProjection,\n featureProjection: opt_options.featureProjection\n };\n }\n\n return this.adaptOptions(options);\n };\n /**\n * Sets the `dataProjection` on the options, if no `dataProjection`\n * is set.\n * @param {WriteOptions|ReadOptions|undefined} options\n * Options.\n * @protected\n * @return {WriteOptions|ReadOptions|undefined}\n * Updated options.\n */\n\n\n FeatureFormat.prototype.adaptOptions = function (options) {\n return obj_assign({\n dataProjection: this.dataProjection,\n featureProjection: this.defaultFeatureProjection\n }, options);\n };\n /**\n * @abstract\n * @return {import("./FormatType.js").default} Format.\n */\n\n\n FeatureFormat.prototype.getType = function () {\n return util_abstract();\n };\n /**\n * Read a single feature from a source.\n *\n * @abstract\n * @param {Document|Element|Object|string} source Source.\n * @param {ReadOptions=} opt_options Read options.\n * @return {import("../Feature.js").FeatureLike} Feature.\n */\n\n\n FeatureFormat.prototype.readFeature = function (source, opt_options) {\n return util_abstract();\n };\n /**\n * Read all features from a source.\n *\n * @abstract\n * @param {Document|Element|ArrayBuffer|Object|string} source Source.\n * @param {ReadOptions=} opt_options Read options.\n * @return {Array<import("../Feature.js").FeatureLike>} Features.\n */\n\n\n FeatureFormat.prototype.readFeatures = function (source, opt_options) {\n return util_abstract();\n };\n /**\n * Read a single geometry from a source.\n *\n * @abstract\n * @param {Document|Element|Object|string} source Source.\n * @param {ReadOptions=} opt_options Read options.\n * @return {import("../geom/Geometry.js").default} Geometry.\n */\n\n\n FeatureFormat.prototype.readGeometry = function (source, opt_options) {\n return util_abstract();\n };\n /**\n * Read the projection from a source.\n *\n * @abstract\n * @param {Document|Element|Object|string} source Source.\n * @return {import("../proj/Projection.js").default} Projection.\n */\n\n\n FeatureFormat.prototype.readProjection = function (source) {\n return util_abstract();\n };\n /**\n * Encode a feature in this format.\n *\n * @abstract\n * @param {import("../Feature.js").default} feature Feature.\n * @param {WriteOptions=} opt_options Write options.\n * @return {string} Result.\n */\n\n\n FeatureFormat.prototype.writeFeature = function (feature, opt_options) {\n return util_abstract();\n };\n /**\n * Encode an array of features in this format.\n *\n * @abstract\n * @param {Array<import("../Feature.js").default>} features Features.\n * @param {WriteOptions=} opt_options Write options.\n * @return {string} Result.\n */\n\n\n FeatureFormat.prototype.writeFeatures = function (features, opt_options) {\n return util_abstract();\n };\n /**\n * Write a single geometry in this format.\n *\n * @abstract\n * @param {import("../geom/Geometry.js").default} geometry Geometry.\n * @param {WriteOptions=} opt_options Write options.\n * @return {string} Result.\n */\n\n\n FeatureFormat.prototype.writeGeometry = function (geometry, opt_options) {\n return util_abstract();\n };\n\n return FeatureFormat;\n}();\n\n/* harmony default export */ var Feature = (FeatureFormat);\n/**\n * @param {import("../geom/Geometry.js").default} geometry Geometry.\n * @param {boolean} write Set to true for writing, false for reading.\n * @param {(WriteOptions|ReadOptions)=} opt_options Options.\n * @return {import("../geom/Geometry.js").default} Transformed geometry.\n */\n\nfunction transformGeometryWithOptions(geometry, write, opt_options) {\n var featureProjection = opt_options ? proj_get(opt_options.featureProjection) : null;\n var dataProjection = opt_options ? proj_get(opt_options.dataProjection) : null;\n var transformed;\n\n if (featureProjection && dataProjection && !equivalent(featureProjection, dataProjection)) {\n transformed = (write ? geometry.clone() : geometry).transform(write ? featureProjection : dataProjection, write ? dataProjection : featureProjection);\n } else {\n transformed = geometry;\n }\n\n if (write && opt_options &&\n /** @type {WriteOptions} */\n opt_options.decimals !== undefined) {\n var power_1 = Math.pow(10,\n /** @type {WriteOptions} */\n opt_options.decimals); // if decimals option on write, round each coordinate appropriately\n\n /**\n * @param {Array<number>} coordinates Coordinates.\n * @return {Array<number>} Transformed coordinates.\n */\n\n var transform = function transform(coordinates) {\n for (var i = 0, ii = coordinates.length; i < ii; ++i) {\n coordinates[i] = Math.round(coordinates[i] * power_1) / power_1;\n }\n\n return coordinates;\n };\n\n if (transformed === geometry) {\n transformed = geometry.clone();\n }\n\n transformed.applyTransform(transform);\n }\n\n return transformed;\n}\n/**\n * @param {import("../extent.js").Extent} extent Extent.\n * @param {ReadOptions=} opt_options Read options.\n * @return {import("../extent.js").Extent} Transformed extent.\n */\n\nfunction transformExtentWithOptions(extent, opt_options) {\n var featureProjection = opt_options ? getProjection(opt_options.featureProjection) : null;\n var dataProjection = opt_options ? getProjection(opt_options.dataProjection) : null;\n\n if (featureProjection && dataProjection && !equivalentProjection(featureProjection, dataProjection)) {\n return transformExtent(extent, dataProjection, featureProjection);\n } else {\n return extent;\n }\n}\n;// CONCATENATED MODULE: ./node_modules/ol/geom/flat/interpolate.js\n/**\n * @module ol/geom/flat/interpolate\n */\n\n\n/**\n * @param {Array<number>} flatCoordinates Flat coordinates.\n * @param {number} offset Offset.\n * @param {number} end End.\n * @param {number} stride Stride.\n * @param {number} fraction Fraction.\n * @param {Array<number>=} opt_dest Destination.\n * @param {number=} opt_dimension Destination dimension (default is `2`)\n * @return {Array<number>} Destination.\n */\n\nfunction interpolatePoint(flatCoordinates, offset, end, stride, fraction, opt_dest, opt_dimension) {\n var o, t;\n var n = (end - offset) / stride;\n\n if (n === 1) {\n o = offset;\n } else if (n === 2) {\n o = offset;\n t = fraction;\n } else if (n !== 0) {\n var x1 = flatCoordinates[offset];\n var y1 = flatCoordinates[offset + 1];\n var length_1 = 0;\n var cumulativeLengths = [0];\n\n for (var i = offset + stride; i < end; i += stride) {\n var x2 = flatCoordinates[i];\n var y2 = flatCoordinates[i + 1];\n length_1 += Math.sqrt((x2 - x1) * (x2 - x1) + (y2 - y1) * (y2 - y1));\n cumulativeLengths.push(length_1);\n x1 = x2;\n y1 = y2;\n }\n\n var target = fraction * length_1;\n var index = binarySearch(cumulativeLengths, target);\n\n if (index < 0) {\n t = (target - cumulativeLengths[-index - 2]) / (cumulativeLengths[-index - 1] - cumulativeLengths[-index - 2]);\n o = offset + (-index - 2) * stride;\n } else {\n o = offset + index * stride;\n }\n }\n\n var dimension = opt_dimension > 1 ? opt_dimension : 2;\n var dest = opt_dest ? opt_dest : new Array(dimension);\n\n for (var i = 0; i < dimension; ++i) {\n dest[i] = o === undefined ? NaN : t === undefined ? flatCoordinates[o + i] : lerp(flatCoordinates[o + i], flatCoordinates[o + stride + i], t);\n }\n\n return dest;\n}\n/**\n * @param {Array<number>} flatCoordinates Flat coordinates.\n * @param {number} offset Offset.\n * @param {number} end End.\n * @param {number} stride Stride.\n * @param {number} m M.\n * @param {boolean} extrapolate Extrapolate.\n * @return {import("../../coordinate.js").Coordinate} Coordinate.\n */\n\nfunction lineStringCoordinateAtM(flatCoordinates, offset, end, stride, m, extrapolate) {\n if (end == offset) {\n return null;\n }\n\n var coordinate;\n\n if (m < flatCoordinates[offset + stride - 1]) {\n if (extrapolate) {\n coordinate = flatCoordinates.slice(offset, offset + stride);\n coordinate[stride - 1] = m;\n return coordinate;\n } else {\n return null;\n }\n } else if (flatCoordinates[end - 1] < m) {\n if (extrapolate) {\n coordinate = flatCoordinates.slice(end - stride, end);\n coordinate[stride - 1] = m;\n return coordinate;\n } else {\n return null;\n }\n } // FIXME use O(1) search\n\n\n if (m == flatCoordinates[offset + stride - 1]) {\n return flatCoordinates.slice(offset, offset + stride);\n }\n\n var lo = offset / stride;\n var hi = end / stride;\n\n while (lo < hi) {\n var mid = lo + hi >> 1;\n\n if (m < flatCoordinates[(mid + 1) * stride - 1]) {\n hi = mid;\n } else {\n lo = mid + 1;\n }\n }\n\n var m0 = flatCoordinates[lo * stride - 1];\n\n if (m == m0) {\n return flatCoordinates.slice((lo - 1) * stride, (lo - 1) * stride + stride);\n }\n\n var m1 = flatCoordinates[(lo + 1) * stride - 1];\n var t = (m - m0) / (m1 - m0);\n coordinate = [];\n\n for (var i = 0; i < stride - 1; ++i) {\n coordinate.push(lerp(flatCoordinates[(lo - 1) * stride + i], flatCoordinates[lo * stride + i], t));\n }\n\n coordinate.push(m);\n return coordinate;\n}\n/**\n * @param {Array<number>} flatCoordinates Flat coordinates.\n * @param {number} offset Offset.\n * @param {Array<number>} ends Ends.\n * @param {number} stride Stride.\n * @param {number} m M.\n * @param {boolean} extrapolate Extrapolate.\n * @param {boolean} interpolate Interpolate.\n * @return {import("../../coordinate.js").Coordinate} Coordinate.\n */\n\nfunction lineStringsCoordinateAtM(flatCoordinates, offset, ends, stride, m, extrapolate, interpolate) {\n if (interpolate) {\n return lineStringCoordinateAtM(flatCoordinates, offset, ends[ends.length - 1], stride, m, extrapolate);\n }\n\n var coordinate;\n\n if (m < flatCoordinates[stride - 1]) {\n if (extrapolate) {\n coordinate = flatCoordinates.slice(0, stride);\n coordinate[stride - 1] = m;\n return coordinate;\n } else {\n return null;\n }\n }\n\n if (flatCoordinates[flatCoordinates.length - 1] < m) {\n if (extrapolate) {\n coordinate = flatCoordinates.slice(flatCoordinates.length - stride);\n coordinate[stride - 1] = m;\n return coordinate;\n } else {\n return null;\n }\n }\n\n for (var i = 0, ii = ends.length; i < ii; ++i) {\n var end = ends[i];\n\n if (offset == end) {\n continue;\n }\n\n if (m < flatCoordinates[offset + stride - 1]) {\n return null;\n } else if (m <= flatCoordinates[end - 1]) {\n return lineStringCoordinateAtM(flatCoordinates, offset, end, stride, m, false);\n }\n\n offset = end;\n }\n\n return null;\n}\n;// CONCATENATED MODULE: ./node_modules/ol/geom/LineString.js\nvar LineString_extends = undefined && undefined.__extends || function () {\n var _extendStatics = function extendStatics(d, b) {\n _extendStatics = Object.setPrototypeOf || {\n __proto__: []\n } instanceof Array && function (d, b) {\n d.__proto__ = b;\n } || function (d, b) {\n for (var p in b) {\n if (Object.prototype.hasOwnProperty.call(b, p)) d[p] = b[p];\n }\n };\n\n return _extendStatics(d, b);\n };\n\n return function (d, b) {\n _extendStatics(d, b);\n\n function __() {\n this.constructor = d;\n }\n\n d.prototype = b === null ? Object.create(b) : (__.prototype = b.prototype, new __());\n };\n}();\n/**\n * @module ol/geom/LineString\n */\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n/**\n * @classdesc\n * Linestring geometry.\n *\n * @api\n */\n\nvar LineString =\n/** @class */\nfunction (_super) {\n LineString_extends(LineString, _super);\n /**\n * @param {Array<import("../coordinate.js").Coordinate>|Array<number>} coordinates Coordinates.\n * For internal use, flat coordinates in combination with `opt_layout` are also accepted.\n * @param {import("./GeometryLayout.js").default=} opt_layout Layout.\n */\n\n\n function LineString(coordinates, opt_layout) {\n var _this = _super.call(this) || this;\n /**\n * @private\n * @type {import("../coordinate.js").Coordinate}\n */\n\n\n _this.flatMidpoint_ = null;\n /**\n * @private\n * @type {number}\n */\n\n _this.flatMidpointRevision_ = -1;\n /**\n * @private\n * @type {number}\n */\n\n _this.maxDelta_ = -1;\n /**\n * @private\n * @type {number}\n */\n\n _this.maxDeltaRevision_ = -1;\n\n if (opt_layout !== undefined && !Array.isArray(coordinates[0])) {\n _this.setFlatCoordinates(opt_layout,\n /** @type {Array<number>} */\n coordinates);\n } else {\n _this.setCoordinates(\n /** @type {Array<import("../coordinate.js").Coordinate>} */\n coordinates, opt_layout);\n }\n\n return _this;\n }\n /**\n * Append the passed coordinate to the coordinates of the linestring.\n * @param {import("../coordinate.js").Coordinate} coordinate Coordinate.\n * @api\n */\n\n\n LineString.prototype.appendCoordinate = function (coordinate) {\n if (!this.flatCoordinates) {\n this.flatCoordinates = coordinate.slice();\n } else {\n array_extend(this.flatCoordinates, coordinate);\n }\n\n this.changed();\n };\n /**\n * Make a complete copy of the geometry.\n * @return {!LineString} Clone.\n * @api\n */\n\n\n LineString.prototype.clone = function () {\n var lineString = new LineString(this.flatCoordinates.slice(), this.layout);\n lineString.applyProperties(this);\n return lineString;\n };\n /**\n * @param {number} x X.\n * @param {number} y Y.\n * @param {import("../coordinate.js").Coordinate} closestPoint Closest point.\n * @param {number} minSquaredDistance Minimum squared distance.\n * @return {number} Minimum squared distance.\n */\n\n\n LineString.prototype.closestPointXY = function (x, y, closestPoint, minSquaredDistance) {\n if (minSquaredDistance < closestSquaredDistanceXY(this.getExtent(), x, y)) {\n return minSquaredDistance;\n }\n\n if (this.maxDeltaRevision_ != this.getRevision()) {\n this.maxDelta_ = Math.sqrt(maxSquaredDelta(this.flatCoordinates, 0, this.flatCoordinates.length, this.stride, 0));\n this.maxDeltaRevision_ = this.getRevision();\n }\n\n return assignClosestPoint(this.flatCoordinates, 0, this.flatCoordinates.length, this.stride, this.maxDelta_, false, x, y, closestPoint, minSquaredDistance);\n };\n /**\n * Iterate over each segment, calling the provided callback.\n * If the callback returns a truthy value the function returns that\n * value immediately. Otherwise the function returns `false`.\n *\n * @param {function(this: S, import("../coordinate.js").Coordinate, import("../coordinate.js").Coordinate): T} callback Function\n * called for each segment. The function will receive two arguments, the start and end coordinates of the segment.\n * @return {T|boolean} Value.\n * @template T,S\n * @api\n */\n\n\n LineString.prototype.forEachSegment = function (callback) {\n return forEach(this.flatCoordinates, 0, this.flatCoordinates.length, this.stride, callback);\n };\n /**\n * Returns the coordinate at `m` using linear interpolation, or `null` if no\n * such coordinate exists.\n *\n * `opt_extrapolate` controls extrapolation beyond the range of Ms in the\n * MultiLineString. If `opt_extrapolate` is `true` then Ms less than the first\n * M will return the first coordinate and Ms greater than the last M will\n * return the last coordinate.\n *\n * @param {number} m M.\n * @param {boolean=} opt_extrapolate Extrapolate. Default is `false`.\n * @return {import("../coordinate.js").Coordinate} Coordinate.\n * @api\n */\n\n\n LineString.prototype.getCoordinateAtM = function (m, opt_extrapolate) {\n if (this.layout != geom_GeometryLayout.XYM && this.layout != geom_GeometryLayout.XYZM) {\n return null;\n }\n\n var extrapolate = opt_extrapolate !== undefined ? opt_extrapolate : false;\n return lineStringCoordinateAtM(this.flatCoordinates, 0, this.flatCoordinates.length, this.stride, m, extrapolate);\n };\n /**\n * Return the coordinates of the linestring.\n * @return {Array<import("../coordinate.js").Coordinate>} Coordinates.\n * @api\n */\n\n\n LineString.prototype.getCoordinates = function () {\n return inflateCoordinates(this.flatCoordinates, 0, this.flatCoordinates.length, this.stride);\n };\n /**\n * Return the coordinate at the provided fraction along the linestring.\n * The `fraction` is a number between 0 and 1, where 0 is the start of the\n * linestring and 1 is the end.\n * @param {number} fraction Fraction.\n * @param {import("../coordinate.js").Coordinate=} opt_dest Optional coordinate whose values will\n * be modified. If not provided, a new coordinate will be returned.\n * @return {import("../coordinate.js").Coordinate} Coordinate of the interpolated point.\n * @api\n */\n\n\n LineString.prototype.getCoordinateAt = function (fraction, opt_dest) {\n return interpolatePoint(this.flatCoordinates, 0, this.flatCoordinates.length, this.stride, fraction, opt_dest, this.stride);\n };\n /**\n * Return the length of the linestring on projected plane.\n * @return {number} Length (on projected plane).\n * @api\n */\n\n\n LineString.prototype.getLength = function () {\n return lineStringLength(this.flatCoordinates, 0, this.flatCoordinates.length, this.stride);\n };\n /**\n * @return {Array<number>} Flat midpoint.\n */\n\n\n LineString.prototype.getFlatMidpoint = function () {\n if (this.flatMidpointRevision_ != this.getRevision()) {\n this.flatMidpoint_ = this.getCoordinateAt(0.5, this.flatMidpoint_);\n this.flatMidpointRevision_ = this.getRevision();\n }\n\n return this.flatMidpoint_;\n };\n /**\n * @param {number} squaredTolerance Squared tolerance.\n * @return {LineString} Simplified LineString.\n * @protected\n */\n\n\n LineString.prototype.getSimplifiedGeometryInternal = function (squaredTolerance) {\n var simplifiedFlatCoordinates = [];\n simplifiedFlatCoordinates.length = douglasPeucker(this.flatCoordinates, 0, this.flatCoordinates.length, this.stride, squaredTolerance, simplifiedFlatCoordinates, 0);\n return new LineString(simplifiedFlatCoordinates, geom_GeometryLayout.XY);\n };\n /**\n * Get the type of this geometry.\n * @return {import("./GeometryType.js").default} Geometry type.\n * @api\n */\n\n\n LineString.prototype.getType = function () {\n return geom_GeometryType.LINE_STRING;\n };\n /**\n * Test if the geometry and the passed extent intersect.\n * @param {import("../extent.js").Extent} extent Extent.\n * @return {boolean} `true` if the geometry and the extent intersect.\n * @api\n */\n\n\n LineString.prototype.intersectsExtent = function (extent) {\n return intersectsLineString(this.flatCoordinates, 0, this.flatCoordinates.length, this.stride, extent);\n };\n /**\n * Set the coordinates of the linestring.\n * @param {!Array<import("../coordinate.js").Coordinate>} coordinates Coordinates.\n * @param {import("./GeometryLayout.js").default=} opt_layout Layout.\n * @api\n */\n\n\n LineString.prototype.setCoordinates = function (coordinates, opt_layout) {\n this.setLayout(opt_layout, coordinates, 1);\n\n if (!this.flatCoordinates) {\n this.flatCoordinates = [];\n }\n\n this.flatCoordinates.length = deflateCoordinates(this.flatCoordinates, 0, coordinates, this.stride);\n this.changed();\n };\n\n return LineString;\n}(geom_SimpleGeometry);\n\n/* harmony default export */ var geom_LineString = (LineString);\n;// CONCATENATED MODULE: ./node_modules/ol/geom/MultiLineString.js\nvar MultiLineString_extends = undefined && undefined.__extends || function () {\n var _extendStatics = function extendStatics(d, b) {\n _extendStatics = Object.setPrototypeOf || {\n __proto__: []\n } instanceof Array && function (d, b) {\n d.__proto__ = b;\n } || function (d, b) {\n for (var p in b) {\n if (Object.prototype.hasOwnProperty.call(b, p)) d[p] = b[p];\n }\n };\n\n return _extendStatics(d, b);\n };\n\n return function (d, b) {\n _extendStatics(d, b);\n\n function __() {\n this.constructor = d;\n }\n\n d.prototype = b === null ? Object.create(b) : (__.prototype = b.prototype, new __());\n };\n}();\n/**\n * @module ol/geom/MultiLineString\n */\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n/**\n * @classdesc\n * Multi-linestring geometry.\n *\n * @api\n */\n\nvar MultiLineString =\n/** @class */\nfunction (_super) {\n MultiLineString_extends(MultiLineString, _super);\n /**\n * @param {Array<Array<import("../coordinate.js").Coordinate>|LineString>|Array<number>} coordinates\n * Coordinates or LineString geometries. (For internal use, flat coordinates in\n * combination with `opt_layout` and `opt_ends` are also accepted.)\n * @param {import("./GeometryLayout.js").default=} opt_layout Layout.\n * @param {Array<number>=} opt_ends Flat coordinate ends for internal use.\n */\n\n\n function MultiLineString(coordinates, opt_layout, opt_ends) {\n var _this = _super.call(this) || this;\n /**\n * @type {Array<number>}\n * @private\n */\n\n\n _this.ends_ = [];\n /**\n * @private\n * @type {number}\n */\n\n _this.maxDelta_ = -1;\n /**\n * @private\n * @type {number}\n */\n\n _this.maxDeltaRevision_ = -1;\n\n if (Array.isArray(coordinates[0])) {\n _this.setCoordinates(\n /** @type {Array<Array<import("../coordinate.js").Coordinate>>} */\n coordinates, opt_layout);\n } else if (opt_layout !== undefined && opt_ends) {\n _this.setFlatCoordinates(opt_layout,\n /** @type {Array<number>} */\n coordinates);\n\n _this.ends_ = opt_ends;\n } else {\n var layout = _this.getLayout();\n\n var lineStrings =\n /** @type {Array<LineString>} */\n coordinates;\n var flatCoordinates = [];\n var ends = [];\n\n for (var i = 0, ii = lineStrings.length; i < ii; ++i) {\n var lineString = lineStrings[i];\n\n if (i === 0) {\n layout = lineString.getLayout();\n }\n\n array_extend(flatCoordinates, lineString.getFlatCoordinates());\n ends.push(flatCoordinates.length);\n }\n\n _this.setFlatCoordinates(layout, flatCoordinates);\n\n _this.ends_ = ends;\n }\n\n return _this;\n }\n /**\n * Append the passed linestring to the multilinestring.\n * @param {LineString} lineString LineString.\n * @api\n */\n\n\n MultiLineString.prototype.appendLineString = function (lineString) {\n if (!this.flatCoordinates) {\n this.flatCoordinates = lineString.getFlatCoordinates().slice();\n } else {\n array_extend(this.flatCoordinates, lineString.getFlatCoordinates().slice());\n }\n\n this.ends_.push(this.flatCoordinates.length);\n this.changed();\n };\n /**\n * Make a complete copy of the geometry.\n * @return {!MultiLineString} Clone.\n * @api\n */\n\n\n MultiLineString.prototype.clone = function () {\n var multiLineString = new MultiLineString(this.flatCoordinates.slice(), this.layout, this.ends_.slice());\n multiLineString.applyProperties(this);\n return multiLineString;\n };\n /**\n * @param {number} x X.\n * @param {number} y Y.\n * @param {import("../coordinate.js").Coordinate} closestPoint Closest point.\n * @param {number} minSquaredDistance Minimum squared distance.\n * @return {number} Minimum squared distance.\n */\n\n\n MultiLineString.prototype.closestPointXY = function (x, y, closestPoint, minSquaredDistance) {\n if (minSquaredDistance < closestSquaredDistanceXY(this.getExtent(), x, y)) {\n return minSquaredDistance;\n }\n\n if (this.maxDeltaRevision_ != this.getRevision()) {\n this.maxDelta_ = Math.sqrt(arrayMaxSquaredDelta(this.flatCoordinates, 0, this.ends_, this.stride, 0));\n this.maxDeltaRevision_ = this.getRevision();\n }\n\n return assignClosestArrayPoint(this.flatCoordinates, 0, this.ends_, this.stride, this.maxDelta_, false, x, y, closestPoint, minSquaredDistance);\n };\n /**\n * Returns the coordinate at `m` using linear interpolation, or `null` if no\n * such coordinate exists.\n *\n * `opt_extrapolate` controls extrapolation beyond the range of Ms in the\n * MultiLineString. If `opt_extrapolate` is `true` then Ms less than the first\n * M will return the first coordinate and Ms greater than the last M will\n * return the last coordinate.\n *\n * `opt_interpolate` controls interpolation between consecutive LineStrings\n * within the MultiLineString. If `opt_interpolate` is `true` the coordinates\n * will be linearly interpolated between the last coordinate of one LineString\n * and the first coordinate of the next LineString. If `opt_interpolate` is\n * `false` then the function will return `null` for Ms falling between\n * LineStrings.\n *\n * @param {number} m M.\n * @param {boolean=} opt_extrapolate Extrapolate. Default is `false`.\n * @param {boolean=} opt_interpolate Interpolate. Default is `false`.\n * @return {import("../coordinate.js").Coordinate} Coordinate.\n * @api\n */\n\n\n MultiLineString.prototype.getCoordinateAtM = function (m, opt_extrapolate, opt_interpolate) {\n if (this.layout != geom_GeometryLayout.XYM && this.layout != geom_GeometryLayout.XYZM || this.flatCoordinates.length === 0) {\n return null;\n }\n\n var extrapolate = opt_extrapolate !== undefined ? opt_extrapolate : false;\n var interpolate = opt_interpolate !== undefined ? opt_interpolate : false;\n return lineStringsCoordinateAtM(this.flatCoordinates, 0, this.ends_, this.stride, m, extrapolate, interpolate);\n };\n /**\n * Return the coordinates of the multilinestring.\n * @return {Array<Array<import("../coordinate.js").Coordinate>>} Coordinates.\n * @api\n */\n\n\n MultiLineString.prototype.getCoordinates = function () {\n return inflateCoordinatesArray(this.flatCoordinates, 0, this.ends_, this.stride);\n };\n /**\n * @return {Array<number>} Ends.\n */\n\n\n MultiLineString.prototype.getEnds = function () {\n return this.ends_;\n };\n /**\n * Return the linestring at the specified index.\n * @param {number} index Index.\n * @return {LineString} LineString.\n * @api\n */\n\n\n MultiLineString.prototype.getLineString = function (index) {\n if (index < 0 || this.ends_.length <= index) {\n return null;\n }\n\n return new geom_LineString(this.flatCoordinates.slice(index === 0 ? 0 : this.ends_[index - 1], this.ends_[index]), this.layout);\n };\n /**\n * Return the linestrings of this multilinestring.\n * @return {Array<LineString>} LineStrings.\n * @api\n */\n\n\n MultiLineString.prototype.getLineStrings = function () {\n var flatCoordinates = this.flatCoordinates;\n var ends = this.ends_;\n var layout = this.layout;\n /** @type {Array<LineString>} */\n\n var lineStrings = [];\n var offset = 0;\n\n for (var i = 0, ii = ends.length; i < ii; ++i) {\n var end = ends[i];\n var lineString = new geom_LineString(flatCoordinates.slice(offset, end), layout);\n lineStrings.push(lineString);\n offset = end;\n }\n\n return lineStrings;\n };\n /**\n * @return {Array<number>} Flat midpoints.\n */\n\n\n MultiLineString.prototype.getFlatMidpoints = function () {\n var midpoints = [];\n var flatCoordinates = this.flatCoordinates;\n var offset = 0;\n var ends = this.ends_;\n var stride = this.stride;\n\n for (var i = 0, ii = ends.length; i < ii; ++i) {\n var end = ends[i];\n var midpoint = interpolatePoint(flatCoordinates, offset, end, stride, 0.5);\n array_extend(midpoints, midpoint);\n offset = end;\n }\n\n return midpoints;\n };\n /**\n * @param {number} squaredTolerance Squared tolerance.\n * @return {MultiLineString} Simplified MultiLineString.\n * @protected\n */\n\n\n MultiLineString.prototype.getSimplifiedGeometryInternal = function (squaredTolerance) {\n var simplifiedFlatCoordinates = [];\n var simplifiedEnds = [];\n simplifiedFlatCoordinates.length = douglasPeuckerArray(this.flatCoordinates, 0, this.ends_, this.stride, squaredTolerance, simplifiedFlatCoordinates, 0, simplifiedEnds);\n return new MultiLineString(simplifiedFlatCoordinates, geom_GeometryLayout.XY, simplifiedEnds);\n };\n /**\n * Get the type of this geometry.\n * @return {import("./GeometryType.js").default} Geometry type.\n * @api\n */\n\n\n MultiLineString.prototype.getType = function () {\n return geom_GeometryType.MULTI_LINE_STRING;\n };\n /**\n * Test if the geometry and the passed extent intersect.\n * @param {import("../extent.js").Extent} extent Extent.\n * @return {boolean} `true` if the geometry and the extent intersect.\n * @api\n */\n\n\n MultiLineString.prototype.intersectsExtent = function (extent) {\n return intersectsLineStringArray(this.flatCoordinates, 0, this.ends_, this.stride, extent);\n };\n /**\n * Set the coordinates of the multilinestring.\n * @param {!Array<Array<import("../coordinate.js").Coordinate>>} coordinates Coordinates.\n * @param {GeometryLayout=} opt_layout Layout.\n * @api\n */\n\n\n MultiLineString.prototype.setCoordinates = function (coordinates, opt_layout) {\n this.setLayout(opt_layout, coordinates, 2);\n\n if (!this.flatCoordinates) {\n this.flatCoordinates = [];\n }\n\n var ends = deflateCoordinatesArray(this.flatCoordinates, 0, coordinates, this.stride, this.ends_);\n this.flatCoordinates.length = ends.length === 0 ? 0 : ends[ends.length - 1];\n this.changed();\n };\n\n return MultiLineString;\n}(geom_SimpleGeometry);\n\n/* harmony default export */ var geom_MultiLineString = (MultiLineString);\n;// CONCATENATED MODULE: ./node_modules/ol/geom/MultiPoint.js\nvar MultiPoint_extends = undefined && undefined.__extends || function () {\n var _extendStatics = function extendStatics(d, b) {\n _extendStatics = Object.setPrototypeOf || {\n __proto__: []\n } instanceof Array && function (d, b) {\n d.__proto__ = b;\n } || function (d, b) {\n for (var p in b) {\n if (Object.prototype.hasOwnProperty.call(b, p)) d[p] = b[p];\n }\n };\n\n return _extendStatics(d, b);\n };\n\n return function (d, b) {\n _extendStatics(d, b);\n\n function __() {\n this.constructor = d;\n }\n\n d.prototype = b === null ? Object.create(b) : (__.prototype = b.prototype, new __());\n };\n}();\n/**\n * @module ol/geom/MultiPoint\n */\n\n\n\n\n\n\n\n\n\n\n/**\n * @classdesc\n * Multi-point geometry.\n *\n * @api\n */\n\nvar MultiPoint =\n/** @class */\nfunction (_super) {\n MultiPoint_extends(MultiPoint, _super);\n /**\n * @param {Array<import("../coordinate.js").Coordinate>|Array<number>} coordinates Coordinates.\n * For internal use, flat coordinates in combination with `opt_layout` are also accepted.\n * @param {import("./GeometryLayout.js").default=} opt_layout Layout.\n */\n\n\n function MultiPoint(coordinates, opt_layout) {\n var _this = _super.call(this) || this;\n\n if (opt_layout && !Array.isArray(coordinates[0])) {\n _this.setFlatCoordinates(opt_layout,\n /** @type {Array<number>} */\n coordinates);\n } else {\n _this.setCoordinates(\n /** @type {Array<import("../coordinate.js").Coordinate>} */\n coordinates, opt_layout);\n }\n\n return _this;\n }\n /**\n * Append the passed point to this multipoint.\n * @param {Point} point Point.\n * @api\n */\n\n\n MultiPoint.prototype.appendPoint = function (point) {\n if (!this.flatCoordinates) {\n this.flatCoordinates = point.getFlatCoordinates().slice();\n } else {\n array_extend(this.flatCoordinates, point.getFlatCoordinates());\n }\n\n this.changed();\n };\n /**\n * Make a complete copy of the geometry.\n * @return {!MultiPoint} Clone.\n * @api\n */\n\n\n MultiPoint.prototype.clone = function () {\n var multiPoint = new MultiPoint(this.flatCoordinates.slice(), this.layout);\n multiPoint.applyProperties(this);\n return multiPoint;\n };\n /**\n * @param {number} x X.\n * @param {number} y Y.\n * @param {import("../coordinate.js").Coordinate} closestPoint Closest point.\n * @param {number} minSquaredDistance Minimum squared distance.\n * @return {number} Minimum squared distance.\n */\n\n\n MultiPoint.prototype.closestPointXY = function (x, y, closestPoint, minSquaredDistance) {\n if (minSquaredDistance < closestSquaredDistanceXY(this.getExtent(), x, y)) {\n return minSquaredDistance;\n }\n\n var flatCoordinates = this.flatCoordinates;\n var stride = this.stride;\n\n for (var i = 0, ii = flatCoordinates.length; i < ii; i += stride) {\n var squaredDistance = math_squaredDistance(x, y, flatCoordinates[i], flatCoordinates[i + 1]);\n\n if (squaredDistance < minSquaredDistance) {\n minSquaredDistance = squaredDistance;\n\n for (var j = 0; j < stride; ++j) {\n closestPoint[j] = flatCoordinates[i + j];\n }\n\n closestPoint.length = stride;\n }\n }\n\n return minSquaredDistance;\n };\n /**\n * Return the coordinates of the multipoint.\n * @return {Array<import("../coordinate.js").Coordinate>} Coordinates.\n * @api\n */\n\n\n MultiPoint.prototype.getCoordinates = function () {\n return inflateCoordinates(this.flatCoordinates, 0, this.flatCoordinates.length, this.stride);\n };\n /**\n * Return the point at the specified index.\n * @param {number} index Index.\n * @return {Point} Point.\n * @api\n */\n\n\n MultiPoint.prototype.getPoint = function (index) {\n var n = !this.flatCoordinates ? 0 : this.flatCoordinates.length / this.stride;\n\n if (index < 0 || n <= index) {\n return null;\n }\n\n return new geom_Point(this.flatCoordinates.slice(index * this.stride, (index + 1) * this.stride), this.layout);\n };\n /**\n * Return the points of this multipoint.\n * @return {Array<Point>} Points.\n * @api\n */\n\n\n MultiPoint.prototype.getPoints = function () {\n var flatCoordinates = this.flatCoordinates;\n var layout = this.layout;\n var stride = this.stride;\n /** @type {Array<Point>} */\n\n var points = [];\n\n for (var i = 0, ii = flatCoordinates.length; i < ii; i += stride) {\n var point = new geom_Point(flatCoordinates.slice(i, i + stride), layout);\n points.push(point);\n }\n\n return points;\n };\n /**\n * Get the type of this geometry.\n * @return {import("./GeometryType.js").default} Geometry type.\n * @api\n */\n\n\n MultiPoint.prototype.getType = function () {\n return geom_GeometryType.MULTI_POINT;\n };\n /**\n * Test if the geometry and the passed extent intersect.\n * @param {import("../extent.js").Extent} extent Extent.\n * @return {boolean} `true` if the geometry and the extent intersect.\n * @api\n */\n\n\n MultiPoint.prototype.intersectsExtent = function (extent) {\n var flatCoordinates = this.flatCoordinates;\n var stride = this.stride;\n\n for (var i = 0, ii = flatCoordinates.length; i < ii; i += stride) {\n var x = flatCoordinates[i];\n var y = flatCoordinates[i + 1];\n\n if (containsXY(extent, x, y)) {\n return true;\n }\n }\n\n return false;\n };\n /**\n * Set the coordinates of the multipoint.\n * @param {!Array<import("../coordinate.js").Coordinate>} coordinates Coordinates.\n * @param {import("./GeometryLayout.js").default=} opt_layout Layout.\n * @api\n */\n\n\n MultiPoint.prototype.setCoordinates = function (coordinates, opt_layout) {\n this.setLayout(opt_layout, coordinates, 1);\n\n if (!this.flatCoordinates) {\n this.flatCoordinates = [];\n }\n\n this.flatCoordinates.length = deflateCoordinates(this.flatCoordinates, 0, coordinates, this.stride);\n this.changed();\n };\n\n return MultiPoint;\n}(geom_SimpleGeometry);\n\n/* harmony default export */ var geom_MultiPoint = (MultiPoint);\n;// CONCATENATED MODULE: ./node_modules/ol/geom/flat/center.js\n/**\n * @module ol/geom/flat/center\n */\n\n/**\n * @param {Array<number>} flatCoordinates Flat coordinates.\n * @param {number} offset Offset.\n * @param {Array<Array<number>>} endss Endss.\n * @param {number} stride Stride.\n * @return {Array<number>} Flat centers.\n */\n\nfunction center_linearRingss(flatCoordinates, offset, endss, stride) {\n var flatCenters = [];\n var extent = createEmpty();\n\n for (var i = 0, ii = endss.length; i < ii; ++i) {\n var ends = endss[i];\n extent = createOrUpdateFromFlatCoordinates(flatCoordinates, offset, ends[0], stride);\n flatCenters.push((extent[0] + extent[2]) / 2, (extent[1] + extent[3]) / 2);\n offset = ends[ends.length - 1];\n }\n\n return flatCenters;\n}\n;// CONCATENATED MODULE: ./node_modules/ol/geom/MultiPolygon.js\nvar MultiPolygon_extends = undefined && undefined.__extends || function () {\n var _extendStatics = function extendStatics(d, b) {\n _extendStatics = Object.setPrototypeOf || {\n __proto__: []\n } instanceof Array && function (d, b) {\n d.__proto__ = b;\n } || function (d, b) {\n for (var p in b) {\n if (Object.prototype.hasOwnProperty.call(b, p)) d[p] = b[p];\n }\n };\n\n return _extendStatics(d, b);\n };\n\n return function (d, b) {\n _extendStatics(d, b);\n\n function __() {\n this.constructor = d;\n }\n\n d.prototype = b === null ? Object.create(b) : (__.prototype = b.prototype, new __());\n };\n}();\n/**\n * @module ol/geom/MultiPolygon\n */\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n/**\n * @classdesc\n * Multi-polygon geometry.\n *\n * @api\n */\n\nvar MultiPolygon =\n/** @class */\nfunction (_super) {\n MultiPolygon_extends(MultiPolygon, _super);\n /**\n * @param {Array<Array<Array<import("../coordinate.js").Coordinate>>|Polygon>|Array<number>} coordinates Coordinates.\n * For internal use, flat coordinates in combination with `opt_layout` and `opt_endss` are also accepted.\n * @param {import("./GeometryLayout.js").default=} opt_layout Layout.\n * @param {Array<Array<number>>=} opt_endss Array of ends for internal use with flat coordinates.\n */\n\n\n function MultiPolygon(coordinates, opt_layout, opt_endss) {\n var _this = _super.call(this) || this;\n /**\n * @type {Array<Array<number>>}\n * @private\n */\n\n\n _this.endss_ = [];\n /**\n * @private\n * @type {number}\n */\n\n _this.flatInteriorPointsRevision_ = -1;\n /**\n * @private\n * @type {Array<number>}\n */\n\n _this.flatInteriorPoints_ = null;\n /**\n * @private\n * @type {number}\n */\n\n _this.maxDelta_ = -1;\n /**\n * @private\n * @type {number}\n */\n\n _this.maxDeltaRevision_ = -1;\n /**\n * @private\n * @type {number}\n */\n\n _this.orientedRevision_ = -1;\n /**\n * @private\n * @type {Array<number>}\n */\n\n _this.orientedFlatCoordinates_ = null;\n\n if (!opt_endss && !Array.isArray(coordinates[0])) {\n var layout = _this.getLayout();\n\n var polygons =\n /** @type {Array<Polygon>} */\n coordinates;\n var flatCoordinates = [];\n var endss = [];\n\n for (var i = 0, ii = polygons.length; i < ii; ++i) {\n var polygon = polygons[i];\n\n if (i === 0) {\n layout = polygon.getLayout();\n }\n\n var offset = flatCoordinates.length;\n var ends = polygon.getEnds();\n\n for (var j = 0, jj = ends.length; j < jj; ++j) {\n ends[j] += offset;\n }\n\n array_extend(flatCoordinates, polygon.getFlatCoordinates());\n endss.push(ends);\n }\n\n opt_layout = layout;\n coordinates = flatCoordinates;\n opt_endss = endss;\n }\n\n if (opt_layout !== undefined && opt_endss) {\n _this.setFlatCoordinates(opt_layout,\n /** @type {Array<number>} */\n coordinates);\n\n _this.endss_ = opt_endss;\n } else {\n _this.setCoordinates(\n /** @type {Array<Array<Array<import("../coordinate.js").Coordinate>>>} */\n coordinates, opt_layout);\n }\n\n return _this;\n }\n /**\n * Append the passed polygon to this multipolygon.\n * @param {Polygon} polygon Polygon.\n * @api\n */\n\n\n MultiPolygon.prototype.appendPolygon = function (polygon) {\n /** @type {Array<number>} */\n var ends;\n\n if (!this.flatCoordinates) {\n this.flatCoordinates = polygon.getFlatCoordinates().slice();\n ends = polygon.getEnds().slice();\n this.endss_.push();\n } else {\n var offset = this.flatCoordinates.length;\n array_extend(this.flatCoordinates, polygon.getFlatCoordinates());\n ends = polygon.getEnds().slice();\n\n for (var i = 0, ii = ends.length; i < ii; ++i) {\n ends[i] += offset;\n }\n }\n\n this.endss_.push(ends);\n this.changed();\n };\n /**\n * Make a complete copy of the geometry.\n * @return {!MultiPolygon} Clone.\n * @api\n */\n\n\n MultiPolygon.prototype.clone = function () {\n var len = this.endss_.length;\n var newEndss = new Array(len);\n\n for (var i = 0; i < len; ++i) {\n newEndss[i] = this.endss_[i].slice();\n }\n\n var multiPolygon = new MultiPolygon(this.flatCoordinates.slice(), this.layout, newEndss);\n multiPolygon.applyProperties(this);\n return multiPolygon;\n };\n /**\n * @param {number} x X.\n * @param {number} y Y.\n * @param {import("../coordinate.js").Coordinate} closestPoint Closest point.\n * @param {number} minSquaredDistance Minimum squared distance.\n * @return {number} Minimum squared distance.\n */\n\n\n MultiPolygon.prototype.closestPointXY = function (x, y, closestPoint, minSquaredDistance) {\n if (minSquaredDistance < closestSquaredDistanceXY(this.getExtent(), x, y)) {\n return minSquaredDistance;\n }\n\n if (this.maxDeltaRevision_ != this.getRevision()) {\n this.maxDelta_ = Math.sqrt(multiArrayMaxSquaredDelta(this.flatCoordinates, 0, this.endss_, this.stride, 0));\n this.maxDeltaRevision_ = this.getRevision();\n }\n\n return assignClosestMultiArrayPoint(this.getOrientedFlatCoordinates(), 0, this.endss_, this.stride, this.maxDelta_, true, x, y, closestPoint, minSquaredDistance);\n };\n /**\n * @param {number} x X.\n * @param {number} y Y.\n * @return {boolean} Contains (x, y).\n */\n\n\n MultiPolygon.prototype.containsXY = function (x, y) {\n return linearRingssContainsXY(this.getOrientedFlatCoordinates(), 0, this.endss_, this.stride, x, y);\n };\n /**\n * Return the area of the multipolygon on projected plane.\n * @return {number} Area (on projected plane).\n * @api\n */\n\n\n MultiPolygon.prototype.getArea = function () {\n return linearRingss(this.getOrientedFlatCoordinates(), 0, this.endss_, this.stride);\n };\n /**\n * Get the coordinate array for this geometry. This array has the structure\n * of a GeoJSON coordinate array for multi-polygons.\n *\n * @param {boolean=} opt_right Orient coordinates according to the right-hand\n * rule (counter-clockwise for exterior and clockwise for interior rings).\n * If `false`, coordinates will be oriented according to the left-hand rule\n * (clockwise for exterior and counter-clockwise for interior rings).\n * By default, coordinate orientation will depend on how the geometry was\n * constructed.\n * @return {Array<Array<Array<import("../coordinate.js").Coordinate>>>} Coordinates.\n * @api\n */\n\n\n MultiPolygon.prototype.getCoordinates = function (opt_right) {\n var flatCoordinates;\n\n if (opt_right !== undefined) {\n flatCoordinates = this.getOrientedFlatCoordinates().slice();\n orientLinearRingsArray(flatCoordinates, 0, this.endss_, this.stride, opt_right);\n } else {\n flatCoordinates = this.flatCoordinates;\n }\n\n return inflateMultiCoordinatesArray(flatCoordinates, 0, this.endss_, this.stride);\n };\n /**\n * @return {Array<Array<number>>} Endss.\n */\n\n\n MultiPolygon.prototype.getEndss = function () {\n return this.endss_;\n };\n /**\n * @return {Array<number>} Flat interior points.\n */\n\n\n MultiPolygon.prototype.getFlatInteriorPoints = function () {\n if (this.flatInteriorPointsRevision_ != this.getRevision()) {\n var flatCenters = center_linearRingss(this.flatCoordinates, 0, this.endss_, this.stride);\n this.flatInteriorPoints_ = getInteriorPointsOfMultiArray(this.getOrientedFlatCoordinates(), 0, this.endss_, this.stride, flatCenters);\n this.flatInteriorPointsRevision_ = this.getRevision();\n }\n\n return this.flatInteriorPoints_;\n };\n /**\n * Return the interior points as {@link module:ol/geom/MultiPoint multipoint}.\n * @return {MultiPoint} Interior points as XYM coordinates, where M is\n * the length of the horizontal intersection that the point belongs to.\n * @api\n */\n\n\n MultiPolygon.prototype.getInteriorPoints = function () {\n return new geom_MultiPoint(this.getFlatInteriorPoints().slice(), geom_GeometryLayout.XYM);\n };\n /**\n * @return {Array<number>} Oriented flat coordinates.\n */\n\n\n MultiPolygon.prototype.getOrientedFlatCoordinates = function () {\n if (this.orientedRevision_ != this.getRevision()) {\n var flatCoordinates = this.flatCoordinates;\n\n if (linearRingssAreOriented(flatCoordinates, 0, this.endss_, this.stride)) {\n this.orientedFlatCoordinates_ = flatCoordinates;\n } else {\n this.orientedFlatCoordinates_ = flatCoordinates.slice();\n this.orientedFlatCoordinates_.length = orientLinearRingsArray(this.orientedFlatCoordinates_, 0, this.endss_, this.stride);\n }\n\n this.orientedRevision_ = this.getRevision();\n }\n\n return this.orientedFlatCoordinates_;\n };\n /**\n * @param {number} squaredTolerance Squared tolerance.\n * @return {MultiPolygon} Simplified MultiPolygon.\n * @protected\n */\n\n\n MultiPolygon.prototype.getSimplifiedGeometryInternal = function (squaredTolerance) {\n var simplifiedFlatCoordinates = [];\n var simplifiedEndss = [];\n simplifiedFlatCoordinates.length = quantizeMultiArray(this.flatCoordinates, 0, this.endss_, this.stride, Math.sqrt(squaredTolerance), simplifiedFlatCoordinates, 0, simplifiedEndss);\n return new MultiPolygon(simplifiedFlatCoordinates, geom_GeometryLayout.XY, simplifiedEndss);\n };\n /**\n * Return the polygon at the specified index.\n * @param {number} index Index.\n * @return {Polygon} Polygon.\n * @api\n */\n\n\n MultiPolygon.prototype.getPolygon = function (index) {\n if (index < 0 || this.endss_.length <= index) {\n return null;\n }\n\n var offset;\n\n if (index === 0) {\n offset = 0;\n } else {\n var prevEnds = this.endss_[index - 1];\n offset = prevEnds[prevEnds.length - 1];\n }\n\n var ends = this.endss_[index].slice();\n var end = ends[ends.length - 1];\n\n if (offset !== 0) {\n for (var i = 0, ii = ends.length; i < ii; ++i) {\n ends[i] -= offset;\n }\n }\n\n return new geom_Polygon(this.flatCoordinates.slice(offset, end), this.layout, ends);\n };\n /**\n * Return the polygons of this multipolygon.\n * @return {Array<Polygon>} Polygons.\n * @api\n */\n\n\n MultiPolygon.prototype.getPolygons = function () {\n var layout = this.layout;\n var flatCoordinates = this.flatCoordinates;\n var endss = this.endss_;\n var polygons = [];\n var offset = 0;\n\n for (var i = 0, ii = endss.length; i < ii; ++i) {\n var ends = endss[i].slice();\n var end = ends[ends.length - 1];\n\n if (offset !== 0) {\n for (var j = 0, jj = ends.length; j < jj; ++j) {\n ends[j] -= offset;\n }\n }\n\n var polygon = new geom_Polygon(flatCoordinates.slice(offset, end), layout, ends);\n polygons.push(polygon);\n offset = end;\n }\n\n return polygons;\n };\n /**\n * Get the type of this geometry.\n * @return {import("./GeometryType.js").default} Geometry type.\n * @api\n */\n\n\n MultiPolygon.prototype.getType = function () {\n return geom_GeometryType.MULTI_POLYGON;\n };\n /**\n * Test if the geometry and the passed extent intersect.\n * @param {import("../extent.js").Extent} extent Extent.\n * @return {boolean} `true` if the geometry and the extent intersect.\n * @api\n */\n\n\n MultiPolygon.prototype.intersectsExtent = function (extent) {\n return intersectsLinearRingMultiArray(this.getOrientedFlatCoordinates(), 0, this.endss_, this.stride, extent);\n };\n /**\n * Set the coordinates of the multipolygon.\n * @param {!Array<Array<Array<import("../coordinate.js").Coordinate>>>} coordinates Coordinates.\n * @param {import("./GeometryLayout.js").default=} opt_layout Layout.\n * @api\n */\n\n\n MultiPolygon.prototype.setCoordinates = function (coordinates, opt_layout) {\n this.setLayout(opt_layout, coordinates, 3);\n\n if (!this.flatCoordinates) {\n this.flatCoordinates = [];\n }\n\n var endss = deflateMultiCoordinatesArray(this.flatCoordinates, 0, coordinates, this.stride, this.endss_);\n\n if (endss.length === 0) {\n this.flatCoordinates.length = 0;\n } else {\n var lastEnds = endss[endss.length - 1];\n this.flatCoordinates.length = lastEnds.length === 0 ? 0 : lastEnds[lastEnds.length - 1];\n }\n\n this.changed();\n };\n\n return MultiPolygon;\n}(geom_SimpleGeometry);\n\n/* harmony default export */ var geom_MultiPolygon = (MultiPolygon);\n// EXTERNAL MODULE: ./node_modules/pbf/index.js\nvar node_modules_pbf = __webpack_require__(4362);\nvar pbf_default = /*#__PURE__*/__webpack_require__.n(node_modules_pbf);\n;// CONCATENATED MODULE: ./node_modules/ol/render/Feature.js\n/**\n * @module ol/render/Feature\n */\n\n\n\n\n\n\n\n\n\n/**\n * @type {import("../transform.js").Transform}\n */\n\nvar Feature_tmpTransform = create();\n/**\n * Lightweight, read-only, {@link module:ol/Feature~Feature} and {@link module:ol/geom/Geometry~Geometry} like\n * structure, optimized for vector tile rendering and styling. Geometry access\n * through the API is limited to getting the type and extent of the geometry.\n */\n\nvar RenderFeature =\n/** @class */\nfunction () {\n /**\n * @param {import("../geom/GeometryType.js").default} type Geometry type.\n * @param {Array<number>} flatCoordinates Flat coordinates. These always need\n * to be right-handed for polygons.\n * @param {Array<number>|Array<Array<number>>} ends Ends or Endss.\n * @param {Object<string, *>} properties Properties.\n * @param {number|string|undefined} id Feature id.\n */\n function RenderFeature(type, flatCoordinates, ends, properties, id) {\n /**\n * @private\n * @type {import("../extent.js").Extent|undefined}\n */\n this.extent_;\n /**\n * @private\n * @type {number|string|undefined}\n */\n\n this.id_ = id;\n /**\n * @private\n * @type {import("../geom/GeometryType.js").default}\n */\n\n this.type_ = type;\n /**\n * @private\n * @type {Array<number>}\n */\n\n this.flatCoordinates_ = flatCoordinates;\n /**\n * @private\n * @type {Array<number>}\n */\n\n this.flatInteriorPoints_ = null;\n /**\n * @private\n * @type {Array<number>}\n */\n\n this.flatMidpoints_ = null;\n /**\n * @private\n * @type {Array<number>|Array<Array<number>>}\n */\n\n this.ends_ = ends;\n /**\n * @private\n * @type {Object<string, *>}\n */\n\n this.properties_ = properties;\n }\n /**\n * Get a feature property by its key.\n * @param {string} key Key\n * @return {*} Value for the requested key.\n * @api\n */\n\n\n RenderFeature.prototype.get = function (key) {\n return this.properties_[key];\n };\n /**\n * Get the extent of this feature\'s geometry.\n * @return {import("../extent.js").Extent} Extent.\n * @api\n */\n\n\n RenderFeature.prototype.getExtent = function () {\n if (!this.extent_) {\n this.extent_ = this.type_ === geom_GeometryType.POINT ? createOrUpdateFromCoordinate(this.flatCoordinates_) : createOrUpdateFromFlatCoordinates(this.flatCoordinates_, 0, this.flatCoordinates_.length, 2);\n }\n\n return this.extent_;\n };\n /**\n * @return {Array<number>} Flat interior points.\n */\n\n\n RenderFeature.prototype.getFlatInteriorPoint = function () {\n if (!this.flatInteriorPoints_) {\n var flatCenter = getCenter(this.getExtent());\n this.flatInteriorPoints_ = getInteriorPointOfArray(this.flatCoordinates_, 0,\n /** @type {Array<number>} */\n this.ends_, 2, flatCenter, 0);\n }\n\n return this.flatInteriorPoints_;\n };\n /**\n * @return {Array<number>} Flat interior points.\n */\n\n\n RenderFeature.prototype.getFlatInteriorPoints = function () {\n if (!this.flatInteriorPoints_) {\n var flatCenters = center_linearRingss(this.flatCoordinates_, 0,\n /** @type {Array<Array<number>>} */\n this.ends_, 2);\n this.flatInteriorPoints_ = getInteriorPointsOfMultiArray(this.flatCoordinates_, 0,\n /** @type {Array<Array<number>>} */\n this.ends_, 2, flatCenters);\n }\n\n return this.flatInteriorPoints_;\n };\n /**\n * @return {Array<number>} Flat midpoint.\n */\n\n\n RenderFeature.prototype.getFlatMidpoint = function () {\n if (!this.flatMidpoints_) {\n this.flatMidpoints_ = interpolatePoint(this.flatCoordinates_, 0, this.flatCoordinates_.length, 2, 0.5);\n }\n\n return this.flatMidpoints_;\n };\n /**\n * @return {Array<number>} Flat midpoints.\n */\n\n\n RenderFeature.prototype.getFlatMidpoints = function () {\n if (!this.flatMidpoints_) {\n this.flatMidpoints_ = [];\n var flatCoordinates = this.flatCoordinates_;\n var offset = 0;\n var ends =\n /** @type {Array<number>} */\n this.ends_;\n\n for (var i = 0, ii = ends.length; i < ii; ++i) {\n var end = ends[i];\n var midpoint = interpolatePoint(flatCoordinates, offset, end, 2, 0.5);\n array_extend(this.flatMidpoints_, midpoint);\n offset = end;\n }\n }\n\n return this.flatMidpoints_;\n };\n /**\n * Get the feature identifier. This is a stable identifier for the feature and\n * is set when reading data from a remote source.\n * @return {number|string|undefined} Id.\n * @api\n */\n\n\n RenderFeature.prototype.getId = function () {\n return this.id_;\n };\n /**\n * @return {Array<number>} Flat coordinates.\n */\n\n\n RenderFeature.prototype.getOrientedFlatCoordinates = function () {\n return this.flatCoordinates_;\n };\n /**\n * For API compatibility with {@link module:ol/Feature~Feature}, this method is useful when\n * determining the geometry type in style function (see {@link #getType}).\n * @return {RenderFeature} Feature.\n * @api\n */\n\n\n RenderFeature.prototype.getGeometry = function () {\n return this;\n };\n /**\n * @param {number} squaredTolerance Squared tolerance.\n * @return {RenderFeature} Simplified geometry.\n */\n\n\n RenderFeature.prototype.getSimplifiedGeometry = function (squaredTolerance) {\n return this;\n };\n /**\n * Get a transformed and simplified version of the geometry.\n * @abstract\n * @param {number} squaredTolerance Squared tolerance.\n * @param {import("../proj.js").TransformFunction} [opt_transform] Optional transform function.\n * @return {RenderFeature} Simplified geometry.\n */\n\n\n RenderFeature.prototype.simplifyTransformed = function (squaredTolerance, opt_transform) {\n return this;\n };\n /**\n * Get the feature properties.\n * @return {Object<string, *>} Feature properties.\n * @api\n */\n\n\n RenderFeature.prototype.getProperties = function () {\n return this.properties_;\n };\n /**\n * @return {number} Stride.\n */\n\n\n RenderFeature.prototype.getStride = function () {\n return 2;\n };\n /**\n * @return {undefined}\n */\n\n\n RenderFeature.prototype.getStyleFunction = function () {\n return undefined;\n };\n /**\n * Get the type of this feature\'s geometry.\n * @return {import("../geom/GeometryType.js").default} Geometry type.\n * @api\n */\n\n\n RenderFeature.prototype.getType = function () {\n return this.type_;\n };\n /**\n * Transform geometry coordinates from tile pixel space to projected.\n *\n * @param {import("../proj.js").ProjectionLike} projection The data projection\n */\n\n\n RenderFeature.prototype.transform = function (projection) {\n projection = proj_get(projection);\n var pixelExtent = projection.getExtent();\n var projectedExtent = projection.getWorldExtent();\n\n if (pixelExtent && projectedExtent) {\n var scale = getHeight(projectedExtent) / getHeight(pixelExtent);\n compose(Feature_tmpTransform, projectedExtent[0], projectedExtent[3], scale, -scale, 0, 0, 0);\n transform2D(this.flatCoordinates_, 0, this.flatCoordinates_.length, 2, Feature_tmpTransform, this.flatCoordinates_);\n }\n };\n /**\n * @return {Array<number>|Array<Array<number>>} Ends or endss.\n */\n\n\n RenderFeature.prototype.getEnds = function () {\n return this.ends_;\n };\n\n return RenderFeature;\n}();\n\nRenderFeature.prototype.getEndss = RenderFeature.prototype.getEnds;\n/**\n * @return {Array<number>} Flat coordinates.\n */\n\nRenderFeature.prototype.getFlatCoordinates = RenderFeature.prototype.getOrientedFlatCoordinates;\n/* harmony default export */ var render_Feature = (RenderFeature);\n;// CONCATENATED MODULE: ./node_modules/ol/format/MVT.js\n/**\n * @module ol/format/MVT\n */\n//FIXME Implement projection handling\nvar MVT_extends = undefined && undefined.__extends || function () {\n var _extendStatics = function extendStatics(d, b) {\n _extendStatics = Object.setPrototypeOf || {\n __proto__: []\n } instanceof Array && function (d, b) {\n d.__proto__ = b;\n } || function (d, b) {\n for (var p in b) {\n if (Object.prototype.hasOwnProperty.call(b, p)) d[p] = b[p];\n }\n };\n\n return _extendStatics(d, b);\n };\n\n return function (d, b) {\n _extendStatics(d, b);\n\n function __() {\n this.constructor = d;\n }\n\n d.prototype = b === null ? Object.create(b) : (__.prototype = b.prototype, new __());\n };\n}();\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n/**\n * @typedef {Object} Options\n * @property {import("../Feature.js").FeatureClass} [featureClass] Class for features returned by\n * {@link module:ol/format/MVT#readFeatures}. Set to {@link module:ol/Feature~Feature} to get full editing and geometry\n * support at the cost of decreased rendering performance. The default is\n * {@link module:ol/render/Feature~RenderFeature}, which is optimized for rendering and hit detection.\n * @property {string} [geometryName=\'geometry\'] Geometry name to use when creating features.\n * @property {string} [layerName=\'layer\'] Name of the feature attribute that holds the layer name.\n * @property {Array<string>} [layers] Layers to read features from. If not provided, features will be read from all\n * @property {string} [idProperty] Optional property that will be assigned as the feature id and removed from the properties.\n * layers.\n */\n\n/**\n * @classdesc\n * Feature format for reading data in the Mapbox MVT format.\n *\n * @param {Options=} opt_options Options.\n * @api\n */\n\nvar MVT =\n/** @class */\nfunction (_super) {\n MVT_extends(MVT, _super);\n /**\n * @param {Options=} opt_options Options.\n */\n\n\n function MVT(opt_options) {\n var _this = _super.call(this) || this;\n\n var options = opt_options ? opt_options : {};\n /**\n * @type {Projection}\n */\n\n _this.dataProjection = new proj_Projection({\n code: \'\',\n units: proj_Units.TILE_PIXELS\n });\n /**\n * @private\n * @type {import("../Feature.js").FeatureClass}\n */\n\n _this.featureClass_ = options.featureClass ? options.featureClass : render_Feature;\n /**\n * @private\n * @type {string|undefined}\n */\n\n _this.geometryName_ = options.geometryName;\n /**\n * @private\n * @type {string}\n */\n\n _this.layerName_ = options.layerName ? options.layerName : \'layer\';\n /**\n * @private\n * @type {Array<string>}\n */\n\n _this.layers_ = options.layers ? options.layers : null;\n /**\n * @private\n * @type {string}\n */\n\n _this.idProperty_ = options.idProperty;\n return _this;\n }\n /**\n * Read the raw geometry from the pbf offset stored in a raw feature\'s geometry\n * property.\n * @param {PBF} pbf PBF.\n * @param {Object} feature Raw feature.\n * @param {Array<number>} flatCoordinates Array to store flat coordinates in.\n * @param {Array<number>} ends Array to store ends in.\n * @private\n */\n\n\n MVT.prototype.readRawGeometry_ = function (pbf, feature, flatCoordinates, ends) {\n pbf.pos = feature.geometry;\n var end = pbf.readVarint() + pbf.pos;\n var cmd = 1;\n var length = 0;\n var x = 0;\n var y = 0;\n var coordsLen = 0;\n var currentEnd = 0;\n\n while (pbf.pos < end) {\n if (!length) {\n var cmdLen = pbf.readVarint();\n cmd = cmdLen & 0x7;\n length = cmdLen >> 3;\n }\n\n length--;\n\n if (cmd === 1 || cmd === 2) {\n x += pbf.readSVarint();\n y += pbf.readSVarint();\n\n if (cmd === 1) {\n // moveTo\n if (coordsLen > currentEnd) {\n ends.push(coordsLen);\n currentEnd = coordsLen;\n }\n }\n\n flatCoordinates.push(x, y);\n coordsLen += 2;\n } else if (cmd === 7) {\n if (coordsLen > currentEnd) {\n // close polygon\n flatCoordinates.push(flatCoordinates[currentEnd], flatCoordinates[currentEnd + 1]);\n coordsLen += 2;\n }\n } else {\n asserts_assert(false, 59); // Invalid command found in the PBF\n }\n }\n\n if (coordsLen > currentEnd) {\n ends.push(coordsLen);\n currentEnd = coordsLen;\n }\n };\n /**\n * @private\n * @param {PBF} pbf PBF\n * @param {Object} rawFeature Raw Mapbox feature.\n * @param {import("./Feature.js").ReadOptions} options Read options.\n * @return {import("../Feature.js").FeatureLike} Feature.\n */\n\n\n MVT.prototype.createFeature_ = function (pbf, rawFeature, options) {\n var type = rawFeature.type;\n\n if (type === 0) {\n return null;\n }\n\n var feature;\n var values = rawFeature.properties;\n var id;\n\n if (!this.idProperty_) {\n id = rawFeature.id;\n } else {\n id = values[this.idProperty_];\n delete values[this.idProperty_];\n }\n\n values[this.layerName_] = rawFeature.layer.name;\n var flatCoordinates = [];\n var ends = [];\n this.readRawGeometry_(pbf, rawFeature, flatCoordinates, ends);\n var geometryType = getGeometryType(type, ends.length);\n\n if (this.featureClass_ === render_Feature) {\n feature = new this.featureClass_(geometryType, flatCoordinates, ends, values, id);\n feature.transform(options.dataProjection);\n } else {\n var geom = void 0;\n\n if (geometryType == geom_GeometryType.POLYGON) {\n var endss = [];\n var offset = 0;\n var prevEndIndex = 0;\n\n for (var i = 0, ii = ends.length; i < ii; ++i) {\n var end = ends[i]; // classifies an array of rings into polygons with outer rings and holes\n\n if (!linearRingIsClockwise(flatCoordinates, offset, end, 2)) {\n endss.push(ends.slice(prevEndIndex, i + 1));\n } else {\n if (endss.length === 0) {\n continue;\n }\n\n endss[endss.length - 1].push(ends[prevEndIndex]);\n }\n\n prevEndIndex = i + 1;\n offset = end;\n }\n\n if (endss.length > 1) {\n geom = new geom_MultiPolygon(flatCoordinates, geom_GeometryLayout.XY, endss);\n } else {\n geom = new geom_Polygon(flatCoordinates, geom_GeometryLayout.XY, ends);\n }\n } else {\n geom = geometryType === geom_GeometryType.POINT ? new geom_Point(flatCoordinates, geom_GeometryLayout.XY) : geometryType === geom_GeometryType.LINE_STRING ? new geom_LineString(flatCoordinates, geom_GeometryLayout.XY) : geometryType === geom_GeometryType.POLYGON ? new geom_Polygon(flatCoordinates, geom_GeometryLayout.XY, ends) : geometryType === geom_GeometryType.MULTI_POINT ? new geom_MultiPoint(flatCoordinates, geom_GeometryLayout.XY) : geometryType === geom_GeometryType.MULTI_LINE_STRING ? new geom_MultiLineString(flatCoordinates, geom_GeometryLayout.XY, ends) : null;\n }\n\n var ctor =\n /** @type {typeof import("../Feature.js").default} */\n this.featureClass_;\n feature = new ctor();\n\n if (this.geometryName_) {\n feature.setGeometryName(this.geometryName_);\n }\n\n var geometry = transformGeometryWithOptions(geom, false, options);\n feature.setGeometry(geometry);\n feature.setId(id);\n feature.setProperties(values, true);\n }\n\n return feature;\n };\n /**\n * @return {import("./FormatType.js").default} Format.\n */\n\n\n MVT.prototype.getType = function () {\n return FormatType.ARRAY_BUFFER;\n };\n /**\n * Read all features.\n *\n * @param {ArrayBuffer} source Source.\n * @param {import("./Feature.js").ReadOptions=} opt_options Read options.\n * @return {Array<import("../Feature.js").FeatureLike>} Features.\n * @api\n */\n\n\n MVT.prototype.readFeatures = function (source, opt_options) {\n var layers = this.layers_;\n var options =\n /** @type {import("./Feature.js").ReadOptions} */\n this.adaptOptions(opt_options);\n var dataProjection = proj_get(options.dataProjection);\n dataProjection.setWorldExtent(options.extent);\n options.dataProjection = dataProjection;\n var pbf = new (pbf_default())(\n /** @type {ArrayBuffer} */\n source);\n var pbfLayers = pbf.readFields(layersPBFReader, {});\n var features = [];\n\n for (var name_1 in pbfLayers) {\n if (layers && layers.indexOf(name_1) == -1) {\n continue;\n }\n\n var pbfLayer = pbfLayers[name_1];\n var extent = pbfLayer ? [0, 0, pbfLayer.extent, pbfLayer.extent] : null;\n dataProjection.setExtent(extent);\n\n for (var i = 0, ii = pbfLayer.length; i < ii; ++i) {\n var rawFeature = readRawFeature(pbf, pbfLayer, i);\n features.push(this.createFeature_(pbf, rawFeature, options));\n }\n }\n\n return features;\n };\n /**\n * Read the projection from the source.\n *\n * @param {Document|Element|Object|string} source Source.\n * @return {import("../proj/Projection.js").default} Projection.\n * @api\n */\n\n\n MVT.prototype.readProjection = function (source) {\n return this.dataProjection;\n };\n /**\n * Sets the layers that features will be read from.\n * @param {Array<string>} layers Layers.\n * @api\n */\n\n\n MVT.prototype.setLayers = function (layers) {\n this.layers_ = layers;\n };\n\n return MVT;\n}(Feature);\n/**\n * Reader callback for parsing layers.\n * @param {number} tag The tag.\n * @param {Object} layers The layers object.\n * @param {PBF} pbf The PBF.\n */\n\n\nfunction layersPBFReader(tag, layers, pbf) {\n if (tag === 3) {\n var layer = {\n keys: [],\n values: [],\n features: []\n };\n var end = pbf.readVarint() + pbf.pos;\n pbf.readFields(layerPBFReader, layer, end);\n layer.length = layer.features.length;\n\n if (layer.length) {\n layers[layer.name] = layer;\n }\n }\n}\n/**\n * Reader callback for parsing layer.\n * @param {number} tag The tag.\n * @param {Object} layer The layer object.\n * @param {PBF} pbf The PBF.\n */\n\n\nfunction layerPBFReader(tag, layer, pbf) {\n if (tag === 15) {\n layer.version = pbf.readVarint();\n } else if (tag === 1) {\n layer.name = pbf.readString();\n } else if (tag === 5) {\n layer.extent = pbf.readVarint();\n } else if (tag === 2) {\n layer.features.push(pbf.pos);\n } else if (tag === 3) {\n layer.keys.push(pbf.readString());\n } else if (tag === 4) {\n var value = null;\n var end = pbf.readVarint() + pbf.pos;\n\n while (pbf.pos < end) {\n tag = pbf.readVarint() >> 3;\n value = tag === 1 ? pbf.readString() : tag === 2 ? pbf.readFloat() : tag === 3 ? pbf.readDouble() : tag === 4 ? pbf.readVarint64() : tag === 5 ? pbf.readVarint() : tag === 6 ? pbf.readSVarint() : tag === 7 ? pbf.readBoolean() : null;\n }\n\n layer.values.push(value);\n }\n}\n/**\n * Reader callback for parsing feature.\n * @param {number} tag The tag.\n * @param {Object} feature The feature object.\n * @param {PBF} pbf The PBF.\n */\n\n\nfunction featurePBFReader(tag, feature, pbf) {\n if (tag == 1) {\n feature.id = pbf.readVarint();\n } else if (tag == 2) {\n var end = pbf.readVarint() + pbf.pos;\n\n while (pbf.pos < end) {\n var key = feature.layer.keys[pbf.readVarint()];\n var value = feature.layer.values[pbf.readVarint()];\n feature.properties[key] = value;\n }\n } else if (tag == 3) {\n feature.type = pbf.readVarint();\n } else if (tag == 4) {\n feature.geometry = pbf.pos;\n }\n}\n/**\n * Read a raw feature from the pbf offset stored at index `i` in the raw layer.\n * @param {PBF} pbf PBF.\n * @param {Object} layer Raw layer.\n * @param {number} i Index of the feature in the raw layer\'s `features` array.\n * @return {Object} Raw feature.\n */\n\n\nfunction readRawFeature(pbf, layer, i) {\n pbf.pos = layer.features[i];\n var end = pbf.readVarint() + pbf.pos;\n var feature = {\n layer: layer,\n type: 0,\n properties: {}\n };\n pbf.readFields(featurePBFReader, feature, end);\n return feature;\n}\n/**\n * @param {number} type The raw feature\'s geometry type\n * @param {number} numEnds Number of ends of the flat coordinates of the\n * geometry.\n * @return {import("../geom/GeometryType.js").default} The geometry type.\n */\n\n\nfunction getGeometryType(type, numEnds) {\n /** @type {import("../geom/GeometryType.js").default} */\n var geometryType;\n\n if (type === 1) {\n geometryType = numEnds === 1 ? geom_GeometryType.POINT : geom_GeometryType.MULTI_POINT;\n } else if (type === 2) {\n geometryType = numEnds === 1 ? geom_GeometryType.LINE_STRING : geom_GeometryType.MULTI_LINE_STRING;\n } else if (type === 3) {\n geometryType = geom_GeometryType.POLYGON; // MultiPolygon not relevant for rendering - winding order determines\n // outer rings of polygons.\n }\n\n return geometryType;\n}\n\n/* harmony default export */ var format_MVT = (MVT);\n;// CONCATENATED MODULE: ./node_modules/ol/structs/RBush.js\n/**\n * @module ol/structs/RBush\n */\n\n\n\n\n/**\n * @typedef {Object} Entry\n * @property {number} minX\n * @property {number} minY\n * @property {number} maxX\n * @property {number} maxY\n * @property {Object} [value]\n */\n\n/**\n * @classdesc\n * Wrapper around the RBush by Vladimir Agafonkin.\n * See https://github.com/mourner/rbush.\n *\n * @template T\n */\n\nvar RBush =\n/** @class */\nfunction () {\n /**\n * @param {number=} opt_maxEntries Max entries.\n */\n function RBush(opt_maxEntries) {\n /**\n * @private\n */\n this.rbush_ = new (rbush_min_default())(opt_maxEntries);\n /**\n * A mapping between the objects added to this rbush wrapper\n * and the objects that are actually added to the internal rbush.\n * @private\n * @type {Object<string, Entry>}\n */\n\n this.items_ = {};\n }\n /**\n * Insert a value into the RBush.\n * @param {import("../extent.js").Extent} extent Extent.\n * @param {T} value Value.\n */\n\n\n RBush.prototype.insert = function (extent, value) {\n /** @type {Entry} */\n var item = {\n minX: extent[0],\n minY: extent[1],\n maxX: extent[2],\n maxY: extent[3],\n value: value\n };\n this.rbush_.insert(item);\n this.items_[util_getUid(value)] = item;\n };\n /**\n * Bulk-insert values into the RBush.\n * @param {Array<import("../extent.js").Extent>} extents Extents.\n * @param {Array<T>} values Values.\n */\n\n\n RBush.prototype.load = function (extents, values) {\n var items = new Array(values.length);\n\n for (var i = 0, l = values.length; i < l; i++) {\n var extent = extents[i];\n var value = values[i];\n /** @type {Entry} */\n\n var item = {\n minX: extent[0],\n minY: extent[1],\n maxX: extent[2],\n maxY: extent[3],\n value: value\n };\n items[i] = item;\n this.items_[util_getUid(value)] = item;\n }\n\n this.rbush_.load(items);\n };\n /**\n * Remove a value from the RBush.\n * @param {T} value Value.\n * @return {boolean} Removed.\n */\n\n\n RBush.prototype.remove = function (value) {\n var uid = util_getUid(value); // get the object in which the value was wrapped when adding to the\n // internal rbush. then use that object to do the removal.\n\n var item = this.items_[uid];\n delete this.items_[uid];\n return this.rbush_.remove(item) !== null;\n };\n /**\n * Update the extent of a value in the RBush.\n * @param {import("../extent.js").Extent} extent Extent.\n * @param {T} value Value.\n */\n\n\n RBush.prototype.update = function (extent, value) {\n var item = this.items_[util_getUid(value)];\n var bbox = [item.minX, item.minY, item.maxX, item.maxY];\n\n if (!extent_equals(bbox, extent)) {\n this.remove(value);\n this.insert(extent, value);\n }\n };\n /**\n * Return all values in the RBush.\n * @return {Array<T>} All.\n */\n\n\n RBush.prototype.getAll = function () {\n var items = this.rbush_.all();\n return items.map(function (item) {\n return item.value;\n });\n };\n /**\n * Return all values in the given extent.\n * @param {import("../extent.js").Extent} extent Extent.\n * @return {Array<T>} All in extent.\n */\n\n\n RBush.prototype.getInExtent = function (extent) {\n /** @type {Entry} */\n var bbox = {\n minX: extent[0],\n minY: extent[1],\n maxX: extent[2],\n maxY: extent[3]\n };\n var items = this.rbush_.search(bbox);\n return items.map(function (item) {\n return item.value;\n });\n };\n /**\n * Calls a callback function with each value in the tree.\n * If the callback returns a truthy value, this value is returned without\n * checking the rest of the tree.\n * @param {function(T): *} callback Callback.\n * @return {*} Callback return value.\n */\n\n\n RBush.prototype.forEach = function (callback) {\n return this.forEach_(this.getAll(), callback);\n };\n /**\n * Calls a callback function with each value in the provided extent.\n * @param {import("../extent.js").Extent} extent Extent.\n * @param {function(T): *} callback Callback.\n * @return {*} Callback return value.\n */\n\n\n RBush.prototype.forEachInExtent = function (extent, callback) {\n return this.forEach_(this.getInExtent(extent), callback);\n };\n /**\n * @param {Array<T>} values Values.\n * @param {function(T): *} callback Callback.\n * @private\n * @return {*} Callback return value.\n */\n\n\n RBush.prototype.forEach_ = function (values, callback) {\n var result;\n\n for (var i = 0, l = values.length; i < l; i++) {\n result = callback(values[i]);\n\n if (result) {\n return result;\n }\n }\n\n return result;\n };\n /**\n * @return {boolean} Is empty.\n */\n\n\n RBush.prototype.isEmpty = function () {\n return obj_isEmpty(this.items_);\n };\n /**\n * Remove all values from the RBush.\n */\n\n\n RBush.prototype.clear = function () {\n this.rbush_.clear();\n this.items_ = {};\n };\n /**\n * @param {import("../extent.js").Extent=} opt_extent Extent.\n * @return {import("../extent.js").Extent} Extent.\n */\n\n\n RBush.prototype.getExtent = function (opt_extent) {\n var data = this.rbush_.toJSON();\n return createOrUpdate(data.minX, data.minY, data.maxX, data.maxY, opt_extent);\n };\n /**\n * @param {RBush} rbush R-Tree.\n */\n\n\n RBush.prototype.concat = function (rbush) {\n this.rbush_.load(rbush.rbush_.all());\n\n for (var i in rbush.items_) {\n this.items_[i] = rbush.items_[i];\n }\n };\n\n return RBush;\n}();\n\n/* harmony default export */ var structs_RBush = (RBush);\n;// CONCATENATED MODULE: ./node_modules/ol/source/VectorEventType.js\n/**\n * @module ol/source/VectorEventType\n */\n\n/**\n * @enum {string}\n */\n/* harmony default export */ var VectorEventType = ({\n /**\n * Triggered when a feature is added to the source.\n * @event module:ol/source/Vector.VectorSourceEvent#addfeature\n * @api\n */\n ADDFEATURE: \'addfeature\',\n\n /**\n * Triggered when a feature is updated.\n * @event module:ol/source/Vector.VectorSourceEvent#changefeature\n * @api\n */\n CHANGEFEATURE: \'changefeature\',\n\n /**\n * Triggered when the clear method is called on the source.\n * @event module:ol/source/Vector.VectorSourceEvent#clear\n * @api\n */\n CLEAR: \'clear\',\n\n /**\n * Triggered when a feature is removed from the source.\n * See {@link module:ol/source/Vector#clear source.clear()} for exceptions.\n * @event module:ol/source/Vector.VectorSourceEvent#removefeature\n * @api\n */\n REMOVEFEATURE: \'removefeature\',\n\n /**\n * Triggered when features starts loading.\n * @event module:ol/source/Vector.VectorSourceEvent#featuresloadstart\n * @api\n */\n FEATURESLOADSTART: \'featuresloadstart\',\n\n /**\n * Triggered when features finishes loading.\n * @event module:ol/source/Vector.VectorSourceEvent#featuresloadend\n * @api\n */\n FEATURESLOADEND: \'featuresloadend\',\n\n /**\n * Triggered if feature loading results in an error.\n * @event module:ol/source/Vector.VectorSourceEvent#featuresloaderror\n * @api\n */\n FEATURESLOADERROR: \'featuresloaderror\'\n});\n;// CONCATENATED MODULE: ./node_modules/ol/loadingstrategy.js\n/**\n * @module ol/loadingstrategy\n */\n\n/**\n * Strategy function for loading all features with a single request.\n * @param {import("./extent.js").Extent} extent Extent.\n * @param {number} resolution Resolution.\n * @return {Array<import("./extent.js").Extent>} Extents.\n * @api\n */\nfunction loadingstrategy_all(extent, resolution) {\n return [[-Infinity, -Infinity, Infinity, Infinity]];\n}\n/**\n * Strategy function for loading features based on the view\'s extent and\n * resolution.\n * @param {import("./extent.js").Extent} extent Extent.\n * @param {number} resolution Resolution.\n * @return {Array<import("./extent.js").Extent>} Extents.\n * @api\n */\n\nfunction bbox(extent, resolution) {\n return [extent];\n}\n/**\n * Creates a strategy function for loading features based on a tile grid.\n * @param {import("./tilegrid/TileGrid.js").default} tileGrid Tile grid.\n * @return {function(import("./extent.js").Extent, number): Array<import("./extent.js").Extent>} Loading strategy.\n * @api\n */\n\nfunction tile(tileGrid) {\n return (\n /**\n * @param {import("./extent.js").Extent} extent Extent.\n * @param {number} resolution Resolution.\n * @return {Array<import("./extent.js").Extent>} Extents.\n */\n function (extent, resolution) {\n var z = tileGrid.getZForResolution(resolution);\n var tileRange = tileGrid.getTileRangeForExtentAndZ(extent, z);\n /** @type {Array<import("./extent.js").Extent>} */\n\n var extents = [];\n /** @type {import("./tilecoord.js").TileCoord} */\n\n var tileCoord = [z, 0, 0];\n\n for (tileCoord[1] = tileRange.minX; tileCoord[1] <= tileRange.maxX; ++tileCoord[1]) {\n for (tileCoord[2] = tileRange.minY; tileCoord[2] <= tileRange.maxY; ++tileCoord[2]) {\n extents.push(tileGrid.getTileCoordExtent(tileCoord));\n }\n }\n\n return extents;\n }\n );\n}\n;// CONCATENATED MODULE: ./node_modules/ol/source/Vector.js\n/**\n * @module ol/source/Vector\n */\nvar Vector_extends = undefined && undefined.__extends || function () {\n var _extendStatics = function extendStatics(d, b) {\n _extendStatics = Object.setPrototypeOf || {\n __proto__: []\n } instanceof Array && function (d, b) {\n d.__proto__ = b;\n } || function (d, b) {\n for (var p in b) {\n if (Object.prototype.hasOwnProperty.call(b, p)) d[p] = b[p];\n }\n };\n\n return _extendStatics(d, b);\n };\n\n return function (d, b) {\n _extendStatics(d, b);\n\n function __() {\n this.constructor = d;\n }\n\n d.prototype = b === null ? Object.create(b) : (__.prototype = b.prototype, new __());\n };\n}();\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n/**\n * A function that takes an {@link module:ol/extent~Extent} and a resolution as arguments, and\n * returns an array of {@link module:ol/extent~Extent} with the extents to load. Usually this\n * is one of the standard {@link module:ol/loadingstrategy} strategies.\n *\n * @typedef {function(import("../extent.js").Extent, number): Array<import("../extent.js").Extent>} LoadingStrategy\n * @api\n */\n\n/**\n * @classdesc\n * Events emitted by {@link module:ol/source/Vector} instances are instances of this\n * type.\n * @template {import("../geom/Geometry.js").default} Geometry\n */\n\nvar VectorSourceEvent =\n/** @class */\nfunction (_super) {\n Vector_extends(VectorSourceEvent, _super);\n /**\n * @param {string} type Type.\n * @param {import("../Feature.js").default<Geometry>=} opt_feature Feature.\n * @param {Array<import("../Feature.js").default<Geometry>>=} opt_features Features.\n */\n\n\n function VectorSourceEvent(type, opt_feature, opt_features) {\n var _this = _super.call(this, type) || this;\n /**\n * The added or removed feature for the `ADDFEATURE` and `REMOVEFEATURE` events, `undefined` otherwise.\n * @type {import("../Feature.js").default<Geometry>|undefined}\n * @api\n */\n\n\n _this.feature = opt_feature;\n /**\n * The loaded features for the `FEATURESLOADED` event, `undefined` otherwise.\n * @type {Array<import("../Feature.js").default<Geometry>>|undefined}\n * @api\n */\n\n _this.features = opt_features;\n return _this;\n }\n\n return VectorSourceEvent;\n}(Event);\n\n\n/**\n * @typedef {Object} Options\n * @property {import("./Source.js").AttributionLike} [attributions] Attributions.\n * @property {Array<import("../Feature.js").default>|Collection<import("../Feature.js").default>} [features]\n * Features. If provided as {@link module:ol/Collection}, the features in the source\n * and the collection will stay in sync.\n * @property {import("../format/Feature.js").default} [format] The feature format used by the XHR\n * feature loader when `url` is set. Required if `url` is set, otherwise ignored.\n * @property {import("../featureloader.js").FeatureLoader} [loader]\n * The loader function used to load features, from a remote source for example.\n * If this is not set and `url` is set, the source will create and use an XHR\n * feature loader.\n *\n * Example:\n *\n * ```js\n * import {Vector} from \'ol/source\';\n * import {GeoJSON} from \'ol/format\';\n * import {bbox} from \'ol/loadingstrategy\';\n *\n * var vectorSource = new Vector({\n * format: new GeoJSON(),\n * loader: function(extent, resolution, projection) {\n * var proj = projection.getCode();\n * var url = \'https://ahocevar.com/geoserver/wfs?service=WFS&\' +\n * \'version=1.1.0&request=GetFeature&typename=osm:water_areas&\' +\n * \'outputFormat=application/json&srsname=\' + proj + \'&\' +\n * \'bbox=\' + extent.join(\',\') + \',\' + proj;\n * var xhr = new XMLHttpRequest();\n * xhr.open(\'GET\', url);\n * var onError = function() {\n * vectorSource.removeLoadedExtent(extent);\n * }\n * xhr.onerror = onError;\n * xhr.onload = function() {\n * if (xhr.status == 200) {\n * vectorSource.addFeatures(\n * vectorSource.getFormat().readFeatures(xhr.responseText));\n * } else {\n * onError();\n * }\n * }\n * xhr.send();\n * },\n * strategy: bbox\n * });\n * ```\n * @property {boolean} [overlaps=true] This source may have overlapping geometries.\n * Setting this to `false` (e.g. for sources with polygons that represent administrative\n * boundaries or TopoJSON sources) allows the renderer to optimise fill and\n * stroke operations.\n * @property {LoadingStrategy} [strategy] The loading strategy to use.\n * By default an {@link module:ol/loadingstrategy~all}\n * strategy is used, a one-off strategy which loads all features at once.\n * @property {string|import("../featureloader.js").FeatureUrlFunction} [url]\n * Setting this option instructs the source to load features using an XHR loader\n * (see {@link module:ol/featureloader~xhr}). Use a `string` and an\n * {@link module:ol/loadingstrategy~all} for a one-off download of all features from\n * the given URL. Use a {@link module:ol/featureloader~FeatureUrlFunction} to generate the url with\n * other loading strategies.\n * Requires `format` to be set as well.\n * When default XHR feature loader is provided, the features will\n * be transformed from the data projection to the view projection\n * during parsing. If your remote data source does not advertise its projection\n * properly, this transformation will be incorrect. For some formats, the\n * default projection (usually EPSG:4326) can be overridden by setting the\n * dataProjection constructor option on the format.\n * Note that if a source contains non-feature data, such as a GeoJSON geometry\n * or a KML NetworkLink, these will be ignored. Use a custom loader to load these.\n * @property {boolean} [useSpatialIndex=true]\n * By default, an RTree is used as spatial index. When features are removed and\n * added frequently, and the total number of features is low, setting this to\n * `false` may improve performance.\n *\n * Note that\n * {@link module:ol/source/Vector~VectorSource#getFeaturesInExtent},\n * {@link module:ol/source/Vector~VectorSource#getClosestFeatureToCoordinate} and\n * {@link module:ol/source/Vector~VectorSource#getExtent} cannot be used when `useSpatialIndex` is\n * set to `false`, and {@link module:ol/source/Vector~VectorSource#forEachFeatureInExtent} will loop\n * through all features.\n *\n * When set to `false`, the features will be maintained in an\n * {@link module:ol/Collection}, which can be retrieved through\n * {@link module:ol/source/Vector~VectorSource#getFeaturesCollection}.\n * @property {boolean} [wrapX=true] Wrap the world horizontally. For vector editing across the\n * -180° and 180° meridians to work properly, this should be set to `false`. The\n * resulting geometry coordinates will then exceed the world bounds.\n */\n\n/**\n * @classdesc\n * Provides a source of features for vector layers. Vector features provided\n * by this source are suitable for editing. See {@link module:ol/source/VectorTile~VectorTile} for\n * vector data that is optimized for rendering.\n *\n * @fires VectorSourceEvent\n * @api\n * @template {import("../geom/Geometry.js").default} Geometry\n */\n\nvar VectorSource =\n/** @class */\nfunction (_super) {\n Vector_extends(VectorSource, _super);\n /**\n * @param {Options=} opt_options Vector source options.\n */\n\n\n function VectorSource(opt_options) {\n var _this = this;\n\n var options = opt_options || {};\n _this = _super.call(this, {\n attributions: options.attributions,\n projection: undefined,\n state: State.READY,\n wrapX: options.wrapX !== undefined ? options.wrapX : true\n }) || this;\n /**\n * @private\n * @type {import("../featureloader.js").FeatureLoader}\n */\n\n _this.loader_ = VOID;\n /**\n * @private\n * @type {import("../format/Feature.js").default|undefined}\n */\n\n _this.format_ = options.format;\n /**\n * @private\n * @type {boolean}\n */\n\n _this.overlaps_ = options.overlaps === undefined ? true : options.overlaps;\n /**\n * @private\n * @type {string|import("../featureloader.js").FeatureUrlFunction|undefined}\n */\n\n _this.url_ = options.url;\n\n if (options.loader !== undefined) {\n _this.loader_ = options.loader;\n } else if (_this.url_ !== undefined) {\n asserts_assert(_this.format_, 7); // `format` must be set when `url` is set\n // create a XHR feature loader for "url" and "format"\n\n _this.loader_ = xhr(_this.url_,\n /** @type {import("../format/Feature.js").default} */\n _this.format_);\n }\n /**\n * @private\n * @type {LoadingStrategy}\n */\n\n\n _this.strategy_ = options.strategy !== undefined ? options.strategy : loadingstrategy_all;\n var useSpatialIndex = options.useSpatialIndex !== undefined ? options.useSpatialIndex : true;\n /**\n * @private\n * @type {RBush<import("../Feature.js").default<Geometry>>}\n */\n\n _this.featuresRtree_ = useSpatialIndex ? new structs_RBush() : null;\n /**\n * @private\n * @type {RBush<{extent: import("../extent.js").Extent}>}\n */\n\n _this.loadedExtentsRtree_ = new structs_RBush();\n /**\n * @private\n * @type {!Object<string, import("../Feature.js").default<Geometry>>}\n */\n\n _this.nullGeometryFeatures_ = {};\n /**\n * A lookup of features by id (the return from feature.getId()).\n * @private\n * @type {!Object<string, import("../Feature.js").default<Geometry>>}\n */\n\n _this.idIndex_ = {};\n /**\n * A lookup of features by uid (using getUid(feature)).\n * @private\n * @type {!Object<string, import("../Feature.js").default<Geometry>>}\n */\n\n _this.uidIndex_ = {};\n /**\n * @private\n * @type {Object<string, Array<import("../events.js").EventsKey>>}\n */\n\n _this.featureChangeKeys_ = {};\n /**\n * @private\n * @type {Collection<import("../Feature.js").default<Geometry>>}\n */\n\n _this.featuresCollection_ = null;\n var collection, features;\n\n if (Array.isArray(options.features)) {\n features = options.features;\n } else if (options.features) {\n collection = options.features;\n features = collection.getArray();\n }\n\n if (!useSpatialIndex && collection === undefined) {\n collection = new ol_Collection(features);\n }\n\n if (features !== undefined) {\n _this.addFeaturesInternal(features);\n }\n\n if (collection !== undefined) {\n _this.bindFeaturesCollection_(collection);\n }\n\n return _this;\n }\n /**\n * Add a single feature to the source. If you want to add a batch of features\n * at once, call {@link module:ol/source/Vector~VectorSource#addFeatures #addFeatures()}\n * instead. A feature will not be added to the source if feature with\n * the same id is already there. The reason for this behavior is to avoid\n * feature duplication when using bbox or tile loading strategies.\n * Note: this also applies if an {@link module:ol/Collection} is used for features,\n * meaning that if a feature with a duplicate id is added in the collection, it will\n * be removed from it right away.\n * @param {import("../Feature.js").default<Geometry>} feature Feature to add.\n * @api\n */\n\n\n VectorSource.prototype.addFeature = function (feature) {\n this.addFeatureInternal(feature);\n this.changed();\n };\n /**\n * Add a feature without firing a `change` event.\n * @param {import("../Feature.js").default<Geometry>} feature Feature.\n * @protected\n */\n\n\n VectorSource.prototype.addFeatureInternal = function (feature) {\n var featureKey = util_getUid(feature);\n\n if (!this.addToIndex_(featureKey, feature)) {\n if (this.featuresCollection_) {\n this.featuresCollection_.remove(feature);\n }\n\n return;\n }\n\n this.setupChangeEvents_(featureKey, feature);\n var geometry = feature.getGeometry();\n\n if (geometry) {\n var extent = geometry.getExtent();\n\n if (this.featuresRtree_) {\n this.featuresRtree_.insert(extent, feature);\n }\n } else {\n this.nullGeometryFeatures_[featureKey] = feature;\n }\n\n this.dispatchEvent(new VectorSourceEvent(VectorEventType.ADDFEATURE, feature));\n };\n /**\n * @param {string} featureKey Unique identifier for the feature.\n * @param {import("../Feature.js").default<Geometry>} feature The feature.\n * @private\n */\n\n\n VectorSource.prototype.setupChangeEvents_ = function (featureKey, feature) {\n this.featureChangeKeys_[featureKey] = [listen(feature, EventType.CHANGE, this.handleFeatureChange_, this), listen(feature, ObjectEventType.PROPERTYCHANGE, this.handleFeatureChange_, this)];\n };\n /**\n * @param {string} featureKey Unique identifier for the feature.\n * @param {import("../Feature.js").default<Geometry>} feature The feature.\n * @return {boolean} The feature is "valid", in the sense that it is also a\n * candidate for insertion into the Rtree.\n * @private\n */\n\n\n VectorSource.prototype.addToIndex_ = function (featureKey, feature) {\n var valid = true;\n var id = feature.getId();\n\n if (id !== undefined) {\n if (!(id.toString() in this.idIndex_)) {\n this.idIndex_[id.toString()] = feature;\n } else {\n valid = false;\n }\n }\n\n if (valid) {\n asserts_assert(!(featureKey in this.uidIndex_), 30); // The passed `feature` was already added to the source\n\n this.uidIndex_[featureKey] = feature;\n }\n\n return valid;\n };\n /**\n * Add a batch of features to the source.\n * @param {Array<import("../Feature.js").default<Geometry>>} features Features to add.\n * @api\n */\n\n\n VectorSource.prototype.addFeatures = function (features) {\n this.addFeaturesInternal(features);\n this.changed();\n };\n /**\n * Add features without firing a `change` event.\n * @param {Array<import("../Feature.js").default<Geometry>>} features Features.\n * @protected\n */\n\n\n VectorSource.prototype.addFeaturesInternal = function (features) {\n var extents = [];\n var newFeatures = [];\n var geometryFeatures = [];\n\n for (var i = 0, length_1 = features.length; i < length_1; i++) {\n var feature = features[i];\n var featureKey = util_getUid(feature);\n\n if (this.addToIndex_(featureKey, feature)) {\n newFeatures.push(feature);\n }\n }\n\n for (var i = 0, length_2 = newFeatures.length; i < length_2; i++) {\n var feature = newFeatures[i];\n var featureKey = util_getUid(feature);\n this.setupChangeEvents_(featureKey, feature);\n var geometry = feature.getGeometry();\n\n if (geometry) {\n var extent = geometry.getExtent();\n extents.push(extent);\n geometryFeatures.push(feature);\n } else {\n this.nullGeometryFeatures_[featureKey] = feature;\n }\n }\n\n if (this.featuresRtree_) {\n this.featuresRtree_.load(extents, geometryFeatures);\n }\n\n for (var i = 0, length_3 = newFeatures.length; i < length_3; i++) {\n this.dispatchEvent(new VectorSourceEvent(VectorEventType.ADDFEATURE, newFeatures[i]));\n }\n };\n /**\n * @param {!Collection<import("../Feature.js").default<Geometry>>} collection Collection.\n * @private\n */\n\n\n VectorSource.prototype.bindFeaturesCollection_ = function (collection) {\n var modifyingCollection = false;\n this.addEventListener(VectorEventType.ADDFEATURE,\n /**\n * @param {VectorSourceEvent<Geometry>} evt The vector source event\n */\n function (evt) {\n if (!modifyingCollection) {\n modifyingCollection = true;\n collection.push(evt.feature);\n modifyingCollection = false;\n }\n });\n this.addEventListener(VectorEventType.REMOVEFEATURE,\n /**\n * @param {VectorSourceEvent<Geometry>} evt The vector source event\n */\n function (evt) {\n if (!modifyingCollection) {\n modifyingCollection = true;\n collection.remove(evt.feature);\n modifyingCollection = false;\n }\n });\n collection.addEventListener(CollectionEventType.ADD,\n /**\n * @param {import("../Collection.js").CollectionEvent} evt The collection event\n */\n function (evt) {\n if (!modifyingCollection) {\n modifyingCollection = true;\n this.addFeature(\n /** @type {import("../Feature.js").default<Geometry>} */\n evt.element);\n modifyingCollection = false;\n }\n }.bind(this));\n collection.addEventListener(CollectionEventType.REMOVE,\n /**\n * @param {import("../Collection.js").CollectionEvent} evt The collection event\n */\n function (evt) {\n if (!modifyingCollection) {\n modifyingCollection = true;\n this.removeFeature(\n /** @type {import("../Feature.js").default<Geometry>} */\n evt.element);\n modifyingCollection = false;\n }\n }.bind(this));\n this.featuresCollection_ = collection;\n };\n /**\n * Remove all features from the source.\n * @param {boolean=} opt_fast Skip dispatching of {@link module:ol/source/Vector.VectorSourceEvent#removefeature} events.\n * @api\n */\n\n\n VectorSource.prototype.clear = function (opt_fast) {\n if (opt_fast) {\n for (var featureId in this.featureChangeKeys_) {\n var keys = this.featureChangeKeys_[featureId];\n keys.forEach(unlistenByKey);\n }\n\n if (!this.featuresCollection_) {\n this.featureChangeKeys_ = {};\n this.idIndex_ = {};\n this.uidIndex_ = {};\n }\n } else {\n if (this.featuresRtree_) {\n this.featuresRtree_.forEach(this.removeFeatureInternal.bind(this));\n\n for (var id in this.nullGeometryFeatures_) {\n this.removeFeatureInternal(this.nullGeometryFeatures_[id]);\n }\n }\n }\n\n if (this.featuresCollection_) {\n this.featuresCollection_.clear();\n }\n\n if (this.featuresRtree_) {\n this.featuresRtree_.clear();\n }\n\n this.nullGeometryFeatures_ = {};\n var clearEvent = new VectorSourceEvent(VectorEventType.CLEAR);\n this.dispatchEvent(clearEvent);\n this.changed();\n };\n /**\n * Iterate through all features on the source, calling the provided callback\n * with each one. If the callback returns any "truthy" value, iteration will\n * stop and the function will return the same value.\n * Note: this function only iterate through the feature that have a defined geometry.\n *\n * @param {function(import("../Feature.js").default<Geometry>): T} callback Called with each feature\n * on the source. Return a truthy value to stop iteration.\n * @return {T|undefined} The return value from the last call to the callback.\n * @template T\n * @api\n */\n\n\n VectorSource.prototype.forEachFeature = function (callback) {\n if (this.featuresRtree_) {\n return this.featuresRtree_.forEach(callback);\n } else if (this.featuresCollection_) {\n this.featuresCollection_.forEach(callback);\n }\n };\n /**\n * Iterate through all features whose geometries contain the provided\n * coordinate, calling the callback with each feature. If the callback returns\n * a "truthy" value, iteration will stop and the function will return the same\n * value.\n *\n * @param {import("../coordinate.js").Coordinate} coordinate Coordinate.\n * @param {function(import("../Feature.js").default<Geometry>): T} callback Called with each feature\n * whose goemetry contains the provided coordinate.\n * @return {T|undefined} The return value from the last call to the callback.\n * @template T\n */\n\n\n VectorSource.prototype.forEachFeatureAtCoordinateDirect = function (coordinate, callback) {\n var extent = [coordinate[0], coordinate[1], coordinate[0], coordinate[1]];\n return this.forEachFeatureInExtent(extent, function (feature) {\n var geometry = feature.getGeometry();\n\n if (geometry.intersectsCoordinate(coordinate)) {\n return callback(feature);\n } else {\n return undefined;\n }\n });\n };\n /**\n * Iterate through all features whose bounding box intersects the provided\n * extent (note that the feature\'s geometry may not intersect the extent),\n * calling the callback with each feature. If the callback returns a "truthy"\n * value, iteration will stop and the function will return the same value.\n *\n * If you are interested in features whose geometry intersects an extent, call\n * the {@link module:ol/source/Vector~VectorSource#forEachFeatureIntersectingExtent #forEachFeatureIntersectingExtent()} method instead.\n *\n * When `useSpatialIndex` is set to false, this method will loop through all\n * features, equivalent to {@link module:ol/source/Vector~VectorSource#forEachFeature #forEachFeature()}.\n *\n * @param {import("../extent.js").Extent} extent Extent.\n * @param {function(import("../Feature.js").default<Geometry>): T} callback Called with each feature\n * whose bounding box intersects the provided extent.\n * @return {T|undefined} The return value from the last call to the callback.\n * @template T\n * @api\n */\n\n\n VectorSource.prototype.forEachFeatureInExtent = function (extent, callback) {\n if (this.featuresRtree_) {\n return this.featuresRtree_.forEachInExtent(extent, callback);\n } else if (this.featuresCollection_) {\n this.featuresCollection_.forEach(callback);\n }\n };\n /**\n * Iterate through all features whose geometry intersects the provided extent,\n * calling the callback with each feature. If the callback returns a "truthy"\n * value, iteration will stop and the function will return the same value.\n *\n * If you only want to test for bounding box intersection, call the\n * {@link module:ol/source/Vector~VectorSource#forEachFeatureInExtent #forEachFeatureInExtent()} method instead.\n *\n * @param {import("../extent.js").Extent} extent Extent.\n * @param {function(import("../Feature.js").default<Geometry>): T} callback Called with each feature\n * whose geometry intersects the provided extent.\n * @return {T|undefined} The return value from the last call to the callback.\n * @template T\n * @api\n */\n\n\n VectorSource.prototype.forEachFeatureIntersectingExtent = function (extent, callback) {\n return this.forEachFeatureInExtent(extent,\n /**\n * @param {import("../Feature.js").default<Geometry>} feature Feature.\n * @return {T|undefined} The return value from the last call to the callback.\n */\n function (feature) {\n var geometry = feature.getGeometry();\n\n if (geometry.intersectsExtent(extent)) {\n var result = callback(feature);\n\n if (result) {\n return result;\n }\n }\n });\n };\n /**\n * Get the features collection associated with this source. Will be `null`\n * unless the source was configured with `useSpatialIndex` set to `false`, or\n * with an {@link module:ol/Collection} as `features`.\n * @return {Collection<import("../Feature.js").default<Geometry>>} The collection of features.\n * @api\n */\n\n\n VectorSource.prototype.getFeaturesCollection = function () {\n return this.featuresCollection_;\n };\n /**\n * Get all features on the source in random order.\n * @return {Array<import("../Feature.js").default<Geometry>>} Features.\n * @api\n */\n\n\n VectorSource.prototype.getFeatures = function () {\n var features;\n\n if (this.featuresCollection_) {\n features = this.featuresCollection_.getArray();\n } else if (this.featuresRtree_) {\n features = this.featuresRtree_.getAll();\n\n if (!obj_isEmpty(this.nullGeometryFeatures_)) {\n array_extend(features, getValues(this.nullGeometryFeatures_));\n }\n }\n\n return (\n /** @type {Array<import("../Feature.js").default<Geometry>>} */\n features\n );\n };\n /**\n * Get all features whose geometry intersects the provided coordinate.\n * @param {import("../coordinate.js").Coordinate} coordinate Coordinate.\n * @return {Array<import("../Feature.js").default<Geometry>>} Features.\n * @api\n */\n\n\n VectorSource.prototype.getFeaturesAtCoordinate = function (coordinate) {\n var features = [];\n this.forEachFeatureAtCoordinateDirect(coordinate, function (feature) {\n features.push(feature);\n });\n return features;\n };\n /**\n * Get all features whose bounding box intersects the provided extent. Note that this returns an array of\n * all features intersecting the given extent in random order (so it may include\n * features whose geometries do not intersect the extent).\n *\n * When `useSpatialIndex` is set to false, this method will return all\n * features.\n *\n * @param {import("../extent.js").Extent} extent Extent.\n * @return {Array<import("../Feature.js").default<Geometry>>} Features.\n * @api\n */\n\n\n VectorSource.prototype.getFeaturesInExtent = function (extent) {\n if (this.featuresRtree_) {\n return this.featuresRtree_.getInExtent(extent);\n } else if (this.featuresCollection_) {\n return this.featuresCollection_.getArray();\n } else {\n return [];\n }\n };\n /**\n * Get the closest feature to the provided coordinate.\n *\n * This method is not available when the source is configured with\n * `useSpatialIndex` set to `false`.\n * @param {import("../coordinate.js").Coordinate} coordinate Coordinate.\n * @param {function(import("../Feature.js").default<Geometry>):boolean=} opt_filter Feature filter function.\n * The filter function will receive one argument, the {@link module:ol/Feature feature}\n * and it should return a boolean value. By default, no filtering is made.\n * @return {import("../Feature.js").default<Geometry>} Closest feature.\n * @api\n */\n\n\n VectorSource.prototype.getClosestFeatureToCoordinate = function (coordinate, opt_filter) {\n // Find the closest feature using branch and bound. We start searching an\n // infinite extent, and find the distance from the first feature found. This\n // becomes the closest feature. We then compute a smaller extent which any\n // closer feature must intersect. We continue searching with this smaller\n // extent, trying to find a closer feature. Every time we find a closer\n // feature, we update the extent being searched so that any even closer\n // feature must intersect it. We continue until we run out of features.\n var x = coordinate[0];\n var y = coordinate[1];\n var closestFeature = null;\n var closestPoint = [NaN, NaN];\n var minSquaredDistance = Infinity;\n var extent = [-Infinity, -Infinity, Infinity, Infinity];\n var filter = opt_filter ? opt_filter : TRUE;\n this.featuresRtree_.forEachInExtent(extent,\n /**\n * @param {import("../Feature.js").default<Geometry>} feature Feature.\n */\n function (feature) {\n if (filter(feature)) {\n var geometry = feature.getGeometry();\n var previousMinSquaredDistance = minSquaredDistance;\n minSquaredDistance = geometry.closestPointXY(x, y, closestPoint, minSquaredDistance);\n\n if (minSquaredDistance < previousMinSquaredDistance) {\n closestFeature = feature; // This is sneaky. Reduce the extent that it is currently being\n // searched while the R-Tree traversal using this same extent object\n // is still in progress. This is safe because the new extent is\n // strictly contained by the old extent.\n\n var minDistance = Math.sqrt(minSquaredDistance);\n extent[0] = x - minDistance;\n extent[1] = y - minDistance;\n extent[2] = x + minDistance;\n extent[3] = y + minDistance;\n }\n }\n });\n return closestFeature;\n };\n /**\n * Get the extent of the features currently in the source.\n *\n * This method is not available when the source is configured with\n * `useSpatialIndex` set to `false`.\n * @param {import("../extent.js").Extent=} opt_extent Destination extent. If provided, no new extent\n * will be created. Instead, that extent\'s coordinates will be overwritten.\n * @return {import("../extent.js").Extent} Extent.\n * @api\n */\n\n\n VectorSource.prototype.getExtent = function (opt_extent) {\n return this.featuresRtree_.getExtent(opt_extent);\n };\n /**\n * Get a feature by its identifier (the value returned by feature.getId()).\n * Note that the index treats string and numeric identifiers as the same. So\n * `source.getFeatureById(2)` will return a feature with id `\'2\'` or `2`.\n *\n * @param {string|number} id Feature identifier.\n * @return {import("../Feature.js").default<Geometry>} The feature (or `null` if not found).\n * @api\n */\n\n\n VectorSource.prototype.getFeatureById = function (id) {\n var feature = this.idIndex_[id.toString()];\n return feature !== undefined ? feature : null;\n };\n /**\n * Get a feature by its internal unique identifier (using `getUid`).\n *\n * @param {string} uid Feature identifier.\n * @return {import("../Feature.js").default<Geometry>} The feature (or `null` if not found).\n */\n\n\n VectorSource.prototype.getFeatureByUid = function (uid) {\n var feature = this.uidIndex_[uid];\n return feature !== undefined ? feature : null;\n };\n /**\n * Get the format associated with this source.\n *\n * @return {import("../format/Feature.js").default|undefined} The feature format.\n * @api\n */\n\n\n VectorSource.prototype.getFormat = function () {\n return this.format_;\n };\n /**\n * @return {boolean} The source can have overlapping geometries.\n */\n\n\n VectorSource.prototype.getOverlaps = function () {\n return this.overlaps_;\n };\n /**\n * Get the url associated with this source.\n *\n * @return {string|import("../featureloader.js").FeatureUrlFunction|undefined} The url.\n * @api\n */\n\n\n VectorSource.prototype.getUrl = function () {\n return this.url_;\n };\n /**\n * @param {Event} event Event.\n * @private\n */\n\n\n VectorSource.prototype.handleFeatureChange_ = function (event) {\n var feature =\n /** @type {import("../Feature.js").default<Geometry>} */\n event.target;\n var featureKey = util_getUid(feature);\n var geometry = feature.getGeometry();\n\n if (!geometry) {\n if (!(featureKey in this.nullGeometryFeatures_)) {\n if (this.featuresRtree_) {\n this.featuresRtree_.remove(feature);\n }\n\n this.nullGeometryFeatures_[featureKey] = feature;\n }\n } else {\n var extent = geometry.getExtent();\n\n if (featureKey in this.nullGeometryFeatures_) {\n delete this.nullGeometryFeatures_[featureKey];\n\n if (this.featuresRtree_) {\n this.featuresRtree_.insert(extent, feature);\n }\n } else {\n if (this.featuresRtree_) {\n this.featuresRtree_.update(extent, feature);\n }\n }\n }\n\n var id = feature.getId();\n\n if (id !== undefined) {\n var sid = id.toString();\n\n if (this.idIndex_[sid] !== feature) {\n this.removeFromIdIndex_(feature);\n this.idIndex_[sid] = feature;\n }\n } else {\n this.removeFromIdIndex_(feature);\n this.uidIndex_[featureKey] = feature;\n }\n\n this.changed();\n this.dispatchEvent(new VectorSourceEvent(VectorEventType.CHANGEFEATURE, feature));\n };\n /**\n * Returns true if the feature is contained within the source.\n * @param {import("../Feature.js").default<Geometry>} feature Feature.\n * @return {boolean} Has feature.\n * @api\n */\n\n\n VectorSource.prototype.hasFeature = function (feature) {\n var id = feature.getId();\n\n if (id !== undefined) {\n return id in this.idIndex_;\n } else {\n return util_getUid(feature) in this.uidIndex_;\n }\n };\n /**\n * @return {boolean} Is empty.\n */\n\n\n VectorSource.prototype.isEmpty = function () {\n return this.featuresRtree_.isEmpty() && obj_isEmpty(this.nullGeometryFeatures_);\n };\n /**\n * @param {import("../extent.js").Extent} extent Extent.\n * @param {number} resolution Resolution.\n * @param {import("../proj/Projection.js").default} projection Projection.\n */\n\n\n VectorSource.prototype.loadFeatures = function (extent, resolution, projection) {\n var loadedExtentsRtree = this.loadedExtentsRtree_;\n var extentsToLoad = this.strategy_(extent, resolution);\n this.loading = false;\n\n var _loop_1 = function _loop_1(i, ii) {\n var extentToLoad = extentsToLoad[i];\n var alreadyLoaded = loadedExtentsRtree.forEachInExtent(extentToLoad,\n /**\n * @param {{extent: import("../extent.js").Extent}} object Object.\n * @return {boolean} Contains.\n */\n function (object) {\n return containsExtent(object.extent, extentToLoad);\n });\n\n if (!alreadyLoaded) {\n this_1.dispatchEvent(new VectorSourceEvent(VectorEventType.FEATURESLOADSTART));\n this_1.loader_.call(this_1, extentToLoad, resolution, projection, function (features) {\n this.dispatchEvent(new VectorSourceEvent(VectorEventType.FEATURESLOADEND, undefined, features));\n }.bind(this_1), function () {\n this.dispatchEvent(new VectorSourceEvent(VectorEventType.FEATURESLOADERROR));\n }.bind(this_1));\n loadedExtentsRtree.insert(extentToLoad, {\n extent: extentToLoad.slice()\n });\n this_1.loading = this_1.loader_ !== VOID;\n }\n };\n\n var this_1 = this;\n\n for (var i = 0, ii = extentsToLoad.length; i < ii; ++i) {\n _loop_1(i, ii);\n }\n };\n\n VectorSource.prototype.refresh = function () {\n this.clear(true);\n this.loadedExtentsRtree_.clear();\n\n _super.prototype.refresh.call(this);\n };\n /**\n * Remove an extent from the list of loaded extents.\n * @param {import("../extent.js").Extent} extent Extent.\n * @api\n */\n\n\n VectorSource.prototype.removeLoadedExtent = function (extent) {\n var loadedExtentsRtree = this.loadedExtentsRtree_;\n var obj;\n loadedExtentsRtree.forEachInExtent(extent, function (object) {\n if (extent_equals(object.extent, extent)) {\n obj = object;\n return true;\n }\n });\n\n if (obj) {\n loadedExtentsRtree.remove(obj);\n }\n };\n /**\n * Remove a single feature from the source. If you want to remove all features\n * at once, use the {@link module:ol/source/Vector~VectorSource#clear #clear()} method\n * instead.\n * @param {import("../Feature.js").default<Geometry>} feature Feature to remove.\n * @api\n */\n\n\n VectorSource.prototype.removeFeature = function (feature) {\n var featureKey = util_getUid(feature);\n\n if (featureKey in this.nullGeometryFeatures_) {\n delete this.nullGeometryFeatures_[featureKey];\n } else {\n if (this.featuresRtree_) {\n this.featuresRtree_.remove(feature);\n }\n }\n\n this.removeFeatureInternal(feature);\n this.changed();\n };\n /**\n * Remove feature without firing a `change` event.\n * @param {import("../Feature.js").default<Geometry>} feature Feature.\n * @protected\n */\n\n\n VectorSource.prototype.removeFeatureInternal = function (feature) {\n var featureKey = util_getUid(feature);\n this.featureChangeKeys_[featureKey].forEach(unlistenByKey);\n delete this.featureChangeKeys_[featureKey];\n var id = feature.getId();\n\n if (id !== undefined) {\n delete this.idIndex_[id.toString()];\n }\n\n delete this.uidIndex_[featureKey];\n this.dispatchEvent(new VectorSourceEvent(VectorEventType.REMOVEFEATURE, feature));\n };\n /**\n * Remove a feature from the id index. Called internally when the feature id\n * may have changed.\n * @param {import("../Feature.js").default<Geometry>} feature The feature.\n * @return {boolean} Removed the feature from the index.\n * @private\n */\n\n\n VectorSource.prototype.removeFromIdIndex_ = function (feature) {\n var removed = false;\n\n for (var id in this.idIndex_) {\n if (this.idIndex_[id] === feature) {\n delete this.idIndex_[id];\n removed = true;\n break;\n }\n }\n\n return removed;\n };\n /**\n * Set the new loader of the source. The next render cycle will use the\n * new loader.\n * @param {import("../featureloader.js").FeatureLoader} loader The loader to set.\n * @api\n */\n\n\n VectorSource.prototype.setLoader = function (loader) {\n this.loader_ = loader;\n };\n /**\n * Points the source to a new url. The next render cycle will use the new url.\n * @param {string|import("../featureloader.js").FeatureUrlFunction} url Url.\n * @api\n */\n\n\n VectorSource.prototype.setUrl = function (url) {\n asserts_assert(this.format_, 7); // `format` must be set when `url` is set\n\n this.setLoader(xhr(url, this.format_));\n };\n\n return VectorSource;\n}(source_Source);\n\n/* harmony default export */ var Vector = (VectorSource);\n;// CONCATENATED MODULE: ./node_modules/ol/ImageTile.js\nvar ImageTile_extends = undefined && undefined.__extends || function () {\n var _extendStatics = function extendStatics(d, b) {\n _extendStatics = Object.setPrototypeOf || {\n __proto__: []\n } instanceof Array && function (d, b) {\n d.__proto__ = b;\n } || function (d, b) {\n for (var p in b) {\n if (Object.prototype.hasOwnProperty.call(b, p)) d[p] = b[p];\n }\n };\n\n return _extendStatics(d, b);\n };\n\n return function (d, b) {\n _extendStatics(d, b);\n\n function __() {\n this.constructor = d;\n }\n\n d.prototype = b === null ? Object.create(b) : (__.prototype = b.prototype, new __());\n };\n}();\n/**\n * @module ol/ImageTile\n */\n\n\n\n\n\n\n\nvar ImageTile =\n/** @class */\nfunction (_super) {\n ImageTile_extends(ImageTile, _super);\n /**\n * @param {import("./tilecoord.js").TileCoord} tileCoord Tile coordinate.\n * @param {import("./TileState.js").default} state State.\n * @param {string} src Image source URI.\n * @param {?string} crossOrigin Cross origin.\n * @param {import("./Tile.js").LoadFunction} tileLoadFunction Tile load function.\n * @param {import("./Tile.js").Options=} opt_options Tile options.\n */\n\n\n function ImageTile(tileCoord, state, src, crossOrigin, tileLoadFunction, opt_options) {\n var _this = _super.call(this, tileCoord, state, opt_options) || this;\n /**\n * @private\n * @type {?string}\n */\n\n\n _this.crossOrigin_ = crossOrigin;\n /**\n * Image URI\n *\n * @private\n * @type {string}\n */\n\n _this.src_ = src;\n _this.key = src;\n /**\n * @private\n * @type {HTMLImageElement|HTMLCanvasElement}\n */\n\n _this.image_ = new Image();\n\n if (crossOrigin !== null) {\n _this.image_.crossOrigin = crossOrigin;\n }\n /**\n * @private\n * @type {?function():void}\n */\n\n\n _this.unlisten_ = null;\n /**\n * @private\n * @type {import("./Tile.js").LoadFunction}\n */\n\n _this.tileLoadFunction_ = tileLoadFunction;\n return _this;\n }\n /**\n * Get the HTML image element for this tile (may be a Canvas, Image, or Video).\n * @return {HTMLCanvasElement|HTMLImageElement|HTMLVideoElement} Image.\n * @api\n */\n\n\n ImageTile.prototype.getImage = function () {\n return this.image_;\n };\n /**\n * Tracks loading or read errors.\n *\n * @private\n */\n\n\n ImageTile.prototype.handleImageError_ = function () {\n this.state = TileState.ERROR;\n this.unlistenImage_();\n this.image_ = getBlankImage();\n this.changed();\n };\n /**\n * Tracks successful image load.\n *\n * @private\n */\n\n\n ImageTile.prototype.handleImageLoad_ = function () {\n var image =\n /** @type {HTMLImageElement} */\n this.image_;\n\n if (image.naturalWidth && image.naturalHeight) {\n this.state = TileState.LOADED;\n } else {\n this.state = TileState.EMPTY;\n }\n\n this.unlistenImage_();\n this.changed();\n };\n /**\n * Load not yet loaded URI.\n * @api\n */\n\n\n ImageTile.prototype.load = function () {\n if (this.state == TileState.ERROR) {\n this.state = TileState.IDLE;\n this.image_ = new Image();\n\n if (this.crossOrigin_ !== null) {\n this.image_.crossOrigin = this.crossOrigin_;\n }\n }\n\n if (this.state == TileState.IDLE) {\n this.state = TileState.LOADING;\n this.changed();\n this.tileLoadFunction_(this, this.src_);\n this.unlisten_ = listenImage(this.image_, this.handleImageLoad_.bind(this), this.handleImageError_.bind(this));\n }\n };\n /**\n * Discards event handlers which listen for load completion or errors.\n *\n * @private\n */\n\n\n ImageTile.prototype.unlistenImage_ = function () {\n if (this.unlisten_) {\n this.unlisten_();\n this.unlisten_ = null;\n }\n };\n\n return ImageTile;\n}(ol_Tile);\n/**\n * Get a 1-pixel blank image.\n * @return {HTMLCanvasElement} Blank image.\n */\n\n\nfunction getBlankImage() {\n var ctx = createCanvasContext2D(1, 1);\n ctx.fillStyle = \'rgba(0,0,0,0)\';\n ctx.fillRect(0, 0, 1, 1);\n return ctx.canvas;\n}\n\n/* harmony default export */ var ol_ImageTile = (ImageTile);\n;// CONCATENATED MODULE: ./node_modules/ol/reproj/common.js\n/**\n * @module ol/reproj/common\n */\n\n/**\n * Default maximum allowed threshold (in pixels) for reprojection\n * triangulation.\n * @type {number}\n */\nvar ERROR_THRESHOLD = 0.5;\n/**\n * Enable automatic reprojection of raster sources. Default is `true`.\n * TODO: decide if we want to expose this as a build flag or remove it\n * @type {boolean}\n */\n\nvar ENABLE_RASTER_REPROJECTION = true;\n;// CONCATENATED MODULE: ./node_modules/ol/reproj/Triangulation.js\n/**\n * @module ol/reproj/Triangulation\n */\n\n\n\n/**\n * Single triangle; consists of 3 source points and 3 target points.\n * @typedef {Object} Triangle\n * @property {Array<import("../coordinate.js").Coordinate>} source\n * @property {Array<import("../coordinate.js").Coordinate>} target\n */\n\n/**\n * Maximum number of subdivision steps during raster reprojection triangulation.\n * Prevents high memory usage and large number of proj4 calls (for certain\n * transformations and areas). At most `2*(2^this)` triangles are created for\n * each triangulated extent (tile/image).\n * @type {number}\n */\n\nvar MAX_SUBDIVISION = 10;\n/**\n * Maximum allowed size of triangle relative to world width. When transforming\n * corners of world extent between certain projections, the resulting\n * triangulation seems to have zero error and no subdivision is performed. If\n * the triangle width is more than this (relative to world width; 0-1),\n * subdivison is forced (up to `MAX_SUBDIVISION`). Default is `0.25`.\n * @type {number}\n */\n\nvar MAX_TRIANGLE_WIDTH = 0.25;\n/**\n * @classdesc\n * Class containing triangulation of the given target extent.\n * Used for determining source data and the reprojection itself.\n */\n\nvar Triangulation =\n/** @class */\nfunction () {\n /**\n * @param {import("../proj/Projection.js").default} sourceProj Source projection.\n * @param {import("../proj/Projection.js").default} targetProj Target projection.\n * @param {import("../extent.js").Extent} targetExtent Target extent to triangulate.\n * @param {import("../extent.js").Extent} maxSourceExtent Maximal source extent that can be used.\n * @param {number} errorThreshold Acceptable error (in source units).\n * @param {?number} opt_destinationResolution The (optional) resolution of the destination.\n */\n function Triangulation(sourceProj, targetProj, targetExtent, maxSourceExtent, errorThreshold, opt_destinationResolution) {\n /**\n * @type {import("../proj/Projection.js").default}\n * @private\n */\n this.sourceProj_ = sourceProj;\n /**\n * @type {import("../proj/Projection.js").default}\n * @private\n */\n\n this.targetProj_ = targetProj;\n /** @type {!Object<string, import("../coordinate.js").Coordinate>} */\n\n var transformInvCache = {};\n var transformInv = getTransform(this.targetProj_, this.sourceProj_);\n /**\n * @param {import("../coordinate.js").Coordinate} c A coordinate.\n * @return {import("../coordinate.js").Coordinate} Transformed coordinate.\n * @private\n */\n\n this.transformInv_ = function (c) {\n var key = c[0] + \'/\' + c[1];\n\n if (!transformInvCache[key]) {\n transformInvCache[key] = transformInv(c);\n }\n\n return transformInvCache[key];\n };\n /**\n * @type {import("../extent.js").Extent}\n * @private\n */\n\n\n this.maxSourceExtent_ = maxSourceExtent;\n /**\n * @type {number}\n * @private\n */\n\n this.errorThresholdSquared_ = errorThreshold * errorThreshold;\n /**\n * @type {Array<Triangle>}\n * @private\n */\n\n this.triangles_ = [];\n /**\n * Indicates that the triangulation crosses edge of the source projection.\n * @type {boolean}\n * @private\n */\n\n this.wrapsXInSource_ = false;\n /**\n * @type {boolean}\n * @private\n */\n\n this.canWrapXInSource_ = this.sourceProj_.canWrapX() && !!maxSourceExtent && !!this.sourceProj_.getExtent() && extent_getWidth(maxSourceExtent) == extent_getWidth(this.sourceProj_.getExtent());\n /**\n * @type {?number}\n * @private\n */\n\n this.sourceWorldWidth_ = this.sourceProj_.getExtent() ? extent_getWidth(this.sourceProj_.getExtent()) : null;\n /**\n * @type {?number}\n * @private\n */\n\n this.targetWorldWidth_ = this.targetProj_.getExtent() ? extent_getWidth(this.targetProj_.getExtent()) : null;\n var destinationTopLeft = getTopLeft(targetExtent);\n var destinationTopRight = getTopRight(targetExtent);\n var destinationBottomRight = getBottomRight(targetExtent);\n var destinationBottomLeft = getBottomLeft(targetExtent);\n var sourceTopLeft = this.transformInv_(destinationTopLeft);\n var sourceTopRight = this.transformInv_(destinationTopRight);\n var sourceBottomRight = this.transformInv_(destinationBottomRight);\n var sourceBottomLeft = this.transformInv_(destinationBottomLeft);\n /*\n * The maxSubdivision controls how many splittings of the target area can\n * be done. The idea here is to do a linear mapping of the target areas\n * but the actual overal reprojection (can be) extremely non-linear. The\n * default value of MAX_SUBDIVISION was chosen based on mapping a 256x256\n * tile size. However this function is also called to remap canvas rendered\n * layers which can be much larger. This calculation increases the maxSubdivision\n * value by the right factor so that each 256x256 pixel area has\n * MAX_SUBDIVISION divisions.\n */\n\n var maxSubdivision = MAX_SUBDIVISION + (opt_destinationResolution ? Math.max(0, Math.ceil(log2(getArea(targetExtent) / (opt_destinationResolution * opt_destinationResolution * 256 * 256)))) : 0);\n this.addQuad_(destinationTopLeft, destinationTopRight, destinationBottomRight, destinationBottomLeft, sourceTopLeft, sourceTopRight, sourceBottomRight, sourceBottomLeft, maxSubdivision);\n\n if (this.wrapsXInSource_) {\n var leftBound_1 = Infinity;\n this.triangles_.forEach(function (triangle, i, arr) {\n leftBound_1 = Math.min(leftBound_1, triangle.source[0][0], triangle.source[1][0], triangle.source[2][0]);\n }); // Shift triangles to be as close to `leftBound` as possible\n // (if the distance is more than `worldWidth / 2` it can be closer.\n\n this.triangles_.forEach(function (triangle) {\n if (Math.max(triangle.source[0][0], triangle.source[1][0], triangle.source[2][0]) - leftBound_1 > this.sourceWorldWidth_ / 2) {\n var newTriangle = [[triangle.source[0][0], triangle.source[0][1]], [triangle.source[1][0], triangle.source[1][1]], [triangle.source[2][0], triangle.source[2][1]]];\n\n if (newTriangle[0][0] - leftBound_1 > this.sourceWorldWidth_ / 2) {\n newTriangle[0][0] -= this.sourceWorldWidth_;\n }\n\n if (newTriangle[1][0] - leftBound_1 > this.sourceWorldWidth_ / 2) {\n newTriangle[1][0] -= this.sourceWorldWidth_;\n }\n\n if (newTriangle[2][0] - leftBound_1 > this.sourceWorldWidth_ / 2) {\n newTriangle[2][0] -= this.sourceWorldWidth_;\n } // Rarely (if the extent contains both the dateline and prime meridian)\n // the shift can in turn break some triangles.\n // Detect this here and don\'t shift in such cases.\n\n\n var minX = Math.min(newTriangle[0][0], newTriangle[1][0], newTriangle[2][0]);\n var maxX = Math.max(newTriangle[0][0], newTriangle[1][0], newTriangle[2][0]);\n\n if (maxX - minX < this.sourceWorldWidth_ / 2) {\n triangle.source = newTriangle;\n }\n }\n }.bind(this));\n }\n\n transformInvCache = {};\n }\n /**\n * Adds triangle to the triangulation.\n * @param {import("../coordinate.js").Coordinate} a The target a coordinate.\n * @param {import("../coordinate.js").Coordinate} b The target b coordinate.\n * @param {import("../coordinate.js").Coordinate} c The target c coordinate.\n * @param {import("../coordinate.js").Coordinate} aSrc The source a coordinate.\n * @param {import("../coordinate.js").Coordinate} bSrc The source b coordinate.\n * @param {import("../coordinate.js").Coordinate} cSrc The source c coordinate.\n * @private\n */\n\n\n Triangulation.prototype.addTriangle_ = function (a, b, c, aSrc, bSrc, cSrc) {\n this.triangles_.push({\n source: [aSrc, bSrc, cSrc],\n target: [a, b, c]\n });\n };\n /**\n * Adds quad (points in clock-wise order) to the triangulation\n * (and reprojects the vertices) if valid.\n * Performs quad subdivision if needed to increase precision.\n *\n * @param {import("../coordinate.js").Coordinate} a The target a coordinate.\n * @param {import("../coordinate.js").Coordinate} b The target b coordinate.\n * @param {import("../coordinate.js").Coordinate} c The target c coordinate.\n * @param {import("../coordinate.js").Coordinate} d The target d coordinate.\n * @param {import("../coordinate.js").Coordinate} aSrc The source a coordinate.\n * @param {import("../coordinate.js").Coordinate} bSrc The source b coordinate.\n * @param {import("../coordinate.js").Coordinate} cSrc The source c coordinate.\n * @param {import("../coordinate.js").Coordinate} dSrc The source d coordinate.\n * @param {number} maxSubdivision Maximal allowed subdivision of the quad.\n * @private\n */\n\n\n Triangulation.prototype.addQuad_ = function (a, b, c, d, aSrc, bSrc, cSrc, dSrc, maxSubdivision) {\n var sourceQuadExtent = boundingExtent([aSrc, bSrc, cSrc, dSrc]);\n var sourceCoverageX = this.sourceWorldWidth_ ? extent_getWidth(sourceQuadExtent) / this.sourceWorldWidth_ : null;\n var sourceWorldWidth =\n /** @type {number} */\n this.sourceWorldWidth_; // when the quad is wrapped in the source projection\n // it covers most of the projection extent, but not fully\n\n var wrapsX = this.sourceProj_.canWrapX() && sourceCoverageX > 0.5 && sourceCoverageX < 1;\n var needsSubdivision = false;\n\n if (maxSubdivision > 0) {\n if (this.targetProj_.isGlobal() && this.targetWorldWidth_) {\n var targetQuadExtent = boundingExtent([a, b, c, d]);\n var targetCoverageX = extent_getWidth(targetQuadExtent) / this.targetWorldWidth_;\n needsSubdivision = targetCoverageX > MAX_TRIANGLE_WIDTH || needsSubdivision;\n }\n\n if (!wrapsX && this.sourceProj_.isGlobal() && sourceCoverageX) {\n needsSubdivision = sourceCoverageX > MAX_TRIANGLE_WIDTH || needsSubdivision;\n }\n }\n\n if (!needsSubdivision && this.maxSourceExtent_) {\n if (isFinite(sourceQuadExtent[0]) && isFinite(sourceQuadExtent[1]) && isFinite(sourceQuadExtent[2]) && isFinite(sourceQuadExtent[3])) {\n if (!intersects(sourceQuadExtent, this.maxSourceExtent_)) {\n // whole quad outside source projection extent -> ignore\n return;\n }\n }\n }\n\n var isNotFinite = 0;\n\n if (!needsSubdivision) {\n if (!isFinite(aSrc[0]) || !isFinite(aSrc[1]) || !isFinite(bSrc[0]) || !isFinite(bSrc[1]) || !isFinite(cSrc[0]) || !isFinite(cSrc[1]) || !isFinite(dSrc[0]) || !isFinite(dSrc[1])) {\n if (maxSubdivision > 0) {\n needsSubdivision = true;\n } else {\n // It might be the case that only 1 of the points is infinite. In this case\n // we can draw a single triangle with the other three points\n isNotFinite = (!isFinite(aSrc[0]) || !isFinite(aSrc[1]) ? 8 : 0) + (!isFinite(bSrc[0]) || !isFinite(bSrc[1]) ? 4 : 0) + (!isFinite(cSrc[0]) || !isFinite(cSrc[1]) ? 2 : 0) + (!isFinite(dSrc[0]) || !isFinite(dSrc[1]) ? 1 : 0);\n\n if (isNotFinite != 1 && isNotFinite != 2 && isNotFinite != 4 && isNotFinite != 8) {\n return;\n }\n }\n }\n }\n\n if (maxSubdivision > 0) {\n if (!needsSubdivision) {\n var center = [(a[0] + c[0]) / 2, (a[1] + c[1]) / 2];\n var centerSrc = this.transformInv_(center);\n var dx = void 0;\n\n if (wrapsX) {\n var centerSrcEstimX = (math_modulo(aSrc[0], sourceWorldWidth) + math_modulo(cSrc[0], sourceWorldWidth)) / 2;\n dx = centerSrcEstimX - math_modulo(centerSrc[0], sourceWorldWidth);\n } else {\n dx = (aSrc[0] + cSrc[0]) / 2 - centerSrc[0];\n }\n\n var dy = (aSrc[1] + cSrc[1]) / 2 - centerSrc[1];\n var centerSrcErrorSquared = dx * dx + dy * dy;\n needsSubdivision = centerSrcErrorSquared > this.errorThresholdSquared_;\n }\n\n if (needsSubdivision) {\n if (Math.abs(a[0] - c[0]) <= Math.abs(a[1] - c[1])) {\n // split horizontally (top & bottom)\n var bc = [(b[0] + c[0]) / 2, (b[1] + c[1]) / 2];\n var bcSrc = this.transformInv_(bc);\n var da = [(d[0] + a[0]) / 2, (d[1] + a[1]) / 2];\n var daSrc = this.transformInv_(da);\n this.addQuad_(a, b, bc, da, aSrc, bSrc, bcSrc, daSrc, maxSubdivision - 1);\n this.addQuad_(da, bc, c, d, daSrc, bcSrc, cSrc, dSrc, maxSubdivision - 1);\n } else {\n // split vertically (left & right)\n var ab = [(a[0] + b[0]) / 2, (a[1] + b[1]) / 2];\n var abSrc = this.transformInv_(ab);\n var cd = [(c[0] + d[0]) / 2, (c[1] + d[1]) / 2];\n var cdSrc = this.transformInv_(cd);\n this.addQuad_(a, ab, cd, d, aSrc, abSrc, cdSrc, dSrc, maxSubdivision - 1);\n this.addQuad_(ab, b, c, cd, abSrc, bSrc, cSrc, cdSrc, maxSubdivision - 1);\n }\n\n return;\n }\n }\n\n if (wrapsX) {\n if (!this.canWrapXInSource_) {\n return;\n }\n\n this.wrapsXInSource_ = true;\n } // Exactly zero or one of *Src is not finite\n // The triangles must have the diagonal line as the first side\n // This is to allow easy code in reproj.s to make it straight for broken\n // browsers that can\'t handle diagonal clipping\n\n\n if ((isNotFinite & 0xb) == 0) {\n this.addTriangle_(a, c, d, aSrc, cSrc, dSrc);\n }\n\n if ((isNotFinite & 0xe) == 0) {\n this.addTriangle_(a, c, b, aSrc, cSrc, bSrc);\n }\n\n if (isNotFinite) {\n // Try the other two triangles\n if ((isNotFinite & 0xd) == 0) {\n this.addTriangle_(b, d, a, bSrc, dSrc, aSrc);\n }\n\n if ((isNotFinite & 0x7) == 0) {\n this.addTriangle_(b, d, c, bSrc, dSrc, cSrc);\n }\n }\n };\n /**\n * Calculates extent of the \'source\' coordinates from all the triangles.\n *\n * @return {import("../extent.js").Extent} Calculated extent.\n */\n\n\n Triangulation.prototype.calculateSourceExtent = function () {\n var extent = createEmpty();\n this.triangles_.forEach(function (triangle, i, arr) {\n var src = triangle.source;\n extendCoordinate(extent, src[0]);\n extendCoordinate(extent, src[1]);\n extendCoordinate(extent, src[2]);\n });\n return extent;\n };\n /**\n * @return {Array<Triangle>} Array of the calculated triangles.\n */\n\n\n Triangulation.prototype.getTriangles = function () {\n return this.triangles_;\n };\n\n return Triangulation;\n}();\n\n/* harmony default export */ var reproj_Triangulation = (Triangulation);\n;// CONCATENATED MODULE: ./node_modules/ol/source/common.js\n/**\n * @module ol/source/common\n */\n\n/**\n * Default WMS version.\n * @type {string}\n */\nvar DEFAULT_WMS_VERSION = \'1.3.0\';\n/**\n * Context options to disable image smoothing.\n * @type {Object}\n */\n\nvar IMAGE_SMOOTHING_DISABLED = {\n imageSmoothingEnabled: false,\n msImageSmoothingEnabled: false\n};\n;// CONCATENATED MODULE: ./node_modules/ol/reproj.js\n/**\n * @module ol/reproj\n */\n\n\n\n\n\n\nvar brokenDiagonalRendering_;\n/**\n * This draws a small triangle into a canvas by setting the triangle as the clip region\n * and then drawing a (too large) rectangle\n *\n * @param {CanvasRenderingContext2D} ctx The context in which to draw the triangle\n * @param {number} u1 The x-coordinate of the second point. The first point is 0,0.\n * @param {number} v1 The y-coordinate of the second point.\n * @param {number} u2 The x-coordinate of the third point.\n * @param {number} v2 The y-coordinate of the third point.\n */\n\nfunction drawTestTriangle(ctx, u1, v1, u2, v2) {\n ctx.beginPath();\n ctx.moveTo(0, 0);\n ctx.lineTo(u1, v1);\n ctx.lineTo(u2, v2);\n ctx.closePath();\n ctx.save();\n ctx.clip();\n ctx.fillRect(0, 0, Math.max(u1, u2) + 1, Math.max(v1, v2));\n ctx.restore();\n}\n/**\n * Given the data from getImageData, see if the right values appear at the provided offset.\n * Returns true if either the color or transparency is off\n *\n * @param {Uint8ClampedArray} data The data returned from getImageData\n * @param {number} offset The pixel offset from the start of data.\n * @return {boolean} true if the diagonal rendering is broken\n */\n\n\nfunction verifyBrokenDiagonalRendering(data, offset) {\n // the values ought to be close to the rgba(210, 0, 0, 0.75)\n return Math.abs(data[offset * 4] - 210) > 2 || Math.abs(data[offset * 4 + 3] - 0.75 * 255) > 2;\n}\n/**\n * Determines if the current browser configuration can render triangular clip regions correctly.\n * This value is cached so the function is only expensive the first time called.\n * Firefox on Windows (as of now) does not if HWA is enabled. See https://bugzilla.mozilla.org/show_bug.cgi?id=1606976\n * IE also doesn\'t. Chrome works, and everything seems to work on OSX and Android. This function caches the\n * result. I suppose that it is conceivably possible that a browser might flip modes while the app is\n * running, but lets hope not.\n *\n * @return {boolean} true if the Diagonal Rendering is broken.\n */\n\n\nfunction isBrokenDiagonalRendering() {\n if (brokenDiagonalRendering_ === undefined) {\n var ctx = document.createElement(\'canvas\').getContext(\'2d\');\n ctx.globalCompositeOperation = \'lighter\';\n ctx.fillStyle = \'rgba(210, 0, 0, 0.75)\';\n drawTestTriangle(ctx, 4, 5, 4, 0);\n drawTestTriangle(ctx, 4, 5, 0, 5);\n var data = ctx.getImageData(0, 0, 3, 3).data;\n brokenDiagonalRendering_ = verifyBrokenDiagonalRendering(data, 0) || verifyBrokenDiagonalRendering(data, 4) || verifyBrokenDiagonalRendering(data, 8);\n }\n\n return brokenDiagonalRendering_;\n}\n/**\n * Calculates ideal resolution to use from the source in order to achieve\n * pixel mapping as close as possible to 1:1 during reprojection.\n * The resolution is calculated regardless of what resolutions\n * are actually available in the dataset (TileGrid, Image, ...).\n *\n * @param {import("./proj/Projection.js").default} sourceProj Source projection.\n * @param {import("./proj/Projection.js").default} targetProj Target projection.\n * @param {import("./coordinate.js").Coordinate} targetCenter Target center.\n * @param {number} targetResolution Target resolution.\n * @return {number} The best resolution to use. Can be +-Infinity, NaN or 0.\n */\n\n\nfunction calculateSourceResolution(sourceProj, targetProj, targetCenter, targetResolution) {\n var sourceCenter = transform(targetCenter, targetProj, sourceProj); // calculate the ideal resolution of the source data\n\n var sourceResolution = getPointResolution(targetProj, targetResolution, targetCenter);\n var targetMetersPerUnit = targetProj.getMetersPerUnit();\n\n if (targetMetersPerUnit !== undefined) {\n sourceResolution *= targetMetersPerUnit;\n }\n\n var sourceMetersPerUnit = sourceProj.getMetersPerUnit();\n\n if (sourceMetersPerUnit !== undefined) {\n sourceResolution /= sourceMetersPerUnit;\n } // Based on the projection properties, the point resolution at the specified\n // coordinates may be slightly different. We need to reverse-compensate this\n // in order to achieve optimal results.\n\n\n var sourceExtent = sourceProj.getExtent();\n\n if (!sourceExtent || containsCoordinate(sourceExtent, sourceCenter)) {\n var compensationFactor = getPointResolution(sourceProj, sourceResolution, sourceCenter) / sourceResolution;\n\n if (isFinite(compensationFactor) && compensationFactor > 0) {\n sourceResolution /= compensationFactor;\n }\n }\n\n return sourceResolution;\n}\n/**\n * Calculates ideal resolution to use from the source in order to achieve\n * pixel mapping as close as possible to 1:1 during reprojection.\n * The resolution is calculated regardless of what resolutions\n * are actually available in the dataset (TileGrid, Image, ...).\n *\n * @param {import("./proj/Projection.js").default} sourceProj Source projection.\n * @param {import("./proj/Projection.js").default} targetProj Target projection.\n * @param {import("./extent.js").Extent} targetExtent Target extent\n * @param {number} targetResolution Target resolution.\n * @return {number} The best resolution to use. Can be +-Infinity, NaN or 0.\n */\n\nfunction calculateSourceExtentResolution(sourceProj, targetProj, targetExtent, targetResolution) {\n var targetCenter = getCenter(targetExtent);\n var sourceResolution = calculateSourceResolution(sourceProj, targetProj, targetCenter, targetResolution);\n\n if (!isFinite(sourceResolution) || sourceResolution <= 0) {\n forEachCorner(targetExtent, function (corner) {\n sourceResolution = calculateSourceResolution(sourceProj, targetProj, corner, targetResolution);\n return isFinite(sourceResolution) && sourceResolution > 0;\n });\n }\n\n return sourceResolution;\n}\n/**\n * Renders the source data into new canvas based on the triangulation.\n *\n * @param {number} width Width of the canvas.\n * @param {number} height Height of the canvas.\n * @param {number} pixelRatio Pixel ratio.\n * @param {number} sourceResolution Source resolution.\n * @param {import("./extent.js").Extent} sourceExtent Extent of the data source.\n * @param {number} targetResolution Target resolution.\n * @param {import("./extent.js").Extent} targetExtent Target extent.\n * @param {import("./reproj/Triangulation.js").default} triangulation\n * Calculated triangulation.\n * @param {Array<{extent: import("./extent.js").Extent,\n * image: (HTMLCanvasElement|HTMLImageElement|HTMLVideoElement)}>} sources\n * Array of sources.\n * @param {number} gutter Gutter of the sources.\n * @param {boolean=} opt_renderEdges Render reprojection edges.\n * @param {object=} opt_contextOptions Properties to set on the canvas context.\n * @return {HTMLCanvasElement} Canvas with reprojected data.\n */\n\nfunction render(width, height, pixelRatio, sourceResolution, sourceExtent, targetResolution, targetExtent, triangulation, sources, gutter, opt_renderEdges, opt_contextOptions) {\n var context = createCanvasContext2D(Math.round(pixelRatio * width), Math.round(pixelRatio * height));\n obj_assign(context, opt_contextOptions);\n\n if (sources.length === 0) {\n return context.canvas;\n }\n\n context.scale(pixelRatio, pixelRatio);\n\n function pixelRound(value) {\n return Math.round(value * pixelRatio) / pixelRatio;\n }\n\n context.globalCompositeOperation = \'lighter\';\n var sourceDataExtent = createEmpty();\n sources.forEach(function (src, i, arr) {\n extent_extend(sourceDataExtent, src.extent);\n });\n var canvasWidthInUnits = extent_getWidth(sourceDataExtent);\n var canvasHeightInUnits = getHeight(sourceDataExtent);\n var stitchContext = createCanvasContext2D(Math.round(pixelRatio * canvasWidthInUnits / sourceResolution), Math.round(pixelRatio * canvasHeightInUnits / sourceResolution));\n obj_assign(stitchContext, opt_contextOptions);\n var stitchScale = pixelRatio / sourceResolution;\n sources.forEach(function (src, i, arr) {\n var xPos = src.extent[0] - sourceDataExtent[0];\n var yPos = -(src.extent[3] - sourceDataExtent[3]);\n var srcWidth = extent_getWidth(src.extent);\n var srcHeight = getHeight(src.extent); // This test should never fail -- but it does. Need to find a fix the upstream condition\n\n if (src.image.width > 0 && src.image.height > 0) {\n stitchContext.drawImage(src.image, gutter, gutter, src.image.width - 2 * gutter, src.image.height - 2 * gutter, xPos * stitchScale, yPos * stitchScale, srcWidth * stitchScale, srcHeight * stitchScale);\n }\n });\n var targetTopLeft = getTopLeft(targetExtent);\n triangulation.getTriangles().forEach(function (triangle, i, arr) {\n /* Calculate affine transform (src -> dst)\n * Resulting matrix can be used to transform coordinate\n * from `sourceProjection` to destination pixels.\n *\n * To optimize number of context calls and increase numerical stability,\n * we also do the following operations:\n * trans(-topLeftExtentCorner), scale(1 / targetResolution), scale(1, -1)\n * here before solving the linear system so [ui, vi] are pixel coordinates.\n *\n * Src points: xi, yi\n * Dst points: ui, vi\n * Affine coefficients: aij\n *\n * | x0 y0 1 0 0 0 | |a00| |u0|\n * | x1 y1 1 0 0 0 | |a01| |u1|\n * | x2 y2 1 0 0 0 | x |a02| = |u2|\n * | 0 0 0 x0 y0 1 | |a10| |v0|\n * | 0 0 0 x1 y1 1 | |a11| |v1|\n * | 0 0 0 x2 y2 1 | |a12| |v2|\n */\n var source = triangle.source;\n var target = triangle.target;\n var x0 = source[0][0],\n y0 = source[0][1];\n var x1 = source[1][0],\n y1 = source[1][1];\n var x2 = source[2][0],\n y2 = source[2][1]; // Make sure that everything is on pixel boundaries\n\n var u0 = pixelRound((target[0][0] - targetTopLeft[0]) / targetResolution);\n var v0 = pixelRound(-(target[0][1] - targetTopLeft[1]) / targetResolution);\n var u1 = pixelRound((target[1][0] - targetTopLeft[0]) / targetResolution);\n var v1 = pixelRound(-(target[1][1] - targetTopLeft[1]) / targetResolution);\n var u2 = pixelRound((target[2][0] - targetTopLeft[0]) / targetResolution);\n var v2 = pixelRound(-(target[2][1] - targetTopLeft[1]) / targetResolution); // Shift all the source points to improve numerical stability\n // of all the subsequent calculations. The [x0, y0] is used here.\n // This is also used to simplify the linear system.\n\n var sourceNumericalShiftX = x0;\n var sourceNumericalShiftY = y0;\n x0 = 0;\n y0 = 0;\n x1 -= sourceNumericalShiftX;\n y1 -= sourceNumericalShiftY;\n x2 -= sourceNumericalShiftX;\n y2 -= sourceNumericalShiftY;\n var augmentedMatrix = [[x1, y1, 0, 0, u1 - u0], [x2, y2, 0, 0, u2 - u0], [0, 0, x1, y1, v1 - v0], [0, 0, x2, y2, v2 - v0]];\n var affineCoefs = solveLinearSystem(augmentedMatrix);\n\n if (!affineCoefs) {\n return;\n }\n\n context.save();\n context.beginPath();\n\n if (isBrokenDiagonalRendering() || opt_contextOptions === IMAGE_SMOOTHING_DISABLED) {\n // Make sure that all lines are horizontal or vertical\n context.moveTo(u1, v1); // This is the diagonal line. Do it in 4 steps\n\n var steps = 4;\n var ud = u0 - u1;\n var vd = v0 - v1;\n\n for (var step = 0; step < steps; step++) {\n // Go horizontally\n context.lineTo(u1 + pixelRound((step + 1) * ud / steps), v1 + pixelRound(step * vd / (steps - 1))); // Go vertically\n\n if (step != steps - 1) {\n context.lineTo(u1 + pixelRound((step + 1) * ud / steps), v1 + pixelRound((step + 1) * vd / (steps - 1)));\n }\n } // We are almost at u0r, v0r\n\n\n context.lineTo(u2, v2);\n } else {\n context.moveTo(u1, v1);\n context.lineTo(u0, v0);\n context.lineTo(u2, v2);\n }\n\n context.clip();\n context.transform(affineCoefs[0], affineCoefs[2], affineCoefs[1], affineCoefs[3], u0, v0);\n context.translate(sourceDataExtent[0] - sourceNumericalShiftX, sourceDataExtent[3] - sourceNumericalShiftY);\n context.scale(sourceResolution / pixelRatio, -sourceResolution / pixelRatio);\n context.drawImage(stitchContext.canvas, 0, 0);\n context.restore();\n });\n\n if (opt_renderEdges) {\n context.save();\n context.globalCompositeOperation = \'source-over\';\n context.strokeStyle = \'black\';\n context.lineWidth = 1;\n triangulation.getTriangles().forEach(function (triangle, i, arr) {\n var target = triangle.target;\n var u0 = (target[0][0] - targetTopLeft[0]) / targetResolution;\n var v0 = -(target[0][1] - targetTopLeft[1]) / targetResolution;\n var u1 = (target[1][0] - targetTopLeft[0]) / targetResolution;\n var v1 = -(target[1][1] - targetTopLeft[1]) / targetResolution;\n var u2 = (target[2][0] - targetTopLeft[0]) / targetResolution;\n var v2 = -(target[2][1] - targetTopLeft[1]) / targetResolution;\n context.beginPath();\n context.moveTo(u1, v1);\n context.lineTo(u0, v0);\n context.lineTo(u2, v2);\n context.closePath();\n context.stroke();\n });\n context.restore();\n }\n\n return context.canvas;\n}\n;// CONCATENATED MODULE: ./node_modules/ol/reproj/Tile.js\nvar reproj_Tile_extends = undefined && undefined.__extends || function () {\n var _extendStatics = function extendStatics(d, b) {\n _extendStatics = Object.setPrototypeOf || {\n __proto__: []\n } instanceof Array && function (d, b) {\n d.__proto__ = b;\n } || function (d, b) {\n for (var p in b) {\n if (Object.prototype.hasOwnProperty.call(b, p)) d[p] = b[p];\n }\n };\n\n return _extendStatics(d, b);\n };\n\n return function (d, b) {\n _extendStatics(d, b);\n\n function __() {\n this.constructor = d;\n }\n\n d.prototype = b === null ? Object.create(b) : (__.prototype = b.prototype, new __());\n };\n}();\n/**\n * @module ol/reproj/Tile\n */\n\n\n\n\n\n\n\n\n\n\n\n/**\n * @typedef {function(number, number, number, number) : import("../Tile.js").default} FunctionType\n */\n\n/**\n * @classdesc\n * Class encapsulating single reprojected tile.\n * See {@link module:ol/source/TileImage~TileImage}.\n *\n */\n\nvar ReprojTile =\n/** @class */\nfunction (_super) {\n reproj_Tile_extends(ReprojTile, _super);\n /**\n * @param {import("../proj/Projection.js").default} sourceProj Source projection.\n * @param {import("../tilegrid/TileGrid.js").default} sourceTileGrid Source tile grid.\n * @param {import("../proj/Projection.js").default} targetProj Target projection.\n * @param {import("../tilegrid/TileGrid.js").default} targetTileGrid Target tile grid.\n * @param {import("../tilecoord.js").TileCoord} tileCoord Coordinate of the tile.\n * @param {import("../tilecoord.js").TileCoord} wrappedTileCoord Coordinate of the tile wrapped in X.\n * @param {number} pixelRatio Pixel ratio.\n * @param {number} gutter Gutter of the source tiles.\n * @param {FunctionType} getTileFunction\n * Function returning source tiles (z, x, y, pixelRatio).\n * @param {number=} opt_errorThreshold Acceptable reprojection error (in px).\n * @param {boolean=} opt_renderEdges Render reprojection edges.\n * @param {object=} opt_contextOptions Properties to set on the canvas context.\n */\n\n\n function ReprojTile(sourceProj, sourceTileGrid, targetProj, targetTileGrid, tileCoord, wrappedTileCoord, pixelRatio, gutter, getTileFunction, opt_errorThreshold, opt_renderEdges, opt_contextOptions) {\n var _this = _super.call(this, tileCoord, TileState.IDLE) || this;\n /**\n * @private\n * @type {boolean}\n */\n\n\n _this.renderEdges_ = opt_renderEdges !== undefined ? opt_renderEdges : false;\n /**\n * @private\n * @type {object}\n */\n\n _this.contextOptions_ = opt_contextOptions;\n /**\n * @private\n * @type {number}\n */\n\n _this.pixelRatio_ = pixelRatio;\n /**\n * @private\n * @type {number}\n */\n\n _this.gutter_ = gutter;\n /**\n * @private\n * @type {HTMLCanvasElement}\n */\n\n _this.canvas_ = null;\n /**\n * @private\n * @type {import("../tilegrid/TileGrid.js").default}\n */\n\n _this.sourceTileGrid_ = sourceTileGrid;\n /**\n * @private\n * @type {import("../tilegrid/TileGrid.js").default}\n */\n\n _this.targetTileGrid_ = targetTileGrid;\n /**\n * @private\n * @type {import("../tilecoord.js").TileCoord}\n */\n\n _this.wrappedTileCoord_ = wrappedTileCoord ? wrappedTileCoord : tileCoord;\n /**\n * @private\n * @type {!Array<import("../Tile.js").default>}\n */\n\n _this.sourceTiles_ = [];\n /**\n * @private\n * @type {?Array<import("../events.js").EventsKey>}\n */\n\n _this.sourcesListenerKeys_ = null;\n /**\n * @private\n * @type {number}\n */\n\n _this.sourceZ_ = 0;\n var targetExtent = targetTileGrid.getTileCoordExtent(_this.wrappedTileCoord_);\n\n var maxTargetExtent = _this.targetTileGrid_.getExtent();\n\n var maxSourceExtent = _this.sourceTileGrid_.getExtent();\n\n var limitedTargetExtent = maxTargetExtent ? getIntersection(targetExtent, maxTargetExtent) : targetExtent;\n\n if (getArea(limitedTargetExtent) === 0) {\n // Tile is completely outside range -> EMPTY\n // TODO: is it actually correct that the source even creates the tile ?\n _this.state = TileState.EMPTY;\n return _this;\n }\n\n var sourceProjExtent = sourceProj.getExtent();\n\n if (sourceProjExtent) {\n if (!maxSourceExtent) {\n maxSourceExtent = sourceProjExtent;\n } else {\n maxSourceExtent = getIntersection(maxSourceExtent, sourceProjExtent);\n }\n }\n\n var targetResolution = targetTileGrid.getResolution(_this.wrappedTileCoord_[0]);\n var sourceResolution = calculateSourceExtentResolution(sourceProj, targetProj, limitedTargetExtent, targetResolution);\n\n if (!isFinite(sourceResolution) || sourceResolution <= 0) {\n // invalid sourceResolution -> EMPTY\n // probably edges of the projections when no extent is defined\n _this.state = TileState.EMPTY;\n return _this;\n }\n\n var errorThresholdInPixels = opt_errorThreshold !== undefined ? opt_errorThreshold : ERROR_THRESHOLD;\n /**\n * @private\n * @type {!import("./Triangulation.js").default}\n */\n\n _this.triangulation_ = new reproj_Triangulation(sourceProj, targetProj, limitedTargetExtent, maxSourceExtent, sourceResolution * errorThresholdInPixels, targetResolution);\n\n if (_this.triangulation_.getTriangles().length === 0) {\n // no valid triangles -> EMPTY\n _this.state = TileState.EMPTY;\n return _this;\n }\n\n _this.sourceZ_ = sourceTileGrid.getZForResolution(sourceResolution);\n\n var sourceExtent = _this.triangulation_.calculateSourceExtent();\n\n if (maxSourceExtent) {\n if (sourceProj.canWrapX()) {\n sourceExtent[1] = math_clamp(sourceExtent[1], maxSourceExtent[1], maxSourceExtent[3]);\n sourceExtent[3] = math_clamp(sourceExtent[3], maxSourceExtent[1], maxSourceExtent[3]);\n } else {\n sourceExtent = getIntersection(sourceExtent, maxSourceExtent);\n }\n }\n\n if (!getArea(sourceExtent)) {\n _this.state = TileState.EMPTY;\n } else {\n var sourceRange = sourceTileGrid.getTileRangeForExtentAndZ(sourceExtent, _this.sourceZ_);\n\n for (var srcX = sourceRange.minX; srcX <= sourceRange.maxX; srcX++) {\n for (var srcY = sourceRange.minY; srcY <= sourceRange.maxY; srcY++) {\n var tile = getTileFunction(_this.sourceZ_, srcX, srcY, pixelRatio);\n\n if (tile) {\n _this.sourceTiles_.push(tile);\n }\n }\n }\n\n if (_this.sourceTiles_.length === 0) {\n _this.state = TileState.EMPTY;\n }\n }\n\n return _this;\n }\n /**\n * Get the HTML Canvas element for this tile.\n * @return {HTMLCanvasElement} Canvas.\n */\n\n\n ReprojTile.prototype.getImage = function () {\n return this.canvas_;\n };\n /**\n * @private\n */\n\n\n ReprojTile.prototype.reproject_ = function () {\n var sources = [];\n this.sourceTiles_.forEach(function (tile, i, arr) {\n if (tile && tile.getState() == TileState.LOADED) {\n sources.push({\n extent: this.sourceTileGrid_.getTileCoordExtent(tile.tileCoord),\n image: tile.getImage()\n });\n }\n }.bind(this));\n this.sourceTiles_.length = 0;\n\n if (sources.length === 0) {\n this.state = TileState.ERROR;\n } else {\n var z = this.wrappedTileCoord_[0];\n var size = this.targetTileGrid_.getTileSize(z);\n var width = typeof size === \'number\' ? size : size[0];\n var height = typeof size === \'number\' ? size : size[1];\n var targetResolution = this.targetTileGrid_.getResolution(z);\n var sourceResolution = this.sourceTileGrid_.getResolution(this.sourceZ_);\n var targetExtent = this.targetTileGrid_.getTileCoordExtent(this.wrappedTileCoord_);\n this.canvas_ = render(width, height, this.pixelRatio_, sourceResolution, this.sourceTileGrid_.getExtent(), targetResolution, targetExtent, this.triangulation_, sources, this.gutter_, this.renderEdges_, this.contextOptions_);\n this.state = TileState.LOADED;\n }\n\n this.changed();\n };\n /**\n * Load not yet loaded URI.\n */\n\n\n ReprojTile.prototype.load = function () {\n if (this.state == TileState.IDLE) {\n this.state = TileState.LOADING;\n this.changed();\n var leftToLoad_1 = 0;\n this.sourcesListenerKeys_ = [];\n this.sourceTiles_.forEach(function (tile, i, arr) {\n var state = tile.getState();\n\n if (state == TileState.IDLE || state == TileState.LOADING) {\n leftToLoad_1++;\n var sourceListenKey_1 = listen(tile, EventType.CHANGE, function (e) {\n var state = tile.getState();\n\n if (state == TileState.LOADED || state == TileState.ERROR || state == TileState.EMPTY) {\n unlistenByKey(sourceListenKey_1);\n leftToLoad_1--;\n\n if (leftToLoad_1 === 0) {\n this.unlistenSources_();\n this.reproject_();\n }\n }\n }, this);\n this.sourcesListenerKeys_.push(sourceListenKey_1);\n }\n }.bind(this));\n this.sourceTiles_.forEach(function (tile, i, arr) {\n var state = tile.getState();\n\n if (state == TileState.IDLE) {\n tile.load();\n }\n });\n\n if (leftToLoad_1 === 0) {\n setTimeout(this.reproject_.bind(this), 0);\n }\n }\n };\n /**\n * @private\n */\n\n\n ReprojTile.prototype.unlistenSources_ = function () {\n this.sourcesListenerKeys_.forEach(unlistenByKey);\n this.sourcesListenerKeys_ = null;\n };\n\n return ReprojTile;\n}(ol_Tile);\n\n/* harmony default export */ var reproj_Tile = (ReprojTile);\n;// CONCATENATED MODULE: ./node_modules/ol/source/TileImage.js\nvar TileImage_extends = undefined && undefined.__extends || function () {\n var _extendStatics = function extendStatics(d, b) {\n _extendStatics = Object.setPrototypeOf || {\n __proto__: []\n } instanceof Array && function (d, b) {\n d.__proto__ = b;\n } || function (d, b) {\n for (var p in b) {\n if (Object.prototype.hasOwnProperty.call(b, p)) d[p] = b[p];\n }\n };\n\n return _extendStatics(d, b);\n };\n\n return function (d, b) {\n _extendStatics(d, b);\n\n function __() {\n this.constructor = d;\n }\n\n d.prototype = b === null ? Object.create(b) : (__.prototype = b.prototype, new __());\n };\n}();\n/**\n * @module ol/source/TileImage\n */\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n/**\n * @typedef {Object} Options\n * @property {import("./Source.js").AttributionLike} [attributions] Attributions.\n * @property {boolean} [attributionsCollapsible=true] Attributions are collapsible.\n * @property {number} [cacheSize] Initial tile cache size. Will auto-grow to hold at least the number of tiles in the viewport.\n * @property {null|string} [crossOrigin] The `crossOrigin` attribute for loaded images. Note that\n * you must provide a `crossOrigin` value if you want to access pixel data with the Canvas renderer.\n * See https://developer.mozilla.org/en-US/docs/Web/HTML/CORS_enabled_image for more detail.\n * @property {boolean} [imageSmoothing=true] Enable image smoothing.\n * @property {boolean} [opaque=false] Whether the layer is opaque.\n * @property {import("../proj.js").ProjectionLike} [projection] Projection. Default is the view projection.\n * @property {number} [reprojectionErrorThreshold=0.5] Maximum allowed reprojection error (in pixels).\n * Higher values can increase reprojection performance, but decrease precision.\n * @property {import("./State.js").default} [state] Source state.\n * @property {typeof import("../ImageTile.js").default} [tileClass] Class used to instantiate image tiles.\n * Default is {@link module:ol/ImageTile~ImageTile}.\n * @property {import("../tilegrid/TileGrid.js").default} [tileGrid] Tile grid.\n * @property {import("../Tile.js").LoadFunction} [tileLoadFunction] Optional function to load a tile given a URL. The default is\n * ```js\n * function(imageTile, src) {\n * imageTile.getImage().src = src;\n * };\n * ```\n * @property {number} [tilePixelRatio=1] The pixel ratio used by the tile service. For example, if the tile\n * service advertizes 256px by 256px tiles but actually sends 512px\n * by 512px images (for retina/hidpi devices) then `tilePixelRatio`\n * should be set to `2`.\n * @property {import("../Tile.js").UrlFunction} [tileUrlFunction] Optional function to get tile URL given a tile coordinate and the projection.\n * @property {string} [url] URL template. Must include `{x}`, `{y}` or `{-y}`, and `{z}` placeholders.\n * A `{?-?}` template pattern, for example `subdomain{a-f}.domain.com`, may be\n * used instead of defining each one separately in the `urls` option.\n * @property {Array<string>} [urls] An array of URL templates.\n * @property {boolean} [wrapX] Whether to wrap the world horizontally. The default, is to\n * request out-of-bounds tiles from the server. When set to `false`, only one\n * world will be rendered. When set to `true`, tiles will be requested for one\n * world only, but they will be wrapped horizontally to render multiple worlds.\n * @property {number} [transition] Duration of the opacity transition for rendering.\n * To disable the opacity transition, pass `transition: 0`.\n * @property {string} [key] Optional tile key for proper cache fetching\n * @property {number} [zDirection=0] Indicate which resolution should be used\n * by a renderer if the view resolution does not match any resolution of the tile source.\n * If 0, the nearest resolution will be used. If 1, the nearest lower resolution\n * will be used. If -1, the nearest higher resolution will be used.\n */\n\n/**\n * @classdesc\n * Base class for sources providing images divided into a tile grid.\n *\n * @fires import("./Tile.js").TileSourceEvent\n * @api\n */\n\nvar TileImage =\n/** @class */\nfunction (_super) {\n TileImage_extends(TileImage, _super);\n /**\n * @param {!Options} options Image tile options.\n */\n\n\n function TileImage(options) {\n var _this = _super.call(this, {\n attributions: options.attributions,\n cacheSize: options.cacheSize,\n opaque: options.opaque,\n projection: options.projection,\n state: options.state,\n tileGrid: options.tileGrid,\n tileLoadFunction: options.tileLoadFunction ? options.tileLoadFunction : defaultTileLoadFunction,\n tilePixelRatio: options.tilePixelRatio,\n tileUrlFunction: options.tileUrlFunction,\n url: options.url,\n urls: options.urls,\n wrapX: options.wrapX,\n transition: options.transition,\n key: options.key,\n attributionsCollapsible: options.attributionsCollapsible,\n zDirection: options.zDirection\n }) || this;\n /**\n * @protected\n * @type {?string}\n */\n\n\n _this.crossOrigin = options.crossOrigin !== undefined ? options.crossOrigin : null;\n /**\n * @protected\n * @type {typeof ImageTile}\n */\n\n _this.tileClass = options.tileClass !== undefined ? options.tileClass : ol_ImageTile;\n /**\n * @protected\n * @type {!Object<string, TileCache>}\n */\n\n _this.tileCacheForProjection = {};\n /**\n * @protected\n * @type {!Object<string, import("../tilegrid/TileGrid.js").default>}\n */\n\n _this.tileGridForProjection = {};\n /**\n * @private\n * @type {number|undefined}\n */\n\n _this.reprojectionErrorThreshold_ = options.reprojectionErrorThreshold;\n /**\n * @private\n * @type {object|undefined}\n */\n\n _this.contextOptions_ = options.imageSmoothing === false ? IMAGE_SMOOTHING_DISABLED : undefined;\n /**\n * @private\n * @type {boolean}\n */\n\n _this.renderReprojectionEdges_ = false;\n return _this;\n }\n /**\n * @return {boolean} Can expire cache.\n */\n\n\n TileImage.prototype.canExpireCache = function () {\n if (!ENABLE_RASTER_REPROJECTION) {\n return _super.prototype.canExpireCache.call(this);\n }\n\n if (this.tileCache.canExpireCache()) {\n return true;\n } else {\n for (var key in this.tileCacheForProjection) {\n if (this.tileCacheForProjection[key].canExpireCache()) {\n return true;\n }\n }\n }\n\n return false;\n };\n /**\n * @param {import("../proj/Projection.js").default} projection Projection.\n * @param {!Object<string, boolean>} usedTiles Used tiles.\n */\n\n\n TileImage.prototype.expireCache = function (projection, usedTiles) {\n if (!ENABLE_RASTER_REPROJECTION) {\n _super.prototype.expireCache.call(this, projection, usedTiles);\n\n return;\n }\n\n var usedTileCache = this.getTileCacheForProjection(projection);\n this.tileCache.expireCache(this.tileCache == usedTileCache ? usedTiles : {});\n\n for (var id in this.tileCacheForProjection) {\n var tileCache = this.tileCacheForProjection[id];\n tileCache.expireCache(tileCache == usedTileCache ? usedTiles : {});\n }\n };\n /**\n * @return {Object|undefined} Context options.\n */\n\n\n TileImage.prototype.getContextOptions = function () {\n return this.contextOptions_;\n };\n /**\n * @param {import("../proj/Projection.js").default} projection Projection.\n * @return {number} Gutter.\n */\n\n\n TileImage.prototype.getGutterForProjection = function (projection) {\n if (ENABLE_RASTER_REPROJECTION && this.getProjection() && projection && !equivalent(this.getProjection(), projection)) {\n return 0;\n } else {\n return this.getGutter();\n }\n };\n /**\n * @return {number} Gutter.\n */\n\n\n TileImage.prototype.getGutter = function () {\n return 0;\n };\n /**\n * Return the key to be used for all tiles in the source.\n * @return {string} The key for all tiles.\n * @protected\n */\n\n\n TileImage.prototype.getKey = function () {\n return _super.prototype.getKey.call(this) + (this.contextOptions_ ? \'\\n\' + JSON.stringify(this.contextOptions_) : \'\');\n };\n /**\n * @param {import("../proj/Projection.js").default} projection Projection.\n * @return {boolean} Opaque.\n */\n\n\n TileImage.prototype.getOpaque = function (projection) {\n if (ENABLE_RASTER_REPROJECTION && this.getProjection() && projection && !equivalent(this.getProjection(), projection)) {\n return false;\n } else {\n return _super.prototype.getOpaque.call(this, projection);\n }\n };\n /**\n * @param {import("../proj/Projection.js").default} projection Projection.\n * @return {!import("../tilegrid/TileGrid.js").default} Tile grid.\n */\n\n\n TileImage.prototype.getTileGridForProjection = function (projection) {\n if (!ENABLE_RASTER_REPROJECTION) {\n return _super.prototype.getTileGridForProjection.call(this, projection);\n }\n\n var thisProj = this.getProjection();\n\n if (this.tileGrid && (!thisProj || equivalent(thisProj, projection))) {\n return this.tileGrid;\n } else {\n var projKey = util_getUid(projection);\n\n if (!(projKey in this.tileGridForProjection)) {\n this.tileGridForProjection[projKey] = getForProjection(projection);\n }\n\n return this.tileGridForProjection[projKey];\n }\n };\n /**\n * @param {import("../proj/Projection.js").default} projection Projection.\n * @return {import("../TileCache.js").default} Tile cache.\n */\n\n\n TileImage.prototype.getTileCacheForProjection = function (projection) {\n if (!ENABLE_RASTER_REPROJECTION) {\n return _super.prototype.getTileCacheForProjection.call(this, projection);\n }\n\n var thisProj = this.getProjection();\n\n if (!thisProj || equivalent(thisProj, projection)) {\n return this.tileCache;\n } else {\n var projKey = util_getUid(projection);\n\n if (!(projKey in this.tileCacheForProjection)) {\n this.tileCacheForProjection[projKey] = new ol_TileCache(this.tileCache.highWaterMark);\n }\n\n return this.tileCacheForProjection[projKey];\n }\n };\n /**\n * @param {number} z Tile coordinate z.\n * @param {number} x Tile coordinate x.\n * @param {number} y Tile coordinate y.\n * @param {number} pixelRatio Pixel ratio.\n * @param {import("../proj/Projection.js").default} projection Projection.\n * @param {string} key The key set on the tile.\n * @return {!import("../Tile.js").default} Tile.\n * @private\n */\n\n\n TileImage.prototype.createTile_ = function (z, x, y, pixelRatio, projection, key) {\n var tileCoord = [z, x, y];\n var urlTileCoord = this.getTileCoordForTileUrlFunction(tileCoord, projection);\n var tileUrl = urlTileCoord ? this.tileUrlFunction(urlTileCoord, pixelRatio, projection) : undefined;\n var tile = new this.tileClass(tileCoord, tileUrl !== undefined ? TileState.IDLE : TileState.EMPTY, tileUrl !== undefined ? tileUrl : \'\', this.crossOrigin, this.tileLoadFunction, this.tileOptions);\n tile.key = key;\n tile.addEventListener(EventType.CHANGE, this.handleTileChange.bind(this));\n return tile;\n };\n /**\n * @param {number} z Tile coordinate z.\n * @param {number} x Tile coordinate x.\n * @param {number} y Tile coordinate y.\n * @param {number} pixelRatio Pixel ratio.\n * @param {import("../proj/Projection.js").default} projection Projection.\n * @return {!import("../Tile.js").default} Tile.\n */\n\n\n TileImage.prototype.getTile = function (z, x, y, pixelRatio, projection) {\n var sourceProjection = this.getProjection();\n\n if (!ENABLE_RASTER_REPROJECTION || !sourceProjection || !projection || equivalent(sourceProjection, projection)) {\n return this.getTileInternal(z, x, y, pixelRatio, sourceProjection || projection);\n } else {\n var cache = this.getTileCacheForProjection(projection);\n var tileCoord = [z, x, y];\n var tile = void 0;\n var tileCoordKey = tilecoord_getKey(tileCoord);\n\n if (cache.containsKey(tileCoordKey)) {\n tile = cache.get(tileCoordKey);\n }\n\n var key = this.getKey();\n\n if (tile && tile.key == key) {\n return tile;\n } else {\n var sourceTileGrid = this.getTileGridForProjection(sourceProjection);\n var targetTileGrid = this.getTileGridForProjection(projection);\n var wrappedTileCoord = this.getTileCoordForTileUrlFunction(tileCoord, projection);\n var newTile = new reproj_Tile(sourceProjection, sourceTileGrid, projection, targetTileGrid, tileCoord, wrappedTileCoord, this.getTilePixelRatio(pixelRatio), this.getGutter(), function (z, x, y, pixelRatio) {\n return this.getTileInternal(z, x, y, pixelRatio, sourceProjection);\n }.bind(this), this.reprojectionErrorThreshold_, this.renderReprojectionEdges_, this.contextOptions_);\n newTile.key = key;\n\n if (tile) {\n newTile.interimTile = tile;\n newTile.refreshInterimChain();\n cache.replace(tileCoordKey, newTile);\n } else {\n cache.set(tileCoordKey, newTile);\n }\n\n return newTile;\n }\n }\n };\n /**\n * @param {number} z Tile coordinate z.\n * @param {number} x Tile coordinate x.\n * @param {number} y Tile coordinate y.\n * @param {number} pixelRatio Pixel ratio.\n * @param {!import("../proj/Projection.js").default} projection Projection.\n * @return {!import("../Tile.js").default} Tile.\n * @protected\n */\n\n\n TileImage.prototype.getTileInternal = function (z, x, y, pixelRatio, projection) {\n var tile = null;\n var tileCoordKey = getKeyZXY(z, x, y);\n var key = this.getKey();\n\n if (!this.tileCache.containsKey(tileCoordKey)) {\n tile = this.createTile_(z, x, y, pixelRatio, projection, key);\n this.tileCache.set(tileCoordKey, tile);\n } else {\n tile = this.tileCache.get(tileCoordKey);\n\n if (tile.key != key) {\n // The source\'s params changed. If the tile has an interim tile and if we\n // can use it then we use it. Otherwise we create a new tile. In both\n // cases we attempt to assign an interim tile to the new tile.\n var interimTile = tile;\n tile = this.createTile_(z, x, y, pixelRatio, projection, key); //make the new tile the head of the list,\n\n if (interimTile.getState() == TileState.IDLE) {\n //the old tile hasn\'t begun loading yet, and is now outdated, so we can simply discard it\n tile.interimTile = interimTile.interimTile;\n } else {\n tile.interimTile = interimTile;\n }\n\n tile.refreshInterimChain();\n this.tileCache.replace(tileCoordKey, tile);\n }\n }\n\n return tile;\n };\n /**\n * Sets whether to render reprojection edges or not (usually for debugging).\n * @param {boolean} render Render the edges.\n * @api\n */\n\n\n TileImage.prototype.setRenderReprojectionEdges = function (render) {\n if (!ENABLE_RASTER_REPROJECTION || this.renderReprojectionEdges_ == render) {\n return;\n }\n\n this.renderReprojectionEdges_ = render;\n\n for (var id in this.tileCacheForProjection) {\n this.tileCacheForProjection[id].clear();\n }\n\n this.changed();\n };\n /**\n * Sets the tile grid to use when reprojecting the tiles to the given\n * projection instead of the default tile grid for the projection.\n *\n * This can be useful when the default tile grid cannot be created\n * (e.g. projection has no extent defined) or\n * for optimization reasons (custom tile size, resolutions, ...).\n *\n * @param {import("../proj.js").ProjectionLike} projection Projection.\n * @param {import("../tilegrid/TileGrid.js").default} tilegrid Tile grid to use for the projection.\n * @api\n */\n\n\n TileImage.prototype.setTileGridForProjection = function (projection, tilegrid) {\n if (ENABLE_RASTER_REPROJECTION) {\n var proj = proj_get(projection);\n\n if (proj) {\n var projKey = util_getUid(proj);\n\n if (!(projKey in this.tileGridForProjection)) {\n this.tileGridForProjection[projKey] = tilegrid;\n }\n }\n }\n };\n\n return TileImage;\n}(source_UrlTile);\n/**\n * @param {ImageTile} imageTile Image tile.\n * @param {string} src Source.\n */\n\n\nfunction defaultTileLoadFunction(imageTile, src) {\n /** @type {HTMLImageElement|HTMLVideoElement} */\n imageTile.getImage().src = src;\n}\n\n/* harmony default export */ var source_TileImage = (TileImage);\n;// CONCATENATED MODULE: ./node_modules/ol/source/XYZ.js\n/**\n * @module ol/source/XYZ\n */\nvar XYZ_extends = undefined && undefined.__extends || function () {\n var _extendStatics = function extendStatics(d, b) {\n _extendStatics = Object.setPrototypeOf || {\n __proto__: []\n } instanceof Array && function (d, b) {\n d.__proto__ = b;\n } || function (d, b) {\n for (var p in b) {\n if (Object.prototype.hasOwnProperty.call(b, p)) d[p] = b[p];\n }\n };\n\n return _extendStatics(d, b);\n };\n\n return function (d, b) {\n _extendStatics(d, b);\n\n function __() {\n this.constructor = d;\n }\n\n d.prototype = b === null ? Object.create(b) : (__.prototype = b.prototype, new __());\n };\n}();\n\n\n\n/**\n * @typedef {Object} Options\n * @property {import("./Source.js").AttributionLike} [attributions] Attributions.\n * @property {boolean} [attributionsCollapsible=true] Attributions are collapsible.\n * @property {number} [cacheSize] Initial tile cache size. Will auto-grow to hold at least the number of tiles in the viewport.\n * @property {null|string} [crossOrigin] The `crossOrigin` attribute for loaded images. Note that\n * you must provide a `crossOrigin` value if you want to access pixel data with the Canvas renderer.\n * See https://developer.mozilla.org/en-US/docs/Web/HTML/CORS_enabled_image for more detail.\n * @property {boolean} [imageSmoothing=true] Enable image smoothing.\n * @property {boolean} [opaque=false] Whether the layer is opaque.\n * @property {import("../proj.js").ProjectionLike} [projection=\'EPSG:3857\'] Projection.\n * @property {number} [reprojectionErrorThreshold=0.5] Maximum allowed reprojection error (in pixels).\n * Higher values can increase reprojection performance, but decrease precision.\n * @property {number} [maxZoom=42] Optional max zoom level. Not used if `tileGrid` is provided.\n * @property {number} [minZoom=0] Optional min zoom level. Not used if `tileGrid` is provided.\n * @property {number} [maxResolution] Optional tile grid resolution at level zero. Not used if `tileGrid` is provided.\n * @property {import("../tilegrid/TileGrid.js").default} [tileGrid] Tile grid.\n * @property {import("../Tile.js").LoadFunction} [tileLoadFunction] Optional function to load a tile given a URL. The default is\n * ```js\n * function(imageTile, src) {\n * imageTile.getImage().src = src;\n * };\n * ```\n * @property {number} [tilePixelRatio=1] The pixel ratio used by the tile service.\n * For example, if the tile service advertizes 256px by 256px tiles but actually sends 512px\n * by 512px images (for retina/hidpi devices) then `tilePixelRatio`\n * should be set to `2`.\n * @property {number|import("../size.js").Size} [tileSize=[256, 256]] The tile size used by the tile service.\n * Not used if `tileGrid` is provided.\n * @property {import("../Tile.js").UrlFunction} [tileUrlFunction] Optional function to get\n * tile URL given a tile coordinate and the projection.\n * Required if `url` or `urls` are not provided.\n * @property {string} [url] URL template. Must include `{x}`, `{y}` or `{-y}`,\n * and `{z}` placeholders. A `{?-?}` template pattern, for example `subdomain{a-f}.domain.com`,\n * may be used instead of defining each one separately in the `urls` option.\n * @property {Array<string>} [urls] An array of URL templates.\n * @property {boolean} [wrapX=true] Whether to wrap the world horizontally.\n * @property {number} [transition=250] Duration of the opacity transition for rendering.\n * To disable the opacity transition, pass `transition: 0`.\n * @property {number} [zDirection=0] Indicate which resolution should be used\n * by a renderer if the view resolution does not match any resolution of the tile source.\n * If 0, the nearest resolution will be used. If 1, the nearest lower resolution\n * will be used. If -1, the nearest higher resolution will be used.\n */\n\n/**\n * @classdesc\n * Layer source for tile data with URLs in a set XYZ format that are\n * defined in a URL template. By default, this follows the widely-used\n * Google grid where `x` 0 and `y` 0 are in the top left. Grids like\n * TMS where `x` 0 and `y` 0 are in the bottom left can be used by\n * using the `{-y}` placeholder in the URL template, so long as the\n * source does not have a custom tile grid. In this case\n * a `tileUrlFunction` can be used, such as:\n * ```js\n * tileUrlFunction: function(coordinate) {\n * return \'http://mapserver.com/\' + coordinate[0] + \'/\' +\n * coordinate[1] + \'/\' + (-coordinate[2] - 1) + \'.png\';\n * }\n * ```\n * @api\n */\n\nvar XYZ =\n/** @class */\nfunction (_super) {\n XYZ_extends(XYZ, _super);\n /**\n * @param {Options=} opt_options XYZ options.\n */\n\n\n function XYZ(opt_options) {\n var _this = this;\n\n var options = opt_options || {};\n var projection = options.projection !== undefined ? options.projection : \'EPSG:3857\';\n var tileGrid = options.tileGrid !== undefined ? options.tileGrid : createXYZ({\n extent: extentFromProjection(projection),\n maxResolution: options.maxResolution,\n maxZoom: options.maxZoom,\n minZoom: options.minZoom,\n tileSize: options.tileSize\n });\n _this = _super.call(this, {\n attributions: options.attributions,\n cacheSize: options.cacheSize,\n crossOrigin: options.crossOrigin,\n imageSmoothing: options.imageSmoothing,\n opaque: options.opaque,\n projection: projection,\n reprojectionErrorThreshold: options.reprojectionErrorThreshold,\n tileGrid: tileGrid,\n tileLoadFunction: options.tileLoadFunction,\n tilePixelRatio: options.tilePixelRatio,\n tileUrlFunction: options.tileUrlFunction,\n url: options.url,\n urls: options.urls,\n wrapX: options.wrapX !== undefined ? options.wrapX : true,\n transition: options.transition,\n attributionsCollapsible: options.attributionsCollapsible,\n zDirection: options.zDirection\n }) || this;\n return _this;\n }\n\n return XYZ;\n}(source_TileImage);\n\n/* harmony default export */ var source_XYZ = (XYZ);\n;// CONCATENATED MODULE: ./src/components/map.module.scss\n// extracted by mini-css-extract-plugin\nvar mapContainer = "map-module--mapContainer--3zBiu";\n;// CONCATENATED MODULE: ./src/components/map.tsx\n;// The below adapted from\n// https://taylor.callsen.me/using-openlayers-with-react-functional-components/\nvar MapWrapper=function MapWrapper(_ref){var features=_ref.features;var _useState=(0,react.useState)(),map=_useState[0],setMap=_useState[1];var _useState2=(0,react.useState)(),featuresLayer=_useState2[0],setFeaturesLayer=_useState2[1];var mapElement=(0,react.useRef)();(0,react.useEffect)(function(){var initalFeaturesLayer=new layer_VectorTile({source:new source_VectorTile({format:new format_MVT(),url:\'https://gis.data.census.gov/arcgis/rest/services/Hosted/VT_2019_150_00_PY_D1/VectorTileServer/tile/{z}/{y}/{x}.mvt\'})});var initialMap=new ol_Map({target:mapElement.current,layers:[new Tile({source:new source_XYZ({url:\'https://{1-4}.basemaps.cartocdn.com/light_all/{z}/{x}/{y}@2x.png\'})}),initalFeaturesLayer],view:new ol_View({projection:\'EPSG:3857\',center:fromLonLat([-95.7129,37.0902]),// [37.0902, 95.7129],\nzoom:3}),controls:[]});setMap(initialMap);setFeaturesLayer(initalFeaturesLayer);},[]);// update map if features prop changes\n(0,react.useEffect)(function(){if(features.length){// may be empty on first render\n// set features to map\nfeaturesLayer===null||featuresLayer===void 0?void 0:featuresLayer.setSource(new Vector({features:features}));var extent=featuresLayer===null||featuresLayer===void 0?void 0:featuresLayer.getSource().getExtent();if(extent!=null){// fit map to feature extent (with 100px of padding)\nmap===null||map===void 0?void 0:map.getView().fit(extent,{padding:[100,100,100,100]});}}},[features]);return/*#__PURE__*/react.createElement("div",{ref:mapElement,className:mapContainer});};/* harmony default export */ var map = (MapWrapper);\n// EXTERNAL MODULE: ./node_modules/@trussworks/react-uswds/lib/index.js\nvar lib = __webpack_require__(2593);\n;// CONCATENATED MODULE: ./src/components/mapControls.module.scss\n// extracted by mini-css-extract-plugin\nvar mapControlContainer = "mapControls-module--mapControlContainer--2wEwz";\n;// CONCATENATED MODULE: ./src/components/mapControls.tsx\nvar MapControls=function MapControls(_ref){var setFeatures=_ref.setFeatures;return/*#__PURE__*/react.createElement(react.Fragment,null,/*#__PURE__*/react.createElement("div",{className:mapControlContainer},/*#__PURE__*/react.createElement("h2",null,"Explore the Tool"),/*#__PURE__*/react.createElement(lib.ButtonGroup,{type:"segmented"},/*#__PURE__*/react.createElement(lib.Button,{type:"button"},"Combined"),/*#__PURE__*/react.createElement(lib.Button,{type:"button",outline:true},"Poverty"),/*#__PURE__*/react.createElement(lib.Button,{type:"button",outline:true},"Linguistic Isolation"))));};/* harmony default export */ var mapControls = (MapControls);\n;// CONCATENATED MODULE: ./src/components/HowYouCanHelp.module.scss\n// extracted by mini-css-extract-plugin\nvar howYouCanHelpContainer = "HowYouCanHelp-module--howYouCanHelpContainer--2kqBa";\n;// CONCATENATED MODULE: ./src/components/HowYouCanHelp.tsx\nvar HowYouCanHelp=function HowYouCanHelp(){return/*#__PURE__*/react.createElement("div",{className:howYouCanHelpContainer},/*#__PURE__*/react.createElement("h2",null,"How You Can Help Improve the Tool"),/*#__PURE__*/react.createElement("ul",null,/*#__PURE__*/react.createElement("li",null,"If you have information that could help, we\\u2019d love to hear from you."),/*#__PURE__*/react.createElement("li",null,"View our full set of data sources and methodology where you can add or download sources and check statuses on our data roadmap."),/*#__PURE__*/react.createElement("li",null,"Check out our timeline and send feedback or attend relevant events."),/*#__PURE__*/react.createElement("li",null,"Contact us and share the stories of your community.")));};/* harmony default export */ var components_HowYouCanHelp = (HowYouCanHelp);\n;// CONCATENATED MODULE: ./src/pages/cejst.module.scss\n// extracted by mini-css-extract-plugin\nvar disclaimer = "cejst-module--disclaimer--3LC1y";\n;// CONCATENATED MODULE: ./src/pages/cejst.tsx\n;var CEJSTPage=function CEJSTPage(_ref){var location=_ref.location;var _useState=(0,react.useState)([]),features=_useState[0],setFeatures=_useState[1];return/*#__PURE__*/react.createElement(layout/* default */.Z,{location:location},/*#__PURE__*/react.createElement("main",{id:"main-content",role:"main"},/*#__PURE__*/react.createElement("p",{className:disclaimer},"The Climate and Economic Justice Screening Tool helps identify and prioritize communities across the United States and US territories that have been historically overburdened and underserved so that they may receive 40% of the benefits from investments in six key areas as outlined in the ",/*#__PURE__*/react.createElement("a",{href:\'https://www.whitehouse.gov/briefing-room/\'+\'presidential-actions/2021/01/27/\'+\'executive-order-on-tackling-the-climate-\'+\'crisis-at-home-and-abroad/\',target:\'_blank\',rel:\'noreferrer\'},"Executive Order on Tackling the Climate Crisis at Home and Abroad"),". Explore the map below or learn more about the methodology and data indicators used to prioritize Justice40 communities."),/*#__PURE__*/react.createElement(lib.Alert,{type:"warning",heading:"Limited Data Sources"},/*#__PURE__*/react.createElement("p",null,"In this tool, we are using data sources that our combined by our cummulative impact methodology. Our sources were selected because sit amet, consectetur adipiscing. See all the sources we are investigating on our data roadmap.")),/*#__PURE__*/react.createElement(mapControls,{setFeatures:setFeatures}),/*#__PURE__*/react.createElement(map,{features:features}),/*#__PURE__*/react.createElement(components_HowYouCanHelp,null)));};/* harmony default export */ var cejst = (CEJSTPage);//# sourceURL=[module]\n//# sourceMappingURL=data:application/json;charset=utf-8;base64,eyJ2ZXJzaW9uIjozLCJzb3VyY2VzIjpbIndlYnBhY2s6Ly9qdXN0aWNlNDAtdG9vbC8uL25vZGVfbW9kdWxlcy9vbC9EaXNwb3NhYmxlLmpzP2I0NDIiLCJ3ZWJwYWNrOi8vanVzdGljZTQwLXRvb2wvLi9ub2RlX21vZHVsZXMvb2wvYXJyYXkuanM/ZjQyZSIsIndlYnBhY2s6Ly9qdXN0aWNlNDAtdG9vbC8uL25vZGVfbW9kdWxlcy9vbC9mdW5jdGlvbnMuanM/YTRlZSIsIndlYnBhY2s6Ly9qdXN0aWNlNDAtdG9vbC8uL25vZGVfbW9kdWxlcy9vbC91dGlsLmpzP2FkNjUiLCJ3ZWJwYWNrOi8vanVzdGljZTQwLXRvb2wvLi9ub2RlX21vZHVsZXMvb2wvQXNzZXJ0aW9uRXJyb3IuanM/YzE5YyIsIndlYnBhY2s6Ly9qdXN0aWNlNDAtdG9vbC8uL25vZGVfbW9kdWxlcy9vbC9hc3NlcnRzLmpzPzdlYWUiLCJ3ZWJwYWNrOi8vanVzdGljZTQwLXRvb2wvLi9ub2RlX21vZHVsZXMvb2wvdHJhbnNmb3JtLmpzPzllZGQiLCJ3ZWJwYWNrOi8vanVzdGljZTQwLXRvb2wvLi9ub2RlX21vZHVsZXMvb2wvZXh0ZW50L0Nvcm5lci5qcz8xMzJjIiwid2VicGFjazovL2p1c3RpY2U0MC10b29sLy4vbm9kZV9tb2R1bGVzL29sL2V4dGVudC9SZWxhdGlvbnNoaXAuanM/NWY0NiIsIndlYnBhY2s6Ly9qdXN0aWNlNDAtdG9vbC8uL25vZGVfbW9kdWxlcy9vbC9leHRlbnQuanM/YWI5ZSIsIndlYnBhY2s6Ly9qdXN0aWNlNDAtdG9vbC8uL25vZGVfbW9kdWxlcy9vbC9tYXRoLmpzPzQwODMiLCJ3ZWJwYWNrOi8vanVzdGljZTQwLXRvb2wvLi9ub2RlX21vZHVsZXMvb2wvY29sb3IuanM/ZWEzOSIsIndlYnBhY2s6Ly9qdXN0aWNlNDAtdG9vbC8uL25vZGVfbW9kdWxlcy9vbC9zdHlsZS9JY29uSW1hZ2VDYWNoZS5qcz8yODdjIiwid2VicGFjazovL2p1c3RpY2U0MC10b29sLy4vbm9kZV9tb2R1bGVzL29sL2V2ZW50cy9FdmVudC5qcz8yMzA2Iiwid2VicGFjazovL2p1c3RpY2U0MC10b29sLy4vbm9kZV9tb2R1bGVzL29sL09iamVjdEV2ZW50VHlwZS5qcz8zM2FkIiwid2VicGFjazovL2p1c3RpY2U0MC10b29sLy4vbm9kZV9tb2R1bGVzL29sL29iai5qcz9jM2M5Iiwid2VicGFjazovL2p1c3RpY2U0MC10b29sLy4vbm9kZV9tb2R1bGVzL29sL2V2ZW50cy9UYXJnZXQuanM/M2Y3YyIsIndlYnBhY2s6Ly9qdXN0aWNlNDAtdG9vbC8uL25vZGVfbW9kdWxlcy9vbC9ldmVudHMvRXZlbnRUeXBlLmpzPzc0NmYiLCJ3ZWJwYWNrOi8vanVzdGljZTQwLXRvb2wvLi9ub2RlX21vZHVsZXMvb2wvZXZlbnRzLmpzP2ZiMmMiLCJ3ZWJwYWNrOi8vanVzdGljZTQwLXRvb2wvLi9ub2RlX21vZHVsZXMvb2wvT2JzZXJ2YWJsZS5qcz83MDRkIiwid2VicGFjazovL2p1c3RpY2U0MC10b29sLy4vbm9kZV9tb2R1bGVzL29sL09iamVjdC5qcz8zM2FiIiwid2VicGFjazovL2p1c3RpY2U0MC10b29sLy4vbm9kZV9tb2R1bGVzL29sL2xheWVyL1Byb3BlcnR5LmpzPzA3OTkiLCJ3ZWJwYWNrOi8vanVzdGljZTQwLXRvb2wvLi9ub2RlX21vZHVsZXMvb2wvbGF5ZXIvQmFzZS5qcz9lMjBmIiwid2VicGFjazovL2p1c3RpY2U0MC10b29sLy4vbm9kZV9tb2R1bGVzL29sL3JlbmRlci9FdmVudFR5cGUuanM/NDYyMiIsIndlYnBhY2s6Ly9qdXN0aWNlNDAtdG9vbC8uL25vZGVfbW9kdWxlcy9vbC9zb3VyY2UvU3RhdGUuanM/NTM5NCIsIndlYnBhY2s6Ly9qdXN0aWNlNDAtdG9vbC8uL25vZGVfbW9kdWxlcy9vbC9sYXllci9MYXllci5qcz9hMjUyIiwid2VicGFjazovL2p1c3RpY2U0MC10b29sLy4vbm9kZV9tb2R1bGVzL29sL2Nvb3JkaW5hdGUuanM/OGVjZSIsIndlYnBhY2s6Ly9qdXN0aWNlNDAtdG9vbC8uL25vZGVfbW9kdWxlcy9vbC9yZW5kZXJlci9NYXAuanM/NDAwYiIsIndlYnBhY2s6Ly9qdXN0aWNlNDAtdG9vbC8uL25vZGVfbW9kdWxlcy9vbC9yZW5kZXIvRXZlbnQuanM/N2Y0ZCIsIndlYnBhY2s6Ly9qdXN0aWNlNDAtdG9vbC8uL25vZGVfbW9kdWxlcy9vbC9jc3MuanM/NDcwMyIsIndlYnBhY2s6Ly9qdXN0aWNlNDAtdG9vbC8uL25vZGVfbW9kdWxlcy9vbC9oYXMuanM/ZGMwMiIsIndlYnBhY2s6Ly9qdXN0aWNlNDAtdG9vbC8uL25vZGVfbW9kdWxlcy9vbC9kb20uanM/YzQxYSIsIndlYnBhY2s6Ly9qdXN0aWNlNDAtdG9vbC8uL25vZGVfbW9kdWxlcy9vbC9yZW5kZXIvY2FudmFzLmpzPzkxZTkiLCJ3ZWJwYWNrOi8vanVzdGljZTQwLXRvb2wvLi9ub2RlX21vZHVsZXMvb2wvcmVuZGVyZXIvQ29tcG9zaXRlLmpzPzc2NWMiLCJ3ZWJwYWNrOi8vanVzdGljZTQwLXRvb2wvLi9ub2RlX21vZHVsZXMvb2wvQ29sbGVjdGlvbkV2ZW50VHlwZS5qcz81YzJkIiwid2VicGFjazovL2p1c3RpY2U0MC10b29sLy4vbm9kZV9tb2R1bGVzL29sL0NvbGxlY3Rpb24uanM/MzA1ZiIsIndlYnBhY2s6Ly9qdXN0aWNlNDAtdG9vbC8uL25vZGVfbW9kdWxlcy9vbC9sYXllci9Hcm91cC5qcz85ZDBiIiwid2VicGFjazovL2p1c3RpY2U0MC10b29sLy4vbm9kZV9tb2R1bGVzL29sL01hcEV2ZW50LmpzPzcxYmYiLCJ3ZWJwYWNrOi8vanVzdGljZTQwLXRvb2wvLi9ub2RlX21vZHVsZXMvb2wvTWFwQnJvd3NlckV2ZW50LmpzPzY0NjUiLCJ3ZWJwYWNrOi8vanVzdGljZTQwLXRvb2wvLi9ub2RlX21vZHVsZXMvb2wvTWFwQnJvd3NlckV2ZW50VHlwZS5qcz83M2RkIiwid2VicGFjazovL2p1c3RpY2U0MC10b29sLy4vbm9kZV9tb2R1bGVzL29sL3BvaW50ZXIvRXZlbnRUeXBlLmpzP2NiMDYiLCJ3ZWJwYWNrOi8vanVzdGljZTQwLXRvb2wvLi9ub2RlX21vZHVsZXMvb2wvTWFwQnJvd3NlckV2ZW50SGFuZGxlci5qcz9kMGMxIiwid2VicGFjazovL2p1c3RpY2U0MC10b29sLy4vbm9kZV9tb2R1bGVzL29sL01hcEV2ZW50VHlwZS5qcz8xNjUzIiwid2VicGFjazovL2p1c3RpY2U0MC10b29sLy4vbm9kZV9tb2R1bGVzL29sL01hcFByb3BlcnR5LmpzP2ZkOWQiLCJ3ZWJwYWNrOi8vanVzdGljZTQwLXRvb2wvLi9ub2RlX21vZHVsZXMvb2wvc3RydWN0cy9Qcmlvcml0eVF1ZXVlLmpzP2Y2MTAiLCJ3ZWJwYWNrOi8vanVzdGljZTQwLXRvb2wvLi9ub2RlX21vZHVsZXMvb2wvVGlsZVN0YXRlLmpzP2MzMGYiLCJ3ZWJwYWNrOi8vanVzdGljZTQwLXRvb2wvLi9ub2RlX21vZHVsZXMvb2wvVGlsZVF1ZXVlLmpzPzk3OTUiLCJ3ZWJwYWNrOi8vanVzdGljZTQwLXRvb2wvLi9ub2RlX21vZHVsZXMvb2wvZ2VvbS9HZW9tZXRyeVR5cGUuanM/MmQyMyIsIndlYnBhY2s6Ly9qdXN0aWNlNDAtdG9vbC8uL25vZGVfbW9kdWxlcy9vbC9wcm9qL1VuaXRzLmpzPzA1MmYiLCJ3ZWJwYWNrOi8vanVzdGljZTQwLXRvb2wvLi9ub2RlX21vZHVsZXMvb2wvVmlld0hpbnQuanM/NWRkZiIsIndlYnBhY2s6Ly9qdXN0aWNlNDAtdG9vbC8uL25vZGVfbW9kdWxlcy9vbC9WaWV3UHJvcGVydHkuanM/YTI1ZSIsIndlYnBhY2s6Ly9qdXN0aWNlNDAtdG9vbC8uL25vZGVfbW9kdWxlcy9vbC90aWxlZ3JpZC9jb21tb24uanM/OTQwZSIsIndlYnBhY2s6Ly9qdXN0aWNlNDAtdG9vbC8uL25vZGVfbW9kdWxlcy9vbC9wcm9qL1Byb2plY3Rpb24uanM/MjM4MCIsIndlYnBhY2s6Ly9qdXN0aWNlNDAtdG9vbC8uL25vZGVfbW9kdWxlcy9vbC9wcm9qL2Vwc2czODU3LmpzPzZlMDAiLCJ3ZWJwYWNrOi8vanVzdGljZTQwLXRvb2wvLi9ub2RlX21vZHVsZXMvb2wvcHJvai9lcHNnNDMyNi5qcz84ODY3Iiwid2VicGFjazovL2p1c3RpY2U0MC10b29sLy4vbm9kZV9tb2R1bGVzL29sL3Byb2ovcHJvamVjdGlvbnMuanM/ZDUzMyIsIndlYnBhY2s6Ly9qdXN0aWNlNDAtdG9vbC8uL25vZGVfbW9kdWxlcy9vbC9wcm9qL3RyYW5zZm9ybXMuanM/ZmMxNiIsIndlYnBhY2s6Ly9qdXN0aWNlNDAtdG9vbC8uL25vZGVfbW9kdWxlcy9vbC9zcGhlcmUuanM/ZmIzMiIsIndlYnBhY2s6Ly9qdXN0aWNlNDAtdG9vbC8uL25vZGVfbW9kdWxlcy9vbC9wcm9qLmpzP2UxZTQiLCJ3ZWJwYWNrOi8vanVzdGljZTQwLXRvb2wvLi9ub2RlX21vZHVsZXMvb2wvY2VudGVyY29uc3RyYWludC5qcz9mMjgyIiwid2VicGFjazovL2p1c3RpY2U0MC10b29sLy4vbm9kZV9tb2R1bGVzL29sL3Jlc29sdXRpb25jb25zdHJhaW50LmpzPzcyYzYiLCJ3ZWJwYWNrOi8vanVzdGljZTQwLXRvb2wvLi9ub2RlX21vZHVsZXMvb2wvcm90YXRpb25jb25zdHJhaW50LmpzP2I1MDgiLCJ3ZWJwYWNrOi8vanVzdGljZTQwLXRvb2wvLi9ub2RlX21vZHVsZXMvb2wvZWFzaW5nLmpzPzkxYzUiLCJ3ZWJwYWNrOi8vanVzdGljZTQwLXRvb2wvLi9ub2RlX21vZHVsZXMvb2wvZ2VvbS9HZW9tZXRyeUxheW91dC5qcz9lZjU4Iiwid2VicGFjazovL2p1c3RpY2U0MC10b29sLy4vbm9kZV9tb2R1bGVzL29sL2dlb20vZmxhdC90cmFuc2Zvcm0uanM/MzQ2MyIsIndlYnBhY2s6Ly9qdXN0aWNlNDAtdG9vbC8uL25vZGVfbW9kdWxlcy9vbC9nZW9tL0dlb21ldHJ5LmpzPzc1MjIiLCJ3ZWJwYWNrOi8vanVzdGljZTQwLXRvb2wvLi9ub2RlX21vZHVsZXMvb2wvZ2VvbS9TaW1wbGVHZW9tZXRyeS5qcz9iMDQwIiwid2VicGFjazovL2p1c3RpY2U0MC10b29sLy4vbm9kZV9tb2R1bGVzL29sL2dlb20vZmxhdC9jbG9zZXN0LmpzPzA1MjIiLCJ3ZWJwYWNrOi8vanVzdGljZTQwLXRvb2wvLi9ub2RlX21vZHVsZXMvb2wvZ2VvbS9mbGF0L2RlZmxhdGUuanM/OTI3OSIsIndlYnBhY2s6Ly9qdXN0aWNlNDAtdG9vbC8uL25vZGVfbW9kdWxlcy9vbC9nZW9tL2ZsYXQvc2ltcGxpZnkuanM/ZTdlYiIsIndlYnBhY2s6Ly9qdXN0aWNlNDAtdG9vbC8uL25vZGVfbW9kdWxlcy9vbC9nZW9tL2ZsYXQvaW5mbGF0ZS5qcz8yZDk1Iiwid2VicGFjazovL2p1c3RpY2U0MC10b29sLy4vbm9kZV9tb2R1bGVzL29sL2dlb20vZmxhdC9hcmVhLmpzPzUwZWYiLCJ3ZWJwYWNrOi8vanVzdGljZTQwLXRvb2wvLi9ub2RlX21vZHVsZXMvb2wvZ2VvbS9MaW5lYXJSaW5nLmpzPzc3NGYiLCJ3ZWJwYWNrOi8vanVzdGljZTQwLXRvb2wvLi9ub2RlX21vZHVsZXMvb2wvZ2VvbS9Qb2ludC5qcz9mMGFjIiwid2VicGFjazovL2p1c3RpY2U0MC10b29sLy4vbm9kZV9tb2R1bGVzL29sL2dlb20vZmxhdC9jb250YWlucy5qcz9lNmUyIiwid2VicGFjazovL2p1c3RpY2U0MC10b29sLy4vbm9kZV9tb2R1bGVzL29sL2dlb20vZmxhdC9pbnRlcmlvcnBvaW50LmpzPzg3NDUiLCJ3ZWJwYWNrOi8vanVzdGljZTQwLXRvb2wvLi9ub2RlX21vZHVsZXMvb2wvZ2VvbS9mbGF0L3NlZ21lbnRzLmpzP2ZhMGMiLCJ3ZWJwYWNrOi8vanVzdGljZTQwLXRvb2wvLi9ub2RlX21vZHVsZXMvb2wvZ2VvbS9mbGF0L2ludGVyc2VjdHNleHRlbnQuanM/NTU5MSIsIndlYnBhY2s6Ly9qdXN0aWNlNDAtdG9vbC8uL25vZGVfbW9kdWxlcy9vbC9nZW9tL2ZsYXQvcmV2ZXJzZS5qcz80MWNmIiwid2VicGFjazovL2p1c3RpY2U0MC10b29sLy4vbm9kZV9tb2R1bGVzL29sL2dlb20vZmxhdC9vcmllbnQuanM/OWZmMiIsIndlYnBhY2s6Ly9qdXN0aWNlNDAtdG9vbC8uL25vZGVfbW9kdWxlcy9vbC9nZW9tL1BvbHlnb24uanM/MDc5OCIsIndlYnBhY2s6Ly9qdXN0aWNlNDAtdG9vbC8uL25vZGVfbW9kdWxlcy9vbC9WaWV3LmpzP2QxOTciLCJ3ZWJwYWNrOi8vanVzdGljZTQwLXRvb2wvLi9ub2RlX21vZHVsZXMvb2wvc2l6ZS5qcz8xMzE1Iiwid2VicGFjazovL2p1c3RpY2U0MC10b29sLy4vbm9kZV9tb2R1bGVzL29sL1BsdWdnYWJsZU1hcC5qcz83YTNhIiwid2VicGFjazovL2p1c3RpY2U0MC10b29sLy4vbm9kZV9tb2R1bGVzL29sL2NvbnRyb2wvQ29udHJvbC5qcz9iNzJhIiwid2VicGFjazovL2p1c3RpY2U0MC10b29sLy4vbm9kZV9tb2R1bGVzL29sL2NvbnRyb2wvQXR0cmlidXRpb24uanM/ZTk2NCIsIndlYnBhY2s6Ly9qdXN0aWNlNDAtdG9vbC8uL25vZGVfbW9kdWxlcy9vbC9jb250cm9sL1JvdGF0ZS5qcz9mNGI1Iiwid2VicGFjazovL2p1c3RpY2U0MC10b29sLy4vbm9kZV9tb2R1bGVzL29sL2NvbnRyb2wvWm9vbS5qcz8xYTFhIiwid2VicGFjazovL2p1c3RpY2U0MC10b29sLy4vbm9kZV9tb2R1bGVzL29sL2NvbnRyb2wuanM/MjJhMSIsIndlYnBhY2s6Ly9qdXN0aWNlNDAtdG9vbC8uL25vZGVfbW9kdWxlcy9vbC9pbnRlcmFjdGlvbi9Qcm9wZXJ0eS5qcz8yZDgxIiwid2VicGFjazovL2p1c3RpY2U0MC10b29sLy4vbm9kZV9tb2R1bGVzL29sL2ludGVyYWN0aW9uL0ludGVyYWN0aW9uLmpzPzM5MmQiLCJ3ZWJwYWNrOi8vanVzdGljZTQwLXRvb2wvLi9ub2RlX21vZHVsZXMvb2wvaW50ZXJhY3Rpb24vRG91YmxlQ2xpY2tab29tLmpzPzQ1YmQiLCJ3ZWJwYWNrOi8vanVzdGljZTQwLXRvb2wvLi9ub2RlX21vZHVsZXMvb2wvaW50ZXJhY3Rpb24vUG9pbnRlci5qcz80OTBjIiwid2VicGFjazovL2p1c3RpY2U0MC10b29sLy4vbm9kZV9tb2R1bGVzL29sL2V2ZW50cy9jb25kaXRpb24uanM/YzgyYiIsIndlYnBhY2s6Ly9qdXN0aWNlNDAtdG9vbC8uL25vZGVfbW9kdWxlcy9vbC9pbnRlcmFjdGlvbi9EcmFnUGFuLmpzP2RkYWQiLCJ3ZWJwYWNrOi8vanVzdGljZTQwLXRvb2wvLi9ub2RlX21vZHVsZXMvb2wvaW50ZXJhY3Rpb24vRHJhZ1JvdGF0ZS5qcz8yMjg4Iiwid2VicGFjazovL2p1c3RpY2U0MC10b29sLy4vbm9kZV9tb2R1bGVzL29sL3JlbmRlci9Cb3guanM/OTdiZiIsIndlYnBhY2s6Ly9qdXN0aWNlNDAtdG9vbC8uL25vZGVfbW9kdWxlcy9vbC9pbnRlcmFjdGlvbi9EcmFnQm94LmpzPzlmMjAiLCJ3ZWJwYWNrOi8vanVzdGljZTQwLXRvb2wvLi9ub2RlX21vZHVsZXMvb2wvaW50ZXJhY3Rpb24vRHJhZ1pvb20uanM/MmJjZCIsIndlYnBhY2s6Ly9qdXN0aWNlNDAtdG9vbC8uL25vZGVfbW9kdWxlcy9vbC9ldmVudHMvS2V5Q29kZS5qcz85NWNmIiwid2VicGFjazovL2p1c3RpY2U0MC10b29sLy4vbm9kZV9tb2R1bGVzL29sL2ludGVyYWN0aW9uL0tleWJvYXJkUGFuLmpzPzhhMWIiLCJ3ZWJwYWNrOi8vanVzdGljZTQwLXRvb2wvLi9ub2RlX21vZHVsZXMvb2wvaW50ZXJhY3Rpb24vS2V5Ym9hcmRab29tLmpzPzEzMjEiLCJ3ZWJwYWNrOi8vanVzdGljZTQwLXRvb2wvLi9ub2RlX21vZHVsZXMvb2wvS2luZXRpYy5qcz9mZTBiIiwid2VicGFjazovL2p1c3RpY2U0MC10b29sLy4vbm9kZV9tb2R1bGVzL29sL2ludGVyYWN0aW9uL01vdXNlV2hlZWxab29tLmpzP2ZhYjEiLCJ3ZWJwYWNrOi8vanVzdGljZTQwLXRvb2wvLi9ub2RlX21vZHVsZXMvb2wvaW50ZXJhY3Rpb24vUGluY2hSb3RhdGUuanM/YjYwZCIsIndlYnBhY2s6Ly9qdXN0aWNlNDAtdG9vbC8uL25vZGVfbW9kdWxlcy9vbC9pbnRlcmFjdGlvbi9QaW5jaFpvb20uanM/MjZiMCIsIndlYnBhY2s6Ly9qdXN0aWNlNDAtdG9vbC8uL25vZGVfbW9kdWxlcy9vbC9pbnRlcmFjdGlvbi5qcz82MDVmIiwid2VicGFjazovL2p1c3RpY2U0MC10b29sLy4vbm9kZV9tb2R1bGVzL29sL01hcC5qcz8xMzdjIiwid2VicGFjazovL2p1c3RpY2U0MC10b29sLy4vbm9kZV9tb2R1bGVzL29sL2xheWVyL1RpbGVQcm9wZXJ0eS5qcz80NGY0Iiwid2VicGFjazovL2p1c3RpY2U0MC10b29sLy4vbm9kZV9tb2R1bGVzL29sL2xheWVyL0Jhc2VUaWxlLmpzPzgwN2MiLCJ3ZWJwYWNrOi8vanVzdGljZTQwLXRvb2wvLi9ub2RlX21vZHVsZXMvb2wvSW1hZ2VTdGF0ZS5qcz9mZDYxIiwid2VicGFjazovL2p1c3RpY2U0MC10b29sLy4vbm9kZV9tb2R1bGVzL29sL3JlbmRlcmVyL0xheWVyLmpzPzI4MzMiLCJ3ZWJwYWNrOi8vanVzdGljZTQwLXRvb2wvLi9ub2RlX21vZHVsZXMvb2wvcmVuZGVyZXIvY2FudmFzL0xheWVyLmpzPzJlZTQiLCJ3ZWJwYWNrOi8vanVzdGljZTQwLXRvb2wvLi9ub2RlX21vZHVsZXMvb2wvVGlsZVJhbmdlLmpzPzZkNmYiLCJ3ZWJwYWNrOi8vanVzdGljZTQwLXRvb2wvLi9ub2RlX21vZHVsZXMvb2wvcmVuZGVyZXIvY2FudmFzL1RpbGVMYXllci5qcz9kYjI4Iiwid2VicGFjazovL2p1c3RpY2U0MC10b29sLy4vbm9kZV9tb2R1bGVzL29sL2xheWVyL1RpbGUuanM/YWUxZSIsIndlYnBhY2s6Ly9qdXN0aWNlNDAtdG9vbC8uL25vZGVfbW9kdWxlcy9vbC9UaWxlLmpzPzkzMTAiLCJ3ZWJwYWNrOi8vanVzdGljZTQwLXRvb2wvLi9ub2RlX21vZHVsZXMvb2wvVmVjdG9yVGlsZS5qcz9jNzI0Iiwid2VicGFjazovL2p1c3RpY2U0MC10b29sLy4vbm9kZV9tb2R1bGVzL29sL3N0cnVjdHMvTFJVQ2FjaGUuanM/ZjRjNSIsIndlYnBhY2s6Ly9qdXN0aWNlNDAtdG9vbC8uL25vZGVfbW9kdWxlcy9vbC90aWxlY29vcmQuanM/NTVmZCIsIndlYnBhY2s6Ly9qdXN0aWNlNDAtdG9vbC8uL25vZGVfbW9kdWxlcy9vbC9UaWxlQ2FjaGUuanM/YjEyYiIsIndlYnBhY2s6Ly9qdXN0aWNlNDAtdG9vbC8uL25vZGVfbW9kdWxlcy9vbC9zb3VyY2UvVGlsZUV2ZW50VHlwZS5qcz9mOGY0Iiwid2VicGFjazovL2p1c3RpY2U0MC10b29sLy4vbm9kZV9tb2R1bGVzL29sL3NvdXJjZS9Tb3VyY2UuanM/ZTRjOSIsIndlYnBhY2s6Ly9qdXN0aWNlNDAtdG9vbC8uL25vZGVfbW9kdWxlcy9vbC90aWxlZ3JpZC9UaWxlR3JpZC5qcz9mN2ZkIiwid2VicGFjazovL2p1c3RpY2U0MC10b29sLy4vbm9kZV9tb2R1bGVzL29sL3RpbGVncmlkLmpzP2VjNGUiLCJ3ZWJwYWNrOi8vanVzdGljZTQwLXRvb2wvLi9ub2RlX21vZHVsZXMvb2wvc291cmNlL1RpbGUuanM/MDBlNSIsIndlYnBhY2s6Ly9qdXN0aWNlNDAtdG9vbC8uL25vZGVfbW9kdWxlcy9vbC90aWxldXJsZnVuY3Rpb24uanM/OTVhNyIsIndlYnBhY2s6Ly9qdXN0aWNlNDAtdG9vbC8uL25vZGVfbW9kdWxlcy9vbC9zb3VyY2UvVXJsVGlsZS5qcz82MDRmIiwid2VicGFjazovL2p1c3RpY2U0MC10b29sLy4vbm9kZV9tb2R1bGVzL29sL1ZlY3RvclJlbmRlclRpbGUuanM/ODc5NSIsIndlYnBhY2s6Ly9qdXN0aWNlNDAtdG9vbC8uL25vZGVfbW9kdWxlcy9vbC9mb3JtYXQvRm9ybWF0VHlwZS5qcz8xMWI4Iiwid2VicGFjazovL2p1c3RpY2U0MC10b29sLy4vbm9kZV9tb2R1bGVzL29sL2ZlYXR1cmVsb2FkZXIuanM/ZWM1MiIsIndlYnBhY2s6Ly9qdXN0aWNlNDAtdG9vbC8uL25vZGVfbW9kdWxlcy9vbC9zb3VyY2UvVmVjdG9yVGlsZS5qcz8xYThjIiwid2VicGFjazovL2p1c3RpY2U0MC10b29sLy4vbm9kZV9tb2R1bGVzL29sL3N0eWxlL0ltYWdlLmpzP2U0MDIiLCJ3ZWJwYWNrOi8vanVzdGljZTQwLXRvb2wvLi9ub2RlX21vZHVsZXMvb2wvY29sb3JsaWtlLmpzP2JmMmIiLCJ3ZWJwYWNrOi8vanVzdGljZTQwLXRvb2wvLi9ub2RlX21vZHVsZXMvb2wvc3R5bGUvUmVndWxhclNoYXBlLmpzPzM2OWIiLCJ3ZWJwYWNrOi8vanVzdGljZTQwLXRvb2wvLi9ub2RlX21vZHVsZXMvb2wvc3R5bGUvQ2lyY2xlLmpzPzFjYTciLCJ3ZWJwYWNrOi8vanVzdGljZTQwLXRvb2wvLi9ub2RlX21vZHVsZXMvb2wvc3R5bGUvRmlsbC5qcz8wNGUyIiwid2VicGFjazovL2p1c3RpY2U0MC10b29sLy4vbm9kZV9tb2R1bGVzL29sL3N0eWxlL1N0cm9rZS5qcz80NTg5Iiwid2VicGFjazovL2p1c3RpY2U0MC10b29sLy4vbm9kZV9tb2R1bGVzL29sL3N0eWxlL1N0eWxlLmpzPzlhNGEiLCJ3ZWJwYWNrOi8vanVzdGljZTQwLXRvb2wvLi9ub2RlX21vZHVsZXMvb2wvbGF5ZXIvQmFzZVZlY3Rvci5qcz8xZDY3Iiwid2VicGFjazovL2p1c3RpY2U0MC10b29sLy4vbm9kZV9tb2R1bGVzL29sL3JlbmRlci9jYW52YXMvSW5zdHJ1Y3Rpb24uanM/YjczMCIsIndlYnBhY2s6Ly9qdXN0aWNlNDAtdG9vbC8uL25vZGVfbW9kdWxlcy9vbC9yZW5kZXIvVmVjdG9yQ29udGV4dC5qcz85ZWM4Iiwid2VicGFjazovL2p1c3RpY2U0MC10b29sLy4vbm9kZV9tb2R1bGVzL29sL3JlbmRlci9jYW52YXMvQnVpbGRlci5qcz9mNmQzIiwid2VicGFjazovL2p1c3RpY2U0MC10b29sLy4vbm9kZV9tb2R1bGVzL29sL3JlbmRlci9jYW52YXMvSW1hZ2VCdWlsZGVyLmpzPzk2ZjAiLCJ3ZWJwYWNrOi8vanVzdGljZTQwLXRvb2wvLi9ub2RlX21vZHVsZXMvb2wvcmVuZGVyL2NhbnZhcy9MaW5lU3RyaW5nQnVpbGRlci5qcz8zNWEwIiwid2VicGFjazovL2p1c3RpY2U0MC10b29sLy4vbm9kZV9tb2R1bGVzL29sL3JlbmRlci9jYW52YXMvUG9seWdvbkJ1aWxkZXIuanM/YTVhZiIsIndlYnBhY2s6Ly9qdXN0aWNlNDAtdG9vbC8uL25vZGVfbW9kdWxlcy9vbC9zdHlsZS9UZXh0UGxhY2VtZW50LmpzPzliNmQiLCJ3ZWJwYWNrOi8vanVzdGljZTQwLXRvb2wvLi9ub2RlX21vZHVsZXMvb2wvZ2VvbS9mbGF0L3N0cmFpZ2h0Y2h1bmsuanM/NTFkMiIsIndlYnBhY2s6Ly9qdXN0aWNlNDAtdG9vbC8uL25vZGVfbW9kdWxlcy9vbC9yZW5kZXIvY2FudmFzL1RleHRCdWlsZGVyLmpzP2RlMGQiLCJ3ZWJwYWNrOi8vanVzdGljZTQwLXRvb2wvLi9ub2RlX21vZHVsZXMvb2wvcmVuZGVyL2NhbnZhcy9CdWlsZGVyR3JvdXAuanM/YmM2NSIsIndlYnBhY2s6Ly9qdXN0aWNlNDAtdG9vbC8uL25vZGVfbW9kdWxlcy9vbC9yZW5kZXIvY2FudmFzL0J1aWxkZXJUeXBlLmpzPzkyMjciLCJ3ZWJwYWNrOi8vanVzdGljZTQwLXRvb2wvLi9ub2RlX21vZHVsZXMvb2wvZ2VvbS9mbGF0L3RleHRwYXRoLmpzP2Q0MTAiLCJ3ZWJwYWNrOi8vanVzdGljZTQwLXRvb2wvLi9ub2RlX21vZHVsZXMvb2wvZ2VvbS9mbGF0L2xlbmd0aC5qcz9mMDJiIiwid2VicGFjazovL2p1c3RpY2U0MC10b29sLy4vbm9kZV9tb2R1bGVzL29sL3JlbmRlci9jYW52YXMvRXhlY3V0b3IuanM/YWFmMyIsIndlYnBhY2s6Ly9qdXN0aWNlNDAtdG9vbC8uL25vZGVfbW9kdWxlcy9vbC9yZW5kZXIvY2FudmFzL0V4ZWN1dG9yR3JvdXAuanM/ODIyZiIsIndlYnBhY2s6Ly9qdXN0aWNlNDAtdG9vbC8uL25vZGVfbW9kdWxlcy9vbC9sYXllci9WZWN0b3JUaWxlUmVuZGVyVHlwZS5qcz81NjUyIiwid2VicGFjazovL2p1c3RpY2U0MC10b29sLy4vbm9kZV9tb2R1bGVzL29sL3JlbmRlci9jYW52YXMvSW1tZWRpYXRlLmpzP2RmZmIiLCJ3ZWJwYWNrOi8vanVzdGljZTQwLXRvb2wvLi9ub2RlX21vZHVsZXMvb2wvc3R5bGUvSWNvbkFuY2hvclVuaXRzLmpzP2Q0ZDMiLCJ3ZWJwYWNrOi8vanVzdGljZTQwLXRvb2wvLi9ub2RlX21vZHVsZXMvb2wvc3R5bGUvSWNvbk9yaWdpbi5qcz9hZjljIiwid2VicGFjazovL2p1c3RpY2U0MC10b29sLy4vbm9kZV9tb2R1bGVzL29sL0ltYWdlQmFzZS5qcz83NGJkIiwid2VicGFjazovL2p1c3RpY2U0MC10b29sLy4vbm9kZV9tb2R1bGVzL29sL0ltYWdlLmpzPzJhOWQiLCJ3ZWJwYWNrOi8vanVzdGljZTQwLXRvb2wvLi9ub2RlX21vZHVsZXMvb2wvc3R5bGUvSWNvbkltYWdlLmpzP2Q0MDEiLCJ3ZWJwYWNrOi8vanVzdGljZTQwLXRvb2wvLi9ub2RlX21vZHVsZXMvb2wvc3R5bGUvSWNvbi5qcz8yNTEzIiwid2VicGFjazovL2p1c3RpY2U0MC10b29sLy4vbm9kZV9tb2R1bGVzL29sL3JlbmRlci9jYW52YXMvaGl0ZGV0ZWN0LmpzPzE3MDciLCJ3ZWJwYWNrOi8vanVzdGljZTQwLXRvb2wvLi9ub2RlX21vZHVsZXMvb2wvcmVuZGVyZXIvdmVjdG9yLmpzPzcwNjUiLCJ3ZWJwYWNrOi8vanVzdGljZTQwLXRvb2wvLi9ub2RlX21vZHVsZXMvb2wvcmVuZGVyZXIvY2FudmFzL1ZlY3RvclRpbGVMYXllci5qcz84MDI3Iiwid2VicGFjazovL2p1c3RpY2U0MC10b29sLy4vbm9kZV9tb2R1bGVzL29sL2xheWVyL1ZlY3RvclRpbGUuanM/ZDlhZSIsIndlYnBhY2s6Ly9qdXN0aWNlNDAtdG9vbC8uL25vZGVfbW9kdWxlcy9vbC9mb3JtYXQvRmVhdHVyZS5qcz8wODA1Iiwid2VicGFjazovL2p1c3RpY2U0MC10b29sLy4vbm9kZV9tb2R1bGVzL29sL2dlb20vZmxhdC9pbnRlcnBvbGF0ZS5qcz83MjVhIiwid2VicGFjazovL2p1c3RpY2U0MC10b29sLy4vbm9kZV9tb2R1bGVzL29sL2dlb20vTGluZVN0cmluZy5qcz8zMjEwIiwid2VicGFjazovL2p1c3RpY2U0MC10b29sLy4vbm9kZV9tb2R1bGVzL29sL2dlb20vTXVsdGlMaW5lU3RyaW5nLmpzPzBhZGEiLCJ3ZWJwYWNrOi8vanVzdGljZTQwLXRvb2wvLi9ub2RlX21vZHVsZXMvb2wvZ2VvbS9NdWx0aVBvaW50LmpzPzYzMDciLCJ3ZWJwYWNrOi8vanVzdGljZTQwLXRvb2wvLi9ub2RlX21vZHVsZXMvb2wvZ2VvbS9mbGF0L2NlbnRlci5qcz82NjQ5Iiwid2VicGFjazovL2p1c3RpY2U0MC10b29sLy4vbm9kZV9tb2R1bGVzL29sL2dlb20vTXVsdGlQb2x5Z29uLmpzPzQzMTUiLCJ3ZWJwYWNrOi8vanVzdGljZTQwLXRvb2wvLi9ub2RlX21vZHVsZXMvb2wvcmVuZGVyL0ZlYXR1cmUuanM/NzI3ZCIsIndlYnBhY2s6Ly9qdXN0aWNlNDAtdG9vbC8uL25vZGVfbW9kdWxlcy9vbC9mb3JtYXQvTVZULmpzP2ZhOWQiLCJ3ZWJwYWNrOi8vanVzdGljZTQwLXRvb2wvLi9ub2RlX21vZHVsZXMvb2wvc3RydWN0cy9SQnVzaC5qcz8zMTI3Iiwid2VicGFjazovL2p1c3RpY2U0MC10b29sLy4vbm9kZV9tb2R1bGVzL29sL3NvdXJjZS9WZWN0b3JFdmVudFR5cGUuanM/NzU5YSIsIndlYnBhY2s6Ly9qdXN0aWNlNDAtdG9vbC8uL25vZGVfbW9kdWxlcy9vbC9sb2FkaW5nc3RyYXRlZ3kuanM/ODllYyIsIndlYnBhY2s6Ly9qdXN0aWNlNDAtdG9vbC8uL25vZGVfbW9kdWxlcy9vbC9zb3VyY2UvVmVjdG9yLmpzP2E2ZmUiLCJ3ZWJwYWNrOi8vanVzdGljZTQwLXRvb2wvLi9ub2RlX21vZHVsZXMvb2wvSW1hZ2VUaWxlLmpzP2NmYmYiLCJ3ZWJwYWNrOi8vanVzdGljZTQwLXRvb2wvLi9ub2RlX21vZHVsZXMvb2wvcmVwcm9qL2NvbW1vbi5qcz9kMTUyIiwid2VicGFjazovL2p1c3RpY2U0MC10b29sLy4vbm9kZV9tb2R1bGVzL29sL3JlcHJvai9Ucmlhbmd1bGF0aW9uLmpzP2Q5MTEiLCJ3ZWJwYWNrOi8vanVzdGljZTQwLXRvb2wvLi9ub2RlX21vZHVsZXMvb2wvc291cmNlL2NvbW1vbi5qcz8xMDU2Iiwid2VicGFjazovL2p1c3RpY2U0MC10b29sLy4vbm9kZV9tb2R1bGVzL29sL3JlcHJvai5qcz8xMzU4Iiwid2VicGFjazovL2p1c3RpY2U0MC10b29sLy4vbm9kZV9tb2R1bGVzL29sL3JlcHJvai9UaWxlLmpzPzBmMDIiLCJ3ZWJwYWNrOi8vanVzdGljZTQwLXRvb2wvLi9ub2RlX21vZHVsZXMvb2wvc291cmNlL1RpbGVJbWFnZS5qcz82Njg0Iiwid2VicGFjazovL2p1c3RpY2U0MC10b29sLy4vbm9kZV9tb2R1bGVzL29sL3NvdXJjZS9YWVouanM/OTlhMSIsIndlYnBhY2s6Ly9qdXN0aWNlNDAtdG9vbC8uL3NyYy9jb21wb25lbnRzL21hcC5tb2R1bGUuc2Nzcz9jYThkIiwid2VicGFjazovL2p1c3RpY2U0MC10b29sLy4vc3JjL2NvbXBvbmVudHMvbWFwLnRzeD82NjlkIiwid2VicGFjazovL2p1c3RpY2U0MC10b29sLy4vc3JjL2NvbXBvbmVudHMvbWFwQ29udHJvbHMubW9kdWxlLnNjc3M/N2Y0ZiIsIndlYnBhY2s6Ly9qdXN0aWNlNDAtdG9vbC8uL3NyYy9jb21wb25lbnRzL21hcENvbnRyb2xzLnRzeD80Zjg1Iiwid2VicGFjazovL2p1c3RpY2U0MC10b29sLy4vc3JjL2NvbXBvbmVudHMvSG93WW91Q2FuSGVscC5tb2R1bGUuc2Nzcz9jY2NiIiwid2VicGFjazovL2p1c3RpY2U0MC10b29sLy4vc3JjL2NvbXBvbmVudHMvSG93WW91Q2FuSGVscC50c3g/OTBiNCIsIndlYnBhY2s6Ly9qdXN0aWNlNDAtdG9vbC8uL3NyYy9wYWdlcy9jZWpzdC5tb2R1bGUuc2Nzcz82MWUzIiwid2VicGFjazovL2p1c3RpY2U0MC10b29sLy4vc3JjL3BhZ2VzL2NlanN0LnRzeD9lMWRmIl0sIm5hbWVzIjpbIk1hcFdyYXBwZXIiLCJmZWF0dXJlcyIsInVzZVN0YXRlIiwibWFwIiwic2V0TWFwIiwiZmVhdHVyZXNMYXllciIsInNldEZlYXR1cmVzTGF5ZXIiLCJtYXBFbGVtZW50IiwidXNlUmVmIiwidXNlRWZmZWN0IiwiaW5pdGFsRmVhdHVyZXNMYXllciIsIlZlY3RvclRpbGVMYXllciIsInNvdXJjZSIsIlZlY3RvclRpbGVTb3VyY2UiLCJmb3JtYXQiLCJNVlQiLCJ1cmwiLCJpbml0aWFsTWFwIiwiTWFwIiwidGFyZ2V0IiwiY3VycmVudCIsImxheWVycyIsIlRpbGVMYXllciIsIlhZWiIsInZpZXciLCJWaWV3IiwicHJvamVjdGlvbiIsImNlbnRlciIsImZyb21Mb25MYXQiLCJ6b29tIiwiY29udHJvbHMiLCJsZW5ndGgiLCJzZXRTb3VyY2UiLCJWZWN0b3JTb3VyY2UiLCJleHRlbnQiLCJnZXRTb3VyY2UiLCJnZXRFeHRlbnQiLCJnZXRWaWV3IiwiZml0IiwicGFkZGluZyIsInN0eWxlcyIsIk1hcENvbnRyb2xzIiwic2V0RmVhdHVyZXMiLCJIb3dZb3VDYW5IZWxwIiwiQ0VKU1RQYWdlIiwibG9jYXRpb24iXSwibWFwcGluZ3MiOiI7Ozs7Ozs7Ozs7Ozs7QUFBQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQSxjQUFjO0FBQ2Q7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7OztBQUdBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOzs7QUFHQTs7QUFFQTtBQUNBLENBQUM7O0FBRUQsa0RBQWUsVUFBVSxFOztBQ3pDekI7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsV0FBVyxTQUFTO0FBQ3BCLFdBQVcsRUFBRTtBQUNiLFdBQVcsVUFBVTtBQUNyQixZQUFZLE9BQU87QUFDbkI7QUFDTztBQUNQO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQSxLQUFL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RXRFOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBLGNBQWMsT0FBTztBQUNyQjs7O0FBR0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBLGFBQWEsT0FBTztBQUNwQixjQUFjLE9BQU87QUFDckI7QUFDQTs7O0FBR0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBLGFBQWEsT0FBTztBQUNwQixjQUFjLE9BQU87QUFDckI7QUFDQTs7O0FBR0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBLGFBQWEsT0FBTztBQUNwQixjQUFjLE9BQU87QUFDckI7QUFDQTs7O0FBR0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7OztBQUdBO0FBQ0E7O0FBRUEsOENBQThDLFFBQVE7QUFDdEQ7QUFDQTtBQUNBO0FBQ0E7QUFDQSxjQUFjLFFBQVE7QUFDdEI7OztBQUdBO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsYUFBYSxPQUFPO0FBQ3BCLGNBQWMsUUFBUTtBQUN0Qjs7O0FBR0E7QUFDQTtBQUNBO0FBQ0E7QUFDQSxhQUFhLEVBQUU7QUFDZixjQUFjLFFBQVE7QUFDdEI7OztBQUdBO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsYUFBYSxPQUFPO0FBQ3BCO0FBQ0E7OztBQUdBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBLGFBQWEsT0FBTztBQUNwQixhQUFhLE9BQU87QUFDcEI7QUFDQTs7O0FBR0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsT0FBTztBQUNQO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7OztBQUdBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQUVBLGVBQWUsT0FBTztBQUN0QjtBQUNBOztBQUVBO0FBQ0E7QUFDQSxP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QUNBO0FBQ0E7QUFDQSxjQUFjO0FBQ2Q7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQSxlQUFlLGFBQWE7QUFDNUI7QUFDQTtBQUNBO0FBQ0EsS0FBSztBQUNMO0FBQ0E7QUFDQSxjQUFjO0FBQ2Q7OztBQUdBLHdDQUF3QyxNQUFlO0FBQ3ZEO0FBQ0E7QUFDQSxjQUFjO0FBQ2Q7O0FBRUEsd0NBQXdDLE1BQWU7QUFDdkQ7QUFDQTtBQUNBLGNBQWM7QUFDZDs7QUFFQTtBQUNBO0FBQ0E7QUFDQSxjQUFjO0FBQ2Q7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQSxjQUFjO0FBQ2Q7O0FBRUE7QUFDQTtBQUNBO0FBQ0EsY0FBYztBQUNkOztBQUVBO0FBQ0E7QUFDQTtBQUNBLGNBQWM7QUFDZDs7QUFFQTtBQUNBO0FBQ0E7QUFDQSxjQUFjO0FBQ2Q7O0FBRUE7QUFDQTtBQUNBO0FBQ0EsY0FBYztBQUNkOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQSxjQUFjO0FBQ2Q7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0EsY0FBYztBQUNkOzs7QUFHQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQSxjQUFjO0FBQ2Q7OztBQUdBO0FBQ0E7QUFDQTtBQUNBLGNBQWM7QUFDZDs7QUFFQTtBQUNBO0FBQ0E7QUFDQSxjQUFjO0FBQ2Q7O0FBRUE7QUFDQTtBQUNBO0FBQ0EsY0FBYztBQUNkOztBQUVBO0FBQ0E7QUFDQSxjQUFjO0FBQ2Q7QUFDQTs7QUFFQSxxREFBcUQsYUFBVTtBQUMvRDtBQUNBLGNBQWM7QUFDZDtBQUNBOztBQUVBLDZEQUE2RCxhQUFVO0FBQ3ZFO0FBQ0EsY0FBYztBQUNkO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQSxjQUFjO0FBQ2Q7O0FBRUE7QUFDQTtBQUNBLGNBQWM7QUFDZDtBQUNBOztBQUVBO0FBQ0E7QUFDQSxjQUFjO0FBQ2Q7QUFDQTs7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ZUEsZ0RBQWVDLFdBQWYsRTs7QUN6QkE7QUFDTyxtRjs7QUNFUCxHQUFNRSxjQUFhLENBQUcsUUFBaEJBLGNBQWdCLEVBQU0sQ0FDMUIsbUJBQ0UsMkJBQUssU0FBUyxDQUFFSCxzQkFBaEIsZUFDRSxrRUFERixjQUVFLDJDQUNFLDBHQURGLGNBRUUsZ0tBRkYsY0FJRSxvR0FKRixjQUtFLG9GQUxGLENBRkYsQ0FERixDQVlELENBYkQsQ0FlQSw2REFBZUcsYUFBZixFOztBQ2xCQTtBQUNPLG1EOztBQ1lOLENBRUQsR0FBTUMsVUFBUyxDQUFHLFFBQVpBLFVBQVksTUFBK0IsSUFBN0JDLFNBQTZCLE1BQTdCQSxRQUE2QixDQUMvQyxjQUFnQzNDLGtCQUFRLENBQXNCLEVBQXRCLENBQXhDLENBQU9ELFFBQVAsY0FBaUJ5QyxXQUFqQixjQUNBLG1CQUNFLG9CQUFDLHFCQUFELEVBQVEsUUFBUSxDQUFFRyxRQUFsQixlQUNFLDRCQUFNLEVBQUUsQ0FBQyxjQUFULENBQXdCLElBQUksQ0FBQyxNQUE3QixlQUNFLHlCQUFHLFNBQVMsQ0FBRUwsVUFBZCxtVEFNa0IseUJBQ2QsSUFBSSxDQUFFLDRDQUNFLGtDQURGLENBRUUsMENBRkYsQ0FHRSw0QkFKTSxDQUtkLE1BQU0sQ0FBRSxRQUxNLENBTWQsR0FBRyxDQUFFLFlBTlMsc0VBTmxCLDZIQURGLGNBb0JFLG9CQUFDLFNBQUQsRUFDRSxJQUFJLENBQUMsU0FEUCxDQUVFLE9BQU8sQ0FBQyxzQkFGVixlQUdFLGtRQUhGLENBcEJGLGNBK0JFLG9CQUFDLFdBQUQsRUFBYSxXQUFXLENBQUVFLFdBQTFCLEVBL0JGLGNBZ0NFLG9CQUFDLEdBQUQsRUFBWSxRQUFRLENBQUV6QyxRQUF0QixFQWhDRixjQWlDRSxvQkFBQyx3QkFBRCxNQWpDRixDQURGLENBREYsQ0F1Q0QsQ0F6Q0QsQ0EyQ0EsMENBQWUyQyxTQUFmIiwiZmlsZSI6Ijk2ODIuanMiLCJzb3VyY2VzQ29udGVudCI6WyIvKipcbiAqIEBtb2R1bGUgb2wvRGlzcG9zYWJsZVxuICovXG5cbi8qKlxuICogQGNsYXNzZGVzY1xuICogT2JqZWN0cyB0aGF0IG5lZWQgdG8gY2xlYW4gdXAgYWZ0ZXIgdGhlbXNlbHZlcy5cbiAqL1xudmFyIERpc3Bvc2FibGUgPVxuLyoqIEBjbGFzcyAqL1xuZnVuY3Rpb24gKCkge1xuICBmdW5jdGlvbiBEaXNwb3NhYmxlKCkge1xuICAgIC8qKlxuICAgICAqIFRoZSBvYmplY3QgaGFzIGFscmVhZHkgYmVlbiBkaXNwb3NlZC5cbiAgICAgKiBAdHlwZSB7Ym9vbGVhbn1cbiAgICAgKiBAcHJvdGVjdGVkXG4gICAgICovXG4gICAgdGhpcy5kaXNwb3NlZCA9IGZhbHNlO1xuICB9XG4gIC8qKlxuICAgKiBDbGVhbiB1cC5cbiAgICovXG5cblxuICBEaXNwb3NhYmxlLnByb3RvdHlwZS5kaXNwb3NlID0gZnVuY3Rpb24gKCkge1xuICAgIGlmICghdGhpcy5kaXNwb3NlZCkge1xuICAgICAgdGhpcy5kaXNwb3NlZCA9IHRydWU7XG4gICAgICB0aGlzLmRpc3Bvc2VJbnRlcm5hbCgpO1xuICAgIH1cbiAgfTtcbiAgLyoqXG4gICAqIEV4dGVuc2lvbiBwb2ludCBmb3IgZGlzcG9zYWJsZSBvYmplY3RzLlxuICAgKiBAcHJvdGVjdGVkXG4gICAqL1xuXG5cbiAgRGlzcG9zYWJsZS5wcm90b3R5cGUuZGlzcG9zZUludGVybmFsID0gZnVuY3Rpb24gKCkge307XG5cbiAgcmV0dXJuIERpc3Bvc2FibGU7XG59KCk7XG5cbmV4cG9ydCBkZWZhdWx0IERpc3Bvc2FibGU7IiwiLyoqXG4gKiBAbW9kdWxlIG9sL2FycmF5XG4gKi9cblxuLyoqXG4gKiBQZXJmb3JtcyBhIGJpbmFyeSBzZWFyY2ggb24gdGhlIHByb3ZpZGVkIHNvcnRlZCBsaXN0IGFuZCByZXR1cm5zIHRoZSBpbmRleCBvZiB0aGUgaXRlbSBpZiBmb3VuZC4gSWYgaXQgY2FuJ3QgYmUgZm91bmQgaXQnbGwgcmV0dXJuIC0xLlxuICogaHR0cHM6Ly9naXRodWIuY29tL2Rhcmtza3lhcHAvYmluYXJ5LXNlYXJjaFxuICpcbiAqIEBwYXJhbSB7QXJyYXk8Kj59IGhheXN0YWNrIEl0ZW1zIHRvIHNlYXJjaCB0aHJvdWdoLlxuICogQHBhcmFtIHsqfSBuZWVkbGUgVGhlIGl0ZW0gdG8gbG9vayBmb3IuXG4gKiBAcGFyYW0ge0Z1bmN0aW9uPX0gb3B0X2NvbXBhcmF0b3IgQ29tcGFyYXRvciBmdW5jdGlvbi5cbiAqIEByZXR1cm4ge251bWJlcn0gVGhlIGluZGV4IG9mIHRoZSBpdGVtIGlmIGZvdW5kLCAtMSBpZiBub3QuXG4gKi9cbmV4cG9ydCBmdW5jdGlvbiBiaW5hcnlTZWFyY2goaGF5c3RhY2ssIG5lZWRsZSwgb3B0X2NvbXBhcmF0b3IpIHtcbiAgdmFyIG1pZCwgY21wO1xuICB2YXIgY29tcGFyYXRvciA9IG9wdF9jb21wYXJhdG9yIHx8IG51bWJlclNhZmVDb21wYXJlRnVuY3Rpb247XG4gIHZhciBsb3cgPSAwO1xuICB2YXIgaGlnaCA9IGhheXN0YWNrLmxlbmd0aDtcbiAgdmFyIGZvdW5kID0gZmFsc2U7XG5cbiAgd2hpbGUgKGxvdyA8IGhpZ2gpIHtcbiAgICAvKiBOb3RlIHRoYXQgXCIobG93ICsgaGlnaCkgPj4+IDFcIiBtYXkgb3ZlcmZsb3csIGFuZCByZXN1bHRzIGluIGEgdHlwZWNhc3RcbiAgICAgKiB0byBkb3VibGUgKHdoaWNoIGdpdmVzIHRoZSB3cm9uZyByZXN1bHRzKS4gKi9cbiAgICBtaWQgPSBsb3cgKyAoaGlnaCAtIGxvdyA+PiAxKTtcbiAgICBjbXAgPSArY29tcGFyYXRvcihoYXlzdGFja1ttaWRdLCBuZWVkbGUpO1xuXG4gICAgaWYgKGNtcCA8IDAuMCkge1xuICAgICAgLyogVG9vIGxvdy4gKi9cbiAgICAgIGxvdyA9IG1pZCArIDE7XG4gICAgfSBlbHNlIHtcbiAgICAgIC8qIEtleSBmb3VuZCBvciB0b28gaGlnaCAqL1xuICAgICAgaGlnaCA9IG1pZDtcbiAgICAgIGZvdW5kID0gIWNtcDtcbiAgICB9XG4gIH1cbiAgLyogS2V5IG5vdCBmb3VuZC4gKi9cblxuXG4gIHJldHVybiBmb3VuZCA/IGxvdyA6IH5sb3c7XG59XG4vKipcbiAqIENvbXBhcmUgZnVuY3Rpb24gZm9yIGFycmF5IHNvcnQgdGhhdCBpcyBzYWZlIGZvciBudW1iZXJzLlxuICogQHBhcmFtIHsqfSBhIFRoZSBmaXJzdCBvYmplY3QgdG8gYmUgY29tcGFyZWQuXG4gKiBAcGFyYW0geyp9IGIgVGhlIHNlY29uZCBvYmplY3QgdG8gYmUgY29tcGFyZWQuXG4gKiBAcmV0dXJuIHtudW1iZXJ9IEEgbmVnYXRpdmUgbnVtYmVyLCB6ZXJvLCBvciBhIHBvc2l0aXZlIG51bWJlciBhcyB0aGUgZmlyc3RcbiAqICAgICBhcmd1bWVudCBpcyBsZXNzIHRoYW4sIGVxdWFsIHRvLCBvciBncmVhdGVyIHRoYW4gdGhlIHNlY29uZC5cbiAqL1xuXG5leHBvcnQgZnVuY3Rpb24gbnVtYmVyU2FmZUNvbXBhcmVGdW5jdGlvbihhLCBiKSB7XG4gIHJldHVybiBhID4gYiA/IDEgOiBhIDwgYiA/IC0xIDogMDtcbn1cbi8qKlxuICogV2hldGhlciB0aGUgYXJyYXkgY29udGFpbnMgdGhlIGdpdmVuIG9iamVjdC5cbiAqIEBwYXJhbSB7QXJyYXk8Kj59IGFyciBUaGUgYXJyYXkgdG8gdGVzdCBmb3IgdGhlIHByZXNlbmNlIG9mIHRoZSBlbGVtZW50LlxuICogQHBhcmFtIHsqfSBvYmogVGhlIG9iamVjdCBmb3Igd2hpY2ggdG8gdGVzdC5cbiAqIEByZXR1cm4ge2Jvb2xlYW59IFRoZSBvYmplY3QgaXMgaW4gdGhlIGFycmF5LlxuICovXG5cbmV4cG9ydCBmdW5jdGlvbiBpbmNsdWRlcyhhcnIsIG9iaikge1xuICByZXR1cm4gYXJyLmluZGV4T2Yob2JqKSA+PSAwO1xufVxuLyoqXG4gKiBAcGFyYW0ge0FycmF5PG51bWJlcj59IGFyciBBcnJheS5cbiAqIEBwYXJhbSB7bnVtYmVyfSB0YXJnZXQgVGFyZ2V0LlxuICogQHBhcmFtIHtudW1iZXJ9IGRpcmVjdGlvbiAwIG1lYW5zIHJldHVybiB0aGUgbmVhcmVzdCwgPiAwXG4gKiAgICBtZWFucyByZXR1cm4gdGhlIGxhcmdlc3QgbmVhcmVzdCwgPCAwIG1lYW5zIHJldHVybiB0aGVcbiAqICAgIHNtYWxsZXN0IG5lYXJlc3QuXG4gKiBAcmV0dXJuIHtudW1iZXJ9IEluZGV4LlxuICovXG5cbmV4cG9ydCBmdW5jdGlvbiBsaW5lYXJGaW5kTmVhcmVzdChhcnIsIHRhcmdldCwgZGlyZWN0aW9uKSB7XG4gIHZhciBuID0gYXJyLmxlbmd0aDtcblxuICBpZiAoYXJyWzBdIDw9IHRhcmdldCkge1xuICAgIHJldHVybiAwO1xuICB9IGVsc2UgaWYgKHRhcmdldCA8PSBhcnJbbiAtIDFdKSB7XG4gICAgcmV0dXJuIG4gLSAxO1xuICB9IGVsc2Uge1xuICAgIHZhciBpID0gdm9pZCAwO1xuXG4gICAgaWYgKGRpcmVjdGlvbiA+IDApIHtcbiAgICAgIGZvciAoaSA9IDE7IGkgPCBuOyArK2kpIHtcbiAgICAgICAgaWYgKGFycltpXSA8IHRhcmdldCkge1xuICAgICAgICAgIHJldHVybiBpIC0gMTtcbiAgICAgICAgfVxuICAgICAgfVxuICAgIH0gZWxzZSBpZiAoZGlyZWN0aW9uIDwgMCkge1xuICAgICAgZm9yIChpID0gMTsgaSA8IG47ICsraSkge1xuICAgICAgICBpZiAoYXJyW2ldIDw9IHRhcmdldCkge1xuICAgICAgICAgIHJldHVybiBpO1xuICAgICAgICB9XG4gICAgICB9XG4gICAgfSBlbHNlIHtcbiAgICAgIGZvciAoaSA9IDE7IGkgPCBuOyArK2kpIHtcbiAgICAgICAgaWYgKGFycltpXSA9PSB0YXJnZXQpIHtcbiAgICAgICAgICByZXR1cm4gaTtcbiAgICAgICAgfSBlbHNlIGlmIChhcnJbaV0gPCB0YXJnZXQpIHtcbiAgICAgICAgICBpZiAoYXJyW2kgLSAxXSAtIHRhcmdldCA8IHRhcmdldCAtIGFycltpXSkge1xuICAgICAgICAgICAgcmV0dXJuIGkgLSAxO1xuICAgICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICByZXR1cm4gaTtcbiAgICAgICAgICB9XG4gICAgICAgIH1cbiAgICAgIH1cbiAgICB9XG5cbiAgICByZXR1cm4gbiAtIDE7XG4gIH1cbn1cbi8qKlxuICogQHBhcmFtIHtBcnJheTwqPn0gYXJyIEFycmF5LlxuICogQHBhcmFtIHtudW1iZXJ9IGJlZ2luIEJlZ2luIGluZGV4LlxuICogQHBhcmFtIHtudW1iZXJ9IGVuZCBFbmQgaW5kZXguXG4gKi9cblxuZXhwb3J0IGZ1bmN0aW9uIHJldmVyc2VTdWJBcnJheShhcnIsIGJlZ2luLCBlbmQpIHtcbiAgd2hpbGUgKGJlZ2luIDwgZW5kKSB7XG4gICAgdmFyIHRtcCA9IGFycltiZWdpbl07XG4gICAgYXJyW2JlZ2luXSA9IGFycltlbmRdO1xuICAgIGFycltlbmRdID0gdG1wO1xuICAgICsrYmVnaW47XG4gICAgLS1lbmQ7XG4gIH1cbn1cbi8qKlxuICogQHBhcmFtIHtBcnJheTxWQUxVRT59IGFyciBUaGUgYXJyYXkgdG8gbW9kaWZ5LlxuICogQHBhcmFtIHshQXJyYXk8VkFMVUU+fFZBTFVFfSBkYXRhIFRoZSBlbGVtZW50cyBvciBhcnJheXMgb2YgZWxlbWVudHMgdG8gYWRkIHRvIGFyci5cbiAqIEB0ZW1wbGF0ZSBWQUxVRVxuICovXG5cbmV4cG9ydCBmdW5jdGlvbiBleHRlbmQoYXJyLCBkYXRhKSB7XG4gIHZhciBleHRlbnNpb24gPSBBcnJheS5pc0FycmF5KGRhdGEpID8gZGF0YSA6IFtkYXRhXTtcbiAgdmFyIGxlbmd0aCA9IGV4dGVuc2lvbi5sZW5ndGg7XG5cbiAgZm9yICh2YXIgaSA9IDA7IGkgPCBsZW5ndGg7IGkrKykge1xuICAgIGFyclthcnIubGVuZ3RoXSA9IGV4dGVuc2lvbltpXTtcbiAgfVxufVxuLyoqXG4gKiBAcGFyYW0ge0FycmF5PFZBTFVFPn0gYXJyIFRoZSBhcnJheSB0byBtb2RpZnkuXG4gKiBAcGFyYW0ge1ZBTFVFfSBvYmogVGhlIGVsZW1lbnQgdG8gcmVtb3ZlLlxuICogQHRlbXBsYXRlIFZBTFVFXG4gKiBAcmV0dXJuIHtib29sZWFufSBJZiB0aGUgZWxlbWVudCB3YXMgcmVtb3ZlZC5cbiAqL1xuXG5leHBvcnQgZnVuY3Rpb24gcmVtb3ZlKGFyciwgb2JqKSB7XG4gIHZhciBpID0gYXJyLmluZGV4T2Yob2JqKTtcbiAgdmFyIGZvdW5kID0gaSA+IC0xO1xuXG4gIGlmIChmb3VuZCkge1xuICAgIGFyci5zcGxpY2UoaSwgMSk7XG4gIH1cblxuICByZXR1cm4gZm91bmQ7XG59XG4vKipcbiAqIEBwYXJhbSB7QXJyYXk8VkFMVUU+fSBhcnIgVGhlIGFycmF5IHRvIHNlYXJjaCBpbi5cbiAqIEBwYXJhbSB7ZnVuY3Rpb24oVkFMVUUsIG51bWJlciwgPykgOiBib29sZWFufSBmdW5jIFRoZSBmdW5jdGlvbiB0byBjb21wYXJlLlxuICogQHRlbXBsYXRlIFZBTFVFXG4gKiBAcmV0dXJuIHtWQUxVRXxudWxsfSBUaGUgZWxlbWVudCBmb3VuZCBvciBudWxsLlxuICovXG5cbmV4cG9ydCBmdW5jdGlvbiBmaW5kKGFyciwgZnVuYykge1xuICB2YXIgbGVuZ3RoID0gYXJyLmxlbmd0aCA+Pj4gMDtcbiAgdmFyIHZhbHVlO1xuXG4gIGZvciAodmFyIGkgPSAwOyBpIDwgbGVuZ3RoOyBpKyspIHtcbiAgICB2YWx1ZSA9IGFycltpXTtcblxuICAgIGlmIChmdW5jKHZhbHVlLCBpLCBhcnIpKSB7XG4gICAgICByZXR1cm4gdmFsdWU7XG4gICAgfVxuICB9XG5cbiAgcmV0dXJuIG51bGw7XG59XG4vKipcbiAqIEBwYXJhbSB7QXJyYXl8VWludDhDbGFtcGVkQXJyYXl9IGFycjEgVGhlIGZpcnN0IGFycmF5IHRvIGNvbXBhcmUuXG4gKiBAcGFyYW0ge0FycmF5fFVpbnQ4Q2xhbXBlZEFycmF5fSBhcnIyIFRoZSBzZWNvbmQgYXJyYXkgdG8gY29tcGFyZS5cbiAqIEByZXR1cm4ge2Jvb2xlYW59IFdoZXRoZXIgdGhlIHR3byBhcnJheXMgYXJlIGVxdWFsLlxuICovXG5cbmV4cG9ydCBmdW5jdGlvbiBlcXVhbHMoYXJyMSwgYXJyMikge1xuICB2YXIgbGVuMSA9IGFycjEubGVuZ3RoO1xuXG4gIGlmIChsZW4xICE9PSBhcnIyLmxlbmd0aCkge1xuICAgIHJldHVybiBmYWxzZTtcbiAgfVxuXG4gIGZvciAodmFyIGkgPSAwOyBpIDwgbGVuMTsgaSsrKSB7XG4gICAgaWYgKGFycjFbaV0gIT09IGFycjJbaV0pIHtcbiAgICAgIHJldHVybiBmYWxzZTtcbiAgICB9XG4gIH1cblxuICByZXR1cm4gdHJ1ZTtcbn1cbi8qKlxuICogU29ydCB0aGUgcGFzc2VkIGFycmF5IHN1Y2ggdGhhdCB0aGUgcmVsYXRpdmUgb3JkZXIgb2YgZXF1YWwgZWxlbWVudHMgaXMgcHJldmVydmVkLlxuICogU2VlIGh0dHBzOi8vZW4ud2lraXBlZGlhLm9yZy93aWtpL1NvcnRpbmdfYWxnb3JpdGhtI1N0YWJpbGl0eSBmb3IgZGV0YWlscy5cbiAqIEBwYXJhbSB7QXJyYXk8Kj59IGFyciBUaGUgYXJyYXkgdG8gc29ydCAobW9kaWZpZXMgb3JpZ2luYWwpLlxuICogQHBhcmFtIHshZnVuY3Rpb24oKiwgKik6IG51bWJlcn0gY29tcGFyZUZuYyBDb21wYXJpc29uIGZ1bmN0aW9uLlxuICogQGFwaVxuICovXG5cbmV4cG9ydCBmdW5jdGlvbiBzdGFibGVTb3J0KGFyciwgY29tcGFyZUZuYykge1xuICB2YXIgbGVuZ3RoID0gYXJyLmxlbmd0aDtcbiAgdmFyIHRtcCA9IEFycmF5KGFyci5sZW5ndGgpO1xuICB2YXIgaTtcblxuICBmb3IgKGkgPSAwOyBpIDwgbGVuZ3RoOyBpKyspIHtcbiAgICB0bXBbaV0gPSB7XG4gICAgICBpbmRleDogaSxcbiAgICAgIHZhbHVlOiBhcnJbaV1cbiAgICB9O1xuICB9XG5cbiAgdG1wLnNvcnQoZnVuY3Rpb24gKGEsIGIpIHtcbiAgICByZXR1cm4gY29tcGFyZUZuYyhhLnZhbHVlLCBiLnZhbHVlKSB8fCBhLmluZGV4IC0gYi5pbmRleDtcbiAgfSk7XG5cbiAgZm9yIChpID0gMDsgaSA8IGFyci5sZW5ndGg7IGkrKykge1xuICAgIGFycltpXSA9IHRtcFtpXS52YWx1ZTtcbiAgfVxufVxuLyoqXG4gKiBAcGFyYW0ge0FycmF5PCo+fSBhcnIgVGhlIGFycmF5IHRvIHNlYXJjaCBpbi5cbiAqIEBwYXJhbSB7RnVuY3Rpb259IGZ1bmMgQ29tcGFyaXNvbiBmdW5jdGlvbi5cbiAqIEByZXR1cm4ge251bWJlcn0gUmV0dXJuIGluZGV4LlxuICovXG5cbmV4cG9ydCBmdW5jdGlvbiBmaW5kSW5kZXgoYXJyLCBmdW5jKSB7XG4gIHZhciBpbmRleDtcbiAgdmFyIGZvdW5kID0gIWFyci5ldmVyeShmdW5jdGlvbiAoZWwsIGlkeCkge1xuICAgIGluZGV4ID0gaWR4O1xuICAgIHJldHVybiAhZnVuYyhlbCwgaWR4LCBhcnIpO1xuICB9KTtcbiAgcmV0dXJuIGZvdW5kID8gaW5kZXggOiAtMTtcbn1cbi8qKlxuICogQHBhcmFtIHtBcnJheTwqPn0gYXJyIFRoZSBhcnJheSB0byB0ZXN0LlxuICogQHBhcmFtIHtGdW5jdGlvbj19IG9wdF9mdW5jIENvbXBhcmlzb24gZnVuY3Rpb24uXG4gKiBAcGFyYW0ge2Jvb2xlYW49fSBvcHRfc3RyaWN0IFN0cmljdGx5IHNvcnRlZCAoZGVmYXVsdCBmYWxzZSkuXG4gKiBAcmV0dXJuIHtib29sZWFufSBSZXR1cm4gaW5kZXguXG4gKi9cblxuZXhwb3J0IGZ1bmN0aW9uIGlzU29ydGVkKGFyciwgb3B0X2Z1bmMsIG9wdF9zdHJpY3QpIHtcbiAgdmFyIGNvbXBhcmUgPSBvcHRfZnVuYyB8fCBudW1iZXJTYWZlQ29tcGFyZUZ1bmN0aW9uO1xuICByZXR1cm4gYXJyLmV2ZXJ5KGZ1bmN0aW9uIChjdXJyZW50VmFsLCBpbmRleCkge1xuICAgIGlmIChpbmRleCA9PT0gMCkge1xuICAgICAgcmV0dXJuIHRydWU7XG4gICAgfVxuXG4gICAgdmFyIHJlcyA9IGNvbXBhcmUoYXJyW2luZGV4IC0gMV0sIGN1cnJlbnRWYWwpO1xuICAgIHJldHVybiAhKHJlcyA+IDAgfHwgb3B0X3N0cmljdCAmJiByZXMgPT09IDApO1xuICB9KTtcbn0iLCIvKipcbiAqIEBtb2R1bGUgb2wvZnVuY3Rpb25zXG4gKi9cbmltcG9ydCB7IGVxdWFscyBhcyBhcnJheUVxdWFscyB9IGZyb20gJy4vYXJyYXkuanMnO1xuLyoqXG4gKiBBbHdheXMgcmV0dXJucyB0cnVlLlxuICogQHJldHVybnMge2Jvb2xlYW59IHRydWUuXG4gKi9cblxuZXhwb3J0IGZ1bmN0aW9uIFRSVUUoKSB7XG4gIHJldHVybiB0cnVlO1xufVxuLyoqXG4gKiBBbHdheXMgcmV0dXJucyBmYWxzZS5cbiAqIEByZXR1cm5zIHtib29sZWFufSBmYWxzZS5cbiAqL1xuXG5leHBvcnQgZnVuY3Rpb24gRkFMU0UoKSB7XG4gIHJldHVybiBmYWxzZTtcbn1cbi8qKlxuICogQSByZXVzYWJsZSBmdW5jdGlvbiwgdXNlZCBlLmcuIGFzIGEgZGVmYXVsdCBmb3IgY2FsbGJhY2tzLlxuICpcbiAqIEByZXR1cm4ge3ZvaWR9IE5vdGhpbmcuXG4gKi9cblxuZXhwb3J0IGZ1bmN0aW9uIFZPSUQoKSB7fVxuLyoqXG4gKiBXcmFwIGEgZnVuY3Rpb24gaW4gYW5vdGhlciBmdW5jdGlvbiB0aGF0IHJlbWVtYmVycyB0aGUgbGFzdCByZXR1cm4uICBJZiB0aGVcbiAqIHJldHVybmVkIGZ1bmN0aW9uIGlzIGNhbGxlZCB0d2ljZSBpbiBhIHJvdyB3aXRoIHRoZSBzYW1lIGFyZ3VtZW50cyBhbmQgdGhlIHNhbWVcbiAqIHRoaXMgb2JqZWN0LCBpdCB3aWxsIHJldHVybiB0aGUgdmFsdWUgZnJvbSB0aGUgZmlyc3QgY2FsbCBpbiB0aGUgc2Vjb25kIGNhbGwuXG4gKlxuICogQHBhcmFtIHtmdW5jdGlvbiguLi5hbnkpOiBSZXR1cm5UeXBlfSBmbiBUaGUgZnVuY3Rpb24gdG8gbWVtb2l6ZS5cbiAqIEByZXR1cm4ge2Z1bmN0aW9uKC4uLmFueSk6IFJldHVyblR5cGV9IFRoZSBtZW1vaXplZCBmdW5jdGlvbi5cbiAqIEB0ZW1wbGF0ZSBSZXR1cm5UeXBlXG4gKi9cblxuZXhwb3J0IGZ1bmN0aW9uIG1lbW9pemVPbmUoZm4pIHtcbiAgdmFyIGNhbGxlZCA9IGZhbHNlO1xuICAvKiogQHR5cGUge1JldHVyblR5cGV9ICovXG5cbiAgdmFyIGxhc3RSZXN1bHQ7XG4gIC8qKiBAdHlwZSB7QXJyYXk8YW55Pn0gKi9cblxuICB2YXIgbGFzdEFyZ3M7XG4gIHZhciBsYXN0VGhpcztcbiAgcmV0dXJuIGZ1bmN0aW9uICgpIHtcbiAgICB2YXIgbmV4dEFyZ3MgPSBBcnJheS5wcm90b3R5cGUuc2xpY2UuY2FsbChhcmd1bWVudHMpO1xuXG4gICAgaWYgKCFjYWxsZWQgfHwgdGhpcyAhPT0gbGFzdFRoaXMgfHwgIWFycmF5RXF1YWxzKG5leHRBcmdzLCBsYXN0QXJncykpIHtcbiAgICAgIGNhbGxlZCA9IHRydWU7XG4gICAgICBsYXN0VGhpcyA9IHRoaXM7XG4gICAgICBsYXN0QXJncyA9IG5leHRBcmdzO1xuICAgICAgbGFzdFJlc3VsdCA9IGZuLmFwcGx5KHRoaXMsIGFyZ3VtZW50cyk7XG4gICAgfVxuXG4gICAgcmV0dXJuIGxhc3RSZXN1bHQ7XG4gIH07XG59IiwiLyoqXG4gKiBAbW9kdWxlIG9sL3V0aWxcbiAqL1xuXG4vKipcbiAqIEByZXR1cm4gez99IEFueSByZXR1cm4uXG4gKi9cbmV4cG9ydCBmdW5jdGlvbiBhYnN0cmFjdCgpIHtcbiAgcmV0dXJuIChcbiAgICAvKiogQHR5cGUgez99ICovXG4gICAgZnVuY3Rpb24gKCkge1xuICAgICAgdGhyb3cgbmV3IEVycm9yKCdVbmltcGxlbWVudGVkIGFic3RyYWN0IG1ldGhvZC4nKTtcbiAgICB9KClcbiAgKTtcbn1cbi8qKlxuICogQ291bnRlciBmb3IgZ2V0VWlkLlxuICogQHR5cGUge251bWJlcn1cbiAqIEBwcml2YXRlXG4gKi9cblxudmFyIHVpZENvdW50ZXJfID0gMDtcbi8qKlxuICogR2V0cyBhIHVuaXF1ZSBJRCBmb3IgYW4gb2JqZWN0LiBUaGlzIG11dGF0ZXMgdGhlIG9iamVjdCBzbyB0aGF0IGZ1cnRoZXIgY2FsbHNcbiAqIHdpdGggdGhlIHNhbWUgb2JqZWN0IGFzIGEgcGFyYW1ldGVyIHJldHVybnMgdGhlIHNhbWUgdmFsdWUuIFVuaXF1ZSBJRHMgYXJlIGdlbmVyYXRlZFxuICogYXMgYSBzdHJpY3RseSBpbmNyZWFzaW5nIHNlcXVlbmNlLiBBZGFwdGVkIGZyb20gZ29vZy5nZXRVaWQuXG4gKlxuICogQHBhcmFtIHtPYmplY3R9IG9iaiBUaGUgb2JqZWN0IHRvIGdldCB0aGUgdW5pcXVlIElEIGZvci5cbiAqIEByZXR1cm4ge3N0cmluZ30gVGhlIHVuaXF1ZSBJRCBmb3IgdGhlIG9iamVjdC5cbiAqIEBhcGlcbiAqL1xuXG5leHBvcnQgZnVuY3Rpb24gZ2V0VWlkKG9iaikge1xuICByZXR1cm4gb2JqLm9sX3VpZCB8fCAob2JqLm9sX3VpZCA9IFN0cmluZygrK3VpZENvdW50ZXJfKSk7XG59XG4vKipcbiAqIE9wZW5MYXllcnMgdmVyc2lvbi5cbiAqIEB0eXBlIHtzdHJpbmd9XG4gKi9cblxuZXhwb3J0IHZhciBWRVJTSU9OID0gJzYuNS4wJzsiLCJ2YXIgX19leHRlbmRzID0gdGhpcyAmJiB0aGlzLl9fZXh0ZW5kcyB8fCBmdW5jdGlvbiAoKSB7XG4gIHZhciBfZXh0ZW5kU3RhdGljcyA9IGZ1bmN0aW9uIGV4dGVuZFN0YXRpY3MoZCwgYikge1xuICAgIF9leHRlbmRTdGF0aWNzID0gT2JqZWN0LnNldFByb3RvdHlwZU9mIHx8IHtcbiAgICAgIF9fcHJvdG9fXzogW11cbiAgICB9IGluc3RhbmNlb2YgQXJyYXkgJiYgZnVuY3Rpb24gKGQsIGIpIHtcbiAgICAgIGQuX19wcm90b19fID0gYjtcbiAgICB9IHx8IGZ1bmN0aW9uIChkLCBiKSB7XG4gICAgICBmb3IgKHZhciBwIGluIGIpIHtcbiAgICAgICAgaWYgKE9iamVjdC5wcm90b3R5cGUuaGFzT3duUHJvcGVydHkuY2FsbChiLCBwKSkgZFtwXSA9IGJbcF07XG4gICAgICB9XG4gICAgfTtcblxuICAgIHJldHVybiBfZXh0ZW5kU3RhdGljcyhkLCBiKTtcbiAgfTtcblxuICByZXR1cm4gZnVuY3Rpb24gKGQsIGIpIHtcbiAgICBfZXh0ZW5kU3RhdGljcyhkLCBiKTtcblxuICAgIGZ1bmN0aW9uIF9fKCkge1xuICAgICAgdGhpcy5jb25zdHJ1Y3RvciA9IGQ7XG4gICAgfVxuXG4gICAgZC5wcm90b3R5cGUgPSBiID09PSBudWxsID8gT2JqZWN0LmNyZWF0ZShiKSA6IChfXy5wcm90b3R5cGUgPSBiLnByb3RvdHlwZSwgbmV3IF9fKCkpO1xuICB9O1xufSgpO1xuLyoqXG4gKiBAbW9kdWxlIG9sL0Fzc2VydGlvbkVycm9yXG4gKi9cblxuXG5pbXBvcnQgeyBWRVJTSU9OIH0gZnJvbSAnLi91dGlsLmpzJztcbi8qKlxuICogRXJyb3Igb2JqZWN0IHRocm93biB3aGVuIGFuIGFzc2VydGlvbiBmYWlsZWQuIFRoaXMgaXMgYW4gRUNNQS0yNjIgRXJyb3IsXG4gKiBleHRlbmRlZCB3aXRoIGEgYGNvZGVgIHByb3BlcnR5LlxuICogU2VlIGh0dHBzOi8vZGV2ZWxvcGVyLm1vemlsbGEub3JnL2VuLVVTL2RvY3MvV2ViL0phdmFTY3JpcHQvUmVmZXJlbmNlL0dsb2JhbF9PYmplY3RzL0Vycm9yLlxuICovXG5cbnZhciBBc3NlcnRpb25FcnJvciA9XG4vKiogQGNsYXNzICovXG5mdW5jdGlvbiAoX3N1cGVyKSB7XG4gIF9fZXh0ZW5kcyhBc3NlcnRpb25FcnJvciwgX3N1cGVyKTtcbiAgLyoqXG4gICAqIEBwYXJhbSB7bnVtYmVyfSBjb2RlIEVycm9yIGNvZGUuXG4gICAqL1xuXG5cbiAgZnVuY3Rpb24gQXNzZXJ0aW9uRXJyb3IoY29kZSkge1xuICAgIHZhciBfdGhpcyA9IHRoaXM7XG5cbiAgICB2YXIgcGF0aCA9IFZFUlNJT04gPT09ICdsYXRlc3QnID8gVkVSU0lPTiA6ICd2JyArIFZFUlNJT04uc3BsaXQoJy0nKVswXTtcbiAgICB2YXIgbWVzc2FnZSA9ICdBc3NlcnRpb24gZmFpbGVkLiBTZWUgaHR0cHM6Ly9vcGVubGF5ZXJzLm9yZy9lbi8nICsgcGF0aCArICcvZG9jL2Vycm9ycy8jJyArIGNvZGUgKyAnIGZvciBkZXRhaWxzLic7XG4gICAgX3RoaXMgPSBfc3VwZXIuY2FsbCh0aGlzLCBtZXNzYWdlKSB8fCB0aGlzO1xuICAgIC8qKlxuICAgICAqIEVycm9yIGNvZGUuIFRoZSBtZWFuaW5nIG9mIHRoZSBjb2RlIGNhbiBiZSBmb3VuZCBvblxuICAgICAqIGh0dHBzOi8vb3BlbmxheWVycy5vcmcvZW4vbGF0ZXN0L2RvYy9lcnJvcnMvIChyZXBsYWNlIGBsYXRlc3RgIHdpdGhcbiAgICAgKiB0aGUgdmVyc2lvbiBmb3VuZCBpbiB0aGUgT3BlbkxheWVycyBzY3JpcHQncyBoZWFkZXIgY29tbWVudCBpZiBhIHZlcnNpb25cbiAgICAgKiBvdGhlciB0aGFuIHRoZSBsYXRlc3QgaXMgdXNlZCkuXG4gICAgICogQHR5cGUge251bWJlcn1cbiAgICAgKiBAYXBpXG4gICAgICovXG5cbiAgICBfdGhpcy5jb2RlID0gY29kZTtcbiAgICAvKipcbiAgICAgKiBAdHlwZSB7c3RyaW5nfVxuICAgICAqL1xuXG4gICAgX3RoaXMubmFtZSA9ICdBc3NlcnRpb25FcnJvcic7IC8vIFJlLWFzc2lnbiBtZXNzYWdlLCBzZWUgaHR0cHM6Ly9naXRodWIuY29tL1JpY2gtSGFycmlzL2J1YmxlL2lzc3Vlcy80MFxuXG4gICAgX3RoaXMubWVzc2FnZSA9IG1lc3NhZ2U7XG4gICAgcmV0dXJuIF90aGlzO1xuICB9XG5cbiAgcmV0dXJuIEFzc2VydGlvbkVycm9yO1xufShFcnJvcik7XG5cbmV4cG9ydCBkZWZhdWx0IEFzc2VydGlvbkVycm9yOyIsIi8qKlxuICogQG1vZHVsZSBvbC9hc3NlcnRzXG4gKi9cbmltcG9ydCBBc3NlcnRpb25FcnJvciBmcm9tICcuL0Fzc2VydGlvbkVycm9yLmpzJztcbi8qKlxuICogQHBhcmFtIHsqfSBhc3NlcnRpb24gQXNzZXJ0aW9uIHdlIGV4cGVjdGVkIHRvIGJlIHRydXRoeS5cbiAqIEBwYXJhbSB7bnVtYmVyfSBlcnJvckNvZGUgRXJyb3IgY29kZS5cbiAqL1xuXG5leHBvcnQgZnVuY3Rpb24gYXNzZXJ0KGFzc2VydGlvbiwgZXJyb3JDb2RlKSB7XG4gIGlmICghYXNzZXJ0aW9uKSB7XG4gICAgdGhyb3cgbmV3IEFzc2VydGlvbkVycm9yKGVycm9yQ29kZSk7XG4gIH1cbn0iLCIvKipcbiAqIEBtb2R1bGUgb2wvdHJhbnNmb3JtXG4gKi9cbmltcG9ydCB7IGFzc2VydCB9IGZyb20gJy4vYXNzZXJ0cy5qcyc7XG4vKipcbiAqIEFuIGFycmF5IHJlcHJlc2VudGluZyBhbiBhZmZpbmUgMmQgdHJhbnNmb3JtYXRpb24gZm9yIHVzZSB3aXRoXG4gKiB7QGxpbmsgbW9kdWxlOm9sL3RyYW5zZm9ybX0gZnVuY3Rpb25zLiBUaGUgYXJyYXkgaGFzIDYgZWxlbWVudHMuXG4gKiBAdHlwZWRlZiB7IUFycmF5PG51bWJlcj59IFRyYW5zZm9ybVxuICogQGFwaVxuICovXG5cbi8qKlxuICogQ29sbGVjdGlvbiBvZiBhZmZpbmUgMmQgdHJhbnNmb3JtYXRpb24gZnVuY3Rpb25zLiBUaGUgZnVuY3Rpb25zIHdvcmsgb24gYW5cbiAqIGFycmF5IG9mIDYgZWxlbWVudHMuIFRoZSBlbGVtZW50IG9yZGVyIGlzIGNvbXBhdGlibGUgd2l0aCB0aGUgW1NWR01hdHJpeFxuICogaW50ZXJmYWNlXShodHRwczovL2RldmVsb3Blci5tb3ppbGxhLm9yZy9lbi1VUy9kb2NzL1dlYi9BUEkvU1ZHTWF0cml4KSBhbmQgaXNcbiAqIGEgc3Vic2V0IChlbGVtZW50cyBhIHRvIGYpIG9mIGEgM8OXMyBtYXRyaXg6XG4gKiBgYGBcbiAqIFsgYSBjIGUgXVxuICogWyBiIGQgZiBdXG4gKiBbIDAgMCAxIF1cbiAqIGBgYFxuICovXG5cbi8qKlxuICogQHByaXZhdGVcbiAqIEB0eXBlIHtUcmFuc2Zvcm19XG4gKi9cblxudmFyIHRtcF8gPSBuZXcgQXJyYXkoNik7XG4vKipcbiAqIENyZWF0ZSBhbiBpZGVudGl0eSB0cmFuc2Zvcm0uXG4gKiBAcmV0dXJuIHshVHJhbnNmb3JtfSBJZGVudGl0eSB0cmFuc2Zvcm0uXG4gKi9cblxuZXhwb3J0IGZ1bmN0aW9uIGNyZWF0ZSgpIHtcbiAgcmV0dXJuIFsxLCAwLCAwLCAxLCAwLCAwXTtcbn1cbi8qKlxuICogUmVzZXRzIHRoZSBnaXZlbiB0cmFuc2Zvcm0gdG8gYW4gaWRlbnRpdHkgdHJhbnNmb3JtLlxuICogQHBhcmFtIHshVHJhbnNmb3JtfSB0cmFuc2Zvcm0gVHJhbnNmb3JtLlxuICogQHJldHVybiB7IVRyYW5zZm9ybX0gVHJhbnNmb3JtLlxuICovXG5cbmV4cG9ydCBmdW5jdGlvbiByZXNldCh0cmFuc2Zvcm0pIHtcbiAgcmV0dXJuIHNldCh0cmFuc2Zvcm0sIDEsIDAsIDAsIDEsIDAsIDApO1xufVxuLyoqXG4gKiBNdWx0aXBseSB0aGUgdW5kZXJseWluZyBtYXRyaWNlcyBvZiB0d28gdHJhbnNmb3JtcyBhbmQgcmV0dXJuIHRoZSByZXN1bHQgaW5cbiAqIHRoZSBmaXJzdCB0cmFuc2Zvcm0uXG4gKiBAcGFyYW0geyFUcmFuc2Zvcm19IHRyYW5zZm9ybTEgVHJhbnNmb3JtIHBhcmFtZXRlcnMgb2YgbWF0cml4IDEuXG4gKiBAcGFyYW0geyFUcmFuc2Zvcm19IHRyYW5zZm9ybTIgVHJhbnNmb3JtIHBhcmFtZXRlcnMgb2YgbWF0cml4IDIuXG4gKiBAcmV0dXJuIHshVHJhbnNmb3JtfSB0cmFuc2Zvcm0xIG11bHRpcGxpZWQgd2l0aCB0cmFuc2Zvcm0yLlxuICovXG5cbmV4cG9ydCBmdW5jdGlvbiBtdWx0aXBseSh0cmFuc2Zvcm0xLCB0cmFuc2Zvcm0yKSB7XG4gIHZhciBhMSA9IHRyYW5zZm9ybTFbMF07XG4gIHZhciBiMSA9IHRyYW5zZm9ybTFbMV07XG4gIHZhciBjMSA9IHRyYW5zZm9ybTFbMl07XG4gIHZhciBkMSA9IHRyYW5zZm9ybTFbM107XG4gIHZhciBlMSA9IHRyYW5zZm9ybTFbNF07XG4gIHZhciBmMSA9IHRyYW5zZm9ybTFbNV07XG4gIHZhciBhMiA9IHRyYW5zZm9ybTJbMF07XG4gIHZhciBiMiA9IHRyYW5zZm9ybTJbMV07XG4gIHZhciBjMiA9IHRyYW5zZm9ybTJbMl07XG4gIHZhciBkMiA9IHRyYW5zZm9ybTJbM107XG4gIHZhciBlMiA9IHRyYW5zZm9ybTJbNF07XG4gIHZhciBmMiA9IHRyYW5zZm9ybTJbNV07XG4gIHRyYW5zZm9ybTFbMF0gPSBhMSAqIGEyICsgYzEgKiBiMjtcbiAgdHJhbnNmb3JtMVsxXSA9IGIxICogYTIgKyBkMSAqIGIyO1xuICB0cmFuc2Zvcm0xWzJdID0gYTEgKiBjMiArIGMxICogZDI7XG4gIHRyYW5zZm9ybTFbM10gPSBiMSAqIGMyICsgZDEgKiBkMjtcbiAgdHJhbnNmb3JtMVs0XSA9IGExICogZTIgKyBjMSAqIGYyICsgZTE7XG4gIHRyYW5zZm9ybTFbNV0gPSBiMSAqIGUyICsgZDEgKiBmMiArIGYxO1xuICByZXR1cm4gdHJhbnNmb3JtMTtcbn1cbi8qKlxuICogU2V0IHRoZSB0cmFuc2Zvcm0gY29tcG9uZW50cyBhLWYgb24gYSBnaXZlbiB0cmFuc2Zvcm0uXG4gKiBAcGFyYW0geyFUcmFuc2Zvcm19IHRyYW5zZm9ybSBUcmFuc2Zvcm0uXG4gKiBAcGFyYW0ge251bWJlcn0gYSBUaGUgYSBjb21wb25lbnQgb2YgdGhlIHRyYW5zZm9ybS5cbiAqIEBwYXJhbSB7bnVtYmVyfSBiIFRoZSBiIGNvbXBvbmVudCBvZiB0aGUgdHJhbnNmb3JtLlxuICogQHBhcmFtIHtudW1iZXJ9IGMgVGhlIGMgY29tcG9uZW50IG9mIHRoZSB0cmFuc2Zvcm0uXG4gKiBAcGFyYW0ge251bWJlcn0gZCBUaGUgZCBjb21wb25lbnQgb2YgdGhlIHRyYW5zZm9ybS5cbiAqIEBwYXJhbSB7bnVtYmVyfSBlIFRoZSBlIGNvbXBvbmVudCBvZiB0aGUgdHJhbnNmb3JtLlxuICogQHBhcmFtIHtudW1iZXJ9IGYgVGhlIGYgY29tcG9uZW50IG9mIHRoZSB0cmFuc2Zvcm0uXG4gKiBAcmV0dXJuIHshVHJhbnNmb3JtfSBNYXRyaXggd2l0aCB0cmFuc2Zvcm0gYXBwbGllZC5cbiAqL1xuXG5leHBvcnQgZnVuY3Rpb24gc2V0KHRyYW5zZm9ybSwgYSwgYiwgYywgZCwgZSwgZikge1xuICB0cmFuc2Zvcm1bMF0gPSBhO1xuICB0cmFuc2Zvcm1bMV0gPSBiO1xuICB0cmFuc2Zvcm1bMl0gPSBjO1xuICB0cmFuc2Zvcm1bM10gPSBkO1xuICB0cmFuc2Zvcm1bNF0gPSBlO1xuICB0cmFuc2Zvcm1bNV0gPSBmO1xuICByZXR1cm4gdHJhbnNmb3JtO1xufVxuLyoqXG4gKiBTZXQgdHJhbnNmb3JtIG9uIG9uZSBtYXRyaXggZnJvbSBhbm90aGVyIG1hdHJpeC5cbiAqIEBwYXJhbSB7IVRyYW5zZm9ybX0gdHJhbnNmb3JtMSBNYXRyaXggdG8gc2V0IHRyYW5zZm9ybSB0by5cbiAqIEBwYXJhbSB7IVRyYW5zZm9ybX0gdHJhbnNmb3JtMiBNYXRyaXggdG8gc2V0IHRyYW5zZm9ybSBmcm9tLlxuICogQHJldHVybiB7IVRyYW5zZm9ybX0gdHJhbnNmb3JtMSB3aXRoIHRyYW5zZm9ybSBmcm9tIHRyYW5zZm9ybTIgYXBwbGllZC5cbiAqL1xuXG5leHBvcnQgZnVuY3Rpb24gc2V0RnJvbUFycmF5KHRyYW5zZm9ybTEsIHRyYW5zZm9ybTIpIHtcbiAgdHJhbnNmb3JtMVswXSA9IHRyYW5zZm9ybTJbMF07XG4gIHRyYW5zZm9ybTFbMV0gPSB0cmFuc2Zvcm0yWzFdO1xuICB0cmFuc2Zvcm0xWzJdID0gdHJhbnNmb3JtMlsyXTtcbiAgdHJhbnNmb3JtMVszXSA9IHRyYW5zZm9ybTJbM107XG4gIHRyYW5zZm9ybTFbNF0gPSB0cmFuc2Zvcm0yWzRdO1xuICB0cmFuc2Zvcm0xWzVdID0gdHJhbnNmb3JtMls1XTtcbiAgcmV0dXJuIHRyYW5zZm9ybTE7XG59XG4vKipcbiAqIFRyYW5zZm9ybXMgdGhlIGdpdmVuIGNvb3JkaW5hdGUgd2l0aCB0aGUgZ2l2ZW4gdHJhbnNmb3JtIHJldHVybmluZyB0aGVcbiAqIHJlc3VsdGluZywgdHJhbnNmb3JtZWQgY29vcmRpbmF0ZS4gVGhlIGNvb3JkaW5hdGUgd2lsbCBiZSBtb2RpZmllZCBpbi1wbGFjZS5cbiAqXG4gKiBAcGFyYW0ge1RyYW5zZm9ybX0gdHJhbnNmb3JtIFRoZSB0cmFuc2Zvcm1hdGlvbi5cbiAqIEBwYXJhbSB7aW1wb3J0KFwiLi9jb29yZGluYXRlLmpzXCIpLkNvb3JkaW5hdGV8aW1wb3J0KFwiLi9waXhlbC5qc1wiKS5QaXhlbH0gY29vcmRpbmF0ZSBUaGUgY29vcmRpbmF0ZSB0byB0cmFuc2Zvcm0uXG4gKiBAcmV0dXJuIHtpbXBvcnQoXCIuL2Nvb3JkaW5hdGUuanNcIikuQ29vcmRpbmF0ZXxpbXBvcnQoXCIuL3BpeGVsLmpzXCIpLlBpeGVsfSByZXR1cm4gY29vcmRpbmF0ZSBzbyB0aGF0IG9wZXJhdGlvbnMgY2FuIGJlXG4gKiAgICAgY2hhaW5lZCB0b2dldGhlci5cbiAqL1xuXG5leHBvcnQgZnVuY3Rpb24gYXBwbHkodHJhbnNmb3JtLCBjb29yZGluYXRlKSB7XG4gIHZhciB4ID0gY29vcmRpbmF0ZVswXTtcbiAgdmFyIHkgPSBjb29yZGluYXRlWzFdO1xuICBjb29yZGluYXRlWzBdID0gdHJhbnNmb3JtWzBdICogeCArIHRyYW5zZm9ybVsyXSAqIHkgKyB0cmFuc2Zvcm1bNF07XG4gIGNvb3JkaW5hdGVbMV0gPSB0cmFuc2Zvcm1bMV0gKiB4ICsgdHJhbnNmb3JtWzNdICogeSArIHRyYW5zZm9ybVs1XTtcbiAgcmV0dXJuIGNvb3JkaW5hdGU7XG59XG4vKipcbiAqIEFwcGxpZXMgcm90YXRpb24gdG8gdGhlIGdpdmVuIHRyYW5zZm9ybS5cbiAqIEBwYXJhbSB7IVRyYW5zZm9ybX0gdHJhbnNmb3JtIFRyYW5zZm9ybS5cbiAqIEBwYXJhbSB7bnVtYmVyfSBhbmdsZSBBbmdsZSBpbiByYWRpYW5zLlxuICogQHJldHVybiB7IVRyYW5zZm9ybX0gVGhlIHJvdGF0ZWQgdHJhbnNmb3JtLlxuICovXG5cbmV4cG9ydCBmdW5jdGlvbiByb3RhdGUodHJhbnNmb3JtLCBhbmdsZSkge1xuICB2YXIgY29zID0gTWF0aC5jb3MoYW5nbGUpO1xuICB2YXIgc2luID0gTWF0aC5zaW4oYW5nbGUpO1xuICByZXR1cm4gbXVsdGlwbHkodHJhbnNmb3JtLCBzZXQodG1wXywgY29zLCBzaW4sIC1zaW4sIGNvcywgMCwgMCkpO1xufVxuLyoqXG4gKiBBcHBsaWVzIHNjYWxlIHRvIGEgZ2l2ZW4gdHJhbnNmb3JtLlxuICogQHBhcmFtIHshVHJhbnNmb3JtfSB0cmFuc2Zvcm0gVHJhbnNmb3JtLlxuICogQHBhcmFtIHtudW1iZXJ9IHggU2NhbGUgZmFjdG9yIHguXG4gKiBAcGFyYW0ge251bWJlcn0geSBTY2FsZSBmYWN0b3IgeS5cbiAqIEByZXR1cm4geyFUcmFuc2Zvcm19IFRoZSBzY2FsZWQgdHJhbnNmb3JtLlxuICovXG5cbmV4cG9ydCBmdW5jdGlvbiBzY2FsZSh0cmFuc2Zvcm0sIHgsIHkpIHtcbiAgcmV0dXJuIG11bHRpcGx5KHRyYW5zZm9ybSwgc2V0KHRtcF8sIHgsIDAsIDAsIHksIDAsIDApKTtcbn1cbi8qKlxuICogQ3JlYXRlcyBhIHNjYWxlIHRyYW5zZm9ybS5cbiAqIEBwYXJhbSB7IVRyYW5zZm9ybX0gdGFyZ2V0IFRyYW5zZm9ybSB0byBvdmVyd3JpdGUuXG4gKiBAcGFyYW0ge251bWJlcn0geCBTY2FsZSBmYWN0b3IgeC5cbiAqIEBwYXJhbSB7bnVtYmVyfSB5IFNjYWxlIGZhY3RvciB5LlxuICogQHJldHVybiB7IVRyYW5zZm9ybX0gVGhlIHNjYWxlIHRyYW5zZm9ybS5cbiAqL1xuXG5leHBvcnQgZnVuY3Rpb24gbWFrZVNjYWxlKHRhcmdldCwgeCwgeSkge1xuICByZXR1cm4gc2V0KHRhcmdldCwgeCwgMCwgMCwgeSwgMCwgMCk7XG59XG4vKipcbiAqIEFwcGxpZXMgdHJhbnNsYXRpb24gdG8gdGhlIGdpdmVuIHRyYW5zZm9ybS5cbiAqIEBwYXJhbSB7IVRyYW5zZm9ybX0gdHJhbnNmb3JtIFRyYW5zZm9ybS5cbiAqIEBwYXJhbSB7bnVtYmVyfSBkeCBUcmFuc2xhdGlvbiB4LlxuICogQHBhcmFtIHtudW1iZXJ9IGR5IFRyYW5zbGF0aW9uIHkuXG4gKiBAcmV0dXJuIHshVHJhbnNmb3JtfSBUaGUgdHJhbnNsYXRlZCB0cmFuc2Zvcm0uXG4gKi9cblxuZXhwb3J0IGZ1bmN0aW9uIHRyYW5zbGF0ZSh0cmFuc2Zvcm0sIGR4LCBkeSkge1xuICByZXR1cm4gbXVsdGlwbHkodHJhbnNmb3JtLCBzZXQodG1wXywgMSwgMCwgMCwgMSwgZHgsIGR5KSk7XG59XG4vKipcbiAqIENyZWF0ZXMgYSBjb21wb3NpdGUgdHJhbnNmb3JtIGdpdmVuIGFuIGluaXRpYWwgdHJhbnNsYXRpb24sIHNjYWxlLCByb3RhdGlvbiwgYW5kXG4gKiBmaW5hbCB0cmFuc2xhdGlvbiAoaW4gdGhhdCBvcmRlciBvbmx5LCBub3QgY29tbXV0YXRpdmUpLlxuICogQHBhcmFtIHshVHJhbnNmb3JtfSB0cmFuc2Zvcm0gVGhlIHRyYW5zZm9ybSAod2lsbCBiZSBtb2RpZmllZCBpbiBwbGFjZSkuXG4gKiBAcGFyYW0ge251bWJlcn0gZHgxIEluaXRpYWwgdHJhbnNsYXRpb24geC5cbiAqIEBwYXJhbSB7bnVtYmVyfSBkeTEgSW5pdGlhbCB0cmFuc2xhdGlvbiB5LlxuICogQHBhcmFtIHtudW1iZXJ9IHN4IFNjYWxlIGZhY3RvciB4LlxuICogQHBhcmFtIHtudW1iZXJ9IHN5IFNjYWxlIGZhY3RvciB5LlxuICogQHBhcmFtIHtudW1iZXJ9IGFuZ2xlIFJvdGF0aW9uIChpbiBjb3VudGVyLWNsb2Nrd2lzZSByYWRpYW5zKS5cbiAqIEBwYXJhbSB7bnVtYmVyfSBkeDIgRmluYWwgdHJhbnNsYXRpb24geC5cbiAqIEBwYXJhbSB7bnVtYmVyfSBkeTIgRmluYWwgdHJhbnNsYXRpb24geS5cbiAqIEByZXR1cm4geyFUcmFuc2Zvcm19IFRoZSBjb21wb3NpdGUgdHJhbnNmb3JtLlxuICovXG5cbmV4cG9ydCBmdW5jdGlvbiBjb21wb3NlKHRyYW5zZm9ybSwgZHgxLCBkeTEsIHN4LCBzeSwgYW5nbGUsIGR4MiwgZHkyKSB7XG4gIHZhciBzaW4gPSBNYXRoLnNpbihhbmdsZSk7XG4gIHZhciBjb3MgPSBNYXRoLmNvcyhhbmdsZSk7XG4gIHRyYW5zZm9ybVswXSA9IHN4ICogY29zO1xuICB0cmFuc2Zvcm1bMV0gPSBzeSAqIHNpbjtcbiAgdHJhbnNmb3JtWzJdID0gLXN4ICogc2luO1xuICB0cmFuc2Zvcm1bM10gPSBzeSAqIGNvcztcbiAgdHJhbnNmb3JtWzRdID0gZHgyICogc3ggKiBjb3MgLSBkeTIgKiBzeCAqIHNpbiArIGR4MTtcbiAgdHJhbnNmb3JtWzVdID0gZHgyICogc3kgKiBzaW4gKyBkeTIgKiBzeSAqIGNvcyArIGR5MTtcbiAgcmV0dXJuIHRyYW5zZm9ybTtcbn1cbi8qKlxuICogQ3JlYXRlcyBhIGNvbXBvc2l0ZSB0cmFuc2Zvcm0gZ2l2ZW4gYW4gaW5pdGlhbCB0cmFuc2xhdGlvbiwgc2NhbGUsIHJvdGF0aW9uLCBhbmRcbiAqIGZpbmFsIHRyYW5zbGF0aW9uIChpbiB0aGF0IG9yZGVyIG9ubHksIG5vdCBjb21tdXRhdGl2ZSkuIFRoZSByZXN1bHRpbmcgdHJhbnNmb3JtXG4gKiBzdHJpbmcgY2FuIGJlIGFwcGxpZWQgYXMgYHRyYW5zZm9ybWAgcG9ycGVydHkgb2YgYW4gSFRNTEVsZW1lbnQncyBzdHlsZS5cbiAqIEBwYXJhbSB7bnVtYmVyfSBkeDEgSW5pdGlhbCB0cmFuc2xhdGlvbiB4LlxuICogQHBhcmFtIHtudW1iZXJ9IGR5MSBJbml0aWFsIHRyYW5zbGF0aW9uIHkuXG4gKiBAcGFyYW0ge251bWJlcn0gc3ggU2NhbGUgZmFjdG9yIHguXG4gKiBAcGFyYW0ge251bWJlcn0gc3kgU2NhbGUgZmFjdG9yIHkuXG4gKiBAcGFyYW0ge251bWJlcn0gYW5nbGUgUm90YXRpb24gKGluIGNvdW50ZXItY2xvY2t3aXNlIHJhZGlhbnMpLlxuICogQHBhcmFtIHtudW1iZXJ9IGR4MiBGaW5hbCB0cmFuc2xhdGlvbiB4LlxuICogQHBhcmFtIHtudW1iZXJ9IGR5MiBGaW5hbCB0cmFuc2xhdGlvbiB5LlxuICogQHJldHVybiB7c3RyaW5nfSBUaGUgY29tcG9zaXRlIGNzcyB0cmFuc2Zvcm0uXG4gKiBAYXBpXG4gKi9cblxuZXhwb3J0IGZ1bmN0aW9uIGNvbXBvc2VDc3NUcmFuc2Zvcm0oZHgxLCBkeTEsIHN4LCBzeSwgYW5nbGUsIGR4MiwgZHkyKSB7XG4gIHJldHVybiB0b1N0cmluZyhjb21wb3NlKGNyZWF0ZSgpLCBkeDEsIGR5MSwgc3gsIHN5LCBhbmdsZSwgZHgyLCBkeTIpKTtcbn1cbi8qKlxuICogSW52ZXJ0IHRoZSBnaXZlbiB0cmFuc2Zvcm0uXG4gKiBAcGFyYW0geyFUcmFuc2Zvcm19IHNvdXJjZSBUaGUgc291cmNlIHRyYW5zZm9ybSB0byBpbnZlcnQuXG4gKiBAcmV0dXJuIHshVHJhbnNmb3JtfSBUaGUgaW52ZXJ0ZWQgKHNvdXJjZSkgdHJhbnNmb3JtLlxuICovXG5cbmV4cG9ydCBmdW5jdGlvbiBpbnZlcnQoc291cmNlKSB7XG4gIHJldHVybiBtYWtlSW52ZXJzZShzb3VyY2UsIHNvdXJjZSk7XG59XG4vKipcbiAqIEludmVydCB0aGUgZ2l2ZW4gdHJhbnNmb3JtLlxuICogQHBhcmFtIHshVHJhbnNmb3JtfSB0YXJnZXQgVHJhbnNmb3JtIHRvIGJlIHNldCBhcyB0aGUgaW52ZXJzZSBvZlxuICogICAgIHRoZSBzb3VyY2UgdHJhbnNmb3JtLlxuICogQHBhcmFtIHshVHJhbnNmb3JtfSBzb3VyY2UgVGhlIHNvdXJjZSB0cmFuc2Zvcm0gdG8gaW52ZXJ0LlxuICogQHJldHVybiB7IVRyYW5zZm9ybX0gVGhlIGludmVydGVkICh0YXJnZXQpIHRyYW5zZm9ybS5cbiAqL1xuXG5leHBvcnQgZnVuY3Rpb24gbWFrZUludmVyc2UodGFyZ2V0LCBzb3VyY2UpIHtcbiAgdmFyIGRldCA9IGRldGVybWluYW50KHNvdXJjZSk7XG4gIGFzc2VydChkZXQgIT09IDAsIDMyKTsgLy8gVHJhbnNmb3JtYXRpb24gbWF0cml4IGNhbm5vdCBiZSBpbnZlcnRlZFxuXG4gIHZhciBhID0gc291cmNlWzBdO1xuICB2YXIgYiA9IHNvdXJjZVsxXTtcbiAgdmFyIGMgPSBzb3VyY2VbMl07XG4gIHZhciBkID0gc291cmNlWzNdO1xuICB2YXIgZSA9IHNvdXJjZVs0XTtcbiAgdmFyIGYgPSBzb3VyY2VbNV07XG4gIHRhcmdldFswXSA9IGQgLyBkZXQ7XG4gIHRhcmdldFsxXSA9IC1iIC8gZGV0O1xuICB0YXJnZXRbMl0gPSAtYyAvIGRldDtcbiAgdGFyZ2V0WzNdID0gYSAvIGRldDtcbiAgdGFyZ2V0WzRdID0gKGMgKiBmIC0gZCAqIGUpIC8gZGV0O1xuICB0YXJnZXRbNV0gPSAtKGEgKiBmIC0gYiAqIGUpIC8gZGV0O1xuICByZXR1cm4gdGFyZ2V0O1xufVxuLyoqXG4gKiBSZXR1cm5zIHRoZSBkZXRlcm1pbmFudCBvZiB0aGUgZ2l2ZW4gbWF0cml4LlxuICogQHBhcmFtIHshVHJhbnNmb3JtfSBtYXQgTWF0cml4LlxuICogQHJldHVybiB7bnVtYmVyfSBEZXRlcm1pbmFudC5cbiAqL1xuXG5leHBvcnQgZnVuY3Rpb24gZGV0ZXJtaW5hbnQobWF0KSB7XG4gIHJldHVybiBtYXRbMF0gKiBtYXRbM10gLSBtYXRbMV0gKiBtYXRbMl07XG59XG4vKipcbiAqIEEgc3RyaW5nIHZlcnNpb24gb2YgdGhlIHRyYW5zZm9ybS4gIFRoaXMgY2FuIGJlIHVzZWRcbiAqIGZvciBDU1MgdHJhbnNmb3Jtcy5cbiAqIEBwYXJhbSB7IVRyYW5zZm9ybX0gbWF0IE1hdHJpeC5cbiAqIEByZXR1cm4ge3N0cmluZ30gVGhlIHRyYW5zZm9ybSBhcyBhIHN0cmluZy5cbiAqL1xuXG5leHBvcnQgZnVuY3Rpb24gdG9TdHJpbmcobWF0KSB7XG4gIHJldHVybiAnbWF0cml4KCcgKyBtYXQuam9pbignLCAnKSArICcpJztcbn0iLCIvKipcbiAqIEBtb2R1bGUgb2wvZXh0ZW50L0Nvcm5lclxuICovXG5cbi8qKlxuICogRXh0ZW50IGNvcm5lci5cbiAqIEBlbnVtIHtzdHJpbmd9XG4gKi9cbmV4cG9ydCBkZWZhdWx0IHtcbiAgQk9UVE9NX0xFRlQ6ICdib3R0b20tbGVmdCcsXG4gIEJPVFRPTV9SSUdIVDogJ2JvdHRvbS1yaWdodCcsXG4gIFRPUF9MRUZUOiAndG9wLWxlZnQnLFxuICBUT1BfUklHSFQ6ICd0b3AtcmlnaHQnXG59OyIsIi8qKlxuICogQG1vZHVsZSBvbC9leHRlbnQvUmVsYXRpb25zaGlwXG4gKi9cblxuLyoqXG4gKiBSZWxhdGlvbnNoaXAgdG8gYW4gZXh0ZW50LlxuICogQGVudW0ge251bWJlcn1cbiAqL1xuZXhwb3J0IGRlZmF1bHQge1xuICBVTktOT1dOOiAwLFxuICBJTlRFUlNFQ1RJTkc6IDEsXG4gIEFCT1ZFOiAyLFxuICBSSUdIVDogNCxcbiAgQkVMT1c6IDgsXG4gIExFRlQ6IDE2XG59OyIsIi8qKlxuICogQG1vZHVsZSBvbC9leHRlbnRcbiAqL1xuaW1wb3J0IENvcm5lciBmcm9tICcuL2V4dGVudC9Db3JuZXIuanMnO1xuaW1wb3J0IFJlbGF0aW9uc2hpcCBmcm9tICcuL2V4dGVudC9SZWxhdGlvbnNoaXAuanMnO1xuaW1wb3J0IHsgYXNzZXJ0IH0gZnJvbSAnLi9hc3NlcnRzLmpzJztcbi8qKlxuICogQW4gYXJyYXkgb2YgbnVtYmVycyByZXByZXNlbnRpbmcgYW4gZXh0ZW50OiBgW21pbngsIG1pbnksIG1heHgsIG1heHldYC5cbiAqIEB0eXBlZGVmIHtBcnJheTxudW1iZXI+fSBFeHRlbnRcbiAqIEBhcGlcbiAqL1xuXG4vKipcbiAqIEJ1aWxkIGFuIGV4dGVudCB0aGF0IGluY2x1ZGVzIGFsbCBnaXZlbiBjb29yZGluYXRlcy5cbiAqXG4gKiBAcGFyYW0ge0FycmF5PGltcG9ydChcIi4vY29vcmRpbmF0ZS5qc1wiKS5Db29yZGluYXRlPn0gY29vcmRpbmF0ZXMgQ29vcmRpbmF0ZXMuXG4gKiBAcmV0dXJuIHtFeHRlbnR9IEJvdW5kaW5nIGV4dGVudC5cbiAqIEBhcGlcbiAqL1xuXG5leHBvcnQgZnVuY3Rpb24gYm91bmRpbmdFeHRlbnQoY29vcmRpbmF0ZXMpIHtcbiAgdmFyIGV4dGVudCA9IGNyZWF0ZUVtcHR5KCk7XG5cbiAgZm9yICh2YXIgaSA9IDAsIGlpID0gY29vcmRpbmF0ZXMubGVuZ3RoOyBpIDwgaWk7ICsraSkge1xuICAgIGV4dGVuZENvb3JkaW5hdGUoZXh0ZW50LCBjb29yZGluYXRlc1tpXSk7XG4gIH1cblxuICByZXR1cm4gZXh0ZW50O1xufVxuLyoqXG4gKiBAcGFyYW0ge0FycmF5PG51bWJlcj59IHhzIFhzLlxuICogQHBhcmFtIHtBcnJheTxudW1iZXI+fSB5cyBZcy5cbiAqIEBwYXJhbSB7RXh0ZW50PX0gb3B0X2V4dGVudCBEZXN0aW5hdGlvbiBleHRlbnQuXG4gKiBAcHJpdmF0ZVxuICogQHJldHVybiB7RXh0ZW50fSBFeHRlbnQuXG4gKi9cblxuZnVuY3Rpb24gX2JvdW5kaW5nRXh0ZW50WFlzKHhzLCB5cywgb3B0X2V4dGVudCkge1xuICB2YXIgbWluWCA9IE1hdGgubWluLmFwcGx5KG51bGwsIHhzKTtcbiAgdmFyIG1pblkgPSBNYXRoLm1pbi5hcHBseShudWxsLCB5cyk7XG4gIHZhciBtYXhYID0gTWF0aC5tYXguYXBwbHkobnVsbCwgeHMpO1xuICB2YXIgbWF4WSA9IE1hdGgubWF4LmFwcGx5KG51bGwsIHlzKTtcbiAgcmV0dXJuIGNyZWF0ZU9yVXBkYXRlKG1pblgsIG1pblksIG1heFgsIG1heFksIG9wdF9leHRlbnQpO1xufVxuLyoqXG4gKiBSZXR1cm4gZXh0ZW50IGluY3JlYXNlZCBieSB0aGUgcHJvdmlkZWQgdmFsdWUuXG4gKiBAcGFyYW0ge0V4dGVudH0gZXh0ZW50IEV4dGVudC5cbiAqIEBwYXJhbSB7bnVtYmVyfSB2YWx1ZSBUaGUgYW1vdW50IGJ5IHdoaWNoIHRoZSBleHRlbnQgc2hvdWxkIGJlIGJ1ZmZlcmVkLlxuICogQHBhcmFtIHtFeHRlbnQ9fSBvcHRfZXh0ZW50IEV4dGVudC5cbiAqIEByZXR1cm4ge0V4dGVudH0gRXh0ZW50LlxuICogQGFwaVxuICovXG5cblxuZXhwb3J0IGZ1bmN0aW9uIGJ1ZmZlcihleHRlbnQsIHZhbHVlLCBvcHRfZXh0ZW50KSB7XG4gIGlmIChvcHRfZXh0ZW50KSB7XG4gICAgb3B0X2V4dGVudFswXSA9IGV4dGVudFswXSAtIHZhbHVlO1xuICAgIG9wdF9leHRlbnRbMV0gPSBleHRlbnRbMV0gLSB2YWx1ZTtcbiAgICBvcHRfZXh0ZW50WzJdID0gZXh0ZW50WzJdICsgdmFsdWU7XG4gICAgb3B0X2V4dGVudFszXSA9IGV4dGVudFszXSArIHZhbHVlO1xuICAgIHJldHVybiBvcHRfZXh0ZW50O1xuICB9IGVsc2Uge1xuICAgIHJldHVybiBbZXh0ZW50WzBdIC0gdmFsdWUsIGV4dGVudFsxXSAtIHZhbHVlLCBleHRlbnRbMl0gKyB2YWx1ZSwgZXh0ZW50WzNdICsgdmFsdWVdO1xuICB9XG59XG4vKipcbiAqIENyZWF0ZXMgYSBjbG9uZSBvZiBhbiBleHRlbnQuXG4gKlxuICogQHBhcmFtIHtFeHRlbnR9IGV4dGVudCBFeHRlbnQgdG8gY2xvbmUuXG4gKiBAcGFyYW0ge0V4dGVudD19IG9wdF9leHRlbnQgRXh0ZW50LlxuICogQHJldHVybiB7RXh0ZW50fSBUaGUgY2xvbmUuXG4gKi9cblxuZXhwb3J0IGZ1bmN0aW9uIGNsb25lKGV4dGVudCwgb3B0X2V4dGVudCkge1xuICBpZiAob3B0X2V4dGVudCkge1xuICAgIG9wdF9leHRlbnRbMF0gPSBleHRlbnRbMF07XG4gICAgb3B0X2V4dGVudFsxXSA9IGV4dGVudFsxXTtcbiAgICBvcHRfZXh0ZW50WzJdID0gZXh0ZW50WzJdO1xuICAgIG9wdF9leHRlbnRbM10gPSBleHRlbnRbM107XG4gICAgcmV0dXJuIG9wdF9leHRlbnQ7XG4gIH0gZWxzZSB7XG4gICAgcmV0dXJuIGV4dGVudC5zbGljZSgpO1xuICB9XG59XG4vKipcbiAqIEBwYXJhbSB7RXh0ZW50fSBleHRlbnQgRXh0ZW50LlxuICogQHBhcmFtIHtudW1iZXJ9IHggWC5cbiAqIEBwYXJhbSB7bnVtYmVyfSB5IFkuXG4gKiBAcmV0dXJuIHtudW1iZXJ9IENsb3Nlc3Qgc3F1YXJlZCBkaXN0YW5jZS5cbiAqL1xuXG5leHBvcnQgZnVuY3Rpb24gY2xvc2VzdFNxdWFyZWREaXN0YW5jZVhZKGV4dGVudCwgeCwgeSkge1xuICB2YXIgZHgsIGR5O1xuXG4gIGlmICh4IDwgZXh0ZW50WzBdKSB7XG4gICAgZHggPSBleHRlbnRbMF0gLSB4O1xuICB9IGVsc2UgaWYgKGV4dGVudFsyXSA8IHgpIHtcbiAgICBkeCA9IHggLSBleHRlbnRbMl07XG4gIH0gZWxzZSB7XG4gICAgZHggPSAwO1xuICB9XG5cbiAgaWYgKHkgPCBleHRlbnRbMV0pIHtcbiAgICBkeSA9IGV4dGVudFsxXSAtIHk7XG4gIH0gZWxzZSBpZiAoZXh0ZW50WzNdIDwgeSkge1xuICAgIGR5ID0geSAtIGV4dGVudFszXTtcbiAgfSBlbHNlIHtcbiAgICBkeSA9IDA7XG4gIH1cblxuICByZXR1cm4gZHggKiBkeCArIGR5ICogZHk7XG59XG4vKipcbiAqIENoZWNrIGlmIHRoZSBwYXNzZWQgY29vcmRpbmF0ZSBpcyBjb250YWluZWQgb3Igb24gdGhlIGVkZ2Ugb2YgdGhlIGV4dGVudC5cbiAqXG4gKiBAcGFyYW0ge0V4dGVudH0gZXh0ZW50IEV4dGVudC5cbiAqIEBwYXJhbSB7aW1wb3J0KFwiLi9jb29yZGluYXRlLmpzXCIpLkNvb3JkaW5hdGV9IGNvb3JkaW5hdGUgQ29vcmRpbmF0ZS5cbiAqIEByZXR1cm4ge2Jvb2xlYW59IFRoZSBjb29yZGluYXRlIGlzIGNvbnRhaW5lZCBpbiB0aGUgZXh0ZW50LlxuICogQGFwaVxuICovXG5cbmV4cG9ydCBmdW5jdGlvbiBjb250YWluc0Nvb3JkaW5hdGUoZXh0ZW50LCBjb29yZGluYXRlKSB7XG4gIHJldHVybiBjb250YWluc1hZKGV4dGVudCwgY29vcmRpbmF0ZVswXSwgY29vcmRpbmF0ZVsxXSk7XG59XG4vKipcbiAqIENoZWNrIGlmIG9uZSBleHRlbnQgY29udGFpbnMgYW5vdGhlci5cbiAqXG4gKiBBbiBleHRlbnQgaXMgZGVlbWVkIGNvbnRhaW5lZCBpZiBpdCBsaWVzIGNvbXBsZXRlbHkgd2l0aGluIHRoZSBvdGhlciBleHRlbnQsXG4gKiBpbmNsdWRpbmcgaWYgdGhleSBzaGFyZSBvbmUgb3IgbW9yZSBlZGdlcy5cbiAqXG4gKiBAcGFyYW0ge0V4dGVudH0gZXh0ZW50MSBFeHRlbnQgMS5cbiAqIEBwYXJhbSB7RXh0ZW50fSBleHRlbnQyIEV4dGVudCAyLlxuICogQHJldHVybiB7Ym9vbGVhbn0gVGhlIHNlY29uZCBleHRlbnQgaXMgY29udGFpbmVkIGJ5IG9yIG9uIHRoZSBlZGdlIG9mIHRoZVxuICogICAgIGZpcnN0LlxuICogQGFwaVxuICovXG5cbmV4cG9ydCBmdW5jdGlvbiBjb250YWluc0V4dGVudChleHRlbnQxLCBleHRlbnQyKSB7XG4gIHJldHVybiBleHRlbnQxWzBdIDw9IGV4dGVudDJbMF0gJiYgZXh0ZW50MlsyXSA8PSBleHRlbnQxWzJdICYmIGV4dGVudDFbMV0gPD0gZXh0ZW50MlsxXSAmJiBleHRlbnQyWzNdIDw9IGV4dGVudDFbM107XG59XG4vKipcbiAqIENoZWNrIGlmIHRoZSBwYXNzZWQgY29vcmRpbmF0ZSBpcyBjb250YWluZWQgb3Igb24gdGhlIGVkZ2Ugb2YgdGhlIGV4dGVudC5cbiAqXG4gKiBAcGFyYW0ge0V4dGVudH0gZXh0ZW50IEV4dGVudC5cbiAqIEBwYXJhbSB7bnVtYmVyfSB4IFggY29vcmRpbmF0ZS5cbiAqIEBwYXJhbSB7bnVtYmVyfSB5IFkgY29vcmRpbmF0ZS5cbiAqIEByZXR1cm4ge2Jvb2xlYW59IFRoZSB4LCB5IHZhbHVlcyBhcmUgY29udGFpbmVkIGluIHRoZSBleHRlbnQuXG4gKiBAYXBpXG4gKi9cblxuZXhwb3J0IGZ1bmN0aW9uIGNvbnRhaW5zWFkoZXh0ZW50LCB4LCB5KSB7XG4gIHJldHVybiBleHRlbnRbMF0gPD0geCAmJiB4IDw9IGV4dGVudFsyXSAmJiBleHRlbnRbMV0gPD0geSAmJiB5IDw9IGV4dGVudFszXTtcbn1cbi8qKlxuICogR2V0IHRoZSByZWxhdGlvbnNoaXAgYmV0d2VlbiBhIGNvb3JkaW5hdGUgYW5kIGV4dGVudC5cbiAqIEBwYXJhbSB7RXh0ZW50fSBleHRlbnQgVGhlIGV4dGVudC5cbiAqIEBwYXJhbSB7aW1wb3J0KFwiLi9jb29yZGluYXRlLmpzXCIpLkNvb3JkaW5hdGV9IGNvb3JkaW5hdGUgVGhlIGNvb3JkaW5hdGUuXG4gKiBAcmV0dXJuIHtpbXBvcnQoXCIuL2V4dGVudC9SZWxhdGlvbnNoaXAuanNcIikuZGVmYXVsdH0gVGhlIHJlbGF0aW9uc2hpcCAoYml0d2lzZSBjb21wYXJlIHdpdGhcbiAqICAgICBpbXBvcnQoXCIuL2V4dGVudC9SZWxhdGlvbnNoaXAuanNcIikuUmVsYXRpb25zaGlwKS5cbiAqL1xuXG5leHBvcnQgZnVuY3Rpb24gY29vcmRpbmF0ZVJlbGF0aW9uc2hpcChleHRlbnQsIGNvb3JkaW5hdGUpIHtcbiAgdmFyIG1pblggPSBleHRlbnRbMF07XG4gIHZhciBtaW5ZID0gZXh0ZW50WzFdO1xuICB2YXIgbWF4WCA9IGV4dGVudFsyXTtcbiAgdmFyIG1heFkgPSBleHRlbnRbM107XG4gIHZhciB4ID0gY29vcmRpbmF0ZVswXTtcbiAgdmFyIHkgPSBjb29yZGluYXRlWzFdO1xuICB2YXIgcmVsYXRpb25zaGlwID0gUmVsYXRpb25zaGlwLlVOS05PV047XG5cbiAgaWYgKHggPCBtaW5YKSB7XG4gICAgcmVsYXRpb25zaGlwID0gcmVsYXRpb25zaGlwIHwgUmVsYXRpb25zaGlwLkxFRlQ7XG4gIH0gZWxzZSBpZiAoeCA+IG1heFgpIHtcbiAgICByZWxhdGlvbnNoaXAgPSByZWxhdGlvbnNoaXAgfCBSZWxhdGlvbnNoaXAuUklHSFQ7XG4gIH1cblxuICBpZiAoeSA8IG1pblkpIHtcbiAgICByZWxhdGlvbnNoaXAgPSByZWxhdGlvbnNoaXAgfCBSZWxhdGlvbnNoaXAuQkVMT1c7XG4gIH0gZWxzZSBpZiAoeSA+IG1heFkpIHtcbiAgICByZWxhdGlvbnNoaXAgPSByZWxhdGlvbnNoaXAgfCBSZWxhdGlvbnNoaXAuQUJPVkU7XG4gIH1cblxuICBpZiAocmVsYXRpb25zaGlwID09PSBSZWxhdGlvbnNoaXAuVU5LTk9XTikge1xuICAgIHJlbGF0aW9uc2hpcCA9IFJlbGF0aW9uc2hpcC5JTlRFUlNFQ1RJTkc7XG4gIH1cblxuICByZXR1cm4gcmVsYXRpb25zaGlwO1xufVxuLyoqXG4gKiBDcmVhdGUgYW4gZW1wdHkgZXh0ZW50LlxuICogQHJldHVybiB7RXh0ZW50fSBFbXB0eSBleHRlbnQuXG4gKiBAYXBpXG4gKi9cblxuZXhwb3J0IGZ1bmN0aW9uIGNyZWF0ZUVtcHR5KCkge1xuICByZXR1cm4gW0luZmluaXR5LCBJbmZpbml0eSwgLUluZmluaXR5LCAtSW5maW5pdHldO1xufVxuLyoqXG4gKiBDcmVhdGUgYSBuZXcgZXh0ZW50IG9yIHVwZGF0ZSB0aGUgcHJvdmlkZWQgZXh0ZW50LlxuICogQHBhcmFtIHtudW1iZXJ9IG1pblggTWluaW11bSBYLlxuICogQHBhcmFtIHtudW1iZXJ9IG1pblkgTWluaW11bSBZLlxuICogQHBhcmFtIHtudW1iZXJ9IG1heFggTWF4aW11bSBYLlxuICogQHBhcmFtIHtudW1iZXJ9IG1heFkgTWF4aW11bSBZLlxuICogQHBhcmFtIHtFeHRlbnQ9fSBvcHRfZXh0ZW50IERlc3RpbmF0aW9uIGV4dGVudC5cbiAqIEByZXR1cm4ge0V4dGVudH0gRXh0ZW50LlxuICovXG5cbmV4cG9ydCBmdW5jdGlvbiBjcmVhdGVPclVwZGF0ZShtaW5YLCBtaW5ZLCBtYXhYLCBtYXhZLCBvcHRfZXh0ZW50KSB7XG4gIGlmIChvcHRfZXh0ZW50KSB7XG4gICAgb3B0X2V4dGVudFswXSA9IG1pblg7XG4gICAgb3B0X2V4dGVudFsxXSA9IG1pblk7XG4gICAgb3B0X2V4dGVudFsyXSA9IG1heFg7XG4gICAgb3B0X2V4dGVudFszXSA9IG1heFk7XG4gICAgcmV0dXJuIG9wdF9leHRlbnQ7XG4gIH0gZWxzZSB7XG4gICAgcmV0dXJuIFttaW5YLCBtaW5ZLCBtYXhYLCBtYXhZXTtcbiAgfVxufVxuLyoqXG4gKiBDcmVhdGUgYSBuZXcgZW1wdHkgZXh0ZW50IG9yIG1ha2UgdGhlIHByb3ZpZGVkIG9uZSBlbXB0eS5cbiAqIEBwYXJhbSB7RXh0ZW50PX0gb3B0X2V4dGVudCBFeHRlbnQuXG4gKiBAcmV0dXJuIHtFeHRlbnR9IEV4dGVudC5cbiAqL1xuXG5leHBvcnQgZnVuY3Rpb24gY3JlYXRlT3JVcGRhdGVFbXB0eShvcHRfZXh0ZW50KSB7XG4gIHJldHVybiBjcmVhdGVPclVwZGF0ZShJbmZpbml0eSwgSW5maW5pdHksIC1JbmZpbml0eSwgLUluZmluaXR5LCBvcHRfZXh0ZW50KTtcbn1cbi8qKlxuICogQHBhcmFtIHtpbXBvcnQoXCIuL2Nvb3JkaW5hdGUuanNcIikuQ29vcmRpbmF0ZX0gY29vcmRpbmF0ZSBDb29yZGluYXRlLlxuICogQHBhcmFtIHtFeHRlbnQ9fSBvcHRfZXh0ZW50IEV4dGVudC5cbiAqIEByZXR1cm4ge0V4dGVudH0gRXh0ZW50LlxuICovXG5cbmV4cG9ydCBmdW5jdGlvbiBjcmVhdGVPclVwZGF0ZUZyb21Db29yZGluYXRlKGNvb3JkaW5hdGUsIG9wdF9leHRlbnQpIHtcbiAgdmFyIHggPSBjb29yZGluYXRlWzBdO1xuICB2YXIgeSA9IGNvb3JkaW5hdGVbMV07XG4gIHJldHVybiBjcmVhdGVPclVwZGF0ZSh4LCB5LCB4LCB5LCBvcHRfZXh0ZW50KTtcbn1cbi8qKlxuICogQHBhcmFtIHtBcnJheTxpbXBvcnQoXCIuL2Nvb3JkaW5hdGUuanNcIikuQ29vcmRpbmF0ZT59IGNvb3JkaW5hdGVzIENvb3JkaW5hdGVzLlxuICogQHBhcmFtIHtFeHRlbnQ9fSBvcHRfZXh0ZW50IEV4dGVudC5cbiAqIEByZXR1cm4ge0V4dGVudH0gRXh0ZW50LlxuICovXG5cbmV4cG9ydCBmdW5jdGlvbiBjcmVhdGVPclVwZGF0ZUZyb21Db29yZGluYXRlcyhjb29yZGluYXRlcywgb3B0X2V4dGVudCkge1xuICB2YXIgZXh0ZW50ID0gY3JlYXRlT3JVcGRhdGVFbXB0eShvcHRfZXh0ZW50KTtcbiAgcmV0dXJuIGV4dGVuZENvb3JkaW5hdGVzKGV4dGVudCwgY29vcmRpbmF0ZXMpO1xufVxuLyoqXG4gKiBAcGFyYW0ge0FycmF5PG51bWJlcj59IGZsYXRDb29yZGluYXRlcyBGbGF0IGNvb3JkaW5hdGVzLlxuICogQHBhcmFtIHtudW1iZXJ9IG9mZnNldCBPZmZzZXQuXG4gKiBAcGFyYW0ge251bWJlcn0gZW5kIEVuZC5cbiAqIEBwYXJhbSB7bnVtYmVyfSBzdHJpZGUgU3RyaWRlLlxuICogQHBhcmFtIHtFeHRlbnQ9fSBvcHRfZXh0ZW50IEV4dGVudC5cbiAqIEByZXR1cm4ge0V4dGVudH0gRXh0ZW50LlxuICovXG5cbmV4cG9ydCBmdW5jdGlvbiBjcmVhdGVPclVwZGF0ZUZyb21GbGF0Q29vcmRpbmF0ZXMoZmxhdENvb3JkaW5hdGVzLCBvZmZzZXQsIGVuZCwgc3RyaWRlLCBvcHRfZXh0ZW50KSB7XG4gIHZhciBleHRlbnQgPSBjcmVhdGVPclVwZGF0ZUVtcHR5KG9wdF9leHRlbnQpO1xuICByZXR1cm4gZXh0ZW5kRmxhdENvb3JkaW5hdGVzKGV4dGVudCwgZmxhdENvb3JkaW5hdGVzLCBvZmZzZXQsIGVuZCwgc3RyaWRlKTtcbn1cbi8qKlxuICogQHBhcmFtIHtBcnJheTxBcnJheTxpbXBvcnQoXCIuL2Nvb3JkaW5hdGUuanNcIikuQ29vcmRpbmF0ZT4+fSByaW5ncyBSaW5ncy5cbiAqIEBwYXJhbSB7RXh0ZW50PX0gb3B0X2V4dGVudCBFeHRlbnQuXG4gKiBAcmV0dXJuIHtFeHRlbnR9IEV4dGVudC5cbiAqL1xuXG5leHBvcnQgZnVuY3Rpb24gY3JlYXRlT3JVcGRhdGVGcm9tUmluZ3MocmluZ3MsIG9wdF9leHRlbnQpIHtcbiAgdmFyIGV4dGVudCA9IGNyZWF0ZU9yVXBkYXRlRW1wdHkob3B0X2V4dGVudCk7XG4gIHJldHVybiBleHRlbmRSaW5ncyhleHRlbnQsIHJpbmdzKTtcbn1cbi8qKlxuICogRGV0ZXJtaW5lIGlmIHR3byBleHRlbnRzIGFyZSBlcXVpdmFsZW50LlxuICogQHBhcmFtIHtFeHRlbnR9IGV4dGVudDEgRXh0ZW50IDEuXG4gKiBAcGFyYW0ge0V4dGVudH0gZXh0ZW50MiBFeHRlbnQgMi5cbiAqIEByZXR1cm4ge2Jvb2xlYW59IFRoZSB0d28gZXh0ZW50cyBhcmUgZXF1aXZhbGVudC5cbiAqIEBhcGlcbiAqL1xuXG5leHBvcnQgZnVuY3Rpb24gZXF1YWxzKGV4dGVudDEsIGV4dGVudDIpIHtcbiAgcmV0dXJuIGV4dGVudDFbMF0gPT0gZXh0ZW50MlswXSAmJiBleHRlbnQxWzJdID09IGV4dGVudDJbMl0gJiYgZXh0ZW50MVsxXSA9PSBleHRlbnQyWzFdICYmIGV4dGVudDFbM10gPT0gZXh0ZW50MlszXTtcbn1cbi8qKlxuICogRGV0ZXJtaW5lIGlmIHR3byBleHRlbnRzIGFyZSBhcHByb3hpbWF0ZWx5IGVxdWl2YWxlbnQuXG4gKiBAcGFyYW0ge0V4dGVudH0gZXh0ZW50MSBFeHRlbnQgMS5cbiAqIEBwYXJhbSB7RXh0ZW50fSBleHRlbnQyIEV4dGVudCAyLlxuICogQHBhcmFtIHtudW1iZXJ9IHRvbGVyYW5jZSBUb2xlcmFuY2UgaW4gZXh0ZW50IGNvb3JkaW5hdGUgdW5pdHMuXG4gKiBAcmV0dXJuIHtib29sZWFufSBUaGUgdHdvIGV4dGVudHMgZGlmZmVyIGJ5IGxlc3MgdGhhbiB0aGUgdG9sZXJhbmNlLlxuICovXG5cbmV4cG9ydCBmdW5jdGlvbiBhcHByb3hpbWF0ZWx5RXF1YWxzKGV4dGVudDEsIGV4dGVudDIsIHRvbGVyYW5jZSkge1xuICByZXR1cm4gTWF0aC5hYnMoZXh0ZW50MVswXSAtIGV4dGVudDJbMF0pIDwgdG9sZXJhbmNlICYmIE1hdGguYWJzKGV4dGVudDFbMl0gLSBleHRlbnQyWzJdKSA8IHRvbGVyYW5jZSAmJiBNYXRoLmFicyhleHRlbnQxWzFdIC0gZXh0ZW50MlsxXSkgPCB0b2xlcmFuY2UgJiYgTWF0aC5hYnMoZXh0ZW50MVszXSAtIGV4dGVudDJbM10pIDwgdG9sZXJhbmNlO1xufVxuLyoqXG4gKiBNb2RpZnkgYW4gZXh0ZW50IHRvIGluY2x1ZGUgYW5vdGhlciBleHRlbnQuXG4gKiBAcGFyYW0ge0V4dGVudH0gZXh0ZW50MSBUaGUgZXh0ZW50IHRvIGJlIG1vZGlmaWVkLlxuICogQHBhcmFtIHtFeHRlbnR9IGV4dGVudDIgVGhlIGV4dGVudCB0aGF0IHdpbGwgYmUgaW5jbHVkZWQgaW4gdGhlIGZpcnN0LlxuICogQHJldHVybiB7RXh0ZW50fSBBIHJlZmVyZW5jZSB0byB0aGUgZmlyc3QgKGV4dGVuZGVkKSBleHRlbnQuXG4gKiBAYXBpXG4gKi9cblxuZXhwb3J0IGZ1bmN0aW9uIGV4dGVuZChleHRlbnQxLCBleHRlbnQyKSB7XG4gIGlmIChleHRlbnQyWzBdIDwgZXh0ZW50MVswXSkge1xuICAgIGV4dGVudDFbMF0gPSBleHRlbnQyWzBdO1xuICB9XG5cbiAgaWYgKGV4dGVudDJbMl0gPiBleHRlbnQxWzJdKSB7XG4gICAgZXh0ZW50MVsyXSA9IGV4dGVudDJbMl07XG4gIH1cblxuICBpZiAoZXh0ZW50MlsxXSA8IGV4dGVudDFbMV0pIHtcbiAgICBleHRlbnQxWzFdID0gZXh0ZW50MlsxXTtcbiAgfVxuXG4gIGlmIChleHRlbnQyWzNdID4gZXh0ZW50MVszXSkge1xuICAgIGV4dGVudDFbM10gPSBleHRlbnQyWzNdO1xuICB9XG5cbiAgcmV0dXJuIGV4dGVudDE7XG59XG4vKipcbiAqIEBwYXJhbSB7RXh0ZW50fSBleHRlbnQgRXh0ZW50LlxuICogQHBhcmFtIHtpbXBvcnQoXCIuL2Nvb3JkaW5hdGUuanNcIikuQ29vcmRpbmF0ZX0gY29vcmRpbmF0ZSBDb29yZGluYXRlLlxuICovXG5cbmV4cG9ydCBmdW5jdGlvbiBleHRlbmRDb29yZGluYXRlKGV4dGVudCwgY29vcmRpbmF0ZSkge1xuICBpZiAoY29vcmRpbmF0ZVswXSA8IGV4dGVudFswXSkge1xuICAgIGV4dGVudFswXSA9IGNvb3JkaW5hdGVbMF07XG4gIH1cblxuICBpZiAoY29vcmRpbmF0ZVswXSA+IGV4dGVudFsyXSkge1xuICAgIGV4dGVudFsyXSA9IGNvb3JkaW5hdGVbMF07XG4gIH1cblxuICBpZiAoY29vcmRpbmF0ZVsxXSA8IGV4dGVudFsxXSkge1xuICAgIGV4dGVudFsxXSA9IGNvb3JkaW5hdGVbMV07XG4gIH1cblxuICBpZiAoY29vcmRpbmF0ZVsxXSA+IGV4dGVudFszXSkge1xuICAgIGV4dGVudFszXSA9IGNvb3JkaW5hdGVbMV07XG4gIH1cbn1cbi8qKlxuICogQHBhcmFtIHtFeHRlbnR9IGV4dGVudCBFeHRlbnQuXG4gKiBAcGFyYW0ge0FycmF5PGltcG9ydChcIi4vY29vcmRpbmF0ZS5qc1wiKS5Db29yZGluYXRlPn0gY29vcmRpbmF0ZXMgQ29vcmRpbmF0ZXMuXG4gKiBAcmV0dXJuIHtFeHRlbnR9IEV4dGVudC5cbiAqL1xuXG5leHBvcnQgZnVuY3Rpb24gZXh0ZW5kQ29vcmRpbmF0ZXMoZXh0ZW50LCBjb29yZGluYXRlcykge1xuICBmb3IgKHZhciBpID0gMCwgaWkgPSBjb29yZGluYXRlcy5sZW5ndGg7IGkgPCBpaTsgKytpKSB7XG4gICAgZXh0ZW5kQ29vcmRpbmF0ZShleHRlbnQsIGNvb3JkaW5hdGVzW2ldKTtcbiAgfVxuXG4gIHJldHVybiBleHRlbnQ7XG59XG4vKipcbiAqIEBwYXJhbSB7RXh0ZW50fSBleHRlbnQgRXh0ZW50LlxuICogQHBhcmFtIHtBcnJheTxudW1iZXI+fSBmbGF0Q29vcmRpbmF0ZXMgRmxhdCBjb29yZGluYXRlcy5cbiAqIEBwYXJhbSB7bnVtYmVyfSBvZmZzZXQgT2Zmc2V0LlxuICogQHBhcmFtIHtudW1iZXJ9IGVuZCBFbmQuXG4gKiBAcGFyYW0ge251bWJlcn0gc3RyaWRlIFN0cmlkZS5cbiAqIEByZXR1cm4ge0V4dGVudH0gRXh0ZW50LlxuICovXG5cbmV4cG9ydCBmdW5jdGlvbiBleHRlbmRGbGF0Q29vcmRpbmF0ZXMoZXh0ZW50LCBmbGF0Q29vcmRpbmF0ZXMsIG9mZnNldCwgZW5kLCBzdHJpZGUpIHtcbiAgZm9yICg7IG9mZnNldCA8IGVuZDsgb2Zmc2V0ICs9IHN0cmlkZSkge1xuICAgIGV4dGVuZFhZKGV4dGVudCwgZmxhdENvb3JkaW5hdGVzW29mZnNldF0sIGZsYXRDb29yZGluYXRlc1tvZmZzZXQgKyAxXSk7XG4gIH1cblxuICByZXR1cm4gZXh0ZW50O1xufVxuLyoqXG4gKiBAcGFyYW0ge0V4dGVudH0gZXh0ZW50IEV4dGVudC5cbiAqIEBwYXJhbSB7QXJyYXk8QXJyYXk8aW1wb3J0KFwiLi9jb29yZGluYXRlLmpzXCIpLkNvb3JkaW5hdGU+Pn0gcmluZ3MgUmluZ3MuXG4gKiBAcmV0dXJuIHtFeHRlbnR9IEV4dGVudC5cbiAqL1xuXG5leHBvcnQgZnVuY3Rpb24gZXh0ZW5kUmluZ3MoZXh0ZW50LCByaW5ncykge1xuICBmb3IgKHZhciBpID0gMCwgaWkgPSByaW5ncy5sZW5ndGg7IGkgPCBpaTsgKytpKSB7XG4gICAgZXh0ZW5kQ29vcmRpbmF0ZXMoZXh0ZW50LCByaW5nc1tpXSk7XG4gIH1cblxuICByZXR1cm4gZXh0ZW50O1xufVxuLyoqXG4gKiBAcGFyYW0ge0V4dGVudH0gZXh0ZW50IEV4dGVudC5cbiAqIEBwYXJhbSB7bnVtYmVyfSB4IFguXG4gKiBAcGFyYW0ge251bWJlcn0geSBZLlxuICovXG5cbmV4cG9ydCBmdW5jdGlvbiBleHRlbmRYWShleHRlbnQsIHgsIHkpIHtcbiAgZXh0ZW50WzBdID0gTWF0aC5taW4oZXh0ZW50WzBdLCB4KTtcbiAgZXh0ZW50WzFdID0gTWF0aC5taW4oZXh0ZW50WzFdLCB5KTtcbiAgZXh0ZW50WzJdID0gTWF0aC5tYXgoZXh0ZW50WzJdLCB4KTtcbiAgZXh0ZW50WzNdID0gTWF0aC5tYXgoZXh0ZW50WzNdLCB5KTtcbn1cbi8qKlxuICogVGhpcyBmdW5jdGlvbiBjYWxscyBgY2FsbGJhY2tgIGZvciBlYWNoIGNvcm5lciBvZiB0aGUgZXh0ZW50LiBJZiB0aGVcbiAqIGNhbGxiYWNrIHJldHVybnMgYSB0cnV0aHkgdmFsdWUgdGhlIGZ1bmN0aW9uIHJldHVybnMgdGhhdCB2YWx1ZVxuICogaW1tZWRpYXRlbHkuIE90aGVyd2lzZSB0aGUgZnVuY3Rpb24gcmV0dXJucyBgZmFsc2VgLlxuICogQHBhcmFtIHtFeHRlbnR9IGV4dGVudCBFeHRlbnQuXG4gKiBAcGFyYW0ge2Z1bmN0aW9uKGltcG9ydChcIi4vY29vcmRpbmF0ZS5qc1wiKS5Db29yZGluYXRlKTogU30gY2FsbGJhY2sgQ2FsbGJhY2suXG4gKiBAcmV0dXJuIHtTfGJvb2xlYW59IFZhbHVlLlxuICogQHRlbXBsYXRlIFNcbiAqL1xuXG5leHBvcnQgZnVuY3Rpb24gZm9yRWFjaENvcm5lcihleHRlbnQsIGNhbGxiYWNrKSB7XG4gIHZhciB2YWw7XG4gIHZhbCA9IGNhbGxiYWNrKGdldEJvdHRvbUxlZnQoZXh0ZW50KSk7XG5cbiAgaWYgKHZhbCkge1xuICAgIHJldHVybiB2YWw7XG4gIH1cblxuICB2YWwgPSBjYWxsYmFjayhnZXRCb3R0b21SaWdodChleHRlbnQpKTtcblxuICBpZiAodmFsKSB7XG4gICAgcmV0dXJuIHZhbDtcbiAgfVxuXG4gIHZhbCA9IGNhbGxiYWNrKGdldFRvcFJpZ2h0KGV4dGVudCkpO1xuXG4gIGlmICh2YWwpIHtcbiAgICByZXR1cm4gdmFsO1xuICB9XG5cbiAgdmFsID0gY2FsbGJhY2soZ2V0VG9wTGVmdChleHRlbnQpKTtcblxuICBpZiAodmFsKSB7XG4gICAgcmV0dXJuIHZhbDtcbiAgfVxuXG4gIHJldHVybiBmYWxzZTtcbn1cbi8qKlxuICogR2V0IHRoZSBzaXplIG9mIGFuIGV4dGVudC5cbiAqIEBwYXJhbSB7RXh0ZW50fSBleHRlbnQgRXh0ZW50LlxuICogQHJldHVybiB7bnVtYmVyfSBBcmVhLlxuICogQGFwaVxuICovXG5cbmV4cG9ydCBmdW5jdGlvbiBnZXRBcmVhKGV4dGVudCkge1xuICB2YXIgYXJlYSA9IDA7XG5cbiAgaWYgKCFpc0VtcHR5KGV4dGVudCkpIHtcbiAgICBhcmVhID0gZ2V0V2lkdGgoZXh0ZW50KSAqIGdldEhlaWdodChleHRlbnQpO1xuICB9XG5cbiAgcmV0dXJuIGFyZWE7XG59XG4vKipcbiAqIEdldCB0aGUgYm90dG9tIGxlZnQgY29vcmRpbmF0ZSBvZiBhbiBleHRlbnQuXG4gKiBAcGFyYW0ge0V4dGVudH0gZXh0ZW50IEV4dGVudC5cbiAqIEByZXR1cm4ge2ltcG9ydChcIi4vY29vcmRpbmF0ZS5qc1wiKS5Db29yZGluYXRlfSBCb3R0b20gbGVmdCBjb29yZGluYXRlLlxuICogQGFwaVxuICovXG5cbmV4cG9ydCBmdW5jdGlvbiBnZXRCb3R0b21MZWZ0KGV4dGVudCkge1xuICByZXR1cm4gW2V4dGVudFswXSwgZXh0ZW50WzFdXTtcbn1cbi8qKlxuICogR2V0IHRoZSBib3R0b20gcmlnaHQgY29vcmRpbmF0ZSBvZiBhbiBleHRlbnQuXG4gKiBAcGFyYW0ge0V4dGVudH0gZXh0ZW50IEV4dGVudC5cbiAqIEByZXR1cm4ge2ltcG9ydChcIi4vY29vcmRpbmF0ZS5qc1wiKS5Db29yZGluYXRlfSBCb3R0b20gcmlnaHQgY29vcmRpbmF0ZS5cbiAqIEBhcGlcbiAqL1xuXG5leHBvcnQgZnVuY3Rpb24gZ2V0Qm90dG9tUmlnaHQoZXh0ZW50KSB7XG4gIHJldHVybiBbZXh0ZW50WzJdLCBleHRlbnRbMV1dO1xufVxuLyoqXG4gKiBHZXQgdGhlIGNlbnRlciBjb29yZGluYXRlIG9mIGFuIGV4dGVudC5cbiAqIEBwYXJhbSB7RXh0ZW50fSBleHRlbnQgRXh0ZW50LlxuICogQHJldHVybiB7aW1wb3J0KFwiLi9jb29yZGluYXRlLmpzXCIpLkNvb3JkaW5hdGV9IENlbnRlci5cbiAqIEBhcGlcbiAqL1xuXG5leHBvcnQgZnVuY3Rpb24gZ2V0Q2VudGVyKGV4dGVudCkge1xuICByZXR1cm4gWyhleHRlbnRbMF0gKyBleHRlbnRbMl0pIC8gMiwgKGV4dGVudFsxXSArIGV4dGVudFszXSkgLyAyXTtcbn1cbi8qKlxuICogR2V0IGEgY29ybmVyIGNvb3JkaW5hdGUgb2YgYW4gZXh0ZW50LlxuICogQHBhcmFtIHtFeHRlbnR9IGV4dGVudCBFeHRlbnQuXG4gKiBAcGFyYW0ge2ltcG9ydChcIi4vZXh0ZW50L0Nvcm5lci5qc1wiKS5kZWZhdWx0fSBjb3JuZXIgQ29ybmVyLlxuICogQHJldHVybiB7aW1wb3J0KFwiLi9jb29yZGluYXRlLmpzXCIpLkNvb3JkaW5hdGV9IENvcm5lciBjb29yZGluYXRlLlxuICovXG5cbmV4cG9ydCBmdW5jdGlvbiBnZXRDb3JuZXIoZXh0ZW50LCBjb3JuZXIpIHtcbiAgdmFyIGNvb3JkaW5hdGU7XG5cbiAgaWYgKGNvcm5lciA9PT0gQ29ybmVyLkJPVFRPTV9MRUZUKSB7XG4gICAgY29vcmRpbmF0ZSA9IGdldEJvdHRvbUxlZnQoZXh0ZW50KTtcbiAgfSBlbHNlIGlmIChjb3JuZXIgPT09IENvcm5lci5CT1RUT01fUklHSFQpIHtcbiAgICBjb29yZGluYXRlID0gZ2V0Qm90dG9tUmlnaHQoZXh0ZW50KTtcbiAgfSBlbHNlIGlmIChjb3JuZXIgPT09IENvcm5lci5UT1BfTEVGVCkge1xuICAgIGNvb3JkaW5hdGUgPSBnZXRUb3BMZWZ0KGV4dGVudCk7XG4gIH0gZWxzZSBpZiAoY29ybmVyID09PSBDb3JuZXIuVE9QX1JJR0hUKSB7XG4gICAgY29vcmRpbmF0ZSA9IGdldFRvcFJpZ2h0KGV4dGVudCk7XG4gIH0gZWxzZSB7XG4gICAgYXNzZXJ0KGZhbHNlLCAxMyk7IC8vIEludmFsaWQgY29ybmVyXG4gIH1cblxuICByZXR1cm4gY29vcmRpbmF0ZTtcbn1cbi8qKlxuICogQHBhcmFtIHtFeHRlbnR9IGV4dGVudDEgRXh0ZW50IDEuXG4gKiBAcGFyYW0ge0V4dGVudH0gZXh0ZW50MiBFeHRlbnQgMi5cbiAqIEByZXR1cm4ge251bWJlcn0gRW5sYXJnZWQgYXJlYS5cbiAqL1xuXG5leHBvcnQgZnVuY3Rpb24gZ2V0RW5sYXJnZWRBcmVhKGV4dGVudDEsIGV4dGVudDIpIHtcbiAgdmFyIG1pblggPSBNYXRoLm1pbihleHRlbnQxWzBdLCBleHRlbnQyWzBdKTtcbiAgdmFyIG1pblkgPSBNYXRoLm1pbihleHRlbnQxWzFdLCBleHRlbnQyWzFdKTtcbiAgdmFyIG1heFggPSBNYXRoLm1heChleHRlbnQxWzJdLCBleHRlbnQyWzJdKTtcbiAgdmFyIG1heFkgPSBNYXRoLm1heChleHRlbnQxWzNdLCBleHRlbnQyWzNdKTtcbiAgcmV0dXJuIChtYXhYIC0gbWluWCkgKiAobWF4WSAtIG1pblkpO1xufVxuLyoqXG4gKiBAcGFyYW0ge2ltcG9ydChcIi4vY29vcmRpbmF0ZS5qc1wiKS5Db29yZGluYXRlfSBjZW50ZXIgQ2VudGVyLlxuICogQHBhcmFtIHtudW1iZXJ9IHJlc29sdXRpb24gUmVzb2x1dGlvbi5cbiAqIEBwYXJhbSB7bnVtYmVyfSByb3RhdGlvbiBSb3RhdGlvbi5cbiAqIEBwYXJhbSB7aW1wb3J0KFwiLi9zaXplLmpzXCIpLlNpemV9IHNpemUgU2l6ZS5cbiAqIEBwYXJhbSB7RXh0ZW50PX0gb3B0X2V4dGVudCBEZXN0aW5hdGlvbiBleHRlbnQuXG4gKiBAcmV0dXJuIHtFeHRlbnR9IEV4dGVudC5cbiAqL1xuXG5leHBvcnQgZnVuY3Rpb24gZ2V0Rm9yVmlld0FuZFNpemUoY2VudGVyLCByZXNvbHV0aW9uLCByb3RhdGlvbiwgc2l6ZSwgb3B0X2V4dGVudCkge1xuICB2YXIgZHggPSByZXNvbHV0aW9uICogc2l6ZVswXSAvIDI7XG4gIHZhciBkeSA9IHJlc29sdXRpb24gKiBzaXplWzFdIC8gMjtcbiAgdmFyIGNvc1JvdGF0aW9uID0gTWF0aC5jb3Mocm90YXRpb24pO1xuICB2YXIgc2luUm90YXRpb24gPSBNYXRoLnNpbihyb3RhdGlvbik7XG4gIHZhciB4Q29zID0gZHggKiBjb3NSb3RhdGlvbjtcbiAgdmFyIHhTaW4gPSBkeCAqIHNpblJvdGF0aW9uO1xuICB2YXIgeUNvcyA9IGR5ICogY29zUm90YXRpb247XG4gIHZhciB5U2luID0gZHkgKiBzaW5Sb3RhdGlvbjtcbiAgdmFyIHggPSBjZW50ZXJbMF07XG4gIHZhciB5ID0gY2VudGVyWzFdO1xuICB2YXIgeDAgPSB4IC0geENvcyArIHlTaW47XG4gIHZhciB4MSA9IHggLSB4Q29zIC0geVNpbjtcbiAgdmFyIHgyID0geCArIHhDb3MgLSB5U2luO1xuICB2YXIgeDMgPSB4ICsgeENvcyArIHlTaW47XG4gIHZhciB5MCA9IHkgLSB4U2luIC0geUNvcztcbiAgdmFyIHkxID0geSAtIHhTaW4gKyB5Q29zO1xuICB2YXIgeTIgPSB5ICsgeFNpbiArIHlDb3M7XG4gIHZhciB5MyA9IHkgKyB4U2luIC0geUNvcztcbiAgcmV0dXJuIGNyZWF0ZU9yVXBkYXRlKE1hdGgubWluKHgwLCB4MSwgeDIsIHgzKSwgTWF0aC5taW4oeTAsIHkxLCB5MiwgeTMpLCBNYXRoLm1heCh4MCwgeDEsIHgyLCB4MyksIE1hdGgubWF4KHkwLCB5MSwgeTIsIHkzKSwgb3B0X2V4dGVudCk7XG59XG4vKipcbiAqIEdldCB0aGUgaGVpZ2h0IG9mIGFuIGV4dGVudC5cbiAqIEBwYXJhbSB7RXh0ZW50fSBleHRlbnQgRXh0ZW50LlxuICogQHJldHVybiB7bnVtYmVyfSBIZWlnaHQuXG4gKiBAYXBpXG4gKi9cblxuZXhwb3J0IGZ1bmN0aW9uIGdldEhlaWdodChleHRlbnQpIHtcbiAgcmV0dXJuIGV4dGVudFszXSAtIGV4dGVudFsxXTtcbn1cbi8qKlxuICogQHBhcmFtIHtFeHRlbnR9IGV4dGVudDEgRXh0ZW50IDEuXG4gKiBAcGFyYW0ge0V4dGVudH0gZXh0ZW50MiBFeHRlbnQgMi5cbiAqIEByZXR1cm4ge251bWJlcn0gSW50ZXJzZWN0aW9uIGFyZWEuXG4gKi9cblxuZXhwb3J0IGZ1bmN0aW9uIGdldEludGVyc2VjdGlvbkFyZWEoZXh0ZW50MSwgZXh0ZW50Mikge1xuICB2YXIgaW50ZXJzZWN0aW9uID0gZ2V0SW50ZXJzZWN0aW9uKGV4dGVudDEsIGV4dGVudDIpO1xuICByZXR1cm4gZ2V0QXJlYShpbnRlcnNlY3Rpb24pO1xufVxuLyoqXG4gKiBHZXQgdGhlIGludGVyc2VjdGlvbiBvZiB0d28gZXh0ZW50cy5cbiAqIEBwYXJhbSB7RXh0ZW50fSBleHRlbnQxIEV4dGVudCAxLlxuICogQHBhcmFtIHtFeHRlbnR9IGV4dGVudDIgRXh0ZW50IDIuXG4gKiBAcGFyYW0ge0V4dGVudD19IG9wdF9leHRlbnQgT3B0aW9uYWwgZXh0ZW50IHRvIHBvcHVsYXRlIHdpdGggaW50ZXJzZWN0aW9uLlxuICogQHJldHVybiB7RXh0ZW50fSBJbnRlcnNlY3RpbmcgZXh0ZW50LlxuICogQGFwaVxuICovXG5cbmV4cG9ydCBmdW5jdGlvbiBnZXRJbnRlcnNlY3Rpb24oZXh0ZW50MSwgZXh0ZW50Miwgb3B0X2V4dGVudCkge1xuICB2YXIgaW50ZXJzZWN0aW9uID0gb3B0X2V4dGVudCA/IG9wdF9leHRlbnQgOiBjcmVhdGVFbXB0eSgpO1xuXG4gIGlmIChpbnRlcnNlY3RzKGV4dGVudDEsIGV4dGVudDIpKSB7XG4gICAgaWYgKGV4dGVudDFbMF0gPiBleHRlbnQyWzBdKSB7XG4gICAgICBpbnRlcnNlY3Rpb25bMF0gPSBleHRlbnQxWzBdO1xuICAgIH0gZWxzZSB7XG4gICAgICBpbnRlcnNlY3Rpb25bMF0gPSBleHRlbnQyWzBdO1xuICAgIH1cblxuICAgIGlmIChleHRlbnQxWzFdID4gZXh0ZW50MlsxXSkge1xuICAgICAgaW50ZXJzZWN0aW9uWzFdID0gZXh0ZW50MVsxXTtcbiAgICB9IGVsc2Uge1xuICAgICAgaW50ZXJzZWN0aW9uWzFdID0gZXh0ZW50MlsxXTtcbiAgICB9XG5cbiAgICBpZiAoZXh0ZW50MVsyXSA8IGV4dGVudDJbMl0pIHtcbiAgICAgIGludGVyc2VjdGlvblsyXSA9IGV4dGVudDFbMl07XG4gICAgfSBlbHNlIHtcbiAgICAgIGludGVyc2VjdGlvblsyXSA9IGV4dGVudDJbMl07XG4gICAgfVxuXG4gICAgaWYgKGV4dGVudDFbM10gPCBleHRlbnQyWzNdKSB7XG4gICAgICBpbnRlcnNlY3Rpb25bM10gPSBleHRlbnQxWzNdO1xuICAgIH0gZWxzZSB7XG4gICAgICBpbnRlcnNlY3Rpb25bM10gPSBleHRlbnQyWzNdO1xuICAgIH1cbiAgfSBlbHNlIHtcbiAgICBjcmVhdGVPclVwZGF0ZUVtcHR5KGludGVyc2VjdGlvbik7XG4gIH1cblxuICByZXR1cm4gaW50ZXJzZWN0aW9uO1xufVxuLyoqXG4gKiBAcGFyYW0ge0V4dGVudH0gZXh0ZW50IEV4dGVudC5cbiAqIEByZXR1cm4ge251bWJlcn0gTWFyZ2luLlxuICovXG5cbmV4cG9ydCBmdW5jdGlvbiBnZXRNYXJnaW4oZXh0ZW50KSB7XG4gIHJldHVybiBnZXRXaWR0aChleHRlbnQpICsgZ2V0SGVpZ2h0KGV4dGVudCk7XG59XG4vKipcbiAqIEdldCB0aGUgc2l6ZSAod2lkdGgsIGhlaWdodCkgb2YgYW4gZXh0ZW50LlxuICogQHBhcmFtIHtFeHRlbnR9IGV4dGVudCBUaGUgZXh0ZW50LlxuICogQHJldHVybiB7aW1wb3J0KFwiLi9zaXplLmpzXCIpLlNpemV9IFRoZSBleHRlbnQgc2l6ZS5cbiAqIEBhcGlcbiAqL1xuXG5leHBvcnQgZnVuY3Rpb24gZ2V0U2l6ZShleHRlbnQpIHtcbiAgcmV0dXJuIFtleHRlbnRbMl0gLSBleHRlbnRbMF0sIGV4dGVudFszXSAtIGV4dGVudFsxXV07XG59XG4vKipcbiAqIEdldCB0aGUgdG9wIGxlZnQgY29vcmRpbmF0ZSBvZiBhbiBleHRlbnQuXG4gKiBAcGFyYW0ge0V4dGVudH0gZXh0ZW50IEV4dGVudC5cbiAqIEByZXR1cm4ge2ltcG9ydChcIi4vY29vcmRpbmF0ZS5qc1wiKS5Db29yZGluYXRlfSBUb3AgbGVmdCBjb29yZGluYXRlLlxuICogQGFwaVxuICovXG5cbmV4cG9ydCBmdW5jdGlvbiBnZXRUb3BMZWZ0KGV4dGVudCkge1xuICByZXR1cm4gW2V4dGVudFswXSwgZXh0ZW50WzNdXTtcbn1cbi8qKlxuICogR2V0IHRoZSB0b3AgcmlnaHQgY29vcmRpbmF0ZSBvZiBhbiBleHRlbnQuXG4gKiBAcGFyYW0ge0V4dGVudH0gZXh0ZW50IEV4dGVudC5cbiAqIEByZXR1cm4ge2ltcG9ydChcIi4vY29vcmRpbmF0ZS5qc1wiKS5Db29yZGluYXRlfSBUb3AgcmlnaHQgY29vcmRpbmF0ZS5cbiAqIEBhcGlcbiAqL1xuXG5leHBvcnQgZnVuY3Rpb24gZ2V0VG9wUmlnaHQoZXh0ZW50KSB7XG4gIHJldHVybiBbZXh0ZW50WzJdLCBleHRlbnRbM11dO1xufVxuLyoqXG4gKiBHZXQgdGhlIHdpZHRoIG9mIGFuIGV4dGVudC5cbiAqIEBwYXJhbSB7RXh0ZW50fSBleHRlbnQgRXh0ZW50LlxuICogQHJldHVybiB7bnVtYmVyfSBXaWR0aC5cbiAqIEBhcGlcbiAqL1xuXG5leHBvcnQgZnVuY3Rpb24gZ2V0V2lkdGgoZXh0ZW50KSB7XG4gIHJldHVybiBleHRlbnRbMl0gLSBleHRlbnRbMF07XG59XG4vKipcbiAqIERldGVybWluZSBpZiBvbmUgZXh0ZW50IGludGVyc2VjdHMgYW5vdGhlci5cbiAqIEBwYXJhbSB7RXh0ZW50fSBleHRlbnQxIEV4dGVudCAxLlxuICogQHBhcmFtIHtFeHRlbnR9IGV4dGVudDIgRXh0ZW50LlxuICogQHJldHVybiB7Ym9vbGVhbn0gVGhlIHR3byBleHRlbnRzIGludGVyc2VjdC5cbiAqIEBhcGlcbiAqL1xuXG5leHBvcnQgZnVuY3Rpb24gaW50ZXJzZWN0cyhleHRlbnQxLCBleHRlbnQyKSB7XG4gIHJldHVybiBleHRlbnQxWzBdIDw9IGV4dGVudDJbMl0gJiYgZXh0ZW50MVsyXSA+PSBleHRlbnQyWzBdICYmIGV4dGVudDFbMV0gPD0gZXh0ZW50MlszXSAmJiBleHRlbnQxWzNdID49IGV4dGVudDJbMV07XG59XG4vKipcbiAqIERldGVybWluZSBpZiBhbiBleHRlbnQgaXMgZW1wdHkuXG4gKiBAcGFyYW0ge0V4dGVudH0gZXh0ZW50IEV4dGVudC5cbiAqIEByZXR1cm4ge2Jvb2xlYW59IElzIGVtcHR5LlxuICogQGFwaVxuICovXG5cbmV4cG9ydCBmdW5jdGlvbiBpc0VtcHR5KGV4dGVudCkge1xuICByZXR1cm4gZXh0ZW50WzJdIDwgZXh0ZW50WzBdIHx8IGV4dGVudFszXSA8IGV4dGVudFsxXTtcbn1cbi8qKlxuICogQHBhcmFtIHtFeHRlbnR9IGV4dGVudCBFeHRlbnQuXG4gKiBAcGFyYW0ge0V4dGVudD19IG9wdF9leHRlbnQgRXh0ZW50LlxuICogQHJldHVybiB7RXh0ZW50fSBFeHRlbnQuXG4gKi9cblxuZXhwb3J0IGZ1bmN0aW9uIHJldHVybk9yVXBkYXRlKGV4dGVudCwgb3B0X2V4dGVudCkge1xuICBpZiAob3B0X2V4dGVudCkge1xuICAgIG9wdF9leHRlbnRbMF0gPSBleHRlbnRbMF07XG4gICAgb3B0X2V4dGVudFsxXSA9IGV4dGVudFsxXTtcbiAgICBvcHRfZXh0ZW50WzJdID0gZXh0ZW50WzJdO1xuICAgIG9wdF9leHRlbnRbM10gPSBleHRlbnRbM107XG4gICAgcmV0dXJuIG9wdF9leHRlbnQ7XG4gIH0gZWxzZSB7XG4gICAgcmV0dXJuIGV4dGVudDtcbiAgfVxufVxuLyoqXG4gKiBAcGFyYW0ge0V4dGVudH0gZXh0ZW50IEV4dGVudC5cbiAqIEBwYXJhbSB7bnVtYmVyfSB2YWx1ZSBWYWx1ZS5cbiAqL1xuXG5leHBvcnQgZnVuY3Rpb24gc2NhbGVGcm9tQ2VudGVyKGV4dGVudCwgdmFsdWUpIHtcbiAgdmFyIGRlbHRhWCA9IChleHRlbnRbMl0gLSBleHRlbnRbMF0pIC8gMiAqICh2YWx1ZSAtIDEpO1xuICB2YXIgZGVsdGFZID0gKGV4dGVudFszXSAtIGV4dGVudFsxXSkgLyAyICogKHZhbHVlIC0gMSk7XG4gIGV4dGVudFswXSAtPSBkZWx0YVg7XG4gIGV4dGVudFsyXSArPSBkZWx0YVg7XG4gIGV4dGVudFsxXSAtPSBkZWx0YVk7XG4gIGV4dGVudFszXSArPSBkZWx0YVk7XG59XG4vKipcbiAqIERldGVybWluZSBpZiB0aGUgc2VnbWVudCBiZXR3ZWVuIHR3byBjb29yZGluYXRlcyBpbnRlcnNlY3RzIChjcm9zc2VzLFxuICogdG91Y2hlcywgb3IgaXMgY29udGFpbmVkIGJ5KSB0aGUgcHJvdmlkZWQgZXh0ZW50LlxuICogQHBhcmFtIHtFeHRlbnR9IGV4dGVudCBUaGUgZXh0ZW50LlxuICogQHBhcmFtIHtpbXBvcnQoXCIuL2Nvb3JkaW5hdGUuanNcIikuQ29vcmRpbmF0ZX0gc3RhcnQgU2VnbWVudCBzdGFydCBjb29yZGluYXRlLlxuICogQHBhcmFtIHtpbXBvcnQoXCIuL2Nvb3JkaW5hdGUuanNcIikuQ29vcmRpbmF0ZX0gZW5kIFNlZ21lbnQgZW5kIGNvb3JkaW5hdGUuXG4gKiBAcmV0dXJuIHtib29sZWFufSBUaGUgc2VnbWVudCBpbnRlcnNlY3RzIHRoZSBleHRlbnQuXG4gKi9cblxuZXhwb3J0IGZ1bmN0aW9uIGludGVyc2VjdHNTZWdtZW50KGV4dGVudCwgc3RhcnQsIGVuZCkge1xuICB2YXIgaW50ZXJzZWN0cyA9IGZhbHNlO1xuICB2YXIgc3RhcnRSZWwgPSBjb29yZGluYXRlUmVsYXRpb25zaGlwKGV4dGVudCwgc3RhcnQpO1xuICB2YXIgZW5kUmVsID0gY29vcmRpbmF0ZVJlbGF0aW9uc2hpcChleHRlbnQsIGVuZCk7XG5cbiAgaWYgKHN0YXJ0UmVsID09PSBSZWxhdGlvbnNoaXAuSU5URVJTRUNUSU5HIHx8IGVuZFJlbCA9PT0gUmVsYXRpb25zaGlwLklOVEVSU0VDVElORykge1xuICAgIGludGVyc2VjdHMgPSB0cnVlO1xuICB9IGVsc2Uge1xuICAgIHZhciBtaW5YID0gZXh0ZW50WzBdO1xuICAgIHZhciBtaW5ZID0gZXh0ZW50WzFdO1xuICAgIHZhciBtYXhYID0gZXh0ZW50WzJdO1xuICAgIHZhciBtYXhZID0gZXh0ZW50WzNdO1xuICAgIHZhciBzdGFydFggPSBzdGFydFswXTtcbiAgICB2YXIgc3RhcnRZID0gc3RhcnRbMV07XG4gICAgdmFyIGVuZFggPSBlbmRbMF07XG4gICAgdmFyIGVuZFkgPSBlbmRbMV07XG4gICAgdmFyIHNsb3BlID0gKGVuZFkgLSBzdGFydFkpIC8gKGVuZFggLSBzdGFydFgpO1xuICAgIHZhciB4ID0gdm9pZCAwLFxuICAgICAgICB5ID0gdm9pZCAwO1xuXG4gICAgaWYgKCEhKGVuZFJlbCAmIFJlbGF0aW9uc2hpcC5BQk9WRSkgJiYgIShzdGFydFJlbCAmIFJlbGF0aW9uc2hpcC5BQk9WRSkpIHtcbiAgICAgIC8vIHBvdGVudGlhbGx5IGludGVyc2VjdHMgdG9wXG4gICAgICB4ID0gZW5kWCAtIChlbmRZIC0gbWF4WSkgLyBzbG9wZTtcbiAgICAgIGludGVyc2VjdHMgPSB4ID49IG1pblggJiYgeCA8PSBtYXhYO1xuICAgIH1cblxuICAgIGlmICghaW50ZXJzZWN0cyAmJiAhIShlbmRSZWwgJiBSZWxhdGlvbnNoaXAuUklHSFQpICYmICEoc3RhcnRSZWwgJiBSZWxhdGlvbnNoaXAuUklHSFQpKSB7XG4gICAgICAvLyBwb3RlbnRpYWxseSBpbnRlcnNlY3RzIHJpZ2h0XG4gICAgICB5ID0gZW5kWSAtIChlbmRYIC0gbWF4WCkgKiBzbG9wZTtcbiAgICAgIGludGVyc2VjdHMgPSB5ID49IG1pblkgJiYgeSA8PSBtYXhZO1xuICAgIH1cblxuICAgIGlmICghaW50ZXJzZWN0cyAmJiAhIShlbmRSZWwgJiBSZWxhdGlvbnNoaXAuQkVMT1cpICYmICEoc3RhcnRSZWwgJiBSZWxhdGlvbnNoaXAuQkVMT1cpKSB7XG4gICAgICAvLyBwb3RlbnRpYWxseSBpbnRlcnNlY3RzIGJvdHRvbVxuICAgICAgeCA9IGVuZFggLSAoZW5kWSAtIG1pblkpIC8gc2xvcGU7XG4gICAgICBpbnRlcnNlY3RzID0geCA+PSBtaW5YICYmIHggPD0gbWF4WDtcbiAgICB9XG5cbiAgICBpZiAoIWludGVyc2VjdHMgJiYgISEoZW5kUmVsICYgUmVsYXRpb25zaGlwLkxFRlQpICYmICEoc3RhcnRSZWwgJiBSZWxhdGlvbnNoaXAuTEVGVCkpIHtcbiAgICAgIC8vIHBvdGVudGlhbGx5IGludGVyc2VjdHMgbGVmdFxuICAgICAgeSA9IGVuZFkgLSAoZW5kWCAtIG1pblgpICogc2xvcGU7XG4gICAgICBpbnRlcnNlY3RzID0geSA+PSBtaW5ZICYmIHkgPD0gbWF4WTtcbiAgICB9XG4gIH1cblxuICByZXR1cm4gaW50ZXJzZWN0cztcbn1cbi8qKlxuICogQXBwbHkgYSB0cmFuc2Zvcm0gZnVuY3Rpb24gdG8gdGhlIGV4dGVudC5cbiAqIEBwYXJhbSB7RXh0ZW50fSBleHRlbnQgRXh0ZW50LlxuICogQHBhcmFtIHtpbXBvcnQoXCIuL3Byb2ouanNcIikuVHJhbnNmb3JtRnVuY3Rpb259IHRyYW5zZm9ybUZuIFRyYW5zZm9ybSBmdW5jdGlvbi5cbiAqIENhbGxlZCB3aXRoIGBbbWluWCwgbWluWSwgbWF4WCwgbWF4WV1gIGV4dGVudCBjb29yZGluYXRlcy5cbiAqIEBwYXJhbSB7RXh0ZW50PX0gb3B0X2V4dGVudCBEZXN0aW5hdGlvbiBleHRlbnQuXG4gKiBAcGFyYW0ge251bWJlcj19IG9wdF9zdG9wcyBOdW1iZXIgb2Ygc3RvcHMgcGVyIHNpZGUgdXNlZCBmb3IgdGhlIHRyYW5zZm9ybS5cbiAqIEJ5IGRlZmF1bHQgb25seSB0aGUgY29ybmVycyBhcmUgdXNlZC5cbiAqIEByZXR1cm4ge0V4dGVudH0gRXh0ZW50LlxuICogQGFwaVxuICovXG5cbmV4cG9ydCBmdW5jdGlvbiBhcHBseVRyYW5zZm9ybShleHRlbnQsIHRyYW5zZm9ybUZuLCBvcHRfZXh0ZW50LCBvcHRfc3RvcHMpIHtcbiAgdmFyIGNvb3JkaW5hdGVzID0gW107XG5cbiAgaWYgKG9wdF9zdG9wcyA+IDEpIHtcbiAgICB2YXIgd2lkdGggPSBleHRlbnRbMl0gLSBleHRlbnRbMF07XG4gICAgdmFyIGhlaWdodCA9IGV4dGVudFszXSAtIGV4dGVudFsxXTtcblxuICAgIGZvciAodmFyIGkgPSAwOyBpIDwgb3B0X3N0b3BzOyArK2kpIHtcbiAgICAgIGNvb3JkaW5hdGVzLnB1c2goZXh0ZW50WzBdICsgd2lkdGggKiBpIC8gb3B0X3N0b3BzLCBleHRlbnRbMV0sIGV4dGVudFsyXSwgZXh0ZW50WzFdICsgaGVpZ2h0ICogaSAvIG9wdF9zdG9wcywgZXh0ZW50WzJdIC0gd2lkdGggKiBpIC8gb3B0X3N0b3BzLCBleHRlbnRbM10sIGV4dGVudFswXSwgZXh0ZW50WzNdIC0gaGVpZ2h0ICogaSAvIG9wdF9zdG9wcyk7XG4gICAgfVxuICB9IGVsc2Uge1xuICAgIGNvb3JkaW5hdGVzID0gW2V4dGVudFswXSwgZXh0ZW50WzFdLCBleHRlbnRbMl0sIGV4dGVudFsxXSwgZXh0ZW50WzJdLCBleHRlbnRbM10sIGV4dGVudFswXSwgZXh0ZW50WzNdXTtcbiAgfVxuXG4gIHRyYW5zZm9ybUZuKGNvb3JkaW5hdGVzLCBjb29yZGluYXRlcywgMik7XG4gIHZhciB4cyA9IFtdO1xuICB2YXIgeXMgPSBbXTtcblxuICBmb3IgKHZhciBpID0gMCwgbCA9IGNvb3JkaW5hdGVzLmxlbmd0aDsgaSA8IGw7IGkgKz0gMikge1xuICAgIHhzLnB1c2goY29vcmRpbmF0ZXNbaV0pO1xuICAgIHlzLnB1c2goY29vcmRpbmF0ZXNbaSArIDFdKTtcbiAgfVxuXG4gIHJldHVybiBfYm91bmRpbmdFeHRlbnRYWXMoeHMsIHlzLCBvcHRfZXh0ZW50KTtcbn1cbi8qKlxuICogTW9kaWZpZXMgdGhlIHByb3ZpZGVkIGV4dGVudCBpbi1wbGFjZSB0byBiZSB3aXRoaW4gdGhlIHJlYWwgd29ybGRcbiAqIGV4dGVudC5cbiAqXG4gKiBAcGFyYW0ge0V4dGVudH0gZXh0ZW50IEV4dGVudC5cbiAqIEBwYXJhbSB7aW1wb3J0KFwiLi9wcm9qL1Byb2plY3Rpb24uanNcIikuZGVmYXVsdH0gcHJvamVjdGlvbiBQcm9qZWN0aW9uXG4gKiBAcmV0dXJuIHtFeHRlbnR9IFRoZSBleHRlbnQgd2l0aGluIHRoZSByZWFsIHdvcmxkIGV4dGVudC5cbiAqL1xuXG5leHBvcnQgZnVuY3Rpb24gd3JhcFgoZXh0ZW50LCBwcm9qZWN0aW9uKSB7XG4gIHZhciBwcm9qZWN0aW9uRXh0ZW50ID0gcHJvamVjdGlvbi5nZXRFeHRlbnQoKTtcbiAgdmFyIGNlbnRlciA9IGdldENlbnRlcihleHRlbnQpO1xuXG4gIGlmIChwcm9qZWN0aW9uLmNhbldyYXBYKCkgJiYgKGNlbnRlclswXSA8IHByb2plY3Rpb25FeHRlbnRbMF0gfHwgY2VudGVyWzBdID49IHByb2plY3Rpb25FeHRlbnRbMl0pKSB7XG4gICAgdmFyIHdvcmxkV2lkdGggPSBnZXRXaWR0aChwcm9qZWN0aW9uRXh0ZW50KTtcbiAgICB2YXIgd29ybGRzQXdheSA9IE1hdGguZmxvb3IoKGNlbnRlclswXSAtIHByb2plY3Rpb25FeHRlbnRbMF0pIC8gd29ybGRXaWR0aCk7XG4gICAgdmFyIG9mZnNldCA9IHdvcmxkc0F3YXkgKiB3b3JsZFdpZHRoO1xuICAgIGV4dGVudFswXSAtPSBvZmZzZXQ7XG4gICAgZXh0ZW50WzJdIC09IG9mZnNldDtcbiAgfVxuXG4gIHJldHVybiBleHRlbnQ7XG59IiwiLyoqXG4gKiBAbW9kdWxlIG9sL21hdGhcbiAqL1xuXG4vKipcbiAqIFRha2VzIGEgbnVtYmVyIGFuZCBjbGFtcHMgaXQgdG8gd2l0aGluIHRoZSBwcm92aWRlZCBib3VuZHMuXG4gKiBAcGFyYW0ge251bWJlcn0gdmFsdWUgVGhlIGlucHV0IG51bWJlci5cbiAqIEBwYXJhbSB7bnVtYmVyfSBtaW4gVGhlIG1pbmltdW0gdmFsdWUgdG8gcmV0dXJuLlxuICogQHBhcmFtIHtudW1iZXJ9IG1heCBUaGUgbWF4aW11bSB2YWx1ZSB0byByZXR1cm4uXG4gKiBAcmV0dXJuIHtudW1iZXJ9IFRoZSBpbnB1dCBudW1iZXIgaWYgaXQgaXMgd2l0aGluIGJvdW5kcywgb3IgdGhlIG5lYXJlc3RcbiAqICAgICBudW1iZXIgd2l0aGluIHRoZSBib3VuZHMuXG4gKi9cbmV4cG9ydCBmdW5jdGlvbiBjbGFtcCh2YWx1ZSwgbWluLCBtYXgpIHtcbiAgcmV0dXJuIE1hdGgubWluKE1hdGgubWF4KHZhbHVlLCBtaW4pLCBtYXgpO1xufVxuLyoqXG4gKiBSZXR1cm4gdGhlIGh5cGVyYm9saWMgY29zaW5lIG9mIGEgZ2l2ZW4gbnVtYmVyLiBUaGUgbWV0aG9kIHdpbGwgdXNlIHRoZVxuICogbmF0aXZlIGBNYXRoLmNvc2hgIGZ1bmN0aW9uIGlmIGl0IGlzIGF2YWlsYWJsZSwgb3RoZXJ3aXNlIHRoZSBoeXBlcmJvbGljXG4gKiBjb3NpbmUgd2lsbCBiZSBjYWxjdWxhdGVkIHZpYSB0aGUgcmVmZXJlbmNlIGltcGxlbWVudGF0aW9uIG9mIHRoZSBNb3ppbGxhXG4gKiBkZXZlbG9wZXIgbmV0d29yay5cbiAqXG4gKiBAcGFyYW0ge251bWJlcn0geCBYLlxuICogQHJldHVybiB7bnVtYmVyfSBIeXBlcmJvbGljIGNvc2luZSBvZiB4LlxuICovXG5cbmV4cG9ydCB2YXIgY29zaCA9IGZ1bmN0aW9uICgpIHtcbiAgLy8gV3JhcHBlZCBpbiBhIGlpZmUsIHRvIHNhdmUgdGhlIG92ZXJoZWFkIG9mIGNoZWNraW5nIGZvciB0aGUgbmF0aXZlXG4gIC8vIGltcGxlbWVudGF0aW9uIG9uIGV2ZXJ5IGludm9jYXRpb24uXG4gIHZhciBjb3NoO1xuXG4gIGlmICgnY29zaCcgaW4gTWF0aCkge1xuICAgIC8vIFRoZSBlbnZpcm9ubWVudCBzdXBwb3J0cyB0aGUgbmF0aXZlIE1hdGguY29zaCBmdW5jdGlvbiwgdXNlIGl04oCmXG4gICAgY29zaCA9IE1hdGguY29zaDtcbiAgfSBlbHNlIHtcbiAgICAvLyDigKYgZWxzZSwgdXNlIHRoZSByZWZlcmVuY2UgaW1wbGVtZW50YXRpb24gb2YgTUROOlxuICAgIGNvc2ggPSBmdW5jdGlvbiBjb3NoKHgpIHtcbiAgICAgIHZhciB5ID1cbiAgICAgIC8qKiBAdHlwZSB7TWF0aH0gKi9cbiAgICAgIE1hdGguZXhwKHgpO1xuICAgICAgcmV0dXJuICh5ICsgMSAvIHkpIC8gMjtcbiAgICB9O1xuICB9XG5cbiAgcmV0dXJuIGNvc2g7XG59KCk7XG4vKipcbiAqIFJldHVybiB0aGUgYmFzZSAyIGxvZ2FyaXRobSBvZiBhIGdpdmVuIG51bWJlci4gVGhlIG1ldGhvZCB3aWxsIHVzZSB0aGVcbiAqIG5hdGl2ZSBgTWF0aC5sb2cyYCBmdW5jdGlvbiBpZiBpdCBpcyBhdmFpbGFibGUsIG90aGVyd2lzZSB0aGUgYmFzZSAyXG4gKiBsb2dhcml0aG0gd2lsbCBiZSBjYWxjdWxhdGVkIHZpYSB0aGUgcmVmZXJlbmNlIGltcGxlbWVudGF0aW9uIG9mIHRoZVxuICogTW96aWxsYSBkZXZlbG9wZXIgbmV0d29yay5cbiAqXG4gKiBAcGFyYW0ge251bWJlcn0geCBYLlxuICogQHJldHVybiB7bnVtYmVyfSBCYXNlIDIgbG9nYXJpdGhtIG9mIHguXG4gKi9cblxuZXhwb3J0IHZhciBsb2cyID0gZnVuY3Rpb24gKCkge1xuICAvLyBXcmFwcGVkIGluIGEgaWlmZSwgdG8gc2F2ZSB0aGUgb3ZlcmhlYWQgb2YgY2hlY2tpbmcgZm9yIHRoZSBuYXRpdmVcbiAgLy8gaW1wbGVtZW50YXRpb24gb24gZXZlcnkgaW52b2NhdGlvbi5cbiAgdmFyIGxvZzI7XG5cbiAgaWYgKCdsb2cyJyBpbiBNYXRoKSB7XG4gICAgLy8gVGhlIGVudmlyb25tZW50IHN1cHBvcnRzIHRoZSBuYXRpdmUgTWF0aC5sb2cyIGZ1bmN0aW9uLCB1c2UgaXTigKZcbiAgICBsb2cyID0gTWF0aC5sb2cyO1xuICB9IGVsc2Uge1xuICAgIC8vIOKApiBlbHNlLCB1c2UgdGhlIHJlZmVyZW5jZSBpbXBsZW1lbnRhdGlvbiBvZiBNRE46XG4gICAgbG9nMiA9IGZ1bmN0aW9uIGxvZzIoeCkge1xuICAgICAgcmV0dXJuIE1hdGgubG9nKHgpICogTWF0aC5MT0cyRTtcbiAgICB9O1xuICB9XG5cbiAgcmV0dXJuIGxvZzI7XG59KCk7XG4vKipcbiAqIFJldHVybnMgdGhlIHNxdWFyZSBvZiB0aGUgY2xvc2VzdCBkaXN0YW5jZSBiZXR3ZWVuIHRoZSBwb2ludCAoeCwgeSkgYW5kIHRoZVxuICogbGluZSBzZWdtZW50ICh4MSwgeTEpIHRvICh4MiwgeTIpLlxuICogQHBhcmFtIHtudW1iZXJ9IHggWC5cbiAqIEBwYXJhbSB7bnVtYmVyfSB5IFkuXG4gKiBAcGFyYW0ge251bWJlcn0geDEgWDEuXG4gKiBAcGFyYW0ge251bWJlcn0geTEgWTEuXG4gKiBAcGFyYW0ge251bWJlcn0geDIgWDIuXG4gKiBAcGFyYW0ge251bWJlcn0geTIgWTIuXG4gKiBAcmV0dXJuIHtudW1iZXJ9IFNxdWFyZWQgZGlzdGFuY2UuXG4gKi9cblxuZXhwb3J0IGZ1bmN0aW9uIHNxdWFyZWRTZWdtZW50RGlzdGFuY2UoeCwgeSwgeDEsIHkxLCB4MiwgeTIpIHtcbiAgdmFyIGR4ID0geDIgLSB4MTtcbiAgdmFyIGR5ID0geTIgLSB5MTtcblxuICBpZiAoZHggIT09IDAgfHwgZHkgIT09IDApIHtcbiAgICB2YXIgdCA9ICgoeCAtIHgxKSAqIGR4ICsgKHkgLSB5MSkgKiBkeSkgLyAoZHggKiBkeCArIGR5ICogZHkpO1xuXG4gICAgaWYgKHQgPiAxKSB7XG4gICAgICB4MSA9IHgyO1xuICAgICAgeTEgPSB5MjtcbiAgICB9IGVsc2UgaWYgKHQgPiAwKSB7XG4gICAgICB4MSArPSBkeCAqIHQ7XG4gICAgICB5MSArPSBkeSAqIHQ7XG4gICAgfVxuICB9XG5cbiAgcmV0dXJuIHNxdWFyZWREaXN0YW5jZSh4LCB5LCB4MSwgeTEpO1xufVxuLyoqXG4gKiBSZXR1cm5zIHRoZSBzcXVhcmUgb2YgdGhlIGRpc3RhbmNlIGJldHdlZW4gdGhlIHBvaW50cyAoeDEsIHkxKSBhbmQgKHgyLCB5MikuXG4gKiBAcGFyYW0ge251bWJlcn0geDEgWDEuXG4gKiBAcGFyYW0ge251bWJlcn0geTEgWTEuXG4gKiBAcGFyYW0ge251bWJlcn0geDIgWDIuXG4gKiBAcGFyYW0ge251bWJlcn0geTIgWTIuXG4gKiBAcmV0dXJuIHtudW1iZXJ9IFNxdWFyZWQgZGlzdGFuY2UuXG4gKi9cblxuZXhwb3J0IGZ1bmN0aW9uIHNxdWFyZWREaXN0YW5jZSh4MSwgeTEsIHgyLCB5Mikge1xuICB2YXIgZHggPSB4MiAtIHgxO1xuICB2YXIgZHkgPSB5MiAtIHkxO1xuICByZXR1cm4gZHggKiBkeCArIGR5ICogZHk7XG59XG4vKipcbiAqIFNvbHZlcyBzeXN0ZW0gb2YgbGluZWFyIGVxdWF0aW9ucyB1c2luZyBHYXVzc2lhbiBlbGltaW5hdGlvbiBtZXRob2QuXG4gKlxuICogQHBhcmFtIHtBcnJheTxBcnJheTxudW1iZXI+Pn0gbWF0IEF1Z21lbnRlZCBtYXRyaXggKG4geCBuICsgMSBjb2x1bW4pXG4gKiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBpbiByb3ctbWFqb3Igb3JkZXIuXG4gKiBAcmV0dXJuIHtBcnJheTxudW1iZXI+fSBUaGUgcmVzdWx0aW5nIHZlY3Rvci5cbiAqL1xuXG5leHBvcnQgZnVuY3Rpb24gc29sdmVMaW5lYXJTeXN0ZW0obWF0KSB7XG4gIHZhciBuID0gbWF0Lmxlbmd0aDtcblxuICBmb3IgKHZhciBpID0gMDsgaSA8IG47IGkrKykge1xuICAgIC8vIEZpbmQgbWF4IGluIHRoZSBpLXRoIGNvbHVtbiAoaWdub3JpbmcgaSAtIDEgZmlyc3Qgcm93cylcbiAgICB2YXIgbWF4Um93ID0gaTtcbiAgICB2YXIgbWF4RWwgPSBNYXRoLmFicyhtYXRbaV1baV0pO1xuXG4gICAgZm9yICh2YXIgciA9IGkgKyAxOyByIDwgbjsgcisrKSB7XG4gICAgICB2YXIgYWJzVmFsdWUgPSBNYXRoLmFicyhtYXRbcl1baV0pO1xuXG4gICAgICBpZiAoYWJzVmFsdWUgPiBtYXhFbCkge1xuICAgICAgICBtYXhFbCA9IGFic1ZhbHVlO1xuICAgICAgICBtYXhSb3cgPSByO1xuICAgICAgfVxuICAgIH1cblxuICAgIGlmIChtYXhFbCA9PT0gMCkge1xuICAgICAgcmV0dXJuIG51bGw7IC8vIG1hdHJpeCBpcyBzaW5ndWxhclxuICAgIH0gLy8gU3dhcCBtYXggcm93IHdpdGggaS10aCAoY3VycmVudCkgcm93XG5cblxuICAgIHZhciB0bXAgPSBtYXRbbWF4Um93XTtcbiAgICBtYXRbbWF4Um93XSA9IG1hdFtpXTtcbiAgICBtYXRbaV0gPSB0bXA7IC8vIFN1YnRyYWN0IHRoZSBpLXRoIHJvdyB0byBtYWtlIGFsbCB0aGUgcmVtYWluaW5nIHJvd3MgMCBpbiB0aGUgaS10aCBjb2x1bW5cblxuICAgIGZvciAodmFyIGogPSBpICsgMTsgaiA8IG47IGorKykge1xuICAgICAgdmFyIGNvZWYgPSAtbWF0W2pdW2ldIC8gbWF0W2ldW2ldO1xuXG4gICAgICBmb3IgKHZhciBrID0gaTsgayA8IG4gKyAxOyBrKyspIHtcbiAgICAgICAgaWYgKGkgPT0gaykge1xuICAgICAgICAgIG1hdFtqXVtrXSA9IDA7XG4gICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgbWF0W2pdW2tdICs9IGNvZWYgKiBtYXRbaV1ba107XG4gICAgICAgIH1cbiAgICAgIH1cbiAgICB9XG4gIH0gLy8gU29sdmUgQXg9YiBmb3IgdXBwZXIgdHJpYW5ndWxhciBtYXRyaXggQSAobWF0KVxuXG5cbiAgdmFyIHggPSBuZXcgQXJyYXkobik7XG5cbiAgZm9yICh2YXIgbCA9IG4gLSAxOyBsID49IDA7IGwtLSkge1xuICAgIHhbbF0gPSBtYXRbbF1bbl0gLyBtYXRbbF1bbF07XG5cbiAgICBmb3IgKHZhciBtID0gbCAtIDE7IG0gPj0gMDsgbS0tKSB7XG4gICAgICBtYXRbbV1bbl0gLT0gbWF0W21dW2xdICogeFtsXTtcbiAgICB9XG4gIH1cblxuICByZXR1cm4geDtcbn1cbi8qKlxuICogQ29udmVydHMgcmFkaWFucyB0byB0byBkZWdyZWVzLlxuICpcbiAqIEBwYXJhbSB7bnVtYmVyfSBhbmdsZUluUmFkaWFucyBBbmdsZSBpbiByYWRpYW5zLlxuICogQHJldHVybiB7bnVtYmVyfSBBbmdsZSBpbiBkZWdyZWVzLlxuICovXG5cbmV4cG9ydCBmdW5jdGlvbiB0b0RlZ3JlZXMoYW5nbGVJblJhZGlhbnMpIHtcbiAgcmV0dXJuIGFuZ2xlSW5SYWRpYW5zICogMTgwIC8gTWF0aC5QSTtcbn1cbi8qKlxuICogQ29udmVydHMgZGVncmVlcyB0byByYWRpYW5zLlxuICpcbiAqIEBwYXJhbSB7bnVtYmVyfSBhbmdsZUluRGVncmVlcyBBbmdsZSBpbiBkZWdyZWVzLlxuICogQHJldHVybiB7bnVtYmVyfSBBbmdsZSBpbiByYWRpYW5zLlxuICovXG5cbmV4cG9ydCBmdW5jdGlvbiB0b1JhZGlhbnMoYW5nbGVJbkRlZ3JlZXMpIHtcbiAgcmV0dXJuIGFuZ2xlSW5EZWdyZWVzICogTWF0aC5QSSAvIDE4MDtcbn1cbi8qKlxuICogUmV0dXJucyB0aGUgbW9kdWxvIG9mIGEgLyBiLCBkZXBlbmRpbmcgb24gdGhlIHNpZ24gb2YgYi5cbiAqXG4gKiBAcGFyYW0ge251bWJlcn0gYSBEaXZpZGVuZC5cbiAqIEBwYXJhbSB7bnVtYmVyfSBiIERpdmlzb3IuXG4gKiBAcmV0dXJuIHtudW1iZXJ9IE1vZHVsby5cbiAqL1xuXG5leHBvcnQgZnVuY3Rpb24gbW9kdWxvKGEsIGIpIHtcbiAgdmFyIHIgPSBhICUgYjtcbiAgcmV0dXJuIHIgKiBiIDwgMCA/IHIgKyBiIDogcjtcbn1cbi8qKlxuICogQ2FsY3VsYXRlcyB0aGUgbGluZWFybHkgaW50ZXJwb2xhdGVkIHZhbHVlIG9mIHggYmV0d2VlbiBhIGFuZCBiLlxuICpcbiAqIEBwYXJhbSB7bnVtYmVyfSBhIE51bWJlclxuICogQHBhcmFtIHtudW1iZXJ9IGIgTnVtYmVyXG4gKiBAcGFyYW0ge251bWJlcn0geCBWYWx1ZSB0byBiZSBpbnRlcnBvbGF0ZWQuXG4gKiBAcmV0dXJuIHtudW1iZXJ9IEludGVycG9sYXRlZCB2YWx1ZS5cbiAqL1xuXG5leHBvcnQgZnVuY3Rpb24gbGVycChhLCBiLCB4KSB7XG4gIHJldHVybiBhICsgeCAqIChiIC0gYSk7XG59IiwiLyoqXG4gKiBAbW9kdWxlIG9sL2NvbG9yXG4gKi9cbmltcG9ydCB7IGFzc2VydCB9IGZyb20gJy4vYXNzZXJ0cy5qcyc7XG5pbXBvcnQgeyBjbGFtcCB9IGZyb20gJy4vbWF0aC5qcyc7XG4vKipcbiAqIEEgY29sb3IgcmVwcmVzZW50ZWQgYXMgYSBzaG9ydCBhcnJheSBbcmVkLCBncmVlbiwgYmx1ZSwgYWxwaGFdLlxuICogcmVkLCBncmVlbiwgYW5kIGJsdWUgc2hvdWxkIGJlIGludGVnZXJzIGluIHRoZSByYW5nZSAwLi4yNTUgaW5jbHVzaXZlLlxuICogYWxwaGEgc2hvdWxkIGJlIGEgZmxvYXQgaW4gdGhlIHJhbmdlIDAuLjEgaW5jbHVzaXZlLiBJZiBubyBhbHBoYSB2YWx1ZSBpc1xuICogZ2l2ZW4gdGhlbiBgMWAgd2lsbCBiZSB1c2VkLlxuICogQHR5cGVkZWYge0FycmF5PG51bWJlcj59IENvbG9yXG4gKiBAYXBpXG4gKi9cblxuLyoqXG4gKiBUaGlzIFJlZ0V4cCBtYXRjaGVzICMgZm9sbG93ZWQgYnkgMywgNCwgNiwgb3IgOCBoZXggZGlnaXRzLlxuICogQGNvbnN0XG4gKiBAdHlwZSB7UmVnRXhwfVxuICogQHByaXZhdGVcbiAqL1xuXG52YXIgSEVYX0NPTE9SX1JFXyA9IC9eIyhbYS1mMC05XXszfXxbYS1mMC05XXs0fSg/OlthLWYwLTldezJ9KXswLDJ9KSQvaTtcbi8qKlxuICogUmVndWxhciBleHByZXNzaW9uIGZvciBtYXRjaGluZyBwb3RlbnRpYWwgbmFtZWQgY29sb3Igc3R5bGUgc3RyaW5ncy5cbiAqIEBjb25zdFxuICogQHR5cGUge1JlZ0V4cH1cbiAqIEBwcml2YXRlXG4gKi9cblxudmFyIE5BTUVEX0NPTE9SX1JFXyA9IC9eKFthLXpdKikkfF5oc2xhP1xcKC4qXFwpJC9pO1xuLyoqXG4gKiBSZXR1cm4gdGhlIGNvbG9yIGFzIGFuIHJnYmEgc3RyaW5nLlxuICogQHBhcmFtIHtDb2xvcnxzdHJpbmd9IGNvbG9yIENvbG9yLlxuICogQHJldHVybiB7c3RyaW5nfSBSZ2JhIHN0cmluZy5cbiAqIEBhcGlcbiAqL1xuXG5leHBvcnQgZnVuY3Rpb24gYXNTdHJpbmcoY29sb3IpIHtcbiAgaWYgKHR5cGVvZiBjb2xvciA9PT0gJ3N0cmluZycpIHtcbiAgICByZXR1cm4gY29sb3I7XG4gIH0gZWxzZSB7XG4gICAgcmV0dXJuIHRvU3RyaW5nKGNvbG9yKTtcbiAgfVxufVxuLyoqXG4gKiBSZXR1cm4gbmFtZWQgY29sb3IgYXMgYW4gcmdiYSBzdHJpbmcuXG4gKiBAcGFyYW0ge3N0cmluZ30gY29sb3IgTmFtZWQgY29sb3IuXG4gKiBAcmV0dXJuIHtzdHJpbmd9IFJnYiBzdHJpbmcuXG4gKi9cblxuZnVuY3Rpb24gZnJvbU5hbWVkKGNvbG9yKSB7XG4gIHZhciBlbCA9IGRvY3VtZW50LmNyZWF0ZUVsZW1lbnQoJ2RpdicpO1xuICBlbC5zdHlsZS5jb2xvciA9IGNvbG9yO1xuXG4gIGlmIChlbC5zdHlsZS5jb2xvciAhPT0gJycpIHtcbiAgICBkb2N1bWVudC5ib2R5LmFwcGVuZENoaWxkKGVsKTtcbiAgICB2YXIgcmdiID0gZ2V0Q29tcHV0ZWRTdHlsZShlbCkuY29sb3I7XG4gICAgZG9jdW1lbnQuYm9keS5yZW1vdmVDaGlsZChlbCk7XG4gICAgcmV0dXJuIHJnYjtcbiAgfSBlbHNlIHtcbiAgICByZXR1cm4gJyc7XG4gIH1cbn1cbi8qKlxuICogQHBhcmFtIHtzdHJpbmd9IHMgU3RyaW5nLlxuICogQHJldHVybiB7Q29sb3J9IENvbG9yLlxuICovXG5cblxuZXhwb3J0IHZhciBmcm9tU3RyaW5nID0gZnVuY3Rpb24gKCkge1xuICAvLyBXZSBtYWludGFpbiBhIHNtYWxsIGNhY2hlIG9mIHBhcnNlZCBzdHJpbmdzLiAgVG8gcHJvdmlkZSBjaGVhcCBMUlUtbGlrZVxuICAvLyBzZW1hbnRpY3MsIHdoZW5ldmVyIHRoZSBjYWNoZSBncm93cyB0b28gbGFyZ2Ugd2Ugc2ltcGx5IGRlbGV0ZSBhblxuICAvLyBhcmJpdHJhcnkgMjUlIG9mIHRoZSBlbnRyaWVzLlxuXG4gIC8qKlxuICAgKiBAY29uc3RcbiAgICogQHR5cGUge251bWJlcn1cbiAgICovXG4gIHZhciBNQVhfQ0FDSEVfU0laRSA9IDEwMjQ7XG4gIC8qKlxuICAgKiBAdHlwZSB7T2JqZWN0PHN0cmluZywgQ29sb3I+fVxuICAgKi9cblxuICB2YXIgY2FjaGUgPSB7fTtcbiAgLyoqXG4gICAqIEB0eXBlIHtudW1iZXJ9XG4gICAqL1xuXG4gIHZhciBjYWNoZVNpemUgPSAwO1xuICByZXR1cm4gKFxuICAgIC8qKlxuICAgICAqIEBwYXJhbSB7c3RyaW5nfSBzIFN0cmluZy5cbiAgICAgKiBAcmV0dXJuIHtDb2xvcn0gQ29sb3IuXG4gICAgICovXG4gICAgZnVuY3Rpb24gKHMpIHtcbiAgICAgIHZhciBjb2xvcjtcblxuICAgICAgaWYgKGNhY2hlLmhhc093blByb3BlcnR5KHMpKSB7XG4gICAgICAgIGNvbG9yID0gY2FjaGVbc107XG4gICAgICB9IGVsc2Uge1xuICAgICAgICBpZiAoY2FjaGVTaXplID49IE1BWF9DQUNIRV9TSVpFKSB7XG4gICAgICAgICAgdmFyIGkgPSAwO1xuXG4gICAgICAgICAgZm9yICh2YXIga2V5IGluIGNhY2hlKSB7XG4gICAgICAgICAgICBpZiAoKGkrKyAmIDMpID09PSAwKSB7XG4gICAgICAgICAgICAgIGRlbGV0ZSBjYWNoZVtrZXldO1xuICAgICAgICAgICAgICAtLWNhY2hlU2l6ZTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgICB9XG4gICAgICAgIH1cblxuICAgICAgICBjb2xvciA9IGZyb21TdHJpbmdJbnRlcm5hbF8ocyk7XG4gICAgICAgIGNhY2hlW3NdID0gY29sb3I7XG4gICAgICAgICsrY2FjaGVTaXplO1xuICAgICAgfVxuXG4gICAgICByZXR1cm4gY29sb3I7XG4gICAgfVxuICApO1xufSgpO1xuLyoqXG4gKiBSZXR1cm4gdGhlIGNvbG9yIGFzIGFuIGFycmF5LiBUaGlzIGZ1bmN0aW9uIG1haW50YWlucyBhIGNhY2hlIG9mIGNhbGN1bGF0ZWRcbiAqIGFycmF5cyB3aGljaCBtZWFucyB0aGUgcmVzdWx0IHNob3VsZCBub3QgYmUgbW9kaWZpZWQuXG4gKiBAcGFyYW0ge0NvbG9yfHN0cmluZ30gY29sb3IgQ29sb3IuXG4gKiBAcmV0dXJuIHtDb2xvcn0gQ29sb3IuXG4gKiBAYXBpXG4gKi9cblxuZXhwb3J0IGZ1bmN0aW9uIGFzQXJyYXkoY29sb3IpIHtcbiAgaWYgKEFycmF5LmlzQXJyYXkoY29sb3IpKSB7XG4gICAgcmV0dXJuIGNvbG9yO1xuICB9IGVsc2Uge1xuICAgIHJldHVybiBmcm9tU3RyaW5nKGNvbG9yKTtcbiAgfVxufVxuLyoqXG4gKiBAcGFyYW0ge3N0cmluZ30gcyBTdHJpbmcuXG4gKiBAcHJpdmF0ZVxuICogQHJldHVybiB7Q29sb3J9IENvbG9yLlxuICovXG5cbmZ1bmN0aW9uIGZyb21TdHJpbmdJbnRlcm5hbF8ocykge1xuICB2YXIgciwgZywgYiwgYSwgY29sb3I7XG5cbiAgaWYgKE5BTUVEX0NPTE9SX1JFXy5leGVjKHMpKSB7XG4gICAgcyA9IGZyb21OYW1lZChzKTtcbiAgfVxuXG4gIGlmIChIRVhfQ09MT1JfUkVfLmV4ZWMocykpIHtcbiAgICAvLyBoZXhcbiAgICB2YXIgbiA9IHMubGVuZ3RoIC0gMTsgLy8gbnVtYmVyIG9mIGhleCBkaWdpdHNcblxuICAgIHZhciBkID0gLy8gbnVtYmVyIG9mIGRpZ2l0cyBwZXIgY2hhbm5lbFxuICAgIHZvaWQgMDsgLy8gbnVtYmVyIG9mIGRpZ2l0cyBwZXIgY2hhbm5lbFxuXG4gICAgaWYgKG4gPD0gNCkge1xuICAgICAgZCA9IDE7XG4gICAgfSBlbHNlIHtcbiAgICAgIGQgPSAyO1xuICAgIH1cblxuICAgIHZhciBoYXNBbHBoYSA9IG4gPT09IDQgfHwgbiA9PT0gODtcbiAgICByID0gcGFyc2VJbnQocy5zdWJzdHIoMSArIDAgKiBkLCBkKSwgMTYpO1xuICAgIGcgPSBwYXJzZUludChzLnN1YnN0cigxICsgMSAqIGQsIGQpLCAxNik7XG4gICAgYiA9IHBhcnNlSW50KHMuc3Vic3RyKDEgKyAyICogZCwgZCksIDE2KTtcblxuICAgIGlmIChoYXNBbHBoYSkge1xuICAgICAgYSA9IHBhcnNlSW50KHMuc3Vic3RyKDEgKyAzICogZCwgZCksIDE2KTtcbiAgICB9IGVsc2Uge1xuICAgICAgYSA9IDI1NTtcbiAgICB9XG5cbiAgICBpZiAoZCA9PSAxKSB7XG4gICAgICByID0gKHIgPDwgNCkgKyByO1xuICAgICAgZyA9IChnIDw8IDQpICsgZztcbiAgICAgIGIgPSAoYiA8PCA0KSArIGI7XG5cbiAgICAgIGlmIChoYXNBbHBoYSkge1xuICAgICAgICBhID0gKGEgPDwgNCkgKyBhO1xuICAgICAgfVxuICAgIH1cblxuICAgIGNvbG9yID0gW3IsIGcsIGIsIGEgLyAyNTVdO1xuICB9IGVsc2UgaWYgKHMuaW5kZXhPZigncmdiYSgnKSA9PSAwKSB7XG4gICAgLy8gcmdiYSgpXG4gICAgY29sb3IgPSBzLnNsaWNlKDUsIC0xKS5zcGxpdCgnLCcpLm1hcChOdW1iZXIpO1xuICAgIG5vcm1hbGl6ZShjb2xvcik7XG4gIH0gZWxzZSBpZiAocy5pbmRleE9mKCdyZ2IoJykgPT0gMCkge1xuICAgIC8vIHJnYigpXG4gICAgY29sb3IgPSBzLnNsaWNlKDQsIC0xKS5zcGxpdCgnLCcpLm1hcChOdW1iZXIpO1xuICAgIGNvbG9yLnB1c2goMSk7XG4gICAgbm9ybWFsaXplKGNvbG9yKTtcbiAgfSBlbHNlIHtcbiAgICBhc3NlcnQoZmFsc2UsIDE0KTsgLy8gSW52YWxpZCBjb2xvclxuICB9XG5cbiAgcmV0dXJuIGNvbG9yO1xufVxuLyoqXG4gKiBUT0RPIHRoaXMgZnVuY3Rpb24gaXMgb25seSB1c2VkIGluIHRoZSB0ZXN0LCB3ZSBwcm9iYWJseSBzaG91bGRuJ3QgZXhwb3J0IGl0XG4gKiBAcGFyYW0ge0NvbG9yfSBjb2xvciBDb2xvci5cbiAqIEByZXR1cm4ge0NvbG9yfSBDbGFtcGVkIGNvbG9yLlxuICovXG5cblxuZXhwb3J0IGZ1bmN0aW9uIG5vcm1hbGl6ZShjb2xvcikge1xuICBjb2xvclswXSA9IGNsYW1wKGNvbG9yWzBdICsgMC41IHwgMCwgMCwgMjU1KTtcbiAgY29sb3JbMV0gPSBjbGFtcChjb2xvclsxXSArIDAuNSB8IDAsIDAsIDI1NSk7XG4gIGNvbG9yWzJdID0gY2xhbXAoY29sb3JbMl0gKyAwLjUgfCAwLCAwLCAyNTUpO1xuICBjb2xvclszXSA9IGNsYW1wKGNvbG9yWzNdLCAwLCAxKTtcbiAgcmV0dXJuIGNvbG9yO1xufVxuLyoqXG4gKiBAcGFyYW0ge0NvbG9yfSBjb2xvciBDb2xvci5cbiAqIEByZXR1cm4ge3N0cmluZ30gU3RyaW5nLlxuICovXG5cbmV4cG9ydCBmdW5jdGlvbiB0b1N0cmluZyhjb2xvcikge1xuICB2YXIgciA9IGNvbG9yWzBdO1xuXG4gIGlmIChyICE9IChyIHwgMCkpIHtcbiAgICByID0gciArIDAuNSB8IDA7XG4gIH1cblxuICB2YXIgZyA9IGNvbG9yWzFdO1xuXG4gIGlmIChnICE9IChnIHwgMCkpIHtcbiAgICBnID0gZyArIDAuNSB8IDA7XG4gIH1cblxuICB2YXIgYiA9IGNvbG9yWzJdO1xuXG4gIGlmIChiICE9IChiIHwgMCkpIHtcbiAgICBiID0gYiArIDAuNSB8IDA7XG4gIH1cblxuICB2YXIgYSA9IGNvbG9yWzNdID09PSB1bmRlZmluZWQgPyAxIDogY29sb3JbM107XG4gIHJldHVybiAncmdiYSgnICsgciArICcsJyArIGcgKyAnLCcgKyBiICsgJywnICsgYSArICcpJztcbn1cbi8qKlxuICogQHBhcmFtIHtzdHJpbmd9IHMgU3RyaW5nLlxuICogQHJldHVybiB7Ym9vbGVhbn0gV2hldGhlciB0aGUgc3RyaW5nIGlzIGFjdHVhbGx5IGEgdmFsaWQgY29sb3JcbiAqL1xuXG5leHBvcnQgZnVuY3Rpb24gaXNTdHJpbmdDb2xvcihzKSB7XG4gIGlmIChOQU1FRF9DT0xPUl9SRV8udGVzdChzKSkge1xuICAgIHMgPSBmcm9tTmFtZWQocyk7XG4gIH1cblxuICByZXR1cm4gSEVYX0NPTE9SX1JFXy50ZXN0KHMpIHx8IHMuaW5kZXhPZigncmdiYSgnKSA9PT0gMCB8fCBzLmluZGV4T2YoJ3JnYignKSA9PT0gMDtcbn0iLCIvKipcbiAqIEBtb2R1bGUgb2wvc3R5bGUvSWNvbkltYWdlQ2FjaGVcbiAqL1xuaW1wb3J0IHsgYXNTdHJpbmcgfSBmcm9tICcuLi9jb2xvci5qcyc7XG4vKipcbiAqIEBjbGFzc2Rlc2NcbiAqIFNpbmdsZXRvbiBjbGFzcy4gQXZhaWxhYmxlIHRocm91Z2gge0BsaW5rIG1vZHVsZTpvbC9zdHlsZS9JY29uSW1hZ2VDYWNoZX5zaGFyZWR9LlxuICovXG5cbnZhciBJY29uSW1hZ2VDYWNoZSA9XG4vKiogQGNsYXNzICovXG5mdW5jdGlvbiAoKSB7XG4gIGZ1bmN0aW9uIEljb25JbWFnZUNhY2hlKCkge1xuICAgIC8qKlxuICAgICAqIEB0eXBlIHshT2JqZWN0PHN0cmluZywgaW1wb3J0KFwiLi9JY29uSW1hZ2UuanNcIikuZGVmYXVsdD59XG4gICAgICogQHByaXZhdGVcbiAgICAgKi9cbiAgICB0aGlzLmNhY2hlXyA9IHt9O1xuICAgIC8qKlxuICAgICAqIEB0eXBlIHtudW1iZXJ9XG4gICAgICogQHByaXZhdGVcbiAgICAgKi9cblxuICAgIHRoaXMuY2FjaGVTaXplXyA9IDA7XG4gICAgLyoqXG4gICAgICogQHR5cGUge251bWJlcn1cbiAgICAgKiBAcHJpdmF0ZVxuICAgICAqL1xuXG4gICAgdGhpcy5tYXhDYWNoZVNpemVfID0gMzI7XG4gIH1cbiAgLyoqXG4gICAqIEZJWE1FIGVtcHR5IGRlc2NyaXB0aW9uIGZvciBqc2RvY1xuICAgKi9cblxuXG4gIEljb25JbWFnZUNhY2hlLnByb3RvdHlwZS5jbGVhciA9IGZ1bmN0aW9uICgpIHtcbiAgICB0aGlzLmNhY2hlXyA9IHt9O1xuICAgIHRoaXMuY2FjaGVTaXplXyA9IDA7XG4gIH07XG4gIC8qKlxuICAgKiBAcmV0dXJuIHtib29sZWFufSBDYW4gZXhwaXJlIGNhY2hlLlxuICAgKi9cblxuXG4gIEljb25JbWFnZUNhY2hlLnByb3RvdHlwZS5jYW5FeHBpcmVDYWNoZSA9IGZ1bmN0aW9uICgpIHtcbiAgICByZXR1cm4gdGhpcy5jYWNoZVNpemVfID4gdGhpcy5tYXhDYWNoZVNpemVfO1xuICB9O1xuICAvKipcbiAgICogRklYTUUgZW1wdHkgZGVzY3JpcHRpb24gZm9yIGpzZG9jXG4gICAqL1xuXG5cbiAgSWNvbkltYWdlQ2FjaGUucHJvdG90eXBlLmV4cGlyZSA9IGZ1bmN0aW9uICgpIHtcbiAgICBpZiAodGhpcy5jYW5FeHBpcmVDYWNoZSgpKSB7XG4gICAgICB2YXIgaSA9IDA7XG5cbiAgICAgIGZvciAodmFyIGtleSBpbiB0aGlzLmNhY2hlXykge1xuICAgICAgICB2YXIgaWNvbkltYWdlID0gdGhpcy5jYWNoZV9ba2V5XTtcblxuICAgICAgICBpZiAoKGkrKyAmIDMpID09PSAwICYmICFpY29uSW1hZ2UuaGFzTGlzdGVuZXIoKSkge1xuICAgICAgICAgIGRlbGV0ZSB0aGlzLmNhY2hlX1trZXldO1xuICAgICAgICAgIC0tdGhpcy5jYWNoZVNpemVfO1xuICAgICAgICB9XG4gICAgICB9XG4gICAgfVxuICB9O1xuICAvKipcbiAgICogQHBhcmFtIHtzdHJpbmd9IHNyYyBTcmMuXG4gICAqIEBwYXJhbSB7P3N0cmluZ30gY3Jvc3NPcmlnaW4gQ3Jvc3Mgb3JpZ2luLlxuICAgKiBAcGFyYW0ge2ltcG9ydChcIi4uL2NvbG9yLmpzXCIpLkNvbG9yfSBjb2xvciBDb2xvci5cbiAgICogQHJldHVybiB7aW1wb3J0KFwiLi9JY29uSW1hZ2UuanNcIikuZGVmYXVsdH0gSWNvbiBpbWFnZS5cbiAgICovXG5cblxuICBJY29uSW1hZ2VDYWNoZS5wcm90b3R5cGUuZ2V0ID0gZnVuY3Rpb24gKHNyYywgY3Jvc3NPcmlnaW4sIGNvbG9yKSB7XG4gICAgdmFyIGtleSA9IGdldEtleShzcmMsIGNyb3NzT3JpZ2luLCBjb2xvcik7XG4gICAgcmV0dXJuIGtleSBpbiB0aGlzLmNhY2hlXyA/IHRoaXMuY2FjaGVfW2tleV0gOiBudWxsO1xuICB9O1xuICAvKipcbiAgICogQHBhcmFtIHtzdHJpbmd9IHNyYyBTcmMuXG4gICAqIEBwYXJhbSB7P3N0cmluZ30gY3Jvc3NPcmlnaW4gQ3Jvc3Mgb3JpZ2luLlxuICAgKiBAcGFyYW0ge2ltcG9ydChcIi4uL2NvbG9yLmpzXCIpLkNvbG9yfSBjb2xvciBDb2xvci5cbiAgICogQHBhcmFtIHtpbXBvcnQoXCIuL0ljb25JbWFnZS5qc1wiKS5kZWZhdWx0fSBpY29uSW1hZ2UgSWNvbiBpbWFnZS5cbiAgICovXG5cblxuICBJY29uSW1hZ2VDYWNoZS5wcm90b3R5cGUuc2V0ID0gZnVuY3Rpb24gKHNyYywgY3Jvc3NPcmlnaW4sIGNvbG9yLCBpY29uSW1hZ2UpIHtcbiAgICB2YXIga2V5ID0gZ2V0S2V5KHNyYywgY3Jvc3NPcmlnaW4sIGNvbG9yKTtcbiAgICB0aGlzLmNhY2hlX1trZXldID0gaWNvbkltYWdlO1xuICAgICsrdGhpcy5jYWNoZVNpemVfO1xuICB9O1xuICAvKipcbiAgICogU2V0IHRoZSBjYWNoZSBzaXplIG9mIHRoZSBpY29uIGNhY2hlLiBEZWZhdWx0IGlzIGAzMmAuIENoYW5nZSB0aGlzIHZhbHVlIHdoZW5cbiAgICogeW91ciBtYXAgdXNlcyBtb3JlIHRoYW4gMzIgZGlmZmVyZW50IGljb24gaW1hZ2VzIGFuZCB5b3UgYXJlIG5vdCBjYWNoaW5nIGljb25cbiAgICogc3R5bGVzIG9uIHRoZSBhcHBsaWNhdGlvbiBsZXZlbC5cbiAgICogQHBhcmFtIHtudW1iZXJ9IG1heENhY2hlU2l6ZSBDYWNoZSBtYXggc2l6ZS5cbiAgICogQGFwaVxuICAgKi9cblxuXG4gIEljb25JbWFnZUNhY2hlLnByb3RvdHlwZS5zZXRTaXplID0gZnVuY3Rpb24gKG1heENhY2hlU2l6ZSkge1xuICAgIHRoaXMubWF4Q2FjaGVTaXplXyA9IG1heENhY2hlU2l6ZTtcbiAgICB0aGlzLmV4cGlyZSgpO1xuICB9O1xuXG4gIHJldHVybiBJY29uSW1hZ2VDYWNoZTtcbn0oKTtcbi8qKlxuICogQHBhcmFtIHtzdHJpbmd9IHNyYyBTcmMuXG4gKiBAcGFyYW0gez9zdHJpbmd9IGNyb3NzT3JpZ2luIENyb3NzIG9yaWdpbi5cbiAqIEBwYXJhbSB7aW1wb3J0KFwiLi4vY29sb3IuanNcIikuQ29sb3J9IGNvbG9yIENvbG9yLlxuICogQHJldHVybiB7c3RyaW5nfSBDYWNoZSBrZXkuXG4gKi9cblxuXG5mdW5jdGlvbiBnZXRLZXkoc3JjLCBjcm9zc09yaWdpbiwgY29sb3IpIHtcbiAgdmFyIGNvbG9yU3RyaW5nID0gY29sb3IgPyBhc1N0cmluZyhjb2xvcikgOiAnbnVsbCc7XG4gIHJldHVybiBjcm9zc09yaWdpbiArICc6JyArIHNyYyArICc6JyArIGNvbG9yU3RyaW5nO1xufVxuXG5leHBvcnQgZGVmYXVsdCBJY29uSW1hZ2VDYWNoZTtcbi8qKlxuICogVGhlIHtAbGluayBtb2R1bGU6b2wvc3R5bGUvSWNvbkltYWdlQ2FjaGV+SWNvbkltYWdlQ2FjaGV9IGZvclxuICoge0BsaW5rIG1vZHVsZTpvbC9zdHlsZS9JY29ufkljb259IGltYWdlcy5cbiAqIEBhcGlcbiAqL1xuXG5leHBvcnQgdmFyIHNoYXJlZCA9IG5ldyBJY29uSW1hZ2VDYWNoZSgpOyIsIi8qKlxuICogQG1vZHVsZSBvbC9ldmVudHMvRXZlbnRcbiAqL1xuXG4vKipcbiAqIEBjbGFzc2Rlc2NcbiAqIFN0cmlwcGVkIGRvd24gaW1wbGVtZW50YXRpb24gb2YgdGhlIFczQyBET00gTGV2ZWwgMiBFdmVudCBpbnRlcmZhY2UuXG4gKiBTZWUgaHR0cHM6Ly93d3cudzMub3JnL1RSL0RPTS1MZXZlbC0yLUV2ZW50cy9ldmVudHMuaHRtbCNFdmVudHMtaW50ZXJmYWNlLlxuICpcbiAqIFRoaXMgaW1wbGVtZW50YXRpb24gb25seSBwcm92aWRlcyBgdHlwZWAgYW5kIGB0YXJnZXRgIHByb3BlcnRpZXMsIGFuZFxuICogYHN0b3BQcm9wYWdhdGlvbmAgYW5kIGBwcmV2ZW50RGVmYXVsdGAgbWV0aG9kcy4gSXQgaXMgbWVhbnQgYXMgYmFzZSBjbGFzc1xuICogZm9yIGhpZ2hlciBsZXZlbCBldmVudHMgZGVmaW5lZCBpbiB0aGUgbGlicmFyeSwgYW5kIHdvcmtzIHdpdGhcbiAqIHtAbGluayBtb2R1bGU6b2wvZXZlbnRzL1RhcmdldH5UYXJnZXR9LlxuICovXG52YXIgQmFzZUV2ZW50ID1cbi8qKiBAY2xhc3MgKi9cbmZ1bmN0aW9uICgpIHtcbiAgLyoqXG4gICAqIEBwYXJhbSB7c3RyaW5nfSB0eXBlIFR5cGUuXG4gICAqL1xuICBmdW5jdGlvbiBCYXNlRXZlbnQodHlwZSkge1xuICAgIC8qKlxuICAgICAqIEB0eXBlIHtib29sZWFufVxuICAgICAqL1xuICAgIHRoaXMucHJvcGFnYXRpb25TdG9wcGVkO1xuICAgIC8qKlxuICAgICAqIFRoZSBldmVudCB0eXBlLlxuICAgICAqIEB0eXBlIHtzdHJpbmd9XG4gICAgICogQGFwaVxuICAgICAqL1xuXG4gICAgdGhpcy50eXBlID0gdHlwZTtcbiAgICAvKipcbiAgICAgKiBUaGUgZXZlbnQgdGFyZ2V0LlxuICAgICAqIEB0eXBlIHtPYmplY3R9XG4gICAgICogQGFwaVxuICAgICAqL1xuXG4gICAgdGhpcy50YXJnZXQgPSBudWxsO1xuICB9XG4gIC8qKlxuICAgKiBTdG9wIGV2ZW50IHByb3BhZ2F0aW9uLlxuICAgKiBAYXBpXG4gICAqL1xuXG5cbiAgQmFzZUV2ZW50LnByb3RvdHlwZS5wcmV2ZW50RGVmYXVsdCA9IGZ1bmN0aW9uICgpIHtcbiAgICB0aGlzLnByb3BhZ2F0aW9uU3RvcHBlZCA9IHRydWU7XG4gIH07XG4gIC8qKlxuICAgKiBTdG9wIGV2ZW50IHByb3BhZ2F0aW9uLlxuICAgKiBAYXBpXG4gICAqL1xuXG5cbiAgQmFzZUV2ZW50LnByb3RvdHlwZS5zdG9wUHJvcGFnYXRpb24gPSBmdW5jdGlvbiAoKSB7XG4gICAgdGhpcy5wcm9wYWdhdGlvblN0b3BwZWQgPSB0cnVlO1xuICB9O1xuXG4gIHJldHVybiBCYXNlRXZlbnQ7XG59KCk7XG4vKipcbiAqIEBwYXJhbSB7RXZlbnR8aW1wb3J0KFwiLi9FdmVudC5qc1wiKS5kZWZhdWx0fSBldnQgRXZlbnRcbiAqL1xuXG5cbmV4cG9ydCBmdW5jdGlvbiBzdG9wUHJvcGFnYXRpb24oZXZ0KSB7XG4gIGV2dC5zdG9wUHJvcGFnYXRpb24oKTtcbn1cbi8qKlxuICogQHBhcmFtIHtFdmVudHxpbXBvcnQoXCIuL0V2ZW50LmpzXCIpLmRlZmF1bHR9IGV2dCBFdmVudFxuICovXG5cbmV4cG9ydCBmdW5jdGlvbiBwcmV2ZW50RGVmYXVsdChldnQpIHtcbiAgZXZ0LnByZXZlbnREZWZhdWx0KCk7XG59XG5leHBvcnQgZGVmYXVsdCBCYXNlRXZlbnQ7IiwiLyoqXG4gKiBAbW9kdWxlIG9sL09iamVjdEV2ZW50VHlwZVxuICovXG5cbi8qKlxuICogQGVudW0ge3N0cmluZ31cbiAqL1xuZXhwb3J0IGRlZmF1bHQge1xuICAvKipcbiAgICogVHJpZ2dlcmVkIHdoZW4gYSBwcm9wZXJ0eSBpcyBjaGFuZ2VkLlxuICAgKiBAZXZlbnQgbW9kdWxlOm9sL09iamVjdC5PYmplY3RFdmVudCNwcm9wZXJ0eWNoYW5nZVxuICAgKiBAYXBpXG4gICAqL1xuICBQUk9QRVJUWUNIQU5HRTogJ3Byb3BlcnR5Y2hhbmdlJ1xufTsiLCIvKipcbiAqIEBtb2R1bGUgb2wvb2JqXG4gKi9cblxuLyoqXG4gKiBQb2x5ZmlsbCBmb3IgT2JqZWN0LmFzc2lnbigpLiAgQXNzaWducyBlbnVtZXJhYmxlIGFuZCBvd24gcHJvcGVydGllcyBmcm9tXG4gKiBvbmUgb3IgbW9yZSBzb3VyY2Ugb2JqZWN0cyB0byBhIHRhcmdldCBvYmplY3QuXG4gKiBTZWUgaHR0cHM6Ly9kZXZlbG9wZXIubW96aWxsYS5vcmcvZW4vZG9jcy9XZWIvSmF2YVNjcmlwdC9SZWZlcmVuY2UvR2xvYmFsX09iamVjdHMvT2JqZWN0L2Fzc2lnbi5cbiAqXG4gKiBAcGFyYW0geyFPYmplY3R9IHRhcmdldCBUaGUgdGFyZ2V0IG9iamVjdC5cbiAqIEBwYXJhbSB7Li4uT2JqZWN0fSB2YXJfc291cmNlcyBUaGUgc291cmNlIG9iamVjdChzKS5cbiAqIEByZXR1cm4geyFPYmplY3R9IFRoZSBtb2RpZmllZCB0YXJnZXQgb2JqZWN0LlxuICovXG5leHBvcnQgdmFyIGFzc2lnbiA9IHR5cGVvZiBPYmplY3QuYXNzaWduID09PSAnZnVuY3Rpb24nID8gT2JqZWN0LmFzc2lnbiA6IGZ1bmN0aW9uICh0YXJnZXQsIHZhcl9zb3VyY2VzKSB7XG4gIGlmICh0YXJnZXQgPT09IHVuZGVmaW5lZCB8fCB0YXJnZXQgPT09IG51bGwpIHtcbiAgICB0aHJvdyBuZXcgVHlwZUVycm9yKCdDYW5ub3QgY29udmVydCB1bmRlZmluZWQgb3IgbnVsbCB0byBvYmplY3QnKTtcbiAgfVxuXG4gIHZhciBvdXRwdXQgPSBPYmplY3QodGFyZ2V0KTtcblxuICBmb3IgKHZhciBpID0gMSwgaWkgPSBhcmd1bWVudHMubGVuZ3RoOyBpIDwgaWk7ICsraSkge1xuICAgIHZhciBzb3VyY2UgPSBhcmd1bWVudHNbaV07XG5cbiAgICBpZiAoc291cmNlICE9PSB1bmRlZmluZWQgJiYgc291cmNlICE9PSBudWxsKSB7XG4gICAgICBmb3IgKHZhciBrZXkgaW4gc291cmNlKSB7XG4gICAgICAgIGlmIChzb3VyY2UuaGFzT3duUHJvcGVydHkoa2V5KSkge1xuICAgICAgICAgIG91dHB1dFtrZXldID0gc291cmNlW2tleV07XG4gICAgICAgIH1cbiAgICAgIH1cbiAgICB9XG4gIH1cblxuICByZXR1cm4gb3V0cHV0O1xufTtcbi8qKlxuICogUmVtb3ZlcyBhbGwgcHJvcGVydGllcyBmcm9tIGFuIG9iamVjdC5cbiAqIEBwYXJhbSB7T2JqZWN0fSBvYmplY3QgVGhlIG9iamVjdCB0byBjbGVhci5cbiAqL1xuXG5leHBvcnQgZnVuY3Rpb24gY2xlYXIob2JqZWN0KSB7XG4gIGZvciAodmFyIHByb3BlcnR5IGluIG9iamVjdCkge1xuICAgIGRlbGV0ZSBvYmplY3RbcHJvcGVydHldO1xuICB9XG59XG4vKipcbiAqIFBvbHlmaWxsIGZvciBPYmplY3QudmFsdWVzKCkuICBHZXQgYW4gYXJyYXkgb2YgcHJvcGVydHkgdmFsdWVzIGZyb20gYW4gb2JqZWN0LlxuICogU2VlIGh0dHBzOi8vZGV2ZWxvcGVyLm1vemlsbGEub3JnL2VuLVVTL2RvY3MvV2ViL0phdmFTY3JpcHQvUmVmZXJlbmNlL0dsb2JhbF9PYmplY3RzL09iamVjdC92YWx1ZXNcbiAqXG4gKiBAcGFyYW0geyFPYmplY3Q8SyxWPn0gb2JqZWN0IFRoZSBvYmplY3QgZnJvbSB3aGljaCB0byBnZXQgdGhlIHZhbHVlcy5cbiAqIEByZXR1cm4geyFBcnJheTxWPn0gVGhlIHByb3BlcnR5IHZhbHVlcy5cbiAqIEB0ZW1wbGF0ZSBLLFZcbiAqL1xuXG5leHBvcnQgdmFyIGdldFZhbHVlcyA9IHR5cGVvZiBPYmplY3QudmFsdWVzID09PSAnZnVuY3Rpb24nID8gT2JqZWN0LnZhbHVlcyA6IGZ1bmN0aW9uIChvYmplY3QpIHtcbiAgdmFyIHZhbHVlcyA9IFtdO1xuXG4gIGZvciAodmFyIHByb3BlcnR5IGluIG9iamVjdCkge1xuICAgIHZhbHVlcy5wdXNoKG9iamVjdFtwcm9wZXJ0eV0pO1xuICB9XG5cbiAgcmV0dXJuIHZhbHVlcztcbn07XG4vKipcbiAqIERldGVybWluZSBpZiBhbiBvYmplY3QgaGFzIGFueSBwcm9wZXJ0aWVzLlxuICogQHBhcmFtIHtPYmplY3R9IG9iamVjdCBUaGUgb2JqZWN0IHRvIGNoZWNrLlxuICogQHJldHVybiB7Ym9vbGVhbn0gVGhlIG9iamVjdCBpcyBlbXB0eS5cbiAqL1xuXG5leHBvcnQgZnVuY3Rpb24gaXNFbXB0eShvYmplY3QpIHtcbiAgdmFyIHByb3BlcnR5O1xuXG4gIGZvciAocHJvcGVydHkgaW4gb2JqZWN0KSB7XG4gICAgcmV0dXJuIGZhbHNlO1xuICB9XG5cbiAgcmV0dXJuICFwcm9wZXJ0eTtcbn0iLCJ2YXIgX19leHRlbmRzID0gdGhpcyAmJiB0aGlzLl9fZXh0ZW5kcyB8fCBmdW5jdGlvbiAoKSB7XG4gIHZhciBfZXh0ZW5kU3RhdGljcyA9IGZ1bmN0aW9uIGV4dGVuZFN0YXRpY3MoZCwgYikge1xuICAgIF9leHRlbmRTdGF0aWNzID0gT2JqZWN0LnNldFByb3RvdHlwZU9mIHx8IHtcbiAgICAgIF9fcHJvdG9fXzogW11cbiAgICB9IGluc3RhbmNlb2YgQXJyYXkgJiYgZnVuY3Rpb24gKGQsIGIpIHtcbiAgICAgIGQuX19wcm90b19fID0gYjtcbiAgICB9IHx8IGZ1bmN0aW9uIChkLCBiKSB7XG4gICAgICBmb3IgKHZhciBwIGluIGIpIHtcbiAgICAgICAgaWYgKE9iamVjdC5wcm90b3R5cGUuaGFzT3duUHJvcGVydHkuY2FsbChiLCBwKSkgZFtwXSA9IGJbcF07XG4gICAgICB9XG4gICAgfTtcblxuICAgIHJldHVybiBfZXh0ZW5kU3RhdGljcyhkLCBiKTtcbiAgfTtcblxuICByZXR1cm4gZnVuY3Rpb24gKGQsIGIpIHtcbiAgICBfZXh0ZW5kU3RhdGljcyhkLCBiKTtcblxuICAgIGZ1bmN0aW9uIF9fKCkge1xuICAgICAgdGhpcy5jb25zdHJ1Y3RvciA9IGQ7XG4gICAgfVxuXG4gICAgZC5wcm90b3R5cGUgPSBiID09PSBudWxsID8gT2JqZWN0LmNyZWF0ZShiKSA6IChfXy5wcm90b3R5cGUgPSBiLnByb3RvdHlwZSwgbmV3IF9fKCkpO1xuICB9O1xufSgpO1xuLyoqXG4gKiBAbW9kdWxlIG9sL2V2ZW50cy9UYXJnZXRcbiAqL1xuXG5cbmltcG9ydCBEaXNwb3NhYmxlIGZyb20gJy4uL0Rpc3Bvc2FibGUuanMnO1xuaW1wb3J0IEV2ZW50IGZyb20gJy4vRXZlbnQuanMnO1xuaW1wb3J0IHsgVk9JRCB9IGZyb20gJy4uL2Z1bmN0aW9ucy5qcyc7XG5pbXBvcnQgeyBjbGVhciB9IGZyb20gJy4uL29iai5qcyc7XG4vKipcbiAqIEB0eXBlZGVmIHtFdmVudFRhcmdldHxUYXJnZXR9IEV2ZW50VGFyZ2V0TGlrZVxuICovXG5cbi8qKlxuICogQGNsYXNzZGVzY1xuICogQSBzaW1wbGlmaWVkIGltcGxlbWVudGF0aW9uIG9mIHRoZSBXM0MgRE9NIExldmVsIDIgRXZlbnRUYXJnZXQgaW50ZXJmYWNlLlxuICogU2VlIGh0dHBzOi8vd3d3LnczLm9yZy9UUi8yMDAwL1JFQy1ET00tTGV2ZWwtMi1FdmVudHMtMjAwMDExMTMvZXZlbnRzLmh0bWwjRXZlbnRzLUV2ZW50VGFyZ2V0LlxuICpcbiAqIFRoZXJlIGFyZSB0d28gaW1wb3J0YW50IHNpbXBsaWZpY2F0aW9ucyBjb21wYXJlZCB0byB0aGUgc3BlY2lmaWNhdGlvbjpcbiAqXG4gKiAxLiBUaGUgaGFuZGxpbmcgb2YgYHVzZUNhcHR1cmVgIGluIGBhZGRFdmVudExpc3RlbmVyYCBhbmRcbiAqICAgIGByZW1vdmVFdmVudExpc3RlbmVyYC4gVGhlcmUgaXMgbm8gcmVhbCBjYXB0dXJlIG1vZGVsLlxuICogMi4gVGhlIGhhbmRsaW5nIG9mIGBzdG9wUHJvcGFnYXRpb25gIGFuZCBgcHJldmVudERlZmF1bHRgIG9uIGBkaXNwYXRjaEV2ZW50YC5cbiAqICAgIFRoZXJlIGlzIG5vIGV2ZW50IHRhcmdldCBoaWVyYXJjaHkuIFdoZW4gYSBsaXN0ZW5lciBjYWxsc1xuICogICAgYHN0b3BQcm9wYWdhdGlvbmAgb3IgYHByZXZlbnREZWZhdWx0YCBvbiBhbiBldmVudCBvYmplY3QsIGl0IG1lYW5zIHRoYXQgbm9cbiAqICAgIG1vcmUgbGlzdGVuZXJzIGFmdGVyIHRoaXMgb25lIHdpbGwgYmUgY2FsbGVkLiBTYW1lIGFzIHdoZW4gdGhlIGxpc3RlbmVyXG4gKiAgICByZXR1cm5zIGZhbHNlLlxuICovXG5cbnZhciBUYXJnZXQgPVxuLyoqIEBjbGFzcyAqL1xuZnVuY3Rpb24gKF9zdXBlcikge1xuICBfX2V4dGVuZHMoVGFyZ2V0LCBfc3VwZXIpO1xuICAvKipcbiAgICogQHBhcmFtIHsqPX0gb3B0X3RhcmdldCBEZWZhdWx0IGV2ZW50IHRhcmdldCBmb3IgZGlzcGF0Y2hlZCBldmVudHMuXG4gICAqL1xuXG5cbiAgZnVuY3Rpb24gVGFyZ2V0KG9wdF90YXJnZXQpIHtcbiAgICB2YXIgX3RoaXMgPSBfc3VwZXIuY2FsbCh0aGlzKSB8fCB0aGlzO1xuICAgIC8qKlxuICAgICAqIEBwcml2YXRlXG4gICAgICogQHR5cGUgeyp9XG4gICAgICovXG5cblxuICAgIF90aGlzLmV2ZW50VGFyZ2V0XyA9IG9wdF90YXJnZXQ7XG4gICAgLyoqXG4gICAgICogQHByaXZhdGVcbiAgICAgKiBAdHlwZSB7T2JqZWN0PHN0cmluZywgbnVtYmVyPn1cbiAgICAgKi9cblxuICAgIF90aGlzLnBlbmRpbmdSZW1vdmFsc18gPSBudWxsO1xuICAgIC8qKlxuICAgICAqIEBwcml2YXRlXG4gICAgICogQHR5cGUge09iamVjdDxzdHJpbmcsIG51bWJlcj59XG4gICAgICovXG5cbiAgICBfdGhpcy5kaXNwYXRjaGluZ18gPSBudWxsO1xuICAgIC8qKlxuICAgICAqIEBwcml2YXRlXG4gICAgICogQHR5cGUge09iamVjdDxzdHJpbmcsIEFycmF5PGltcG9ydChcIi4uL2V2ZW50cy5qc1wiKS5MaXN0ZW5lcj4+fVxuICAgICAqL1xuXG4gICAgX3RoaXMubGlzdGVuZXJzXyA9IG51bGw7XG4gICAgcmV0dXJuIF90aGlzO1xuICB9XG4gIC8qKlxuICAgKiBAcGFyYW0ge3N0cmluZ30gdHlwZSBUeXBlLlxuICAgKiBAcGFyYW0ge2ltcG9ydChcIi4uL2V2ZW50cy5qc1wiKS5MaXN0ZW5lcn0gbGlzdGVuZXIgTGlzdGVuZXIuXG4gICAqL1xuXG5cbiAgVGFyZ2V0LnByb3RvdHlwZS5hZGRFdmVudExpc3RlbmVyID0gZnVuY3Rpb24gKHR5cGUsIGxpc3RlbmVyKSB7XG4gICAgaWYgKCF0eXBlIHx8ICFsaXN0ZW5lcikge1xuICAgICAgcmV0dXJuO1xuICAgIH1cblxuICAgIHZhciBsaXN0ZW5lcnMgPSB0aGlzLmxpc3RlbmVyc18gfHwgKHRoaXMubGlzdGVuZXJzXyA9IHt9KTtcbiAgICB2YXIgbGlzdGVuZXJzRm9yVHlwZSA9IGxpc3RlbmVyc1t0eXBlXSB8fCAobGlzdGVuZXJzW3R5cGVdID0gW10pO1xuXG4gICAgaWYgKGxpc3RlbmVyc0ZvclR5cGUuaW5kZXhPZihsaXN0ZW5lcikgPT09IC0xKSB7XG4gICAgICBsaXN0ZW5lcnNGb3JUeXBlLnB1c2gobGlzdGVuZXIpO1xuICAgIH1cbiAgfTtcbiAgLyoqXG4gICAqIERpc3BhdGNoZXMgYW4gZXZlbnQgYW5kIGNhbGxzIGFsbCBsaXN0ZW5lcnMgbGlzdGVuaW5nIGZvciBldmVudHNcbiAgICogb2YgdGhpcyB0eXBlLiBUaGUgZXZlbnQgcGFyYW1ldGVyIGNhbiBlaXRoZXIgYmUgYSBzdHJpbmcgb3IgYW5cbiAgICogT2JqZWN0IHdpdGggYSBgdHlwZWAgcHJvcGVydHkuXG4gICAqXG4gICAqIEBwYXJhbSB7aW1wb3J0KFwiLi9FdmVudC5qc1wiKS5kZWZhdWx0fHN0cmluZ30gZXZlbnQgRXZlbnQgb2JqZWN0LlxuICAgKiBAcmV0dXJuIHtib29sZWFufHVuZGVmaW5lZH0gYGZhbHNlYCBpZiBhbnlvbmUgY2FsbGVkIHByZXZlbnREZWZhdWx0IG9uIHRoZVxuICAgKiAgICAgZXZlbnQgb2JqZWN0IG9yIGlmIGFueSBvZiB0aGUgbGlzdGVuZXJzIHJldHVybmVkIGZhbHNlLlxuICAgKiBAYXBpXG4gICAqL1xuXG5cbiAgVGFyZ2V0LnByb3RvdHlwZS5kaXNwYXRjaEV2ZW50ID0gZnVuY3Rpb24gKGV2ZW50KSB7XG4gICAgLyoqIEB0eXBlIHtpbXBvcnQoXCIuL0V2ZW50LmpzXCIpLmRlZmF1bHR8RXZlbnR9ICovXG4gICAgdmFyIGV2dCA9IHR5cGVvZiBldmVudCA9PT0gJ3N0cmluZycgPyBuZXcgRXZlbnQoZXZlbnQpIDogZXZlbnQ7XG4gICAgdmFyIHR5cGUgPSBldnQudHlwZTtcblxuICAgIGlmICghZXZ0LnRhcmdldCkge1xuICAgICAgZXZ0LnRhcmdldCA9IHRoaXMuZXZlbnRUYXJnZXRfIHx8IHRoaXM7XG4gICAgfVxuXG4gICAgdmFyIGxpc3RlbmVycyA9IHRoaXMubGlzdGVuZXJzXyAmJiB0aGlzLmxpc3RlbmVyc19bdHlwZV07XG4gICAgdmFyIHByb3BhZ2F0ZTtcblxuICAgIGlmIChsaXN0ZW5lcnMpIHtcbiAgICAgIHZhciBkaXNwYXRjaGluZyA9IHRoaXMuZGlzcGF0Y2hpbmdfIHx8ICh0aGlzLmRpc3BhdGNoaW5nXyA9IHt9KTtcbiAgICAgIHZhciBwZW5kaW5nUmVtb3ZhbHMgPSB0aGlzLnBlbmRpbmdSZW1vdmFsc18gfHwgKHRoaXMucGVuZGluZ1JlbW92YWxzXyA9IHt9KTtcblxuICAgICAgaWYgKCEodHlwZSBpbiBkaXNwYXRjaGluZykpIHtcbiAgICAgICAgZGlzcGF0Y2hpbmdbdHlwZV0gPSAwO1xuICAgICAgICBwZW5kaW5nUmVtb3ZhbHNbdHlwZV0gPSAwO1xuICAgICAgfVxuXG4gICAgICArK2Rpc3BhdGNoaW5nW3R5cGVdO1xuXG4gICAgICBmb3IgKHZhciBpID0gMCwgaWkgPSBsaXN0ZW5lcnMubGVuZ3RoOyBpIDwgaWk7ICsraSkge1xuICAgICAgICBpZiAoJ2hhbmRsZUV2ZW50JyBpbiBsaXN0ZW5lcnNbaV0pIHtcbiAgICAgICAgICBwcm9wYWdhdGUgPVxuICAgICAgICAgIC8qKiBAdHlwZSB7aW1wb3J0KFwiLi4vZXZlbnRzLmpzXCIpLkxpc3RlbmVyT2JqZWN0fSAqL1xuICAgICAgICAgIGxpc3RlbmVyc1tpXS5oYW5kbGVFdmVudChldnQpO1xuICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgIHByb3BhZ2F0ZSA9XG4gICAgICAgICAgLyoqIEB0eXBlIHtpbXBvcnQoXCIuLi9ldmVudHMuanNcIikuTGlzdGVuZXJGdW5jdGlvbn0gKi9cbiAgICAgICAgICBsaXN0ZW5lcnNbaV0uY2FsbCh0aGlzLCBldnQpO1xuICAgICAgICB9XG5cbiAgICAgICAgaWYgKHByb3BhZ2F0ZSA9PT0gZmFsc2UgfHwgZXZ0LnByb3BhZ2F0aW9uU3RvcHBlZCkge1xuICAgICAgICAgIHByb3BhZ2F0ZSA9IGZhbHNlO1xuICAgICAgICAgIGJyZWFrO1xuICAgICAgICB9XG4gICAgICB9XG5cbiAgICAgIC0tZGlzcGF0Y2hpbmdbdHlwZV07XG5cbiAgICAgIGlmIChkaXNwYXRjaGluZ1t0eXBlXSA9PT0gMCkge1xuICAgICAgICB2YXIgcHIgPSBwZW5kaW5nUmVtb3ZhbHNbdHlwZV07XG4gICAgICAgIGRlbGV0ZSBwZW5kaW5nUmVtb3ZhbHNbdHlwZV07XG5cbiAgICAgICAgd2hpbGUgKHByLS0pIHtcbiAgICAgICAgICB0aGlzLnJlbW92ZUV2ZW50TGlzdGVuZXIodHlwZSwgVk9JRCk7XG4gICAgICAgIH1cblxuICAgICAgICBkZWxldGUgZGlzcGF0Y2hpbmdbdHlwZV07XG4gICAgICB9XG5cbiAgICAgIHJldHVybiBwcm9wYWdhdGU7XG4gICAgfVxuICB9O1xuICAvKipcbiAgICogQ2xlYW4gdXAuXG4gICAqL1xuXG5cbiAgVGFyZ2V0LnByb3RvdHlwZS5kaXNwb3NlSW50ZXJuYWwgPSBmdW5jdGlvbiAoKSB7XG4gICAgdGhpcy5saXN0ZW5lcnNfICYmIGNsZWFyKHRoaXMubGlzdGVuZXJzXyk7XG4gIH07XG4gIC8qKlxuICAgKiBHZXQgdGhlIGxpc3RlbmVycyBmb3IgYSBzcGVjaWZpZWQgZXZlbnQgdHlwZS4gTGlzdGVuZXJzIGFyZSByZXR1cm5lZCBpbiB0aGVcbiAgICogb3JkZXIgdGhhdCB0aGV5IHdpbGwgYmUgY2FsbGVkIGluLlxuICAgKlxuICAgKiBAcGFyYW0ge3N0cmluZ30gdHlwZSBUeXBlLlxuICAgKiBAcmV0dXJuIHtBcnJheTxpbXBvcnQoXCIuLi9ldmVudHMuanNcIikuTGlzdGVuZXI+fHVuZGVmaW5lZH0gTGlzdGVuZXJzLlxuICAgKi9cblxuXG4gIFRhcmdldC5wcm90b3R5cGUuZ2V0TGlzdGVuZXJzID0gZnVuY3Rpb24gKHR5cGUpIHtcbiAgICByZXR1cm4gdGhpcy5saXN0ZW5lcnNfICYmIHRoaXMubGlzdGVuZXJzX1t0eXBlXSB8fCB1bmRlZmluZWQ7XG4gIH07XG4gIC8qKlxuICAgKiBAcGFyYW0ge3N0cmluZz19IG9wdF90eXBlIFR5cGUuIElmIG5vdCBwcm92aWRlZCxcbiAgICogICAgIGB0cnVlYCB3aWxsIGJlIHJldHVybmVkIGlmIHRoaXMgZXZlbnQgdGFyZ2V0IGhhcyBhbnkgbGlzdGVuZXJzLlxuICAgKiBAcmV0dXJuIHtib29sZWFufSBIYXMgbGlzdGVuZXJzLlxuICAgKi9cblxuXG4gIFRhcmdldC5wcm90b3R5cGUuaGFzTGlzdGVuZXIgPSBmdW5jdGlvbiAob3B0X3R5cGUpIHtcbiAgICBpZiAoIXRoaXMubGlzdGVuZXJzXykge1xuICAgICAgcmV0dXJuIGZhbHNlO1xuICAgIH1cblxuICAgIHJldHVybiBvcHRfdHlwZSA/IG9wdF90eXBlIGluIHRoaXMubGlzdGVuZXJzXyA6IE9iamVjdC5rZXlzKHRoaXMubGlzdGVuZXJzXykubGVuZ3RoID4gMDtcbiAgfTtcbiAgLyoqXG4gICAqIEBwYXJhbSB7c3RyaW5nfSB0eXBlIFR5cGUuXG4gICAqIEBwYXJhbSB7aW1wb3J0KFwiLi4vZXZlbnRzLmpzXCIpLkxpc3RlbmVyfSBsaXN0ZW5lciBMaXN0ZW5lci5cbiAgICovXG5cblxuICBUYXJnZXQucHJvdG90eXBlLnJlbW92ZUV2ZW50TGlzdGVuZXIgPSBmdW5jdGlvbiAodHlwZSwgbGlzdGVuZXIpIHtcbiAgICB2YXIgbGlzdGVuZXJzID0gdGhpcy5saXN0ZW5lcnNfICYmIHRoaXMubGlzdGVuZXJzX1t0eXBlXTtcblxuICAgIGlmIChsaXN0ZW5lcnMpIHtcbiAgICAgIHZhciBpbmRleCA9IGxpc3RlbmVycy5pbmRleE9mKGxpc3RlbmVyKTtcblxuICAgICAgaWYgKGluZGV4ICE9PSAtMSkge1xuICAgICAgICBpZiAodGhpcy5wZW5kaW5nUmVtb3ZhbHNfICYmIHR5cGUgaW4gdGhpcy5wZW5kaW5nUmVtb3ZhbHNfKSB7XG4gICAgICAgICAgLy8gbWFrZSBsaXN0ZW5lciBhIG5vLW9wLCBhbmQgcmVtb3ZlIGxhdGVyIGluICNkaXNwYXRjaEV2ZW50KClcbiAgICAgICAgICBsaXN0ZW5lcnNbaW5kZXhdID0gVk9JRDtcbiAgICAgICAgICArK3RoaXMucGVuZGluZ1JlbW92YWxzX1t0eXBlXTtcbiAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICBsaXN0ZW5lcnMuc3BsaWNlKGluZGV4LCAxKTtcblxuICAgICAgICAgIGlmIChsaXN0ZW5lcnMubGVuZ3RoID09PSAwKSB7XG4gICAgICAgICAgICBkZWxldGUgdGhpcy5saXN0ZW5lcnNfW3R5cGVdO1xuICAgICAgICAgIH1cbiAgICAgICAgfVxuICAgICAgfVxuICAgIH1cbiAgfTtcblxuICByZXR1cm4gVGFyZ2V0O1xufShEaXNwb3NhYmxlKTtcblxuZXhwb3J0IGRlZmF1bHQgVGFyZ2V0OyIsIi8qKlxuICogQG1vZHVsZSBvbC9ldmVudHMvRXZlbnRUeXBlXG4gKi9cblxuLyoqXG4gKiBAZW51bSB7c3RyaW5nfVxuICogQGNvbnN0XG4gKi9cbmV4cG9ydCBkZWZhdWx0IHtcbiAgLyoqXG4gICAqIEdlbmVyaWMgY2hhbmdlIGV2ZW50LiBUcmlnZ2VyZWQgd2hlbiB0aGUgcmV2aXNpb24gY291bnRlciBpcyBpbmNyZWFzZWQuXG4gICAqIEBldmVudCBtb2R1bGU6b2wvZXZlbnRzL0V2ZW50fkJhc2VFdmVudCNjaGFuZ2VcbiAgICogQGFwaVxuICAgKi9cbiAgQ0hBTkdFOiAnY2hhbmdlJyxcblxuICAvKipcbiAgICogR2VuZXJpYyBlcnJvciBldmVudC4gVHJpZ2dlcmVkIHdoZW4gYW4gZXJyb3Igb2NjdXJzLlxuICAgKiBAZXZlbnQgbW9kdWxlOm9sL2V2ZW50cy9FdmVudH5CYXNlRXZlbnQjZXJyb3JcbiAgICogQGFwaVxuICAgKi9cbiAgRVJST1I6ICdlcnJvcicsXG4gIEJMVVI6ICdibHVyJyxcbiAgQ0xFQVI6ICdjbGVhcicsXG4gIENPTlRFWFRNRU5VOiAnY29udGV4dG1lbnUnLFxuICBDTElDSzogJ2NsaWNrJyxcbiAgREJMQ0xJQ0s6ICdkYmxjbGljaycsXG4gIERSQUdFTlRFUjogJ2RyYWdlbnRlcicsXG4gIERSQUdPVkVSOiAnZHJhZ292ZXInLFxuICBEUk9QOiAnZHJvcCcsXG4gIEZPQ1VTOiAnZm9jdXMnLFxuICBLRVlET1dOOiAna2V5ZG93bicsXG4gIEtFWVBSRVNTOiAna2V5cHJlc3MnLFxuICBMT0FEOiAnbG9hZCcsXG4gIFJFU0laRTogJ3Jlc2l6ZScsXG4gIFRPVUNITU9WRTogJ3RvdWNobW92ZScsXG4gIFdIRUVMOiAnd2hlZWwnXG59OyIsIi8qKlxuICogQG1vZHVsZSBvbC9ldmVudHNcbiAqL1xuaW1wb3J0IHsgY2xlYXIgfSBmcm9tICcuL29iai5qcyc7XG4vKipcbiAqIEtleSB0byB1c2Ugd2l0aCB7QGxpbmsgbW9kdWxlOm9sL09ic2VydmFibGV+T2JzZXJ2YWJsZSN1bkJ5S2V5fS5cbiAqIEB0eXBlZGVmIHtPYmplY3R9IEV2ZW50c0tleVxuICogQHByb3BlcnR5IHtMaXN0ZW5lckZ1bmN0aW9ufSBsaXN0ZW5lclxuICogQHByb3BlcnR5IHtpbXBvcnQoXCIuL2V2ZW50cy9UYXJnZXQuanNcIikuRXZlbnRUYXJnZXRMaWtlfSB0YXJnZXRcbiAqIEBwcm9wZXJ0eSB7c3RyaW5nfSB0eXBlXG4gKiBAYXBpXG4gKi9cblxuLyoqXG4gKiBMaXN0ZW5lciBmdW5jdGlvbi4gVGhpcyBmdW5jdGlvbiBpcyBjYWxsZWQgd2l0aCBhbiBldmVudCBvYmplY3QgYXMgYXJndW1lbnQuXG4gKiBXaGVuIHRoZSBmdW5jdGlvbiByZXR1cm5zIGBmYWxzZWAsIGV2ZW50IHByb3BhZ2F0aW9uIHdpbGwgc3RvcC5cbiAqXG4gKiBAdHlwZWRlZiB7ZnVuY3Rpb24oKEV2ZW50fGltcG9ydChcIi4vZXZlbnRzL0V2ZW50LmpzXCIpLmRlZmF1bHQpKTogKHZvaWR8Ym9vbGVhbil9IExpc3RlbmVyRnVuY3Rpb25cbiAqIEBhcGlcbiAqL1xuXG4vKipcbiAqIEB0eXBlZGVmIHtPYmplY3R9IExpc3RlbmVyT2JqZWN0XG4gKiBAcHJvcGVydHkge0xpc3RlbmVyRnVuY3Rpb259IGhhbmRsZUV2ZW50XG4gKi9cblxuLyoqXG4gKiBAdHlwZWRlZiB7TGlzdGVuZXJGdW5jdGlvbnxMaXN0ZW5lck9iamVjdH0gTGlzdGVuZXJcbiAqL1xuXG4vKipcbiAqIFJlZ2lzdGVycyBhbiBldmVudCBsaXN0ZW5lciBvbiBhbiBldmVudCB0YXJnZXQuIEluc3BpcmVkIGJ5XG4gKiBodHRwczovL2dvb2dsZS5naXRodWIuaW8vY2xvc3VyZS1saWJyYXJ5L2FwaS9zb3VyY2UvY2xvc3VyZS9nb29nL2V2ZW50cy9ldmVudHMuanMuc3JjLmh0bWxcbiAqXG4gKiBUaGlzIGZ1bmN0aW9uIGVmZmljaWVudGx5IGJpbmRzIGEgYGxpc3RlbmVyYCB0byBhIGB0aGlzYCBvYmplY3QsIGFuZCByZXR1cm5zXG4gKiBhIGtleSBmb3IgdXNlIHdpdGgge0BsaW5rIG1vZHVsZTpvbC9ldmVudHN+dW5saXN0ZW5CeUtleX0uXG4gKlxuICogQHBhcmFtIHtpbXBvcnQoXCIuL2V2ZW50cy9UYXJnZXQuanNcIikuRXZlbnRUYXJnZXRMaWtlfSB0YXJnZXQgRXZlbnQgdGFyZ2V0LlxuICogQHBhcmFtIHtzdHJpbmd9IHR5cGUgRXZlbnQgdHlwZS5cbiAqIEBwYXJhbSB7TGlzdGVuZXJGdW5jdGlvbn0gbGlzdGVuZXIgTGlzdGVuZXIuXG4gKiBAcGFyYW0ge09iamVjdD19IG9wdF90aGlzIE9iamVjdCByZWZlcmVuY2VkIGJ5IHRoZSBgdGhpc2Aga2V5d29yZCBpbiB0aGVcbiAqICAgICBsaXN0ZW5lci4gRGVmYXVsdCBpcyB0aGUgYHRhcmdldGAuXG4gKiBAcGFyYW0ge2Jvb2xlYW49fSBvcHRfb25jZSBJZiB0cnVlLCBhZGQgdGhlIGxpc3RlbmVyIGFzIG9uZS1vZmYgbGlzdGVuZXIuXG4gKiBAcmV0dXJuIHtFdmVudHNLZXl9IFVuaXF1ZSBrZXkgZm9yIHRoZSBsaXN0ZW5lci5cbiAqL1xuXG5leHBvcnQgZnVuY3Rpb24gbGlzdGVuKHRhcmdldCwgdHlwZSwgX2xpc3RlbmVyLCBvcHRfdGhpcywgb3B0X29uY2UpIHtcbiAgaWYgKG9wdF90aGlzICYmIG9wdF90aGlzICE9PSB0YXJnZXQpIHtcbiAgICBfbGlzdGVuZXIgPSBfbGlzdGVuZXIuYmluZChvcHRfdGhpcyk7XG4gIH1cblxuICBpZiAob3B0X29uY2UpIHtcbiAgICB2YXIgb3JpZ2luYWxMaXN0ZW5lcl8xID0gX2xpc3RlbmVyO1xuXG4gICAgX2xpc3RlbmVyID0gZnVuY3Rpb24gbGlzdGVuZXIoKSB7XG4gICAgICB0YXJnZXQucmVtb3ZlRXZlbnRMaXN0ZW5lcih0eXBlLCBfbGlzdGVuZXIpO1xuICAgICAgb3JpZ2luYWxMaXN0ZW5lcl8xLmFwcGx5KHRoaXMsIGFyZ3VtZW50cyk7XG4gICAgfTtcbiAgfVxuXG4gIHZhciBldmVudHNLZXkgPSB7XG4gICAgdGFyZ2V0OiB0YXJnZXQsXG4gICAgdHlwZTogdHlwZSxcbiAgICBsaXN0ZW5lcjogX2xpc3RlbmVyXG4gIH07XG4gIHRhcmdldC5hZGRFdmVudExpc3RlbmVyKHR5cGUsIF9saXN0ZW5lcik7XG4gIHJldHVybiBldmVudHNLZXk7XG59XG4vKipcbiAqIFJlZ2lzdGVycyBhIG9uZS1vZmYgZXZlbnQgbGlzdGVuZXIgb24gYW4gZXZlbnQgdGFyZ2V0LiBJbnNwaXJlZCBieVxuICogaHR0cHM6Ly9nb29nbGUuZ2l0aHViLmlvL2Nsb3N1cmUtbGlicmFyeS9hcGkvc291cmNlL2Nsb3N1cmUvZ29vZy9ldmVudHMvZXZlbnRzLmpzLnNyYy5odG1sXG4gKlxuICogVGhpcyBmdW5jdGlvbiBlZmZpY2llbnRseSBiaW5kcyBhIGBsaXN0ZW5lcmAgYXMgc2VsZi11bnJlZ2lzdGVyaW5nIGxpc3RlbmVyXG4gKiB0byBhIGB0aGlzYCBvYmplY3QsIGFuZCByZXR1cm5zIGEga2V5IGZvciB1c2Ugd2l0aFxuICoge0BsaW5rIG1vZHVsZTpvbC9ldmVudHN+dW5saXN0ZW5CeUtleX0gaW4gY2FzZSB0aGUgbGlzdGVuZXIgbmVlZHMgdG8gYmVcbiAqIHVucmVnaXN0ZXJlZCBiZWZvcmUgaXQgaXMgY2FsbGVkLlxuICpcbiAqIFdoZW4ge0BsaW5rIG1vZHVsZTpvbC9ldmVudHN+bGlzdGVufSBpcyBjYWxsZWQgd2l0aCB0aGUgc2FtZSBhcmd1bWVudHMgYWZ0ZXIgdGhpc1xuICogZnVuY3Rpb24sIHRoZSBzZWxmLXVucmVnaXN0ZXJpbmcgbGlzdGVuZXIgd2lsbCBiZSB0dXJuZWQgaW50byBhIHBlcm1hbmVudFxuICogbGlzdGVuZXIuXG4gKlxuICogQHBhcmFtIHtpbXBvcnQoXCIuL2V2ZW50cy9UYXJnZXQuanNcIikuRXZlbnRUYXJnZXRMaWtlfSB0YXJnZXQgRXZlbnQgdGFyZ2V0LlxuICogQHBhcmFtIHtzdHJpbmd9IHR5cGUgRXZlbnQgdHlwZS5cbiAqIEBwYXJhbSB7TGlzdGVuZXJGdW5jdGlvbn0gbGlzdGVuZXIgTGlzdGVuZXIuXG4gKiBAcGFyYW0ge09iamVjdD19IG9wdF90aGlzIE9iamVjdCByZWZlcmVuY2VkIGJ5IHRoZSBgdGhpc2Aga2V5d29yZCBpbiB0aGVcbiAqICAgICBsaXN0ZW5lci4gRGVmYXVsdCBpcyB0aGUgYHRhcmdldGAuXG4gKiBAcmV0dXJuIHtFdmVudHNLZXl9IEtleSBmb3IgdW5saXN0ZW5CeUtleS5cbiAqL1xuXG5leHBvcnQgZnVuY3Rpb24gbGlzdGVuT25jZSh0YXJnZXQsIHR5cGUsIGxpc3RlbmVyLCBvcHRfdGhpcykge1xuICByZXR1cm4gbGlzdGVuKHRhcmdldCwgdHlwZSwgbGlzdGVuZXIsIG9wdF90aGlzLCB0cnVlKTtcbn1cbi8qKlxuICogVW5yZWdpc3RlcnMgZXZlbnQgbGlzdGVuZXJzIG9uIGFuIGV2ZW50IHRhcmdldC4gSW5zcGlyZWQgYnlcbiAqIGh0dHBzOi8vZ29vZ2xlLmdpdGh1Yi5pby9jbG9zdXJlLWxpYnJhcnkvYXBpL3NvdXJjZS9jbG9zdXJlL2dvb2cvZXZlbnRzL2V2ZW50cy5qcy5zcmMuaHRtbFxuICpcbiAqIFRoZSBhcmd1bWVudCBwYXNzZWQgdG8gdGhpcyBmdW5jdGlvbiBpcyB0aGUga2V5IHJldHVybmVkIGZyb21cbiAqIHtAbGluayBtb2R1bGU6b2wvZXZlbnRzfmxpc3Rlbn0gb3Ige0BsaW5rIG1vZHVsZTpvbC9ldmVudHN+bGlzdGVuT25jZX0uXG4gKlxuICogQHBhcmFtIHtFdmVudHNLZXl9IGtleSBUaGUga2V5LlxuICovXG5cbmV4cG9ydCBmdW5jdGlvbiB1bmxpc3RlbkJ5S2V5KGtleSkge1xuICBpZiAoa2V5ICYmIGtleS50YXJnZXQpIHtcbiAgICBrZXkudGFyZ2V0LnJlbW92ZUV2ZW50TGlzdGVuZXIoa2V5LnR5cGUsIGtleS5saXN0ZW5lcik7XG4gICAgY2xlYXIoa2V5KTtcbiAgfVxufSIsInZhciBfX2V4dGVuZHMgPSB0aGlzICYmIHRoaXMuX19leHRlbmRzIHx8IGZ1bmN0aW9uICgpIHtcbiAgdmFyIF9leHRlbmRTdGF0aWNzID0gZnVuY3Rpb24gZXh0ZW5kU3RhdGljcyhkLCBiKSB7XG4gICAgX2V4dGVuZFN0YXRpY3MgPSBPYmplY3Quc2V0UHJvdG90eXBlT2YgfHwge1xuICAgICAgX19wcm90b19fOiBbXVxuICAgIH0gaW5zdGFuY2VvZiBBcnJheSAmJiBmdW5jdGlvbiAoZCwgYikge1xuICAgICAgZC5fX3Byb3RvX18gPSBiO1xuICAgIH0gfHwgZnVuY3Rpb24gKGQsIGIpIHtcbiAgICAgIGZvciAodmFyIHAgaW4gYikge1xuICAgICAgICBpZiAoT2JqZWN0LnByb3RvdHlwZS5oYXNPd25Qcm9wZXJ0eS5jYWxsKGIsIHApKSBkW3BdID0gYltwXTtcbiAgICAgIH1cbiAgICB9O1xuXG4gICAgcmV0dXJuIF9leHRlbmRTdGF0aWNzKGQsIGIpO1xuICB9O1xuXG4gIHJldHVybiBmdW5jdGlvbiAoZCwgYikge1xuICAgIF9leHRlbmRTdGF0aWNzKGQsIGIpO1xuXG4gICAgZnVuY3Rpb24gX18oKSB7XG4gICAgICB0aGlzLmNvbnN0cnVjdG9yID0gZDtcbiAgICB9XG5cbiAgICBkLnByb3RvdHlwZSA9IGIgPT09IG51bGwgPyBPYmplY3QuY3JlYXRlKGIpIDogKF9fLnByb3RvdHlwZSA9IGIucHJvdG90eXBlLCBuZXcgX18oKSk7XG4gIH07XG59KCk7XG4vKipcbiAqIEBtb2R1bGUgb2wvT2JzZXJ2YWJsZVxuICovXG5cblxuaW1wb3J0IEV2ZW50VGFyZ2V0IGZyb20gJy4vZXZlbnRzL1RhcmdldC5qcyc7XG5pbXBvcnQgRXZlbnRUeXBlIGZyb20gJy4vZXZlbnRzL0V2ZW50VHlwZS5qcyc7XG5pbXBvcnQgeyBsaXN0ZW4sIGxpc3Rlbk9uY2UsIHVubGlzdGVuQnlLZXkgfSBmcm9tICcuL2V2ZW50cy5qcyc7XG4vKipcbiAqIEBjbGFzc2Rlc2NcbiAqIEFic3RyYWN0IGJhc2UgY2xhc3M7IG5vcm1hbGx5IG9ubHkgdXNlZCBmb3IgY3JlYXRpbmcgc3ViY2xhc3NlcyBhbmQgbm90XG4gKiBpbnN0YW50aWF0ZWQgaW4gYXBwcy5cbiAqIEFuIGV2ZW50IHRhcmdldCBwcm92aWRpbmcgY29udmVuaWVudCBtZXRob2RzIGZvciBsaXN0ZW5lciByZWdpc3RyYXRpb25cbiAqIGFuZCB1bnJlZ2lzdHJhdGlvbi4gQSBnZW5lcmljIGBjaGFuZ2VgIGV2ZW50IGlzIGFsd2F5cyBhdmFpbGFibGUgdGhyb3VnaFxuICoge0BsaW5rIG1vZHVsZTpvbC9PYnNlcnZhYmxlfk9ic2VydmFibGUjY2hhbmdlZH0uXG4gKlxuICogQGZpcmVzIGltcG9ydChcIi4vZXZlbnRzL0V2ZW50LmpzXCIpLmRlZmF1bHRcbiAqIEBhcGlcbiAqL1xuXG52YXIgT2JzZXJ2YWJsZSA9XG4vKiogQGNsYXNzICovXG5mdW5jdGlvbiAoX3N1cGVyKSB7XG4gIF9fZXh0ZW5kcyhPYnNlcnZhYmxlLCBfc3VwZXIpO1xuXG4gIGZ1bmN0aW9uIE9ic2VydmFibGUoKSB7XG4gICAgdmFyIF90aGlzID0gX3N1cGVyLmNhbGwodGhpcykgfHwgdGhpcztcbiAgICAvKipcbiAgICAgKiBAcHJpdmF0ZVxuICAgICAqIEB0eXBlIHtudW1iZXJ9XG4gICAgICovXG5cblxuICAgIF90aGlzLnJldmlzaW9uXyA9IDA7XG4gICAgcmV0dXJuIF90aGlzO1xuICB9XG4gIC8qKlxuICAgKiBJbmNyZWFzZXMgdGhlIHJldmlzaW9uIGNvdW50ZXIgYW5kIGRpc3BhdGNoZXMgYSAnY2hhbmdlJyBldmVudC5cbiAgICogQGFwaVxuICAgKi9cblxuXG4gIE9ic2VydmFibGUucHJvdG90eXBlLmNoYW5nZWQgPSBmdW5jdGlvbiAoKSB7XG4gICAgKyt0aGlzLnJldmlzaW9uXztcbiAgICB0aGlzLmRpc3BhdGNoRXZlbnQoRXZlbnRUeXBlLkNIQU5HRSk7XG4gIH07XG4gIC8qKlxuICAgKiBHZXQgdGhlIHZlcnNpb24gbnVtYmVyIGZvciB0aGlzIG9iamVjdC4gIEVhY2ggdGltZSB0aGUgb2JqZWN0IGlzIG1vZGlmaWVkLFxuICAgKiBpdHMgdmVyc2lvbiBudW1iZXIgd2lsbCBiZSBpbmNyZW1lbnRlZC5cbiAgICogQHJldHVybiB7bnVtYmVyfSBSZXZpc2lvbi5cbiAgICogQGFwaVxuICAgKi9cblxuXG4gIE9ic2VydmFibGUucHJvdG90eXBlLmdldFJldmlzaW9uID0gZnVuY3Rpb24gKCkge1xuICAgIHJldHVybiB0aGlzLnJldmlzaW9uXztcbiAgfTtcbiAgLyoqXG4gICAqIExpc3RlbiBmb3IgYSBjZXJ0YWluIHR5cGUgb2YgZXZlbnQuXG4gICAqIEBwYXJhbSB7c3RyaW5nfEFycmF5PHN0cmluZz59IHR5cGUgVGhlIGV2ZW50IHR5cGUgb3IgYXJyYXkgb2YgZXZlbnQgdHlwZXMuXG4gICAqIEBwYXJhbSB7ZnVuY3Rpb24oPyk6ID99IGxpc3RlbmVyIFRoZSBsaXN0ZW5lciBmdW5jdGlvbi5cbiAgICogQHJldHVybiB7aW1wb3J0KFwiLi9ldmVudHMuanNcIikuRXZlbnRzS2V5fEFycmF5PGltcG9ydChcIi4vZXZlbnRzLmpzXCIpLkV2ZW50c0tleT59IFVuaXF1ZSBrZXkgZm9yIHRoZSBsaXN0ZW5lci4gSWZcbiAgICogICAgIGNhbGxlZCB3aXRoIGFuIGFycmF5IG9mIGV2ZW50IHR5cGVzIGFzIHRoZSBmaXJzdCBhcmd1bWVudCwgdGhlIHJldHVyblxuICAgKiAgICAgd2lsbCBiZSBhbiBhcnJheSBvZiBrZXlzLlxuICAgKiBAYXBpXG4gICAqL1xuXG5cbiAgT2JzZXJ2YWJsZS5wcm90b3R5cGUub24gPSBmdW5jdGlvbiAodHlwZSwgbGlzdGVuZXIpIHtcbiAgICBpZiAoQXJyYXkuaXNBcnJheSh0eXBlKSkge1xuICAgICAgdmFyIGxlbiA9IHR5cGUubGVuZ3RoO1xuICAgICAgdmFyIGtleXMgPSBuZXcgQXJyYXkobGVuKTtcblxuICAgICAgZm9yICh2YXIgaSA9IDA7IGkgPCBsZW47ICsraSkge1xuICAgICAgICBrZXlzW2ldID0gbGlzdGVuKHRoaXMsIHR5cGVbaV0sIGxpc3RlbmVyKTtcbiAgICAgIH1cblxuICAgICAgcmV0dXJuIGtleXM7XG4gICAgfSBlbHNlIHtcbiAgICAgIHJldHVybiBsaXN0ZW4odGhpcyxcbiAgICAgIC8qKiBAdHlwZSB7c3RyaW5nfSAqL1xuICAgICAgdHlwZSwgbGlzdGVuZXIpO1xuICAgIH1cbiAgfTtcbiAgLyoqXG4gICAqIExpc3RlbiBvbmNlIGZvciBhIGNlcnRhaW4gdHlwZSBvZiBldmVudC5cbiAgICogQHBhcmFtIHtzdHJpbmd8QXJyYXk8c3RyaW5nPn0gdHlwZSBUaGUgZXZlbnQgdHlwZSBvciBhcnJheSBvZiBldmVudCB0eXBlcy5cbiAgICogQHBhcmFtIHtmdW5jdGlvbig/KTogP30gbGlzdGVuZXIgVGhlIGxpc3RlbmVyIGZ1bmN0aW9uLlxuICAgKiBAcmV0dXJuIHtpbXBvcnQoXCIuL2V2ZW50cy5qc1wiKS5FdmVudHNLZXl8QXJyYXk8aW1wb3J0KFwiLi9ldmVudHMuanNcIikuRXZlbnRzS2V5Pn0gVW5pcXVlIGtleSBmb3IgdGhlIGxpc3RlbmVyLiBJZlxuICAgKiAgICAgY2FsbGVkIHdpdGggYW4gYXJyYXkgb2YgZXZlbnQgdHlwZXMgYXMgdGhlIGZpcnN0IGFyZ3VtZW50LCB0aGUgcmV0dXJuXG4gICAqICAgICB3aWxsIGJlIGFuIGFycmF5IG9mIGtleXMuXG4gICAqIEBhcGlcbiAgICovXG5cblxuICBPYnNlcnZhYmxlLnByb3RvdHlwZS5vbmNlID0gZnVuY3Rpb24gKHR5cGUsIGxpc3RlbmVyKSB7XG4gICAgdmFyIGtleTtcblxuICAgIGlmIChBcnJheS5pc0FycmF5KHR5cGUpKSB7XG4gICAgICB2YXIgbGVuID0gdHlwZS5sZW5ndGg7XG4gICAgICBrZXkgPSBuZXcgQXJyYXkobGVuKTtcblxuICAgICAgZm9yICh2YXIgaSA9IDA7IGkgPCBsZW47ICsraSkge1xuICAgICAgICBrZXlbaV0gPSBsaXN0ZW5PbmNlKHRoaXMsIHR5cGVbaV0sIGxpc3RlbmVyKTtcbiAgICAgIH1cbiAgICB9IGVsc2Uge1xuICAgICAga2V5ID0gbGlzdGVuT25jZSh0aGlzLFxuICAgICAgLyoqIEB0eXBlIHtzdHJpbmd9ICovXG4gICAgICB0eXBlLCBsaXN0ZW5lcik7XG4gICAgfVxuICAgIC8qKiBAdHlwZSB7T2JqZWN0fSAqL1xuXG5cbiAgICBsaXN0ZW5lci5vbF9rZXkgPSBrZXk7XG4gICAgcmV0dXJuIGtleTtcbiAgfTtcbiAgLyoqXG4gICAqIFVubGlzdGVuIGZvciBhIGNlcnRhaW4gdHlwZSBvZiBldmVudC5cbiAgICogQHBhcmFtIHtzdHJpbmd8QXJyYXk8c3RyaW5nPn0gdHlwZSBUaGUgZXZlbnQgdHlwZSBvciBhcnJheSBvZiBldmVudCB0eXBlcy5cbiAgICogQHBhcmFtIHtmdW5jdGlvbig/KTogP30gbGlzdGVuZXIgVGhlIGxpc3RlbmVyIGZ1bmN0aW9uLlxuICAgKiBAYXBpXG4gICAqL1xuXG5cbiAgT2JzZXJ2YWJsZS5wcm90b3R5cGUudW4gPSBmdW5jdGlvbiAodHlwZSwgbGlzdGVuZXIpIHtcbiAgICB2YXIga2V5ID1cbiAgICAvKiogQHR5cGUge09iamVjdH0gKi9cbiAgICBsaXN0ZW5lci5vbF9rZXk7XG5cbiAgICBpZiAoa2V5KSB7XG4gICAgICB1bkJ5S2V5KGtleSk7XG4gICAgfSBlbHNlIGlmIChBcnJheS5pc0FycmF5KHR5cGUpKSB7XG4gICAgICBmb3IgKHZhciBpID0gMCwgaWkgPSB0eXBlLmxlbmd0aDsgaSA8IGlpOyArK2kpIHtcbiAgICAgICAgdGhpcy5yZW1vdmVFdmVudExpc3RlbmVyKHR5cGVbaV0sIGxpc3RlbmVyKTtcbiAgICAgIH1cbiAgICB9IGVsc2Uge1xuICAgICAgdGhpcy5yZW1vdmVFdmVudExpc3RlbmVyKHR5cGUsIGxpc3RlbmVyKTtcbiAgICB9XG4gIH07XG5cbiAgcmV0dXJuIE9ic2VydmFibGU7XG59KEV2ZW50VGFyZ2V0KTtcbi8qKlxuICogUmVtb3ZlcyBhbiBldmVudCBsaXN0ZW5lciB1c2luZyB0aGUga2V5IHJldHVybmVkIGJ5IGBvbigpYCBvciBgb25jZSgpYC5cbiAqIEBwYXJhbSB7aW1wb3J0KFwiLi9ldmVudHMuanNcIikuRXZlbnRzS2V5fEFycmF5PGltcG9ydChcIi4vZXZlbnRzLmpzXCIpLkV2ZW50c0tleT59IGtleSBUaGUga2V5IHJldHVybmVkIGJ5IGBvbigpYFxuICogICAgIG9yIGBvbmNlKClgIChvciBhbiBhcnJheSBvZiBrZXlzKS5cbiAqIEBhcGlcbiAqL1xuXG5cbmV4cG9ydCBmdW5jdGlvbiB1bkJ5S2V5KGtleSkge1xuICBpZiAoQXJyYXkuaXNBcnJheShrZXkpKSB7XG4gICAgZm9yICh2YXIgaSA9IDAsIGlpID0ga2V5Lmxlbmd0aDsgaSA8IGlpOyArK2kpIHtcbiAgICAgIHVubGlzdGVuQnlLZXkoa2V5W2ldKTtcbiAgICB9XG4gIH0gZWxzZSB7XG4gICAgdW5saXN0ZW5CeUtleShcbiAgICAvKiogQHR5cGUge2ltcG9ydChcIi4vZXZlbnRzLmpzXCIpLkV2ZW50c0tleX0gKi9cbiAgICBrZXkpO1xuICB9XG59XG5leHBvcnQgZGVmYXVsdCBPYnNlcnZhYmxlOyIsInZhciBfX2V4dGVuZHMgPSB0aGlzICYmIHRoaXMuX19leHRlbmRzIHx8IGZ1bmN0aW9uICgpIHtcbiAgdmFyIF9leHRlbmRTdGF0aWNzID0gZnVuY3Rpb24gZXh0ZW5kU3RhdGljcyhkLCBiKSB7XG4gICAgX2V4dGVuZFN0YXRpY3MgPSBPYmplY3Quc2V0UHJvdG90eXBlT2YgfHwge1xuICAgICAgX19wcm90b19fOiBbXVxuICAgIH0gaW5zdGFuY2VvZiBBcnJheSAmJiBmdW5jdGlvbiAoZCwgYikge1xuICAgICAgZC5fX3Byb3RvX18gPSBiO1xuICAgIH0gfHwgZnVuY3Rpb24gKGQsIGIpIHtcbiAgICAgIGZvciAodmFyIHAgaW4gYikge1xuICAgICAgICBpZiAoT2JqZWN0LnByb3RvdHlwZS5oYXNPd25Qcm9wZXJ0eS5jYWxsKGIsIHApKSBkW3BdID0gYltwXTtcbiAgICAgIH1cbiAgICB9O1xuXG4gICAgcmV0dXJuIF9leHRlbmRTdGF0aWNzKGQsIGIpO1xuICB9O1xuXG4gIHJldHVybiBmdW5jdGlvbiAoZCwgYikge1xuICAgIF9leHRlbmRTdGF0aWNzKGQsIGIpO1xuXG4gICAgZnVuY3Rpb24gX18oKSB7XG4gICAgICB0aGlzLmNvbnN0cnVjdG9yID0gZDtcbiAgICB9XG5cbiAgICBkLnByb3RvdHlwZSA9IGIgPT09IG51bGwgPyBPYmplY3QuY3JlYXRlKGIpIDogKF9fLnByb3RvdHlwZSA9IGIucHJvdG90eXBlLCBuZXcgX18oKSk7XG4gIH07XG59KCk7XG4vKipcbiAqIEBtb2R1bGUgb2wvT2JqZWN0XG4gKi9cblxuXG5pbXBvcnQgRXZlbnQgZnJvbSAnLi9ldmVudHMvRXZlbnQuanMnO1xuaW1wb3J0IE9iamVjdEV2ZW50VHlwZSBmcm9tICcuL09iamVjdEV2ZW50VHlwZS5qcyc7XG5pbXBvcnQgT2JzZXJ2YWJsZSBmcm9tICcuL09ic2VydmFibGUuanMnO1xuaW1wb3J0IHsgYXNzaWduLCBpc0VtcHR5IH0gZnJvbSAnLi9vYmouanMnO1xuaW1wb3J0IHsgZ2V0VWlkIH0gZnJvbSAnLi91dGlsLmpzJztcbi8qKlxuICogQGNsYXNzZGVzY1xuICogRXZlbnRzIGVtaXR0ZWQgYnkge0BsaW5rIG1vZHVsZTpvbC9PYmplY3R+QmFzZU9iamVjdH0gaW5zdGFuY2VzIGFyZSBpbnN0YW5jZXMgb2YgdGhpcyB0eXBlLlxuICovXG5cbnZhciBPYmplY3RFdmVudCA9XG4vKiogQGNsYXNzICovXG5mdW5jdGlvbiAoX3N1cGVyKSB7XG4gIF9fZXh0ZW5kcyhPYmplY3RFdmVudCwgX3N1cGVyKTtcbiAgLyoqXG4gICAqIEBwYXJhbSB7c3RyaW5nfSB0eXBlIFRoZSBldmVudCB0eXBlLlxuICAgKiBAcGFyYW0ge3N0cmluZ30ga2V5IFRoZSBwcm9wZXJ0eSBuYW1lLlxuICAgKiBAcGFyYW0geyp9IG9sZFZhbHVlIFRoZSBvbGQgdmFsdWUgZm9yIGBrZXlgLlxuICAgKi9cblxuXG4gIGZ1bmN0aW9uIE9iamVjdEV2ZW50KHR5cGUsIGtleSwgb2xkVmFsdWUpIHtcbiAgICB2YXIgX3RoaXMgPSBfc3VwZXIuY2FsbCh0aGlzLCB0eXBlKSB8fCB0aGlzO1xuICAgIC8qKlxuICAgICAqIFRoZSBuYW1lIG9mIHRoZSBwcm9wZXJ0eSB3aG9zZSB2YWx1ZSBpcyBjaGFuZ2luZy5cbiAgICAgKiBAdHlwZSB7c3RyaW5nfVxuICAgICAqIEBhcGlcbiAgICAgKi9cblxuXG4gICAgX3RoaXMua2V5ID0ga2V5O1xuICAgIC8qKlxuICAgICAqIFRoZSBvbGQgdmFsdWUuIFRvIGdldCB0aGUgbmV3IHZhbHVlIHVzZSBgZS50YXJnZXQuZ2V0KGUua2V5KWAgd2hlcmVcbiAgICAgKiBgZWAgaXMgdGhlIGV2ZW50IG9iamVjdC5cbiAgICAgKiBAdHlwZSB7Kn1cbiAgICAgKiBAYXBpXG4gICAgICovXG5cbiAgICBfdGhpcy5vbGRWYWx1ZSA9IG9sZFZhbHVlO1xuICAgIHJldHVybiBfdGhpcztcbiAgfVxuXG4gIHJldHVybiBPYmplY3RFdmVudDtcbn0oRXZlbnQpO1xuXG5leHBvcnQgeyBPYmplY3RFdmVudCB9O1xuLyoqXG4gKiBAY2xhc3NkZXNjXG4gKiBBYnN0cmFjdCBiYXNlIGNsYXNzOyBub3JtYWxseSBvbmx5IHVzZWQgZm9yIGNyZWF0aW5nIHN1YmNsYXNzZXMgYW5kIG5vdFxuICogaW5zdGFudGlhdGVkIGluIGFwcHMuXG4gKiBNb3N0IG5vbi10cml2aWFsIGNsYXNzZXMgaW5oZXJpdCBmcm9tIHRoaXMuXG4gKlxuICogVGhpcyBleHRlbmRzIHtAbGluayBtb2R1bGU6b2wvT2JzZXJ2YWJsZX0gd2l0aCBvYnNlcnZhYmxlXG4gKiBwcm9wZXJ0aWVzLCB3aGVyZSBlYWNoIHByb3BlcnR5IGlzIG9ic2VydmFibGUgYXMgd2VsbCBhcyB0aGUgb2JqZWN0IGFzIGFcbiAqIHdob2xlLlxuICpcbiAqIENsYXNzZXMgdGhhdCBpbmhlcml0IGZyb20gdGhpcyBoYXZlIHByZS1kZWZpbmVkIHByb3BlcnRpZXMsIHRvIHdoaWNoIHlvdSBjYW5cbiAqIGFkZCB5b3VyIG93bnMuIFRoZSBwcmUtZGVmaW5lZCBwcm9wZXJ0aWVzIGFyZSBsaXN0ZWQgaW4gdGhpcyBkb2N1bWVudGF0aW9uIGFzXG4gKiAnT2JzZXJ2YWJsZSBQcm9wZXJ0aWVzJywgYW5kIGhhdmUgdGhlaXIgb3duIGFjY2Vzc29yczsgZm9yIGV4YW1wbGUsXG4gKiB7QGxpbmsgbW9kdWxlOm9sL01hcH5NYXB9IGhhcyBhIGB0YXJnZXRgIHByb3BlcnR5LCBhY2Nlc3NlZCB3aXRoXG4gKiBgZ2V0VGFyZ2V0KClgIGFuZCBjaGFuZ2VkIHdpdGggYHNldFRhcmdldCgpYC4gTm90IGFsbCBwcm9wZXJ0aWVzIGFyZSBob3dldmVyXG4gKiBzZXR0YWJsZS4gVGhlcmUgYXJlIGFsc28gZ2VuZXJhbC1wdXJwb3NlIGFjY2Vzc29ycyBgZ2V0KClgIGFuZCBgc2V0KClgLiBGb3JcbiAqIGV4YW1wbGUsIGBnZXQoJ3RhcmdldCcpYCBpcyBlcXVpdmFsZW50IHRvIGBnZXRUYXJnZXQoKWAuXG4gKlxuICogVGhlIGBzZXRgIGFjY2Vzc29ycyB0cmlnZ2VyIGEgY2hhbmdlIGV2ZW50LCBhbmQgeW91IGNhbiBtb25pdG9yIHRoaXMgYnlcbiAqIHJlZ2lzdGVyaW5nIGEgbGlzdGVuZXIuIEZvciBleGFtcGxlLCB7QGxpbmsgbW9kdWxlOm9sL1ZpZXd+Vmlld30gaGFzIGFcbiAqIGBjZW50ZXJgIHByb3BlcnR5LCBzbyBgdmlldy5vbignY2hhbmdlOmNlbnRlcicsIGZ1bmN0aW9uKGV2dCkgey4uLn0pO2Agd291bGRcbiAqIGNhbGwgdGhlIGZ1bmN0aW9uIHdoZW5ldmVyIHRoZSB2YWx1ZSBvZiB0aGUgY2VudGVyIHByb3BlcnR5IGNoYW5nZXMuIFdpdGhpblxuICogdGhlIGZ1bmN0aW9uLCBgZXZ0LnRhcmdldGAgd291bGQgYmUgdGhlIHZpZXcsIHNvIGBldnQudGFyZ2V0LmdldENlbnRlcigpYFxuICogd291bGQgcmV0dXJuIHRoZSBuZXcgY2VudGVyLlxuICpcbiAqIFlvdSBjYW4gYWRkIHlvdXIgb3duIG9ic2VydmFibGUgcHJvcGVydGllcyB3aXRoXG4gKiBgb2JqZWN0LnNldCgncHJvcCcsICd2YWx1ZScpYCwgYW5kIHJldHJpZXZlIHRoYXQgd2l0aCBgb2JqZWN0LmdldCgncHJvcCcpYC5cbiAqIFlvdSBjYW4gbGlzdGVuIGZvciBjaGFuZ2VzIG9uIHRoYXQgcHJvcGVydHkgdmFsdWUgd2l0aFxuICogYG9iamVjdC5vbignY2hhbmdlOnByb3AnLCBsaXN0ZW5lcilgLiBZb3UgY2FuIGdldCBhIGxpc3Qgb2YgYWxsXG4gKiBwcm9wZXJ0aWVzIHdpdGgge0BsaW5rIG1vZHVsZTpvbC9PYmplY3R+QmFzZU9iamVjdCNnZXRQcm9wZXJ0aWVzfS5cbiAqXG4gKiBOb3RlIHRoYXQgdGhlIG9ic2VydmFibGUgcHJvcGVydGllcyBhcmUgc2VwYXJhdGUgZnJvbSBzdGFuZGFyZCBKUyBwcm9wZXJ0aWVzLlxuICogWW91IGNhbiwgZm9yIGV4YW1wbGUsIGdpdmUgeW91ciBtYXAgb2JqZWN0IGEgdGl0bGUgd2l0aFxuICogYG1hcC50aXRsZT0nTmV3IHRpdGxlJ2AgYW5kIHdpdGggYG1hcC5zZXQoJ3RpdGxlJywgJ0Fub3RoZXIgdGl0bGUnKWAuIFRoZVxuICogZmlyc3Qgd2lsbCBiZSBhIGBoYXNPd25Qcm9wZXJ0eWA7IHRoZSBzZWNvbmQgd2lsbCBhcHBlYXIgaW5cbiAqIGBnZXRQcm9wZXJ0aWVzKClgLiBPbmx5IHRoZSBzZWNvbmQgaXMgb2JzZXJ2YWJsZS5cbiAqXG4gKiBQcm9wZXJ0aWVzIGNhbiBiZSBkZWxldGVkIGJ5IHVzaW5nIHRoZSB1bnNldCBtZXRob2QuIEUuZy5cbiAqIG9iamVjdC51bnNldCgnZm9vJykuXG4gKlxuICogQGZpcmVzIE9iamVjdEV2ZW50XG4gKiBAYXBpXG4gKi9cblxudmFyIEJhc2VPYmplY3QgPVxuLyoqIEBjbGFzcyAqL1xuZnVuY3Rpb24gKF9zdXBlcikge1xuICBfX2V4dGVuZHMoQmFzZU9iamVjdCwgX3N1cGVyKTtcbiAgLyoqXG4gICAqIEBwYXJhbSB7T2JqZWN0PHN0cmluZywgKj49fSBvcHRfdmFsdWVzIEFuIG9iamVjdCB3aXRoIGtleS12YWx1ZSBwYWlycy5cbiAgICovXG5cblxuICBmdW5jdGlvbiBCYXNlT2JqZWN0KG9wdF92YWx1ZXMpIHtcbiAgICB2YXIgX3RoaXMgPSBfc3VwZXIuY2FsbCh0aGlzKSB8fCB0aGlzOyAvLyBDYWxsIHtAbGluayBtb2R1bGU6b2wvdXRpbH5nZXRVaWR9IHRvIGVuc3VyZSB0aGF0IHRoZSBvcmRlciBvZiBvYmplY3RzJyBpZHMgaXNcbiAgICAvLyB0aGUgc2FtZSBhcyB0aGUgb3JkZXIgaW4gd2hpY2ggdGhleSB3ZXJlIGNyZWF0ZWQuICBUaGlzIGFsc28gaGVscHMgdG9cbiAgICAvLyBlbnN1cmUgdGhhdCBvYmplY3QgcHJvcGVydGllcyBhcmUgYWx3YXlzIGFkZGVkIGluIHRoZSBzYW1lIG9yZGVyLCB3aGljaFxuICAgIC8vIGhlbHBzIG1hbnkgSmF2YVNjcmlwdCBlbmdpbmVzIGdlbmVyYXRlIGZhc3RlciBjb2RlLlxuXG5cbiAgICBnZXRVaWQoX3RoaXMpO1xuICAgIC8qKlxuICAgICAqIEBwcml2YXRlXG4gICAgICogQHR5cGUge09iamVjdDxzdHJpbmcsICo+fVxuICAgICAqL1xuXG4gICAgX3RoaXMudmFsdWVzXyA9IG51bGw7XG5cbiAgICBpZiAob3B0X3ZhbHVlcyAhPT0gdW5kZWZpbmVkKSB7XG4gICAgICBfdGhpcy5zZXRQcm9wZXJ0aWVzKG9wdF92YWx1ZXMpO1xuICAgIH1cblxuICAgIHJldHVybiBfdGhpcztcbiAgfVxuICAvKipcbiAgICogR2V0cyBhIHZhbHVlLlxuICAgKiBAcGFyYW0ge3N0cmluZ30ga2V5IEtleSBuYW1lLlxuICAgKiBAcmV0dXJuIHsqfSBWYWx1ZS5cbiAgICogQGFwaVxuICAgKi9cblxuXG4gIEJhc2VPYmplY3QucHJvdG90eXBlLmdldCA9IGZ1bmN0aW9uIChrZXkpIHtcbiAgICB2YXIgdmFsdWU7XG5cbiAgICBpZiAodGhpcy52YWx1ZXNfICYmIHRoaXMudmFsdWVzXy5oYXNPd25Qcm9wZXJ0eShrZXkpKSB7XG4gICAgICB2YWx1ZSA9IHRoaXMudmFsdWVzX1trZXldO1xuICAgIH1cblxuICAgIHJldHVybiB2YWx1ZTtcbiAgfTtcbiAgLyoqXG4gICAqIEdldCBhIGxpc3Qgb2Ygb2JqZWN0IHByb3BlcnR5IG5hbWVzLlxuICAgKiBAcmV0dXJuIHtBcnJheTxzdHJpbmc+fSBMaXN0IG9mIHByb3BlcnR5IG5hbWVzLlxuICAgKiBAYXBpXG4gICAqL1xuXG5cbiAgQmFzZU9iamVjdC5wcm90b3R5cGUuZ2V0S2V5cyA9IGZ1bmN0aW9uICgpIHtcbiAgICByZXR1cm4gdGhpcy52YWx1ZXNfICYmIE9iamVjdC5rZXlzKHRoaXMudmFsdWVzXykgfHwgW107XG4gIH07XG4gIC8qKlxuICAgKiBHZXQgYW4gb2JqZWN0IG9mIGFsbCBwcm9wZXJ0eSBuYW1lcyBhbmQgdmFsdWVzLlxuICAgKiBAcmV0dXJuIHtPYmplY3Q8c3RyaW5nLCAqPn0gT2JqZWN0LlxuICAgKiBAYXBpXG4gICAqL1xuXG5cbiAgQmFzZU9iamVjdC5wcm90b3R5cGUuZ2V0UHJvcGVydGllcyA9IGZ1bmN0aW9uICgpIHtcbiAgICByZXR1cm4gdGhpcy52YWx1ZXNfICYmIGFzc2lnbih7fSwgdGhpcy52YWx1ZXNfKSB8fCB7fTtcbiAgfTtcbiAgLyoqXG4gICAqIEByZXR1cm4ge2Jvb2xlYW59IFRoZSBvYmplY3QgaGFzIHByb3BlcnRpZXMuXG4gICAqL1xuXG5cbiAgQmFzZU9iamVjdC5wcm90b3R5cGUuaGFzUHJvcGVydGllcyA9IGZ1bmN0aW9uICgpIHtcbiAgICByZXR1cm4gISF0aGlzLnZhbHVlc187XG4gIH07XG4gIC8qKlxuICAgKiBAcGFyYW0ge3N0cmluZ30ga2V5IEtleSBuYW1lLlxuICAgKiBAcGFyYW0geyp9IG9sZFZhbHVlIE9sZCB2YWx1ZS5cbiAgICovXG5cblxuICBCYXNlT2JqZWN0LnByb3RvdHlwZS5ub3RpZnkgPSBmdW5jdGlvbiAoa2V5LCBvbGRWYWx1ZSkge1xuICAgIHZhciBldmVudFR5cGU7XG4gICAgZXZlbnRUeXBlID0gZ2V0Q2hhbmdlRXZlbnRUeXBlKGtleSk7XG4gICAgdGhpcy5kaXNwYXRjaEV2ZW50KG5ldyBPYmplY3RFdmVudChldmVudFR5cGUsIGtleSwgb2xkVmFsdWUpKTtcbiAgICBldmVudFR5cGUgPSBPYmplY3RFdmVudFR5cGUuUFJPUEVSVFlDSEFOR0U7XG4gICAgdGhpcy5kaXNwYXRjaEV2ZW50KG5ldyBPYmplY3RFdmVudChldmVudFR5cGUsIGtleSwgb2xkVmFsdWUpKTtcbiAgfTtcbiAgLyoqXG4gICAqIFNldHMgYSB2YWx1ZS5cbiAgICogQHBhcmFtIHtzdHJpbmd9IGtleSBLZXkgbmFtZS5cbiAgICogQHBhcmFtIHsqfSB2YWx1ZSBWYWx1ZS5cbiAgICogQHBhcmFtIHtib29sZWFuPX0gb3B0X3NpbGVudCBVcGRhdGUgd2l0aG91dCB0cmlnZ2VyaW5nIGFuIGV2ZW50LlxuICAgKiBAYXBpXG4gICAqL1xuXG5cbiAgQmFzZU9iamVjdC5wcm90b3R5cGUuc2V0ID0gZnVuY3Rpb24gKGtleSwgdmFsdWUsIG9wdF9zaWxlbnQpIHtcbiAgICB2YXIgdmFsdWVzID0gdGhpcy52YWx1ZXNfIHx8ICh0aGlzLnZhbHVlc18gPSB7fSk7XG5cbiAgICBpZiAob3B0X3NpbGVudCkge1xuICAgICAgdmFsdWVzW2tleV0gPSB2YWx1ZTtcbiAgICB9IGVsc2Uge1xuICAgICAgdmFyIG9sZFZhbHVlID0gdmFsdWVzW2tleV07XG4gICAgICB2YWx1ZXNba2V5XSA9IHZhbHVlO1xuXG4gICAgICBpZiAob2xkVmFsdWUgIT09IHZhbHVlKSB7XG4gICAgICAgIHRoaXMubm90aWZ5KGtleSwgb2xkVmFsdWUpO1xuICAgICAgfVxuICAgIH1cbiAgfTtcbiAgLyoqXG4gICAqIFNldHMgYSBjb2xsZWN0aW9uIG9mIGtleS12YWx1ZSBwYWlycy4gIE5vdGUgdGhhdCB0aGlzIGNoYW5nZXMgYW55IGV4aXN0aW5nXG4gICAqIHByb3BlcnRpZXMgYW5kIGFkZHMgbmV3IG9uZXMgKGl0IGRvZXMgbm90IHJlbW92ZSBhbnkgZXhpc3RpbmcgcHJvcGVydGllcykuXG4gICAqIEBwYXJhbSB7T2JqZWN0PHN0cmluZywgKj59IHZhbHVlcyBWYWx1ZXMuXG4gICAqIEBwYXJhbSB7Ym9vbGVhbj19IG9wdF9zaWxlbnQgVXBkYXRlIHdpdGhvdXQgdHJpZ2dlcmluZyBhbiBldmVudC5cbiAgICogQGFwaVxuICAgKi9cblxuXG4gIEJhc2VPYmplY3QucHJvdG90eXBlLnNldFByb3BlcnRpZXMgPSBmdW5jdGlvbiAodmFsdWVzLCBvcHRfc2lsZW50KSB7XG4gICAgZm9yICh2YXIga2V5IGluIHZhbHVlcykge1xuICAgICAgdGhpcy5zZXQoa2V5LCB2YWx1ZXNba2V5XSwgb3B0X3NpbGVudCk7XG4gICAgfVxuICB9O1xuICAvKipcbiAgICogQXBwbHkgYW55IHByb3BlcnRpZXMgZnJvbSBhbm90aGVyIG9iamVjdCB3aXRob3V0IHRyaWdnZXJpbmcgZXZlbnRzLlxuICAgKiBAcGFyYW0ge0Jhc2VPYmplY3R9IHNvdXJjZSBUaGUgc291cmNlIG9iamVjdC5cbiAgICogQHByb3RlY3RlZFxuICAgKi9cblxuXG4gIEJhc2VPYmplY3QucHJvdG90eXBlLmFwcGx5UHJvcGVydGllcyA9IGZ1bmN0aW9uIChzb3VyY2UpIHtcbiAgICBpZiAoIXNvdXJjZS52YWx1ZXNfKSB7XG4gICAgICByZXR1cm47XG4gICAgfVxuXG4gICAgYXNzaWduKHRoaXMudmFsdWVzXyB8fCAodGhpcy52YWx1ZXNfID0ge30pLCBzb3VyY2UudmFsdWVzXyk7XG4gIH07XG4gIC8qKlxuICAgKiBVbnNldHMgYSBwcm9wZXJ0eS5cbiAgICogQHBhcmFtIHtzdHJpbmd9IGtleSBLZXkgbmFtZS5cbiAgICogQHBhcmFtIHtib29sZWFuPX0gb3B0X3NpbGVudCBVbnNldCB3aXRob3V0IHRyaWdnZXJpbmcgYW4gZXZlbnQuXG4gICAqIEBhcGlcbiAgICovXG5cblxuICBCYXNlT2JqZWN0LnByb3RvdHlwZS51bnNldCA9IGZ1bmN0aW9uIChrZXksIG9wdF9zaWxlbnQpIHtcbiAgICBpZiAodGhpcy52YWx1ZXNfICYmIGtleSBpbiB0aGlzLnZhbHVlc18pIHtcbiAgICAgIHZhciBvbGRWYWx1ZSA9IHRoaXMudmFsdWVzX1trZXldO1xuICAgICAgZGVsZXRlIHRoaXMudmFsdWVzX1trZXldO1xuXG4gICAgICBpZiAoaXNFbXB0eSh0aGlzLnZhbHVlc18pKSB7XG4gICAgICAgIHRoaXMudmFsdWVzXyA9IG51bGw7XG4gICAgICB9XG5cbiAgICAgIGlmICghb3B0X3NpbGVudCkge1xuICAgICAgICB0aGlzLm5vdGlmeShrZXksIG9sZFZhbHVlKTtcbiAgICAgIH1cbiAgICB9XG4gIH07XG5cbiAgcmV0dXJuIEJhc2VPYmplY3Q7XG59KE9ic2VydmFibGUpO1xuLyoqXG4gKiBAdHlwZSB7T2JqZWN0PHN0cmluZywgc3RyaW5nPn1cbiAqL1xuXG5cbnZhciBjaGFuZ2VFdmVudFR5cGVDYWNoZSA9IHt9O1xuLyoqXG4gKiBAcGFyYW0ge3N0cmluZ30ga2V5IEtleSBuYW1lLlxuICogQHJldHVybiB7c3RyaW5nfSBDaGFuZ2UgbmFtZS5cbiAqL1xuXG5leHBvcnQgZnVuY3Rpb24gZ2V0Q2hhbmdlRXZlbnRUeXBlKGtleSkge1xuICByZXR1cm4gY2hhbmdlRXZlbnRUeXBlQ2FjaGUuaGFzT3duUHJvcGVydHkoa2V5KSA/IGNoYW5nZUV2ZW50VHlwZUNhY2hlW2tleV0gOiBjaGFuZ2VFdmVudFR5cGVDYWNoZVtrZXldID0gJ2NoYW5nZTonICsga2V5O1xufVxuZXhwb3J0IGRlZmF1bHQgQmFzZU9iamVjdDsiLCIvKipcbiAqIEBtb2R1bGUgb2wvbGF5ZXIvUHJvcGVydHlcbiAqL1xuXG4vKipcbiAqIEBlbnVtIHtzdHJpbmd9XG4gKi9cbmV4cG9ydCBkZWZhdWx0IHtcbiAgT1BBQ0lUWTogJ29wYWNpdHknLFxuICBWSVNJQkxFOiAndmlzaWJsZScsXG4gIEVYVEVOVDogJ2V4dGVudCcsXG4gIFpfSU5ERVg6ICd6SW5kZXgnLFxuICBNQVhfUkVTT0xVVElPTjogJ21heFJlc29sdXRpb24nLFxuICBNSU5fUkVTT0xVVElPTjogJ21pblJlc29sdXRpb24nLFxuICBNQVhfWk9PTTogJ21heFpvb20nLFxuICBNSU5fWk9PTTogJ21pblpvb20nLFxuICBTT1VSQ0U6ICdzb3VyY2UnXG59OyIsInZhciBfX2V4dGVuZHMgPSB0aGlzICYmIHRoaXMuX19leHRlbmRzIHx8IGZ1bmN0aW9uICgpIHtcbiAgdmFyIF9leHRlbmRTdGF0aWNzID0gZnVuY3Rpb24gZXh0ZW5kU3RhdGljcyhkLCBiKSB7XG4gICAgX2V4dGVuZFN0YXRpY3MgPSBPYmplY3Quc2V0UHJvdG90eXBlT2YgfHwge1xuICAgICAgX19wcm90b19fOiBbXVxuICAgIH0gaW5zdGFuY2VvZiBBcnJheSAmJiBmdW5jdGlvbiAoZCwgYikge1xuICAgICAgZC5fX3Byb3RvX18gPSBiO1xuICAgIH0gfHwgZnVuY3Rpb24gKGQsIGIpIHtcbiAgICAgIGZvciAodmFyIHAgaW4gYikge1xuICAgICAgICBpZiAoT2JqZWN0LnByb3RvdHlwZS5oYXNPd25Qcm9wZXJ0eS5jYWxsKGIsIHApKSBkW3BdID0gYltwXTtcbiAgICAgIH1cbiAgICB9O1xuXG4gICAgcmV0dXJuIF9leHRlbmRTdGF0aWNzKGQsIGIpO1xuICB9O1xuXG4gIHJldHVybiBmdW5jdGlvbiAoZCwgYikge1xuICAgIF9leHRlbmRTdGF0aWNzKGQsIGIpO1xuXG4gICAgZnVuY3Rpb24gX18oKSB7XG4gICAgICB0aGlzLmNvbnN0cnVjdG9yID0gZDtcbiAgICB9XG5cbiAgICBkLnByb3RvdHlwZSA9IGIgPT09IG51bGwgPyBPYmplY3QuY3JlYXRlKGIpIDogKF9fLnByb3RvdHlwZSA9IGIucHJvdG90eXBlLCBuZXcgX18oKSk7XG4gIH07XG59KCk7XG4vKipcbiAqIEBtb2R1bGUgb2wvbGF5ZXIvQmFzZVxuICovXG5cblxuaW1wb3J0IEJhc2VPYmplY3QgZnJvbSAnLi4vT2JqZWN0LmpzJztcbmltcG9ydCBMYXllclByb3BlcnR5IGZyb20gJy4vUHJvcGVydHkuanMnO1xuaW1wb3J0IHsgYWJzdHJhY3QgfSBmcm9tICcuLi91dGlsLmpzJztcbmltcG9ydCB7IGFzc2VydCB9IGZyb20gJy4uL2Fzc2VydHMuanMnO1xuaW1wb3J0IHsgYXNzaWduIH0gZnJvbSAnLi4vb2JqLmpzJztcbmltcG9ydCB7IGNsYW1wIH0gZnJvbSAnLi4vbWF0aC5qcyc7XG4vKipcbiAqIEB0eXBlZGVmIHtPYmplY3R9IE9wdGlvbnNcbiAqIEBwcm9wZXJ0eSB7c3RyaW5nfSBbY2xhc3NOYW1lPSdvbC1sYXllciddIEEgQ1NTIGNsYXNzIG5hbWUgdG8gc2V0IHRvIHRoZSBsYXllciBlbGVtZW50LlxuICogQHByb3BlcnR5IHtudW1iZXJ9IFtvcGFjaXR5PTFdIE9wYWNpdHkgKDAsIDEpLlxuICogQHByb3BlcnR5IHtib29sZWFufSBbdmlzaWJsZT10cnVlXSBWaXNpYmlsaXR5LlxuICogQHByb3BlcnR5IHtpbXBvcnQoXCIuLi9leHRlbnQuanNcIikuRXh0ZW50fSBbZXh0ZW50XSBUaGUgYm91bmRpbmcgZXh0ZW50IGZvciBsYXllciByZW5kZXJpbmcuICBUaGUgbGF5ZXIgd2lsbCBub3QgYmVcbiAqIHJlbmRlcmVkIG91dHNpZGUgb2YgdGhpcyBleHRlbnQuXG4gKiBAcHJvcGVydHkge251bWJlcn0gW3pJbmRleF0gVGhlIHotaW5kZXggZm9yIGxheWVyIHJlbmRlcmluZy4gIEF0IHJlbmRlcmluZyB0aW1lLCB0aGUgbGF5ZXJzXG4gKiB3aWxsIGJlIG9yZGVyZWQsIGZpcnN0IGJ5IFotaW5kZXggYW5kIHRoZW4gYnkgcG9zaXRpb24uIFdoZW4gYHVuZGVmaW5lZGAsIGEgYHpJbmRleGAgb2YgMCBpcyBhc3N1bWVkXG4gKiBmb3IgbGF5ZXJzIHRoYXQgYXJlIGFkZGVkIHRvIHRoZSBtYXAncyBgbGF5ZXJzYCBjb2xsZWN0aW9uLCBvciBgSW5maW5pdHlgIHdoZW4gdGhlIGxheWVyJ3MgYHNldE1hcCgpYFxuICogbWV0aG9kIHdhcyB1c2VkLlxuICogQHByb3BlcnR5IHtudW1iZXJ9IFttaW5SZXNvbHV0aW9uXSBUaGUgbWluaW11bSByZXNvbHV0aW9uIChpbmNsdXNpdmUpIGF0IHdoaWNoIHRoaXMgbGF5ZXIgd2lsbCBiZVxuICogdmlzaWJsZS5cbiAqIEBwcm9wZXJ0eSB7bnVtYmVyfSBbbWF4UmVzb2x1dGlvbl0gVGhlIG1heGltdW0gcmVzb2x1dGlvbiAoZXhjbHVzaXZlKSBiZWxvdyB3aGljaCB0aGlzIGxheWVyIHdpbGxcbiAqIGJlIHZpc2libGUuXG4gKiBAcHJvcGVydHkge251bWJlcn0gW21pblpvb21dIFRoZSBtaW5pbXVtIHZpZXcgem9vbSBsZXZlbCAoZXhjbHVzaXZlKSBhYm92ZSB3aGljaCB0aGlzIGxheWVyIHdpbGwgYmVcbiAqIHZpc2libGUuXG4gKiBAcHJvcGVydHkge251bWJlcn0gW21heFpvb21dIFRoZSBtYXhpbXVtIHZpZXcgem9vbSBsZXZlbCAoaW5jbHVzaXZlKSBhdCB3aGljaCB0aGlzIGxheWVyIHdpbGxcbiAqIGJlIHZpc2libGUuXG4gKi9cblxuLyoqXG4gKiBAY2xhc3NkZXNjXG4gKiBBYnN0cmFjdCBiYXNlIGNsYXNzOyBub3JtYWxseSBvbmx5IHVzZWQgZm9yIGNyZWF0aW5nIHN1YmNsYXNzZXMgYW5kIG5vdFxuICogaW5zdGFudGlhdGVkIGluIGFwcHMuXG4gKiBOb3RlIHRoYXQgd2l0aCB7QGxpbmsgbW9kdWxlOm9sL2xheWVyL0Jhc2V9IGFuZCBhbGwgaXRzIHN1YmNsYXNzZXMsIGFueSBwcm9wZXJ0eSBzZXQgaW5cbiAqIHRoZSBvcHRpb25zIGlzIHNldCBhcyBhIHtAbGluayBtb2R1bGU6b2wvT2JqZWN0fSBwcm9wZXJ0eSBvbiB0aGUgbGF5ZXIgb2JqZWN0LCBzb1xuICogaXMgb2JzZXJ2YWJsZSwgYW5kIGhhcyBnZXQvc2V0IGFjY2Vzc29ycy5cbiAqXG4gKiBAYXBpXG4gKi9cblxudmFyIEJhc2VMYXllciA9XG4vKiogQGNsYXNzICovXG5mdW5jdGlvbiAoX3N1cGVyKSB7XG4gIF9fZXh0ZW5kcyhCYXNlTGF5ZXIsIF9zdXBlcik7XG4gIC8qKlxuICAgKiBAcGFyYW0ge09wdGlvbnN9IG9wdGlvbnMgTGF5ZXIgb3B0aW9ucy5cbiAgICovXG5cblxuICBmdW5jdGlvbiBCYXNlTGF5ZXIob3B0aW9ucykge1xuICAgIHZhciBfdGhpcyA9IF9zdXBlci5jYWxsKHRoaXMpIHx8IHRoaXM7XG4gICAgLyoqXG4gICAgICogQHR5cGUge09iamVjdDxzdHJpbmcsICo+fVxuICAgICAqL1xuXG5cbiAgICB2YXIgcHJvcGVydGllcyA9IGFzc2lnbih7fSwgb3B0aW9ucyk7XG4gICAgcHJvcGVydGllc1tMYXllclByb3BlcnR5Lk9QQUNJVFldID0gb3B0aW9ucy5vcGFjaXR5ICE9PSB1bmRlZmluZWQgPyBvcHRpb25zLm9wYWNpdHkgOiAxO1xuICAgIGFzc2VydCh0eXBlb2YgcHJvcGVydGllc1tMYXllclByb3BlcnR5Lk9QQUNJVFldID09PSAnbnVtYmVyJywgNjQpOyAvLyBMYXllciBvcGFjaXR5IG11c3QgYmUgYSBudW1iZXJcblxuICAgIHByb3BlcnRpZXNbTGF5ZXJQcm9wZXJ0eS5WSVNJQkxFXSA9IG9wdGlvbnMudmlzaWJsZSAhPT0gdW5kZWZpbmVkID8gb3B0aW9ucy52aXNpYmxlIDogdHJ1ZTtcbiAgICBwcm9wZXJ0aWVzW0xheWVyUHJvcGVydHkuWl9JTkRFWF0gPSBvcHRpb25zLnpJbmRleDtcbiAgICBwcm9wZXJ0aWVzW0xheWVyUHJvcGVydHkuTUFYX1JFU09MVVRJT05dID0gb3B0aW9ucy5tYXhSZXNvbHV0aW9uICE9PSB1bmRlZmluZWQgPyBvcHRpb25zLm1heFJlc29sdXRpb24gOiBJbmZpbml0eTtcbiAgICBwcm9wZXJ0aWVzW0xheWVyUHJvcGVydHkuTUlOX1JFU09MVVRJT05dID0gb3B0aW9ucy5taW5SZXNvbHV0aW9uICE9PSB1bmRlZmluZWQgPyBvcHRpb25zLm1pblJlc29sdXRpb24gOiAwO1xuICAgIHByb3BlcnRpZXNbTGF5ZXJQcm9wZXJ0eS5NSU5fWk9PTV0gPSBvcHRpb25zLm1pblpvb20gIT09IHVuZGVmaW5lZCA/IG9wdGlvbnMubWluWm9vbSA6IC1JbmZpbml0eTtcbiAgICBwcm9wZXJ0aWVzW0xheWVyUHJvcGVydHkuTUFYX1pPT01dID0gb3B0aW9ucy5tYXhab29tICE9PSB1bmRlZmluZWQgPyBvcHRpb25zLm1heFpvb20gOiBJbmZpbml0eTtcbiAgICAvKipcbiAgICAgKiBAdHlwZSB7c3RyaW5nfVxuICAgICAqIEBwcml2YXRlXG4gICAgICovXG5cbiAgICBfdGhpcy5jbGFzc05hbWVfID0gcHJvcGVydGllcy5jbGFzc05hbWUgIT09IHVuZGVmaW5lZCA/IG9wdGlvbnMuY2xhc3NOYW1lIDogJ29sLWxheWVyJztcbiAgICBkZWxldGUgcHJvcGVydGllcy5jbGFzc05hbWU7XG5cbiAgICBfdGhpcy5zZXRQcm9wZXJ0aWVzKHByb3BlcnRpZXMpO1xuICAgIC8qKlxuICAgICAqIEB0eXBlIHtpbXBvcnQoXCIuL0xheWVyLmpzXCIpLlN0YXRlfVxuICAgICAqIEBwcml2YXRlXG4gICAgICovXG5cblxuICAgIF90aGlzLnN0YXRlXyA9IG51bGw7XG4gICAgcmV0dXJuIF90aGlzO1xuICB9XG4gIC8qKlxuICAgKiBAcmV0dXJuIHtzdHJpbmd9IENTUyBjbGFzcyBuYW1lLlxuICAgKi9cblxuXG4gIEJhc2VMYXllci5wcm90b3R5cGUuZ2V0Q2xhc3NOYW1lID0gZnVuY3Rpb24gKCkge1xuICAgIHJldHVybiB0aGlzLmNsYXNzTmFtZV87XG4gIH07XG4gIC8qKlxuICAgKiBUaGlzIG1ldGhvZCBpcyBub3QgbWVhbnQgdG8gYmUgY2FsbGVkIGJ5IGxheWVycyBvciBsYXllciByZW5kZXJlcnMgYmVjYXVzZSB0aGUgc3RhdGVcbiAgICogaXMgaW5jb3JyZWN0IGlmIHRoZSBsYXllciBpcyBpbmNsdWRlZCBpbiBhIGxheWVyIGdyb3VwLlxuICAgKlxuICAgKiBAcGFyYW0ge2Jvb2xlYW49fSBvcHRfbWFuYWdlZCBMYXllciBpcyBtYW5hZ2VkLlxuICAgKiBAcmV0dXJuIHtpbXBvcnQoXCIuL0xheWVyLmpzXCIpLlN0YXRlfSBMYXllciBzdGF0ZS5cbiAgICovXG5cblxuICBCYXNlTGF5ZXIucHJvdG90eXBlLmdldExheWVyU3RhdGUgPSBmdW5jdGlvbiAob3B0X21hbmFnZWQpIHtcbiAgICAvKiogQHR5cGUge2ltcG9ydChcIi4vTGF5ZXIuanNcIikuU3RhdGV9ICovXG4gICAgdmFyIHN0YXRlID0gdGhpcy5zdGF0ZV8gfHxcbiAgICAvKiogQHR5cGUgez99ICovXG4gICAge1xuICAgICAgbGF5ZXI6IHRoaXMsXG4gICAgICBtYW5hZ2VkOiBvcHRfbWFuYWdlZCA9PT0gdW5kZWZpbmVkID8gdHJ1ZSA6IG9wdF9tYW5hZ2VkXG4gICAgfTtcbiAgICB2YXIgekluZGV4ID0gdGhpcy5nZXRaSW5kZXgoKTtcbiAgICBzdGF0ZS5vcGFjaXR5ID0gY2xhbXAoTWF0aC5yb3VuZCh0aGlzLmdldE9wYWNpdHkoKSAqIDEwMCkgLyAxMDAsIDAsIDEpO1xuICAgIHN0YXRlLnNvdXJjZVN0YXRlID0gdGhpcy5nZXRTb3VyY2VTdGF0ZSgpO1xuICAgIHN0YXRlLnZpc2libGUgPSB0aGlzLmdldFZpc2libGUoKTtcbiAgICBzdGF0ZS5leHRlbnQgPSB0aGlzLmdldEV4dGVudCgpO1xuICAgIHN0YXRlLnpJbmRleCA9IHpJbmRleCAhPT0gdW5kZWZpbmVkID8gekluZGV4IDogc3RhdGUubWFuYWdlZCA9PT0gZmFsc2UgPyBJbmZpbml0eSA6IDA7XG4gICAgc3RhdGUubWF4UmVzb2x1dGlvbiA9IHRoaXMuZ2V0TWF4UmVzb2x1dGlvbigpO1xuICAgIHN0YXRlLm1pblJlc29sdXRpb24gPSBNYXRoLm1heCh0aGlzLmdldE1pblJlc29sdXRpb24oKSwgMCk7XG4gICAgc3RhdGUubWluWm9vbSA9IHRoaXMuZ2V0TWluWm9vbSgpO1xuICAgIHN0YXRlLm1heFpvb20gPSB0aGlzLmdldE1heFpvb20oKTtcbiAgICB0aGlzLnN0YXRlXyA9IHN0YXRlO1xuICAgIHJldHVybiBzdGF0ZTtcbiAgfTtcbiAgLyoqXG4gICAqIEBhYnN0cmFjdFxuICAgKiBAcGFyYW0ge0FycmF5PGltcG9ydChcIi4vTGF5ZXIuanNcIikuZGVmYXVsdD49fSBvcHRfYXJyYXkgQXJyYXkgb2YgbGF5ZXJzICh0byBiZVxuICAgKiAgICAgbW9kaWZpZWQgaW4gcGxhY2UpLlxuICAgKiBAcmV0dXJuIHtBcnJheTxpbXBvcnQoXCIuL0xheWVyLmpzXCIpLmRlZmF1bHQ+fSBBcnJheSBvZiBsYXllcnMuXG4gICAqL1xuXG5cbiAgQmFzZUxheWVyLnByb3RvdHlwZS5nZXRMYXllcnNBcnJheSA9IGZ1bmN0aW9uIChvcHRfYXJyYXkpIHtcbiAgICByZXR1cm4gYWJzdHJhY3QoKTtcbiAgfTtcbiAgLyoqXG4gICAqIEBhYnN0cmFjdFxuICAgKiBAcGFyYW0ge0FycmF5PGltcG9ydChcIi4vTGF5ZXIuanNcIikuU3RhdGU+PX0gb3B0X3N0YXRlcyBPcHRpb25hbCBsaXN0IG9mIGxheWVyXG4gICAqICAgICBzdGF0ZXMgKHRvIGJlIG1vZGlmaWVkIGluIHBsYWNlKS5cbiAgICogQHJldHVybiB7QXJyYXk8aW1wb3J0KFwiLi9MYXllci5qc1wiKS5TdGF0ZT59IExpc3Qgb2YgbGF5ZXIgc3RhdGVzLlxuICAgKi9cblxuXG4gIEJhc2VMYXllci5wcm90b3R5cGUuZ2V0TGF5ZXJTdGF0ZXNBcnJheSA9IGZ1bmN0aW9uIChvcHRfc3RhdGVzKSB7XG4gICAgcmV0dXJuIGFic3RyYWN0KCk7XG4gIH07XG4gIC8qKlxuICAgKiBSZXR1cm4gdGhlIHtAbGluayBtb2R1bGU6b2wvZXh0ZW50fkV4dGVudCBleHRlbnR9IG9mIHRoZSBsYXllciBvciBgdW5kZWZpbmVkYCBpZiBpdFxuICAgKiB3aWxsIGJlIHZpc2libGUgcmVnYXJkbGVzcyBvZiBleHRlbnQuXG4gICAqIEByZXR1cm4ge2ltcG9ydChcIi4uL2V4dGVudC5qc1wiKS5FeHRlbnR8dW5kZWZpbmVkfSBUaGUgbGF5ZXIgZXh0ZW50LlxuICAgKiBAb2JzZXJ2YWJsZVxuICAgKiBAYXBpXG4gICAqL1xuXG5cbiAgQmFzZUxheWVyLnByb3RvdHlwZS5nZXRFeHRlbnQgPSBmdW5jdGlvbiAoKSB7XG4gICAgcmV0dXJuIChcbiAgICAgIC8qKiBAdHlwZSB7aW1wb3J0KFwiLi4vZXh0ZW50LmpzXCIpLkV4dGVudHx1bmRlZmluZWR9ICovXG4gICAgICB0aGlzLmdldChMYXllclByb3BlcnR5LkVYVEVOVClcbiAgICApO1xuICB9O1xuICAvKipcbiAgICogUmV0dXJuIHRoZSBtYXhpbXVtIHJlc29sdXRpb24gb2YgdGhlIGxheWVyLlxuICAgKiBAcmV0dXJuIHtudW1iZXJ9IFRoZSBtYXhpbXVtIHJlc29sdXRpb24gb2YgdGhlIGxheWVyLlxuICAgKiBAb2JzZXJ2YWJsZVxuICAgKiBAYXBpXG4gICAqL1xuXG5cbiAgQmFzZUxheWVyLnByb3RvdHlwZS5nZXRNYXhSZXNvbHV0aW9uID0gZnVuY3Rpb24gKCkge1xuICAgIHJldHVybiAoXG4gICAgICAvKiogQHR5cGUge251bWJlcn0gKi9cbiAgICAgIHRoaXMuZ2V0KExheWVyUHJvcGVydHkuTUFYX1JFU09MVVRJT04pXG4gICAgKTtcbiAgfTtcbiAgLyoqXG4gICAqIFJldHVybiB0aGUgbWluaW11bSByZXNvbHV0aW9uIG9mIHRoZSBsYXllci5cbiAgICogQHJldHVybiB7bnVtYmVyfSBUaGUgbWluaW11bSByZXNvbHV0aW9uIG9mIHRoZSBsYXllci5cbiAgICogQG9ic2VydmFibGVcbiAgICogQGFwaVxuICAgKi9cblxuXG4gIEJhc2VMYXllci5wcm90b3R5cGUuZ2V0TWluUmVzb2x1dGlvbiA9IGZ1bmN0aW9uICgpIHtcbiAgICByZXR1cm4gKFxuICAgICAgLyoqIEB0eXBlIHtudW1iZXJ9ICovXG4gICAgICB0aGlzLmdldChMYXllclByb3BlcnR5Lk1JTl9SRVNPTFVUSU9OKVxuICAgICk7XG4gIH07XG4gIC8qKlxuICAgKiBSZXR1cm4gdGhlIG1pbmltdW0gem9vbSBsZXZlbCBvZiB0aGUgbGF5ZXIuXG4gICAqIEByZXR1cm4ge251bWJlcn0gVGhlIG1pbmltdW0gem9vbSBsZXZlbCBvZiB0aGUgbGF5ZXIuXG4gICAqIEBvYnNlcnZhYmxlXG4gICAqIEBhcGlcbiAgICovXG5cblxuICBCYXNlTGF5ZXIucHJvdG90eXBlLmdldE1pblpvb20gPSBmdW5jdGlvbiAoKSB7XG4gICAgcmV0dXJuIChcbiAgICAgIC8qKiBAdHlwZSB7bnVtYmVyfSAqL1xuICAgICAgdGhpcy5nZXQoTGF5ZXJQcm9wZXJ0eS5NSU5fWk9PTSlcbiAgICApO1xuICB9O1xuICAvKipcbiAgICogUmV0dXJuIHRoZSBtYXhpbXVtIHpvb20gbGV2ZWwgb2YgdGhlIGxheWVyLlxuICAgKiBAcmV0dXJuIHtudW1iZXJ9IFRoZSBtYXhpbXVtIHpvb20gbGV2ZWwgb2YgdGhlIGxheWVyLlxuICAgKiBAb2JzZXJ2YWJsZVxuICAgKiBAYXBpXG4gICAqL1xuXG5cbiAgQmFzZUxheWVyLnByb3RvdHlwZS5nZXRNYXhab29tID0gZnVuY3Rpb24gKCkge1xuICAgIHJldHVybiAoXG4gICAgICAvKiogQHR5cGUge251bWJlcn0gKi9cbiAgICAgIHRoaXMuZ2V0KExheWVyUHJvcGVydHkuTUFYX1pPT00pXG4gICAgKTtcbiAgfTtcbiAgLyoqXG4gICAqIFJldHVybiB0aGUgb3BhY2l0eSBvZiB0aGUgbGF5ZXIgKGJldHdlZW4gMCBhbmQgMSkuXG4gICAqIEByZXR1cm4ge251bWJlcn0gVGhlIG9wYWNpdHkgb2YgdGhlIGxheWVyLlxuICAgKiBAb2JzZXJ2YWJsZVxuICAgKiBAYXBpXG4gICAqL1xuXG5cbiAgQmFzZUxheWVyLnByb3RvdHlwZS5nZXRPcGFjaXR5ID0gZnVuY3Rpb24gKCkge1xuICAgIHJldHVybiAoXG4gICAgICAvKiogQHR5cGUge251bWJlcn0gKi9cbiAgICAgIHRoaXMuZ2V0KExheWVyUHJvcGVydHkuT1BBQ0lUWSlcbiAgICApO1xuICB9O1xuICAvKipcbiAgICogQGFic3RyYWN0XG4gICAqIEByZXR1cm4ge2ltcG9ydChcIi4uL3NvdXJjZS9TdGF0ZS5qc1wiKS5kZWZhdWx0fSBTb3VyY2Ugc3RhdGUuXG4gICAqL1xuXG5cbiAgQmFzZUxheWVyLnByb3RvdHlwZS5nZXRTb3VyY2VTdGF0ZSA9IGZ1bmN0aW9uICgpIHtcbiAgICByZXR1cm4gYWJzdHJhY3QoKTtcbiAgfTtcbiAgLyoqXG4gICAqIFJldHVybiB0aGUgdmlzaWJpbGl0eSBvZiB0aGUgbGF5ZXIgKGB0cnVlYCBvciBgZmFsc2VgKS5cbiAgICogQHJldHVybiB7Ym9vbGVhbn0gVGhlIHZpc2liaWxpdHkgb2YgdGhlIGxheWVyLlxuICAgKiBAb2JzZXJ2YWJsZVxuICAgKiBAYXBpXG4gICAqL1xuXG5cbiAgQmFzZUxheWVyLnByb3RvdHlwZS5nZXRWaXNpYmxlID0gZnVuY3Rpb24gKCkge1xuICAgIHJldHVybiAoXG4gICAgICAvKiogQHR5cGUge2Jvb2xlYW59ICovXG4gICAgICB0aGlzLmdldChMYXllclByb3BlcnR5LlZJU0lCTEUpXG4gICAgKTtcbiAgfTtcbiAgLyoqXG4gICAqIFJldHVybiB0aGUgWi1pbmRleCBvZiB0aGUgbGF5ZXIsIHdoaWNoIGlzIHVzZWQgdG8gb3JkZXIgbGF5ZXJzIGJlZm9yZVxuICAgKiByZW5kZXJpbmcuIFRoZSBkZWZhdWx0IFotaW5kZXggaXMgMC5cbiAgICogQHJldHVybiB7bnVtYmVyfSBUaGUgWi1pbmRleCBvZiB0aGUgbGF5ZXIuXG4gICAqIEBvYnNlcnZhYmxlXG4gICAqIEBhcGlcbiAgICovXG5cblxuICBCYXNlTGF5ZXIucHJvdG90eXBlLmdldFpJbmRleCA9IGZ1bmN0aW9uICgpIHtcbiAgICByZXR1cm4gKFxuICAgICAgLyoqIEB0eXBlIHtudW1iZXJ9ICovXG4gICAgICB0aGlzLmdldChMYXllclByb3BlcnR5LlpfSU5ERVgpXG4gICAgKTtcbiAgfTtcbiAgLyoqXG4gICAqIFNldCB0aGUgZXh0ZW50IGF0IHdoaWNoIHRoZSBsYXllciBpcyB2aXNpYmxlLiAgSWYgYHVuZGVmaW5lZGAsIHRoZSBsYXllclxuICAgKiB3aWxsIGJlIHZpc2libGUgYXQgYWxsIGV4dGVudHMuXG4gICAqIEBwYXJhbSB7aW1wb3J0KFwiLi4vZXh0ZW50LmpzXCIpLkV4dGVudHx1bmRlZmluZWR9IGV4dGVudCBUaGUgZXh0ZW50IG9mIHRoZSBsYXllci5cbiAgICogQG9ic2VydmFibGVcbiAgICogQGFwaVxuICAgKi9cblxuXG4gIEJhc2VMYXllci5wcm90b3R5cGUuc2V0RXh0ZW50ID0gZnVuY3Rpb24gKGV4dGVudCkge1xuICAgIHRoaXMuc2V0KExheWVyUHJvcGVydHkuRVhURU5ULCBleHRlbnQpO1xuICB9O1xuICAvKipcbiAgICogU2V0IHRoZSBtYXhpbXVtIHJlc29sdXRpb24gYXQgd2hpY2ggdGhlIGxheWVyIGlzIHZpc2libGUuXG4gICAqIEBwYXJhbSB7bnVtYmVyfSBtYXhSZXNvbHV0aW9uIFRoZSBtYXhpbXVtIHJlc29sdXRpb24gb2YgdGhlIGxheWVyLlxuICAgKiBAb2JzZXJ2YWJsZVxuICAgKiBAYXBpXG4gICAqL1xuXG5cbiAgQmFzZUxheWVyLnByb3RvdHlwZS5zZXRNYXhSZXNvbHV0aW9uID0gZnVuY3Rpb24gKG1heFJlc29sdXRpb24pIHtcbiAgICB0aGlzLnNldChMYXllclByb3BlcnR5Lk1BWF9SRVNPTFVUSU9OLCBtYXhSZXNvbHV0aW9uKTtcbiAgfTtcbiAgLyoqXG4gICAqIFNldCB0aGUgbWluaW11bSByZXNvbHV0aW9uIGF0IHdoaWNoIHRoZSBsYXllciBpcyB2aXNpYmxlLlxuICAgKiBAcGFyYW0ge251bWJlcn0gbWluUmVzb2x1dGlvbiBUaGUgbWluaW11bSByZXNvbHV0aW9uIG9mIHRoZSBsYXllci5cbiAgICogQG9ic2VydmFibGVcbiAgICogQGFwaVxuICAgKi9cblxuXG4gIEJhc2VMYXllci5wcm90b3R5cGUuc2V0TWluUmVzb2x1dGlvbiA9IGZ1bmN0aW9uIChtaW5SZXNvbHV0aW9uKSB7XG4gICAgdGhpcy5zZXQoTGF5ZXJQcm9wZXJ0eS5NSU5fUkVTT0xVVElPTiwgbWluUmVzb2x1dGlvbik7XG4gIH07XG4gIC8qKlxuICAgKiBTZXQgdGhlIG1heGltdW0gem9vbSAoZXhjbHVzaXZlKSBhdCB3aGljaCB0aGUgbGF5ZXIgaXMgdmlzaWJsZS5cbiAgICogTm90ZSB0aGF0IHRoZSB6b29tIGxldmVscyBmb3IgbGF5ZXIgdmlzaWJpbGl0eSBhcmUgYmFzZWQgb24gdGhlXG4gICAqIHZpZXcgem9vbSBsZXZlbCwgd2hpY2ggbWF5IGJlIGRpZmZlcmVudCBmcm9tIGEgdGlsZSBzb3VyY2Ugem9vbSBsZXZlbC5cbiAgICogQHBhcmFtIHtudW1iZXJ9IG1heFpvb20gVGhlIG1heGltdW0gem9vbSBvZiB0aGUgbGF5ZXIuXG4gICAqIEBvYnNlcnZhYmxlXG4gICAqIEBhcGlcbiAgICovXG5cblxuICBCYXNlTGF5ZXIucHJvdG90eXBlLnNldE1heFpvb20gPSBmdW5jdGlvbiAobWF4Wm9vbSkge1xuICAgIHRoaXMuc2V0KExheWVyUHJvcGVydHkuTUFYX1pPT00sIG1heFpvb20pO1xuICB9O1xuICAvKipcbiAgICogU2V0IHRoZSBtaW5pbXVtIHpvb20gKGluY2x1c2l2ZSkgYXQgd2hpY2ggdGhlIGxheWVyIGlzIHZpc2libGUuXG4gICAqIE5vdGUgdGhhdCB0aGUgem9vbSBsZXZlbHMgZm9yIGxheWVyIHZpc2liaWxpdHkgYXJlIGJhc2VkIG9uIHRoZVxuICAgKiB2aWV3IHpvb20gbGV2ZWwsIHdoaWNoIG1heSBiZSBkaWZmZXJlbnQgZnJvbSBhIHRpbGUgc291cmNlIHpvb20gbGV2ZWwuXG4gICAqIEBwYXJhbSB7bnVtYmVyfSBtaW5ab29tIFRoZSBtaW5pbXVtIHpvb20gb2YgdGhlIGxheWVyLlxuICAgKiBAb2JzZXJ2YWJsZVxuICAgKiBAYXBpXG4gICAqL1xuXG5cbiAgQmFzZUxheWVyLnByb3RvdHlwZS5zZXRNaW5ab29tID0gZnVuY3Rpb24gKG1pblpvb20pIHtcbiAgICB0aGlzLnNldChMYXllclByb3BlcnR5Lk1JTl9aT09NLCBtaW5ab29tKTtcbiAgfTtcbiAgLyoqXG4gICAqIFNldCB0aGUgb3BhY2l0eSBvZiB0aGUgbGF5ZXIsIGFsbG93ZWQgdmFsdWVzIHJhbmdlIGZyb20gMCB0byAxLlxuICAgKiBAcGFyYW0ge251bWJlcn0gb3BhY2l0eSBUaGUgb3BhY2l0eSBvZiB0aGUgbGF5ZXIuXG4gICAqIEBvYnNlcnZhYmxlXG4gICAqIEBhcGlcbiAgICovXG5cblxuICBCYXNlTGF5ZXIucHJvdG90eXBlLnNldE9wYWNpdHkgPSBmdW5jdGlvbiAob3BhY2l0eSkge1xuICAgIGFzc2VydCh0eXBlb2Ygb3BhY2l0eSA9PT0gJ251bWJlcicsIDY0KTsgLy8gTGF5ZXIgb3BhY2l0eSBtdXN0IGJlIGEgbnVtYmVyXG5cbiAgICB0aGlzLnNldChMYXllclByb3BlcnR5Lk9QQUNJVFksIG9wYWNpdHkpO1xuICB9O1xuICAvKipcbiAgICogU2V0IHRoZSB2aXNpYmlsaXR5IG9mIHRoZSBsYXllciAoYHRydWVgIG9yIGBmYWxzZWApLlxuICAgKiBAcGFyYW0ge2Jvb2xlYW59IHZpc2libGUgVGhlIHZpc2liaWxpdHkgb2YgdGhlIGxheWVyLlxuICAgKiBAb2JzZXJ2YWJsZVxuICAgKiBAYXBpXG4gICAqL1xuXG5cbiAgQmFzZUxheWVyLnByb3RvdHlwZS5zZXRWaXNpYmxlID0gZnVuY3Rpb24gKHZpc2libGUpIHtcbiAgICB0aGlzLnNldChMYXllclByb3BlcnR5LlZJU0lCTEUsIHZpc2libGUpO1xuICB9O1xuICAvKipcbiAgICogU2V0IFotaW5kZXggb2YgdGhlIGxheWVyLCB3aGljaCBpcyB1c2VkIHRvIG9yZGVyIGxheWVycyBiZWZvcmUgcmVuZGVyaW5nLlxuICAgKiBUaGUgZGVmYXVsdCBaLWluZGV4IGlzIDAuXG4gICAqIEBwYXJhbSB7bnVtYmVyfSB6aW5kZXggVGhlIHotaW5kZXggb2YgdGhlIGxheWVyLlxuICAgKiBAb2JzZXJ2YWJsZVxuICAgKiBAYXBpXG4gICAqL1xuXG5cbiAgQmFzZUxheWVyLnByb3RvdHlwZS5zZXRaSW5kZXggPSBmdW5jdGlvbiAoemluZGV4KSB7XG4gICAgdGhpcy5zZXQoTGF5ZXJQcm9wZXJ0eS5aX0lOREVYLCB6aW5kZXgpO1xuICB9O1xuICAvKipcbiAgICogQ2xlYW4gdXAuXG4gICAqL1xuXG5cbiAgQmFzZUxheWVyLnByb3RvdHlwZS5kaXNwb3NlSW50ZXJuYWwgPSBmdW5jdGlvbiAoKSB7XG4gICAgaWYgKHRoaXMuc3RhdGVfKSB7XG4gICAgICB0aGlzLnN0YXRlXy5sYXllciA9IG51bGw7XG4gICAgICB0aGlzLnN0YXRlXyA9IG51bGw7XG4gICAgfVxuXG4gICAgX3N1cGVyLnByb3RvdHlwZS5kaXNwb3NlSW50ZXJuYWwuY2FsbCh0aGlzKTtcbiAgfTtcblxuICByZXR1cm4gQmFzZUxheWVyO1xufShCYXNlT2JqZWN0KTtcblxuZXhwb3J0IGRlZmF1bHQgQmFzZUxheWVyOyIsIi8qKlxuICogQG1vZHVsZSBvbC9yZW5kZXIvRXZlbnRUeXBlXG4gKi9cblxuLyoqXG4gKiBAZW51bSB7c3RyaW5nfVxuICovXG5leHBvcnQgZGVmYXVsdCB7XG4gIC8qKlxuICAgKiBUcmlnZ2VyZWQgYmVmb3JlIGEgbGF5ZXIgaXMgcmVuZGVyZWQuXG4gICAqIEBldmVudCBtb2R1bGU6b2wvcmVuZGVyL0V2ZW50flJlbmRlckV2ZW50I3ByZXJlbmRlclxuICAgKiBAYXBpXG4gICAqL1xuICBQUkVSRU5ERVI6ICdwcmVyZW5kZXInLFxuXG4gIC8qKlxuICAgKiBUcmlnZ2VyZWQgYWZ0ZXIgYSBsYXllciBpcyByZW5kZXJlZC5cbiAgICogQGV2ZW50IG1vZHVsZTpvbC9yZW5kZXIvRXZlbnR+UmVuZGVyRXZlbnQjcG9zdHJlbmRlclxuICAgKiBAYXBpXG4gICAqL1xuICBQT1NUUkVOREVSOiAncG9zdHJlbmRlcicsXG5cbiAgLyoqXG4gICAqIFRyaWdnZXJlZCBiZWZvcmUgbGF5ZXJzIGFyZSByZW5kZXJlZC5cbiAgICogVGhlIGV2ZW50IG9iamVjdCB3aWxsIG5vdCBoYXZlIGEgYGNvbnRleHRgIHNldC5cbiAgICogQGV2ZW50IG1vZHVsZTpvbC9yZW5kZXIvRXZlbnR+UmVuZGVyRXZlbnQjcHJlY29tcG9zZVxuICAgKiBAYXBpXG4gICAqL1xuICBQUkVDT01QT1NFOiAncHJlY29tcG9zZScsXG5cbiAgLyoqXG4gICAqIFRyaWdnZXJlZCBhZnRlciBhbGwgbGF5ZXJzIGFyZSByZW5kZXJlZC5cbiAgICogVGhlIGV2ZW50IG9iamVjdCB3aWxsIG5vdCBoYXZlIGEgYGNvbnRleHRgIHNldC5cbiAgICogQGV2ZW50IG1vZHVsZTpvbC9yZW5kZXIvRXZlbnR+UmVuZGVyRXZlbnQjcG9zdGNvbXBvc2VcbiAgICogQGFwaVxuICAgKi9cbiAgUE9TVENPTVBPU0U6ICdwb3N0Y29tcG9zZScsXG5cbiAgLyoqXG4gICAqIFRyaWdnZXJlZCB3aGVuIHJlbmRlcmluZyBpcyBjb21wbGV0ZSwgaS5lLiBhbGwgc291cmNlcyBhbmQgdGlsZXMgaGF2ZVxuICAgKiBmaW5pc2hlZCBsb2FkaW5nIGZvciB0aGUgY3VycmVudCB2aWV3cG9ydCwgYW5kIGFsbCB0aWxlcyBhcmUgZmFkZWQgaW4uXG4gICAqIFRoZSBldmVudCBvYmplY3Qgd2lsbCBub3QgaGF2ZSBhIGBjb250ZXh0YCBzZXQuXG4gICAqIEBldmVudCBtb2R1bGU6b2wvcmVuZGVyL0V2ZW50flJlbmRlckV2ZW50I3JlbmRlcmNvbXBsZXRlXG4gICAqIEBhcGlcbiAgICovXG4gIFJFTkRFUkNPTVBMRVRFOiAncmVuZGVyY29tcGxldGUnXG59OyIsIi8qKlxuICogQG1vZHVsZSBvbC9zb3VyY2UvU3RhdGVcbiAqL1xuXG4vKipcbiAqIEBlbnVtIHtzdHJpbmd9XG4gKiBTdGF0ZSBvZiB0aGUgc291cmNlLCBvbmUgb2YgJ3VuZGVmaW5lZCcsICdsb2FkaW5nJywgJ3JlYWR5JyBvciAnZXJyb3InLlxuICovXG5leHBvcnQgZGVmYXVsdCB7XG4gIFVOREVGSU5FRDogJ3VuZGVmaW5lZCcsXG4gIExPQURJTkc6ICdsb2FkaW5nJyxcbiAgUkVBRFk6ICdyZWFkeScsXG4gIEVSUk9SOiAnZXJyb3InXG59OyIsInZhciBfX2V4dGVuZHMgPSB0aGlzICYmIHRoaXMuX19leHRlbmRzIHx8IGZ1bmN0aW9uICgpIHtcbiAgdmFyIF9leHRlbmRTdGF0aWNzID0gZnVuY3Rpb24gZXh0ZW5kU3RhdGljcyhkLCBiKSB7XG4gICAgX2V4dGVuZFN0YXRpY3MgPSBPYmplY3Quc2V0UHJvdG90eXBlT2YgfHwge1xuICAgICAgX19wcm90b19fOiBbXVxuICAgIH0gaW5zdGFuY2VvZiBBcnJheSAmJiBmdW5jdGlvbiAoZCwgYikge1xuICAgICAgZC5fX3Byb3RvX18gPSBiO1xuICAgIH0gfHwgZnVuY3Rpb24gKGQsIGIpIHtcbiAgICAgIGZvciAodmFyIHAgaW4gYikge1xuICAgICAgICBpZiAoT2JqZWN0LnByb3RvdHlwZS5oYXNPd25Qcm9wZXJ0eS5jYWxsKGIsIHApKSBkW3BdID0gYltwXTtcbiAgICAgIH1cbiAgICB9O1xuXG4gICAgcmV0dXJuIF9leHRlbmRTdGF0aWNzKGQsIGIpO1xuICB9O1xuXG4gIHJldHVybiBmdW5jdGlvbiAoZCwgYikge1xuICAgIF9leHRlbmRTdGF0aWNzKGQsIGIpO1xuXG4gICAgZnVuY3Rpb24gX18oKSB7XG4gICAgICB0aGlzLmNvbnN0cnVjdG9yID0gZDtcbiAgICB9XG5cbiAgICBkLnByb3RvdHlwZSA9IGIgPT09IG51bGwgPyBPYmplY3QuY3JlYXRlKGIpIDogKF9fLnByb3RvdHlwZSA9IGIucHJvdG90eXBlLCBuZXcgX18oKSk7XG4gIH07XG59KCk7XG4vKipcbiAqIEBtb2R1bGUgb2wvbGF5ZXIvTGF5ZXJcbiAqL1xuXG5cbmltcG9ydCBCYXNlTGF5ZXIgZnJvbSAnLi9CYXNlLmpzJztcbmltcG9ydCBFdmVudFR5cGUgZnJvbSAnLi4vZXZlbnRzL0V2ZW50VHlwZS5qcyc7XG5pbXBvcnQgTGF5ZXJQcm9wZXJ0eSBmcm9tICcuL1Byb3BlcnR5LmpzJztcbmltcG9ydCBSZW5kZXJFdmVudFR5cGUgZnJvbSAnLi4vcmVuZGVyL0V2ZW50VHlwZS5qcyc7XG5pbXBvcnQgU291cmNlU3RhdGUgZnJvbSAnLi4vc291cmNlL1N0YXRlLmpzJztcbmltcG9ydCB7IGFzc2VydCB9IGZyb20gJy4uL2Fzc2VydHMuanMnO1xuaW1wb3J0IHsgYXNzaWduIH0gZnJvbSAnLi4vb2JqLmpzJztcbmltcG9ydCB7IGdldENoYW5nZUV2ZW50VHlwZSB9IGZyb20gJy4uL09iamVjdC5qcyc7XG5pbXBvcnQgeyBsaXN0ZW4sIHVubGlzdGVuQnlLZXkgfSBmcm9tICcuLi9ldmVudHMuanMnO1xuLyoqXG4gKiBAdHlwZWRlZiB7ZnVuY3Rpb24oaW1wb3J0KFwiLi4vUGx1Z2dhYmxlTWFwLmpzXCIpLkZyYW1lU3RhdGUpOkhUTUxFbGVtZW50fSBSZW5kZXJGdW5jdGlvblxuICovXG5cbi8qKlxuICogQHR5cGVkZWYge09iamVjdH0gT3B0aW9uc1xuICogQHByb3BlcnR5IHtzdHJpbmd9IFtjbGFzc05hbWU9J29sLWxheWVyJ10gQSBDU1MgY2xhc3MgbmFtZSB0byBzZXQgdG8gdGhlIGxheWVyIGVsZW1lbnQuXG4gKiBAcHJvcGVydHkge251bWJlcn0gW29wYWNpdHk9MV0gT3BhY2l0eSAoMCwgMSkuXG4gKiBAcHJvcGVydHkge2Jvb2xlYW59IFt2aXNpYmxlPXRydWVdIFZpc2liaWxpdHkuXG4gKiBAcHJvcGVydHkge2ltcG9ydChcIi4uL2V4dGVudC5qc1wiKS5FeHRlbnR9IFtleHRlbnRdIFRoZSBib3VuZGluZyBleHRlbnQgZm9yIGxheWVyIHJlbmRlcmluZy4gIFRoZSBsYXllciB3aWxsIG5vdCBiZVxuICogcmVuZGVyZWQgb3V0c2lkZSBvZiB0aGlzIGV4dGVudC5cbiAqIEBwcm9wZXJ0eSB7bnVtYmVyfSBbekluZGV4XSBUaGUgei1pbmRleCBmb3IgbGF5ZXIgcmVuZGVyaW5nLiAgQXQgcmVuZGVyaW5nIHRpbWUsIHRoZSBsYXllcnNcbiAqIHdpbGwgYmUgb3JkZXJlZCwgZmlyc3QgYnkgWi1pbmRleCBhbmQgdGhlbiBieSBwb3NpdGlvbi4gV2hlbiBgdW5kZWZpbmVkYCwgYSBgekluZGV4YCBvZiAwIGlzIGFzc3VtZWRcbiAqIGZvciBsYXllcnMgdGhhdCBhcmUgYWRkZWQgdG8gdGhlIG1hcCdzIGBsYXllcnNgIGNvbGxlY3Rpb24sIG9yIGBJbmZpbml0eWAgd2hlbiB0aGUgbGF5ZXIncyBgc2V0TWFwKClgXG4gKiBtZXRob2Qgd2FzIHVzZWQuXG4gKiBAcHJvcGVydHkge251bWJlcn0gW21pblJlc29sdXRpb25dIFRoZSBtaW5pbXVtIHJlc29sdXRpb24gKGluY2x1c2l2ZSkgYXQgd2hpY2ggdGhpcyBsYXllciB3aWxsIGJlXG4gKiB2aXNpYmxlLlxuICogQHByb3BlcnR5IHtudW1iZXJ9IFttYXhSZXNvbHV0aW9uXSBUaGUgbWF4aW11bSByZXNvbHV0aW9uIChleGNsdXNpdmUpIGJlbG93IHdoaWNoIHRoaXMgbGF5ZXIgd2lsbFxuICogYmUgdmlzaWJsZS5cbiAqIEBwcm9wZXJ0eSB7bnVtYmVyfSBbbWluWm9vbV0gVGhlIG1pbmltdW0gdmlldyB6b29tIGxldmVsIChleGNsdXNpdmUpIGFib3ZlIHdoaWNoIHRoaXMgbGF5ZXIgd2lsbCBiZVxuICogdmlzaWJsZS5cbiAqIEBwcm9wZXJ0eSB7bnVtYmVyfSBbbWF4Wm9vbV0gVGhlIG1heGltdW0gdmlldyB6b29tIGxldmVsIChpbmNsdXNpdmUpIGF0IHdoaWNoIHRoaXMgbGF5ZXIgd2lsbFxuICogYmUgdmlzaWJsZS5cbiAqIEBwcm9wZXJ0eSB7aW1wb3J0KFwiLi4vc291cmNlL1NvdXJjZS5qc1wiKS5kZWZhdWx0fSBbc291cmNlXSBTb3VyY2UgZm9yIHRoaXMgbGF5ZXIuICBJZiBub3QgcHJvdmlkZWQgdG8gdGhlIGNvbnN0cnVjdG9yLFxuICogdGhlIHNvdXJjZSBjYW4gYmUgc2V0IGJ5IGNhbGxpbmcge0BsaW5rIG1vZHVsZTpvbC9sYXllci9MYXllciNzZXRTb3VyY2UgbGF5ZXIuc2V0U291cmNlKHNvdXJjZSl9IGFmdGVyXG4gKiBjb25zdHJ1Y3Rpb24uXG4gKiBAcHJvcGVydHkge2ltcG9ydChcIi4uL1BsdWdnYWJsZU1hcC5qc1wiKS5kZWZhdWx0fSBbbWFwXSBNYXAuXG4gKiBAcHJvcGVydHkge1JlbmRlckZ1bmN0aW9ufSBbcmVuZGVyXSBSZW5kZXIgZnVuY3Rpb24uIFRha2VzIHRoZSBmcmFtZSBzdGF0ZSBhcyBpbnB1dCBhbmQgaXMgZXhwZWN0ZWQgdG8gcmV0dXJuIGFuXG4gKiBIVE1MIGVsZW1lbnQuIFdpbGwgb3ZlcndyaXRlIHRoZSBkZWZhdWx0IHJlbmRlcmluZyBmb3IgdGhlIGxheWVyLlxuICovXG5cbi8qKlxuICogQHR5cGVkZWYge09iamVjdH0gU3RhdGVcbiAqIEBwcm9wZXJ0eSB7aW1wb3J0KFwiLi9MYXllci5qc1wiKS5kZWZhdWx0fSBsYXllclxuICogQHByb3BlcnR5IHtudW1iZXJ9IG9wYWNpdHkgT3BhY2l0eSwgdGhlIHZhbHVlIGlzIHJvdW5kZWQgdG8gdHdvIGRpZ2l0cyB0byBhcHBlYXIgYWZ0ZXIgdGhlIGRlY2ltYWwgcG9pbnQuXG4gKiBAcHJvcGVydHkge2ltcG9ydChcIi4uL3NvdXJjZS9TdGF0ZS5qc1wiKS5kZWZhdWx0fSBzb3VyY2VTdGF0ZVxuICogQHByb3BlcnR5IHtib29sZWFufSB2aXNpYmxlXG4gKiBAcHJvcGVydHkge2Jvb2xlYW59IG1hbmFnZWRcbiAqIEBwcm9wZXJ0eSB7aW1wb3J0KFwiLi4vZXh0ZW50LmpzXCIpLkV4dGVudH0gW2V4dGVudF1cbiAqIEBwcm9wZXJ0eSB7bnVtYmVyfSB6SW5kZXhcbiAqIEBwcm9wZXJ0eSB7bnVtYmVyfSBtYXhSZXNvbHV0aW9uXG4gKiBAcHJvcGVydHkge251bWJlcn0gbWluUmVzb2x1dGlvblxuICogQHByb3BlcnR5IHtudW1iZXJ9IG1pblpvb21cbiAqIEBwcm9wZXJ0eSB7bnVtYmVyfSBtYXhab29tXG4gKi9cblxuLyoqXG4gKiBAY2xhc3NkZXNjXG4gKiBCYXNlIGNsYXNzIGZyb20gd2hpY2ggYWxsIGxheWVyIHR5cGVzIGFyZSBkZXJpdmVkLiBUaGlzIHNob3VsZCBvbmx5IGJlIGluc3RhbnRpYXRlZFxuICogaW4gdGhlIGNhc2Ugd2hlcmUgYSBjdXN0b20gbGF5ZXIgaXMgYmUgYWRkZWQgdG8gdGhlIG1hcCB3aXRoIGEgY3VzdG9tIGByZW5kZXJgIGZ1bmN0aW9uLlxuICogU3VjaCBhIGZ1bmN0aW9uIGNhbiBiZSBzcGVjaWZpZWQgaW4gdGhlIGBvcHRpb25zYCBvYmplY3QsIGFuZCBpcyBleHBlY3RlZCB0byByZXR1cm4gYW4gSFRNTCBlbGVtZW50LlxuICpcbiAqIEEgdmlzdWFsIHJlcHJlc2VudGF0aW9uIG9mIHJhc3RlciBvciB2ZWN0b3IgbWFwIGRhdGEuXG4gKiBMYXllcnMgZ3JvdXAgdG9nZXRoZXIgdGhvc2UgcHJvcGVydGllcyB0aGF0IHBlcnRhaW4gdG8gaG93IHRoZSBkYXRhIGlzIHRvIGJlXG4gKiBkaXNwbGF5ZWQsIGlycmVzcGVjdGl2ZSBvZiB0aGUgc291cmNlIG9mIHRoYXQgZGF0YS5cbiAqXG4gKiBMYXllcnMgYXJlIHVzdWFsbHkgYWRkZWQgdG8gYSBtYXAgd2l0aCB7QGxpbmsgbW9kdWxlOm9sL01hcCNhZGRMYXllcn0uIENvbXBvbmVudHNcbiAqIGxpa2Uge0BsaW5rIG1vZHVsZTpvbC9pbnRlcmFjdGlvbi9TZWxlY3R+U2VsZWN0fSB1c2UgdW5tYW5hZ2VkIGxheWVyc1xuICogaW50ZXJuYWxseS4gVGhlc2UgdW5tYW5hZ2VkIGxheWVycyBhcmUgYXNzb2NpYXRlZCB3aXRoIHRoZSBtYXAgdXNpbmdcbiAqIHtAbGluayBtb2R1bGU6b2wvbGF5ZXIvTGF5ZXJ+TGF5ZXIjc2V0TWFwfSBpbnN0ZWFkLlxuICpcbiAqIEEgZ2VuZXJpYyBgY2hhbmdlYCBldmVudCBpcyBmaXJlZCB3aGVuIHRoZSBzdGF0ZSBvZiB0aGUgc291cmNlIGNoYW5nZXMuXG4gKlxuICogUGxlYXNlIG5vdGUgdGhhdCBmb3IgcGVyZm9ybWFuY2UgcmVhc29ucyBzZXZlcmFsIGxheWVycyBtaWdodCBnZXQgcmVuZGVyZWQgdG9cbiAqIHRoZSBzYW1lIEhUTUwgZWxlbWVudCwgd2hpY2ggd2lsbCBjYXVzZSB7QGxpbmsgbW9kdWxlOm9sL01hcH5NYXAjZm9yRWFjaExheWVyQXRQaXhlbH0gdG9cbiAqIGdpdmUgZmFsc2UgcG9zaXRpdmVzLiBUbyBhdm9pZCB0aGlzLCBhcHBseSBkaWZmZXJlbnQgYGNsYXNzTmFtZWAgcHJvcGVydGllcyB0byB0aGVcbiAqIGxheWVycyBhdCBjcmVhdGlvbiB0aW1lLlxuICpcbiAqIEBmaXJlcyBpbXBvcnQoXCIuLi9yZW5kZXIvRXZlbnQuanNcIikuUmVuZGVyRXZlbnQjcHJlcmVuZGVyXG4gKiBAZmlyZXMgaW1wb3J0KFwiLi4vcmVuZGVyL0V2ZW50LmpzXCIpLlJlbmRlckV2ZW50I3Bvc3RyZW5kZXJcbiAqXG4gKiBAdGVtcGxhdGUge2ltcG9ydChcIi4uL3NvdXJjZS9Tb3VyY2UuanNcIikuZGVmYXVsdH0gU291cmNlVHlwZVxuICogQGFwaVxuICovXG5cbnZhciBMYXllciA9XG4vKiogQGNsYXNzICovXG5mdW5jdGlvbiAoX3N1cGVyKSB7XG4gIF9fZXh0ZW5kcyhMYXllciwgX3N1cGVyKTtcbiAgLyoqXG4gICAqIEBwYXJhbSB7T3B0aW9uc30gb3B0aW9ucyBMYXllciBvcHRpb25zLlxuICAgKi9cblxuXG4gIGZ1bmN0aW9uIExheWVyKG9wdGlvbnMpIHtcbiAgICB2YXIgX3RoaXMgPSB0aGlzO1xuXG4gICAgdmFyIGJhc2VPcHRpb25zID0gYXNzaWduKHt9LCBvcHRpb25zKTtcbiAgICBkZWxldGUgYmFzZU9wdGlvbnMuc291cmNlO1xuICAgIF90aGlzID0gX3N1cGVyLmNhbGwodGhpcywgYmFzZU9wdGlvbnMpIHx8IHRoaXM7XG4gICAgLyoqXG4gICAgICogQHByaXZhdGVcbiAgICAgKiBAdHlwZSB7P2ltcG9ydChcIi4uL2V2ZW50cy5qc1wiKS5FdmVudHNLZXl9XG4gICAgICovXG5cbiAgICBfdGhpcy5tYXBQcmVjb21wb3NlS2V5XyA9IG51bGw7XG4gICAgLyoqXG4gICAgICogQHByaXZhdGVcbiAgICAgKiBAdHlwZSB7P2ltcG9ydChcIi4uL2V2ZW50cy5qc1wiKS5FdmVudHNLZXl9XG4gICAgICovXG5cbiAgICBfdGhpcy5tYXBSZW5kZXJLZXlfID0gbnVsbDtcbiAgICAvKipcbiAgICAgKiBAcHJpdmF0ZVxuICAgICAqIEB0eXBlIHs/aW1wb3J0KFwiLi4vZXZlbnRzLmpzXCIpLkV2ZW50c0tleX1cbiAgICAgKi9cblxuICAgIF90aGlzLnNvdXJjZUNoYW5nZUtleV8gPSBudWxsO1xuICAgIC8qKlxuICAgICAqIEBwcml2YXRlXG4gICAgICogQHR5cGUge2ltcG9ydChcIi4uL3JlbmRlcmVyL0xheWVyLmpzXCIpLmRlZmF1bHR9XG4gICAgICovXG5cbiAgICBfdGhpcy5yZW5kZXJlcl8gPSBudWxsOyAvLyBPdmVyd3JpdGUgZGVmYXVsdCByZW5kZXIgbWV0aG9kIHdpdGggYSBjdXN0b20gb25lXG5cbiAgICBpZiAob3B0aW9ucy5yZW5kZXIpIHtcbiAgICAgIF90aGlzLnJlbmRlciA9IG9wdGlvbnMucmVuZGVyO1xuICAgIH1cblxuICAgIGlmIChvcHRpb25zLm1hcCkge1xuICAgICAgX3RoaXMuc2V0TWFwKG9wdGlvbnMubWFwKTtcbiAgICB9XG5cbiAgICBfdGhpcy5hZGRFdmVudExpc3RlbmVyKGdldENoYW5nZUV2ZW50VHlwZShMYXllclByb3BlcnR5LlNPVVJDRSksIF90aGlzLmhhbmRsZVNvdXJjZVByb3BlcnR5Q2hhbmdlXyk7XG5cbiAgICB2YXIgc291cmNlID0gb3B0aW9ucy5zb3VyY2UgP1xuICAgIC8qKiBAdHlwZSB7U291cmNlVHlwZX0gKi9cbiAgICBvcHRpb25zLnNvdXJjZSA6IG51bGw7XG5cbiAgICBfdGhpcy5zZXRTb3VyY2Uoc291cmNlKTtcblxuICAgIHJldHVybiBfdGhpcztcbiAgfVxuICAvKipcbiAgICogQHBhcmFtIHtBcnJheTxpbXBvcnQoXCIuL0xheWVyLmpzXCIpLmRlZmF1bHQ+PX0gb3B0X2FycmF5IEFycmF5IG9mIGxheWVycyAodG8gYmUgbW9kaWZpZWQgaW4gcGxhY2UpLlxuICAgKiBAcmV0dXJuIHtBcnJheTxpbXBvcnQoXCIuL0xheWVyLmpzXCIpLmRlZmF1bHQ+fSBBcnJheSBvZiBsYXllcnMuXG4gICAqL1xuXG5cbiAgTGF5ZXIucHJvdG90eXBlLmdldExheWVyc0FycmF5ID0gZnVuY3Rpb24gKG9wdF9hcnJheSkge1xuICAgIHZhciBhcnJheSA9IG9wdF9hcnJheSA/IG9wdF9hcnJheSA6IFtdO1xuICAgIGFycmF5LnB1c2godGhpcyk7XG4gICAgcmV0dXJuIGFycmF5O1xuICB9O1xuICAvKipcbiAgICogQHBhcmFtIHtBcnJheTxpbXBvcnQoXCIuL0xheWVyLmpzXCIpLlN0YXRlPj19IG9wdF9zdGF0ZXMgT3B0aW9uYWwgbGlzdCBvZiBsYXllciBzdGF0ZXMgKHRvIGJlIG1vZGlmaWVkIGluIHBsYWNlKS5cbiAgICogQHJldHVybiB7QXJyYXk8aW1wb3J0KFwiLi9MYXllci5qc1wiKS5TdGF0ZT59IExpc3Qgb2YgbGF5ZXIgc3RhdGVzLlxuICAgKi9cblxuXG4gIExheWVyLnByb3RvdHlwZS5nZXRMYXllclN0YXRlc0FycmF5ID0gZnVuY3Rpb24gKG9wdF9zdGF0ZXMpIHtcbiAgICB2YXIgc3RhdGVzID0gb3B0X3N0YXRlcyA/IG9wdF9zdGF0ZXMgOiBbXTtcbiAgICBzdGF0ZXMucHVzaCh0aGlzLmdldExheWVyU3RhdGUoKSk7XG4gICAgcmV0dXJuIHN0YXRlcztcbiAgfTtcbiAgLyoqXG4gICAqIEdldCB0aGUgbGF5ZXIgc291cmNlLlxuICAgKiBAcmV0dXJuIHtTb3VyY2VUeXBlfSBUaGUgbGF5ZXIgc291cmNlIChvciBgbnVsbGAgaWYgbm90IHlldCBzZXQpLlxuICAgKiBAb2JzZXJ2YWJsZVxuICAgKiBAYXBpXG4gICAqL1xuXG5cbiAgTGF5ZXIucHJvdG90eXBlLmdldFNvdXJjZSA9IGZ1bmN0aW9uICgpIHtcbiAgICByZXR1cm4gKFxuICAgICAgLyoqIEB0eXBlIHtTb3VyY2VUeXBlfSAqL1xuICAgICAgdGhpcy5nZXQoTGF5ZXJQcm9wZXJ0eS5TT1VSQ0UpIHx8IG51bGxcbiAgICApO1xuICB9O1xuICAvKipcbiAgICogQHJldHVybiB7aW1wb3J0KFwiLi4vc291cmNlL1N0YXRlLmpzXCIpLmRlZmF1bHR9IFNvdXJjZSBzdGF0ZS5cbiAgICovXG5cblxuICBMYXllci5wcm90b3R5cGUuZ2V0U291cmNlU3RhdGUgPSBmdW5jdGlvbiAoKSB7XG4gICAgdmFyIHNvdXJjZSA9IHRoaXMuZ2V0U291cmNlKCk7XG4gICAgcmV0dXJuICFzb3VyY2UgPyBTb3VyY2VTdGF0ZS5VTkRFRklORUQgOiBzb3VyY2UuZ2V0U3RhdGUoKTtcbiAgfTtcbiAgLyoqXG4gICAqIEBwcml2YXRlXG4gICAqL1xuXG5cbiAgTGF5ZXIucHJvdG90eXBlLmhhbmRsZVNvdXJjZUNoYW5nZV8gPSBmdW5jdGlvbiAoKSB7XG4gICAgdGhpcy5jaGFuZ2VkKCk7XG4gIH07XG4gIC8qKlxuICAgKiBAcHJpdmF0ZVxuICAgKi9cblxuXG4gIExheWVyLnByb3RvdHlwZS5oYW5kbGVTb3VyY2VQcm9wZXJ0eUNoYW5nZV8gPSBmdW5jdGlvbiAoKSB7XG4gICAgaWYgKHRoaXMuc291cmNlQ2hhbmdlS2V5Xykge1xuICAgICAgdW5saXN0ZW5CeUtleSh0aGlzLnNvdXJjZUNoYW5nZUtleV8pO1xuICAgICAgdGhpcy5zb3VyY2VDaGFuZ2VLZXlfID0gbnVsbDtcbiAgICB9XG5cbiAgICB2YXIgc291cmNlID0gdGhpcy5nZXRTb3VyY2UoKTtcblxuICAgIGlmIChzb3VyY2UpIHtcbiAgICAgIHRoaXMuc291cmNlQ2hhbmdlS2V5XyA9IGxpc3Rlbihzb3VyY2UsIEV2ZW50VHlwZS5DSEFOR0UsIHRoaXMuaGFuZGxlU291cmNlQ2hhbmdlXywgdGhpcyk7XG4gICAgfVxuXG4gICAgdGhpcy5jaGFuZ2VkKCk7XG4gIH07XG4gIC8qKlxuICAgKiBAcGFyYW0ge2ltcG9ydChcIi4uL3BpeGVsXCIpLlBpeGVsfSBwaXhlbCBQaXhlbC5cbiAgICogQHJldHVybiB7UHJvbWlzZTxBcnJheTxpbXBvcnQoXCIuLi9GZWF0dXJlXCIpLmRlZmF1bHQ+Pn0gUHJvbWlzZSB0aGF0IHJlc29sdmVzIHdpdGhcbiAgICogYW4gYXJyYXkgb2YgZmVhdHVyZXMuXG4gICAqL1xuXG5cbiAgTGF5ZXIucHJvdG90eXBlLmdldEZlYXR1cmVzID0gZnVuY3Rpb24gKHBpeGVsKSB7XG4gICAgcmV0dXJuIHRoaXMucmVuZGVyZXJfLmdldEZlYXR1cmVzKHBpeGVsKTtcbiAgfTtcbiAgLyoqXG4gICAqIEluIGNoYXJnZSB0byBtYW5hZ2UgdGhlIHJlbmRlcmluZyBvZiB0aGUgbGF5ZXIuIE9uZSBsYXllciB0eXBlIGlzXG4gICAqIGJvdW5kZWQgd2l0aCBvbmUgbGF5ZXIgcmVuZGVyZXIuXG4gICAqIEBwYXJhbSB7P2ltcG9ydChcIi4uL1BsdWdnYWJsZU1hcC5qc1wiKS5GcmFtZVN0YXRlfSBmcmFtZVN0YXRlIEZyYW1lIHN0YXRlLlxuICAgKiBAcGFyYW0ge0hUTUxFbGVtZW50fSB0YXJnZXQgVGFyZ2V0IHdoaWNoIHRoZSByZW5kZXJlciBtYXkgKGJ1dCBuZWVkIG5vdCkgdXNlXG4gICAqIGZvciByZW5kZXJpbmcgaXRzIGNvbnRlbnQuXG4gICAqIEByZXR1cm4ge0hUTUxFbGVtZW50fSBUaGUgcmVuZGVyZWQgZWxlbWVudC5cbiAgICovXG5cblxuICBMYXllci5wcm90b3R5cGUucmVuZGVyID0gZnVuY3Rpb24gKGZyYW1lU3RhdGUsIHRhcmdldCkge1xuICAgIHZhciBsYXllclJlbmRlcmVyID0gdGhpcy5nZXRSZW5kZXJlcigpO1xuXG4gICAgaWYgKGxheWVyUmVuZGVyZXIucHJlcGFyZUZyYW1lKGZyYW1lU3RhdGUpKSB7XG4gICAgICByZXR1cm4gbGF5ZXJSZW5kZXJlci5yZW5kZXJGcmFtZShmcmFtZVN0YXRlLCB0YXJnZXQpO1xuICAgIH1cbiAgfTtcbiAgLyoqXG4gICAqIFNldHMgdGhlIGxheWVyIHRvIGJlIHJlbmRlcmVkIG9uIHRvcCBvZiBvdGhlciBsYXllcnMgb24gYSBtYXAuIFRoZSBtYXAgd2lsbFxuICAgKiBub3QgbWFuYWdlIHRoaXMgbGF5ZXIgaW4gaXRzIGxheWVycyBjb2xsZWN0aW9uLCBhbmQgdGhlIGNhbGxiYWNrIGluXG4gICAqIHtAbGluayBtb2R1bGU6b2wvTWFwI2ZvckVhY2hMYXllckF0UGl4ZWx9IHdpbGwgcmVjZWl2ZSBgbnVsbGAgYXMgbGF5ZXIuIFRoaXNcbiAgICogaXMgdXNlZnVsIGZvciB0ZW1wb3JhcnkgbGF5ZXJzLiBUbyByZW1vdmUgYW4gdW5tYW5hZ2VkIGxheWVyIGZyb20gdGhlIG1hcCxcbiAgICogdXNlIGAjc2V0TWFwKG51bGwpYC5cbiAgICpcbiAgICogVG8gYWRkIHRoZSBsYXllciB0byBhIG1hcCBhbmQgaGF2ZSBpdCBtYW5hZ2VkIGJ5IHRoZSBtYXAsIHVzZVxuICAgKiB7QGxpbmsgbW9kdWxlOm9sL01hcCNhZGRMYXllcn0gaW5zdGVhZC5cbiAgICogQHBhcmFtIHtpbXBvcnQoXCIuLi9QbHVnZ2FibGVNYXAuanNcIikuZGVmYXVsdH0gbWFwIE1hcC5cbiAgICogQGFwaVxuICAgKi9cblxuXG4gIExheWVyLnByb3RvdHlwZS5zZXRNYXAgPSBmdW5jdGlvbiAobWFwKSB7XG4gICAgaWYgKHRoaXMubWFwUHJlY29tcG9zZUtleV8pIHtcbiAgICAgIHVubGlzdGVuQnlLZXkodGhpcy5tYXBQcmVjb21wb3NlS2V5Xyk7XG4gICAgICB0aGlzLm1hcFByZWNvbXBvc2VLZXlfID0gbnVsbDtcbiAgICB9XG5cbiAgICBpZiAoIW1hcCkge1xuICAgICAgdGhpcy5jaGFuZ2VkKCk7XG4gICAgfVxuXG4gICAgaWYgKHRoaXMubWFwUmVuZGVyS2V5Xykge1xuICAgICAgdW5saXN0ZW5CeUtleSh0aGlzLm1hcFJlbmRlcktleV8pO1xuICAgICAgdGhpcy5tYXBSZW5kZXJLZXlfID0gbnVsbDtcbiAgICB9XG5cbiAgICBpZiAobWFwKSB7XG4gICAgICB0aGlzLm1hcFByZWNvbXBvc2VLZXlfID0gbGlzdGVuKG1hcCwgUmVuZGVyRXZlbnRUeXBlLlBSRUNPTVBPU0UsIGZ1bmN0aW9uIChldnQpIHtcbiAgICAgICAgdmFyIHJlbmRlckV2ZW50ID1cbiAgICAgICAgLyoqIEB0eXBlIHtpbXBvcnQoXCIuLi9yZW5kZXIvRXZlbnQuanNcIikuZGVmYXVsdH0gKi9cbiAgICAgICAgZXZ0O1xuICAgICAgICB2YXIgbGF5ZXJTdGF0ZXNBcnJheSA9IHJlbmRlckV2ZW50LmZyYW1lU3RhdGUubGF5ZXJTdGF0ZXNBcnJheTtcbiAgICAgICAgdmFyIGxheWVyU3RhdGUgPSB0aGlzLmdldExheWVyU3RhdGUoZmFsc2UpOyAvLyBBIGxheWVyIGNhbiBvbmx5IGJlIGFkZGVkIHRvIHRoZSBtYXAgb25jZS4gVXNlIGVpdGhlciBgbGF5ZXIuc2V0TWFwKClgIG9yIGBtYXAuYWRkTGF5ZXIoKWAsIG5vdCBib3RoLlxuXG4gICAgICAgIGFzc2VydCghbGF5ZXJTdGF0ZXNBcnJheS5zb21lKGZ1bmN0aW9uIChhcnJheUxheWVyU3RhdGUpIHtcbiAgICAgICAgICByZXR1cm4gYXJyYXlMYXllclN0YXRlLmxheWVyID09PSBsYXllclN0YXRlLmxheWVyO1xuICAgICAgICB9KSwgNjcpO1xuICAgICAgICBsYXllclN0YXRlc0FycmF5LnB1c2gobGF5ZXJTdGF0ZSk7XG4gICAgICB9LCB0aGlzKTtcbiAgICAgIHRoaXMubWFwUmVuZGVyS2V5XyA9IGxpc3Rlbih0aGlzLCBFdmVudFR5cGUuQ0hBTkdFLCBtYXAucmVuZGVyLCBtYXApO1xuICAgICAgdGhpcy5jaGFuZ2VkKCk7XG4gICAgfVxuICB9O1xuICAvKipcbiAgICogU2V0IHRoZSBsYXllciBzb3VyY2UuXG4gICAqIEBwYXJhbSB7U291cmNlVHlwZX0gc291cmNlIFRoZSBsYXllciBzb3VyY2UuXG4gICAqIEBvYnNlcnZhYmxlXG4gICAqIEBhcGlcbiAgICovXG5cblxuICBMYXllci5wcm90b3R5cGUuc2V0U291cmNlID0gZnVuY3Rpb24gKHNvdXJjZSkge1xuICAgIHRoaXMuc2V0KExheWVyUHJvcGVydHkuU09VUkNFLCBzb3VyY2UpO1xuICB9O1xuICAvKipcbiAgICogR2V0IHRoZSByZW5kZXJlciBmb3IgdGhpcyBsYXllci5cbiAgICogQHJldHVybiB7aW1wb3J0KFwiLi4vcmVuZGVyZXIvTGF5ZXIuanNcIikuZGVmYXVsdH0gVGhlIGxheWVyIHJlbmRlcmVyLlxuICAgKi9cblxuXG4gIExheWVyLnByb3RvdHlwZS5nZXRSZW5kZXJlciA9IGZ1bmN0aW9uICgpIHtcbiAgICBpZiAoIXRoaXMucmVuZGVyZXJfKSB7XG4gICAgICB0aGlzLnJlbmRlcmVyXyA9IHRoaXMuY3JlYXRlUmVuZGVyZXIoKTtcbiAgICB9XG5cbiAgICByZXR1cm4gdGhpcy5yZW5kZXJlcl87XG4gIH07XG4gIC8qKlxuICAgKiBAcmV0dXJuIHtib29sZWFufSBUaGUgbGF5ZXIgaGFzIGEgcmVuZGVyZXIuXG4gICAqL1xuXG5cbiAgTGF5ZXIucHJvdG90eXBlLmhhc1JlbmRlcmVyID0gZnVuY3Rpb24gKCkge1xuICAgIHJldHVybiAhIXRoaXMucmVuZGVyZXJfO1xuICB9O1xuICAvKipcbiAgICogQ3JlYXRlIGEgcmVuZGVyZXIgZm9yIHRoaXMgbGF5ZXIuXG4gICAqIEByZXR1cm4ge2ltcG9ydChcIi4uL3JlbmRlcmVyL0xheWVyLmpzXCIpLmRlZmF1bHR9IEEgbGF5ZXIgcmVuZGVyZXIuXG4gICAqIEBwcm90ZWN0ZWRcbiAgICovXG5cblxuICBMYXllci5wcm90b3R5cGUuY3JlYXRlUmVuZGVyZXIgPSBmdW5jdGlvbiAoKSB7XG4gICAgcmV0dXJuIG51bGw7XG4gIH07XG4gIC8qKlxuICAgKiBDbGVhbiB1cC5cbiAgICovXG5cblxuICBMYXllci5wcm90b3R5cGUuZGlzcG9zZUludGVybmFsID0gZnVuY3Rpb24gKCkge1xuICAgIHRoaXMuc2V0U291cmNlKG51bGwpO1xuXG4gICAgX3N1cGVyLnByb3RvdHlwZS5kaXNwb3NlSW50ZXJuYWwuY2FsbCh0aGlzKTtcbiAgfTtcblxuICByZXR1cm4gTGF5ZXI7XG59KEJhc2VMYXllcik7XG4vKipcbiAqIFJldHVybiBgdHJ1ZWAgaWYgdGhlIGxheWVyIGlzIHZpc2libGUgYW5kIGlmIHRoZSBwcm92aWRlZCB2aWV3IHN0YXRlXG4gKiBoYXMgcmVzb2x1dGlvbiBhbmQgem9vbSBsZXZlbHMgdGhhdCBhcmUgaW4gcmFuZ2Ugb2YgdGhlIGxheWVyJ3MgbWluL21heC5cbiAqIEBwYXJhbSB7U3RhdGV9IGxheWVyU3RhdGUgTGF5ZXIgc3RhdGUuXG4gKiBAcGFyYW0ge2ltcG9ydChcIi4uL1ZpZXcuanNcIikuU3RhdGV9IHZpZXdTdGF0ZSBWaWV3IHN0YXRlLlxuICogQHJldHVybiB7Ym9vbGVhbn0gVGhlIGxheWVyIGlzIHZpc2libGUgYXQgdGhlIGdpdmVuIHZpZXcgc3RhdGUuXG4gKi9cblxuXG5leHBvcnQgZnVuY3Rpb24gaW5WaWV3KGxheWVyU3RhdGUsIHZpZXdTdGF0ZSkge1xuICBpZiAoIWxheWVyU3RhdGUudmlzaWJsZSkge1xuICAgIHJldHVybiBmYWxzZTtcbiAgfVxuXG4gIHZhciByZXNvbHV0aW9uID0gdmlld1N0YXRlLnJlc29sdXRpb247XG5cbiAgaWYgKHJlc29sdXRpb24gPCBsYXllclN0YXRlLm1pblJlc29sdXRpb24gfHwgcmVzb2x1dGlvbiA+PSBsYXllclN0YXRlLm1heFJlc29sdXRpb24pIHtcbiAgICByZXR1cm4gZmFsc2U7XG4gIH1cblxuICB2YXIgem9vbSA9IHZpZXdTdGF0ZS56b29tO1xuICByZXR1cm4gem9vbSA+IGxheWVyU3RhdGUubWluWm9vbSAmJiB6b29tIDw9IGxheWVyU3RhdGUubWF4Wm9vbTtcbn1cbmV4cG9ydCBkZWZhdWx0IExheWVyOyIsIi8qKlxuICogQG1vZHVsZSBvbC9jb29yZGluYXRlXG4gKi9cbmltcG9ydCB7IGdldFdpZHRoIH0gZnJvbSAnLi9leHRlbnQuanMnO1xuaW1wb3J0IHsgbW9kdWxvIH0gZnJvbSAnLi9tYXRoLmpzJztcbmltcG9ydCB7IHBhZE51bWJlciB9IGZyb20gJy4vc3RyaW5nLmpzJztcbi8qKlxuICogQW4gYXJyYXkgb2YgbnVtYmVycyByZXByZXNlbnRpbmcgYW4geHkgY29vcmRpbmF0ZS4gRXhhbXBsZTogYFsxNiwgNDhdYC5cbiAqIEB0eXBlZGVmIHtBcnJheTxudW1iZXI+fSBDb29yZGluYXRlXG4gKiBAYXBpXG4gKi9cblxuLyoqXG4gKiBBIGZ1bmN0aW9uIHRoYXQgdGFrZXMgYSB7QGxpbmsgbW9kdWxlOm9sL2Nvb3JkaW5hdGV+Q29vcmRpbmF0ZX0gYW5kXG4gKiB0cmFuc2Zvcm1zIGl0IGludG8gYSBge3N0cmluZ31gLlxuICpcbiAqIEB0eXBlZGVmIHtmdW5jdGlvbigoQ29vcmRpbmF0ZXx1bmRlZmluZWQpKTogc3RyaW5nfSBDb29yZGluYXRlRm9ybWF0XG4gKiBAYXBpXG4gKi9cblxuLyoqXG4gKiBBZGQgYGRlbHRhYCB0byBgY29vcmRpbmF0ZWAuIGBjb29yZGluYXRlYCBpcyBtb2RpZmllZCBpbiBwbGFjZSBhbmQgcmV0dXJuZWRcbiAqIGJ5IHRoZSBmdW5jdGlvbi5cbiAqXG4gKiBFeGFtcGxlOlxuICpcbiAqICAgICBpbXBvcnQge2FkZH0gZnJvbSAnb2wvY29vcmRpbmF0ZSc7XG4gKlxuICogICAgIHZhciBjb29yZCA9IFs3Ljg1LCA0Ny45ODMzMzNdO1xuICogICAgIGFkZChjb29yZCwgWy0yLCA0XSk7XG4gKiAgICAgLy8gY29vcmQgaXMgbm93IFs1Ljg1LCA1MS45ODMzMzNdXG4gKlxuICogQHBhcmFtIHtDb29yZGluYXRlfSBjb29yZGluYXRlIENvb3JkaW5hdGUuXG4gKiBAcGFyYW0ge0Nvb3JkaW5hdGV9IGRlbHRhIERlbHRhLlxuICogQHJldHVybiB7Q29vcmRpbmF0ZX0gVGhlIGlucHV0IGNvb3JkaW5hdGUgYWRqdXN0ZWQgYnlcbiAqIHRoZSBnaXZlbiBkZWx0YS5cbiAqIEBhcGlcbiAqL1xuXG5leHBvcnQgZnVuY3Rpb24gYWRkKGNvb3JkaW5hdGUsIGRlbHRhKSB7XG4gIGNvb3JkaW5hdGVbMF0gKz0gK2RlbHRhWzBdO1xuICBjb29yZGluYXRlWzFdICs9ICtkZWx0YVsxXTtcbiAgcmV0dXJuIGNvb3JkaW5hdGU7XG59XG4vKipcbiAqIENhbGN1bGF0ZXMgdGhlIHBvaW50IGNsb3Nlc3QgdG8gdGhlIHBhc3NlZCBjb29yZGluYXRlIG9uIHRoZSBwYXNzZWQgY2lyY2xlLlxuICpcbiAqIEBwYXJhbSB7Q29vcmRpbmF0ZX0gY29vcmRpbmF0ZSBUaGUgY29vcmRpbmF0ZS5cbiAqIEBwYXJhbSB7aW1wb3J0KFwiLi9nZW9tL0NpcmNsZS5qc1wiKS5kZWZhdWx0fSBjaXJjbGUgVGhlIGNpcmNsZS5cbiAqIEByZXR1cm4ge0Nvb3JkaW5hdGV9IENsb3Nlc3QgcG9pbnQgb24gdGhlIGNpcmN1bWZlcmVuY2UuXG4gKi9cblxuZXhwb3J0IGZ1bmN0aW9uIGNsb3Nlc3RPbkNpcmNsZShjb29yZGluYXRlLCBjaXJjbGUpIHtcbiAgdmFyIHIgPSBjaXJjbGUuZ2V0UmFkaXVzKCk7XG4gIHZhciBjZW50ZXIgPSBjaXJjbGUuZ2V0Q2VudGVyKCk7XG4gIHZhciB4MCA9IGNlbnRlclswXTtcbiAgdmFyIHkwID0gY2VudGVyWzFdO1xuICB2YXIgeDEgPSBjb29yZGluYXRlWzBdO1xuICB2YXIgeTEgPSBjb29yZGluYXRlWzFdO1xuICB2YXIgZHggPSB4MSAtIHgwO1xuICB2YXIgZHkgPSB5MSAtIHkwO1xuXG4gIGlmIChkeCA9PT0gMCAmJiBkeSA9PT0gMCkge1xuICAgIGR4ID0gMTtcbiAgfVxuXG4gIHZhciBkID0gTWF0aC5zcXJ0KGR4ICogZHggKyBkeSAqIGR5KTtcbiAgdmFyIHggPSB4MCArIHIgKiBkeCAvIGQ7XG4gIHZhciB5ID0geTAgKyByICogZHkgLyBkO1xuICByZXR1cm4gW3gsIHldO1xufVxuLyoqXG4gKiBDYWxjdWxhdGVzIHRoZSBwb2ludCBjbG9zZXN0IHRvIHRoZSBwYXNzZWQgY29vcmRpbmF0ZSBvbiB0aGUgcGFzc2VkIHNlZ21lbnQuXG4gKiBUaGlzIGlzIHRoZSBmb290IG9mIHRoZSBwZXJwZW5kaWN1bGFyIG9mIHRoZSBjb29yZGluYXRlIHRvIHRoZSBzZWdtZW50IHdoZW5cbiAqIHRoZSBmb290IGlzIG9uIHRoZSBzZWdtZW50LCBvciB0aGUgY2xvc2VzdCBzZWdtZW50IGNvb3JkaW5hdGUgd2hlbiB0aGUgZm9vdFxuICogaXMgb3V0c2lkZSB0aGUgc2VnbWVudC5cbiAqXG4gKiBAcGFyYW0ge0Nvb3JkaW5hdGV9IGNvb3JkaW5hdGUgVGhlIGNvb3JkaW5hdGUuXG4gKiBAcGFyYW0ge0FycmF5PENvb3JkaW5hdGU+fSBzZWdtZW50IFRoZSB0d28gY29vcmRpbmF0ZXNcbiAqIG9mIHRoZSBzZWdtZW50LlxuICogQHJldHVybiB7Q29vcmRpbmF0ZX0gVGhlIGZvb3Qgb2YgdGhlIHBlcnBlbmRpY3VsYXIgb2ZcbiAqIHRoZSBjb29yZGluYXRlIHRvIHRoZSBzZWdtZW50LlxuICovXG5cbmV4cG9ydCBmdW5jdGlvbiBjbG9zZXN0T25TZWdtZW50KGNvb3JkaW5hdGUsIHNlZ21lbnQpIHtcbiAgdmFyIHgwID0gY29vcmRpbmF0ZVswXTtcbiAgdmFyIHkwID0gY29vcmRpbmF0ZVsxXTtcbiAgdmFyIHN0YXJ0ID0gc2VnbWVudFswXTtcbiAgdmFyIGVuZCA9IHNlZ21lbnRbMV07XG4gIHZhciB4MSA9IHN0YXJ0WzBdO1xuICB2YXIgeTEgPSBzdGFydFsxXTtcbiAgdmFyIHgyID0gZW5kWzBdO1xuICB2YXIgeTIgPSBlbmRbMV07XG4gIHZhciBkeCA9IHgyIC0geDE7XG4gIHZhciBkeSA9IHkyIC0geTE7XG4gIHZhciBhbG9uZyA9IGR4ID09PSAwICYmIGR5ID09PSAwID8gMCA6IChkeCAqICh4MCAtIHgxKSArIGR5ICogKHkwIC0geTEpKSAvIChkeCAqIGR4ICsgZHkgKiBkeSB8fCAwKTtcbiAgdmFyIHgsIHk7XG5cbiAgaWYgKGFsb25nIDw9IDApIHtcbiAgICB4ID0geDE7XG4gICAgeSA9IHkxO1xuICB9IGVsc2UgaWYgKGFsb25nID49IDEpIHtcbiAgICB4ID0geDI7XG4gICAgeSA9IHkyO1xuICB9IGVsc2Uge1xuICAgIHggPSB4MSArIGFsb25nICogZHg7XG4gICAgeSA9IHkxICsgYWxvbmcgKiBkeTtcbiAgfVxuXG4gIHJldHVybiBbeCwgeV07XG59XG4vKipcbiAqIFJldHVybnMgYSB7QGxpbmsgbW9kdWxlOm9sL2Nvb3JkaW5hdGV+Q29vcmRpbmF0ZUZvcm1hdH0gZnVuY3Rpb24gdGhhdCBjYW4gYmVcbiAqIHVzZWQgdG8gZm9ybWF0XG4gKiBhIHtDb29yZGluYXRlfSB0byBhIHN0cmluZy5cbiAqXG4gKiBFeGFtcGxlIHdpdGhvdXQgc3BlY2lmeWluZyB0aGUgZnJhY3Rpb25hbCBkaWdpdHM6XG4gKlxuICogICAgIGltcG9ydCB7Y3JlYXRlU3RyaW5nWFl9IGZyb20gJ29sL2Nvb3JkaW5hdGUnO1xuICpcbiAqICAgICB2YXIgY29vcmQgPSBbNy44NSwgNDcuOTgzMzMzXTtcbiAqICAgICB2YXIgc3RyaW5naWZ5RnVuYyA9IGNyZWF0ZVN0cmluZ1hZKCk7XG4gKiAgICAgdmFyIG91dCA9IHN0cmluZ2lmeUZ1bmMoY29vcmQpO1xuICogICAgIC8vIG91dCBpcyBub3cgJzgsIDQ4J1xuICpcbiAqIEV4YW1wbGUgd2l0aCBleHBsaWNpdGx5IHNwZWNpZnlpbmcgMiBmcmFjdGlvbmFsIGRpZ2l0czpcbiAqXG4gKiAgICAgaW1wb3J0IHtjcmVhdGVTdHJpbmdYWX0gZnJvbSAnb2wvY29vcmRpbmF0ZSc7XG4gKlxuICogICAgIHZhciBjb29yZCA9IFs3Ljg1LCA0Ny45ODMzMzNdO1xuICogICAgIHZhciBzdHJpbmdpZnlGdW5jID0gY3JlYXRlU3RyaW5nWFkoMik7XG4gKiAgICAgdmFyIG91dCA9IHN0cmluZ2lmeUZ1bmMoY29vcmQpO1xuICogICAgIC8vIG91dCBpcyBub3cgJzcuODUsIDQ3Ljk4J1xuICpcbiAqIEBwYXJhbSB7bnVtYmVyPX0gb3B0X2ZyYWN0aW9uRGlnaXRzIFRoZSBudW1iZXIgb2YgZGlnaXRzIHRvIGluY2x1ZGVcbiAqICAgIGFmdGVyIHRoZSBkZWNpbWFsIHBvaW50LiBEZWZhdWx0IGlzIGAwYC5cbiAqIEByZXR1cm4ge0Nvb3JkaW5hdGVGb3JtYXR9IENvb3JkaW5hdGUgZm9ybWF0LlxuICogQGFwaVxuICovXG5cbmV4cG9ydCBmdW5jdGlvbiBjcmVhdGVTdHJpbmdYWShvcHRfZnJhY3Rpb25EaWdpdHMpIHtcbiAgcmV0dXJuIChcbiAgICAvKipcbiAgICAgKiBAcGFyYW0ge0Nvb3JkaW5hdGV9IGNvb3JkaW5hdGUgQ29vcmRpbmF0ZS5cbiAgICAgKiBAcmV0dXJuIHtzdHJpbmd9IFN0cmluZyBYWS5cbiAgICAgKi9cbiAgICBmdW5jdGlvbiAoY29vcmRpbmF0ZSkge1xuICAgICAgcmV0dXJuIHRvU3RyaW5nWFkoY29vcmRpbmF0ZSwgb3B0X2ZyYWN0aW9uRGlnaXRzKTtcbiAgICB9XG4gICk7XG59XG4vKipcbiAqIEBwYXJhbSB7c3RyaW5nfSBoZW1pc3BoZXJlcyBIZW1pc3BoZXJlcy5cbiAqIEBwYXJhbSB7bnVtYmVyfSBkZWdyZWVzIERlZ3JlZXMuXG4gKiBAcGFyYW0ge251bWJlcj19IG9wdF9mcmFjdGlvbkRpZ2l0cyBUaGUgbnVtYmVyIG9mIGRpZ2l0cyB0byBpbmNsdWRlXG4gKiAgICBhZnRlciB0aGUgZGVjaW1hbCBwb2ludC4gRGVmYXVsdCBpcyBgMGAuXG4gKiBAcmV0dXJuIHtzdHJpbmd9IFN0cmluZy5cbiAqL1xuXG5leHBvcnQgZnVuY3Rpb24gZGVncmVlc1RvU3RyaW5nSERNUyhoZW1pc3BoZXJlcywgZGVncmVlcywgb3B0X2ZyYWN0aW9uRGlnaXRzKSB7XG4gIHZhciBub3JtYWxpemVkRGVncmVlcyA9IG1vZHVsbyhkZWdyZWVzICsgMTgwLCAzNjApIC0gMTgwO1xuICB2YXIgeCA9IE1hdGguYWJzKDM2MDAgKiBub3JtYWxpemVkRGVncmVlcyk7XG4gIHZhciBkZmxQcmVjaXNpb24gPSBvcHRfZnJhY3Rpb25EaWdpdHMgfHwgMDtcbiAgdmFyIHByZWNpc2lvbiA9IE1hdGgucG93KDEwLCBkZmxQcmVjaXNpb24pO1xuICB2YXIgZGVnID0gTWF0aC5mbG9vcih4IC8gMzYwMCk7XG4gIHZhciBtaW4gPSBNYXRoLmZsb29yKCh4IC0gZGVnICogMzYwMCkgLyA2MCk7XG4gIHZhciBzZWMgPSB4IC0gZGVnICogMzYwMCAtIG1pbiAqIDYwO1xuICBzZWMgPSBNYXRoLmNlaWwoc2VjICogcHJlY2lzaW9uKSAvIHByZWNpc2lvbjtcblxuICBpZiAoc2VjID49IDYwKSB7XG4gICAgc2VjID0gMDtcbiAgICBtaW4gKz0gMTtcbiAgfVxuXG4gIGlmIChtaW4gPj0gNjApIHtcbiAgICBtaW4gPSAwO1xuICAgIGRlZyArPSAxO1xuICB9XG5cbiAgcmV0dXJuIGRlZyArIFwiXFx4QjAgXCIgKyBwYWROdW1iZXIobWluLCAyKSArIFwiXFx1MjAzMiBcIiArIHBhZE51bWJlcihzZWMsIDIsIGRmbFByZWNpc2lvbikgKyBcIlxcdTIwMzNcIiArIChub3JtYWxpemVkRGVncmVlcyA9PSAwID8gJycgOiAnICcgKyBoZW1pc3BoZXJlcy5jaGFyQXQobm9ybWFsaXplZERlZ3JlZXMgPCAwID8gMSA6IDApKTtcbn1cbi8qKlxuICogVHJhbnNmb3JtcyB0aGUgZ2l2ZW4ge0BsaW5rIG1vZHVsZTpvbC9jb29yZGluYXRlfkNvb3JkaW5hdGV9IHRvIGEgc3RyaW5nXG4gKiB1c2luZyB0aGUgZ2l2ZW4gc3RyaW5nIHRlbXBsYXRlLiBUaGUgc3RyaW5ncyBge3h9YCBhbmQgYHt5fWAgaW4gdGhlIHRlbXBsYXRlXG4gKiB3aWxsIGJlIHJlcGxhY2VkIHdpdGggdGhlIGZpcnN0IGFuZCBzZWNvbmQgY29vcmRpbmF0ZSB2YWx1ZXMgcmVzcGVjdGl2ZWx5LlxuICpcbiAqIEV4YW1wbGUgd2l0aG91dCBzcGVjaWZ5aW5nIHRoZSBmcmFjdGlvbmFsIGRpZ2l0czpcbiAqXG4gKiAgICAgaW1wb3J0IHtmb3JtYXR9IGZyb20gJ29sL2Nvb3JkaW5hdGUnO1xuICpcbiAqICAgICB2YXIgY29vcmQgPSBbNy44NSwgNDcuOTgzMzMzXTtcbiAqICAgICB2YXIgdGVtcGxhdGUgPSAnQ29vcmRpbmF0ZSBpcyAoe3h9fHt5fSkuJztcbiAqICAgICB2YXIgb3V0ID0gZm9ybWF0KGNvb3JkLCB0ZW1wbGF0ZSk7XG4gKiAgICAgLy8gb3V0IGlzIG5vdyAnQ29vcmRpbmF0ZSBpcyAoOHw0OCkuJ1xuICpcbiAqIEV4YW1wbGUgZXhwbGljaXRseSBzcGVjaWZ5aW5nIHRoZSBmcmFjdGlvbmFsIGRpZ2l0czpcbiAqXG4gKiAgICAgaW1wb3J0IHtmb3JtYXR9IGZyb20gJ29sL2Nvb3JkaW5hdGUnO1xuICpcbiAqICAgICB2YXIgY29vcmQgPSBbNy44NSwgNDcuOTgzMzMzXTtcbiAqICAgICB2YXIgdGVtcGxhdGUgPSAnQ29vcmRpbmF0ZSBpcyAoe3h9fHt5fSkuJztcbiAqICAgICB2YXIgb3V0ID0gZm9ybWF0KGNvb3JkLCB0ZW1wbGF0ZSwgMik7XG4gKiAgICAgLy8gb3V0IGlzIG5vdyAnQ29vcmRpbmF0ZSBpcyAoNy44NXw0Ny45OCkuJ1xuICpcbiAqIEBwYXJhbSB7Q29vcmRpbmF0ZX0gY29vcmRpbmF0ZSBDb29yZGluYXRlLlxuICogQHBhcmFtIHtzdHJpbmd9IHRlbXBsYXRlIEEgdGVtcGxhdGUgc3RyaW5nIHdpdGggYHt4fWAgYW5kIGB7eX1gIHBsYWNlaG9sZGVyc1xuICogICAgIHRoYXQgd2lsbCBiZSByZXBsYWNlZCBieSBmaXJzdCBhbmQgc2Vjb25kIGNvb3JkaW5hdGUgdmFsdWVzLlxuICogQHBhcmFtIHtudW1iZXI9fSBvcHRfZnJhY3Rpb25EaWdpdHMgVGhlIG51bWJlciBvZiBkaWdpdHMgdG8gaW5jbHVkZVxuICogICAgYWZ0ZXIgdGhlIGRlY2ltYWwgcG9pbnQuIERlZmF1bHQgaXMgYDBgLlxuICogQHJldHVybiB7c3RyaW5nfSBGb3JtYXR0ZWQgY29vcmRpbmF0ZS5cbiAqIEBhcGlcbiAqL1xuXG5leHBvcnQgZnVuY3Rpb24gZm9ybWF0KGNvb3JkaW5hdGUsIHRlbXBsYXRlLCBvcHRfZnJhY3Rpb25EaWdpdHMpIHtcbiAgaWYgKGNvb3JkaW5hdGUpIHtcbiAgICByZXR1cm4gdGVtcGxhdGUucmVwbGFjZSgne3h9JywgY29vcmRpbmF0ZVswXS50b0ZpeGVkKG9wdF9mcmFjdGlvbkRpZ2l0cykpLnJlcGxhY2UoJ3t5fScsIGNvb3JkaW5hdGVbMV0udG9GaXhlZChvcHRfZnJhY3Rpb25EaWdpdHMpKTtcbiAgfSBlbHNlIHtcbiAgICByZXR1cm4gJyc7XG4gIH1cbn1cbi8qKlxuICogQHBhcmFtIHtDb29yZGluYXRlfSBjb29yZGluYXRlMSBGaXJzdCBjb29yZGluYXRlLlxuICogQHBhcmFtIHtDb29yZGluYXRlfSBjb29yZGluYXRlMiBTZWNvbmQgY29vcmRpbmF0ZS5cbiAqIEByZXR1cm4ge2Jvb2xlYW59IFRoZSB0d28gY29vcmRpbmF0ZXMgYXJlIGVxdWFsLlxuICovXG5cbmV4cG9ydCBmdW5jdGlvbiBlcXVhbHMoY29vcmRpbmF0ZTEsIGNvb3JkaW5hdGUyKSB7XG4gIHZhciBlcXVhbHMgPSB0cnVlO1xuXG4gIGZvciAodmFyIGkgPSBjb29yZGluYXRlMS5sZW5ndGggLSAxOyBpID49IDA7IC0taSkge1xuICAgIGlmIChjb29yZGluYXRlMVtpXSAhPSBjb29yZGluYXRlMltpXSkge1xuICAgICAgZXF1YWxzID0gZmFsc2U7XG4gICAgICBicmVhaztcbiAgICB9XG4gIH1cblxuICByZXR1cm4gZXF1YWxzO1xufVxuLyoqXG4gKiBSb3RhdGUgYGNvb3JkaW5hdGVgIGJ5IGBhbmdsZWAuIGBjb29yZGluYXRlYCBpcyBtb2RpZmllZCBpbiBwbGFjZSBhbmRcbiAqIHJldHVybmVkIGJ5IHRoZSBmdW5jdGlvbi5cbiAqXG4gKiBFeGFtcGxlOlxuICpcbiAqICAgICBpbXBvcnQge3JvdGF0ZX0gZnJvbSAnb2wvY29vcmRpbmF0ZSc7XG4gKlxuICogICAgIHZhciBjb29yZCA9IFs3Ljg1LCA0Ny45ODMzMzNdO1xuICogICAgIHZhciByb3RhdGVSYWRpYW5zID0gTWF0aC5QSSAvIDI7IC8vIDkwIGRlZ3JlZXNcbiAqICAgICByb3RhdGUoY29vcmQsIHJvdGF0ZVJhZGlhbnMpO1xuICogICAgIC8vIGNvb3JkIGlzIG5vdyBbLTQ3Ljk4MzMzMywgNy44NV1cbiAqXG4gKiBAcGFyYW0ge0Nvb3JkaW5hdGV9IGNvb3JkaW5hdGUgQ29vcmRpbmF0ZS5cbiAqIEBwYXJhbSB7bnVtYmVyfSBhbmdsZSBBbmdsZSBpbiByYWRpYW4uXG4gKiBAcmV0dXJuIHtDb29yZGluYXRlfSBDb29yZGluYXRlLlxuICogQGFwaVxuICovXG5cbmV4cG9ydCBmdW5jdGlvbiByb3RhdGUoY29vcmRpbmF0ZSwgYW5nbGUpIHtcbiAgdmFyIGNvc0FuZ2xlID0gTWF0aC5jb3MoYW5nbGUpO1xuICB2YXIgc2luQW5nbGUgPSBNYXRoLnNpbihhbmdsZSk7XG4gIHZhciB4ID0gY29vcmRpbmF0ZVswXSAqIGNvc0FuZ2xlIC0gY29vcmRpbmF0ZVsxXSAqIHNpbkFuZ2xlO1xuICB2YXIgeSA9IGNvb3JkaW5hdGVbMV0gKiBjb3NBbmdsZSArIGNvb3JkaW5hdGVbMF0gKiBzaW5BbmdsZTtcbiAgY29vcmRpbmF0ZVswXSA9IHg7XG4gIGNvb3JkaW5hdGVbMV0gPSB5O1xuICByZXR1cm4gY29vcmRpbmF0ZTtcbn1cbi8qKlxuICogU2NhbGUgYGNvb3JkaW5hdGVgIGJ5IGBzY2FsZWAuIGBjb29yZGluYXRlYCBpcyBtb2RpZmllZCBpbiBwbGFjZSBhbmQgcmV0dXJuZWRcbiAqIGJ5IHRoZSBmdW5jdGlvbi5cbiAqXG4gKiBFeGFtcGxlOlxuICpcbiAqICAgICBpbXBvcnQge3NjYWxlIGFzIHNjYWxlQ29vcmRpbmF0ZX0gZnJvbSAnb2wvY29vcmRpbmF0ZSc7XG4gKlxuICogICAgIHZhciBjb29yZCA9IFs3Ljg1LCA0Ny45ODMzMzNdO1xuICogICAgIHZhciBzY2FsZSA9IDEuMjtcbiAqICAgICBzY2FsZUNvb3JkaW5hdGUoY29vcmQsIHNjYWxlKTtcbiAqICAgICAvLyBjb29yZCBpcyBub3cgWzkuNDIsIDU3LjU3OTk5OTZdXG4gKlxuICogQHBhcmFtIHtDb29yZGluYXRlfSBjb29yZGluYXRlIENvb3JkaW5hdGUuXG4gKiBAcGFyYW0ge251bWJlcn0gc2NhbGUgU2NhbGUgZmFjdG9yLlxuICogQHJldHVybiB7Q29vcmRpbmF0ZX0gQ29vcmRpbmF0ZS5cbiAqL1xuXG5leHBvcnQgZnVuY3Rpb24gc2NhbGUoY29vcmRpbmF0ZSwgc2NhbGUpIHtcbiAgY29vcmRpbmF0ZVswXSAqPSBzY2FsZTtcbiAgY29vcmRpbmF0ZVsxXSAqPSBzY2FsZTtcbiAgcmV0dXJuIGNvb3JkaW5hdGU7XG59XG4vKipcbiAqIEBwYXJhbSB7Q29vcmRpbmF0ZX0gY29vcmQxIEZpcnN0IGNvb3JkaW5hdGUuXG4gKiBAcGFyYW0ge0Nvb3JkaW5hdGV9IGNvb3JkMiBTZWNvbmQgY29vcmRpbmF0ZS5cbiAqIEByZXR1cm4ge251bWJlcn0gU3F1YXJlZCBkaXN0YW5jZSBiZXR3ZWVuIGNvb3JkMSBhbmQgY29vcmQyLlxuICovXG5cbmV4cG9ydCBmdW5jdGlvbiBzcXVhcmVkRGlzdGFuY2UoY29vcmQxLCBjb29yZDIpIHtcbiAgdmFyIGR4ID0gY29vcmQxWzBdIC0gY29vcmQyWzBdO1xuICB2YXIgZHkgPSBjb29yZDFbMV0gLSBjb29yZDJbMV07XG4gIHJldHVybiBkeCAqIGR4ICsgZHkgKiBkeTtcbn1cbi8qKlxuICogQHBhcmFtIHtDb29yZGluYXRlfSBjb29yZDEgRmlyc3QgY29vcmRpbmF0ZS5cbiAqIEBwYXJhbSB7Q29vcmRpbmF0ZX0gY29vcmQyIFNlY29uZCBjb29yZGluYXRlLlxuICogQHJldHVybiB7bnVtYmVyfSBEaXN0YW5jZSBiZXR3ZWVuIGNvb3JkMSBhbmQgY29vcmQyLlxuICovXG5cbmV4cG9ydCBmdW5jdGlvbiBkaXN0YW5jZShjb29yZDEsIGNvb3JkMikge1xuICByZXR1cm4gTWF0aC5zcXJ0KHNxdWFyZWREaXN0YW5jZShjb29yZDEsIGNvb3JkMikpO1xufVxuLyoqXG4gKiBDYWxjdWxhdGUgdGhlIHNxdWFyZWQgZGlzdGFuY2UgZnJvbSBhIGNvb3JkaW5hdGUgdG8gYSBsaW5lIHNlZ21lbnQuXG4gKlxuICogQHBhcmFtIHtDb29yZGluYXRlfSBjb29yZGluYXRlIENvb3JkaW5hdGUgb2YgdGhlIHBvaW50LlxuICogQHBhcmFtIHtBcnJheTxDb29yZGluYXRlPn0gc2VnbWVudCBMaW5lIHNlZ21lbnQgKDJcbiAqIGNvb3JkaW5hdGVzKS5cbiAqIEByZXR1cm4ge251bWJlcn0gU3F1YXJlZCBkaXN0YW5jZSBmcm9tIHRoZSBwb2ludCB0byB0aGUgbGluZSBzZWdtZW50LlxuICovXG5cbmV4cG9ydCBmdW5jdGlvbiBzcXVhcmVkRGlzdGFuY2VUb1NlZ21lbnQoY29vcmRpbmF0ZSwgc2VnbWVudCkge1xuICByZXR1cm4gc3F1YXJlZERpc3RhbmNlKGNvb3JkaW5hdGUsIGNsb3Nlc3RPblNlZ21lbnQoY29vcmRpbmF0ZSwgc2VnbWVudCkpO1xufVxuLyoqXG4gKiBGb3JtYXQgYSBnZW9ncmFwaGljIGNvb3JkaW5hdGUgd2l0aCB0aGUgaGVtaXNwaGVyZSwgZGVncmVlcywgbWludXRlcywgYW5kXG4gKiBzZWNvbmRzLlxuICpcbiAqIEV4YW1wbGUgd2l0aG91dCBzcGVjaWZ5aW5nIGZyYWN0aW9uYWwgZGlnaXRzOlxuICpcbiAqICAgICBpbXBvcnQge3RvU3RyaW5nSERNU30gZnJvbSAnb2wvY29vcmRpbmF0ZSc7XG4gKlxuICogICAgIHZhciBjb29yZCA9IFs3Ljg1LCA0Ny45ODMzMzNdO1xuICogICAgIHZhciBvdXQgPSB0b1N0cmluZ0hETVMoY29vcmQpO1xuICogICAgIC8vIG91dCBpcyBub3cgJzQ3wrAgNTjigLIgNjDigLMgTiA3wrAgNTDigLIgNjDigLMgRSdcbiAqXG4gKiBFeGFtcGxlIGV4cGxpY2l0bHkgc3BlY2lmeWluZyAxIGZyYWN0aW9uYWwgZGlnaXQ6XG4gKlxuICogICAgIGltcG9ydCB7dG9TdHJpbmdIRE1TfSBmcm9tICdvbC9jb29yZGluYXRlJztcbiAqXG4gKiAgICAgdmFyIGNvb3JkID0gWzcuODUsIDQ3Ljk4MzMzM107XG4gKiAgICAgdmFyIG91dCA9IHRvU3RyaW5nSERNUyhjb29yZCwgMSk7XG4gKiAgICAgLy8gb3V0IGlzIG5vdyAnNDfCsCA1OOKAsiA2MC4w4oCzIE4gN8KwIDUw4oCyIDYwLjDigLMgRSdcbiAqXG4gKiBAcGFyYW0ge0Nvb3JkaW5hdGV9IGNvb3JkaW5hdGUgQ29vcmRpbmF0ZS5cbiAqIEBwYXJhbSB7bnVtYmVyPX0gb3B0X2ZyYWN0aW9uRGlnaXRzIFRoZSBudW1iZXIgb2YgZGlnaXRzIHRvIGluY2x1ZGVcbiAqICAgIGFmdGVyIHRoZSBkZWNpbWFsIHBvaW50LiBEZWZhdWx0IGlzIGAwYC5cbiAqIEByZXR1cm4ge3N0cmluZ30gSGVtaXNwaGVyZSwgZGVncmVlcywgbWludXRlcyBhbmQgc2Vjb25kcy5cbiAqIEBhcGlcbiAqL1xuXG5leHBvcnQgZnVuY3Rpb24gdG9TdHJpbmdIRE1TKGNvb3JkaW5hdGUsIG9wdF9mcmFjdGlvbkRpZ2l0cykge1xuICBpZiAoY29vcmRpbmF0ZSkge1xuICAgIHJldHVybiBkZWdyZWVzVG9TdHJpbmdIRE1TKCdOUycsIGNvb3JkaW5hdGVbMV0sIG9wdF9mcmFjdGlvbkRpZ2l0cykgKyAnICcgKyBkZWdyZWVzVG9TdHJpbmdIRE1TKCdFVycsIGNvb3JkaW5hdGVbMF0sIG9wdF9mcmFjdGlvbkRpZ2l0cyk7XG4gIH0gZWxzZSB7XG4gICAgcmV0dXJuICcnO1xuICB9XG59XG4vKipcbiAqIEZvcm1hdCBhIGNvb3JkaW5hdGUgYXMgYSBjb21tYSBkZWxpbWl0ZWQgc3RyaW5nLlxuICpcbiAqIEV4YW1wbGUgd2l0aG91dCBzcGVjaWZ5aW5nIGZyYWN0aW9uYWwgZGlnaXRzOlxuICpcbiAqICAgICBpbXBvcnQge3RvU3RyaW5nWFl9IGZyb20gJ29sL2Nvb3JkaW5hdGUnO1xuICpcbiAqICAgICB2YXIgY29vcmQgPSBbNy44NSwgNDcuOTgzMzMzXTtcbiAqICAgICB2YXIgb3V0ID0gdG9TdHJpbmdYWShjb29yZCk7XG4gKiAgICAgLy8gb3V0IGlzIG5vdyAnOCwgNDgnXG4gKlxuICogRXhhbXBsZSBleHBsaWNpdGx5IHNwZWNpZnlpbmcgMSBmcmFjdGlvbmFsIGRpZ2l0OlxuICpcbiAqICAgICBpbXBvcnQge3RvU3RyaW5nWFl9IGZyb20gJ29sL2Nvb3JkaW5hdGUnO1xuICpcbiAqICAgICB2YXIgY29vcmQgPSBbNy44NSwgNDcuOTgzMzMzXTtcbiAqICAgICB2YXIgb3V0ID0gdG9TdHJpbmdYWShjb29yZCwgMSk7XG4gKiAgICAgLy8gb3V0IGlzIG5vdyAnNy44LCA0OC4wJ1xuICpcbiAqIEBwYXJhbSB7Q29vcmRpbmF0ZX0gY29vcmRpbmF0ZSBDb29yZGluYXRlLlxuICogQHBhcmFtIHtudW1iZXI9fSBvcHRfZnJhY3Rpb25EaWdpdHMgVGhlIG51bWJlciBvZiBkaWdpdHMgdG8gaW5jbHVkZVxuICogICAgYWZ0ZXIgdGhlIGRlY2ltYWwgcG9pbnQuIERlZmF1bHQgaXMgYDBgLlxuICogQHJldHVybiB7c3RyaW5nfSBYWS5cbiAqIEBhcGlcbiAqL1xuXG5leHBvcnQgZnVuY3Rpb24gdG9TdHJpbmdYWShjb29yZGluYXRlLCBvcHRfZnJhY3Rpb25EaWdpdHMpIHtcbiAgcmV0dXJuIGZvcm1hdChjb29yZGluYXRlLCAne3h9LCB7eX0nLCBvcHRfZnJhY3Rpb25EaWdpdHMpO1xufVxuLyoqXG4gKiBNb2RpZmllcyB0aGUgcHJvdmlkZWQgY29vcmRpbmF0ZSBpbi1wbGFjZSB0byBiZSB3aXRoaW4gdGhlIHJlYWwgd29ybGRcbiAqIGV4dGVudC4gVGhlIGxvd2VyIHByb2plY3Rpb24gZXh0ZW50IGJvdW5kYXJ5IGlzIGluY2x1c2l2ZSwgdGhlIHVwcGVyIG9uZVxuICogZXhjbHVzaXZlLlxuICpcbiAqIEBwYXJhbSB7Q29vcmRpbmF0ZX0gY29vcmRpbmF0ZSBDb29yZGluYXRlLlxuICogQHBhcmFtIHtpbXBvcnQoXCIuL3Byb2ovUHJvamVjdGlvbi5qc1wiKS5kZWZhdWx0fSBwcm9qZWN0aW9uIFByb2plY3Rpb24uXG4gKiBAcmV0dXJuIHtDb29yZGluYXRlfSBUaGUgY29vcmRpbmF0ZSB3aXRoaW4gdGhlIHJlYWwgd29ybGQgZXh0ZW50LlxuICovXG5cbmV4cG9ydCBmdW5jdGlvbiB3cmFwWChjb29yZGluYXRlLCBwcm9qZWN0aW9uKSB7XG4gIGlmIChwcm9qZWN0aW9uLmNhbldyYXBYKCkpIHtcbiAgICB2YXIgd29ybGRXaWR0aCA9IGdldFdpZHRoKHByb2plY3Rpb24uZ2V0RXh0ZW50KCkpO1xuICAgIHZhciB3b3JsZHNBd2F5ID0gZ2V0V29ybGRzQXdheShjb29yZGluYXRlLCBwcm9qZWN0aW9uLCB3b3JsZFdpZHRoKTtcblxuICAgIGlmICh3b3JsZHNBd2F5KSB7XG4gICAgICBjb29yZGluYXRlWzBdIC09IHdvcmxkc0F3YXkgKiB3b3JsZFdpZHRoO1xuICAgIH1cbiAgfVxuXG4gIHJldHVybiBjb29yZGluYXRlO1xufVxuLyoqXG4gKiBAcGFyYW0ge0Nvb3JkaW5hdGV9IGNvb3JkaW5hdGUgQ29vcmRpbmF0ZS5cbiAqIEBwYXJhbSB7aW1wb3J0KFwiLi9wcm9qL1Byb2plY3Rpb24uanNcIikuZGVmYXVsdH0gcHJvamVjdGlvbiBQcm9qZWN0aW9uLlxuICogQHBhcmFtIHtudW1iZXI9fSBvcHRfc291cmNlRXh0ZW50V2lkdGggV2lkdGggb2YgdGhlIHNvdXJjZSBleHRlbnQuXG4gKiBAcmV0dXJuIHtudW1iZXJ9IE9mZnNldCBpbiB3b3JsZCB3aWR0aHMuXG4gKi9cblxuZXhwb3J0IGZ1bmN0aW9uIGdldFdvcmxkc0F3YXkoY29vcmRpbmF0ZSwgcHJvamVjdGlvbiwgb3B0X3NvdXJjZUV4dGVudFdpZHRoKSB7XG4gIHZhciBwcm9qZWN0aW9uRXh0ZW50ID0gcHJvamVjdGlvbi5nZXRFeHRlbnQoKTtcbiAgdmFyIHdvcmxkc0F3YXkgPSAwO1xuXG4gIGlmIChwcm9qZWN0aW9uLmNhbldyYXBYKCkgJiYgKGNvb3JkaW5hdGVbMF0gPCBwcm9qZWN0aW9uRXh0ZW50WzBdIHx8IGNvb3JkaW5hdGVbMF0gPiBwcm9qZWN0aW9uRXh0ZW50WzJdKSkge1xuICAgIHZhciBzb3VyY2VFeHRlbnRXaWR0aCA9IG9wdF9zb3VyY2VFeHRlbnRXaWR0aCB8fCBnZXRXaWR0aChwcm9qZWN0aW9uRXh0ZW50KTtcbiAgICB3b3JsZHNBd2F5ID0gTWF0aC5mbG9vcigoY29vcmRpbmF0ZVswXSAtIHByb2plY3Rpb25FeHRlbnRbMF0pIC8gc291cmNlRXh0ZW50V2lkdGgpO1xuICB9XG5cbiAgcmV0dXJuIHdvcmxkc0F3YXk7XG59IiwidmFyIF9fZXh0ZW5kcyA9IHRoaXMgJiYgdGhpcy5fX2V4dGVuZHMgfHwgZnVuY3Rpb24gKCkge1xuICB2YXIgX2V4dGVuZFN0YXRpY3MgPSBmdW5jdGlvbiBleHRlbmRTdGF0aWNzKGQsIGIpIHtcbiAgICBfZXh0ZW5kU3RhdGljcyA9IE9iamVjdC5zZXRQcm90b3R5cGVPZiB8fCB7XG4gICAgICBfX3Byb3RvX186IFtdXG4gICAgfSBpbnN0YW5jZW9mIEFycmF5ICYmIGZ1bmN0aW9uIChkLCBiKSB7XG4gICAgICBkLl9fcHJvdG9fXyA9IGI7XG4gICAgfSB8fCBmdW5jdGlvbiAoZCwgYikge1xuICAgICAgZm9yICh2YXIgcCBpbiBiKSB7XG4gICAgICAgIGlmIChPYmplY3QucHJvdG90eXBlLmhhc093blByb3BlcnR5LmNhbGwoYiwgcCkpIGRbcF0gPSBiW3BdO1xuICAgICAgfVxuICAgIH07XG5cbiAgICByZXR1cm4gX2V4dGVuZFN0YXRpY3MoZCwgYik7XG4gIH07XG5cbiAgcmV0dXJuIGZ1bmN0aW9uIChkLCBiKSB7XG4gICAgX2V4dGVuZFN0YXRpY3MoZCwgYik7XG5cbiAgICBmdW5jdGlvbiBfXygpIHtcbiAgICAgIHRoaXMuY29uc3RydWN0b3IgPSBkO1xuICAgIH1cblxuICAgIGQucHJvdG90eXBlID0gYiA9PT0gbnVsbCA/IE9iamVjdC5jcmVhdGUoYikgOiAoX18ucHJvdG90eXBlID0gYi5wcm90b3R5cGUsIG5ldyBfXygpKTtcbiAgfTtcbn0oKTtcbi8qKlxuICogQG1vZHVsZSBvbC9yZW5kZXJlci9NYXBcbiAqL1xuXG5cbmltcG9ydCBEaXNwb3NhYmxlIGZyb20gJy4uL0Rpc3Bvc2FibGUuanMnO1xuaW1wb3J0IHsgVFJVRSB9IGZyb20gJy4uL2Z1bmN0aW9ucy5qcyc7XG5pbXBvcnQgeyBhYnN0cmFjdCB9IGZyb20gJy4uL3V0aWwuanMnO1xuaW1wb3J0IHsgY29tcG9zZSBhcyBjb21wb3NlVHJhbnNmb3JtLCBtYWtlSW52ZXJzZSB9IGZyb20gJy4uL3RyYW5zZm9ybS5qcyc7XG5pbXBvcnQgeyBnZXRXaWR0aCB9IGZyb20gJy4uL2V4dGVudC5qcyc7XG5pbXBvcnQgeyBzaGFyZWQgYXMgaWNvbkltYWdlQ2FjaGUgfSBmcm9tICcuLi9zdHlsZS9JY29uSW1hZ2VDYWNoZS5qcyc7XG5pbXBvcnQgeyBpblZpZXcgfSBmcm9tICcuLi9sYXllci9MYXllci5qcyc7XG5pbXBvcnQgeyB3cmFwWCB9IGZyb20gJy4uL2Nvb3JkaW5hdGUuanMnO1xuLyoqXG4gKiBAdHlwZWRlZiBIaXRNYXRjaFxuICogQHByb3BlcnR5IHtpbXBvcnQoXCIuLi9GZWF0dXJlLmpzXCIpLkZlYXR1cmVMaWtlfSBmZWF0dXJlXG4gKiBAcHJvcGVydHkge2ltcG9ydChcIi4uL2xheWVyL0xheWVyLmpzXCIpLmRlZmF1bHR9IGxheWVyXG4gKiBAcHJvcGVydHkge2ltcG9ydChcIi4uL2dlb20vU2ltcGxlR2VvbWV0cnkuanNcIikuZGVmYXVsdH0gZ2VvbWV0cnlcbiAqIEBwcm9wZXJ0eSB7bnVtYmVyfSBkaXN0YW5jZVNxXG4gKiBAcHJvcGVydHkge2ltcG9ydChcIi4vdmVjdG9yLmpzXCIpLkZlYXR1cmVDYWxsYmFjazxUPn0gY2FsbGJhY2tcbiAqIEB0ZW1wbGF0ZSBUXG4gKi9cblxuLyoqXG4gKiBAYWJzdHJhY3RcbiAqL1xuXG52YXIgTWFwUmVuZGVyZXIgPVxuLyoqIEBjbGFzcyAqL1xuZnVuY3Rpb24gKF9zdXBlcikge1xuICBfX2V4dGVuZHMoTWFwUmVuZGVyZXIsIF9zdXBlcik7XG4gIC8qKlxuICAgKiBAcGFyYW0ge2ltcG9ydChcIi4uL1BsdWdnYWJsZU1hcC5qc1wiKS5kZWZhdWx0fSBtYXAgTWFwLlxuICAgKi9cblxuXG4gIGZ1bmN0aW9uIE1hcFJlbmRlcmVyKG1hcCkge1xuICAgIHZhciBfdGhpcyA9IF9zdXBlci5jYWxsKHRoaXMpIHx8IHRoaXM7XG4gICAgLyoqXG4gICAgICogQHByaXZhdGVcbiAgICAgKiBAdHlwZSB7aW1wb3J0KFwiLi4vUGx1Z2dhYmxlTWFwLmpzXCIpLmRlZmF1bHR9XG4gICAgICovXG5cblxuICAgIF90aGlzLm1hcF8gPSBtYXA7XG4gICAgcmV0dXJuIF90aGlzO1xuICB9XG4gIC8qKlxuICAgKiBAYWJzdHJhY3RcbiAgICogQHBhcmFtIHtpbXBvcnQoXCIuLi9yZW5kZXIvRXZlbnRUeXBlLmpzXCIpLmRlZmF1bHR9IHR5cGUgRXZlbnQgdHlwZS5cbiAgICogQHBhcmFtIHtpbXBvcnQoXCIuLi9QbHVnZ2FibGVNYXAuanNcIikuRnJhbWVTdGF0ZX0gZnJhbWVTdGF0ZSBGcmFtZSBzdGF0ZS5cbiAgICovXG5cblxuICBNYXBSZW5kZXJlci5wcm90b3R5cGUuZGlzcGF0Y2hSZW5kZXJFdmVudCA9IGZ1bmN0aW9uICh0eXBlLCBmcmFtZVN0YXRlKSB7XG4gICAgYWJzdHJhY3QoKTtcbiAgfTtcbiAgLyoqXG4gICAqIEBwYXJhbSB7aW1wb3J0KFwiLi4vUGx1Z2dhYmxlTWFwLmpzXCIpLkZyYW1lU3RhdGV9IGZyYW1lU3RhdGUgRnJhbWVTdGF0ZS5cbiAgICogQHByb3RlY3RlZFxuICAgKi9cblxuXG4gIE1hcFJlbmRlcmVyLnByb3RvdHlwZS5jYWxjdWxhdGVNYXRyaWNlczJEID0gZnVuY3Rpb24gKGZyYW1lU3RhdGUpIHtcbiAgICB2YXIgdmlld1N0YXRlID0gZnJhbWVTdGF0ZS52aWV3U3RhdGU7XG4gICAgdmFyIGNvb3JkaW5hdGVUb1BpeGVsVHJhbnNmb3JtID0gZnJhbWVTdGF0ZS5jb29yZGluYXRlVG9QaXhlbFRyYW5zZm9ybTtcbiAgICB2YXIgcGl4ZWxUb0Nvb3JkaW5hdGVUcmFuc2Zvcm0gPSBmcmFtZVN0YXRlLnBpeGVsVG9Db29yZGluYXRlVHJhbnNmb3JtO1xuICAgIGNvbXBvc2VUcmFuc2Zvcm0oY29vcmRpbmF0ZVRvUGl4ZWxUcmFuc2Zvcm0sIGZyYW1lU3RhdGUuc2l6ZVswXSAvIDIsIGZyYW1lU3RhdGUuc2l6ZVsxXSAvIDIsIDEgLyB2aWV3U3RhdGUucmVzb2x1dGlvbiwgLTEgLyB2aWV3U3RhdGUucmVzb2x1dGlvbiwgLXZpZXdTdGF0ZS5yb3RhdGlvbiwgLXZpZXdTdGF0ZS5jZW50ZXJbMF0sIC12aWV3U3RhdGUuY2VudGVyWzFdKTtcbiAgICBtYWtlSW52ZXJzZShwaXhlbFRvQ29vcmRpbmF0ZVRyYW5zZm9ybSwgY29vcmRpbmF0ZVRvUGl4ZWxUcmFuc2Zvcm0pO1xuICB9O1xuICAvKipcbiAgICogQHBhcmFtIHtpbXBvcnQoXCIuLi9jb29yZGluYXRlLmpzXCIpLkNvb3JkaW5hdGV9IGNvb3JkaW5hdGUgQ29vcmRpbmF0ZS5cbiAgICogQHBhcmFtIHtpbXBvcnQoXCIuLi9QbHVnZ2FibGVNYXAuanNcIikuRnJhbWVTdGF0ZX0gZnJhbWVTdGF0ZSBGcmFtZVN0YXRlLlxuICAgKiBAcGFyYW0ge251bWJlcn0gaGl0VG9sZXJhbmNlIEhpdCB0b2xlcmFuY2UgaW4gcGl4ZWxzLlxuICAgKiBAcGFyYW0ge2Jvb2xlYW59IGNoZWNrV3JhcHBlZCBDaGVjayBmb3Igd3JhcHBlZCBnZW9tZXRyaWVzLlxuICAgKiBAcGFyYW0ge2ltcG9ydChcIi4vdmVjdG9yLmpzXCIpLkZlYXR1cmVDYWxsYmFjazxUPn0gY2FsbGJhY2sgRmVhdHVyZSBjYWxsYmFjay5cbiAgICogQHBhcmFtIHtTfSB0aGlzQXJnIFZhbHVlIHRvIHVzZSBhcyBgdGhpc2Agd2hlbiBleGVjdXRpbmcgYGNhbGxiYWNrYC5cbiAgICogQHBhcmFtIHtmdW5jdGlvbih0aGlzOiBVLCBpbXBvcnQoXCIuLi9sYXllci9MYXllci5qc1wiKS5kZWZhdWx0KTogYm9vbGVhbn0gbGF5ZXJGaWx0ZXIgTGF5ZXIgZmlsdGVyXG4gICAqICAgICBmdW5jdGlvbiwgb25seSBsYXllcnMgd2hpY2ggYXJlIHZpc2libGUgYW5kIGZvciB3aGljaCB0aGlzIGZ1bmN0aW9uXG4gICAqICAgICByZXR1cm5zIGB0cnVlYCB3aWxsIGJlIHRlc3RlZCBmb3IgZmVhdHVyZXMuICBCeSBkZWZhdWx0LCBhbGwgdmlzaWJsZVxuICAgKiAgICAgbGF5ZXJzIHdpbGwgYmUgdGVzdGVkLlxuICAgKiBAcGFyYW0ge1V9IHRoaXNBcmcyIFZhbHVlIHRvIHVzZSBhcyBgdGhpc2Agd2hlbiBleGVjdXRpbmcgYGxheWVyRmlsdGVyYC5cbiAgICogQHJldHVybiB7VHx1bmRlZmluZWR9IENhbGxiYWNrIHJlc3VsdC5cbiAgICogQHRlbXBsYXRlIFMsVCxVXG4gICAqL1xuXG5cbiAgTWFwUmVuZGVyZXIucHJvdG90eXBlLmZvckVhY2hGZWF0dXJlQXRDb29yZGluYXRlID0gZnVuY3Rpb24gKGNvb3JkaW5hdGUsIGZyYW1lU3RhdGUsIGhpdFRvbGVyYW5jZSwgY2hlY2tXcmFwcGVkLCBjYWxsYmFjaywgdGhpc0FyZywgbGF5ZXJGaWx0ZXIsIHRoaXNBcmcyKSB7XG4gICAgdmFyIHJlc3VsdDtcbiAgICB2YXIgdmlld1N0YXRlID0gZnJhbWVTdGF0ZS52aWV3U3RhdGU7XG4gICAgLyoqXG4gICAgICogQHBhcmFtIHtib29sZWFufSBtYW5hZ2VkIE1hbmFnZWQgbGF5ZXIuXG4gICAgICogQHBhcmFtIHtpbXBvcnQoXCIuLi9GZWF0dXJlLmpzXCIpLkZlYXR1cmVMaWtlfSBmZWF0dXJlIEZlYXR1cmUuXG4gICAgICogQHBhcmFtIHtpbXBvcnQoXCIuLi9sYXllci9MYXllci5qc1wiKS5kZWZhdWx0fSBsYXllciBMYXllci5cbiAgICAgKiBAcGFyYW0ge2ltcG9ydChcIi4uL2dlb20vR2VvbWV0cnkuanNcIikuZGVmYXVsdH0gZ2VvbWV0cnkgR2VvbWV0cnkuXG4gICAgICogQHJldHVybiB7VHx1bmRlZmluZWR9IENhbGxiYWNrIHJlc3VsdC5cbiAgICAgKi9cblxuICAgIGZ1bmN0aW9uIGZvckVhY2hGZWF0dXJlQXRDb29yZGluYXRlKG1hbmFnZWQsIGZlYXR1cmUsIGxheWVyLCBnZW9tZXRyeSkge1xuICAgICAgcmV0dXJuIGNhbGxiYWNrLmNhbGwodGhpc0FyZywgZmVhdHVyZSwgbWFuYWdlZCA/IGxheWVyIDogbnVsbCwgZ2VvbWV0cnkpO1xuICAgIH1cblxuICAgIHZhciBwcm9qZWN0aW9uID0gdmlld1N0YXRlLnByb2plY3Rpb247XG4gICAgdmFyIHRyYW5zbGF0ZWRDb29yZGluYXRlID0gd3JhcFgoY29vcmRpbmF0ZS5zbGljZSgpLCBwcm9qZWN0aW9uKTtcbiAgICB2YXIgb2Zmc2V0cyA9IFtbMCwgMF1dO1xuXG4gICAgaWYgKHByb2plY3Rpb24uY2FuV3JhcFgoKSAmJiBjaGVja1dyYXBwZWQpIHtcbiAgICAgIHZhciBwcm9qZWN0aW9uRXh0ZW50ID0gcHJvamVjdGlvbi5nZXRFeHRlbnQoKTtcbiAgICAgIHZhciB3b3JsZFdpZHRoID0gZ2V0V2lkdGgocHJvamVjdGlvbkV4dGVudCk7XG4gICAgICBvZmZzZXRzLnB1c2goWy13b3JsZFdpZHRoLCAwXSwgW3dvcmxkV2lkdGgsIDBdKTtcbiAgICB9XG5cbiAgICB2YXIgbGF5ZXJTdGF0ZXMgPSBmcmFtZVN0YXRlLmxheWVyU3RhdGVzQXJyYXk7XG4gICAgdmFyIG51bUxheWVycyA9IGxheWVyU3RhdGVzLmxlbmd0aDtcbiAgICB2YXIgbWF0Y2hlcyA9XG4gICAgLyoqIEB0eXBlIHtBcnJheTxIaXRNYXRjaDxUPj59ICovXG4gICAgW107XG4gICAgdmFyIHRtcENvb3JkID0gW107XG5cbiAgICBmb3IgKHZhciBpID0gMDsgaSA8IG9mZnNldHMubGVuZ3RoOyBpKyspIHtcbiAgICAgIGZvciAodmFyIGogPSBudW1MYXllcnMgLSAxOyBqID49IDA7IC0taikge1xuICAgICAgICB2YXIgbGF5ZXJTdGF0ZSA9IGxheWVyU3RhdGVzW2pdO1xuICAgICAgICB2YXIgbGF5ZXIgPSBsYXllclN0YXRlLmxheWVyO1xuXG4gICAgICAgIGlmIChsYXllci5oYXNSZW5kZXJlcigpICYmIGluVmlldyhsYXllclN0YXRlLCB2aWV3U3RhdGUpICYmIGxheWVyRmlsdGVyLmNhbGwodGhpc0FyZzIsIGxheWVyKSkge1xuICAgICAgICAgIHZhciBsYXllclJlbmRlcmVyID0gbGF5ZXIuZ2V0UmVuZGVyZXIoKTtcbiAgICAgICAgICB2YXIgc291cmNlID0gbGF5ZXIuZ2V0U291cmNlKCk7XG5cbiAgICAgICAgICBpZiAobGF5ZXJSZW5kZXJlciAmJiBzb3VyY2UpIHtcbiAgICAgICAgICAgIHZhciBjb29yZGluYXRlcyA9IHNvdXJjZS5nZXRXcmFwWCgpID8gdHJhbnNsYXRlZENvb3JkaW5hdGUgOiBjb29yZGluYXRlO1xuICAgICAgICAgICAgdmFyIGNhbGxiYWNrXzEgPSBmb3JFYWNoRmVhdHVyZUF0Q29vcmRpbmF0ZS5iaW5kKG51bGwsIGxheWVyU3RhdGUubWFuYWdlZCk7XG4gICAgICAgICAgICB0bXBDb29yZFswXSA9IGNvb3JkaW5hdGVzWzBdICsgb2Zmc2V0c1tpXVswXTtcbiAgICAgICAgICAgIHRtcENvb3JkWzFdID0gY29vcmRpbmF0ZXNbMV0gKyBvZmZzZXRzW2ldWzFdO1xuICAgICAgICAgICAgcmVzdWx0ID0gbGF5ZXJSZW5kZXJlci5mb3JFYWNoRmVhdHVyZUF0Q29vcmRpbmF0ZSh0bXBDb29yZCwgZnJhbWVTdGF0ZSwgaGl0VG9sZXJhbmNlLCBjYWxsYmFja18xLCBtYXRjaGVzKTtcbiAgICAgICAgICB9XG5cbiAgICAgICAgICBpZiAocmVzdWx0KSB7XG4gICAgICAgICAgICByZXR1cm4gcmVzdWx0O1xuICAgICAgICAgIH1cbiAgICAgICAgfVxuICAgICAgfVxuICAgIH1cblxuICAgIGlmIChtYXRjaGVzLmxlbmd0aCA9PT0gMCkge1xuICAgICAgcmV0dXJuIHVuZGVmaW5lZDtcbiAgICB9XG5cbiAgICB2YXIgb3JkZXIgPSAxIC8gbWF0Y2hlcy5sZW5ndGg7XG4gICAgbWF0Y2hlcy5mb3JFYWNoKGZ1bmN0aW9uIChtLCBpKSB7XG4gICAgICByZXR1cm4gbS5kaXN0YW5jZVNxICs9IGkgKiBvcmRlcjtcbiAgICB9KTtcbiAgICBtYXRjaGVzLnNvcnQoZnVuY3Rpb24gKGEsIGIpIHtcbiAgICAgIHJldHVybiBhLmRpc3RhbmNlU3EgLSBiLmRpc3RhbmNlU3E7XG4gICAgfSk7XG4gICAgbWF0Y2hlcy5zb21lKGZ1bmN0aW9uIChtKSB7XG4gICAgICByZXR1cm4gcmVzdWx0ID0gbS5jYWxsYmFjayhtLmZlYXR1cmUsIG0ubGF5ZXIsIG0uZ2VvbWV0cnkpO1xuICAgIH0pO1xuICAgIHJldHVybiByZXN1bHQ7XG4gIH07XG4gIC8qKlxuICAgKiBAYWJzdHJhY3RcbiAgICogQHBhcmFtIHtpbXBvcnQoXCIuLi9waXhlbC5qc1wiKS5QaXhlbH0gcGl4ZWwgUGl4ZWwuXG4gICAqIEBwYXJhbSB7aW1wb3J0KFwiLi4vUGx1Z2dhYmxlTWFwLmpzXCIpLkZyYW1lU3RhdGV9IGZyYW1lU3RhdGUgRnJhbWVTdGF0ZS5cbiAgICogQHBhcmFtIHtudW1iZXJ9IGhpdFRvbGVyYW5jZSBIaXQgdG9sZXJhbmNlIGluIHBpeGVscy5cbiAgICogQHBhcmFtIHtmdW5jdGlvbihpbXBvcnQoXCIuLi9sYXllci9MYXllci5qc1wiKS5kZWZhdWx0LCAoVWludDhDbGFtcGVkQXJyYXl8VWludDhBcnJheSkpOiBUfSBjYWxsYmFjayBMYXllclxuICAgKiAgICAgY2FsbGJhY2suXG4gICAqIEBwYXJhbSB7ZnVuY3Rpb24oaW1wb3J0KFwiLi4vbGF5ZXIvTGF5ZXIuanNcIikuZGVmYXVsdCk6IGJvb2xlYW59IGxheWVyRmlsdGVyIExheWVyIGZpbHRlclxuICAgKiAgICAgZnVuY3Rpb24sIG9ubHkgbGF5ZXJzIHdoaWNoIGFyZSB2aXNpYmxlIGFuZCBmb3Igd2hpY2ggdGhpcyBmdW5jdGlvblxuICAgKiAgICAgcmV0dXJucyBgdHJ1ZWAgd2lsbCBiZSB0ZXN0ZWQgZm9yIGZlYXR1cmVzLiAgQnkgZGVmYXVsdCwgYWxsIHZpc2libGVcbiAgICogICAgIGxheWVycyB3aWxsIGJlIHRlc3RlZC5cbiAgICogQHJldHVybiB7VHx1bmRlZmluZWR9IENhbGxiYWNrIHJlc3VsdC5cbiAgICogQHRlbXBsYXRlIFRcbiAgICovXG5cblxuICBNYXBSZW5kZXJlci5wcm90b3R5cGUuZm9yRWFjaExheWVyQXRQaXhlbCA9IGZ1bmN0aW9uIChwaXhlbCwgZnJhbWVTdGF0ZSwgaGl0VG9sZXJhbmNlLCBjYWxsYmFjaywgbGF5ZXJGaWx0ZXIpIHtcbiAgICByZXR1cm4gYWJzdHJhY3QoKTtcbiAgfTtcbiAgLyoqXG4gICAqIEBwYXJhbSB7aW1wb3J0KFwiLi4vY29vcmRpbmF0ZS5qc1wiKS5Db29yZGluYXRlfSBjb29yZGluYXRlIENvb3JkaW5hdGUuXG4gICAqIEBwYXJhbSB7aW1wb3J0KFwiLi4vUGx1Z2dhYmxlTWFwLmpzXCIpLkZyYW1lU3RhdGV9IGZyYW1lU3RhdGUgRnJhbWVTdGF0ZS5cbiAgICogQHBhcmFtIHtudW1iZXJ9IGhpdFRvbGVyYW5jZSBIaXQgdG9sZXJhbmNlIGluIHBpeGVscy5cbiAgICogQHBhcmFtIHtib29sZWFufSBjaGVja1dyYXBwZWQgQ2hlY2sgZm9yIHdyYXBwZWQgZ2VvbWV0cmllcy5cbiAgICogQHBhcmFtIHtmdW5jdGlvbih0aGlzOiBVLCBpbXBvcnQoXCIuLi9sYXllci9MYXllci5qc1wiKS5kZWZhdWx0KTogYm9vbGVhbn0gbGF5ZXJGaWx0ZXIgTGF5ZXIgZmlsdGVyXG4gICAqICAgICBmdW5jdGlvbiwgb25seSBsYXllcnMgd2hpY2ggYXJlIHZpc2libGUgYW5kIGZvciB3aGljaCB0aGlzIGZ1bmN0aW9uXG4gICAqICAgICByZXR1cm5zIGB0cnVlYCB3aWxsIGJlIHRlc3RlZCBmb3IgZmVhdHVyZXMuICBCeSBkZWZhdWx0LCBhbGwgdmlzaWJsZVxuICAgKiAgICAgbGF5ZXJzIHdpbGwgYmUgdGVzdGVkLlxuICAgKiBAcGFyYW0ge1V9IHRoaXNBcmcgVmFsdWUgdG8gdXNlIGFzIGB0aGlzYCB3aGVuIGV4ZWN1dGluZyBgbGF5ZXJGaWx0ZXJgLlxuICAgKiBAcmV0dXJuIHtib29sZWFufSBJcyB0aGVyZSBhIGZlYXR1cmUgYXQgdGhlIGdpdmVuIGNvb3JkaW5hdGU/XG4gICAqIEB0ZW1wbGF0ZSBVXG4gICAqL1xuXG5cbiAgTWFwUmVuZGVyZXIucHJvdG90eXBlLmhhc0ZlYXR1cmVBdENvb3JkaW5hdGUgPSBmdW5jdGlvbiAoY29vcmRpbmF0ZSwgZnJhbWVTdGF0ZSwgaGl0VG9sZXJhbmNlLCBjaGVja1dyYXBwZWQsIGxheWVyRmlsdGVyLCB0aGlzQXJnKSB7XG4gICAgdmFyIGhhc0ZlYXR1cmUgPSB0aGlzLmZvckVhY2hGZWF0dXJlQXRDb29yZGluYXRlKGNvb3JkaW5hdGUsIGZyYW1lU3RhdGUsIGhpdFRvbGVyYW5jZSwgY2hlY2tXcmFwcGVkLCBUUlVFLCB0aGlzLCBsYXllckZpbHRlciwgdGhpc0FyZyk7XG4gICAgcmV0dXJuIGhhc0ZlYXR1cmUgIT09IHVuZGVmaW5lZDtcbiAgfTtcbiAgLyoqXG4gICAqIEByZXR1cm4ge2ltcG9ydChcIi4uL1BsdWdnYWJsZU1hcC5qc1wiKS5kZWZhdWx0fSBNYXAuXG4gICAqL1xuXG5cbiAgTWFwUmVuZGVyZXIucHJvdG90eXBlLmdldE1hcCA9IGZ1bmN0aW9uICgpIHtcbiAgICByZXR1cm4gdGhpcy5tYXBfO1xuICB9O1xuICAvKipcbiAgICogUmVuZGVyLlxuICAgKiBAYWJzdHJhY3RcbiAgICogQHBhcmFtIHs/aW1wb3J0KFwiLi4vUGx1Z2dhYmxlTWFwLmpzXCIpLkZyYW1lU3RhdGV9IGZyYW1lU3RhdGUgRnJhbWUgc3RhdGUuXG4gICAqL1xuXG5cbiAgTWFwUmVuZGVyZXIucHJvdG90eXBlLnJlbmRlckZyYW1lID0gZnVuY3Rpb24gKGZyYW1lU3RhdGUpIHtcbiAgICBhYnN0cmFjdCgpO1xuICB9O1xuICAvKipcbiAgICogQHBhcmFtIHtpbXBvcnQoXCIuLi9QbHVnZ2FibGVNYXAuanNcIikuRnJhbWVTdGF0ZX0gZnJhbWVTdGF0ZSBGcmFtZSBzdGF0ZS5cbiAgICogQHByb3RlY3RlZFxuICAgKi9cblxuXG4gIE1hcFJlbmRlcmVyLnByb3RvdHlwZS5zY2hlZHVsZUV4cGlyZUljb25DYWNoZSA9IGZ1bmN0aW9uIChmcmFtZVN0YXRlKSB7XG4gICAgaWYgKGljb25JbWFnZUNhY2hlLmNhbkV4cGlyZUNhY2hlKCkpIHtcbiAgICAgIGZyYW1lU3RhdGUucG9zdFJlbmRlckZ1bmN0aW9ucy5wdXNoKGV4cGlyZUljb25DYWNoZSk7XG4gICAgfVxuICB9O1xuXG4gIHJldHVybiBNYXBSZW5kZXJlcjtcbn0oRGlzcG9zYWJsZSk7XG4vKipcbiAqIEBwYXJhbSB7aW1wb3J0KFwiLi4vUGx1Z2dhYmxlTWFwLmpzXCIpLmRlZmF1bHR9IG1hcCBNYXAuXG4gKiBAcGFyYW0ge2ltcG9ydChcIi4uL1BsdWdnYWJsZU1hcC5qc1wiKS5GcmFtZVN0YXRlfSBmcmFtZVN0YXRlIEZyYW1lIHN0YXRlLlxuICovXG5cblxuZnVuY3Rpb24gZXhwaXJlSWNvbkNhY2hlKG1hcCwgZnJhbWVTdGF0ZSkge1xuICBpY29uSW1hZ2VDYWNoZS5leHBpcmUoKTtcbn1cblxuZXhwb3J0IGRlZmF1bHQgTWFwUmVuZGVyZXI7IiwiLyoqXG4gKiBAbW9kdWxlIG9sL3JlbmRlci9FdmVudFxuICovXG52YXIgX19leHRlbmRzID0gdGhpcyAmJiB0aGlzLl9fZXh0ZW5kcyB8fCBmdW5jdGlvbiAoKSB7XG4gIHZhciBfZXh0ZW5kU3RhdGljcyA9IGZ1bmN0aW9uIGV4dGVuZFN0YXRpY3MoZCwgYikge1xuICAgIF9leHRlbmRTdGF0aWNzID0gT2JqZWN0LnNldFByb3RvdHlwZU9mIHx8IHtcbiAgICAgIF9fcHJvdG9fXzogW11cbiAgICB9IGluc3RhbmNlb2YgQXJyYXkgJiYgZnVuY3Rpb24gKGQsIGIpIHtcbiAgICAgIGQuX19wcm90b19fID0gYjtcbiAgICB9IHx8IGZ1bmN0aW9uIChkLCBiKSB7XG4gICAgICBmb3IgKHZhciBwIGluIGIpIHtcbiAgICAgICAgaWYgKE9iamVjdC5wcm90b3R5cGUuaGFzT3duUHJvcGVydHkuY2FsbChiLCBwKSkgZFtwXSA9IGJbcF07XG4gICAgICB9XG4gICAgfTtcblxuICAgIHJldHVybiBfZXh0ZW5kU3RhdGljcyhkLCBiKTtcbiAgfTtcblxuICByZXR1cm4gZnVuY3Rpb24gKGQsIGIpIHtcbiAgICBfZXh0ZW5kU3RhdGljcyhkLCBiKTtcblxuICAgIGZ1bmN0aW9uIF9fKCkge1xuICAgICAgdGhpcy5jb25zdHJ1Y3RvciA9IGQ7XG4gICAgfVxuXG4gICAgZC5wcm90b3R5cGUgPSBiID09PSBudWxsID8gT2JqZWN0LmNyZWF0ZShiKSA6IChfXy5wcm90b3R5cGUgPSBiLnByb3RvdHlwZSwgbmV3IF9fKCkpO1xuICB9O1xufSgpO1xuXG5pbXBvcnQgRXZlbnQgZnJvbSAnLi4vZXZlbnRzL0V2ZW50LmpzJztcblxudmFyIFJlbmRlckV2ZW50ID1cbi8qKiBAY2xhc3MgKi9cbmZ1bmN0aW9uIChfc3VwZXIpIHtcbiAgX19leHRlbmRzKFJlbmRlckV2ZW50LCBfc3VwZXIpO1xuICAvKipcbiAgICogQHBhcmFtIHtpbXBvcnQoXCIuL0V2ZW50VHlwZS5qc1wiKS5kZWZhdWx0fSB0eXBlIFR5cGUuXG4gICAqIEBwYXJhbSB7aW1wb3J0KFwiLi4vdHJhbnNmb3JtLmpzXCIpLlRyYW5zZm9ybT19IG9wdF9pbnZlcnNlUGl4ZWxUcmFuc2Zvcm0gVHJhbnNmb3JtIGZvclxuICAgKiAgICAgQ1NTIHBpeGVscyB0byByZW5kZXJlZCBwaXhlbHMuXG4gICAqIEBwYXJhbSB7aW1wb3J0KFwiLi4vUGx1Z2dhYmxlTWFwLmpzXCIpLkZyYW1lU3RhdGU9fSBvcHRfZnJhbWVTdGF0ZSBGcmFtZSBzdGF0ZS5cbiAgICogQHBhcmFtIHs/Q2FudmFzUmVuZGVyaW5nQ29udGV4dDJEPX0gb3B0X2NvbnRleHQgQ29udGV4dC5cbiAgICovXG5cblxuICBmdW5jdGlvbiBSZW5kZXJFdmVudCh0eXBlLCBvcHRfaW52ZXJzZVBpeGVsVHJhbnNmb3JtLCBvcHRfZnJhbWVTdGF0ZSwgb3B0X2NvbnRleHQpIHtcbiAgICB2YXIgX3RoaXMgPSBfc3VwZXIuY2FsbCh0aGlzLCB0eXBlKSB8fCB0aGlzO1xuICAgIC8qKlxuICAgICAqIFRyYW5zZm9ybSBmcm9tIENTUyBwaXhlbHMgKHJlbGF0aXZlIHRvIHRoZSB0b3AtbGVmdCBjb3JuZXIgb2YgdGhlIG1hcCB2aWV3cG9ydClcbiAgICAgKiB0byByZW5kZXJlZCBwaXhlbHMgb24gdGhpcyBldmVudCdzIGBjb250ZXh0YC4gT25seSBhdmFpbGFibGUgd2hlbiBhIENhbnZhcyByZW5kZXJlciBpcyB1c2VkLCBudWxsIG90aGVyd2lzZS5cbiAgICAgKiBAdHlwZSB7aW1wb3J0KFwiLi4vdHJhbnNmb3JtLmpzXCIpLlRyYW5zZm9ybXx1bmRlZmluZWR9XG4gICAgICogQGFwaVxuICAgICAqL1xuXG5cbiAgICBfdGhpcy5pbnZlcnNlUGl4ZWxUcmFuc2Zvcm0gPSBvcHRfaW52ZXJzZVBpeGVsVHJhbnNmb3JtO1xuICAgIC8qKlxuICAgICAqIEFuIG9iamVjdCByZXByZXNlbnRpbmcgdGhlIGN1cnJlbnQgcmVuZGVyIGZyYW1lIHN0YXRlLlxuICAgICAqIEB0eXBlIHtpbXBvcnQoXCIuLi9QbHVnZ2FibGVNYXAuanNcIikuRnJhbWVTdGF0ZXx1bmRlZmluZWR9XG4gICAgICogQGFwaVxuICAgICAqL1xuXG4gICAgX3RoaXMuZnJhbWVTdGF0ZSA9IG9wdF9mcmFtZVN0YXRlO1xuICAgIC8qKlxuICAgICAqIENhbnZhcyBjb250ZXh0LiBOb3QgYXZhaWxhYmxlIHdoZW4gdGhlIGV2ZW50IGlzIGRpc3BhdGNoZWQgYnkgdGhlIG1hcC4gT25seSBhdmFpbGFibGVcbiAgICAgKiB3aGVuIGEgQ2FudmFzIHJlbmRlcmVyIGlzIHVzZWQsIG51bGwgb3RoZXJ3aXNlLlxuICAgICAqIEB0eXBlIHtDYW52YXNSZW5kZXJpbmdDb250ZXh0MkR8bnVsbHx1bmRlZmluZWR9XG4gICAgICogQGFwaVxuICAgICAqL1xuXG4gICAgX3RoaXMuY29udGV4dCA9IG9wdF9jb250ZXh0O1xuICAgIHJldHVybiBfdGhpcztcbiAgfVxuXG4gIHJldHVybiBSZW5kZXJFdmVudDtcbn0oRXZlbnQpO1xuXG5leHBvcnQgZGVmYXVsdCBSZW5kZXJFdmVudDsiLCIvKipcbiAqIEBtb2R1bGUgb2wvY3NzXG4gKi9cblxuLyoqXG4gKiBAdHlwZWRlZiB7T2JqZWN0fSBGb250UGFyYW1ldGVyc1xuICogQHByb3BlcnR5IHtzdHJpbmd9IHN0eWxlXG4gKiBAcHJvcGVydHkge3N0cmluZ30gdmFyaWFudFxuICogQHByb3BlcnR5IHtzdHJpbmd9IHdlaWdodFxuICogQHByb3BlcnR5IHtzdHJpbmd9IHNpemVcbiAqIEBwcm9wZXJ0eSB7c3RyaW5nfSBsaW5lSGVpZ2h0XG4gKiBAcHJvcGVydHkge3N0cmluZ30gZmFtaWx5XG4gKiBAcHJvcGVydHkge0FycmF5PHN0cmluZz59IGZhbWlsaWVzXG4gKi9cblxuLyoqXG4gKiBUaGUgQ1NTIGNsYXNzIGZvciBoaWRkZW4gZmVhdHVyZS5cbiAqXG4gKiBAY29uc3RcbiAqIEB0eXBlIHtzdHJpbmd9XG4gKi9cbmV4cG9ydCB2YXIgQ0xBU1NfSElEREVOID0gJ29sLWhpZGRlbic7XG4vKipcbiAqIFRoZSBDU1MgY2xhc3MgdGhhdCB3ZSdsbCBnaXZlIHRoZSBET00gZWxlbWVudHMgdG8gaGF2ZSB0aGVtIHNlbGVjdGFibGUuXG4gKlxuICogQGNvbnN0XG4gKiBAdHlwZSB7c3RyaW5nfVxuICovXG5cbmV4cG9ydCB2YXIgQ0xBU1NfU0VMRUNUQUJMRSA9ICdvbC1zZWxlY3RhYmxlJztcbi8qKlxuICogVGhlIENTUyBjbGFzcyB0aGF0IHdlJ2xsIGdpdmUgdGhlIERPTSBlbGVtZW50cyB0byBoYXZlIHRoZW0gdW5zZWxlY3RhYmxlLlxuICpcbiAqIEBjb25zdFxuICogQHR5cGUge3N0cmluZ31cbiAqL1xuXG5leHBvcnQgdmFyIENMQVNTX1VOU0VMRUNUQUJMRSA9ICdvbC11bnNlbGVjdGFibGUnO1xuLyoqXG4gKiBUaGUgQ1NTIGNsYXNzIGZvciB1bnN1cHBvcnRlZCBmZWF0dXJlLlxuICpcbiAqIEBjb25zdFxuICogQHR5cGUge3N0cmluZ31cbiAqL1xuXG5leHBvcnQgdmFyIENMQVNTX1VOU1VQUE9SVEVEID0gJ29sLXVuc3VwcG9ydGVkJztcbi8qKlxuICogVGhlIENTUyBjbGFzcyBmb3IgY29udHJvbHMuXG4gKlxuICogQGNvbnN0XG4gKiBAdHlwZSB7c3RyaW5nfVxuICovXG5cbmV4cG9ydCB2YXIgQ0xBU1NfQ09OVFJPTCA9ICdvbC1jb250cm9sJztcbi8qKlxuICogVGhlIENTUyBjbGFzcyB0aGF0IHdlJ2xsIGdpdmUgdGhlIERPTSBlbGVtZW50cyB0aGF0IGFyZSBjb2xsYXBzZWQsIGkuZS5cbiAqIHRvIHRob3NlIGVsZW1lbnRzIHdoaWNoIHVzdWFsbHkgY2FuIGJlIGV4cGFuZGVkLlxuICpcbiAqIEBjb25zdFxuICogQHR5cGUge3N0cmluZ31cbiAqL1xuXG5leHBvcnQgdmFyIENMQVNTX0NPTExBUFNFRCA9ICdvbC1jb2xsYXBzZWQnO1xuLyoqXG4gKiBGcm9tIGh0dHA6Ly9zdGFja292ZXJmbG93LmNvbS9xdWVzdGlvbnMvMTAxMzU2OTcvcmVnZXgtdG8tcGFyc2UtYW55LWNzcy1mb250XG4gKiBAdHlwZSB7UmVnRXhwfVxuICovXG5cbnZhciBmb250UmVnRXggPSBuZXcgUmVnRXhwKFsnXlxcXFxzKig/PSg/Oig/OlstYS16XStcXFxccyopezAsMn0oaXRhbGljfG9ibGlxdWUpKT8pJywgJyg/PSg/Oig/OlstYS16XStcXFxccyopezAsMn0oc21hbGwtY2FwcykpPyknLCAnKD89KD86KD86Wy1hLXpdK1xcXFxzKil7MCwyfShib2xkKD86ZXIpP3xsaWdodGVyfFsxLTldMDAgKSk/KScsICcoPzooPzpub3JtYWx8XFxcXDF8XFxcXDJ8XFxcXDMpXFxcXHMqKXswLDN9KCg/Onh4Py0pPycsICcoPzpzbWFsbHxsYXJnZSl8bWVkaXVtfHNtYWxsZXJ8bGFyZ2VyfFtcXFxcLlxcXFxkXSsoPzpcXFxcJXxpbnxbY2VtXW18ZXh8cFtjdHhdKSknLCAnKD86XFxcXHMqXFxcXC9cXFxccyoobm9ybWFsfFtcXFxcLlxcXFxkXSsoPzpcXFxcJXxpbnxbY2VtXW18ZXh8cFtjdHhdKT8pKScsICc/XFxcXHMqKFstLFxcXFxcIlxcXFxcXCdcXFxcc2Etel0rPylcXFxccyokJ10uam9pbignJyksICdpJyk7XG52YXIgZm9udFJlZ0V4TWF0Y2hJbmRleCA9IFsnc3R5bGUnLCAndmFyaWFudCcsICd3ZWlnaHQnLCAnc2l6ZScsICdsaW5lSGVpZ2h0JywgJ2ZhbWlseSddO1xuLyoqXG4gKiBHZXQgdGhlIGxpc3Qgb2YgZm9udCBmYW1pbGllcyBmcm9tIGEgZm9udCBzcGVjLiAgTm90ZSB0aGF0IHRoaXMgZG9lc24ndCB3b3JrXG4gKiBmb3IgZm9udCBmYW1pbGllcyB0aGF0IGhhdmUgY29tbWFzIGluIHRoZW0uXG4gKiBAcGFyYW0ge3N0cmluZ30gZm9udFNwZWMgVGhlIENTUyBmb250IHByb3BlcnR5LlxuICogQHJldHVybiB7Rm9udFBhcmFtZXRlcnN9IFRoZSBmb250IHBhcmFtZXRlcnMgKG9yIG51bGwgaWYgdGhlIGlucHV0IHNwZWMgaXMgaW52YWxpZCkuXG4gKi9cblxuZXhwb3J0IHZhciBnZXRGb250UGFyYW1ldGVycyA9IGZ1bmN0aW9uIGdldEZvbnRQYXJhbWV0ZXJzKGZvbnRTcGVjKSB7XG4gIHZhciBtYXRjaCA9IGZvbnRTcGVjLm1hdGNoKGZvbnRSZWdFeCk7XG5cbiAgaWYgKCFtYXRjaCkge1xuICAgIHJldHVybiBudWxsO1xuICB9XG5cbiAgdmFyIHN0eWxlID1cbiAgLyoqIEB0eXBlIHtGb250UGFyYW1ldGVyc30gKi9cbiAge1xuICAgIGxpbmVIZWlnaHQ6ICdub3JtYWwnLFxuICAgIHNpemU6ICcxLjJlbScsXG4gICAgc3R5bGU6ICdub3JtYWwnLFxuICAgIHdlaWdodDogJ25vcm1hbCcsXG4gICAgdmFyaWFudDogJ25vcm1hbCdcbiAgfTtcblxuICBmb3IgKHZhciBpID0gMCwgaWkgPSBmb250UmVnRXhNYXRjaEluZGV4Lmxlbmd0aDsgaSA8IGlpOyArK2kpIHtcbiAgICB2YXIgdmFsdWUgPSBtYXRjaFtpICsgMV07XG5cbiAgICBpZiAodmFsdWUgIT09IHVuZGVmaW5lZCkge1xuICAgICAgc3R5bGVbZm9udFJlZ0V4TWF0Y2hJbmRleFtpXV0gPSB2YWx1ZTtcbiAgICB9XG4gIH1cblxuICBzdHlsZS5mYW1pbGllcyA9IHN0eWxlLmZhbWlseS5zcGxpdCgvLFxccz8vKTtcbiAgcmV0dXJuIHN0eWxlO1xufTsiLCIvKipcbiAqIEBtb2R1bGUgb2wvaGFzXG4gKi9cbnZhciB1YSA9IHR5cGVvZiBuYXZpZ2F0b3IgIT09ICd1bmRlZmluZWQnICYmIHR5cGVvZiBuYXZpZ2F0b3IudXNlckFnZW50ICE9PSAndW5kZWZpbmVkJyA/IG5hdmlnYXRvci51c2VyQWdlbnQudG9Mb3dlckNhc2UoKSA6ICcnO1xuLyoqXG4gKiBVc2VyIGFnZW50IHN0cmluZyBzYXlzIHdlIGFyZSBkZWFsaW5nIHdpdGggRmlyZWZveCBhcyBicm93c2VyLlxuICogQHR5cGUge2Jvb2xlYW59XG4gKi9cblxuZXhwb3J0IHZhciBGSVJFRk9YID0gdWEuaW5kZXhPZignZmlyZWZveCcpICE9PSAtMTtcbi8qKlxuICogVXNlciBhZ2VudCBzdHJpbmcgc2F5cyB3ZSBhcmUgZGVhbGluZyB3aXRoIFNhZmFyaSBhcyBicm93c2VyLlxuICogQHR5cGUge2Jvb2xlYW59XG4gKi9cblxuZXhwb3J0IHZhciBTQUZBUkkgPSB1YS5pbmRleE9mKCdzYWZhcmknKSAhPT0gLTEgJiYgdWEuaW5kZXhPZignY2hyb20nKSA9PSAtMTtcbi8qKlxuICogVXNlciBhZ2VudCBzdHJpbmcgc2F5cyB3ZSBhcmUgZGVhbGluZyB3aXRoIGEgV2ViS2l0IGVuZ2luZS5cbiAqIEB0eXBlIHtib29sZWFufVxuICovXG5cbmV4cG9ydCB2YXIgV0VCS0lUID0gdWEuaW5kZXhPZignd2Via2l0JykgIT09IC0xICYmIHVhLmluZGV4T2YoJ2VkZ2UnKSA9PSAtMTtcbi8qKlxuICogVXNlciBhZ2VudCBzdHJpbmcgc2F5cyB3ZSBhcmUgZGVhbGluZyB3aXRoIGEgTWFjIGFzIHBsYXRmb3JtLlxuICogQHR5cGUge2Jvb2xlYW59XG4gKi9cblxuZXhwb3J0IHZhciBNQUMgPSB1YS5pbmRleE9mKCdtYWNpbnRvc2gnKSAhPT0gLTE7XG4vKipcbiAqIFRoZSByYXRpbyBiZXR3ZWVuIHBoeXNpY2FsIHBpeGVscyBhbmQgZGV2aWNlLWluZGVwZW5kZW50IHBpeGVsc1xuICogKGRpcHMpIG9uIHRoZSBkZXZpY2UgKGB3aW5kb3cuZGV2aWNlUGl4ZWxSYXRpb2ApLlxuICogQGNvbnN0XG4gKiBAdHlwZSB7bnVtYmVyfVxuICogQGFwaVxuICovXG5cbmV4cG9ydCB2YXIgREVWSUNFX1BJWEVMX1JBVElPID0gdHlwZW9mIGRldmljZVBpeGVsUmF0aW8gIT09ICd1bmRlZmluZWQnID8gZGV2aWNlUGl4ZWxSYXRpbyA6IDE7XG4vKipcbiAqIFRoZSBleGVjdXRpb24gY29udGV4dCBpcyBhIHdvcmtlciB3aXRoIE9mZnNjcmVlbkNhbnZhcyBhdmFpbGFibGUuXG4gKiBAY29uc3RcbiAqIEB0eXBlIHtib29sZWFufVxuICovXG5cbmV4cG9ydCB2YXIgV09SS0VSX09GRlNDUkVFTl9DQU5WQVMgPSB0eXBlb2YgV29ya2VyR2xvYmFsU2NvcGUgIT09ICd1bmRlZmluZWQnICYmIHR5cGVvZiBPZmZzY3JlZW5DYW52YXMgIT09ICd1bmRlZmluZWQnICYmIHNlbGYgaW5zdGFuY2VvZiBXb3JrZXJHbG9iYWxTY29wZTsgLy9lc2xpbnQtZGlzYWJsZS1saW5lXG5cbi8qKlxuICogSW1hZ2UucHJvdG90eXBlLmRlY29kZSgpIGlzIHN1cHBvcnRlZC5cbiAqIEB0eXBlIHtib29sZWFufVxuICovXG5cbmV4cG9ydCB2YXIgSU1BR0VfREVDT0RFID0gdHlwZW9mIEltYWdlICE9PSAndW5kZWZpbmVkJyAmJiBJbWFnZS5wcm90b3R5cGUuZGVjb2RlO1xuLyoqXG4gKiBAdHlwZSB7Ym9vbGVhbn1cbiAqL1xuXG5leHBvcnQgdmFyIFBBU1NJVkVfRVZFTlRfTElTVEVORVJTID0gZnVuY3Rpb24gKCkge1xuICB2YXIgcGFzc2l2ZSA9IGZhbHNlO1xuXG4gIHRyeSB7XG4gICAgdmFyIG9wdGlvbnMgPSBPYmplY3QuZGVmaW5lUHJvcGVydHkoe30sICdwYXNzaXZlJywge1xuICAgICAgZ2V0OiBmdW5jdGlvbiBnZXQoKSB7XG4gICAgICAgIHBhc3NpdmUgPSB0cnVlO1xuICAgICAgfVxuICAgIH0pO1xuICAgIHdpbmRvdy5hZGRFdmVudExpc3RlbmVyKCdfJywgbnVsbCwgb3B0aW9ucyk7XG4gICAgd2luZG93LnJlbW92ZUV2ZW50TGlzdGVuZXIoJ18nLCBudWxsLCBvcHRpb25zKTtcbiAgfSBjYXRjaCAoZXJyb3IpIHsvLyBwYXNzaXZlIG5vdCBzdXBwb3J0ZWRcbiAgfVxuXG4gIHJldHVybiBwYXNzaXZlO1xufSgpOyIsImltcG9ydCB7IFdPUktFUl9PRkZTQ1JFRU5fQ0FOVkFTIH0gZnJvbSAnLi9oYXMuanMnO1xuLyoqXG4gKiBAbW9kdWxlIG9sL2RvbVxuICovXG4vL0ZJWE1FIE1vdmUgdGhpcyBmdW5jdGlvbiB0byB0aGUgY2FudmFzIG1vZHVsZVxuXG4vKipcbiAqIENyZWF0ZSBhbiBodG1sIGNhbnZhcyBlbGVtZW50IGFuZCByZXR1cm5zIGl0cyAyZCBjb250ZXh0LlxuICogQHBhcmFtIHtudW1iZXI9fSBvcHRfd2lkdGggQ2FudmFzIHdpZHRoLlxuICogQHBhcmFtIHtudW1iZXI9fSBvcHRfaGVpZ2h0IENhbnZhcyBoZWlnaHQuXG4gKiBAcGFyYW0ge0FycmF5PEhUTUxDYW52YXNFbGVtZW50Pj19IG9wdF9jYW52YXNQb29sIENhbnZhcyBwb29sIHRvIHRha2UgZXhpc3RpbmcgY2FudmFzIGZyb20uXG4gKiBAcmV0dXJuIHtDYW52YXNSZW5kZXJpbmdDb250ZXh0MkR9IFRoZSBjb250ZXh0LlxuICovXG5cbmV4cG9ydCBmdW5jdGlvbiBjcmVhdGVDYW52YXNDb250ZXh0MkQob3B0X3dpZHRoLCBvcHRfaGVpZ2h0LCBvcHRfY2FudmFzUG9vbCkge1xuICB2YXIgY2FudmFzID0gb3B0X2NhbnZhc1Bvb2wgJiYgb3B0X2NhbnZhc1Bvb2wubGVuZ3RoID8gb3B0X2NhbnZhc1Bvb2wuc2hpZnQoKSA6IFdPUktFUl9PRkZTQ1JFRU5fQ0FOVkFTID8gbmV3IE9mZnNjcmVlbkNhbnZhcyhvcHRfd2lkdGggfHwgMzAwLCBvcHRfaGVpZ2h0IHx8IDMwMCkgOiBkb2N1bWVudC5jcmVhdGVFbGVtZW50KCdjYW52YXMnKTtcblxuICBpZiAob3B0X3dpZHRoKSB7XG4gICAgY2FudmFzLndpZHRoID0gb3B0X3dpZHRoO1xuICB9XG5cbiAgaWYgKG9wdF9oZWlnaHQpIHtcbiAgICBjYW52YXMuaGVpZ2h0ID0gb3B0X2hlaWdodDtcbiAgfSAvL0ZJWE1FIEFsbG93IE9mZnNjcmVlbkNhbnZhc1JlbmRlcmluZ0NvbnRleHQyRCBhcyByZXR1cm4gdHlwZVxuXG5cbiAgcmV0dXJuIChcbiAgICAvKiogQHR5cGUge0NhbnZhc1JlbmRlcmluZ0NvbnRleHQyRH0gKi9cbiAgICBjYW52YXMuZ2V0Q29udGV4dCgnMmQnKVxuICApO1xufVxuLyoqXG4gKiBHZXQgdGhlIGN1cnJlbnQgY29tcHV0ZWQgd2lkdGggZm9yIHRoZSBnaXZlbiBlbGVtZW50IGluY2x1ZGluZyBtYXJnaW4sXG4gKiBwYWRkaW5nIGFuZCBib3JkZXIuXG4gKiBFcXVpdmFsZW50IHRvIGpRdWVyeSdzIGAkKGVsKS5vdXRlcldpZHRoKHRydWUpYC5cbiAqIEBwYXJhbSB7IUhUTUxFbGVtZW50fSBlbGVtZW50IEVsZW1lbnQuXG4gKiBAcmV0dXJuIHtudW1iZXJ9IFRoZSB3aWR0aC5cbiAqL1xuXG5leHBvcnQgZnVuY3Rpb24gb3V0ZXJXaWR0aChlbGVtZW50KSB7XG4gIHZhciB3aWR0aCA9IGVsZW1lbnQub2Zmc2V0V2lkdGg7XG4gIHZhciBzdHlsZSA9IGdldENvbXB1dGVkU3R5bGUoZWxlbWVudCk7XG4gIHdpZHRoICs9IHBhcnNlSW50KHN0eWxlLm1hcmdpbkxlZnQsIDEwKSArIHBhcnNlSW50KHN0eWxlLm1hcmdpblJpZ2h0LCAxMCk7XG4gIHJldHVybiB3aWR0aDtcbn1cbi8qKlxuICogR2V0IHRoZSBjdXJyZW50IGNvbXB1dGVkIGhlaWdodCBmb3IgdGhlIGdpdmVuIGVsZW1lbnQgaW5jbHVkaW5nIG1hcmdpbixcbiAqIHBhZGRpbmcgYW5kIGJvcmRlci5cbiAqIEVxdWl2YWxlbnQgdG8galF1ZXJ5J3MgYCQoZWwpLm91dGVySGVpZ2h0KHRydWUpYC5cbiAqIEBwYXJhbSB7IUhUTUxFbGVtZW50fSBlbGVtZW50IEVsZW1lbnQuXG4gKiBAcmV0dXJuIHtudW1iZXJ9IFRoZSBoZWlnaHQuXG4gKi9cblxuZXhwb3J0IGZ1bmN0aW9uIG91dGVySGVpZ2h0KGVsZW1lbnQpIHtcbiAgdmFyIGhlaWdodCA9IGVsZW1lbnQub2Zmc2V0SGVpZ2h0O1xuICB2YXIgc3R5bGUgPSBnZXRDb21wdXRlZFN0eWxlKGVsZW1lbnQpO1xuICBoZWlnaHQgKz0gcGFyc2VJbnQoc3R5bGUubWFyZ2luVG9wLCAxMCkgKyBwYXJzZUludChzdHlsZS5tYXJnaW5Cb3R0b20sIDEwKTtcbiAgcmV0dXJuIGhlaWdodDtcbn1cbi8qKlxuICogQHBhcmFtIHtOb2RlfSBuZXdOb2RlIE5vZGUgdG8gcmVwbGFjZSBvbGQgbm9kZVxuICogQHBhcmFtIHtOb2RlfSBvbGROb2RlIFRoZSBub2RlIHRvIGJlIHJlcGxhY2VkXG4gKi9cblxuZXhwb3J0IGZ1bmN0aW9uIHJlcGxhY2VOb2RlKG5ld05vZGUsIG9sZE5vZGUpIHtcbiAgdmFyIHBhcmVudCA9IG9sZE5vZGUucGFyZW50Tm9kZTtcblxuICBpZiAocGFyZW50KSB7XG4gICAgcGFyZW50LnJlcGxhY2VDaGlsZChuZXdOb2RlLCBvbGROb2RlKTtcbiAgfVxufVxuLyoqXG4gKiBAcGFyYW0ge05vZGV9IG5vZGUgVGhlIG5vZGUgdG8gcmVtb3ZlLlxuICogQHJldHVybnMge05vZGV9IFRoZSBub2RlIHRoYXQgd2FzIHJlbW92ZWQgb3IgbnVsbC5cbiAqL1xuXG5leHBvcnQgZnVuY3Rpb24gcmVtb3ZlTm9kZShub2RlKSB7XG4gIHJldHVybiBub2RlICYmIG5vZGUucGFyZW50Tm9kZSA/IG5vZGUucGFyZW50Tm9kZS5yZW1vdmVDaGlsZChub2RlKSA6IG51bGw7XG59XG4vKipcbiAqIEBwYXJhbSB7Tm9kZX0gbm9kZSBUaGUgbm9kZSB0byByZW1vdmUgdGhlIGNoaWxkcmVuIGZyb20uXG4gKi9cblxuZXhwb3J0IGZ1bmN0aW9uIHJlbW92ZUNoaWxkcmVuKG5vZGUpIHtcbiAgd2hpbGUgKG5vZGUubGFzdENoaWxkKSB7XG4gICAgbm9kZS5yZW1vdmVDaGlsZChub2RlLmxhc3RDaGlsZCk7XG4gIH1cbn1cbi8qKlxuICogVHJhbnNmb3JtIHRoZSBjaGlsZHJlbiBvZiBhIHBhcmVudCBub2RlIHNvIHRoZXkgbWF0Y2ggdGhlXG4gKiBwcm92aWRlZCBsaXN0IG9mIGNoaWxkcmVuLiAgVGhpcyBmdW5jdGlvbiBhaW1zIHRvIGVmZmljaWVudGx5XG4gKiByZW1vdmUsIGFkZCwgYW5kIHJlb3JkZXIgY2hpbGQgbm9kZXMgd2hpbGUgbWFpbnRhaW5pbmcgYSBzaW1wbGVcbiAqIGltcGxlbWVudGF0aW9uIChpdCBpcyBub3QgZ3VhcmFudGVlZCB0byBtaW5pbWl6ZSBET00gb3BlcmF0aW9ucykuXG4gKiBAcGFyYW0ge05vZGV9IG5vZGUgVGhlIHBhcmVudCBub2RlIHdob3NlIGNoaWxkcmVuIG5lZWQgcmV3b3JraW5nLlxuICogQHBhcmFtIHtBcnJheTxOb2RlPn0gY2hpbGRyZW4gVGhlIGRlc2lyZWQgY2hpbGRyZW4uXG4gKi9cblxuZXhwb3J0IGZ1bmN0aW9uIHJlcGxhY2VDaGlsZHJlbihub2RlLCBjaGlsZHJlbikge1xuICB2YXIgb2xkQ2hpbGRyZW4gPSBub2RlLmNoaWxkTm9kZXM7XG5cbiAgZm9yICh2YXIgaSA9IDA7IHRydWU7ICsraSkge1xuICAgIHZhciBvbGRDaGlsZCA9IG9sZENoaWxkcmVuW2ldO1xuICAgIHZhciBuZXdDaGlsZCA9IGNoaWxkcmVuW2ldOyAvLyBjaGVjayBpZiBvdXIgd29yayBpcyBkb25lXG5cbiAgICBpZiAoIW9sZENoaWxkICYmICFuZXdDaGlsZCkge1xuICAgICAgYnJlYWs7XG4gICAgfSAvLyBjaGVjayBpZiBjaGlsZHJlbiBtYXRjaFxuXG5cbiAgICBpZiAob2xkQ2hpbGQgPT09IG5ld0NoaWxkKSB7XG4gICAgICBjb250aW51ZTtcbiAgICB9IC8vIGNoZWNrIGlmIGEgbmV3IGNoaWxkIG5lZWRzIHRvIGJlIGFkZGVkXG5cblxuICAgIGlmICghb2xkQ2hpbGQpIHtcbiAgICAgIG5vZGUuYXBwZW5kQ2hpbGQobmV3Q2hpbGQpO1xuICAgICAgY29udGludWU7XG4gICAgfSAvLyBjaGVjayBpZiBhbiBvbGQgY2hpbGQgbmVlZHMgdG8gYmUgcmVtb3ZlZFxuXG5cbiAgICBpZiAoIW5ld0NoaWxkKSB7XG4gICAgICBub2RlLnJlbW92ZUNoaWxkKG9sZENoaWxkKTtcbiAgICAgIC0taTtcbiAgICAgIGNvbnRpbnVlO1xuICAgIH0gLy8gcmVvcmRlclxuXG5cbiAgICBub2RlLmluc2VydEJlZm9yZShuZXdDaGlsZCwgb2xkQ2hpbGQpO1xuICB9XG59IiwiLyoqXG4gKiBAbW9kdWxlIG9sL3JlbmRlci9jYW52YXNcbiAqL1xuaW1wb3J0IEJhc2VPYmplY3QgZnJvbSAnLi4vT2JqZWN0LmpzJztcbmltcG9ydCBFdmVudFRhcmdldCBmcm9tICcuLi9ldmVudHMvVGFyZ2V0LmpzJztcbmltcG9ydCB7IFdPUktFUl9PRkZTQ1JFRU5fQ0FOVkFTIH0gZnJvbSAnLi4vaGFzLmpzJztcbmltcG9ydCB7IGNsZWFyIH0gZnJvbSAnLi4vb2JqLmpzJztcbmltcG9ydCB7IGNyZWF0ZUNhbnZhc0NvbnRleHQyRCB9IGZyb20gJy4uL2RvbS5qcyc7XG5pbXBvcnQgeyBnZXRGb250UGFyYW1ldGVycyB9IGZyb20gJy4uL2Nzcy5qcyc7XG5pbXBvcnQgeyB0b1N0cmluZyB9IGZyb20gJy4uL3RyYW5zZm9ybS5qcyc7XG4vKipcbiAqIEB0eXBlZGVmIHtPYmplY3R9IEZpbGxTdGF0ZVxuICogQHByb3BlcnR5IHtpbXBvcnQoXCIuLi9jb2xvcmxpa2UuanNcIikuQ29sb3JMaWtlfSBmaWxsU3R5bGVcbiAqL1xuXG4vKipcbiAqIEB0eXBlZGVmIExhYmVsXG4gKiBAcHJvcGVydHkge251bWJlcn0gd2lkdGhcbiAqIEBwcm9wZXJ0eSB7bnVtYmVyfSBoZWlnaHRcbiAqIEBwcm9wZXJ0eSB7QXJyYXk8c3RyaW5nfG51bWJlcj59IGNvbnRleHRJbnN0cnVjdGlvbnNcbiAqL1xuXG4vKipcbiAqIEB0eXBlZGVmIHtPYmplY3R9IEZpbGxTdHJva2VTdGF0ZVxuICogQHByb3BlcnR5IHtpbXBvcnQoXCIuLi9jb2xvcmxpa2UuanNcIikuQ29sb3JMaWtlfSBbY3VycmVudEZpbGxTdHlsZV1cbiAqIEBwcm9wZXJ0eSB7aW1wb3J0KFwiLi4vY29sb3JsaWtlLmpzXCIpLkNvbG9yTGlrZX0gW2N1cnJlbnRTdHJva2VTdHlsZV1cbiAqIEBwcm9wZXJ0eSB7Q2FudmFzTGluZUNhcH0gW2N1cnJlbnRMaW5lQ2FwXVxuICogQHByb3BlcnR5IHtBcnJheTxudW1iZXI+fSBjdXJyZW50TGluZURhc2hcbiAqIEBwcm9wZXJ0eSB7bnVtYmVyfSBbY3VycmVudExpbmVEYXNoT2Zmc2V0XVxuICogQHByb3BlcnR5IHtDYW52YXNMaW5lSm9pbn0gW2N1cnJlbnRMaW5lSm9pbl1cbiAqIEBwcm9wZXJ0eSB7bnVtYmVyfSBbY3VycmVudExpbmVXaWR0aF1cbiAqIEBwcm9wZXJ0eSB7bnVtYmVyfSBbY3VycmVudE1pdGVyTGltaXRdXG4gKiBAcHJvcGVydHkge251bWJlcn0gW2xhc3RTdHJva2VdXG4gKiBAcHJvcGVydHkge2ltcG9ydChcIi4uL2NvbG9ybGlrZS5qc1wiKS5Db2xvckxpa2V9IFtmaWxsU3R5bGVdXG4gKiBAcHJvcGVydHkge2ltcG9ydChcIi4uL2NvbG9ybGlrZS5qc1wiKS5Db2xvckxpa2V9IFtzdHJva2VTdHlsZV1cbiAqIEBwcm9wZXJ0eSB7Q2FudmFzTGluZUNhcH0gW2xpbmVDYXBdXG4gKiBAcHJvcGVydHkge0FycmF5PG51bWJlcj59IGxpbmVEYXNoXG4gKiBAcHJvcGVydHkge251bWJlcn0gW2xpbmVEYXNoT2Zmc2V0XVxuICogQHByb3BlcnR5IHtDYW52YXNMaW5lSm9pbn0gW2xpbmVKb2luXVxuICogQHByb3BlcnR5IHtudW1iZXJ9IFtsaW5lV2lkdGhdXG4gKiBAcHJvcGVydHkge251bWJlcn0gW21pdGVyTGltaXRdXG4gKi9cblxuLyoqXG4gKiBAdHlwZWRlZiB7T2JqZWN0fSBTdHJva2VTdGF0ZVxuICogQHByb3BlcnR5IHtDYW52YXNMaW5lQ2FwfSBsaW5lQ2FwXG4gKiBAcHJvcGVydHkge0FycmF5PG51bWJlcj59IGxpbmVEYXNoXG4gKiBAcHJvcGVydHkge251bWJlcn0gbGluZURhc2hPZmZzZXRcbiAqIEBwcm9wZXJ0eSB7Q2FudmFzTGluZUpvaW59IGxpbmVKb2luXG4gKiBAcHJvcGVydHkge251bWJlcn0gbGluZVdpZHRoXG4gKiBAcHJvcGVydHkge251bWJlcn0gbWl0ZXJMaW1pdFxuICogQHByb3BlcnR5IHtpbXBvcnQoXCIuLi9jb2xvcmxpa2UuanNcIikuQ29sb3JMaWtlfSBzdHJva2VTdHlsZVxuICovXG5cbi8qKlxuICogQHR5cGVkZWYge09iamVjdH0gVGV4dFN0YXRlXG4gKiBAcHJvcGVydHkge3N0cmluZ30gZm9udFxuICogQHByb3BlcnR5IHtzdHJpbmd9IFt0ZXh0QWxpZ25dXG4gKiBAcHJvcGVydHkge3N0cmluZ30gdGV4dEJhc2VsaW5lXG4gKiBAcHJvcGVydHkge3N0cmluZ30gW3BsYWNlbWVudF1cbiAqIEBwcm9wZXJ0eSB7bnVtYmVyfSBbbWF4QW5nbGVdXG4gKiBAcHJvcGVydHkge2Jvb2xlYW59IFtvdmVyZmxvd11cbiAqIEBwcm9wZXJ0eSB7aW1wb3J0KFwiLi4vc3R5bGUvRmlsbC5qc1wiKS5kZWZhdWx0fSBbYmFja2dyb3VuZEZpbGxdXG4gKiBAcHJvcGVydHkge2ltcG9ydChcIi4uL3N0eWxlL1N0cm9rZS5qc1wiKS5kZWZhdWx0fSBbYmFja2dyb3VuZFN0cm9rZV1cbiAqIEBwcm9wZXJ0eSB7aW1wb3J0KFwiLi4vc2l6ZS5qc1wiKS5TaXplfSBbc2NhbGVdXG4gKiBAcHJvcGVydHkge0FycmF5PG51bWJlcj59IFtwYWRkaW5nXVxuICovXG5cbi8qKlxuICogQHR5cGVkZWYge09iamVjdH0gU2VyaWFsaXphYmxlSW5zdHJ1Y3Rpb25zXG4gKiBAcHJvcGVydHkge0FycmF5PCo+fSBpbnN0cnVjdGlvbnMgVGhlIHJlbmRlcmluZyBpbnN0cnVjdGlvbnMuXG4gKiBAcHJvcGVydHkge0FycmF5PCo+fSBoaXREZXRlY3Rpb25JbnN0cnVjdGlvbnMgVGhlIHJlbmRlcmluZyBoaXQgZGV0ZWN0aW9uIGluc3RydWN0aW9ucy5cbiAqIEBwcm9wZXJ0eSB7QXJyYXk8bnVtYmVyPn0gY29vcmRpbmF0ZXMgVGhlIGFycmF5IG9mIGFsbCBjb29yZGluYXRlcy5cbiAqIEBwcm9wZXJ0eSB7IU9iamVjdDxzdHJpbmcsIFRleHRTdGF0ZT59IFt0ZXh0U3RhdGVzXSBUaGUgdGV4dCBzdGF0ZXMgKGRlY2x1dHRlcmluZykuXG4gKiBAcHJvcGVydHkgeyFPYmplY3Q8c3RyaW5nLCBGaWxsU3RhdGU+fSBbZmlsbFN0YXRlc10gVGhlIGZpbGwgc3RhdGVzIChkZWNsdXR0ZXJpbmcpLlxuICogQHByb3BlcnR5IHshT2JqZWN0PHN0cmluZywgU3Ryb2tlU3RhdGU+fSBbc3Ryb2tlU3RhdGVzXSBUaGUgc3Ryb2tlIHN0YXRlcyAoZGVjbHV0dGVyaW5nKS5cbiAqL1xuXG4vKipcbiAqIEB0eXBlZGVmIHtPYmplY3Q8bnVtYmVyLCBpbXBvcnQoXCIuL2NhbnZhcy9FeGVjdXRvci5qc1wiKS5SZXBsYXlJbWFnZU9yTGFiZWxBcmdzPn0gRGVjbHV0dGVySW1hZ2VXaXRoVGV4dFxuICovXG5cbi8qKlxuICogQGNvbnN0XG4gKiBAdHlwZSB7c3RyaW5nfVxuICovXG5cbmV4cG9ydCB2YXIgZGVmYXVsdEZvbnQgPSAnMTBweCBzYW5zLXNlcmlmJztcbi8qKlxuICogQGNvbnN0XG4gKiBAdHlwZSB7aW1wb3J0KFwiLi4vY29sb3JsaWtlLmpzXCIpLkNvbG9yTGlrZX1cbiAqL1xuXG5leHBvcnQgdmFyIGRlZmF1bHRGaWxsU3R5bGUgPSAnIzAwMCc7XG4vKipcbiAqIEBjb25zdFxuICogQHR5cGUge0NhbnZhc0xpbmVDYXB9XG4gKi9cblxuZXhwb3J0IHZhciBkZWZhdWx0TGluZUNhcCA9ICdyb3VuZCc7XG4vKipcbiAqIEBjb25zdFxuICogQHR5cGUge0FycmF5PG51bWJlcj59XG4gKi9cblxuZXhwb3J0IHZhciBkZWZhdWx0TGluZURhc2ggPSBbXTtcbi8qKlxuICogQGNvbnN0XG4gKiBAdHlwZSB7bnVtYmVyfVxuICovXG5cbmV4cG9ydCB2YXIgZGVmYXVsdExpbmVEYXNoT2Zmc2V0ID0gMDtcbi8qKlxuICogQGNvbnN0XG4gKiBAdHlwZSB7Q2FudmFzTGluZUpvaW59XG4gKi9cblxuZXhwb3J0IHZhciBkZWZhdWx0TGluZUpvaW4gPSAncm91bmQnO1xuLyoqXG4gKiBAY29uc3RcbiAqIEB0eXBlIHtudW1iZXJ9XG4gKi9cblxuZXhwb3J0IHZhciBkZWZhdWx0TWl0ZXJMaW1pdCA9IDEwO1xuLyoqXG4gKiBAY29uc3RcbiAqIEB0eXBlIHtpbXBvcnQoXCIuLi9jb2xvcmxpa2UuanNcIikuQ29sb3JMaWtlfVxuICovXG5cbmV4cG9ydCB2YXIgZGVmYXVsdFN0cm9rZVN0eWxlID0gJyMwMDAnO1xuLyoqXG4gKiBAY29uc3RcbiAqIEB0eXBlIHtzdHJpbmd9XG4gKi9cblxuZXhwb3J0IHZhciBkZWZhdWx0VGV4dEFsaWduID0gJ2NlbnRlcic7XG4vKipcbiAqIEBjb25zdFxuICogQHR5cGUge3N0cmluZ31cbiAqL1xuXG5leHBvcnQgdmFyIGRlZmF1bHRUZXh0QmFzZWxpbmUgPSAnbWlkZGxlJztcbi8qKlxuICogQGNvbnN0XG4gKiBAdHlwZSB7QXJyYXk8bnVtYmVyPn1cbiAqL1xuXG5leHBvcnQgdmFyIGRlZmF1bHRQYWRkaW5nID0gWzAsIDAsIDAsIDBdO1xuLyoqXG4gKiBAY29uc3RcbiAqIEB0eXBlIHtudW1iZXJ9XG4gKi9cblxuZXhwb3J0IHZhciBkZWZhdWx0TGluZVdpZHRoID0gMTtcbi8qKlxuICogQHR5cGUge0Jhc2VPYmplY3R9XG4gKi9cblxuZXhwb3J0IHZhciBjaGVja2VkRm9udHMgPSBuZXcgQmFzZU9iamVjdCgpO1xuLyoqXG4gKiBUaGUgbGFiZWwgY2FjaGUgZm9yIHRleHQgcmVuZGVyaW5nLiBUbyBjaGFuZ2UgdGhlIGRlZmF1bHQgY2FjaGUgc2l6ZSBvZiAyMDQ4XG4gKiBlbnRyaWVzLCB1c2Uge0BsaW5rIG1vZHVsZTpvbC9zdHJ1Y3RzL0xSVUNhY2hlI3NldFNpemV9LlxuICogRGVwcmVjYXRlZCAtIHRoZXJlIGlzIG5vIGxhYmVsIGNhY2hlIGFueSBtb3JlLlxuICogQHR5cGUgez99XG4gKiBAYXBpXG4gKiBAZGVwcmVjYXRlZFxuICovXG5cbmV4cG9ydCB2YXIgbGFiZWxDYWNoZSA9IG5ldyBFdmVudFRhcmdldCgpO1xuXG5sYWJlbENhY2hlLnNldFNpemUgPSBmdW5jdGlvbiAoKSB7XG4gIGNvbnNvbGUud2FybignbGFiZWxDYWNoZSBpcyBkZXByZWNhdGVkLicpOyAvL2VzbGludC1kaXNhYmxlLWxpbmVcbn07XG4vKipcbiAqIEB0eXBlIHtDYW52YXNSZW5kZXJpbmdDb250ZXh0MkR9XG4gKi9cblxuXG52YXIgbWVhc3VyZUNvbnRleHQgPSBudWxsO1xuLyoqXG4gKiBAdHlwZSB7c3RyaW5nfVxuICovXG5cbnZhciBtZWFzdXJlRm9udDtcbi8qKlxuICogQHR5cGUgeyFPYmplY3Q8c3RyaW5nLCBudW1iZXI+fVxuICovXG5cbmV4cG9ydCB2YXIgdGV4dEhlaWdodHMgPSB7fTtcbi8qKlxuICogQ2xlYXJzIHRoZSBsYWJlbCBjYWNoZSB3aGVuIGEgZm9udCBiZWNvbWVzIGF2YWlsYWJsZS5cbiAqIEBwYXJhbSB7c3RyaW5nfSBmb250U3BlYyBDU1MgZm9udCBzcGVjLlxuICovXG5cbmV4cG9ydCB2YXIgcmVnaXN0ZXJGb250ID0gZnVuY3Rpb24gKCkge1xuICB2YXIgcmV0cmllcyA9IDEwMDtcbiAgdmFyIHNpemUgPSAnMzJweCAnO1xuICB2YXIgcmVmZXJlbmNlRm9udHMgPSBbJ21vbm9zcGFjZScsICdzZXJpZiddO1xuICB2YXIgbGVuID0gcmVmZXJlbmNlRm9udHMubGVuZ3RoO1xuICB2YXIgdGV4dCA9IFwid215dHppbFdNWVRaSUxAIy8mPyQlMTBcXHVGMDEzXCI7XG4gIHZhciBpbnRlcnZhbCwgcmVmZXJlbmNlV2lkdGg7XG4gIC8qKlxuICAgKiBAcGFyYW0ge3N0cmluZ30gZm9udFN0eWxlIENzcyBmb250LXN0eWxlXG4gICAqIEBwYXJhbSB7c3RyaW5nfSBmb250V2VpZ2h0IENzcyBmb250LXdlaWdodFxuICAgKiBAcGFyYW0geyp9IGZvbnRGYW1pbHkgQ3NzIGZvbnQtZmFtaWx5XG4gICAqIEByZXR1cm4ge2Jvb2xlYW59IEZvbnQgd2l0aCBzdHlsZSBhbmQgd2VpZ2h0IGlzIGF2YWlsYWJsZVxuICAgKi9cblxuICBmdW5jdGlvbiBpc0F2YWlsYWJsZShmb250U3R5bGUsIGZvbnRXZWlnaHQsIGZvbnRGYW1pbHkpIHtcbiAgICB2YXIgYXZhaWxhYmxlID0gdHJ1ZTtcblxuICAgIGZvciAodmFyIGkgPSAwOyBpIDwgbGVuOyArK2kpIHtcbiAgICAgIHZhciByZWZlcmVuY2VGb250ID0gcmVmZXJlbmNlRm9udHNbaV07XG4gICAgICByZWZlcmVuY2VXaWR0aCA9IG1lYXN1cmVUZXh0V2lkdGgoZm9udFN0eWxlICsgJyAnICsgZm9udFdlaWdodCArICcgJyArIHNpemUgKyByZWZlcmVuY2VGb250LCB0ZXh0KTtcblxuICAgICAgaWYgKGZvbnRGYW1pbHkgIT0gcmVmZXJlbmNlRm9udCkge1xuICAgICAgICB2YXIgd2lkdGggPSBtZWFzdXJlVGV4dFdpZHRoKGZvbnRTdHlsZSArICcgJyArIGZvbnRXZWlnaHQgKyAnICcgKyBzaXplICsgZm9udEZhbWlseSArICcsJyArIHJlZmVyZW5jZUZvbnQsIHRleHQpOyAvLyBJZiB3aWR0aCBhbmQgcmVmZXJlbmNlV2lkdGggYXJlIHRoZSBzYW1lLCB0aGVuIHRoZSBmYWxsYmFjayB3YXMgdXNlZFxuICAgICAgICAvLyBpbnN0ZWFkIG9mIHRoZSBmb250IHdlIHdhbnRlZCwgc28gdGhlIGZvbnQgaXMgbm90IGF2YWlsYWJsZS5cblxuICAgICAgICBhdmFpbGFibGUgPSBhdmFpbGFibGUgJiYgd2lkdGggIT0gcmVmZXJlbmNlV2lkdGg7XG4gICAgICB9XG4gICAgfVxuXG4gICAgaWYgKGF2YWlsYWJsZSkge1xuICAgICAgcmV0dXJuIHRydWU7XG4gICAgfVxuXG4gICAgcmV0dXJuIGZhbHNlO1xuICB9XG5cbiAgZnVuY3Rpb24gY2hlY2soKSB7XG4gICAgdmFyIGRvbmUgPSB0cnVlO1xuICAgIHZhciBmb250cyA9IGNoZWNrZWRGb250cy5nZXRLZXlzKCk7XG5cbiAgICBmb3IgKHZhciBpID0gMCwgaWkgPSBmb250cy5sZW5ndGg7IGkgPCBpaTsgKytpKSB7XG4gICAgICB2YXIgZm9udCA9IGZvbnRzW2ldO1xuXG4gICAgICBpZiAoY2hlY2tlZEZvbnRzLmdldChmb250KSA8IHJldHJpZXMpIHtcbiAgICAgICAgaWYgKGlzQXZhaWxhYmxlLmFwcGx5KHRoaXMsIGZvbnQuc3BsaXQoJ1xcbicpKSkge1xuICAgICAgICAgIGNsZWFyKHRleHRIZWlnaHRzKTsgLy8gTWFrZSBzdXJlIHRoYXQgbG9hZGVkIGZvbnRzIGFyZSBwaWNrZWQgdXAgYnkgU2FmYXJpXG5cbiAgICAgICAgICBtZWFzdXJlQ29udGV4dCA9IG51bGw7XG4gICAgICAgICAgbWVhc3VyZUZvbnQgPSB1bmRlZmluZWQ7XG4gICAgICAgICAgY2hlY2tlZEZvbnRzLnNldChmb250LCByZXRyaWVzKTtcbiAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICBjaGVja2VkRm9udHMuc2V0KGZvbnQsIGNoZWNrZWRGb250cy5nZXQoZm9udCkgKyAxLCB0cnVlKTtcbiAgICAgICAgICBkb25lID0gZmFsc2U7XG4gICAgICAgIH1cbiAgICAgIH1cbiAgICB9XG5cbiAgICBpZiAoZG9uZSkge1xuICAgICAgY2xlYXJJbnRlcnZhbChpbnRlcnZhbCk7XG4gICAgICBpbnRlcnZhbCA9IHVuZGVmaW5lZDtcbiAgICB9XG4gIH1cblxuICByZXR1cm4gZnVuY3Rpb24gKGZvbnRTcGVjKSB7XG4gICAgdmFyIGZvbnQgPSBnZXRGb250UGFyYW1ldGVycyhmb250U3BlYyk7XG5cbiAgICBpZiAoIWZvbnQpIHtcbiAgICAgIHJldHVybjtcbiAgICB9XG5cbiAgICB2YXIgZmFtaWxpZXMgPSBmb250LmZhbWlsaWVzO1xuXG4gICAgZm9yICh2YXIgaSA9IDAsIGlpID0gZmFtaWxpZXMubGVuZ3RoOyBpIDwgaWk7ICsraSkge1xuICAgICAgdmFyIGZhbWlseSA9IGZhbWlsaWVzW2ldO1xuICAgICAgdmFyIGtleSA9IGZvbnQuc3R5bGUgKyAnXFxuJyArIGZvbnQud2VpZ2h0ICsgJ1xcbicgKyBmYW1pbHk7XG5cbiAgICAgIGlmIChjaGVja2VkRm9udHMuZ2V0KGtleSkgPT09IHVuZGVmaW5lZCkge1xuICAgICAgICBjaGVja2VkRm9udHMuc2V0KGtleSwgcmV0cmllcywgdHJ1ZSk7XG5cbiAgICAgICAgaWYgKCFpc0F2YWlsYWJsZShmb250LnN0eWxlLCBmb250LndlaWdodCwgZmFtaWx5KSkge1xuICAgICAgICAgIGNoZWNrZWRGb250cy5zZXQoa2V5LCAwLCB0cnVlKTtcblxuICAgICAgICAgIGlmIChpbnRlcnZhbCA9PT0gdW5kZWZpbmVkKSB7XG4gICAgICAgICAgICBpbnRlcnZhbCA9IHNldEludGVydmFsKGNoZWNrLCAzMik7XG4gICAgICAgICAgfVxuICAgICAgICB9XG4gICAgICB9XG4gICAgfVxuICB9O1xufSgpO1xuLyoqXG4gKiBAcGFyYW0ge3N0cmluZ30gZm9udCBGb250IHRvIHVzZSBmb3IgbWVhc3VyaW5nLlxuICogQHJldHVybiB7aW1wb3J0KFwiLi4vc2l6ZS5qc1wiKS5TaXplfSBNZWFzdXJlbWVudC5cbiAqL1xuXG5leHBvcnQgdmFyIG1lYXN1cmVUZXh0SGVpZ2h0ID0gZnVuY3Rpb24gKCkge1xuICAvKipcbiAgICogQHR5cGUge0hUTUxEaXZFbGVtZW50fVxuICAgKi9cbiAgdmFyIGRpdjtcbiAgcmV0dXJuIGZ1bmN0aW9uIChmb250U3BlYykge1xuICAgIHZhciBoZWlnaHQgPSB0ZXh0SGVpZ2h0c1tmb250U3BlY107XG5cbiAgICBpZiAoaGVpZ2h0ID09IHVuZGVmaW5lZCkge1xuICAgICAgaWYgKFdPUktFUl9PRkZTQ1JFRU5fQ0FOVkFTKSB7XG4gICAgICAgIHZhciBmb250ID0gZ2V0Rm9udFBhcmFtZXRlcnMoZm9udFNwZWMpO1xuICAgICAgICB2YXIgbWV0cmljcyA9IG1lYXN1cmVUZXh0KGZvbnRTcGVjLCAnxb1nJyk7XG4gICAgICAgIHZhciBsaW5lSGVpZ2h0ID0gaXNOYU4oTnVtYmVyKGZvbnQubGluZUhlaWdodCkpID8gMS4yIDogTnVtYmVyKGZvbnQubGluZUhlaWdodCk7XG4gICAgICAgIGhlaWdodCA9IGxpbmVIZWlnaHQgKiAobWV0cmljcy5hY3R1YWxCb3VuZGluZ0JveEFzY2VudCArIG1ldHJpY3MuYWN0dWFsQm91bmRpbmdCb3hEZXNjZW50KTtcbiAgICAgIH0gZWxzZSB7XG4gICAgICAgIGlmICghZGl2KSB7XG4gICAgICAgICAgZGl2ID0gZG9jdW1lbnQuY3JlYXRlRWxlbWVudCgnZGl2Jyk7XG4gICAgICAgICAgZGl2LmlubmVySFRNTCA9ICdNJztcbiAgICAgICAgICBkaXYuc3R5bGUubWFyZ2luID0gJzAgIWltcG9ydGFudCc7XG4gICAgICAgICAgZGl2LnN0eWxlLnBhZGRpbmcgPSAnMCAhaW1wb3J0YW50JztcbiAgICAgICAgICBkaXYuc3R5bGUucG9zaXRpb24gPSAnYWJzb2x1dGUgIWltcG9ydGFudCc7XG4gICAgICAgICAgZGl2LnN0eWxlLmxlZnQgPSAnLTk5OTk5cHggIWltcG9ydGFudCc7XG4gICAgICAgIH1cblxuICAgICAgICBkaXYuc3R5bGUuZm9udCA9IGZvbnRTcGVjO1xuICAgICAgICBkb2N1bWVudC5ib2R5LmFwcGVuZENoaWxkKGRpdik7XG4gICAgICAgIGhlaWdodCA9IGRpdi5vZmZzZXRIZWlnaHQ7XG4gICAgICAgIGRvY3VtZW50LmJvZHkucmVtb3ZlQ2hpbGQoZGl2KTtcbiAgICAgIH1cblxuICAgICAgdGV4dEhlaWdodHNbZm9udFNwZWNdID0gaGVpZ2h0O1xuICAgIH1cblxuICAgIHJldHVybiBoZWlnaHQ7XG4gIH07XG59KCk7XG4vKipcbiAqIEBwYXJhbSB7c3RyaW5nfSBmb250IEZvbnQuXG4gKiBAcGFyYW0ge3N0cmluZ30gdGV4dCBUZXh0LlxuICogQHJldHVybiB7VGV4dE1ldHJpY3N9IFRleHQgbWV0cmljcy5cbiAqL1xuXG5mdW5jdGlvbiBtZWFzdXJlVGV4dChmb250LCB0ZXh0KSB7XG4gIGlmICghbWVhc3VyZUNvbnRleHQpIHtcbiAgICBtZWFzdXJlQ29udGV4dCA9IGNyZWF0ZUNhbnZhc0NvbnRleHQyRCgxLCAxKTtcbiAgfVxuXG4gIGlmIChmb250ICE9IG1lYXN1cmVGb250KSB7XG4gICAgbWVhc3VyZUNvbnRleHQuZm9udCA9IGZvbnQ7XG4gICAgbWVhc3VyZUZvbnQgPSBtZWFzdXJlQ29udGV4dC5mb250O1xuICB9XG5cbiAgcmV0dXJuIG1lYXN1cmVDb250ZXh0Lm1lYXN1cmVUZXh0KHRleHQpO1xufVxuLyoqXG4gKiBAcGFyYW0ge3N0cmluZ30gZm9udCBGb250LlxuICogQHBhcmFtIHtzdHJpbmd9IHRleHQgVGV4dC5cbiAqIEByZXR1cm4ge251bWJlcn0gV2lkdGguXG4gKi9cblxuXG5leHBvcnQgZnVuY3Rpb24gbWVhc3VyZVRleHRXaWR0aChmb250LCB0ZXh0KSB7XG4gIHJldHVybiBtZWFzdXJlVGV4dChmb250LCB0ZXh0KS53aWR0aDtcbn1cbi8qKlxuICogTWVhc3VyZSB0ZXh0IHdpZHRoIHVzaW5nIGEgY2FjaGUuXG4gKiBAcGFyYW0ge3N0cmluZ30gZm9udCBUaGUgZm9udC5cbiAqIEBwYXJhbSB7c3RyaW5nfSB0ZXh0IFRoZSB0ZXh0IHRvIG1lYXN1cmUuXG4gKiBAcGFyYW0ge09iamVjdDxzdHJpbmcsIG51bWJlcj59IGNhY2hlIEEgbG9va3VwIG9mIGNhY2hlZCB3aWR0aHMgYnkgdGV4dC5cbiAqIEByZXR1cm5zIHtudW1iZXJ9IFRoZSB0ZXh0IHdpZHRoLlxuICovXG5cbmV4cG9ydCBmdW5jdGlvbiBtZWFzdXJlQW5kQ2FjaGVUZXh0V2lkdGgoZm9udCwgdGV4dCwgY2FjaGUpIHtcbiAgaWYgKHRleHQgaW4gY2FjaGUpIHtcbiAgICByZXR1cm4gY2FjaGVbdGV4dF07XG4gIH1cblxuICB2YXIgd2lkdGggPSBtZWFzdXJlVGV4dFdpZHRoKGZvbnQsIHRleHQpO1xuICBjYWNoZVt0ZXh0XSA9IHdpZHRoO1xuICByZXR1cm4gd2lkdGg7XG59XG4vKipcbiAqIEBwYXJhbSB7c3RyaW5nfSBmb250IEZvbnQgdG8gdXNlIGZvciBtZWFzdXJpbmcuXG4gKiBAcGFyYW0ge0FycmF5PHN0cmluZz59IGxpbmVzIExpbmVzIHRvIG1lYXN1cmUuXG4gKiBAcGFyYW0ge0FycmF5PG51bWJlcj59IHdpZHRocyBBcnJheSB3aWxsIGJlIHBvcHVsYXRlZCB3aXRoIHRoZSB3aWR0aHMgb2ZcbiAqIGVhY2ggbGluZS5cbiAqIEByZXR1cm4ge251bWJlcn0gV2lkdGggb2YgdGhlIHdob2xlIHRleHQuXG4gKi9cblxuZXhwb3J0IGZ1bmN0aW9uIG1lYXN1cmVUZXh0V2lkdGhzKGZvbnQsIGxpbmVzLCB3aWR0aHMpIHtcbiAgdmFyIG51bUxpbmVzID0gbGluZXMubGVuZ3RoO1xuICB2YXIgd2lkdGggPSAwO1xuXG4gIGZvciAodmFyIGkgPSAwOyBpIDwgbnVtTGluZXM7ICsraSkge1xuICAgIHZhciBjdXJyZW50V2lkdGggPSBtZWFzdXJlVGV4dFdpZHRoKGZvbnQsIGxpbmVzW2ldKTtcbiAgICB3aWR0aCA9IE1hdGgubWF4KHdpZHRoLCBjdXJyZW50V2lkdGgpO1xuICAgIHdpZHRocy5wdXNoKGN1cnJlbnRXaWR0aCk7XG4gIH1cblxuICByZXR1cm4gd2lkdGg7XG59XG4vKipcbiAqIEBwYXJhbSB7Q2FudmFzUmVuZGVyaW5nQ29udGV4dDJEfSBjb250ZXh0IENvbnRleHQuXG4gKiBAcGFyYW0ge251bWJlcn0gcm90YXRpb24gUm90YXRpb24uXG4gKiBAcGFyYW0ge251bWJlcn0gb2Zmc2V0WCBYIG9mZnNldC5cbiAqIEBwYXJhbSB7bnVtYmVyfSBvZmZzZXRZIFkgb2Zmc2V0LlxuICovXG5cbmV4cG9ydCBmdW5jdGlvbiByb3RhdGVBdE9mZnNldChjb250ZXh0LCByb3RhdGlvbiwgb2Zmc2V0WCwgb2Zmc2V0WSkge1xuICBpZiAocm90YXRpb24gIT09IDApIHtcbiAgICBjb250ZXh0LnRyYW5zbGF0ZShvZmZzZXRYLCBvZmZzZXRZKTtcbiAgICBjb250ZXh0LnJvdGF0ZShyb3RhdGlvbik7XG4gICAgY29udGV4dC50cmFuc2xhdGUoLW9mZnNldFgsIC1vZmZzZXRZKTtcbiAgfVxufVxuLyoqXG4gKiBAcGFyYW0ge0NhbnZhc1JlbmRlcmluZ0NvbnRleHQyRH0gY29udGV4dCBDb250ZXh0LlxuICogQHBhcmFtIHtpbXBvcnQoXCIuLi90cmFuc2Zvcm0uanNcIikuVHJhbnNmb3JtfG51bGx9IHRyYW5zZm9ybSBUcmFuc2Zvcm0uXG4gKiBAcGFyYW0ge251bWJlcn0gb3BhY2l0eSBPcGFjaXR5LlxuICogQHBhcmFtIHtMYWJlbHxIVE1MQ2FudmFzRWxlbWVudHxIVE1MSW1hZ2VFbGVtZW50fEhUTUxWaWRlb0VsZW1lbnR9IGxhYmVsT3JJbWFnZSBMYWJlbC5cbiAqIEBwYXJhbSB7bnVtYmVyfSBvcmlnaW5YIE9yaWdpbiBYLlxuICogQHBhcmFtIHtudW1iZXJ9IG9yaWdpblkgT3JpZ2luIFkuXG4gKiBAcGFyYW0ge251bWJlcn0gdyBXaWR0aC5cbiAqIEBwYXJhbSB7bnVtYmVyfSBoIEhlaWdodC5cbiAqIEBwYXJhbSB7bnVtYmVyfSB4IFguXG4gKiBAcGFyYW0ge251bWJlcn0geSBZLlxuICogQHBhcmFtIHtpbXBvcnQoXCIuLi9zaXplLmpzXCIpLlNpemV9IHNjYWxlIFNjYWxlLlxuICovXG5cbmV4cG9ydCBmdW5jdGlvbiBkcmF3SW1hZ2VPckxhYmVsKGNvbnRleHQsIHRyYW5zZm9ybSwgb3BhY2l0eSwgbGFiZWxPckltYWdlLCBvcmlnaW5YLCBvcmlnaW5ZLCB3LCBoLCB4LCB5LCBzY2FsZSkge1xuICBjb250ZXh0LnNhdmUoKTtcblxuICBpZiAob3BhY2l0eSAhPT0gMSkge1xuICAgIGNvbnRleHQuZ2xvYmFsQWxwaGEgKj0gb3BhY2l0eTtcbiAgfVxuXG4gIGlmICh0cmFuc2Zvcm0pIHtcbiAgICBjb250ZXh0LnNldFRyYW5zZm9ybS5hcHBseShjb250ZXh0LCB0cmFuc2Zvcm0pO1xuICB9XG5cbiAgaWYgKFxuICAvKiogQHR5cGUgeyp9ICovXG4gIGxhYmVsT3JJbWFnZS5jb250ZXh0SW5zdHJ1Y3Rpb25zKSB7XG4gICAgLy8gbGFiZWxcbiAgICBjb250ZXh0LnRyYW5zbGF0ZSh4LCB5KTtcbiAgICBjb250ZXh0LnNjYWxlKHNjYWxlWzBdLCBzY2FsZVsxXSk7XG4gICAgZXhlY3V0ZUxhYmVsSW5zdHJ1Y3Rpb25zKFxuICAgIC8qKiBAdHlwZSB7TGFiZWx9ICovXG4gICAgbGFiZWxPckltYWdlLCBjb250ZXh0KTtcbiAgfSBlbHNlIGlmIChzY2FsZVswXSA8IDAgfHwgc2NhbGVbMV0gPCAwKSB7XG4gICAgLy8gZmxpcHBlZCBpbWFnZVxuICAgIGNvbnRleHQudHJhbnNsYXRlKHgsIHkpO1xuICAgIGNvbnRleHQuc2NhbGUoc2NhbGVbMF0sIHNjYWxlWzFdKTtcbiAgICBjb250ZXh0LmRyYXdJbWFnZShcbiAgICAvKiogQHR5cGUge0hUTUxDYW52YXNFbGVtZW50fEhUTUxJbWFnZUVsZW1lbnR8SFRNTFZpZGVvRWxlbWVudH0gKi9cbiAgICBsYWJlbE9ySW1hZ2UsIG9yaWdpblgsIG9yaWdpblksIHcsIGgsIDAsIDAsIHcsIGgpO1xuICB9IGVsc2Uge1xuICAgIC8vIGlmIGltYWdlIG5vdCBmbGlwcGVkIHRyYW5zbGF0ZSBhbmQgc2NhbGUgY2FuIGJlIGF2b2lkZWRcbiAgICBjb250ZXh0LmRyYXdJbWFnZShcbiAgICAvKiogQHR5cGUge0hUTUxDYW52YXNFbGVtZW50fEhUTUxJbWFnZUVsZW1lbnR8SFRNTFZpZGVvRWxlbWVudH0gKi9cbiAgICBsYWJlbE9ySW1hZ2UsIG9yaWdpblgsIG9yaWdpblksIHcsIGgsIHgsIHksIHcgKiBzY2FsZVswXSwgaCAqIHNjYWxlWzFdKTtcbiAgfVxuXG4gIGNvbnRleHQucmVzdG9yZSgpO1xufVxuLyoqXG4gKiBAcGFyYW0ge0xhYmVsfSBsYWJlbCBMYWJlbC5cbiAqIEBwYXJhbSB7Q2FudmFzUmVuZGVyaW5nQ29udGV4dDJEfSBjb250ZXh0IENvbnRleHQuXG4gKi9cblxuZnVuY3Rpb24gZXhlY3V0ZUxhYmVsSW5zdHJ1Y3Rpb25zKGxhYmVsLCBjb250ZXh0KSB7XG4gIHZhciBjb250ZXh0SW5zdHJ1Y3Rpb25zID0gbGFiZWwuY29udGV4dEluc3RydWN0aW9ucztcblxuICBmb3IgKHZhciBpID0gMCwgaWkgPSBjb250ZXh0SW5zdHJ1Y3Rpb25zLmxlbmd0aDsgaSA8IGlpOyBpICs9IDIpIHtcbiAgICBpZiAoQXJyYXkuaXNBcnJheShjb250ZXh0SW5zdHJ1Y3Rpb25zW2kgKyAxXSkpIHtcbiAgICAgIGNvbnRleHRbY29udGV4dEluc3RydWN0aW9uc1tpXV0uYXBwbHkoY29udGV4dCwgY29udGV4dEluc3RydWN0aW9uc1tpICsgMV0pO1xuICAgIH0gZWxzZSB7XG4gICAgICBjb250ZXh0W2NvbnRleHRJbnN0cnVjdGlvbnNbaV1dID0gY29udGV4dEluc3RydWN0aW9uc1tpICsgMV07XG4gICAgfVxuICB9XG59XG4vKipcbiAqIEB0eXBlIHtIVE1MQ2FudmFzRWxlbWVudH1cbiAqIEBwcml2YXRlXG4gKi9cblxuXG52YXIgY3JlYXRlVHJhbnNmb3JtU3RyaW5nQ2FudmFzID0gbnVsbDtcbi8qKlxuICogQHBhcmFtIHtpbXBvcnQoXCIuLi90cmFuc2Zvcm0uanNcIikuVHJhbnNmb3JtfSB0cmFuc2Zvcm0gVHJhbnNmb3JtLlxuICogQHJldHVybiB7c3RyaW5nfSBDU1MgdHJhbnNmb3JtLlxuICovXG5cbmV4cG9ydCBmdW5jdGlvbiBjcmVhdGVUcmFuc2Zvcm1TdHJpbmcodHJhbnNmb3JtKSB7XG4gIGlmIChXT1JLRVJfT0ZGU0NSRUVOX0NBTlZBUykge1xuICAgIHJldHVybiB0b1N0cmluZyh0cmFuc2Zvcm0pO1xuICB9IGVsc2Uge1xuICAgIGlmICghY3JlYXRlVHJhbnNmb3JtU3RyaW5nQ2FudmFzKSB7XG4gICAgICBjcmVhdGVUcmFuc2Zvcm1TdHJpbmdDYW52YXMgPSBjcmVhdGVDYW52YXNDb250ZXh0MkQoMSwgMSkuY2FudmFzO1xuICAgIH1cblxuICAgIGNyZWF0ZVRyYW5zZm9ybVN0cmluZ0NhbnZhcy5zdHlsZS50cmFuc2Zvcm0gPSB0b1N0cmluZyh0cmFuc2Zvcm0pO1xuICAgIHJldHVybiBjcmVhdGVUcmFuc2Zvcm1TdHJpbmdDYW52YXMuc3R5bGUudHJhbnNmb3JtO1xuICB9XG59IiwidmFyIF9fZXh0ZW5kcyA9IHRoaXMgJiYgdGhpcy5fX2V4dGVuZHMgfHwgZnVuY3Rpb24gKCkge1xuICB2YXIgX2V4dGVuZFN0YXRpY3MgPSBmdW5jdGlvbiBleHRlbmRTdGF0aWNzKGQsIGIpIHtcbiAgICBfZXh0ZW5kU3RhdGljcyA9IE9iamVjdC5zZXRQcm90b3R5cGVPZiB8fCB7XG4gICAgICBfX3Byb3RvX186IFtdXG4gICAgfSBpbnN0YW5jZW9mIEFycmF5ICYmIGZ1bmN0aW9uIChkLCBiKSB7XG4gICAgICBkLl9fcHJvdG9fXyA9IGI7XG4gICAgfSB8fCBmdW5jdGlvbiAoZCwgYikge1xuICAgICAgZm9yICh2YXIgcCBpbiBiKSB7XG4gICAgICAgIGlmIChPYmplY3QucHJvdG90eXBlLmhhc093blByb3BlcnR5LmNhbGwoYiwgcCkpIGRbcF0gPSBiW3BdO1xuICAgICAgfVxuICAgIH07XG5cbiAgICByZXR1cm4gX2V4dGVuZFN0YXRpY3MoZCwgYik7XG4gIH07XG5cbiAgcmV0dXJuIGZ1bmN0aW9uIChkLCBiKSB7XG4gICAgX2V4dGVuZFN0YXRpY3MoZCwgYik7XG5cbiAgICBmdW5jdGlvbiBfXygpIHtcbiAgICAgIHRoaXMuY29uc3RydWN0b3IgPSBkO1xuICAgIH1cblxuICAgIGQucHJvdG90eXBlID0gYiA9PT0gbnVsbCA/IE9iamVjdC5jcmVhdGUoYikgOiAoX18ucHJvdG90eXBlID0gYi5wcm90b3R5cGUsIG5ldyBfXygpKTtcbiAgfTtcbn0oKTtcbi8qKlxuICogQG1vZHVsZSBvbC9yZW5kZXJlci9Db21wb3NpdGVcbiAqL1xuXG5cbmltcG9ydCBNYXBSZW5kZXJlciBmcm9tICcuL01hcC5qcyc7XG5pbXBvcnQgT2JqZWN0RXZlbnRUeXBlIGZyb20gJy4uL09iamVjdEV2ZW50VHlwZS5qcyc7XG5pbXBvcnQgUmVuZGVyRXZlbnQgZnJvbSAnLi4vcmVuZGVyL0V2ZW50LmpzJztcbmltcG9ydCBSZW5kZXJFdmVudFR5cGUgZnJvbSAnLi4vcmVuZGVyL0V2ZW50VHlwZS5qcyc7XG5pbXBvcnQgU291cmNlU3RhdGUgZnJvbSAnLi4vc291cmNlL1N0YXRlLmpzJztcbmltcG9ydCB7IENMQVNTX1VOU0VMRUNUQUJMRSB9IGZyb20gJy4uL2Nzcy5qcyc7XG5pbXBvcnQgeyBjaGVja2VkRm9udHMgfSBmcm9tICcuLi9yZW5kZXIvY2FudmFzLmpzJztcbmltcG9ydCB7IGluVmlldyB9IGZyb20gJy4uL2xheWVyL0xheWVyLmpzJztcbmltcG9ydCB7IGxpc3RlbiwgdW5saXN0ZW5CeUtleSB9IGZyb20gJy4uL2V2ZW50cy5qcyc7XG5pbXBvcnQgeyByZXBsYWNlQ2hpbGRyZW4gfSBmcm9tICcuLi9kb20uanMnO1xuLyoqXG4gKiBAY2xhc3NkZXNjXG4gKiBDYW52YXMgbWFwIHJlbmRlcmVyLlxuICogQGFwaVxuICovXG5cbnZhciBDb21wb3NpdGVNYXBSZW5kZXJlciA9XG4vKiogQGNsYXNzICovXG5mdW5jdGlvbiAoX3N1cGVyKSB7XG4gIF9fZXh0ZW5kcyhDb21wb3NpdGVNYXBSZW5kZXJlciwgX3N1cGVyKTtcbiAgLyoqXG4gICAqIEBwYXJhbSB7aW1wb3J0KFwiLi4vUGx1Z2dhYmxlTWFwLmpzXCIpLmRlZmF1bHR9IG1hcCBNYXAuXG4gICAqL1xuXG5cbiAgZnVuY3Rpb24gQ29tcG9zaXRlTWFwUmVuZGVyZXIobWFwKSB7XG4gICAgdmFyIF90aGlzID0gX3N1cGVyLmNhbGwodGhpcywgbWFwKSB8fCB0aGlzO1xuICAgIC8qKlxuICAgICAqIEB0eXBlIHtpbXBvcnQoXCIuLi9ldmVudHMuanNcIikuRXZlbnRzS2V5fVxuICAgICAqL1xuXG5cbiAgICBfdGhpcy5mb250Q2hhbmdlTGlzdGVuZXJLZXlfID0gbGlzdGVuKGNoZWNrZWRGb250cywgT2JqZWN0RXZlbnRUeXBlLlBST1BFUlRZQ0hBTkdFLCBtYXAucmVkcmF3VGV4dC5iaW5kKG1hcCkpO1xuICAgIC8qKlxuICAgICAqIEBwcml2YXRlXG4gICAgICogQHR5cGUge0hUTUxEaXZFbGVtZW50fVxuICAgICAqL1xuXG4gICAgX3RoaXMuZWxlbWVudF8gPSBkb2N1bWVudC5jcmVhdGVFbGVtZW50KCdkaXYnKTtcbiAgICB2YXIgc3R5bGUgPSBfdGhpcy5lbGVtZW50Xy5zdHlsZTtcbiAgICBzdHlsZS5wb3NpdGlvbiA9ICdhYnNvbHV0ZSc7XG4gICAgc3R5bGUud2lkdGggPSAnMTAwJSc7XG4gICAgc3R5bGUuaGVpZ2h0ID0gJzEwMCUnO1xuICAgIHN0eWxlLnpJbmRleCA9ICcwJztcbiAgICBfdGhpcy5lbGVtZW50Xy5jbGFzc05hbWUgPSBDTEFTU19VTlNFTEVDVEFCTEUgKyAnIG9sLWxheWVycyc7XG4gICAgdmFyIGNvbnRhaW5lciA9IG1hcC5nZXRWaWV3cG9ydCgpO1xuICAgIGNvbnRhaW5lci5pbnNlcnRCZWZvcmUoX3RoaXMuZWxlbWVudF8sIGNvbnRhaW5lci5maXJzdENoaWxkIHx8IG51bGwpO1xuICAgIC8qKlxuICAgICAqIEBwcml2YXRlXG4gICAgICogQHR5cGUge0FycmF5PEhUTUxFbGVtZW50Pn1cbiAgICAgKi9cblxuICAgIF90aGlzLmNoaWxkcmVuXyA9IFtdO1xuICAgIC8qKlxuICAgICAqIEBwcml2YXRlXG4gICAgICogQHR5cGUge2Jvb2xlYW59XG4gICAgICovXG5cbiAgICBfdGhpcy5yZW5kZXJlZFZpc2libGVfID0gdHJ1ZTtcbiAgICByZXR1cm4gX3RoaXM7XG4gIH1cbiAgLyoqXG4gICAqIEBwYXJhbSB7aW1wb3J0KFwiLi4vcmVuZGVyL0V2ZW50VHlwZS5qc1wiKS5kZWZhdWx0fSB0eXBlIEV2ZW50IHR5cGUuXG4gICAqIEBwYXJhbSB7aW1wb3J0KFwiLi4vUGx1Z2dhYmxlTWFwLmpzXCIpLkZyYW1lU3RhdGV9IGZyYW1lU3RhdGUgRnJhbWUgc3RhdGUuXG4gICAqL1xuXG5cbiAgQ29tcG9zaXRlTWFwUmVuZGVyZXIucHJvdG90eXBlLmRpc3BhdGNoUmVuZGVyRXZlbnQgPSBmdW5jdGlvbiAodHlwZSwgZnJhbWVTdGF0ZSkge1xuICAgIHZhciBtYXAgPSB0aGlzLmdldE1hcCgpO1xuXG4gICAgaWYgKG1hcC5oYXNMaXN0ZW5lcih0eXBlKSkge1xuICAgICAgdmFyIGV2ZW50XzEgPSBuZXcgUmVuZGVyRXZlbnQodHlwZSwgdW5kZWZpbmVkLCBmcmFtZVN0YXRlKTtcbiAgICAgIG1hcC5kaXNwYXRjaEV2ZW50KGV2ZW50XzEpO1xuICAgIH1cbiAgfTtcblxuICBDb21wb3NpdGVNYXBSZW5kZXJlci5wcm90b3R5cGUuZGlzcG9zZUludGVybmFsID0gZnVuY3Rpb24gKCkge1xuICAgIHVubGlzdGVuQnlLZXkodGhpcy5mb250Q2hhbmdlTGlzdGVuZXJLZXlfKTtcbiAgICB0aGlzLmVsZW1lbnRfLnBhcmVudE5vZGUucmVtb3ZlQ2hpbGQodGhpcy5lbGVtZW50Xyk7XG5cbiAgICBfc3VwZXIucHJvdG90eXBlLmRpc3Bvc2VJbnRlcm5hbC5jYWxsKHRoaXMpO1xuICB9O1xuICAvKipcbiAgICogUmVuZGVyLlxuICAgKiBAcGFyYW0gez9pbXBvcnQoXCIuLi9QbHVnZ2FibGVNYXAuanNcIikuRnJhbWVTdGF0ZX0gZnJhbWVTdGF0ZSBGcmFtZSBzdGF0ZS5cbiAgICovXG5cblxuICBDb21wb3NpdGVNYXBSZW5kZXJlci5wcm90b3R5cGUucmVuZGVyRnJhbWUgPSBmdW5jdGlvbiAoZnJhbWVTdGF0ZSkge1xuICAgIGlmICghZnJhbWVTdGF0ZSkge1xuICAgICAgaWYgKHRoaXMucmVuZGVyZWRWaXNpYmxlXykge1xuICAgICAgICB0aGlzLmVsZW1lbnRfLnN0eWxlLmRpc3BsYXkgPSAnbm9uZSc7XG4gICAgICAgIHRoaXMucmVuZGVyZWRWaXNpYmxlXyA9IGZhbHNlO1xuICAgICAgfVxuXG4gICAgICByZXR1cm47XG4gICAgfVxuXG4gICAgdGhpcy5jYWxjdWxhdGVNYXRyaWNlczJEKGZyYW1lU3RhdGUpO1xuICAgIHRoaXMuZGlzcGF0Y2hSZW5kZXJFdmVudChSZW5kZXJFdmVudFR5cGUuUFJFQ09NUE9TRSwgZnJhbWVTdGF0ZSk7XG4gICAgdmFyIGxheWVyU3RhdGVzQXJyYXkgPSBmcmFtZVN0YXRlLmxheWVyU3RhdGVzQXJyYXkuc29ydChmdW5jdGlvbiAoYSwgYikge1xuICAgICAgcmV0dXJuIGEuekluZGV4IC0gYi56SW5kZXg7XG4gICAgfSk7XG4gICAgdmFyIHZpZXdTdGF0ZSA9IGZyYW1lU3RhdGUudmlld1N0YXRlO1xuICAgIHRoaXMuY2hpbGRyZW5fLmxlbmd0aCA9IDA7XG4gICAgLyoqXG4gICAgICogQHR5cGUge0FycmF5PGltcG9ydChcIi4uL2xheWVyL0Jhc2VWZWN0b3IuanNcIikuZGVmYXVsdD59XG4gICAgICovXG5cbiAgICB2YXIgZGVjbHV0dGVyTGF5ZXJzID0gW107XG4gICAgdmFyIHByZXZpb3VzRWxlbWVudCA9IG51bGw7XG5cbiAgICBmb3IgKHZhciBpID0gMCwgaWkgPSBsYXllclN0YXRlc0FycmF5Lmxlbmd0aDsgaSA8IGlpOyArK2kpIHtcbiAgICAgIHZhciBsYXllclN0YXRlID0gbGF5ZXJTdGF0ZXNBcnJheVtpXTtcbiAgICAgIGZyYW1lU3RhdGUubGF5ZXJJbmRleCA9IGk7XG5cbiAgICAgIGlmICghaW5WaWV3KGxheWVyU3RhdGUsIHZpZXdTdGF0ZSkgfHwgbGF5ZXJTdGF0ZS5zb3VyY2VTdGF0ZSAhPSBTb3VyY2VTdGF0ZS5SRUFEWSAmJiBsYXllclN0YXRlLnNvdXJjZVN0YXRlICE9IFNvdXJjZVN0YXRlLlVOREVGSU5FRCkge1xuICAgICAgICBjb250aW51ZTtcbiAgICAgIH1cblxuICAgICAgdmFyIGxheWVyID0gbGF5ZXJTdGF0ZS5sYXllcjtcbiAgICAgIHZhciBlbGVtZW50ID0gbGF5ZXIucmVuZGVyKGZyYW1lU3RhdGUsIHByZXZpb3VzRWxlbWVudCk7XG5cbiAgICAgIGlmICghZWxlbWVudCkge1xuICAgICAgICBjb250aW51ZTtcbiAgICAgIH1cblxuICAgICAgaWYgKGVsZW1lbnQgIT09IHByZXZpb3VzRWxlbWVudCkge1xuICAgICAgICB0aGlzLmNoaWxkcmVuXy5wdXNoKGVsZW1lbnQpO1xuICAgICAgICBwcmV2aW91c0VsZW1lbnQgPSBlbGVtZW50O1xuICAgICAgfVxuXG4gICAgICBpZiAoJ2dldERlY2x1dHRlcicgaW4gbGF5ZXIpIHtcbiAgICAgICAgZGVjbHV0dGVyTGF5ZXJzLnB1c2gobGF5ZXIpO1xuICAgICAgfVxuICAgIH1cblxuICAgIGZvciAodmFyIGkgPSBkZWNsdXR0ZXJMYXllcnMubGVuZ3RoIC0gMTsgaSA+PSAwOyAtLWkpIHtcbiAgICAgIGRlY2x1dHRlckxheWVyc1tpXS5yZW5kZXJEZWNsdXR0ZXIoZnJhbWVTdGF0ZSk7XG4gICAgfVxuXG4gICAgcmVwbGFjZUNoaWxkcmVuKHRoaXMuZWxlbWVudF8sIHRoaXMuY2hpbGRyZW5fKTtcbiAgICB0aGlzLmRpc3BhdGNoUmVuZGVyRXZlbnQoUmVuZGVyRXZlbnRUeXBlLlBPU1RDT01QT1NFLCBmcmFtZVN0YXRlKTtcblxuICAgIGlmICghdGhpcy5yZW5kZXJlZFZpc2libGVfKSB7XG4gICAgICB0aGlzLmVsZW1lbnRfLnN0eWxlLmRpc3BsYXkgPSAnJztcbiAgICAgIHRoaXMucmVuZGVyZWRWaXNpYmxlXyA9IHRydWU7XG4gICAgfVxuXG4gICAgdGhpcy5zY2hlZHVsZUV4cGlyZUljb25DYWNoZShmcmFtZVN0YXRlKTtcbiAgfTtcbiAgLyoqXG4gICAqIEBwYXJhbSB7aW1wb3J0KFwiLi4vcGl4ZWwuanNcIikuUGl4ZWx9IHBpeGVsIFBpeGVsLlxuICAgKiBAcGFyYW0ge2ltcG9ydChcIi4uL1BsdWdnYWJsZU1hcC5qc1wiKS5GcmFtZVN0YXRlfSBmcmFtZVN0YXRlIEZyYW1lU3RhdGUuXG4gICAqIEBwYXJhbSB7bnVtYmVyfSBoaXRUb2xlcmFuY2UgSGl0IHRvbGVyYW5jZSBpbiBwaXhlbHMuXG4gICAqIEBwYXJhbSB7ZnVuY3Rpb24oaW1wb3J0KFwiLi4vbGF5ZXIvTGF5ZXIuanNcIikuZGVmYXVsdCwgKFVpbnQ4Q2xhbXBlZEFycmF5fFVpbnQ4QXJyYXkpKTogVH0gY2FsbGJhY2sgTGF5ZXJcbiAgICogICAgIGNhbGxiYWNrLlxuICAgKiBAcGFyYW0ge2Z1bmN0aW9uKGltcG9ydChcIi4uL2xheWVyL0xheWVyLmpzXCIpLmRlZmF1bHQpOiBib29sZWFufSBsYXllckZpbHRlciBMYXllciBmaWx0ZXJcbiAgICogICAgIGZ1bmN0aW9uLCBvbmx5IGxheWVycyB3aGljaCBhcmUgdmlzaWJsZSBhbmQgZm9yIHdoaWNoIHRoaXMgZnVuY3Rpb25cbiAgICogICAgIHJldHVybnMgYHRydWVgIHdpbGwgYmUgdGVzdGVkIGZvciBmZWF0dXJlcy4gIEJ5IGRlZmF1bHQsIGFsbCB2aXNpYmxlXG4gICAqICAgICBsYXllcnMgd2lsbCBiZSB0ZXN0ZWQuXG4gICAqIEByZXR1cm4ge1R8dW5kZWZpbmVkfSBDYWxsYmFjayByZXN1bHQuXG4gICAqIEB0ZW1wbGF0ZSBUXG4gICAqL1xuXG5cbiAgQ29tcG9zaXRlTWFwUmVuZGVyZXIucHJvdG90eXBlLmZvckVhY2hMYXllckF0UGl4ZWwgPSBmdW5jdGlvbiAocGl4ZWwsIGZyYW1lU3RhdGUsIGhpdFRvbGVyYW5jZSwgY2FsbGJhY2ssIGxheWVyRmlsdGVyKSB7XG4gICAgdmFyIHZpZXdTdGF0ZSA9IGZyYW1lU3RhdGUudmlld1N0YXRlO1xuICAgIHZhciBsYXllclN0YXRlcyA9IGZyYW1lU3RhdGUubGF5ZXJTdGF0ZXNBcnJheTtcbiAgICB2YXIgbnVtTGF5ZXJzID0gbGF5ZXJTdGF0ZXMubGVuZ3RoO1xuXG4gICAgZm9yICh2YXIgaSA9IG51bUxheWVycyAtIDE7IGkgPj0gMDsgLS1pKSB7XG4gICAgICB2YXIgbGF5ZXJTdGF0ZSA9IGxheWVyU3RhdGVzW2ldO1xuICAgICAgdmFyIGxheWVyID0gbGF5ZXJTdGF0ZS5sYXllcjtcblxuICAgICAgaWYgKGxheWVyLmhhc1JlbmRlcmVyKCkgJiYgaW5WaWV3KGxheWVyU3RhdGUsIHZpZXdTdGF0ZSkgJiYgbGF5ZXJGaWx0ZXIobGF5ZXIpKSB7XG4gICAgICAgIHZhciBsYXllclJlbmRlcmVyID0gbGF5ZXIuZ2V0UmVuZGVyZXIoKTtcbiAgICAgICAgdmFyIGRhdGEgPSBsYXllclJlbmRlcmVyLmdldERhdGFBdFBpeGVsKHBpeGVsLCBmcmFtZVN0YXRlLCBoaXRUb2xlcmFuY2UpO1xuXG4gICAgICAgIGlmIChkYXRhKSB7XG4gICAgICAgICAgdmFyIHJlc3VsdCA9IGNhbGxiYWNrKGxheWVyLCBkYXRhKTtcblxuICAgICAgICAgIGlmIChyZXN1bHQpIHtcbiAgICAgICAgICAgIHJldHVybiByZXN1bHQ7XG4gICAgICAgICAgfVxuICAgICAgICB9XG4gICAgICB9XG4gICAgfVxuXG4gICAgcmV0dXJuIHVuZGVmaW5lZDtcbiAgfTtcblxuICByZXR1cm4gQ29tcG9zaXRlTWFwUmVuZGVyZXI7XG59KE1hcFJlbmRlcmVyKTtcblxuZXhwb3J0IGRlZmF1bHQgQ29tcG9zaXRlTWFwUmVuZGVyZXI7IiwiLyoqXG4gKiBAbW9kdWxlIG9sL0NvbGxlY3Rpb25FdmVudFR5cGVcbiAqL1xuXG4vKipcbiAqIEBlbnVtIHtzdHJpbmd9XG4gKi9cbmV4cG9ydCBkZWZhdWx0IHtcbiAgLyoqXG4gICAqIFRyaWdnZXJlZCB3aGVuIGFuIGl0ZW0gaXMgYWRkZWQgdG8gdGhlIGNvbGxlY3Rpb24uXG4gICAqIEBldmVudCBtb2R1bGU6b2wvQ29sbGVjdGlvbi5Db2xsZWN0aW9uRXZlbnQjYWRkXG4gICAqIEBhcGlcbiAgICovXG4gIEFERDogJ2FkZCcsXG5cbiAgLyoqXG4gICAqIFRyaWdnZXJlZCB3aGVuIGFuIGl0ZW0gaXMgcmVtb3ZlZCBmcm9tIHRoZSBjb2xsZWN0aW9uLlxuICAgKiBAZXZlbnQgbW9kdWxlOm9sL0NvbGxlY3Rpb24uQ29sbGVjdGlvbkV2ZW50I3JlbW92ZVxuICAgKiBAYXBpXG4gICAqL1xuICBSRU1PVkU6ICdyZW1vdmUnXG59OyIsInZhciBfX2V4dGVuZHMgPSB0aGlzICYmIHRoaXMuX19leHRlbmRzIHx8IGZ1bmN0aW9uICgpIHtcbiAgdmFyIF9leHRlbmRTdGF0aWNzID0gZnVuY3Rpb24gZXh0ZW5kU3RhdGljcyhkLCBiKSB7XG4gICAgX2V4dGVuZFN0YXRpY3MgPSBPYmplY3Quc2V0UHJvdG90eXBlT2YgfHwge1xuICAgICAgX19wcm90b19fOiBbXVxuICAgIH0gaW5zdGFuY2VvZiBBcnJheSAmJiBmdW5jdGlvbiAoZCwgYikge1xuICAgICAgZC5fX3Byb3RvX18gPSBiO1xuICAgIH0gfHwgZnVuY3Rpb24gKGQsIGIpIHtcbiAgICAgIGZvciAodmFyIHAgaW4gYikge1xuICAgICAgICBpZiAoT2JqZWN0LnByb3RvdHlwZS5oYXNPd25Qcm9wZXJ0eS5jYWxsKGIsIHApKSBkW3BdID0gYltwXTtcbiAgICAgIH1cbiAgICB9O1xuXG4gICAgcmV0dXJuIF9leHRlbmRTdGF0aWNzKGQsIGIpO1xuICB9O1xuXG4gIHJldHVybiBmdW5jdGlvbiAoZCwgYikge1xuICAgIF9leHRlbmRTdGF0aWNzKGQsIGIpO1xuXG4gICAgZnVuY3Rpb24gX18oKSB7XG4gICAgICB0aGlzLmNvbnN0cnVjdG9yID0gZDtcbiAgICB9XG5cbiAgICBkLnByb3RvdHlwZSA9IGIgPT09IG51bGwgPyBPYmplY3QuY3JlYXRlKGIpIDogKF9fLnByb3RvdHlwZSA9IGIucHJvdG90eXBlLCBuZXcgX18oKSk7XG4gIH07XG59KCk7XG4vKipcbiAqIEBtb2R1bGUgb2wvQ29sbGVjdGlvblxuICovXG5cblxuaW1wb3J0IEFzc2VydGlvbkVycm9yIGZyb20gJy4vQXNzZXJ0aW9uRXJyb3IuanMnO1xuaW1wb3J0IEJhc2VPYmplY3QgZnJvbSAnLi9PYmplY3QuanMnO1xuaW1wb3J0IENvbGxlY3Rpb25FdmVudFR5cGUgZnJvbSAnLi9Db2xsZWN0aW9uRXZlbnRUeXBlLmpzJztcbmltcG9ydCBFdmVudCBmcm9tICcuL2V2ZW50cy9FdmVudC5qcyc7XG4vKipcbiAqIEBlbnVtIHtzdHJpbmd9XG4gKiBAcHJpdmF0ZVxuICovXG5cbnZhciBQcm9wZXJ0eSA9IHtcbiAgTEVOR1RIOiAnbGVuZ3RoJ1xufTtcbi8qKlxuICogQGNsYXNzZGVzY1xuICogRXZlbnRzIGVtaXR0ZWQgYnkge0BsaW5rIG1vZHVsZTpvbC9Db2xsZWN0aW9ufkNvbGxlY3Rpb259IGluc3RhbmNlcyBhcmUgaW5zdGFuY2VzIG9mIHRoaXNcbiAqIHR5cGUuXG4gKi9cblxudmFyIENvbGxlY3Rpb25FdmVudCA9XG4vKiogQGNsYXNzICovXG5mdW5jdGlvbiAoX3N1cGVyKSB7XG4gIF9fZXh0ZW5kcyhDb2xsZWN0aW9uRXZlbnQsIF9zdXBlcik7XG4gIC8qKlxuICAgKiBAcGFyYW0ge2ltcG9ydChcIi4vQ29sbGVjdGlvbkV2ZW50VHlwZS5qc1wiKS5kZWZhdWx0fSB0eXBlIFR5cGUuXG4gICAqIEBwYXJhbSB7Kj19IG9wdF9lbGVtZW50IEVsZW1lbnQuXG4gICAqIEBwYXJhbSB7bnVtYmVyPX0gb3B0X2luZGV4IFRoZSBpbmRleCBvZiB0aGUgYWRkZWQgb3IgcmVtb3ZlZCBlbGVtZW50LlxuICAgKi9cblxuXG4gIGZ1bmN0aW9uIENvbGxlY3Rpb25FdmVudCh0eXBlLCBvcHRfZWxlbWVudCwgb3B0X2luZGV4KSB7XG4gICAgdmFyIF90aGlzID0gX3N1cGVyLmNhbGwodGhpcywgdHlwZSkgfHwgdGhpcztcbiAgICAvKipcbiAgICAgKiBUaGUgZWxlbWVudCB0aGF0IGlzIGFkZGVkIHRvIG9yIHJlbW92ZWQgZnJvbSB0aGUgY29sbGVjdGlvbi5cbiAgICAgKiBAdHlwZSB7Kn1cbiAgICAgKiBAYXBpXG4gICAgICovXG5cblxuICAgIF90aGlzLmVsZW1lbnQgPSBvcHRfZWxlbWVudDtcbiAgICAvKipcbiAgICAgKiBUaGUgaW5kZXggb2YgdGhlIGFkZGVkIG9yIHJlbW92ZWQgZWxlbWVudC5cbiAgICAgKiBAdHlwZSB7bnVtYmVyfVxuICAgICAqIEBhcGlcbiAgICAgKi9cblxuICAgIF90aGlzLmluZGV4ID0gb3B0X2luZGV4O1xuICAgIHJldHVybiBfdGhpcztcbiAgfVxuXG4gIHJldHVybiBDb2xsZWN0aW9uRXZlbnQ7XG59KEV2ZW50KTtcblxuZXhwb3J0IHsgQ29sbGVjdGlvbkV2ZW50IH07XG4vKipcbiAqIEB0eXBlZGVmIHtPYmplY3R9IE9wdGlvbnNcbiAqIEBwcm9wZXJ0eSB7Ym9vbGVhbn0gW3VuaXF1ZT1mYWxzZV0gRGlzYWxsb3cgdGhlIHNhbWUgaXRlbSBmcm9tIGJlaW5nIGFkZGVkIHRvXG4gKiB0aGUgY29sbGVjdGlvbiB0d2ljZS5cbiAqL1xuXG4vKipcbiAqIEBjbGFzc2Rlc2NcbiAqIEFuIGV4cGFuZGVkIHZlcnNpb24gb2Ygc3RhbmRhcmQgSlMgQXJyYXksIGFkZGluZyBjb252ZW5pZW5jZSBtZXRob2RzIGZvclxuICogbWFuaXB1bGF0aW9uLiBBZGQgYW5kIHJlbW92ZSBjaGFuZ2VzIHRvIHRoZSBDb2xsZWN0aW9uIHRyaWdnZXIgYSBDb2xsZWN0aW9uXG4gKiBldmVudC4gTm90ZSB0aGF0IHRoaXMgZG9lcyBub3QgY292ZXIgY2hhbmdlcyB0byB0aGUgb2JqZWN0cyBfd2l0aGluXyB0aGVcbiAqIENvbGxlY3Rpb247IHRoZXkgdHJpZ2dlciBldmVudHMgb24gdGhlIGFwcHJvcHJpYXRlIG9iamVjdCwgbm90IG9uIHRoZVxuICogQ29sbGVjdGlvbiBhcyBhIHdob2xlLlxuICpcbiAqIEBmaXJlcyBDb2xsZWN0aW9uRXZlbnRcbiAqXG4gKiBAdGVtcGxhdGUgVFxuICogQGFwaVxuICovXG5cbnZhciBDb2xsZWN0aW9uID1cbi8qKiBAY2xhc3MgKi9cbmZ1bmN0aW9uIChfc3VwZXIpIHtcbiAgX19leHRlbmRzKENvbGxlY3Rpb24sIF9zdXBlcik7XG4gIC8qKlxuICAgKiBAcGFyYW0ge0FycmF5PFQ+PX0gb3B0X2FycmF5IEFycmF5LlxuICAgKiBAcGFyYW0ge09wdGlvbnM9fSBvcHRfb3B0aW9ucyBDb2xsZWN0aW9uIG9wdGlvbnMuXG4gICAqL1xuXG5cbiAgZnVuY3Rpb24gQ29sbGVjdGlvbihvcHRfYXJyYXksIG9wdF9vcHRpb25zKSB7XG4gICAgdmFyIF90aGlzID0gX3N1cGVyLmNhbGwodGhpcykgfHwgdGhpcztcblxuICAgIHZhciBvcHRpb25zID0gb3B0X29wdGlvbnMgfHwge307XG4gICAgLyoqXG4gICAgICogQHByaXZhdGVcbiAgICAgKiBAdHlwZSB7Ym9vbGVhbn1cbiAgICAgKi9cblxuICAgIF90aGlzLnVuaXF1ZV8gPSAhIW9wdGlvbnMudW5pcXVlO1xuICAgIC8qKlxuICAgICAqIEBwcml2YXRlXG4gICAgICogQHR5cGUgeyFBcnJheTxUPn1cbiAgICAgKi9cblxuICAgIF90aGlzLmFycmF5XyA9IG9wdF9hcnJheSA/IG9wdF9hcnJheSA6IFtdO1xuXG4gICAgaWYgKF90aGlzLnVuaXF1ZV8pIHtcbiAgICAgIGZvciAodmFyIGkgPSAwLCBpaSA9IF90aGlzLmFycmF5Xy5sZW5ndGg7IGkgPCBpaTsgKytpKSB7XG4gICAgICAgIF90aGlzLmFzc2VydFVuaXF1ZV8oX3RoaXMuYXJyYXlfW2ldLCBpKTtcbiAgICAgIH1cbiAgICB9XG5cbiAgICBfdGhpcy51cGRhdGVMZW5ndGhfKCk7XG5cbiAgICByZXR1cm4gX3RoaXM7XG4gIH1cbiAgLyoqXG4gICAqIFJlbW92ZSBhbGwgZWxlbWVudHMgZnJvbSB0aGUgY29sbGVjdGlvbi5cbiAgICogQGFwaVxuICAgKi9cblxuXG4gIENvbGxlY3Rpb24ucHJvdG90eXBlLmNsZWFyID0gZnVuY3Rpb24gKCkge1xuICAgIHdoaWxlICh0aGlzLmdldExlbmd0aCgpID4gMCkge1xuICAgICAgdGhpcy5wb3AoKTtcbiAgICB9XG4gIH07XG4gIC8qKlxuICAgKiBBZGQgZWxlbWVudHMgdG8gdGhlIGNvbGxlY3Rpb24uICBUaGlzIHB1c2hlcyBlYWNoIGl0ZW0gaW4gdGhlIHByb3ZpZGVkIGFycmF5XG4gICAqIHRvIHRoZSBlbmQgb2YgdGhlIGNvbGxlY3Rpb24uXG4gICAqIEBwYXJhbSB7IUFycmF5PFQ+fSBhcnIgQXJyYXkuXG4gICAqIEByZXR1cm4ge0NvbGxlY3Rpb248VD59IFRoaXMgY29sbGVjdGlvbi5cbiAgICogQGFwaVxuICAgKi9cblxuXG4gIENvbGxlY3Rpb24ucHJvdG90eXBlLmV4dGVuZCA9IGZ1bmN0aW9uIChhcnIpIHtcbiAgICBmb3IgKHZhciBpID0gMCwgaWkgPSBhcnIubGVuZ3RoOyBpIDwgaWk7ICsraSkge1xuICAgICAgdGhpcy5wdXNoKGFycltpXSk7XG4gICAgfVxuXG4gICAgcmV0dXJuIHRoaXM7XG4gIH07XG4gIC8qKlxuICAgKiBJdGVyYXRlIG92ZXIgZWFjaCBlbGVtZW50LCBjYWxsaW5nIHRoZSBwcm92aWRlZCBjYWxsYmFjay5cbiAgICogQHBhcmFtIHtmdW5jdGlvbihULCBudW1iZXIsIEFycmF5PFQ+KTogKn0gZiBUaGUgZnVuY3Rpb24gdG8gY2FsbFxuICAgKiAgICAgZm9yIGV2ZXJ5IGVsZW1lbnQuIFRoaXMgZnVuY3Rpb24gdGFrZXMgMyBhcmd1bWVudHMgKHRoZSBlbGVtZW50LCB0aGVcbiAgICogICAgIGluZGV4IGFuZCB0aGUgYXJyYXkpLiBUaGUgcmV0dXJuIHZhbHVlIGlzIGlnbm9yZWQuXG4gICAqIEBhcGlcbiAgICovXG5cblxuICBDb2xsZWN0aW9uLnByb3RvdHlwZS5mb3JFYWNoID0gZnVuY3Rpb24gKGYpIHtcbiAgICB2YXIgYXJyYXkgPSB0aGlzLmFycmF5XztcblxuICAgIGZvciAodmFyIGkgPSAwLCBpaSA9IGFycmF5Lmxlbmd0aDsgaSA8IGlpOyArK2kpIHtcbiAgICAgIGYoYXJyYXlbaV0sIGksIGFycmF5KTtcbiAgICB9XG4gIH07XG4gIC8qKlxuICAgKiBHZXQgYSByZWZlcmVuY2UgdG8gdGhlIHVuZGVybHlpbmcgQXJyYXkgb2JqZWN0LiBXYXJuaW5nOiBpZiB0aGUgYXJyYXlcbiAgICogaXMgbXV0YXRlZCwgbm8gZXZlbnRzIHdpbGwgYmUgZGlzcGF0Y2hlZCBieSB0aGUgY29sbGVjdGlvbiwgYW5kIHRoZVxuICAgKiBjb2xsZWN0aW9uJ3MgXCJsZW5ndGhcIiBwcm9wZXJ0eSB3b24ndCBiZSBpbiBzeW5jIHdpdGggdGhlIGFjdHVhbCBsZW5ndGhcbiAgICogb2YgdGhlIGFycmF5LlxuICAgKiBAcmV0dXJuIHshQXJyYXk8VD59IEFycmF5LlxuICAgKiBAYXBpXG4gICAqL1xuXG5cbiAgQ29sbGVjdGlvbi5wcm90b3R5cGUuZ2V0QXJyYXkgPSBmdW5jdGlvbiAoKSB7XG4gICAgcmV0dXJuIHRoaXMuYXJyYXlfO1xuICB9O1xuICAvKipcbiAgICogR2V0IHRoZSBlbGVtZW50IGF0IHRoZSBwcm92aWRlZCBpbmRleC5cbiAgICogQHBhcmFtIHtudW1iZXJ9IGluZGV4IEluZGV4LlxuICAgKiBAcmV0dXJuIHtUfSBFbGVtZW50LlxuICAgKiBAYXBpXG4gICAqL1xuXG5cbiAgQ29sbGVjdGlvbi5wcm90b3R5cGUuaXRlbSA9IGZ1bmN0aW9uIChpbmRleCkge1xuICAgIHJldHVybiB0aGlzLmFycmF5X1tpbmRleF07XG4gIH07XG4gIC8qKlxuICAgKiBHZXQgdGhlIGxlbmd0aCBvZiB0aGlzIGNvbGxlY3Rpb24uXG4gICAqIEByZXR1cm4ge251bWJlcn0gVGhlIGxlbmd0aCBvZiB0aGUgYXJyYXkuXG4gICAqIEBvYnNlcnZhYmxlXG4gICAqIEBhcGlcbiAgICovXG5cblxuICBDb2xsZWN0aW9uLnByb3RvdHlwZS5nZXRMZW5ndGggPSBmdW5jdGlvbiAoKSB7XG4gICAgcmV0dXJuIHRoaXMuZ2V0KFByb3BlcnR5LkxFTkdUSCk7XG4gIH07XG4gIC8qKlxuICAgKiBJbnNlcnQgYW4gZWxlbWVudCBhdCB0aGUgcHJvdmlkZWQgaW5kZXguXG4gICAqIEBwYXJhbSB7bnVtYmVyfSBpbmRleCBJbmRleC5cbiAgICogQHBhcmFtIHtUfSBlbGVtIEVsZW1lbnQuXG4gICAqIEBhcGlcbiAgICovXG5cblxuICBDb2xsZWN0aW9uLnByb3RvdHlwZS5pbnNlcnRBdCA9IGZ1bmN0aW9uIChpbmRleCwgZWxlbSkge1xuICAgIGlmICh0aGlzLnVuaXF1ZV8pIHtcbiAgICAgIHRoaXMuYXNzZXJ0VW5pcXVlXyhlbGVtKTtcbiAgICB9XG5cbiAgICB0aGlzLmFycmF5Xy5zcGxpY2UoaW5kZXgsIDAsIGVsZW0pO1xuICAgIHRoaXMudXBkYXRlTGVuZ3RoXygpO1xuICAgIHRoaXMuZGlzcGF0Y2hFdmVudChuZXcgQ29sbGVjdGlvbkV2ZW50KENvbGxlY3Rpb25FdmVudFR5cGUuQURELCBlbGVtLCBpbmRleCkpO1xuICB9O1xuICAvKipcbiAgICogUmVtb3ZlIHRoZSBsYXN0IGVsZW1lbnQgb2YgdGhlIGNvbGxlY3Rpb24gYW5kIHJldHVybiBpdC5cbiAgICogUmV0dXJuIGB1bmRlZmluZWRgIGlmIHRoZSBjb2xsZWN0aW9uIGlzIGVtcHR5LlxuICAgKiBAcmV0dXJuIHtUfHVuZGVmaW5lZH0gRWxlbWVudC5cbiAgICogQGFwaVxuICAgKi9cblxuXG4gIENvbGxlY3Rpb24ucHJvdG90eXBlLnBvcCA9IGZ1bmN0aW9uICgpIHtcbiAgICByZXR1cm4gdGhpcy5yZW1vdmVBdCh0aGlzLmdldExlbmd0aCgpIC0gMSk7XG4gIH07XG4gIC8qKlxuICAgKiBJbnNlcnQgdGhlIHByb3ZpZGVkIGVsZW1lbnQgYXQgdGhlIGVuZCBvZiB0aGUgY29sbGVjdGlvbi5cbiAgICogQHBhcmFtIHtUfSBlbGVtIEVsZW1lbnQuXG4gICAqIEByZXR1cm4ge251bWJlcn0gTmV3IGxlbmd0aCBvZiB0aGUgY29sbGVjdGlvbi5cbiAgICogQGFwaVxuICAgKi9cblxuXG4gIENvbGxlY3Rpb24ucHJvdG90eXBlLnB1c2ggPSBmdW5jdGlvbiAoZWxlbSkge1xuICAgIGlmICh0aGlzLnVuaXF1ZV8pIHtcbiAgICAgIHRoaXMuYXNzZXJ0VW5pcXVlXyhlbGVtKTtcbiAgICB9XG5cbiAgICB2YXIgbiA9IHRoaXMuZ2V0TGVuZ3RoKCk7XG4gICAgdGhpcy5pbnNlcnRBdChuLCBlbGVtKTtcbiAgICByZXR1cm4gdGhpcy5nZXRMZW5ndGgoKTtcbiAgfTtcbiAgLyoqXG4gICAqIFJlbW92ZSB0aGUgZmlyc3Qgb2NjdXJyZW5jZSBvZiBhbiBlbGVtZW50IGZyb20gdGhlIGNvbGxlY3Rpb24uXG4gICAqIEBwYXJhbSB7VH0gZWxlbSBFbGVtZW50LlxuICAgKiBAcmV0dXJuIHtUfHVuZGVmaW5lZH0gVGhlIHJlbW92ZWQgZWxlbWVudCBvciB1bmRlZmluZWQgaWYgbm9uZSBmb3VuZC5cbiAgICogQGFwaVxuICAgKi9cblxuXG4gIENvbGxlY3Rpb24ucHJvdG90eXBlLnJlbW92ZSA9IGZ1bmN0aW9uIChlbGVtKSB7XG4gICAgdmFyIGFyciA9IHRoaXMuYXJyYXlfO1xuXG4gICAgZm9yICh2YXIgaSA9IDAsIGlpID0gYXJyLmxlbmd0aDsgaSA8IGlpOyArK2kpIHtcbiAgICAgIGlmIChhcnJbaV0gPT09IGVsZW0pIHtcbiAgICAgICAgcmV0dXJuIHRoaXMucmVtb3ZlQXQoaSk7XG4gICAgICB9XG4gICAgfVxuXG4gICAgcmV0dXJuIHVuZGVmaW5lZDtcbiAgfTtcbiAgLyoqXG4gICAqIFJlbW92ZSB0aGUgZWxlbWVudCBhdCB0aGUgcHJvdmlkZWQgaW5kZXggYW5kIHJldHVybiBpdC5cbiAgICogUmV0dXJuIGB1bmRlZmluZWRgIGlmIHRoZSBjb2xsZWN0aW9uIGRvZXMgbm90IGNvbnRhaW4gdGhpcyBpbmRleC5cbiAgICogQHBhcmFtIHtudW1iZXJ9IGluZGV4IEluZGV4LlxuICAgKiBAcmV0dXJuIHtUfHVuZGVmaW5lZH0gVmFsdWUuXG4gICAqIEBhcGlcbiAgICovXG5cblxuICBDb2xsZWN0aW9uLnByb3RvdHlwZS5yZW1vdmVBdCA9IGZ1bmN0aW9uIChpbmRleCkge1xuICAgIHZhciBwcmV2ID0gdGhpcy5hcnJheV9baW5kZXhdO1xuICAgIHRoaXMuYXJyYXlfLnNwbGljZShpbmRleCwgMSk7XG4gICAgdGhpcy51cGRhdGVMZW5ndGhfKCk7XG4gICAgdGhpcy5kaXNwYXRjaEV2ZW50KG5ldyBDb2xsZWN0aW9uRXZlbnQoQ29sbGVjdGlvbkV2ZW50VHlwZS5SRU1PVkUsIHByZXYsIGluZGV4KSk7XG4gICAgcmV0dXJuIHByZXY7XG4gIH07XG4gIC8qKlxuICAgKiBTZXQgdGhlIGVsZW1lbnQgYXQgdGhlIHByb3ZpZGVkIGluZGV4LlxuICAgKiBAcGFyYW0ge251bWJlcn0gaW5kZXggSW5kZXguXG4gICAqIEBwYXJhbSB7VH0gZWxlbSBFbGVtZW50LlxuICAgKiBAYXBpXG4gICAqL1xuXG5cbiAgQ29sbGVjdGlvbi5wcm90b3R5cGUuc2V0QXQgPSBmdW5jdGlvbiAoaW5kZXgsIGVsZW0pIHtcbiAgICB2YXIgbiA9IHRoaXMuZ2V0TGVuZ3RoKCk7XG5cbiAgICBpZiAoaW5kZXggPCBuKSB7XG4gICAgICBpZiAodGhpcy51bmlxdWVfKSB7XG4gICAgICAgIHRoaXMuYXNzZXJ0VW5pcXVlXyhlbGVtLCBpbmRleCk7XG4gICAgICB9XG5cbiAgICAgIHZhciBwcmV2ID0gdGhpcy5hcnJheV9baW5kZXhdO1xuICAgICAgdGhpcy5hcnJheV9baW5kZXhdID0gZWxlbTtcbiAgICAgIHRoaXMuZGlzcGF0Y2hFdmVudChuZXcgQ29sbGVjdGlvbkV2ZW50KENvbGxlY3Rpb25FdmVudFR5cGUuUkVNT1ZFLCBwcmV2LCBpbmRleCkpO1xuICAgICAgdGhpcy5kaXNwYXRjaEV2ZW50KG5ldyBDb2xsZWN0aW9uRXZlbnQoQ29sbGVjdGlvbkV2ZW50VHlwZS5BREQsIGVsZW0sIGluZGV4KSk7XG4gICAgfSBlbHNlIHtcbiAgICAgIGZvciAodmFyIGogPSBuOyBqIDwgaW5kZXg7ICsraikge1xuICAgICAgICB0aGlzLmluc2VydEF0KGosIHVuZGVmaW5lZCk7XG4gICAgICB9XG5cbiAgICAgIHRoaXMuaW5zZXJ0QXQoaW5kZXgsIGVsZW0pO1xuICAgIH1cbiAgfTtcbiAgLyoqXG4gICAqIEBwcml2YXRlXG4gICAqL1xuXG5cbiAgQ29sbGVjdGlvbi5wcm90b3R5cGUudXBkYXRlTGVuZ3RoXyA9IGZ1bmN0aW9uICgpIHtcbiAgICB0aGlzLnNldChQcm9wZXJ0eS5MRU5HVEgsIHRoaXMuYXJyYXlfLmxlbmd0aCk7XG4gIH07XG4gIC8qKlxuICAgKiBAcHJpdmF0ZVxuICAgKiBAcGFyYW0ge1R9IGVsZW0gRWxlbWVudC5cbiAgICogQHBhcmFtIHtudW1iZXI9fSBvcHRfZXhjZXB0IE9wdGlvbmFsIGluZGV4IHRvIGlnbm9yZS5cbiAgICovXG5cblxuICBDb2xsZWN0aW9uLnByb3RvdHlwZS5hc3NlcnRVbmlxdWVfID0gZnVuY3Rpb24gKGVsZW0sIG9wdF9leGNlcHQpIHtcbiAgICBmb3IgKHZhciBpID0gMCwgaWkgPSB0aGlzLmFycmF5Xy5sZW5ndGg7IGkgPCBpaTsgKytpKSB7XG4gICAgICBpZiAodGhpcy5hcnJheV9baV0gPT09IGVsZW0gJiYgaSAhPT0gb3B0X2V4Y2VwdCkge1xuICAgICAgICB0aHJvdyBuZXcgQXNzZXJ0aW9uRXJyb3IoNTgpO1xuICAgICAgfVxuICAgIH1cbiAgfTtcblxuICByZXR1cm4gQ29sbGVjdGlvbjtcbn0oQmFzZU9iamVjdCk7XG5cbmV4cG9ydCBkZWZhdWx0IENvbGxlY3Rpb247IiwidmFyIF9fZXh0ZW5kcyA9IHRoaXMgJiYgdGhpcy5fX2V4dGVuZHMgfHwgZnVuY3Rpb24gKCkge1xuICB2YXIgX2V4dGVuZFN0YXRpY3MgPSBmdW5jdGlvbiBleHRlbmRTdGF0aWNzKGQsIGIpIHtcbiAgICBfZXh0ZW5kU3RhdGljcyA9IE9iamVjdC5zZXRQcm90b3R5cGVPZiB8fCB7XG4gICAgICBfX3Byb3RvX186IFtdXG4gICAgfSBpbnN0YW5jZW9mIEFycmF5ICYmIGZ1bmN0aW9uIChkLCBiKSB7XG4gICAgICBkLl9fcHJvdG9fXyA9IGI7XG4gICAgfSB8fCBmdW5jdGlvbiAoZCwgYikge1xuICAgICAgZm9yICh2YXIgcCBpbiBiKSB7XG4gICAgICAgIGlmIChPYmplY3QucHJvdG90eXBlLmhhc093blByb3BlcnR5LmNhbGwoYiwgcCkpIGRbcF0gPSBiW3BdO1xuICAgICAgfVxuICAgIH07XG5cbiAgICByZXR1cm4gX2V4dGVuZFN0YXRpY3MoZCwgYik7XG4gIH07XG5cbiAgcmV0dXJuIGZ1bmN0aW9uIChkLCBiKSB7XG4gICAgX2V4dGVuZFN0YXRpY3MoZCwgYik7XG5cbiAgICBmdW5jdGlvbiBfXygpIHtcbiAgICAgIHRoaXMuY29uc3RydWN0b3IgPSBkO1xuICAgIH1cblxuICAgIGQucHJvdG90eXBlID0gYiA9PT0gbnVsbCA/IE9iamVjdC5jcmVhdGUoYikgOiAoX18ucHJvdG90eXBlID0gYi5wcm90b3R5cGUsIG5ldyBfXygpKTtcbiAgfTtcbn0oKTtcbi8qKlxuICogQG1vZHVsZSBvbC9sYXllci9Hcm91cFxuICovXG5cblxuaW1wb3J0IEJhc2VMYXllciBmcm9tICcuL0Jhc2UuanMnO1xuaW1wb3J0IENvbGxlY3Rpb24gZnJvbSAnLi4vQ29sbGVjdGlvbi5qcyc7XG5pbXBvcnQgQ29sbGVjdGlvbkV2ZW50VHlwZSBmcm9tICcuLi9Db2xsZWN0aW9uRXZlbnRUeXBlLmpzJztcbmltcG9ydCBFdmVudFR5cGUgZnJvbSAnLi4vZXZlbnRzL0V2ZW50VHlwZS5qcyc7XG5pbXBvcnQgT2JqZWN0RXZlbnRUeXBlIGZyb20gJy4uL09iamVjdEV2ZW50VHlwZS5qcyc7XG5pbXBvcnQgU291cmNlU3RhdGUgZnJvbSAnLi4vc291cmNlL1N0YXRlLmpzJztcbmltcG9ydCB7IGFzc2VydCB9IGZyb20gJy4uL2Fzc2VydHMuanMnO1xuaW1wb3J0IHsgYXNzaWduLCBjbGVhciB9IGZyb20gJy4uL29iai5qcyc7XG5pbXBvcnQgeyBnZXRDaGFuZ2VFdmVudFR5cGUgfSBmcm9tICcuLi9PYmplY3QuanMnO1xuaW1wb3J0IHsgZ2V0SW50ZXJzZWN0aW9uIH0gZnJvbSAnLi4vZXh0ZW50LmpzJztcbmltcG9ydCB7IGdldFVpZCB9IGZyb20gJy4uL3V0aWwuanMnO1xuaW1wb3J0IHsgbGlzdGVuLCB1bmxpc3RlbkJ5S2V5IH0gZnJvbSAnLi4vZXZlbnRzLmpzJztcbi8qKlxuICogQHR5cGVkZWYge09iamVjdH0gT3B0aW9uc1xuICogQHByb3BlcnR5IHtudW1iZXJ9IFtvcGFjaXR5PTFdIE9wYWNpdHkgKDAsIDEpLlxuICogQHByb3BlcnR5IHtib29sZWFufSBbdmlzaWJsZT10cnVlXSBWaXNpYmlsaXR5LlxuICogQHByb3BlcnR5IHtpbXBvcnQoXCIuLi9leHRlbnQuanNcIikuRXh0ZW50fSBbZXh0ZW50XSBUaGUgYm91bmRpbmcgZXh0ZW50IGZvciBsYXllciByZW5kZXJpbmcuICBUaGUgbGF5ZXIgd2lsbCBub3QgYmVcbiAqIHJlbmRlcmVkIG91dHNpZGUgb2YgdGhpcyBleHRlbnQuXG4gKiBAcHJvcGVydHkge251bWJlcn0gW3pJbmRleF0gVGhlIHotaW5kZXggZm9yIGxheWVyIHJlbmRlcmluZy4gIEF0IHJlbmRlcmluZyB0aW1lLCB0aGUgbGF5ZXJzXG4gKiB3aWxsIGJlIG9yZGVyZWQsIGZpcnN0IGJ5IFotaW5kZXggYW5kIHRoZW4gYnkgcG9zaXRpb24uIFdoZW4gYHVuZGVmaW5lZGAsIGEgYHpJbmRleGAgb2YgMCBpcyBhc3N1bWVkXG4gKiBmb3IgbGF5ZXJzIHRoYXQgYXJlIGFkZGVkIHRvIHRoZSBtYXAncyBgbGF5ZXJzYCBjb2xsZWN0aW9uLCBvciBgSW5maW5pdHlgIHdoZW4gdGhlIGxheWVyJ3MgYHNldE1hcCgpYFxuICogbWV0aG9kIHdhcyB1c2VkLlxuICogQHByb3BlcnR5IHtudW1iZXJ9IFttaW5SZXNvbHV0aW9uXSBUaGUgbWluaW11bSByZXNvbHV0aW9uIChpbmNsdXNpdmUpIGF0IHdoaWNoIHRoaXMgbGF5ZXIgd2lsbCBiZVxuICogdmlzaWJsZS5cbiAqIEBwcm9wZXJ0eSB7bnVtYmVyfSBbbWF4UmVzb2x1dGlvbl0gVGhlIG1heGltdW0gcmVzb2x1dGlvbiAoZXhjbHVzaXZlKSBiZWxvdyB3aGljaCB0aGlzIGxheWVyIHdpbGxcbiAqIGJlIHZpc2libGUuXG4gKiBAcHJvcGVydHkge251bWJlcn0gW21pblpvb21dIFRoZSBtaW5pbXVtIHZpZXcgem9vbSBsZXZlbCAoZXhjbHVzaXZlKSBhYm92ZSB3aGljaCB0aGlzIGxheWVyIHdpbGwgYmVcbiAqIHZpc2libGUuXG4gKiBAcHJvcGVydHkge251bWJlcn0gW21heFpvb21dIFRoZSBtYXhpbXVtIHZpZXcgem9vbSBsZXZlbCAoaW5jbHVzaXZlKSBhdCB3aGljaCB0aGlzIGxheWVyIHdpbGxcbiAqIGJlIHZpc2libGUuXG4gKiBAcHJvcGVydHkge251bWJlcn0gW21pblpvb21dIFRoZSBtaW5pbXVtIHZpZXcgem9vbSBsZXZlbCAoZXhjbHVzaXZlKSBhYm92ZSB3aGljaCB0aGlzIGxheWVyIHdpbGwgYmVcbiAqIHZpc2libGUuXG4gKiBAcHJvcGVydHkge251bWJlcn0gW21heFpvb21dIFRoZSBtYXhpbXVtIHZpZXcgem9vbSBsZXZlbCAoaW5jbHVzaXZlKSBhdCB3aGljaCB0aGlzIGxheWVyIHdpbGxcbiAqIGJlIHZpc2libGUuXG4gKiBAcHJvcGVydHkge0FycmF5PGltcG9ydChcIi4vQmFzZS5qc1wiKS5kZWZhdWx0PnxpbXBvcnQoXCIuLi9Db2xsZWN0aW9uLmpzXCIpLmRlZmF1bHQ8aW1wb3J0KFwiLi9CYXNlLmpzXCIpLmRlZmF1bHQ+fSBbbGF5ZXJzXSBDaGlsZCBsYXllcnMuXG4gKi9cblxuLyoqXG4gKiBAZW51bSB7c3RyaW5nfVxuICogQHByaXZhdGVcbiAqL1xuXG52YXIgUHJvcGVydHkgPSB7XG4gIExBWUVSUzogJ2xheWVycydcbn07XG4vKipcbiAqIEBjbGFzc2Rlc2NcbiAqIEEge0BsaW5rIG1vZHVsZTpvbC9Db2xsZWN0aW9ufkNvbGxlY3Rpb259IG9mIGxheWVycyB0aGF0IGFyZSBoYW5kbGVkIHRvZ2V0aGVyLlxuICpcbiAqIEEgZ2VuZXJpYyBgY2hhbmdlYCBldmVudCBpcyB0cmlnZ2VyZWQgd2hlbiB0aGUgZ3JvdXAvQ29sbGVjdGlvbiBjaGFuZ2VzLlxuICpcbiAqIEBhcGlcbiAqL1xuXG52YXIgTGF5ZXJHcm91cCA9XG4vKiogQGNsYXNzICovXG5mdW5jdGlvbiAoX3N1cGVyKSB7XG4gIF9fZXh0ZW5kcyhMYXllckdyb3VwLCBfc3VwZXIpO1xuICAvKipcbiAgICogQHBhcmFtIHtPcHRpb25zPX0gb3B0X29wdGlvbnMgTGF5ZXIgb3B0aW9ucy5cbiAgICovXG5cblxuICBmdW5jdGlvbiBMYXllckdyb3VwKG9wdF9vcHRpb25zKSB7XG4gICAgdmFyIF90aGlzID0gdGhpcztcblxuICAgIHZhciBvcHRpb25zID0gb3B0X29wdGlvbnMgfHwge307XG4gICAgdmFyIGJhc2VPcHRpb25zID1cbiAgICAvKiogQHR5cGUge09wdGlvbnN9ICovXG4gICAgYXNzaWduKHt9LCBvcHRpb25zKTtcbiAgICBkZWxldGUgYmFzZU9wdGlvbnMubGF5ZXJzO1xuICAgIHZhciBsYXllcnMgPSBvcHRpb25zLmxheWVycztcbiAgICBfdGhpcyA9IF9zdXBlci5jYWxsKHRoaXMsIGJhc2VPcHRpb25zKSB8fCB0aGlzO1xuICAgIC8qKlxuICAgICAqIEBwcml2YXRlXG4gICAgICogQHR5cGUge0FycmF5PGltcG9ydChcIi4uL2V2ZW50cy5qc1wiKS5FdmVudHNLZXk+fVxuICAgICAqL1xuXG4gICAgX3RoaXMubGF5ZXJzTGlzdGVuZXJLZXlzXyA9IFtdO1xuICAgIC8qKlxuICAgICAqIEBwcml2YXRlXG4gICAgICogQHR5cGUge09iamVjdDxzdHJpbmcsIEFycmF5PGltcG9ydChcIi4uL2V2ZW50cy5qc1wiKS5FdmVudHNLZXk+Pn1cbiAgICAgKi9cblxuICAgIF90aGlzLmxpc3RlbmVyS2V5c18gPSB7fTtcblxuICAgIF90aGlzLmFkZEV2ZW50TGlzdGVuZXIoZ2V0Q2hhbmdlRXZlbnRUeXBlKFByb3BlcnR5LkxBWUVSUyksIF90aGlzLmhhbmRsZUxheWVyc0NoYW5nZWRfKTtcblxuICAgIGlmIChsYXllcnMpIHtcbiAgICAgIGlmIChBcnJheS5pc0FycmF5KGxheWVycykpIHtcbiAgICAgICAgbGF5ZXJzID0gbmV3IENvbGxlY3Rpb24obGF5ZXJzLnNsaWNlKCksIHtcbiAgICAgICAgICB1bmlxdWU6IHRydWVcbiAgICAgICAgfSk7XG4gICAgICB9IGVsc2Uge1xuICAgICAgICBhc3NlcnQodHlwZW9mXG4gICAgICAgIC8qKiBAdHlwZSB7P30gKi9cbiAgICAgICAgbGF5ZXJzLmdldEFycmF5ID09PSAnZnVuY3Rpb24nLCA0Myk7IC8vIEV4cGVjdGVkIGBsYXllcnNgIHRvIGJlIGFuIGFycmF5IG9yIGEgYENvbGxlY3Rpb25gXG4gICAgICB9XG4gICAgfSBlbHNlIHtcbiAgICAgIGxheWVycyA9IG5ldyBDb2xsZWN0aW9uKHVuZGVmaW5lZCwge1xuICAgICAgICB1bmlxdWU6IHRydWVcbiAgICAgIH0pO1xuICAgIH1cblxuICAgIF90aGlzLnNldExheWVycyhsYXllcnMpO1xuXG4gICAgcmV0dXJuIF90aGlzO1xuICB9XG4gIC8qKlxuICAgKiBAcHJpdmF0ZVxuICAgKi9cblxuXG4gIExheWVyR3JvdXAucHJvdG90eXBlLmhhbmRsZUxheWVyQ2hhbmdlXyA9IGZ1bmN0aW9uICgpIHtcbiAgICB0aGlzLmNoYW5nZWQoKTtcbiAgfTtcbiAgLyoqXG4gICAqIEBwcml2YXRlXG4gICAqL1xuXG5cbiAgTGF5ZXJHcm91cC5wcm90b3R5cGUuaGFuZGxlTGF5ZXJzQ2hhbmdlZF8gPSBmdW5jdGlvbiAoKSB7XG4gICAgdGhpcy5sYXllcnNMaXN0ZW5lcktleXNfLmZvckVhY2godW5saXN0ZW5CeUtleSk7XG4gICAgdGhpcy5sYXllcnNMaXN0ZW5lcktleXNfLmxlbmd0aCA9IDA7XG4gICAgdmFyIGxheWVycyA9IHRoaXMuZ2V0TGF5ZXJzKCk7XG4gICAgdGhpcy5sYXllcnNMaXN0ZW5lcktleXNfLnB1c2gobGlzdGVuKGxheWVycywgQ29sbGVjdGlvbkV2ZW50VHlwZS5BREQsIHRoaXMuaGFuZGxlTGF5ZXJzQWRkXywgdGhpcyksIGxpc3RlbihsYXllcnMsIENvbGxlY3Rpb25FdmVudFR5cGUuUkVNT1ZFLCB0aGlzLmhhbmRsZUxheWVyc1JlbW92ZV8sIHRoaXMpKTtcblxuICAgIGZvciAodmFyIGlkIGluIHRoaXMubGlzdGVuZXJLZXlzXykge1xuICAgICAgdGhpcy5saXN0ZW5lcktleXNfW2lkXS5mb3JFYWNoKHVubGlzdGVuQnlLZXkpO1xuICAgIH1cblxuICAgIGNsZWFyKHRoaXMubGlzdGVuZXJLZXlzXyk7XG4gICAgdmFyIGxheWVyc0FycmF5ID0gbGF5ZXJzLmdldEFycmF5KCk7XG5cbiAgICBmb3IgKHZhciBpID0gMCwgaWkgPSBsYXllcnNBcnJheS5sZW5ndGg7IGkgPCBpaTsgaSsrKSB7XG4gICAgICB2YXIgbGF5ZXIgPSBsYXllcnNBcnJheVtpXTtcbiAgICAgIHRoaXMubGlzdGVuZXJLZXlzX1tnZXRVaWQobGF5ZXIpXSA9IFtsaXN0ZW4obGF5ZXIsIE9iamVjdEV2ZW50VHlwZS5QUk9QRVJUWUNIQU5HRSwgdGhpcy5oYW5kbGVMYXllckNoYW5nZV8sIHRoaXMpLCBsaXN0ZW4obGF5ZXIsIEV2ZW50VHlwZS5DSEFOR0UsIHRoaXMuaGFuZGxlTGF5ZXJDaGFuZ2VfLCB0aGlzKV07XG4gICAgfVxuXG4gICAgdGhpcy5jaGFuZ2VkKCk7XG4gIH07XG4gIC8qKlxuICAgKiBAcGFyYW0ge2ltcG9ydChcIi4uL0NvbGxlY3Rpb24uanNcIikuQ29sbGVjdGlvbkV2ZW50fSBjb2xsZWN0aW9uRXZlbnQgQ29sbGVjdGlvbkV2ZW50LlxuICAgKiBAcHJpdmF0ZVxuICAgKi9cblxuXG4gIExheWVyR3JvdXAucHJvdG90eXBlLmhhbmRsZUxheWVyc0FkZF8gPSBmdW5jdGlvbiAoY29sbGVjdGlvbkV2ZW50KSB7XG4gICAgdmFyIGxheWVyID1cbiAgICAvKiogQHR5cGUge2ltcG9ydChcIi4vQmFzZS5qc1wiKS5kZWZhdWx0fSAqL1xuICAgIGNvbGxlY3Rpb25FdmVudC5lbGVtZW50O1xuICAgIHRoaXMubGlzdGVuZXJLZXlzX1tnZXRVaWQobGF5ZXIpXSA9IFtsaXN0ZW4obGF5ZXIsIE9iamVjdEV2ZW50VHlwZS5QUk9QRVJUWUNIQU5HRSwgdGhpcy5oYW5kbGVMYXllckNoYW5nZV8sIHRoaXMpLCBsaXN0ZW4obGF5ZXIsIEV2ZW50VHlwZS5DSEFOR0UsIHRoaXMuaGFuZGxlTGF5ZXJDaGFuZ2VfLCB0aGlzKV07XG4gICAgdGhpcy5jaGFuZ2VkKCk7XG4gIH07XG4gIC8qKlxuICAgKiBAcGFyYW0ge2ltcG9ydChcIi4uL0NvbGxlY3Rpb24uanNcIikuQ29sbGVjdGlvbkV2ZW50fSBjb2xsZWN0aW9uRXZlbnQgQ29sbGVjdGlvbkV2ZW50LlxuICAgKiBAcHJpdmF0ZVxuICAgKi9cblxuXG4gIExheWVyR3JvdXAucHJvdG90eXBlLmhhbmRsZUxheWVyc1JlbW92ZV8gPSBmdW5jdGlvbiAoY29sbGVjdGlvbkV2ZW50KSB7XG4gICAgdmFyIGxheWVyID1cbiAgICAvKiogQHR5cGUge2ltcG9ydChcIi4vQmFzZS5qc1wiKS5kZWZhdWx0fSAqL1xuICAgIGNvbGxlY3Rpb25FdmVudC5lbGVtZW50O1xuICAgIHZhciBrZXkgPSBnZXRVaWQobGF5ZXIpO1xuICAgIHRoaXMubGlzdGVuZXJLZXlzX1trZXldLmZvckVhY2godW5saXN0ZW5CeUtleSk7XG4gICAgZGVsZXRlIHRoaXMubGlzdGVuZXJLZXlzX1trZXldO1xuICAgIHRoaXMuY2hhbmdlZCgpO1xuICB9O1xuICAvKipcbiAgICogUmV0dXJucyB0aGUge0BsaW5rIG1vZHVsZTpvbC9Db2xsZWN0aW9uIGNvbGxlY3Rpb259IG9mIHtAbGluayBtb2R1bGU6b2wvbGF5ZXIvTGF5ZXJ+TGF5ZXIgbGF5ZXJzfVxuICAgKiBpbiB0aGlzIGdyb3VwLlxuICAgKiBAcmV0dXJuIHshaW1wb3J0KFwiLi4vQ29sbGVjdGlvbi5qc1wiKS5kZWZhdWx0PGltcG9ydChcIi4vQmFzZS5qc1wiKS5kZWZhdWx0Pn0gQ29sbGVjdGlvbiBvZlxuICAgKiAgIHtAbGluayBtb2R1bGU6b2wvbGF5ZXIvQmFzZSBsYXllcnN9IHRoYXQgYXJlIHBhcnQgb2YgdGhpcyBncm91cC5cbiAgICogQG9ic2VydmFibGVcbiAgICogQGFwaVxuICAgKi9cblxuXG4gIExheWVyR3JvdXAucHJvdG90eXBlLmdldExheWVycyA9IGZ1bmN0aW9uICgpIHtcbiAgICByZXR1cm4gKFxuICAgICAgLyoqIEB0eXBlIHshaW1wb3J0KFwiLi4vQ29sbGVjdGlvbi5qc1wiKS5kZWZhdWx0PGltcG9ydChcIi4vQmFzZS5qc1wiKS5kZWZhdWx0Pn0gKi9cbiAgICAgIHRoaXMuZ2V0KFByb3BlcnR5LkxBWUVSUylcbiAgICApO1xuICB9O1xuICAvKipcbiAgICogU2V0IHRoZSB7QGxpbmsgbW9kdWxlOm9sL0NvbGxlY3Rpb24gY29sbGVjdGlvbn0gb2Yge0BsaW5rIG1vZHVsZTpvbC9sYXllci9MYXllcn5MYXllciBsYXllcnN9XG4gICAqIGluIHRoaXMgZ3JvdXAuXG4gICAqIEBwYXJhbSB7IWltcG9ydChcIi4uL0NvbGxlY3Rpb24uanNcIikuZGVmYXVsdDxpbXBvcnQoXCIuL0Jhc2UuanNcIikuZGVmYXVsdD59IGxheWVycyBDb2xsZWN0aW9uIG9mXG4gICAqICAge0BsaW5rIG1vZHVsZTpvbC9sYXllci9CYXNlIGxheWVyc30gdGhhdCBhcmUgcGFydCBvZiB0aGlzIGdyb3VwLlxuICAgKiBAb2JzZXJ2YWJsZVxuICAgKiBAYXBpXG4gICAqL1xuXG5cbiAgTGF5ZXJHcm91cC5wcm90b3R5cGUuc2V0TGF5ZXJzID0gZnVuY3Rpb24gKGxheWVycykge1xuICAgIHRoaXMuc2V0KFByb3BlcnR5LkxBWUVSUywgbGF5ZXJzKTtcbiAgfTtcbiAgLyoqXG4gICAqIEBwYXJhbSB7QXJyYXk8aW1wb3J0KFwiLi9MYXllci5qc1wiKS5kZWZhdWx0Pj19IG9wdF9hcnJheSBBcnJheSBvZiBsYXllcnMgKHRvIGJlIG1vZGlmaWVkIGluIHBsYWNlKS5cbiAgICogQHJldHVybiB7QXJyYXk8aW1wb3J0KFwiLi9MYXllci5qc1wiKS5kZWZhdWx0Pn0gQXJyYXkgb2YgbGF5ZXJzLlxuICAgKi9cblxuXG4gIExheWVyR3JvdXAucHJvdG90eXBlLmdldExheWVyc0FycmF5ID0gZnVuY3Rpb24gKG9wdF9hcnJheSkge1xuICAgIHZhciBhcnJheSA9IG9wdF9hcnJheSAhPT0gdW5kZWZpbmVkID8gb3B0X2FycmF5IDogW107XG4gICAgdGhpcy5nZXRMYXllcnMoKS5mb3JFYWNoKGZ1bmN0aW9uIChsYXllcikge1xuICAgICAgbGF5ZXIuZ2V0TGF5ZXJzQXJyYXkoYXJyYXkpO1xuICAgIH0pO1xuICAgIHJldHVybiBhcnJheTtcbiAgfTtcbiAgLyoqXG4gICAqIEBwYXJhbSB7QXJyYXk8aW1wb3J0KFwiLi9MYXllci5qc1wiKS5TdGF0ZT49fSBvcHRfc3RhdGVzIE9wdGlvbmFsIGxpc3Qgb2YgbGF5ZXIgc3RhdGVzICh0byBiZSBtb2RpZmllZCBpbiBwbGFjZSkuXG4gICAqIEByZXR1cm4ge0FycmF5PGltcG9ydChcIi4vTGF5ZXIuanNcIikuU3RhdGU+fSBMaXN0IG9mIGxheWVyIHN0YXRlcy5cbiAgICovXG5cblxuICBMYXllckdyb3VwLnByb3RvdHlwZS5nZXRMYXllclN0YXRlc0FycmF5ID0gZnVuY3Rpb24gKG9wdF9zdGF0ZXMpIHtcbiAgICB2YXIgc3RhdGVzID0gb3B0X3N0YXRlcyAhPT0gdW5kZWZpbmVkID8gb3B0X3N0YXRlcyA6IFtdO1xuICAgIHZhciBwb3MgPSBzdGF0ZXMubGVuZ3RoO1xuICAgIHRoaXMuZ2V0TGF5ZXJzKCkuZm9yRWFjaChmdW5jdGlvbiAobGF5ZXIpIHtcbiAgICAgIGxheWVyLmdldExheWVyU3RhdGVzQXJyYXkoc3RhdGVzKTtcbiAgICB9KTtcbiAgICB2YXIgb3duTGF5ZXJTdGF0ZSA9IHRoaXMuZ2V0TGF5ZXJTdGF0ZSgpO1xuXG4gICAgZm9yICh2YXIgaSA9IHBvcywgaWkgPSBzdGF0ZXMubGVuZ3RoOyBpIDwgaWk7IGkrKykge1xuICAgICAgdmFyIGxheWVyU3RhdGUgPSBzdGF0ZXNbaV07XG4gICAgICBsYXllclN0YXRlLm9wYWNpdHkgKj0gb3duTGF5ZXJTdGF0ZS5vcGFjaXR5O1xuICAgICAgbGF5ZXJTdGF0ZS52aXNpYmxlID0gbGF5ZXJTdGF0ZS52aXNpYmxlICYmIG93bkxheWVyU3RhdGUudmlzaWJsZTtcbiAgICAgIGxheWVyU3RhdGUubWF4UmVzb2x1dGlvbiA9IE1hdGgubWluKGxheWVyU3RhdGUubWF4UmVzb2x1dGlvbiwgb3duTGF5ZXJTdGF0ZS5tYXhSZXNvbHV0aW9uKTtcbiAgICAgIGxheWVyU3RhdGUubWluUmVzb2x1dGlvbiA9IE1hdGgubWF4KGxheWVyU3RhdGUubWluUmVzb2x1dGlvbiwgb3duTGF5ZXJTdGF0ZS5taW5SZXNvbHV0aW9uKTtcbiAgICAgIGxheWVyU3RhdGUubWluWm9vbSA9IE1hdGgubWF4KGxheWVyU3RhdGUubWluWm9vbSwgb3duTGF5ZXJTdGF0ZS5taW5ab29tKTtcbiAgICAgIGxheWVyU3RhdGUubWF4Wm9vbSA9IE1hdGgubWluKGxheWVyU3RhdGUubWF4Wm9vbSwgb3duTGF5ZXJTdGF0ZS5tYXhab29tKTtcblxuICAgICAgaWYgKG93bkxheWVyU3RhdGUuZXh0ZW50ICE9PSB1bmRlZmluZWQpIHtcbiAgICAgICAgaWYgKGxheWVyU3RhdGUuZXh0ZW50ICE9PSB1bmRlZmluZWQpIHtcbiAgICAgICAgICBsYXllclN0YXRlLmV4dGVudCA9IGdldEludGVyc2VjdGlvbihsYXllclN0YXRlLmV4dGVudCwgb3duTGF5ZXJTdGF0ZS5leHRlbnQpO1xuICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgIGxheWVyU3RhdGUuZXh0ZW50ID0gb3duTGF5ZXJTdGF0ZS5leHRlbnQ7XG4gICAgICAgIH1cbiAgICAgIH1cbiAgICB9XG5cbiAgICByZXR1cm4gc3RhdGVzO1xuICB9O1xuICAvKipcbiAgICogQHJldHVybiB7aW1wb3J0KFwiLi4vc291cmNlL1N0YXRlLmpzXCIpLmRlZmF1bHR9IFNvdXJjZSBzdGF0ZS5cbiAgICovXG5cblxuICBMYXllckdyb3VwLnByb3RvdHlwZS5nZXRTb3VyY2VTdGF0ZSA9IGZ1bmN0aW9uICgpIHtcbiAgICByZXR1cm4gU291cmNlU3RhdGUuUkVBRFk7XG4gIH07XG5cbiAgcmV0dXJuIExheWVyR3JvdXA7XG59KEJhc2VMYXllcik7XG5cbmV4cG9ydCBkZWZhdWx0IExheWVyR3JvdXA7IiwidmFyIF9fZXh0ZW5kcyA9IHRoaXMgJiYgdGhpcy5fX2V4dGVuZHMgfHwgZnVuY3Rpb24gKCkge1xuICB2YXIgX2V4dGVuZFN0YXRpY3MgPSBmdW5jdGlvbiBleHRlbmRTdGF0aWNzKGQsIGIpIHtcbiAgICBfZXh0ZW5kU3RhdGljcyA9IE9iamVjdC5zZXRQcm90b3R5cGVPZiB8fCB7XG4gICAgICBfX3Byb3RvX186IFtdXG4gICAgfSBpbnN0YW5jZW9mIEFycmF5ICYmIGZ1bmN0aW9uIChkLCBiKSB7XG4gICAgICBkLl9fcHJvdG9fXyA9IGI7XG4gICAgfSB8fCBmdW5jdGlvbiAoZCwgYikge1xuICAgICAgZm9yICh2YXIgcCBpbiBiKSB7XG4gICAgICAgIGlmIChPYmplY3QucHJvdG90eXBlLmhhc093blByb3BlcnR5LmNhbGwoYiwgcCkpIGRbcF0gPSBiW3BdO1xuICAgICAgfVxuICAgIH07XG5cbiAgICByZXR1cm4gX2V4dGVuZFN0YXRpY3MoZCwgYik7XG4gIH07XG5cbiAgcmV0dXJuIGZ1bmN0aW9uIChkLCBiKSB7XG4gICAgX2V4dGVuZFN0YXRpY3MoZCwgYik7XG5cbiAgICBmdW5jdGlvbiBfXygpIHtcbiAgICAgIHRoaXMuY29uc3RydWN0b3IgPSBkO1xuICAgIH1cblxuICAgIGQucHJvdG90eXBlID0gYiA9PT0gbnVsbCA/IE9iamVjdC5jcmVhdGUoYikgOiAoX18ucHJvdG90eXBlID0gYi5wcm90b3R5cGUsIG5ldyBfXygpKTtcbiAgfTtcbn0oKTtcbi8qKlxuICogQG1vZHVsZSBvbC9NYXBFdmVudFxuICovXG5cblxuaW1wb3J0IEV2ZW50IGZyb20gJy4vZXZlbnRzL0V2ZW50LmpzJztcbi8qKlxuICogQGNsYXNzZGVzY1xuICogRXZlbnRzIGVtaXR0ZWQgYXMgbWFwIGV2ZW50cyBhcmUgaW5zdGFuY2VzIG9mIHRoaXMgdHlwZS5cbiAqIFNlZSB7QGxpbmsgbW9kdWxlOm9sL1BsdWdnYWJsZU1hcH5QbHVnZ2FibGVNYXB9IGZvciB3aGljaCBldmVudHMgdHJpZ2dlciBhIG1hcCBldmVudC5cbiAqL1xuXG52YXIgTWFwRXZlbnQgPVxuLyoqIEBjbGFzcyAqL1xuZnVuY3Rpb24gKF9zdXBlcikge1xuICBfX2V4dGVuZHMoTWFwRXZlbnQsIF9zdXBlcik7XG4gIC8qKlxuICAgKiBAcGFyYW0ge3N0cmluZ30gdHlwZSBFdmVudCB0eXBlLlxuICAgKiBAcGFyYW0ge2ltcG9ydChcIi4vUGx1Z2dhYmxlTWFwLmpzXCIpLmRlZmF1bHR9IG1hcCBNYXAuXG4gICAqIEBwYXJhbSB7P2ltcG9ydChcIi4vUGx1Z2dhYmxlTWFwLmpzXCIpLkZyYW1lU3RhdGU9fSBvcHRfZnJhbWVTdGF0ZSBGcmFtZSBzdGF0ZS5cbiAgICovXG5cblxuICBmdW5jdGlvbiBNYXBFdmVudCh0eXBlLCBtYXAsIG9wdF9mcmFtZVN0YXRlKSB7XG4gICAgdmFyIF90aGlzID0gX3N1cGVyLmNhbGwodGhpcywgdHlwZSkgfHwgdGhpcztcbiAgICAvKipcbiAgICAgKiBUaGUgbWFwIHdoZXJlIHRoZSBldmVudCBvY2N1cnJlZC5cbiAgICAgKiBAdHlwZSB7aW1wb3J0KFwiLi9QbHVnZ2FibGVNYXAuanNcIikuZGVmYXVsdH1cbiAgICAgKiBAYXBpXG4gICAgICovXG5cblxuICAgIF90aGlzLm1hcCA9IG1hcDtcbiAgICAvKipcbiAgICAgKiBUaGUgZnJhbWUgc3RhdGUgYXQgdGhlIHRpbWUgb2YgdGhlIGV2ZW50LlxuICAgICAqIEB0eXBlIHs/aW1wb3J0KFwiLi9QbHVnZ2FibGVNYXAuanNcIikuRnJhbWVTdGF0ZX1cbiAgICAgKiBAYXBpXG4gICAgICovXG5cbiAgICBfdGhpcy5mcmFtZVN0YXRlID0gb3B0X2ZyYW1lU3RhdGUgIT09IHVuZGVmaW5lZCA/IG9wdF9mcmFtZVN0YXRlIDogbnVsbDtcbiAgICByZXR1cm4gX3RoaXM7XG4gIH1cblxuICByZXR1cm4gTWFwRXZlbnQ7XG59KEV2ZW50KTtcblxuZXhwb3J0IGRlZmF1bHQgTWFwRXZlbnQ7IiwidmFyIF9fZXh0ZW5kcyA9IHRoaXMgJiYgdGhpcy5fX2V4dGVuZHMgfHwgZnVuY3Rpb24gKCkge1xuICB2YXIgX2V4dGVuZFN0YXRpY3MgPSBmdW5jdGlvbiBleHRlbmRTdGF0aWNzKGQsIGIpIHtcbiAgICBfZXh0ZW5kU3RhdGljcyA9IE9iamVjdC5zZXRQcm90b3R5cGVPZiB8fCB7XG4gICAgICBfX3Byb3RvX186IFtdXG4gICAgfSBpbnN0YW5jZW9mIEFycmF5ICYmIGZ1bmN0aW9uIChkLCBiKSB7XG4gICAgICBkLl9fcHJvdG9fXyA9IGI7XG4gICAgfSB8fCBmdW5jdGlvbiAoZCwgYikge1xuICAgICAgZm9yICh2YXIgcCBpbiBiKSB7XG4gICAgICAgIGlmIChPYmplY3QucHJvdG90eXBlLmhhc093blByb3BlcnR5LmNhbGwoYiwgcCkpIGRbcF0gPSBiW3BdO1xuICAgICAgfVxuICAgIH07XG5cbiAgICByZXR1cm4gX2V4dGVuZFN0YXRpY3MoZCwgYik7XG4gIH07XG5cbiAgcmV0dXJuIGZ1bmN0aW9uIChkLCBiKSB7XG4gICAgX2V4dGVuZFN0YXRpY3MoZCwgYik7XG5cbiAgICBmdW5jdGlvbiBfXygpIHtcbiAgICAgIHRoaXMuY29uc3RydWN0b3IgPSBkO1xuICAgIH1cblxuICAgIGQucHJvdG90eXBlID0gYiA9PT0gbnVsbCA/IE9iamVjdC5jcmVhdGUoYikgOiAoX18ucHJvdG90eXBlID0gYi5wcm90b3R5cGUsIG5ldyBfXygpKTtcbiAgfTtcbn0oKTtcbi8qKlxuICogQG1vZHVsZSBvbC9NYXBCcm93c2VyRXZlbnRcbiAqL1xuXG5cbmltcG9ydCBNYXBFdmVudCBmcm9tICcuL01hcEV2ZW50LmpzJztcbi8qKlxuICogQGNsYXNzZGVzY1xuICogRXZlbnRzIGVtaXR0ZWQgYXMgbWFwIGJyb3dzZXIgZXZlbnRzIGFyZSBpbnN0YW5jZXMgb2YgdGhpcyB0eXBlLlxuICogU2VlIHtAbGluayBtb2R1bGU6b2wvUGx1Z2dhYmxlTWFwflBsdWdnYWJsZU1hcH0gZm9yIHdoaWNoIGV2ZW50cyB0cmlnZ2VyIGEgbWFwIGJyb3dzZXIgZXZlbnQuXG4gKiBAdGVtcGxhdGUge1VJRXZlbnR9IEVWRU5UXG4gKi9cblxudmFyIE1hcEJyb3dzZXJFdmVudCA9XG4vKiogQGNsYXNzICovXG5mdW5jdGlvbiAoX3N1cGVyKSB7XG4gIF9fZXh0ZW5kcyhNYXBCcm93c2VyRXZlbnQsIF9zdXBlcik7XG4gIC8qKlxuICAgKiBAcGFyYW0ge3N0cmluZ30gdHlwZSBFdmVudCB0eXBlLlxuICAgKiBAcGFyYW0ge2ltcG9ydChcIi4vUGx1Z2dhYmxlTWFwLmpzXCIpLmRlZmF1bHR9IG1hcCBNYXAuXG4gICAqIEBwYXJhbSB7RVZFTlR9IG9yaWdpbmFsRXZlbnQgT3JpZ2luYWwgZXZlbnQuXG4gICAqIEBwYXJhbSB7Ym9vbGVhbj19IG9wdF9kcmFnZ2luZyBJcyB0aGUgbWFwIGN1cnJlbnRseSBiZWluZyBkcmFnZ2VkP1xuICAgKiBAcGFyYW0gez9pbXBvcnQoXCIuL1BsdWdnYWJsZU1hcC5qc1wiKS5GcmFtZVN0YXRlPX0gb3B0X2ZyYW1lU3RhdGUgRnJhbWUgc3RhdGUuXG4gICAqL1xuXG5cbiAgZnVuY3Rpb24gTWFwQnJvd3NlckV2ZW50KHR5cGUsIG1hcCwgb3JpZ2luYWxFdmVudCwgb3B0X2RyYWdnaW5nLCBvcHRfZnJhbWVTdGF0ZSkge1xuICAgIHZhciBfdGhpcyA9IF9zdXBlci5jYWxsKHRoaXMsIHR5cGUsIG1hcCwgb3B0X2ZyYW1lU3RhdGUpIHx8IHRoaXM7XG4gICAgLyoqXG4gICAgICogVGhlIG9yaWdpbmFsIGJyb3dzZXIgZXZlbnQuXG4gICAgICogQGNvbnN0XG4gICAgICogQHR5cGUge0VWRU5UfVxuICAgICAqIEBhcGlcbiAgICAgKi9cblxuXG4gICAgX3RoaXMub3JpZ2luYWxFdmVudCA9IG9yaWdpbmFsRXZlbnQ7XG4gICAgLyoqXG4gICAgICogVGhlIG1hcCBwaXhlbCByZWxhdGl2ZSB0byB0aGUgdmlld3BvcnQgY29ycmVzcG9uZGluZyB0byB0aGUgb3JpZ2luYWwgYnJvd3NlciBldmVudC5cbiAgICAgKiBAdHlwZSB7P2ltcG9ydChcIi4vcGl4ZWwuanNcIikuUGl4ZWx9XG4gICAgICovXG5cbiAgICBfdGhpcy5waXhlbF8gPSBudWxsO1xuICAgIC8qKlxuICAgICAqIFRoZSBjb29yZGluYXRlIGluIHRoZSB1c2VyIHByb2plY3Rpb24gY29ycmVzcG9uZGluZyB0byB0aGUgb3JpZ2luYWwgYnJvd3NlciBldmVudC5cbiAgICAgKiBAdHlwZSB7P2ltcG9ydChcIi4vY29vcmRpbmF0ZS5qc1wiKS5Db29yZGluYXRlfVxuICAgICAqL1xuXG4gICAgX3RoaXMuY29vcmRpbmF0ZV8gPSBudWxsO1xuICAgIC8qKlxuICAgICAqIEluZGljYXRlcyBpZiB0aGUgbWFwIGlzIGN1cnJlbnRseSBiZWluZyBkcmFnZ2VkLiBPbmx5IHNldCBmb3JcbiAgICAgKiBgUE9JTlRFUkRSQUdgIGFuZCBgUE9JTlRFUk1PVkVgIGV2ZW50cy4gRGVmYXVsdCBpcyBgZmFsc2VgLlxuICAgICAqXG4gICAgICogQHR5cGUge2Jvb2xlYW59XG4gICAgICogQGFwaVxuICAgICAqL1xuXG4gICAgX3RoaXMuZHJhZ2dpbmcgPSBvcHRfZHJhZ2dpbmcgIT09IHVuZGVmaW5lZCA/IG9wdF9kcmFnZ2luZyA6IGZhbHNlO1xuICAgIHJldHVybiBfdGhpcztcbiAgfVxuXG4gIE9iamVjdC5kZWZpbmVQcm9wZXJ0eShNYXBCcm93c2VyRXZlbnQucHJvdG90eXBlLCBcInBpeGVsXCIsIHtcbiAgICAvKipcbiAgICAgKiBUaGUgbWFwIHBpeGVsIHJlbGF0aXZlIHRvIHRoZSB2aWV3cG9ydCBjb3JyZXNwb25kaW5nIHRvIHRoZSBvcmlnaW5hbCBldmVudC5cbiAgICAgKiBAdHlwZSB7aW1wb3J0KFwiLi9waXhlbC5qc1wiKS5QaXhlbH1cbiAgICAgKiBAYXBpXG4gICAgICovXG4gICAgZ2V0OiBmdW5jdGlvbiBnZXQoKSB7XG4gICAgICBpZiAoIXRoaXMucGl4ZWxfKSB7XG4gICAgICAgIHRoaXMucGl4ZWxfID0gdGhpcy5tYXAuZ2V0RXZlbnRQaXhlbCh0aGlzLm9yaWdpbmFsRXZlbnQpO1xuICAgICAgfVxuXG4gICAgICByZXR1cm4gdGhpcy5waXhlbF87XG4gICAgfSxcbiAgICBzZXQ6IGZ1bmN0aW9uIHNldChwaXhlbCkge1xuICAgICAgdGhpcy5waXhlbF8gPSBwaXhlbDtcbiAgICB9LFxuICAgIGVudW1lcmFibGU6IGZhbHNlLFxuICAgIGNvbmZpZ3VyYWJsZTogdHJ1ZVxuICB9KTtcbiAgT2JqZWN0LmRlZmluZVByb3BlcnR5KE1hcEJyb3dzZXJFdmVudC5wcm90b3R5cGUsIFwiY29vcmRpbmF0ZVwiLCB7XG4gICAgLyoqXG4gICAgICogVGhlIGNvb3JkaW5hdGUgY29ycmVzcG9uZGluZyB0byB0aGUgb3JpZ2luYWwgYnJvd3NlciBldmVudC4gIFRoaXMgd2lsbCBiZSBpbiB0aGUgdXNlclxuICAgICAqIHByb2plY3Rpb24gaWYgb25lIGlzIHNldC4gIE90aGVyd2lzZSBpdCB3aWxsIGJlIGluIHRoZSB2aWV3IHByb2plY3Rpb24uXG4gICAgICogQHR5cGUge2ltcG9ydChcIi4vY29vcmRpbmF0ZS5qc1wiKS5Db29yZGluYXRlfVxuICAgICAqIEBhcGlcbiAgICAgKi9cbiAgICBnZXQ6IGZ1bmN0aW9uIGdldCgpIHtcbiAgICAgIGlmICghdGhpcy5jb29yZGluYXRlXykge1xuICAgICAgICB0aGlzLmNvb3JkaW5hdGVfID0gdGhpcy5tYXAuZ2V0Q29vcmRpbmF0ZUZyb21QaXhlbCh0aGlzLnBpeGVsKTtcbiAgICAgIH1cblxuICAgICAgcmV0dXJuIHRoaXMuY29vcmRpbmF0ZV87XG4gICAgfSxcbiAgICBzZXQ6IGZ1bmN0aW9uIHNldChjb29yZGluYXRlKSB7XG4gICAgICB0aGlzLmNvb3JkaW5hdGVfID0gY29vcmRpbmF0ZTtcbiAgICB9LFxuICAgIGVudW1lcmFibGU6IGZhbHNlLFxuICAgIGNvbmZpZ3VyYWJsZTogdHJ1ZVxuICB9KTtcbiAgLyoqXG4gICAqIFByZXZlbnRzIHRoZSBkZWZhdWx0IGJyb3dzZXIgYWN0aW9uLlxuICAgKiBTZWUgaHR0cHM6Ly9kZXZlbG9wZXIubW96aWxsYS5vcmcvZW4tVVMvZG9jcy9XZWIvQVBJL2V2ZW50LnByZXZlbnREZWZhdWx0LlxuICAgKiBAYXBpXG4gICAqL1xuXG4gIE1hcEJyb3dzZXJFdmVudC5wcm90b3R5cGUucHJldmVudERlZmF1bHQgPSBmdW5jdGlvbiAoKSB7XG4gICAgX3N1cGVyLnByb3RvdHlwZS5wcmV2ZW50RGVmYXVsdC5jYWxsKHRoaXMpO1xuXG4gICAgdGhpcy5vcmlnaW5hbEV2ZW50LnByZXZlbnREZWZhdWx0KCk7XG4gIH07XG4gIC8qKlxuICAgKiBQcmV2ZW50cyBmdXJ0aGVyIHByb3BhZ2F0aW9uIG9mIHRoZSBjdXJyZW50IGV2ZW50LlxuICAgKiBTZWUgaHR0cHM6Ly9kZXZlbG9wZXIubW96aWxsYS5vcmcvZW4tVVMvZG9jcy9XZWIvQVBJL2V2ZW50LnN0b3BQcm9wYWdhdGlvbi5cbiAgICogQGFwaVxuICAgKi9cblxuXG4gIE1hcEJyb3dzZXJFdmVudC5wcm90b3R5cGUuc3RvcFByb3BhZ2F0aW9uID0gZnVuY3Rpb24gKCkge1xuICAgIF9zdXBlci5wcm90b3R5cGUuc3RvcFByb3BhZ2F0aW9uLmNhbGwodGhpcyk7XG5cbiAgICB0aGlzLm9yaWdpbmFsRXZlbnQuc3RvcFByb3BhZ2F0aW9uKCk7XG4gIH07XG5cbiAgcmV0dXJuIE1hcEJyb3dzZXJFdmVudDtcbn0oTWFwRXZlbnQpO1xuXG5leHBvcnQgZGVmYXVsdCBNYXBCcm93c2VyRXZlbnQ7IiwiLyoqXG4gKiBAbW9kdWxlIG9sL01hcEJyb3dzZXJFdmVudFR5cGVcbiAqL1xuaW1wb3J0IEV2ZW50VHlwZSBmcm9tICcuL2V2ZW50cy9FdmVudFR5cGUuanMnO1xuLyoqXG4gKiBDb25zdGFudHMgZm9yIGV2ZW50IG5hbWVzLlxuICogQGVudW0ge3N0cmluZ31cbiAqL1xuXG5leHBvcnQgZGVmYXVsdCB7XG4gIC8qKlxuICAgKiBBIHRydWUgc2luZ2xlIGNsaWNrIHdpdGggbm8gZHJhZ2dpbmcgYW5kIG5vIGRvdWJsZSBjbGljay4gTm90ZSB0aGF0IHRoaXNcbiAgICogZXZlbnQgaXMgZGVsYXllZCBieSAyNTAgbXMgdG8gZW5zdXJlIHRoYXQgaXQgaXMgbm90IGEgZG91YmxlIGNsaWNrLlxuICAgKiBAZXZlbnQgbW9kdWxlOm9sL01hcEJyb3dzZXJFdmVudH5NYXBCcm93c2VyRXZlbnQjc2luZ2xlY2xpY2tcbiAgICogQGFwaVxuICAgKi9cbiAgU0lOR0xFQ0xJQ0s6ICdzaW5nbGVjbGljaycsXG5cbiAgLyoqXG4gICAqIEEgY2xpY2sgd2l0aCBubyBkcmFnZ2luZy4gQSBkb3VibGUgY2xpY2sgd2lsbCBmaXJlIHR3byBvZiB0aGlzLlxuICAgKiBAZXZlbnQgbW9kdWxlOm9sL01hcEJyb3dzZXJFdmVudH5NYXBCcm93c2VyRXZlbnQjY2xpY2tcbiAgICogQGFwaVxuICAgKi9cbiAgQ0xJQ0s6IEV2ZW50VHlwZS5DTElDSyxcblxuICAvKipcbiAgICogQSB0cnVlIGRvdWJsZSBjbGljaywgd2l0aCBubyBkcmFnZ2luZy5cbiAgICogQGV2ZW50IG1vZHVsZTpvbC9NYXBCcm93c2VyRXZlbnR+TWFwQnJvd3NlckV2ZW50I2RibGNsaWNrXG4gICAqIEBhcGlcbiAgICovXG4gIERCTENMSUNLOiBFdmVudFR5cGUuREJMQ0xJQ0ssXG5cbiAgLyoqXG4gICAqIFRyaWdnZXJlZCB3aGVuIGEgcG9pbnRlciBpcyBkcmFnZ2VkLlxuICAgKiBAZXZlbnQgbW9kdWxlOm9sL01hcEJyb3dzZXJFdmVudH5NYXBCcm93c2VyRXZlbnQjcG9pbnRlcmRyYWdcbiAgICogQGFwaVxuICAgKi9cbiAgUE9JTlRFUkRSQUc6ICdwb2ludGVyZHJhZycsXG5cbiAgLyoqXG4gICAqIFRyaWdnZXJlZCB3aGVuIGEgcG9pbnRlciBpcyBtb3ZlZC4gTm90ZSB0aGF0IG9uIHRvdWNoIGRldmljZXMgdGhpcyBpc1xuICAgKiB0cmlnZ2VyZWQgd2hlbiB0aGUgbWFwIGlzIHBhbm5lZCwgc28gaXMgbm90IHRoZSBzYW1lIGFzIG1vdXNlbW92ZS5cbiAgICogQGV2ZW50IG1vZHVsZTpvbC9NYXBCcm93c2VyRXZlbnR+TWFwQnJvd3NlckV2ZW50I3BvaW50ZXJtb3ZlXG4gICAqIEBhcGlcbiAgICovXG4gIFBPSU5URVJNT1ZFOiAncG9pbnRlcm1vdmUnLFxuICBQT0lOVEVSRE9XTjogJ3BvaW50ZXJkb3duJyxcbiAgUE9JTlRFUlVQOiAncG9pbnRlcnVwJyxcbiAgUE9JTlRFUk9WRVI6ICdwb2ludGVyb3ZlcicsXG4gIFBPSU5URVJPVVQ6ICdwb2ludGVyb3V0JyxcbiAgUE9JTlRFUkVOVEVSOiAncG9pbnRlcmVudGVyJyxcbiAgUE9JTlRFUkxFQVZFOiAncG9pbnRlcmxlYXZlJyxcbiAgUE9JTlRFUkNBTkNFTDogJ3BvaW50ZXJjYW5jZWwnXG59OyIsIi8qKlxuICogQG1vZHVsZSBvbC9wb2ludGVyL0V2ZW50VHlwZVxuICovXG5cbi8qKlxuICogQ29uc3RhbnRzIGZvciBldmVudCBuYW1lcy5cbiAqIEBlbnVtIHtzdHJpbmd9XG4gKi9cbmV4cG9ydCBkZWZhdWx0IHtcbiAgUE9JTlRFUk1PVkU6ICdwb2ludGVybW92ZScsXG4gIFBPSU5URVJET1dOOiAncG9pbnRlcmRvd24nLFxuICBQT0lOVEVSVVA6ICdwb2ludGVydXAnLFxuICBQT0lOVEVST1ZFUjogJ3BvaW50ZXJvdmVyJyxcbiAgUE9JTlRFUk9VVDogJ3BvaW50ZXJvdXQnLFxuICBQT0lOVEVSRU5URVI6ICdwb2ludGVyZW50ZXInLFxuICBQT0lOVEVSTEVBVkU6ICdwb2ludGVybGVhdmUnLFxuICBQT0lOVEVSQ0FOQ0VMOiAncG9pbnRlcmNhbmNlbCdcbn07IiwiLyoqXG4gKiBAbW9kdWxlIG9sL01hcEJyb3dzZXJFdmVudEhhbmRsZXJcbiAqL1xudmFyIF9fZXh0ZW5kcyA9IHRoaXMgJiYgdGhpcy5fX2V4dGVuZHMgfHwgZnVuY3Rpb24gKCkge1xuICB2YXIgX2V4dGVuZFN0YXRpY3MgPSBmdW5jdGlvbiBleHRlbmRTdGF0aWNzKGQsIGIpIHtcbiAgICBfZXh0ZW5kU3RhdGljcyA9IE9iamVjdC5zZXRQcm90b3R5cGVPZiB8fCB7XG4gICAgICBfX3Byb3RvX186IFtdXG4gICAgfSBpbnN0YW5jZW9mIEFycmF5ICYmIGZ1bmN0aW9uIChkLCBiKSB7XG4gICAgICBkLl9fcHJvdG9fXyA9IGI7XG4gICAgfSB8fCBmdW5jdGlvbiAoZCwgYikge1xuICAgICAgZm9yICh2YXIgcCBpbiBiKSB7XG4gICAgICAgIGlmIChPYmplY3QucHJvdG90eXBlLmhhc093blByb3BlcnR5LmNhbGwoYiwgcCkpIGRbcF0gPSBiW3BdO1xuICAgICAgfVxuICAgIH07XG5cbiAgICByZXR1cm4gX2V4dGVuZFN0YXRpY3MoZCwgYik7XG4gIH07XG5cbiAgcmV0dXJuIGZ1bmN0aW9uIChkLCBiKSB7XG4gICAgX2V4dGVuZFN0YXRpY3MoZCwgYik7XG5cbiAgICBmdW5jdGlvbiBfXygpIHtcbiAgICAgIHRoaXMuY29uc3RydWN0b3IgPSBkO1xuICAgIH1cblxuICAgIGQucHJvdG90eXBlID0gYiA9PT0gbnVsbCA/IE9iamVjdC5jcmVhdGUoYikgOiAoX18ucHJvdG90eXBlID0gYi5wcm90b3R5cGUsIG5ldyBfXygpKTtcbiAgfTtcbn0oKTtcblxuaW1wb3J0IEV2ZW50VGFyZ2V0IGZyb20gJy4vZXZlbnRzL1RhcmdldC5qcyc7XG5pbXBvcnQgRXZlbnRUeXBlIGZyb20gJy4vZXZlbnRzL0V2ZW50VHlwZS5qcyc7XG5pbXBvcnQgTWFwQnJvd3NlckV2ZW50IGZyb20gJy4vTWFwQnJvd3NlckV2ZW50LmpzJztcbmltcG9ydCBNYXBCcm93c2VyRXZlbnRUeXBlIGZyb20gJy4vTWFwQnJvd3NlckV2ZW50VHlwZS5qcyc7XG5pbXBvcnQgUG9pbnRlckV2ZW50VHlwZSBmcm9tICcuL3BvaW50ZXIvRXZlbnRUeXBlLmpzJztcbmltcG9ydCB7IERFVklDRV9QSVhFTF9SQVRJTywgUEFTU0lWRV9FVkVOVF9MSVNURU5FUlMgfSBmcm9tICcuL2hhcy5qcyc7XG5pbXBvcnQgeyBsaXN0ZW4sIHVubGlzdGVuQnlLZXkgfSBmcm9tICcuL2V2ZW50cy5qcyc7XG5cbnZhciBNYXBCcm93c2VyRXZlbnRIYW5kbGVyID1cbi8qKiBAY2xhc3MgKi9cbmZ1bmN0aW9uIChfc3VwZXIpIHtcbiAgX19leHRlbmRzKE1hcEJyb3dzZXJFdmVudEhhbmRsZXIsIF9zdXBlcik7XG4gIC8qKlxuICAgKiBAcGFyYW0ge2ltcG9ydChcIi4vUGx1Z2dhYmxlTWFwLmpzXCIpLmRlZmF1bHR9IG1hcCBUaGUgbWFwIHdpdGggdGhlIHZpZXdwb3J0IHRvIGxpc3RlbiB0byBldmVudHMgb24uXG4gICAqIEBwYXJhbSB7bnVtYmVyPX0gbW92ZVRvbGVyYW5jZSBUaGUgbWluaW1hbCBkaXN0YW5jZSB0aGUgcG9pbnRlciBtdXN0IHRyYXZlbCB0byB0cmlnZ2VyIGEgbW92ZS5cbiAgICovXG5cblxuICBmdW5jdGlvbiBNYXBCcm93c2VyRXZlbnRIYW5kbGVyKG1hcCwgbW92ZVRvbGVyYW5jZSkge1xuICAgIHZhciBfdGhpcyA9IF9zdXBlci5jYWxsKHRoaXMsIG1hcCkgfHwgdGhpcztcbiAgICAvKipcbiAgICAgKiBUaGlzIGlzIHRoZSBlbGVtZW50IHRoYXQgd2Ugd2lsbCBsaXN0ZW4gdG8gdGhlIHJlYWwgZXZlbnRzIG9uLlxuICAgICAqIEB0eXBlIHtpbXBvcnQoXCIuL1BsdWdnYWJsZU1hcC5qc1wiKS5kZWZhdWx0fVxuICAgICAqIEBwcml2YXRlXG4gICAgICovXG5cblxuICAgIF90aGlzLm1hcF8gPSBtYXA7XG4gICAgLyoqXG4gICAgICogQHR5cGUge2FueX1cbiAgICAgKiBAcHJpdmF0ZVxuICAgICAqL1xuXG4gICAgX3RoaXMuY2xpY2tUaW1lb3V0SWRfO1xuICAgIC8qKlxuICAgICAqIEVtdWxhdGUgZGJsY2xpY2sgYW5kIHNpbmdsZWNsaWNrLiBXaWxsIGJlIHRydWUgd2hlbiBvbmx5IG9uZSBwb2ludGVyIGlzIGFjdGl2ZS5cbiAgICAgKiBAdHlwZSB7Ym9vbGVhbn1cbiAgICAgKi9cblxuICAgIF90aGlzLmVtdWxhdGVDbGlja3NfID0gZmFsc2U7XG4gICAgLyoqXG4gICAgICogQHR5cGUge2Jvb2xlYW59XG4gICAgICogQHByaXZhdGVcbiAgICAgKi9cblxuICAgIF90aGlzLmRyYWdnaW5nXyA9IGZhbHNlO1xuICAgIC8qKlxuICAgICAqIEB0eXBlIHshQXJyYXk8aW1wb3J0KFwiLi9ldmVudHMuanNcIikuRXZlbnRzS2V5Pn1cbiAgICAgKiBAcHJpdmF0ZVxuICAgICAqL1xuXG4gICAgX3RoaXMuZHJhZ0xpc3RlbmVyS2V5c18gPSBbXTtcbiAgICAvKipcbiAgICAgKiBAdHlwZSB7bnVtYmVyfVxuICAgICAqIEBwcml2YXRlXG4gICAgICovXG5cbiAgICBfdGhpcy5tb3ZlVG9sZXJhbmNlXyA9IG1vdmVUb2xlcmFuY2UgPyBtb3ZlVG9sZXJhbmNlICogREVWSUNFX1BJWEVMX1JBVElPIDogREVWSUNFX1BJWEVMX1JBVElPO1xuICAgIC8qKlxuICAgICAqIFRoZSBtb3N0IHJlY2VudCBcImRvd25cIiB0eXBlIGV2ZW50IChvciBudWxsIGlmIG5vbmUgaGF2ZSBvY2N1cnJlZCkuXG4gICAgICogU2V0IG9uIHBvaW50ZXJkb3duLlxuICAgICAqIEB0eXBlIHtQb2ludGVyRXZlbnR9XG4gICAgICogQHByaXZhdGVcbiAgICAgKi9cblxuICAgIF90aGlzLmRvd25fID0gbnVsbDtcblxuICAgIHZhciBlbGVtZW50ID0gX3RoaXMubWFwXy5nZXRWaWV3cG9ydCgpO1xuICAgIC8qKlxuICAgICAqIEB0eXBlIHtudW1iZXJ9XG4gICAgICogQHByaXZhdGVcbiAgICAgKi9cblxuXG4gICAgX3RoaXMuYWN0aXZlUG9pbnRlcnNfID0gMDtcbiAgICAvKipcbiAgICAgKiBAdHlwZSB7IU9iamVjdDxudW1iZXIsIGJvb2xlYW4+fVxuICAgICAqIEBwcml2YXRlXG4gICAgICovXG5cbiAgICBfdGhpcy50cmFja2VkVG91Y2hlc18gPSB7fTtcbiAgICBfdGhpcy5lbGVtZW50XyA9IGVsZW1lbnQ7XG4gICAgLyoqXG4gICAgICogQHR5cGUgez9pbXBvcnQoXCIuL2V2ZW50cy5qc1wiKS5FdmVudHNLZXl9XG4gICAgICogQHByaXZhdGVcbiAgICAgKi9cblxuICAgIF90aGlzLnBvaW50ZXJkb3duTGlzdGVuZXJLZXlfID0gbGlzdGVuKGVsZW1lbnQsIFBvaW50ZXJFdmVudFR5cGUuUE9JTlRFUkRPV04sIF90aGlzLmhhbmRsZVBvaW50ZXJEb3duXywgX3RoaXMpO1xuICAgIC8qKlxuICAgICAqIEB0eXBlIHtQb2ludGVyRXZlbnR9XG4gICAgICogQHByaXZhdGVcbiAgICAgKi9cblxuICAgIF90aGlzLm9yaWdpbmFsUG9pbnRlck1vdmVFdmVudF87XG4gICAgLyoqXG4gICAgICogQHR5cGUgez9pbXBvcnQoXCIuL2V2ZW50cy5qc1wiKS5FdmVudHNLZXl9XG4gICAgICogQHByaXZhdGVcbiAgICAgKi9cblxuICAgIF90aGlzLnJlbGF5ZWRMaXN0ZW5lcktleV8gPSBsaXN0ZW4oZWxlbWVudCwgUG9pbnRlckV2ZW50VHlwZS5QT0lOVEVSTU9WRSwgX3RoaXMucmVsYXlFdmVudF8sIF90aGlzKTtcbiAgICAvKipcbiAgICAgKiBAcHJpdmF0ZVxuICAgICAqL1xuXG4gICAgX3RoaXMuYm91bmRIYW5kbGVUb3VjaE1vdmVfID0gX3RoaXMuaGFuZGxlVG91Y2hNb3ZlXy5iaW5kKF90aGlzKTtcblxuICAgIF90aGlzLmVsZW1lbnRfLmFkZEV2ZW50TGlzdGVuZXIoRXZlbnRUeXBlLlRPVUNITU9WRSwgX3RoaXMuYm91bmRIYW5kbGVUb3VjaE1vdmVfLCBQQVNTSVZFX0VWRU5UX0xJU1RFTkVSUyA/IHtcbiAgICAgIHBhc3NpdmU6IGZhbHNlXG4gICAgfSA6IGZhbHNlKTtcblxuICAgIHJldHVybiBfdGhpcztcbiAgfVxuICAvKipcbiAgICogQHBhcmFtIHtQb2ludGVyRXZlbnR9IHBvaW50ZXJFdmVudCBQb2ludGVyXG4gICAqIGV2ZW50LlxuICAgKiBAcHJpdmF0ZVxuICAgKi9cblxuXG4gIE1hcEJyb3dzZXJFdmVudEhhbmRsZXIucHJvdG90eXBlLmVtdWxhdGVDbGlja18gPSBmdW5jdGlvbiAocG9pbnRlckV2ZW50KSB7XG4gICAgdmFyIG5ld0V2ZW50ID0gbmV3IE1hcEJyb3dzZXJFdmVudChNYXBCcm93c2VyRXZlbnRUeXBlLkNMSUNLLCB0aGlzLm1hcF8sIHBvaW50ZXJFdmVudCk7XG4gICAgdGhpcy5kaXNwYXRjaEV2ZW50KG5ld0V2ZW50KTtcblxuICAgIGlmICh0aGlzLmNsaWNrVGltZW91dElkXyAhPT0gdW5kZWZpbmVkKSB7XG4gICAgICAvLyBkb3VibGUtY2xpY2tcbiAgICAgIGNsZWFyVGltZW91dCh0aGlzLmNsaWNrVGltZW91dElkXyk7XG4gICAgICB0aGlzLmNsaWNrVGltZW91dElkXyA9IHVuZGVmaW5lZDtcbiAgICAgIG5ld0V2ZW50ID0gbmV3IE1hcEJyb3dzZXJFdmVudChNYXBCcm93c2VyRXZlbnRUeXBlLkRCTENMSUNLLCB0aGlzLm1hcF8sIHBvaW50ZXJFdmVudCk7XG4gICAgICB0aGlzLmRpc3BhdGNoRXZlbnQobmV3RXZlbnQpO1xuICAgIH0gZWxzZSB7XG4gICAgICAvLyBjbGlja1xuICAgICAgdGhpcy5jbGlja1RpbWVvdXRJZF8gPSBzZXRUaW1lb3V0KFxuICAgICAgLyoqIEB0aGlzIHtNYXBCcm93c2VyRXZlbnRIYW5kbGVyfSAqL1xuICAgICAgZnVuY3Rpb24gKCkge1xuICAgICAgICB0aGlzLmNsaWNrVGltZW91dElkXyA9IHVuZGVmaW5lZDtcbiAgICAgICAgdmFyIG5ld0V2ZW50ID0gbmV3IE1hcEJyb3dzZXJFdmVudChNYXBCcm93c2VyRXZlbnRUeXBlLlNJTkdMRUNMSUNLLCB0aGlzLm1hcF8sIHBvaW50ZXJFdmVudCk7XG4gICAgICAgIHRoaXMuZGlzcGF0Y2hFdmVudChuZXdFdmVudCk7XG4gICAgICB9LmJpbmQodGhpcyksIDI1MCk7XG4gICAgfVxuICB9O1xuICAvKipcbiAgICogS2VlcHMgdHJhY2sgb24gaG93IG1hbnkgcG9pbnRlcnMgYXJlIGN1cnJlbnRseSBhY3RpdmUuXG4gICAqXG4gICAqIEBwYXJhbSB7UG9pbnRlckV2ZW50fSBwb2ludGVyRXZlbnQgUG9pbnRlclxuICAgKiBldmVudC5cbiAgICogQHByaXZhdGVcbiAgICovXG5cblxuICBNYXBCcm93c2VyRXZlbnRIYW5kbGVyLnByb3RvdHlwZS51cGRhdGVBY3RpdmVQb2ludGVyc18gPSBmdW5jdGlvbiAocG9pbnRlckV2ZW50KSB7XG4gICAgdmFyIGV2ZW50ID0gcG9pbnRlckV2ZW50O1xuXG4gICAgaWYgKGV2ZW50LnR5cGUgPT0gTWFwQnJvd3NlckV2ZW50VHlwZS5QT0lOVEVSVVAgfHwgZXZlbnQudHlwZSA9PSBNYXBCcm93c2VyRXZlbnRUeXBlLlBPSU5URVJDQU5DRUwpIHtcbiAgICAgIGRlbGV0ZSB0aGlzLnRyYWNrZWRUb3VjaGVzX1tldmVudC5wb2ludGVySWRdO1xuICAgIH0gZWxzZSBpZiAoZXZlbnQudHlwZSA9PSBNYXBCcm93c2VyRXZlbnRUeXBlLlBPSU5URVJET1dOKSB7XG4gICAgICB0aGlzLnRyYWNrZWRUb3VjaGVzX1tldmVudC5wb2ludGVySWRdID0gdHJ1ZTtcbiAgICB9XG5cbiAgICB0aGlzLmFjdGl2ZVBvaW50ZXJzXyA9IE9iamVjdC5rZXlzKHRoaXMudHJhY2tlZFRvdWNoZXNfKS5sZW5ndGg7XG4gIH07XG4gIC8qKlxuICAgKiBAcGFyYW0ge1BvaW50ZXJFdmVudH0gcG9pbnRlckV2ZW50IFBvaW50ZXJcbiAgICogZXZlbnQuXG4gICAqIEBwcml2YXRlXG4gICAqL1xuXG5cbiAgTWFwQnJvd3NlckV2ZW50SGFuZGxlci5wcm90b3R5cGUuaGFuZGxlUG9pbnRlclVwXyA9IGZ1bmN0aW9uIChwb2ludGVyRXZlbnQpIHtcbiAgICB0aGlzLnVwZGF0ZUFjdGl2ZVBvaW50ZXJzXyhwb2ludGVyRXZlbnQpO1xuICAgIHZhciBuZXdFdmVudCA9IG5ldyBNYXBCcm93c2VyRXZlbnQoTWFwQnJvd3NlckV2ZW50VHlwZS5QT0lOVEVSVVAsIHRoaXMubWFwXywgcG9pbnRlckV2ZW50KTtcbiAgICB0aGlzLmRpc3BhdGNoRXZlbnQobmV3RXZlbnQpOyAvLyBXZSBlbXVsYXRlIGNsaWNrIGV2ZW50cyBvbiBsZWZ0IG1vdXNlIGJ1dHRvbiBjbGljaywgdG91Y2ggY29udGFjdCwgYW5kIHBlblxuICAgIC8vIGNvbnRhY3QuIGlzTW91c2VBY3Rpb25CdXR0b24gcmV0dXJucyB0cnVlIGluIHRoZXNlIGNhc2VzIChldnQuYnV0dG9uIGlzIHNldFxuICAgIC8vIHRvIDApLlxuICAgIC8vIFNlZSBodHRwOi8vd3d3LnczLm9yZy9UUi9wb2ludGVyZXZlbnRzLyNidXR0b24tc3RhdGVzXG4gICAgLy8gV2Ugb25seSBmaXJlIGNsaWNrLCBzaW5nbGVjbGljaywgYW5kIGRvdWJsZWNsaWNrIGlmIG5vYm9keSBoYXMgY2FsbGVkXG4gICAgLy8gZXZlbnQuc3RvcFByb3BhZ2F0aW9uKCkgb3IgZXZlbnQucHJldmVudERlZmF1bHQoKS5cblxuICAgIGlmICh0aGlzLmVtdWxhdGVDbGlja3NfICYmICFuZXdFdmVudC5wcm9wYWdhdGlvblN0b3BwZWQgJiYgIXRoaXMuZHJhZ2dpbmdfICYmIHRoaXMuaXNNb3VzZUFjdGlvbkJ1dHRvbl8ocG9pbnRlckV2ZW50KSkge1xuICAgICAgdGhpcy5lbXVsYXRlQ2xpY2tfKHRoaXMuZG93bl8pO1xuICAgIH1cblxuICAgIGlmICh0aGlzLmFjdGl2ZVBvaW50ZXJzXyA9PT0gMCkge1xuICAgICAgdGhpcy5kcmFnTGlzdGVuZXJLZXlzXy5mb3JFYWNoKHVubGlzdGVuQnlLZXkpO1xuICAgICAgdGhpcy5kcmFnTGlzdGVuZXJLZXlzXy5sZW5ndGggPSAwO1xuICAgICAgdGhpcy5kcmFnZ2luZ18gPSBmYWxzZTtcbiAgICAgIHRoaXMuZG93bl8gPSBudWxsO1xuICAgIH1cbiAgfTtcbiAgLyoqXG4gICAqIEBwYXJhbSB7UG9pbnRlckV2ZW50fSBwb2ludGVyRXZlbnQgUG9pbnRlclxuICAgKiBldmVudC5cbiAgICogQHJldHVybiB7Ym9vbGVhbn0gSWYgdGhlIGxlZnQgbW91c2UgYnV0dG9uIHdhcyBwcmVzc2VkLlxuICAgKiBAcHJpdmF0ZVxuICAgKi9cblxuXG4gIE1hcEJyb3dzZXJFdmVudEhhbmRsZXIucHJvdG90eXBlLmlzTW91c2VBY3Rpb25CdXR0b25fID0gZnVuY3Rpb24gKHBvaW50ZXJFdmVudCkge1xuICAgIHJldHVybiBwb2ludGVyRXZlbnQuYnV0dG9uID09PSAwO1xuICB9O1xuICAvKipcbiAgICogQHBhcmFtIHtQb2ludGVyRXZlbnR9IHBvaW50ZXJFdmVudCBQb2ludGVyXG4gICAqIGV2ZW50LlxuICAgKiBAcHJpdmF0ZVxuICAgKi9cblxuXG4gIE1hcEJyb3dzZXJFdmVudEhhbmRsZXIucHJvdG90eXBlLmhhbmRsZVBvaW50ZXJEb3duXyA9IGZ1bmN0aW9uIChwb2ludGVyRXZlbnQpIHtcbiAgICB0aGlzLmVtdWxhdGVDbGlja3NfID0gdGhpcy5hY3RpdmVQb2ludGVyc18gPT09IDA7XG4gICAgdGhpcy51cGRhdGVBY3RpdmVQb2ludGVyc18ocG9pbnRlckV2ZW50KTtcbiAgICB2YXIgbmV3RXZlbnQgPSBuZXcgTWFwQnJvd3NlckV2ZW50KE1hcEJyb3dzZXJFdmVudFR5cGUuUE9JTlRFUkRPV04sIHRoaXMubWFwXywgcG9pbnRlckV2ZW50KTtcbiAgICB0aGlzLmRpc3BhdGNoRXZlbnQobmV3RXZlbnQpO1xuICAgIHRoaXMuZG93bl8gPSBwb2ludGVyRXZlbnQ7XG5cbiAgICBpZiAodGhpcy5kcmFnTGlzdGVuZXJLZXlzXy5sZW5ndGggPT09IDApIHtcbiAgICAgIHZhciBkb2MgPSB0aGlzLm1hcF8uZ2V0T3duZXJEb2N1bWVudCgpO1xuICAgICAgdGhpcy5kcmFnTGlzdGVuZXJLZXlzXy5wdXNoKGxpc3Rlbihkb2MsIE1hcEJyb3dzZXJFdmVudFR5cGUuUE9JTlRFUk1PVkUsIHRoaXMuaGFuZGxlUG9pbnRlck1vdmVfLCB0aGlzKSwgbGlzdGVuKGRvYywgTWFwQnJvd3NlckV2ZW50VHlwZS5QT0lOVEVSVVAsIHRoaXMuaGFuZGxlUG9pbnRlclVwXywgdGhpcyksXG4gICAgICAvKiBOb3RlIHRoYXQgdGhlIGxpc3RlbmVyIGZvciBgcG9pbnRlcmNhbmNlbCBpcyBzZXQgdXAgb25cbiAgICAgICAqIGBwb2ludGVyRXZlbnRIYW5kbGVyX2AgYW5kIG5vdCBgZG9jdW1lbnRQb2ludGVyRXZlbnRIYW5kbGVyX2AgbGlrZVxuICAgICAgICogdGhlIGBwb2ludGVydXBgIGFuZCBgcG9pbnRlcm1vdmVgIGxpc3RlbmVycy5cbiAgICAgICAqXG4gICAgICAgKiBUaGUgcmVhc29uIGZvciB0aGlzIGlzIHRoZSBmb2xsb3dpbmc6IGBUb3VjaFNvdXJjZS52YWN1dW1Ub3VjaGVzXygpYFxuICAgICAgICogaXNzdWVzIGBwb2ludGVyY2FuY2VsYCBldmVudHMsIHdoZW4gdGhlcmUgd2FzIG5vIGB0b3VjaGVuZGAgZm9yIGFcbiAgICAgICAqIGB0b3VjaHN0YXJ0YC4gTm93LCBsZXQncyBzYXkgYSBmaXJzdCBgdG91Y2hzdGFydGAgaXMgcmVnaXN0ZXJlZCBvblxuICAgICAgICogYHBvaW50ZXJFdmVudEhhbmRsZXJfYC4gVGhlIGBkb2N1bWVudFBvaW50ZXJFdmVudEhhbmRsZXJfYCBpcyBzZXQgdXAuXG4gICAgICAgKiBCdXQgYGRvY3VtZW50UG9pbnRlckV2ZW50SGFuZGxlcl9gIGRvZXNuJ3Qga25vdyBhYm91dCB0aGUgZmlyc3RcbiAgICAgICAqIGB0b3VjaHN0YXJ0YC4gSWYgdGhlcmUgaXMgbm8gYHRvdWNoZW5kYCBmb3IgdGhlIGB0b3VjaHN0YXJ0YCwgd2UgY2FuXG4gICAgICAgKiBvbmx5IHJlY2VpdmUgYSBgdG91Y2hjYW5jZWxgIGZyb20gYHBvaW50ZXJFdmVudEhhbmRsZXJfYCwgYmVjYXVzZSBpdCBpc1xuICAgICAgICogb25seSByZWdpc3RlcmVkIHRoZXJlLlxuICAgICAgICovXG4gICAgICBsaXN0ZW4odGhpcy5lbGVtZW50XywgTWFwQnJvd3NlckV2ZW50VHlwZS5QT0lOVEVSQ0FOQ0VMLCB0aGlzLmhhbmRsZVBvaW50ZXJVcF8sIHRoaXMpKTtcblxuICAgICAgaWYgKHRoaXMuZWxlbWVudF8uZ2V0Um9vdE5vZGUgJiYgdGhpcy5lbGVtZW50Xy5nZXRSb290Tm9kZSgpICE9PSBkb2MpIHtcbiAgICAgICAgdGhpcy5kcmFnTGlzdGVuZXJLZXlzXy5wdXNoKGxpc3Rlbih0aGlzLmVsZW1lbnRfLmdldFJvb3ROb2RlKCksIE1hcEJyb3dzZXJFdmVudFR5cGUuUE9JTlRFUlVQLCB0aGlzLmhhbmRsZVBvaW50ZXJVcF8sIHRoaXMpKTtcbiAgICAgIH1cbiAgICB9XG4gIH07XG4gIC8qKlxuICAgKiBAcGFyYW0ge1BvaW50ZXJFdmVudH0gcG9pbnRlckV2ZW50IFBvaW50ZXJcbiAgICogZXZlbnQuXG4gICAqIEBwcml2YXRlXG4gICAqL1xuXG5cbiAgTWFwQnJvd3NlckV2ZW50SGFuZGxlci5wcm90b3R5cGUuaGFuZGxlUG9pbnRlck1vdmVfID0gZnVuY3Rpb24gKHBvaW50ZXJFdmVudCkge1xuICAgIC8vIEJldHdlZW4gcG9pbnRlcmRvd24gYW5kIHBvaW50ZXJ1cCwgcG9pbnRlcm1vdmUgZXZlbnRzIGFyZSB0cmlnZ2VyZWQuXG4gICAgLy8gVG8gYXZvaWQgYSAnZmFsc2UnIHRvdWNobW92ZSBldmVudCB0byBiZSBkaXNwYXRjaGVkLCB3ZSB0ZXN0IGlmIHRoZSBwb2ludGVyXG4gICAgLy8gbW92ZWQgYSBzaWduaWZpY2FudCBkaXN0YW5jZS5cbiAgICBpZiAodGhpcy5pc01vdmluZ18ocG9pbnRlckV2ZW50KSkge1xuICAgICAgdGhpcy5kcmFnZ2luZ18gPSB0cnVlO1xuICAgICAgdmFyIG5ld0V2ZW50ID0gbmV3IE1hcEJyb3dzZXJFdmVudChNYXBCcm93c2VyRXZlbnRUeXBlLlBPSU5URVJEUkFHLCB0aGlzLm1hcF8sIHBvaW50ZXJFdmVudCwgdGhpcy5kcmFnZ2luZ18pO1xuICAgICAgdGhpcy5kaXNwYXRjaEV2ZW50KG5ld0V2ZW50KTtcbiAgICB9XG4gIH07XG4gIC8qKlxuICAgKiBXcmFwIGFuZCByZWxheSBhIHBvaW50ZXIgZXZlbnQuICBOb3RlIHRoYXQgdGhpcyByZXF1aXJlcyB0aGF0IHRoZSB0eXBlXG4gICAqIHN0cmluZyBmb3IgdGhlIE1hcEJyb3dzZXJFdmVudCBtYXRjaGVzIHRoZSBQb2ludGVyRXZlbnQgdHlwZS5cbiAgICogQHBhcmFtIHtQb2ludGVyRXZlbnR9IHBvaW50ZXJFdmVudCBQb2ludGVyXG4gICAqIGV2ZW50LlxuICAgKiBAcHJpdmF0ZVxuICAgKi9cblxuXG4gIE1hcEJyb3dzZXJFdmVudEhhbmRsZXIucHJvdG90eXBlLnJlbGF5RXZlbnRfID0gZnVuY3Rpb24gKHBvaW50ZXJFdmVudCkge1xuICAgIHRoaXMub3JpZ2luYWxQb2ludGVyTW92ZUV2ZW50XyA9IHBvaW50ZXJFdmVudDtcbiAgICB2YXIgZHJhZ2dpbmcgPSAhISh0aGlzLmRvd25fICYmIHRoaXMuaXNNb3ZpbmdfKHBvaW50ZXJFdmVudCkpO1xuICAgIHRoaXMuZGlzcGF0Y2hFdmVudChuZXcgTWFwQnJvd3NlckV2ZW50KHBvaW50ZXJFdmVudC50eXBlLCB0aGlzLm1hcF8sIHBvaW50ZXJFdmVudCwgZHJhZ2dpbmcpKTtcbiAgfTtcbiAgLyoqXG4gICAqIEZsZXhpYmxlIGhhbmRsaW5nIG9mIGEgYHRvdWNoLWFjdGlvbjogbm9uZWAgY3NzIGVxdWl2YWxlbnQ6IGJlY2F1c2UgY2FsbGluZ1xuICAgKiBgcHJldmVudERlZmF1bHQoKWAgb24gYSBgcG9pbnRlcm1vdmVgIGV2ZW50IGRvZXMgbm90IHN0b3AgbmF0aXZlIHBhZ2Ugc2Nyb2xsaW5nXG4gICAqIGFuZCB6b29taW5nLCB3ZSBhbHNvIGxpc3RlbiBmb3IgYHRvdWNobW92ZWAgYW5kIGNhbGwgYHByZXZlbnREZWZhdWx0KClgIG9uIGl0XG4gICAqIHdoZW4gYW4gaW50ZXJhY3Rpb24gKGN1cnJlbnRseSBgRHJhZ1BhbmAgaGFuZGxlcyB0aGUgZXZlbnQuXG4gICAqIEBwYXJhbSB7VG91Y2hFdmVudH0gZXZlbnQgRXZlbnQuXG4gICAqIEBwcml2YXRlXG4gICAqL1xuXG5cbiAgTWFwQnJvd3NlckV2ZW50SGFuZGxlci5wcm90b3R5cGUuaGFuZGxlVG91Y2hNb3ZlXyA9IGZ1bmN0aW9uIChldmVudCkge1xuICAgIC8vIER1ZSB0byBodHRwczovL2dpdGh1Yi5jb20vbXBpemVuYmVyZy9lbG0tcGVwL2lzc3Vlcy8yLCBgdGhpcy5vcmlnaW5hbFBvaW50ZXJNb3ZlRXZlbnRfYFxuICAgIC8vIG1heSBub3QgYmUgaW5pdGlhbGl6ZWQgeWV0IHdoZW4gd2UgZ2V0IGhlcmUgb24gYSBwbGF0Zm9ybSB3aXRob3V0IG5hdGl2ZSBwb2ludGVyIGV2ZW50cy5cbiAgICBpZiAoIXRoaXMub3JpZ2luYWxQb2ludGVyTW92ZUV2ZW50XyB8fCB0aGlzLm9yaWdpbmFsUG9pbnRlck1vdmVFdmVudF8uZGVmYXVsdFByZXZlbnRlZCkge1xuICAgICAgZXZlbnQucHJldmVudERlZmF1bHQoKTtcbiAgICB9XG4gIH07XG4gIC8qKlxuICAgKiBAcGFyYW0ge1BvaW50ZXJFdmVudH0gcG9pbnRlckV2ZW50IFBvaW50ZXJcbiAgICogZXZlbnQuXG4gICAqIEByZXR1cm4ge2Jvb2xlYW59IElzIG1vdmluZy5cbiAgICogQHByaXZhdGVcbiAgICovXG5cblxuICBNYXBCcm93c2VyRXZlbnRIYW5kbGVyLnByb3RvdHlwZS5pc01vdmluZ18gPSBmdW5jdGlvbiAocG9pbnRlckV2ZW50KSB7XG4gICAgcmV0dXJuIHRoaXMuZHJhZ2dpbmdfIHx8IE1hdGguYWJzKHBvaW50ZXJFdmVudC5jbGllbnRYIC0gdGhpcy5kb3duXy5jbGllbnRYKSA+IHRoaXMubW92ZVRvbGVyYW5jZV8gfHwgTWF0aC5hYnMocG9pbnRlckV2ZW50LmNsaWVudFkgLSB0aGlzLmRvd25fLmNsaWVudFkpID4gdGhpcy5tb3ZlVG9sZXJhbmNlXztcbiAgfTtcbiAgLyoqXG4gICAqIENsZWFuIHVwLlxuICAgKi9cblxuXG4gIE1hcEJyb3dzZXJFdmVudEhhbmRsZXIucHJvdG90eXBlLmRpc3Bvc2VJbnRlcm5hbCA9IGZ1bmN0aW9uICgpIHtcbiAgICBpZiAodGhpcy5yZWxheWVkTGlzdGVuZXJLZXlfKSB7XG4gICAgICB1bmxpc3RlbkJ5S2V5KHRoaXMucmVsYXllZExpc3RlbmVyS2V5Xyk7XG4gICAgICB0aGlzLnJlbGF5ZWRMaXN0ZW5lcktleV8gPSBudWxsO1xuICAgIH1cblxuICAgIHRoaXMuZWxlbWVudF8ucmVtb3ZlRXZlbnRMaXN0ZW5lcihFdmVudFR5cGUuVE9VQ0hNT1ZFLCB0aGlzLmJvdW5kSGFuZGxlVG91Y2hNb3ZlXyk7XG5cbiAgICBpZiAodGhpcy5wb2ludGVyZG93bkxpc3RlbmVyS2V5Xykge1xuICAgICAgdW5saXN0ZW5CeUtleSh0aGlzLnBvaW50ZXJkb3duTGlzdGVuZXJLZXlfKTtcbiAgICAgIHRoaXMucG9pbnRlcmRvd25MaXN0ZW5lcktleV8gPSBudWxsO1xuICAgIH1cblxuICAgIHRoaXMuZHJhZ0xpc3RlbmVyS2V5c18uZm9yRWFjaCh1bmxpc3RlbkJ5S2V5KTtcbiAgICB0aGlzLmRyYWdMaXN0ZW5lcktleXNfLmxlbmd0aCA9IDA7XG4gICAgdGhpcy5lbGVtZW50XyA9IG51bGw7XG5cbiAgICBfc3VwZXIucHJvdG90eXBlLmRpc3Bvc2VJbnRlcm5hbC5jYWxsKHRoaXMpO1xuICB9O1xuXG4gIHJldHVybiBNYXBCcm93c2VyRXZlbnRIYW5kbGVyO1xufShFdmVudFRhcmdldCk7XG5cbmV4cG9ydCBkZWZhdWx0IE1hcEJyb3dzZXJFdmVudEhhbmRsZXI7IiwiLyoqXG4gKiBAbW9kdWxlIG9sL01hcEV2ZW50VHlwZVxuICovXG5cbi8qKlxuICogQGVudW0ge3N0cmluZ31cbiAqL1xuZXhwb3J0IGRlZmF1bHQge1xuICAvKipcbiAgICogVHJpZ2dlcmVkIGFmdGVyIGEgbWFwIGZyYW1lIGlzIHJlbmRlcmVkLlxuICAgKiBAZXZlbnQgbW9kdWxlOm9sL01hcEV2ZW50fk1hcEV2ZW50I3Bvc3RyZW5kZXJcbiAgICogQGFwaVxuICAgKi9cbiAgUE9TVFJFTkRFUjogJ3Bvc3RyZW5kZXInLFxuXG4gIC8qKlxuICAgKiBUcmlnZ2VyZWQgd2hlbiB0aGUgbWFwIHN0YXJ0cyBtb3ZpbmcuXG4gICAqIEBldmVudCBtb2R1bGU6b2wvTWFwRXZlbnR+TWFwRXZlbnQjbW92ZXN0YXJ0XG4gICAqIEBhcGlcbiAgICovXG4gIE1PVkVTVEFSVDogJ21vdmVzdGFydCcsXG5cbiAgLyoqXG4gICAqIFRyaWdnZXJlZCBhZnRlciB0aGUgbWFwIGlzIG1vdmVkLlxuICAgKiBAZXZlbnQgbW9kdWxlOm9sL01hcEV2ZW50fk1hcEV2ZW50I21vdmVlbmRcbiAgICogQGFwaVxuICAgKi9cbiAgTU9WRUVORDogJ21vdmVlbmQnXG59OyIsIi8qKlxuICogQG1vZHVsZSBvbC9NYXBQcm9wZXJ0eVxuICovXG5cbi8qKlxuICogQGVudW0ge3N0cmluZ31cbiAqL1xuZXhwb3J0IGRlZmF1bHQge1xuICBMQVlFUkdST1VQOiAnbGF5ZXJncm91cCcsXG4gIFNJWkU6ICdzaXplJyxcbiAgVEFSR0VUOiAndGFyZ2V0JyxcbiAgVklFVzogJ3ZpZXcnXG59OyIsIi8qKlxuICogQG1vZHVsZSBvbC9zdHJ1Y3RzL1ByaW9yaXR5UXVldWVcbiAqL1xuaW1wb3J0IHsgYXNzZXJ0IH0gZnJvbSAnLi4vYXNzZXJ0cy5qcyc7XG5pbXBvcnQgeyBjbGVhciB9IGZyb20gJy4uL29iai5qcyc7XG4vKipcbiAqIEB0eXBlIHtudW1iZXJ9XG4gKi9cblxuZXhwb3J0IHZhciBEUk9QID0gSW5maW5pdHk7XG4vKipcbiAqIEBjbGFzc2Rlc2NcbiAqIFByaW9yaXR5IHF1ZXVlLlxuICpcbiAqIFRoZSBpbXBsZW1lbnRhdGlvbiBpcyBpbnNwaXJlZCBmcm9tIHRoZSBDbG9zdXJlIExpYnJhcnkncyBIZWFwIGNsYXNzIGFuZFxuICogUHl0aG9uJ3MgaGVhcHEgbW9kdWxlLlxuICpcbiAqIFNlZSBodHRwOi8vY2xvc3VyZS1saWJyYXJ5Lmdvb2dsZWNvZGUuY29tL3N2bi9kb2NzL2Nsb3N1cmVfZ29vZ19zdHJ1Y3RzX2hlYXAuanMuc291cmNlLmh0bWxcbiAqIGFuZCBodHRwOi8vaGcucHl0aG9uLm9yZy9jcHl0aG9uL2ZpbGUvMi43L0xpYi9oZWFwcS5weS5cbiAqXG4gKiBAdGVtcGxhdGUgVFxuICovXG5cbnZhciBQcmlvcml0eVF1ZXVlID1cbi8qKiBAY2xhc3MgKi9cbmZ1bmN0aW9uICgpIHtcbiAgLyoqXG4gICAqIEBwYXJhbSB7ZnVuY3Rpb24oVCk6IG51bWJlcn0gcHJpb3JpdHlGdW5jdGlvbiBQcmlvcml0eSBmdW5jdGlvbi5cbiAgICogQHBhcmFtIHtmdW5jdGlvbihUKTogc3RyaW5nfSBrZXlGdW5jdGlvbiBLZXkgZnVuY3Rpb24uXG4gICAqL1xuICBmdW5jdGlvbiBQcmlvcml0eVF1ZXVlKHByaW9yaXR5RnVuY3Rpb24sIGtleUZ1bmN0aW9uKSB7XG4gICAgLyoqXG4gICAgICogQHR5cGUge2Z1bmN0aW9uKFQpOiBudW1iZXJ9XG4gICAgICogQHByaXZhdGVcbiAgICAgKi9cbiAgICB0aGlzLnByaW9yaXR5RnVuY3Rpb25fID0gcHJpb3JpdHlGdW5jdGlvbjtcbiAgICAvKipcbiAgICAgKiBAdHlwZSB7ZnVuY3Rpb24oVCk6IHN0cmluZ31cbiAgICAgKiBAcHJpdmF0ZVxuICAgICAqL1xuXG4gICAgdGhpcy5rZXlGdW5jdGlvbl8gPSBrZXlGdW5jdGlvbjtcbiAgICAvKipcbiAgICAgKiBAdHlwZSB7QXJyYXk8VD59XG4gICAgICogQHByaXZhdGVcbiAgICAgKi9cblxuICAgIHRoaXMuZWxlbWVudHNfID0gW107XG4gICAgLyoqXG4gICAgICogQHR5cGUge0FycmF5PG51bWJlcj59XG4gICAgICogQHByaXZhdGVcbiAgICAgKi9cblxuICAgIHRoaXMucHJpb3JpdGllc18gPSBbXTtcbiAgICAvKipcbiAgICAgKiBAdHlwZSB7IU9iamVjdDxzdHJpbmcsIGJvb2xlYW4+fVxuICAgICAqIEBwcml2YXRlXG4gICAgICovXG5cbiAgICB0aGlzLnF1ZXVlZEVsZW1lbnRzXyA9IHt9O1xuICB9XG4gIC8qKlxuICAgKiBGSVhNRSBlbXB0eSBkZXNjcmlwdGlvbiBmb3IganNkb2NcbiAgICovXG5cblxuICBQcmlvcml0eVF1ZXVlLnByb3RvdHlwZS5jbGVhciA9IGZ1bmN0aW9uICgpIHtcbiAgICB0aGlzLmVsZW1lbnRzXy5sZW5ndGggPSAwO1xuICAgIHRoaXMucHJpb3JpdGllc18ubGVuZ3RoID0gMDtcbiAgICBjbGVhcih0aGlzLnF1ZXVlZEVsZW1lbnRzXyk7XG4gIH07XG4gIC8qKlxuICAgKiBSZW1vdmUgYW5kIHJldHVybiB0aGUgaGlnaGVzdC1wcmlvcml0eSBlbGVtZW50LiBPKGxvZyBOKS5cbiAgICogQHJldHVybiB7VH0gRWxlbWVudC5cbiAgICovXG5cblxuICBQcmlvcml0eVF1ZXVlLnByb3RvdHlwZS5kZXF1ZXVlID0gZnVuY3Rpb24gKCkge1xuICAgIHZhciBlbGVtZW50cyA9IHRoaXMuZWxlbWVudHNfO1xuICAgIHZhciBwcmlvcml0aWVzID0gdGhpcy5wcmlvcml0aWVzXztcbiAgICB2YXIgZWxlbWVudCA9IGVsZW1lbnRzWzBdO1xuXG4gICAgaWYgKGVsZW1lbnRzLmxlbmd0aCA9PSAxKSB7XG4gICAgICBlbGVtZW50cy5sZW5ndGggPSAwO1xuICAgICAgcHJpb3JpdGllcy5sZW5ndGggPSAwO1xuICAgIH0gZWxzZSB7XG4gICAgICBlbGVtZW50c1swXSA9IGVsZW1lbnRzLnBvcCgpO1xuICAgICAgcHJpb3JpdGllc1swXSA9IHByaW9yaXRpZXMucG9wKCk7XG4gICAgICB0aGlzLnNpZnRVcF8oMCk7XG4gICAgfVxuXG4gICAgdmFyIGVsZW1lbnRLZXkgPSB0aGlzLmtleUZ1bmN0aW9uXyhlbGVtZW50KTtcbiAgICBkZWxldGUgdGhpcy5xdWV1ZWRFbGVtZW50c19bZWxlbWVudEtleV07XG4gICAgcmV0dXJuIGVsZW1lbnQ7XG4gIH07XG4gIC8qKlxuICAgKiBFbnF1ZXVlIGFuIGVsZW1lbnQuIE8obG9nIE4pLlxuICAgKiBAcGFyYW0ge1R9IGVsZW1lbnQgRWxlbWVudC5cbiAgICogQHJldHVybiB7Ym9vbGVhbn0gVGhlIGVsZW1lbnQgd2FzIGFkZGVkIHRvIHRoZSBxdWV1ZS5cbiAgICovXG5cblxuICBQcmlvcml0eVF1ZXVlLnByb3RvdHlwZS5lbnF1ZXVlID0gZnVuY3Rpb24gKGVsZW1lbnQpIHtcbiAgICBhc3NlcnQoISh0aGlzLmtleUZ1bmN0aW9uXyhlbGVtZW50KSBpbiB0aGlzLnF1ZXVlZEVsZW1lbnRzXyksIDMxKTsgLy8gVHJpZWQgdG8gZW5xdWV1ZSBhbiBgZWxlbWVudGAgdGhhdCB3YXMgYWxyZWFkeSBhZGRlZCB0byB0aGUgcXVldWVcblxuICAgIHZhciBwcmlvcml0eSA9IHRoaXMucHJpb3JpdHlGdW5jdGlvbl8oZWxlbWVudCk7XG5cbiAgICBpZiAocHJpb3JpdHkgIT0gRFJPUCkge1xuICAgICAgdGhpcy5lbGVtZW50c18ucHVzaChlbGVtZW50KTtcbiAgICAgIHRoaXMucHJpb3JpdGllc18ucHVzaChwcmlvcml0eSk7XG4gICAgICB0aGlzLnF1ZXVlZEVsZW1lbnRzX1t0aGlzLmtleUZ1bmN0aW9uXyhlbGVtZW50KV0gPSB0cnVlO1xuICAgICAgdGhpcy5zaWZ0RG93bl8oMCwgdGhpcy5lbGVtZW50c18ubGVuZ3RoIC0gMSk7XG4gICAgICByZXR1cm4gdHJ1ZTtcbiAgICB9XG5cbiAgICByZXR1cm4gZmFsc2U7XG4gIH07XG4gIC8qKlxuICAgKiBAcmV0dXJuIHtudW1iZXJ9IENvdW50LlxuICAgKi9cblxuXG4gIFByaW9yaXR5UXVldWUucHJvdG90eXBlLmdldENvdW50ID0gZnVuY3Rpb24gKCkge1xuICAgIHJldHVybiB0aGlzLmVsZW1lbnRzXy5sZW5ndGg7XG4gIH07XG4gIC8qKlxuICAgKiBHZXRzIHRoZSBpbmRleCBvZiB0aGUgbGVmdCBjaGlsZCBvZiB0aGUgbm9kZSBhdCB0aGUgZ2l2ZW4gaW5kZXguXG4gICAqIEBwYXJhbSB7bnVtYmVyfSBpbmRleCBUaGUgaW5kZXggb2YgdGhlIG5vZGUgdG8gZ2V0IHRoZSBsZWZ0IGNoaWxkIGZvci5cbiAgICogQHJldHVybiB7bnVtYmVyfSBUaGUgaW5kZXggb2YgdGhlIGxlZnQgY2hpbGQuXG4gICAqIEBwcml2YXRlXG4gICAqL1xuXG5cbiAgUHJpb3JpdHlRdWV1ZS5wcm90b3R5cGUuZ2V0TGVmdENoaWxkSW5kZXhfID0gZnVuY3Rpb24gKGluZGV4KSB7XG4gICAgcmV0dXJuIGluZGV4ICogMiArIDE7XG4gIH07XG4gIC8qKlxuICAgKiBHZXRzIHRoZSBpbmRleCBvZiB0aGUgcmlnaHQgY2hpbGQgb2YgdGhlIG5vZGUgYXQgdGhlIGdpdmVuIGluZGV4LlxuICAgKiBAcGFyYW0ge251bWJlcn0gaW5kZXggVGhlIGluZGV4IG9mIHRoZSBub2RlIHRvIGdldCB0aGUgcmlnaHQgY2hpbGQgZm9yLlxuICAgKiBAcmV0dXJuIHtudW1iZXJ9IFRoZSBpbmRleCBvZiB0aGUgcmlnaHQgY2hpbGQuXG4gICAqIEBwcml2YXRlXG4gICAqL1xuXG5cbiAgUHJpb3JpdHlRdWV1ZS5wcm90b3R5cGUuZ2V0UmlnaHRDaGlsZEluZGV4XyA9IGZ1bmN0aW9uIChpbmRleCkge1xuICAgIHJldHVybiBpbmRleCAqIDIgKyAyO1xuICB9O1xuICAvKipcbiAgICogR2V0cyB0aGUgaW5kZXggb2YgdGhlIHBhcmVudCBvZiB0aGUgbm9kZSBhdCB0aGUgZ2l2ZW4gaW5kZXguXG4gICAqIEBwYXJhbSB7bnVtYmVyfSBpbmRleCBUaGUgaW5kZXggb2YgdGhlIG5vZGUgdG8gZ2V0IHRoZSBwYXJlbnQgZm9yLlxuICAgKiBAcmV0dXJuIHtudW1iZXJ9IFRoZSBpbmRleCBvZiB0aGUgcGFyZW50LlxuICAgKiBAcHJpdmF0ZVxuICAgKi9cblxuXG4gIFByaW9yaXR5UXVldWUucHJvdG90eXBlLmdldFBhcmVudEluZGV4XyA9IGZ1bmN0aW9uIChpbmRleCkge1xuICAgIHJldHVybiBpbmRleCAtIDEgPj4gMTtcbiAgfTtcbiAgLyoqXG4gICAqIE1ha2UgdGhpcyBhIGhlYXAuIE8oTikuXG4gICAqIEBwcml2YXRlXG4gICAqL1xuXG5cbiAgUHJpb3JpdHlRdWV1ZS5wcm90b3R5cGUuaGVhcGlmeV8gPSBmdW5jdGlvbiAoKSB7XG4gICAgdmFyIGk7XG5cbiAgICBmb3IgKGkgPSAodGhpcy5lbGVtZW50c18ubGVuZ3RoID4+IDEpIC0gMTsgaSA+PSAwOyBpLS0pIHtcbiAgICAgIHRoaXMuc2lmdFVwXyhpKTtcbiAgICB9XG4gIH07XG4gIC8qKlxuICAgKiBAcmV0dXJuIHtib29sZWFufSBJcyBlbXB0eS5cbiAgICovXG5cblxuICBQcmlvcml0eVF1ZXVlLnByb3RvdHlwZS5pc0VtcHR5ID0gZnVuY3Rpb24gKCkge1xuICAgIHJldHVybiB0aGlzLmVsZW1lbnRzXy5sZW5ndGggPT09IDA7XG4gIH07XG4gIC8qKlxuICAgKiBAcGFyYW0ge3N0cmluZ30ga2V5IEtleS5cbiAgICogQHJldHVybiB7Ym9vbGVhbn0gSXMga2V5IHF1ZXVlZC5cbiAgICovXG5cblxuICBQcmlvcml0eVF1ZXVlLnByb3RvdHlwZS5pc0tleVF1ZXVlZCA9IGZ1bmN0aW9uIChrZXkpIHtcbiAgICByZXR1cm4ga2V5IGluIHRoaXMucXVldWVkRWxlbWVudHNfO1xuICB9O1xuICAvKipcbiAgICogQHBhcmFtIHtUfSBlbGVtZW50IEVsZW1lbnQuXG4gICAqIEByZXR1cm4ge2Jvb2xlYW59IElzIHF1ZXVlZC5cbiAgICovXG5cblxuICBQcmlvcml0eVF1ZXVlLnByb3RvdHlwZS5pc1F1ZXVlZCA9IGZ1bmN0aW9uIChlbGVtZW50KSB7XG4gICAgcmV0dXJuIHRoaXMuaXNLZXlRdWV1ZWQodGhpcy5rZXlGdW5jdGlvbl8oZWxlbWVudCkpO1xuICB9O1xuICAvKipcbiAgICogQHBhcmFtIHtudW1iZXJ9IGluZGV4IFRoZSBpbmRleCBvZiB0aGUgbm9kZSB0byBtb3ZlIGRvd24uXG4gICAqIEBwcml2YXRlXG4gICAqL1xuXG5cbiAgUHJpb3JpdHlRdWV1ZS5wcm90b3R5cGUuc2lmdFVwXyA9IGZ1bmN0aW9uIChpbmRleCkge1xuICAgIHZhciBlbGVtZW50cyA9IHRoaXMuZWxlbWVudHNfO1xuICAgIHZhciBwcmlvcml0aWVzID0gdGhpcy5wcmlvcml0aWVzXztcbiAgICB2YXIgY291bnQgPSBlbGVtZW50cy5sZW5ndGg7XG4gICAgdmFyIGVsZW1lbnQgPSBlbGVtZW50c1tpbmRleF07XG4gICAgdmFyIHByaW9yaXR5ID0gcHJpb3JpdGllc1tpbmRleF07XG4gICAgdmFyIHN0YXJ0SW5kZXggPSBpbmRleDtcblxuICAgIHdoaWxlIChpbmRleCA8IGNvdW50ID4+IDEpIHtcbiAgICAgIHZhciBsSW5kZXggPSB0aGlzLmdldExlZnRDaGlsZEluZGV4XyhpbmRleCk7XG4gICAgICB2YXIgckluZGV4ID0gdGhpcy5nZXRSaWdodENoaWxkSW5kZXhfKGluZGV4KTtcbiAgICAgIHZhciBzbWFsbGVyQ2hpbGRJbmRleCA9IHJJbmRleCA8IGNvdW50ICYmIHByaW9yaXRpZXNbckluZGV4XSA8IHByaW9yaXRpZXNbbEluZGV4XSA/IHJJbmRleCA6IGxJbmRleDtcbiAgICAgIGVsZW1lbnRzW2luZGV4XSA9IGVsZW1lbnRzW3NtYWxsZXJDaGlsZEluZGV4XTtcbiAgICAgIHByaW9yaXRpZXNbaW5kZXhdID0gcHJpb3JpdGllc1tzbWFsbGVyQ2hpbGRJbmRleF07XG4gICAgICBpbmRleCA9IHNtYWxsZXJDaGlsZEluZGV4O1xuICAgIH1cblxuICAgIGVsZW1lbnRzW2luZGV4XSA9IGVsZW1lbnQ7XG4gICAgcHJpb3JpdGllc1tpbmRleF0gPSBwcmlvcml0eTtcbiAgICB0aGlzLnNpZnREb3duXyhzdGFydEluZGV4LCBpbmRleCk7XG4gIH07XG4gIC8qKlxuICAgKiBAcGFyYW0ge251bWJlcn0gc3RhcnRJbmRleCBUaGUgaW5kZXggb2YgdGhlIHJvb3QuXG4gICAqIEBwYXJhbSB7bnVtYmVyfSBpbmRleCBUaGUgaW5kZXggb2YgdGhlIG5vZGUgdG8gbW92ZSB1cC5cbiAgICogQHByaXZhdGVcbiAgICovXG5cblxuICBQcmlvcml0eVF1ZXVlLnByb3RvdHlwZS5zaWZ0RG93bl8gPSBmdW5jdGlvbiAoc3RhcnRJbmRleCwgaW5kZXgpIHtcbiAgICB2YXIgZWxlbWVudHMgPSB0aGlzLmVsZW1lbnRzXztcbiAgICB2YXIgcHJpb3JpdGllcyA9IHRoaXMucHJpb3JpdGllc187XG4gICAgdmFyIGVsZW1lbnQgPSBlbGVtZW50c1tpbmRleF07XG4gICAgdmFyIHByaW9yaXR5ID0gcHJpb3JpdGllc1tpbmRleF07XG5cbiAgICB3aGlsZSAoaW5kZXggPiBzdGFydEluZGV4KSB7XG4gICAgICB2YXIgcGFyZW50SW5kZXggPSB0aGlzLmdldFBhcmVudEluZGV4XyhpbmRleCk7XG5cbiAgICAgIGlmIChwcmlvcml0aWVzW3BhcmVudEluZGV4XSA+IHByaW9yaXR5KSB7XG4gICAgICAgIGVsZW1lbnRzW2luZGV4XSA9IGVsZW1lbnRzW3BhcmVudEluZGV4XTtcbiAgICAgICAgcHJpb3JpdGllc1tpbmRleF0gPSBwcmlvcml0aWVzW3BhcmVudEluZGV4XTtcbiAgICAgICAgaW5kZXggPSBwYXJlbnRJbmRleDtcbiAgICAgIH0gZWxzZSB7XG4gICAgICAgIGJyZWFrO1xuICAgICAgfVxuICAgIH1cblxuICAgIGVsZW1lbnRzW2luZGV4XSA9IGVsZW1lbnQ7XG4gICAgcHJpb3JpdGllc1tpbmRleF0gPSBwcmlvcml0eTtcbiAgfTtcbiAgLyoqXG4gICAqIEZJWE1FIGVtcHR5IGRlc2NyaXB0aW9uIGZvciBqc2RvY1xuICAgKi9cblxuXG4gIFByaW9yaXR5UXVldWUucHJvdG90eXBlLnJlcHJpb3JpdGl6ZSA9IGZ1bmN0aW9uICgpIHtcbiAgICB2YXIgcHJpb3JpdHlGdW5jdGlvbiA9IHRoaXMucHJpb3JpdHlGdW5jdGlvbl87XG4gICAgdmFyIGVsZW1lbnRzID0gdGhpcy5lbGVtZW50c187XG4gICAgdmFyIHByaW9yaXRpZXMgPSB0aGlzLnByaW9yaXRpZXNfO1xuICAgIHZhciBpbmRleCA9IDA7XG4gICAgdmFyIG4gPSBlbGVtZW50cy5sZW5ndGg7XG4gICAgdmFyIGVsZW1lbnQsIGksIHByaW9yaXR5O1xuXG4gICAgZm9yIChpID0gMDsgaSA8IG47ICsraSkge1xuICAgICAgZWxlbWVudCA9IGVsZW1lbnRzW2ldO1xuICAgICAgcHJpb3JpdHkgPSBwcmlvcml0eUZ1bmN0aW9uKGVsZW1lbnQpO1xuXG4gICAgICBpZiAocHJpb3JpdHkgPT0gRFJPUCkge1xuICAgICAgICBkZWxldGUgdGhpcy5xdWV1ZWRFbGVtZW50c19bdGhpcy5rZXlGdW5jdGlvbl8oZWxlbWVudCldO1xuICAgICAgfSBlbHNlIHtcbiAgICAgICAgcHJpb3JpdGllc1tpbmRleF0gPSBwcmlvcml0eTtcbiAgICAgICAgZWxlbWVudHNbaW5kZXgrK10gPSBlbGVtZW50O1xuICAgICAgfVxuICAgIH1cblxuICAgIGVsZW1lbnRzLmxlbmd0aCA9IGluZGV4O1xuICAgIHByaW9yaXRpZXMubGVuZ3RoID0gaW5kZXg7XG4gICAgdGhpcy5oZWFwaWZ5XygpO1xuICB9O1xuXG4gIHJldHVybiBQcmlvcml0eVF1ZXVlO1xufSgpO1xuXG5leHBvcnQgZGVmYXVsdCBQcmlvcml0eVF1ZXVlOyIsIi8qKlxuICogQG1vZHVsZSBvbC9UaWxlU3RhdGVcbiAqL1xuXG4vKipcbiAqIEBlbnVtIHtudW1iZXJ9XG4gKi9cbmV4cG9ydCBkZWZhdWx0IHtcbiAgSURMRTogMCxcbiAgTE9BRElORzogMSxcbiAgTE9BREVEOiAyLFxuXG4gIC8qKlxuICAgKiBJbmRpY2F0ZXMgdGhhdCB0aWxlIGxvYWRpbmcgZmFpbGVkXG4gICAqIEB0eXBlIHtudW1iZXJ9XG4gICAqL1xuICBFUlJPUjogMyxcbiAgRU1QVFk6IDRcbn07IiwidmFyIF9fZXh0ZW5kcyA9IHRoaXMgJiYgdGhpcy5fX2V4dGVuZHMgfHwgZnVuY3Rpb24gKCkge1xuICB2YXIgX2V4dGVuZFN0YXRpY3MgPSBmdW5jdGlvbiBleHRlbmRTdGF0aWNzKGQsIGIpIHtcbiAgICBfZXh0ZW5kU3RhdGljcyA9IE9iamVjdC5zZXRQcm90b3R5cGVPZiB8fCB7XG4gICAgICBfX3Byb3RvX186IFtdXG4gICAgfSBpbnN0YW5jZW9mIEFycmF5ICYmIGZ1bmN0aW9uIChkLCBiKSB7XG4gICAgICBkLl9fcHJvdG9fXyA9IGI7XG4gICAgfSB8fCBmdW5jdGlvbiAoZCwgYikge1xuICAgICAgZm9yICh2YXIgcCBpbiBiKSB7XG4gICAgICAgIGlmIChPYmplY3QucHJvdG90eXBlLmhhc093blByb3BlcnR5LmNhbGwoYiwgcCkpIGRbcF0gPSBiW3BdO1xuICAgICAgfVxuICAgIH07XG5cbiAgICByZXR1cm4gX2V4dGVuZFN0YXRpY3MoZCwgYik7XG4gIH07XG5cbiAgcmV0dXJuIGZ1bmN0aW9uIChkLCBiKSB7XG4gICAgX2V4dGVuZFN0YXRpY3MoZCwgYik7XG5cbiAgICBmdW5jdGlvbiBfXygpIHtcbiAgICAgIHRoaXMuY29uc3RydWN0b3IgPSBkO1xuICAgIH1cblxuICAgIGQucHJvdG90eXBlID0gYiA9PT0gbnVsbCA/IE9iamVjdC5jcmVhdGUoYikgOiAoX18ucHJvdG90eXBlID0gYi5wcm90b3R5cGUsIG5ldyBfXygpKTtcbiAgfTtcbn0oKTtcbi8qKlxuICogQG1vZHVsZSBvbC9UaWxlUXVldWVcbiAqL1xuXG5cbmltcG9ydCBFdmVudFR5cGUgZnJvbSAnLi9ldmVudHMvRXZlbnRUeXBlLmpzJztcbmltcG9ydCBQcmlvcml0eVF1ZXVlLCB7IERST1AgfSBmcm9tICcuL3N0cnVjdHMvUHJpb3JpdHlRdWV1ZS5qcyc7XG5pbXBvcnQgVGlsZVN0YXRlIGZyb20gJy4vVGlsZVN0YXRlLmpzJztcbi8qKlxuICogQHR5cGVkZWYge2Z1bmN0aW9uKGltcG9ydChcIi4vVGlsZS5qc1wiKS5kZWZhdWx0LCBzdHJpbmcsIGltcG9ydChcIi4vY29vcmRpbmF0ZS5qc1wiKS5Db29yZGluYXRlLCBudW1iZXIpOiBudW1iZXJ9IFByaW9yaXR5RnVuY3Rpb25cbiAqL1xuXG52YXIgVGlsZVF1ZXVlID1cbi8qKiBAY2xhc3MgKi9cbmZ1bmN0aW9uIChfc3VwZXIpIHtcbiAgX19leHRlbmRzKFRpbGVRdWV1ZSwgX3N1cGVyKTtcbiAgLyoqXG4gICAqIEBwYXJhbSB7UHJpb3JpdHlGdW5jdGlvbn0gdGlsZVByaW9yaXR5RnVuY3Rpb24gVGlsZSBwcmlvcml0eSBmdW5jdGlvbi5cbiAgICogQHBhcmFtIHtmdW5jdGlvbigpOiA/fSB0aWxlQ2hhbmdlQ2FsbGJhY2sgRnVuY3Rpb24gY2FsbGVkIG9uIGVhY2ggdGlsZSBjaGFuZ2UgZXZlbnQuXG4gICAqL1xuXG5cbiAgZnVuY3Rpb24gVGlsZVF1ZXVlKHRpbGVQcmlvcml0eUZ1bmN0aW9uLCB0aWxlQ2hhbmdlQ2FsbGJhY2spIHtcbiAgICB2YXIgX3RoaXMgPSBfc3VwZXIuY2FsbCh0aGlzLFxuICAgIC8qKlxuICAgICAqIEBwYXJhbSB7QXJyYXl9IGVsZW1lbnQgRWxlbWVudC5cbiAgICAgKiBAcmV0dXJuIHtudW1iZXJ9IFByaW9yaXR5LlxuICAgICAqL1xuICAgIGZ1bmN0aW9uIChlbGVtZW50KSB7XG4gICAgICByZXR1cm4gdGlsZVByaW9yaXR5RnVuY3Rpb24uYXBwbHkobnVsbCwgZWxlbWVudCk7XG4gICAgfSxcbiAgICAvKipcbiAgICAgKiBAcGFyYW0ge0FycmF5fSBlbGVtZW50IEVsZW1lbnQuXG4gICAgICogQHJldHVybiB7c3RyaW5nfSBLZXkuXG4gICAgICovXG4gICAgZnVuY3Rpb24gKGVsZW1lbnQpIHtcbiAgICAgIHJldHVybiAoXG4gICAgICAgIC8qKiBAdHlwZSB7aW1wb3J0KFwiLi9UaWxlLmpzXCIpLmRlZmF1bHR9ICovXG4gICAgICAgIGVsZW1lbnRbMF0uZ2V0S2V5KClcbiAgICAgICk7XG4gICAgfSkgfHwgdGhpcztcbiAgICAvKiogQHByaXZhdGUgKi9cblxuXG4gICAgX3RoaXMuYm91bmRIYW5kbGVUaWxlQ2hhbmdlXyA9IF90aGlzLmhhbmRsZVRpbGVDaGFuZ2UuYmluZChfdGhpcyk7XG4gICAgLyoqXG4gICAgICogQHByaXZhdGVcbiAgICAgKiBAdHlwZSB7ZnVuY3Rpb24oKTogP31cbiAgICAgKi9cblxuICAgIF90aGlzLnRpbGVDaGFuZ2VDYWxsYmFja18gPSB0aWxlQ2hhbmdlQ2FsbGJhY2s7XG4gICAgLyoqXG4gICAgICogQHByaXZhdGVcbiAgICAgKiBAdHlwZSB7bnVtYmVyfVxuICAgICAqL1xuXG4gICAgX3RoaXMudGlsZXNMb2FkaW5nXyA9IDA7XG4gICAgLyoqXG4gICAgICogQHByaXZhdGVcbiAgICAgKiBAdHlwZSB7IU9iamVjdDxzdHJpbmcsYm9vbGVhbj59XG4gICAgICovXG5cbiAgICBfdGhpcy50aWxlc0xvYWRpbmdLZXlzXyA9IHt9O1xuICAgIHJldHVybiBfdGhpcztcbiAgfVxuICAvKipcbiAgICogQHBhcmFtIHtBcnJheX0gZWxlbWVudCBFbGVtZW50LlxuICAgKiBAcmV0dXJuIHtib29sZWFufSBUaGUgZWxlbWVudCB3YXMgYWRkZWQgdG8gdGhlIHF1ZXVlLlxuICAgKi9cblxuXG4gIFRpbGVRdWV1ZS5wcm90b3R5cGUuZW5xdWV1ZSA9IGZ1bmN0aW9uIChlbGVtZW50KSB7XG4gICAgdmFyIGFkZGVkID0gX3N1cGVyLnByb3RvdHlwZS5lbnF1ZXVlLmNhbGwodGhpcywgZWxlbWVudCk7XG5cbiAgICBpZiAoYWRkZWQpIHtcbiAgICAgIHZhciB0aWxlID0gZWxlbWVudFswXTtcbiAgICAgIHRpbGUuYWRkRXZlbnRMaXN0ZW5lcihFdmVudFR5cGUuQ0hBTkdFLCB0aGlzLmJvdW5kSGFuZGxlVGlsZUNoYW5nZV8pO1xuICAgIH1cblxuICAgIHJldHVybiBhZGRlZDtcbiAgfTtcbiAgLyoqXG4gICAqIEByZXR1cm4ge251bWJlcn0gTnVtYmVyIG9mIHRpbGVzIGxvYWRpbmcuXG4gICAqL1xuXG5cbiAgVGlsZVF1ZXVlLnByb3RvdHlwZS5nZXRUaWxlc0xvYWRpbmcgPSBmdW5jdGlvbiAoKSB7XG4gICAgcmV0dXJuIHRoaXMudGlsZXNMb2FkaW5nXztcbiAgfTtcbiAgLyoqXG4gICAqIEBwYXJhbSB7aW1wb3J0KFwiLi9ldmVudHMvRXZlbnQuanNcIikuZGVmYXVsdH0gZXZlbnQgRXZlbnQuXG4gICAqIEBwcm90ZWN0ZWRcbiAgICovXG5cblxuICBUaWxlUXVldWUucHJvdG90eXBlLmhhbmRsZVRpbGVDaGFuZ2UgPSBmdW5jdGlvbiAoZXZlbnQpIHtcbiAgICB2YXIgdGlsZSA9XG4gICAgLyoqIEB0eXBlIHtpbXBvcnQoXCIuL1RpbGUuanNcIikuZGVmYXVsdH0gKi9cbiAgICBldmVudC50YXJnZXQ7XG4gICAgdmFyIHN0YXRlID0gdGlsZS5nZXRTdGF0ZSgpO1xuXG4gICAgaWYgKHRpbGUuaGlmaSAmJiBzdGF0ZSA9PT0gVGlsZVN0YXRlLkxPQURFRCB8fCBzdGF0ZSA9PT0gVGlsZVN0YXRlLkVSUk9SIHx8IHN0YXRlID09PSBUaWxlU3RhdGUuRU1QVFkpIHtcbiAgICAgIHRpbGUucmVtb3ZlRXZlbnRMaXN0ZW5lcihFdmVudFR5cGUuQ0hBTkdFLCB0aGlzLmJvdW5kSGFuZGxlVGlsZUNoYW5nZV8pO1xuICAgICAgdmFyIHRpbGVLZXkgPSB0aWxlLmdldEtleSgpO1xuXG4gICAgICBpZiAodGlsZUtleSBpbiB0aGlzLnRpbGVzTG9hZGluZ0tleXNfKSB7XG4gICAgICAgIGRlbGV0ZSB0aGlzLnRpbGVzTG9hZGluZ0tleXNfW3RpbGVLZXldO1xuICAgICAgICAtLXRoaXMudGlsZXNMb2FkaW5nXztcbiAgICAgIH1cblxuICAgICAgdGhpcy50aWxlQ2hhbmdlQ2FsbGJhY2tfKCk7XG4gICAgfVxuICB9O1xuICAvKipcbiAgICogQHBhcmFtIHtudW1iZXJ9IG1heFRvdGFsTG9hZGluZyBNYXhpbXVtIG51bWJlciB0aWxlcyB0byBsb2FkIHNpbXVsdGFuZW91c2x5LlxuICAgKiBAcGFyYW0ge251bWJlcn0gbWF4TmV3TG9hZHMgTWF4aW11bSBudW1iZXIgb2YgbmV3IHRpbGVzIHRvIGxvYWQuXG4gICAqL1xuXG5cbiAgVGlsZVF1ZXVlLnByb3RvdHlwZS5sb2FkTW9yZVRpbGVzID0gZnVuY3Rpb24gKG1heFRvdGFsTG9hZGluZywgbWF4TmV3TG9hZHMpIHtcbiAgICB2YXIgbmV3TG9hZHMgPSAwO1xuICAgIHZhciBzdGF0ZSwgdGlsZSwgdGlsZUtleTtcblxuICAgIHdoaWxlICh0aGlzLnRpbGVzTG9hZGluZ18gPCBtYXhUb3RhbExvYWRpbmcgJiYgbmV3TG9hZHMgPCBtYXhOZXdMb2FkcyAmJiB0aGlzLmdldENvdW50KCkgPiAwKSB7XG4gICAgICB0aWxlID1cbiAgICAgIC8qKiBAdHlwZSB7aW1wb3J0KFwiLi9UaWxlLmpzXCIpLmRlZmF1bHR9ICovXG4gICAgICB0aGlzLmRlcXVldWUoKVswXTtcbiAgICAgIHRpbGVLZXkgPSB0aWxlLmdldEtleSgpO1xuICAgICAgc3RhdGUgPSB0aWxlLmdldFN0YXRlKCk7XG5cbiAgICAgIGlmIChzdGF0ZSA9PT0gVGlsZVN0YXRlLklETEUgJiYgISh0aWxlS2V5IGluIHRoaXMudGlsZXNMb2FkaW5nS2V5c18pKSB7XG4gICAgICAgIHRoaXMudGlsZXNMb2FkaW5nS2V5c19bdGlsZUtleV0gPSB0cnVlO1xuICAgICAgICArK3RoaXMudGlsZXNMb2FkaW5nXztcbiAgICAgICAgKytuZXdMb2FkcztcbiAgICAgICAgdGlsZS5sb2FkKCk7XG4gICAgICB9XG4gICAgfVxuICB9O1xuXG4gIHJldHVybiBUaWxlUXVldWU7XG59KFByaW9yaXR5UXVldWUpO1xuXG5leHBvcnQgZGVmYXVsdCBUaWxlUXVldWU7XG4vKipcbiAqIEBwYXJhbSB7aW1wb3J0KCcuL1BsdWdnYWJsZU1hcC5qcycpLkZyYW1lU3RhdGV9IGZyYW1lU3RhdGUgRnJhbWUgc3RhdGUuXG4gKiBAcGFyYW0ge2ltcG9ydChcIi4vVGlsZS5qc1wiKS5kZWZhdWx0fSB0aWxlIFRpbGUuXG4gKiBAcGFyYW0ge3N0cmluZ30gdGlsZVNvdXJjZUtleSBUaWxlIHNvdXJjZSBrZXkuXG4gKiBAcGFyYW0ge2ltcG9ydChcIi4vY29vcmRpbmF0ZS5qc1wiKS5Db29yZGluYXRlfSB0aWxlQ2VudGVyIFRpbGUgY2VudGVyLlxuICogQHBhcmFtIHtudW1iZXJ9IHRpbGVSZXNvbHV0aW9uIFRpbGUgcmVzb2x1dGlvbi5cbiAqIEByZXR1cm4ge251bWJlcn0gVGlsZSBwcmlvcml0eS5cbiAqL1xuXG5leHBvcnQgZnVuY3Rpb24gZ2V0VGlsZVByaW9yaXR5KGZyYW1lU3RhdGUsIHRpbGUsIHRpbGVTb3VyY2VLZXksIHRpbGVDZW50ZXIsIHRpbGVSZXNvbHV0aW9uKSB7XG4gIC8vIEZpbHRlciBvdXQgdGlsZXMgYXQgaGlnaGVyIHpvb20gbGV2ZWxzIHRoYW4gdGhlIGN1cnJlbnQgem9vbSBsZXZlbCwgb3IgdGhhdFxuICAvLyBhcmUgb3V0c2lkZSB0aGUgdmlzaWJsZSBleHRlbnQuXG4gIGlmICghZnJhbWVTdGF0ZSB8fCAhKHRpbGVTb3VyY2VLZXkgaW4gZnJhbWVTdGF0ZS53YW50ZWRUaWxlcykpIHtcbiAgICByZXR1cm4gRFJPUDtcbiAgfVxuXG4gIGlmICghZnJhbWVTdGF0ZS53YW50ZWRUaWxlc1t0aWxlU291cmNlS2V5XVt0aWxlLmdldEtleSgpXSkge1xuICAgIHJldHVybiBEUk9QO1xuICB9IC8vIFByaW9yaXRpemUgdGhlIGhpZ2hlc3Qgem9vbSBsZXZlbCB0aWxlcyBjbG9zZXN0IHRvIHRoZSBmb2N1cy5cbiAgLy8gVGlsZXMgYXQgaGlnaGVyIHpvb20gbGV2ZWxzIGFyZSBwcmlvcml0aXplZCB1c2luZyBNYXRoLmxvZyh0aWxlUmVzb2x1dGlvbikuXG4gIC8vIFdpdGhpbiBhIHpvb20gbGV2ZWwsIHRpbGVzIGFyZSBwcmlvcml0aXplZCBieSB0aGUgZGlzdGFuY2UgaW4gcGl4ZWxzIGJldHdlZW5cbiAgLy8gdGhlIGNlbnRlciBvZiB0aGUgdGlsZSBhbmQgdGhlIGNlbnRlciBvZiB0aGUgdmlld3BvcnQuICBUaGUgZmFjdG9yIG9mIDY1NTM2XG4gIC8vIG1lYW5zIHRoYXQgdGhlIHByaW9yaXRpemF0aW9uIHNob3VsZCBiZWhhdmUgYXMgZGVzaXJlZCBmb3IgdGlsZXMgdXAgdG9cbiAgLy8gNjU1MzYgKiBNYXRoLmxvZygyKSA9IDQ1NDI2IHBpeGVscyBmcm9tIHRoZSBmb2N1cy5cblxuXG4gIHZhciBjZW50ZXIgPSBmcmFtZVN0YXRlLnZpZXdTdGF0ZS5jZW50ZXI7XG4gIHZhciBkZWx0YVggPSB0aWxlQ2VudGVyWzBdIC0gY2VudGVyWzBdO1xuICB2YXIgZGVsdGFZID0gdGlsZUNlbnRlclsxXSAtIGNlbnRlclsxXTtcbiAgcmV0dXJuIDY1NTM2ICogTWF0aC5sb2codGlsZVJlc29sdXRpb24pICsgTWF0aC5zcXJ0KGRlbHRhWCAqIGRlbHRhWCArIGRlbHRhWSAqIGRlbHRhWSkgLyB0aWxlUmVzb2x1dGlvbjtcbn0iLCIvKipcbiAqIEBtb2R1bGUgb2wvZ2VvbS9HZW9tZXRyeVR5cGVcbiAqL1xuXG4vKipcbiAqIFRoZSBnZW9tZXRyeSB0eXBlLiBPbmUgb2YgYCdQb2ludCdgLCBgJ0xpbmVTdHJpbmcnYCwgYCdMaW5lYXJSaW5nJ2AsXG4gKiBgJ1BvbHlnb24nYCwgYCdNdWx0aVBvaW50J2AsIGAnTXVsdGlMaW5lU3RyaW5nJ2AsIGAnTXVsdGlQb2x5Z29uJ2AsXG4gKiBgJ0dlb21ldHJ5Q29sbGVjdGlvbidgLCBgJ0NpcmNsZSdgLlxuICogQGVudW0ge3N0cmluZ31cbiAqL1xuZXhwb3J0IGRlZmF1bHQge1xuICBQT0lOVDogJ1BvaW50JyxcbiAgTElORV9TVFJJTkc6ICdMaW5lU3RyaW5nJyxcbiAgTElORUFSX1JJTkc6ICdMaW5lYXJSaW5nJyxcbiAgUE9MWUdPTjogJ1BvbHlnb24nLFxuICBNVUxUSV9QT0lOVDogJ011bHRpUG9pbnQnLFxuICBNVUxUSV9MSU5FX1NUUklORzogJ011bHRpTGluZVN0cmluZycsXG4gIE1VTFRJX1BPTFlHT046ICdNdWx0aVBvbHlnb24nLFxuICBHRU9NRVRSWV9DT0xMRUNUSU9OOiAnR2VvbWV0cnlDb2xsZWN0aW9uJyxcbiAgQ0lSQ0xFOiAnQ2lyY2xlJ1xufTsiLCIvKipcbiAqIEBtb2R1bGUgb2wvcHJvai9Vbml0c1xuICovXG5cbi8qKlxuICogUHJvamVjdGlvbiB1bml0czogYCdkZWdyZWVzJ2AsIGAnZnQnYCwgYCdtJ2AsIGAncGl4ZWxzJ2AsIGAndGlsZS1waXhlbHMnYCBvclxuICogYCd1cy1mdCdgLlxuICogQGVudW0ge3N0cmluZ31cbiAqL1xudmFyIFVuaXRzID0ge1xuICAvKipcbiAgICogRGVncmVlc1xuICAgKiBAYXBpXG4gICAqL1xuICBERUdSRUVTOiAnZGVncmVlcycsXG5cbiAgLyoqXG4gICAqIEZlZXRcbiAgICogQGFwaVxuICAgKi9cbiAgRkVFVDogJ2Z0JyxcblxuICAvKipcbiAgICogTWV0ZXJzXG4gICAqIEBhcGlcbiAgICovXG4gIE1FVEVSUzogJ20nLFxuXG4gIC8qKlxuICAgKiBQaXhlbHNcbiAgICogQGFwaVxuICAgKi9cbiAgUElYRUxTOiAncGl4ZWxzJyxcblxuICAvKipcbiAgICogVGlsZSBQaXhlbHNcbiAgICogQGFwaVxuICAgKi9cbiAgVElMRV9QSVhFTFM6ICd0aWxlLXBpeGVscycsXG5cbiAgLyoqXG4gICAqIFVTIEZlZXRcbiAgICogQGFwaVxuICAgKi9cbiAgVVNGRUVUOiAndXMtZnQnXG59O1xuLyoqXG4gKiBNZXRlcnMgcGVyIHVuaXQgbG9va3VwIHRhYmxlLlxuICogQGNvbnN0XG4gKiBAdHlwZSB7T2JqZWN0PFVuaXRzLCBudW1iZXI+fVxuICogQGFwaVxuICovXG5cbmV4cG9ydCB2YXIgTUVURVJTX1BFUl9VTklUID0ge307IC8vIHVzZSB0aGUgcmFkaXVzIG9mIHRoZSBOb3JtYWwgc3BoZXJlXG5cbk1FVEVSU19QRVJfVU5JVFtVbml0cy5ERUdSRUVTXSA9IDIgKiBNYXRoLlBJICogNjM3MDk5NyAvIDM2MDtcbk1FVEVSU19QRVJfVU5JVFtVbml0cy5GRUVUXSA9IDAuMzA0ODtcbk1FVEVSU19QRVJfVU5JVFtVbml0cy5NRVRFUlNdID0gMTtcbk1FVEVSU19QRVJfVU5JVFtVbml0cy5VU0ZFRVRdID0gMTIwMCAvIDM5Mzc7XG5leHBvcnQgZGVmYXVsdCBVbml0czsiLCIvKipcbiAqIEBtb2R1bGUgb2wvVmlld0hpbnRcbiAqL1xuXG4vKipcbiAqIEBlbnVtIHtudW1iZXJ9XG4gKi9cbmV4cG9ydCBkZWZhdWx0IHtcbiAgQU5JTUFUSU5HOiAwLFxuICBJTlRFUkFDVElORzogMVxufTsiLCIvKipcbiAqIEBtb2R1bGUgb2wvVmlld1Byb3BlcnR5XG4gKi9cblxuLyoqXG4gKiBAZW51bSB7c3RyaW5nfVxuICovXG5leHBvcnQgZGVmYXVsdCB7XG4gIENFTlRFUjogJ2NlbnRlcicsXG4gIFJFU09MVVRJT046ICdyZXNvbHV0aW9uJyxcbiAgUk9UQVRJT046ICdyb3RhdGlvbidcbn07IiwiLyoqXG4gKiBAbW9kdWxlIG9sL3RpbGVncmlkL2NvbW1vblxuICovXG5cbi8qKlxuICogRGVmYXVsdCBtYXhpbXVtIHpvb20gZm9yIGRlZmF1bHQgdGlsZSBncmlkcy5cbiAqIEB0eXBlIHtudW1iZXJ9XG4gKi9cbmV4cG9ydCB2YXIgREVGQVVMVF9NQVhfWk9PTSA9IDQyO1xuLyoqXG4gKiBEZWZhdWx0IHRpbGUgc2l6ZS5cbiAqIEB0eXBlIHtudW1iZXJ9XG4gKi9cblxuZXhwb3J0IHZhciBERUZBVUxUX1RJTEVfU0laRSA9IDI1NjsiLCIvKipcbiAqIEBtb2R1bGUgb2wvcHJvai9Qcm9qZWN0aW9uXG4gKi9cbmltcG9ydCB7IE1FVEVSU19QRVJfVU5JVCB9IGZyb20gJy4vVW5pdHMuanMnO1xuLyoqXG4gKiBAdHlwZWRlZiB7T2JqZWN0fSBPcHRpb25zXG4gKiBAcHJvcGVydHkge3N0cmluZ30gY29kZSBUaGUgU1JTIGlkZW50aWZpZXIgY29kZSwgZS5nLiBgRVBTRzo0MzI2YC5cbiAqIEBwcm9wZXJ0eSB7aW1wb3J0KFwiLi9Vbml0cy5qc1wiKS5kZWZhdWx0fHN0cmluZ30gW3VuaXRzXSBVbml0cy4gUmVxdWlyZWQgdW5sZXNzIGFcbiAqIHByb2o0IHByb2plY3Rpb24gaXMgZGVmaW5lZCBmb3IgYGNvZGVgLlxuICogQHByb3BlcnR5IHtpbXBvcnQoXCIuLi9leHRlbnQuanNcIikuRXh0ZW50fSBbZXh0ZW50XSBUaGUgdmFsaWRpdHkgZXh0ZW50IGZvciB0aGUgU1JTLlxuICogQHByb3BlcnR5IHtzdHJpbmd9IFtheGlzT3JpZW50YXRpb249J2VudSddIFRoZSBheGlzIG9yaWVudGF0aW9uIGFzIHNwZWNpZmllZCBpbiBQcm9qNC5cbiAqIEBwcm9wZXJ0eSB7Ym9vbGVhbn0gW2dsb2JhbD1mYWxzZV0gV2hldGhlciB0aGUgcHJvamVjdGlvbiBpcyB2YWxpZCBmb3IgdGhlIHdob2xlIGdsb2JlLlxuICogQHByb3BlcnR5IHtudW1iZXJ9IFttZXRlcnNQZXJVbml0XSBUaGUgbWV0ZXJzIHBlciB1bml0IGZvciB0aGUgU1JTLlxuICogSWYgbm90IHByb3ZpZGVkLCB0aGUgYHVuaXRzYCBhcmUgdXNlZCB0byBnZXQgdGhlIG1ldGVycyBwZXIgdW5pdCBmcm9tIHRoZSB7QGxpbmsgbW9kdWxlOm9sL3Byb2ovVW5pdHN+TUVURVJTX1BFUl9VTklUfVxuICogbG9va3VwIHRhYmxlLlxuICogQHByb3BlcnR5IHtpbXBvcnQoXCIuLi9leHRlbnQuanNcIikuRXh0ZW50fSBbd29ybGRFeHRlbnRdIFRoZSB3b3JsZCBleHRlbnQgZm9yIHRoZSBTUlMuXG4gKiBAcHJvcGVydHkge2Z1bmN0aW9uKG51bWJlciwgaW1wb3J0KFwiLi4vY29vcmRpbmF0ZS5qc1wiKS5Db29yZGluYXRlKTpudW1iZXJ9IFtnZXRQb2ludFJlc29sdXRpb25dXG4gKiBGdW5jdGlvbiB0byBkZXRlcm1pbmUgcmVzb2x1dGlvbiBhdCBhIHBvaW50LiBUaGUgZnVuY3Rpb24gaXMgY2FsbGVkIHdpdGggYVxuICogYHtudW1iZXJ9YCB2aWV3IHJlc29sdXRpb24gYW5kIGFuIGB7aW1wb3J0KFwiLi4vY29vcmRpbmF0ZS5qc1wiKS5Db29yZGluYXRlfWAgYXMgYXJndW1lbnRzLCBhbmQgcmV0dXJuc1xuICogdGhlIGB7bnVtYmVyfWAgcmVzb2x1dGlvbiBpbiBwcm9qZWN0aW9uIHVuaXRzIGF0IHRoZSBwYXNzZWQgY29vcmRpbmF0ZS4gSWYgdGhpcyBpcyBgdW5kZWZpbmVkYCxcbiAqIHRoZSBkZWZhdWx0IHtAbGluayBtb2R1bGU6b2wvcHJvaiNnZXRQb2ludFJlc29sdXRpb259IGZ1bmN0aW9uIHdpbGwgYmUgdXNlZC5cbiAqL1xuXG4vKipcbiAqIEBjbGFzc2Rlc2NcbiAqIFByb2plY3Rpb24gZGVmaW5pdGlvbiBjbGFzcy4gT25lIG9mIHRoZXNlIGlzIGNyZWF0ZWQgZm9yIGVhY2ggcHJvamVjdGlvblxuICogc3VwcG9ydGVkIGluIHRoZSBhcHBsaWNhdGlvbiBhbmQgc3RvcmVkIGluIHRoZSB7QGxpbmsgbW9kdWxlOm9sL3Byb2p9IG5hbWVzcGFjZS5cbiAqIFlvdSBjYW4gdXNlIHRoZXNlIGluIGFwcGxpY2F0aW9ucywgYnV0IHRoaXMgaXMgbm90IHJlcXVpcmVkLCBhcyBBUEkgcGFyYW1zXG4gKiBhbmQgb3B0aW9ucyB1c2Uge0BsaW5rIG1vZHVsZTpvbC9wcm9qflByb2plY3Rpb25MaWtlfSB3aGljaCBtZWFucyB0aGUgc2ltcGxlIHN0cmluZ1xuICogY29kZSB3aWxsIHN1ZmZpY2UuXG4gKlxuICogWW91IGNhbiB1c2Uge0BsaW5rIG1vZHVsZTpvbC9wcm9qfmdldH0gdG8gcmV0cmlldmUgdGhlIG9iamVjdCBmb3IgYSBwYXJ0aWN1bGFyXG4gKiBwcm9qZWN0aW9uLlxuICpcbiAqIFRoZSBsaWJyYXJ5IGluY2x1ZGVzIGRlZmluaXRpb25zIGZvciBgRVBTRzo0MzI2YCBhbmQgYEVQU0c6Mzg1N2AsIHRvZ2V0aGVyXG4gKiB3aXRoIHRoZSBmb2xsb3dpbmcgYWxpYXNlczpcbiAqICogYEVQU0c6NDMyNmA6IENSUzo4NCwgdXJuOm9nYzpkZWY6Y3JzOkVQU0c6Ni42OjQzMjYsXG4gKiAgICAgdXJuOm9nYzpkZWY6Y3JzOk9HQzoxLjM6Q1JTODQsIHVybjpvZ2M6ZGVmOmNyczpPR0M6Mjo4NCxcbiAqICAgICBodHRwOi8vd3d3Lm9wZW5naXMubmV0L2dtbC9zcnMvZXBzZy54bWwjNDMyNixcbiAqICAgICB1cm46eC1vZ2M6ZGVmOmNyczpFUFNHOjQzMjZcbiAqICogYEVQU0c6Mzg1N2A6IEVQU0c6MTAyMTAwLCBFUFNHOjEwMjExMywgRVBTRzo5MDA5MTMsXG4gKiAgICAgdXJuOm9nYzpkZWY6Y3JzOkVQU0c6Ni4xODozOjM4NTcsXG4gKiAgICAgaHR0cDovL3d3dy5vcGVuZ2lzLm5ldC9nbWwvc3JzL2Vwc2cueG1sIzM4NTdcbiAqXG4gKiBJZiB5b3UgdXNlIFtwcm9qNGpzXShodHRwczovL2dpdGh1Yi5jb20vcHJvajRqcy9wcm9qNGpzKSwgYWxpYXNlcyBjYW5cbiAqIGJlIGFkZGVkIHVzaW5nIGBwcm9qNC5kZWZzKClgLiBBZnRlciBhbGwgcmVxdWlyZWQgcHJvamVjdGlvbiBkZWZpbml0aW9ucyBhcmVcbiAqIGFkZGVkLCBjYWxsIHRoZSB7QGxpbmsgbW9kdWxlOm9sL3Byb2ovcHJvajR+cmVnaXN0ZXJ9IGZ1bmN0aW9uLlxuICpcbiAqIEBhcGlcbiAqL1xuXG52YXIgUHJvamVjdGlvbiA9XG4vKiogQGNsYXNzICovXG5mdW5jdGlvbiAoKSB7XG4gIC8qKlxuICAgKiBAcGFyYW0ge09wdGlvbnN9IG9wdGlvbnMgUHJvamVjdGlvbiBvcHRpb25zLlxuICAgKi9cbiAgZnVuY3Rpb24gUHJvamVjdGlvbihvcHRpb25zKSB7XG4gICAgLyoqXG4gICAgICogQHByaXZhdGVcbiAgICAgKiBAdHlwZSB7c3RyaW5nfVxuICAgICAqL1xuICAgIHRoaXMuY29kZV8gPSBvcHRpb25zLmNvZGU7XG4gICAgLyoqXG4gICAgICogVW5pdHMgb2YgcHJvamVjdGVkIGNvb3JkaW5hdGVzLiBXaGVuIHNldCB0byBgVElMRV9QSVhFTFNgLCBhXG4gICAgICogYHRoaXMuZXh0ZW50X2AgYW5kIGB0aGlzLndvcmxkRXh0ZW50X2AgbXVzdCBiZSBjb25maWd1cmVkIHByb3Blcmx5IGZvciBlYWNoXG4gICAgICogdGlsZS5cbiAgICAgKiBAcHJpdmF0ZVxuICAgICAqIEB0eXBlIHtpbXBvcnQoXCIuL1VuaXRzLmpzXCIpLmRlZmF1bHR9XG4gICAgICovXG5cbiAgICB0aGlzLnVuaXRzXyA9XG4gICAgLyoqIEB0eXBlIHtpbXBvcnQoXCIuL1VuaXRzLmpzXCIpLmRlZmF1bHR9ICovXG4gICAgb3B0aW9ucy51bml0cztcbiAgICAvKipcbiAgICAgKiBWYWxpZGl0eSBleHRlbnQgb2YgdGhlIHByb2plY3Rpb24gaW4gcHJvamVjdGVkIGNvb3JkaW5hdGVzLiBGb3IgcHJvamVjdGlvbnNcbiAgICAgKiB3aXRoIGBUSUxFX1BJWEVMU2AgdW5pdHMsIHRoaXMgaXMgdGhlIGV4dGVudCBvZiB0aGUgdGlsZSBpblxuICAgICAqIHRpbGUgcGl4ZWwgc3BhY2UuXG4gICAgICogQHByaXZhdGVcbiAgICAgKiBAdHlwZSB7aW1wb3J0KFwiLi4vZXh0ZW50LmpzXCIpLkV4dGVudH1cbiAgICAgKi9cblxuICAgIHRoaXMuZXh0ZW50XyA9IG9wdGlvbnMuZXh0ZW50ICE9PSB1bmRlZmluZWQgPyBvcHRpb25zLmV4dGVudCA6IG51bGw7XG4gICAgLyoqXG4gICAgICogRXh0ZW50IG9mIHRoZSB3b3JsZCBpbiBFUFNHOjQzMjYuIEZvciBwcm9qZWN0aW9ucyB3aXRoXG4gICAgICogYFRJTEVfUElYRUxTYCB1bml0cywgdGhpcyBpcyB0aGUgZXh0ZW50IG9mIHRoZSB0aWxlIGluXG4gICAgICogcHJvamVjdGVkIGNvb3JkaW5hdGUgc3BhY2UuXG4gICAgICogQHByaXZhdGVcbiAgICAgKiBAdHlwZSB7aW1wb3J0KFwiLi4vZXh0ZW50LmpzXCIpLkV4dGVudH1cbiAgICAgKi9cblxuICAgIHRoaXMud29ybGRFeHRlbnRfID0gb3B0aW9ucy53b3JsZEV4dGVudCAhPT0gdW5kZWZpbmVkID8gb3B0aW9ucy53b3JsZEV4dGVudCA6IG51bGw7XG4gICAgLyoqXG4gICAgICogQHByaXZhdGVcbiAgICAgKiBAdHlwZSB7c3RyaW5nfVxuICAgICAqL1xuXG4gICAgdGhpcy5heGlzT3JpZW50YXRpb25fID0gb3B0aW9ucy5heGlzT3JpZW50YXRpb24gIT09IHVuZGVmaW5lZCA/IG9wdGlvbnMuYXhpc09yaWVudGF0aW9uIDogJ2VudSc7XG4gICAgLyoqXG4gICAgICogQHByaXZhdGVcbiAgICAgKiBAdHlwZSB7Ym9vbGVhbn1cbiAgICAgKi9cblxuICAgIHRoaXMuZ2xvYmFsXyA9IG9wdGlvbnMuZ2xvYmFsICE9PSB1bmRlZmluZWQgPyBvcHRpb25zLmdsb2JhbCA6IGZhbHNlO1xuICAgIC8qKlxuICAgICAqIEBwcml2YXRlXG4gICAgICogQHR5cGUge2Jvb2xlYW59XG4gICAgICovXG5cbiAgICB0aGlzLmNhbldyYXBYXyA9ICEhKHRoaXMuZ2xvYmFsXyAmJiB0aGlzLmV4dGVudF8pO1xuICAgIC8qKlxuICAgICAqIEBwcml2YXRlXG4gICAgICogQHR5cGUge2Z1bmN0aW9uKG51bWJlciwgaW1wb3J0KFwiLi4vY29vcmRpbmF0ZS5qc1wiKS5Db29yZGluYXRlKTpudW1iZXJ8dW5kZWZpbmVkfVxuICAgICAqL1xuXG4gICAgdGhpcy5nZXRQb2ludFJlc29sdXRpb25GdW5jXyA9IG9wdGlvbnMuZ2V0UG9pbnRSZXNvbHV0aW9uO1xuICAgIC8qKlxuICAgICAqIEBwcml2YXRlXG4gICAgICogQHR5cGUge2ltcG9ydChcIi4uL3RpbGVncmlkL1RpbGVHcmlkLmpzXCIpLmRlZmF1bHR9XG4gICAgICovXG5cbiAgICB0aGlzLmRlZmF1bHRUaWxlR3JpZF8gPSBudWxsO1xuICAgIC8qKlxuICAgICAqIEBwcml2YXRlXG4gICAgICogQHR5cGUge251bWJlcnx1bmRlZmluZWR9XG4gICAgICovXG5cbiAgICB0aGlzLm1ldGVyc1BlclVuaXRfID0gb3B0aW9ucy5tZXRlcnNQZXJVbml0O1xuICB9XG4gIC8qKlxuICAgKiBAcmV0dXJuIHtib29sZWFufSBUaGUgcHJvamVjdGlvbiBpcyBzdWl0YWJsZSBmb3Igd3JhcHBpbmcgdGhlIHgtYXhpc1xuICAgKi9cblxuXG4gIFByb2plY3Rpb24ucHJvdG90eXBlLmNhbldyYXBYID0gZnVuY3Rpb24gKCkge1xuICAgIHJldHVybiB0aGlzLmNhbldyYXBYXztcbiAgfTtcbiAgLyoqXG4gICAqIEdldCB0aGUgY29kZSBmb3IgdGhpcyBwcm9qZWN0aW9uLCBlLmcuICdFUFNHOjQzMjYnLlxuICAgKiBAcmV0dXJuIHtzdHJpbmd9IENvZGUuXG4gICAqIEBhcGlcbiAgICovXG5cblxuICBQcm9qZWN0aW9uLnByb3RvdHlwZS5nZXRDb2RlID0gZnVuY3Rpb24gKCkge1xuICAgIHJldHVybiB0aGlzLmNvZGVfO1xuICB9O1xuICAvKipcbiAgICogR2V0IHRoZSB2YWxpZGl0eSBleHRlbnQgZm9yIHRoaXMgcHJvamVjdGlvbi5cbiAgICogQHJldHVybiB7aW1wb3J0KFwiLi4vZXh0ZW50LmpzXCIpLkV4dGVudH0gRXh0ZW50LlxuICAgKiBAYXBpXG4gICAqL1xuXG5cbiAgUHJvamVjdGlvbi5wcm90b3R5cGUuZ2V0RXh0ZW50ID0gZnVuY3Rpb24gKCkge1xuICAgIHJldHVybiB0aGlzLmV4dGVudF87XG4gIH07XG4gIC8qKlxuICAgKiBHZXQgdGhlIHVuaXRzIG9mIHRoaXMgcHJvamVjdGlvbi5cbiAgICogQHJldHVybiB7aW1wb3J0KFwiLi9Vbml0cy5qc1wiKS5kZWZhdWx0fSBVbml0cy5cbiAgICogQGFwaVxuICAgKi9cblxuXG4gIFByb2plY3Rpb24ucHJvdG90eXBlLmdldFVuaXRzID0gZnVuY3Rpb24gKCkge1xuICAgIHJldHVybiB0aGlzLnVuaXRzXztcbiAgfTtcbiAgLyoqXG4gICAqIEdldCB0aGUgYW1vdW50IG9mIG1ldGVycyBwZXIgdW5pdCBvZiB0aGlzIHByb2plY3Rpb24uICBJZiB0aGUgcHJvamVjdGlvbiBpc1xuICAgKiBub3QgY29uZmlndXJlZCB3aXRoIGBtZXRlcnNQZXJVbml0YCBvciBhIHVuaXRzIGlkZW50aWZpZXIsIHRoZSByZXR1cm4gaXNcbiAgICogYHVuZGVmaW5lZGAuXG4gICAqIEByZXR1cm4ge251bWJlcnx1bmRlZmluZWR9IE1ldGVycy5cbiAgICogQGFwaVxuICAgKi9cblxuXG4gIFByb2plY3Rpb24ucHJvdG90eXBlLmdldE1ldGVyc1BlclVuaXQgPSBmdW5jdGlvbiAoKSB7XG4gICAgcmV0dXJuIHRoaXMubWV0ZXJzUGVyVW5pdF8gfHwgTUVURVJTX1BFUl9VTklUW3RoaXMudW5pdHNfXTtcbiAgfTtcbiAgLyoqXG4gICAqIEdldCB0aGUgd29ybGQgZXh0ZW50IGZvciB0aGlzIHByb2plY3Rpb24uXG4gICAqIEByZXR1cm4ge2ltcG9ydChcIi4uL2V4dGVudC5qc1wiKS5FeHRlbnR9IEV4dGVudC5cbiAgICogQGFwaVxuICAgKi9cblxuXG4gIFByb2plY3Rpb24ucHJvdG90eXBlLmdldFdvcmxkRXh0ZW50ID0gZnVuY3Rpb24gKCkge1xuICAgIHJldHVybiB0aGlzLndvcmxkRXh0ZW50XztcbiAgfTtcbiAgLyoqXG4gICAqIEdldCB0aGUgYXhpcyBvcmllbnRhdGlvbiBvZiB0aGlzIHByb2plY3Rpb24uXG4gICAqIEV4YW1wbGUgdmFsdWVzIGFyZTpcbiAgICogZW51IC0gdGhlIGRlZmF1bHQgZWFzdGluZywgbm9ydGhpbmcsIGVsZXZhdGlvbi5cbiAgICogbmV1IC0gbm9ydGhpbmcsIGVhc3RpbmcsIHVwIC0gdXNlZnVsIGZvciBcImxhdC9sb25nXCIgZ2VvZ3JhcGhpYyBjb29yZGluYXRlcyxcbiAgICogICAgIG9yIHNvdXRoIG9yaWVudGF0ZWQgdHJhbnN2ZXJzZSBtZXJjYXRvci5cbiAgICogd251IC0gd2VzdGluZywgbm9ydGhpbmcsIHVwIC0gc29tZSBwbGFuZXRhcnkgY29vcmRpbmF0ZSBzeXN0ZW1zIGhhdmVcbiAgICogICAgIFwid2VzdCBwb3NpdGl2ZVwiIGNvb3JkaW5hdGUgc3lzdGVtc1xuICAgKiBAcmV0dXJuIHtzdHJpbmd9IEF4aXMgb3JpZW50YXRpb24uXG4gICAqIEBhcGlcbiAgICovXG5cblxuICBQcm9qZWN0aW9uLnByb3RvdHlwZS5nZXRBeGlzT3JpZW50YXRpb24gPSBmdW5jdGlvbiAoKSB7XG4gICAgcmV0dXJuIHRoaXMuYXhpc09yaWVudGF0aW9uXztcbiAgfTtcbiAgLyoqXG4gICAqIElzIHRoaXMgcHJvamVjdGlvbiBhIGdsb2JhbCBwcm9qZWN0aW9uIHdoaWNoIHNwYW5zIHRoZSB3aG9sZSB3b3JsZD9cbiAgICogQHJldHVybiB7Ym9vbGVhbn0gV2hldGhlciB0aGUgcHJvamVjdGlvbiBpcyBnbG9iYWwuXG4gICAqIEBhcGlcbiAgICovXG5cblxuICBQcm9qZWN0aW9uLnByb3RvdHlwZS5pc0dsb2JhbCA9IGZ1bmN0aW9uICgpIHtcbiAgICByZXR1cm4gdGhpcy5nbG9iYWxfO1xuICB9O1xuICAvKipcbiAgICogU2V0IGlmIHRoZSBwcm9qZWN0aW9uIGlzIGEgZ2xvYmFsIHByb2plY3Rpb24gd2hpY2ggc3BhbnMgdGhlIHdob2xlIHdvcmxkXG4gICAqIEBwYXJhbSB7Ym9vbGVhbn0gZ2xvYmFsIFdoZXRoZXIgdGhlIHByb2plY3Rpb24gaXMgZ2xvYmFsLlxuICAgKiBAYXBpXG4gICAqL1xuXG5cbiAgUHJvamVjdGlvbi5wcm90b3R5cGUuc2V0R2xvYmFsID0gZnVuY3Rpb24gKGdsb2JhbCkge1xuICAgIHRoaXMuZ2xvYmFsXyA9IGdsb2JhbDtcbiAgICB0aGlzLmNhbldyYXBYXyA9ICEhKGdsb2JhbCAmJiB0aGlzLmV4dGVudF8pO1xuICB9O1xuICAvKipcbiAgICogQHJldHVybiB7aW1wb3J0KFwiLi4vdGlsZWdyaWQvVGlsZUdyaWQuanNcIikuZGVmYXVsdH0gVGhlIGRlZmF1bHQgdGlsZSBncmlkLlxuICAgKi9cblxuXG4gIFByb2plY3Rpb24ucHJvdG90eXBlLmdldERlZmF1bHRUaWxlR3JpZCA9IGZ1bmN0aW9uICgpIHtcbiAgICByZXR1cm4gdGhpcy5kZWZhdWx0VGlsZUdyaWRfO1xuICB9O1xuICAvKipcbiAgICogQHBhcmFtIHtpbXBvcnQoXCIuLi90aWxlZ3JpZC9UaWxlR3JpZC5qc1wiKS5kZWZhdWx0fSB0aWxlR3JpZCBUaGUgZGVmYXVsdCB0aWxlIGdyaWQuXG4gICAqL1xuXG5cbiAgUHJvamVjdGlvbi5wcm90b3R5cGUuc2V0RGVmYXVsdFRpbGVHcmlkID0gZnVuY3Rpb24gKHRpbGVHcmlkKSB7XG4gICAgdGhpcy5kZWZhdWx0VGlsZUdyaWRfID0gdGlsZUdyaWQ7XG4gIH07XG4gIC8qKlxuICAgKiBTZXQgdGhlIHZhbGlkaXR5IGV4dGVudCBmb3IgdGhpcyBwcm9qZWN0aW9uLlxuICAgKiBAcGFyYW0ge2ltcG9ydChcIi4uL2V4dGVudC5qc1wiKS5FeHRlbnR9IGV4dGVudCBFeHRlbnQuXG4gICAqIEBhcGlcbiAgICovXG5cblxuICBQcm9qZWN0aW9uLnByb3RvdHlwZS5zZXRFeHRlbnQgPSBmdW5jdGlvbiAoZXh0ZW50KSB7XG4gICAgdGhpcy5leHRlbnRfID0gZXh0ZW50O1xuICAgIHRoaXMuY2FuV3JhcFhfID0gISEodGhpcy5nbG9iYWxfICYmIGV4dGVudCk7XG4gIH07XG4gIC8qKlxuICAgKiBTZXQgdGhlIHdvcmxkIGV4dGVudCBmb3IgdGhpcyBwcm9qZWN0aW9uLlxuICAgKiBAcGFyYW0ge2ltcG9ydChcIi4uL2V4dGVudC5qc1wiKS5FeHRlbnR9IHdvcmxkRXh0ZW50IFdvcmxkIGV4dGVudFxuICAgKiAgICAgW21pbmxvbiwgbWlubGF0LCBtYXhsb24sIG1heGxhdF0uXG4gICAqIEBhcGlcbiAgICovXG5cblxuICBQcm9qZWN0aW9uLnByb3RvdHlwZS5zZXRXb3JsZEV4dGVudCA9IGZ1bmN0aW9uICh3b3JsZEV4dGVudCkge1xuICAgIHRoaXMud29ybGRFeHRlbnRfID0gd29ybGRFeHRlbnQ7XG4gIH07XG4gIC8qKlxuICAgKiBTZXQgdGhlIGdldFBvaW50UmVzb2x1dGlvbiBmdW5jdGlvbiAoc2VlIHtAbGluayBtb2R1bGU6b2wvcHJvan5nZXRQb2ludFJlc29sdXRpb259XG4gICAqIGZvciB0aGlzIHByb2plY3Rpb24uXG4gICAqIEBwYXJhbSB7ZnVuY3Rpb24obnVtYmVyLCBpbXBvcnQoXCIuLi9jb29yZGluYXRlLmpzXCIpLkNvb3JkaW5hdGUpOm51bWJlcn0gZnVuYyBGdW5jdGlvblxuICAgKiBAYXBpXG4gICAqL1xuXG5cbiAgUHJvamVjdGlvbi5wcm90b3R5cGUuc2V0R2V0UG9pbnRSZXNvbHV0aW9uID0gZnVuY3Rpb24gKGZ1bmMpIHtcbiAgICB0aGlzLmdldFBvaW50UmVzb2x1dGlvbkZ1bmNfID0gZnVuYztcbiAgfTtcbiAgLyoqXG4gICAqIEdldCB0aGUgY3VzdG9tIHBvaW50IHJlc29sdXRpb24gZnVuY3Rpb24gZm9yIHRoaXMgcHJvamVjdGlvbiAoaWYgc2V0KS5cbiAgICogQHJldHVybiB7ZnVuY3Rpb24obnVtYmVyLCBpbXBvcnQoXCIuLi9jb29yZGluYXRlLmpzXCIpLkNvb3JkaW5hdGUpOm51bWJlcnx1bmRlZmluZWR9IFRoZSBjdXN0b20gcG9pbnRcbiAgICogcmVzb2x1dGlvbiBmdW5jdGlvbiAoaWYgc2V0KS5cbiAgICovXG5cblxuICBQcm9qZWN0aW9uLnByb3RvdHlwZS5nZXRQb2ludFJlc29sdXRpb25GdW5jID0gZnVuY3Rpb24gKCkge1xuICAgIHJldHVybiB0aGlzLmdldFBvaW50UmVzb2x1dGlvbkZ1bmNfO1xuICB9O1xuXG4gIHJldHVybiBQcm9qZWN0aW9uO1xufSgpO1xuXG5leHBvcnQgZGVmYXVsdCBQcm9qZWN0aW9uOyIsInZhciBfX2V4dGVuZHMgPSB0aGlzICYmIHRoaXMuX19leHRlbmRzIHx8IGZ1bmN0aW9uICgpIHtcbiAgdmFyIF9leHRlbmRTdGF0aWNzID0gZnVuY3Rpb24gZXh0ZW5kU3RhdGljcyhkLCBiKSB7XG4gICAgX2V4dGVuZFN0YXRpY3MgPSBPYmplY3Quc2V0UHJvdG90eXBlT2YgfHwge1xuICAgICAgX19wcm90b19fOiBbXVxuICAgIH0gaW5zdGFuY2VvZiBBcnJheSAmJiBmdW5jdGlvbiAoZCwgYikge1xuICAgICAgZC5fX3Byb3RvX18gPSBiO1xuICAgIH0gfHwgZnVuY3Rpb24gKGQsIGIpIHtcbiAgICAgIGZvciAodmFyIHAgaW4gYikge1xuICAgICAgICBpZiAoT2JqZWN0LnByb3RvdHlwZS5oYXNPd25Qcm9wZXJ0eS5jYWxsKGIsIHApKSBkW3BdID0gYltwXTtcbiAgICAgIH1cbiAgICB9O1xuXG4gICAgcmV0dXJuIF9leHRlbmRTdGF0aWNzKGQsIGIpO1xuICB9O1xuXG4gIHJldHVybiBmdW5jdGlvbiAoZCwgYikge1xuICAgIF9leHRlbmRTdGF0aWNzKGQsIGIpO1xuXG4gICAgZnVuY3Rpb24gX18oKSB7XG4gICAgICB0aGlzLmNvbnN0cnVjdG9yID0gZDtcbiAgICB9XG5cbiAgICBkLnByb3RvdHlwZSA9IGIgPT09IG51bGwgPyBPYmplY3QuY3JlYXRlKGIpIDogKF9fLnByb3RvdHlwZSA9IGIucHJvdG90eXBlLCBuZXcgX18oKSk7XG4gIH07XG59KCk7XG4vKipcbiAqIEBtb2R1bGUgb2wvcHJvai9lcHNnMzg1N1xuICovXG5cblxuaW1wb3J0IFByb2plY3Rpb24gZnJvbSAnLi9Qcm9qZWN0aW9uLmpzJztcbmltcG9ydCBVbml0cyBmcm9tICcuL1VuaXRzLmpzJztcbmltcG9ydCB7IGNvc2ggfSBmcm9tICcuLi9tYXRoLmpzJztcbi8qKlxuICogUmFkaXVzIG9mIFdHUzg0IHNwaGVyZVxuICpcbiAqIEBjb25zdFxuICogQHR5cGUge251bWJlcn1cbiAqL1xuXG5leHBvcnQgdmFyIFJBRElVUyA9IDYzNzgxMzc7XG4vKipcbiAqIEBjb25zdFxuICogQHR5cGUge251bWJlcn1cbiAqL1xuXG5leHBvcnQgdmFyIEhBTEZfU0laRSA9IE1hdGguUEkgKiBSQURJVVM7XG4vKipcbiAqIEBjb25zdFxuICogQHR5cGUge2ltcG9ydChcIi4uL2V4dGVudC5qc1wiKS5FeHRlbnR9XG4gKi9cblxuZXhwb3J0IHZhciBFWFRFTlQgPSBbLUhBTEZfU0laRSwgLUhBTEZfU0laRSwgSEFMRl9TSVpFLCBIQUxGX1NJWkVdO1xuLyoqXG4gKiBAY29uc3RcbiAqIEB0eXBlIHtpbXBvcnQoXCIuLi9leHRlbnQuanNcIikuRXh0ZW50fVxuICovXG5cbmV4cG9ydCB2YXIgV09STERfRVhURU5UID0gWy0xODAsIC04NSwgMTgwLCA4NV07XG4vKipcbiAqIE1heGltdW0gc2FmZSB2YWx1ZSBpbiB5IGRpcmVjdGlvblxuICogQGNvbnN0XG4gKiBAdHlwZSB7bnVtYmVyfVxuICovXG5cbmV4cG9ydCB2YXIgTUFYX1NBRkVfWSA9IFJBRElVUyAqIE1hdGgubG9nKE1hdGgudGFuKE1hdGguUEkgLyAyKSk7XG4vKipcbiAqIEBjbGFzc2Rlc2NcbiAqIFByb2plY3Rpb24gb2JqZWN0IGZvciB3ZWIvc3BoZXJpY2FsIE1lcmNhdG9yIChFUFNHOjM4NTcpLlxuICovXG5cbnZhciBFUFNHMzg1N1Byb2plY3Rpb24gPVxuLyoqIEBjbGFzcyAqL1xuZnVuY3Rpb24gKF9zdXBlcikge1xuICBfX2V4dGVuZHMoRVBTRzM4NTdQcm9qZWN0aW9uLCBfc3VwZXIpO1xuICAvKipcbiAgICogQHBhcmFtIHtzdHJpbmd9IGNvZGUgQ29kZS5cbiAgICovXG5cblxuICBmdW5jdGlvbiBFUFNHMzg1N1Byb2plY3Rpb24oY29kZSkge1xuICAgIHJldHVybiBfc3VwZXIuY2FsbCh0aGlzLCB7XG4gICAgICBjb2RlOiBjb2RlLFxuICAgICAgdW5pdHM6IFVuaXRzLk1FVEVSUyxcbiAgICAgIGV4dGVudDogRVhURU5ULFxuICAgICAgZ2xvYmFsOiB0cnVlLFxuICAgICAgd29ybGRFeHRlbnQ6IFdPUkxEX0VYVEVOVCxcbiAgICAgIGdldFBvaW50UmVzb2x1dGlvbjogZnVuY3Rpb24gZ2V0UG9pbnRSZXNvbHV0aW9uKHJlc29sdXRpb24sIHBvaW50KSB7XG4gICAgICAgIHJldHVybiByZXNvbHV0aW9uIC8gY29zaChwb2ludFsxXSAvIFJBRElVUyk7XG4gICAgICB9XG4gICAgfSkgfHwgdGhpcztcbiAgfVxuXG4gIHJldHVybiBFUFNHMzg1N1Byb2plY3Rpb247XG59KFByb2plY3Rpb24pO1xuLyoqXG4gKiBQcm9qZWN0aW9ucyBlcXVhbCB0byBFUFNHOjM4NTcuXG4gKlxuICogQGNvbnN0XG4gKiBAdHlwZSB7QXJyYXk8aW1wb3J0KFwiLi9Qcm9qZWN0aW9uLmpzXCIpLmRlZmF1bHQ+fVxuICovXG5cblxuZXhwb3J0IHZhciBQUk9KRUNUSU9OUyA9IFtuZXcgRVBTRzM4NTdQcm9qZWN0aW9uKCdFUFNHOjM4NTcnKSwgbmV3IEVQU0czODU3UHJvamVjdGlvbignRVBTRzoxMDIxMDAnKSwgbmV3IEVQU0czODU3UHJvamVjdGlvbignRVBTRzoxMDIxMTMnKSwgbmV3IEVQU0czODU3UHJvamVjdGlvbignRVBTRzo5MDA5MTMnKSwgbmV3IEVQU0czODU3UHJvamVjdGlvbignaHR0cDovL3d3dy5vcGVuZ2lzLm5ldC9nbWwvc3JzL2Vwc2cueG1sIzM4NTcnKV07XG4vKipcbiAqIFRyYW5zZm9ybWF0aW9uIGZyb20gRVBTRzo0MzI2IHRvIEVQU0c6Mzg1Ny5cbiAqXG4gKiBAcGFyYW0ge0FycmF5PG51bWJlcj59IGlucHV0IElucHV0IGFycmF5IG9mIGNvb3JkaW5hdGUgdmFsdWVzLlxuICogQHBhcmFtIHtBcnJheTxudW1iZXI+PX0gb3B0X291dHB1dCBPdXRwdXQgYXJyYXkgb2YgY29vcmRpbmF0ZSB2YWx1ZXMuXG4gKiBAcGFyYW0ge251bWJlcj19IG9wdF9kaW1lbnNpb24gRGltZW5zaW9uIChkZWZhdWx0IGlzIGAyYCkuXG4gKiBAcmV0dXJuIHtBcnJheTxudW1iZXI+fSBPdXRwdXQgYXJyYXkgb2YgY29vcmRpbmF0ZSB2YWx1ZXMuXG4gKi9cblxuZXhwb3J0IGZ1bmN0aW9uIGZyb21FUFNHNDMyNihpbnB1dCwgb3B0X291dHB1dCwgb3B0X2RpbWVuc2lvbikge1xuICB2YXIgbGVuZ3RoID0gaW5wdXQubGVuZ3RoO1xuICB2YXIgZGltZW5zaW9uID0gb3B0X2RpbWVuc2lvbiA+IDEgPyBvcHRfZGltZW5zaW9uIDogMjtcbiAgdmFyIG91dHB1dCA9IG9wdF9vdXRwdXQ7XG5cbiAgaWYgKG91dHB1dCA9PT0gdW5kZWZpbmVkKSB7XG4gICAgaWYgKGRpbWVuc2lvbiA+IDIpIHtcbiAgICAgIC8vIHByZXNlcnZlIHZhbHVlcyBiZXlvbmQgc2Vjb25kIGRpbWVuc2lvblxuICAgICAgb3V0cHV0ID0gaW5wdXQuc2xpY2UoKTtcbiAgICB9IGVsc2Uge1xuICAgICAgb3V0cHV0ID0gbmV3IEFycmF5KGxlbmd0aCk7XG4gICAgfVxuICB9XG5cbiAgZm9yICh2YXIgaSA9IDA7IGkgPCBsZW5ndGg7IGkgKz0gZGltZW5zaW9uKSB7XG4gICAgb3V0cHV0W2ldID0gSEFMRl9TSVpFICogaW5wdXRbaV0gLyAxODA7XG4gICAgdmFyIHkgPSBSQURJVVMgKiBNYXRoLmxvZyhNYXRoLnRhbihNYXRoLlBJICogKCtpbnB1dFtpICsgMV0gKyA5MCkgLyAzNjApKTtcblxuICAgIGlmICh5ID4gTUFYX1NBRkVfWSkge1xuICAgICAgeSA9IE1BWF9TQUZFX1k7XG4gICAgfSBlbHNlIGlmICh5IDwgLU1BWF9TQUZFX1kpIHtcbiAgICAgIHkgPSAtTUFYX1NBRkVfWTtcbiAgICB9XG5cbiAgICBvdXRwdXRbaSArIDFdID0geTtcbiAgfVxuXG4gIHJldHVybiBvdXRwdXQ7XG59XG4vKipcbiAqIFRyYW5zZm9ybWF0aW9uIGZyb20gRVBTRzozODU3IHRvIEVQU0c6NDMyNi5cbiAqXG4gKiBAcGFyYW0ge0FycmF5PG51bWJlcj59IGlucHV0IElucHV0IGFycmF5IG9mIGNvb3JkaW5hdGUgdmFsdWVzLlxuICogQHBhcmFtIHtBcnJheTxudW1iZXI+PX0gb3B0X291dHB1dCBPdXRwdXQgYXJyYXkgb2YgY29vcmRpbmF0ZSB2YWx1ZXMuXG4gKiBAcGFyYW0ge251bWJlcj19IG9wdF9kaW1lbnNpb24gRGltZW5zaW9uIChkZWZhdWx0IGlzIGAyYCkuXG4gKiBAcmV0dXJuIHtBcnJheTxudW1iZXI+fSBPdXRwdXQgYXJyYXkgb2YgY29vcmRpbmF0ZSB2YWx1ZXMuXG4gKi9cblxuZXhwb3J0IGZ1bmN0aW9uIHRvRVBTRzQzMjYoaW5wdXQsIG9wdF9vdXRwdXQsIG9wdF9kaW1lbnNpb24pIHtcbiAgdmFyIGxlbmd0aCA9IGlucHV0Lmxlbmd0aDtcbiAgdmFyIGRpbWVuc2lvbiA9IG9wdF9kaW1lbnNpb24gPiAxID8gb3B0X2RpbWVuc2lvbiA6IDI7XG4gIHZhciBvdXRwdXQgPSBvcHRfb3V0cHV0O1xuXG4gIGlmIChvdXRwdXQgPT09IHVuZGVmaW5lZCkge1xuICAgIGlmIChkaW1lbnNpb24gPiAyKSB7XG4gICAgICAvLyBwcmVzZXJ2ZSB2YWx1ZXMgYmV5b25kIHNlY29uZCBkaW1lbnNpb25cbiAgICAgIG91dHB1dCA9IGlucHV0LnNsaWNlKCk7XG4gICAgfSBlbHNlIHtcbiAgICAgIG91dHB1dCA9IG5ldyBBcnJheShsZW5ndGgpO1xuICAgIH1cbiAgfVxuXG4gIGZvciAodmFyIGkgPSAwOyBpIDwgbGVuZ3RoOyBpICs9IGRpbWVuc2lvbikge1xuICAgIG91dHB1dFtpXSA9IDE4MCAqIGlucHV0W2ldIC8gSEFMRl9TSVpFO1xuICAgIG91dHB1dFtpICsgMV0gPSAzNjAgKiBNYXRoLmF0YW4oTWF0aC5leHAoaW5wdXRbaSArIDFdIC8gUkFESVVTKSkgLyBNYXRoLlBJIC0gOTA7XG4gIH1cblxuICByZXR1cm4gb3V0cHV0O1xufSIsInZhciBfX2V4dGVuZHMgPSB0aGlzICYmIHRoaXMuX19leHRlbmRzIHx8IGZ1bmN0aW9uICgpIHtcbiAgdmFyIF9leHRlbmRTdGF0aWNzID0gZnVuY3Rpb24gZXh0ZW5kU3RhdGljcyhkLCBiKSB7XG4gICAgX2V4dGVuZFN0YXRpY3MgPSBPYmplY3Quc2V0UHJvdG90eXBlT2YgfHwge1xuICAgICAgX19wcm90b19fOiBbXVxuICAgIH0gaW5zdGFuY2VvZiBBcnJheSAmJiBmdW5jdGlvbiAoZCwgYikge1xuICAgICAgZC5fX3Byb3RvX18gPSBiO1xuICAgIH0gfHwgZnVuY3Rpb24gKGQsIGIpIHtcbiAgICAgIGZvciAodmFyIHAgaW4gYikge1xuICAgICAgICBpZiAoT2JqZWN0LnByb3RvdHlwZS5oYXNPd25Qcm9wZXJ0eS5jYWxsKGIsIHApKSBkW3BdID0gYltwXTtcbiAgICAgIH1cbiAgICB9O1xuXG4gICAgcmV0dXJuIF9leHRlbmRTdGF0aWNzKGQsIGIpO1xuICB9O1xuXG4gIHJldHVybiBmdW5jdGlvbiAoZCwgYikge1xuICAgIF9leHRlbmRTdGF0aWNzKGQsIGIpO1xuXG4gICAgZnVuY3Rpb24gX18oKSB7XG4gICAgICB0aGlzLmNvbnN0cnVjdG9yID0gZDtcbiAgICB9XG5cbiAgICBkLnByb3RvdHlwZSA9IGIgPT09IG51bGwgPyBPYmplY3QuY3JlYXRlKGIpIDogKF9fLnByb3RvdHlwZSA9IGIucHJvdG90eXBlLCBuZXcgX18oKSk7XG4gIH07XG59KCk7XG4vKipcbiAqIEBtb2R1bGUgb2wvcHJvai9lcHNnNDMyNlxuICovXG5cblxuaW1wb3J0IFByb2plY3Rpb24gZnJvbSAnLi9Qcm9qZWN0aW9uLmpzJztcbmltcG9ydCBVbml0cyBmcm9tICcuL1VuaXRzLmpzJztcbi8qKlxuICogU2VtaS1tYWpvciByYWRpdXMgb2YgdGhlIFdHUzg0IGVsbGlwc29pZC5cbiAqXG4gKiBAY29uc3RcbiAqIEB0eXBlIHtudW1iZXJ9XG4gKi9cblxuZXhwb3J0IHZhciBSQURJVVMgPSA2Mzc4MTM3O1xuLyoqXG4gKiBFeHRlbnQgb2YgdGhlIEVQU0c6NDMyNiBwcm9qZWN0aW9uIHdoaWNoIGlzIHRoZSB3aG9sZSB3b3JsZC5cbiAqXG4gKiBAY29uc3RcbiAqIEB0eXBlIHtpbXBvcnQoXCIuLi9leHRlbnQuanNcIikuRXh0ZW50fVxuICovXG5cbmV4cG9ydCB2YXIgRVhURU5UID0gWy0xODAsIC05MCwgMTgwLCA5MF07XG4vKipcbiAqIEBjb25zdFxuICogQHR5cGUge251bWJlcn1cbiAqL1xuXG5leHBvcnQgdmFyIE1FVEVSU19QRVJfVU5JVCA9IE1hdGguUEkgKiBSQURJVVMgLyAxODA7XG4vKipcbiAqIEBjbGFzc2Rlc2NcbiAqIFByb2plY3Rpb24gb2JqZWN0IGZvciBXR1M4NCBnZW9ncmFwaGljIGNvb3JkaW5hdGVzIChFUFNHOjQzMjYpLlxuICpcbiAqIE5vdGUgdGhhdCBPcGVuTGF5ZXJzIGRvZXMgbm90IHN0cmljdGx5IGNvbXBseSB3aXRoIHRoZSBFUFNHIGRlZmluaXRpb24uXG4gKiBUaGUgRVBTRyByZWdpc3RyeSBkZWZpbmVzIDQzMjYgYXMgYSBDUlMgZm9yIExhdGl0dWRlLExvbmdpdHVkZSAoeSx4KS5cbiAqIE9wZW5MYXllcnMgdHJlYXRzIEVQU0c6NDMyNiBhcyBhIHBzZXVkby1wcm9qZWN0aW9uLCB3aXRoIHgseSBjb29yZGluYXRlcy5cbiAqL1xuXG52YXIgRVBTRzQzMjZQcm9qZWN0aW9uID1cbi8qKiBAY2xhc3MgKi9cbmZ1bmN0aW9uIChfc3VwZXIpIHtcbiAgX19leHRlbmRzKEVQU0c0MzI2UHJvamVjdGlvbiwgX3N1cGVyKTtcbiAgLyoqXG4gICAqIEBwYXJhbSB7c3RyaW5nfSBjb2RlIENvZGUuXG4gICAqIEBwYXJhbSB7c3RyaW5nPX0gb3B0X2F4aXNPcmllbnRhdGlvbiBBeGlzIG9yaWVudGF0aW9uLlxuICAgKi9cblxuXG4gIGZ1bmN0aW9uIEVQU0c0MzI2UHJvamVjdGlvbihjb2RlLCBvcHRfYXhpc09yaWVudGF0aW9uKSB7XG4gICAgcmV0dXJuIF9zdXBlci5jYWxsKHRoaXMsIHtcbiAgICAgIGNvZGU6IGNvZGUsXG4gICAgICB1bml0czogVW5pdHMuREVHUkVFUyxcbiAgICAgIGV4dGVudDogRVhURU5ULFxuICAgICAgYXhpc09yaWVudGF0aW9uOiBvcHRfYXhpc09yaWVudGF0aW9uLFxuICAgICAgZ2xvYmFsOiB0cnVlLFxuICAgICAgbWV0ZXJzUGVyVW5pdDogTUVURVJTX1BFUl9VTklULFxuICAgICAgd29ybGRFeHRlbnQ6IEVYVEVOVFxuICAgIH0pIHx8IHRoaXM7XG4gIH1cblxuICByZXR1cm4gRVBTRzQzMjZQcm9qZWN0aW9uO1xufShQcm9qZWN0aW9uKTtcbi8qKlxuICogUHJvamVjdGlvbnMgZXF1YWwgdG8gRVBTRzo0MzI2LlxuICpcbiAqIEBjb25zdFxuICogQHR5cGUge0FycmF5PGltcG9ydChcIi4vUHJvamVjdGlvbi5qc1wiKS5kZWZhdWx0Pn1cbiAqL1xuXG5cbmV4cG9ydCB2YXIgUFJPSkVDVElPTlMgPSBbbmV3IEVQU0c0MzI2UHJvamVjdGlvbignQ1JTOjg0JyksIG5ldyBFUFNHNDMyNlByb2plY3Rpb24oJ0VQU0c6NDMyNicsICduZXUnKSwgbmV3IEVQU0c0MzI2UHJvamVjdGlvbigndXJuOm9nYzpkZWY6Y3JzOk9HQzoxLjM6Q1JTODQnKSwgbmV3IEVQU0c0MzI2UHJvamVjdGlvbigndXJuOm9nYzpkZWY6Y3JzOk9HQzoyOjg0JyksIG5ldyBFUFNHNDMyNlByb2plY3Rpb24oJ2h0dHA6Ly93d3cub3Blbmdpcy5uZXQvZ21sL3Nycy9lcHNnLnhtbCM0MzI2JywgJ25ldScpXTsiLCIvKipcbiAqIEBtb2R1bGUgb2wvcHJvai9wcm9qZWN0aW9uc1xuICovXG5cbi8qKlxuICogQHR5cGUge09iamVjdDxzdHJpbmcsIGltcG9ydChcIi4vUHJvamVjdGlvbi5qc1wiKS5kZWZhdWx0Pn1cbiAqL1xudmFyIGNhY2hlID0ge307XG4vKipcbiAqIENsZWFyIHRoZSBwcm9qZWN0aW9ucyBjYWNoZS5cbiAqL1xuXG5leHBvcnQgZnVuY3Rpb24gY2xlYXIoKSB7XG4gIGNhY2hlID0ge307XG59XG4vKipcbiAqIEdldCBhIGNhY2hlZCBwcm9qZWN0aW9uIGJ5IGNvZGUuXG4gKiBAcGFyYW0ge3N0cmluZ30gY29kZSBUaGUgY29kZSBmb3IgdGhlIHByb2plY3Rpb24uXG4gKiBAcmV0dXJuIHtpbXBvcnQoXCIuL1Byb2plY3Rpb24uanNcIikuZGVmYXVsdH0gVGhlIHByb2plY3Rpb24gKGlmIGNhY2hlZCkuXG4gKi9cblxuZXhwb3J0IGZ1bmN0aW9uIGdldChjb2RlKSB7XG4gIHJldHVybiBjYWNoZVtjb2RlXSB8fCBjYWNoZVtjb2RlLnJlcGxhY2UoL3VybjooeC0pP29nYzpkZWY6Y3JzOkVQU0c6KC4qOik/KFxcdyspJC8sICdFUFNHOiQzJyldIHx8IG51bGw7XG59XG4vKipcbiAqIEFkZCBhIHByb2plY3Rpb24gdG8gdGhlIGNhY2hlLlxuICogQHBhcmFtIHtzdHJpbmd9IGNvZGUgVGhlIHByb2plY3Rpb24gY29kZS5cbiAqIEBwYXJhbSB7aW1wb3J0KFwiLi9Qcm9qZWN0aW9uLmpzXCIpLmRlZmF1bHR9IHByb2plY3Rpb24gVGhlIHByb2plY3Rpb24gdG8gY2FjaGUuXG4gKi9cblxuZXhwb3J0IGZ1bmN0aW9uIGFkZChjb2RlLCBwcm9qZWN0aW9uKSB7XG4gIGNhY2hlW2NvZGVdID0gcHJvamVjdGlvbjtcbn0iLCIvKipcbiAqIEBtb2R1bGUgb2wvcHJvai90cmFuc2Zvcm1zXG4gKi9cbmltcG9ydCB7IGlzRW1wdHkgfSBmcm9tICcuLi9vYmouanMnO1xuLyoqXG4gKiBAcHJpdmF0ZVxuICogQHR5cGUgeyFPYmplY3Q8c3RyaW5nLCBPYmplY3Q8c3RyaW5nLCBpbXBvcnQoXCIuLi9wcm9qLmpzXCIpLlRyYW5zZm9ybUZ1bmN0aW9uPj59XG4gKi9cblxudmFyIHRyYW5zZm9ybXMgPSB7fTtcbi8qKlxuICogQ2xlYXIgdGhlIHRyYW5zZm9ybSBjYWNoZS5cbiAqL1xuXG5leHBvcnQgZnVuY3Rpb24gY2xlYXIoKSB7XG4gIHRyYW5zZm9ybXMgPSB7fTtcbn1cbi8qKlxuICogUmVnaXN0ZXJzIGEgY29udmVyc2lvbiBmdW5jdGlvbiB0byBjb252ZXJ0IGNvb3JkaW5hdGVzIGZyb20gdGhlIHNvdXJjZVxuICogcHJvamVjdGlvbiB0byB0aGUgZGVzdGluYXRpb24gcHJvamVjdGlvbi5cbiAqXG4gKiBAcGFyYW0ge2ltcG9ydChcIi4vUHJvamVjdGlvbi5qc1wiKS5kZWZhdWx0fSBzb3VyY2UgU291cmNlLlxuICogQHBhcmFtIHtpbXBvcnQoXCIuL1Byb2plY3Rpb24uanNcIikuZGVmYXVsdH0gZGVzdGluYXRpb24gRGVzdGluYXRpb24uXG4gKiBAcGFyYW0ge2ltcG9ydChcIi4uL3Byb2ouanNcIikuVHJhbnNmb3JtRnVuY3Rpb259IHRyYW5zZm9ybUZuIFRyYW5zZm9ybS5cbiAqL1xuXG5leHBvcnQgZnVuY3Rpb24gYWRkKHNvdXJjZSwgZGVzdGluYXRpb24sIHRyYW5zZm9ybUZuKSB7XG4gIHZhciBzb3VyY2VDb2RlID0gc291cmNlLmdldENvZGUoKTtcbiAgdmFyIGRlc3RpbmF0aW9uQ29kZSA9IGRlc3RpbmF0aW9uLmdldENvZGUoKTtcblxuICBpZiAoIShzb3VyY2VDb2RlIGluIHRyYW5zZm9ybXMpKSB7XG4gICAgdHJhbnNmb3Jtc1tzb3VyY2VDb2RlXSA9IHt9O1xuICB9XG5cbiAgdHJhbnNmb3Jtc1tzb3VyY2VDb2RlXVtkZXN0aW5hdGlvbkNvZGVdID0gdHJhbnNmb3JtRm47XG59XG4vKipcbiAqIFVucmVnaXN0ZXJzIHRoZSBjb252ZXJzaW9uIGZ1bmN0aW9uIHRvIGNvbnZlcnQgY29vcmRpbmF0ZXMgZnJvbSB0aGUgc291cmNlXG4gKiBwcm9qZWN0aW9uIHRvIHRoZSBkZXN0aW5hdGlvbiBwcm9qZWN0aW9uLiAgVGhpcyBtZXRob2QgaXMgdXNlZCB0byBjbGVhbiB1cFxuICogY2FjaGVkIHRyYW5zZm9ybXMgZHVyaW5nIHRlc3RpbmcuXG4gKlxuICogQHBhcmFtIHtpbXBvcnQoXCIuL1Byb2plY3Rpb24uanNcIikuZGVmYXVsdH0gc291cmNlIFNvdXJjZSBwcm9qZWN0aW9uLlxuICogQHBhcmFtIHtpbXBvcnQoXCIuL1Byb2plY3Rpb24uanNcIikuZGVmYXVsdH0gZGVzdGluYXRpb24gRGVzdGluYXRpb24gcHJvamVjdGlvbi5cbiAqIEByZXR1cm4ge2ltcG9ydChcIi4uL3Byb2ouanNcIikuVHJhbnNmb3JtRnVuY3Rpb259IHRyYW5zZm9ybUZuIFRoZSB1bnJlZ2lzdGVyZWQgdHJhbnNmb3JtLlxuICovXG5cbmV4cG9ydCBmdW5jdGlvbiByZW1vdmUoc291cmNlLCBkZXN0aW5hdGlvbikge1xuICB2YXIgc291cmNlQ29kZSA9IHNvdXJjZS5nZXRDb2RlKCk7XG4gIHZhciBkZXN0aW5hdGlvbkNvZGUgPSBkZXN0aW5hdGlvbi5nZXRDb2RlKCk7XG4gIHZhciB0cmFuc2Zvcm0gPSB0cmFuc2Zvcm1zW3NvdXJjZUNvZGVdW2Rlc3RpbmF0aW9uQ29kZV07XG4gIGRlbGV0ZSB0cmFuc2Zvcm1zW3NvdXJjZUNvZGVdW2Rlc3RpbmF0aW9uQ29kZV07XG5cbiAgaWYgKGlzRW1wdHkodHJhbnNmb3Jtc1tzb3VyY2VDb2RlXSkpIHtcbiAgICBkZWxldGUgdHJhbnNmb3Jtc1tzb3VyY2VDb2RlXTtcbiAgfVxuXG4gIHJldHVybiB0cmFuc2Zvcm07XG59XG4vKipcbiAqIEdldCBhIHRyYW5zZm9ybSBnaXZlbiBhIHNvdXJjZSBjb2RlIGFuZCBhIGRlc3RpbmF0aW9uIGNvZGUuXG4gKiBAcGFyYW0ge3N0cmluZ30gc291cmNlQ29kZSBUaGUgY29kZSBmb3IgdGhlIHNvdXJjZSBwcm9qZWN0aW9uLlxuICogQHBhcmFtIHtzdHJpbmd9IGRlc3RpbmF0aW9uQ29kZSBUaGUgY29kZSBmb3IgdGhlIGRlc3RpbmF0aW9uIHByb2plY3Rpb24uXG4gKiBAcmV0dXJuIHtpbXBvcnQoXCIuLi9wcm9qLmpzXCIpLlRyYW5zZm9ybUZ1bmN0aW9ufHVuZGVmaW5lZH0gVGhlIHRyYW5zZm9ybSBmdW5jdGlvbiAoaWYgZm91bmQpLlxuICovXG5cbmV4cG9ydCBmdW5jdGlvbiBnZXQoc291cmNlQ29kZSwgZGVzdGluYXRpb25Db2RlKSB7XG4gIHZhciB0cmFuc2Zvcm07XG5cbiAgaWYgKHNvdXJjZUNvZGUgaW4gdHJhbnNmb3JtcyAmJiBkZXN0aW5hdGlvbkNvZGUgaW4gdHJhbnNmb3Jtc1tzb3VyY2VDb2RlXSkge1xuICAgIHRyYW5zZm9ybSA9IHRyYW5zZm9ybXNbc291cmNlQ29kZV1bZGVzdGluYXRpb25Db2RlXTtcbiAgfVxuXG4gIHJldHVybiB0cmFuc2Zvcm07XG59IiwiLyoqXG4gKiBAbW9kdWxlIG9sL3NwaGVyZVxuICovXG5pbXBvcnQgR2VvbWV0cnlUeXBlIGZyb20gJy4vZ2VvbS9HZW9tZXRyeVR5cGUuanMnO1xuaW1wb3J0IHsgdG9EZWdyZWVzLCB0b1JhZGlhbnMgfSBmcm9tICcuL21hdGguanMnO1xuLyoqXG4gKiBPYmplY3QgbGl0ZXJhbCB3aXRoIG9wdGlvbnMgZm9yIHRoZSB7QGxpbmsgZ2V0TGVuZ3RofSBvciB7QGxpbmsgZ2V0QXJlYX1cbiAqIGZ1bmN0aW9ucy5cbiAqIEB0eXBlZGVmIHtPYmplY3R9IFNwaGVyZU1ldHJpY09wdGlvbnNcbiAqIEBwcm9wZXJ0eSB7aW1wb3J0KFwiLi9wcm9qLmpzXCIpLlByb2plY3Rpb25MaWtlfSBbcHJvamVjdGlvbj0nRVBTRzozODU3J11cbiAqIFByb2plY3Rpb24gb2YgdGhlICBnZW9tZXRyeS4gIEJ5IGRlZmF1bHQsIHRoZSBnZW9tZXRyeSBpcyBhc3N1bWVkIHRvIGJlIGluXG4gKiBXZWIgTWVyY2F0b3IuXG4gKiBAcHJvcGVydHkge251bWJlcn0gW3JhZGl1cz02MzcxMDA4LjhdIFNwaGVyZSByYWRpdXMuICBCeSBkZWZhdWx0LCB0aGVcbiAqIFttZWFuIEVhcnRoIHJhZGl1c10oaHR0cHM6Ly9lbi53aWtpcGVkaWEub3JnL3dpa2kvRWFydGhfcmFkaXVzI01lYW5fcmFkaXVzKVxuICogZm9yIHRoZSBXR1M4NCBlbGxpcHNvaWQgaXMgdXNlZC5cbiAqL1xuXG4vKipcbiAqIFRoZSBtZWFuIEVhcnRoIHJhZGl1cyAoMS8zICogKDJhICsgYikpIGZvciB0aGUgV0dTODQgZWxsaXBzb2lkLlxuICogaHR0cHM6Ly9lbi53aWtpcGVkaWEub3JnL3dpa2kvRWFydGhfcmFkaXVzI01lYW5fcmFkaXVzXG4gKiBAdHlwZSB7bnVtYmVyfVxuICovXG5cbmV4cG9ydCB2YXIgREVGQVVMVF9SQURJVVMgPSA2MzcxMDA4Ljg7XG4vKipcbiAqIEdldCB0aGUgZ3JlYXQgY2lyY2xlIGRpc3RhbmNlIChpbiBtZXRlcnMpIGJldHdlZW4gdHdvIGdlb2dyYXBoaWMgY29vcmRpbmF0ZXMuXG4gKiBAcGFyYW0ge0FycmF5fSBjMSBTdGFydGluZyBjb29yZGluYXRlLlxuICogQHBhcmFtIHtBcnJheX0gYzIgRW5kaW5nIGNvb3JkaW5hdGUuXG4gKiBAcGFyYW0ge251bWJlcj19IG9wdF9yYWRpdXMgVGhlIHNwaGVyZSByYWRpdXMgdG8gdXNlLiAgRGVmYXVsdHMgdG8gdGhlIEVhcnRoJ3NcbiAqICAgICBtZWFuIHJhZGl1cyB1c2luZyB0aGUgV0dTODQgZWxsaXBzb2lkLlxuICogQHJldHVybiB7bnVtYmVyfSBUaGUgZ3JlYXQgY2lyY2xlIGRpc3RhbmNlIGJldHdlZW4gdGhlIHBvaW50cyAoaW4gbWV0ZXJzKS5cbiAqIEBhcGlcbiAqL1xuXG5leHBvcnQgZnVuY3Rpb24gZ2V0RGlzdGFuY2UoYzEsIGMyLCBvcHRfcmFkaXVzKSB7XG4gIHZhciByYWRpdXMgPSBvcHRfcmFkaXVzIHx8IERFRkFVTFRfUkFESVVTO1xuICB2YXIgbGF0MSA9IHRvUmFkaWFucyhjMVsxXSk7XG4gIHZhciBsYXQyID0gdG9SYWRpYW5zKGMyWzFdKTtcbiAgdmFyIGRlbHRhTGF0QnkyID0gKGxhdDIgLSBsYXQxKSAvIDI7XG4gIHZhciBkZWx0YUxvbkJ5MiA9IHRvUmFkaWFucyhjMlswXSAtIGMxWzBdKSAvIDI7XG4gIHZhciBhID0gTWF0aC5zaW4oZGVsdGFMYXRCeTIpICogTWF0aC5zaW4oZGVsdGFMYXRCeTIpICsgTWF0aC5zaW4oZGVsdGFMb25CeTIpICogTWF0aC5zaW4oZGVsdGFMb25CeTIpICogTWF0aC5jb3MobGF0MSkgKiBNYXRoLmNvcyhsYXQyKTtcbiAgcmV0dXJuIDIgKiByYWRpdXMgKiBNYXRoLmF0YW4yKE1hdGguc3FydChhKSwgTWF0aC5zcXJ0KDEgLSBhKSk7XG59XG4vKipcbiAqIEdldCB0aGUgY3VtdWxhdGl2ZSBncmVhdCBjaXJjbGUgbGVuZ3RoIG9mIGxpbmVzdHJpbmcgY29vcmRpbmF0ZXMgKGdlb2dyYXBoaWMpLlxuICogQHBhcmFtIHtBcnJheX0gY29vcmRpbmF0ZXMgTGluZXN0cmluZyBjb29yZGluYXRlcy5cbiAqIEBwYXJhbSB7bnVtYmVyfSByYWRpdXMgVGhlIHNwaGVyZSByYWRpdXMgdG8gdXNlLlxuICogQHJldHVybiB7bnVtYmVyfSBUaGUgbGVuZ3RoIChpbiBtZXRlcnMpLlxuICovXG5cbmZ1bmN0aW9uIGdldExlbmd0aEludGVybmFsKGNvb3JkaW5hdGVzLCByYWRpdXMpIHtcbiAgdmFyIGxlbmd0aCA9IDA7XG5cbiAgZm9yICh2YXIgaSA9IDAsIGlpID0gY29vcmRpbmF0ZXMubGVuZ3RoOyBpIDwgaWkgLSAxOyArK2kpIHtcbiAgICBsZW5ndGggKz0gZ2V0RGlzdGFuY2UoY29vcmRpbmF0ZXNbaV0sIGNvb3JkaW5hdGVzW2kgKyAxXSwgcmFkaXVzKTtcbiAgfVxuXG4gIHJldHVybiBsZW5ndGg7XG59XG4vKipcbiAqIEdldCB0aGUgc3BoZXJpY2FsIGxlbmd0aCBvZiBhIGdlb21ldHJ5LiAgVGhpcyBsZW5ndGggaXMgdGhlIHN1bSBvZiB0aGVcbiAqIGdyZWF0IGNpcmNsZSBkaXN0YW5jZXMgYmV0d2VlbiBjb29yZGluYXRlcy4gIEZvciBwb2x5Z29ucywgdGhlIGxlbmd0aCBpc1xuICogdGhlIHN1bSBvZiBhbGwgcmluZ3MuICBGb3IgcG9pbnRzLCB0aGUgbGVuZ3RoIGlzIHplcm8uICBGb3IgbXVsdGktcGFydFxuICogZ2VvbWV0cmllcywgdGhlIGxlbmd0aCBpcyB0aGUgc3VtIG9mIHRoZSBsZW5ndGggb2YgZWFjaCBwYXJ0LlxuICogQHBhcmFtIHtpbXBvcnQoXCIuL2dlb20vR2VvbWV0cnkuanNcIikuZGVmYXVsdH0gZ2VvbWV0cnkgQSBnZW9tZXRyeS5cbiAqIEBwYXJhbSB7U3BoZXJlTWV0cmljT3B0aW9ucz19IG9wdF9vcHRpb25zIE9wdGlvbnMgZm9yIHRoZVxuICogbGVuZ3RoIGNhbGN1bGF0aW9uLiAgQnkgZGVmYXVsdCwgZ2VvbWV0cmllcyBhcmUgYXNzdW1lZCB0byBiZSBpbiAnRVBTRzozODU3Jy5cbiAqIFlvdSBjYW4gY2hhbmdlIHRoaXMgYnkgcHJvdmlkaW5nIGEgYHByb2plY3Rpb25gIG9wdGlvbi5cbiAqIEByZXR1cm4ge251bWJlcn0gVGhlIHNwaGVyaWNhbCBsZW5ndGggKGluIG1ldGVycykuXG4gKiBAYXBpXG4gKi9cblxuXG5leHBvcnQgZnVuY3Rpb24gZ2V0TGVuZ3RoKGdlb21ldHJ5LCBvcHRfb3B0aW9ucykge1xuICB2YXIgb3B0aW9ucyA9IG9wdF9vcHRpb25zIHx8IHt9O1xuICB2YXIgcmFkaXVzID0gb3B0aW9ucy5yYWRpdXMgfHwgREVGQVVMVF9SQURJVVM7XG4gIHZhciBwcm9qZWN0aW9uID0gb3B0aW9ucy5wcm9qZWN0aW9uIHx8ICdFUFNHOjM4NTcnO1xuICB2YXIgdHlwZSA9IGdlb21ldHJ5LmdldFR5cGUoKTtcblxuICBpZiAodHlwZSAhPT0gR2VvbWV0cnlUeXBlLkdFT01FVFJZX0NPTExFQ1RJT04pIHtcbiAgICBnZW9tZXRyeSA9IGdlb21ldHJ5LmNsb25lKCkudHJhbnNmb3JtKHByb2plY3Rpb24sICdFUFNHOjQzMjYnKTtcbiAgfVxuXG4gIHZhciBsZW5ndGggPSAwO1xuICB2YXIgY29vcmRpbmF0ZXMsIGNvb3JkcywgaSwgaWksIGosIGpqO1xuXG4gIHN3aXRjaCAodHlwZSkge1xuICAgIGNhc2UgR2VvbWV0cnlUeXBlLlBPSU5UOlxuICAgIGNhc2UgR2VvbWV0cnlUeXBlLk1VTFRJX1BPSU5UOlxuICAgICAge1xuICAgICAgICBicmVhaztcbiAgICAgIH1cblxuICAgIGNhc2UgR2VvbWV0cnlUeXBlLkxJTkVfU1RSSU5HOlxuICAgIGNhc2UgR2VvbWV0cnlUeXBlLkxJTkVBUl9SSU5HOlxuICAgICAge1xuICAgICAgICBjb29yZGluYXRlcyA9XG4gICAgICAgIC8qKiBAdHlwZSB7aW1wb3J0KFwiLi9nZW9tL1NpbXBsZUdlb21ldHJ5LmpzXCIpLmRlZmF1bHR9ICovXG4gICAgICAgIGdlb21ldHJ5LmdldENvb3JkaW5hdGVzKCk7XG4gICAgICAgIGxlbmd0aCA9IGdldExlbmd0aEludGVybmFsKGNvb3JkaW5hdGVzLCByYWRpdXMpO1xuICAgICAgICBicmVhaztcbiAgICAgIH1cblxuICAgIGNhc2UgR2VvbWV0cnlUeXBlLk1VTFRJX0xJTkVfU1RSSU5HOlxuICAgIGNhc2UgR2VvbWV0cnlUeXBlLlBPTFlHT046XG4gICAgICB7XG4gICAgICAgIGNvb3JkaW5hdGVzID1cbiAgICAgICAgLyoqIEB0eXBlIHtpbXBvcnQoXCIuL2dlb20vU2ltcGxlR2VvbWV0cnkuanNcIikuZGVmYXVsdH0gKi9cbiAgICAgICAgZ2VvbWV0cnkuZ2V0Q29vcmRpbmF0ZXMoKTtcblxuICAgICAgICBmb3IgKGkgPSAwLCBpaSA9IGNvb3JkaW5hdGVzLmxlbmd0aDsgaSA8IGlpOyArK2kpIHtcbiAgICAgICAgICBsZW5ndGggKz0gZ2V0TGVuZ3RoSW50ZXJuYWwoY29vcmRpbmF0ZXNbaV0sIHJhZGl1cyk7XG4gICAgICAgIH1cblxuICAgICAgICBicmVhaztcbiAgICAgIH1cblxuICAgIGNhc2UgR2VvbWV0cnlUeXBlLk1VTFRJX1BPTFlHT046XG4gICAgICB7XG4gICAgICAgIGNvb3JkaW5hdGVzID1cbiAgICAgICAgLyoqIEB0eXBlIHtpbXBvcnQoXCIuL2dlb20vU2ltcGxlR2VvbWV0cnkuanNcIikuZGVmYXVsdH0gKi9cbiAgICAgICAgZ2VvbWV0cnkuZ2V0Q29vcmRpbmF0ZXMoKTtcblxuICAgICAgICBmb3IgKGkgPSAwLCBpaSA9IGNvb3JkaW5hdGVzLmxlbmd0aDsgaSA8IGlpOyArK2kpIHtcbiAgICAgICAgICBjb29yZHMgPSBjb29yZGluYXRlc1tpXTtcblxuICAgICAgICAgIGZvciAoaiA9IDAsIGpqID0gY29vcmRzLmxlbmd0aDsgaiA8IGpqOyArK2opIHtcbiAgICAgICAgICAgIGxlbmd0aCArPSBnZXRMZW5ndGhJbnRlcm5hbChjb29yZHNbal0sIHJhZGl1cyk7XG4gICAgICAgICAgfVxuICAgICAgICB9XG5cbiAgICAgICAgYnJlYWs7XG4gICAgICB9XG5cbiAgICBjYXNlIEdlb21ldHJ5VHlwZS5HRU9NRVRSWV9DT0xMRUNUSU9OOlxuICAgICAge1xuICAgICAgICB2YXIgZ2VvbWV0cmllcyA9XG4gICAgICAgIC8qKiBAdHlwZSB7aW1wb3J0KFwiLi9nZW9tL0dlb21ldHJ5Q29sbGVjdGlvbi5qc1wiKS5kZWZhdWx0fSAqL1xuICAgICAgICBnZW9tZXRyeS5nZXRHZW9tZXRyaWVzKCk7XG5cbiAgICAgICAgZm9yIChpID0gMCwgaWkgPSBnZW9tZXRyaWVzLmxlbmd0aDsgaSA8IGlpOyArK2kpIHtcbiAgICAgICAgICBsZW5ndGggKz0gZ2V0TGVuZ3RoKGdlb21ldHJpZXNbaV0sIG9wdF9vcHRpb25zKTtcbiAgICAgICAgfVxuXG4gICAgICAgIGJyZWFrO1xuICAgICAgfVxuXG4gICAgZGVmYXVsdDpcbiAgICAgIHtcbiAgICAgICAgdGhyb3cgbmV3IEVycm9yKCdVbnN1cHBvcnRlZCBnZW9tZXRyeSB0eXBlOiAnICsgdHlwZSk7XG4gICAgICB9XG4gIH1cblxuICByZXR1cm4gbGVuZ3RoO1xufVxuLyoqXG4gKiBSZXR1cm5zIHRoZSBzcGhlcmljYWwgYXJlYSBmb3IgYSBsaXN0IG9mIGNvb3JkaW5hdGVzLlxuICpcbiAqIFtSZWZlcmVuY2VdKGh0dHBzOi8vdHJzLW5ldy5qcGwubmFzYS5nb3YvaGFuZGxlLzIwMTQvNDA0MDkpXG4gKiBSb2JlcnQuIEcuIENoYW1iZXJsYWluIGFuZCBXaWxsaWFtIEguIER1cXVldHRlLCBcIlNvbWUgQWxnb3JpdGhtcyBmb3JcbiAqIFBvbHlnb25zIG9uIGEgU3BoZXJlXCIsIEpQTCBQdWJsaWNhdGlvbiAwNy0wMywgSmV0IFByb3B1bHNpb25cbiAqIExhYm9yYXRvcnksIFBhc2FkZW5hLCBDQSwgSnVuZSAyMDA3XG4gKlxuICogQHBhcmFtIHtBcnJheTxpbXBvcnQoXCIuL2Nvb3JkaW5hdGUuanNcIikuQ29vcmRpbmF0ZT59IGNvb3JkaW5hdGVzIExpc3Qgb2YgY29vcmRpbmF0ZXMgb2YgYSBsaW5lYXJcbiAqIHJpbmcuIElmIHRoZSByaW5nIGlzIG9yaWVudGVkIGNsb2Nrd2lzZSwgdGhlIGFyZWEgd2lsbCBiZSBwb3NpdGl2ZSxcbiAqIG90aGVyd2lzZSBpdCB3aWxsIGJlIG5lZ2F0aXZlLlxuICogQHBhcmFtIHtudW1iZXJ9IHJhZGl1cyBUaGUgc3BoZXJlIHJhZGl1cy5cbiAqIEByZXR1cm4ge251bWJlcn0gQXJlYSAoaW4gc3F1YXJlIG1ldGVycykuXG4gKi9cblxuZnVuY3Rpb24gZ2V0QXJlYUludGVybmFsKGNvb3JkaW5hdGVzLCByYWRpdXMpIHtcbiAgdmFyIGFyZWEgPSAwO1xuICB2YXIgbGVuID0gY29vcmRpbmF0ZXMubGVuZ3RoO1xuICB2YXIgeDEgPSBjb29yZGluYXRlc1tsZW4gLSAxXVswXTtcbiAgdmFyIHkxID0gY29vcmRpbmF0ZXNbbGVuIC0gMV1bMV07XG5cbiAgZm9yICh2YXIgaSA9IDA7IGkgPCBsZW47IGkrKykge1xuICAgIHZhciB4MiA9IGNvb3JkaW5hdGVzW2ldWzBdO1xuICAgIHZhciB5MiA9IGNvb3JkaW5hdGVzW2ldWzFdO1xuICAgIGFyZWEgKz0gdG9SYWRpYW5zKHgyIC0geDEpICogKDIgKyBNYXRoLnNpbih0b1JhZGlhbnMoeTEpKSArIE1hdGguc2luKHRvUmFkaWFucyh5MikpKTtcbiAgICB4MSA9IHgyO1xuICAgIHkxID0geTI7XG4gIH1cblxuICByZXR1cm4gYXJlYSAqIHJhZGl1cyAqIHJhZGl1cyAvIDIuMDtcbn1cbi8qKlxuICogR2V0IHRoZSBzcGhlcmljYWwgYXJlYSBvZiBhIGdlb21ldHJ5LiAgVGhpcyBpcyB0aGUgYXJlYSAoaW4gbWV0ZXJzKSBhc3N1bWluZ1xuICogdGhhdCBwb2x5Z29uIGVkZ2VzIGFyZSBzZWdtZW50cyBvZiBncmVhdCBjaXJjbGVzIG9uIGEgc3BoZXJlLlxuICogQHBhcmFtIHtpbXBvcnQoXCIuL2dlb20vR2VvbWV0cnkuanNcIikuZGVmYXVsdH0gZ2VvbWV0cnkgQSBnZW9tZXRyeS5cbiAqIEBwYXJhbSB7U3BoZXJlTWV0cmljT3B0aW9ucz19IG9wdF9vcHRpb25zIE9wdGlvbnMgZm9yIHRoZSBhcmVhXG4gKiAgICAgY2FsY3VsYXRpb24uICBCeSBkZWZhdWx0LCBnZW9tZXRyaWVzIGFyZSBhc3N1bWVkIHRvIGJlIGluICdFUFNHOjM4NTcnLlxuICogICAgIFlvdSBjYW4gY2hhbmdlIHRoaXMgYnkgcHJvdmlkaW5nIGEgYHByb2plY3Rpb25gIG9wdGlvbi5cbiAqIEByZXR1cm4ge251bWJlcn0gVGhlIHNwaGVyaWNhbCBhcmVhIChpbiBzcXVhcmUgbWV0ZXJzKS5cbiAqIEBhcGlcbiAqL1xuXG5cbmV4cG9ydCBmdW5jdGlvbiBnZXRBcmVhKGdlb21ldHJ5LCBvcHRfb3B0aW9ucykge1xuICB2YXIgb3B0aW9ucyA9IG9wdF9vcHRpb25zIHx8IHt9O1xuICB2YXIgcmFkaXVzID0gb3B0aW9ucy5yYWRpdXMgfHwgREVGQVVMVF9SQURJVVM7XG4gIHZhciBwcm9qZWN0aW9uID0gb3B0aW9ucy5wcm9qZWN0aW9uIHx8ICdFUFNHOjM4NTcnO1xuICB2YXIgdHlwZSA9IGdlb21ldHJ5LmdldFR5cGUoKTtcblxuICBpZiAodHlwZSAhPT0gR2VvbWV0cnlUeXBlLkdFT01FVFJZX0NPTExFQ1RJT04pIHtcbiAgICBnZW9tZXRyeSA9IGdlb21ldHJ5LmNsb25lKCkudHJhbnNmb3JtKHByb2plY3Rpb24sICdFUFNHOjQzMjYnKTtcbiAgfVxuXG4gIHZhciBhcmVhID0gMDtcbiAgdmFyIGNvb3JkaW5hdGVzLCBjb29yZHMsIGksIGlpLCBqLCBqajtcblxuICBzd2l0Y2ggKHR5cGUpIHtcbiAgICBjYXNlIEdlb21ldHJ5VHlwZS5QT0lOVDpcbiAgICBjYXNlIEdlb21ldHJ5VHlwZS5NVUxUSV9QT0lOVDpcbiAgICBjYXNlIEdlb21ldHJ5VHlwZS5MSU5FX1NUUklORzpcbiAgICBjYXNlIEdlb21ldHJ5VHlwZS5NVUxUSV9MSU5FX1NUUklORzpcbiAgICBjYXNlIEdlb21ldHJ5VHlwZS5MSU5FQVJfUklORzpcbiAgICAgIHtcbiAgICAgICAgYnJlYWs7XG4gICAgICB9XG5cbiAgICBjYXNlIEdlb21ldHJ5VHlwZS5QT0xZR09OOlxuICAgICAge1xuICAgICAgICBjb29yZGluYXRlcyA9XG4gICAgICAgIC8qKiBAdHlwZSB7aW1wb3J0KFwiLi9nZW9tL1BvbHlnb24uanNcIikuZGVmYXVsdH0gKi9cbiAgICAgICAgZ2VvbWV0cnkuZ2V0Q29vcmRpbmF0ZXMoKTtcbiAgICAgICAgYXJlYSA9IE1hdGguYWJzKGdldEFyZWFJbnRlcm5hbChjb29yZGluYXRlc1swXSwgcmFkaXVzKSk7XG5cbiAgICAgICAgZm9yIChpID0gMSwgaWkgPSBjb29yZGluYXRlcy5sZW5ndGg7IGkgPCBpaTsgKytpKSB7XG4gICAgICAgICAgYXJlYSAtPSBNYXRoLmFicyhnZXRBcmVhSW50ZXJuYWwoY29vcmRpbmF0ZXNbaV0sIHJhZGl1cykpO1xuICAgICAgICB9XG5cbiAgICAgICAgYnJlYWs7XG4gICAgICB9XG5cbiAgICBjYXNlIEdlb21ldHJ5VHlwZS5NVUxUSV9QT0xZR09OOlxuICAgICAge1xuICAgICAgICBjb29yZGluYXRlcyA9XG4gICAgICAgIC8qKiBAdHlwZSB7aW1wb3J0KFwiLi9nZW9tL1NpbXBsZUdlb21ldHJ5LmpzXCIpLmRlZmF1bHR9ICovXG4gICAgICAgIGdlb21ldHJ5LmdldENvb3JkaW5hdGVzKCk7XG5cbiAgICAgICAgZm9yIChpID0gMCwgaWkgPSBjb29yZGluYXRlcy5sZW5ndGg7IGkgPCBpaTsgKytpKSB7XG4gICAgICAgICAgY29vcmRzID0gY29vcmRpbmF0ZXNbaV07XG4gICAgICAgICAgYXJlYSArPSBNYXRoLmFicyhnZXRBcmVhSW50ZXJuYWwoY29vcmRzWzBdLCByYWRpdXMpKTtcblxuICAgICAgICAgIGZvciAoaiA9IDEsIGpqID0gY29vcmRzLmxlbmd0aDsgaiA8IGpqOyArK2opIHtcbiAgICAgICAgICAgIGFyZWEgLT0gTWF0aC5hYnMoZ2V0QXJlYUludGVybmFsKGNvb3Jkc1tqXSwgcmFkaXVzKSk7XG4gICAgICAgICAgfVxuICAgICAgICB9XG5cbiAgICAgICAgYnJlYWs7XG4gICAgICB9XG5cbiAgICBjYXNlIEdlb21ldHJ5VHlwZS5HRU9NRVRSWV9DT0xMRUNUSU9OOlxuICAgICAge1xuICAgICAgICB2YXIgZ2VvbWV0cmllcyA9XG4gICAgICAgIC8qKiBAdHlwZSB7aW1wb3J0KFwiLi9nZW9tL0dlb21ldHJ5Q29sbGVjdGlvbi5qc1wiKS5kZWZhdWx0fSAqL1xuICAgICAgICBnZW9tZXRyeS5nZXRHZW9tZXRyaWVzKCk7XG5cbiAgICAgICAgZm9yIChpID0gMCwgaWkgPSBnZW9tZXRyaWVzLmxlbmd0aDsgaSA8IGlpOyArK2kpIHtcbiAgICAgICAgICBhcmVhICs9IGdldEFyZWEoZ2VvbWV0cmllc1tpXSwgb3B0X29wdGlvbnMpO1xuICAgICAgICB9XG5cbiAgICAgICAgYnJlYWs7XG4gICAgICB9XG5cbiAgICBkZWZhdWx0OlxuICAgICAge1xuICAgICAgICB0aHJvdyBuZXcgRXJyb3IoJ1Vuc3VwcG9ydGVkIGdlb21ldHJ5IHR5cGU6ICcgKyB0eXBlKTtcbiAgICAgIH1cbiAgfVxuXG4gIHJldHVybiBhcmVhO1xufVxuLyoqXG4gKiBSZXR1cm5zIHRoZSBjb29yZGluYXRlIGF0IHRoZSBnaXZlbiBkaXN0YW5jZSBhbmQgYmVhcmluZyBmcm9tIGBjMWAuXG4gKlxuICogQHBhcmFtIHtpbXBvcnQoXCIuL2Nvb3JkaW5hdGUuanNcIikuQ29vcmRpbmF0ZX0gYzEgVGhlIG9yaWdpbiBwb2ludCAoYFtsb24sIGxhdF1gIGluIGRlZ3JlZXMpLlxuICogQHBhcmFtIHtudW1iZXJ9IGRpc3RhbmNlIFRoZSBncmVhdC1jaXJjbGUgZGlzdGFuY2UgYmV0d2VlbiB0aGUgb3JpZ2luXG4gKiAgICAgcG9pbnQgYW5kIHRoZSB0YXJnZXQgcG9pbnQuXG4gKiBAcGFyYW0ge251bWJlcn0gYmVhcmluZyBUaGUgYmVhcmluZyAoaW4gcmFkaWFucykuXG4gKiBAcGFyYW0ge251bWJlcj19IG9wdF9yYWRpdXMgVGhlIHNwaGVyZSByYWRpdXMgdG8gdXNlLiAgRGVmYXVsdHMgdG8gdGhlIEVhcnRoJ3NcbiAqICAgICBtZWFuIHJhZGl1cyB1c2luZyB0aGUgV0dTODQgZWxsaXBzb2lkLlxuICogQHJldHVybiB7aW1wb3J0KFwiLi9jb29yZGluYXRlLmpzXCIpLkNvb3JkaW5hdGV9IFRoZSB0YXJnZXQgcG9pbnQuXG4gKi9cblxuZXhwb3J0IGZ1bmN0aW9uIG9mZnNldChjMSwgZGlzdGFuY2UsIGJlYXJpbmcsIG9wdF9yYWRpdXMpIHtcbiAgdmFyIHJhZGl1cyA9IG9wdF9yYWRpdXMgfHwgREVGQVVMVF9SQURJVVM7XG4gIHZhciBsYXQxID0gdG9SYWRpYW5zKGMxWzFdKTtcbiAgdmFyIGxvbjEgPSB0b1JhZGlhbnMoYzFbMF0pO1xuICB2YXIgZEJ5UiA9IGRpc3RhbmNlIC8gcmFkaXVzO1xuICB2YXIgbGF0ID0gTWF0aC5hc2luKE1hdGguc2luKGxhdDEpICogTWF0aC5jb3MoZEJ5UikgKyBNYXRoLmNvcyhsYXQxKSAqIE1hdGguc2luKGRCeVIpICogTWF0aC5jb3MoYmVhcmluZykpO1xuICB2YXIgbG9uID0gbG9uMSArIE1hdGguYXRhbjIoTWF0aC5zaW4oYmVhcmluZykgKiBNYXRoLnNpbihkQnlSKSAqIE1hdGguY29zKGxhdDEpLCBNYXRoLmNvcyhkQnlSKSAtIE1hdGguc2luKGxhdDEpICogTWF0aC5zaW4obGF0KSk7XG4gIHJldHVybiBbdG9EZWdyZWVzKGxvbiksIHRvRGVncmVlcyhsYXQpXTtcbn0iLCIvKipcbiAqIEBtb2R1bGUgb2wvcHJvalxuICovXG5cbi8qKlxuICogVGhlIG9sL3Byb2ogbW9kdWxlIHN0b3JlczpcbiAqICogYSBsaXN0IG9mIHtAbGluayBtb2R1bGU6b2wvcHJvai9Qcm9qZWN0aW9ufVxuICogb2JqZWN0cywgb25lIGZvciBlYWNoIHByb2plY3Rpb24gc3VwcG9ydGVkIGJ5IHRoZSBhcHBsaWNhdGlvblxuICogKiBhIGxpc3Qgb2YgdHJhbnNmb3JtIGZ1bmN0aW9ucyBuZWVkZWQgdG8gY29udmVydCBjb29yZGluYXRlcyBpbiBvbmUgcHJvamVjdGlvblxuICogaW50byBhbm90aGVyLlxuICpcbiAqIFRoZSBzdGF0aWMgZnVuY3Rpb25zIGFyZSB0aGUgbWV0aG9kcyB1c2VkIHRvIG1haW50YWluIHRoZXNlLlxuICogRWFjaCB0cmFuc2Zvcm0gZnVuY3Rpb24gY2FuIGhhbmRsZSBub3Qgb25seSBzaW1wbGUgY29vcmRpbmF0ZSBwYWlycywgYnV0IGFsc29cbiAqIGxhcmdlIGFycmF5cyBvZiBjb29yZGluYXRlcyBzdWNoIGFzIHZlY3RvciBnZW9tZXRyaWVzLlxuICpcbiAqIFdoZW4gbG9hZGVkLCB0aGUgbGlicmFyeSBhZGRzIHByb2plY3Rpb24gb2JqZWN0cyBmb3IgRVBTRzo0MzI2IChXR1M4NFxuICogZ2VvZ3JhcGhpYyBjb29yZGluYXRlcykgYW5kIEVQU0c6Mzg1NyAoV2ViIG9yIFNwaGVyaWNhbCBNZXJjYXRvciwgYXMgdXNlZFxuICogZm9yIGV4YW1wbGUgYnkgQmluZyBNYXBzIG9yIE9wZW5TdHJlZXRNYXApLCB0b2dldGhlciB3aXRoIHRoZSByZWxldmFudFxuICogdHJhbnNmb3JtIGZ1bmN0aW9ucy5cbiAqXG4gKiBBZGRpdGlvbmFsIHRyYW5zZm9ybXMgbWF5IGJlIGFkZGVkIGJ5IHVzaW5nIHRoZSBodHRwOi8vcHJvajRqcy5vcmcvXG4gKiBsaWJyYXJ5ICh2ZXJzaW9uIDIuMiBvciBsYXRlcikuIFlvdSBjYW4gdXNlIHRoZSBmdWxsIGJ1aWxkIHN1cHBsaWVkIGJ5XG4gKiBQcm9qNGpzLCBvciBjcmVhdGUgYSBjdXN0b20gYnVpbGQgdG8gc3VwcG9ydCB0aG9zZSBwcm9qZWN0aW9ucyB5b3UgbmVlZDsgc2VlXG4gKiB0aGUgUHJvajRqcyB3ZWJzaXRlIGZvciBob3cgdG8gZG8gdGhpcy4gWW91IGFsc28gbmVlZCB0aGUgUHJvajRqcyBkZWZpbml0aW9uc1xuICogZm9yIHRoZSByZXF1aXJlZCBwcm9qZWN0aW9ucy4gVGhlc2UgZGVmaW5pdGlvbnMgY2FuIGJlIG9idGFpbmVkIGZyb21cbiAqIGh0dHBzOi8vZXBzZy5pby8sIGFuZCBhcmUgYSBKUyBmdW5jdGlvbiwgc28gY2FuIGJlIGxvYWRlZCBpbiBhIHNjcmlwdFxuICogdGFnIChhcyBpbiB0aGUgZXhhbXBsZXMpIG9yIHBhc3RlZCBpbnRvIHlvdXIgYXBwbGljYXRpb24uXG4gKlxuICogQWZ0ZXIgYWxsIHJlcXVpcmVkIHByb2plY3Rpb24gZGVmaW5pdGlvbnMgYXJlIGFkZGVkIHRvIHByb2o0J3MgcmVnaXN0cnkgKGJ5XG4gKiB1c2luZyBgcHJvajQuZGVmcygpYCksIHNpbXBseSBjYWxsIGByZWdpc3Rlcihwcm9qNClgIGZyb20gdGhlIGBvbC9wcm9qL3Byb2o0YFxuICogcGFja2FnZS4gRXhpc3RpbmcgdHJhbnNmb3JtcyBhcmUgbm90IGNoYW5nZWQgYnkgdGhpcyBmdW5jdGlvbi4gU2VlXG4gKiBleGFtcGxlcy93bXMtaW1hZ2UtY3VzdG9tLXByb2ogZm9yIGFuIGV4YW1wbGUgb2YgdGhpcy5cbiAqXG4gKiBBZGRpdGlvbmFsIHByb2plY3Rpb24gZGVmaW5pdGlvbnMgY2FuIGJlIHJlZ2lzdGVyZWQgd2l0aCBgcHJvajQuZGVmcygpYCBhbnlcbiAqIHRpbWUuIEp1c3QgbWFrZSBzdXJlIHRvIGNhbGwgYHJlZ2lzdGVyKHByb2o0KWAgYWdhaW47IGZvciBleGFtcGxlLCB3aXRoIHVzZXItc3VwcGxpZWQgZGF0YSB3aGVyZSB5b3UgZG9uJ3RcbiAqIGtub3cgaW4gYWR2YW5jZSB3aGF0IHByb2plY3Rpb25zIGFyZSBuZWVkZWQsIHlvdSBjYW4gaW5pdGlhbGx5IGxvYWQgbWluaW1hbFxuICogc3VwcG9ydCBhbmQgdGhlbiBsb2FkIHdoaWNoZXZlciBhcmUgcmVxdWVzdGVkLlxuICpcbiAqIE5vdGUgdGhhdCBQcm9qNGpzIGRvZXMgbm90IHN1cHBvcnQgcHJvamVjdGlvbiBleHRlbnRzLiBJZiB5b3Ugd2FudCB0byBhZGRcbiAqIG9uZSBmb3IgY3JlYXRpbmcgZGVmYXVsdCB0aWxlIGdyaWRzLCB5b3UgY2FuIGFkZCBpdCBhZnRlciB0aGUgUHJvamVjdGlvblxuICogb2JqZWN0IGhhcyBiZWVuIGNyZWF0ZWQgd2l0aCBgc2V0RXh0ZW50YCwgZm9yIGV4YW1wbGUsXG4gKiBgZ2V0KCdFUFNHOjEyMzQnKS5zZXRFeHRlbnQoZXh0ZW50KWAuXG4gKlxuICogSW4gYWRkaXRpb24gdG8gUHJvajRqcyBzdXBwb3J0LCBhbnkgdHJhbnNmb3JtIGZ1bmN0aW9ucyBjYW4gYmUgYWRkZWQgd2l0aFxuICoge0BsaW5rIG1vZHVsZTpvbC9wcm9qfmFkZENvb3JkaW5hdGVUcmFuc2Zvcm1zfS4gVG8gdXNlIHRoaXMsIHlvdSBtdXN0IGZpcnN0IGNyZWF0ZVxuICogYSB7QGxpbmsgbW9kdWxlOm9sL3Byb2ovUHJvamVjdGlvbn0gb2JqZWN0IGZvciB0aGUgbmV3IHByb2plY3Rpb24gYW5kIGFkZCBpdCB3aXRoXG4gKiB7QGxpbmsgbW9kdWxlOm9sL3Byb2p+YWRkUHJvamVjdGlvbn0uIFlvdSBjYW4gdGhlbiBhZGQgdGhlIGZvcndhcmQgYW5kIGludmVyc2VcbiAqIGZ1bmN0aW9ucyB3aXRoIHtAbGluayBtb2R1bGU6b2wvcHJvan5hZGRDb29yZGluYXRlVHJhbnNmb3Jtc30uIFNlZVxuICogZXhhbXBsZXMvd21zLWN1c3RvbS1wcm9qIGZvciBhbiBleGFtcGxlIG9mIHRoaXMuXG4gKlxuICogTm90ZSB0aGF0IGlmIG5vIHRyYW5zZm9ybXMgYXJlIG5lZWRlZCBhbmQgeW91IG9ubHkgbmVlZCB0byBkZWZpbmUgdGhlXG4gKiBwcm9qZWN0aW9uLCBqdXN0IGFkZCBhIHtAbGluayBtb2R1bGU6b2wvcHJvai9Qcm9qZWN0aW9ufSB3aXRoXG4gKiB7QGxpbmsgbW9kdWxlOm9sL3Byb2p+YWRkUHJvamVjdGlvbn0uIFNlZSBleGFtcGxlcy93bXMtbm8tcHJvaiBmb3IgYW4gZXhhbXBsZSBvZlxuICogdGhpcy5cbiAqL1xuaW1wb3J0IFByb2plY3Rpb24gZnJvbSAnLi9wcm9qL1Byb2plY3Rpb24uanMnO1xuaW1wb3J0IFVuaXRzLCB7IE1FVEVSU19QRVJfVU5JVCB9IGZyb20gJy4vcHJvai9Vbml0cy5qcyc7XG5pbXBvcnQgeyBQUk9KRUNUSU9OUyBhcyBFUFNHMzg1N19QUk9KRUNUSU9OUywgZnJvbUVQU0c0MzI2LCB0b0VQU0c0MzI2IH0gZnJvbSAnLi9wcm9qL2Vwc2czODU3LmpzJztcbmltcG9ydCB7IFBST0pFQ1RJT05TIGFzIEVQU0c0MzI2X1BST0pFQ1RJT05TIH0gZnJvbSAnLi9wcm9qL2Vwc2c0MzI2LmpzJztcbmltcG9ydCB7IGFkZCBhcyBhZGRQcm9qLCBjbGVhciBhcyBjbGVhclByb2osIGdldCBhcyBnZXRQcm9qIH0gZnJvbSAnLi9wcm9qL3Byb2plY3Rpb25zLmpzJztcbmltcG9ydCB7IGFkZCBhcyBhZGRUcmFuc2Zvcm1GdW5jLCBjbGVhciBhcyBjbGVhclRyYW5zZm9ybUZ1bmNzLCBnZXQgYXMgZ2V0VHJhbnNmb3JtRnVuYyB9IGZyb20gJy4vcHJvai90cmFuc2Zvcm1zLmpzJztcbmltcG9ydCB7IGFwcGx5VHJhbnNmb3JtLCBnZXRXaWR0aCB9IGZyb20gJy4vZXh0ZW50LmpzJztcbmltcG9ydCB7IGNsYW1wLCBtb2R1bG8gfSBmcm9tICcuL21hdGguanMnO1xuaW1wb3J0IHsgZ2V0RGlzdGFuY2UgfSBmcm9tICcuL3NwaGVyZS5qcyc7XG5pbXBvcnQgeyBnZXRXb3JsZHNBd2F5IH0gZnJvbSAnLi9jb29yZGluYXRlLmpzJztcbi8qKlxuICogQSBwcm9qZWN0aW9uIGFzIHtAbGluayBtb2R1bGU6b2wvcHJvai9Qcm9qZWN0aW9ufSwgU1JTIGlkZW50aWZpZXJcbiAqIHN0cmluZyBvciB1bmRlZmluZWQuXG4gKiBAdHlwZWRlZiB7UHJvamVjdGlvbnxzdHJpbmd8dW5kZWZpbmVkfSBQcm9qZWN0aW9uTGlrZVxuICogQGFwaVxuICovXG5cbi8qKlxuICogQSB0cmFuc2Zvcm0gZnVuY3Rpb24gYWNjZXB0cyBhbiBhcnJheSBvZiBpbnB1dCBjb29yZGluYXRlIHZhbHVlcywgYW4gb3B0aW9uYWxcbiAqIG91dHB1dCBhcnJheSwgYW5kIGFuIG9wdGlvbmFsIGRpbWVuc2lvbiAoZGVmYXVsdCBzaG91bGQgYmUgMikuICBUaGUgZnVuY3Rpb25cbiAqIHRyYW5zZm9ybXMgdGhlIGlucHV0IGNvb3JkaW5hdGUgdmFsdWVzLCBwb3B1bGF0ZXMgdGhlIG91dHB1dCBhcnJheSwgYW5kXG4gKiByZXR1cm5zIHRoZSBvdXRwdXQgYXJyYXkuXG4gKlxuICogQHR5cGVkZWYge2Z1bmN0aW9uKEFycmF5PG51bWJlcj4sIEFycmF5PG51bWJlcj49LCBudW1iZXI9KTogQXJyYXk8bnVtYmVyPn0gVHJhbnNmb3JtRnVuY3Rpb25cbiAqIEBhcGlcbiAqL1xuXG5leHBvcnQgeyBNRVRFUlNfUEVSX1VOSVQgfTtcbmV4cG9ydCB7IFByb2plY3Rpb24gfTtcbi8qKlxuICogQHBhcmFtIHtBcnJheTxudW1iZXI+fSBpbnB1dCBJbnB1dCBjb29yZGluYXRlIGFycmF5LlxuICogQHBhcmFtIHtBcnJheTxudW1iZXI+PX0gb3B0X291dHB1dCBPdXRwdXQgYXJyYXkgb2YgY29vcmRpbmF0ZSB2YWx1ZXMuXG4gKiBAcGFyYW0ge251bWJlcj19IG9wdF9kaW1lbnNpb24gRGltZW5zaW9uLlxuICogQHJldHVybiB7QXJyYXk8bnVtYmVyPn0gT3V0cHV0IGNvb3JkaW5hdGUgYXJyYXkgKG5ldyBhcnJheSwgc2FtZSBjb29yZGluYXRlXG4gKiAgICAgdmFsdWVzKS5cbiAqL1xuXG5leHBvcnQgZnVuY3Rpb24gY2xvbmVUcmFuc2Zvcm0oaW5wdXQsIG9wdF9vdXRwdXQsIG9wdF9kaW1lbnNpb24pIHtcbiAgdmFyIG91dHB1dDtcblxuICBpZiAob3B0X291dHB1dCAhPT0gdW5kZWZpbmVkKSB7XG4gICAgZm9yICh2YXIgaSA9IDAsIGlpID0gaW5wdXQubGVuZ3RoOyBpIDwgaWk7ICsraSkge1xuICAgICAgb3B0X291dHB1dFtpXSA9IGlucHV0W2ldO1xuICAgIH1cblxuICAgIG91dHB1dCA9IG9wdF9vdXRwdXQ7XG4gIH0gZWxzZSB7XG4gICAgb3V0cHV0ID0gaW5wdXQuc2xpY2UoKTtcbiAgfVxuXG4gIHJldHVybiBvdXRwdXQ7XG59XG4vKipcbiAqIEBwYXJhbSB7QXJyYXk8bnVtYmVyPn0gaW5wdXQgSW5wdXQgY29vcmRpbmF0ZSBhcnJheS5cbiAqIEBwYXJhbSB7QXJyYXk8bnVtYmVyPj19IG9wdF9vdXRwdXQgT3V0cHV0IGFycmF5IG9mIGNvb3JkaW5hdGUgdmFsdWVzLlxuICogQHBhcmFtIHtudW1iZXI9fSBvcHRfZGltZW5zaW9uIERpbWVuc2lvbi5cbiAqIEByZXR1cm4ge0FycmF5PG51bWJlcj59IElucHV0IGNvb3JkaW5hdGUgYXJyYXkgKHNhbWUgYXJyYXkgYXMgaW5wdXQpLlxuICovXG5cbmV4cG9ydCBmdW5jdGlvbiBpZGVudGl0eVRyYW5zZm9ybShpbnB1dCwgb3B0X291dHB1dCwgb3B0X2RpbWVuc2lvbikge1xuICBpZiAob3B0X291dHB1dCAhPT0gdW5kZWZpbmVkICYmIGlucHV0ICE9PSBvcHRfb3V0cHV0KSB7XG4gICAgZm9yICh2YXIgaSA9IDAsIGlpID0gaW5wdXQubGVuZ3RoOyBpIDwgaWk7ICsraSkge1xuICAgICAgb3B0X291dHB1dFtpXSA9IGlucHV0W2ldO1xuICAgIH1cblxuICAgIGlucHV0ID0gb3B0X291dHB1dDtcbiAgfVxuXG4gIHJldHVybiBpbnB1dDtcbn1cbi8qKlxuICogQWRkIGEgUHJvamVjdGlvbiBvYmplY3QgdG8gdGhlIGxpc3Qgb2Ygc3VwcG9ydGVkIHByb2plY3Rpb25zIHRoYXQgY2FuIGJlXG4gKiBsb29rZWQgdXAgYnkgdGhlaXIgY29kZS5cbiAqXG4gKiBAcGFyYW0ge1Byb2plY3Rpb259IHByb2plY3Rpb24gUHJvamVjdGlvbiBpbnN0YW5jZS5cbiAqIEBhcGlcbiAqL1xuXG5leHBvcnQgZnVuY3Rpb24gYWRkUHJvamVjdGlvbihwcm9qZWN0aW9uKSB7XG4gIGFkZFByb2oocHJvamVjdGlvbi5nZXRDb2RlKCksIHByb2plY3Rpb24pO1xuICBhZGRUcmFuc2Zvcm1GdW5jKHByb2plY3Rpb24sIHByb2plY3Rpb24sIGNsb25lVHJhbnNmb3JtKTtcbn1cbi8qKlxuICogQHBhcmFtIHtBcnJheTxQcm9qZWN0aW9uPn0gcHJvamVjdGlvbnMgUHJvamVjdGlvbnMuXG4gKi9cblxuZXhwb3J0IGZ1bmN0aW9uIGFkZFByb2plY3Rpb25zKHByb2plY3Rpb25zKSB7XG4gIHByb2plY3Rpb25zLmZvckVhY2goYWRkUHJvamVjdGlvbik7XG59XG4vKipcbiAqIEZldGNoZXMgYSBQcm9qZWN0aW9uIG9iamVjdCBmb3IgdGhlIGNvZGUgc3BlY2lmaWVkLlxuICpcbiAqIEBwYXJhbSB7UHJvamVjdGlvbkxpa2V9IHByb2plY3Rpb25MaWtlIEVpdGhlciBhIGNvZGUgc3RyaW5nIHdoaWNoIGlzXG4gKiAgICAgYSBjb21iaW5hdGlvbiBvZiBhdXRob3JpdHkgYW5kIGlkZW50aWZpZXIgc3VjaCBhcyBcIkVQU0c6NDMyNlwiLCBvciBhblxuICogICAgIGV4aXN0aW5nIHByb2plY3Rpb24gb2JqZWN0LCBvciB1bmRlZmluZWQuXG4gKiBAcmV0dXJuIHtQcm9qZWN0aW9ufSBQcm9qZWN0aW9uIG9iamVjdCwgb3IgbnVsbCBpZiBub3QgaW4gbGlzdC5cbiAqIEBhcGlcbiAqL1xuXG5leHBvcnQgZnVuY3Rpb24gZ2V0KHByb2plY3Rpb25MaWtlKSB7XG4gIHJldHVybiB0eXBlb2YgcHJvamVjdGlvbkxpa2UgPT09ICdzdHJpbmcnID8gZ2V0UHJvaihcbiAgLyoqIEB0eXBlIHtzdHJpbmd9ICovXG4gIHByb2plY3Rpb25MaWtlKSA6XG4gIC8qKiBAdHlwZSB7UHJvamVjdGlvbn0gKi9cbiAgcHJvamVjdGlvbkxpa2UgfHwgbnVsbDtcbn1cbi8qKlxuICogR2V0IHRoZSByZXNvbHV0aW9uIG9mIHRoZSBwb2ludCBpbiBkZWdyZWVzIG9yIGRpc3RhbmNlIHVuaXRzLlxuICogRm9yIHByb2plY3Rpb25zIHdpdGggZGVncmVlcyBhcyB0aGUgdW5pdCB0aGlzIHdpbGwgc2ltcGx5IHJldHVybiB0aGVcbiAqIHByb3ZpZGVkIHJlc29sdXRpb24uIEZvciBvdGhlciBwcm9qZWN0aW9ucyB0aGUgcG9pbnQgcmVzb2x1dGlvbiBpc1xuICogYnkgZGVmYXVsdCBlc3RpbWF0ZWQgYnkgdHJhbnNmb3JtaW5nIHRoZSAncG9pbnQnIHBpeGVsIHRvIEVQU0c6NDMyNixcbiAqIG1lYXN1cmluZyBpdHMgd2lkdGggYW5kIGhlaWdodCBvbiB0aGUgbm9ybWFsIHNwaGVyZSxcbiAqIGFuZCB0YWtpbmcgdGhlIGF2ZXJhZ2Ugb2YgdGhlIHdpZHRoIGFuZCBoZWlnaHQuXG4gKiBBIGN1c3RvbSBmdW5jdGlvbiBjYW4gYmUgcHJvdmlkZWQgZm9yIGEgc3BlY2lmaWMgcHJvamVjdGlvbiwgZWl0aGVyXG4gKiBieSBzZXR0aW5nIHRoZSBgZ2V0UG9pbnRSZXNvbHV0aW9uYCBvcHRpb24gaW4gdGhlXG4gKiB7QGxpbmsgbW9kdWxlOm9sL3Byb2ovUHJvamVjdGlvbn5Qcm9qZWN0aW9ufSBjb25zdHJ1Y3RvciBvciBieSB1c2luZ1xuICoge0BsaW5rIG1vZHVsZTpvbC9wcm9qL1Byb2plY3Rpb25+UHJvamVjdGlvbiNzZXRHZXRQb2ludFJlc29sdXRpb259IHRvIGNoYW5nZSBhbiBleGlzdGluZ1xuICogcHJvamVjdGlvbiBvYmplY3QuXG4gKiBAcGFyYW0ge1Byb2plY3Rpb25MaWtlfSBwcm9qZWN0aW9uIFRoZSBwcm9qZWN0aW9uLlxuICogQHBhcmFtIHtudW1iZXJ9IHJlc29sdXRpb24gTm9taW5hbCByZXNvbHV0aW9uIGluIHByb2plY3Rpb24gdW5pdHMuXG4gKiBAcGFyYW0ge2ltcG9ydChcIi4vY29vcmRpbmF0ZS5qc1wiKS5Db29yZGluYXRlfSBwb2ludCBQb2ludCB0byBmaW5kIGFkanVzdGVkIHJlc29sdXRpb24gYXQuXG4gKiBAcGFyYW0ge2ltcG9ydChcIi4vcHJvai9Vbml0cy5qc1wiKS5kZWZhdWx0PX0gb3B0X3VuaXRzIFVuaXRzIHRvIGdldCB0aGUgcG9pbnQgcmVzb2x1dGlvbiBpbi5cbiAqIERlZmF1bHQgaXMgdGhlIHByb2plY3Rpb24ncyB1bml0cy5cbiAqIEByZXR1cm4ge251bWJlcn0gUG9pbnQgcmVzb2x1dGlvbi5cbiAqIEBhcGlcbiAqL1xuXG5leHBvcnQgZnVuY3Rpb24gZ2V0UG9pbnRSZXNvbHV0aW9uKHByb2plY3Rpb24sIHJlc29sdXRpb24sIHBvaW50LCBvcHRfdW5pdHMpIHtcbiAgcHJvamVjdGlvbiA9IGdldChwcm9qZWN0aW9uKTtcbiAgdmFyIHBvaW50UmVzb2x1dGlvbjtcbiAgdmFyIGdldHRlciA9IHByb2plY3Rpb24uZ2V0UG9pbnRSZXNvbHV0aW9uRnVuYygpO1xuXG4gIGlmIChnZXR0ZXIpIHtcbiAgICBwb2ludFJlc29sdXRpb24gPSBnZXR0ZXIocmVzb2x1dGlvbiwgcG9pbnQpO1xuXG4gICAgaWYgKG9wdF91bml0cyAmJiBvcHRfdW5pdHMgIT09IHByb2plY3Rpb24uZ2V0VW5pdHMoKSkge1xuICAgICAgdmFyIG1ldGVyc1BlclVuaXQgPSBwcm9qZWN0aW9uLmdldE1ldGVyc1BlclVuaXQoKTtcblxuICAgICAgaWYgKG1ldGVyc1BlclVuaXQpIHtcbiAgICAgICAgcG9pbnRSZXNvbHV0aW9uID0gcG9pbnRSZXNvbHV0aW9uICogbWV0ZXJzUGVyVW5pdCAvIE1FVEVSU19QRVJfVU5JVFtvcHRfdW5pdHNdO1xuICAgICAgfVxuICAgIH1cbiAgfSBlbHNlIHtcbiAgICB2YXIgdW5pdHMgPSBwcm9qZWN0aW9uLmdldFVuaXRzKCk7XG5cbiAgICBpZiAodW5pdHMgPT0gVW5pdHMuREVHUkVFUyAmJiAhb3B0X3VuaXRzIHx8IG9wdF91bml0cyA9PSBVbml0cy5ERUdSRUVTKSB7XG4gICAgICBwb2ludFJlc29sdXRpb24gPSByZXNvbHV0aW9uO1xuICAgIH0gZWxzZSB7XG4gICAgICAvLyBFc3RpbWF0ZSBwb2ludCByZXNvbHV0aW9uIGJ5IHRyYW5zZm9ybWluZyB0aGUgY2VudGVyIHBpeGVsIHRvIEVQU0c6NDMyNixcbiAgICAgIC8vIG1lYXN1cmluZyBpdHMgd2lkdGggYW5kIGhlaWdodCBvbiB0aGUgbm9ybWFsIHNwaGVyZSwgYW5kIHRha2luZyB0aGVcbiAgICAgIC8vIGF2ZXJhZ2Ugb2YgdGhlIHdpZHRoIGFuZCBoZWlnaHQuXG4gICAgICB2YXIgdG9FUFNHNDMyNl8xID0gZ2V0VHJhbnNmb3JtRnJvbVByb2plY3Rpb25zKHByb2plY3Rpb24sIGdldCgnRVBTRzo0MzI2JykpO1xuXG4gICAgICBpZiAodG9FUFNHNDMyNl8xID09PSBpZGVudGl0eVRyYW5zZm9ybSAmJiB1bml0cyAhPT0gVW5pdHMuREVHUkVFUykge1xuICAgICAgICAvLyBubyB0cmFuc2Zvcm0gaXMgYXZhaWxhYmxlXG4gICAgICAgIHBvaW50UmVzb2x1dGlvbiA9IHJlc29sdXRpb24gKiBwcm9qZWN0aW9uLmdldE1ldGVyc1BlclVuaXQoKTtcbiAgICAgIH0gZWxzZSB7XG4gICAgICAgIHZhciB2ZXJ0aWNlcyA9IFtwb2ludFswXSAtIHJlc29sdXRpb24gLyAyLCBwb2ludFsxXSwgcG9pbnRbMF0gKyByZXNvbHV0aW9uIC8gMiwgcG9pbnRbMV0sIHBvaW50WzBdLCBwb2ludFsxXSAtIHJlc29sdXRpb24gLyAyLCBwb2ludFswXSwgcG9pbnRbMV0gKyByZXNvbHV0aW9uIC8gMl07XG4gICAgICAgIHZlcnRpY2VzID0gdG9FUFNHNDMyNl8xKHZlcnRpY2VzLCB2ZXJ0aWNlcywgMik7XG4gICAgICAgIHZhciB3aWR0aCA9IGdldERpc3RhbmNlKHZlcnRpY2VzLnNsaWNlKDAsIDIpLCB2ZXJ0aWNlcy5zbGljZSgyLCA0KSk7XG4gICAgICAgIHZhciBoZWlnaHQgPSBnZXREaXN0YW5jZSh2ZXJ0aWNlcy5zbGljZSg0LCA2KSwgdmVydGljZXMuc2xpY2UoNiwgOCkpO1xuICAgICAgICBwb2ludFJlc29sdXRpb24gPSAod2lkdGggKyBoZWlnaHQpIC8gMjtcbiAgICAgIH1cblxuICAgICAgdmFyIG1ldGVyc1BlclVuaXQgPSBvcHRfdW5pdHMgPyBNRVRFUlNfUEVSX1VOSVRbb3B0X3VuaXRzXSA6IHByb2plY3Rpb24uZ2V0TWV0ZXJzUGVyVW5pdCgpO1xuXG4gICAgICBpZiAobWV0ZXJzUGVyVW5pdCAhPT0gdW5kZWZpbmVkKSB7XG4gICAgICAgIHBvaW50UmVzb2x1dGlvbiAvPSBtZXRlcnNQZXJVbml0O1xuICAgICAgfVxuICAgIH1cbiAgfVxuXG4gIHJldHVybiBwb2ludFJlc29sdXRpb247XG59XG4vKipcbiAqIFJlZ2lzdGVycyB0cmFuc2Zvcm1hdGlvbiBmdW5jdGlvbnMgdGhhdCBkb24ndCBhbHRlciBjb29yZGluYXRlcy4gVGhvc2UgYWxsb3dcbiAqIHRvIHRyYW5zZm9ybSBiZXR3ZWVuIHByb2plY3Rpb25zIHdpdGggZXF1YWwgbWVhbmluZy5cbiAqXG4gKiBAcGFyYW0ge0FycmF5PFByb2plY3Rpb24+fSBwcm9qZWN0aW9ucyBQcm9qZWN0aW9ucy5cbiAqIEBhcGlcbiAqL1xuXG5leHBvcnQgZnVuY3Rpb24gYWRkRXF1aXZhbGVudFByb2plY3Rpb25zKHByb2plY3Rpb25zKSB7XG4gIGFkZFByb2plY3Rpb25zKHByb2plY3Rpb25zKTtcbiAgcHJvamVjdGlvbnMuZm9yRWFjaChmdW5jdGlvbiAoc291cmNlKSB7XG4gICAgcHJvamVjdGlvbnMuZm9yRWFjaChmdW5jdGlvbiAoZGVzdGluYXRpb24pIHtcbiAgICAgIGlmIChzb3VyY2UgIT09IGRlc3RpbmF0aW9uKSB7XG4gICAgICAgIGFkZFRyYW5zZm9ybUZ1bmMoc291cmNlLCBkZXN0aW5hdGlvbiwgY2xvbmVUcmFuc2Zvcm0pO1xuICAgICAgfVxuICAgIH0pO1xuICB9KTtcbn1cbi8qKlxuICogUmVnaXN0ZXJzIHRyYW5zZm9ybWF0aW9uIGZ1bmN0aW9ucyB0byBjb252ZXJ0IGNvb3JkaW5hdGVzIGluIGFueSBwcm9qZWN0aW9uXG4gKiBpbiBwcm9qZWN0aW9uMSB0byBhbnkgcHJvamVjdGlvbiBpbiBwcm9qZWN0aW9uMi5cbiAqXG4gKiBAcGFyYW0ge0FycmF5PFByb2plY3Rpb24+fSBwcm9qZWN0aW9uczEgUHJvamVjdGlvbnMgd2l0aCBlcXVhbFxuICogICAgIG1lYW5pbmcuXG4gKiBAcGFyYW0ge0FycmF5PFByb2plY3Rpb24+fSBwcm9qZWN0aW9uczIgUHJvamVjdGlvbnMgd2l0aCBlcXVhbFxuICogICAgIG1lYW5pbmcuXG4gKiBAcGFyYW0ge1RyYW5zZm9ybUZ1bmN0aW9ufSBmb3J3YXJkVHJhbnNmb3JtIFRyYW5zZm9ybWF0aW9uIGZyb20gYW55XG4gKiAgIHByb2plY3Rpb24gaW4gcHJvamVjdGlvbjEgdG8gYW55IHByb2plY3Rpb24gaW4gcHJvamVjdGlvbjIuXG4gKiBAcGFyYW0ge1RyYW5zZm9ybUZ1bmN0aW9ufSBpbnZlcnNlVHJhbnNmb3JtIFRyYW5zZm9ybSBmcm9tIGFueSBwcm9qZWN0aW9uXG4gKiAgIGluIHByb2plY3Rpb24yIHRvIGFueSBwcm9qZWN0aW9uIGluIHByb2plY3Rpb24xLi5cbiAqL1xuXG5leHBvcnQgZnVuY3Rpb24gYWRkRXF1aXZhbGVudFRyYW5zZm9ybXMocHJvamVjdGlvbnMxLCBwcm9qZWN0aW9uczIsIGZvcndhcmRUcmFuc2Zvcm0sIGludmVyc2VUcmFuc2Zvcm0pIHtcbiAgcHJvamVjdGlvbnMxLmZvckVhY2goZnVuY3Rpb24gKHByb2plY3Rpb24xKSB7XG4gICAgcHJvamVjdGlvbnMyLmZvckVhY2goZnVuY3Rpb24gKHByb2plY3Rpb24yKSB7XG4gICAgICBhZGRUcmFuc2Zvcm1GdW5jKHByb2plY3Rpb24xLCBwcm9qZWN0aW9uMiwgZm9yd2FyZFRyYW5zZm9ybSk7XG4gICAgICBhZGRUcmFuc2Zvcm1GdW5jKHByb2plY3Rpb24yLCBwcm9qZWN0aW9uMSwgaW52ZXJzZVRyYW5zZm9ybSk7XG4gICAgfSk7XG4gIH0pO1xufVxuLyoqXG4gKiBDbGVhciBhbGwgY2FjaGVkIHByb2plY3Rpb25zIGFuZCB0cmFuc2Zvcm1zLlxuICovXG5cbmV4cG9ydCBmdW5jdGlvbiBjbGVhckFsbFByb2plY3Rpb25zKCkge1xuICBjbGVhclByb2ooKTtcbiAgY2xlYXJUcmFuc2Zvcm1GdW5jcygpO1xufVxuLyoqXG4gKiBAcGFyYW0ge1Byb2plY3Rpb258c3RyaW5nfHVuZGVmaW5lZH0gcHJvamVjdGlvbiBQcm9qZWN0aW9uLlxuICogQHBhcmFtIHtzdHJpbmd9IGRlZmF1bHRDb2RlIERlZmF1bHQgY29kZS5cbiAqIEByZXR1cm4ge1Byb2plY3Rpb259IFByb2plY3Rpb24uXG4gKi9cblxuZXhwb3J0IGZ1bmN0aW9uIGNyZWF0ZVByb2plY3Rpb24ocHJvamVjdGlvbiwgZGVmYXVsdENvZGUpIHtcbiAgaWYgKCFwcm9qZWN0aW9uKSB7XG4gICAgcmV0dXJuIGdldChkZWZhdWx0Q29kZSk7XG4gIH0gZWxzZSBpZiAodHlwZW9mIHByb2plY3Rpb24gPT09ICdzdHJpbmcnKSB7XG4gICAgcmV0dXJuIGdldChwcm9qZWN0aW9uKTtcbiAgfSBlbHNlIHtcbiAgICByZXR1cm4gKFxuICAgICAgLyoqIEB0eXBlIHtQcm9qZWN0aW9ufSAqL1xuICAgICAgcHJvamVjdGlvblxuICAgICk7XG4gIH1cbn1cbi8qKlxuICogQ3JlYXRlcyBhIHtAbGluayBtb2R1bGU6b2wvcHJvan5UcmFuc2Zvcm1GdW5jdGlvbn0gZnJvbSBhIHNpbXBsZSAyRCBjb29yZGluYXRlIHRyYW5zZm9ybVxuICogZnVuY3Rpb24uXG4gKiBAcGFyYW0ge2Z1bmN0aW9uKGltcG9ydChcIi4vY29vcmRpbmF0ZS5qc1wiKS5Db29yZGluYXRlKTogaW1wb3J0KFwiLi9jb29yZGluYXRlLmpzXCIpLkNvb3JkaW5hdGV9IGNvb3JkVHJhbnNmb3JtIENvb3JkaW5hdGVcbiAqICAgICB0cmFuc2Zvcm0uXG4gKiBAcmV0dXJuIHtUcmFuc2Zvcm1GdW5jdGlvbn0gVHJhbnNmb3JtIGZ1bmN0aW9uLlxuICovXG5cbmV4cG9ydCBmdW5jdGlvbiBjcmVhdGVUcmFuc2Zvcm1Gcm9tQ29vcmRpbmF0ZVRyYW5zZm9ybShjb29yZFRyYW5zZm9ybSkge1xuICByZXR1cm4gKFxuICAgIC8qKlxuICAgICAqIEBwYXJhbSB7QXJyYXk8bnVtYmVyPn0gaW5wdXQgSW5wdXQuXG4gICAgICogQHBhcmFtIHtBcnJheTxudW1iZXI+PX0gb3B0X291dHB1dCBPdXRwdXQuXG4gICAgICogQHBhcmFtIHtudW1iZXI9fSBvcHRfZGltZW5zaW9uIERpbWVuc2lvbi5cbiAgICAgKiBAcmV0dXJuIHtBcnJheTxudW1iZXI+fSBPdXRwdXQuXG4gICAgICovXG4gICAgZnVuY3Rpb24gKGlucHV0LCBvcHRfb3V0cHV0LCBvcHRfZGltZW5zaW9uKSB7XG4gICAgICB2YXIgbGVuZ3RoID0gaW5wdXQubGVuZ3RoO1xuICAgICAgdmFyIGRpbWVuc2lvbiA9IG9wdF9kaW1lbnNpb24gIT09IHVuZGVmaW5lZCA/IG9wdF9kaW1lbnNpb24gOiAyO1xuICAgICAgdmFyIG91dHB1dCA9IG9wdF9vdXRwdXQgIT09IHVuZGVmaW5lZCA/IG9wdF9vdXRwdXQgOiBuZXcgQXJyYXkobGVuZ3RoKTtcblxuICAgICAgZm9yICh2YXIgaSA9IDA7IGkgPCBsZW5ndGg7IGkgKz0gZGltZW5zaW9uKSB7XG4gICAgICAgIHZhciBwb2ludCA9IGNvb3JkVHJhbnNmb3JtKFtpbnB1dFtpXSwgaW5wdXRbaSArIDFdXSk7XG4gICAgICAgIG91dHB1dFtpXSA9IHBvaW50WzBdO1xuICAgICAgICBvdXRwdXRbaSArIDFdID0gcG9pbnRbMV07XG5cbiAgICAgICAgZm9yICh2YXIgaiA9IGRpbWVuc2lvbiAtIDE7IGogPj0gMjsgLS1qKSB7XG4gICAgICAgICAgb3V0cHV0W2kgKyBqXSA9IGlucHV0W2kgKyBqXTtcbiAgICAgICAgfVxuICAgICAgfVxuXG4gICAgICByZXR1cm4gb3V0cHV0O1xuICAgIH1cbiAgKTtcbn1cbi8qKlxuICogUmVnaXN0ZXJzIGNvb3JkaW5hdGUgdHJhbnNmb3JtIGZ1bmN0aW9ucyB0byBjb252ZXJ0IGNvb3JkaW5hdGVzIGJldHdlZW4gdGhlXG4gKiBzb3VyY2UgcHJvamVjdGlvbiBhbmQgdGhlIGRlc3RpbmF0aW9uIHByb2plY3Rpb24uXG4gKiBUaGUgZm9yd2FyZCBhbmQgaW52ZXJzZSBmdW5jdGlvbnMgY29udmVydCBjb29yZGluYXRlIHBhaXJzOyB0aGlzIGZ1bmN0aW9uXG4gKiBjb252ZXJ0cyB0aGVzZSBpbnRvIHRoZSBmdW5jdGlvbnMgdXNlZCBpbnRlcm5hbGx5IHdoaWNoIGFsc28gaGFuZGxlXG4gKiBleHRlbnRzIGFuZCBjb29yZGluYXRlIGFycmF5cy5cbiAqXG4gKiBAcGFyYW0ge1Byb2plY3Rpb25MaWtlfSBzb3VyY2UgU291cmNlIHByb2plY3Rpb24uXG4gKiBAcGFyYW0ge1Byb2plY3Rpb25MaWtlfSBkZXN0aW5hdGlvbiBEZXN0aW5hdGlvbiBwcm9qZWN0aW9uLlxuICogQHBhcmFtIHtmdW5jdGlvbihpbXBvcnQoXCIuL2Nvb3JkaW5hdGUuanNcIikuQ29vcmRpbmF0ZSk6IGltcG9ydChcIi4vY29vcmRpbmF0ZS5qc1wiKS5Db29yZGluYXRlfSBmb3J3YXJkIFRoZSBmb3J3YXJkIHRyYW5zZm9ybVxuICogICAgIGZ1bmN0aW9uICh0aGF0IGlzLCBmcm9tIHRoZSBzb3VyY2UgcHJvamVjdGlvbiB0byB0aGUgZGVzdGluYXRpb25cbiAqICAgICBwcm9qZWN0aW9uKSB0aGF0IHRha2VzIGEge0BsaW5rIG1vZHVsZTpvbC9jb29yZGluYXRlfkNvb3JkaW5hdGV9IGFzIGFyZ3VtZW50IGFuZCByZXR1cm5zXG4gKiAgICAgdGhlIHRyYW5zZm9ybWVkIHtAbGluayBtb2R1bGU6b2wvY29vcmRpbmF0ZX5Db29yZGluYXRlfS5cbiAqIEBwYXJhbSB7ZnVuY3Rpb24oaW1wb3J0KFwiLi9jb29yZGluYXRlLmpzXCIpLkNvb3JkaW5hdGUpOiBpbXBvcnQoXCIuL2Nvb3JkaW5hdGUuanNcIikuQ29vcmRpbmF0ZX0gaW52ZXJzZSBUaGUgaW52ZXJzZSB0cmFuc2Zvcm1cbiAqICAgICBmdW5jdGlvbiAodGhhdCBpcywgZnJvbSB0aGUgZGVzdGluYXRpb24gcHJvamVjdGlvbiB0byB0aGUgc291cmNlXG4gKiAgICAgcHJvamVjdGlvbikgdGhhdCB0YWtlcyBhIHtAbGluayBtb2R1bGU6b2wvY29vcmRpbmF0ZX5Db29yZGluYXRlfSBhcyBhcmd1bWVudCBhbmQgcmV0dXJuc1xuICogICAgIHRoZSB0cmFuc2Zvcm1lZCB7QGxpbmsgbW9kdWxlOm9sL2Nvb3JkaW5hdGV+Q29vcmRpbmF0ZX0uXG4gKiBAYXBpXG4gKi9cblxuZXhwb3J0IGZ1bmN0aW9uIGFkZENvb3JkaW5hdGVUcmFuc2Zvcm1zKHNvdXJjZSwgZGVzdGluYXRpb24sIGZvcndhcmQsIGludmVyc2UpIHtcbiAgdmFyIHNvdXJjZVByb2ogPSBnZXQoc291cmNlKTtcbiAgdmFyIGRlc3RQcm9qID0gZ2V0KGRlc3RpbmF0aW9uKTtcbiAgYWRkVHJhbnNmb3JtRnVuYyhzb3VyY2VQcm9qLCBkZXN0UHJvaiwgY3JlYXRlVHJhbnNmb3JtRnJvbUNvb3JkaW5hdGVUcmFuc2Zvcm0oZm9yd2FyZCkpO1xuICBhZGRUcmFuc2Zvcm1GdW5jKGRlc3RQcm9qLCBzb3VyY2VQcm9qLCBjcmVhdGVUcmFuc2Zvcm1Gcm9tQ29vcmRpbmF0ZVRyYW5zZm9ybShpbnZlcnNlKSk7XG59XG4vKipcbiAqIFRyYW5zZm9ybXMgYSBjb29yZGluYXRlIGZyb20gbG9uZ2l0dWRlL2xhdGl0dWRlIHRvIGEgZGlmZmVyZW50IHByb2plY3Rpb24uXG4gKiBAcGFyYW0ge2ltcG9ydChcIi4vY29vcmRpbmF0ZS5qc1wiKS5Db29yZGluYXRlfSBjb29yZGluYXRlIENvb3JkaW5hdGUgYXMgbG9uZ2l0dWRlIGFuZCBsYXRpdHVkZSwgaS5lLlxuICogICAgIGFuIGFycmF5IHdpdGggbG9uZ2l0dWRlIGFzIDFzdCBhbmQgbGF0aXR1ZGUgYXMgMm5kIGVsZW1lbnQuXG4gKiBAcGFyYW0ge1Byb2plY3Rpb25MaWtlPX0gb3B0X3Byb2plY3Rpb24gVGFyZ2V0IHByb2plY3Rpb24uIFRoZVxuICogICAgIGRlZmF1bHQgaXMgV2ViIE1lcmNhdG9yLCBpLmUuICdFUFNHOjM4NTcnLlxuICogQHJldHVybiB7aW1wb3J0KFwiLi9jb29yZGluYXRlLmpzXCIpLkNvb3JkaW5hdGV9IENvb3JkaW5hdGUgcHJvamVjdGVkIHRvIHRoZSB0YXJnZXQgcHJvamVjdGlvbi5cbiAqIEBhcGlcbiAqL1xuXG5leHBvcnQgZnVuY3Rpb24gZnJvbUxvbkxhdChjb29yZGluYXRlLCBvcHRfcHJvamVjdGlvbikge1xuICByZXR1cm4gdHJhbnNmb3JtKGNvb3JkaW5hdGUsICdFUFNHOjQzMjYnLCBvcHRfcHJvamVjdGlvbiAhPT0gdW5kZWZpbmVkID8gb3B0X3Byb2plY3Rpb24gOiAnRVBTRzozODU3Jyk7XG59XG4vKipcbiAqIFRyYW5zZm9ybXMgYSBjb29yZGluYXRlIHRvIGxvbmdpdHVkZS9sYXRpdHVkZS5cbiAqIEBwYXJhbSB7aW1wb3J0KFwiLi9jb29yZGluYXRlLmpzXCIpLkNvb3JkaW5hdGV9IGNvb3JkaW5hdGUgUHJvamVjdGVkIGNvb3JkaW5hdGUuXG4gKiBAcGFyYW0ge1Byb2plY3Rpb25MaWtlPX0gb3B0X3Byb2plY3Rpb24gUHJvamVjdGlvbiBvZiB0aGUgY29vcmRpbmF0ZS5cbiAqICAgICBUaGUgZGVmYXVsdCBpcyBXZWIgTWVyY2F0b3IsIGkuZS4gJ0VQU0c6Mzg1NycuXG4gKiBAcmV0dXJuIHtpbXBvcnQoXCIuL2Nvb3JkaW5hdGUuanNcIikuQ29vcmRpbmF0ZX0gQ29vcmRpbmF0ZSBhcyBsb25naXR1ZGUgYW5kIGxhdGl0dWRlLCBpLmUuIGFuIGFycmF5XG4gKiAgICAgd2l0aCBsb25naXR1ZGUgYXMgMXN0IGFuZCBsYXRpdHVkZSBhcyAybmQgZWxlbWVudC5cbiAqIEBhcGlcbiAqL1xuXG5leHBvcnQgZnVuY3Rpb24gdG9Mb25MYXQoY29vcmRpbmF0ZSwgb3B0X3Byb2plY3Rpb24pIHtcbiAgdmFyIGxvbkxhdCA9IHRyYW5zZm9ybShjb29yZGluYXRlLCBvcHRfcHJvamVjdGlvbiAhPT0gdW5kZWZpbmVkID8gb3B0X3Byb2plY3Rpb24gOiAnRVBTRzozODU3JywgJ0VQU0c6NDMyNicpO1xuICB2YXIgbG9uID0gbG9uTGF0WzBdO1xuXG4gIGlmIChsb24gPCAtMTgwIHx8IGxvbiA+IDE4MCkge1xuICAgIGxvbkxhdFswXSA9IG1vZHVsbyhsb24gKyAxODAsIDM2MCkgLSAxODA7XG4gIH1cblxuICByZXR1cm4gbG9uTGF0O1xufVxuLyoqXG4gKiBDaGVja3MgaWYgdHdvIHByb2plY3Rpb25zIGFyZSB0aGUgc2FtZSwgdGhhdCBpcyBldmVyeSBjb29yZGluYXRlIGluIG9uZVxuICogcHJvamVjdGlvbiBkb2VzIHJlcHJlc2VudCB0aGUgc2FtZSBnZW9ncmFwaGljIHBvaW50IGFzIHRoZSBzYW1lIGNvb3JkaW5hdGUgaW5cbiAqIHRoZSBvdGhlciBwcm9qZWN0aW9uLlxuICpcbiAqIEBwYXJhbSB7UHJvamVjdGlvbn0gcHJvamVjdGlvbjEgUHJvamVjdGlvbiAxLlxuICogQHBhcmFtIHtQcm9qZWN0aW9ufSBwcm9qZWN0aW9uMiBQcm9qZWN0aW9uIDIuXG4gKiBAcmV0dXJuIHtib29sZWFufSBFcXVpdmFsZW50LlxuICogQGFwaVxuICovXG5cbmV4cG9ydCBmdW5jdGlvbiBlcXVpdmFsZW50KHByb2plY3Rpb24xLCBwcm9qZWN0aW9uMikge1xuICBpZiAocHJvamVjdGlvbjEgPT09IHByb2plY3Rpb24yKSB7XG4gICAgcmV0dXJuIHRydWU7XG4gIH1cblxuICB2YXIgZXF1YWxVbml0cyA9IHByb2plY3Rpb24xLmdldFVuaXRzKCkgPT09IHByb2plY3Rpb24yLmdldFVuaXRzKCk7XG5cbiAgaWYgKHByb2plY3Rpb24xLmdldENvZGUoKSA9PT0gcHJvamVjdGlvbjIuZ2V0Q29kZSgpKSB7XG4gICAgcmV0dXJuIGVxdWFsVW5pdHM7XG4gIH0gZWxzZSB7XG4gICAgdmFyIHRyYW5zZm9ybUZ1bmMgPSBnZXRUcmFuc2Zvcm1Gcm9tUHJvamVjdGlvbnMocHJvamVjdGlvbjEsIHByb2plY3Rpb24yKTtcbiAgICByZXR1cm4gdHJhbnNmb3JtRnVuYyA9PT0gY2xvbmVUcmFuc2Zvcm0gJiYgZXF1YWxVbml0cztcbiAgfVxufVxuLyoqXG4gKiBTZWFyY2hlcyBpbiB0aGUgbGlzdCBvZiB0cmFuc2Zvcm0gZnVuY3Rpb25zIGZvciB0aGUgZnVuY3Rpb24gZm9yIGNvbnZlcnRpbmdcbiAqIGNvb3JkaW5hdGVzIGZyb20gdGhlIHNvdXJjZSBwcm9qZWN0aW9uIHRvIHRoZSBkZXN0aW5hdGlvbiBwcm9qZWN0aW9uLlxuICpcbiAqIEBwYXJhbSB7UHJvamVjdGlvbn0gc291cmNlUHJvamVjdGlvbiBTb3VyY2UgUHJvamVjdGlvbiBvYmplY3QuXG4gKiBAcGFyYW0ge1Byb2plY3Rpb259IGRlc3RpbmF0aW9uUHJvamVjdGlvbiBEZXN0aW5hdGlvbiBQcm9qZWN0aW9uXG4gKiAgICAgb2JqZWN0LlxuICogQHJldHVybiB7VHJhbnNmb3JtRnVuY3Rpb259IFRyYW5zZm9ybSBmdW5jdGlvbi5cbiAqL1xuXG5leHBvcnQgZnVuY3Rpb24gZ2V0VHJhbnNmb3JtRnJvbVByb2plY3Rpb25zKHNvdXJjZVByb2plY3Rpb24sIGRlc3RpbmF0aW9uUHJvamVjdGlvbikge1xuICB2YXIgc291cmNlQ29kZSA9IHNvdXJjZVByb2plY3Rpb24uZ2V0Q29kZSgpO1xuICB2YXIgZGVzdGluYXRpb25Db2RlID0gZGVzdGluYXRpb25Qcm9qZWN0aW9uLmdldENvZGUoKTtcbiAgdmFyIHRyYW5zZm9ybUZ1bmMgPSBnZXRUcmFuc2Zvcm1GdW5jKHNvdXJjZUNvZGUsIGRlc3RpbmF0aW9uQ29kZSk7XG5cbiAgaWYgKCF0cmFuc2Zvcm1GdW5jKSB7XG4gICAgdHJhbnNmb3JtRnVuYyA9IGlkZW50aXR5VHJhbnNmb3JtO1xuICB9XG5cbiAgcmV0dXJuIHRyYW5zZm9ybUZ1bmM7XG59XG4vKipcbiAqIEdpdmVuIHRoZSBwcm9qZWN0aW9uLWxpa2Ugb2JqZWN0cywgc2VhcmNoZXMgZm9yIGEgdHJhbnNmb3JtYXRpb25cbiAqIGZ1bmN0aW9uIHRvIGNvbnZlcnQgYSBjb29yZGluYXRlcyBhcnJheSBmcm9tIHRoZSBzb3VyY2UgcHJvamVjdGlvbiB0byB0aGVcbiAqIGRlc3RpbmF0aW9uIHByb2plY3Rpb24uXG4gKlxuICogQHBhcmFtIHtQcm9qZWN0aW9uTGlrZX0gc291cmNlIFNvdXJjZS5cbiAqIEBwYXJhbSB7UHJvamVjdGlvbkxpa2V9IGRlc3RpbmF0aW9uIERlc3RpbmF0aW9uLlxuICogQHJldHVybiB7VHJhbnNmb3JtRnVuY3Rpb259IFRyYW5zZm9ybSBmdW5jdGlvbi5cbiAqIEBhcGlcbiAqL1xuXG5leHBvcnQgZnVuY3Rpb24gZ2V0VHJhbnNmb3JtKHNvdXJjZSwgZGVzdGluYXRpb24pIHtcbiAgdmFyIHNvdXJjZVByb2plY3Rpb24gPSBnZXQoc291cmNlKTtcbiAgdmFyIGRlc3RpbmF0aW9uUHJvamVjdGlvbiA9IGdldChkZXN0aW5hdGlvbik7XG4gIHJldHVybiBnZXRUcmFuc2Zvcm1Gcm9tUHJvamVjdGlvbnMoc291cmNlUHJvamVjdGlvbiwgZGVzdGluYXRpb25Qcm9qZWN0aW9uKTtcbn1cbi8qKlxuICogVHJhbnNmb3JtcyBhIGNvb3JkaW5hdGUgZnJvbSBzb3VyY2UgcHJvamVjdGlvbiB0byBkZXN0aW5hdGlvbiBwcm9qZWN0aW9uLlxuICogVGhpcyByZXR1cm5zIGEgbmV3IGNvb3JkaW5hdGUgKGFuZCBkb2VzIG5vdCBtb2RpZnkgdGhlIG9yaWdpbmFsKS5cbiAqXG4gKiBTZWUge0BsaW5rIG1vZHVsZTpvbC9wcm9qfnRyYW5zZm9ybUV4dGVudH0gZm9yIGV4dGVudCB0cmFuc2Zvcm1hdGlvbi5cbiAqIFNlZSB0aGUgdHJhbnNmb3JtIG1ldGhvZCBvZiB7QGxpbmsgbW9kdWxlOm9sL2dlb20vR2VvbWV0cnl+R2VvbWV0cnl9IGFuZCBpdHNcbiAqIHN1YmNsYXNzZXMgZm9yIGdlb21ldHJ5IHRyYW5zZm9ybXMuXG4gKlxuICogQHBhcmFtIHtpbXBvcnQoXCIuL2Nvb3JkaW5hdGUuanNcIikuQ29vcmRpbmF0ZX0gY29vcmRpbmF0ZSBDb29yZGluYXRlLlxuICogQHBhcmFtIHtQcm9qZWN0aW9uTGlrZX0gc291cmNlIFNvdXJjZSBwcm9qZWN0aW9uLWxpa2UuXG4gKiBAcGFyYW0ge1Byb2plY3Rpb25MaWtlfSBkZXN0aW5hdGlvbiBEZXN0aW5hdGlvbiBwcm9qZWN0aW9uLWxpa2UuXG4gKiBAcmV0dXJuIHtpbXBvcnQoXCIuL2Nvb3JkaW5hdGUuanNcIikuQ29vcmRpbmF0ZX0gQ29vcmRpbmF0ZS5cbiAqIEBhcGlcbiAqL1xuXG5leHBvcnQgZnVuY3Rpb24gdHJhbnNmb3JtKGNvb3JkaW5hdGUsIHNvdXJjZSwgZGVzdGluYXRpb24pIHtcbiAgdmFyIHRyYW5zZm9ybUZ1bmMgPSBnZXRUcmFuc2Zvcm0oc291cmNlLCBkZXN0aW5hdGlvbik7XG4gIHJldHVybiB0cmFuc2Zvcm1GdW5jKGNvb3JkaW5hdGUsIHVuZGVmaW5lZCwgY29vcmRpbmF0ZS5sZW5ndGgpO1xufVxuLyoqXG4gKiBUcmFuc2Zvcm1zIGFuIGV4dGVudCBmcm9tIHNvdXJjZSBwcm9qZWN0aW9uIHRvIGRlc3RpbmF0aW9uIHByb2plY3Rpb24uICBUaGlzXG4gKiByZXR1cm5zIGEgbmV3IGV4dGVudCAoYW5kIGRvZXMgbm90IG1vZGlmeSB0aGUgb3JpZ2luYWwpLlxuICpcbiAqIEBwYXJhbSB7aW1wb3J0KFwiLi9leHRlbnQuanNcIikuRXh0ZW50fSBleHRlbnQgVGhlIGV4dGVudCB0byB0cmFuc2Zvcm0uXG4gKiBAcGFyYW0ge1Byb2plY3Rpb25MaWtlfSBzb3VyY2UgU291cmNlIHByb2plY3Rpb24tbGlrZS5cbiAqIEBwYXJhbSB7UHJvamVjdGlvbkxpa2V9IGRlc3RpbmF0aW9uIERlc3RpbmF0aW9uIHByb2plY3Rpb24tbGlrZS5cbiAqIEBwYXJhbSB7bnVtYmVyPX0gb3B0X3N0b3BzIE51bWJlciBvZiBzdG9wcyBwZXIgc2lkZSB1c2VkIGZvciB0aGUgdHJhbnNmb3JtLlxuICogQnkgZGVmYXVsdCBvbmx5IHRoZSBjb3JuZXJzIGFyZSB1c2VkLlxuICogQHJldHVybiB7aW1wb3J0KFwiLi9leHRlbnQuanNcIikuRXh0ZW50fSBUaGUgdHJhbnNmb3JtZWQgZXh0ZW50LlxuICogQGFwaVxuICovXG5cbmV4cG9ydCBmdW5jdGlvbiB0cmFuc2Zvcm1FeHRlbnQoZXh0ZW50LCBzb3VyY2UsIGRlc3RpbmF0aW9uLCBvcHRfc3RvcHMpIHtcbiAgdmFyIHRyYW5zZm9ybUZ1bmMgPSBnZXRUcmFuc2Zvcm0oc291cmNlLCBkZXN0aW5hdGlvbik7XG4gIHJldHVybiBhcHBseVRyYW5zZm9ybShleHRlbnQsIHRyYW5zZm9ybUZ1bmMsIHVuZGVmaW5lZCwgb3B0X3N0b3BzKTtcbn1cbi8qKlxuICogVHJhbnNmb3JtcyB0aGUgZ2l2ZW4gcG9pbnQgdG8gdGhlIGRlc3RpbmF0aW9uIHByb2plY3Rpb24uXG4gKlxuICogQHBhcmFtIHtpbXBvcnQoXCIuL2Nvb3JkaW5hdGUuanNcIikuQ29vcmRpbmF0ZX0gcG9pbnQgUG9pbnQuXG4gKiBAcGFyYW0ge1Byb2plY3Rpb259IHNvdXJjZVByb2plY3Rpb24gU291cmNlIHByb2plY3Rpb24uXG4gKiBAcGFyYW0ge1Byb2plY3Rpb259IGRlc3RpbmF0aW9uUHJvamVjdGlvbiBEZXN0aW5hdGlvbiBwcm9qZWN0aW9uLlxuICogQHJldHVybiB7aW1wb3J0KFwiLi9jb29yZGluYXRlLmpzXCIpLkNvb3JkaW5hdGV9IFBvaW50LlxuICovXG5cbmV4cG9ydCBmdW5jdGlvbiB0cmFuc2Zvcm1XaXRoUHJvamVjdGlvbnMocG9pbnQsIHNvdXJjZVByb2plY3Rpb24sIGRlc3RpbmF0aW9uUHJvamVjdGlvbikge1xuICB2YXIgdHJhbnNmb3JtRnVuYyA9IGdldFRyYW5zZm9ybUZyb21Qcm9qZWN0aW9ucyhzb3VyY2VQcm9qZWN0aW9uLCBkZXN0aW5hdGlvblByb2plY3Rpb24pO1xuICByZXR1cm4gdHJhbnNmb3JtRnVuYyhwb2ludCk7XG59XG4vKipcbiAqIEB0eXBlIHs/UHJvamVjdGlvbn1cbiAqL1xuXG52YXIgdXNlclByb2plY3Rpb24gPSBudWxsO1xuLyoqXG4gKiBTZXQgdGhlIHByb2plY3Rpb24gZm9yIGNvb3JkaW5hdGVzIHN1cHBsaWVkIGZyb20gYW5kIHJldHVybmVkIGJ5IEFQSSBtZXRob2RzLlxuICogTm90ZSB0aGF0IHRoaXMgbWV0aG9kIGlzIG5vdCB5ZXQgYSBwYXJ0IG9mIHRoZSBzdGFibGUgQVBJLiAgU3VwcG9ydCBmb3IgdXNlclxuICogcHJvamVjdGlvbnMgaXMgbm90IHlldCBjb21wbGV0ZSBhbmQgc2hvdWxkIGJlIGNvbnNpZGVyZWQgZXhwZXJpbWVudGFsLlxuICogQHBhcmFtIHtQcm9qZWN0aW9uTGlrZX0gcHJvamVjdGlvbiBUaGUgdXNlciBwcm9qZWN0aW9uLlxuICovXG5cbmV4cG9ydCBmdW5jdGlvbiBzZXRVc2VyUHJvamVjdGlvbihwcm9qZWN0aW9uKSB7XG4gIHVzZXJQcm9qZWN0aW9uID0gZ2V0KHByb2plY3Rpb24pO1xufVxuLyoqXG4gKiBDbGVhciB0aGUgdXNlciBwcm9qZWN0aW9uIGlmIHNldC4gIE5vdGUgdGhhdCB0aGlzIG1ldGhvZCBpcyBub3QgeWV0IGEgcGFydCBvZlxuICogdGhlIHN0YWJsZSBBUEkuICBTdXBwb3J0IGZvciB1c2VyIHByb2plY3Rpb25zIGlzIG5vdCB5ZXQgY29tcGxldGUgYW5kIHNob3VsZFxuICogYmUgY29uc2lkZXJlZCBleHBlcmltZW50YWwuXG4gKi9cblxuZXhwb3J0IGZ1bmN0aW9uIGNsZWFyVXNlclByb2plY3Rpb24oKSB7XG4gIHVzZXJQcm9qZWN0aW9uID0gbnVsbDtcbn1cbi8qKlxuICogR2V0IHRoZSBwcm9qZWN0aW9uIGZvciBjb29yZGluYXRlcyBzdXBwbGllZCBmcm9tIGFuZCByZXR1cm5lZCBieSBBUEkgbWV0aG9kcy5cbiAqIE5vdGUgdGhhdCB0aGlzIG1ldGhvZCBpcyBub3QgeWV0IGEgcGFydCBvZiB0aGUgc3RhYmxlIEFQSS4gIFN1cHBvcnQgZm9yIHVzZXJcbiAqIHByb2plY3Rpb25zIGlzIG5vdCB5ZXQgY29tcGxldGUgYW5kIHNob3VsZCBiZSBjb25zaWRlcmVkIGV4cGVyaW1lbnRhbC5cbiAqIEByZXR1cm5zIHs/UHJvamVjdGlvbn0gVGhlIHVzZXIgcHJvamVjdGlvbiAob3IgbnVsbCBpZiBub3Qgc2V0KS5cbiAqL1xuXG5leHBvcnQgZnVuY3Rpb24gZ2V0VXNlclByb2plY3Rpb24oKSB7XG4gIHJldHVybiB1c2VyUHJvamVjdGlvbjtcbn1cbi8qKlxuICogVXNlIGdlb2dyYXBoaWMgY29vcmRpbmF0ZXMgKFdHUy04NCBkYXR1bSkgaW4gQVBJIG1ldGhvZHMuICBOb3RlIHRoYXQgdGhpc1xuICogbWV0aG9kIGlzIG5vdCB5ZXQgYSBwYXJ0IG9mIHRoZSBzdGFibGUgQVBJLiAgU3VwcG9ydCBmb3IgdXNlciBwcm9qZWN0aW9ucyBpc1xuICogbm90IHlldCBjb21wbGV0ZSBhbmQgc2hvdWxkIGJlIGNvbnNpZGVyZWQgZXhwZXJpbWVudGFsLlxuICovXG5cbmV4cG9ydCBmdW5jdGlvbiB1c2VHZW9ncmFwaGljKCkge1xuICBzZXRVc2VyUHJvamVjdGlvbignRVBTRzo0MzI2Jyk7XG59XG4vKipcbiAqIFJldHVybiBhIGNvb3JkaW5hdGUgdHJhbnNmb3JtZWQgaW50byB0aGUgdXNlciBwcm9qZWN0aW9uLiAgSWYgbm8gdXNlciBwcm9qZWN0aW9uXG4gKiBpcyBzZXQsIHRoZSBvcmlnaW5hbCBjb29yZGluYXRlIGlzIHJldHVybmVkLlxuICogQHBhcmFtIHtBcnJheTxudW1iZXI+fSBjb29yZGluYXRlIElucHV0IGNvb3JkaW5hdGUuXG4gKiBAcGFyYW0ge1Byb2plY3Rpb25MaWtlfSBzb3VyY2VQcm9qZWN0aW9uIFRoZSBpbnB1dCBjb29yZGluYXRlIHByb2plY3Rpb24uXG4gKiBAcmV0dXJucyB7QXJyYXk8bnVtYmVyPn0gVGhlIGlucHV0IGNvb3JkaW5hdGUgaW4gdGhlIHVzZXIgcHJvamVjdGlvbi5cbiAqL1xuXG5leHBvcnQgZnVuY3Rpb24gdG9Vc2VyQ29vcmRpbmF0ZShjb29yZGluYXRlLCBzb3VyY2VQcm9qZWN0aW9uKSB7XG4gIGlmICghdXNlclByb2plY3Rpb24pIHtcbiAgICByZXR1cm4gY29vcmRpbmF0ZTtcbiAgfVxuXG4gIHJldHVybiB0cmFuc2Zvcm0oY29vcmRpbmF0ZSwgc291cmNlUHJvamVjdGlvbiwgdXNlclByb2plY3Rpb24pO1xufVxuLyoqXG4gKiBSZXR1cm4gYSBjb29yZGluYXRlIHRyYW5zZm9ybWVkIGZyb20gdGhlIHVzZXIgcHJvamVjdGlvbi4gIElmIG5vIHVzZXIgcHJvamVjdGlvblxuICogaXMgc2V0LCB0aGUgb3JpZ2luYWwgY29vcmRpbmF0ZSBpcyByZXR1cm5lZC5cbiAqIEBwYXJhbSB7QXJyYXk8bnVtYmVyPn0gY29vcmRpbmF0ZSBJbnB1dCBjb29yZGluYXRlLlxuICogQHBhcmFtIHtQcm9qZWN0aW9uTGlrZX0gZGVzdFByb2plY3Rpb24gVGhlIGRlc3RpbmF0aW9uIHByb2plY3Rpb24uXG4gKiBAcmV0dXJucyB7QXJyYXk8bnVtYmVyPn0gVGhlIGlucHV0IGNvb3JkaW5hdGUgdHJhbnNmb3JtZWQuXG4gKi9cblxuZXhwb3J0IGZ1bmN0aW9uIGZyb21Vc2VyQ29vcmRpbmF0ZShjb29yZGluYXRlLCBkZXN0UHJvamVjdGlvbikge1xuICBpZiAoIXVzZXJQcm9qZWN0aW9uKSB7XG4gICAgcmV0dXJuIGNvb3JkaW5hdGU7XG4gIH1cblxuICByZXR1cm4gdHJhbnNmb3JtKGNvb3JkaW5hdGUsIHVzZXJQcm9qZWN0aW9uLCBkZXN0UHJvamVjdGlvbik7XG59XG4vKipcbiAqIFJldHVybiBhbiBleHRlbnQgdHJhbnNmb3JtZWQgaW50byB0aGUgdXNlciBwcm9qZWN0aW9uLiAgSWYgbm8gdXNlciBwcm9qZWN0aW9uXG4gKiBpcyBzZXQsIHRoZSBvcmlnaW5hbCBleHRlbnQgaXMgcmV0dXJuZWQuXG4gKiBAcGFyYW0ge2ltcG9ydChcIi4vZXh0ZW50LmpzXCIpLkV4dGVudH0gZXh0ZW50IElucHV0IGV4dGVudC5cbiAqIEBwYXJhbSB7UHJvamVjdGlvbkxpa2V9IHNvdXJjZVByb2plY3Rpb24gVGhlIGlucHV0IGV4dGVudCBwcm9qZWN0aW9uLlxuICogQHJldHVybnMge2ltcG9ydChcIi4vZXh0ZW50LmpzXCIpLkV4dGVudH0gVGhlIGlucHV0IGV4dGVudCBpbiB0aGUgdXNlciBwcm9qZWN0aW9uLlxuICovXG5cbmV4cG9ydCBmdW5jdGlvbiB0b1VzZXJFeHRlbnQoZXh0ZW50LCBzb3VyY2VQcm9qZWN0aW9uKSB7XG4gIGlmICghdXNlclByb2plY3Rpb24pIHtcbiAgICByZXR1cm4gZXh0ZW50O1xuICB9XG5cbiAgcmV0dXJuIHRyYW5zZm9ybUV4dGVudChleHRlbnQsIHNvdXJjZVByb2plY3Rpb24sIHVzZXJQcm9qZWN0aW9uKTtcbn1cbi8qKlxuICogUmV0dXJuIGFuIGV4dGVudCB0cmFuc2Zvcm1lZCBmcm9tIHRoZSB1c2VyIHByb2plY3Rpb24uICBJZiBubyB1c2VyIHByb2plY3Rpb25cbiAqIGlzIHNldCwgdGhlIG9yaWdpbmFsIGV4dGVudCBpcyByZXR1cm5lZC5cbiAqIEBwYXJhbSB7aW1wb3J0KFwiLi9leHRlbnQuanNcIikuRXh0ZW50fSBleHRlbnQgSW5wdXQgZXh0ZW50LlxuICogQHBhcmFtIHtQcm9qZWN0aW9uTGlrZX0gZGVzdFByb2plY3Rpb24gVGhlIGRlc3RpbmF0aW9uIHByb2plY3Rpb24uXG4gKiBAcmV0dXJucyB7aW1wb3J0KFwiLi9leHRlbnQuanNcIikuRXh0ZW50fSBUaGUgaW5wdXQgZXh0ZW50IHRyYW5zZm9ybWVkLlxuICovXG5cbmV4cG9ydCBmdW5jdGlvbiBmcm9tVXNlckV4dGVudChleHRlbnQsIGRlc3RQcm9qZWN0aW9uKSB7XG4gIGlmICghdXNlclByb2plY3Rpb24pIHtcbiAgICByZXR1cm4gZXh0ZW50O1xuICB9XG5cbiAgcmV0dXJuIHRyYW5zZm9ybUV4dGVudChleHRlbnQsIHVzZXJQcm9qZWN0aW9uLCBkZXN0UHJvamVjdGlvbik7XG59XG4vKipcbiAqIENyZWF0ZXMgYSBzYWZlIGNvb3JkaW5hdGUgdHJhbnNmb3JtIGZ1bmN0aW9uIGZyb20gYSBjb29yZGluYXRlIHRyYW5zZm9ybSBmdW5jdGlvbi5cbiAqIFwiU2FmZVwiIG1lYW5zIHRoYXQgaXQgY2FuIGhhbmRsZSB3cmFwcGluZyBvZiB4LWNvb3JkaW5hdGVzIGZvciBnbG9iYWwgcHJvamVjdGlvbnMsXG4gKiBhbmQgdGhhdCBjb29yZGluYXRlcyBleGNlZWRpbmcgdGhlIHNvdXJjZSBwcm9qZWN0aW9uIHZhbGlkaXR5IGV4dGVudCdzIHJhbmdlIHdpbGwgYmVcbiAqIGNsYW1wZWQgdG8gdGhlIHZhbGlkaXR5IHJhbmdlLlxuICogQHBhcmFtIHtQcm9qZWN0aW9ufSBzb3VyY2VQcm9qIFNvdXJjZSBwcm9qZWN0aW9uLlxuICogQHBhcmFtIHtQcm9qZWN0aW9ufSBkZXN0UHJvaiBEZXN0aW5hdGlvbiBwcm9qZWN0aW9uLlxuICogQHBhcmFtIHtmdW5jdGlvbihpbXBvcnQoXCIuL2Nvb3JkaW5hdGUuanNcIikuQ29vcmRpbmF0ZSk6IGltcG9ydChcIi4vY29vcmRpbmF0ZS5qc1wiKS5Db29yZGluYXRlfSB0cmFuc2Zvcm0gVHJhbnNmb3JtIGZ1bmN0aW9uIChzb3VyY2UgdG8gZGVzdGlhdGlvbikuXG4gKiBAcmV0dXJuIHtmdW5jdGlvbihpbXBvcnQoXCIuL2Nvb3JkaW5hdGUuanNcIikuQ29vcmRpbmF0ZSk6IGltcG9ydChcIi4vY29vcmRpbmF0ZS5qc1wiKS5Db29yZGluYXRlfSBTYWZlIHRyYW5zZm9ybSBmdW5jdGlvbiAoc291cmNlIHRvIGRlc3RpYXRpb24pLlxuICovXG5cbmV4cG9ydCBmdW5jdGlvbiBjcmVhdGVTYWZlQ29vcmRpbmF0ZVRyYW5zZm9ybShzb3VyY2VQcm9qLCBkZXN0UHJvaiwgdHJhbnNmb3JtKSB7XG4gIHJldHVybiBmdW5jdGlvbiAoY29vcmQpIHtcbiAgICB2YXIgc291cmNlWCA9IGNvb3JkWzBdO1xuICAgIHZhciBzb3VyY2VZID0gY29vcmRbMV07XG4gICAgdmFyIHRyYW5zZm9ybWVkLCB3b3JsZHNBd2F5O1xuXG4gICAgaWYgKHNvdXJjZVByb2ouY2FuV3JhcFgoKSkge1xuICAgICAgdmFyIHNvdXJjZUV4dGVudCA9IHNvdXJjZVByb2ouZ2V0RXh0ZW50KCk7XG4gICAgICB2YXIgc291cmNlRXh0ZW50V2lkdGggPSBnZXRXaWR0aChzb3VyY2VFeHRlbnQpO1xuICAgICAgd29ybGRzQXdheSA9IGdldFdvcmxkc0F3YXkoY29vcmQsIHNvdXJjZVByb2osIHNvdXJjZUV4dGVudFdpZHRoKTtcblxuICAgICAgaWYgKHdvcmxkc0F3YXkpIHtcbiAgICAgICAgLy8gTW92ZSB4IHRvIHRoZSByZWFsIHdvcmxkXG4gICAgICAgIHNvdXJjZVggPSBzb3VyY2VYIC0gd29ybGRzQXdheSAqIHNvdXJjZUV4dGVudFdpZHRoO1xuICAgICAgfVxuXG4gICAgICBzb3VyY2VYID0gY2xhbXAoc291cmNlWCwgc291cmNlRXh0ZW50WzBdLCBzb3VyY2VFeHRlbnRbMl0pO1xuICAgICAgc291cmNlWSA9IGNsYW1wKHNvdXJjZVksIHNvdXJjZUV4dGVudFsxXSwgc291cmNlRXh0ZW50WzNdKTtcbiAgICAgIHRyYW5zZm9ybWVkID0gdHJhbnNmb3JtKFtzb3VyY2VYLCBzb3VyY2VZXSk7XG4gICAgfSBlbHNlIHtcbiAgICAgIHRyYW5zZm9ybWVkID0gdHJhbnNmb3JtKGNvb3JkKTtcbiAgICB9XG5cbiAgICBpZiAod29ybGRzQXdheSAmJiBkZXN0UHJvai5jYW5XcmFwWCgpKSB7XG4gICAgICAvLyBNb3ZlIHRyYW5zZm9ybWVkIGNvb3JkaW5hdGUgYmFjayB0byB0aGUgb2Zmc2V0IHdvcmxkXG4gICAgICB0cmFuc2Zvcm1lZFswXSArPSB3b3JsZHNBd2F5ICogZ2V0V2lkdGgoZGVzdFByb2ouZ2V0RXh0ZW50KCkpO1xuICAgIH1cblxuICAgIHJldHVybiB0cmFuc2Zvcm1lZDtcbiAgfTtcbn1cbi8qKlxuICogQWRkIHRyYW5zZm9ybXMgdG8gYW5kIGZyb20gRVBTRzo0MzI2IGFuZCBFUFNHOjM4NTcuICBUaGlzIGZ1bmN0aW9uIGlzIGNhbGxlZFxuICogYnkgd2hlbiB0aGlzIG1vZHVsZSBpcyBleGVjdXRlZCBhbmQgc2hvdWxkIG9ubHkgbmVlZCB0byBiZSBjYWxsZWQgYWdhaW4gYWZ0ZXJcbiAqIGBjbGVhckFsbFByb2plY3Rpb25zKClgIGlzIGNhbGxlZCAoZS5nLiBpbiB0ZXN0cykuXG4gKi9cblxuZXhwb3J0IGZ1bmN0aW9uIGFkZENvbW1vbigpIHtcbiAgLy8gQWRkIHRyYW5zZm9ybWF0aW9ucyB0aGF0IGRvbid0IGFsdGVyIGNvb3JkaW5hdGVzIHRvIGNvbnZlcnQgd2l0aGluIHNldCBvZlxuICAvLyBwcm9qZWN0aW9ucyB3aXRoIGVxdWFsIG1lYW5pbmcuXG4gIGFkZEVxdWl2YWxlbnRQcm9qZWN0aW9ucyhFUFNHMzg1N19QUk9KRUNUSU9OUyk7XG4gIGFkZEVxdWl2YWxlbnRQcm9qZWN0aW9ucyhFUFNHNDMyNl9QUk9KRUNUSU9OUyk7IC8vIEFkZCB0cmFuc2Zvcm1hdGlvbnMgdG8gY29udmVydCBFUFNHOjQzMjYgbGlrZSBjb29yZGluYXRlcyB0byBFUFNHOjM4NTcgbGlrZVxuICAvLyBjb29yZGluYXRlcyBhbmQgYmFjay5cblxuICBhZGRFcXVpdmFsZW50VHJhbnNmb3JtcyhFUFNHNDMyNl9QUk9KRUNUSU9OUywgRVBTRzM4NTdfUFJPSkVDVElPTlMsIGZyb21FUFNHNDMyNiwgdG9FUFNHNDMyNik7XG59XG5hZGRDb21tb24oKTsiLCIvKipcbiAqIEBtb2R1bGUgb2wvY2VudGVyY29uc3RyYWludFxuICovXG5pbXBvcnQgeyBjbGFtcCB9IGZyb20gJy4vbWF0aC5qcyc7XG4vKipcbiAqIEB0eXBlZGVmIHtmdW5jdGlvbigoaW1wb3J0KFwiLi9jb29yZGluYXRlLmpzXCIpLkNvb3JkaW5hdGV8dW5kZWZpbmVkKSwgbnVtYmVyLCBpbXBvcnQoXCIuL3NpemUuanNcIikuU2l6ZSwgYm9vbGVhbj0sIEFycmF5PG51bWJlcj49KTogKGltcG9ydChcIi4vY29vcmRpbmF0ZS5qc1wiKS5Db29yZGluYXRlfHVuZGVmaW5lZCl9IFR5cGVcbiAqL1xuXG4vKipcbiAqIEBwYXJhbSB7aW1wb3J0KFwiLi9leHRlbnQuanNcIikuRXh0ZW50fSBleHRlbnQgRXh0ZW50LlxuICogQHBhcmFtIHtib29sZWFufSBvbmx5Q2VudGVyIElmIHRydWUsIHRoZSBjb25zdHJhaW50IHdpbGwgb25seSBhcHBseSB0byB0aGUgdmlldyBjZW50ZXIuXG4gKiBAcGFyYW0ge2Jvb2xlYW59IHNtb290aCBJZiB0cnVlLCB0aGUgdmlldyB3aWxsIGJlIGFibGUgdG8gZ28gc2xpZ2h0bHkgb3V0IG9mIHRoZSBnaXZlbiBleHRlbnRcbiAqIChvbmx5IGR1cmluZyBpbnRlcmFjdGlvbiBhbmQgYW5pbWF0aW9uKS5cbiAqIEByZXR1cm4ge1R5cGV9IFRoZSBjb25zdHJhaW50LlxuICovXG5cbmV4cG9ydCBmdW5jdGlvbiBjcmVhdGVFeHRlbnQoZXh0ZW50LCBvbmx5Q2VudGVyLCBzbW9vdGgpIHtcbiAgcmV0dXJuIChcbiAgICAvKipcbiAgICAgKiBAcGFyYW0ge2ltcG9ydChcIi4vY29vcmRpbmF0ZS5qc1wiKS5Db29yZGluYXRlfHVuZGVmaW5lZH0gY2VudGVyIENlbnRlci5cbiAgICAgKiBAcGFyYW0ge251bWJlcn0gcmVzb2x1dGlvbiBSZXNvbHV0aW9uLlxuICAgICAqIEBwYXJhbSB7aW1wb3J0KFwiLi9zaXplLmpzXCIpLlNpemV9IHNpemUgVmlld3BvcnQgc2l6ZTsgdW51c2VkIGlmIGBvbmx5Q2VudGVyYCB3YXMgc3BlY2lmaWVkLlxuICAgICAqIEBwYXJhbSB7Ym9vbGVhbj19IG9wdF9pc01vdmluZyBUcnVlIGlmIGFuIGludGVyYWN0aW9uIG9yIGFuaW1hdGlvbiBpcyBpbiBwcm9ncmVzcy5cbiAgICAgKiBAcGFyYW0ge0FycmF5PG51bWJlcj49fSBvcHRfY2VudGVyU2hpZnQgU2hpZnQgYmV0d2VlbiBtYXAgY2VudGVyIGFuZCB2aWV3cG9ydCBjZW50ZXIuXG4gICAgICogQHJldHVybiB7aW1wb3J0KFwiLi9jb29yZGluYXRlLmpzXCIpLkNvb3JkaW5hdGV8dW5kZWZpbmVkfSBDZW50ZXIuXG4gICAgICovXG4gICAgZnVuY3Rpb24gKGNlbnRlciwgcmVzb2x1dGlvbiwgc2l6ZSwgb3B0X2lzTW92aW5nLCBvcHRfY2VudGVyU2hpZnQpIHtcbiAgICAgIGlmIChjZW50ZXIpIHtcbiAgICAgICAgdmFyIHZpZXdXaWR0aCA9IG9ubHlDZW50ZXIgPyAwIDogc2l6ZVswXSAqIHJlc29sdXRpb247XG4gICAgICAgIHZhciB2aWV3SGVpZ2h0ID0gb25seUNlbnRlciA/IDAgOiBzaXplWzFdICogcmVzb2x1dGlvbjtcbiAgICAgICAgdmFyIHNoaWZ0WCA9IG9wdF9jZW50ZXJTaGlmdCA/IG9wdF9jZW50ZXJTaGlmdFswXSA6IDA7XG4gICAgICAgIHZhciBzaGlmdFkgPSBvcHRfY2VudGVyU2hpZnQgPyBvcHRfY2VudGVyU2hpZnRbMV0gOiAwO1xuICAgICAgICB2YXIgbWluWCA9IGV4dGVudFswXSArIHZpZXdXaWR0aCAvIDIgKyBzaGlmdFg7XG4gICAgICAgIHZhciBtYXhYID0gZXh0ZW50WzJdIC0gdmlld1dpZHRoIC8gMiArIHNoaWZ0WDtcbiAgICAgICAgdmFyIG1pblkgPSBleHRlbnRbMV0gKyB2aWV3SGVpZ2h0IC8gMiArIHNoaWZ0WTtcbiAgICAgICAgdmFyIG1heFkgPSBleHRlbnRbM10gLSB2aWV3SGVpZ2h0IC8gMiArIHNoaWZ0WTsgLy8gbm90ZTogd2hlbiB6b29taW5nIG91dCBvZiBib3VuZHMsIG1pbiBhbmQgbWF4IHZhbHVlcyBmb3IgeCBhbmQgeSBtYXlcbiAgICAgICAgLy8gZW5kIHVwIGludmVydGVkIChtaW4gPiBtYXgpOyB0aGlzIGhhcyB0byBiZSBhY2NvdW50ZWQgZm9yXG5cbiAgICAgICAgaWYgKG1pblggPiBtYXhYKSB7XG4gICAgICAgICAgbWluWCA9IChtYXhYICsgbWluWCkgLyAyO1xuICAgICAgICAgIG1heFggPSBtaW5YO1xuICAgICAgICB9XG5cbiAgICAgICAgaWYgKG1pblkgPiBtYXhZKSB7XG4gICAgICAgICAgbWluWSA9IChtYXhZICsgbWluWSkgLyAyO1xuICAgICAgICAgIG1heFkgPSBtaW5ZO1xuICAgICAgICB9XG5cbiAgICAgICAgdmFyIHggPSBjbGFtcChjZW50ZXJbMF0sIG1pblgsIG1heFgpO1xuICAgICAgICB2YXIgeSA9IGNsYW1wKGNlbnRlclsxXSwgbWluWSwgbWF4WSk7XG4gICAgICAgIHZhciByYXRpbyA9IDMwICogcmVzb2x1dGlvbjsgLy8gZHVyaW5nIGFuIGludGVyYWN0aW9uLCBhbGxvdyBzb21lIG92ZXJzY3JvbGxcblxuICAgICAgICBpZiAob3B0X2lzTW92aW5nICYmIHNtb290aCkge1xuICAgICAgICAgIHggKz0gLXJhdGlvICogTWF0aC5sb2coMSArIE1hdGgubWF4KDAsIG1pblggLSBjZW50ZXJbMF0pIC8gcmF0aW8pICsgcmF0aW8gKiBNYXRoLmxvZygxICsgTWF0aC5tYXgoMCwgY2VudGVyWzBdIC0gbWF4WCkgLyByYXRpbyk7XG4gICAgICAgICAgeSArPSAtcmF0aW8gKiBNYXRoLmxvZygxICsgTWF0aC5tYXgoMCwgbWluWSAtIGNlbnRlclsxXSkgLyByYXRpbykgKyByYXRpbyAqIE1hdGgubG9nKDEgKyBNYXRoLm1heCgwLCBjZW50ZXJbMV0gLSBtYXhZKSAvIHJhdGlvKTtcbiAgICAgICAgfVxuXG4gICAgICAgIHJldHVybiBbeCwgeV07XG4gICAgICB9IGVsc2Uge1xuICAgICAgICByZXR1cm4gdW5kZWZpbmVkO1xuICAgICAgfVxuICAgIH1cbiAgKTtcbn1cbi8qKlxuICogQHBhcmFtIHtpbXBvcnQoXCIuL2Nvb3JkaW5hdGUuanNcIikuQ29vcmRpbmF0ZT19IGNlbnRlciBDZW50ZXIuXG4gKiBAcmV0dXJuIHtpbXBvcnQoXCIuL2Nvb3JkaW5hdGUuanNcIikuQ29vcmRpbmF0ZXx1bmRlZmluZWR9IENlbnRlci5cbiAqL1xuXG5leHBvcnQgZnVuY3Rpb24gbm9uZShjZW50ZXIpIHtcbiAgcmV0dXJuIGNlbnRlcjtcbn0iLCIvKipcbiAqIEBtb2R1bGUgb2wvcmVzb2x1dGlvbmNvbnN0cmFpbnRcbiAqL1xuaW1wb3J0IHsgY2xhbXAgfSBmcm9tICcuL21hdGguanMnO1xuaW1wb3J0IHsgZ2V0SGVpZ2h0LCBnZXRXaWR0aCB9IGZyb20gJy4vZXh0ZW50LmpzJztcbmltcG9ydCB7IGxpbmVhckZpbmROZWFyZXN0IH0gZnJvbSAnLi9hcnJheS5qcyc7XG4vKipcbiAqIEB0eXBlZGVmIHtmdW5jdGlvbigobnVtYmVyfHVuZGVmaW5lZCksIG51bWJlciwgaW1wb3J0KFwiLi9zaXplLmpzXCIpLlNpemUsIGJvb2xlYW49KTogKG51bWJlcnx1bmRlZmluZWQpfSBUeXBlXG4gKi9cblxuLyoqXG4gKiBSZXR1cm5zIGEgbW9kaWZpZWQgcmVzb2x1dGlvbiB0YWtpbmcgaW50byBhY2NvdW50IHRoZSB2aWV3cG9ydCBzaXplIGFuZCBtYXhpbXVtXG4gKiBhbGxvd2VkIGV4dGVudC5cbiAqIEBwYXJhbSB7bnVtYmVyfSByZXNvbHV0aW9uIFJlc29sdXRpb25cbiAqIEBwYXJhbSB7aW1wb3J0KFwiLi9leHRlbnQuanNcIikuRXh0ZW50fSBtYXhFeHRlbnQgTWF4aW11bSBhbGxvd2VkIGV4dGVudC5cbiAqIEBwYXJhbSB7aW1wb3J0KFwiLi9zaXplLmpzXCIpLlNpemV9IHZpZXdwb3J0U2l6ZSBWaWV3cG9ydCBzaXplLlxuICogQHBhcmFtIHtib29sZWFufSBzaG93RnVsbEV4dGVudCBXaGV0aGVyIHRvIHNob3cgdGhlIGZ1bGwgZXh0ZW50LlxuICogQHJldHVybiB7bnVtYmVyfSBDYXBwZWQgcmVzb2x1dGlvbi5cbiAqL1xuXG5mdW5jdGlvbiBnZXRWaWV3cG9ydENsYW1wZWRSZXNvbHV0aW9uKHJlc29sdXRpb24sIG1heEV4dGVudCwgdmlld3BvcnRTaXplLCBzaG93RnVsbEV4dGVudCkge1xuICB2YXIgeFJlc29sdXRpb24gPSBnZXRXaWR0aChtYXhFeHRlbnQpIC8gdmlld3BvcnRTaXplWzBdO1xuICB2YXIgeVJlc29sdXRpb24gPSBnZXRIZWlnaHQobWF4RXh0ZW50KSAvIHZpZXdwb3J0U2l6ZVsxXTtcblxuICBpZiAoc2hvd0Z1bGxFeHRlbnQpIHtcbiAgICByZXR1cm4gTWF0aC5taW4ocmVzb2x1dGlvbiwgTWF0aC5tYXgoeFJlc29sdXRpb24sIHlSZXNvbHV0aW9uKSk7XG4gIH1cblxuICByZXR1cm4gTWF0aC5taW4ocmVzb2x1dGlvbiwgTWF0aC5taW4oeFJlc29sdXRpb24sIHlSZXNvbHV0aW9uKSk7XG59XG4vKipcbiAqIFJldHVybnMgYSBtb2RpZmllZCByZXNvbHV0aW9uIHRvIGJlIGJldHdlZW4gbWF4UmVzb2x1dGlvbiBhbmQgbWluUmVzb2x1dGlvbiB3aGlsZVxuICogc3RpbGwgYWxsb3dpbmcgdGhlIHZhbHVlIHRvIGJlIHNsaWdodGx5IG91dCBvZiBib3VuZHMuXG4gKiBOb3RlOiB0aGUgY29tcHV0YXRpb24gaXMgYmFzZWQgb24gdGhlIGxvZ2FyaXRobSBmdW5jdGlvbiAobG4pOlxuICogIC0gYXQgMSwgbG4oeCkgaXMgMFxuICogIC0gYWJvdmUgMSwgbG4oeCkga2VlcHMgaW5jcmVhc2luZyBidXQgYXQgYSBtdWNoIHNsb3dlciBwYWNlIHRoYW4geFxuICogVGhlIGZpbmFsIHJlc3VsdCBpcyBjbGFtcGVkIHRvIHByZXZlbnQgZ2V0dGluZyB0b28gZmFyIGF3YXkgZnJvbSBib3VuZHMuXG4gKiBAcGFyYW0ge251bWJlcn0gcmVzb2x1dGlvbiBSZXNvbHV0aW9uLlxuICogQHBhcmFtIHtudW1iZXJ9IG1heFJlc29sdXRpb24gTWF4IHJlc29sdXRpb24uXG4gKiBAcGFyYW0ge251bWJlcn0gbWluUmVzb2x1dGlvbiBNaW4gcmVzb2x1dGlvbi5cbiAqIEByZXR1cm4ge251bWJlcn0gU21vb3RoZWQgcmVzb2x1dGlvbi5cbiAqL1xuXG5cbmZ1bmN0aW9uIGdldFNtb290aENsYW1wZWRSZXNvbHV0aW9uKHJlc29sdXRpb24sIG1heFJlc29sdXRpb24sIG1pblJlc29sdXRpb24pIHtcbiAgdmFyIHJlc3VsdCA9IE1hdGgubWluKHJlc29sdXRpb24sIG1heFJlc29sdXRpb24pO1xuICB2YXIgcmF0aW8gPSA1MDtcbiAgcmVzdWx0ICo9IE1hdGgubG9nKDEgKyByYXRpbyAqIE1hdGgubWF4KDAsIHJlc29sdXRpb24gLyBtYXhSZXNvbHV0aW9uIC0gMSkpIC8gcmF0aW8gKyAxO1xuXG4gIGlmIChtaW5SZXNvbHV0aW9uKSB7XG4gICAgcmVzdWx0ID0gTWF0aC5tYXgocmVzdWx0LCBtaW5SZXNvbHV0aW9uKTtcbiAgICByZXN1bHQgLz0gTWF0aC5sb2coMSArIHJhdGlvICogTWF0aC5tYXgoMCwgbWluUmVzb2x1dGlvbiAvIHJlc29sdXRpb24gLSAxKSkgLyByYXRpbyArIDE7XG4gIH1cblxuICByZXR1cm4gY2xhbXAocmVzdWx0LCBtaW5SZXNvbHV0aW9uIC8gMiwgbWF4UmVzb2x1dGlvbiAqIDIpO1xufVxuLyoqXG4gKiBAcGFyYW0ge0FycmF5PG51bWJlcj59IHJlc29sdXRpb25zIFJlc29sdXRpb25zLlxuICogQHBhcmFtIHtib29sZWFuPX0gb3B0X3Ntb290aCBJZiB0cnVlLCB0aGUgdmlldyB3aWxsIGJlIGFibGUgdG8gc2xpZ2h0bHkgZXhjZWVkIHJlc29sdXRpb24gbGltaXRzLiBEZWZhdWx0OiB0cnVlLlxuICogQHBhcmFtIHtpbXBvcnQoXCIuL2V4dGVudC5qc1wiKS5FeHRlbnQ9fSBvcHRfbWF4RXh0ZW50IE1heGltdW0gYWxsb3dlZCBleHRlbnQuXG4gKiBAcGFyYW0ge2Jvb2xlYW49fSBvcHRfc2hvd0Z1bGxFeHRlbnQgSWYgdHJ1ZSwgYWxsb3dzIHVzIHRvIHNob3cgdGhlIGZ1bGwgZXh0ZW50LiBEZWZhdWx0OiBmYWxzZS5cbiAqIEByZXR1cm4ge1R5cGV9IFpvb20gZnVuY3Rpb24uXG4gKi9cblxuXG5leHBvcnQgZnVuY3Rpb24gY3JlYXRlU25hcFRvUmVzb2x1dGlvbnMocmVzb2x1dGlvbnMsIG9wdF9zbW9vdGgsIG9wdF9tYXhFeHRlbnQsIG9wdF9zaG93RnVsbEV4dGVudCkge1xuICByZXR1cm4gKFxuICAgIC8qKlxuICAgICAqIEBwYXJhbSB7bnVtYmVyfHVuZGVmaW5lZH0gcmVzb2x1dGlvbiBSZXNvbHV0aW9uLlxuICAgICAqIEBwYXJhbSB7bnVtYmVyfSBkaXJlY3Rpb24gRGlyZWN0aW9uLlxuICAgICAqIEBwYXJhbSB7aW1wb3J0KFwiLi9zaXplLmpzXCIpLlNpemV9IHNpemUgVmlld3BvcnQgc2l6ZS5cbiAgICAgKiBAcGFyYW0ge2Jvb2xlYW49fSBvcHRfaXNNb3ZpbmcgVHJ1ZSBpZiBhbiBpbnRlcmFjdGlvbiBvciBhbmltYXRpb24gaXMgaW4gcHJvZ3Jlc3MuXG4gICAgICogQHJldHVybiB7bnVtYmVyfHVuZGVmaW5lZH0gUmVzb2x1dGlvbi5cbiAgICAgKi9cbiAgICBmdW5jdGlvbiAocmVzb2x1dGlvbiwgZGlyZWN0aW9uLCBzaXplLCBvcHRfaXNNb3ZpbmcpIHtcbiAgICAgIGlmIChyZXNvbHV0aW9uICE9PSB1bmRlZmluZWQpIHtcbiAgICAgICAgdmFyIG1heFJlc29sdXRpb24gPSByZXNvbHV0aW9uc1swXTtcbiAgICAgICAgdmFyIG1pblJlc29sdXRpb24gPSByZXNvbHV0aW9uc1tyZXNvbHV0aW9ucy5sZW5ndGggLSAxXTtcbiAgICAgICAgdmFyIGNhcHBlZE1heFJlcyA9IG9wdF9tYXhFeHRlbnQgPyBnZXRWaWV3cG9ydENsYW1wZWRSZXNvbHV0aW9uKG1heFJlc29sdXRpb24sIG9wdF9tYXhFeHRlbnQsIHNpemUsIG9wdF9zaG93RnVsbEV4dGVudCkgOiBtYXhSZXNvbHV0aW9uOyAvLyBkdXJpbmcgaW50ZXJhY3Rpbmcgb3IgYW5pbWF0aW5nLCBhbGxvdyBpbnRlcm1lZGlhcnkgdmFsdWVzXG5cbiAgICAgICAgaWYgKG9wdF9pc01vdmluZykge1xuICAgICAgICAgIHZhciBzbW9vdGggPSBvcHRfc21vb3RoICE9PSB1bmRlZmluZWQgPyBvcHRfc21vb3RoIDogdHJ1ZTtcblxuICAgICAgICAgIGlmICghc21vb3RoKSB7XG4gICAgICAgICAgICByZXR1cm4gY2xhbXAocmVzb2x1dGlvbiwgbWluUmVzb2x1dGlvbiwgY2FwcGVkTWF4UmVzKTtcbiAgICAgICAgICB9XG5cbiAgICAgICAgICByZXR1cm4gZ2V0U21vb3RoQ2xhbXBlZFJlc29sdXRpb24ocmVzb2x1dGlvbiwgY2FwcGVkTWF4UmVzLCBtaW5SZXNvbHV0aW9uKTtcbiAgICAgICAgfVxuXG4gICAgICAgIHZhciBjYXBwZWQgPSBNYXRoLm1pbihjYXBwZWRNYXhSZXMsIHJlc29sdXRpb24pO1xuICAgICAgICB2YXIgeiA9IE1hdGguZmxvb3IobGluZWFyRmluZE5lYXJlc3QocmVzb2x1dGlvbnMsIGNhcHBlZCwgZGlyZWN0aW9uKSk7XG5cbiAgICAgICAgaWYgKHJlc29sdXRpb25zW3pdID4gY2FwcGVkTWF4UmVzICYmIHogPCByZXNvbHV0aW9ucy5sZW5ndGggLSAxKSB7XG4gICAgICAgICAgcmV0dXJuIHJlc29sdXRpb25zW3ogKyAxXTtcbiAgICAgICAgfVxuXG4gICAgICAgIHJldHVybiByZXNvbHV0aW9uc1t6XTtcbiAgICAgIH0gZWxzZSB7XG4gICAgICAgIHJldHVybiB1bmRlZmluZWQ7XG4gICAgICB9XG4gICAgfVxuICApO1xufVxuLyoqXG4gKiBAcGFyYW0ge251bWJlcn0gcG93ZXIgUG93ZXIuXG4gKiBAcGFyYW0ge251bWJlcn0gbWF4UmVzb2x1dGlvbiBNYXhpbXVtIHJlc29sdXRpb24uXG4gKiBAcGFyYW0ge251bWJlcj19IG9wdF9taW5SZXNvbHV0aW9uIE1pbmltdW0gcmVzb2x1dGlvbi5cbiAqIEBwYXJhbSB7Ym9vbGVhbj19IG9wdF9zbW9vdGggSWYgdHJ1ZSwgdGhlIHZpZXcgd2lsbCBiZSBhYmxlIHRvIHNsaWdodGx5IGV4Y2VlZCByZXNvbHV0aW9uIGxpbWl0cy4gRGVmYXVsdDogdHJ1ZS5cbiAqIEBwYXJhbSB7aW1wb3J0KFwiLi9leHRlbnQuanNcIikuRXh0ZW50PX0gb3B0X21heEV4dGVudCBNYXhpbXVtIGFsbG93ZWQgZXh0ZW50LlxuICogQHBhcmFtIHtib29sZWFuPX0gb3B0X3Nob3dGdWxsRXh0ZW50IElmIHRydWUsIGFsbG93cyB1cyB0byBzaG93IHRoZSBmdWxsIGV4dGVudC4gRGVmYXVsdDogZmFsc2UuXG4gKiBAcmV0dXJuIHtUeXBlfSBab29tIGZ1bmN0aW9uLlxuICovXG5cbmV4cG9ydCBmdW5jdGlvbiBjcmVhdGVTbmFwVG9Qb3dlcihwb3dlciwgbWF4UmVzb2x1dGlvbiwgb3B0X21pblJlc29sdXRpb24sIG9wdF9zbW9vdGgsIG9wdF9tYXhFeHRlbnQsIG9wdF9zaG93RnVsbEV4dGVudCkge1xuICByZXR1cm4gKFxuICAgIC8qKlxuICAgICAqIEBwYXJhbSB7bnVtYmVyfHVuZGVmaW5lZH0gcmVzb2x1dGlvbiBSZXNvbHV0aW9uLlxuICAgICAqIEBwYXJhbSB7bnVtYmVyfSBkaXJlY3Rpb24gRGlyZWN0aW9uLlxuICAgICAqIEBwYXJhbSB7aW1wb3J0KFwiLi9zaXplLmpzXCIpLlNpemV9IHNpemUgVmlld3BvcnQgc2l6ZS5cbiAgICAgKiBAcGFyYW0ge2Jvb2xlYW49fSBvcHRfaXNNb3ZpbmcgVHJ1ZSBpZiBhbiBpbnRlcmFjdGlvbiBvciBhbmltYXRpb24gaXMgaW4gcHJvZ3Jlc3MuXG4gICAgICogQHJldHVybiB7bnVtYmVyfHVuZGVmaW5lZH0gUmVzb2x1dGlvbi5cbiAgICAgKi9cbiAgICBmdW5jdGlvbiAocmVzb2x1dGlvbiwgZGlyZWN0aW9uLCBzaXplLCBvcHRfaXNNb3ZpbmcpIHtcbiAgICAgIGlmIChyZXNvbHV0aW9uICE9PSB1bmRlZmluZWQpIHtcbiAgICAgICAgdmFyIGNhcHBlZE1heFJlcyA9IG9wdF9tYXhFeHRlbnQgPyBnZXRWaWV3cG9ydENsYW1wZWRSZXNvbHV0aW9uKG1heFJlc29sdXRpb24sIG9wdF9tYXhFeHRlbnQsIHNpemUsIG9wdF9zaG93RnVsbEV4dGVudCkgOiBtYXhSZXNvbHV0aW9uO1xuICAgICAgICB2YXIgbWluUmVzb2x1dGlvbiA9IG9wdF9taW5SZXNvbHV0aW9uICE9PSB1bmRlZmluZWQgPyBvcHRfbWluUmVzb2x1dGlvbiA6IDA7IC8vIGR1cmluZyBpbnRlcmFjdGluZyBvciBhbmltYXRpbmcsIGFsbG93IGludGVybWVkaWFyeSB2YWx1ZXNcblxuICAgICAgICBpZiAob3B0X2lzTW92aW5nKSB7XG4gICAgICAgICAgdmFyIHNtb290aCA9IG9wdF9zbW9vdGggIT09IHVuZGVmaW5lZCA/IG9wdF9zbW9vdGggOiB0cnVlO1xuXG4gICAgICAgICAgaWYgKCFzbW9vdGgpIHtcbiAgICAgICAgICAgIHJldHVybiBjbGFtcChyZXNvbHV0aW9uLCBtaW5SZXNvbHV0aW9uLCBjYXBwZWRNYXhSZXMpO1xuICAgICAgICAgIH1cblxuICAgICAgICAgIHJldHVybiBnZXRTbW9vdGhDbGFtcGVkUmVzb2x1dGlvbihyZXNvbHV0aW9uLCBjYXBwZWRNYXhSZXMsIG1pblJlc29sdXRpb24pO1xuICAgICAgICB9XG5cbiAgICAgICAgdmFyIHRvbGVyYW5jZSA9IDFlLTk7XG4gICAgICAgIHZhciBtaW5ab29tTGV2ZWwgPSBNYXRoLmNlaWwoTWF0aC5sb2cobWF4UmVzb2x1dGlvbiAvIGNhcHBlZE1heFJlcykgLyBNYXRoLmxvZyhwb3dlcikgLSB0b2xlcmFuY2UpO1xuICAgICAgICB2YXIgb2Zmc2V0ID0gLWRpcmVjdGlvbiAqICgwLjUgLSB0b2xlcmFuY2UpICsgMC41O1xuICAgICAgICB2YXIgY2FwcGVkID0gTWF0aC5taW4oY2FwcGVkTWF4UmVzLCByZXNvbHV0aW9uKTtcbiAgICAgICAgdmFyIGNhcHBlZFpvb21MZXZlbCA9IE1hdGguZmxvb3IoTWF0aC5sb2cobWF4UmVzb2x1dGlvbiAvIGNhcHBlZCkgLyBNYXRoLmxvZyhwb3dlcikgKyBvZmZzZXQpO1xuICAgICAgICB2YXIgem9vbUxldmVsID0gTWF0aC5tYXgobWluWm9vbUxldmVsLCBjYXBwZWRab29tTGV2ZWwpO1xuICAgICAgICB2YXIgbmV3UmVzb2x1dGlvbiA9IG1heFJlc29sdXRpb24gLyBNYXRoLnBvdyhwb3dlciwgem9vbUxldmVsKTtcbiAgICAgICAgcmV0dXJuIGNsYW1wKG5ld1Jlc29sdXRpb24sIG1pblJlc29sdXRpb24sIGNhcHBlZE1heFJlcyk7XG4gICAgICB9IGVsc2Uge1xuICAgICAgICByZXR1cm4gdW5kZWZpbmVkO1xuICAgICAgfVxuICAgIH1cbiAgKTtcbn1cbi8qKlxuICogQHBhcmFtIHtudW1iZXJ9IG1heFJlc29sdXRpb24gTWF4IHJlc29sdXRpb24uXG4gKiBAcGFyYW0ge251bWJlcn0gbWluUmVzb2x1dGlvbiBNaW4gcmVzb2x1dGlvbi5cbiAqIEBwYXJhbSB7Ym9vbGVhbj19IG9wdF9zbW9vdGggSWYgdHJ1ZSwgdGhlIHZpZXcgd2lsbCBiZSBhYmxlIHRvIHNsaWdodGx5IGV4Y2VlZCByZXNvbHV0aW9uIGxpbWl0cy4gRGVmYXVsdDogdHJ1ZS5cbiAqIEBwYXJhbSB7aW1wb3J0KFwiLi9leHRlbnQuanNcIikuRXh0ZW50PX0gb3B0X21heEV4dGVudCBNYXhpbXVtIGFsbG93ZWQgZXh0ZW50LlxuICogQHBhcmFtIHtib29sZWFuPX0gb3B0X3Nob3dGdWxsRXh0ZW50IElmIHRydWUsIGFsbG93cyB1cyB0byBzaG93IHRoZSBmdWxsIGV4dGVudC4gRGVmYXVsdDogZmFsc2UuXG4gKiBAcmV0dXJuIHtUeXBlfSBab29tIGZ1bmN0aW9uLlxuICovXG5cbmV4cG9ydCBmdW5jdGlvbiBjcmVhdGVNaW5NYXhSZXNvbHV0aW9uKG1heFJlc29sdXRpb24sIG1pblJlc29sdXRpb24sIG9wdF9zbW9vdGgsIG9wdF9tYXhFeHRlbnQsIG9wdF9zaG93RnVsbEV4dGVudCkge1xuICByZXR1cm4gKFxuICAgIC8qKlxuICAgICAqIEBwYXJhbSB7bnVtYmVyfHVuZGVmaW5lZH0gcmVzb2x1dGlvbiBSZXNvbHV0aW9uLlxuICAgICAqIEBwYXJhbSB7bnVtYmVyfSBkaXJlY3Rpb24gRGlyZWN0aW9uLlxuICAgICAqIEBwYXJhbSB7aW1wb3J0KFwiLi9zaXplLmpzXCIpLlNpemV9IHNpemUgVmlld3BvcnQgc2l6ZS5cbiAgICAgKiBAcGFyYW0ge2Jvb2xlYW49fSBvcHRfaXNNb3ZpbmcgVHJ1ZSBpZiBhbiBpbnRlcmFjdGlvbiBvciBhbmltYXRpb24gaXMgaW4gcHJvZ3Jlc3MuXG4gICAgICogQHJldHVybiB7bnVtYmVyfHVuZGVmaW5lZH0gUmVzb2x1dGlvbi5cbiAgICAgKi9cbiAgICBmdW5jdGlvbiAocmVzb2x1dGlvbiwgZGlyZWN0aW9uLCBzaXplLCBvcHRfaXNNb3ZpbmcpIHtcbiAgICAgIGlmIChyZXNvbHV0aW9uICE9PSB1bmRlZmluZWQpIHtcbiAgICAgICAgdmFyIGNhcHBlZE1heFJlcyA9IG9wdF9tYXhFeHRlbnQgPyBnZXRWaWV3cG9ydENsYW1wZWRSZXNvbHV0aW9uKG1heFJlc29sdXRpb24sIG9wdF9tYXhFeHRlbnQsIHNpemUsIG9wdF9zaG93RnVsbEV4dGVudCkgOiBtYXhSZXNvbHV0aW9uO1xuICAgICAgICB2YXIgc21vb3RoID0gb3B0X3Ntb290aCAhPT0gdW5kZWZpbmVkID8gb3B0X3Ntb290aCA6IHRydWU7XG5cbiAgICAgICAgaWYgKCFzbW9vdGggfHwgIW9wdF9pc01vdmluZykge1xuICAgICAgICAgIHJldHVybiBjbGFtcChyZXNvbHV0aW9uLCBtaW5SZXNvbHV0aW9uLCBjYXBwZWRNYXhSZXMpO1xuICAgICAgICB9XG5cbiAgICAgICAgcmV0dXJuIGdldFNtb290aENsYW1wZWRSZXNvbHV0aW9uKHJlc29sdXRpb24sIGNhcHBlZE1heFJlcywgbWluUmVzb2x1dGlvbik7XG4gICAgICB9IGVsc2Uge1xuICAgICAgICByZXR1cm4gdW5kZWZpbmVkO1xuICAgICAgfVxuICAgIH1cbiAgKTtcbn0iLCIvKipcbiAqIEBtb2R1bGUgb2wvcm90YXRpb25jb25zdHJhaW50XG4gKi9cbmltcG9ydCB7IHRvUmFkaWFucyB9IGZyb20gJy4vbWF0aC5qcyc7XG4vKipcbiAqIEB0eXBlZGVmIHtmdW5jdGlvbigobnVtYmVyfHVuZGVmaW5lZCksIGJvb2xlYW49KTogKG51bWJlcnx1bmRlZmluZWQpfSBUeXBlXG4gKi9cblxuLyoqXG4gKiBAcGFyYW0ge251bWJlcnx1bmRlZmluZWR9IHJvdGF0aW9uIFJvdGF0aW9uLlxuICogQHJldHVybiB7bnVtYmVyfHVuZGVmaW5lZH0gUm90YXRpb24uXG4gKi9cblxuZXhwb3J0IGZ1bmN0aW9uIGRpc2FibGUocm90YXRpb24pIHtcbiAgaWYgKHJvdGF0aW9uICE9PSB1bmRlZmluZWQpIHtcbiAgICByZXR1cm4gMDtcbiAgfSBlbHNlIHtcbiAgICByZXR1cm4gdW5kZWZpbmVkO1xuICB9XG59XG4vKipcbiAqIEBwYXJhbSB7bnVtYmVyfHVuZGVmaW5lZH0gcm90YXRpb24gUm90YXRpb24uXG4gKiBAcmV0dXJuIHtudW1iZXJ8dW5kZWZpbmVkfSBSb3RhdGlvbi5cbiAqL1xuXG5leHBvcnQgZnVuY3Rpb24gbm9uZShyb3RhdGlvbikge1xuICBpZiAocm90YXRpb24gIT09IHVuZGVmaW5lZCkge1xuICAgIHJldHVybiByb3RhdGlvbjtcbiAgfSBlbHNlIHtcbiAgICByZXR1cm4gdW5kZWZpbmVkO1xuICB9XG59XG4vKipcbiAqIEBwYXJhbSB7bnVtYmVyfSBuIE4uXG4gKiBAcmV0dXJuIHtUeXBlfSBSb3RhdGlvbiBjb25zdHJhaW50LlxuICovXG5cbmV4cG9ydCBmdW5jdGlvbiBjcmVhdGVTbmFwVG9OKG4pIHtcbiAgdmFyIHRoZXRhID0gMiAqIE1hdGguUEkgLyBuO1xuICByZXR1cm4gKFxuICAgIC8qKlxuICAgICAqIEBwYXJhbSB7bnVtYmVyfHVuZGVmaW5lZH0gcm90YXRpb24gUm90YXRpb24uXG4gICAgICogQHBhcmFtIHtib29sZWFuPX0gb3B0X2lzTW92aW5nIFRydWUgaWYgYW4gaW50ZXJhY3Rpb24gb3IgYW5pbWF0aW9uIGlzIGluIHByb2dyZXNzLlxuICAgICAqIEByZXR1cm4ge251bWJlcnx1bmRlZmluZWR9IFJvdGF0aW9uLlxuICAgICAqL1xuICAgIGZ1bmN0aW9uIChyb3RhdGlvbiwgb3B0X2lzTW92aW5nKSB7XG4gICAgICBpZiAob3B0X2lzTW92aW5nKSB7XG4gICAgICAgIHJldHVybiByb3RhdGlvbjtcbiAgICAgIH1cblxuICAgICAgaWYgKHJvdGF0aW9uICE9PSB1bmRlZmluZWQpIHtcbiAgICAgICAgcm90YXRpb24gPSBNYXRoLmZsb29yKHJvdGF0aW9uIC8gdGhldGEgKyAwLjUpICogdGhldGE7XG4gICAgICAgIHJldHVybiByb3RhdGlvbjtcbiAgICAgIH0gZWxzZSB7XG4gICAgICAgIHJldHVybiB1bmRlZmluZWQ7XG4gICAgICB9XG4gICAgfVxuICApO1xufVxuLyoqXG4gKiBAcGFyYW0ge251bWJlcj19IG9wdF90b2xlcmFuY2UgVG9sZXJhbmNlLlxuICogQHJldHVybiB7VHlwZX0gUm90YXRpb24gY29uc3RyYWludC5cbiAqL1xuXG5leHBvcnQgZnVuY3Rpb24gY3JlYXRlU25hcFRvWmVybyhvcHRfdG9sZXJhbmNlKSB7XG4gIHZhciB0b2xlcmFuY2UgPSBvcHRfdG9sZXJhbmNlIHx8IHRvUmFkaWFucyg1KTtcbiAgcmV0dXJuIChcbiAgICAvKipcbiAgICAgKiBAcGFyYW0ge251bWJlcnx1bmRlZmluZWR9IHJvdGF0aW9uIFJvdGF0aW9uLlxuICAgICAqIEBwYXJhbSB7Ym9vbGVhbj19IG9wdF9pc01vdmluZyBUcnVlIGlmIGFuIGludGVyYWN0aW9uIG9yIGFuaW1hdGlvbiBpcyBpbiBwcm9ncmVzcy5cbiAgICAgKiBAcmV0dXJuIHtudW1iZXJ8dW5kZWZpbmVkfSBSb3RhdGlvbi5cbiAgICAgKi9cbiAgICBmdW5jdGlvbiAocm90YXRpb24sIG9wdF9pc01vdmluZykge1xuICAgICAgaWYgKG9wdF9pc01vdmluZykge1xuICAgICAgICByZXR1cm4gcm90YXRpb247XG4gICAgICB9XG5cbiAgICAgIGlmIChyb3RhdGlvbiAhPT0gdW5kZWZpbmVkKSB7XG4gICAgICAgIGlmIChNYXRoLmFicyhyb3RhdGlvbikgPD0gdG9sZXJhbmNlKSB7XG4gICAgICAgICAgcmV0dXJuIDA7XG4gICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgcmV0dXJuIHJvdGF0aW9uO1xuICAgICAgICB9XG4gICAgICB9IGVsc2Uge1xuICAgICAgICByZXR1cm4gdW5kZWZpbmVkO1xuICAgICAgfVxuICAgIH1cbiAgKTtcbn0iLCIvKipcbiAqIEBtb2R1bGUgb2wvZWFzaW5nXG4gKi9cblxuLyoqXG4gKiBTdGFydCBzbG93IGFuZCBzcGVlZCB1cC5cbiAqIEBwYXJhbSB7bnVtYmVyfSB0IElucHV0IGJldHdlZW4gMCBhbmQgMS5cbiAqIEByZXR1cm4ge251bWJlcn0gT3V0cHV0IGJldHdlZW4gMCBhbmQgMS5cbiAqIEBhcGlcbiAqL1xuZXhwb3J0IGZ1bmN0aW9uIGVhc2VJbih0KSB7XG4gIHJldHVybiBNYXRoLnBvdyh0LCAzKTtcbn1cbi8qKlxuICogU3RhcnQgZmFzdCBhbmQgc2xvdyBkb3duLlxuICogQHBhcmFtIHtudW1iZXJ9IHQgSW5wdXQgYmV0d2VlbiAwIGFuZCAxLlxuICogQHJldHVybiB7bnVtYmVyfSBPdXRwdXQgYmV0d2VlbiAwIGFuZCAxLlxuICogQGFwaVxuICovXG5cbmV4cG9ydCBmdW5jdGlvbiBlYXNlT3V0KHQpIHtcbiAgcmV0dXJuIDEgLSBlYXNlSW4oMSAtIHQpO1xufVxuLyoqXG4gKiBTdGFydCBzbG93LCBzcGVlZCB1cCwgYW5kIHRoZW4gc2xvdyBkb3duIGFnYWluLlxuICogQHBhcmFtIHtudW1iZXJ9IHQgSW5wdXQgYmV0d2VlbiAwIGFuZCAxLlxuICogQHJldHVybiB7bnVtYmVyfSBPdXRwdXQgYmV0d2VlbiAwIGFuZCAxLlxuICogQGFwaVxuICovXG5cbmV4cG9ydCBmdW5jdGlvbiBpbkFuZE91dCh0KSB7XG4gIHJldHVybiAzICogdCAqIHQgLSAyICogdCAqIHQgKiB0O1xufVxuLyoqXG4gKiBNYWludGFpbiBhIGNvbnN0YW50IHNwZWVkIG92ZXIgdGltZS5cbiAqIEBwYXJhbSB7bnVtYmVyfSB0IElucHV0IGJldHdlZW4gMCBhbmQgMS5cbiAqIEByZXR1cm4ge251bWJlcn0gT3V0cHV0IGJldHdlZW4gMCBhbmQgMS5cbiAqIEBhcGlcbiAqL1xuXG5leHBvcnQgZnVuY3Rpb24gbGluZWFyKHQpIHtcbiAgcmV0dXJuIHQ7XG59XG4vKipcbiAqIFN0YXJ0IHNsb3csIHNwZWVkIHVwLCBhbmQgYXQgdGhlIHZlcnkgZW5kIHNsb3cgZG93biBhZ2Fpbi4gIFRoaXMgaGFzIHRoZVxuICogc2FtZSBnZW5lcmFsIGJlaGF2aW9yIGFzIHtAbGluayBtb2R1bGU6b2wvZWFzaW5nfmluQW5kT3V0fSwgYnV0IHRoZSBmaW5hbFxuICogc2xvd2Rvd24gaXMgZGVsYXllZC5cbiAqIEBwYXJhbSB7bnVtYmVyfSB0IElucHV0IGJldHdlZW4gMCBhbmQgMS5cbiAqIEByZXR1cm4ge251bWJlcn0gT3V0cHV0IGJldHdlZW4gMCBhbmQgMS5cbiAqIEBhcGlcbiAqL1xuXG5leHBvcnQgZnVuY3Rpb24gdXBBbmREb3duKHQpIHtcbiAgaWYgKHQgPCAwLjUpIHtcbiAgICByZXR1cm4gaW5BbmRPdXQoMiAqIHQpO1xuICB9IGVsc2Uge1xuICAgIHJldHVybiAxIC0gaW5BbmRPdXQoMiAqICh0IC0gMC41KSk7XG4gIH1cbn0iLCIvKipcbiAqIEBtb2R1bGUgb2wvZ2VvbS9HZW9tZXRyeUxheW91dFxuICovXG5cbi8qKlxuICogVGhlIGNvb3JkaW5hdGUgbGF5b3V0IGZvciBnZW9tZXRyaWVzLCBpbmRpY2F0aW5nIHdoZXRoZXIgYSAzcmQgb3IgNHRoIHogKCdaJylcbiAqIG9yIG1lYXN1cmUgKCdNJykgY29vcmRpbmF0ZSBpcyBhdmFpbGFibGUuIFN1cHBvcnRlZCB2YWx1ZXMgYXJlIGAnWFknYCxcbiAqIGAnWFlaJ2AsIGAnWFlNJ2AsIGAnWFlaTSdgLlxuICogQGVudW0ge3N0cmluZ31cbiAqL1xuZXhwb3J0IGRlZmF1bHQge1xuICBYWTogJ1hZJyxcbiAgWFlaOiAnWFlaJyxcbiAgWFlNOiAnWFlNJyxcbiAgWFlaTTogJ1hZWk0nXG59OyIsIi8qKlxuICogQG1vZHVsZSBvbC9nZW9tL2ZsYXQvdHJhbnNmb3JtXG4gKi9cblxuLyoqXG4gKiBAcGFyYW0ge0FycmF5PG51bWJlcj59IGZsYXRDb29yZGluYXRlcyBGbGF0IGNvb3JkaW5hdGVzLlxuICogQHBhcmFtIHtudW1iZXJ9IG9mZnNldCBPZmZzZXQuXG4gKiBAcGFyYW0ge251bWJlcn0gZW5kIEVuZC5cbiAqIEBwYXJhbSB7bnVtYmVyfSBzdHJpZGUgU3RyaWRlLlxuICogQHBhcmFtIHtpbXBvcnQoXCIuLi8uLi90cmFuc2Zvcm0uanNcIikuVHJhbnNmb3JtfSB0cmFuc2Zvcm0gVHJhbnNmb3JtLlxuICogQHBhcmFtIHtBcnJheTxudW1iZXI+PX0gb3B0X2Rlc3QgRGVzdGluYXRpb24uXG4gKiBAcmV0dXJuIHtBcnJheTxudW1iZXI+fSBUcmFuc2Zvcm1lZCBjb29yZGluYXRlcy5cbiAqL1xuZXhwb3J0IGZ1bmN0aW9uIHRyYW5zZm9ybTJEKGZsYXRDb29yZGluYXRlcywgb2Zmc2V0LCBlbmQsIHN0cmlkZSwgdHJhbnNmb3JtLCBvcHRfZGVzdCkge1xuICB2YXIgZGVzdCA9IG9wdF9kZXN0ID8gb3B0X2Rlc3QgOiBbXTtcbiAgdmFyIGkgPSAwO1xuXG4gIGZvciAodmFyIGogPSBvZmZzZXQ7IGogPCBlbmQ7IGogKz0gc3RyaWRlKSB7XG4gICAgdmFyIHggPSBmbGF0Q29vcmRpbmF0ZXNbal07XG4gICAgdmFyIHkgPSBmbGF0Q29vcmRpbmF0ZXNbaiArIDFdO1xuICAgIGRlc3RbaSsrXSA9IHRyYW5zZm9ybVswXSAqIHggKyB0cmFuc2Zvcm1bMl0gKiB5ICsgdHJhbnNmb3JtWzRdO1xuICAgIGRlc3RbaSsrXSA9IHRyYW5zZm9ybVsxXSAqIHggKyB0cmFuc2Zvcm1bM10gKiB5ICsgdHJhbnNmb3JtWzVdO1xuICB9XG5cbiAgaWYgKG9wdF9kZXN0ICYmIGRlc3QubGVuZ3RoICE9IGkpIHtcbiAgICBkZXN0Lmxlbmd0aCA9IGk7XG4gIH1cblxuICByZXR1cm4gZGVzdDtcbn1cbi8qKlxuICogQHBhcmFtIHtBcnJheTxudW1iZXI+fSBmbGF0Q29vcmRpbmF0ZXMgRmxhdCBjb29yZGluYXRlcy5cbiAqIEBwYXJhbSB7bnVtYmVyfSBvZmZzZXQgT2Zmc2V0LlxuICogQHBhcmFtIHtudW1iZXJ9IGVuZCBFbmQuXG4gKiBAcGFyYW0ge251bWJlcn0gc3RyaWRlIFN0cmlkZS5cbiAqIEBwYXJhbSB7bnVtYmVyfSBhbmdsZSBBbmdsZS5cbiAqIEBwYXJhbSB7QXJyYXk8bnVtYmVyPn0gYW5jaG9yIFJvdGF0aW9uIGFuY2hvciBwb2ludC5cbiAqIEBwYXJhbSB7QXJyYXk8bnVtYmVyPj19IG9wdF9kZXN0IERlc3RpbmF0aW9uLlxuICogQHJldHVybiB7QXJyYXk8bnVtYmVyPn0gVHJhbnNmb3JtZWQgY29vcmRpbmF0ZXMuXG4gKi9cblxuZXhwb3J0IGZ1bmN0aW9uIHJvdGF0ZShmbGF0Q29vcmRpbmF0ZXMsIG9mZnNldCwgZW5kLCBzdHJpZGUsIGFuZ2xlLCBhbmNob3IsIG9wdF9kZXN0KSB7XG4gIHZhciBkZXN0ID0gb3B0X2Rlc3QgPyBvcHRfZGVzdCA6IFtdO1xuICB2YXIgY29zID0gTWF0aC5jb3MoYW5nbGUpO1xuICB2YXIgc2luID0gTWF0aC5zaW4oYW5nbGUpO1xuICB2YXIgYW5jaG9yWCA9IGFuY2hvclswXTtcbiAgdmFyIGFuY2hvclkgPSBhbmNob3JbMV07XG4gIHZhciBpID0gMDtcblxuICBmb3IgKHZhciBqID0gb2Zmc2V0OyBqIDwgZW5kOyBqICs9IHN0cmlkZSkge1xuICAgIHZhciBkZWx0YVggPSBmbGF0Q29vcmRpbmF0ZXNbal0gLSBhbmNob3JYO1xuICAgIHZhciBkZWx0YVkgPSBmbGF0Q29vcmRpbmF0ZXNbaiArIDFdIC0gYW5jaG9yWTtcbiAgICBkZXN0W2krK10gPSBhbmNob3JYICsgZGVsdGFYICogY29zIC0gZGVsdGFZICogc2luO1xuICAgIGRlc3RbaSsrXSA9IGFuY2hvclkgKyBkZWx0YVggKiBzaW4gKyBkZWx0YVkgKiBjb3M7XG5cbiAgICBmb3IgKHZhciBrID0gaiArIDI7IGsgPCBqICsgc3RyaWRlOyArK2spIHtcbiAgICAgIGRlc3RbaSsrXSA9IGZsYXRDb29yZGluYXRlc1trXTtcbiAgICB9XG4gIH1cblxuICBpZiAob3B0X2Rlc3QgJiYgZGVzdC5sZW5ndGggIT0gaSkge1xuICAgIGRlc3QubGVuZ3RoID0gaTtcbiAgfVxuXG4gIHJldHVybiBkZXN0O1xufVxuLyoqXG4gKiBTY2FsZSB0aGUgY29vcmRpbmF0ZXMuXG4gKiBAcGFyYW0ge0FycmF5PG51bWJlcj59IGZsYXRDb29yZGluYXRlcyBGbGF0IGNvb3JkaW5hdGVzLlxuICogQHBhcmFtIHtudW1iZXJ9IG9mZnNldCBPZmZzZXQuXG4gKiBAcGFyYW0ge251bWJlcn0gZW5kIEVuZC5cbiAqIEBwYXJhbSB7bnVtYmVyfSBzdHJpZGUgU3RyaWRlLlxuICogQHBhcmFtIHtudW1iZXJ9IHN4IFNjYWxlIGZhY3RvciBpbiB0aGUgeC1kaXJlY3Rpb24uXG4gKiBAcGFyYW0ge251bWJlcn0gc3kgU2NhbGUgZmFjdG9yIGluIHRoZSB5LWRpcmVjdGlvbi5cbiAqIEBwYXJhbSB7QXJyYXk8bnVtYmVyPn0gYW5jaG9yIFNjYWxlIGFuY2hvciBwb2ludC5cbiAqIEBwYXJhbSB7QXJyYXk8bnVtYmVyPj19IG9wdF9kZXN0IERlc3RpbmF0aW9uLlxuICogQHJldHVybiB7QXJyYXk8bnVtYmVyPn0gVHJhbnNmb3JtZWQgY29vcmRpbmF0ZXMuXG4gKi9cblxuZXhwb3J0IGZ1bmN0aW9uIHNjYWxlKGZsYXRDb29yZGluYXRlcywgb2Zmc2V0LCBlbmQsIHN0cmlkZSwgc3gsIHN5LCBhbmNob3IsIG9wdF9kZXN0KSB7XG4gIHZhciBkZXN0ID0gb3B0X2Rlc3QgPyBvcHRfZGVzdCA6IFtdO1xuICB2YXIgYW5jaG9yWCA9IGFuY2hvclswXTtcbiAgdmFyIGFuY2hvclkgPSBhbmNob3JbMV07XG4gIHZhciBpID0gMDtcblxuICBmb3IgKHZhciBqID0gb2Zmc2V0OyBqIDwgZW5kOyBqICs9IHN0cmlkZSkge1xuICAgIHZhciBkZWx0YVggPSBmbGF0Q29vcmRpbmF0ZXNbal0gLSBhbmNob3JYO1xuICAgIHZhciBkZWx0YVkgPSBmbGF0Q29vcmRpbmF0ZXNbaiArIDFdIC0gYW5jaG9yWTtcbiAgICBkZXN0W2krK10gPSBhbmNob3JYICsgc3ggKiBkZWx0YVg7XG4gICAgZGVzdFtpKytdID0gYW5jaG9yWSArIHN5ICogZGVsdGFZO1xuXG4gICAgZm9yICh2YXIgayA9IGogKyAyOyBrIDwgaiArIHN0cmlkZTsgKytrKSB7XG4gICAgICBkZXN0W2krK10gPSBmbGF0Q29vcmRpbmF0ZXNba107XG4gICAgfVxuICB9XG5cbiAgaWYgKG9wdF9kZXN0ICYmIGRlc3QubGVuZ3RoICE9IGkpIHtcbiAgICBkZXN0Lmxlbmd0aCA9IGk7XG4gIH1cblxuICByZXR1cm4gZGVzdDtcbn1cbi8qKlxuICogQHBhcmFtIHtBcnJheTxudW1iZXI+fSBmbGF0Q29vcmRpbmF0ZXMgRmxhdCBjb29yZGluYXRlcy5cbiAqIEBwYXJhbSB7bnVtYmVyfSBvZmZzZXQgT2Zmc2V0LlxuICogQHBhcmFtIHtudW1iZXJ9IGVuZCBFbmQuXG4gKiBAcGFyYW0ge251bWJlcn0gc3RyaWRlIFN0cmlkZS5cbiAqIEBwYXJhbSB7bnVtYmVyfSBkZWx0YVggRGVsdGEgWC5cbiAqIEBwYXJhbSB7bnVtYmVyfSBkZWx0YVkgRGVsdGEgWS5cbiAqIEBwYXJhbSB7QXJyYXk8bnVtYmVyPj19IG9wdF9kZXN0IERlc3RpbmF0aW9uLlxuICogQHJldHVybiB7QXJyYXk8bnVtYmVyPn0gVHJhbnNmb3JtZWQgY29vcmRpbmF0ZXMuXG4gKi9cblxuZXhwb3J0IGZ1bmN0aW9uIHRyYW5zbGF0ZShmbGF0Q29vcmRpbmF0ZXMsIG9mZnNldCwgZW5kLCBzdHJpZGUsIGRlbHRhWCwgZGVsdGFZLCBvcHRfZGVzdCkge1xuICB2YXIgZGVzdCA9IG9wdF9kZXN0ID8gb3B0X2Rlc3QgOiBbXTtcbiAgdmFyIGkgPSAwO1xuXG4gIGZvciAodmFyIGogPSBvZmZzZXQ7IGogPCBlbmQ7IGogKz0gc3RyaWRlKSB7XG4gICAgZGVzdFtpKytdID0gZmxhdENvb3JkaW5hdGVzW2pdICsgZGVsdGFYO1xuICAgIGRlc3RbaSsrXSA9IGZsYXRDb29yZGluYXRlc1tqICsgMV0gKyBkZWx0YVk7XG5cbiAgICBmb3IgKHZhciBrID0gaiArIDI7IGsgPCBqICsgc3RyaWRlOyArK2spIHtcbiAgICAgIGRlc3RbaSsrXSA9IGZsYXRDb29yZGluYXRlc1trXTtcbiAgICB9XG4gIH1cblxuICBpZiAob3B0X2Rlc3QgJiYgZGVzdC5sZW5ndGggIT0gaSkge1xuICAgIGRlc3QubGVuZ3RoID0gaTtcbiAgfVxuXG4gIHJldHVybiBkZXN0O1xufSIsInZhciBfX2V4dGVuZHMgPSB0aGlzICYmIHRoaXMuX19leHRlbmRzIHx8IGZ1bmN0aW9uICgpIHtcbiAgdmFyIF9leHRlbmRTdGF0aWNzID0gZnVuY3Rpb24gZXh0ZW5kU3RhdGljcyhkLCBiKSB7XG4gICAgX2V4dGVuZFN0YXRpY3MgPSBPYmplY3Quc2V0UHJvdG90eXBlT2YgfHwge1xuICAgICAgX19wcm90b19fOiBbXVxuICAgIH0gaW5zdGFuY2VvZiBBcnJheSAmJiBmdW5jdGlvbiAoZCwgYikge1xuICAgICAgZC5fX3Byb3RvX18gPSBiO1xuICAgIH0gfHwgZnVuY3Rpb24gKGQsIGIpIHtcbiAgICAgIGZvciAodmFyIHAgaW4gYikge1xuICAgICAgICBpZiAoT2JqZWN0LnByb3RvdHlwZS5oYXNPd25Qcm9wZXJ0eS5jYWxsKGIsIHApKSBkW3BdID0gYltwXTtcbiAgICAgIH1cbiAgICB9O1xuXG4gICAgcmV0dXJuIF9leHRlbmRTdGF0aWNzKGQsIGIpO1xuICB9O1xuXG4gIHJldHVybiBmdW5jdGlvbiAoZCwgYikge1xuICAgIF9leHRlbmRTdGF0aWNzKGQsIGIpO1xuXG4gICAgZnVuY3Rpb24gX18oKSB7XG4gICAgICB0aGlzLmNvbnN0cnVjdG9yID0gZDtcbiAgICB9XG5cbiAgICBkLnByb3RvdHlwZSA9IGIgPT09IG51bGwgPyBPYmplY3QuY3JlYXRlKGIpIDogKF9fLnByb3RvdHlwZSA9IGIucHJvdG90eXBlLCBuZXcgX18oKSk7XG4gIH07XG59KCk7XG4vKipcbiAqIEBtb2R1bGUgb2wvZ2VvbS9HZW9tZXRyeVxuICovXG5cblxuaW1wb3J0IEJhc2VPYmplY3QgZnJvbSAnLi4vT2JqZWN0LmpzJztcbmltcG9ydCBVbml0cyBmcm9tICcuLi9wcm9qL1VuaXRzLmpzJztcbmltcG9ydCB7IGFic3RyYWN0IH0gZnJvbSAnLi4vdXRpbC5qcyc7XG5pbXBvcnQgeyBjb21wb3NlIGFzIGNvbXBvc2VUcmFuc2Zvcm0sIGNyZWF0ZSBhcyBjcmVhdGVUcmFuc2Zvcm0gfSBmcm9tICcuLi90cmFuc2Zvcm0uanMnO1xuaW1wb3J0IHsgY3JlYXRlRW1wdHksIGNyZWF0ZU9yVXBkYXRlRW1wdHksIGdldEhlaWdodCwgcmV0dXJuT3JVcGRhdGUgfSBmcm9tICcuLi9leHRlbnQuanMnO1xuaW1wb3J0IHsgZ2V0IGFzIGdldFByb2plY3Rpb24sIGdldFRyYW5zZm9ybSB9IGZyb20gJy4uL3Byb2ouanMnO1xuaW1wb3J0IHsgbWVtb2l6ZU9uZSB9IGZyb20gJy4uL2Z1bmN0aW9ucy5qcyc7XG5pbXBvcnQgeyB0cmFuc2Zvcm0yRCB9IGZyb20gJy4vZmxhdC90cmFuc2Zvcm0uanMnO1xuLyoqXG4gKiBAdHlwZSB7aW1wb3J0KFwiLi4vdHJhbnNmb3JtLmpzXCIpLlRyYW5zZm9ybX1cbiAqL1xuXG52YXIgdG1wVHJhbnNmb3JtID0gY3JlYXRlVHJhbnNmb3JtKCk7XG4vKipcbiAqIEBjbGFzc2Rlc2NcbiAqIEFic3RyYWN0IGJhc2UgY2xhc3M7IG5vcm1hbGx5IG9ubHkgdXNlZCBmb3IgY3JlYXRpbmcgc3ViY2xhc3NlcyBhbmQgbm90XG4gKiBpbnN0YW50aWF0ZWQgaW4gYXBwcy5cbiAqIEJhc2UgY2xhc3MgZm9yIHZlY3RvciBnZW9tZXRyaWVzLlxuICpcbiAqIFRvIGdldCBub3RpZmllZCBvZiBjaGFuZ2VzIHRvIHRoZSBnZW9tZXRyeSwgcmVnaXN0ZXIgYSBsaXN0ZW5lciBmb3IgdGhlXG4gKiBnZW5lcmljIGBjaGFuZ2VgIGV2ZW50IG9uIHlvdXIgZ2VvbWV0cnkgaW5zdGFuY2UuXG4gKlxuICogQGFic3RyYWN0XG4gKiBAYXBpXG4gKi9cblxudmFyIEdlb21ldHJ5ID1cbi8qKiBAY2xhc3MgKi9cbmZ1bmN0aW9uIChfc3VwZXIpIHtcbiAgX19leHRlbmRzKEdlb21ldHJ5LCBfc3VwZXIpO1xuXG4gIGZ1bmN0aW9uIEdlb21ldHJ5KCkge1xuICAgIHZhciBfdGhpcyA9IF9zdXBlci5jYWxsKHRoaXMpIHx8IHRoaXM7XG4gICAgLyoqXG4gICAgICogQHByaXZhdGVcbiAgICAgKiBAdHlwZSB7aW1wb3J0KFwiLi4vZXh0ZW50LmpzXCIpLkV4dGVudH1cbiAgICAgKi9cblxuXG4gICAgX3RoaXMuZXh0ZW50XyA9IGNyZWF0ZUVtcHR5KCk7XG4gICAgLyoqXG4gICAgICogQHByaXZhdGVcbiAgICAgKiBAdHlwZSB7bnVtYmVyfVxuICAgICAqL1xuXG4gICAgX3RoaXMuZXh0ZW50UmV2aXNpb25fID0gLTE7XG4gICAgLyoqXG4gICAgICogQHByb3RlY3RlZFxuICAgICAqIEB0eXBlIHtudW1iZXJ9XG4gICAgICovXG5cbiAgICBfdGhpcy5zaW1wbGlmaWVkR2VvbWV0cnlNYXhNaW5TcXVhcmVkVG9sZXJhbmNlID0gMDtcbiAgICAvKipcbiAgICAgKiBAcHJvdGVjdGVkXG4gICAgICogQHR5cGUge251bWJlcn1cbiAgICAgKi9cblxuICAgIF90aGlzLnNpbXBsaWZpZWRHZW9tZXRyeVJldmlzaW9uID0gMDtcbiAgICAvKipcbiAgICAgKiBHZXQgYSB0cmFuc2Zvcm1lZCBhbmQgc2ltcGxpZmllZCB2ZXJzaW9uIG9mIHRoZSBnZW9tZXRyeS5cbiAgICAgKiBAYWJzdHJhY3RcbiAgICAgKiBAcGFyYW0ge251bWJlcn0gcmV2aXNpb24gVGhlIGdlb21ldHJ5IHJldmlzaW9uLlxuICAgICAqIEBwYXJhbSB7bnVtYmVyfSBzcXVhcmVkVG9sZXJhbmNlIFNxdWFyZWQgdG9sZXJhbmNlLlxuICAgICAqIEBwYXJhbSB7aW1wb3J0KFwiLi4vcHJvai5qc1wiKS5UcmFuc2Zvcm1GdW5jdGlvbn0gW29wdF90cmFuc2Zvcm1dIE9wdGlvbmFsIHRyYW5zZm9ybSBmdW5jdGlvbi5cbiAgICAgKiBAcmV0dXJuIHtHZW9tZXRyeX0gU2ltcGxpZmllZCBnZW9tZXRyeS5cbiAgICAgKi9cblxuICAgIF90aGlzLnNpbXBsaWZ5VHJhbnNmb3JtZWRJbnRlcm5hbCA9IG1lbW9pemVPbmUoZnVuY3Rpb24gKHJldmlzaW9uLCBzcXVhcmVkVG9sZXJhbmNlLCBvcHRfdHJhbnNmb3JtKSB7XG4gICAgICBpZiAoIW9wdF90cmFuc2Zvcm0pIHtcbiAgICAgICAgcmV0dXJuIHRoaXMuZ2V0U2ltcGxpZmllZEdlb21ldHJ5KHNxdWFyZWRUb2xlcmFuY2UpO1xuICAgICAgfVxuXG4gICAgICB2YXIgY2xvbmUgPSB0aGlzLmNsb25lKCk7XG4gICAgICBjbG9uZS5hcHBseVRyYW5zZm9ybShvcHRfdHJhbnNmb3JtKTtcbiAgICAgIHJldHVybiBjbG9uZS5nZXRTaW1wbGlmaWVkR2VvbWV0cnkoc3F1YXJlZFRvbGVyYW5jZSk7XG4gICAgfSk7XG4gICAgcmV0dXJuIF90aGlzO1xuICB9XG4gIC8qKlxuICAgKiBHZXQgYSB0cmFuc2Zvcm1lZCBhbmQgc2ltcGxpZmllZCB2ZXJzaW9uIG9mIHRoZSBnZW9tZXRyeS5cbiAgICogQGFic3RyYWN0XG4gICAqIEBwYXJhbSB7bnVtYmVyfSBzcXVhcmVkVG9sZXJhbmNlIFNxdWFyZWQgdG9sZXJhbmNlLlxuICAgKiBAcGFyYW0ge2ltcG9ydChcIi4uL3Byb2ouanNcIikuVHJhbnNmb3JtRnVuY3Rpb259IFtvcHRfdHJhbnNmb3JtXSBPcHRpb25hbCB0cmFuc2Zvcm0gZnVuY3Rpb24uXG4gICAqIEByZXR1cm4ge0dlb21ldHJ5fSBTaW1wbGlmaWVkIGdlb21ldHJ5LlxuICAgKi9cblxuXG4gIEdlb21ldHJ5LnByb3RvdHlwZS5zaW1wbGlmeVRyYW5zZm9ybWVkID0gZnVuY3Rpb24gKHNxdWFyZWRUb2xlcmFuY2UsIG9wdF90cmFuc2Zvcm0pIHtcbiAgICByZXR1cm4gdGhpcy5zaW1wbGlmeVRyYW5zZm9ybWVkSW50ZXJuYWwodGhpcy5nZXRSZXZpc2lvbigpLCBzcXVhcmVkVG9sZXJhbmNlLCBvcHRfdHJhbnNmb3JtKTtcbiAgfTtcbiAgLyoqXG4gICAqIE1ha2UgYSBjb21wbGV0ZSBjb3B5IG9mIHRoZSBnZW9tZXRyeS5cbiAgICogQGFic3RyYWN0XG4gICAqIEByZXR1cm4geyFHZW9tZXRyeX0gQ2xvbmUuXG4gICAqL1xuXG5cbiAgR2VvbWV0cnkucHJvdG90eXBlLmNsb25lID0gZnVuY3Rpb24gKCkge1xuICAgIHJldHVybiBhYnN0cmFjdCgpO1xuICB9O1xuICAvKipcbiAgICogQGFic3RyYWN0XG4gICAqIEBwYXJhbSB7bnVtYmVyfSB4IFguXG4gICAqIEBwYXJhbSB7bnVtYmVyfSB5IFkuXG4gICAqIEBwYXJhbSB7aW1wb3J0KFwiLi4vY29vcmRpbmF0ZS5qc1wiKS5Db29yZGluYXRlfSBjbG9zZXN0UG9pbnQgQ2xvc2VzdCBwb2ludC5cbiAgICogQHBhcmFtIHtudW1iZXJ9IG1pblNxdWFyZWREaXN0YW5jZSBNaW5pbXVtIHNxdWFyZWQgZGlzdGFuY2UuXG4gICAqIEByZXR1cm4ge251bWJlcn0gTWluaW11bSBzcXVhcmVkIGRpc3RhbmNlLlxuICAgKi9cblxuXG4gIEdlb21ldHJ5LnByb3RvdHlwZS5jbG9zZXN0UG9pbnRYWSA9IGZ1bmN0aW9uICh4LCB5LCBjbG9zZXN0UG9pbnQsIG1pblNxdWFyZWREaXN0YW5jZSkge1xuICAgIHJldHVybiBhYnN0cmFjdCgpO1xuICB9O1xuICAvKipcbiAgICogQHBhcmFtIHtudW1iZXJ9IHggWC5cbiAgICogQHBhcmFtIHtudW1iZXJ9IHkgWS5cbiAgICogQHJldHVybiB7Ym9vbGVhbn0gQ29udGFpbnMgKHgsIHkpLlxuICAgKi9cblxuXG4gIEdlb21ldHJ5LnByb3RvdHlwZS5jb250YWluc1hZID0gZnVuY3Rpb24gKHgsIHkpIHtcbiAgICB2YXIgY29vcmQgPSB0aGlzLmdldENsb3Nlc3RQb2ludChbeCwgeV0pO1xuICAgIHJldHVybiBjb29yZFswXSA9PT0geCAmJiBjb29yZFsxXSA9PT0geTtcbiAgfTtcbiAgLyoqXG4gICAqIFJldHVybiB0aGUgY2xvc2VzdCBwb2ludCBvZiB0aGUgZ2VvbWV0cnkgdG8gdGhlIHBhc3NlZCBwb2ludCBhc1xuICAgKiB7QGxpbmsgbW9kdWxlOm9sL2Nvb3JkaW5hdGV+Q29vcmRpbmF0ZSBjb29yZGluYXRlfS5cbiAgICogQHBhcmFtIHtpbXBvcnQoXCIuLi9jb29yZGluYXRlLmpzXCIpLkNvb3JkaW5hdGV9IHBvaW50IFBvaW50LlxuICAgKiBAcGFyYW0ge2ltcG9ydChcIi4uL2Nvb3JkaW5hdGUuanNcIikuQ29vcmRpbmF0ZT19IG9wdF9jbG9zZXN0UG9pbnQgQ2xvc2VzdCBwb2ludC5cbiAgICogQHJldHVybiB7aW1wb3J0KFwiLi4vY29vcmRpbmF0ZS5qc1wiKS5Db29yZGluYXRlfSBDbG9zZXN0IHBvaW50LlxuICAgKiBAYXBpXG4gICAqL1xuXG5cbiAgR2VvbWV0cnkucHJvdG90eXBlLmdldENsb3Nlc3RQb2ludCA9IGZ1bmN0aW9uIChwb2ludCwgb3B0X2Nsb3Nlc3RQb2ludCkge1xuICAgIHZhciBjbG9zZXN0UG9pbnQgPSBvcHRfY2xvc2VzdFBvaW50ID8gb3B0X2Nsb3Nlc3RQb2ludCA6IFtOYU4sIE5hTl07XG4gICAgdGhpcy5jbG9zZXN0UG9pbnRYWShwb2ludFswXSwgcG9pbnRbMV0sIGNsb3Nlc3RQb2ludCwgSW5maW5pdHkpO1xuICAgIHJldHVybiBjbG9zZXN0UG9pbnQ7XG4gIH07XG4gIC8qKlxuICAgKiBSZXR1cm5zIHRydWUgaWYgdGhpcyBnZW9tZXRyeSBpbmNsdWRlcyB0aGUgc3BlY2lmaWVkIGNvb3JkaW5hdGUuIElmIHRoZVxuICAgKiBjb29yZGluYXRlIGlzIG9uIHRoZSBib3VuZGFyeSBvZiB0aGUgZ2VvbWV0cnksIHJldHVybnMgZmFsc2UuXG4gICAqIEBwYXJhbSB7aW1wb3J0KFwiLi4vY29vcmRpbmF0ZS5qc1wiKS5Db29yZGluYXRlfSBjb29yZGluYXRlIENvb3JkaW5hdGUuXG4gICAqIEByZXR1cm4ge2Jvb2xlYW59IENvbnRhaW5zIGNvb3JkaW5hdGUuXG4gICAqIEBhcGlcbiAgICovXG5cblxuICBHZW9tZXRyeS5wcm90b3R5cGUuaW50ZXJzZWN0c0Nvb3JkaW5hdGUgPSBmdW5jdGlvbiAoY29vcmRpbmF0ZSkge1xuICAgIHJldHVybiB0aGlzLmNvbnRhaW5zWFkoY29vcmRpbmF0ZVswXSwgY29vcmRpbmF0ZVsxXSk7XG4gIH07XG4gIC8qKlxuICAgKiBAYWJzdHJhY3RcbiAgICogQHBhcmFtIHtpbXBvcnQoXCIuLi9leHRlbnQuanNcIikuRXh0ZW50fSBleHRlbnQgRXh0ZW50LlxuICAgKiBAcHJvdGVjdGVkXG4gICAqIEByZXR1cm4ge2ltcG9ydChcIi4uL2V4dGVudC5qc1wiKS5FeHRlbnR9IGV4dGVudCBFeHRlbnQuXG4gICAqL1xuXG5cbiAgR2VvbWV0cnkucHJvdG90eXBlLmNvbXB1dGVFeHRlbnQgPSBmdW5jdGlvbiAoZXh0ZW50KSB7XG4gICAgcmV0dXJuIGFic3RyYWN0KCk7XG4gIH07XG4gIC8qKlxuICAgKiBHZXQgdGhlIGV4dGVudCBvZiB0aGUgZ2VvbWV0cnkuXG4gICAqIEBwYXJhbSB7aW1wb3J0KFwiLi4vZXh0ZW50LmpzXCIpLkV4dGVudD19IG9wdF9leHRlbnQgRXh0ZW50LlxuICAgKiBAcmV0dXJuIHtpbXBvcnQoXCIuLi9leHRlbnQuanNcIikuRXh0ZW50fSBleHRlbnQgRXh0ZW50LlxuICAgKiBAYXBpXG4gICAqL1xuXG5cbiAgR2VvbWV0cnkucHJvdG90eXBlLmdldEV4dGVudCA9IGZ1bmN0aW9uIChvcHRfZXh0ZW50KSB7XG4gICAgaWYgKHRoaXMuZXh0ZW50UmV2aXNpb25fICE9IHRoaXMuZ2V0UmV2aXNpb24oKSkge1xuICAgICAgdmFyIGV4dGVudCA9IHRoaXMuY29tcHV0ZUV4dGVudCh0aGlzLmV4dGVudF8pO1xuXG4gICAgICBpZiAoaXNOYU4oZXh0ZW50WzBdKSB8fCBpc05hTihleHRlbnRbMV0pKSB7XG4gICAgICAgIGNyZWF0ZU9yVXBkYXRlRW1wdHkoZXh0ZW50KTtcbiAgICAgIH1cblxuICAgICAgdGhpcy5leHRlbnRSZXZpc2lvbl8gPSB0aGlzLmdldFJldmlzaW9uKCk7XG4gICAgfVxuXG4gICAgcmV0dXJuIHJldHVybk9yVXBkYXRlKHRoaXMuZXh0ZW50Xywgb3B0X2V4dGVudCk7XG4gIH07XG4gIC8qKlxuICAgKiBSb3RhdGUgdGhlIGdlb21ldHJ5IGFyb3VuZCBhIGdpdmVuIGNvb3JkaW5hdGUuIFRoaXMgbW9kaWZpZXMgdGhlIGdlb21ldHJ5XG4gICAqIGNvb3JkaW5hdGVzIGluIHBsYWNlLlxuICAgKiBAYWJzdHJhY3RcbiAgICogQHBhcmFtIHtudW1iZXJ9IGFuZ2xlIFJvdGF0aW9uIGFuZ2xlIGluIHJhZGlhbnMuXG4gICAqIEBwYXJhbSB7aW1wb3J0KFwiLi4vY29vcmRpbmF0ZS5qc1wiKS5Db29yZGluYXRlfSBhbmNob3IgVGhlIHJvdGF0aW9uIGNlbnRlci5cbiAgICogQGFwaVxuICAgKi9cblxuXG4gIEdlb21ldHJ5LnByb3RvdHlwZS5yb3RhdGUgPSBmdW5jdGlvbiAoYW5nbGUsIGFuY2hvcikge1xuICAgIGFic3RyYWN0KCk7XG4gIH07XG4gIC8qKlxuICAgKiBTY2FsZSB0aGUgZ2VvbWV0cnkgKHdpdGggYW4gb3B0aW9uYWwgb3JpZ2luKS4gIFRoaXMgbW9kaWZpZXMgdGhlIGdlb21ldHJ5XG4gICAqIGNvb3JkaW5hdGVzIGluIHBsYWNlLlxuICAgKiBAYWJzdHJhY3RcbiAgICogQHBhcmFtIHtudW1iZXJ9IHN4IFRoZSBzY2FsaW5nIGZhY3RvciBpbiB0aGUgeC1kaXJlY3Rpb24uXG4gICAqIEBwYXJhbSB7bnVtYmVyPX0gb3B0X3N5IFRoZSBzY2FsaW5nIGZhY3RvciBpbiB0aGUgeS1kaXJlY3Rpb24gKGRlZmF1bHRzIHRvIHN4KS5cbiAgICogQHBhcmFtIHtpbXBvcnQoXCIuLi9jb29yZGluYXRlLmpzXCIpLkNvb3JkaW5hdGU9fSBvcHRfYW5jaG9yIFRoZSBzY2FsZSBvcmlnaW4gKGRlZmF1bHRzIHRvIHRoZSBjZW50ZXJcbiAgICogICAgIG9mIHRoZSBnZW9tZXRyeSBleHRlbnQpLlxuICAgKiBAYXBpXG4gICAqL1xuXG5cbiAgR2VvbWV0cnkucHJvdG90eXBlLnNjYWxlID0gZnVuY3Rpb24gKHN4LCBvcHRfc3ksIG9wdF9hbmNob3IpIHtcbiAgICBhYnN0cmFjdCgpO1xuICB9O1xuICAvKipcbiAgICogQ3JlYXRlIGEgc2ltcGxpZmllZCB2ZXJzaW9uIG9mIHRoaXMgZ2VvbWV0cnkuICBGb3IgbGluZXN0cmluZ3MsIHRoaXMgdXNlc1xuICAgKiB0aGUgW0RvdWdsYXMgUGV1Y2tlcl0oaHR0cHM6Ly9lbi53aWtpcGVkaWEub3JnL3dpa2kvUmFtZXItRG91Z2xhcy1QZXVja2VyX2FsZ29yaXRobSlcbiAgICogYWxnb3JpdGhtLiAgRm9yIHBvbHlnb25zLCBhIHF1YW50aXphdGlvbi1iYXNlZFxuICAgKiBzaW1wbGlmaWNhdGlvbiBpcyB1c2VkIHRvIHByZXNlcnZlIHRvcG9sb2d5LlxuICAgKiBAcGFyYW0ge251bWJlcn0gdG9sZXJhbmNlIFRoZSB0b2xlcmFuY2UgZGlzdGFuY2UgZm9yIHNpbXBsaWZpY2F0aW9uLlxuICAgKiBAcmV0dXJuIHtHZW9tZXRyeX0gQSBuZXcsIHNpbXBsaWZpZWQgdmVyc2lvbiBvZiB0aGUgb3JpZ2luYWwgZ2VvbWV0cnkuXG4gICAqIEBhcGlcbiAgICovXG5cblxuICBHZW9tZXRyeS5wcm90b3R5cGUuc2ltcGxpZnkgPSBmdW5jdGlvbiAodG9sZXJhbmNlKSB7XG4gICAgcmV0dXJuIHRoaXMuZ2V0U2ltcGxpZmllZEdlb21ldHJ5KHRvbGVyYW5jZSAqIHRvbGVyYW5jZSk7XG4gIH07XG4gIC8qKlxuICAgKiBDcmVhdGUgYSBzaW1wbGlmaWVkIHZlcnNpb24gb2YgdGhpcyBnZW9tZXRyeSB1c2luZyB0aGUgRG91Z2xhcyBQZXVja2VyXG4gICAqIGFsZ29yaXRobS5cbiAgICogU2VlIGh0dHBzOi8vZW4ud2lraXBlZGlhLm9yZy93aWtpL1JhbWVyLURvdWdsYXMtUGV1Y2tlcl9hbGdvcml0aG0uXG4gICAqIEBhYnN0cmFjdFxuICAgKiBAcGFyYW0ge251bWJlcn0gc3F1YXJlZFRvbGVyYW5jZSBTcXVhcmVkIHRvbGVyYW5jZS5cbiAgICogQHJldHVybiB7R2VvbWV0cnl9IFNpbXBsaWZpZWQgZ2VvbWV0cnkuXG4gICAqL1xuXG5cbiAgR2VvbWV0cnkucHJvdG90eXBlLmdldFNpbXBsaWZpZWRHZW9tZXRyeSA9IGZ1bmN0aW9uIChzcXVhcmVkVG9sZXJhbmNlKSB7XG4gICAgcmV0dXJuIGFic3RyYWN0KCk7XG4gIH07XG4gIC8qKlxuICAgKiBHZXQgdGhlIHR5cGUgb2YgdGhpcyBnZW9tZXRyeS5cbiAgICogQGFic3RyYWN0XG4gICAqIEByZXR1cm4ge2ltcG9ydChcIi4vR2VvbWV0cnlUeXBlLmpzXCIpLmRlZmF1bHR9IEdlb21ldHJ5IHR5cGUuXG4gICAqL1xuXG5cbiAgR2VvbWV0cnkucHJvdG90eXBlLmdldFR5cGUgPSBmdW5jdGlvbiAoKSB7XG4gICAgcmV0dXJuIGFic3RyYWN0KCk7XG4gIH07XG4gIC8qKlxuICAgKiBBcHBseSBhIHRyYW5zZm9ybSBmdW5jdGlvbiB0byB0aGUgY29vcmRpbmF0ZXMgb2YgdGhlIGdlb21ldHJ5LlxuICAgKiBUaGUgZ2VvbWV0cnkgaXMgbW9kaWZpZWQgaW4gcGxhY2UuXG4gICAqIElmIHlvdSBkbyBub3Qgd2FudCB0aGUgZ2VvbWV0cnkgbW9kaWZpZWQgaW4gcGxhY2UsIGZpcnN0IGBjbG9uZSgpYCBpdCBhbmRcbiAgICogdGhlbiB1c2UgdGhpcyBmdW5jdGlvbiBvbiB0aGUgY2xvbmUuXG4gICAqIEBhYnN0cmFjdFxuICAgKiBAcGFyYW0ge2ltcG9ydChcIi4uL3Byb2ouanNcIikuVHJhbnNmb3JtRnVuY3Rpb259IHRyYW5zZm9ybUZuIFRyYW5zZm9ybSBmdW5jdGlvbi5cbiAgICogQ2FsbGVkIHdpdGggYSBmbGF0IGFycmF5IG9mIGdlb21ldHJ5IGNvb3JkaW5hdGVzLlxuICAgKi9cblxuXG4gIEdlb21ldHJ5LnByb3RvdHlwZS5hcHBseVRyYW5zZm9ybSA9IGZ1bmN0aW9uICh0cmFuc2Zvcm1Gbikge1xuICAgIGFic3RyYWN0KCk7XG4gIH07XG4gIC8qKlxuICAgKiBUZXN0IGlmIHRoZSBnZW9tZXRyeSBhbmQgdGhlIHBhc3NlZCBleHRlbnQgaW50ZXJzZWN0LlxuICAgKiBAYWJzdHJhY3RcbiAgICogQHBhcmFtIHtpbXBvcnQoXCIuLi9leHRlbnQuanNcIikuRXh0ZW50fSBleHRlbnQgRXh0ZW50LlxuICAgKiBAcmV0dXJuIHtib29sZWFufSBgdHJ1ZWAgaWYgdGhlIGdlb21ldHJ5IGFuZCB0aGUgZXh0ZW50IGludGVyc2VjdC5cbiAgICovXG5cblxuICBHZW9tZXRyeS5wcm90b3R5cGUuaW50ZXJzZWN0c0V4dGVudCA9IGZ1bmN0aW9uIChleHRlbnQpIHtcbiAgICByZXR1cm4gYWJzdHJhY3QoKTtcbiAgfTtcbiAgLyoqXG4gICAqIFRyYW5zbGF0ZSB0aGUgZ2VvbWV0cnkuICBUaGlzIG1vZGlmaWVzIHRoZSBnZW9tZXRyeSBjb29yZGluYXRlcyBpbiBwbGFjZS4gIElmXG4gICAqIGluc3RlYWQgeW91IHdhbnQgYSBuZXcgZ2VvbWV0cnksIGZpcnN0IGBjbG9uZSgpYCB0aGlzIGdlb21ldHJ5LlxuICAgKiBAYWJzdHJhY3RcbiAgICogQHBhcmFtIHtudW1iZXJ9IGRlbHRhWCBEZWx0YSBYLlxuICAgKiBAcGFyYW0ge251bWJlcn0gZGVsdGFZIERlbHRhIFkuXG4gICAqIEBhcGlcbiAgICovXG5cblxuICBHZW9tZXRyeS5wcm90b3R5cGUudHJhbnNsYXRlID0gZnVuY3Rpb24gKGRlbHRhWCwgZGVsdGFZKSB7XG4gICAgYWJzdHJhY3QoKTtcbiAgfTtcbiAgLyoqXG4gICAqIFRyYW5zZm9ybSBlYWNoIGNvb3JkaW5hdGUgb2YgdGhlIGdlb21ldHJ5IGZyb20gb25lIGNvb3JkaW5hdGUgcmVmZXJlbmNlXG4gICAqIHN5c3RlbSB0byBhbm90aGVyLiBUaGUgZ2VvbWV0cnkgaXMgbW9kaWZpZWQgaW4gcGxhY2UuXG4gICAqIEZvciBleGFtcGxlLCBhIGxpbmUgd2lsbCBiZSB0cmFuc2Zvcm1lZCB0byBhIGxpbmUgYW5kIGEgY2lyY2xlIHRvIGEgY2lyY2xlLlxuICAgKiBJZiB5b3UgZG8gbm90IHdhbnQgdGhlIGdlb21ldHJ5IG1vZGlmaWVkIGluIHBsYWNlLCBmaXJzdCBgY2xvbmUoKWAgaXQgYW5kXG4gICAqIHRoZW4gdXNlIHRoaXMgZnVuY3Rpb24gb24gdGhlIGNsb25lLlxuICAgKlxuICAgKiBAcGFyYW0ge2ltcG9ydChcIi4uL3Byb2ouanNcIikuUHJvamVjdGlvbkxpa2V9IHNvdXJjZSBUaGUgY3VycmVudCBwcm9qZWN0aW9uLiAgQ2FuIGJlIGFcbiAgICogICAgIHN0cmluZyBpZGVudGlmaWVyIG9yIGEge0BsaW5rIG1vZHVsZTpvbC9wcm9qL1Byb2plY3Rpb25+UHJvamVjdGlvbn0gb2JqZWN0LlxuICAgKiBAcGFyYW0ge2ltcG9ydChcIi4uL3Byb2ouanNcIikuUHJvamVjdGlvbkxpa2V9IGRlc3RpbmF0aW9uIFRoZSBkZXNpcmVkIHByb2plY3Rpb24uICBDYW4gYmUgYVxuICAgKiAgICAgc3RyaW5nIGlkZW50aWZpZXIgb3IgYSB7QGxpbmsgbW9kdWxlOm9sL3Byb2ovUHJvamVjdGlvbn5Qcm9qZWN0aW9ufSBvYmplY3QuXG4gICAqIEByZXR1cm4ge0dlb21ldHJ5fSBUaGlzIGdlb21ldHJ5LiAgTm90ZSB0aGF0IG9yaWdpbmFsIGdlb21ldHJ5IGlzXG4gICAqICAgICBtb2RpZmllZCBpbiBwbGFjZS5cbiAgICogQGFwaVxuICAgKi9cblxuXG4gIEdlb21ldHJ5LnByb3RvdHlwZS50cmFuc2Zvcm0gPSBmdW5jdGlvbiAoc291cmNlLCBkZXN0aW5hdGlvbikge1xuICAgIC8qKiBAdHlwZSB7aW1wb3J0KFwiLi4vcHJvai9Qcm9qZWN0aW9uLmpzXCIpLmRlZmF1bHR9ICovXG4gICAgdmFyIHNvdXJjZVByb2ogPSBnZXRQcm9qZWN0aW9uKHNvdXJjZSk7XG4gICAgdmFyIHRyYW5zZm9ybUZuID0gc291cmNlUHJvai5nZXRVbml0cygpID09IFVuaXRzLlRJTEVfUElYRUxTID8gZnVuY3Rpb24gKGluQ29vcmRpbmF0ZXMsIG91dENvb3JkaW5hdGVzLCBzdHJpZGUpIHtcbiAgICAgIHZhciBwaXhlbEV4dGVudCA9IHNvdXJjZVByb2ouZ2V0RXh0ZW50KCk7XG4gICAgICB2YXIgcHJvamVjdGVkRXh0ZW50ID0gc291cmNlUHJvai5nZXRXb3JsZEV4dGVudCgpO1xuICAgICAgdmFyIHNjYWxlID0gZ2V0SGVpZ2h0KHByb2plY3RlZEV4dGVudCkgLyBnZXRIZWlnaHQocGl4ZWxFeHRlbnQpO1xuICAgICAgY29tcG9zZVRyYW5zZm9ybSh0bXBUcmFuc2Zvcm0sIHByb2plY3RlZEV4dGVudFswXSwgcHJvamVjdGVkRXh0ZW50WzNdLCBzY2FsZSwgLXNjYWxlLCAwLCAwLCAwKTtcbiAgICAgIHRyYW5zZm9ybTJEKGluQ29vcmRpbmF0ZXMsIDAsIGluQ29vcmRpbmF0ZXMubGVuZ3RoLCBzdHJpZGUsIHRtcFRyYW5zZm9ybSwgb3V0Q29vcmRpbmF0ZXMpO1xuICAgICAgcmV0dXJuIGdldFRyYW5zZm9ybShzb3VyY2VQcm9qLCBkZXN0aW5hdGlvbikoaW5Db29yZGluYXRlcywgb3V0Q29vcmRpbmF0ZXMsIHN0cmlkZSk7XG4gICAgfSA6IGdldFRyYW5zZm9ybShzb3VyY2VQcm9qLCBkZXN0aW5hdGlvbik7XG4gICAgdGhpcy5hcHBseVRyYW5zZm9ybSh0cmFuc2Zvcm1Gbik7XG4gICAgcmV0dXJuIHRoaXM7XG4gIH07XG5cbiAgcmV0dXJuIEdlb21ldHJ5O1xufShCYXNlT2JqZWN0KTtcblxuZXhwb3J0IGRlZmF1bHQgR2VvbWV0cnk7IiwidmFyIF9fZXh0ZW5kcyA9IHRoaXMgJiYgdGhpcy5fX2V4dGVuZHMgfHwgZnVuY3Rpb24gKCkge1xuICB2YXIgX2V4dGVuZFN0YXRpY3MgPSBmdW5jdGlvbiBleHRlbmRTdGF0aWNzKGQsIGIpIHtcbiAgICBfZXh0ZW5kU3RhdGljcyA9IE9iamVjdC5zZXRQcm90b3R5cGVPZiB8fCB7XG4gICAgICBfX3Byb3RvX186IFtdXG4gICAgfSBpbnN0YW5jZW9mIEFycmF5ICYmIGZ1bmN0aW9uIChkLCBiKSB7XG4gICAgICBkLl9fcHJvdG9fXyA9IGI7XG4gICAgfSB8fCBmdW5jdGlvbiAoZCwgYikge1xuICAgICAgZm9yICh2YXIgcCBpbiBiKSB7XG4gICAgICAgIGlmIChPYmplY3QucHJvdG90eXBlLmhhc093blByb3BlcnR5LmNhbGwoYiwgcCkpIGRbcF0gPSBiW3BdO1xuICAgICAgfVxuICAgIH07XG5cbiAgICByZXR1cm4gX2V4dGVuZFN0YXRpY3MoZCwgYik7XG4gIH07XG5cbiAgcmV0dXJuIGZ1bmN0aW9uIChkLCBiKSB7XG4gICAgX2V4dGVuZFN0YXRpY3MoZCwgYik7XG5cbiAgICBmdW5jdGlvbiBfXygpIHtcbiAgICAgIHRoaXMuY29uc3RydWN0b3IgPSBkO1xuICAgIH1cblxuICAgIGQucHJvdG90eXBlID0gYiA9PT0gbnVsbCA/IE9iamVjdC5jcmVhdGUoYikgOiAoX18ucHJvdG90eXBlID0gYi5wcm90b3R5cGUsIG5ldyBfXygpKTtcbiAgfTtcbn0oKTtcbi8qKlxuICogQG1vZHVsZSBvbC9nZW9tL1NpbXBsZUdlb21ldHJ5XG4gKi9cblxuXG5pbXBvcnQgR2VvbWV0cnkgZnJvbSAnLi9HZW9tZXRyeS5qcyc7XG5pbXBvcnQgR2VvbWV0cnlMYXlvdXQgZnJvbSAnLi9HZW9tZXRyeUxheW91dC5qcyc7XG5pbXBvcnQgeyBhYnN0cmFjdCB9IGZyb20gJy4uL3V0aWwuanMnO1xuaW1wb3J0IHsgY3JlYXRlT3JVcGRhdGVGcm9tRmxhdENvb3JkaW5hdGVzLCBnZXRDZW50ZXIgfSBmcm9tICcuLi9leHRlbnQuanMnO1xuaW1wb3J0IHsgcm90YXRlLCBzY2FsZSwgdHJhbnNmb3JtMkQsIHRyYW5zbGF0ZSB9IGZyb20gJy4vZmxhdC90cmFuc2Zvcm0uanMnO1xuLyoqXG4gKiBAY2xhc3NkZXNjXG4gKiBBYnN0cmFjdCBiYXNlIGNsYXNzOyBvbmx5IHVzZWQgZm9yIGNyZWF0aW5nIHN1YmNsYXNzZXM7IGRvIG5vdCBpbnN0YW50aWF0ZVxuICogaW4gYXBwcywgYXMgY2Fubm90IGJlIHJlbmRlcmVkLlxuICpcbiAqIEBhYnN0cmFjdFxuICogQGFwaVxuICovXG5cbnZhciBTaW1wbGVHZW9tZXRyeSA9XG4vKiogQGNsYXNzICovXG5mdW5jdGlvbiAoX3N1cGVyKSB7XG4gIF9fZXh0ZW5kcyhTaW1wbGVHZW9tZXRyeSwgX3N1cGVyKTtcblxuICBmdW5jdGlvbiBTaW1wbGVHZW9tZXRyeSgpIHtcbiAgICB2YXIgX3RoaXMgPSBfc3VwZXIuY2FsbCh0aGlzKSB8fCB0aGlzO1xuICAgIC8qKlxuICAgICAqIEBwcm90ZWN0ZWRcbiAgICAgKiBAdHlwZSB7aW1wb3J0KFwiLi9HZW9tZXRyeUxheW91dC5qc1wiKS5kZWZhdWx0fVxuICAgICAqL1xuXG5cbiAgICBfdGhpcy5sYXlvdXQgPSBHZW9tZXRyeUxheW91dC5YWTtcbiAgICAvKipcbiAgICAgKiBAcHJvdGVjdGVkXG4gICAgICogQHR5cGUge251bWJlcn1cbiAgICAgKi9cblxuICAgIF90aGlzLnN0cmlkZSA9IDI7XG4gICAgLyoqXG4gICAgICogQHByb3RlY3RlZFxuICAgICAqIEB0eXBlIHtBcnJheTxudW1iZXI+fVxuICAgICAqL1xuXG4gICAgX3RoaXMuZmxhdENvb3JkaW5hdGVzID0gbnVsbDtcbiAgICByZXR1cm4gX3RoaXM7XG4gIH1cbiAgLyoqXG4gICAqIEBwYXJhbSB7aW1wb3J0KFwiLi4vZXh0ZW50LmpzXCIpLkV4dGVudH0gZXh0ZW50IEV4dGVudC5cbiAgICogQHByb3RlY3RlZFxuICAgKiBAcmV0dXJuIHtpbXBvcnQoXCIuLi9leHRlbnQuanNcIikuRXh0ZW50fSBleHRlbnQgRXh0ZW50LlxuICAgKi9cblxuXG4gIFNpbXBsZUdlb21ldHJ5LnByb3RvdHlwZS5jb21wdXRlRXh0ZW50ID0gZnVuY3Rpb24gKGV4dGVudCkge1xuICAgIHJldHVybiBjcmVhdGVPclVwZGF0ZUZyb21GbGF0Q29vcmRpbmF0ZXModGhpcy5mbGF0Q29vcmRpbmF0ZXMsIDAsIHRoaXMuZmxhdENvb3JkaW5hdGVzLmxlbmd0aCwgdGhpcy5zdHJpZGUsIGV4dGVudCk7XG4gIH07XG4gIC8qKlxuICAgKiBAYWJzdHJhY3RcbiAgICogQHJldHVybiB7QXJyYXk8Kj59IENvb3JkaW5hdGVzLlxuICAgKi9cblxuXG4gIFNpbXBsZUdlb21ldHJ5LnByb3RvdHlwZS5nZXRDb29yZGluYXRlcyA9IGZ1bmN0aW9uICgpIHtcbiAgICByZXR1cm4gYWJzdHJhY3QoKTtcbiAgfTtcbiAgLyoqXG4gICAqIFJldHVybiB0aGUgZmlyc3QgY29vcmRpbmF0ZSBvZiB0aGUgZ2VvbWV0cnkuXG4gICAqIEByZXR1cm4ge2ltcG9ydChcIi4uL2Nvb3JkaW5hdGUuanNcIikuQ29vcmRpbmF0ZX0gRmlyc3QgY29vcmRpbmF0ZS5cbiAgICogQGFwaVxuICAgKi9cblxuXG4gIFNpbXBsZUdlb21ldHJ5LnByb3RvdHlwZS5nZXRGaXJzdENvb3JkaW5hdGUgPSBmdW5jdGlvbiAoKSB7XG4gICAgcmV0dXJuIHRoaXMuZmxhdENvb3JkaW5hdGVzLnNsaWNlKDAsIHRoaXMuc3RyaWRlKTtcbiAgfTtcbiAgLyoqXG4gICAqIEByZXR1cm4ge0FycmF5PG51bWJlcj59IEZsYXQgY29vcmRpbmF0ZXMuXG4gICAqL1xuXG5cbiAgU2ltcGxlR2VvbWV0cnkucHJvdG90eXBlLmdldEZsYXRDb29yZGluYXRlcyA9IGZ1bmN0aW9uICgpIHtcbiAgICByZXR1cm4gdGhpcy5mbGF0Q29vcmRpbmF0ZXM7XG4gIH07XG4gIC8qKlxuICAgKiBSZXR1cm4gdGhlIGxhc3QgY29vcmRpbmF0ZSBvZiB0aGUgZ2VvbWV0cnkuXG4gICAqIEByZXR1cm4ge2ltcG9ydChcIi4uL2Nvb3JkaW5hdGUuanNcIikuQ29vcmRpbmF0ZX0gTGFzdCBwb2ludC5cbiAgICogQGFwaVxuICAgKi9cblxuXG4gIFNpbXBsZUdlb21ldHJ5LnByb3RvdHlwZS5nZXRMYXN0Q29vcmRpbmF0ZSA9IGZ1bmN0aW9uICgpIHtcbiAgICByZXR1cm4gdGhpcy5mbGF0Q29vcmRpbmF0ZXMuc2xpY2UodGhpcy5mbGF0Q29vcmRpbmF0ZXMubGVuZ3RoIC0gdGhpcy5zdHJpZGUpO1xuICB9O1xuICAvKipcbiAgICogUmV0dXJuIHRoZSB7QGxpbmsgbW9kdWxlOm9sL2dlb20vR2VvbWV0cnlMYXlvdXQgbGF5b3V0fSBvZiB0aGUgZ2VvbWV0cnkuXG4gICAqIEByZXR1cm4ge2ltcG9ydChcIi4vR2VvbWV0cnlMYXlvdXQuanNcIikuZGVmYXVsdH0gTGF5b3V0LlxuICAgKiBAYXBpXG4gICAqL1xuXG5cbiAgU2ltcGxlR2VvbWV0cnkucHJvdG90eXBlLmdldExheW91dCA9IGZ1bmN0aW9uICgpIHtcbiAgICByZXR1cm4gdGhpcy5sYXlvdXQ7XG4gIH07XG4gIC8qKlxuICAgKiBDcmVhdGUgYSBzaW1wbGlmaWVkIHZlcnNpb24gb2YgdGhpcyBnZW9tZXRyeSB1c2luZyB0aGUgRG91Z2xhcyBQZXVja2VyIGFsZ29yaXRobS5cbiAgICogQHBhcmFtIHtudW1iZXJ9IHNxdWFyZWRUb2xlcmFuY2UgU3F1YXJlZCB0b2xlcmFuY2UuXG4gICAqIEByZXR1cm4ge1NpbXBsZUdlb21ldHJ5fSBTaW1wbGlmaWVkIGdlb21ldHJ5LlxuICAgKi9cblxuXG4gIFNpbXBsZUdlb21ldHJ5LnByb3RvdHlwZS5nZXRTaW1wbGlmaWVkR2VvbWV0cnkgPSBmdW5jdGlvbiAoc3F1YXJlZFRvbGVyYW5jZSkge1xuICAgIGlmICh0aGlzLnNpbXBsaWZpZWRHZW9tZXRyeVJldmlzaW9uICE9PSB0aGlzLmdldFJldmlzaW9uKCkpIHtcbiAgICAgIHRoaXMuc2ltcGxpZmllZEdlb21ldHJ5TWF4TWluU3F1YXJlZFRvbGVyYW5jZSA9IDA7XG4gICAgICB0aGlzLnNpbXBsaWZpZWRHZW9tZXRyeVJldmlzaW9uID0gdGhpcy5nZXRSZXZpc2lvbigpO1xuICAgIH0gLy8gSWYgc3F1YXJlZFRvbGVyYW5jZSBpcyBuZWdhdGl2ZSBvciBpZiB3ZSBrbm93IHRoYXQgc2ltcGxpZmljYXRpb24gd2lsbCBub3RcbiAgICAvLyBoYXZlIGFueSBlZmZlY3QgdGhlbiBqdXN0IHJldHVybiB0aGlzLlxuXG5cbiAgICBpZiAoc3F1YXJlZFRvbGVyYW5jZSA8IDAgfHwgdGhpcy5zaW1wbGlmaWVkR2VvbWV0cnlNYXhNaW5TcXVhcmVkVG9sZXJhbmNlICE9PSAwICYmIHNxdWFyZWRUb2xlcmFuY2UgPD0gdGhpcy5zaW1wbGlmaWVkR2VvbWV0cnlNYXhNaW5TcXVhcmVkVG9sZXJhbmNlKSB7XG4gICAgICByZXR1cm4gdGhpcztcbiAgICB9XG5cbiAgICB2YXIgc2ltcGxpZmllZEdlb21ldHJ5ID0gdGhpcy5nZXRTaW1wbGlmaWVkR2VvbWV0cnlJbnRlcm5hbChzcXVhcmVkVG9sZXJhbmNlKTtcbiAgICB2YXIgc2ltcGxpZmllZEZsYXRDb29yZGluYXRlcyA9IHNpbXBsaWZpZWRHZW9tZXRyeS5nZXRGbGF0Q29vcmRpbmF0ZXMoKTtcblxuICAgIGlmIChzaW1wbGlmaWVkRmxhdENvb3JkaW5hdGVzLmxlbmd0aCA8IHRoaXMuZmxhdENvb3JkaW5hdGVzLmxlbmd0aCkge1xuICAgICAgcmV0dXJuIHNpbXBsaWZpZWRHZW9tZXRyeTtcbiAgICB9IGVsc2Uge1xuICAgICAgLy8gU2ltcGxpZmljYXRpb24gZGlkIG5vdCBhY3R1YWxseSByZW1vdmUgYW55IGNvb3JkaW5hdGVzLiAgV2Ugbm93IGtub3dcbiAgICAgIC8vIHRoYXQgYW55IGNhbGxzIHRvIGdldFNpbXBsaWZpZWRHZW9tZXRyeSB3aXRoIGEgc3F1YXJlZFRvbGVyYW5jZSBsZXNzXG4gICAgICAvLyB0aGFuIG9yIGVxdWFsIHRvIHRoZSBjdXJyZW50IHNxdWFyZWRUb2xlcmFuY2Ugd2lsbCBhbHNvIG5vdCBoYXZlIGFueVxuICAgICAgLy8gZWZmZWN0LiAgVGhpcyBhbGxvd3MgdXMgdG8gc2hvcnQgY2lyY3VpdCBzaW1wbGlmaWNhdGlvbiAoc2F2aW5nIENQVVxuICAgICAgLy8gY3ljbGVzKSBhbmQgcHJldmVudHMgdGhlIGNhY2hlIG9mIHNpbXBsaWZpZWQgZ2VvbWV0cmllcyBmcm9tIGZpbGxpbmdcbiAgICAgIC8vIHVwIHdpdGggdXNlbGVzcyBpZGVudGljYWwgY29waWVzIG9mIHRoaXMgZ2VvbWV0cnkgKHNhdmluZyBtZW1vcnkpLlxuICAgICAgdGhpcy5zaW1wbGlmaWVkR2VvbWV0cnlNYXhNaW5TcXVhcmVkVG9sZXJhbmNlID0gc3F1YXJlZFRvbGVyYW5jZTtcbiAgICAgIHJldHVybiB0aGlzO1xuICAgIH1cbiAgfTtcbiAgLyoqXG4gICAqIEBwYXJhbSB7bnVtYmVyfSBzcXVhcmVkVG9sZXJhbmNlIFNxdWFyZWQgdG9sZXJhbmNlLlxuICAgKiBAcmV0dXJuIHtTaW1wbGVHZW9tZXRyeX0gU2ltcGxpZmllZCBnZW9tZXRyeS5cbiAgICogQHByb3RlY3RlZFxuICAgKi9cblxuXG4gIFNpbXBsZUdlb21ldHJ5LnByb3RvdHlwZS5nZXRTaW1wbGlmaWVkR2VvbWV0cnlJbnRlcm5hbCA9IGZ1bmN0aW9uIChzcXVhcmVkVG9sZXJhbmNlKSB7XG4gICAgcmV0dXJuIHRoaXM7XG4gIH07XG4gIC8qKlxuICAgKiBAcmV0dXJuIHtudW1iZXJ9IFN0cmlkZS5cbiAgICovXG5cblxuICBTaW1wbGVHZW9tZXRyeS5wcm90b3R5cGUuZ2V0U3RyaWRlID0gZnVuY3Rpb24gKCkge1xuICAgIHJldHVybiB0aGlzLnN0cmlkZTtcbiAgfTtcbiAgLyoqXG4gICAqIEBwYXJhbSB7aW1wb3J0KFwiLi9HZW9tZXRyeUxheW91dC5qc1wiKS5kZWZhdWx0fSBsYXlvdXQgTGF5b3V0LlxuICAgKiBAcGFyYW0ge0FycmF5PG51bWJlcj59IGZsYXRDb29yZGluYXRlcyBGbGF0IGNvb3JkaW5hdGVzLlxuICAgKi9cblxuXG4gIFNpbXBsZUdlb21ldHJ5LnByb3RvdHlwZS5zZXRGbGF0Q29vcmRpbmF0ZXMgPSBmdW5jdGlvbiAobGF5b3V0LCBmbGF0Q29vcmRpbmF0ZXMpIHtcbiAgICB0aGlzLnN0cmlkZSA9IGdldFN0cmlkZUZvckxheW91dChsYXlvdXQpO1xuICAgIHRoaXMubGF5b3V0ID0gbGF5b3V0O1xuICAgIHRoaXMuZmxhdENvb3JkaW5hdGVzID0gZmxhdENvb3JkaW5hdGVzO1xuICB9O1xuICAvKipcbiAgICogQGFic3RyYWN0XG4gICAqIEBwYXJhbSB7IUFycmF5PCo+fSBjb29yZGluYXRlcyBDb29yZGluYXRlcy5cbiAgICogQHBhcmFtIHtpbXBvcnQoXCIuL0dlb21ldHJ5TGF5b3V0LmpzXCIpLmRlZmF1bHQ9fSBvcHRfbGF5b3V0IExheW91dC5cbiAgICovXG5cblxuICBTaW1wbGVHZW9tZXRyeS5wcm90b3R5cGUuc2V0Q29vcmRpbmF0ZXMgPSBmdW5jdGlvbiAoY29vcmRpbmF0ZXMsIG9wdF9sYXlvdXQpIHtcbiAgICBhYnN0cmFjdCgpO1xuICB9O1xuICAvKipcbiAgICogQHBhcmFtIHtpbXBvcnQoXCIuL0dlb21ldHJ5TGF5b3V0LmpzXCIpLmRlZmF1bHR8dW5kZWZpbmVkfSBsYXlvdXQgTGF5b3V0LlxuICAgKiBAcGFyYW0ge0FycmF5PCo+fSBjb29yZGluYXRlcyBDb29yZGluYXRlcy5cbiAgICogQHBhcmFtIHtudW1iZXJ9IG5lc3RpbmcgTmVzdGluZy5cbiAgICogQHByb3RlY3RlZFxuICAgKi9cblxuXG4gIFNpbXBsZUdlb21ldHJ5LnByb3RvdHlwZS5zZXRMYXlvdXQgPSBmdW5jdGlvbiAobGF5b3V0LCBjb29yZGluYXRlcywgbmVzdGluZykge1xuICAgIC8qKiBAdHlwZSB7bnVtYmVyfSAqL1xuICAgIHZhciBzdHJpZGU7XG5cbiAgICBpZiAobGF5b3V0KSB7XG4gICAgICBzdHJpZGUgPSBnZXRTdHJpZGVGb3JMYXlvdXQobGF5b3V0KTtcbiAgICB9IGVsc2Uge1xuICAgICAgZm9yICh2YXIgaSA9IDA7IGkgPCBuZXN0aW5nOyArK2kpIHtcbiAgICAgICAgaWYgKGNvb3JkaW5hdGVzLmxlbmd0aCA9PT0gMCkge1xuICAgICAgICAgIHRoaXMubGF5b3V0ID0gR2VvbWV0cnlMYXlvdXQuWFk7XG4gICAgICAgICAgdGhpcy5zdHJpZGUgPSAyO1xuICAgICAgICAgIHJldHVybjtcbiAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICBjb29yZGluYXRlcyA9XG4gICAgICAgICAgLyoqIEB0eXBlIHtBcnJheX0gKi9cbiAgICAgICAgICBjb29yZGluYXRlc1swXTtcbiAgICAgICAgfVxuICAgICAgfVxuXG4gICAgICBzdHJpZGUgPSBjb29yZGluYXRlcy5sZW5ndGg7XG4gICAgICBsYXlvdXQgPSBnZXRMYXlvdXRGb3JTdHJpZGUoc3RyaWRlKTtcbiAgICB9XG5cbiAgICB0aGlzLmxheW91dCA9IGxheW91dDtcbiAgICB0aGlzLnN0cmlkZSA9IHN0cmlkZTtcbiAgfTtcbiAgLyoqXG4gICAqIEFwcGx5IGEgdHJhbnNmb3JtIGZ1bmN0aW9uIHRvIHRoZSBjb29yZGluYXRlcyBvZiB0aGUgZ2VvbWV0cnkuXG4gICAqIFRoZSBnZW9tZXRyeSBpcyBtb2RpZmllZCBpbiBwbGFjZS5cbiAgICogSWYgeW91IGRvIG5vdCB3YW50IHRoZSBnZW9tZXRyeSBtb2RpZmllZCBpbiBwbGFjZSwgZmlyc3QgYGNsb25lKClgIGl0IGFuZFxuICAgKiB0aGVuIHVzZSB0aGlzIGZ1bmN0aW9uIG9uIHRoZSBjbG9uZS5cbiAgICogQHBhcmFtIHtpbXBvcnQoXCIuLi9wcm9qLmpzXCIpLlRyYW5zZm9ybUZ1bmN0aW9ufSB0cmFuc2Zvcm1GbiBUcmFuc2Zvcm0gZnVuY3Rpb24uXG4gICAqIENhbGxlZCB3aXRoIGEgZmxhdCBhcnJheSBvZiBnZW9tZXRyeSBjb29yZGluYXRlcy5cbiAgICogQGFwaVxuICAgKi9cblxuXG4gIFNpbXBsZUdlb21ldHJ5LnByb3RvdHlwZS5hcHBseVRyYW5zZm9ybSA9IGZ1bmN0aW9uICh0cmFuc2Zvcm1Gbikge1xuICAgIGlmICh0aGlzLmZsYXRDb29yZGluYXRlcykge1xuICAgICAgdHJhbnNmb3JtRm4odGhpcy5mbGF0Q29vcmRpbmF0ZXMsIHRoaXMuZmxhdENvb3JkaW5hdGVzLCB0aGlzLnN0cmlkZSk7XG4gICAgICB0aGlzLmNoYW5nZWQoKTtcbiAgICB9XG4gIH07XG4gIC8qKlxuICAgKiBSb3RhdGUgdGhlIGdlb21ldHJ5IGFyb3VuZCBhIGdpdmVuIGNvb3JkaW5hdGUuIFRoaXMgbW9kaWZpZXMgdGhlIGdlb21ldHJ5XG4gICAqIGNvb3JkaW5hdGVzIGluIHBsYWNlLlxuICAgKiBAcGFyYW0ge251bWJlcn0gYW5nbGUgUm90YXRpb24gYW5nbGUgaW4gY291bnRlci1jbG9ja3dpc2UgcmFkaWFucy5cbiAgICogQHBhcmFtIHtpbXBvcnQoXCIuLi9jb29yZGluYXRlLmpzXCIpLkNvb3JkaW5hdGV9IGFuY2hvciBUaGUgcm90YXRpb24gY2VudGVyLlxuICAgKiBAYXBpXG4gICAqL1xuXG5cbiAgU2ltcGxlR2VvbWV0cnkucHJvdG90eXBlLnJvdGF0ZSA9IGZ1bmN0aW9uIChhbmdsZSwgYW5jaG9yKSB7XG4gICAgdmFyIGZsYXRDb29yZGluYXRlcyA9IHRoaXMuZ2V0RmxhdENvb3JkaW5hdGVzKCk7XG5cbiAgICBpZiAoZmxhdENvb3JkaW5hdGVzKSB7XG4gICAgICB2YXIgc3RyaWRlID0gdGhpcy5nZXRTdHJpZGUoKTtcbiAgICAgIHJvdGF0ZShmbGF0Q29vcmRpbmF0ZXMsIDAsIGZsYXRDb29yZGluYXRlcy5sZW5ndGgsIHN0cmlkZSwgYW5nbGUsIGFuY2hvciwgZmxhdENvb3JkaW5hdGVzKTtcbiAgICAgIHRoaXMuY2hhbmdlZCgpO1xuICAgIH1cbiAgfTtcbiAgLyoqXG4gICAqIFNjYWxlIHRoZSBnZW9tZXRyeSAod2l0aCBhbiBvcHRpb25hbCBvcmlnaW4pLiAgVGhpcyBtb2RpZmllcyB0aGUgZ2VvbWV0cnlcbiAgICogY29vcmRpbmF0ZXMgaW4gcGxhY2UuXG4gICAqIEBwYXJhbSB7bnVtYmVyfSBzeCBUaGUgc2NhbGluZyBmYWN0b3IgaW4gdGhlIHgtZGlyZWN0aW9uLlxuICAgKiBAcGFyYW0ge251bWJlcj19IG9wdF9zeSBUaGUgc2NhbGluZyBmYWN0b3IgaW4gdGhlIHktZGlyZWN0aW9uIChkZWZhdWx0cyB0byBzeCkuXG4gICAqIEBwYXJhbSB7aW1wb3J0KFwiLi4vY29vcmRpbmF0ZS5qc1wiKS5Db29yZGluYXRlPX0gb3B0X2FuY2hvciBUaGUgc2NhbGUgb3JpZ2luIChkZWZhdWx0cyB0byB0aGUgY2VudGVyXG4gICAqICAgICBvZiB0aGUgZ2VvbWV0cnkgZXh0ZW50KS5cbiAgICogQGFwaVxuICAgKi9cblxuXG4gIFNpbXBsZUdlb21ldHJ5LnByb3RvdHlwZS5zY2FsZSA9IGZ1bmN0aW9uIChzeCwgb3B0X3N5LCBvcHRfYW5jaG9yKSB7XG4gICAgdmFyIHN5ID0gb3B0X3N5O1xuXG4gICAgaWYgKHN5ID09PSB1bmRlZmluZWQpIHtcbiAgICAgIHN5ID0gc3g7XG4gICAgfVxuXG4gICAgdmFyIGFuY2hvciA9IG9wdF9hbmNob3I7XG5cbiAgICBpZiAoIWFuY2hvcikge1xuICAgICAgYW5jaG9yID0gZ2V0Q2VudGVyKHRoaXMuZ2V0RXh0ZW50KCkpO1xuICAgIH1cblxuICAgIHZhciBmbGF0Q29vcmRpbmF0ZXMgPSB0aGlzLmdldEZsYXRDb29yZGluYXRlcygpO1xuXG4gICAgaWYgKGZsYXRDb29yZGluYXRlcykge1xuICAgICAgdmFyIHN0cmlkZSA9IHRoaXMuZ2V0U3RyaWRlKCk7XG4gICAgICBzY2FsZShmbGF0Q29vcmRpbmF0ZXMsIDAsIGZsYXRDb29yZGluYXRlcy5sZW5ndGgsIHN0cmlkZSwgc3gsIHN5LCBhbmNob3IsIGZsYXRDb29yZGluYXRlcyk7XG4gICAgICB0aGlzLmNoYW5nZWQoKTtcbiAgICB9XG4gIH07XG4gIC8qKlxuICAgKiBUcmFuc2xhdGUgdGhlIGdlb21ldHJ5LiAgVGhpcyBtb2RpZmllcyB0aGUgZ2VvbWV0cnkgY29vcmRpbmF0ZXMgaW4gcGxhY2UuICBJZlxuICAgKiBpbnN0ZWFkIHlvdSB3YW50IGEgbmV3IGdlb21ldHJ5LCBmaXJzdCBgY2xvbmUoKWAgdGhpcyBnZW9tZXRyeS5cbiAgICogQHBhcmFtIHtudW1iZXJ9IGRlbHRhWCBEZWx0YSBYLlxuICAgKiBAcGFyYW0ge251bWJlcn0gZGVsdGFZIERlbHRhIFkuXG4gICAqIEBhcGlcbiAgICovXG5cblxuICBTaW1wbGVHZW9tZXRyeS5wcm90b3R5cGUudHJhbnNsYXRlID0gZnVuY3Rpb24gKGRlbHRhWCwgZGVsdGFZKSB7XG4gICAgdmFyIGZsYXRDb29yZGluYXRlcyA9IHRoaXMuZ2V0RmxhdENvb3JkaW5hdGVzKCk7XG5cbiAgICBpZiAoZmxhdENvb3JkaW5hdGVzKSB7XG4gICAgICB2YXIgc3RyaWRlID0gdGhpcy5nZXRTdHJpZGUoKTtcbiAgICAgIHRyYW5zbGF0ZShmbGF0Q29vcmRpbmF0ZXMsIDAsIGZsYXRDb29yZGluYXRlcy5sZW5ndGgsIHN0cmlkZSwgZGVsdGFYLCBkZWx0YVksIGZsYXRDb29yZGluYXRlcyk7XG4gICAgICB0aGlzLmNoYW5nZWQoKTtcbiAgICB9XG4gIH07XG5cbiAgcmV0dXJuIFNpbXBsZUdlb21ldHJ5O1xufShHZW9tZXRyeSk7XG4vKipcbiAqIEBwYXJhbSB7bnVtYmVyfSBzdHJpZGUgU3RyaWRlLlxuICogQHJldHVybiB7aW1wb3J0KFwiLi9HZW9tZXRyeUxheW91dC5qc1wiKS5kZWZhdWx0fSBsYXlvdXQgTGF5b3V0LlxuICovXG5cblxuZnVuY3Rpb24gZ2V0TGF5b3V0Rm9yU3RyaWRlKHN0cmlkZSkge1xuICB2YXIgbGF5b3V0O1xuXG4gIGlmIChzdHJpZGUgPT0gMikge1xuICAgIGxheW91dCA9IEdlb21ldHJ5TGF5b3V0LlhZO1xuICB9IGVsc2UgaWYgKHN0cmlkZSA9PSAzKSB7XG4gICAgbGF5b3V0ID0gR2VvbWV0cnlMYXlvdXQuWFlaO1xuICB9IGVsc2UgaWYgKHN0cmlkZSA9PSA0KSB7XG4gICAgbGF5b3V0ID0gR2VvbWV0cnlMYXlvdXQuWFlaTTtcbiAgfVxuXG4gIHJldHVybiAoXG4gICAgLyoqIEB0eXBlIHtpbXBvcnQoXCIuL0dlb21ldHJ5TGF5b3V0LmpzXCIpLmRlZmF1bHR9ICovXG4gICAgbGF5b3V0XG4gICk7XG59XG4vKipcbiAqIEBwYXJhbSB7aW1wb3J0KFwiLi9HZW9tZXRyeUxheW91dC5qc1wiKS5kZWZhdWx0fSBsYXlvdXQgTGF5b3V0LlxuICogQHJldHVybiB7bnVtYmVyfSBTdHJpZGUuXG4gKi9cblxuXG5leHBvcnQgZnVuY3Rpb24gZ2V0U3RyaWRlRm9yTGF5b3V0KGxheW91dCkge1xuICB2YXIgc3RyaWRlO1xuXG4gIGlmIChsYXlvdXQgPT0gR2VvbWV0cnlMYXlvdXQuWFkpIHtcbiAgICBzdHJpZGUgPSAyO1xuICB9IGVsc2UgaWYgKGxheW91dCA9PSBHZW9tZXRyeUxheW91dC5YWVogfHwgbGF5b3V0ID09IEdlb21ldHJ5TGF5b3V0LlhZTSkge1xuICAgIHN0cmlkZSA9IDM7XG4gIH0gZWxzZSBpZiAobGF5b3V0ID09IEdlb21ldHJ5TGF5b3V0LlhZWk0pIHtcbiAgICBzdHJpZGUgPSA0O1xuICB9XG5cbiAgcmV0dXJuIChcbiAgICAvKiogQHR5cGUge251bWJlcn0gKi9cbiAgICBzdHJpZGVcbiAgKTtcbn1cbi8qKlxuICogQHBhcmFtIHtTaW1wbGVHZW9tZXRyeX0gc2ltcGxlR2VvbWV0cnkgU2ltcGxlIGdlb21ldHJ5LlxuICogQHBhcmFtIHtpbXBvcnQoXCIuLi90cmFuc2Zvcm0uanNcIikuVHJhbnNmb3JtfSB0cmFuc2Zvcm0gVHJhbnNmb3JtLlxuICogQHBhcmFtIHtBcnJheTxudW1iZXI+PX0gb3B0X2Rlc3QgRGVzdGluYXRpb24uXG4gKiBAcmV0dXJuIHtBcnJheTxudW1iZXI+fSBUcmFuc2Zvcm1lZCBmbGF0IGNvb3JkaW5hdGVzLlxuICovXG5cbmV4cG9ydCBmdW5jdGlvbiB0cmFuc2Zvcm1HZW9tMkQoc2ltcGxlR2VvbWV0cnksIHRyYW5zZm9ybSwgb3B0X2Rlc3QpIHtcbiAgdmFyIGZsYXRDb29yZGluYXRlcyA9IHNpbXBsZUdlb21ldHJ5LmdldEZsYXRDb29yZGluYXRlcygpO1xuXG4gIGlmICghZmxhdENvb3JkaW5hdGVzKSB7XG4gICAgcmV0dXJuIG51bGw7XG4gIH0gZWxzZSB7XG4gICAgdmFyIHN0cmlkZSA9IHNpbXBsZUdlb21ldHJ5LmdldFN0cmlkZSgpO1xuICAgIHJldHVybiB0cmFuc2Zvcm0yRChmbGF0Q29vcmRpbmF0ZXMsIDAsIGZsYXRDb29yZGluYXRlcy5sZW5ndGgsIHN0cmlkZSwgdHJhbnNmb3JtLCBvcHRfZGVzdCk7XG4gIH1cbn1cbmV4cG9ydCBkZWZhdWx0IFNpbXBsZUdlb21ldHJ5OyIsIi8qKlxuICogQG1vZHVsZSBvbC9nZW9tL2ZsYXQvY2xvc2VzdFxuICovXG5pbXBvcnQgeyBsZXJwLCBzcXVhcmVkRGlzdGFuY2UgYXMgc3F1YXJlZER4IH0gZnJvbSAnLi4vLi4vbWF0aC5qcyc7XG4vKipcbiAqIFJldHVybnMgdGhlIHBvaW50IG9uIHRoZSAyRCBsaW5lIHNlZ21lbnQgZmxhdENvb3JkaW5hdGVzW29mZnNldDFdIHRvXG4gKiBmbGF0Q29vcmRpbmF0ZXNbb2Zmc2V0Ml0gdGhhdCBpcyBjbG9zZXN0IHRvIHRoZSBwb2ludCAoeCwgeSkuICBFeHRyYVxuICogZGltZW5zaW9ucyBhcmUgbGluZWFybHkgaW50ZXJwb2xhdGVkLlxuICogQHBhcmFtIHtBcnJheTxudW1iZXI+fSBmbGF0Q29vcmRpbmF0ZXMgRmxhdCBjb29yZGluYXRlcy5cbiAqIEBwYXJhbSB7bnVtYmVyfSBvZmZzZXQxIE9mZnNldCAxLlxuICogQHBhcmFtIHtudW1iZXJ9IG9mZnNldDIgT2Zmc2V0IDIuXG4gKiBAcGFyYW0ge251bWJlcn0gc3RyaWRlIFN0cmlkZS5cbiAqIEBwYXJhbSB7bnVtYmVyfSB4IFguXG4gKiBAcGFyYW0ge251bWJlcn0geSBZLlxuICogQHBhcmFtIHtBcnJheTxudW1iZXI+fSBjbG9zZXN0UG9pbnQgQ2xvc2VzdCBwb2ludC5cbiAqL1xuXG5mdW5jdGlvbiBhc3NpZ25DbG9zZXN0KGZsYXRDb29yZGluYXRlcywgb2Zmc2V0MSwgb2Zmc2V0Miwgc3RyaWRlLCB4LCB5LCBjbG9zZXN0UG9pbnQpIHtcbiAgdmFyIHgxID0gZmxhdENvb3JkaW5hdGVzW29mZnNldDFdO1xuICB2YXIgeTEgPSBmbGF0Q29vcmRpbmF0ZXNbb2Zmc2V0MSArIDFdO1xuICB2YXIgZHggPSBmbGF0Q29vcmRpbmF0ZXNbb2Zmc2V0Ml0gLSB4MTtcbiAgdmFyIGR5ID0gZmxhdENvb3JkaW5hdGVzW29mZnNldDIgKyAxXSAtIHkxO1xuICB2YXIgb2Zmc2V0O1xuXG4gIGlmIChkeCA9PT0gMCAmJiBkeSA9PT0gMCkge1xuICAgIG9mZnNldCA9IG9mZnNldDE7XG4gIH0gZWxzZSB7XG4gICAgdmFyIHQgPSAoKHggLSB4MSkgKiBkeCArICh5IC0geTEpICogZHkpIC8gKGR4ICogZHggKyBkeSAqIGR5KTtcblxuICAgIGlmICh0ID4gMSkge1xuICAgICAgb2Zmc2V0ID0gb2Zmc2V0MjtcbiAgICB9IGVsc2UgaWYgKHQgPiAwKSB7XG4gICAgICBmb3IgKHZhciBpID0gMDsgaSA8IHN0cmlkZTsgKytpKSB7XG4gICAgICAgIGNsb3Nlc3RQb2ludFtpXSA9IGxlcnAoZmxhdENvb3JkaW5hdGVzW29mZnNldDEgKyBpXSwgZmxhdENvb3JkaW5hdGVzW29mZnNldDIgKyBpXSwgdCk7XG4gICAgICB9XG5cbiAgICAgIGNsb3Nlc3RQb2ludC5sZW5ndGggPSBzdHJpZGU7XG4gICAgICByZXR1cm47XG4gICAgfSBlbHNlIHtcbiAgICAgIG9mZnNldCA9IG9mZnNldDE7XG4gICAgfVxuICB9XG5cbiAgZm9yICh2YXIgaSA9IDA7IGkgPCBzdHJpZGU7ICsraSkge1xuICAgIGNsb3Nlc3RQb2ludFtpXSA9IGZsYXRDb29yZGluYXRlc1tvZmZzZXQgKyBpXTtcbiAgfVxuXG4gIGNsb3Nlc3RQb2ludC5sZW5ndGggPSBzdHJpZGU7XG59XG4vKipcbiAqIFJldHVybiB0aGUgc3F1YXJlZCBvZiB0aGUgbGFyZ2VzdCBkaXN0YW5jZSBiZXR3ZWVuIGFueSBwYWlyIG9mIGNvbnNlY3V0aXZlXG4gKiBjb29yZGluYXRlcy5cbiAqIEBwYXJhbSB7QXJyYXk8bnVtYmVyPn0gZmxhdENvb3JkaW5hdGVzIEZsYXQgY29vcmRpbmF0ZXMuXG4gKiBAcGFyYW0ge251bWJlcn0gb2Zmc2V0IE9mZnNldC5cbiAqIEBwYXJhbSB7bnVtYmVyfSBlbmQgRW5kLlxuICogQHBhcmFtIHtudW1iZXJ9IHN0cmlkZSBTdHJpZGUuXG4gKiBAcGFyYW0ge251bWJlcn0gbWF4IE1heCBzcXVhcmVkIGRlbHRhLlxuICogQHJldHVybiB7bnVtYmVyfSBNYXggc3F1YXJlZCBkZWx0YS5cbiAqL1xuXG5cbmV4cG9ydCBmdW5jdGlvbiBtYXhTcXVhcmVkRGVsdGEoZmxhdENvb3JkaW5hdGVzLCBvZmZzZXQsIGVuZCwgc3RyaWRlLCBtYXgpIHtcbiAgdmFyIHgxID0gZmxhdENvb3JkaW5hdGVzW29mZnNldF07XG4gIHZhciB5MSA9IGZsYXRDb29yZGluYXRlc1tvZmZzZXQgKyAxXTtcblxuICBmb3IgKG9mZnNldCArPSBzdHJpZGU7IG9mZnNldCA8IGVuZDsgb2Zmc2V0ICs9IHN0cmlkZSkge1xuICAgIHZhciB4MiA9IGZsYXRDb29yZGluYXRlc1tvZmZzZXRdO1xuICAgIHZhciB5MiA9IGZsYXRDb29yZGluYXRlc1tvZmZzZXQgKyAxXTtcbiAgICB2YXIgc3F1YXJlZERlbHRhID0gc3F1YXJlZER4KHgxLCB5MSwgeDIsIHkyKTtcblxuICAgIGlmIChzcXVhcmVkRGVsdGEgPiBtYXgpIHtcbiAgICAgIG1heCA9IHNxdWFyZWREZWx0YTtcbiAgICB9XG5cbiAgICB4MSA9IHgyO1xuICAgIHkxID0geTI7XG4gIH1cblxuICByZXR1cm4gbWF4O1xufVxuLyoqXG4gKiBAcGFyYW0ge0FycmF5PG51bWJlcj59IGZsYXRDb29yZGluYXRlcyBGbGF0IGNvb3JkaW5hdGVzLlxuICogQHBhcmFtIHtudW1iZXJ9IG9mZnNldCBPZmZzZXQuXG4gKiBAcGFyYW0ge0FycmF5PG51bWJlcj59IGVuZHMgRW5kcy5cbiAqIEBwYXJhbSB7bnVtYmVyfSBzdHJpZGUgU3RyaWRlLlxuICogQHBhcmFtIHtudW1iZXJ9IG1heCBNYXggc3F1YXJlZCBkZWx0YS5cbiAqIEByZXR1cm4ge251bWJlcn0gTWF4IHNxdWFyZWQgZGVsdGEuXG4gKi9cblxuZXhwb3J0IGZ1bmN0aW9uIGFycmF5TWF4U3F1YXJlZERlbHRhKGZsYXRDb29yZGluYXRlcywgb2Zmc2V0LCBlbmRzLCBzdHJpZGUsIG1heCkge1xuICBmb3IgKHZhciBpID0gMCwgaWkgPSBlbmRzLmxlbmd0aDsgaSA8IGlpOyArK2kpIHtcbiAgICB2YXIgZW5kID0gZW5kc1tpXTtcbiAgICBtYXggPSBtYXhTcXVhcmVkRGVsdGEoZmxhdENvb3JkaW5hdGVzLCBvZmZzZXQsIGVuZCwgc3RyaWRlLCBtYXgpO1xuICAgIG9mZnNldCA9IGVuZDtcbiAgfVxuXG4gIHJldHVybiBtYXg7XG59XG4vKipcbiAqIEBwYXJhbSB7QXJyYXk8bnVtYmVyPn0gZmxhdENvb3JkaW5hdGVzIEZsYXQgY29vcmRpbmF0ZXMuXG4gKiBAcGFyYW0ge251bWJlcn0gb2Zmc2V0IE9mZnNldC5cbiAqIEBwYXJhbSB7QXJyYXk8QXJyYXk8bnVtYmVyPj59IGVuZHNzIEVuZHNzLlxuICogQHBhcmFtIHtudW1iZXJ9IHN0cmlkZSBTdHJpZGUuXG4gKiBAcGFyYW0ge251bWJlcn0gbWF4IE1heCBzcXVhcmVkIGRlbHRhLlxuICogQHJldHVybiB7bnVtYmVyfSBNYXggc3F1YXJlZCBkZWx0YS5cbiAqL1xuXG5leHBvcnQgZnVuY3Rpb24gbXVsdGlBcnJheU1heFNxdWFyZWREZWx0YShmbGF0Q29vcmRpbmF0ZXMsIG9mZnNldCwgZW5kc3MsIHN0cmlkZSwgbWF4KSB7XG4gIGZvciAodmFyIGkgPSAwLCBpaSA9IGVuZHNzLmxlbmd0aDsgaSA8IGlpOyArK2kpIHtcbiAgICB2YXIgZW5kcyA9IGVuZHNzW2ldO1xuICAgIG1heCA9IGFycmF5TWF4U3F1YXJlZERlbHRhKGZsYXRDb29yZGluYXRlcywgb2Zmc2V0LCBlbmRzLCBzdHJpZGUsIG1heCk7XG4gICAgb2Zmc2V0ID0gZW5kc1tlbmRzLmxlbmd0aCAtIDFdO1xuICB9XG5cbiAgcmV0dXJuIG1heDtcbn1cbi8qKlxuICogQHBhcmFtIHtBcnJheTxudW1iZXI+fSBmbGF0Q29vcmRpbmF0ZXMgRmxhdCBjb29yZGluYXRlcy5cbiAqIEBwYXJhbSB7bnVtYmVyfSBvZmZzZXQgT2Zmc2V0LlxuICogQHBhcmFtIHtudW1iZXJ9IGVuZCBFbmQuXG4gKiBAcGFyYW0ge251bWJlcn0gc3RyaWRlIFN0cmlkZS5cbiAqIEBwYXJhbSB7bnVtYmVyfSBtYXhEZWx0YSBNYXggZGVsdGEuXG4gKiBAcGFyYW0ge2Jvb2xlYW59IGlzUmluZyBJcyByaW5nLlxuICogQHBhcmFtIHtudW1iZXJ9IHggWC5cbiAqIEBwYXJhbSB7bnVtYmVyfSB5IFkuXG4gKiBAcGFyYW0ge0FycmF5PG51bWJlcj59IGNsb3Nlc3RQb2ludCBDbG9zZXN0IHBvaW50LlxuICogQHBhcmFtIHtudW1iZXJ9IG1pblNxdWFyZWREaXN0YW5jZSBNaW5pbXVtIHNxdWFyZWQgZGlzdGFuY2UuXG4gKiBAcGFyYW0ge0FycmF5PG51bWJlcj49fSBvcHRfdG1wUG9pbnQgVGVtcG9yYXJ5IHBvaW50IG9iamVjdC5cbiAqIEByZXR1cm4ge251bWJlcn0gTWluaW11bSBzcXVhcmVkIGRpc3RhbmNlLlxuICovXG5cbmV4cG9ydCBmdW5jdGlvbiBhc3NpZ25DbG9zZXN0UG9pbnQoZmxhdENvb3JkaW5hdGVzLCBvZmZzZXQsIGVuZCwgc3RyaWRlLCBtYXhEZWx0YSwgaXNSaW5nLCB4LCB5LCBjbG9zZXN0UG9pbnQsIG1pblNxdWFyZWREaXN0YW5jZSwgb3B0X3RtcFBvaW50KSB7XG4gIGlmIChvZmZzZXQgPT0gZW5kKSB7XG4gICAgcmV0dXJuIG1pblNxdWFyZWREaXN0YW5jZTtcbiAgfVxuXG4gIHZhciBpLCBzcXVhcmVkRGlzdGFuY2U7XG5cbiAgaWYgKG1heERlbHRhID09PSAwKSB7XG4gICAgLy8gQWxsIHBvaW50cyBhcmUgaWRlbnRpY2FsLCBzbyBqdXN0IHRlc3QgdGhlIGZpcnN0IHBvaW50LlxuICAgIHNxdWFyZWREaXN0YW5jZSA9IHNxdWFyZWREeCh4LCB5LCBmbGF0Q29vcmRpbmF0ZXNbb2Zmc2V0XSwgZmxhdENvb3JkaW5hdGVzW29mZnNldCArIDFdKTtcblxuICAgIGlmIChzcXVhcmVkRGlzdGFuY2UgPCBtaW5TcXVhcmVkRGlzdGFuY2UpIHtcbiAgICAgIGZvciAoaSA9IDA7IGkgPCBzdHJpZGU7ICsraSkge1xuICAgICAgICBjbG9zZXN0UG9pbnRbaV0gPSBmbGF0Q29vcmRpbmF0ZXNbb2Zmc2V0ICsgaV07XG4gICAgICB9XG5cbiAgICAgIGNsb3Nlc3RQb2ludC5sZW5ndGggPSBzdHJpZGU7XG4gICAgICByZXR1cm4gc3F1YXJlZERpc3RhbmNlO1xuICAgIH0gZWxzZSB7XG4gICAgICByZXR1cm4gbWluU3F1YXJlZERpc3RhbmNlO1xuICAgIH1cbiAgfVxuXG4gIHZhciB0bXBQb2ludCA9IG9wdF90bXBQb2ludCA/IG9wdF90bXBQb2ludCA6IFtOYU4sIE5hTl07XG4gIHZhciBpbmRleCA9IG9mZnNldCArIHN0cmlkZTtcblxuICB3aGlsZSAoaW5kZXggPCBlbmQpIHtcbiAgICBhc3NpZ25DbG9zZXN0KGZsYXRDb29yZGluYXRlcywgaW5kZXggLSBzdHJpZGUsIGluZGV4LCBzdHJpZGUsIHgsIHksIHRtcFBvaW50KTtcbiAgICBzcXVhcmVkRGlzdGFuY2UgPSBzcXVhcmVkRHgoeCwgeSwgdG1wUG9pbnRbMF0sIHRtcFBvaW50WzFdKTtcblxuICAgIGlmIChzcXVhcmVkRGlzdGFuY2UgPCBtaW5TcXVhcmVkRGlzdGFuY2UpIHtcbiAgICAgIG1pblNxdWFyZWREaXN0YW5jZSA9IHNxdWFyZWREaXN0YW5jZTtcblxuICAgICAgZm9yIChpID0gMDsgaSA8IHN0cmlkZTsgKytpKSB7XG4gICAgICAgIGNsb3Nlc3RQb2ludFtpXSA9IHRtcFBvaW50W2ldO1xuICAgICAgfVxuXG4gICAgICBjbG9zZXN0UG9pbnQubGVuZ3RoID0gc3RyaWRlO1xuICAgICAgaW5kZXggKz0gc3RyaWRlO1xuICAgIH0gZWxzZSB7XG4gICAgICAvLyBTa2lwIGFoZWFkIG11bHRpcGxlIHBvaW50cywgYmVjYXVzZSB3ZSBrbm93IHRoYXQgYWxsIHRoZSBza2lwcGVkXG4gICAgICAvLyBwb2ludHMgY2Fubm90IGJlIGFueSBjbG9zZXIgdGhhbiB0aGUgY2xvc2VzdCBwb2ludCB3ZSBoYXZlIGZvdW5kIHNvXG4gICAgICAvLyBmYXIuICBXZSBrbm93IHRoaXMgYmVjYXVzZSB3ZSBrbm93IGhvdyBjbG9zZSB0aGUgY3VycmVudCBwb2ludCBpcywgaG93XG4gICAgICAvLyBjbG9zZSB0aGUgY2xvc2VzdCBwb2ludCB3ZSBoYXZlIGZvdW5kIHNvIGZhciBpcywgYW5kIHRoZSBtYXhpbXVtXG4gICAgICAvLyBkaXN0YW5jZSBiZXR3ZWVuIGNvbnNlY3V0aXZlIHBvaW50cy4gIEZvciBleGFtcGxlLCBpZiB3ZSdyZSBjdXJyZW50bHlcbiAgICAgIC8vIGF0IGRpc3RhbmNlIDEwLCB0aGUgYmVzdCB3ZSd2ZSBmb3VuZCBzbyBmYXIgaXMgMywgYW5kIHRoYXQgdGhlIG1heGltdW1cbiAgICAgIC8vIGRpc3RhbmNlIGJldHdlZW4gY29uc2VjdXRpdmUgcG9pbnRzIGlzIDIsIHRoZW4gd2UnbGwgbmVlZCB0byBza2lwIGF0XG4gICAgICAvLyBsZWFzdCAoMTAgLSAzKSAvIDIgPT0gMyAocm91bmRlZCBkb3duKSBwb2ludHMgdG8gaGF2ZSBhbnkgY2hhbmNlIG9mXG4gICAgICAvLyBmaW5kaW5nIGEgY2xvc2VyIHBvaW50LiAgV2UgdXNlIE1hdGgubWF4KC4uLiwgMSkgdG8gZW5zdXJlIHRoYXQgd2VcbiAgICAgIC8vIGFsd2F5cyBhZHZhbmNlIGF0IGxlYXN0IG9uZSBwb2ludCwgdG8gYXZvaWQgYW4gaW5maW5pdGUgbG9vcC5cbiAgICAgIGluZGV4ICs9IHN0cmlkZSAqIE1hdGgubWF4KChNYXRoLnNxcnQoc3F1YXJlZERpc3RhbmNlKSAtIE1hdGguc3FydChtaW5TcXVhcmVkRGlzdGFuY2UpKSAvIG1heERlbHRhIHwgMCwgMSk7XG4gICAgfVxuICB9XG5cbiAgaWYgKGlzUmluZykge1xuICAgIC8vIENoZWNrIHRoZSBjbG9zaW5nIHNlZ21lbnQuXG4gICAgYXNzaWduQ2xvc2VzdChmbGF0Q29vcmRpbmF0ZXMsIGVuZCAtIHN0cmlkZSwgb2Zmc2V0LCBzdHJpZGUsIHgsIHksIHRtcFBvaW50KTtcbiAgICBzcXVhcmVkRGlzdGFuY2UgPSBzcXVhcmVkRHgoeCwgeSwgdG1wUG9pbnRbMF0sIHRtcFBvaW50WzFdKTtcblxuICAgIGlmIChzcXVhcmVkRGlzdGFuY2UgPCBtaW5TcXVhcmVkRGlzdGFuY2UpIHtcbiAgICAgIG1pblNxdWFyZWREaXN0YW5jZSA9IHNxdWFyZWREaXN0YW5jZTtcblxuICAgICAgZm9yIChpID0gMDsgaSA8IHN0cmlkZTsgKytpKSB7XG4gICAgICAgIGNsb3Nlc3RQb2ludFtpXSA9IHRtcFBvaW50W2ldO1xuICAgICAgfVxuXG4gICAgICBjbG9zZXN0UG9pbnQubGVuZ3RoID0gc3RyaWRlO1xuICAgIH1cbiAgfVxuXG4gIHJldHVybiBtaW5TcXVhcmVkRGlzdGFuY2U7XG59XG4vKipcbiAqIEBwYXJhbSB7QXJyYXk8bnVtYmVyPn0gZmxhdENvb3JkaW5hdGVzIEZsYXQgY29vcmRpbmF0ZXMuXG4gKiBAcGFyYW0ge251bWJlcn0gb2Zmc2V0IE9mZnNldC5cbiAqIEBwYXJhbSB7QXJyYXk8bnVtYmVyPn0gZW5kcyBFbmRzLlxuICogQHBhcmFtIHtudW1iZXJ9IHN0cmlkZSBTdHJpZGUuXG4gKiBAcGFyYW0ge251bWJlcn0gbWF4RGVsdGEgTWF4IGRlbHRhLlxuICogQHBhcmFtIHtib29sZWFufSBpc1JpbmcgSXMgcmluZy5cbiAqIEBwYXJhbSB7bnVtYmVyfSB4IFguXG4gKiBAcGFyYW0ge251bWJlcn0geSBZLlxuICogQHBhcmFtIHtBcnJheTxudW1iZXI+fSBjbG9zZXN0UG9pbnQgQ2xvc2VzdCBwb2ludC5cbiAqIEBwYXJhbSB7bnVtYmVyfSBtaW5TcXVhcmVkRGlzdGFuY2UgTWluaW11bSBzcXVhcmVkIGRpc3RhbmNlLlxuICogQHBhcmFtIHtBcnJheTxudW1iZXI+PX0gb3B0X3RtcFBvaW50IFRlbXBvcmFyeSBwb2ludCBvYmplY3QuXG4gKiBAcmV0dXJuIHtudW1iZXJ9IE1pbmltdW0gc3F1YXJlZCBkaXN0YW5jZS5cbiAqL1xuXG5leHBvcnQgZnVuY3Rpb24gYXNzaWduQ2xvc2VzdEFycmF5UG9pbnQoZmxhdENvb3JkaW5hdGVzLCBvZmZzZXQsIGVuZHMsIHN0cmlkZSwgbWF4RGVsdGEsIGlzUmluZywgeCwgeSwgY2xvc2VzdFBvaW50LCBtaW5TcXVhcmVkRGlzdGFuY2UsIG9wdF90bXBQb2ludCkge1xuICB2YXIgdG1wUG9pbnQgPSBvcHRfdG1wUG9pbnQgPyBvcHRfdG1wUG9pbnQgOiBbTmFOLCBOYU5dO1xuXG4gIGZvciAodmFyIGkgPSAwLCBpaSA9IGVuZHMubGVuZ3RoOyBpIDwgaWk7ICsraSkge1xuICAgIHZhciBlbmQgPSBlbmRzW2ldO1xuICAgIG1pblNxdWFyZWREaXN0YW5jZSA9IGFzc2lnbkNsb3Nlc3RQb2ludChmbGF0Q29vcmRpbmF0ZXMsIG9mZnNldCwgZW5kLCBzdHJpZGUsIG1heERlbHRhLCBpc1JpbmcsIHgsIHksIGNsb3Nlc3RQb2ludCwgbWluU3F1YXJlZERpc3RhbmNlLCB0bXBQb2ludCk7XG4gICAgb2Zmc2V0ID0gZW5kO1xuICB9XG5cbiAgcmV0dXJuIG1pblNxdWFyZWREaXN0YW5jZTtcbn1cbi8qKlxuICogQHBhcmFtIHtBcnJheTxudW1iZXI+fSBmbGF0Q29vcmRpbmF0ZXMgRmxhdCBjb29yZGluYXRlcy5cbiAqIEBwYXJhbSB7bnVtYmVyfSBvZmZzZXQgT2Zmc2V0LlxuICogQHBhcmFtIHtBcnJheTxBcnJheTxudW1iZXI+Pn0gZW5kc3MgRW5kc3MuXG4gKiBAcGFyYW0ge251bWJlcn0gc3RyaWRlIFN0cmlkZS5cbiAqIEBwYXJhbSB7bnVtYmVyfSBtYXhEZWx0YSBNYXggZGVsdGEuXG4gKiBAcGFyYW0ge2Jvb2xlYW59IGlzUmluZyBJcyByaW5nLlxuICogQHBhcmFtIHtudW1iZXJ9IHggWC5cbiAqIEBwYXJhbSB7bnVtYmVyfSB5IFkuXG4gKiBAcGFyYW0ge0FycmF5PG51bWJlcj59IGNsb3Nlc3RQb2ludCBDbG9zZXN0IHBvaW50LlxuICogQHBhcmFtIHtudW1iZXJ9IG1pblNxdWFyZWREaXN0YW5jZSBNaW5pbXVtIHNxdWFyZWQgZGlzdGFuY2UuXG4gKiBAcGFyYW0ge0FycmF5PG51bWJlcj49fSBvcHRfdG1wUG9pbnQgVGVtcG9yYXJ5IHBvaW50IG9iamVjdC5cbiAqIEByZXR1cm4ge251bWJlcn0gTWluaW11bSBzcXVhcmVkIGRpc3RhbmNlLlxuICovXG5cbmV4cG9ydCBmdW5jdGlvbiBhc3NpZ25DbG9zZXN0TXVsdGlBcnJheVBvaW50KGZsYXRDb29yZGluYXRlcywgb2Zmc2V0LCBlbmRzcywgc3RyaWRlLCBtYXhEZWx0YSwgaXNSaW5nLCB4LCB5LCBjbG9zZXN0UG9pbnQsIG1pblNxdWFyZWREaXN0YW5jZSwgb3B0X3RtcFBvaW50KSB7XG4gIHZhciB0bXBQb2ludCA9IG9wdF90bXBQb2ludCA/IG9wdF90bXBQb2ludCA6IFtOYU4sIE5hTl07XG5cbiAgZm9yICh2YXIgaSA9IDAsIGlpID0gZW5kc3MubGVuZ3RoOyBpIDwgaWk7ICsraSkge1xuICAgIHZhciBlbmRzID0gZW5kc3NbaV07XG4gICAgbWluU3F1YXJlZERpc3RhbmNlID0gYXNzaWduQ2xvc2VzdEFycmF5UG9pbnQoZmxhdENvb3JkaW5hdGVzLCBvZmZzZXQsIGVuZHMsIHN0cmlkZSwgbWF4RGVsdGEsIGlzUmluZywgeCwgeSwgY2xvc2VzdFBvaW50LCBtaW5TcXVhcmVkRGlzdGFuY2UsIHRtcFBvaW50KTtcbiAgICBvZmZzZXQgPSBlbmRzW2VuZHMubGVuZ3RoIC0gMV07XG4gIH1cblxuICByZXR1cm4gbWluU3F1YXJlZERpc3RhbmNlO1xufSIsIi8qKlxuICogQG1vZHVsZSBvbC9nZW9tL2ZsYXQvZGVmbGF0ZVxuICovXG5cbi8qKlxuICogQHBhcmFtIHtBcnJheTxudW1iZXI+fSBmbGF0Q29vcmRpbmF0ZXMgRmxhdCBjb29yZGluYXRlcy5cbiAqIEBwYXJhbSB7bnVtYmVyfSBvZmZzZXQgT2Zmc2V0LlxuICogQHBhcmFtIHtpbXBvcnQoXCIuLi8uLi9jb29yZGluYXRlLmpzXCIpLkNvb3JkaW5hdGV9IGNvb3JkaW5hdGUgQ29vcmRpbmF0ZS5cbiAqIEBwYXJhbSB7bnVtYmVyfSBzdHJpZGUgU3RyaWRlLlxuICogQHJldHVybiB7bnVtYmVyfSBvZmZzZXQgT2Zmc2V0LlxuICovXG5leHBvcnQgZnVuY3Rpb24gZGVmbGF0ZUNvb3JkaW5hdGUoZmxhdENvb3JkaW5hdGVzLCBvZmZzZXQsIGNvb3JkaW5hdGUsIHN0cmlkZSkge1xuICBmb3IgKHZhciBpID0gMCwgaWkgPSBjb29yZGluYXRlLmxlbmd0aDsgaSA8IGlpOyArK2kpIHtcbiAgICBmbGF0Q29vcmRpbmF0ZXNbb2Zmc2V0KytdID0gY29vcmRpbmF0ZVtpXTtcbiAgfVxuXG4gIHJldHVybiBvZmZzZXQ7XG59XG4vKipcbiAqIEBwYXJhbSB7QXJyYXk8bnVtYmVyPn0gZmxhdENvb3JkaW5hdGVzIEZsYXQgY29vcmRpbmF0ZXMuXG4gKiBAcGFyYW0ge251bWJlcn0gb2Zmc2V0IE9mZnNldC5cbiAqIEBwYXJhbSB7QXJyYXk8aW1wb3J0KFwiLi4vLi4vY29vcmRpbmF0ZS5qc1wiKS5Db29yZGluYXRlPn0gY29vcmRpbmF0ZXMgQ29vcmRpbmF0ZXMuXG4gKiBAcGFyYW0ge251bWJlcn0gc3RyaWRlIFN0cmlkZS5cbiAqIEByZXR1cm4ge251bWJlcn0gb2Zmc2V0IE9mZnNldC5cbiAqL1xuXG5leHBvcnQgZnVuY3Rpb24gZGVmbGF0ZUNvb3JkaW5hdGVzKGZsYXRDb29yZGluYXRlcywgb2Zmc2V0LCBjb29yZGluYXRlcywgc3RyaWRlKSB7XG4gIGZvciAodmFyIGkgPSAwLCBpaSA9IGNvb3JkaW5hdGVzLmxlbmd0aDsgaSA8IGlpOyArK2kpIHtcbiAgICB2YXIgY29vcmRpbmF0ZSA9IGNvb3JkaW5hdGVzW2ldO1xuXG4gICAgZm9yICh2YXIgaiA9IDA7IGogPCBzdHJpZGU7ICsraikge1xuICAgICAgZmxhdENvb3JkaW5hdGVzW29mZnNldCsrXSA9IGNvb3JkaW5hdGVbal07XG4gICAgfVxuICB9XG5cbiAgcmV0dXJuIG9mZnNldDtcbn1cbi8qKlxuICogQHBhcmFtIHtBcnJheTxudW1iZXI+fSBmbGF0Q29vcmRpbmF0ZXMgRmxhdCBjb29yZGluYXRlcy5cbiAqIEBwYXJhbSB7bnVtYmVyfSBvZmZzZXQgT2Zmc2V0LlxuICogQHBhcmFtIHtBcnJheTxBcnJheTxpbXBvcnQoXCIuLi8uLi9jb29yZGluYXRlLmpzXCIpLkNvb3JkaW5hdGU+Pn0gY29vcmRpbmF0ZXNzIENvb3JkaW5hdGVzcy5cbiAqIEBwYXJhbSB7bnVtYmVyfSBzdHJpZGUgU3RyaWRlLlxuICogQHBhcmFtIHtBcnJheTxudW1iZXI+PX0gb3B0X2VuZHMgRW5kcy5cbiAqIEByZXR1cm4ge0FycmF5PG51bWJlcj59IEVuZHMuXG4gKi9cblxuZXhwb3J0IGZ1bmN0aW9uIGRlZmxhdGVDb29yZGluYXRlc0FycmF5KGZsYXRDb29yZGluYXRlcywgb2Zmc2V0LCBjb29yZGluYXRlc3MsIHN0cmlkZSwgb3B0X2VuZHMpIHtcbiAgdmFyIGVuZHMgPSBvcHRfZW5kcyA/IG9wdF9lbmRzIDogW107XG4gIHZhciBpID0gMDtcblxuICBmb3IgKHZhciBqID0gMCwgamogPSBjb29yZGluYXRlc3MubGVuZ3RoOyBqIDwgamo7ICsraikge1xuICAgIHZhciBlbmQgPSBkZWZsYXRlQ29vcmRpbmF0ZXMoZmxhdENvb3JkaW5hdGVzLCBvZmZzZXQsIGNvb3JkaW5hdGVzc1tqXSwgc3RyaWRlKTtcbiAgICBlbmRzW2krK10gPSBlbmQ7XG4gICAgb2Zmc2V0ID0gZW5kO1xuICB9XG5cbiAgZW5kcy5sZW5ndGggPSBpO1xuICByZXR1cm4gZW5kcztcbn1cbi8qKlxuICogQHBhcmFtIHtBcnJheTxudW1iZXI+fSBmbGF0Q29vcmRpbmF0ZXMgRmxhdCBjb29yZGluYXRlcy5cbiAqIEBwYXJhbSB7bnVtYmVyfSBvZmZzZXQgT2Zmc2V0LlxuICogQHBhcmFtIHtBcnJheTxBcnJheTxBcnJheTxpbXBvcnQoXCIuLi8uLi9jb29yZGluYXRlLmpzXCIpLkNvb3JkaW5hdGU+Pj59IGNvb3JkaW5hdGVzc3MgQ29vcmRpbmF0ZXNzcy5cbiAqIEBwYXJhbSB7bnVtYmVyfSBzdHJpZGUgU3RyaWRlLlxuICogQHBhcmFtIHtBcnJheTxBcnJheTxudW1iZXI+Pj19IG9wdF9lbmRzcyBFbmRzcy5cbiAqIEByZXR1cm4ge0FycmF5PEFycmF5PG51bWJlcj4+fSBFbmRzcy5cbiAqL1xuXG5leHBvcnQgZnVuY3Rpb24gZGVmbGF0ZU11bHRpQ29vcmRpbmF0ZXNBcnJheShmbGF0Q29vcmRpbmF0ZXMsIG9mZnNldCwgY29vcmRpbmF0ZXNzcywgc3RyaWRlLCBvcHRfZW5kc3MpIHtcbiAgdmFyIGVuZHNzID0gb3B0X2VuZHNzID8gb3B0X2VuZHNzIDogW107XG4gIHZhciBpID0gMDtcblxuICBmb3IgKHZhciBqID0gMCwgamogPSBjb29yZGluYXRlc3NzLmxlbmd0aDsgaiA8IGpqOyArK2opIHtcbiAgICB2YXIgZW5kcyA9IGRlZmxhdGVDb29yZGluYXRlc0FycmF5KGZsYXRDb29yZGluYXRlcywgb2Zmc2V0LCBjb29yZGluYXRlc3NzW2pdLCBzdHJpZGUsIGVuZHNzW2ldKTtcbiAgICBlbmRzc1tpKytdID0gZW5kcztcbiAgICBvZmZzZXQgPSBlbmRzW2VuZHMubGVuZ3RoIC0gMV07XG4gIH1cblxuICBlbmRzcy5sZW5ndGggPSBpO1xuICByZXR1cm4gZW5kc3M7XG59IiwiLyoqXG4gKiBAbW9kdWxlIG9sL2dlb20vZmxhdC9zaW1wbGlmeVxuICovXG4vLyBCYXNlZCBvbiBzaW1wbGlmeS1qcyBodHRwczovL2dpdGh1Yi5jb20vbW91cm5lci9zaW1wbGlmeS1qc1xuLy8gQ29weXJpZ2h0IChjKSAyMDEyLCBWbGFkaW1pciBBZ2Fmb25raW5cbi8vIEFsbCByaWdodHMgcmVzZXJ2ZWQuXG4vL1xuLy8gUmVkaXN0cmlidXRpb24gYW5kIHVzZSBpbiBzb3VyY2UgYW5kIGJpbmFyeSBmb3Jtcywgd2l0aCBvciB3aXRob3V0XG4vLyBtb2RpZmljYXRpb24sIGFyZSBwZXJtaXR0ZWQgcHJvdmlkZWQgdGhhdCB0aGUgZm9sbG93aW5nIGNvbmRpdGlvbnMgYXJlIG1ldDpcbi8vXG4vLyAgICAxLiBSZWRpc3RyaWJ1dGlvbnMgb2Ygc291cmNlIGNvZGUgbXVzdCByZXRhaW4gdGhlIGFib3ZlIGNvcHlyaWdodCBub3RpY2UsXG4vLyAgICAgICB0aGlzIGxpc3Qgb2YgY29uZGl0aW9ucyBhbmQgdGhlIGZvbGxvd2luZyBkaXNjbGFpbWVyLlxuLy9cbi8vICAgIDIuIFJlZGlzdHJpYnV0aW9ucyBpbiBiaW5hcnkgZm9ybSBtdXN0IHJlcHJvZHVjZSB0aGUgYWJvdmUgY29weXJpZ2h0XG4vLyAgICAgICBub3RpY2UsIHRoaXMgbGlzdCBvZiBjb25kaXRpb25zIGFuZCB0aGUgZm9sbG93aW5nIGRpc2NsYWltZXIgaW4gdGhlXG4vLyAgICAgICBkb2N1bWVudGF0aW9uIGFuZC9vciBvdGhlciBtYXRlcmlhbHMgcHJvdmlkZWQgd2l0aCB0aGUgZGlzdHJpYnV0aW9uLlxuLy9cbi8vIFRISVMgU09GVFdBUkUgSVMgUFJPVklERUQgQlkgVEhFIENPUFlSSUdIVCBIT0xERVJTIEFORCBDT05UUklCVVRPUlMgXCJBUyBJU1wiXG4vLyBBTkQgQU5ZIEVYUFJFU1MgT1IgSU1QTElFRCBXQVJSQU5USUVTLCBJTkNMVURJTkcsIEJVVCBOT1QgTElNSVRFRCBUTywgVEhFXG4vLyBJTVBMSUVEIFdBUlJBTlRJRVMgT0YgTUVSQ0hBTlRBQklMSVRZIEFORCBGSVRORVNTIEZPUiBBIFBBUlRJQ1VMQVIgUFVSUE9TRVxuLy8gQVJFIERJU0NMQUlNRUQuIElOIE5PIEVWRU5UIFNIQUxMIFRIRSBDT1BZUklHSFQgSE9MREVSIE9SIENPTlRSSUJVVE9SUyBCRVxuLy8gTElBQkxFIEZPUiBBTlkgRElSRUNULCBJTkRJUkVDVCwgSU5DSURFTlRBTCwgU1BFQ0lBTCwgRVhFTVBMQVJZLCBPUlxuLy8gQ09OU0VRVUVOVElBTCBEQU1BR0VTIChJTkNMVURJTkcsIEJVVCBOT1QgTElNSVRFRCBUTywgUFJPQ1VSRU1FTlQgT0Zcbi8vIFNVQlNUSVRVVEUgR09PRFMgT1IgU0VSVklDRVM7IExPU1MgT0YgVVNFLCBEQVRBLCBPUiBQUk9GSVRTOyBPUiBCVVNJTkVTU1xuLy8gSU5URVJSVVBUSU9OKSBIT1dFVkVSIENBVVNFRCBBTkQgT04gQU5ZIFRIRU9SWSBPRiBMSUFCSUxJVFksIFdIRVRIRVIgSU5cbi8vIENPTlRSQUNULCBTVFJJQ1QgTElBQklMSVRZLCBPUiBUT1JUIChJTkNMVURJTkcgTkVHTElHRU5DRSBPUiBPVEhFUldJU0UpXG4vLyBBUklTSU5HIElOIEFOWSBXQVkgT1VUIE9GIFRIRSBVU0UgT0YgVEhJUyBTT0ZUV0FSRSwgRVZFTiBJRiBBRFZJU0VEIE9GIFRIRVxuLy8gUE9TU0lCSUxJVFkgT0YgU1VDSCBEQU1BR0UuXG5pbXBvcnQgeyBzcXVhcmVkRGlzdGFuY2UsIHNxdWFyZWRTZWdtZW50RGlzdGFuY2UgfSBmcm9tICcuLi8uLi9tYXRoLmpzJztcbi8qKlxuICogQHBhcmFtIHtBcnJheTxudW1iZXI+fSBmbGF0Q29vcmRpbmF0ZXMgRmxhdCBjb29yZGluYXRlcy5cbiAqIEBwYXJhbSB7bnVtYmVyfSBvZmZzZXQgT2Zmc2V0LlxuICogQHBhcmFtIHtudW1iZXJ9IGVuZCBFbmQuXG4gKiBAcGFyYW0ge251bWJlcn0gc3RyaWRlIFN0cmlkZS5cbiAqIEBwYXJhbSB7bnVtYmVyfSBzcXVhcmVkVG9sZXJhbmNlIFNxdWFyZWQgdG9sZXJhbmNlLlxuICogQHBhcmFtIHtib29sZWFufSBoaWdoUXVhbGl0eSBIaWdoZXN0IHF1YWxpdHkuXG4gKiBAcGFyYW0ge0FycmF5PG51bWJlcj49fSBvcHRfc2ltcGxpZmllZEZsYXRDb29yZGluYXRlcyBTaW1wbGlmaWVkIGZsYXRcbiAqICAgICBjb29yZGluYXRlcy5cbiAqIEByZXR1cm4ge0FycmF5PG51bWJlcj59IFNpbXBsaWZpZWQgbGluZSBzdHJpbmcuXG4gKi9cblxuZXhwb3J0IGZ1bmN0aW9uIHNpbXBsaWZ5TGluZVN0cmluZyhmbGF0Q29vcmRpbmF0ZXMsIG9mZnNldCwgZW5kLCBzdHJpZGUsIHNxdWFyZWRUb2xlcmFuY2UsIGhpZ2hRdWFsaXR5LCBvcHRfc2ltcGxpZmllZEZsYXRDb29yZGluYXRlcykge1xuICB2YXIgc2ltcGxpZmllZEZsYXRDb29yZGluYXRlcyA9IG9wdF9zaW1wbGlmaWVkRmxhdENvb3JkaW5hdGVzICE9PSB1bmRlZmluZWQgPyBvcHRfc2ltcGxpZmllZEZsYXRDb29yZGluYXRlcyA6IFtdO1xuXG4gIGlmICghaGlnaFF1YWxpdHkpIHtcbiAgICBlbmQgPSByYWRpYWxEaXN0YW5jZShmbGF0Q29vcmRpbmF0ZXMsIG9mZnNldCwgZW5kLCBzdHJpZGUsIHNxdWFyZWRUb2xlcmFuY2UsIHNpbXBsaWZpZWRGbGF0Q29vcmRpbmF0ZXMsIDApO1xuICAgIGZsYXRDb29yZGluYXRlcyA9IHNpbXBsaWZpZWRGbGF0Q29vcmRpbmF0ZXM7XG4gICAgb2Zmc2V0ID0gMDtcbiAgICBzdHJpZGUgPSAyO1xuICB9XG5cbiAgc2ltcGxpZmllZEZsYXRDb29yZGluYXRlcy5sZW5ndGggPSBkb3VnbGFzUGV1Y2tlcihmbGF0Q29vcmRpbmF0ZXMsIG9mZnNldCwgZW5kLCBzdHJpZGUsIHNxdWFyZWRUb2xlcmFuY2UsIHNpbXBsaWZpZWRGbGF0Q29vcmRpbmF0ZXMsIDApO1xuICByZXR1cm4gc2ltcGxpZmllZEZsYXRDb29yZGluYXRlcztcbn1cbi8qKlxuICogQHBhcmFtIHtBcnJheTxudW1iZXI+fSBmbGF0Q29vcmRpbmF0ZXMgRmxhdCBjb29yZGluYXRlcy5cbiAqIEBwYXJhbSB7bnVtYmVyfSBvZmZzZXQgT2Zmc2V0LlxuICogQHBhcmFtIHtudW1iZXJ9IGVuZCBFbmQuXG4gKiBAcGFyYW0ge251bWJlcn0gc3RyaWRlIFN0cmlkZS5cbiAqIEBwYXJhbSB7bnVtYmVyfSBzcXVhcmVkVG9sZXJhbmNlIFNxdWFyZWQgdG9sZXJhbmNlLlxuICogQHBhcmFtIHtBcnJheTxudW1iZXI+fSBzaW1wbGlmaWVkRmxhdENvb3JkaW5hdGVzIFNpbXBsaWZpZWQgZmxhdFxuICogICAgIGNvb3JkaW5hdGVzLlxuICogQHBhcmFtIHtudW1iZXJ9IHNpbXBsaWZpZWRPZmZzZXQgU2ltcGxpZmllZCBvZmZzZXQuXG4gKiBAcmV0dXJuIHtudW1iZXJ9IFNpbXBsaWZpZWQgb2Zmc2V0LlxuICovXG5cbmV4cG9ydCBmdW5jdGlvbiBkb3VnbGFzUGV1Y2tlcihmbGF0Q29vcmRpbmF0ZXMsIG9mZnNldCwgZW5kLCBzdHJpZGUsIHNxdWFyZWRUb2xlcmFuY2UsIHNpbXBsaWZpZWRGbGF0Q29vcmRpbmF0ZXMsIHNpbXBsaWZpZWRPZmZzZXQpIHtcbiAgdmFyIG4gPSAoZW5kIC0gb2Zmc2V0KSAvIHN0cmlkZTtcblxuICBpZiAobiA8IDMpIHtcbiAgICBmb3IgKDsgb2Zmc2V0IDwgZW5kOyBvZmZzZXQgKz0gc3RyaWRlKSB7XG4gICAgICBzaW1wbGlmaWVkRmxhdENvb3JkaW5hdGVzW3NpbXBsaWZpZWRPZmZzZXQrK10gPSBmbGF0Q29vcmRpbmF0ZXNbb2Zmc2V0XTtcbiAgICAgIHNpbXBsaWZpZWRGbGF0Q29vcmRpbmF0ZXNbc2ltcGxpZmllZE9mZnNldCsrXSA9IGZsYXRDb29yZGluYXRlc1tvZmZzZXQgKyAxXTtcbiAgICB9XG5cbiAgICByZXR1cm4gc2ltcGxpZmllZE9mZnNldDtcbiAgfVxuICAvKiogQHR5cGUge0FycmF5PG51bWJlcj59ICovXG5cblxuICB2YXIgbWFya2VycyA9IG5ldyBBcnJheShuKTtcbiAgbWFya2Vyc1swXSA9IDE7XG4gIG1hcmtlcnNbbiAtIDFdID0gMTtcbiAgLyoqIEB0eXBlIHtBcnJheTxudW1iZXI+fSAqL1xuXG4gIHZhciBzdGFjayA9IFtvZmZzZXQsIGVuZCAtIHN0cmlkZV07XG4gIHZhciBpbmRleCA9IDA7XG5cbiAgd2hpbGUgKHN0YWNrLmxlbmd0aCA+IDApIHtcbiAgICB2YXIgbGFzdCA9IHN0YWNrLnBvcCgpO1xuICAgIHZhciBmaXJzdCA9IHN0YWNrLnBvcCgpO1xuICAgIHZhciBtYXhTcXVhcmVkRGlzdGFuY2UgPSAwO1xuICAgIHZhciB4MSA9IGZsYXRDb29yZGluYXRlc1tmaXJzdF07XG4gICAgdmFyIHkxID0gZmxhdENvb3JkaW5hdGVzW2ZpcnN0ICsgMV07XG4gICAgdmFyIHgyID0gZmxhdENvb3JkaW5hdGVzW2xhc3RdO1xuICAgIHZhciB5MiA9IGZsYXRDb29yZGluYXRlc1tsYXN0ICsgMV07XG5cbiAgICBmb3IgKHZhciBpID0gZmlyc3QgKyBzdHJpZGU7IGkgPCBsYXN0OyBpICs9IHN0cmlkZSkge1xuICAgICAgdmFyIHggPSBmbGF0Q29vcmRpbmF0ZXNbaV07XG4gICAgICB2YXIgeSA9IGZsYXRDb29yZGluYXRlc1tpICsgMV07XG4gICAgICB2YXIgc3F1YXJlZERpc3RhbmNlXzEgPSBzcXVhcmVkU2VnbWVudERpc3RhbmNlKHgsIHksIHgxLCB5MSwgeDIsIHkyKTtcblxuICAgICAgaWYgKHNxdWFyZWREaXN0YW5jZV8xID4gbWF4U3F1YXJlZERpc3RhbmNlKSB7XG4gICAgICAgIGluZGV4ID0gaTtcbiAgICAgICAgbWF4U3F1YXJlZERpc3RhbmNlID0gc3F1YXJlZERpc3RhbmNlXzE7XG4gICAgICB9XG4gICAgfVxuXG4gICAgaWYgKG1heFNxdWFyZWREaXN0YW5jZSA+IHNxdWFyZWRUb2xlcmFuY2UpIHtcbiAgICAgIG1hcmtlcnNbKGluZGV4IC0gb2Zmc2V0KSAvIHN0cmlkZV0gPSAxO1xuXG4gICAgICBpZiAoZmlyc3QgKyBzdHJpZGUgPCBpbmRleCkge1xuICAgICAgICBzdGFjay5wdXNoKGZpcnN0LCBpbmRleCk7XG4gICAgICB9XG5cbiAgICAgIGlmIChpbmRleCArIHN0cmlkZSA8IGxhc3QpIHtcbiAgICAgICAgc3RhY2sucHVzaChpbmRleCwgbGFzdCk7XG4gICAgICB9XG4gICAgfVxuICB9XG5cbiAgZm9yICh2YXIgaSA9IDA7IGkgPCBuOyArK2kpIHtcbiAgICBpZiAobWFya2Vyc1tpXSkge1xuICAgICAgc2ltcGxpZmllZEZsYXRDb29yZGluYXRlc1tzaW1wbGlmaWVkT2Zmc2V0KytdID0gZmxhdENvb3JkaW5hdGVzW29mZnNldCArIGkgKiBzdHJpZGVdO1xuICAgICAgc2ltcGxpZmllZEZsYXRDb29yZGluYXRlc1tzaW1wbGlmaWVkT2Zmc2V0KytdID0gZmxhdENvb3JkaW5hdGVzW29mZnNldCArIGkgKiBzdHJpZGUgKyAxXTtcbiAgICB9XG4gIH1cblxuICByZXR1cm4gc2ltcGxpZmllZE9mZnNldDtcbn1cbi8qKlxuICogQHBhcmFtIHtBcnJheTxudW1iZXI+fSBmbGF0Q29vcmRpbmF0ZXMgRmxhdCBjb29yZGluYXRlcy5cbiAqIEBwYXJhbSB7bnVtYmVyfSBvZmZzZXQgT2Zmc2V0LlxuICogQHBhcmFtIHtBcnJheTxudW1iZXI+fSBlbmRzIEVuZHMuXG4gKiBAcGFyYW0ge251bWJlcn0gc3RyaWRlIFN0cmlkZS5cbiAqIEBwYXJhbSB7bnVtYmVyfSBzcXVhcmVkVG9sZXJhbmNlIFNxdWFyZWQgdG9sZXJhbmNlLlxuICogQHBhcmFtIHtBcnJheTxudW1iZXI+fSBzaW1wbGlmaWVkRmxhdENvb3JkaW5hdGVzIFNpbXBsaWZpZWQgZmxhdFxuICogICAgIGNvb3JkaW5hdGVzLlxuICogQHBhcmFtIHtudW1iZXJ9IHNpbXBsaWZpZWRPZmZzZXQgU2ltcGxpZmllZCBvZmZzZXQuXG4gKiBAcGFyYW0ge0FycmF5PG51bWJlcj59IHNpbXBsaWZpZWRFbmRzIFNpbXBsaWZpZWQgZW5kcy5cbiAqIEByZXR1cm4ge251bWJlcn0gU2ltcGxpZmllZCBvZmZzZXQuXG4gKi9cblxuZXhwb3J0IGZ1bmN0aW9uIGRvdWdsYXNQZXVja2VyQXJyYXkoZmxhdENvb3JkaW5hdGVzLCBvZmZzZXQsIGVuZHMsIHN0cmlkZSwgc3F1YXJlZFRvbGVyYW5jZSwgc2ltcGxpZmllZEZsYXRDb29yZGluYXRlcywgc2ltcGxpZmllZE9mZnNldCwgc2ltcGxpZmllZEVuZHMpIHtcbiAgZm9yICh2YXIgaSA9IDAsIGlpID0gZW5kcy5sZW5ndGg7IGkgPCBpaTsgKytpKSB7XG4gICAgdmFyIGVuZCA9IGVuZHNbaV07XG4gICAgc2ltcGxpZmllZE9mZnNldCA9IGRvdWdsYXNQZXVja2VyKGZsYXRDb29yZGluYXRlcywgb2Zmc2V0LCBlbmQsIHN0cmlkZSwgc3F1YXJlZFRvbGVyYW5jZSwgc2ltcGxpZmllZEZsYXRDb29yZGluYXRlcywgc2ltcGxpZmllZE9mZnNldCk7XG4gICAgc2ltcGxpZmllZEVuZHMucHVzaChzaW1wbGlmaWVkT2Zmc2V0KTtcbiAgICBvZmZzZXQgPSBlbmQ7XG4gIH1cblxuICByZXR1cm4gc2ltcGxpZmllZE9mZnNldDtcbn1cbi8qKlxuICogQHBhcmFtIHtBcnJheTxudW1iZXI+fSBmbGF0Q29vcmRpbmF0ZXMgRmxhdCBjb29yZGluYXRlcy5cbiAqIEBwYXJhbSB7bnVtYmVyfSBvZmZzZXQgT2Zmc2V0LlxuICogQHBhcmFtIHtBcnJheTxBcnJheTxudW1iZXI+Pn0gZW5kc3MgRW5kc3MuXG4gKiBAcGFyYW0ge251bWJlcn0gc3RyaWRlIFN0cmlkZS5cbiAqIEBwYXJhbSB7bnVtYmVyfSBzcXVhcmVkVG9sZXJhbmNlIFNxdWFyZWQgdG9sZXJhbmNlLlxuICogQHBhcmFtIHtBcnJheTxudW1iZXI+fSBzaW1wbGlmaWVkRmxhdENvb3JkaW5hdGVzIFNpbXBsaWZpZWQgZmxhdFxuICogICAgIGNvb3JkaW5hdGVzLlxuICogQHBhcmFtIHtudW1iZXJ9IHNpbXBsaWZpZWRPZmZzZXQgU2ltcGxpZmllZCBvZmZzZXQuXG4gKiBAcGFyYW0ge0FycmF5PEFycmF5PG51bWJlcj4+fSBzaW1wbGlmaWVkRW5kc3MgU2ltcGxpZmllZCBlbmRzcy5cbiAqIEByZXR1cm4ge251bWJlcn0gU2ltcGxpZmllZCBvZmZzZXQuXG4gKi9cblxuZXhwb3J0IGZ1bmN0aW9uIGRvdWdsYXNQZXVja2VyTXVsdGlBcnJheShmbGF0Q29vcmRpbmF0ZXMsIG9mZnNldCwgZW5kc3MsIHN0cmlkZSwgc3F1YXJlZFRvbGVyYW5jZSwgc2ltcGxpZmllZEZsYXRDb29yZGluYXRlcywgc2ltcGxpZmllZE9mZnNldCwgc2ltcGxpZmllZEVuZHNzKSB7XG4gIGZvciAodmFyIGkgPSAwLCBpaSA9IGVuZHNzLmxlbmd0aDsgaSA8IGlpOyArK2kpIHtcbiAgICB2YXIgZW5kcyA9IGVuZHNzW2ldO1xuICAgIHZhciBzaW1wbGlmaWVkRW5kcyA9IFtdO1xuICAgIHNpbXBsaWZpZWRPZmZzZXQgPSBkb3VnbGFzUGV1Y2tlckFycmF5KGZsYXRDb29yZGluYXRlcywgb2Zmc2V0LCBlbmRzLCBzdHJpZGUsIHNxdWFyZWRUb2xlcmFuY2UsIHNpbXBsaWZpZWRGbGF0Q29vcmRpbmF0ZXMsIHNpbXBsaWZpZWRPZmZzZXQsIHNpbXBsaWZpZWRFbmRzKTtcbiAgICBzaW1wbGlmaWVkRW5kc3MucHVzaChzaW1wbGlmaWVkRW5kcyk7XG4gICAgb2Zmc2V0ID0gZW5kc1tlbmRzLmxlbmd0aCAtIDFdO1xuICB9XG5cbiAgcmV0dXJuIHNpbXBsaWZpZWRPZmZzZXQ7XG59XG4vKipcbiAqIEBwYXJhbSB7QXJyYXk8bnVtYmVyPn0gZmxhdENvb3JkaW5hdGVzIEZsYXQgY29vcmRpbmF0ZXMuXG4gKiBAcGFyYW0ge251bWJlcn0gb2Zmc2V0IE9mZnNldC5cbiAqIEBwYXJhbSB7bnVtYmVyfSBlbmQgRW5kLlxuICogQHBhcmFtIHtudW1iZXJ9IHN0cmlkZSBTdHJpZGUuXG4gKiBAcGFyYW0ge251bWJlcn0gc3F1YXJlZFRvbGVyYW5jZSBTcXVhcmVkIHRvbGVyYW5jZS5cbiAqIEBwYXJhbSB7QXJyYXk8bnVtYmVyPn0gc2ltcGxpZmllZEZsYXRDb29yZGluYXRlcyBTaW1wbGlmaWVkIGZsYXRcbiAqICAgICBjb29yZGluYXRlcy5cbiAqIEBwYXJhbSB7bnVtYmVyfSBzaW1wbGlmaWVkT2Zmc2V0IFNpbXBsaWZpZWQgb2Zmc2V0LlxuICogQHJldHVybiB7bnVtYmVyfSBTaW1wbGlmaWVkIG9mZnNldC5cbiAqL1xuXG5leHBvcnQgZnVuY3Rpb24gcmFkaWFsRGlzdGFuY2UoZmxhdENvb3JkaW5hdGVzLCBvZmZzZXQsIGVuZCwgc3RyaWRlLCBzcXVhcmVkVG9sZXJhbmNlLCBzaW1wbGlmaWVkRmxhdENvb3JkaW5hdGVzLCBzaW1wbGlmaWVkT2Zmc2V0KSB7XG4gIGlmIChlbmQgPD0gb2Zmc2V0ICsgc3RyaWRlKSB7XG4gICAgLy8gemVybyBvciBvbmUgcG9pbnQsIG5vIHNpbXBsaWZpY2F0aW9uIHBvc3NpYmxlLCBzbyBjb3B5IGFuZCByZXR1cm5cbiAgICBmb3IgKDsgb2Zmc2V0IDwgZW5kOyBvZmZzZXQgKz0gc3RyaWRlKSB7XG4gICAgICBzaW1wbGlmaWVkRmxhdENvb3JkaW5hdGVzW3NpbXBsaWZpZWRPZmZzZXQrK10gPSBmbGF0Q29vcmRpbmF0ZXNbb2Zmc2V0XTtcbiAgICAgIHNpbXBsaWZpZWRGbGF0Q29vcmRpbmF0ZXNbc2ltcGxpZmllZE9mZnNldCsrXSA9IGZsYXRDb29yZGluYXRlc1tvZmZzZXQgKyAxXTtcbiAgICB9XG5cbiAgICByZXR1cm4gc2ltcGxpZmllZE9mZnNldDtcbiAgfVxuXG4gIHZhciB4MSA9IGZsYXRDb29yZGluYXRlc1tvZmZzZXRdO1xuICB2YXIgeTEgPSBmbGF0Q29vcmRpbmF0ZXNbb2Zmc2V0ICsgMV07IC8vIGNvcHkgZmlyc3QgcG9pbnRcblxuICBzaW1wbGlmaWVkRmxhdENvb3JkaW5hdGVzW3NpbXBsaWZpZWRPZmZzZXQrK10gPSB4MTtcbiAgc2ltcGxpZmllZEZsYXRDb29yZGluYXRlc1tzaW1wbGlmaWVkT2Zmc2V0KytdID0geTE7XG4gIHZhciB4MiA9IHgxO1xuICB2YXIgeTIgPSB5MTtcblxuICBmb3IgKG9mZnNldCArPSBzdHJpZGU7IG9mZnNldCA8IGVuZDsgb2Zmc2V0ICs9IHN0cmlkZSkge1xuICAgIHgyID0gZmxhdENvb3JkaW5hdGVzW29mZnNldF07XG4gICAgeTIgPSBmbGF0Q29vcmRpbmF0ZXNbb2Zmc2V0ICsgMV07XG5cbiAgICBpZiAoc3F1YXJlZERpc3RhbmNlKHgxLCB5MSwgeDIsIHkyKSA+IHNxdWFyZWRUb2xlcmFuY2UpIHtcbiAgICAgIC8vIGNvcHkgcG9pbnQgYXQgb2Zmc2V0XG4gICAgICBzaW1wbGlmaWVkRmxhdENvb3JkaW5hdGVzW3NpbXBsaWZpZWRPZmZzZXQrK10gPSB4MjtcbiAgICAgIHNpbXBsaWZpZWRGbGF0Q29vcmRpbmF0ZXNbc2ltcGxpZmllZE9mZnNldCsrXSA9IHkyO1xuICAgICAgeDEgPSB4MjtcbiAgICAgIHkxID0geTI7XG4gICAgfVxuICB9XG5cbiAgaWYgKHgyICE9IHgxIHx8IHkyICE9IHkxKSB7XG4gICAgLy8gY29weSBsYXN0IHBvaW50XG4gICAgc2ltcGxpZmllZEZsYXRDb29yZGluYXRlc1tzaW1wbGlmaWVkT2Zmc2V0KytdID0geDI7XG4gICAgc2ltcGxpZmllZEZsYXRDb29yZGluYXRlc1tzaW1wbGlmaWVkT2Zmc2V0KytdID0geTI7XG4gIH1cblxuICByZXR1cm4gc2ltcGxpZmllZE9mZnNldDtcbn1cbi8qKlxuICogQHBhcmFtIHtudW1iZXJ9IHZhbHVlIFZhbHVlLlxuICogQHBhcmFtIHtudW1iZXJ9IHRvbGVyYW5jZSBUb2xlcmFuY2UuXG4gKiBAcmV0dXJuIHtudW1iZXJ9IFJvdW5kZWQgdmFsdWUuXG4gKi9cblxuZXhwb3J0IGZ1bmN0aW9uIHNuYXAodmFsdWUsIHRvbGVyYW5jZSkge1xuICByZXR1cm4gdG9sZXJhbmNlICogTWF0aC5yb3VuZCh2YWx1ZSAvIHRvbGVyYW5jZSk7XG59XG4vKipcbiAqIFNpbXBsaWZpZXMgYSBsaW5lIHN0cmluZyB1c2luZyBhbiBhbGdvcml0aG0gZGVzaWduZWQgYnkgVGltIFNjaGF1Yi5cbiAqIENvb3JkaW5hdGVzIGFyZSBzbmFwcGVkIHRvIHRoZSBuZWFyZXN0IHZhbHVlIGluIGEgdmlydHVhbCBncmlkIGFuZFxuICogY29uc2VjdXRpdmUgZHVwbGljYXRlIGNvb3JkaW5hdGVzIGFyZSBkaXNjYXJkZWQuICBUaGlzIGVmZmVjdGl2ZWx5IHByZXNlcnZlc1xuICogdG9wb2xvZ3kgYXMgdGhlIHNpbXBsaWZpY2F0aW9uIG9mIGFueSBzdWJzZWN0aW9uIG9mIGEgbGluZSBzdHJpbmcgaXNcbiAqIGluZGVwZW5kZW50IG9mIHRoZSByZXN0IG9mIHRoZSBsaW5lIHN0cmluZy4gIFRoaXMgbWVhbnMgdGhhdCwgZm9yIGV4YW1wbGVzLFxuICogdGhlIGNvbW1vbiBlZGdlIGJldHdlZW4gdHdvIHBvbHlnb25zIHdpbGwgYmUgc2ltcGxpZmllZCB0byB0aGUgc2FtZSBsaW5lXG4gKiBzdHJpbmcgaW5kZXBlbmRlbnRseSBpbiBib3RoIHBvbHlnb25zLiAgVGhpcyBpbXBsZW1lbnRhdGlvbiB1c2VzIGEgc2luZ2xlXG4gKiBwYXNzIG92ZXIgdGhlIGNvb3JkaW5hdGVzIGFuZCBlbGltaW5hdGVzIGludGVybWVkaWF0ZSBjb2xsaW5lYXIgcG9pbnRzLlxuICogQHBhcmFtIHtBcnJheTxudW1iZXI+fSBmbGF0Q29vcmRpbmF0ZXMgRmxhdCBjb29yZGluYXRlcy5cbiAqIEBwYXJhbSB7bnVtYmVyfSBvZmZzZXQgT2Zmc2V0LlxuICogQHBhcmFtIHtudW1iZXJ9IGVuZCBFbmQuXG4gKiBAcGFyYW0ge251bWJlcn0gc3RyaWRlIFN0cmlkZS5cbiAqIEBwYXJhbSB7bnVtYmVyfSB0b2xlcmFuY2UgVG9sZXJhbmNlLlxuICogQHBhcmFtIHtBcnJheTxudW1iZXI+fSBzaW1wbGlmaWVkRmxhdENvb3JkaW5hdGVzIFNpbXBsaWZpZWQgZmxhdFxuICogICAgIGNvb3JkaW5hdGVzLlxuICogQHBhcmFtIHtudW1iZXJ9IHNpbXBsaWZpZWRPZmZzZXQgU2ltcGxpZmllZCBvZmZzZXQuXG4gKiBAcmV0dXJuIHtudW1iZXJ9IFNpbXBsaWZpZWQgb2Zmc2V0LlxuICovXG5cbmV4cG9ydCBmdW5jdGlvbiBxdWFudGl6ZShmbGF0Q29vcmRpbmF0ZXMsIG9mZnNldCwgZW5kLCBzdHJpZGUsIHRvbGVyYW5jZSwgc2ltcGxpZmllZEZsYXRDb29yZGluYXRlcywgc2ltcGxpZmllZE9mZnNldCkge1xuICAvLyBkbyBub3RoaW5nIGlmIHRoZSBsaW5lIGlzIGVtcHR5XG4gIGlmIChvZmZzZXQgPT0gZW5kKSB7XG4gICAgcmV0dXJuIHNpbXBsaWZpZWRPZmZzZXQ7XG4gIH0gLy8gc25hcCB0aGUgZmlyc3QgY29vcmRpbmF0ZSAoUDEpXG5cblxuICB2YXIgeDEgPSBzbmFwKGZsYXRDb29yZGluYXRlc1tvZmZzZXRdLCB0b2xlcmFuY2UpO1xuICB2YXIgeTEgPSBzbmFwKGZsYXRDb29yZGluYXRlc1tvZmZzZXQgKyAxXSwgdG9sZXJhbmNlKTtcbiAgb2Zmc2V0ICs9IHN0cmlkZTsgLy8gYWRkIHRoZSBmaXJzdCBjb29yZGluYXRlIHRvIHRoZSBvdXRwdXRcblxuICBzaW1wbGlmaWVkRmxhdENvb3JkaW5hdGVzW3NpbXBsaWZpZWRPZmZzZXQrK10gPSB4MTtcbiAgc2ltcGxpZmllZEZsYXRDb29yZGluYXRlc1tzaW1wbGlmaWVkT2Zmc2V0KytdID0geTE7IC8vIGZpbmQgdGhlIG5leHQgY29vcmRpbmF0ZSB0aGF0IGRvZXMgbm90IHNuYXAgdG8gdGhlIHNhbWUgdmFsdWUgYXMgdGhlIGZpcnN0XG4gIC8vIGNvb3JkaW5hdGUgKFAyKVxuXG4gIHZhciB4MiwgeTI7XG5cbiAgZG8ge1xuICAgIHgyID0gc25hcChmbGF0Q29vcmRpbmF0ZXNbb2Zmc2V0XSwgdG9sZXJhbmNlKTtcbiAgICB5MiA9IHNuYXAoZmxhdENvb3JkaW5hdGVzW29mZnNldCArIDFdLCB0b2xlcmFuY2UpO1xuICAgIG9mZnNldCArPSBzdHJpZGU7XG5cbiAgICBpZiAob2Zmc2V0ID09IGVuZCkge1xuICAgICAgLy8gYWxsIGNvb3JkaW5hdGVzIHNuYXAgdG8gdGhlIHNhbWUgdmFsdWUsIHRoZSBsaW5lIGNvbGxhcHNlcyB0byBhIHBvaW50XG4gICAgICAvLyBwdXNoIHRoZSBsYXN0IHNuYXBwZWQgdmFsdWUgYW55d2F5IHRvIGVuc3VyZSB0aGF0IHRoZSBvdXRwdXQgY29udGFpbnNcbiAgICAgIC8vIGF0IGxlYXN0IHR3byBwb2ludHNcbiAgICAgIC8vIEZJWE1FIHNob3VsZCB3ZSByZWFsbHkgcmV0dXJuIGF0IGxlYXN0IHR3byBwb2ludHMgYW55d2F5P1xuICAgICAgc2ltcGxpZmllZEZsYXRDb29yZGluYXRlc1tzaW1wbGlmaWVkT2Zmc2V0KytdID0geDI7XG4gICAgICBzaW1wbGlmaWVkRmxhdENvb3JkaW5hdGVzW3NpbXBsaWZpZWRPZmZzZXQrK10gPSB5MjtcbiAgICAgIHJldHVybiBzaW1wbGlmaWVkT2Zmc2V0O1xuICAgIH1cbiAgfSB3aGlsZSAoeDIgPT0geDEgJiYgeTIgPT0geTEpO1xuXG4gIHdoaWxlIChvZmZzZXQgPCBlbmQpIHtcbiAgICAvLyBzbmFwIHRoZSBuZXh0IGNvb3JkaW5hdGUgKFAzKVxuICAgIHZhciB4MyA9IHNuYXAoZmxhdENvb3JkaW5hdGVzW29mZnNldF0sIHRvbGVyYW5jZSk7XG4gICAgdmFyIHkzID0gc25hcChmbGF0Q29vcmRpbmF0ZXNbb2Zmc2V0ICsgMV0sIHRvbGVyYW5jZSk7XG4gICAgb2Zmc2V0ICs9IHN0cmlkZTsgLy8gc2tpcCBQMyBpZiBpdCBpcyBlcXVhbCB0byBQMlxuXG4gICAgaWYgKHgzID09IHgyICYmIHkzID09IHkyKSB7XG4gICAgICBjb250aW51ZTtcbiAgICB9IC8vIGNhbGN1bGF0ZSB0aGUgZGVsdGEgYmV0d2VlbiBQMSBhbmQgUDJcblxuXG4gICAgdmFyIGR4MSA9IHgyIC0geDE7XG4gICAgdmFyIGR5MSA9IHkyIC0geTE7IC8vIGNhbGN1bGF0ZSB0aGUgZGVsdGEgYmV0d2VlbiBQMyBhbmQgUDFcblxuICAgIHZhciBkeDIgPSB4MyAtIHgxO1xuICAgIHZhciBkeTIgPSB5MyAtIHkxOyAvLyBpZiBQMSwgUDIsIGFuZCBQMyBhcmUgY29saW5lYXIgYW5kIFAzIGlzIGZ1cnRoZXIgZnJvbSBQMSB0aGFuIFAyIGlzIGZyb21cbiAgICAvLyBQMSBpbiB0aGUgc2FtZSBkaXJlY3Rpb24gdGhlbiBQMiBpcyBvbiB0aGUgc3RyYWlnaHQgbGluZSBiZXR3ZWVuIFAxIGFuZFxuICAgIC8vIFAzXG5cbiAgICBpZiAoZHgxICogZHkyID09IGR5MSAqIGR4MiAmJiAoZHgxIDwgMCAmJiBkeDIgPCBkeDEgfHwgZHgxID09IGR4MiB8fCBkeDEgPiAwICYmIGR4MiA+IGR4MSkgJiYgKGR5MSA8IDAgJiYgZHkyIDwgZHkxIHx8IGR5MSA9PSBkeTIgfHwgZHkxID4gMCAmJiBkeTIgPiBkeTEpKSB7XG4gICAgICAvLyBkaXNjYXJkIFAyIGFuZCBzZXQgUDIgPSBQM1xuICAgICAgeDIgPSB4MztcbiAgICAgIHkyID0geTM7XG4gICAgICBjb250aW51ZTtcbiAgICB9IC8vIGVpdGhlciBQMSwgUDIsIGFuZCBQMyBhcmUgbm90IGNvbGluZWFyLCBvciB0aGV5IGFyZSBjb2xpbmVhciBidXQgUDMgaXNcbiAgICAvLyBiZXR3ZWVuIFAzIGFuZCBQMSBvciBvbiB0aGUgb3Bwb3NpdGUgaGFsZiBvZiB0aGUgbGluZSB0byBQMi4gIGFkZCBQMixcbiAgICAvLyBhbmQgY29udGludWUgd2l0aCBQMSA9IFAyIGFuZCBQMiA9IFAzXG5cblxuICAgIHNpbXBsaWZpZWRGbGF0Q29vcmRpbmF0ZXNbc2ltcGxpZmllZE9mZnNldCsrXSA9IHgyO1xuICAgIHNpbXBsaWZpZWRGbGF0Q29vcmRpbmF0ZXNbc2ltcGxpZmllZE9mZnNldCsrXSA9IHkyO1xuICAgIHgxID0geDI7XG4gICAgeTEgPSB5MjtcbiAgICB4MiA9IHgzO1xuICAgIHkyID0geTM7XG4gIH0gLy8gYWRkIHRoZSBsYXN0IHBvaW50IChQMilcblxuXG4gIHNpbXBsaWZpZWRGbGF0Q29vcmRpbmF0ZXNbc2ltcGxpZmllZE9mZnNldCsrXSA9IHgyO1xuICBzaW1wbGlmaWVkRmxhdENvb3JkaW5hdGVzW3NpbXBsaWZpZWRPZmZzZXQrK10gPSB5MjtcbiAgcmV0dXJuIHNpbXBsaWZpZWRPZmZzZXQ7XG59XG4vKipcbiAqIEBwYXJhbSB7QXJyYXk8bnVtYmVyPn0gZmxhdENvb3JkaW5hdGVzIEZsYXQgY29vcmRpbmF0ZXMuXG4gKiBAcGFyYW0ge251bWJlcn0gb2Zmc2V0IE9mZnNldC5cbiAqIEBwYXJhbSB7QXJyYXk8bnVtYmVyPn0gZW5kcyBFbmRzLlxuICogQHBhcmFtIHtudW1iZXJ9IHN0cmlkZSBTdHJpZGUuXG4gKiBAcGFyYW0ge251bWJlcn0gdG9sZXJhbmNlIFRvbGVyYW5jZS5cbiAqIEBwYXJhbSB7QXJyYXk8bnVtYmVyPn0gc2ltcGxpZmllZEZsYXRDb29yZGluYXRlcyBTaW1wbGlmaWVkIGZsYXRcbiAqICAgICBjb29yZGluYXRlcy5cbiAqIEBwYXJhbSB7bnVtYmVyfSBzaW1wbGlmaWVkT2Zmc2V0IFNpbXBsaWZpZWQgb2Zmc2V0LlxuICogQHBhcmFtIHtBcnJheTxudW1iZXI+fSBzaW1wbGlmaWVkRW5kcyBTaW1wbGlmaWVkIGVuZHMuXG4gKiBAcmV0dXJuIHtudW1iZXJ9IFNpbXBsaWZpZWQgb2Zmc2V0LlxuICovXG5cbmV4cG9ydCBmdW5jdGlvbiBxdWFudGl6ZUFycmF5KGZsYXRDb29yZGluYXRlcywgb2Zmc2V0LCBlbmRzLCBzdHJpZGUsIHRvbGVyYW5jZSwgc2ltcGxpZmllZEZsYXRDb29yZGluYXRlcywgc2ltcGxpZmllZE9mZnNldCwgc2ltcGxpZmllZEVuZHMpIHtcbiAgZm9yICh2YXIgaSA9IDAsIGlpID0gZW5kcy5sZW5ndGg7IGkgPCBpaTsgKytpKSB7XG4gICAgdmFyIGVuZCA9IGVuZHNbaV07XG4gICAgc2ltcGxpZmllZE9mZnNldCA9IHF1YW50aXplKGZsYXRDb29yZGluYXRlcywgb2Zmc2V0LCBlbmQsIHN0cmlkZSwgdG9sZXJhbmNlLCBzaW1wbGlmaWVkRmxhdENvb3JkaW5hdGVzLCBzaW1wbGlmaWVkT2Zmc2V0KTtcbiAgICBzaW1wbGlmaWVkRW5kcy5wdXNoKHNpbXBsaWZpZWRPZmZzZXQpO1xuICAgIG9mZnNldCA9IGVuZDtcbiAgfVxuXG4gIHJldHVybiBzaW1wbGlmaWVkT2Zmc2V0O1xufVxuLyoqXG4gKiBAcGFyYW0ge0FycmF5PG51bWJlcj59IGZsYXRDb29yZGluYXRlcyBGbGF0IGNvb3JkaW5hdGVzLlxuICogQHBhcmFtIHtudW1iZXJ9IG9mZnNldCBPZmZzZXQuXG4gKiBAcGFyYW0ge0FycmF5PEFycmF5PG51bWJlcj4+fSBlbmRzcyBFbmRzcy5cbiAqIEBwYXJhbSB7bnVtYmVyfSBzdHJpZGUgU3RyaWRlLlxuICogQHBhcmFtIHtudW1iZXJ9IHRvbGVyYW5jZSBUb2xlcmFuY2UuXG4gKiBAcGFyYW0ge0FycmF5PG51bWJlcj59IHNpbXBsaWZpZWRGbGF0Q29vcmRpbmF0ZXMgU2ltcGxpZmllZCBmbGF0XG4gKiAgICAgY29vcmRpbmF0ZXMuXG4gKiBAcGFyYW0ge251bWJlcn0gc2ltcGxpZmllZE9mZnNldCBTaW1wbGlmaWVkIG9mZnNldC5cbiAqIEBwYXJhbSB7QXJyYXk8QXJyYXk8bnVtYmVyPj59IHNpbXBsaWZpZWRFbmRzcyBTaW1wbGlmaWVkIGVuZHNzLlxuICogQHJldHVybiB7bnVtYmVyfSBTaW1wbGlmaWVkIG9mZnNldC5cbiAqL1xuXG5leHBvcnQgZnVuY3Rpb24gcXVhbnRpemVNdWx0aUFycmF5KGZsYXRDb29yZGluYXRlcywgb2Zmc2V0LCBlbmRzcywgc3RyaWRlLCB0b2xlcmFuY2UsIHNpbXBsaWZpZWRGbGF0Q29vcmRpbmF0ZXMsIHNpbXBsaWZpZWRPZmZzZXQsIHNpbXBsaWZpZWRFbmRzcykge1xuICBmb3IgKHZhciBpID0gMCwgaWkgPSBlbmRzcy5sZW5ndGg7IGkgPCBpaTsgKytpKSB7XG4gICAgdmFyIGVuZHMgPSBlbmRzc1tpXTtcbiAgICB2YXIgc2ltcGxpZmllZEVuZHMgPSBbXTtcbiAgICBzaW1wbGlmaWVkT2Zmc2V0ID0gcXVhbnRpemVBcnJheShmbGF0Q29vcmRpbmF0ZXMsIG9mZnNldCwgZW5kcywgc3RyaWRlLCB0b2xlcmFuY2UsIHNpbXBsaWZpZWRGbGF0Q29vcmRpbmF0ZXMsIHNpbXBsaWZpZWRPZmZzZXQsIHNpbXBsaWZpZWRFbmRzKTtcbiAgICBzaW1wbGlmaWVkRW5kc3MucHVzaChzaW1wbGlmaWVkRW5kcyk7XG4gICAgb2Zmc2V0ID0gZW5kc1tlbmRzLmxlbmd0aCAtIDFdO1xuICB9XG5cbiAgcmV0dXJuIHNpbXBsaWZpZWRPZmZzZXQ7XG59IiwiLyoqXG4gKiBAbW9kdWxlIG9sL2dlb20vZmxhdC9pbmZsYXRlXG4gKi9cblxuLyoqXG4gKiBAcGFyYW0ge0FycmF5PG51bWJlcj59IGZsYXRDb29yZGluYXRlcyBGbGF0IGNvb3JkaW5hdGVzLlxuICogQHBhcmFtIHtudW1iZXJ9IG9mZnNldCBPZmZzZXQuXG4gKiBAcGFyYW0ge251bWJlcn0gZW5kIEVuZC5cbiAqIEBwYXJhbSB7bnVtYmVyfSBzdHJpZGUgU3RyaWRlLlxuICogQHBhcmFtIHtBcnJheTxpbXBvcnQoXCIuLi8uLi9jb29yZGluYXRlLmpzXCIpLkNvb3JkaW5hdGU+PX0gb3B0X2Nvb3JkaW5hdGVzIENvb3JkaW5hdGVzLlxuICogQHJldHVybiB7QXJyYXk8aW1wb3J0KFwiLi4vLi4vY29vcmRpbmF0ZS5qc1wiKS5Db29yZGluYXRlPn0gQ29vcmRpbmF0ZXMuXG4gKi9cbmV4cG9ydCBmdW5jdGlvbiBpbmZsYXRlQ29vcmRpbmF0ZXMoZmxhdENvb3JkaW5hdGVzLCBvZmZzZXQsIGVuZCwgc3RyaWRlLCBvcHRfY29vcmRpbmF0ZXMpIHtcbiAgdmFyIGNvb3JkaW5hdGVzID0gb3B0X2Nvb3JkaW5hdGVzICE9PSB1bmRlZmluZWQgPyBvcHRfY29vcmRpbmF0ZXMgOiBbXTtcbiAgdmFyIGkgPSAwO1xuXG4gIGZvciAodmFyIGogPSBvZmZzZXQ7IGogPCBlbmQ7IGogKz0gc3RyaWRlKSB7XG4gICAgY29vcmRpbmF0ZXNbaSsrXSA9IGZsYXRDb29yZGluYXRlcy5zbGljZShqLCBqICsgc3RyaWRlKTtcbiAgfVxuXG4gIGNvb3JkaW5hdGVzLmxlbmd0aCA9IGk7XG4gIHJldHVybiBjb29yZGluYXRlcztcbn1cbi8qKlxuICogQHBhcmFtIHtBcnJheTxudW1iZXI+fSBmbGF0Q29vcmRpbmF0ZXMgRmxhdCBjb29yZGluYXRlcy5cbiAqIEBwYXJhbSB7bnVtYmVyfSBvZmZzZXQgT2Zmc2V0LlxuICogQHBhcmFtIHtBcnJheTxudW1iZXI+fSBlbmRzIEVuZHMuXG4gKiBAcGFyYW0ge251bWJlcn0gc3RyaWRlIFN0cmlkZS5cbiAqIEBwYXJhbSB7QXJyYXk8QXJyYXk8aW1wb3J0KFwiLi4vLi4vY29vcmRpbmF0ZS5qc1wiKS5Db29yZGluYXRlPj49fSBvcHRfY29vcmRpbmF0ZXNzIENvb3JkaW5hdGVzcy5cbiAqIEByZXR1cm4ge0FycmF5PEFycmF5PGltcG9ydChcIi4uLy4uL2Nvb3JkaW5hdGUuanNcIikuQ29vcmRpbmF0ZT4+fSBDb29yZGluYXRlc3MuXG4gKi9cblxuZXhwb3J0IGZ1bmN0aW9uIGluZmxhdGVDb29yZGluYXRlc0FycmF5KGZsYXRDb29yZGluYXRlcywgb2Zmc2V0LCBlbmRzLCBzdHJpZGUsIG9wdF9jb29yZGluYXRlc3MpIHtcbiAgdmFyIGNvb3JkaW5hdGVzcyA9IG9wdF9jb29yZGluYXRlc3MgIT09IHVuZGVmaW5lZCA/IG9wdF9jb29yZGluYXRlc3MgOiBbXTtcbiAgdmFyIGkgPSAwO1xuXG4gIGZvciAodmFyIGogPSAwLCBqaiA9IGVuZHMubGVuZ3RoOyBqIDwgamo7ICsraikge1xuICAgIHZhciBlbmQgPSBlbmRzW2pdO1xuICAgIGNvb3JkaW5hdGVzc1tpKytdID0gaW5mbGF0ZUNvb3JkaW5hdGVzKGZsYXRDb29yZGluYXRlcywgb2Zmc2V0LCBlbmQsIHN0cmlkZSwgY29vcmRpbmF0ZXNzW2ldKTtcbiAgICBvZmZzZXQgPSBlbmQ7XG4gIH1cblxuICBjb29yZGluYXRlc3MubGVuZ3RoID0gaTtcbiAgcmV0dXJuIGNvb3JkaW5hdGVzcztcbn1cbi8qKlxuICogQHBhcmFtIHtBcnJheTxudW1iZXI+fSBmbGF0Q29vcmRpbmF0ZXMgRmxhdCBjb29yZGluYXRlcy5cbiAqIEBwYXJhbSB7bnVtYmVyfSBvZmZzZXQgT2Zmc2V0LlxuICogQHBhcmFtIHtBcnJheTxBcnJheTxudW1iZXI+Pn0gZW5kc3MgRW5kc3MuXG4gKiBAcGFyYW0ge251bWJlcn0gc3RyaWRlIFN0cmlkZS5cbiAqIEBwYXJhbSB7QXJyYXk8QXJyYXk8QXJyYXk8aW1wb3J0KFwiLi4vLi4vY29vcmRpbmF0ZS5qc1wiKS5Db29yZGluYXRlPj4+PX0gb3B0X2Nvb3JkaW5hdGVzc3NcbiAqICAgICBDb29yZGluYXRlc3NzLlxuICogQHJldHVybiB7QXJyYXk8QXJyYXk8QXJyYXk8aW1wb3J0KFwiLi4vLi4vY29vcmRpbmF0ZS5qc1wiKS5Db29yZGluYXRlPj4+fSBDb29yZGluYXRlc3NzLlxuICovXG5cbmV4cG9ydCBmdW5jdGlvbiBpbmZsYXRlTXVsdGlDb29yZGluYXRlc0FycmF5KGZsYXRDb29yZGluYXRlcywgb2Zmc2V0LCBlbmRzcywgc3RyaWRlLCBvcHRfY29vcmRpbmF0ZXNzcykge1xuICB2YXIgY29vcmRpbmF0ZXNzcyA9IG9wdF9jb29yZGluYXRlc3NzICE9PSB1bmRlZmluZWQgPyBvcHRfY29vcmRpbmF0ZXNzcyA6IFtdO1xuICB2YXIgaSA9IDA7XG5cbiAgZm9yICh2YXIgaiA9IDAsIGpqID0gZW5kc3MubGVuZ3RoOyBqIDwgamo7ICsraikge1xuICAgIHZhciBlbmRzID0gZW5kc3Nbal07XG4gICAgY29vcmRpbmF0ZXNzc1tpKytdID0gaW5mbGF0ZUNvb3JkaW5hdGVzQXJyYXkoZmxhdENvb3JkaW5hdGVzLCBvZmZzZXQsIGVuZHMsIHN0cmlkZSwgY29vcmRpbmF0ZXNzc1tpXSk7XG4gICAgb2Zmc2V0ID0gZW5kc1tlbmRzLmxlbmd0aCAtIDFdO1xuICB9XG5cbiAgY29vcmRpbmF0ZXNzcy5sZW5ndGggPSBpO1xuICByZXR1cm4gY29vcmRpbmF0ZXNzcztcbn0iLCIvKipcbiAqIEBtb2R1bGUgb2wvZ2VvbS9mbGF0L2FyZWFcbiAqL1xuXG4vKipcbiAqIEBwYXJhbSB7QXJyYXk8bnVtYmVyPn0gZmxhdENvb3JkaW5hdGVzIEZsYXQgY29vcmRpbmF0ZXMuXG4gKiBAcGFyYW0ge251bWJlcn0gb2Zmc2V0IE9mZnNldC5cbiAqIEBwYXJhbSB7bnVtYmVyfSBlbmQgRW5kLlxuICogQHBhcmFtIHtudW1iZXJ9IHN0cmlkZSBTdHJpZGUuXG4gKiBAcmV0dXJuIHtudW1iZXJ9IEFyZWEuXG4gKi9cbmV4cG9ydCBmdW5jdGlvbiBsaW5lYXJSaW5nKGZsYXRDb29yZGluYXRlcywgb2Zmc2V0LCBlbmQsIHN0cmlkZSkge1xuICB2YXIgdHdpY2VBcmVhID0gMDtcbiAgdmFyIHgxID0gZmxhdENvb3JkaW5hdGVzW2VuZCAtIHN0cmlkZV07XG4gIHZhciB5MSA9IGZsYXRDb29yZGluYXRlc1tlbmQgLSBzdHJpZGUgKyAxXTtcblxuICBmb3IgKDsgb2Zmc2V0IDwgZW5kOyBvZmZzZXQgKz0gc3RyaWRlKSB7XG4gICAgdmFyIHgyID0gZmxhdENvb3JkaW5hdGVzW29mZnNldF07XG4gICAgdmFyIHkyID0gZmxhdENvb3JkaW5hdGVzW29mZnNldCArIDFdO1xuICAgIHR3aWNlQXJlYSArPSB5MSAqIHgyIC0geDEgKiB5MjtcbiAgICB4MSA9IHgyO1xuICAgIHkxID0geTI7XG4gIH1cblxuICByZXR1cm4gdHdpY2VBcmVhIC8gMjtcbn1cbi8qKlxuICogQHBhcmFtIHtBcnJheTxudW1iZXI+fSBmbGF0Q29vcmRpbmF0ZXMgRmxhdCBjb29yZGluYXRlcy5cbiAqIEBwYXJhbSB7bnVtYmVyfSBvZmZzZXQgT2Zmc2V0LlxuICogQHBhcmFtIHtBcnJheTxudW1iZXI+fSBlbmRzIEVuZHMuXG4gKiBAcGFyYW0ge251bWJlcn0gc3RyaWRlIFN0cmlkZS5cbiAqIEByZXR1cm4ge251bWJlcn0gQXJlYS5cbiAqL1xuXG5leHBvcnQgZnVuY3Rpb24gbGluZWFyUmluZ3MoZmxhdENvb3JkaW5hdGVzLCBvZmZzZXQsIGVuZHMsIHN0cmlkZSkge1xuICB2YXIgYXJlYSA9IDA7XG5cbiAgZm9yICh2YXIgaSA9IDAsIGlpID0gZW5kcy5sZW5ndGg7IGkgPCBpaTsgKytpKSB7XG4gICAgdmFyIGVuZCA9IGVuZHNbaV07XG4gICAgYXJlYSArPSBsaW5lYXJSaW5nKGZsYXRDb29yZGluYXRlcywgb2Zmc2V0LCBlbmQsIHN0cmlkZSk7XG4gICAgb2Zmc2V0ID0gZW5kO1xuICB9XG5cbiAgcmV0dXJuIGFyZWE7XG59XG4vKipcbiAqIEBwYXJhbSB7QXJyYXk8bnVtYmVyPn0gZmxhdENvb3JkaW5hdGVzIEZsYXQgY29vcmRpbmF0ZXMuXG4gKiBAcGFyYW0ge251bWJlcn0gb2Zmc2V0IE9mZnNldC5cbiAqIEBwYXJhbSB7QXJyYXk8QXJyYXk8bnVtYmVyPj59IGVuZHNzIEVuZHNzLlxuICogQHBhcmFtIHtudW1iZXJ9IHN0cmlkZSBTdHJpZGUuXG4gKiBAcmV0dXJuIHtudW1iZXJ9IEFyZWEuXG4gKi9cblxuZXhwb3J0IGZ1bmN0aW9uIGxpbmVhclJpbmdzcyhmbGF0Q29vcmRpbmF0ZXMsIG9mZnNldCwgZW5kc3MsIHN0cmlkZSkge1xuICB2YXIgYXJlYSA9IDA7XG5cbiAgZm9yICh2YXIgaSA9IDAsIGlpID0gZW5kc3MubGVuZ3RoOyBpIDwgaWk7ICsraSkge1xuICAgIHZhciBlbmRzID0gZW5kc3NbaV07XG4gICAgYXJlYSArPSBsaW5lYXJSaW5ncyhmbGF0Q29vcmRpbmF0ZXMsIG9mZnNldCwgZW5kcywgc3RyaWRlKTtcbiAgICBvZmZzZXQgPSBlbmRzW2VuZHMubGVuZ3RoIC0gMV07XG4gIH1cblxuICByZXR1cm4gYXJlYTtcbn0iLCJ2YXIgX19leHRlbmRzID0gdGhpcyAmJiB0aGlzLl9fZXh0ZW5kcyB8fCBmdW5jdGlvbiAoKSB7XG4gIHZhciBfZXh0ZW5kU3RhdGljcyA9IGZ1bmN0aW9uIGV4dGVuZFN0YXRpY3MoZCwgYikge1xuICAgIF9leHRlbmRTdGF0aWNzID0gT2JqZWN0LnNldFByb3RvdHlwZU9mIHx8IHtcbiAgICAgIF9fcHJvdG9fXzogW11cbiAgICB9IGluc3RhbmNlb2YgQXJyYXkgJiYgZnVuY3Rpb24gKGQsIGIpIHtcbiAgICAgIGQuX19wcm90b19fID0gYjtcbiAgICB9IHx8IGZ1bmN0aW9uIChkLCBiKSB7XG4gICAgICBmb3IgKHZhciBwIGluIGIpIHtcbiAgICAgICAgaWYgKE9iamVjdC5wcm90b3R5cGUuaGFzT3duUHJvcGVydHkuY2FsbChiLCBwKSkgZFtwXSA9IGJbcF07XG4gICAgICB9XG4gICAgfTtcblxuICAgIHJldHVybiBfZXh0ZW5kU3RhdGljcyhkLCBiKTtcbiAgfTtcblxuICByZXR1cm4gZnVuY3Rpb24gKGQsIGIpIHtcbiAgICBfZXh0ZW5kU3RhdGljcyhkLCBiKTtcblxuICAgIGZ1bmN0aW9uIF9fKCkge1xuICAgICAgdGhpcy5jb25zdHJ1Y3RvciA9IGQ7XG4gICAgfVxuXG4gICAgZC5wcm90b3R5cGUgPSBiID09PSBudWxsID8gT2JqZWN0LmNyZWF0ZShiKSA6IChfXy5wcm90b3R5cGUgPSBiLnByb3RvdHlwZSwgbmV3IF9fKCkpO1xuICB9O1xufSgpO1xuLyoqXG4gKiBAbW9kdWxlIG9sL2dlb20vTGluZWFyUmluZ1xuICovXG5cblxuaW1wb3J0IEdlb21ldHJ5TGF5b3V0IGZyb20gJy4vR2VvbWV0cnlMYXlvdXQuanMnO1xuaW1wb3J0IEdlb21ldHJ5VHlwZSBmcm9tICcuL0dlb21ldHJ5VHlwZS5qcyc7XG5pbXBvcnQgU2ltcGxlR2VvbWV0cnkgZnJvbSAnLi9TaW1wbGVHZW9tZXRyeS5qcyc7XG5pbXBvcnQgeyBhc3NpZ25DbG9zZXN0UG9pbnQsIG1heFNxdWFyZWREZWx0YSB9IGZyb20gJy4vZmxhdC9jbG9zZXN0LmpzJztcbmltcG9ydCB7IGNsb3Nlc3RTcXVhcmVkRGlzdGFuY2VYWSB9IGZyb20gJy4uL2V4dGVudC5qcyc7XG5pbXBvcnQgeyBkZWZsYXRlQ29vcmRpbmF0ZXMgfSBmcm9tICcuL2ZsYXQvZGVmbGF0ZS5qcyc7XG5pbXBvcnQgeyBkb3VnbGFzUGV1Y2tlciB9IGZyb20gJy4vZmxhdC9zaW1wbGlmeS5qcyc7XG5pbXBvcnQgeyBpbmZsYXRlQ29vcmRpbmF0ZXMgfSBmcm9tICcuL2ZsYXQvaW5mbGF0ZS5qcyc7XG5pbXBvcnQgeyBsaW5lYXJSaW5nIGFzIGxpbmVhclJpbmdBcmVhIH0gZnJvbSAnLi9mbGF0L2FyZWEuanMnO1xuLyoqXG4gKiBAY2xhc3NkZXNjXG4gKiBMaW5lYXIgcmluZyBnZW9tZXRyeS4gT25seSB1c2VkIGFzIHBhcnQgb2YgcG9seWdvbjsgY2Fubm90IGJlIHJlbmRlcmVkXG4gKiBvbiBpdHMgb3duLlxuICpcbiAqIEBhcGlcbiAqL1xuXG52YXIgTGluZWFyUmluZyA9XG4vKiogQGNsYXNzICovXG5mdW5jdGlvbiAoX3N1cGVyKSB7XG4gIF9fZXh0ZW5kcyhMaW5lYXJSaW5nLCBfc3VwZXIpO1xuICAvKipcbiAgICogQHBhcmFtIHtBcnJheTxpbXBvcnQoXCIuLi9jb29yZGluYXRlLmpzXCIpLkNvb3JkaW5hdGU+fEFycmF5PG51bWJlcj59IGNvb3JkaW5hdGVzIENvb3JkaW5hdGVzLlxuICAgKiAgICAgRm9yIGludGVybmFsIHVzZSwgZmxhdCBjb29yZGluYXRlcyBpbiBjb21iaW5hdGlvbiB3aXRoIGBvcHRfbGF5b3V0YCBhcmUgYWxzbyBhY2NlcHRlZC5cbiAgICogQHBhcmFtIHtpbXBvcnQoXCIuL0dlb21ldHJ5TGF5b3V0LmpzXCIpLmRlZmF1bHQ9fSBvcHRfbGF5b3V0IExheW91dC5cbiAgICovXG5cblxuICBmdW5jdGlvbiBMaW5lYXJSaW5nKGNvb3JkaW5hdGVzLCBvcHRfbGF5b3V0KSB7XG4gICAgdmFyIF90aGlzID0gX3N1cGVyLmNhbGwodGhpcykgfHwgdGhpcztcbiAgICAvKipcbiAgICAgKiBAcHJpdmF0ZVxuICAgICAqIEB0eXBlIHtudW1iZXJ9XG4gICAgICovXG5cblxuICAgIF90aGlzLm1heERlbHRhXyA9IC0xO1xuICAgIC8qKlxuICAgICAqIEBwcml2YXRlXG4gICAgICogQHR5cGUge251bWJlcn1cbiAgICAgKi9cblxuICAgIF90aGlzLm1heERlbHRhUmV2aXNpb25fID0gLTE7XG5cbiAgICBpZiAob3B0X2xheW91dCAhPT0gdW5kZWZpbmVkICYmICFBcnJheS5pc0FycmF5KGNvb3JkaW5hdGVzWzBdKSkge1xuICAgICAgX3RoaXMuc2V0RmxhdENvb3JkaW5hdGVzKG9wdF9sYXlvdXQsXG4gICAgICAvKiogQHR5cGUge0FycmF5PG51bWJlcj59ICovXG4gICAgICBjb29yZGluYXRlcyk7XG4gICAgfSBlbHNlIHtcbiAgICAgIF90aGlzLnNldENvb3JkaW5hdGVzKFxuICAgICAgLyoqIEB0eXBlIHtBcnJheTxpbXBvcnQoXCIuLi9jb29yZGluYXRlLmpzXCIpLkNvb3JkaW5hdGU+fSAqL1xuICAgICAgY29vcmRpbmF0ZXMsIG9wdF9sYXlvdXQpO1xuICAgIH1cblxuICAgIHJldHVybiBfdGhpcztcbiAgfVxuICAvKipcbiAgICogTWFrZSBhIGNvbXBsZXRlIGNvcHkgb2YgdGhlIGdlb21ldHJ5LlxuICAgKiBAcmV0dXJuIHshTGluZWFyUmluZ30gQ2xvbmUuXG4gICAqIEBhcGlcbiAgICovXG5cblxuICBMaW5lYXJSaW5nLnByb3RvdHlwZS5jbG9uZSA9IGZ1bmN0aW9uICgpIHtcbiAgICByZXR1cm4gbmV3IExpbmVhclJpbmcodGhpcy5mbGF0Q29vcmRpbmF0ZXMuc2xpY2UoKSwgdGhpcy5sYXlvdXQpO1xuICB9O1xuICAvKipcbiAgICogQHBhcmFtIHtudW1iZXJ9IHggWC5cbiAgICogQHBhcmFtIHtudW1iZXJ9IHkgWS5cbiAgICogQHBhcmFtIHtpbXBvcnQoXCIuLi9jb29yZGluYXRlLmpzXCIpLkNvb3JkaW5hdGV9IGNsb3Nlc3RQb2ludCBDbG9zZXN0IHBvaW50LlxuICAgKiBAcGFyYW0ge251bWJlcn0gbWluU3F1YXJlZERpc3RhbmNlIE1pbmltdW0gc3F1YXJlZCBkaXN0YW5jZS5cbiAgICogQHJldHVybiB7bnVtYmVyfSBNaW5pbXVtIHNxdWFyZWQgZGlzdGFuY2UuXG4gICAqL1xuXG5cbiAgTGluZWFyUmluZy5wcm90b3R5cGUuY2xvc2VzdFBvaW50WFkgPSBmdW5jdGlvbiAoeCwgeSwgY2xvc2VzdFBvaW50LCBtaW5TcXVhcmVkRGlzdGFuY2UpIHtcbiAgICBpZiAobWluU3F1YXJlZERpc3RhbmNlIDwgY2xvc2VzdFNxdWFyZWREaXN0YW5jZVhZKHRoaXMuZ2V0RXh0ZW50KCksIHgsIHkpKSB7XG4gICAgICByZXR1cm4gbWluU3F1YXJlZERpc3RhbmNlO1xuICAgIH1cblxuICAgIGlmICh0aGlzLm1heERlbHRhUmV2aXNpb25fICE9IHRoaXMuZ2V0UmV2aXNpb24oKSkge1xuICAgICAgdGhpcy5tYXhEZWx0YV8gPSBNYXRoLnNxcnQobWF4U3F1YXJlZERlbHRhKHRoaXMuZmxhdENvb3JkaW5hdGVzLCAwLCB0aGlzLmZsYXRDb29yZGluYXRlcy5sZW5ndGgsIHRoaXMuc3RyaWRlLCAwKSk7XG4gICAgICB0aGlzLm1heERlbHRhUmV2aXNpb25fID0gdGhpcy5nZXRSZXZpc2lvbigpO1xuICAgIH1cblxuICAgIHJldHVybiBhc3NpZ25DbG9zZXN0UG9pbnQodGhpcy5mbGF0Q29vcmRpbmF0ZXMsIDAsIHRoaXMuZmxhdENvb3JkaW5hdGVzLmxlbmd0aCwgdGhpcy5zdHJpZGUsIHRoaXMubWF4RGVsdGFfLCB0cnVlLCB4LCB5LCBjbG9zZXN0UG9pbnQsIG1pblNxdWFyZWREaXN0YW5jZSk7XG4gIH07XG4gIC8qKlxuICAgKiBSZXR1cm4gdGhlIGFyZWEgb2YgdGhlIGxpbmVhciByaW5nIG9uIHByb2plY3RlZCBwbGFuZS5cbiAgICogQHJldHVybiB7bnVtYmVyfSBBcmVhIChvbiBwcm9qZWN0ZWQgcGxhbmUpLlxuICAgKiBAYXBpXG4gICAqL1xuXG5cbiAgTGluZWFyUmluZy5wcm90b3R5cGUuZ2V0QXJlYSA9IGZ1bmN0aW9uICgpIHtcbiAgICByZXR1cm4gbGluZWFyUmluZ0FyZWEodGhpcy5mbGF0Q29vcmRpbmF0ZXMsIDAsIHRoaXMuZmxhdENvb3JkaW5hdGVzLmxlbmd0aCwgdGhpcy5zdHJpZGUpO1xuICB9O1xuICAvKipcbiAgICogUmV0dXJuIHRoZSBjb29yZGluYXRlcyBvZiB0aGUgbGluZWFyIHJpbmcuXG4gICAqIEByZXR1cm4ge0FycmF5PGltcG9ydChcIi4uL2Nvb3JkaW5hdGUuanNcIikuQ29vcmRpbmF0ZT59IENvb3JkaW5hdGVzLlxuICAgKiBAYXBpXG4gICAqL1xuXG5cbiAgTGluZWFyUmluZy5wcm90b3R5cGUuZ2V0Q29vcmRpbmF0ZXMgPSBmdW5jdGlvbiAoKSB7XG4gICAgcmV0dXJuIGluZmxhdGVDb29yZGluYXRlcyh0aGlzLmZsYXRDb29yZGluYXRlcywgMCwgdGhpcy5mbGF0Q29vcmRpbmF0ZXMubGVuZ3RoLCB0aGlzLnN0cmlkZSk7XG4gIH07XG4gIC8qKlxuICAgKiBAcGFyYW0ge251bWJlcn0gc3F1YXJlZFRvbGVyYW5jZSBTcXVhcmVkIHRvbGVyYW5jZS5cbiAgICogQHJldHVybiB7TGluZWFyUmluZ30gU2ltcGxpZmllZCBMaW5lYXJSaW5nLlxuICAgKiBAcHJvdGVjdGVkXG4gICAqL1xuXG5cbiAgTGluZWFyUmluZy5wcm90b3R5cGUuZ2V0U2ltcGxpZmllZEdlb21ldHJ5SW50ZXJuYWwgPSBmdW5jdGlvbiAoc3F1YXJlZFRvbGVyYW5jZSkge1xuICAgIHZhciBzaW1wbGlmaWVkRmxhdENvb3JkaW5hdGVzID0gW107XG4gICAgc2ltcGxpZmllZEZsYXRDb29yZGluYXRlcy5sZW5ndGggPSBkb3VnbGFzUGV1Y2tlcih0aGlzLmZsYXRDb29yZGluYXRlcywgMCwgdGhpcy5mbGF0Q29vcmRpbmF0ZXMubGVuZ3RoLCB0aGlzLnN0cmlkZSwgc3F1YXJlZFRvbGVyYW5jZSwgc2ltcGxpZmllZEZsYXRDb29yZGluYXRlcywgMCk7XG4gICAgcmV0dXJuIG5ldyBMaW5lYXJSaW5nKHNpbXBsaWZpZWRGbGF0Q29vcmRpbmF0ZXMsIEdlb21ldHJ5TGF5b3V0LlhZKTtcbiAgfTtcbiAgLyoqXG4gICAqIEdldCB0aGUgdHlwZSBvZiB0aGlzIGdlb21ldHJ5LlxuICAgKiBAcmV0dXJuIHtpbXBvcnQoXCIuL0dlb21ldHJ5VHlwZS5qc1wiKS5kZWZhdWx0fSBHZW9tZXRyeSB0eXBlLlxuICAgKiBAYXBpXG4gICAqL1xuXG5cbiAgTGluZWFyUmluZy5wcm90b3R5cGUuZ2V0VHlwZSA9IGZ1bmN0aW9uICgpIHtcbiAgICByZXR1cm4gR2VvbWV0cnlUeXBlLkxJTkVBUl9SSU5HO1xuICB9O1xuICAvKipcbiAgICogVGVzdCBpZiB0aGUgZ2VvbWV0cnkgYW5kIHRoZSBwYXNzZWQgZXh0ZW50IGludGVyc2VjdC5cbiAgICogQHBhcmFtIHtpbXBvcnQoXCIuLi9leHRlbnQuanNcIikuRXh0ZW50fSBleHRlbnQgRXh0ZW50LlxuICAgKiBAcmV0dXJuIHtib29sZWFufSBgdHJ1ZWAgaWYgdGhlIGdlb21ldHJ5IGFuZCB0aGUgZXh0ZW50IGludGVyc2VjdC5cbiAgICogQGFwaVxuICAgKi9cblxuXG4gIExpbmVhclJpbmcucHJvdG90eXBlLmludGVyc2VjdHNFeHRlbnQgPSBmdW5jdGlvbiAoZXh0ZW50KSB7XG4gICAgcmV0dXJuIGZhbHNlO1xuICB9O1xuICAvKipcbiAgICogU2V0IHRoZSBjb29yZGluYXRlcyBvZiB0aGUgbGluZWFyIHJpbmcuXG4gICAqIEBwYXJhbSB7IUFycmF5PGltcG9ydChcIi4uL2Nvb3JkaW5hdGUuanNcIikuQ29vcmRpbmF0ZT59IGNvb3JkaW5hdGVzIENvb3JkaW5hdGVzLlxuICAgKiBAcGFyYW0ge2ltcG9ydChcIi4vR2VvbWV0cnlMYXlvdXQuanNcIikuZGVmYXVsdD19IG9wdF9sYXlvdXQgTGF5b3V0LlxuICAgKiBAYXBpXG4gICAqL1xuXG5cbiAgTGluZWFyUmluZy5wcm90b3R5cGUuc2V0Q29vcmRpbmF0ZXMgPSBmdW5jdGlvbiAoY29vcmRpbmF0ZXMsIG9wdF9sYXlvdXQpIHtcbiAgICB0aGlzLnNldExheW91dChvcHRfbGF5b3V0LCBjb29yZGluYXRlcywgMSk7XG5cbiAgICBpZiAoIXRoaXMuZmxhdENvb3JkaW5hdGVzKSB7XG4gICAgICB0aGlzLmZsYXRDb29yZGluYXRlcyA9IFtdO1xuICAgIH1cblxuICAgIHRoaXMuZmxhdENvb3JkaW5hdGVzLmxlbmd0aCA9IGRlZmxhdGVDb29yZGluYXRlcyh0aGlzLmZsYXRDb29yZGluYXRlcywgMCwgY29vcmRpbmF0ZXMsIHRoaXMuc3RyaWRlKTtcbiAgICB0aGlzLmNoYW5nZWQoKTtcbiAgfTtcblxuICByZXR1cm4gTGluZWFyUmluZztcbn0oU2ltcGxlR2VvbWV0cnkpO1xuXG5leHBvcnQgZGVmYXVsdCBMaW5lYXJSaW5nOyIsInZhciBfX2V4dGVuZHMgPSB0aGlzICYmIHRoaXMuX19leHRlbmRzIHx8IGZ1bmN0aW9uICgpIHtcbiAgdmFyIF9leHRlbmRTdGF0aWNzID0gZnVuY3Rpb24gZXh0ZW5kU3RhdGljcyhkLCBiKSB7XG4gICAgX2V4dGVuZFN0YXRpY3MgPSBPYmplY3Quc2V0UHJvdG90eXBlT2YgfHwge1xuICAgICAgX19wcm90b19fOiBbXVxuICAgIH0gaW5zdGFuY2VvZiBBcnJheSAmJiBmdW5jdGlvbiAoZCwgYikge1xuICAgICAgZC5fX3Byb3RvX18gPSBiO1xuICAgIH0gfHwgZnVuY3Rpb24gKGQsIGIpIHtcbiAgICAgIGZvciAodmFyIHAgaW4gYikge1xuICAgICAgICBpZiAoT2JqZWN0LnByb3RvdHlwZS5oYXNPd25Qcm9wZXJ0eS5jYWxsKGIsIHApKSBkW3BdID0gYltwXTtcbiAgICAgIH1cbiAgICB9O1xuXG4gICAgcmV0dXJuIF9leHRlbmRTdGF0aWNzKGQsIGIpO1xuICB9O1xuXG4gIHJldHVybiBmdW5jdGlvbiAoZCwgYikge1xuICAgIF9leHRlbmRTdGF0aWNzKGQsIGIpO1xuXG4gICAgZnVuY3Rpb24gX18oKSB7XG4gICAgICB0aGlzLmNvbnN0cnVjdG9yID0gZDtcbiAgICB9XG5cbiAgICBkLnByb3RvdHlwZSA9IGIgPT09IG51bGwgPyBPYmplY3QuY3JlYXRlKGIpIDogKF9fLnByb3RvdHlwZSA9IGIucHJvdG90eXBlLCBuZXcgX18oKSk7XG4gIH07XG59KCk7XG4vKipcbiAqIEBtb2R1bGUgb2wvZ2VvbS9Qb2ludFxuICovXG5cblxuaW1wb3J0IEdlb21ldHJ5VHlwZSBmcm9tICcuL0dlb21ldHJ5VHlwZS5qcyc7XG5pbXBvcnQgU2ltcGxlR2VvbWV0cnkgZnJvbSAnLi9TaW1wbGVHZW9tZXRyeS5qcyc7XG5pbXBvcnQgeyBjb250YWluc1hZLCBjcmVhdGVPclVwZGF0ZUZyb21Db29yZGluYXRlIH0gZnJvbSAnLi4vZXh0ZW50LmpzJztcbmltcG9ydCB7IGRlZmxhdGVDb29yZGluYXRlIH0gZnJvbSAnLi9mbGF0L2RlZmxhdGUuanMnO1xuaW1wb3J0IHsgc3F1YXJlZERpc3RhbmNlIGFzIHNxdWFyZWREeCB9IGZyb20gJy4uL21hdGguanMnO1xuLyoqXG4gKiBAY2xhc3NkZXNjXG4gKiBQb2ludCBnZW9tZXRyeS5cbiAqXG4gKiBAYXBpXG4gKi9cblxudmFyIFBvaW50ID1cbi8qKiBAY2xhc3MgKi9cbmZ1bmN0aW9uIChfc3VwZXIpIHtcbiAgX19leHRlbmRzKFBvaW50LCBfc3VwZXIpO1xuICAvKipcbiAgICogQHBhcmFtIHtpbXBvcnQoXCIuLi9jb29yZGluYXRlLmpzXCIpLkNvb3JkaW5hdGV9IGNvb3JkaW5hdGVzIENvb3JkaW5hdGVzLlxuICAgKiBAcGFyYW0ge2ltcG9ydChcIi4vR2VvbWV0cnlMYXlvdXQuanNcIikuZGVmYXVsdD19IG9wdF9sYXlvdXQgTGF5b3V0LlxuICAgKi9cblxuXG4gIGZ1bmN0aW9uIFBvaW50KGNvb3JkaW5hdGVzLCBvcHRfbGF5b3V0KSB7XG4gICAgdmFyIF90aGlzID0gX3N1cGVyLmNhbGwodGhpcykgfHwgdGhpcztcblxuICAgIF90aGlzLnNldENvb3JkaW5hdGVzKGNvb3JkaW5hdGVzLCBvcHRfbGF5b3V0KTtcblxuICAgIHJldHVybiBfdGhpcztcbiAgfVxuICAvKipcbiAgICogTWFrZSBhIGNvbXBsZXRlIGNvcHkgb2YgdGhlIGdlb21ldHJ5LlxuICAgKiBAcmV0dXJuIHshUG9pbnR9IENsb25lLlxuICAgKiBAYXBpXG4gICAqL1xuXG5cbiAgUG9pbnQucHJvdG90eXBlLmNsb25lID0gZnVuY3Rpb24gKCkge1xuICAgIHZhciBwb2ludCA9IG5ldyBQb2ludCh0aGlzLmZsYXRDb29yZGluYXRlcy5zbGljZSgpLCB0aGlzLmxheW91dCk7XG4gICAgcG9pbnQuYXBwbHlQcm9wZXJ0aWVzKHRoaXMpO1xuICAgIHJldHVybiBwb2ludDtcbiAgfTtcbiAgLyoqXG4gICAqIEBwYXJhbSB7bnVtYmVyfSB4IFguXG4gICAqIEBwYXJhbSB7bnVtYmVyfSB5IFkuXG4gICAqIEBwYXJhbSB7aW1wb3J0KFwiLi4vY29vcmRpbmF0ZS5qc1wiKS5Db29yZGluYXRlfSBjbG9zZXN0UG9pbnQgQ2xvc2VzdCBwb2ludC5cbiAgICogQHBhcmFtIHtudW1iZXJ9IG1pblNxdWFyZWREaXN0YW5jZSBNaW5pbXVtIHNxdWFyZWQgZGlzdGFuY2UuXG4gICAqIEByZXR1cm4ge251bWJlcn0gTWluaW11bSBzcXVhcmVkIGRpc3RhbmNlLlxuICAgKi9cblxuXG4gIFBvaW50LnByb3RvdHlwZS5jbG9zZXN0UG9pbnRYWSA9IGZ1bmN0aW9uICh4LCB5LCBjbG9zZXN0UG9pbnQsIG1pblNxdWFyZWREaXN0YW5jZSkge1xuICAgIHZhciBmbGF0Q29vcmRpbmF0ZXMgPSB0aGlzLmZsYXRDb29yZGluYXRlcztcbiAgICB2YXIgc3F1YXJlZERpc3RhbmNlID0gc3F1YXJlZER4KHgsIHksIGZsYXRDb29yZGluYXRlc1swXSwgZmxhdENvb3JkaW5hdGVzWzFdKTtcblxuICAgIGlmIChzcXVhcmVkRGlzdGFuY2UgPCBtaW5TcXVhcmVkRGlzdGFuY2UpIHtcbiAgICAgIHZhciBzdHJpZGUgPSB0aGlzLnN0cmlkZTtcblxuICAgICAgZm9yICh2YXIgaSA9IDA7IGkgPCBzdHJpZGU7ICsraSkge1xuICAgICAgICBjbG9zZXN0UG9pbnRbaV0gPSBmbGF0Q29vcmRpbmF0ZXNbaV07XG4gICAgICB9XG5cbiAgICAgIGNsb3Nlc3RQb2ludC5sZW5ndGggPSBzdHJpZGU7XG4gICAgICByZXR1cm4gc3F1YXJlZERpc3RhbmNlO1xuICAgIH0gZWxzZSB7XG4gICAgICByZXR1cm4gbWluU3F1YXJlZERpc3RhbmNlO1xuICAgIH1cbiAgfTtcbiAgLyoqXG4gICAqIFJldHVybiB0aGUgY29vcmRpbmF0ZSBvZiB0aGUgcG9pbnQuXG4gICAqIEByZXR1cm4ge2ltcG9ydChcIi4uL2Nvb3JkaW5hdGUuanNcIikuQ29vcmRpbmF0ZX0gQ29vcmRpbmF0ZXMuXG4gICAqIEBhcGlcbiAgICovXG5cblxuICBQb2ludC5wcm90b3R5cGUuZ2V0Q29vcmRpbmF0ZXMgPSBmdW5jdGlvbiAoKSB7XG4gICAgcmV0dXJuICF0aGlzLmZsYXRDb29yZGluYXRlcyA/IFtdIDogdGhpcy5mbGF0Q29vcmRpbmF0ZXMuc2xpY2UoKTtcbiAgfTtcbiAgLyoqXG4gICAqIEBwYXJhbSB7aW1wb3J0KFwiLi4vZXh0ZW50LmpzXCIpLkV4dGVudH0gZXh0ZW50IEV4dGVudC5cbiAgICogQHByb3RlY3RlZFxuICAgKiBAcmV0dXJuIHtpbXBvcnQoXCIuLi9leHRlbnQuanNcIikuRXh0ZW50fSBleHRlbnQgRXh0ZW50LlxuICAgKi9cblxuXG4gIFBvaW50LnByb3RvdHlwZS5jb21wdXRlRXh0ZW50ID0gZnVuY3Rpb24gKGV4dGVudCkge1xuICAgIHJldHVybiBjcmVhdGVPclVwZGF0ZUZyb21Db29yZGluYXRlKHRoaXMuZmxhdENvb3JkaW5hdGVzLCBleHRlbnQpO1xuICB9O1xuICAvKipcbiAgICogR2V0IHRoZSB0eXBlIG9mIHRoaXMgZ2VvbWV0cnkuXG4gICAqIEByZXR1cm4ge2ltcG9ydChcIi4vR2VvbWV0cnlUeXBlLmpzXCIpLmRlZmF1bHR9IEdlb21ldHJ5IHR5cGUuXG4gICAqIEBhcGlcbiAgICovXG5cblxuICBQb2ludC5wcm90b3R5cGUuZ2V0VHlwZSA9IGZ1bmN0aW9uICgpIHtcbiAgICByZXR1cm4gR2VvbWV0cnlUeXBlLlBPSU5UO1xuICB9O1xuICAvKipcbiAgICogVGVzdCBpZiB0aGUgZ2VvbWV0cnkgYW5kIHRoZSBwYXNzZWQgZXh0ZW50IGludGVyc2VjdC5cbiAgICogQHBhcmFtIHtpbXBvcnQoXCIuLi9leHRlbnQuanNcIikuRXh0ZW50fSBleHRlbnQgRXh0ZW50LlxuICAgKiBAcmV0dXJuIHtib29sZWFufSBgdHJ1ZWAgaWYgdGhlIGdlb21ldHJ5IGFuZCB0aGUgZXh0ZW50IGludGVyc2VjdC5cbiAgICogQGFwaVxuICAgKi9cblxuXG4gIFBvaW50LnByb3RvdHlwZS5pbnRlcnNlY3RzRXh0ZW50ID0gZnVuY3Rpb24gKGV4dGVudCkge1xuICAgIHJldHVybiBjb250YWluc1hZKGV4dGVudCwgdGhpcy5mbGF0Q29vcmRpbmF0ZXNbMF0sIHRoaXMuZmxhdENvb3JkaW5hdGVzWzFdKTtcbiAgfTtcbiAgLyoqXG4gICAqIEBwYXJhbSB7IUFycmF5PCo+fSBjb29yZGluYXRlcyBDb29yZGluYXRlcy5cbiAgICogQHBhcmFtIHtpbXBvcnQoXCIuL0dlb21ldHJ5TGF5b3V0LmpzXCIpLmRlZmF1bHQ9fSBvcHRfbGF5b3V0IExheW91dC5cbiAgICogQGFwaVxuICAgKi9cblxuXG4gIFBvaW50LnByb3RvdHlwZS5zZXRDb29yZGluYXRlcyA9IGZ1bmN0aW9uIChjb29yZGluYXRlcywgb3B0X2xheW91dCkge1xuICAgIHRoaXMuc2V0TGF5b3V0KG9wdF9sYXlvdXQsIGNvb3JkaW5hdGVzLCAwKTtcblxuICAgIGlmICghdGhpcy5mbGF0Q29vcmRpbmF0ZXMpIHtcbiAgICAgIHRoaXMuZmxhdENvb3JkaW5hdGVzID0gW107XG4gICAgfVxuXG4gICAgdGhpcy5mbGF0Q29vcmRpbmF0ZXMubGVuZ3RoID0gZGVmbGF0ZUNvb3JkaW5hdGUodGhpcy5mbGF0Q29vcmRpbmF0ZXMsIDAsIGNvb3JkaW5hdGVzLCB0aGlzLnN0cmlkZSk7XG4gICAgdGhpcy5jaGFuZ2VkKCk7XG4gIH07XG5cbiAgcmV0dXJuIFBvaW50O1xufShTaW1wbGVHZW9tZXRyeSk7XG5cbmV4cG9ydCBkZWZhdWx0IFBvaW50OyIsIi8qKlxuICogQG1vZHVsZSBvbC9nZW9tL2ZsYXQvY29udGFpbnNcbiAqL1xuaW1wb3J0IHsgZm9yRWFjaENvcm5lciB9IGZyb20gJy4uLy4uL2V4dGVudC5qcyc7XG4vKipcbiAqIEBwYXJhbSB7QXJyYXk8bnVtYmVyPn0gZmxhdENvb3JkaW5hdGVzIEZsYXQgY29vcmRpbmF0ZXMuXG4gKiBAcGFyYW0ge251bWJlcn0gb2Zmc2V0IE9mZnNldC5cbiAqIEBwYXJhbSB7bnVtYmVyfSBlbmQgRW5kLlxuICogQHBhcmFtIHtudW1iZXJ9IHN0cmlkZSBTdHJpZGUuXG4gKiBAcGFyYW0ge2ltcG9ydChcIi4uLy4uL2V4dGVudC5qc1wiKS5FeHRlbnR9IGV4dGVudCBFeHRlbnQuXG4gKiBAcmV0dXJuIHtib29sZWFufSBDb250YWlucyBleHRlbnQuXG4gKi9cblxuZXhwb3J0IGZ1bmN0aW9uIGxpbmVhclJpbmdDb250YWluc0V4dGVudChmbGF0Q29vcmRpbmF0ZXMsIG9mZnNldCwgZW5kLCBzdHJpZGUsIGV4dGVudCkge1xuICB2YXIgb3V0c2lkZSA9IGZvckVhY2hDb3JuZXIoZXh0ZW50LFxuICAvKipcbiAgICogQHBhcmFtIHtpbXBvcnQoXCIuLi8uLi9jb29yZGluYXRlLmpzXCIpLkNvb3JkaW5hdGV9IGNvb3JkaW5hdGUgQ29vcmRpbmF0ZS5cbiAgICogQHJldHVybiB7Ym9vbGVhbn0gQ29udGFpbnMgKHgsIHkpLlxuICAgKi9cbiAgZnVuY3Rpb24gKGNvb3JkaW5hdGUpIHtcbiAgICByZXR1cm4gIWxpbmVhclJpbmdDb250YWluc1hZKGZsYXRDb29yZGluYXRlcywgb2Zmc2V0LCBlbmQsIHN0cmlkZSwgY29vcmRpbmF0ZVswXSwgY29vcmRpbmF0ZVsxXSk7XG4gIH0pO1xuICByZXR1cm4gIW91dHNpZGU7XG59XG4vKipcbiAqIEBwYXJhbSB7QXJyYXk8bnVtYmVyPn0gZmxhdENvb3JkaW5hdGVzIEZsYXQgY29vcmRpbmF0ZXMuXG4gKiBAcGFyYW0ge251bWJlcn0gb2Zmc2V0IE9mZnNldC5cbiAqIEBwYXJhbSB7bnVtYmVyfSBlbmQgRW5kLlxuICogQHBhcmFtIHtudW1iZXJ9IHN0cmlkZSBTdHJpZGUuXG4gKiBAcGFyYW0ge251bWJlcn0geCBYLlxuICogQHBhcmFtIHtudW1iZXJ9IHkgWS5cbiAqIEByZXR1cm4ge2Jvb2xlYW59IENvbnRhaW5zICh4LCB5KS5cbiAqL1xuXG5leHBvcnQgZnVuY3Rpb24gbGluZWFyUmluZ0NvbnRhaW5zWFkoZmxhdENvb3JkaW5hdGVzLCBvZmZzZXQsIGVuZCwgc3RyaWRlLCB4LCB5KSB7XG4gIC8vIGh0dHA6Ly9nZW9tYWxnb3JpdGhtcy5jb20vYTAzLV9pbmNsdXNpb24uaHRtbFxuICAvLyBDb3B5cmlnaHQgMjAwMCBzb2Z0U3VyZmVyLCAyMDEyIERhbiBTdW5kYXlcbiAgLy8gVGhpcyBjb2RlIG1heSBiZSBmcmVlbHkgdXNlZCBhbmQgbW9kaWZpZWQgZm9yIGFueSBwdXJwb3NlXG4gIC8vIHByb3ZpZGluZyB0aGF0IHRoaXMgY29weXJpZ2h0IG5vdGljZSBpcyBpbmNsdWRlZCB3aXRoIGl0LlxuICAvLyBTb2Z0U3VyZmVyIG1ha2VzIG5vIHdhcnJhbnR5IGZvciB0aGlzIGNvZGUsIGFuZCBjYW5ub3QgYmUgaGVsZFxuICAvLyBsaWFibGUgZm9yIGFueSByZWFsIG9yIGltYWdpbmVkIGRhbWFnZSByZXN1bHRpbmcgZnJvbSBpdHMgdXNlLlxuICAvLyBVc2VycyBvZiB0aGlzIGNvZGUgbXVzdCB2ZXJpZnkgY29ycmVjdG5lc3MgZm9yIHRoZWlyIGFwcGxpY2F0aW9uLlxuICB2YXIgd24gPSAwO1xuICB2YXIgeDEgPSBmbGF0Q29vcmRpbmF0ZXNbZW5kIC0gc3RyaWRlXTtcbiAgdmFyIHkxID0gZmxhdENvb3JkaW5hdGVzW2VuZCAtIHN0cmlkZSArIDFdO1xuXG4gIGZvciAoOyBvZmZzZXQgPCBlbmQ7IG9mZnNldCArPSBzdHJpZGUpIHtcbiAgICB2YXIgeDIgPSBmbGF0Q29vcmRpbmF0ZXNbb2Zmc2V0XTtcbiAgICB2YXIgeTIgPSBmbGF0Q29vcmRpbmF0ZXNbb2Zmc2V0ICsgMV07XG5cbiAgICBpZiAoeTEgPD0geSkge1xuICAgICAgaWYgKHkyID4geSAmJiAoeDIgLSB4MSkgKiAoeSAtIHkxKSAtICh4IC0geDEpICogKHkyIC0geTEpID4gMCkge1xuICAgICAgICB3bisrO1xuICAgICAgfVxuICAgIH0gZWxzZSBpZiAoeTIgPD0geSAmJiAoeDIgLSB4MSkgKiAoeSAtIHkxKSAtICh4IC0geDEpICogKHkyIC0geTEpIDwgMCkge1xuICAgICAgd24tLTtcbiAgICB9XG5cbiAgICB4MSA9IHgyO1xuICAgIHkxID0geTI7XG4gIH1cblxuICByZXR1cm4gd24gIT09IDA7XG59XG4vKipcbiAqIEBwYXJhbSB7QXJyYXk8bnVtYmVyPn0gZmxhdENvb3JkaW5hdGVzIEZsYXQgY29vcmRpbmF0ZXMuXG4gKiBAcGFyYW0ge251bWJlcn0gb2Zmc2V0IE9mZnNldC5cbiAqIEBwYXJhbSB7QXJyYXk8bnVtYmVyPn0gZW5kcyBFbmRzLlxuICogQHBhcmFtIHtudW1iZXJ9IHN0cmlkZSBTdHJpZGUuXG4gKiBAcGFyYW0ge251bWJlcn0geCBYLlxuICogQHBhcmFtIHtudW1iZXJ9IHkgWS5cbiAqIEByZXR1cm4ge2Jvb2xlYW59IENvbnRhaW5zICh4LCB5KS5cbiAqL1xuXG5leHBvcnQgZnVuY3Rpb24gbGluZWFyUmluZ3NDb250YWluc1hZKGZsYXRDb29yZGluYXRlcywgb2Zmc2V0LCBlbmRzLCBzdHJpZGUsIHgsIHkpIHtcbiAgaWYgKGVuZHMubGVuZ3RoID09PSAwKSB7XG4gICAgcmV0dXJuIGZhbHNlO1xuICB9XG5cbiAgaWYgKCFsaW5lYXJSaW5nQ29udGFpbnNYWShmbGF0Q29vcmRpbmF0ZXMsIG9mZnNldCwgZW5kc1swXSwgc3RyaWRlLCB4LCB5KSkge1xuICAgIHJldHVybiBmYWxzZTtcbiAgfVxuXG4gIGZvciAodmFyIGkgPSAxLCBpaSA9IGVuZHMubGVuZ3RoOyBpIDwgaWk7ICsraSkge1xuICAgIGlmIChsaW5lYXJSaW5nQ29udGFpbnNYWShmbGF0Q29vcmRpbmF0ZXMsIGVuZHNbaSAtIDFdLCBlbmRzW2ldLCBzdHJpZGUsIHgsIHkpKSB7XG4gICAgICByZXR1cm4gZmFsc2U7XG4gICAgfVxuICB9XG5cbiAgcmV0dXJuIHRydWU7XG59XG4vKipcbiAqIEBwYXJhbSB7QXJyYXk8bnVtYmVyPn0gZmxhdENvb3JkaW5hdGVzIEZsYXQgY29vcmRpbmF0ZXMuXG4gKiBAcGFyYW0ge251bWJlcn0gb2Zmc2V0IE9mZnNldC5cbiAqIEBwYXJhbSB7QXJyYXk8QXJyYXk8bnVtYmVyPj59IGVuZHNzIEVuZHNzLlxuICogQHBhcmFtIHtudW1iZXJ9IHN0cmlkZSBTdHJpZGUuXG4gKiBAcGFyYW0ge251bWJlcn0geCBYLlxuICogQHBhcmFtIHtudW1iZXJ9IHkgWS5cbiAqIEByZXR1cm4ge2Jvb2xlYW59IENvbnRhaW5zICh4LCB5KS5cbiAqL1xuXG5leHBvcnQgZnVuY3Rpb24gbGluZWFyUmluZ3NzQ29udGFpbnNYWShmbGF0Q29vcmRpbmF0ZXMsIG9mZnNldCwgZW5kc3MsIHN0cmlkZSwgeCwgeSkge1xuICBpZiAoZW5kc3MubGVuZ3RoID09PSAwKSB7XG4gICAgcmV0dXJuIGZhbHNlO1xuICB9XG5cbiAgZm9yICh2YXIgaSA9IDAsIGlpID0gZW5kc3MubGVuZ3RoOyBpIDwgaWk7ICsraSkge1xuICAgIHZhciBlbmRzID0gZW5kc3NbaV07XG5cbiAgICBpZiAobGluZWFyUmluZ3NDb250YWluc1hZKGZsYXRDb29yZGluYXRlcywgb2Zmc2V0LCBlbmRzLCBzdHJpZGUsIHgsIHkpKSB7XG4gICAgICByZXR1cm4gdHJ1ZTtcbiAgICB9XG5cbiAgICBvZmZzZXQgPSBlbmRzW2VuZHMubGVuZ3RoIC0gMV07XG4gIH1cblxuICByZXR1cm4gZmFsc2U7XG59IiwiLyoqXG4gKiBAbW9kdWxlIG9sL2dlb20vZmxhdC9pbnRlcmlvcnBvaW50XG4gKi9cbmltcG9ydCB7IGxpbmVhclJpbmdzQ29udGFpbnNYWSB9IGZyb20gJy4vY29udGFpbnMuanMnO1xuaW1wb3J0IHsgbnVtYmVyU2FmZUNvbXBhcmVGdW5jdGlvbiB9IGZyb20gJy4uLy4uL2FycmF5LmpzJztcbi8qKlxuICogQ2FsY3VsYXRlcyBhIHBvaW50IHRoYXQgaXMgbGlrZWx5IHRvIGxpZSBpbiB0aGUgaW50ZXJpb3Igb2YgdGhlIGxpbmVhciByaW5ncy5cbiAqIEluc3BpcmVkIGJ5IEpUUydzIGNvbS52aXZpZHNvbHV0aW9ucy5qdHMuZ2VvbS5HZW9tZXRyeSNnZXRJbnRlcmlvclBvaW50LlxuICogQHBhcmFtIHtBcnJheTxudW1iZXI+fSBmbGF0Q29vcmRpbmF0ZXMgRmxhdCBjb29yZGluYXRlcy5cbiAqIEBwYXJhbSB7bnVtYmVyfSBvZmZzZXQgT2Zmc2V0LlxuICogQHBhcmFtIHtBcnJheTxudW1iZXI+fSBlbmRzIEVuZHMuXG4gKiBAcGFyYW0ge251bWJlcn0gc3RyaWRlIFN0cmlkZS5cbiAqIEBwYXJhbSB7QXJyYXk8bnVtYmVyPn0gZmxhdENlbnRlcnMgRmxhdCBjZW50ZXJzLlxuICogQHBhcmFtIHtudW1iZXJ9IGZsYXRDZW50ZXJzT2Zmc2V0IEZsYXQgY2VudGVyIG9mZnNldC5cbiAqIEBwYXJhbSB7QXJyYXk8bnVtYmVyPj19IG9wdF9kZXN0IERlc3RpbmF0aW9uLlxuICogQHJldHVybiB7QXJyYXk8bnVtYmVyPn0gRGVzdGluYXRpb24gcG9pbnQgYXMgWFlNIGNvb3JkaW5hdGUsIHdoZXJlIE0gaXMgdGhlXG4gKiBsZW5ndGggb2YgdGhlIGhvcml6b250YWwgaW50ZXJzZWN0aW9uIHRoYXQgdGhlIHBvaW50IGJlbG9uZ3MgdG8uXG4gKi9cblxuZXhwb3J0IGZ1bmN0aW9uIGdldEludGVyaW9yUG9pbnRPZkFycmF5KGZsYXRDb29yZGluYXRlcywgb2Zmc2V0LCBlbmRzLCBzdHJpZGUsIGZsYXRDZW50ZXJzLCBmbGF0Q2VudGVyc09mZnNldCwgb3B0X2Rlc3QpIHtcbiAgdmFyIGksIGlpLCB4LCB4MSwgeDIsIHkxLCB5MjtcbiAgdmFyIHkgPSBmbGF0Q2VudGVyc1tmbGF0Q2VudGVyc09mZnNldCArIDFdO1xuICAvKiogQHR5cGUge0FycmF5PG51bWJlcj59ICovXG5cbiAgdmFyIGludGVyc2VjdGlvbnMgPSBbXTsgLy8gQ2FsY3VsYXRlIGludGVyc2VjdGlvbnMgd2l0aCB0aGUgaG9yaXpvbnRhbCBsaW5lXG5cbiAgZm9yICh2YXIgciA9IDAsIHJyID0gZW5kcy5sZW5ndGg7IHIgPCBycjsgKytyKSB7XG4gICAgdmFyIGVuZCA9IGVuZHNbcl07XG4gICAgeDEgPSBmbGF0Q29vcmRpbmF0ZXNbZW5kIC0gc3RyaWRlXTtcbiAgICB5MSA9IGZsYXRDb29yZGluYXRlc1tlbmQgLSBzdHJpZGUgKyAxXTtcblxuICAgIGZvciAoaSA9IG9mZnNldDsgaSA8IGVuZDsgaSArPSBzdHJpZGUpIHtcbiAgICAgIHgyID0gZmxhdENvb3JkaW5hdGVzW2ldO1xuICAgICAgeTIgPSBmbGF0Q29vcmRpbmF0ZXNbaSArIDFdO1xuXG4gICAgICBpZiAoeSA8PSB5MSAmJiB5MiA8PSB5IHx8IHkxIDw9IHkgJiYgeSA8PSB5Mikge1xuICAgICAgICB4ID0gKHkgLSB5MSkgLyAoeTIgLSB5MSkgKiAoeDIgLSB4MSkgKyB4MTtcbiAgICAgICAgaW50ZXJzZWN0aW9ucy5wdXNoKHgpO1xuICAgICAgfVxuXG4gICAgICB4MSA9IHgyO1xuICAgICAgeTEgPSB5MjtcbiAgICB9XG4gIH0gLy8gRmluZCB0aGUgbG9uZ2VzdCBzZWdtZW50IG9mIHRoZSBob3Jpem9udGFsIGxpbmUgdGhhdCBoYXMgaXRzIGNlbnRlciBwb2ludFxuICAvLyBpbnNpZGUgdGhlIGxpbmVhciByaW5nLlxuXG5cbiAgdmFyIHBvaW50WCA9IE5hTjtcbiAgdmFyIG1heFNlZ21lbnRMZW5ndGggPSAtSW5maW5pdHk7XG4gIGludGVyc2VjdGlvbnMuc29ydChudW1iZXJTYWZlQ29tcGFyZUZ1bmN0aW9uKTtcbiAgeDEgPSBpbnRlcnNlY3Rpb25zWzBdO1xuXG4gIGZvciAoaSA9IDEsIGlpID0gaW50ZXJzZWN0aW9ucy5sZW5ndGg7IGkgPCBpaTsgKytpKSB7XG4gICAgeDIgPSBpbnRlcnNlY3Rpb25zW2ldO1xuICAgIHZhciBzZWdtZW50TGVuZ3RoID0gTWF0aC5hYnMoeDIgLSB4MSk7XG5cbiAgICBpZiAoc2VnbWVudExlbmd0aCA+IG1heFNlZ21lbnRMZW5ndGgpIHtcbiAgICAgIHggPSAoeDEgKyB4MikgLyAyO1xuXG4gICAgICBpZiAobGluZWFyUmluZ3NDb250YWluc1hZKGZsYXRDb29yZGluYXRlcywgb2Zmc2V0LCBlbmRzLCBzdHJpZGUsIHgsIHkpKSB7XG4gICAgICAgIHBvaW50WCA9IHg7XG4gICAgICAgIG1heFNlZ21lbnRMZW5ndGggPSBzZWdtZW50TGVuZ3RoO1xuICAgICAgfVxuICAgIH1cblxuICAgIHgxID0geDI7XG4gIH1cblxuICBpZiAoaXNOYU4ocG9pbnRYKSkge1xuICAgIC8vIFRoZXJlIGlzIG5vIGhvcml6b250YWwgbGluZSB0aGF0IGhhcyBpdHMgY2VudGVyIHBvaW50IGluc2lkZSB0aGUgbGluZWFyXG4gICAgLy8gcmluZy4gIFVzZSB0aGUgY2VudGVyIG9mIHRoZSB0aGUgbGluZWFyIHJpbmcncyBleHRlbnQuXG4gICAgcG9pbnRYID0gZmxhdENlbnRlcnNbZmxhdENlbnRlcnNPZmZzZXRdO1xuICB9XG5cbiAgaWYgKG9wdF9kZXN0KSB7XG4gICAgb3B0X2Rlc3QucHVzaChwb2ludFgsIHksIG1heFNlZ21lbnRMZW5ndGgpO1xuICAgIHJldHVybiBvcHRfZGVzdDtcbiAgfSBlbHNlIHtcbiAgICByZXR1cm4gW3BvaW50WCwgeSwgbWF4U2VnbWVudExlbmd0aF07XG4gIH1cbn1cbi8qKlxuICogQHBhcmFtIHtBcnJheTxudW1iZXI+fSBmbGF0Q29vcmRpbmF0ZXMgRmxhdCBjb29yZGluYXRlcy5cbiAqIEBwYXJhbSB7bnVtYmVyfSBvZmZzZXQgT2Zmc2V0LlxuICogQHBhcmFtIHtBcnJheTxBcnJheTxudW1iZXI+Pn0gZW5kc3MgRW5kc3MuXG4gKiBAcGFyYW0ge251bWJlcn0gc3RyaWRlIFN0cmlkZS5cbiAqIEBwYXJhbSB7QXJyYXk8bnVtYmVyPn0gZmxhdENlbnRlcnMgRmxhdCBjZW50ZXJzLlxuICogQHJldHVybiB7QXJyYXk8bnVtYmVyPn0gSW50ZXJpb3IgcG9pbnRzIGFzIFhZTSBjb29yZGluYXRlcywgd2hlcmUgTSBpcyB0aGVcbiAqIGxlbmd0aCBvZiB0aGUgaG9yaXpvbnRhbCBpbnRlcnNlY3Rpb24gdGhhdCB0aGUgcG9pbnQgYmVsb25ncyB0by5cbiAqL1xuXG5leHBvcnQgZnVuY3Rpb24gZ2V0SW50ZXJpb3JQb2ludHNPZk11bHRpQXJyYXkoZmxhdENvb3JkaW5hdGVzLCBvZmZzZXQsIGVuZHNzLCBzdHJpZGUsIGZsYXRDZW50ZXJzKSB7XG4gIHZhciBpbnRlcmlvclBvaW50cyA9IFtdO1xuXG4gIGZvciAodmFyIGkgPSAwLCBpaSA9IGVuZHNzLmxlbmd0aDsgaSA8IGlpOyArK2kpIHtcbiAgICB2YXIgZW5kcyA9IGVuZHNzW2ldO1xuICAgIGludGVyaW9yUG9pbnRzID0gZ2V0SW50ZXJpb3JQb2ludE9mQXJyYXkoZmxhdENvb3JkaW5hdGVzLCBvZmZzZXQsIGVuZHMsIHN0cmlkZSwgZmxhdENlbnRlcnMsIDIgKiBpLCBpbnRlcmlvclBvaW50cyk7XG4gICAgb2Zmc2V0ID0gZW5kc1tlbmRzLmxlbmd0aCAtIDFdO1xuICB9XG5cbiAgcmV0dXJuIGludGVyaW9yUG9pbnRzO1xufSIsIi8qKlxuICogQG1vZHVsZSBvbC9nZW9tL2ZsYXQvc2VnbWVudHNcbiAqL1xuXG4vKipcbiAqIFRoaXMgZnVuY3Rpb24gY2FsbHMgYGNhbGxiYWNrYCBmb3IgZWFjaCBzZWdtZW50IG9mIHRoZSBmbGF0IGNvb3JkaW5hdGVzXG4gKiBhcnJheS4gSWYgdGhlIGNhbGxiYWNrIHJldHVybnMgYSB0cnV0aHkgdmFsdWUgdGhlIGZ1bmN0aW9uIHJldHVybnMgdGhhdFxuICogdmFsdWUgaW1tZWRpYXRlbHkuIE90aGVyd2lzZSB0aGUgZnVuY3Rpb24gcmV0dXJucyBgZmFsc2VgLlxuICogQHBhcmFtIHtBcnJheTxudW1iZXI+fSBmbGF0Q29vcmRpbmF0ZXMgRmxhdCBjb29yZGluYXRlcy5cbiAqIEBwYXJhbSB7bnVtYmVyfSBvZmZzZXQgT2Zmc2V0LlxuICogQHBhcmFtIHtudW1iZXJ9IGVuZCBFbmQuXG4gKiBAcGFyYW0ge251bWJlcn0gc3RyaWRlIFN0cmlkZS5cbiAqIEBwYXJhbSB7ZnVuY3Rpb24oaW1wb3J0KFwiLi4vLi4vY29vcmRpbmF0ZS5qc1wiKS5Db29yZGluYXRlLCBpbXBvcnQoXCIuLi8uLi9jb29yZGluYXRlLmpzXCIpLkNvb3JkaW5hdGUpOiBUfSBjYWxsYmFjayBGdW5jdGlvblxuICogICAgIGNhbGxlZCBmb3IgZWFjaCBzZWdtZW50LlxuICogQHJldHVybiB7VHxib29sZWFufSBWYWx1ZS5cbiAqIEB0ZW1wbGF0ZSBUXG4gKi9cbmV4cG9ydCBmdW5jdGlvbiBmb3JFYWNoKGZsYXRDb29yZGluYXRlcywgb2Zmc2V0LCBlbmQsIHN0cmlkZSwgY2FsbGJhY2spIHtcbiAgdmFyIHBvaW50MSA9IFtmbGF0Q29vcmRpbmF0ZXNbb2Zmc2V0XSwgZmxhdENvb3JkaW5hdGVzW29mZnNldCArIDFdXTtcbiAgdmFyIHBvaW50MiA9IFtdO1xuICB2YXIgcmV0O1xuXG4gIGZvciAoOyBvZmZzZXQgKyBzdHJpZGUgPCBlbmQ7IG9mZnNldCArPSBzdHJpZGUpIHtcbiAgICBwb2ludDJbMF0gPSBmbGF0Q29vcmRpbmF0ZXNbb2Zmc2V0ICsgc3RyaWRlXTtcbiAgICBwb2ludDJbMV0gPSBmbGF0Q29vcmRpbmF0ZXNbb2Zmc2V0ICsgc3RyaWRlICsgMV07XG4gICAgcmV0ID0gY2FsbGJhY2socG9pbnQxLCBwb2ludDIpO1xuXG4gICAgaWYgKHJldCkge1xuICAgICAgcmV0dXJuIHJldDtcbiAgICB9XG5cbiAgICBwb2ludDFbMF0gPSBwb2ludDJbMF07XG4gICAgcG9pbnQxWzFdID0gcG9pbnQyWzFdO1xuICB9XG5cbiAgcmV0dXJuIGZhbHNlO1xufSIsIi8qKlxuICogQG1vZHVsZSBvbC9nZW9tL2ZsYXQvaW50ZXJzZWN0c2V4dGVudFxuICovXG5pbXBvcnQgeyBjb250YWluc0V4dGVudCwgY3JlYXRlRW1wdHksIGV4dGVuZEZsYXRDb29yZGluYXRlcywgaW50ZXJzZWN0cywgaW50ZXJzZWN0c1NlZ21lbnQgfSBmcm9tICcuLi8uLi9leHRlbnQuanMnO1xuaW1wb3J0IHsgZm9yRWFjaCBhcyBmb3JFYWNoU2VnbWVudCB9IGZyb20gJy4vc2VnbWVudHMuanMnO1xuaW1wb3J0IHsgbGluZWFyUmluZ0NvbnRhaW5zRXh0ZW50LCBsaW5lYXJSaW5nQ29udGFpbnNYWSB9IGZyb20gJy4vY29udGFpbnMuanMnO1xuLyoqXG4gKiBAcGFyYW0ge0FycmF5PG51bWJlcj59IGZsYXRDb29yZGluYXRlcyBGbGF0IGNvb3JkaW5hdGVzLlxuICogQHBhcmFtIHtudW1iZXJ9IG9mZnNldCBPZmZzZXQuXG4gKiBAcGFyYW0ge251bWJlcn0gZW5kIEVuZC5cbiAqIEBwYXJhbSB7bnVtYmVyfSBzdHJpZGUgU3RyaWRlLlxuICogQHBhcmFtIHtpbXBvcnQoXCIuLi8uLi9leHRlbnQuanNcIikuRXh0ZW50fSBleHRlbnQgRXh0ZW50LlxuICogQHJldHVybiB7Ym9vbGVhbn0gVHJ1ZSBpZiB0aGUgZ2VvbWV0cnkgYW5kIHRoZSBleHRlbnQgaW50ZXJzZWN0LlxuICovXG5cbmV4cG9ydCBmdW5jdGlvbiBpbnRlcnNlY3RzTGluZVN0cmluZyhmbGF0Q29vcmRpbmF0ZXMsIG9mZnNldCwgZW5kLCBzdHJpZGUsIGV4dGVudCkge1xuICB2YXIgY29vcmRpbmF0ZXNFeHRlbnQgPSBleHRlbmRGbGF0Q29vcmRpbmF0ZXMoY3JlYXRlRW1wdHkoKSwgZmxhdENvb3JkaW5hdGVzLCBvZmZzZXQsIGVuZCwgc3RyaWRlKTtcblxuICBpZiAoIWludGVyc2VjdHMoZXh0ZW50LCBjb29yZGluYXRlc0V4dGVudCkpIHtcbiAgICByZXR1cm4gZmFsc2U7XG4gIH1cblxuICBpZiAoY29udGFpbnNFeHRlbnQoZXh0ZW50LCBjb29yZGluYXRlc0V4dGVudCkpIHtcbiAgICByZXR1cm4gdHJ1ZTtcbiAgfVxuXG4gIGlmIChjb29yZGluYXRlc0V4dGVudFswXSA+PSBleHRlbnRbMF0gJiYgY29vcmRpbmF0ZXNFeHRlbnRbMl0gPD0gZXh0ZW50WzJdKSB7XG4gICAgcmV0dXJuIHRydWU7XG4gIH1cblxuICBpZiAoY29vcmRpbmF0ZXNFeHRlbnRbMV0gPj0gZXh0ZW50WzFdICYmIGNvb3JkaW5hdGVzRXh0ZW50WzNdIDw9IGV4dGVudFszXSkge1xuICAgIHJldHVybiB0cnVlO1xuICB9XG5cbiAgcmV0dXJuIGZvckVhY2hTZWdtZW50KGZsYXRDb29yZGluYXRlcywgb2Zmc2V0LCBlbmQsIHN0cmlkZSxcbiAgLyoqXG4gICAqIEBwYXJhbSB7aW1wb3J0KFwiLi4vLi4vY29vcmRpbmF0ZS5qc1wiKS5Db29yZGluYXRlfSBwb2ludDEgU3RhcnQgcG9pbnQuXG4gICAqIEBwYXJhbSB7aW1wb3J0KFwiLi4vLi4vY29vcmRpbmF0ZS5qc1wiKS5Db29yZGluYXRlfSBwb2ludDIgRW5kIHBvaW50LlxuICAgKiBAcmV0dXJuIHtib29sZWFufSBgdHJ1ZWAgaWYgdGhlIHNlZ21lbnQgYW5kIHRoZSBleHRlbnQgaW50ZXJzZWN0LFxuICAgKiAgICAgYGZhbHNlYCBvdGhlcndpc2UuXG4gICAqL1xuICBmdW5jdGlvbiAocG9pbnQxLCBwb2ludDIpIHtcbiAgICByZXR1cm4gaW50ZXJzZWN0c1NlZ21lbnQoZXh0ZW50LCBwb2ludDEsIHBvaW50Mik7XG4gIH0pO1xufVxuLyoqXG4gKiBAcGFyYW0ge0FycmF5PG51bWJlcj59IGZsYXRDb29yZGluYXRlcyBGbGF0IGNvb3JkaW5hdGVzLlxuICogQHBhcmFtIHtudW1iZXJ9IG9mZnNldCBPZmZzZXQuXG4gKiBAcGFyYW0ge0FycmF5PG51bWJlcj59IGVuZHMgRW5kcy5cbiAqIEBwYXJhbSB7bnVtYmVyfSBzdHJpZGUgU3RyaWRlLlxuICogQHBhcmFtIHtpbXBvcnQoXCIuLi8uLi9leHRlbnQuanNcIikuRXh0ZW50fSBleHRlbnQgRXh0ZW50LlxuICogQHJldHVybiB7Ym9vbGVhbn0gVHJ1ZSBpZiB0aGUgZ2VvbWV0cnkgYW5kIHRoZSBleHRlbnQgaW50ZXJzZWN0LlxuICovXG5cbmV4cG9ydCBmdW5jdGlvbiBpbnRlcnNlY3RzTGluZVN0cmluZ0FycmF5KGZsYXRDb29yZGluYXRlcywgb2Zmc2V0LCBlbmRzLCBzdHJpZGUsIGV4dGVudCkge1xuICBmb3IgKHZhciBpID0gMCwgaWkgPSBlbmRzLmxlbmd0aDsgaSA8IGlpOyArK2kpIHtcbiAgICBpZiAoaW50ZXJzZWN0c0xpbmVTdHJpbmcoZmxhdENvb3JkaW5hdGVzLCBvZmZzZXQsIGVuZHNbaV0sIHN0cmlkZSwgZXh0ZW50KSkge1xuICAgICAgcmV0dXJuIHRydWU7XG4gICAgfVxuXG4gICAgb2Zmc2V0ID0gZW5kc1tpXTtcbiAgfVxuXG4gIHJldHVybiBmYWxzZTtcbn1cbi8qKlxuICogQHBhcmFtIHtBcnJheTxudW1iZXI+fSBmbGF0Q29vcmRpbmF0ZXMgRmxhdCBjb29yZGluYXRlcy5cbiAqIEBwYXJhbSB7bnVtYmVyfSBvZmZzZXQgT2Zmc2V0LlxuICogQHBhcmFtIHtudW1iZXJ9IGVuZCBFbmQuXG4gKiBAcGFyYW0ge251bWJlcn0gc3RyaWRlIFN0cmlkZS5cbiAqIEBwYXJhbSB7aW1wb3J0KFwiLi4vLi4vZXh0ZW50LmpzXCIpLkV4dGVudH0gZXh0ZW50IEV4dGVudC5cbiAqIEByZXR1cm4ge2Jvb2xlYW59IFRydWUgaWYgdGhlIGdlb21ldHJ5IGFuZCB0aGUgZXh0ZW50IGludGVyc2VjdC5cbiAqL1xuXG5leHBvcnQgZnVuY3Rpb24gaW50ZXJzZWN0c0xpbmVhclJpbmcoZmxhdENvb3JkaW5hdGVzLCBvZmZzZXQsIGVuZCwgc3RyaWRlLCBleHRlbnQpIHtcbiAgaWYgKGludGVyc2VjdHNMaW5lU3RyaW5nKGZsYXRDb29yZGluYXRlcywgb2Zmc2V0LCBlbmQsIHN0cmlkZSwgZXh0ZW50KSkge1xuICAgIHJldHVybiB0cnVlO1xuICB9XG5cbiAgaWYgKGxpbmVhclJpbmdDb250YWluc1hZKGZsYXRDb29yZGluYXRlcywgb2Zmc2V0LCBlbmQsIHN0cmlkZSwgZXh0ZW50WzBdLCBleHRlbnRbMV0pKSB7XG4gICAgcmV0dXJuIHRydWU7XG4gIH1cblxuICBpZiAobGluZWFyUmluZ0NvbnRhaW5zWFkoZmxhdENvb3JkaW5hdGVzLCBvZmZzZXQsIGVuZCwgc3RyaWRlLCBleHRlbnRbMF0sIGV4dGVudFszXSkpIHtcbiAgICByZXR1cm4gdHJ1ZTtcbiAgfVxuXG4gIGlmIChsaW5lYXJSaW5nQ29udGFpbnNYWShmbGF0Q29vcmRpbmF0ZXMsIG9mZnNldCwgZW5kLCBzdHJpZGUsIGV4dGVudFsyXSwgZXh0ZW50WzFdKSkge1xuICAgIHJldHVybiB0cnVlO1xuICB9XG5cbiAgaWYgKGxpbmVhclJpbmdDb250YWluc1hZKGZsYXRDb29yZGluYXRlcywgb2Zmc2V0LCBlbmQsIHN0cmlkZSwgZXh0ZW50WzJdLCBleHRlbnRbM10pKSB7XG4gICAgcmV0dXJuIHRydWU7XG4gIH1cblxuICByZXR1cm4gZmFsc2U7XG59XG4vKipcbiAqIEBwYXJhbSB7QXJyYXk8bnVtYmVyPn0gZmxhdENvb3JkaW5hdGVzIEZsYXQgY29vcmRpbmF0ZXMuXG4gKiBAcGFyYW0ge251bWJlcn0gb2Zmc2V0IE9mZnNldC5cbiAqIEBwYXJhbSB7QXJyYXk8bnVtYmVyPn0gZW5kcyBFbmRzLlxuICogQHBhcmFtIHtudW1iZXJ9IHN0cmlkZSBTdHJpZGUuXG4gKiBAcGFyYW0ge2ltcG9ydChcIi4uLy4uL2V4dGVudC5qc1wiKS5FeHRlbnR9IGV4dGVudCBFeHRlbnQuXG4gKiBAcmV0dXJuIHtib29sZWFufSBUcnVlIGlmIHRoZSBnZW9tZXRyeSBhbmQgdGhlIGV4dGVudCBpbnRlcnNlY3QuXG4gKi9cblxuZXhwb3J0IGZ1bmN0aW9uIGludGVyc2VjdHNMaW5lYXJSaW5nQXJyYXkoZmxhdENvb3JkaW5hdGVzLCBvZmZzZXQsIGVuZHMsIHN0cmlkZSwgZXh0ZW50KSB7XG4gIGlmICghaW50ZXJzZWN0c0xpbmVhclJpbmcoZmxhdENvb3JkaW5hdGVzLCBvZmZzZXQsIGVuZHNbMF0sIHN0cmlkZSwgZXh0ZW50KSkge1xuICAgIHJldHVybiBmYWxzZTtcbiAgfVxuXG4gIGlmIChlbmRzLmxlbmd0aCA9PT0gMSkge1xuICAgIHJldHVybiB0cnVlO1xuICB9XG5cbiAgZm9yICh2YXIgaSA9IDEsIGlpID0gZW5kcy5sZW5ndGg7IGkgPCBpaTsgKytpKSB7XG4gICAgaWYgKGxpbmVhclJpbmdDb250YWluc0V4dGVudChmbGF0Q29vcmRpbmF0ZXMsIGVuZHNbaSAtIDFdLCBlbmRzW2ldLCBzdHJpZGUsIGV4dGVudCkpIHtcbiAgICAgIGlmICghaW50ZXJzZWN0c0xpbmVTdHJpbmcoZmxhdENvb3JkaW5hdGVzLCBlbmRzW2kgLSAxXSwgZW5kc1tpXSwgc3RyaWRlLCBleHRlbnQpKSB7XG4gICAgICAgIHJldHVybiBmYWxzZTtcbiAgICAgIH1cbiAgICB9XG4gIH1cblxuICByZXR1cm4gdHJ1ZTtcbn1cbi8qKlxuICogQHBhcmFtIHtBcnJheTxudW1iZXI+fSBmbGF0Q29vcmRpbmF0ZXMgRmxhdCBjb29yZGluYXRlcy5cbiAqIEBwYXJhbSB7bnVtYmVyfSBvZmZzZXQgT2Zmc2V0LlxuICogQHBhcmFtIHtBcnJheTxBcnJheTxudW1iZXI+Pn0gZW5kc3MgRW5kc3MuXG4gKiBAcGFyYW0ge251bWJlcn0gc3RyaWRlIFN0cmlkZS5cbiAqIEBwYXJhbSB7aW1wb3J0KFwiLi4vLi4vZXh0ZW50LmpzXCIpLkV4dGVudH0gZXh0ZW50IEV4dGVudC5cbiAqIEByZXR1cm4ge2Jvb2xlYW59IFRydWUgaWYgdGhlIGdlb21ldHJ5IGFuZCB0aGUgZXh0ZW50IGludGVyc2VjdC5cbiAqL1xuXG5leHBvcnQgZnVuY3Rpb24gaW50ZXJzZWN0c0xpbmVhclJpbmdNdWx0aUFycmF5KGZsYXRDb29yZGluYXRlcywgb2Zmc2V0LCBlbmRzcywgc3RyaWRlLCBleHRlbnQpIHtcbiAgZm9yICh2YXIgaSA9IDAsIGlpID0gZW5kc3MubGVuZ3RoOyBpIDwgaWk7ICsraSkge1xuICAgIHZhciBlbmRzID0gZW5kc3NbaV07XG5cbiAgICBpZiAoaW50ZXJzZWN0c0xpbmVhclJpbmdBcnJheShmbGF0Q29vcmRpbmF0ZXMsIG9mZnNldCwgZW5kcywgc3RyaWRlLCBleHRlbnQpKSB7XG4gICAgICByZXR1cm4gdHJ1ZTtcbiAgICB9XG5cbiAgICBvZmZzZXQgPSBlbmRzW2VuZHMubGVuZ3RoIC0gMV07XG4gIH1cblxuICByZXR1cm4gZmFsc2U7XG59IiwiLyoqXG4gKiBAbW9kdWxlIG9sL2dlb20vZmxhdC9yZXZlcnNlXG4gKi9cblxuLyoqXG4gKiBAcGFyYW0ge0FycmF5PG51bWJlcj59IGZsYXRDb29yZGluYXRlcyBGbGF0IGNvb3JkaW5hdGVzLlxuICogQHBhcmFtIHtudW1iZXJ9IG9mZnNldCBPZmZzZXQuXG4gKiBAcGFyYW0ge251bWJlcn0gZW5kIEVuZC5cbiAqIEBwYXJhbSB7bnVtYmVyfSBzdHJpZGUgU3RyaWRlLlxuICovXG5leHBvcnQgZnVuY3Rpb24gY29vcmRpbmF0ZXMoZmxhdENvb3JkaW5hdGVzLCBvZmZzZXQsIGVuZCwgc3RyaWRlKSB7XG4gIHdoaWxlIChvZmZzZXQgPCBlbmQgLSBzdHJpZGUpIHtcbiAgICBmb3IgKHZhciBpID0gMDsgaSA8IHN0cmlkZTsgKytpKSB7XG4gICAgICB2YXIgdG1wID0gZmxhdENvb3JkaW5hdGVzW29mZnNldCArIGldO1xuICAgICAgZmxhdENvb3JkaW5hdGVzW29mZnNldCArIGldID0gZmxhdENvb3JkaW5hdGVzW2VuZCAtIHN0cmlkZSArIGldO1xuICAgICAgZmxhdENvb3JkaW5hdGVzW2VuZCAtIHN0cmlkZSArIGldID0gdG1wO1xuICAgIH1cblxuICAgIG9mZnNldCArPSBzdHJpZGU7XG4gICAgZW5kIC09IHN0cmlkZTtcbiAgfVxufSIsIi8qKlxuICogQG1vZHVsZSBvbC9nZW9tL2ZsYXQvb3JpZW50XG4gKi9cbmltcG9ydCB7IGNvb3JkaW5hdGVzIGFzIHJldmVyc2VDb29yZGluYXRlcyB9IGZyb20gJy4vcmV2ZXJzZS5qcyc7XG4vKipcbiAqIElzIHRoZSBsaW5lYXIgcmluZyBvcmllbnRlZCBjbG9ja3dpc2UgaW4gYSBjb29yZGluYXRlIHN5c3RlbSB3aXRoIGEgYm90dG9tLWxlZnRcbiAqIGNvb3JkaW5hdGUgb3JpZ2luPyBGb3IgYSBjb29yZGluYXRlIHN5c3RlbSB3aXRoIGEgdG9wLWxlZnQgY29vcmRpbmF0ZSBvcmlnaW4sXG4gKiB0aGUgcmluZydzIG9yaWVudGF0aW9uIGlzIGNsb2Nrd2lzZSB3aGVuIHRoaXMgZnVuY3Rpb24gcmV0dXJucyBmYWxzZS5cbiAqIEBwYXJhbSB7QXJyYXk8bnVtYmVyPn0gZmxhdENvb3JkaW5hdGVzIEZsYXQgY29vcmRpbmF0ZXMuXG4gKiBAcGFyYW0ge251bWJlcn0gb2Zmc2V0IE9mZnNldC5cbiAqIEBwYXJhbSB7bnVtYmVyfSBlbmQgRW5kLlxuICogQHBhcmFtIHtudW1iZXJ9IHN0cmlkZSBTdHJpZGUuXG4gKiBAcmV0dXJuIHtib29sZWFufSBJcyBjbG9ja3dpc2UuXG4gKi9cblxuZXhwb3J0IGZ1bmN0aW9uIGxpbmVhclJpbmdJc0Nsb2Nrd2lzZShmbGF0Q29vcmRpbmF0ZXMsIG9mZnNldCwgZW5kLCBzdHJpZGUpIHtcbiAgLy8gaHR0cDovL3Rpbnl1cmwuY29tL2Nsb2Nrd2lzZS1tZXRob2RcbiAgLy8gaHR0cHM6Ly9naXRodWIuY29tL09TR2VvL2dkYWwvYmxvYi90cnVuay9nZGFsL29nci9vZ3JsaW5lYXJyaW5nLmNwcFxuICB2YXIgZWRnZSA9IDA7XG4gIHZhciB4MSA9IGZsYXRDb29yZGluYXRlc1tlbmQgLSBzdHJpZGVdO1xuICB2YXIgeTEgPSBmbGF0Q29vcmRpbmF0ZXNbZW5kIC0gc3RyaWRlICsgMV07XG5cbiAgZm9yICg7IG9mZnNldCA8IGVuZDsgb2Zmc2V0ICs9IHN0cmlkZSkge1xuICAgIHZhciB4MiA9IGZsYXRDb29yZGluYXRlc1tvZmZzZXRdO1xuICAgIHZhciB5MiA9IGZsYXRDb29yZGluYXRlc1tvZmZzZXQgKyAxXTtcbiAgICBlZGdlICs9ICh4MiAtIHgxKSAqICh5MiArIHkxKTtcbiAgICB4MSA9IHgyO1xuICAgIHkxID0geTI7XG4gIH1cblxuICByZXR1cm4gZWRnZSA9PT0gMCA/IHVuZGVmaW5lZCA6IGVkZ2UgPiAwO1xufVxuLyoqXG4gKiBEZXRlcm1pbmVzIGlmIGxpbmVhciByaW5ncyBhcmUgb3JpZW50ZWQuICBCeSBkZWZhdWx0LCBsZWZ0LWhhbmQgb3JpZW50YXRpb25cbiAqIGlzIHRlc3RlZCAoZmlyc3QgcmluZyBtdXN0IGJlIGNsb2Nrd2lzZSwgcmVtYWluaW5nIHJpbmdzIGNvdW50ZXItY2xvY2t3aXNlKS5cbiAqIFRvIHRlc3QgZm9yIHJpZ2h0LWhhbmQgb3JpZW50YXRpb24sIHVzZSB0aGUgYG9wdF9yaWdodGAgYXJndW1lbnQuXG4gKlxuICogQHBhcmFtIHtBcnJheTxudW1iZXI+fSBmbGF0Q29vcmRpbmF0ZXMgRmxhdCBjb29yZGluYXRlcy5cbiAqIEBwYXJhbSB7bnVtYmVyfSBvZmZzZXQgT2Zmc2V0LlxuICogQHBhcmFtIHtBcnJheTxudW1iZXI+fSBlbmRzIEFycmF5IG9mIGVuZCBpbmRleGVzLlxuICogQHBhcmFtIHtudW1iZXJ9IHN0cmlkZSBTdHJpZGUuXG4gKiBAcGFyYW0ge2Jvb2xlYW49fSBvcHRfcmlnaHQgVGVzdCBmb3IgcmlnaHQtaGFuZCBvcmllbnRhdGlvblxuICogICAgIChjb3VudGVyLWNsb2Nrd2lzZSBleHRlcmlvciByaW5nIGFuZCBjbG9ja3dpc2UgaW50ZXJpb3IgcmluZ3MpLlxuICogQHJldHVybiB7Ym9vbGVhbn0gUmluZ3MgYXJlIGNvcnJlY3RseSBvcmllbnRlZC5cbiAqL1xuXG5leHBvcnQgZnVuY3Rpb24gbGluZWFyUmluZ3NBcmVPcmllbnRlZChmbGF0Q29vcmRpbmF0ZXMsIG9mZnNldCwgZW5kcywgc3RyaWRlLCBvcHRfcmlnaHQpIHtcbiAgdmFyIHJpZ2h0ID0gb3B0X3JpZ2h0ICE9PSB1bmRlZmluZWQgPyBvcHRfcmlnaHQgOiBmYWxzZTtcblxuICBmb3IgKHZhciBpID0gMCwgaWkgPSBlbmRzLmxlbmd0aDsgaSA8IGlpOyArK2kpIHtcbiAgICB2YXIgZW5kID0gZW5kc1tpXTtcbiAgICB2YXIgaXNDbG9ja3dpc2UgPSBsaW5lYXJSaW5nSXNDbG9ja3dpc2UoZmxhdENvb3JkaW5hdGVzLCBvZmZzZXQsIGVuZCwgc3RyaWRlKTtcblxuICAgIGlmIChpID09PSAwKSB7XG4gICAgICBpZiAocmlnaHQgJiYgaXNDbG9ja3dpc2UgfHwgIXJpZ2h0ICYmICFpc0Nsb2Nrd2lzZSkge1xuICAgICAgICByZXR1cm4gZmFsc2U7XG4gICAgICB9XG4gICAgfSBlbHNlIHtcbiAgICAgIGlmIChyaWdodCAmJiAhaXNDbG9ja3dpc2UgfHwgIXJpZ2h0ICYmIGlzQ2xvY2t3aXNlKSB7XG4gICAgICAgIHJldHVybiBmYWxzZTtcbiAgICAgIH1cbiAgICB9XG5cbiAgICBvZmZzZXQgPSBlbmQ7XG4gIH1cblxuICByZXR1cm4gdHJ1ZTtcbn1cbi8qKlxuICogRGV0ZXJtaW5lcyBpZiBsaW5lYXIgcmluZ3MgYXJlIG9yaWVudGVkLiAgQnkgZGVmYXVsdCwgbGVmdC1oYW5kIG9yaWVudGF0aW9uXG4gKiBpcyB0ZXN0ZWQgKGZpcnN0IHJpbmcgbXVzdCBiZSBjbG9ja3dpc2UsIHJlbWFpbmluZyByaW5ncyBjb3VudGVyLWNsb2Nrd2lzZSkuXG4gKiBUbyB0ZXN0IGZvciByaWdodC1oYW5kIG9yaWVudGF0aW9uLCB1c2UgdGhlIGBvcHRfcmlnaHRgIGFyZ3VtZW50LlxuICpcbiAqIEBwYXJhbSB7QXJyYXk8bnVtYmVyPn0gZmxhdENvb3JkaW5hdGVzIEZsYXQgY29vcmRpbmF0ZXMuXG4gKiBAcGFyYW0ge251bWJlcn0gb2Zmc2V0IE9mZnNldC5cbiAqIEBwYXJhbSB7QXJyYXk8QXJyYXk8bnVtYmVyPj59IGVuZHNzIEFycmF5IG9mIGFycmF5IG9mIGVuZCBpbmRleGVzLlxuICogQHBhcmFtIHtudW1iZXJ9IHN0cmlkZSBTdHJpZGUuXG4gKiBAcGFyYW0ge2Jvb2xlYW49fSBvcHRfcmlnaHQgVGVzdCBmb3IgcmlnaHQtaGFuZCBvcmllbnRhdGlvblxuICogICAgIChjb3VudGVyLWNsb2Nrd2lzZSBleHRlcmlvciByaW5nIGFuZCBjbG9ja3dpc2UgaW50ZXJpb3IgcmluZ3MpLlxuICogQHJldHVybiB7Ym9vbGVhbn0gUmluZ3MgYXJlIGNvcnJlY3RseSBvcmllbnRlZC5cbiAqL1xuXG5leHBvcnQgZnVuY3Rpb24gbGluZWFyUmluZ3NzQXJlT3JpZW50ZWQoZmxhdENvb3JkaW5hdGVzLCBvZmZzZXQsIGVuZHNzLCBzdHJpZGUsIG9wdF9yaWdodCkge1xuICBmb3IgKHZhciBpID0gMCwgaWkgPSBlbmRzcy5sZW5ndGg7IGkgPCBpaTsgKytpKSB7XG4gICAgdmFyIGVuZHMgPSBlbmRzc1tpXTtcblxuICAgIGlmICghbGluZWFyUmluZ3NBcmVPcmllbnRlZChmbGF0Q29vcmRpbmF0ZXMsIG9mZnNldCwgZW5kcywgc3RyaWRlLCBvcHRfcmlnaHQpKSB7XG4gICAgICByZXR1cm4gZmFsc2U7XG4gICAgfVxuXG4gICAgaWYgKGVuZHMubGVuZ3RoKSB7XG4gICAgICBvZmZzZXQgPSBlbmRzW2VuZHMubGVuZ3RoIC0gMV07XG4gICAgfVxuICB9XG5cbiAgcmV0dXJuIHRydWU7XG59XG4vKipcbiAqIE9yaWVudCBjb29yZGluYXRlcyBpbiBhIGZsYXQgYXJyYXkgb2YgbGluZWFyIHJpbmdzLiAgQnkgZGVmYXVsdCwgcmluZ3NcbiAqIGFyZSBvcmllbnRlZCBmb2xsb3dpbmcgdGhlIGxlZnQtaGFuZCBydWxlIChjbG9ja3dpc2UgZm9yIGV4dGVyaW9yIGFuZFxuICogY291bnRlci1jbG9ja3dpc2UgZm9yIGludGVyaW9yIHJpbmdzKS4gIFRvIG9yaWVudCBhY2NvcmRpbmcgdG8gdGhlXG4gKiByaWdodC1oYW5kIHJ1bGUsIHVzZSB0aGUgYG9wdF9yaWdodGAgYXJndW1lbnQuXG4gKlxuICogQHBhcmFtIHtBcnJheTxudW1iZXI+fSBmbGF0Q29vcmRpbmF0ZXMgRmxhdCBjb29yZGluYXRlcy5cbiAqIEBwYXJhbSB7bnVtYmVyfSBvZmZzZXQgT2Zmc2V0LlxuICogQHBhcmFtIHtBcnJheTxudW1iZXI+fSBlbmRzIEVuZHMuXG4gKiBAcGFyYW0ge251bWJlcn0gc3RyaWRlIFN0cmlkZS5cbiAqIEBwYXJhbSB7Ym9vbGVhbj19IG9wdF9yaWdodCBGb2xsb3cgdGhlIHJpZ2h0LWhhbmQgcnVsZSBmb3Igb3JpZW50YXRpb24uXG4gKiBAcmV0dXJuIHtudW1iZXJ9IEVuZC5cbiAqL1xuXG5leHBvcnQgZnVuY3Rpb24gb3JpZW50TGluZWFyUmluZ3MoZmxhdENvb3JkaW5hdGVzLCBvZmZzZXQsIGVuZHMsIHN0cmlkZSwgb3B0X3JpZ2h0KSB7XG4gIHZhciByaWdodCA9IG9wdF9yaWdodCAhPT0gdW5kZWZpbmVkID8gb3B0X3JpZ2h0IDogZmFsc2U7XG5cbiAgZm9yICh2YXIgaSA9IDAsIGlpID0gZW5kcy5sZW5ndGg7IGkgPCBpaTsgKytpKSB7XG4gICAgdmFyIGVuZCA9IGVuZHNbaV07XG4gICAgdmFyIGlzQ2xvY2t3aXNlID0gbGluZWFyUmluZ0lzQ2xvY2t3aXNlKGZsYXRDb29yZGluYXRlcywgb2Zmc2V0LCBlbmQsIHN0cmlkZSk7XG4gICAgdmFyIHJldmVyc2UgPSBpID09PSAwID8gcmlnaHQgJiYgaXNDbG9ja3dpc2UgfHwgIXJpZ2h0ICYmICFpc0Nsb2Nrd2lzZSA6IHJpZ2h0ICYmICFpc0Nsb2Nrd2lzZSB8fCAhcmlnaHQgJiYgaXNDbG9ja3dpc2U7XG5cbiAgICBpZiAocmV2ZXJzZSkge1xuICAgICAgcmV2ZXJzZUNvb3JkaW5hdGVzKGZsYXRDb29yZGluYXRlcywgb2Zmc2V0LCBlbmQsIHN0cmlkZSk7XG4gICAgfVxuXG4gICAgb2Zmc2V0ID0gZW5kO1xuICB9XG5cbiAgcmV0dXJuIG9mZnNldDtcbn1cbi8qKlxuICogT3JpZW50IGNvb3JkaW5hdGVzIGluIGEgZmxhdCBhcnJheSBvZiBsaW5lYXIgcmluZ3MuICBCeSBkZWZhdWx0LCByaW5nc1xuICogYXJlIG9yaWVudGVkIGZvbGxvd2luZyB0aGUgbGVmdC1oYW5kIHJ1bGUgKGNsb2Nrd2lzZSBmb3IgZXh0ZXJpb3IgYW5kXG4gKiBjb3VudGVyLWNsb2Nrd2lzZSBmb3IgaW50ZXJpb3IgcmluZ3MpLiAgVG8gb3JpZW50IGFjY29yZGluZyB0byB0aGVcbiAqIHJpZ2h0LWhhbmQgcnVsZSwgdXNlIHRoZSBgb3B0X3JpZ2h0YCBhcmd1bWVudC5cbiAqXG4gKiBAcGFyYW0ge0FycmF5PG51bWJlcj59IGZsYXRDb29yZGluYXRlcyBGbGF0IGNvb3JkaW5hdGVzLlxuICogQHBhcmFtIHtudW1iZXJ9IG9mZnNldCBPZmZzZXQuXG4gKiBAcGFyYW0ge0FycmF5PEFycmF5PG51bWJlcj4+fSBlbmRzcyBBcnJheSBvZiBhcnJheSBvZiBlbmQgaW5kZXhlcy5cbiAqIEBwYXJhbSB7bnVtYmVyfSBzdHJpZGUgU3RyaWRlLlxuICogQHBhcmFtIHtib29sZWFuPX0gb3B0X3JpZ2h0IEZvbGxvdyB0aGUgcmlnaHQtaGFuZCBydWxlIGZvciBvcmllbnRhdGlvbi5cbiAqIEByZXR1cm4ge251bWJlcn0gRW5kLlxuICovXG5cbmV4cG9ydCBmdW5jdGlvbiBvcmllbnRMaW5lYXJSaW5nc0FycmF5KGZsYXRDb29yZGluYXRlcywgb2Zmc2V0LCBlbmRzcywgc3RyaWRlLCBvcHRfcmlnaHQpIHtcbiAgZm9yICh2YXIgaSA9IDAsIGlpID0gZW5kc3MubGVuZ3RoOyBpIDwgaWk7ICsraSkge1xuICAgIG9mZnNldCA9IG9yaWVudExpbmVhclJpbmdzKGZsYXRDb29yZGluYXRlcywgb2Zmc2V0LCBlbmRzc1tpXSwgc3RyaWRlLCBvcHRfcmlnaHQpO1xuICB9XG5cbiAgcmV0dXJuIG9mZnNldDtcbn0iLCJ2YXIgX19leHRlbmRzID0gdGhpcyAmJiB0aGlzLl9fZXh0ZW5kcyB8fCBmdW5jdGlvbiAoKSB7XG4gIHZhciBfZXh0ZW5kU3RhdGljcyA9IGZ1bmN0aW9uIGV4dGVuZFN0YXRpY3MoZCwgYikge1xuICAgIF9leHRlbmRTdGF0aWNzID0gT2JqZWN0LnNldFByb3RvdHlwZU9mIHx8IHtcbiAgICAgIF9fcHJvdG9fXzogW11cbiAgICB9IGluc3RhbmNlb2YgQXJyYXkgJiYgZnVuY3Rpb24gKGQsIGIpIHtcbiAgICAgIGQuX19wcm90b19fID0gYjtcbiAgICB9IHx8IGZ1bmN0aW9uIChkLCBiKSB7XG4gICAgICBmb3IgKHZhciBwIGluIGIpIHtcbiAgICAgICAgaWYgKE9iamVjdC5wcm90b3R5cGUuaGFzT3duUHJvcGVydHkuY2FsbChiLCBwKSkgZFtwXSA9IGJbcF07XG4gICAgICB9XG4gICAgfTtcblxuICAgIHJldHVybiBfZXh0ZW5kU3RhdGljcyhkLCBiKTtcbiAgfTtcblxuICByZXR1cm4gZnVuY3Rpb24gKGQsIGIpIHtcbiAgICBfZXh0ZW5kU3RhdGljcyhkLCBiKTtcblxuICAgIGZ1bmN0aW9uIF9fKCkge1xuICAgICAgdGhpcy5jb25zdHJ1Y3RvciA9IGQ7XG4gICAgfVxuXG4gICAgZC5wcm90b3R5cGUgPSBiID09PSBudWxsID8gT2JqZWN0LmNyZWF0ZShiKSA6IChfXy5wcm90b3R5cGUgPSBiLnByb3RvdHlwZSwgbmV3IF9fKCkpO1xuICB9O1xufSgpO1xuLyoqXG4gKiBAbW9kdWxlIG9sL2dlb20vUG9seWdvblxuICovXG5cblxuaW1wb3J0IEdlb21ldHJ5TGF5b3V0IGZyb20gJy4vR2VvbWV0cnlMYXlvdXQuanMnO1xuaW1wb3J0IEdlb21ldHJ5VHlwZSBmcm9tICcuL0dlb21ldHJ5VHlwZS5qcyc7XG5pbXBvcnQgTGluZWFyUmluZyBmcm9tICcuL0xpbmVhclJpbmcuanMnO1xuaW1wb3J0IFBvaW50IGZyb20gJy4vUG9pbnQuanMnO1xuaW1wb3J0IFNpbXBsZUdlb21ldHJ5IGZyb20gJy4vU2ltcGxlR2VvbWV0cnkuanMnO1xuaW1wb3J0IHsgYXJyYXlNYXhTcXVhcmVkRGVsdGEsIGFzc2lnbkNsb3Nlc3RBcnJheVBvaW50IH0gZnJvbSAnLi9mbGF0L2Nsb3Nlc3QuanMnO1xuaW1wb3J0IHsgY2xvc2VzdFNxdWFyZWREaXN0YW5jZVhZLCBnZXRDZW50ZXIgfSBmcm9tICcuLi9leHRlbnQuanMnO1xuaW1wb3J0IHsgZGVmbGF0ZUNvb3JkaW5hdGVzQXJyYXkgfSBmcm9tICcuL2ZsYXQvZGVmbGF0ZS5qcyc7XG5pbXBvcnQgeyBleHRlbmQgfSBmcm9tICcuLi9hcnJheS5qcyc7XG5pbXBvcnQgeyBnZXRJbnRlcmlvclBvaW50T2ZBcnJheSB9IGZyb20gJy4vZmxhdC9pbnRlcmlvcnBvaW50LmpzJztcbmltcG9ydCB7IGluZmxhdGVDb29yZGluYXRlc0FycmF5IH0gZnJvbSAnLi9mbGF0L2luZmxhdGUuanMnO1xuaW1wb3J0IHsgaW50ZXJzZWN0c0xpbmVhclJpbmdBcnJheSB9IGZyb20gJy4vZmxhdC9pbnRlcnNlY3RzZXh0ZW50LmpzJztcbmltcG9ydCB7IGxpbmVhclJpbmdzQXJlT3JpZW50ZWQsIG9yaWVudExpbmVhclJpbmdzIH0gZnJvbSAnLi9mbGF0L29yaWVudC5qcyc7XG5pbXBvcnQgeyBsaW5lYXJSaW5ncyBhcyBsaW5lYXJSaW5nc0FyZWEgfSBmcm9tICcuL2ZsYXQvYXJlYS5qcyc7XG5pbXBvcnQgeyBsaW5lYXJSaW5nc0NvbnRhaW5zWFkgfSBmcm9tICcuL2ZsYXQvY29udGFpbnMuanMnO1xuaW1wb3J0IHsgbW9kdWxvIH0gZnJvbSAnLi4vbWF0aC5qcyc7XG5pbXBvcnQgeyBxdWFudGl6ZUFycmF5IH0gZnJvbSAnLi9mbGF0L3NpbXBsaWZ5LmpzJztcbmltcG9ydCB7IG9mZnNldCBhcyBzcGhlcmVPZmZzZXQgfSBmcm9tICcuLi9zcGhlcmUuanMnO1xuLyoqXG4gKiBAY2xhc3NkZXNjXG4gKiBQb2x5Z29uIGdlb21ldHJ5LlxuICpcbiAqIEBhcGlcbiAqL1xuXG52YXIgUG9seWdvbiA9XG4vKiogQGNsYXNzICovXG5mdW5jdGlvbiAoX3N1cGVyKSB7XG4gIF9fZXh0ZW5kcyhQb2x5Z29uLCBfc3VwZXIpO1xuICAvKipcbiAgICogQHBhcmFtIHshQXJyYXk8QXJyYXk8aW1wb3J0KFwiLi4vY29vcmRpbmF0ZS5qc1wiKS5Db29yZGluYXRlPj58IUFycmF5PG51bWJlcj59IGNvb3JkaW5hdGVzXG4gICAqICAgICBBcnJheSBvZiBsaW5lYXIgcmluZ3MgdGhhdCBkZWZpbmUgdGhlIHBvbHlnb24uIFRoZSBmaXJzdCBsaW5lYXIgcmluZyBvZiB0aGVcbiAgICogICAgIGFycmF5IGRlZmluZXMgdGhlIG91dGVyLWJvdW5kYXJ5IG9yIHN1cmZhY2Ugb2YgdGhlIHBvbHlnb24uIEVhY2ggc3Vic2VxdWVudFxuICAgKiAgICAgbGluZWFyIHJpbmcgZGVmaW5lcyBhIGhvbGUgaW4gdGhlIHN1cmZhY2Ugb2YgdGhlIHBvbHlnb24uIEEgbGluZWFyIHJpbmcgaXNcbiAgICogICAgIGFuIGFycmF5IG9mIHZlcnRpY2VzJyBjb29yZGluYXRlcyB3aGVyZSB0aGUgZmlyc3QgY29vcmRpbmF0ZSBhbmQgdGhlIGxhc3QgYXJlXG4gICAqICAgICBlcXVpdmFsZW50LiAoRm9yIGludGVybmFsIHVzZSwgZmxhdCBjb29yZGluYXRlcyBpbiBjb21iaW5hdGlvbiB3aXRoXG4gICAqICAgICBgb3B0X2xheW91dGAgYW5kIGBvcHRfZW5kc2AgYXJlIGFsc28gYWNjZXB0ZWQuKVxuICAgKiBAcGFyYW0ge2ltcG9ydChcIi4vR2VvbWV0cnlMYXlvdXQuanNcIikuZGVmYXVsdD19IG9wdF9sYXlvdXQgTGF5b3V0LlxuICAgKiBAcGFyYW0ge0FycmF5PG51bWJlcj49fSBvcHRfZW5kcyBFbmRzIChmb3IgaW50ZXJuYWwgdXNlIHdpdGggZmxhdCBjb29yZGluYXRlcykuXG4gICAqL1xuXG5cbiAgZnVuY3Rpb24gUG9seWdvbihjb29yZGluYXRlcywgb3B0X2xheW91dCwgb3B0X2VuZHMpIHtcbiAgICB2YXIgX3RoaXMgPSBfc3VwZXIuY2FsbCh0aGlzKSB8fCB0aGlzO1xuICAgIC8qKlxuICAgICAqIEB0eXBlIHtBcnJheTxudW1iZXI+fVxuICAgICAqIEBwcml2YXRlXG4gICAgICovXG5cblxuICAgIF90aGlzLmVuZHNfID0gW107XG4gICAgLyoqXG4gICAgICogQHByaXZhdGVcbiAgICAgKiBAdHlwZSB7bnVtYmVyfVxuICAgICAqL1xuXG4gICAgX3RoaXMuZmxhdEludGVyaW9yUG9pbnRSZXZpc2lvbl8gPSAtMTtcbiAgICAvKipcbiAgICAgKiBAcHJpdmF0ZVxuICAgICAqIEB0eXBlIHtpbXBvcnQoXCIuLi9jb29yZGluYXRlLmpzXCIpLkNvb3JkaW5hdGV9XG4gICAgICovXG5cbiAgICBfdGhpcy5mbGF0SW50ZXJpb3JQb2ludF8gPSBudWxsO1xuICAgIC8qKlxuICAgICAqIEBwcml2YXRlXG4gICAgICogQHR5cGUge251bWJlcn1cbiAgICAgKi9cblxuICAgIF90aGlzLm1heERlbHRhXyA9IC0xO1xuICAgIC8qKlxuICAgICAqIEBwcml2YXRlXG4gICAgICogQHR5cGUge251bWJlcn1cbiAgICAgKi9cblxuICAgIF90aGlzLm1heERlbHRhUmV2aXNpb25fID0gLTE7XG4gICAgLyoqXG4gICAgICogQHByaXZhdGVcbiAgICAgKiBAdHlwZSB7bnVtYmVyfVxuICAgICAqL1xuXG4gICAgX3RoaXMub3JpZW50ZWRSZXZpc2lvbl8gPSAtMTtcbiAgICAvKipcbiAgICAgKiBAcHJpdmF0ZVxuICAgICAqIEB0eXBlIHtBcnJheTxudW1iZXI+fVxuICAgICAqL1xuXG4gICAgX3RoaXMub3JpZW50ZWRGbGF0Q29vcmRpbmF0ZXNfID0gbnVsbDtcblxuICAgIGlmIChvcHRfbGF5b3V0ICE9PSB1bmRlZmluZWQgJiYgb3B0X2VuZHMpIHtcbiAgICAgIF90aGlzLnNldEZsYXRDb29yZGluYXRlcyhvcHRfbGF5b3V0LFxuICAgICAgLyoqIEB0eXBlIHtBcnJheTxudW1iZXI+fSAqL1xuICAgICAgY29vcmRpbmF0ZXMpO1xuXG4gICAgICBfdGhpcy5lbmRzXyA9IG9wdF9lbmRzO1xuICAgIH0gZWxzZSB7XG4gICAgICBfdGhpcy5zZXRDb29yZGluYXRlcyhcbiAgICAgIC8qKiBAdHlwZSB7QXJyYXk8QXJyYXk8aW1wb3J0KFwiLi4vY29vcmRpbmF0ZS5qc1wiKS5Db29yZGluYXRlPj59ICovXG4gICAgICBjb29yZGluYXRlcywgb3B0X2xheW91dCk7XG4gICAgfVxuXG4gICAgcmV0dXJuIF90aGlzO1xuICB9XG4gIC8qKlxuICAgKiBBcHBlbmQgdGhlIHBhc3NlZCBsaW5lYXIgcmluZyB0byB0aGlzIHBvbHlnb24uXG4gICAqIEBwYXJhbSB7TGluZWFyUmluZ30gbGluZWFyUmluZyBMaW5lYXIgcmluZy5cbiAgICogQGFwaVxuICAgKi9cblxuXG4gIFBvbHlnb24ucHJvdG90eXBlLmFwcGVuZExpbmVhclJpbmcgPSBmdW5jdGlvbiAobGluZWFyUmluZykge1xuICAgIGlmICghdGhpcy5mbGF0Q29vcmRpbmF0ZXMpIHtcbiAgICAgIHRoaXMuZmxhdENvb3JkaW5hdGVzID0gbGluZWFyUmluZy5nZXRGbGF0Q29vcmRpbmF0ZXMoKS5zbGljZSgpO1xuICAgIH0gZWxzZSB7XG4gICAgICBleHRlbmQodGhpcy5mbGF0Q29vcmRpbmF0ZXMsIGxpbmVhclJpbmcuZ2V0RmxhdENvb3JkaW5hdGVzKCkpO1xuICAgIH1cblxuICAgIHRoaXMuZW5kc18ucHVzaCh0aGlzLmZsYXRDb29yZGluYXRlcy5sZW5ndGgpO1xuICAgIHRoaXMuY2hhbmdlZCgpO1xuICB9O1xuICAvKipcbiAgICogTWFrZSBhIGNvbXBsZXRlIGNvcHkgb2YgdGhlIGdlb21ldHJ5LlxuICAgKiBAcmV0dXJuIHshUG9seWdvbn0gQ2xvbmUuXG4gICAqIEBhcGlcbiAgICovXG5cblxuICBQb2x5Z29uLnByb3RvdHlwZS5jbG9uZSA9IGZ1bmN0aW9uICgpIHtcbiAgICB2YXIgcG9seWdvbiA9IG5ldyBQb2x5Z29uKHRoaXMuZmxhdENvb3JkaW5hdGVzLnNsaWNlKCksIHRoaXMubGF5b3V0LCB0aGlzLmVuZHNfLnNsaWNlKCkpO1xuICAgIHBvbHlnb24uYXBwbHlQcm9wZXJ0aWVzKHRoaXMpO1xuICAgIHJldHVybiBwb2x5Z29uO1xuICB9O1xuICAvKipcbiAgICogQHBhcmFtIHtudW1iZXJ9IHggWC5cbiAgICogQHBhcmFtIHtudW1iZXJ9IHkgWS5cbiAgICogQHBhcmFtIHtpbXBvcnQoXCIuLi9jb29yZGluYXRlLmpzXCIpLkNvb3JkaW5hdGV9IGNsb3Nlc3RQb2ludCBDbG9zZXN0IHBvaW50LlxuICAgKiBAcGFyYW0ge251bWJlcn0gbWluU3F1YXJlZERpc3RhbmNlIE1pbmltdW0gc3F1YXJlZCBkaXN0YW5jZS5cbiAgICogQHJldHVybiB7bnVtYmVyfSBNaW5pbXVtIHNxdWFyZWQgZGlzdGFuY2UuXG4gICAqL1xuXG5cbiAgUG9seWdvbi5wcm90b3R5cGUuY2xvc2VzdFBvaW50WFkgPSBmdW5jdGlvbiAoeCwgeSwgY2xvc2VzdFBvaW50LCBtaW5TcXVhcmVkRGlzdGFuY2UpIHtcbiAgICBpZiAobWluU3F1YXJlZERpc3RhbmNlIDwgY2xvc2VzdFNxdWFyZWREaXN0YW5jZVhZKHRoaXMuZ2V0RXh0ZW50KCksIHgsIHkpKSB7XG4gICAgICByZXR1cm4gbWluU3F1YXJlZERpc3RhbmNlO1xuICAgIH1cblxuICAgIGlmICh0aGlzLm1heERlbHRhUmV2aXNpb25fICE9IHRoaXMuZ2V0UmV2aXNpb24oKSkge1xuICAgICAgdGhpcy5tYXhEZWx0YV8gPSBNYXRoLnNxcnQoYXJyYXlNYXhTcXVhcmVkRGVsdGEodGhpcy5mbGF0Q29vcmRpbmF0ZXMsIDAsIHRoaXMuZW5kc18sIHRoaXMuc3RyaWRlLCAwKSk7XG4gICAgICB0aGlzLm1heERlbHRhUmV2aXNpb25fID0gdGhpcy5nZXRSZXZpc2lvbigpO1xuICAgIH1cblxuICAgIHJldHVybiBhc3NpZ25DbG9zZXN0QXJyYXlQb2ludCh0aGlzLmZsYXRDb29yZGluYXRlcywgMCwgdGhpcy5lbmRzXywgdGhpcy5zdHJpZGUsIHRoaXMubWF4RGVsdGFfLCB0cnVlLCB4LCB5LCBjbG9zZXN0UG9pbnQsIG1pblNxdWFyZWREaXN0YW5jZSk7XG4gIH07XG4gIC8qKlxuICAgKiBAcGFyYW0ge251bWJlcn0geCBYLlxuICAgKiBAcGFyYW0ge251bWJlcn0geSBZLlxuICAgKiBAcmV0dXJuIHtib29sZWFufSBDb250YWlucyAoeCwgeSkuXG4gICAqL1xuXG5cbiAgUG9seWdvbi5wcm90b3R5cGUuY29udGFpbnNYWSA9IGZ1bmN0aW9uICh4LCB5KSB7XG4gICAgcmV0dXJuIGxpbmVhclJpbmdzQ29udGFpbnNYWSh0aGlzLmdldE9yaWVudGVkRmxhdENvb3JkaW5hdGVzKCksIDAsIHRoaXMuZW5kc18sIHRoaXMuc3RyaWRlLCB4LCB5KTtcbiAgfTtcbiAgLyoqXG4gICAqIFJldHVybiB0aGUgYXJlYSBvZiB0aGUgcG9seWdvbiBvbiBwcm9qZWN0ZWQgcGxhbmUuXG4gICAqIEByZXR1cm4ge251bWJlcn0gQXJlYSAob24gcHJvamVjdGVkIHBsYW5lKS5cbiAgICogQGFwaVxuICAgKi9cblxuXG4gIFBvbHlnb24ucHJvdG90eXBlLmdldEFyZWEgPSBmdW5jdGlvbiAoKSB7XG4gICAgcmV0dXJuIGxpbmVhclJpbmdzQXJlYSh0aGlzLmdldE9yaWVudGVkRmxhdENvb3JkaW5hdGVzKCksIDAsIHRoaXMuZW5kc18sIHRoaXMuc3RyaWRlKTtcbiAgfTtcbiAgLyoqXG4gICAqIEdldCB0aGUgY29vcmRpbmF0ZSBhcnJheSBmb3IgdGhpcyBnZW9tZXRyeS4gIFRoaXMgYXJyYXkgaGFzIHRoZSBzdHJ1Y3R1cmVcbiAgICogb2YgYSBHZW9KU09OIGNvb3JkaW5hdGUgYXJyYXkgZm9yIHBvbHlnb25zLlxuICAgKlxuICAgKiBAcGFyYW0ge2Jvb2xlYW49fSBvcHRfcmlnaHQgT3JpZW50IGNvb3JkaW5hdGVzIGFjY29yZGluZyB0byB0aGUgcmlnaHQtaGFuZFxuICAgKiAgICAgcnVsZSAoY291bnRlci1jbG9ja3dpc2UgZm9yIGV4dGVyaW9yIGFuZCBjbG9ja3dpc2UgZm9yIGludGVyaW9yIHJpbmdzKS5cbiAgICogICAgIElmIGBmYWxzZWAsIGNvb3JkaW5hdGVzIHdpbGwgYmUgb3JpZW50ZWQgYWNjb3JkaW5nIHRvIHRoZSBsZWZ0LWhhbmQgcnVsZVxuICAgKiAgICAgKGNsb2Nrd2lzZSBmb3IgZXh0ZXJpb3IgYW5kIGNvdW50ZXItY2xvY2t3aXNlIGZvciBpbnRlcmlvciByaW5ncykuXG4gICAqICAgICBCeSBkZWZhdWx0LCBjb29yZGluYXRlIG9yaWVudGF0aW9uIHdpbGwgZGVwZW5kIG9uIGhvdyB0aGUgZ2VvbWV0cnkgd2FzXG4gICAqICAgICBjb25zdHJ1Y3RlZC5cbiAgICogQHJldHVybiB7QXJyYXk8QXJyYXk8aW1wb3J0KFwiLi4vY29vcmRpbmF0ZS5qc1wiKS5Db29yZGluYXRlPj59IENvb3JkaW5hdGVzLlxuICAgKiBAYXBpXG4gICAqL1xuXG5cbiAgUG9seWdvbi5wcm90b3R5cGUuZ2V0Q29vcmRpbmF0ZXMgPSBmdW5jdGlvbiAob3B0X3JpZ2h0KSB7XG4gICAgdmFyIGZsYXRDb29yZGluYXRlcztcblxuICAgIGlmIChvcHRfcmlnaHQgIT09IHVuZGVmaW5lZCkge1xuICAgICAgZmxhdENvb3JkaW5hdGVzID0gdGhpcy5nZXRPcmllbnRlZEZsYXRDb29yZGluYXRlcygpLnNsaWNlKCk7XG4gICAgICBvcmllbnRMaW5lYXJSaW5ncyhmbGF0Q29vcmRpbmF0ZXMsIDAsIHRoaXMuZW5kc18sIHRoaXMuc3RyaWRlLCBvcHRfcmlnaHQpO1xuICAgIH0gZWxzZSB7XG4gICAgICBmbGF0Q29vcmRpbmF0ZXMgPSB0aGlzLmZsYXRDb29yZGluYXRlcztcbiAgICB9XG5cbiAgICByZXR1cm4gaW5mbGF0ZUNvb3JkaW5hdGVzQXJyYXkoZmxhdENvb3JkaW5hdGVzLCAwLCB0aGlzLmVuZHNfLCB0aGlzLnN0cmlkZSk7XG4gIH07XG4gIC8qKlxuICAgKiBAcmV0dXJuIHtBcnJheTxudW1iZXI+fSBFbmRzLlxuICAgKi9cblxuXG4gIFBvbHlnb24ucHJvdG90eXBlLmdldEVuZHMgPSBmdW5jdGlvbiAoKSB7XG4gICAgcmV0dXJuIHRoaXMuZW5kc187XG4gIH07XG4gIC8qKlxuICAgKiBAcmV0dXJuIHtBcnJheTxudW1iZXI+fSBJbnRlcmlvciBwb2ludC5cbiAgICovXG5cblxuICBQb2x5Z29uLnByb3RvdHlwZS5nZXRGbGF0SW50ZXJpb3JQb2ludCA9IGZ1bmN0aW9uICgpIHtcbiAgICBpZiAodGhpcy5mbGF0SW50ZXJpb3JQb2ludFJldmlzaW9uXyAhPSB0aGlzLmdldFJldmlzaW9uKCkpIHtcbiAgICAgIHZhciBmbGF0Q2VudGVyID0gZ2V0Q2VudGVyKHRoaXMuZ2V0RXh0ZW50KCkpO1xuICAgICAgdGhpcy5mbGF0SW50ZXJpb3JQb2ludF8gPSBnZXRJbnRlcmlvclBvaW50T2ZBcnJheSh0aGlzLmdldE9yaWVudGVkRmxhdENvb3JkaW5hdGVzKCksIDAsIHRoaXMuZW5kc18sIHRoaXMuc3RyaWRlLCBmbGF0Q2VudGVyLCAwKTtcbiAgICAgIHRoaXMuZmxhdEludGVyaW9yUG9pbnRSZXZpc2lvbl8gPSB0aGlzLmdldFJldmlzaW9uKCk7XG4gICAgfVxuXG4gICAgcmV0dXJuIHRoaXMuZmxhdEludGVyaW9yUG9pbnRfO1xuICB9O1xuICAvKipcbiAgICogUmV0dXJuIGFuIGludGVyaW9yIHBvaW50IG9mIHRoZSBwb2x5Z29uLlxuICAgKiBAcmV0dXJuIHtQb2ludH0gSW50ZXJpb3IgcG9pbnQgYXMgWFlNIGNvb3JkaW5hdGUsIHdoZXJlIE0gaXMgdGhlXG4gICAqIGxlbmd0aCBvZiB0aGUgaG9yaXpvbnRhbCBpbnRlcnNlY3Rpb24gdGhhdCB0aGUgcG9pbnQgYmVsb25ncyB0by5cbiAgICogQGFwaVxuICAgKi9cblxuXG4gIFBvbHlnb24ucHJvdG90eXBlLmdldEludGVyaW9yUG9pbnQgPSBmdW5jdGlvbiAoKSB7XG4gICAgcmV0dXJuIG5ldyBQb2ludCh0aGlzLmdldEZsYXRJbnRlcmlvclBvaW50KCksIEdlb21ldHJ5TGF5b3V0LlhZTSk7XG4gIH07XG4gIC8qKlxuICAgKiBSZXR1cm4gdGhlIG51bWJlciBvZiByaW5ncyBvZiB0aGUgcG9seWdvbiwgIHRoaXMgaW5jbHVkZXMgdGhlIGV4dGVyaW9yXG4gICAqIHJpbmcgYW5kIGFueSBpbnRlcmlvciByaW5ncy5cbiAgICpcbiAgICogQHJldHVybiB7bnVtYmVyfSBOdW1iZXIgb2YgcmluZ3MuXG4gICAqIEBhcGlcbiAgICovXG5cblxuICBQb2x5Z29uLnByb3RvdHlwZS5nZXRMaW5lYXJSaW5nQ291bnQgPSBmdW5jdGlvbiAoKSB7XG4gICAgcmV0dXJuIHRoaXMuZW5kc18ubGVuZ3RoO1xuICB9O1xuICAvKipcbiAgICogUmV0dXJuIHRoZSBOdGggbGluZWFyIHJpbmcgb2YgdGhlIHBvbHlnb24gZ2VvbWV0cnkuIFJldHVybiBgbnVsbGAgaWYgdGhlXG4gICAqIGdpdmVuIGluZGV4IGlzIG91dCBvZiByYW5nZS5cbiAgICogVGhlIGV4dGVyaW9yIGxpbmVhciByaW5nIGlzIGF2YWlsYWJsZSBhdCBpbmRleCBgMGAgYW5kIHRoZSBpbnRlcmlvciByaW5nc1xuICAgKiBhdCBpbmRleCBgMWAgYW5kIGJleW9uZC5cbiAgICpcbiAgICogQHBhcmFtIHtudW1iZXJ9IGluZGV4IEluZGV4LlxuICAgKiBAcmV0dXJuIHtMaW5lYXJSaW5nfSBMaW5lYXIgcmluZy5cbiAgICogQGFwaVxuICAgKi9cblxuXG4gIFBvbHlnb24ucHJvdG90eXBlLmdldExpbmVhclJpbmcgPSBmdW5jdGlvbiAoaW5kZXgpIHtcbiAgICBpZiAoaW5kZXggPCAwIHx8IHRoaXMuZW5kc18ubGVuZ3RoIDw9IGluZGV4KSB7XG4gICAgICByZXR1cm4gbnVsbDtcbiAgICB9XG5cbiAgICByZXR1cm4gbmV3IExpbmVhclJpbmcodGhpcy5mbGF0Q29vcmRpbmF0ZXMuc2xpY2UoaW5kZXggPT09IDAgPyAwIDogdGhpcy5lbmRzX1tpbmRleCAtIDFdLCB0aGlzLmVuZHNfW2luZGV4XSksIHRoaXMubGF5b3V0KTtcbiAgfTtcbiAgLyoqXG4gICAqIFJldHVybiB0aGUgbGluZWFyIHJpbmdzIG9mIHRoZSBwb2x5Z29uLlxuICAgKiBAcmV0dXJuIHtBcnJheTxMaW5lYXJSaW5nPn0gTGluZWFyIHJpbmdzLlxuICAgKiBAYXBpXG4gICAqL1xuXG5cbiAgUG9seWdvbi5wcm90b3R5cGUuZ2V0TGluZWFyUmluZ3MgPSBmdW5jdGlvbiAoKSB7XG4gICAgdmFyIGxheW91dCA9IHRoaXMubGF5b3V0O1xuICAgIHZhciBmbGF0Q29vcmRpbmF0ZXMgPSB0aGlzLmZsYXRDb29yZGluYXRlcztcbiAgICB2YXIgZW5kcyA9IHRoaXMuZW5kc187XG4gICAgdmFyIGxpbmVhclJpbmdzID0gW107XG4gICAgdmFyIG9mZnNldCA9IDA7XG5cbiAgICBmb3IgKHZhciBpID0gMCwgaWkgPSBlbmRzLmxlbmd0aDsgaSA8IGlpOyArK2kpIHtcbiAgICAgIHZhciBlbmQgPSBlbmRzW2ldO1xuICAgICAgdmFyIGxpbmVhclJpbmcgPSBuZXcgTGluZWFyUmluZyhmbGF0Q29vcmRpbmF0ZXMuc2xpY2Uob2Zmc2V0LCBlbmQpLCBsYXlvdXQpO1xuICAgICAgbGluZWFyUmluZ3MucHVzaChsaW5lYXJSaW5nKTtcbiAgICAgIG9mZnNldCA9IGVuZDtcbiAgICB9XG5cbiAgICByZXR1cm4gbGluZWFyUmluZ3M7XG4gIH07XG4gIC8qKlxuICAgKiBAcmV0dXJuIHtBcnJheTxudW1iZXI+fSBPcmllbnRlZCBmbGF0IGNvb3JkaW5hdGVzLlxuICAgKi9cblxuXG4gIFBvbHlnb24ucHJvdG90eXBlLmdldE9yaWVudGVkRmxhdENvb3JkaW5hdGVzID0gZnVuY3Rpb24gKCkge1xuICAgIGlmICh0aGlzLm9yaWVudGVkUmV2aXNpb25fICE9IHRoaXMuZ2V0UmV2aXNpb24oKSkge1xuICAgICAgdmFyIGZsYXRDb29yZGluYXRlcyA9IHRoaXMuZmxhdENvb3JkaW5hdGVzO1xuXG4gICAgICBpZiAobGluZWFyUmluZ3NBcmVPcmllbnRlZChmbGF0Q29vcmRpbmF0ZXMsIDAsIHRoaXMuZW5kc18sIHRoaXMuc3RyaWRlKSkge1xuICAgICAgICB0aGlzLm9yaWVudGVkRmxhdENvb3JkaW5hdGVzXyA9IGZsYXRDb29yZGluYXRlcztcbiAgICAgIH0gZWxzZSB7XG4gICAgICAgIHRoaXMub3JpZW50ZWRGbGF0Q29vcmRpbmF0ZXNfID0gZmxhdENvb3JkaW5hdGVzLnNsaWNlKCk7XG4gICAgICAgIHRoaXMub3JpZW50ZWRGbGF0Q29vcmRpbmF0ZXNfLmxlbmd0aCA9IG9yaWVudExpbmVhclJpbmdzKHRoaXMub3JpZW50ZWRGbGF0Q29vcmRpbmF0ZXNfLCAwLCB0aGlzLmVuZHNfLCB0aGlzLnN0cmlkZSk7XG4gICAgICB9XG5cbiAgICAgIHRoaXMub3JpZW50ZWRSZXZpc2lvbl8gPSB0aGlzLmdldFJldmlzaW9uKCk7XG4gICAgfVxuXG4gICAgcmV0dXJuIHRoaXMub3JpZW50ZWRGbGF0Q29vcmRpbmF0ZXNfO1xuICB9O1xuICAvKipcbiAgICogQHBhcmFtIHtudW1iZXJ9IHNxdWFyZWRUb2xlcmFuY2UgU3F1YXJlZCB0b2xlcmFuY2UuXG4gICAqIEByZXR1cm4ge1BvbHlnb259IFNpbXBsaWZpZWQgUG9seWdvbi5cbiAgICogQHByb3RlY3RlZFxuICAgKi9cblxuXG4gIFBvbHlnb24ucHJvdG90eXBlLmdldFNpbXBsaWZpZWRHZW9tZXRyeUludGVybmFsID0gZnVuY3Rpb24gKHNxdWFyZWRUb2xlcmFuY2UpIHtcbiAgICB2YXIgc2ltcGxpZmllZEZsYXRDb29yZGluYXRlcyA9IFtdO1xuICAgIHZhciBzaW1wbGlmaWVkRW5kcyA9IFtdO1xuICAgIHNpbXBsaWZpZWRGbGF0Q29vcmRpbmF0ZXMubGVuZ3RoID0gcXVhbnRpemVBcnJheSh0aGlzLmZsYXRDb29yZGluYXRlcywgMCwgdGhpcy5lbmRzXywgdGhpcy5zdHJpZGUsIE1hdGguc3FydChzcXVhcmVkVG9sZXJhbmNlKSwgc2ltcGxpZmllZEZsYXRDb29yZGluYXRlcywgMCwgc2ltcGxpZmllZEVuZHMpO1xuICAgIHJldHVybiBuZXcgUG9seWdvbihzaW1wbGlmaWVkRmxhdENvb3JkaW5hdGVzLCBHZW9tZXRyeUxheW91dC5YWSwgc2ltcGxpZmllZEVuZHMpO1xuICB9O1xuICAvKipcbiAgICogR2V0IHRoZSB0eXBlIG9mIHRoaXMgZ2VvbWV0cnkuXG4gICAqIEByZXR1cm4ge2ltcG9ydChcIi4vR2VvbWV0cnlUeXBlLmpzXCIpLmRlZmF1bHR9IEdlb21ldHJ5IHR5cGUuXG4gICAqIEBhcGlcbiAgICovXG5cblxuICBQb2x5Z29uLnByb3RvdHlwZS5nZXRUeXBlID0gZnVuY3Rpb24gKCkge1xuICAgIHJldHVybiBHZW9tZXRyeVR5cGUuUE9MWUdPTjtcbiAgfTtcbiAgLyoqXG4gICAqIFRlc3QgaWYgdGhlIGdlb21ldHJ5IGFuZCB0aGUgcGFzc2VkIGV4dGVudCBpbnRlcnNlY3QuXG4gICAqIEBwYXJhbSB7aW1wb3J0KFwiLi4vZXh0ZW50LmpzXCIpLkV4dGVudH0gZXh0ZW50IEV4dGVudC5cbiAgICogQHJldHVybiB7Ym9vbGVhbn0gYHRydWVgIGlmIHRoZSBnZW9tZXRyeSBhbmQgdGhlIGV4dGVudCBpbnRlcnNlY3QuXG4gICAqIEBhcGlcbiAgICovXG5cblxuICBQb2x5Z29uLnByb3RvdHlwZS5pbnRlcnNlY3RzRXh0ZW50ID0gZnVuY3Rpb24gKGV4dGVudCkge1xuICAgIHJldHVybiBpbnRlcnNlY3RzTGluZWFyUmluZ0FycmF5KHRoaXMuZ2V0T3JpZW50ZWRGbGF0Q29vcmRpbmF0ZXMoKSwgMCwgdGhpcy5lbmRzXywgdGhpcy5zdHJpZGUsIGV4dGVudCk7XG4gIH07XG4gIC8qKlxuICAgKiBTZXQgdGhlIGNvb3JkaW5hdGVzIG9mIHRoZSBwb2x5Z29uLlxuICAgKiBAcGFyYW0geyFBcnJheTxBcnJheTxpbXBvcnQoXCIuLi9jb29yZGluYXRlLmpzXCIpLkNvb3JkaW5hdGU+Pn0gY29vcmRpbmF0ZXMgQ29vcmRpbmF0ZXMuXG4gICAqIEBwYXJhbSB7aW1wb3J0KFwiLi9HZW9tZXRyeUxheW91dC5qc1wiKS5kZWZhdWx0PX0gb3B0X2xheW91dCBMYXlvdXQuXG4gICAqIEBhcGlcbiAgICovXG5cblxuICBQb2x5Z29uLnByb3RvdHlwZS5zZXRDb29yZGluYXRlcyA9IGZ1bmN0aW9uIChjb29yZGluYXRlcywgb3B0X2xheW91dCkge1xuICAgIHRoaXMuc2V0TGF5b3V0KG9wdF9sYXlvdXQsIGNvb3JkaW5hdGVzLCAyKTtcblxuICAgIGlmICghdGhpcy5mbGF0Q29vcmRpbmF0ZXMpIHtcbiAgICAgIHRoaXMuZmxhdENvb3JkaW5hdGVzID0gW107XG4gICAgfVxuXG4gICAgdmFyIGVuZHMgPSBkZWZsYXRlQ29vcmRpbmF0ZXNBcnJheSh0aGlzLmZsYXRDb29yZGluYXRlcywgMCwgY29vcmRpbmF0ZXMsIHRoaXMuc3RyaWRlLCB0aGlzLmVuZHNfKTtcbiAgICB0aGlzLmZsYXRDb29yZGluYXRlcy5sZW5ndGggPSBlbmRzLmxlbmd0aCA9PT0gMCA/IDAgOiBlbmRzW2VuZHMubGVuZ3RoIC0gMV07XG4gICAgdGhpcy5jaGFuZ2VkKCk7XG4gIH07XG5cbiAgcmV0dXJuIFBvbHlnb247XG59KFNpbXBsZUdlb21ldHJ5KTtcblxuZXhwb3J0IGRlZmF1bHQgUG9seWdvbjtcbi8qKlxuICogQ3JlYXRlIGFuIGFwcHJveGltYXRpb24gb2YgYSBjaXJjbGUgb24gdGhlIHN1cmZhY2Ugb2YgYSBzcGhlcmUuXG4gKiBAcGFyYW0ge2ltcG9ydChcIi4uL2Nvb3JkaW5hdGUuanNcIikuQ29vcmRpbmF0ZX0gY2VudGVyIENlbnRlciAoYFtsb24sIGxhdF1gIGluIGRlZ3JlZXMpLlxuICogQHBhcmFtIHtudW1iZXJ9IHJhZGl1cyBUaGUgZ3JlYXQtY2lyY2xlIGRpc3RhbmNlIGZyb20gdGhlIGNlbnRlciB0b1xuICogICAgIHRoZSBwb2x5Z29uIHZlcnRpY2VzLlxuICogQHBhcmFtIHtudW1iZXI9fSBvcHRfbiBPcHRpb25hbCBudW1iZXIgb2YgdmVydGljZXMgZm9yIHRoZSByZXN1bHRpbmdcbiAqICAgICBwb2x5Z29uLiBEZWZhdWx0IGlzIGAzMmAuXG4gKiBAcGFyYW0ge251bWJlcj19IG9wdF9zcGhlcmVSYWRpdXMgT3B0aW9uYWwgcmFkaXVzIGZvciB0aGUgc3BoZXJlIChkZWZhdWx0cyB0b1xuICogICAgIHRoZSBFYXJ0aCdzIG1lYW4gcmFkaXVzIHVzaW5nIHRoZSBXR1M4NCBlbGxpcHNvaWQpLlxuICogQHJldHVybiB7UG9seWdvbn0gVGhlIFwiY2lyY3VsYXJcIiBwb2x5Z29uLlxuICogQGFwaVxuICovXG5cbmV4cG9ydCBmdW5jdGlvbiBjaXJjdWxhcihjZW50ZXIsIHJhZGl1cywgb3B0X24sIG9wdF9zcGhlcmVSYWRpdXMpIHtcbiAgdmFyIG4gPSBvcHRfbiA/IG9wdF9uIDogMzI7XG4gIC8qKiBAdHlwZSB7QXJyYXk8bnVtYmVyPn0gKi9cblxuICB2YXIgZmxhdENvb3JkaW5hdGVzID0gW107XG5cbiAgZm9yICh2YXIgaSA9IDA7IGkgPCBuOyArK2kpIHtcbiAgICBleHRlbmQoZmxhdENvb3JkaW5hdGVzLCBzcGhlcmVPZmZzZXQoY2VudGVyLCByYWRpdXMsIDIgKiBNYXRoLlBJICogaSAvIG4sIG9wdF9zcGhlcmVSYWRpdXMpKTtcbiAgfVxuXG4gIGZsYXRDb29yZGluYXRlcy5wdXNoKGZsYXRDb29yZGluYXRlc1swXSwgZmxhdENvb3JkaW5hdGVzWzFdKTtcbiAgcmV0dXJuIG5ldyBQb2x5Z29uKGZsYXRDb29yZGluYXRlcywgR2VvbWV0cnlMYXlvdXQuWFksIFtmbGF0Q29vcmRpbmF0ZXMubGVuZ3RoXSk7XG59XG4vKipcbiAqIENyZWF0ZSBhIHBvbHlnb24gZnJvbSBhbiBleHRlbnQuIFRoZSBsYXlvdXQgdXNlZCBpcyBgWFlgLlxuICogQHBhcmFtIHtpbXBvcnQoXCIuLi9leHRlbnQuanNcIikuRXh0ZW50fSBleHRlbnQgVGhlIGV4dGVudC5cbiAqIEByZXR1cm4ge1BvbHlnb259IFRoZSBwb2x5Z29uLlxuICogQGFwaVxuICovXG5cbmV4cG9ydCBmdW5jdGlvbiBmcm9tRXh0ZW50KGV4dGVudCkge1xuICB2YXIgbWluWCA9IGV4dGVudFswXTtcbiAgdmFyIG1pblkgPSBleHRlbnRbMV07XG4gIHZhciBtYXhYID0gZXh0ZW50WzJdO1xuICB2YXIgbWF4WSA9IGV4dGVudFszXTtcbiAgdmFyIGZsYXRDb29yZGluYXRlcyA9IFttaW5YLCBtaW5ZLCBtaW5YLCBtYXhZLCBtYXhYLCBtYXhZLCBtYXhYLCBtaW5ZLCBtaW5YLCBtaW5ZXTtcbiAgcmV0dXJuIG5ldyBQb2x5Z29uKGZsYXRDb29yZGluYXRlcywgR2VvbWV0cnlMYXlvdXQuWFksIFtmbGF0Q29vcmRpbmF0ZXMubGVuZ3RoXSk7XG59XG4vKipcbiAqIENyZWF0ZSBhIHJlZ3VsYXIgcG9seWdvbiBmcm9tIGEgY2lyY2xlLlxuICogQHBhcmFtIHtpbXBvcnQoXCIuL0NpcmNsZS5qc1wiKS5kZWZhdWx0fSBjaXJjbGUgQ2lyY2xlIGdlb21ldHJ5LlxuICogQHBhcmFtIHtudW1iZXI9fSBvcHRfc2lkZXMgTnVtYmVyIG9mIHNpZGVzIG9mIHRoZSBwb2x5Z29uLiBEZWZhdWx0IGlzIDMyLlxuICogQHBhcmFtIHtudW1iZXI9fSBvcHRfYW5nbGUgU3RhcnQgYW5nbGUgZm9yIHRoZSBmaXJzdCB2ZXJ0ZXggb2YgdGhlIHBvbHlnb24gaW5cbiAqICAgICBjb3VudGVyLWNsb2Nrd2lzZSByYWRpYW5zLiAwIG1lYW5zIEVhc3QuIERlZmF1bHQgaXMgMC5cbiAqIEByZXR1cm4ge1BvbHlnb259IFBvbHlnb24gZ2VvbWV0cnkuXG4gKiBAYXBpXG4gKi9cblxuZXhwb3J0IGZ1bmN0aW9uIGZyb21DaXJjbGUoY2lyY2xlLCBvcHRfc2lkZXMsIG9wdF9hbmdsZSkge1xuICB2YXIgc2lkZXMgPSBvcHRfc2lkZXMgPyBvcHRfc2lkZXMgOiAzMjtcbiAgdmFyIHN0cmlkZSA9IGNpcmNsZS5nZXRTdHJpZGUoKTtcbiAgdmFyIGxheW91dCA9IGNpcmNsZS5nZXRMYXlvdXQoKTtcbiAgdmFyIGNlbnRlciA9IGNpcmNsZS5nZXRDZW50ZXIoKTtcbiAgdmFyIGFycmF5TGVuZ3RoID0gc3RyaWRlICogKHNpZGVzICsgMSk7XG4gIHZhciBmbGF0Q29vcmRpbmF0ZXMgPSBuZXcgQXJyYXkoYXJyYXlMZW5ndGgpO1xuXG4gIGZvciAodmFyIGkgPSAwOyBpIDwgYXJyYXlMZW5ndGg7IGkgKz0gc3RyaWRlKSB7XG4gICAgZmxhdENvb3JkaW5hdGVzW2ldID0gMDtcbiAgICBmbGF0Q29vcmRpbmF0ZXNbaSArIDFdID0gMDtcblxuICAgIGZvciAodmFyIGogPSAyOyBqIDwgc3RyaWRlOyBqKyspIHtcbiAgICAgIGZsYXRDb29yZGluYXRlc1tpICsgal0gPSBjZW50ZXJbal07XG4gICAgfVxuICB9XG5cbiAgdmFyIGVuZHMgPSBbZmxhdENvb3JkaW5hdGVzLmxlbmd0aF07XG4gIHZhciBwb2x5Z29uID0gbmV3IFBvbHlnb24oZmxhdENvb3JkaW5hdGVzLCBsYXlvdXQsIGVuZHMpO1xuICBtYWtlUmVndWxhcihwb2x5Z29uLCBjZW50ZXIsIGNpcmNsZS5nZXRSYWRpdXMoKSwgb3B0X2FuZ2xlKTtcbiAgcmV0dXJuIHBvbHlnb247XG59XG4vKipcbiAqIE1vZGlmeSB0aGUgY29vcmRpbmF0ZXMgb2YgYSBwb2x5Z29uIHRvIG1ha2UgaXQgYSByZWd1bGFyIHBvbHlnb24uXG4gKiBAcGFyYW0ge1BvbHlnb259IHBvbHlnb24gUG9seWdvbiBnZW9tZXRyeS5cbiAqIEBwYXJhbSB7aW1wb3J0KFwiLi4vY29vcmRpbmF0ZS5qc1wiKS5Db29yZGluYXRlfSBjZW50ZXIgQ2VudGVyIG9mIHRoZSByZWd1bGFyIHBvbHlnb24uXG4gKiBAcGFyYW0ge251bWJlcn0gcmFkaXVzIFJhZGl1cyBvZiB0aGUgcmVndWxhciBwb2x5Z29uLlxuICogQHBhcmFtIHtudW1iZXI9fSBvcHRfYW5nbGUgU3RhcnQgYW5nbGUgZm9yIHRoZSBmaXJzdCB2ZXJ0ZXggb2YgdGhlIHBvbHlnb24gaW5cbiAqICAgICBjb3VudGVyLWNsb2Nrd2lzZSByYWRpYW5zLiAwIG1lYW5zIEVhc3QuIERlZmF1bHQgaXMgMC5cbiAqL1xuXG5leHBvcnQgZnVuY3Rpb24gbWFrZVJlZ3VsYXIocG9seWdvbiwgY2VudGVyLCByYWRpdXMsIG9wdF9hbmdsZSkge1xuICB2YXIgZmxhdENvb3JkaW5hdGVzID0gcG9seWdvbi5nZXRGbGF0Q29vcmRpbmF0ZXMoKTtcbiAgdmFyIHN0cmlkZSA9IHBvbHlnb24uZ2V0U3RyaWRlKCk7XG4gIHZhciBzaWRlcyA9IGZsYXRDb29yZGluYXRlcy5sZW5ndGggLyBzdHJpZGUgLSAxO1xuICB2YXIgc3RhcnRBbmdsZSA9IG9wdF9hbmdsZSA/IG9wdF9hbmdsZSA6IDA7XG5cbiAgZm9yICh2YXIgaSA9IDA7IGkgPD0gc2lkZXM7ICsraSkge1xuICAgIHZhciBvZmZzZXQgPSBpICogc3RyaWRlO1xuICAgIHZhciBhbmdsZSA9IHN0YXJ0QW5nbGUgKyBtb2R1bG8oaSwgc2lkZXMpICogMiAqIE1hdGguUEkgLyBzaWRlcztcbiAgICBmbGF0Q29vcmRpbmF0ZXNbb2Zmc2V0XSA9IGNlbnRlclswXSArIHJhZGl1cyAqIE1hdGguY29zKGFuZ2xlKTtcbiAgICBmbGF0Q29vcmRpbmF0ZXNbb2Zmc2V0ICsgMV0gPSBjZW50ZXJbMV0gKyByYWRpdXMgKiBNYXRoLnNpbihhbmdsZSk7XG4gIH1cblxuICBwb2x5Z29uLmNoYW5nZWQoKTtcbn0iLCJ2YXIgX19leHRlbmRzID0gdGhpcyAmJiB0aGlzLl9fZXh0ZW5kcyB8fCBmdW5jdGlvbiAoKSB7XG4gIHZhciBfZXh0ZW5kU3RhdGljcyA9IGZ1bmN0aW9uIGV4dGVuZFN0YXRpY3MoZCwgYikge1xuICAgIF9leHRlbmRTdGF0aWNzID0gT2JqZWN0LnNldFByb3RvdHlwZU9mIHx8IHtcbiAgICAgIF9fcHJvdG9fXzogW11cbiAgICB9IGluc3RhbmNlb2YgQXJyYXkgJiYgZnVuY3Rpb24gKGQsIGIpIHtcbiAgICAgIGQuX19wcm90b19fID0gYjtcbiAgICB9IHx8IGZ1bmN0aW9uIChkLCBiKSB7XG4gICAgICBmb3IgKHZhciBwIGluIGIpIHtcbiAgICAgICAgaWYgKE9iamVjdC5wcm90b3R5cGUuaGFzT3duUHJvcGVydHkuY2FsbChiLCBwKSkgZFtwXSA9IGJbcF07XG4gICAgICB9XG4gICAgfTtcblxuICAgIHJldHVybiBfZXh0ZW5kU3RhdGljcyhkLCBiKTtcbiAgfTtcblxuICByZXR1cm4gZnVuY3Rpb24gKGQsIGIpIHtcbiAgICBfZXh0ZW5kU3RhdGljcyhkLCBiKTtcblxuICAgIGZ1bmN0aW9uIF9fKCkge1xuICAgICAgdGhpcy5jb25zdHJ1Y3RvciA9IGQ7XG4gICAgfVxuXG4gICAgZC5wcm90b3R5cGUgPSBiID09PSBudWxsID8gT2JqZWN0LmNyZWF0ZShiKSA6IChfXy5wcm90b3R5cGUgPSBiLnByb3RvdHlwZSwgbmV3IF9fKCkpO1xuICB9O1xufSgpO1xuLyoqXG4gKiBAbW9kdWxlIG9sL1ZpZXdcbiAqL1xuXG5cbmltcG9ydCBCYXNlT2JqZWN0IGZyb20gJy4vT2JqZWN0LmpzJztcbmltcG9ydCBHZW9tZXRyeVR5cGUgZnJvbSAnLi9nZW9tL0dlb21ldHJ5VHlwZS5qcyc7XG5pbXBvcnQgVW5pdHMgZnJvbSAnLi9wcm9qL1VuaXRzLmpzJztcbmltcG9ydCBWaWV3SGludCBmcm9tICcuL1ZpZXdIaW50LmpzJztcbmltcG9ydCBWaWV3UHJvcGVydHkgZnJvbSAnLi9WaWV3UHJvcGVydHkuanMnO1xuaW1wb3J0IHsgREVGQVVMVF9USUxFX1NJWkUgfSBmcm9tICcuL3RpbGVncmlkL2NvbW1vbi5qcyc7XG5pbXBvcnQgeyBNRVRFUlNfUEVSX1VOSVQsIGNyZWF0ZVByb2plY3Rpb24sIGZyb21Vc2VyQ29vcmRpbmF0ZSwgZnJvbVVzZXJFeHRlbnQsIGdldFVzZXJQcm9qZWN0aW9uLCB0b1VzZXJDb29yZGluYXRlLCB0b1VzZXJFeHRlbnQgfSBmcm9tICcuL3Byb2ouanMnO1xuaW1wb3J0IHsgVk9JRCB9IGZyb20gJy4vZnVuY3Rpb25zLmpzJztcbmltcG9ydCB7IGFkZCBhcyBhZGRDb29yZGluYXRlLCBlcXVhbHMgYXMgY29vcmRpbmF0ZXNFcXVhbCwgcm90YXRlIGFzIHJvdGF0ZUNvb3JkaW5hdGUgfSBmcm9tICcuL2Nvb3JkaW5hdGUuanMnO1xuaW1wb3J0IHsgYXNzZXJ0IH0gZnJvbSAnLi9hc3NlcnRzLmpzJztcbmltcG9ydCB7IGFzc2lnbiB9IGZyb20gJy4vb2JqLmpzJztcbmltcG9ydCB7IG5vbmUgYXMgY2VudGVyTm9uZSwgY3JlYXRlRXh0ZW50IH0gZnJvbSAnLi9jZW50ZXJjb25zdHJhaW50LmpzJztcbmltcG9ydCB7IGNsYW1wLCBtb2R1bG8gfSBmcm9tICcuL21hdGguanMnO1xuaW1wb3J0IHsgY3JlYXRlTWluTWF4UmVzb2x1dGlvbiB9IGZyb20gJy4vcmVzb2x1dGlvbmNvbnN0cmFpbnQuanMnO1xuaW1wb3J0IHsgY3JlYXRlU25hcFRvTiwgY3JlYXRlU25hcFRvWmVybywgZGlzYWJsZSwgbm9uZSBhcyByb3RhdGlvbk5vbmUgfSBmcm9tICcuL3JvdGF0aW9uY29uc3RyYWludC5qcyc7XG5pbXBvcnQgeyBjcmVhdGVTbmFwVG9Qb3dlciwgY3JlYXRlU25hcFRvUmVzb2x1dGlvbnMgfSBmcm9tICcuL3Jlc29sdXRpb25jb25zdHJhaW50LmpzJztcbmltcG9ydCB7IGVhc2VPdXQgfSBmcm9tICcuL2Vhc2luZy5qcyc7XG5pbXBvcnQgeyBlcXVhbHMgfSBmcm9tICcuL2Nvb3JkaW5hdGUuanMnO1xuaW1wb3J0IHsgZ2V0Q2VudGVyLCBnZXRGb3JWaWV3QW5kU2l6ZSwgZ2V0SGVpZ2h0LCBnZXRXaWR0aCwgaXNFbXB0eSB9IGZyb20gJy4vZXh0ZW50LmpzJztcbmltcG9ydCB7IGluQW5kT3V0IH0gZnJvbSAnLi9lYXNpbmcuanMnO1xuaW1wb3J0IHsgbGluZWFyRmluZE5lYXJlc3QgfSBmcm9tICcuL2FycmF5LmpzJztcbmltcG9ydCB7IGZyb21FeHRlbnQgYXMgcG9seWdvbkZyb21FeHRlbnQgfSBmcm9tICcuL2dlb20vUG9seWdvbi5qcyc7XG4vKipcbiAqIEFuIGFuaW1hdGlvbiBjb25maWd1cmF0aW9uXG4gKlxuICogQHR5cGVkZWYge09iamVjdH0gQW5pbWF0aW9uXG4gKiBAcHJvcGVydHkge2ltcG9ydChcIi4vY29vcmRpbmF0ZS5qc1wiKS5Db29yZGluYXRlfSBbc291cmNlQ2VudGVyXVxuICogQHByb3BlcnR5IHtpbXBvcnQoXCIuL2Nvb3JkaW5hdGUuanNcIikuQ29vcmRpbmF0ZX0gW3RhcmdldENlbnRlcl1cbiAqIEBwcm9wZXJ0eSB7bnVtYmVyfSBbc291cmNlUmVzb2x1dGlvbl1cbiAqIEBwcm9wZXJ0eSB7bnVtYmVyfSBbdGFyZ2V0UmVzb2x1dGlvbl1cbiAqIEBwcm9wZXJ0eSB7bnVtYmVyfSBbc291cmNlUm90YXRpb25dXG4gKiBAcHJvcGVydHkge251bWJlcn0gW3RhcmdldFJvdGF0aW9uXVxuICogQHByb3BlcnR5IHtpbXBvcnQoXCIuL2Nvb3JkaW5hdGUuanNcIikuQ29vcmRpbmF0ZX0gW2FuY2hvcl1cbiAqIEBwcm9wZXJ0eSB7bnVtYmVyfSBzdGFydFxuICogQHByb3BlcnR5IHtudW1iZXJ9IGR1cmF0aW9uXG4gKiBAcHJvcGVydHkge2Jvb2xlYW59IGNvbXBsZXRlXG4gKiBAcHJvcGVydHkge2Z1bmN0aW9uKG51bWJlcik6bnVtYmVyfSBlYXNpbmdcbiAqIEBwcm9wZXJ0eSB7ZnVuY3Rpb24oYm9vbGVhbik6dm9pZH0gY2FsbGJhY2tcbiAqL1xuXG4vKipcbiAqIEB0eXBlZGVmIHtPYmplY3R9IENvbnN0cmFpbnRzXG4gKiBAcHJvcGVydHkge2ltcG9ydChcIi4vY2VudGVyY29uc3RyYWludC5qc1wiKS5UeXBlfSBjZW50ZXJcbiAqIEBwcm9wZXJ0eSB7aW1wb3J0KFwiLi9yZXNvbHV0aW9uY29uc3RyYWludC5qc1wiKS5UeXBlfSByZXNvbHV0aW9uXG4gKiBAcHJvcGVydHkge2ltcG9ydChcIi4vcm90YXRpb25jb25zdHJhaW50LmpzXCIpLlR5cGV9IHJvdGF0aW9uXG4gKi9cblxuLyoqXG4gKiBAdHlwZWRlZiB7T2JqZWN0fSBGaXRPcHRpb25zXG4gKiBAcHJvcGVydHkge2ltcG9ydChcIi4vc2l6ZS5qc1wiKS5TaXplfSBbc2l6ZV0gVGhlIHNpemUgaW4gcGl4ZWxzIG9mIHRoZSBib3ggdG8gZml0XG4gKiB0aGUgZXh0ZW50IGludG8uIERlZmF1bHQgaXMgdGhlIGN1cnJlbnQgc2l6ZSBvZiB0aGUgZmlyc3QgbWFwIGluIHRoZSBET00gdGhhdFxuICogdXNlcyB0aGlzIHZpZXcsIG9yIGBbMTAwLCAxMDBdYCBpZiBubyBzdWNoIG1hcCBpcyBmb3VuZC5cbiAqIEBwcm9wZXJ0eSB7IUFycmF5PG51bWJlcj59IFtwYWRkaW5nPVswLCAwLCAwLCAwXV0gUGFkZGluZyAoaW4gcGl4ZWxzKSB0byBiZVxuICogY2xlYXJlZCBpbnNpZGUgdGhlIHZpZXcuIFZhbHVlcyBpbiB0aGUgYXJyYXkgYXJlIHRvcCwgcmlnaHQsIGJvdHRvbSBhbmQgbGVmdFxuICogcGFkZGluZy5cbiAqIEBwcm9wZXJ0eSB7Ym9vbGVhbn0gW25lYXJlc3Q9ZmFsc2VdIElmIHRoZSB2aWV3IGBjb25zdHJhaW5SZXNvbHV0aW9uYCBvcHRpb24gaXMgYHRydWVgLFxuICogZ2V0IHRoZSBuZWFyZXN0IGV4dGVudCBpbnN0ZWFkIG9mIHRoZSBjbG9zZXN0IHRoYXQgYWN0dWFsbHkgZml0cyB0aGUgdmlldy5cbiAqIEBwcm9wZXJ0eSB7bnVtYmVyfSBbbWluUmVzb2x1dGlvbj0wXSBNaW5pbXVtIHJlc29sdXRpb24gdGhhdCB3ZSB6b29tIHRvLlxuICogQHByb3BlcnR5IHtudW1iZXJ9IFttYXhab29tXSBNYXhpbXVtIHpvb20gbGV2ZWwgdGhhdCB3ZSB6b29tIHRvLiBJZlxuICogYG1pblJlc29sdXRpb25gIGlzIGdpdmVuLCB0aGlzIHByb3BlcnR5IGlzIGlnbm9yZWQuXG4gKiBAcHJvcGVydHkge251bWJlcn0gW2R1cmF0aW9uXSBUaGUgZHVyYXRpb24gb2YgdGhlIGFuaW1hdGlvbiBpbiBtaWxsaXNlY29uZHMuXG4gKiBCeSBkZWZhdWx0LCB0aGVyZSBpcyBubyBhbmltYXRpb24gdG8gdGhlIHRhcmdldCBleHRlbnQuXG4gKiBAcHJvcGVydHkge2Z1bmN0aW9uKG51bWJlcik6bnVtYmVyfSBbZWFzaW5nXSBUaGUgZWFzaW5nIGZ1bmN0aW9uIHVzZWQgZHVyaW5nXG4gKiB0aGUgYW5pbWF0aW9uIChkZWZhdWx0cyB0byB7QGxpbmsgbW9kdWxlOm9sL2Vhc2luZ35pbkFuZE91dH0pLlxuICogVGhlIGZ1bmN0aW9uIHdpbGwgYmUgY2FsbGVkIGZvciBlYWNoIGZyYW1lIHdpdGggYSBudW1iZXIgcmVwcmVzZW50aW5nIGFcbiAqIGZyYWN0aW9uIG9mIHRoZSBhbmltYXRpb24ncyBkdXJhdGlvbi4gIFRoZSBmdW5jdGlvbiBzaG91bGQgcmV0dXJuIGEgbnVtYmVyXG4gKiBiZXR3ZWVuIDAgYW5kIDEgcmVwcmVzZW50aW5nIHRoZSBwcm9ncmVzcyB0b3dhcmQgdGhlIGRlc3RpbmF0aW9uIHN0YXRlLlxuICogQHByb3BlcnR5IHtmdW5jdGlvbihib29sZWFuKTp2b2lkfSBbY2FsbGJhY2tdIEZ1bmN0aW9uIGNhbGxlZCB3aGVuIHRoZSB2aWV3IGlzIGluXG4gKiBpdHMgZmluYWwgcG9zaXRpb24uIFRoZSBjYWxsYmFjayB3aWxsIGJlIGNhbGxlZCB3aXRoIGB0cnVlYCBpZiB0aGUgYW5pbWF0aW9uXG4gKiBzZXJpZXMgY29tcGxldGVkIG9uIGl0cyBvd24gb3IgYGZhbHNlYCBpZiBpdCB3YXMgY2FuY2VsbGVkLlxuICovXG5cbi8qKlxuICogQHR5cGVkZWYge09iamVjdH0gVmlld09wdGlvbnNcbiAqIEBwcm9wZXJ0eSB7aW1wb3J0KFwiLi9jb29yZGluYXRlLmpzXCIpLkNvb3JkaW5hdGV9IFtjZW50ZXJdIFRoZSBpbml0aWFsIGNlbnRlciBmb3JcbiAqIHRoZSB2aWV3LiBJZiBhIHVzZXIgcHJvamVjdGlvbiBpcyBub3Qgc2V0LCB0aGUgY29vcmRpbmF0ZSBzeXN0ZW0gZm9yIHRoZSBjZW50ZXIgaXNcbiAqIHNwZWNpZmllZCB3aXRoIHRoZSBgcHJvamVjdGlvbmAgb3B0aW9uLiBMYXllciBzb3VyY2VzIHdpbGwgbm90IGJlIGZldGNoZWQgaWYgdGhpc1xuICogaXMgbm90IHNldCwgYnV0IHRoZSBjZW50ZXIgY2FuIGJlIHNldCBsYXRlciB3aXRoIHtAbGluayAjc2V0Q2VudGVyfS5cbiAqIEBwcm9wZXJ0eSB7Ym9vbGVhbnxudW1iZXJ9IFtjb25zdHJhaW5Sb3RhdGlvbj10cnVlXSBSb3RhdGlvbiBjb25zdHJhaW50LlxuICogYGZhbHNlYCBtZWFucyBubyBjb25zdHJhaW50LiBgdHJ1ZWAgbWVhbnMgbm8gY29uc3RyYWludCwgYnV0IHNuYXAgdG8gemVyb1xuICogbmVhciB6ZXJvLiBBIG51bWJlciBjb25zdHJhaW5zIHRoZSByb3RhdGlvbiB0byB0aGF0IG51bWJlciBvZiB2YWx1ZXMuIEZvclxuICogZXhhbXBsZSwgYDRgIHdpbGwgY29uc3RyYWluIHRoZSByb3RhdGlvbiB0byAwLCA5MCwgMTgwLCBhbmQgMjcwIGRlZ3JlZXMuXG4gKiBAcHJvcGVydHkge2Jvb2xlYW59IFtlbmFibGVSb3RhdGlvbj10cnVlXSBFbmFibGUgcm90YXRpb24uXG4gKiBJZiBgZmFsc2VgLCBhIHJvdGF0aW9uIGNvbnN0cmFpbnQgdGhhdCBhbHdheXMgc2V0cyB0aGUgcm90YXRpb24gdG8gemVybyBpc1xuICogdXNlZC4gVGhlIGBjb25zdHJhaW5Sb3RhdGlvbmAgb3B0aW9uIGhhcyBubyBlZmZlY3QgaWYgYGVuYWJsZVJvdGF0aW9uYCBpc1xuICogYGZhbHNlYC5cbiAqIEBwcm9wZXJ0eSB7aW1wb3J0KFwiLi9leHRlbnQuanNcIikuRXh0ZW50fSBbZXh0ZW50XSBUaGUgZXh0ZW50IHRoYXQgY29uc3RyYWlucyB0aGVcbiAqIHZpZXcsIGluIG90aGVyIHdvcmRzLCBub3RoaW5nIG91dHNpZGUgb2YgdGhpcyBleHRlbnQgY2FuIGJlIHZpc2libGUgb24gdGhlIG1hcC5cbiAqIEBwcm9wZXJ0eSB7Ym9vbGVhbn0gW2NvbnN0cmFpbk9ubHlDZW50ZXI9ZmFsc2VdIElmIHRydWUsIHRoZSBleHRlbnRcbiAqIGNvbnN0cmFpbnQgd2lsbCBvbmx5IGFwcGx5IHRvIHRoZSB2aWV3IGNlbnRlciBhbmQgbm90IHRoZSB3aG9sZSBleHRlbnQuXG4gKiBAcHJvcGVydHkge2Jvb2xlYW59IFtzbW9vdGhFeHRlbnRDb25zdHJhaW50PXRydWVdIElmIHRydWUsIHRoZSBleHRlbnRcbiAqIGNvbnN0cmFpbnQgd2lsbCBiZSBhcHBsaWVkIHNtb290aGx5LCBpLmUuIGFsbG93IHRoZSB2aWV3IHRvIGdvIHNsaWdodGx5IG91dHNpZGVcbiAqIG9mIHRoZSBnaXZlbiBgZXh0ZW50YC5cbiAqIEBwcm9wZXJ0eSB7bnVtYmVyfSBbbWF4UmVzb2x1dGlvbl0gVGhlIG1heGltdW0gcmVzb2x1dGlvbiB1c2VkIHRvIGRldGVybWluZVxuICogdGhlIHJlc29sdXRpb24gY29uc3RyYWludC4gSXQgaXMgdXNlZCB0b2dldGhlciB3aXRoIGBtaW5SZXNvbHV0aW9uYCAob3JcbiAqIGBtYXhab29tYCkgYW5kIGB6b29tRmFjdG9yYC4gSWYgdW5zcGVjaWZpZWQgaXQgaXMgY2FsY3VsYXRlZCBpbiBzdWNoIGEgd2F5XG4gKiB0aGF0IHRoZSBwcm9qZWN0aW9uJ3MgdmFsaWRpdHkgZXh0ZW50IGZpdHMgaW4gYSAyNTZ4MjU2IHB4IHRpbGUuIElmIHRoZVxuICogcHJvamVjdGlvbiBpcyBTcGhlcmljYWwgTWVyY2F0b3IgKHRoZSBkZWZhdWx0KSB0aGVuIGBtYXhSZXNvbHV0aW9uYCBkZWZhdWx0c1xuICogdG8gYDQwMDc1MDE2LjY4NTU3ODQ5IC8gMjU2ID0gMTU2NTQzLjAzMzkyODA0MDk3YC5cbiAqIEBwcm9wZXJ0eSB7bnVtYmVyfSBbbWluUmVzb2x1dGlvbl0gVGhlIG1pbmltdW0gcmVzb2x1dGlvbiB1c2VkIHRvIGRldGVybWluZVxuICogdGhlIHJlc29sdXRpb24gY29uc3RyYWludC4gIEl0IGlzIHVzZWQgdG9nZXRoZXIgd2l0aCBgbWF4UmVzb2x1dGlvbmAgKG9yXG4gKiBgbWluWm9vbWApIGFuZCBgem9vbUZhY3RvcmAuICBJZiB1bnNwZWNpZmllZCBpdCBpcyBjYWxjdWxhdGVkIGFzc3VtaW5nIDI5XG4gKiB6b29tIGxldmVscyAod2l0aCBhIGZhY3RvciBvZiAyKS4gSWYgdGhlIHByb2plY3Rpb24gaXMgU3BoZXJpY2FsIE1lcmNhdG9yXG4gKiAodGhlIGRlZmF1bHQpIHRoZW4gYG1pblJlc29sdXRpb25gIGRlZmF1bHRzIHRvXG4gKiBgNDAwNzUwMTYuNjg1NTc4NDkgLyAyNTYgLyBNYXRoLnBvdygyLCAyOCkgPSAwLjAwMDU4MzE2ODI0NTU4MzkyNTNgLlxuICogQHByb3BlcnR5IHtudW1iZXJ9IFttYXhab29tPTI4XSBUaGUgbWF4aW11bSB6b29tIGxldmVsIHVzZWQgdG8gZGV0ZXJtaW5lIHRoZVxuICogcmVzb2x1dGlvbiBjb25zdHJhaW50LiBJdCBpcyB1c2VkIHRvZ2V0aGVyIHdpdGggYG1pblpvb21gIChvclxuICogYG1heFJlc29sdXRpb25gKSBhbmQgYHpvb21GYWN0b3JgLiAgTm90ZSB0aGF0IGlmIGBtaW5SZXNvbHV0aW9uYCBpcyBhbHNvXG4gKiBwcm92aWRlZCwgaXQgaXMgZ2l2ZW4gcHJlY2VkZW5jZSBvdmVyIGBtYXhab29tYC5cbiAqIEBwcm9wZXJ0eSB7bnVtYmVyfSBbbWluWm9vbT0wXSBUaGUgbWluaW11bSB6b29tIGxldmVsIHVzZWQgdG8gZGV0ZXJtaW5lIHRoZVxuICogcmVzb2x1dGlvbiBjb25zdHJhaW50LiBJdCBpcyB1c2VkIHRvZ2V0aGVyIHdpdGggYG1heFpvb21gIChvclxuICogYG1pblJlc29sdXRpb25gKSBhbmQgYHpvb21GYWN0b3JgLiAgTm90ZSB0aGF0IGlmIGBtYXhSZXNvbHV0aW9uYCBpcyBhbHNvXG4gKiBwcm92aWRlZCwgaXQgaXMgZ2l2ZW4gcHJlY2VkZW5jZSBvdmVyIGBtaW5ab29tYC5cbiAqIEBwcm9wZXJ0eSB7Ym9vbGVhbn0gW211bHRpV29ybGQ9ZmFsc2VdIElmIGBmYWxzZWAgdGhlIHZpZXcgaXMgY29uc3RyYWluZWQgc29cbiAqIG9ubHkgb25lIHdvcmxkIGlzIHZpc2libGUsIGFuZCB5b3UgY2Fubm90IHBhbiBvZmYgdGhlIGVkZ2UuICBJZiBgdHJ1ZWAgdGhlIG1hcFxuICogbWF5IHNob3cgbXVsdGlwbGUgd29ybGRzIGF0IGxvdyB6b29tIGxldmVscy4gIE9ubHkgdXNlZCBpZiB0aGUgYHByb2plY3Rpb25gIGlzXG4gKiBnbG9iYWwuICBOb3RlIHRoYXQgaWYgYGV4dGVudGAgaXMgYWxzbyBwcm92aWRlZCBpdCBpcyBnaXZlbiBwcmVjZWRlbmNlLlxuICogQHByb3BlcnR5IHtib29sZWFufSBbY29uc3RyYWluUmVzb2x1dGlvbj1mYWxzZV0gSWYgdHJ1ZSwgdGhlIHZpZXcgd2lsbCBhbHdheXNcbiAqIGFuaW1hdGUgdG8gdGhlIGNsb3Nlc3Qgem9vbSBsZXZlbCBhZnRlciBhbiBpbnRlcmFjdGlvbjsgZmFsc2UgbWVhbnNcbiAqIGludGVybWVkaWFyeSB6b29tIGxldmVscyBhcmUgYWxsb3dlZC5cbiAqIEBwcm9wZXJ0eSB7Ym9vbGVhbn0gW3Ntb290aFJlc29sdXRpb25Db25zdHJhaW50PXRydWVdIElmIHRydWUsIHRoZSByZXNvbHV0aW9uXG4gKiBtaW4vbWF4IHZhbHVlcyB3aWxsIGJlIGFwcGxpZWQgc21vb3RobHksIGkuIGUuIGFsbG93IHRoZSB2aWV3IHRvIGV4Y2VlZCBzbGlnaHRseVxuICogdGhlIGdpdmVuIHJlc29sdXRpb24gb3Igem9vbSBib3VuZHMuXG4gKiBAcHJvcGVydHkge2Jvb2xlYW59IFtzaG93RnVsbEV4dGVudD1mYWxzZV0gQWxsb3cgdGhlIHZpZXcgdG8gYmUgem9vbWVkIG91dCB0b1xuICogc2hvdyB0aGUgZnVsbCBjb25maWd1cmVkIGV4dGVudC4gQnkgZGVmYXVsdCwgd2hlbiBhIHZpZXcgaXMgY29uZmlndXJlZCB3aXRoIGFuXG4gKiBleHRlbnQsIHVzZXJzIHdpbGwgbm90IGJlIGFibGUgdG8gem9vbSBvdXQgc28gdGhlIHZpZXdwb3J0IGV4Y2VlZHMgdGhlIGV4dGVudCBpblxuICogZWl0aGVyIGRpbWVuc2lvbi4gVGhpcyBtZWFucyB0aGUgZnVsbCBleHRlbnQgbWF5IG5vdCBiZSB2aXNpYmxlIGlmIHRoZSB2aWV3cG9ydFxuICogaXMgdGFsbGVyIG9yIHdpZGVyIHRoYW4gdGhlIGFzcGVjdCByYXRpbyBvZiB0aGUgY29uZmlndXJlZCBleHRlbnQuIElmXG4gKiBzaG93RnVsbEV4dGVudCBpcyB0cnVlLCB0aGUgdXNlciB3aWxsIGJlIGFibGUgdG8gem9vbSBvdXQgc28gdGhhdCB0aGUgdmlld3BvcnRcbiAqIGV4Y2VlZHMgdGhlIGhlaWdodCBvciB3aWR0aCBvZiB0aGUgY29uZmlndXJlZCBleHRlbnQsIGJ1dCBub3QgYm90aCwgYWxsb3dpbmcgdGhlXG4gKiBmdWxsIGV4dGVudCB0byBiZSBzaG93bi5cbiAqIEBwcm9wZXJ0eSB7aW1wb3J0KFwiLi9wcm9qLmpzXCIpLlByb2plY3Rpb25MaWtlfSBbcHJvamVjdGlvbj0nRVBTRzozODU3J10gVGhlXG4gKiBwcm9qZWN0aW9uLiBUaGUgZGVmYXVsdCBpcyBTcGhlcmljYWwgTWVyY2F0b3IuXG4gKiBAcHJvcGVydHkge251bWJlcn0gW3Jlc29sdXRpb25dIFRoZSBpbml0aWFsIHJlc29sdXRpb24gZm9yIHRoZSB2aWV3LiBUaGVcbiAqIHVuaXRzIGFyZSBgcHJvamVjdGlvbmAgdW5pdHMgcGVyIHBpeGVsIChlLmcuIG1ldGVycyBwZXIgcGl4ZWwpLiBBblxuICogYWx0ZXJuYXRpdmUgdG8gc2V0dGluZyB0aGlzIGlzIHRvIHNldCBgem9vbWAuIExheWVyIHNvdXJjZXMgd2lsbCBub3QgYmVcbiAqIGZldGNoZWQgaWYgbmVpdGhlciB0aGlzIG5vciBgem9vbWAgYXJlIGRlZmluZWQsIGJ1dCB0aGV5IGNhbiBiZSBzZXQgbGF0ZXJcbiAqIHdpdGgge0BsaW5rICNzZXRab29tfSBvciB7QGxpbmsgI3NldFJlc29sdXRpb259LlxuICogQHByb3BlcnR5IHtBcnJheTxudW1iZXI+fSBbcmVzb2x1dGlvbnNdIFJlc29sdXRpb25zIHRvIGRldGVybWluZSB0aGVcbiAqIHJlc29sdXRpb24gY29uc3RyYWludC4gSWYgc2V0IHRoZSBgbWF4UmVzb2x1dGlvbmAsIGBtaW5SZXNvbHV0aW9uYCxcbiAqIGBtaW5ab29tYCwgYG1heFpvb21gLCBhbmQgYHpvb21GYWN0b3JgIG9wdGlvbnMgYXJlIGlnbm9yZWQuXG4gKiBAcHJvcGVydHkge251bWJlcn0gW3JvdGF0aW9uPTBdIFRoZSBpbml0aWFsIHJvdGF0aW9uIGZvciB0aGUgdmlldyBpbiByYWRpYW5zXG4gKiAocG9zaXRpdmUgcm90YXRpb24gY2xvY2t3aXNlLCAwIG1lYW5zIE5vcnRoKS5cbiAqIEBwcm9wZXJ0eSB7bnVtYmVyfSBbem9vbV0gT25seSB1c2VkIGlmIGByZXNvbHV0aW9uYCBpcyBub3QgZGVmaW5lZC4gWm9vbVxuICogbGV2ZWwgdXNlZCB0byBjYWxjdWxhdGUgdGhlIGluaXRpYWwgcmVzb2x1dGlvbiBmb3IgdGhlIHZpZXcuXG4gKiBAcHJvcGVydHkge251bWJlcn0gW3pvb21GYWN0b3I9Ml0gVGhlIHpvb20gZmFjdG9yIHVzZWQgdG8gY29tcHV0ZSB0aGVcbiAqIGNvcnJlc3BvbmRpbmcgcmVzb2x1dGlvbi5cbiAqIEBwcm9wZXJ0eSB7IUFycmF5PG51bWJlcj59IFtwYWRkaW5nPVswLCAwLCAwLCAwXV0gUGFkZGluZyAoaW4gY3NzIHBpeGVscykuXG4gKiBJZiB0aGUgbWFwIHZpZXdwb3J0IGlzIHBhcnRpYWxseSBjb3ZlcmVkIHdpdGggb3RoZXIgY29udGVudCAob3ZlcmxheXMpIGFsb25nXG4gKiBpdHMgZWRnZXMsIHRoaXMgc2V0dGluZyBhbGxvd3MgdG8gc2hpZnQgdGhlIGNlbnRlciBvZiB0aGUgdmlld3BvcnQgYXdheSBmcm9tXG4gKiB0aGF0IGNvbnRlbnQuIFRoZSBvcmRlciBvZiB0aGUgdmFsdWVzIGlzIHRvcCwgcmlnaHQsIGJvdHRvbSwgbGVmdC5cbiAqL1xuXG4vKipcbiAqIEB0eXBlZGVmIHtPYmplY3R9IEFuaW1hdGlvbk9wdGlvbnNcbiAqIEBwcm9wZXJ0eSB7aW1wb3J0KFwiLi9jb29yZGluYXRlLmpzXCIpLkNvb3JkaW5hdGV9IFtjZW50ZXJdIFRoZSBjZW50ZXIgb2YgdGhlIHZpZXcgYXQgdGhlIGVuZCBvZlxuICogdGhlIGFuaW1hdGlvbi5cbiAqIEBwcm9wZXJ0eSB7bnVtYmVyfSBbem9vbV0gVGhlIHpvb20gbGV2ZWwgb2YgdGhlIHZpZXcgYXQgdGhlIGVuZCBvZiB0aGVcbiAqIGFuaW1hdGlvbi4gVGhpcyB0YWtlcyBwcmVjZWRlbmNlIG92ZXIgYHJlc29sdXRpb25gLlxuICogQHByb3BlcnR5IHtudW1iZXJ9IFtyZXNvbHV0aW9uXSBUaGUgcmVzb2x1dGlvbiBvZiB0aGUgdmlldyBhdCB0aGUgZW5kXG4gKiBvZiB0aGUgYW5pbWF0aW9uLiAgSWYgYHpvb21gIGlzIGFsc28gcHJvdmlkZWQsIHRoaXMgb3B0aW9uIHdpbGwgYmUgaWdub3JlZC5cbiAqIEBwcm9wZXJ0eSB7bnVtYmVyfSBbcm90YXRpb25dIFRoZSByb3RhdGlvbiBvZiB0aGUgdmlldyBhdCB0aGUgZW5kIG9mXG4gKiB0aGUgYW5pbWF0aW9uLlxuICogQHByb3BlcnR5IHtpbXBvcnQoXCIuL2Nvb3JkaW5hdGUuanNcIikuQ29vcmRpbmF0ZX0gW2FuY2hvcl0gT3B0aW9uYWwgYW5jaG9yIHRvIHJlbWFpbiBmaXhlZFxuICogZHVyaW5nIGEgcm90YXRpb24gb3IgcmVzb2x1dGlvbiBhbmltYXRpb24uXG4gKiBAcHJvcGVydHkge251bWJlcn0gW2R1cmF0aW9uPTEwMDBdIFRoZSBkdXJhdGlvbiBvZiB0aGUgYW5pbWF0aW9uIGluIG1pbGxpc2Vjb25kcy5cbiAqIEBwcm9wZXJ0eSB7ZnVuY3Rpb24obnVtYmVyKTpudW1iZXJ9IFtlYXNpbmddIFRoZSBlYXNpbmcgZnVuY3Rpb24gdXNlZFxuICogZHVyaW5nIHRoZSBhbmltYXRpb24gKGRlZmF1bHRzIHRvIHtAbGluayBtb2R1bGU6b2wvZWFzaW5nfmluQW5kT3V0fSkuXG4gKiBUaGUgZnVuY3Rpb24gd2lsbCBiZSBjYWxsZWQgZm9yIGVhY2ggZnJhbWUgd2l0aCBhIG51bWJlciByZXByZXNlbnRpbmcgYVxuICogZnJhY3Rpb24gb2YgdGhlIGFuaW1hdGlvbidzIGR1cmF0aW9uLiAgVGhlIGZ1bmN0aW9uIHNob3VsZCByZXR1cm4gYSBudW1iZXJcbiAqIGJldHdlZW4gMCBhbmQgMSByZXByZXNlbnRpbmcgdGhlIHByb2dyZXNzIHRvd2FyZCB0aGUgZGVzdGluYXRpb24gc3RhdGUuXG4gKi9cblxuLyoqXG4gKiBAdHlwZWRlZiB7T2JqZWN0fSBTdGF0ZVxuICogQHByb3BlcnR5IHtpbXBvcnQoXCIuL2Nvb3JkaW5hdGUuanNcIikuQ29vcmRpbmF0ZX0gY2VudGVyXG4gKiBAcHJvcGVydHkge2ltcG9ydChcIi4vcHJvai9Qcm9qZWN0aW9uLmpzXCIpLmRlZmF1bHR9IHByb2plY3Rpb25cbiAqIEBwcm9wZXJ0eSB7bnVtYmVyfSByZXNvbHV0aW9uXG4gKiBAcHJvcGVydHkge251bWJlcn0gcm90YXRpb25cbiAqIEBwcm9wZXJ0eSB7bnVtYmVyfSB6b29tXG4gKi9cblxuLyoqXG4gKiBEZWZhdWx0IG1pbiB6b29tIGxldmVsIGZvciB0aGUgbWFwIHZpZXcuXG4gKiBAdHlwZSB7bnVtYmVyfVxuICovXG5cbnZhciBERUZBVUxUX01JTl9aT09NID0gMDtcbi8qKlxuICogQGNsYXNzZGVzY1xuICogQSBWaWV3IG9iamVjdCByZXByZXNlbnRzIGEgc2ltcGxlIDJEIHZpZXcgb2YgdGhlIG1hcC5cbiAqXG4gKiBUaGlzIGlzIHRoZSBvYmplY3QgdG8gYWN0IHVwb24gdG8gY2hhbmdlIHRoZSBjZW50ZXIsIHJlc29sdXRpb24sXG4gKiBhbmQgcm90YXRpb24gb2YgdGhlIG1hcC5cbiAqXG4gKiBBIFZpZXcgaGFzIGEgYHByb2plY3Rpb25gLiBUaGUgcHJvamVjdGlvbiBkZXRlcm1pbmVzIHRoZVxuICogY29vcmRpbmF0ZSBzeXN0ZW0gb2YgdGhlIGNlbnRlciwgYW5kIGl0cyB1bml0cyBkZXRlcm1pbmUgdGhlIHVuaXRzIG9mIHRoZVxuICogcmVzb2x1dGlvbiAocHJvamVjdGlvbiB1bml0cyBwZXIgcGl4ZWwpLiBUaGUgZGVmYXVsdCBwcm9qZWN0aW9uIGlzXG4gKiBTcGhlcmljYWwgTWVyY2F0b3IgKEVQU0c6Mzg1NykuXG4gKlxuICogIyMjIFRoZSB2aWV3IHN0YXRlc1xuICpcbiAqIEEgVmlldyBpcyBkZXRlcm1pbmVkIGJ5IHRocmVlIHN0YXRlczogYGNlbnRlcmAsIGByZXNvbHV0aW9uYCxcbiAqIGFuZCBgcm90YXRpb25gLiBFYWNoIHN0YXRlIGhhcyBhIGNvcnJlc3BvbmRpbmcgZ2V0dGVyIGFuZCBzZXR0ZXIsIGUuZy5cbiAqIGBnZXRDZW50ZXJgIGFuZCBgc2V0Q2VudGVyYCBmb3IgdGhlIGBjZW50ZXJgIHN0YXRlLlxuICpcbiAqIFRoZSBgem9vbWAgc3RhdGUgaXMgYWN0dWFsbHkgbm90IHNhdmVkIG9uIHRoZSB2aWV3OiBhbGwgY29tcHV0YXRpb25zXG4gKiBpbnRlcm5hbGx5IHVzZSB0aGUgYHJlc29sdXRpb25gIHN0YXRlLiBTdGlsbCwgdGhlIGBzZXRab29tYCBhbmQgYGdldFpvb21gXG4gKiBtZXRob2RzIGFyZSBhdmFpbGFibGUsIGFzIHdlbGwgYXMgYGdldFJlc29sdXRpb25Gb3Jab29tYCBhbmRcbiAqIGBnZXRab29tRm9yUmVzb2x1dGlvbmAgdG8gc3dpdGNoIGZyb20gb25lIHN5c3RlbSB0byB0aGUgb3RoZXIuXG4gKlxuICogIyMjIFRoZSBjb25zdHJhaW50c1xuICpcbiAqIGBzZXRDZW50ZXJgLCBgc2V0UmVzb2x1dGlvbmAgYW5kIGBzZXRSb3RhdGlvbmAgY2FuIGJlIHVzZWQgdG8gY2hhbmdlIHRoZVxuICogc3RhdGVzIG9mIHRoZSB2aWV3LCBidXQgYW55IGNvbnN0cmFpbnQgZGVmaW5lZCBpbiB0aGUgY29uc3RydWN0b3Igd2lsbFxuICogYmUgYXBwbGllZCBhbG9uZyB0aGUgd2F5LlxuICpcbiAqIEEgVmlldyBvYmplY3QgY2FuIGhhdmUgYSAqcmVzb2x1dGlvbiBjb25zdHJhaW50KiwgYSAqcm90YXRpb24gY29uc3RyYWludCpcbiAqIGFuZCBhICpjZW50ZXIgY29uc3RyYWludCouXG4gKlxuICogVGhlICpyZXNvbHV0aW9uIGNvbnN0cmFpbnQqIHR5cGljYWxseSByZXN0cmljdHMgbWluL21heCB2YWx1ZXMgYW5kXG4gKiBzbmFwcyB0byBzcGVjaWZpYyByZXNvbHV0aW9ucy4gSXQgaXMgZGV0ZXJtaW5lZCBieSB0aGUgZm9sbG93aW5nXG4gKiBvcHRpb25zOiBgcmVzb2x1dGlvbnNgLCBgbWF4UmVzb2x1dGlvbmAsIGBtYXhab29tYCBhbmQgYHpvb21GYWN0b3JgLlxuICogSWYgYHJlc29sdXRpb25zYCBpcyBzZXQsIHRoZSBvdGhlciB0aHJlZSBvcHRpb25zIGFyZSBpZ25vcmVkLiBTZWVcbiAqIGRvY3VtZW50YXRpb24gZm9yIGVhY2ggb3B0aW9uIGZvciBtb3JlIGluZm9ybWF0aW9uLiBCeSBkZWZhdWx0LCB0aGUgdmlld1xuICogb25seSBoYXMgYSBtaW4vbWF4IHJlc3RyaWN0aW9uIGFuZCBhbGxvdyBpbnRlcm1lZGlhcnkgem9vbSBsZXZlbHMgd2hlblxuICogcGluY2gtem9vbWluZyBmb3IgZXhhbXBsZS5cbiAqXG4gKiBUaGUgKnJvdGF0aW9uIGNvbnN0cmFpbnQqIHNuYXBzIHRvIHNwZWNpZmljIGFuZ2xlcy4gSXQgaXMgZGV0ZXJtaW5lZFxuICogYnkgdGhlIGZvbGxvd2luZyBvcHRpb25zOiBgZW5hYmxlUm90YXRpb25gIGFuZCBgY29uc3RyYWluUm90YXRpb25gLlxuICogQnkgZGVmYXVsdCByb3RhdGlvbiBpcyBhbGxvd2VkIGFuZCBpdHMgdmFsdWUgaXMgc25hcHBlZCB0byB6ZXJvIHdoZW4gYXBwcm9hY2hpbmcgdGhlXG4gKiBob3Jpem9udGFsLlxuICpcbiAqIFRoZSAqY2VudGVyIGNvbnN0cmFpbnQqIGlzIGRldGVybWluZWQgYnkgdGhlIGBleHRlbnRgIG9wdGlvbi4gQnlcbiAqIGRlZmF1bHQgdGhlIHZpZXcgY2VudGVyIGlzIG5vdCBjb25zdHJhaW5lZCBhdCBhbGwuXG4gKlxuICogIyMjIENoYW5naW5nIHRoZSB2aWV3IHN0YXRlXG4gKlxuICogSXQgaXMgaW1wb3J0YW50IHRvIG5vdGUgdGhhdCBgc2V0Wm9vbWAsIGBzZXRSZXNvbHV0aW9uYCwgYHNldENlbnRlcmAgYW5kXG4gKiBgc2V0Um90YXRpb25gIGFyZSBzdWJqZWN0IHRvIHRoZSBhYm92ZSBtZW50aW9uZWQgY29uc3RyYWludHMuIEFzIHN1Y2gsIGl0XG4gKiBtYXkgc29tZXRpbWVzIG5vdCBiZSBwb3NzaWJsZSB0byBrbm93IGluIGFkdmFuY2UgdGhlIHJlc3VsdGluZyBzdGF0ZSBvZiB0aGVcbiAqIFZpZXcuIEZvciBleGFtcGxlLCBjYWxsaW5nIGBzZXRSZXNvbHV0aW9uKDEwKWAgZG9lcyBub3QgZ3VhcmFudGVlIHRoYXRcbiAqIGBnZXRSZXNvbHV0aW9uKClgIHdpbGwgcmV0dXJuIGAxMGAuXG4gKlxuICogQSBjb25zZXF1ZW5jZSBvZiB0aGlzIGlzIHRoYXQsIHdoZW4gYXBwbHlpbmcgYSBkZWx0YSBvbiB0aGUgdmlldyBzdGF0ZSwgb25lXG4gKiBzaG91bGQgdXNlIGBhZGp1c3RDZW50ZXJgLCBgYWRqdXN0Um90YXRpb25gLCBgYWRqdXN0Wm9vbWAgYW5kIGBhZGp1c3RSZXNvbHV0aW9uYFxuICogcmF0aGVyIHRoYW4gdGhlIGNvcnJlc3BvbmRpbmcgc2V0dGVycy4gVGhpcyB3aWxsIGxldCB2aWV3IGRvIGl0cyBpbnRlcm5hbFxuICogY29tcHV0YXRpb25zLiBCZXNpZGVzLCB0aGUgYGFkanVzdCpgIG1ldGhvZHMgYWxzbyB0YWtlIGFuIGBvcHRfYW5jaG9yYFxuICogYXJndW1lbnQgd2hpY2ggYWxsb3dzIHNwZWNpZnlpbmcgYW4gb3JpZ2luIGZvciB0aGUgdHJhbnNmb3JtYXRpb24uXG4gKlxuICogIyMjIEludGVyYWN0aW5nIHdpdGggdGhlIHZpZXdcbiAqXG4gKiBWaWV3IGNvbnN0cmFpbnRzIGFyZSB1c3VhbGx5IG9ubHkgYXBwbGllZCB3aGVuIHRoZSB2aWV3IGlzICphdCByZXN0KiwgbWVhbmluZyB0aGF0XG4gKiBubyBpbnRlcmFjdGlvbiBvciBhbmltYXRpb24gaXMgb25nb2luZy4gQXMgc3VjaCwgaWYgdGhlIHVzZXIgcHV0cyB0aGUgdmlldyBpbiBhXG4gKiBzdGF0ZSB0aGF0IGlzIG5vdCBlcXVpdmFsZW50IHRvIGEgY29uc3RyYWluZWQgb25lIChlLmcuIHJvdGF0aW5nIHRoZSB2aWV3IHdoZW5cbiAqIHRoZSBzbmFwIGFuZ2xlIGlzIDApLCBhbiBhbmltYXRpb24gd2lsbCBiZSB0cmlnZ2VyZWQgYXQgdGhlIGludGVyYWN0aW9uIGVuZCB0b1xuICogcHV0IGJhY2sgdGhlIHZpZXcgdG8gYSBzdGFibGUgc3RhdGU7XG4gKlxuICogQGFwaVxuICovXG5cbnZhciBWaWV3ID1cbi8qKiBAY2xhc3MgKi9cbmZ1bmN0aW9uIChfc3VwZXIpIHtcbiAgX19leHRlbmRzKFZpZXcsIF9zdXBlcik7XG4gIC8qKlxuICAgKiBAcGFyYW0ge1ZpZXdPcHRpb25zPX0gb3B0X29wdGlvbnMgVmlldyBvcHRpb25zLlxuICAgKi9cblxuXG4gIGZ1bmN0aW9uIFZpZXcob3B0X29wdGlvbnMpIHtcbiAgICB2YXIgX3RoaXMgPSBfc3VwZXIuY2FsbCh0aGlzKSB8fCB0aGlzO1xuXG4gICAgdmFyIG9wdGlvbnMgPSBhc3NpZ24oe30sIG9wdF9vcHRpb25zKTtcbiAgICAvKipcbiAgICAgKiBAcHJpdmF0ZVxuICAgICAqIEB0eXBlIHtBcnJheTxudW1iZXI+fVxuICAgICAqL1xuXG4gICAgX3RoaXMuaGludHNfID0gWzAsIDBdO1xuICAgIC8qKlxuICAgICAqIEBwcml2YXRlXG4gICAgICogQHR5cGUge0FycmF5PEFycmF5PEFuaW1hdGlvbj4+fVxuICAgICAqL1xuXG4gICAgX3RoaXMuYW5pbWF0aW9uc18gPSBbXTtcbiAgICAvKipcbiAgICAgKiBAcHJpdmF0ZVxuICAgICAqIEB0eXBlIHtudW1iZXJ8dW5kZWZpbmVkfVxuICAgICAqL1xuXG4gICAgX3RoaXMudXBkYXRlQW5pbWF0aW9uS2V5XztcbiAgICAvKipcbiAgICAgKiBAcHJpdmF0ZVxuICAgICAqIEBjb25zdFxuICAgICAqIEB0eXBlIHtpbXBvcnQoXCIuL3Byb2ovUHJvamVjdGlvbi5qc1wiKS5kZWZhdWx0fVxuICAgICAqL1xuXG4gICAgX3RoaXMucHJvamVjdGlvbl8gPSBjcmVhdGVQcm9qZWN0aW9uKG9wdGlvbnMucHJvamVjdGlvbiwgJ0VQU0c6Mzg1NycpO1xuICAgIC8qKlxuICAgICAqIEBwcml2YXRlXG4gICAgICogQHR5cGUge2ltcG9ydChcIi4vc2l6ZS5qc1wiKS5TaXplfVxuICAgICAqL1xuXG4gICAgX3RoaXMudmlld3BvcnRTaXplXyA9IFsxMDAsIDEwMF07XG4gICAgLyoqXG4gICAgICogQHByaXZhdGVcbiAgICAgKiBAdHlwZSB7aW1wb3J0KFwiLi9jb29yZGluYXRlLmpzXCIpLkNvb3JkaW5hdGV8dW5kZWZpbmVkfVxuICAgICAqL1xuXG4gICAgX3RoaXMudGFyZ2V0Q2VudGVyXyA9IG51bGw7XG4gICAgLyoqXG4gICAgICogQHByaXZhdGVcbiAgICAgKiBAdHlwZSB7bnVtYmVyfHVuZGVmaW5lZH1cbiAgICAgKi9cblxuICAgIF90aGlzLnRhcmdldFJlc29sdXRpb25fO1xuICAgIC8qKlxuICAgICAqIEBwcml2YXRlXG4gICAgICogQHR5cGUge251bWJlcnx1bmRlZmluZWR9XG4gICAgICovXG5cbiAgICBfdGhpcy50YXJnZXRSb3RhdGlvbl87XG4gICAgLyoqXG4gICAgICogQHByaXZhdGVcbiAgICAgKiBAdHlwZSB7aW1wb3J0KFwiLi9jb29yZGluYXRlLmpzXCIpLkNvb3JkaW5hdGV8dW5kZWZpbmVkfVxuICAgICAqL1xuXG4gICAgX3RoaXMuY2FuY2VsQW5jaG9yXyA9IHVuZGVmaW5lZDtcblxuICAgIGlmIChvcHRpb25zLmNlbnRlcikge1xuICAgICAgb3B0aW9ucy5jZW50ZXIgPSBmcm9tVXNlckNvb3JkaW5hdGUob3B0aW9ucy5jZW50ZXIsIF90aGlzLnByb2plY3Rpb25fKTtcbiAgICB9XG5cbiAgICBpZiAob3B0aW9ucy5leHRlbnQpIHtcbiAgICAgIG9wdGlvbnMuZXh0ZW50ID0gZnJvbVVzZXJFeHRlbnQob3B0aW9ucy5leHRlbnQsIF90aGlzLnByb2plY3Rpb25fKTtcbiAgICB9XG5cbiAgICBfdGhpcy5hcHBseU9wdGlvbnNfKG9wdGlvbnMpO1xuXG4gICAgcmV0dXJuIF90aGlzO1xuICB9XG4gIC8qKlxuICAgKiBTZXQgdXAgdGhlIHZpZXcgd2l0aCB0aGUgZ2l2ZW4gb3B0aW9ucy5cbiAgICogQHBhcmFtIHtWaWV3T3B0aW9uc30gb3B0aW9ucyBWaWV3IG9wdGlvbnMuXG4gICAqL1xuXG5cbiAgVmlldy5wcm90b3R5cGUuYXBwbHlPcHRpb25zXyA9IGZ1bmN0aW9uIChvcHRpb25zKSB7XG4gICAgLyoqXG4gICAgICogQHR5cGUge09iamVjdDxzdHJpbmcsICo+fVxuICAgICAqL1xuICAgIHZhciBwcm9wZXJ0aWVzID0ge307XG4gICAgdmFyIHJlc29sdXRpb25Db25zdHJhaW50SW5mbyA9IGNyZWF0ZVJlc29sdXRpb25Db25zdHJhaW50KG9wdGlvbnMpO1xuICAgIC8qKlxuICAgICAqIEBwcml2YXRlXG4gICAgICogQHR5cGUge251bWJlcn1cbiAgICAgKi9cblxuICAgIHRoaXMubWF4UmVzb2x1dGlvbl8gPSByZXNvbHV0aW9uQ29uc3RyYWludEluZm8ubWF4UmVzb2x1dGlvbjtcbiAgICAvKipcbiAgICAgKiBAcHJpdmF0ZVxuICAgICAqIEB0eXBlIHtudW1iZXJ9XG4gICAgICovXG5cbiAgICB0aGlzLm1pblJlc29sdXRpb25fID0gcmVzb2x1dGlvbkNvbnN0cmFpbnRJbmZvLm1pblJlc29sdXRpb247XG4gICAgLyoqXG4gICAgICogQHByaXZhdGVcbiAgICAgKiBAdHlwZSB7bnVtYmVyfVxuICAgICAqL1xuXG4gICAgdGhpcy56b29tRmFjdG9yXyA9IHJlc29sdXRpb25Db25zdHJhaW50SW5mby56b29tRmFjdG9yO1xuICAgIC8qKlxuICAgICAqIEBwcml2YXRlXG4gICAgICogQHR5cGUge0FycmF5PG51bWJlcj58dW5kZWZpbmVkfVxuICAgICAqL1xuXG4gICAgdGhpcy5yZXNvbHV0aW9uc18gPSBvcHRpb25zLnJlc29sdXRpb25zO1xuICAgIC8qKlxuICAgICAqIFBhZGRpbmcgKGluIGNzcyBwaXhlbHMpLlxuICAgICAqIElmIHRoZSBtYXAgdmlld3BvcnQgaXMgcGFydGlhbGx5IGNvdmVyZWQgd2l0aCBvdGhlciBjb250ZW50IChvdmVybGF5cykgYWxvbmdcbiAgICAgKiBpdHMgZWRnZXMsIHRoaXMgc2V0dGluZyBhbGxvd3MgdG8gc2hpZnQgdGhlIGNlbnRlciBvZiB0aGUgdmlld3BvcnQgYXdheSBmcm9tIHRoYXRcbiAgICAgKiBjb250ZW50LiBUaGUgb3JkZXIgb2YgdGhlIHZhbHVlcyBpbiB0aGUgYXJyYXkgaXMgdG9wLCByaWdodCwgYm90dG9tLCBsZWZ0LlxuICAgICAqIFRoZSBkZWZhdWx0IGlzIG5vIHBhZGRpbmcsIHdoaWNoIGlzIGVxdWl2YWxlbnQgdG8gYFswLCAwLCAwLCAwXWAuXG4gICAgICogQHR5cGUge0FycmF5PG51bWJlcj58dW5kZWZpbmVkfVxuICAgICAqIEBhcGlcbiAgICAgKi9cblxuICAgIHRoaXMucGFkZGluZyA9IG9wdGlvbnMucGFkZGluZztcbiAgICAvKipcbiAgICAgKiBAcHJpdmF0ZVxuICAgICAqIEB0eXBlIHtudW1iZXJ9XG4gICAgICovXG5cbiAgICB0aGlzLm1pblpvb21fID0gcmVzb2x1dGlvbkNvbnN0cmFpbnRJbmZvLm1pblpvb207XG4gICAgdmFyIGNlbnRlckNvbnN0cmFpbnQgPSBjcmVhdGVDZW50ZXJDb25zdHJhaW50KG9wdGlvbnMpO1xuICAgIHZhciByZXNvbHV0aW9uQ29uc3RyYWludCA9IHJlc29sdXRpb25Db25zdHJhaW50SW5mby5jb25zdHJhaW50O1xuICAgIHZhciByb3RhdGlvbkNvbnN0cmFpbnQgPSBjcmVhdGVSb3RhdGlvbkNvbnN0cmFpbnQob3B0aW9ucyk7XG4gICAgLyoqXG4gICAgICogQHByaXZhdGVcbiAgICAgKiBAdHlwZSB7Q29uc3RyYWludHN9XG4gICAgICovXG5cbiAgICB0aGlzLmNvbnN0cmFpbnRzXyA9IHtcbiAgICAgIGNlbnRlcjogY2VudGVyQ29uc3RyYWludCxcbiAgICAgIHJlc29sdXRpb246IHJlc29sdXRpb25Db25zdHJhaW50LFxuICAgICAgcm90YXRpb246IHJvdGF0aW9uQ29uc3RyYWludFxuICAgIH07XG4gICAgdGhpcy5zZXRSb3RhdGlvbihvcHRpb25zLnJvdGF0aW9uICE9PSB1bmRlZmluZWQgPyBvcHRpb25zLnJvdGF0aW9uIDogMCk7XG4gICAgdGhpcy5zZXRDZW50ZXJJbnRlcm5hbChvcHRpb25zLmNlbnRlciAhPT0gdW5kZWZpbmVkID8gb3B0aW9ucy5jZW50ZXIgOiBudWxsKTtcblxuICAgIGlmIChvcHRpb25zLnJlc29sdXRpb24gIT09IHVuZGVmaW5lZCkge1xuICAgICAgdGhpcy5zZXRSZXNvbHV0aW9uKG9wdGlvbnMucmVzb2x1dGlvbik7XG4gICAgfSBlbHNlIGlmIChvcHRpb25zLnpvb20gIT09IHVuZGVmaW5lZCkge1xuICAgICAgdGhpcy5zZXRab29tKG9wdGlvbnMuem9vbSk7XG4gICAgfVxuXG4gICAgdGhpcy5zZXRQcm9wZXJ0aWVzKHByb3BlcnRpZXMpO1xuICAgIC8qKlxuICAgICAqIEBwcml2YXRlXG4gICAgICogQHR5cGUge1ZpZXdPcHRpb25zfVxuICAgICAqL1xuXG4gICAgdGhpcy5vcHRpb25zXyA9IG9wdGlvbnM7XG4gIH07XG4gIC8qKlxuICAgKiBHZXQgYW4gdXBkYXRlZCB2ZXJzaW9uIG9mIHRoZSB2aWV3IG9wdGlvbnMgdXNlZCB0byBjb25zdHJ1Y3QgdGhlIHZpZXcuICBUaGVcbiAgICogY3VycmVudCByZXNvbHV0aW9uIChvciB6b29tKSwgY2VudGVyLCBhbmQgcm90YXRpb24gYXJlIGFwcGxpZWQgdG8gYW55IHN0b3JlZFxuICAgKiBvcHRpb25zLiAgVGhlIHByb3ZpZGVkIG9wdGlvbnMgY2FuIGJlIHVzZWQgdG8gYXBwbHkgbmV3IG1pbi9tYXggem9vbSBvclxuICAgKiByZXNvbHV0aW9uIGxpbWl0cy5cbiAgICogQHBhcmFtIHtWaWV3T3B0aW9uc30gbmV3T3B0aW9ucyBOZXcgb3B0aW9ucyB0byBiZSBhcHBsaWVkLlxuICAgKiBAcmV0dXJuIHtWaWV3T3B0aW9uc30gTmV3IG9wdGlvbnMgdXBkYXRlZCB3aXRoIHRoZSBjdXJyZW50IHZpZXcgc3RhdGUuXG4gICAqL1xuXG5cbiAgVmlldy5wcm90b3R5cGUuZ2V0VXBkYXRlZE9wdGlvbnNfID0gZnVuY3Rpb24gKG5ld09wdGlvbnMpIHtcbiAgICB2YXIgb3B0aW9ucyA9IGFzc2lnbih7fSwgdGhpcy5vcHRpb25zXyk7IC8vIHByZXNlcnZlIHJlc29sdXRpb24gKG9yIHpvb20pXG5cbiAgICBpZiAob3B0aW9ucy5yZXNvbHV0aW9uICE9PSB1bmRlZmluZWQpIHtcbiAgICAgIG9wdGlvbnMucmVzb2x1dGlvbiA9IHRoaXMuZ2V0UmVzb2x1dGlvbigpO1xuICAgIH0gZWxzZSB7XG4gICAgICBvcHRpb25zLnpvb20gPSB0aGlzLmdldFpvb20oKTtcbiAgICB9IC8vIHByZXNlcnZlIGNlbnRlclxuXG5cbiAgICBvcHRpb25zLmNlbnRlciA9IHRoaXMuZ2V0Q2VudGVySW50ZXJuYWwoKTsgLy8gcHJlc2VydmUgcm90YXRpb25cblxuICAgIG9wdGlvbnMucm90YXRpb24gPSB0aGlzLmdldFJvdGF0aW9uKCk7XG4gICAgcmV0dXJuIGFzc2lnbih7fSwgb3B0aW9ucywgbmV3T3B0aW9ucyk7XG4gIH07XG4gIC8qKlxuICAgKiBBbmltYXRlIHRoZSB2aWV3LiAgVGhlIHZpZXcncyBjZW50ZXIsIHpvb20gKG9yIHJlc29sdXRpb24pLCBhbmQgcm90YXRpb25cbiAgICogY2FuIGJlIGFuaW1hdGVkIGZvciBzbW9vdGggdHJhbnNpdGlvbnMgYmV0d2VlbiB2aWV3IHN0YXRlcy4gIEZvciBleGFtcGxlLFxuICAgKiB0byBhbmltYXRlIHRoZSB2aWV3IHRvIGEgbmV3IHpvb20gbGV2ZWw6XG4gICAqXG4gICAqICAgICB2aWV3LmFuaW1hdGUoe3pvb206IHZpZXcuZ2V0Wm9vbSgpICsgMX0pO1xuICAgKlxuICAgKiBCeSBkZWZhdWx0LCB0aGUgYW5pbWF0aW9uIGxhc3RzIG9uZSBzZWNvbmQgYW5kIHVzZXMgaW4tYW5kLW91dCBlYXNpbmcuICBZb3VcbiAgICogY2FuIGN1c3RvbWl6ZSB0aGlzIGJlaGF2aW9yIGJ5IGluY2x1ZGluZyBgZHVyYXRpb25gIChpbiBtaWxsaXNlY29uZHMpIGFuZFxuICAgKiBgZWFzaW5nYCBvcHRpb25zIChzZWUge0BsaW5rIG1vZHVsZTpvbC9lYXNpbmd9KS5cbiAgICpcbiAgICogVG8gY2hhaW4gdG9nZXRoZXIgbXVsdGlwbGUgYW5pbWF0aW9ucywgY2FsbCB0aGUgbWV0aG9kIHdpdGggbXVsdGlwbGVcbiAgICogYW5pbWF0aW9uIG9iamVjdHMuICBGb3IgZXhhbXBsZSwgdG8gZmlyc3Qgem9vbSBhbmQgdGhlbiBwYW46XG4gICAqXG4gICAqICAgICB2aWV3LmFuaW1hdGUoe3pvb206IDEwfSwge2NlbnRlcjogWzAsIDBdfSk7XG4gICAqXG4gICAqIElmIHlvdSBwcm92aWRlIGEgZnVuY3Rpb24gYXMgdGhlIGxhc3QgYXJndW1lbnQgdG8gdGhlIGFuaW1hdGUgbWV0aG9kLCBpdFxuICAgKiB3aWxsIGdldCBjYWxsZWQgYXQgdGhlIGVuZCBvZiBhbiBhbmltYXRpb24gc2VyaWVzLiAgVGhlIGNhbGxiYWNrIHdpbGwgYmVcbiAgICogY2FsbGVkIHdpdGggYHRydWVgIGlmIHRoZSBhbmltYXRpb24gc2VyaWVzIGNvbXBsZXRlZCBvbiBpdHMgb3duIG9yIGBmYWxzZWBcbiAgICogaWYgaXQgd2FzIGNhbmNlbGxlZC5cbiAgICpcbiAgICogQW5pbWF0aW9ucyBhcmUgY2FuY2VsbGVkIGJ5IHVzZXIgaW50ZXJhY3Rpb25zIChlLmcuIGRyYWdnaW5nIHRoZSBtYXApIG9yIGJ5XG4gICAqIGNhbGxpbmcgYHZpZXcuc2V0Q2VudGVyKClgLCBgdmlldy5zZXRSZXNvbHV0aW9uKClgLCBvciBgdmlldy5zZXRSb3RhdGlvbigpYFxuICAgKiAob3IgYW5vdGhlciBtZXRob2QgdGhhdCBjYWxscyBvbmUgb2YgdGhlc2UpLlxuICAgKlxuICAgKiBAcGFyYW0gey4uLihBbmltYXRpb25PcHRpb25zfGZ1bmN0aW9uKGJvb2xlYW4pOiB2b2lkKX0gdmFyX2FyZ3MgQW5pbWF0aW9uXG4gICAqICAgICBvcHRpb25zLiAgTXVsdGlwbGUgYW5pbWF0aW9ucyBjYW4gYmUgcnVuIGluIHNlcmllcyBieSBwYXNzaW5nIG11bHRpcGxlXG4gICAqICAgICBvcHRpb25zIG9iamVjdHMuICBUbyBydW4gbXVsdGlwbGUgYW5pbWF0aW9ucyBpbiBwYXJhbGxlbCwgY2FsbCB0aGUgbWV0aG9kXG4gICAqICAgICBtdWx0aXBsZSB0aW1lcy4gIEFuIG9wdGlvbmFsIGNhbGxiYWNrIGNhbiBiZSBwcm92aWRlZCBhcyBhIGZpbmFsXG4gICAqICAgICBhcmd1bWVudC4gIFRoZSBjYWxsYmFjayB3aWxsIGJlIGNhbGxlZCB3aXRoIGEgYm9vbGVhbiBpbmRpY2F0aW5nIHdoZXRoZXJcbiAgICogICAgIHRoZSBhbmltYXRpb24gY29tcGxldGVkIHdpdGhvdXQgYmVpbmcgY2FuY2VsbGVkLlxuICAgKiBAYXBpXG4gICAqL1xuXG5cbiAgVmlldy5wcm90b3R5cGUuYW5pbWF0ZSA9IGZ1bmN0aW9uICh2YXJfYXJncykge1xuICAgIGlmICh0aGlzLmlzRGVmKCkgJiYgIXRoaXMuZ2V0QW5pbWF0aW5nKCkpIHtcbiAgICAgIHRoaXMucmVzb2x2ZUNvbnN0cmFpbnRzKDApO1xuICAgIH1cblxuICAgIHZhciBhcmdzID0gbmV3IEFycmF5KGFyZ3VtZW50cy5sZW5ndGgpO1xuXG4gICAgZm9yICh2YXIgaSA9IDA7IGkgPCBhcmdzLmxlbmd0aDsgKytpKSB7XG4gICAgICB2YXIgb3B0aW9ucyA9IGFyZ3VtZW50c1tpXTtcblxuICAgICAgaWYgKG9wdGlvbnMuY2VudGVyKSB7XG4gICAgICAgIG9wdGlvbnMgPSBhc3NpZ24oe30sIG9wdGlvbnMpO1xuICAgICAgICBvcHRpb25zLmNlbnRlciA9IGZyb21Vc2VyQ29vcmRpbmF0ZShvcHRpb25zLmNlbnRlciwgdGhpcy5nZXRQcm9qZWN0aW9uKCkpO1xuICAgICAgfVxuXG4gICAgICBpZiAob3B0aW9ucy5hbmNob3IpIHtcbiAgICAgICAgb3B0aW9ucyA9IGFzc2lnbih7fSwgb3B0aW9ucyk7XG4gICAgICAgIG9wdGlvbnMuYW5jaG9yID0gZnJvbVVzZXJDb29yZGluYXRlKG9wdGlvbnMuYW5jaG9yLCB0aGlzLmdldFByb2plY3Rpb24oKSk7XG4gICAgICB9XG5cbiAgICAgIGFyZ3NbaV0gPSBvcHRpb25zO1xuICAgIH1cblxuICAgIHRoaXMuYW5pbWF0ZUludGVybmFsLmFwcGx5KHRoaXMsIGFyZ3MpO1xuICB9O1xuICAvKipcbiAgICogQHBhcmFtIHsuLi4oQW5pbWF0aW9uT3B0aW9uc3xmdW5jdGlvbihib29sZWFuKTogdm9pZCl9IHZhcl9hcmdzIEFuaW1hdGlvbiBvcHRpb25zLlxuICAgKi9cblxuXG4gIFZpZXcucHJvdG90eXBlLmFuaW1hdGVJbnRlcm5hbCA9IGZ1bmN0aW9uICh2YXJfYXJncykge1xuICAgIHZhciBhbmltYXRpb25Db3VudCA9IGFyZ3VtZW50cy5sZW5ndGg7XG4gICAgdmFyIGNhbGxiYWNrO1xuXG4gICAgaWYgKGFuaW1hdGlvbkNvdW50ID4gMSAmJiB0eXBlb2YgYXJndW1lbnRzW2FuaW1hdGlvbkNvdW50IC0gMV0gPT09ICdmdW5jdGlvbicpIHtcbiAgICAgIGNhbGxiYWNrID0gYXJndW1lbnRzW2FuaW1hdGlvbkNvdW50IC0gMV07XG4gICAgICAtLWFuaW1hdGlvbkNvdW50O1xuICAgIH1cblxuICAgIGlmICghdGhpcy5pc0RlZigpKSB7XG4gICAgICAvLyBpZiB2aWV3IHByb3BlcnRpZXMgYXJlIG5vdCB5ZXQgc2V0LCBzaG9ydGN1dCB0byB0aGUgZmluYWwgc3RhdGVcbiAgICAgIHZhciBzdGF0ZSA9IGFyZ3VtZW50c1thbmltYXRpb25Db3VudCAtIDFdO1xuXG4gICAgICBpZiAoc3RhdGUuY2VudGVyKSB7XG4gICAgICAgIHRoaXMuc2V0Q2VudGVySW50ZXJuYWwoc3RhdGUuY2VudGVyKTtcbiAgICAgIH1cblxuICAgICAgaWYgKHN0YXRlLnpvb20gIT09IHVuZGVmaW5lZCkge1xuICAgICAgICB0aGlzLnNldFpvb20oc3RhdGUuem9vbSk7XG4gICAgICB9XG5cbiAgICAgIGlmIChzdGF0ZS5yb3RhdGlvbiAhPT0gdW5kZWZpbmVkKSB7XG4gICAgICAgIHRoaXMuc2V0Um90YXRpb24oc3RhdGUucm90YXRpb24pO1xuICAgICAgfVxuXG4gICAgICBpZiAoY2FsbGJhY2spIHtcbiAgICAgICAgYW5pbWF0aW9uQ2FsbGJhY2soY2FsbGJhY2ssIHRydWUpO1xuICAgICAgfVxuXG4gICAgICByZXR1cm47XG4gICAgfVxuXG4gICAgdmFyIHN0YXJ0ID0gRGF0ZS5ub3coKTtcbiAgICB2YXIgY2VudGVyID0gdGhpcy50YXJnZXRDZW50ZXJfLnNsaWNlKCk7XG4gICAgdmFyIHJlc29sdXRpb24gPSB0aGlzLnRhcmdldFJlc29sdXRpb25fO1xuICAgIHZhciByb3RhdGlvbiA9IHRoaXMudGFyZ2V0Um90YXRpb25fO1xuICAgIHZhciBzZXJpZXMgPSBbXTtcblxuICAgIGZvciAodmFyIGkgPSAwOyBpIDwgYW5pbWF0aW9uQ291bnQ7ICsraSkge1xuICAgICAgdmFyIG9wdGlvbnMgPVxuICAgICAgLyoqIEB0eXBlIHtBbmltYXRpb25PcHRpb25zfSAqL1xuICAgICAgYXJndW1lbnRzW2ldO1xuICAgICAgdmFyIGFuaW1hdGlvbiA9IHtcbiAgICAgICAgc3RhcnQ6IHN0YXJ0LFxuICAgICAgICBjb21wbGV0ZTogZmFsc2UsXG4gICAgICAgIGFuY2hvcjogb3B0aW9ucy5hbmNob3IsXG4gICAgICAgIGR1cmF0aW9uOiBvcHRpb25zLmR1cmF0aW9uICE9PSB1bmRlZmluZWQgPyBvcHRpb25zLmR1cmF0aW9uIDogMTAwMCxcbiAgICAgICAgZWFzaW5nOiBvcHRpb25zLmVhc2luZyB8fCBpbkFuZE91dCxcbiAgICAgICAgY2FsbGJhY2s6IGNhbGxiYWNrXG4gICAgICB9O1xuXG4gICAgICBpZiAob3B0aW9ucy5jZW50ZXIpIHtcbiAgICAgICAgYW5pbWF0aW9uLnNvdXJjZUNlbnRlciA9IGNlbnRlcjtcbiAgICAgICAgYW5pbWF0aW9uLnRhcmdldENlbnRlciA9IG9wdGlvbnMuY2VudGVyLnNsaWNlKCk7XG4gICAgICAgIGNlbnRlciA9IGFuaW1hdGlvbi50YXJnZXRDZW50ZXI7XG4gICAgICB9XG5cbiAgICAgIGlmIChvcHRpb25zLnpvb20gIT09IHVuZGVmaW5lZCkge1xuICAgICAgICBhbmltYXRpb24uc291cmNlUmVzb2x1dGlvbiA9IHJlc29sdXRpb247XG4gICAgICAgIGFuaW1hdGlvbi50YXJnZXRSZXNvbHV0aW9uID0gdGhpcy5nZXRSZXNvbHV0aW9uRm9yWm9vbShvcHRpb25zLnpvb20pO1xuICAgICAgICByZXNvbHV0aW9uID0gYW5pbWF0aW9uLnRhcmdldFJlc29sdXRpb247XG4gICAgICB9IGVsc2UgaWYgKG9wdGlvbnMucmVzb2x1dGlvbikge1xuICAgICAgICBhbmltYXRpb24uc291cmNlUmVzb2x1dGlvbiA9IHJlc29sdXRpb247XG4gICAgICAgIGFuaW1hdGlvbi50YXJnZXRSZXNvbHV0aW9uID0gb3B0aW9ucy5yZXNvbHV0aW9uO1xuICAgICAgICByZXNvbHV0aW9uID0gYW5pbWF0aW9uLnRhcmdldFJlc29sdXRpb247XG4gICAgICB9XG5cbiAgICAgIGlmIChvcHRpb25zLnJvdGF0aW9uICE9PSB1bmRlZmluZWQpIHtcbiAgICAgICAgYW5pbWF0aW9uLnNvdXJjZVJvdGF0aW9uID0gcm90YXRpb247XG4gICAgICAgIHZhciBkZWx0YSA9IG1vZHVsbyhvcHRpb25zLnJvdGF0aW9uIC0gcm90YXRpb24gKyBNYXRoLlBJLCAyICogTWF0aC5QSSkgLSBNYXRoLlBJO1xuICAgICAgICBhbmltYXRpb24udGFyZ2V0Um90YXRpb24gPSByb3RhdGlvbiArIGRlbHRhO1xuICAgICAgICByb3RhdGlvbiA9IGFuaW1hdGlvbi50YXJnZXRSb3RhdGlvbjtcbiAgICAgIH0gLy8gY2hlY2sgaWYgYW5pbWF0aW9uIGlzIGEgbm8tb3BcblxuXG4gICAgICBpZiAoaXNOb29wQW5pbWF0aW9uKGFuaW1hdGlvbikpIHtcbiAgICAgICAgYW5pbWF0aW9uLmNvbXBsZXRlID0gdHJ1ZTsgLy8gd2Ugc3RpbGwgcHVzaCBpdCBvbnRvIHRoZSBzZXJpZXMgZm9yIGNhbGxiYWNrIGhhbmRsaW5nXG4gICAgICB9IGVsc2Uge1xuICAgICAgICBzdGFydCArPSBhbmltYXRpb24uZHVyYXRpb247XG4gICAgICB9XG5cbiAgICAgIHNlcmllcy5wdXNoKGFuaW1hdGlvbik7XG4gICAgfVxuXG4gICAgdGhpcy5hbmltYXRpb25zXy5wdXNoKHNlcmllcyk7XG4gICAgdGhpcy5zZXRIaW50KFZpZXdIaW50LkFOSU1BVElORywgMSk7XG4gICAgdGhpcy51cGRhdGVBbmltYXRpb25zXygpO1xuICB9O1xuICAvKipcbiAgICogRGV0ZXJtaW5lIGlmIHRoZSB2aWV3IGlzIGJlaW5nIGFuaW1hdGVkLlxuICAgKiBAcmV0dXJuIHtib29sZWFufSBUaGUgdmlldyBpcyBiZWluZyBhbmltYXRlZC5cbiAgICogQGFwaVxuICAgKi9cblxuXG4gIFZpZXcucHJvdG90eXBlLmdldEFuaW1hdGluZyA9IGZ1bmN0aW9uICgpIHtcbiAgICByZXR1cm4gdGhpcy5oaW50c19bVmlld0hpbnQuQU5JTUFUSU5HXSA+IDA7XG4gIH07XG4gIC8qKlxuICAgKiBEZXRlcm1pbmUgaWYgdGhlIHVzZXIgaXMgaW50ZXJhY3Rpbmcgd2l0aCB0aGUgdmlldywgc3VjaCBhcyBwYW5uaW5nIG9yIHpvb21pbmcuXG4gICAqIEByZXR1cm4ge2Jvb2xlYW59IFRoZSB2aWV3IGlzIGJlaW5nIGludGVyYWN0ZWQgd2l0aC5cbiAgICogQGFwaVxuICAgKi9cblxuXG4gIFZpZXcucHJvdG90eXBlLmdldEludGVyYWN0aW5nID0gZnVuY3Rpb24gKCkge1xuICAgIHJldHVybiB0aGlzLmhpbnRzX1tWaWV3SGludC5JTlRFUkFDVElOR10gPiAwO1xuICB9O1xuICAvKipcbiAgICogQ2FuY2VsIGFueSBvbmdvaW5nIGFuaW1hdGlvbnMuXG4gICAqIEBhcGlcbiAgICovXG5cblxuICBWaWV3LnByb3RvdHlwZS5jYW5jZWxBbmltYXRpb25zID0gZnVuY3Rpb24gKCkge1xuICAgIHRoaXMuc2V0SGludChWaWV3SGludC5BTklNQVRJTkcsIC10aGlzLmhpbnRzX1tWaWV3SGludC5BTklNQVRJTkddKTtcbiAgICB2YXIgYW5jaG9yO1xuXG4gICAgZm9yICh2YXIgaSA9IDAsIGlpID0gdGhpcy5hbmltYXRpb25zXy5sZW5ndGg7IGkgPCBpaTsgKytpKSB7XG4gICAgICB2YXIgc2VyaWVzID0gdGhpcy5hbmltYXRpb25zX1tpXTtcblxuICAgICAgaWYgKHNlcmllc1swXS5jYWxsYmFjaykge1xuICAgICAgICBhbmltYXRpb25DYWxsYmFjayhzZXJpZXNbMF0uY2FsbGJhY2ssIGZhbHNlKTtcbiAgICAgIH1cblxuICAgICAgaWYgKCFhbmNob3IpIHtcbiAgICAgICAgZm9yICh2YXIgaiA9IDAsIGpqID0gc2VyaWVzLmxlbmd0aDsgaiA8IGpqOyArK2opIHtcbiAgICAgICAgICB2YXIgYW5pbWF0aW9uID0gc2VyaWVzW2pdO1xuXG4gICAgICAgICAgaWYgKCFhbmltYXRpb24uY29tcGxldGUpIHtcbiAgICAgICAgICAgIGFuY2hvciA9IGFuaW1hdGlvbi5hbmNob3I7XG4gICAgICAgICAgICBicmVhaztcbiAgICAgICAgICB9XG4gICAgICAgIH1cbiAgICAgIH1cbiAgICB9XG5cbiAgICB0aGlzLmFuaW1hdGlvbnNfLmxlbmd0aCA9IDA7XG4gICAgdGhpcy5jYW5jZWxBbmNob3JfID0gYW5jaG9yO1xuICB9O1xuICAvKipcbiAgICogVXBkYXRlIGFsbCBhbmltYXRpb25zLlxuICAgKi9cblxuXG4gIFZpZXcucHJvdG90eXBlLnVwZGF0ZUFuaW1hdGlvbnNfID0gZnVuY3Rpb24gKCkge1xuICAgIGlmICh0aGlzLnVwZGF0ZUFuaW1hdGlvbktleV8gIT09IHVuZGVmaW5lZCkge1xuICAgICAgY2FuY2VsQW5pbWF0aW9uRnJhbWUodGhpcy51cGRhdGVBbmltYXRpb25LZXlfKTtcbiAgICAgIHRoaXMudXBkYXRlQW5pbWF0aW9uS2V5XyA9IHVuZGVmaW5lZDtcbiAgICB9XG5cbiAgICBpZiAoIXRoaXMuZ2V0QW5pbWF0aW5nKCkpIHtcbiAgICAgIHJldHVybjtcbiAgICB9XG5cbiAgICB2YXIgbm93ID0gRGF0ZS5ub3coKTtcbiAgICB2YXIgbW9yZSA9IGZhbHNlO1xuXG4gICAgZm9yICh2YXIgaSA9IHRoaXMuYW5pbWF0aW9uc18ubGVuZ3RoIC0gMTsgaSA+PSAwOyAtLWkpIHtcbiAgICAgIHZhciBzZXJpZXMgPSB0aGlzLmFuaW1hdGlvbnNfW2ldO1xuICAgICAgdmFyIHNlcmllc0NvbXBsZXRlID0gdHJ1ZTtcblxuICAgICAgZm9yICh2YXIgaiA9IDAsIGpqID0gc2VyaWVzLmxlbmd0aDsgaiA8IGpqOyArK2opIHtcbiAgICAgICAgdmFyIGFuaW1hdGlvbiA9IHNlcmllc1tqXTtcblxuICAgICAgICBpZiAoYW5pbWF0aW9uLmNvbXBsZXRlKSB7XG4gICAgICAgICAgY29udGludWU7XG4gICAgICAgIH1cblxuICAgICAgICB2YXIgZWxhcHNlZCA9IG5vdyAtIGFuaW1hdGlvbi5zdGFydDtcbiAgICAgICAgdmFyIGZyYWN0aW9uID0gYW5pbWF0aW9uLmR1cmF0aW9uID4gMCA/IGVsYXBzZWQgLyBhbmltYXRpb24uZHVyYXRpb24gOiAxO1xuXG4gICAgICAgIGlmIChmcmFjdGlvbiA+PSAxKSB7XG4gICAgICAgICAgYW5pbWF0aW9uLmNvbXBsZXRlID0gdHJ1ZTtcbiAgICAgICAgICBmcmFjdGlvbiA9IDE7XG4gICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgc2VyaWVzQ29tcGxldGUgPSBmYWxzZTtcbiAgICAgICAgfVxuXG4gICAgICAgIHZhciBwcm9ncmVzcyA9IGFuaW1hdGlvbi5lYXNpbmcoZnJhY3Rpb24pO1xuXG4gICAgICAgIGlmIChhbmltYXRpb24uc291cmNlQ2VudGVyKSB7XG4gICAgICAgICAgdmFyIHgwID0gYW5pbWF0aW9uLnNvdXJjZUNlbnRlclswXTtcbiAgICAgICAgICB2YXIgeTAgPSBhbmltYXRpb24uc291cmNlQ2VudGVyWzFdO1xuICAgICAgICAgIHZhciB4MSA9IGFuaW1hdGlvbi50YXJnZXRDZW50ZXJbMF07XG4gICAgICAgICAgdmFyIHkxID0gYW5pbWF0aW9uLnRhcmdldENlbnRlclsxXTtcbiAgICAgICAgICB2YXIgeCA9IHgwICsgcHJvZ3Jlc3MgKiAoeDEgLSB4MCk7XG4gICAgICAgICAgdmFyIHkgPSB5MCArIHByb2dyZXNzICogKHkxIC0geTApO1xuICAgICAgICAgIHRoaXMudGFyZ2V0Q2VudGVyXyA9IFt4LCB5XTtcbiAgICAgICAgfVxuXG4gICAgICAgIGlmIChhbmltYXRpb24uc291cmNlUmVzb2x1dGlvbiAmJiBhbmltYXRpb24udGFyZ2V0UmVzb2x1dGlvbikge1xuICAgICAgICAgIHZhciByZXNvbHV0aW9uID0gcHJvZ3Jlc3MgPT09IDEgPyBhbmltYXRpb24udGFyZ2V0UmVzb2x1dGlvbiA6IGFuaW1hdGlvbi5zb3VyY2VSZXNvbHV0aW9uICsgcHJvZ3Jlc3MgKiAoYW5pbWF0aW9uLnRhcmdldFJlc29sdXRpb24gLSBhbmltYXRpb24uc291cmNlUmVzb2x1dGlvbik7XG5cbiAgICAgICAgICBpZiAoYW5pbWF0aW9uLmFuY2hvcikge1xuICAgICAgICAgICAgdmFyIHNpemUgPSB0aGlzLmdldFZpZXdwb3J0U2l6ZV8odGhpcy5nZXRSb3RhdGlvbigpKTtcbiAgICAgICAgICAgIHZhciBjb25zdHJhaW5lZFJlc29sdXRpb24gPSB0aGlzLmNvbnN0cmFpbnRzXy5yZXNvbHV0aW9uKHJlc29sdXRpb24sIDAsIHNpemUsIHRydWUpO1xuICAgICAgICAgICAgdGhpcy50YXJnZXRDZW50ZXJfID0gdGhpcy5jYWxjdWxhdGVDZW50ZXJab29tKGNvbnN0cmFpbmVkUmVzb2x1dGlvbiwgYW5pbWF0aW9uLmFuY2hvcik7XG4gICAgICAgICAgfVxuXG4gICAgICAgICAgdGhpcy50YXJnZXRSZXNvbHV0aW9uXyA9IHJlc29sdXRpb247XG4gICAgICAgICAgdGhpcy5hcHBseVRhcmdldFN0YXRlXyh0cnVlKTtcbiAgICAgICAgfVxuXG4gICAgICAgIGlmIChhbmltYXRpb24uc291cmNlUm90YXRpb24gIT09IHVuZGVmaW5lZCAmJiBhbmltYXRpb24udGFyZ2V0Um90YXRpb24gIT09IHVuZGVmaW5lZCkge1xuICAgICAgICAgIHZhciByb3RhdGlvbiA9IHByb2dyZXNzID09PSAxID8gbW9kdWxvKGFuaW1hdGlvbi50YXJnZXRSb3RhdGlvbiArIE1hdGguUEksIDIgKiBNYXRoLlBJKSAtIE1hdGguUEkgOiBhbmltYXRpb24uc291cmNlUm90YXRpb24gKyBwcm9ncmVzcyAqIChhbmltYXRpb24udGFyZ2V0Um90YXRpb24gLSBhbmltYXRpb24uc291cmNlUm90YXRpb24pO1xuXG4gICAgICAgICAgaWYgKGFuaW1hdGlvbi5hbmNob3IpIHtcbiAgICAgICAgICAgIHZhciBjb25zdHJhaW5lZFJvdGF0aW9uID0gdGhpcy5jb25zdHJhaW50c18ucm90YXRpb24ocm90YXRpb24sIHRydWUpO1xuICAgICAgICAgICAgdGhpcy50YXJnZXRDZW50ZXJfID0gdGhpcy5jYWxjdWxhdGVDZW50ZXJSb3RhdGUoY29uc3RyYWluZWRSb3RhdGlvbiwgYW5pbWF0aW9uLmFuY2hvcik7XG4gICAgICAgICAgfVxuXG4gICAgICAgICAgdGhpcy50YXJnZXRSb3RhdGlvbl8gPSByb3RhdGlvbjtcbiAgICAgICAgfVxuXG4gICAgICAgIHRoaXMuYXBwbHlUYXJnZXRTdGF0ZV8odHJ1ZSk7XG4gICAgICAgIG1vcmUgPSB0cnVlO1xuXG4gICAgICAgIGlmICghYW5pbWF0aW9uLmNvbXBsZXRlKSB7XG4gICAgICAgICAgYnJlYWs7XG4gICAgICAgIH1cbiAgICAgIH1cblxuICAgICAgaWYgKHNlcmllc0NvbXBsZXRlKSB7XG4gICAgICAgIHRoaXMuYW5pbWF0aW9uc19baV0gPSBudWxsO1xuICAgICAgICB0aGlzLnNldEhpbnQoVmlld0hpbnQuQU5JTUFUSU5HLCAtMSk7XG4gICAgICAgIHZhciBjYWxsYmFjayA9IHNlcmllc1swXS5jYWxsYmFjaztcblxuICAgICAgICBpZiAoY2FsbGJhY2spIHtcbiAgICAgICAgICBhbmltYXRpb25DYWxsYmFjayhjYWxsYmFjaywgdHJ1ZSk7XG4gICAgICAgIH1cbiAgICAgIH1cbiAgICB9IC8vIHBydW5lIGNvbXBsZXRlZCBzZXJpZXNcblxuXG4gICAgdGhpcy5hbmltYXRpb25zXyA9IHRoaXMuYW5pbWF0aW9uc18uZmlsdGVyKEJvb2xlYW4pO1xuXG4gICAgaWYgKG1vcmUgJiYgdGhpcy51cGRhdGVBbmltYXRpb25LZXlfID09PSB1bmRlZmluZWQpIHtcbiAgICAgIHRoaXMudXBkYXRlQW5pbWF0aW9uS2V5XyA9IHJlcXVlc3RBbmltYXRpb25GcmFtZSh0aGlzLnVwZGF0ZUFuaW1hdGlvbnNfLmJpbmQodGhpcykpO1xuICAgIH1cbiAgfTtcbiAgLyoqXG4gICAqIEBwYXJhbSB7bnVtYmVyfSByb3RhdGlvbiBUYXJnZXQgcm90YXRpb24uXG4gICAqIEBwYXJhbSB7aW1wb3J0KFwiLi9jb29yZGluYXRlLmpzXCIpLkNvb3JkaW5hdGV9IGFuY2hvciBSb3RhdGlvbiBhbmNob3IuXG4gICAqIEByZXR1cm4ge2ltcG9ydChcIi4vY29vcmRpbmF0ZS5qc1wiKS5Db29yZGluYXRlfHVuZGVmaW5lZH0gQ2VudGVyIGZvciByb3RhdGlvbiBhbmQgYW5jaG9yLlxuICAgKi9cblxuXG4gIFZpZXcucHJvdG90eXBlLmNhbGN1bGF0ZUNlbnRlclJvdGF0ZSA9IGZ1bmN0aW9uIChyb3RhdGlvbiwgYW5jaG9yKSB7XG4gICAgdmFyIGNlbnRlcjtcbiAgICB2YXIgY3VycmVudENlbnRlciA9IHRoaXMuZ2V0Q2VudGVySW50ZXJuYWwoKTtcblxuICAgIGlmIChjdXJyZW50Q2VudGVyICE9PSB1bmRlZmluZWQpIHtcbiAgICAgIGNlbnRlciA9IFtjdXJyZW50Q2VudGVyWzBdIC0gYW5jaG9yWzBdLCBjdXJyZW50Q2VudGVyWzFdIC0gYW5jaG9yWzFdXTtcbiAgICAgIHJvdGF0ZUNvb3JkaW5hdGUoY2VudGVyLCByb3RhdGlvbiAtIHRoaXMuZ2V0Um90YXRpb24oKSk7XG4gICAgICBhZGRDb29yZGluYXRlKGNlbnRlciwgYW5jaG9yKTtcbiAgICB9XG5cbiAgICByZXR1cm4gY2VudGVyO1xuICB9O1xuICAvKipcbiAgICogQHBhcmFtIHtudW1iZXJ9IHJlc29sdXRpb24gVGFyZ2V0IHJlc29sdXRpb24uXG4gICAqIEBwYXJhbSB7aW1wb3J0KFwiLi9jb29yZGluYXRlLmpzXCIpLkNvb3JkaW5hdGV9IGFuY2hvciBab29tIGFuY2hvci5cbiAgICogQHJldHVybiB7aW1wb3J0KFwiLi9jb29yZGluYXRlLmpzXCIpLkNvb3JkaW5hdGV8dW5kZWZpbmVkfSBDZW50ZXIgZm9yIHJlc29sdXRpb24gYW5kIGFuY2hvci5cbiAgICovXG5cblxuICBWaWV3LnByb3RvdHlwZS5jYWxjdWxhdGVDZW50ZXJab29tID0gZnVuY3Rpb24gKHJlc29sdXRpb24sIGFuY2hvcikge1xuICAgIHZhciBjZW50ZXI7XG4gICAgdmFyIGN1cnJlbnRDZW50ZXIgPSB0aGlzLmdldENlbnRlckludGVybmFsKCk7XG4gICAgdmFyIGN1cnJlbnRSZXNvbHV0aW9uID0gdGhpcy5nZXRSZXNvbHV0aW9uKCk7XG5cbiAgICBpZiAoY3VycmVudENlbnRlciAhPT0gdW5kZWZpbmVkICYmIGN1cnJlbnRSZXNvbHV0aW9uICE9PSB1bmRlZmluZWQpIHtcbiAgICAgIHZhciB4ID0gYW5jaG9yWzBdIC0gcmVzb2x1dGlvbiAqIChhbmNob3JbMF0gLSBjdXJyZW50Q2VudGVyWzBdKSAvIGN1cnJlbnRSZXNvbHV0aW9uO1xuICAgICAgdmFyIHkgPSBhbmNob3JbMV0gLSByZXNvbHV0aW9uICogKGFuY2hvclsxXSAtIGN1cnJlbnRDZW50ZXJbMV0pIC8gY3VycmVudFJlc29sdXRpb247XG4gICAgICBjZW50ZXIgPSBbeCwgeV07XG4gICAgfVxuXG4gICAgcmV0dXJuIGNlbnRlcjtcbiAgfTtcbiAgLyoqXG4gICAqIFJldHVybnMgdGhlIGN1cnJlbnQgdmlld3BvcnQgc2l6ZS5cbiAgICogQHByaXZhdGVcbiAgICogQHBhcmFtIHtudW1iZXI9fSBvcHRfcm90YXRpb24gVGFrZSBpbnRvIGFjY291bnQgdGhlIHJvdGF0aW9uIG9mIHRoZSB2aWV3cG9ydCB3aGVuIGdpdmluZyB0aGUgc2l6ZVxuICAgKiBAcmV0dXJuIHtpbXBvcnQoXCIuL3NpemUuanNcIikuU2l6ZX0gVmlld3BvcnQgc2l6ZSBvciBgWzEwMCwgMTAwXWAgd2hlbiBubyB2aWV3cG9ydCBpcyBmb3VuZC5cbiAgICovXG5cblxuICBWaWV3LnByb3RvdHlwZS5nZXRWaWV3cG9ydFNpemVfID0gZnVuY3Rpb24gKG9wdF9yb3RhdGlvbikge1xuICAgIHZhciBzaXplID0gdGhpcy52aWV3cG9ydFNpemVfO1xuXG4gICAgaWYgKG9wdF9yb3RhdGlvbikge1xuICAgICAgdmFyIHcgPSBzaXplWzBdO1xuICAgICAgdmFyIGggPSBzaXplWzFdO1xuICAgICAgcmV0dXJuIFtNYXRoLmFicyh3ICogTWF0aC5jb3Mob3B0X3JvdGF0aW9uKSkgKyBNYXRoLmFicyhoICogTWF0aC5zaW4ob3B0X3JvdGF0aW9uKSksIE1hdGguYWJzKHcgKiBNYXRoLnNpbihvcHRfcm90YXRpb24pKSArIE1hdGguYWJzKGggKiBNYXRoLmNvcyhvcHRfcm90YXRpb24pKV07XG4gICAgfSBlbHNlIHtcbiAgICAgIHJldHVybiBzaXplO1xuICAgIH1cbiAgfTtcbiAgLyoqXG4gICAqIFN0b3JlcyB0aGUgdmlld3BvcnQgc2l6ZSBvbiB0aGUgdmlldy4gVGhlIHZpZXdwb3J0IHNpemUgaXMgbm90IHJlYWQgZXZlcnkgdGltZSBmcm9tIHRoZSBET01cbiAgICogdG8gYXZvaWQgcGVyZm9ybWFuY2UgaGl0IGFuZCBsYXlvdXQgcmVmbG93LlxuICAgKiBUaGlzIHNob3VsZCBiZSBkb25lIG9uIG1hcCBzaXplIGNoYW5nZS5cbiAgICogTm90ZTogdGhlIGNvbnN0cmFpbnRzIGFyZSBub3QgcmVzb2x2ZWQgZHVyaW5nIGFuIGFuaW1hdGlvbiB0byBhdm9pZCBzdG9wcGluZyBpdFxuICAgKiBAcGFyYW0ge2ltcG9ydChcIi4vc2l6ZS5qc1wiKS5TaXplPX0gb3B0X3NpemUgVmlld3BvcnQgc2l6ZTsgaWYgdW5kZWZpbmVkLCBbMTAwLCAxMDBdIGlzIGFzc3VtZWRcbiAgICovXG5cblxuICBWaWV3LnByb3RvdHlwZS5zZXRWaWV3cG9ydFNpemUgPSBmdW5jdGlvbiAob3B0X3NpemUpIHtcbiAgICB0aGlzLnZpZXdwb3J0U2l6ZV8gPSBBcnJheS5pc0FycmF5KG9wdF9zaXplKSA/IG9wdF9zaXplLnNsaWNlKCkgOiBbMTAwLCAxMDBdO1xuXG4gICAgaWYgKCF0aGlzLmdldEFuaW1hdGluZygpKSB7XG4gICAgICB0aGlzLnJlc29sdmVDb25zdHJhaW50cygwKTtcbiAgICB9XG4gIH07XG4gIC8qKlxuICAgKiBHZXQgdGhlIHZpZXcgY2VudGVyLlxuICAgKiBAcmV0dXJuIHtpbXBvcnQoXCIuL2Nvb3JkaW5hdGUuanNcIikuQ29vcmRpbmF0ZXx1bmRlZmluZWR9IFRoZSBjZW50ZXIgb2YgdGhlIHZpZXcuXG4gICAqIEBvYnNlcnZhYmxlXG4gICAqIEBhcGlcbiAgICovXG5cblxuICBWaWV3LnByb3RvdHlwZS5nZXRDZW50ZXIgPSBmdW5jdGlvbiAoKSB7XG4gICAgdmFyIGNlbnRlciA9IHRoaXMuZ2V0Q2VudGVySW50ZXJuYWwoKTtcblxuICAgIGlmICghY2VudGVyKSB7XG4gICAgICByZXR1cm4gY2VudGVyO1xuICAgIH1cblxuICAgIHJldHVybiB0b1VzZXJDb29yZGluYXRlKGNlbnRlciwgdGhpcy5nZXRQcm9qZWN0aW9uKCkpO1xuICB9O1xuICAvKipcbiAgICogR2V0IHRoZSB2aWV3IGNlbnRlciB3aXRob3V0IHRyYW5zZm9ybWluZyB0byB1c2VyIHByb2plY3Rpb24uXG4gICAqIEByZXR1cm4ge2ltcG9ydChcIi4vY29vcmRpbmF0ZS5qc1wiKS5Db29yZGluYXRlfHVuZGVmaW5lZH0gVGhlIGNlbnRlciBvZiB0aGUgdmlldy5cbiAgICovXG5cblxuICBWaWV3LnByb3RvdHlwZS5nZXRDZW50ZXJJbnRlcm5hbCA9IGZ1bmN0aW9uICgpIHtcbiAgICByZXR1cm4gKFxuICAgICAgLyoqIEB0eXBlIHtpbXBvcnQoXCIuL2Nvb3JkaW5hdGUuanNcIikuQ29vcmRpbmF0ZXx1bmRlZmluZWR9ICovXG4gICAgICB0aGlzLmdldChWaWV3UHJvcGVydHkuQ0VOVEVSKVxuICAgICk7XG4gIH07XG4gIC8qKlxuICAgKiBAcmV0dXJuIHtDb25zdHJhaW50c30gQ29uc3RyYWludHMuXG4gICAqL1xuXG5cbiAgVmlldy5wcm90b3R5cGUuZ2V0Q29uc3RyYWludHMgPSBmdW5jdGlvbiAoKSB7XG4gICAgcmV0dXJuIHRoaXMuY29uc3RyYWludHNfO1xuICB9O1xuICAvKipcbiAgICogQHJldHVybiB7Ym9vbGVhbn0gUmVzb2x1dGlvbiBjb25zdHJhaW50IGlzIHNldFxuICAgKi9cblxuXG4gIFZpZXcucHJvdG90eXBlLmdldENvbnN0cmFpblJlc29sdXRpb24gPSBmdW5jdGlvbiAoKSB7XG4gICAgcmV0dXJuIHRoaXMub3B0aW9uc18uY29uc3RyYWluUmVzb2x1dGlvbjtcbiAgfTtcbiAgLyoqXG4gICAqIEBwYXJhbSB7QXJyYXk8bnVtYmVyPj19IG9wdF9oaW50cyBEZXN0aW5hdGlvbiBhcnJheS5cbiAgICogQHJldHVybiB7QXJyYXk8bnVtYmVyPn0gSGludC5cbiAgICovXG5cblxuICBWaWV3LnByb3RvdHlwZS5nZXRIaW50cyA9IGZ1bmN0aW9uIChvcHRfaGludHMpIHtcbiAgICBpZiAob3B0X2hpbnRzICE9PSB1bmRlZmluZWQpIHtcbiAgICAgIG9wdF9oaW50c1swXSA9IHRoaXMuaGludHNfWzBdO1xuICAgICAgb3B0X2hpbnRzWzFdID0gdGhpcy5oaW50c19bMV07XG4gICAgICByZXR1cm4gb3B0X2hpbnRzO1xuICAgIH0gZWxzZSB7XG4gICAgICByZXR1cm4gdGhpcy5oaW50c18uc2xpY2UoKTtcbiAgICB9XG4gIH07XG4gIC8qKlxuICAgKiBDYWxjdWxhdGUgdGhlIGV4dGVudCBmb3IgdGhlIGN1cnJlbnQgdmlldyBzdGF0ZSBhbmQgdGhlIHBhc3NlZCBzaXplLlxuICAgKiBUaGUgc2l6ZSBpcyB0aGUgcGl4ZWwgZGltZW5zaW9ucyBvZiB0aGUgYm94IGludG8gd2hpY2ggdGhlIGNhbGN1bGF0ZWQgZXh0ZW50XG4gICAqIHNob3VsZCBmaXQuIEluIG1vc3QgY2FzZXMgeW91IHdhbnQgdG8gZ2V0IHRoZSBleHRlbnQgb2YgdGhlIGVudGlyZSBtYXAsXG4gICAqIHRoYXQgaXMgYG1hcC5nZXRTaXplKClgLlxuICAgKiBAcGFyYW0ge2ltcG9ydChcIi4vc2l6ZS5qc1wiKS5TaXplPX0gb3B0X3NpemUgQm94IHBpeGVsIHNpemUuIElmIG5vdCBwcm92aWRlZCwgdGhlIHNpemVcbiAgICogb2YgdGhlIG1hcCB0aGF0IHVzZXMgdGhpcyB2aWV3IHdpbGwgYmUgdXNlZC5cbiAgICogQHJldHVybiB7aW1wb3J0KFwiLi9leHRlbnQuanNcIikuRXh0ZW50fSBFeHRlbnQuXG4gICAqIEBhcGlcbiAgICovXG5cblxuICBWaWV3LnByb3RvdHlwZS5jYWxjdWxhdGVFeHRlbnQgPSBmdW5jdGlvbiAob3B0X3NpemUpIHtcbiAgICB2YXIgZXh0ZW50ID0gdGhpcy5jYWxjdWxhdGVFeHRlbnRJbnRlcm5hbChvcHRfc2l6ZSk7XG4gICAgcmV0dXJuIHRvVXNlckV4dGVudChleHRlbnQsIHRoaXMuZ2V0UHJvamVjdGlvbigpKTtcbiAgfTtcbiAgLyoqXG4gICAqIEBwYXJhbSB7aW1wb3J0KFwiLi9zaXplLmpzXCIpLlNpemU9fSBvcHRfc2l6ZSBCb3ggcGl4ZWwgc2l6ZS4gSWYgbm90IHByb3ZpZGVkLFxuICAgKiB0aGUgbWFwJ3MgbGFzdCBrbm93biB2aWV3cG9ydCBzaXplIHdpbGwgYmUgdXNlZC5cbiAgICogQHJldHVybiB7aW1wb3J0KFwiLi9leHRlbnQuanNcIikuRXh0ZW50fSBFeHRlbnQuXG4gICAqL1xuXG5cbiAgVmlldy5wcm90b3R5cGUuY2FsY3VsYXRlRXh0ZW50SW50ZXJuYWwgPSBmdW5jdGlvbiAob3B0X3NpemUpIHtcbiAgICB2YXIgc2l6ZSA9IG9wdF9zaXplIHx8IHRoaXMuZ2V0Vmlld3BvcnRTaXplXygpO1xuICAgIHZhciBjZW50ZXIgPVxuICAgIC8qKiBAdHlwZSB7IWltcG9ydChcIi4vY29vcmRpbmF0ZS5qc1wiKS5Db29yZGluYXRlfSAqL1xuICAgIHRoaXMuZ2V0Q2VudGVySW50ZXJuYWwoKTtcbiAgICBhc3NlcnQoY2VudGVyLCAxKTsgLy8gVGhlIHZpZXcgY2VudGVyIGlzIG5vdCBkZWZpbmVkXG5cbiAgICB2YXIgcmVzb2x1dGlvbiA9XG4gICAgLyoqIEB0eXBlIHshbnVtYmVyfSAqL1xuICAgIHRoaXMuZ2V0UmVzb2x1dGlvbigpO1xuICAgIGFzc2VydChyZXNvbHV0aW9uICE9PSB1bmRlZmluZWQsIDIpOyAvLyBUaGUgdmlldyByZXNvbHV0aW9uIGlzIG5vdCBkZWZpbmVkXG5cbiAgICB2YXIgcm90YXRpb24gPVxuICAgIC8qKiBAdHlwZSB7IW51bWJlcn0gKi9cbiAgICB0aGlzLmdldFJvdGF0aW9uKCk7XG4gICAgYXNzZXJ0KHJvdGF0aW9uICE9PSB1bmRlZmluZWQsIDMpOyAvLyBUaGUgdmlldyByb3RhdGlvbiBpcyBub3QgZGVmaW5lZFxuXG4gICAgcmV0dXJuIGdldEZvclZpZXdBbmRTaXplKGNlbnRlciwgcmVzb2x1dGlvbiwgcm90YXRpb24sIHNpemUpO1xuICB9O1xuICAvKipcbiAgICogR2V0IHRoZSBtYXhpbXVtIHJlc29sdXRpb24gb2YgdGhlIHZpZXcuXG4gICAqIEByZXR1cm4ge251bWJlcn0gVGhlIG1heGltdW0gcmVzb2x1dGlvbiBvZiB0aGUgdmlldy5cbiAgICogQGFwaVxuICAgKi9cblxuXG4gIFZpZXcucHJvdG90eXBlLmdldE1heFJlc29sdXRpb24gPSBmdW5jdGlvbiAoKSB7XG4gICAgcmV0dXJuIHRoaXMubWF4UmVzb2x1dGlvbl87XG4gIH07XG4gIC8qKlxuICAgKiBHZXQgdGhlIG1pbmltdW0gcmVzb2x1dGlvbiBvZiB0aGUgdmlldy5cbiAgICogQHJldHVybiB7bnVtYmVyfSBUaGUgbWluaW11bSByZXNvbHV0aW9uIG9mIHRoZSB2aWV3LlxuICAgKiBAYXBpXG4gICAqL1xuXG5cbiAgVmlldy5wcm90b3R5cGUuZ2V0TWluUmVzb2x1dGlvbiA9IGZ1bmN0aW9uICgpIHtcbiAgICByZXR1cm4gdGhpcy5taW5SZXNvbHV0aW9uXztcbiAgfTtcbiAgLyoqXG4gICAqIEdldCB0aGUgbWF4aW11bSB6b29tIGxldmVsIGZvciB0aGUgdmlldy5cbiAgICogQHJldHVybiB7bnVtYmVyfSBUaGUgbWF4aW11bSB6b29tIGxldmVsLlxuICAgKiBAYXBpXG4gICAqL1xuXG5cbiAgVmlldy5wcm90b3R5cGUuZ2V0TWF4Wm9vbSA9IGZ1bmN0aW9uICgpIHtcbiAgICByZXR1cm4gKFxuICAgICAgLyoqIEB0eXBlIHtudW1iZXJ9ICovXG4gICAgICB0aGlzLmdldFpvb21Gb3JSZXNvbHV0aW9uKHRoaXMubWluUmVzb2x1dGlvbl8pXG4gICAgKTtcbiAgfTtcbiAgLyoqXG4gICAqIFNldCBhIG5ldyBtYXhpbXVtIHpvb20gbGV2ZWwgZm9yIHRoZSB2aWV3LlxuICAgKiBAcGFyYW0ge251bWJlcn0gem9vbSBUaGUgbWF4aW11bSB6b29tIGxldmVsLlxuICAgKiBAYXBpXG4gICAqL1xuXG5cbiAgVmlldy5wcm90b3R5cGUuc2V0TWF4Wm9vbSA9IGZ1bmN0aW9uICh6b29tKSB7XG4gICAgdGhpcy5hcHBseU9wdGlvbnNfKHRoaXMuZ2V0VXBkYXRlZE9wdGlvbnNfKHtcbiAgICAgIG1heFpvb206IHpvb21cbiAgICB9KSk7XG4gIH07XG4gIC8qKlxuICAgKiBHZXQgdGhlIG1pbmltdW0gem9vbSBsZXZlbCBmb3IgdGhlIHZpZXcuXG4gICAqIEByZXR1cm4ge251bWJlcn0gVGhlIG1pbmltdW0gem9vbSBsZXZlbC5cbiAgICogQGFwaVxuICAgKi9cblxuXG4gIFZpZXcucHJvdG90eXBlLmdldE1pblpvb20gPSBmdW5jdGlvbiAoKSB7XG4gICAgcmV0dXJuIChcbiAgICAgIC8qKiBAdHlwZSB7bnVtYmVyfSAqL1xuICAgICAgdGhpcy5nZXRab29tRm9yUmVzb2x1dGlvbih0aGlzLm1heFJlc29sdXRpb25fKVxuICAgICk7XG4gIH07XG4gIC8qKlxuICAgKiBTZXQgYSBuZXcgbWluaW11bSB6b29tIGxldmVsIGZvciB0aGUgdmlldy5cbiAgICogQHBhcmFtIHtudW1iZXJ9IHpvb20gVGhlIG1pbmltdW0gem9vbSBsZXZlbC5cbiAgICogQGFwaVxuICAgKi9cblxuXG4gIFZpZXcucHJvdG90eXBlLnNldE1pblpvb20gPSBmdW5jdGlvbiAoem9vbSkge1xuICAgIHRoaXMuYXBwbHlPcHRpb25zXyh0aGlzLmdldFVwZGF0ZWRPcHRpb25zXyh7XG4gICAgICBtaW5ab29tOiB6b29tXG4gICAgfSkpO1xuICB9O1xuICAvKipcbiAgICogU2V0IHdoZXRoZXIgdGhlIHZpZXcgc2hvdWQgYWxsb3cgaW50ZXJtZWRpYXJ5IHpvb20gbGV2ZWxzLlxuICAgKiBAcGFyYW0ge2Jvb2xlYW59IGVuYWJsZWQgV2hldGhlciB0aGUgcmVzb2x1dGlvbiBpcyBjb25zdHJhaW5lZC5cbiAgICogQGFwaVxuICAgKi9cblxuXG4gIFZpZXcucHJvdG90eXBlLnNldENvbnN0cmFpblJlc29sdXRpb24gPSBmdW5jdGlvbiAoZW5hYmxlZCkge1xuICAgIHRoaXMuYXBwbHlPcHRpb25zXyh0aGlzLmdldFVwZGF0ZWRPcHRpb25zXyh7XG4gICAgICBjb25zdHJhaW5SZXNvbHV0aW9uOiBlbmFibGVkXG4gICAgfSkpO1xuICB9O1xuICAvKipcbiAgICogR2V0IHRoZSB2aWV3IHByb2plY3Rpb24uXG4gICAqIEByZXR1cm4ge2ltcG9ydChcIi4vcHJvai9Qcm9qZWN0aW9uLmpzXCIpLmRlZmF1bHR9IFRoZSBwcm9qZWN0aW9uIG9mIHRoZSB2aWV3LlxuICAgKiBAYXBpXG4gICAqL1xuXG5cbiAgVmlldy5wcm90b3R5cGUuZ2V0UHJvamVjdGlvbiA9IGZ1bmN0aW9uICgpIHtcbiAgICByZXR1cm4gdGhpcy5wcm9qZWN0aW9uXztcbiAgfTtcbiAgLyoqXG4gICAqIEdldCB0aGUgdmlldyByZXNvbHV0aW9uLlxuICAgKiBAcmV0dXJuIHtudW1iZXJ8dW5kZWZpbmVkfSBUaGUgcmVzb2x1dGlvbiBvZiB0aGUgdmlldy5cbiAgICogQG9ic2VydmFibGVcbiAgICogQGFwaVxuICAgKi9cblxuXG4gIFZpZXcucHJvdG90eXBlLmdldFJlc29sdXRpb24gPSBmdW5jdGlvbiAoKSB7XG4gICAgcmV0dXJuIChcbiAgICAgIC8qKiBAdHlwZSB7bnVtYmVyfHVuZGVmaW5lZH0gKi9cbiAgICAgIHRoaXMuZ2V0KFZpZXdQcm9wZXJ0eS5SRVNPTFVUSU9OKVxuICAgICk7XG4gIH07XG4gIC8qKlxuICAgKiBHZXQgdGhlIHJlc29sdXRpb25zIGZvciB0aGUgdmlldy4gVGhpcyByZXR1cm5zIHRoZSBhcnJheSBvZiByZXNvbHV0aW9uc1xuICAgKiBwYXNzZWQgdG8gdGhlIGNvbnN0cnVjdG9yIG9mIHRoZSBWaWV3LCBvciB1bmRlZmluZWQgaWYgbm9uZSB3ZXJlIGdpdmVuLlxuICAgKiBAcmV0dXJuIHtBcnJheTxudW1iZXI+fHVuZGVmaW5lZH0gVGhlIHJlc29sdXRpb25zIG9mIHRoZSB2aWV3LlxuICAgKiBAYXBpXG4gICAqL1xuXG5cbiAgVmlldy5wcm90b3R5cGUuZ2V0UmVzb2x1dGlvbnMgPSBmdW5jdGlvbiAoKSB7XG4gICAgcmV0dXJuIHRoaXMucmVzb2x1dGlvbnNfO1xuICB9O1xuICAvKipcbiAgICogR2V0IHRoZSByZXNvbHV0aW9uIGZvciBhIHByb3ZpZGVkIGV4dGVudCAoaW4gbWFwIHVuaXRzKSBhbmQgc2l6ZSAoaW4gcGl4ZWxzKS5cbiAgICogQHBhcmFtIHtpbXBvcnQoXCIuL2V4dGVudC5qc1wiKS5FeHRlbnR9IGV4dGVudCBFeHRlbnQuXG4gICAqIEBwYXJhbSB7aW1wb3J0KFwiLi9zaXplLmpzXCIpLlNpemU9fSBvcHRfc2l6ZSBCb3ggcGl4ZWwgc2l6ZS5cbiAgICogQHJldHVybiB7bnVtYmVyfSBUaGUgcmVzb2x1dGlvbiBhdCB3aGljaCB0aGUgcHJvdmlkZWQgZXh0ZW50IHdpbGwgcmVuZGVyIGF0XG4gICAqICAgICB0aGUgZ2l2ZW4gc2l6ZS5cbiAgICogQGFwaVxuICAgKi9cblxuXG4gIFZpZXcucHJvdG90eXBlLmdldFJlc29sdXRpb25Gb3JFeHRlbnQgPSBmdW5jdGlvbiAoZXh0ZW50LCBvcHRfc2l6ZSkge1xuICAgIHJldHVybiB0aGlzLmdldFJlc29sdXRpb25Gb3JFeHRlbnRJbnRlcm5hbChmcm9tVXNlckV4dGVudChleHRlbnQsIHRoaXMuZ2V0UHJvamVjdGlvbigpKSwgb3B0X3NpemUpO1xuICB9O1xuICAvKipcbiAgICogR2V0IHRoZSByZXNvbHV0aW9uIGZvciBhIHByb3ZpZGVkIGV4dGVudCAoaW4gbWFwIHVuaXRzKSBhbmQgc2l6ZSAoaW4gcGl4ZWxzKS5cbiAgICogQHBhcmFtIHtpbXBvcnQoXCIuL2V4dGVudC5qc1wiKS5FeHRlbnR9IGV4dGVudCBFeHRlbnQuXG4gICAqIEBwYXJhbSB7aW1wb3J0KFwiLi9zaXplLmpzXCIpLlNpemU9fSBvcHRfc2l6ZSBCb3ggcGl4ZWwgc2l6ZS5cbiAgICogQHJldHVybiB7bnVtYmVyfSBUaGUgcmVzb2x1dGlvbiBhdCB3aGljaCB0aGUgcHJvdmlkZWQgZXh0ZW50IHdpbGwgcmVuZGVyIGF0XG4gICAqICAgICB0aGUgZ2l2ZW4gc2l6ZS5cbiAgICovXG5cblxuICBWaWV3LnByb3RvdHlwZS5nZXRSZXNvbHV0aW9uRm9yRXh0ZW50SW50ZXJuYWwgPSBmdW5jdGlvbiAoZXh0ZW50LCBvcHRfc2l6ZSkge1xuICAgIHZhciBzaXplID0gb3B0X3NpemUgfHwgdGhpcy5nZXRWaWV3cG9ydFNpemVfKCk7XG4gICAgdmFyIHhSZXNvbHV0aW9uID0gZ2V0V2lkdGgoZXh0ZW50KSAvIHNpemVbMF07XG4gICAgdmFyIHlSZXNvbHV0aW9uID0gZ2V0SGVpZ2h0KGV4dGVudCkgLyBzaXplWzFdO1xuICAgIHJldHVybiBNYXRoLm1heCh4UmVzb2x1dGlvbiwgeVJlc29sdXRpb24pO1xuICB9O1xuICAvKipcbiAgICogUmV0dXJuIGEgZnVuY3Rpb24gdGhhdCByZXR1cm5zIGEgdmFsdWUgYmV0d2VlbiAwIGFuZCAxIGZvciBhXG4gICAqIHJlc29sdXRpb24uIEV4cG9uZW50aWFsIHNjYWxpbmcgaXMgYXNzdW1lZC5cbiAgICogQHBhcmFtIHtudW1iZXI9fSBvcHRfcG93ZXIgUG93ZXIuXG4gICAqIEByZXR1cm4ge2Z1bmN0aW9uKG51bWJlcik6IG51bWJlcn0gUmVzb2x1dGlvbiBmb3IgdmFsdWUgZnVuY3Rpb24uXG4gICAqL1xuXG5cbiAgVmlldy5wcm90b3R5cGUuZ2V0UmVzb2x1dGlvbkZvclZhbHVlRnVuY3Rpb24gPSBmdW5jdGlvbiAob3B0X3Bvd2VyKSB7XG4gICAgdmFyIHBvd2VyID0gb3B0X3Bvd2VyIHx8IDI7XG4gICAgdmFyIG1heFJlc29sdXRpb24gPSB0aGlzLmdldENvbnN0cmFpbmVkUmVzb2x1dGlvbih0aGlzLm1heFJlc29sdXRpb25fKTtcbiAgICB2YXIgbWluUmVzb2x1dGlvbiA9IHRoaXMubWluUmVzb2x1dGlvbl87XG4gICAgdmFyIG1heCA9IE1hdGgubG9nKG1heFJlc29sdXRpb24gLyBtaW5SZXNvbHV0aW9uKSAvIE1hdGgubG9nKHBvd2VyKTtcbiAgICByZXR1cm4gKFxuICAgICAgLyoqXG4gICAgICAgKiBAcGFyYW0ge251bWJlcn0gdmFsdWUgVmFsdWUuXG4gICAgICAgKiBAcmV0dXJuIHtudW1iZXJ9IFJlc29sdXRpb24uXG4gICAgICAgKi9cbiAgICAgIGZ1bmN0aW9uICh2YWx1ZSkge1xuICAgICAgICB2YXIgcmVzb2x1dGlvbiA9IG1heFJlc29sdXRpb24gLyBNYXRoLnBvdyhwb3dlciwgdmFsdWUgKiBtYXgpO1xuICAgICAgICByZXR1cm4gcmVzb2x1dGlvbjtcbiAgICAgIH1cbiAgICApO1xuICB9O1xuICAvKipcbiAgICogR2V0IHRoZSB2aWV3IHJvdGF0aW9uLlxuICAgKiBAcmV0dXJuIHtudW1iZXJ9IFRoZSByb3RhdGlvbiBvZiB0aGUgdmlldyBpbiByYWRpYW5zLlxuICAgKiBAb2JzZXJ2YWJsZVxuICAgKiBAYXBpXG4gICAqL1xuXG5cbiAgVmlldy5wcm90b3R5cGUuZ2V0Um90YXRpb24gPSBmdW5jdGlvbiAoKSB7XG4gICAgcmV0dXJuIChcbiAgICAgIC8qKiBAdHlwZSB7bnVtYmVyfSAqL1xuICAgICAgdGhpcy5nZXQoVmlld1Byb3BlcnR5LlJPVEFUSU9OKVxuICAgICk7XG4gIH07XG4gIC8qKlxuICAgKiBSZXR1cm4gYSBmdW5jdGlvbiB0aGF0IHJldHVybnMgYSByZXNvbHV0aW9uIGZvciBhIHZhbHVlIGJldHdlZW5cbiAgICogMCBhbmQgMS4gRXhwb25lbnRpYWwgc2NhbGluZyBpcyBhc3N1bWVkLlxuICAgKiBAcGFyYW0ge251bWJlcj19IG9wdF9wb3dlciBQb3dlci5cbiAgICogQHJldHVybiB7ZnVuY3Rpb24obnVtYmVyKTogbnVtYmVyfSBWYWx1ZSBmb3IgcmVzb2x1dGlvbiBmdW5jdGlvbi5cbiAgICovXG5cblxuICBWaWV3LnByb3RvdHlwZS5nZXRWYWx1ZUZvclJlc29sdXRpb25GdW5jdGlvbiA9IGZ1bmN0aW9uIChvcHRfcG93ZXIpIHtcbiAgICB2YXIgbG9nUG93ZXIgPSBNYXRoLmxvZyhvcHRfcG93ZXIgfHwgMik7XG4gICAgdmFyIG1heFJlc29sdXRpb24gPSB0aGlzLmdldENvbnN0cmFpbmVkUmVzb2x1dGlvbih0aGlzLm1heFJlc29sdXRpb25fKTtcbiAgICB2YXIgbWluUmVzb2x1dGlvbiA9IHRoaXMubWluUmVzb2x1dGlvbl87XG4gICAgdmFyIG1heCA9IE1hdGgubG9nKG1heFJlc29sdXRpb24gLyBtaW5SZXNvbHV0aW9uKSAvIGxvZ1Bvd2VyO1xuICAgIHJldHVybiAoXG4gICAgICAvKipcbiAgICAgICAqIEBwYXJhbSB7bnVtYmVyfSByZXNvbHV0aW9uIFJlc29sdXRpb24uXG4gICAgICAgKiBAcmV0dXJuIHtudW1iZXJ9IFZhbHVlLlxuICAgICAgICovXG4gICAgICBmdW5jdGlvbiAocmVzb2x1dGlvbikge1xuICAgICAgICB2YXIgdmFsdWUgPSBNYXRoLmxvZyhtYXhSZXNvbHV0aW9uIC8gcmVzb2x1dGlvbikgLyBsb2dQb3dlciAvIG1heDtcbiAgICAgICAgcmV0dXJuIHZhbHVlO1xuICAgICAgfVxuICAgICk7XG4gIH07XG4gIC8qKlxuICAgKiBSZXR1cm5zIHRoZSBzaXplIG9mIHRoZSB2aWV3cG9ydCBtaW51cyBwYWRkaW5nLlxuICAgKiBAcHJpdmF0ZVxuICAgKiBAcGFyYW0ge251bWJlcj19IG9wdF9yb3RhdGlvbiBUYWtlIGludG8gYWNjb3VudCB0aGUgcm90YXRpb24gb2YgdGhlIHZpZXdwb3J0IHdoZW4gZ2l2aW5nIHRoZSBzaXplXG4gICAqIEByZXR1cm4ge2ltcG9ydChcIi4vc2l6ZS5qc1wiKS5TaXplfSBWaWV3cG9ydCBzaXplIHJlZHVjZWQgYnkgdGhlIHBhZGRpbmcuXG4gICAqL1xuXG5cbiAgVmlldy5wcm90b3R5cGUuZ2V0Vmlld3BvcnRTaXplTWludXNQYWRkaW5nXyA9IGZ1bmN0aW9uIChvcHRfcm90YXRpb24pIHtcbiAgICB2YXIgc2l6ZSA9IHRoaXMuZ2V0Vmlld3BvcnRTaXplXyhvcHRfcm90YXRpb24pO1xuICAgIHZhciBwYWRkaW5nID0gdGhpcy5wYWRkaW5nO1xuXG4gICAgaWYgKHBhZGRpbmcpIHtcbiAgICAgIHNpemUgPSBbc2l6ZVswXSAtIHBhZGRpbmdbMV0gLSBwYWRkaW5nWzNdLCBzaXplWzFdIC0gcGFkZGluZ1swXSAtIHBhZGRpbmdbMl1dO1xuICAgIH1cblxuICAgIHJldHVybiBzaXplO1xuICB9O1xuICAvKipcbiAgICogQHJldHVybiB7U3RhdGV9IFZpZXcgc3RhdGUuXG4gICAqL1xuXG5cbiAgVmlldy5wcm90b3R5cGUuZ2V0U3RhdGUgPSBmdW5jdGlvbiAoKSB7XG4gICAgdmFyIHByb2plY3Rpb24gPSB0aGlzLmdldFByb2plY3Rpb24oKTtcbiAgICB2YXIgcmVzb2x1dGlvbiA9XG4gICAgLyoqIEB0eXBlIHtudW1iZXJ9ICovXG4gICAgdGhpcy5nZXRSZXNvbHV0aW9uKCk7XG4gICAgdmFyIHJvdGF0aW9uID0gdGhpcy5nZXRSb3RhdGlvbigpO1xuICAgIHZhciBjZW50ZXIgPVxuICAgIC8qKiBAdHlwZSB7aW1wb3J0KFwiLi9jb29yZGluYXRlLmpzXCIpLkNvb3JkaW5hdGV9ICovXG4gICAgdGhpcy5nZXRDZW50ZXJJbnRlcm5hbCgpO1xuICAgIHZhciBwYWRkaW5nID0gdGhpcy5wYWRkaW5nO1xuXG4gICAgaWYgKHBhZGRpbmcpIHtcbiAgICAgIHZhciByZWR1Y2VkU2l6ZSA9IHRoaXMuZ2V0Vmlld3BvcnRTaXplTWludXNQYWRkaW5nXygpO1xuICAgICAgY2VudGVyID0gY2FsY3VsYXRlQ2VudGVyT24oY2VudGVyLCB0aGlzLmdldFZpZXdwb3J0U2l6ZV8oKSwgW3JlZHVjZWRTaXplWzBdIC8gMiArIHBhZGRpbmdbM10sIHJlZHVjZWRTaXplWzFdIC8gMiArIHBhZGRpbmdbMF1dLCByZXNvbHV0aW9uLCByb3RhdGlvbik7XG4gICAgfVxuXG4gICAgcmV0dXJuIHtcbiAgICAgIGNlbnRlcjogY2VudGVyLnNsaWNlKDApLFxuICAgICAgcHJvamVjdGlvbjogcHJvamVjdGlvbiAhPT0gdW5kZWZpbmVkID8gcHJvamVjdGlvbiA6IG51bGwsXG4gICAgICByZXNvbHV0aW9uOiByZXNvbHV0aW9uLFxuICAgICAgcm90YXRpb246IHJvdGF0aW9uLFxuICAgICAgem9vbTogdGhpcy5nZXRab29tKClcbiAgICB9O1xuICB9O1xuICAvKipcbiAgICogR2V0IHRoZSBjdXJyZW50IHpvb20gbGV2ZWwuIFRoaXMgbWV0aG9kIG1heSByZXR1cm4gbm9uLWludGVnZXIgem9vbSBsZXZlbHNcbiAgICogaWYgdGhlIHZpZXcgZG9lcyBub3QgY29uc3RyYWluIHRoZSByZXNvbHV0aW9uLCBvciBpZiBhbiBpbnRlcmFjdGlvbiBvclxuICAgKiBhbmltYXRpb24gaXMgdW5kZXJ3YXkuXG4gICAqIEByZXR1cm4ge251bWJlcnx1bmRlZmluZWR9IFpvb20uXG4gICAqIEBhcGlcbiAgICovXG5cblxuICBWaWV3LnByb3RvdHlwZS5nZXRab29tID0gZnVuY3Rpb24gKCkge1xuICAgIHZhciB6b29tO1xuICAgIHZhciByZXNvbHV0aW9uID0gdGhpcy5nZXRSZXNvbHV0aW9uKCk7XG5cbiAgICBpZiAocmVzb2x1dGlvbiAhPT0gdW5kZWZpbmVkKSB7XG4gICAgICB6b29tID0gdGhpcy5nZXRab29tRm9yUmVzb2x1dGlvbihyZXNvbHV0aW9uKTtcbiAgICB9XG5cbiAgICByZXR1cm4gem9vbTtcbiAgfTtcbiAgLyoqXG4gICAqIEdldCB0aGUgem9vbSBsZXZlbCBmb3IgYSByZXNvbHV0aW9uLlxuICAgKiBAcGFyYW0ge251bWJlcn0gcmVzb2x1dGlvbiBUaGUgcmVzb2x1dGlvbi5cbiAgICogQHJldHVybiB7bnVtYmVyfHVuZGVmaW5lZH0gVGhlIHpvb20gbGV2ZWwgZm9yIHRoZSBwcm92aWRlZCByZXNvbHV0aW9uLlxuICAgKiBAYXBpXG4gICAqL1xuXG5cbiAgVmlldy5wcm90b3R5cGUuZ2V0Wm9vbUZvclJlc29sdXRpb24gPSBmdW5jdGlvbiAocmVzb2x1dGlvbikge1xuICAgIHZhciBvZmZzZXQgPSB0aGlzLm1pblpvb21fIHx8IDA7XG4gICAgdmFyIG1heCwgem9vbUZhY3RvcjtcblxuICAgIGlmICh0aGlzLnJlc29sdXRpb25zXykge1xuICAgICAgdmFyIG5lYXJlc3QgPSBsaW5lYXJGaW5kTmVhcmVzdCh0aGlzLnJlc29sdXRpb25zXywgcmVzb2x1dGlvbiwgMSk7XG4gICAgICBvZmZzZXQgPSBuZWFyZXN0O1xuICAgICAgbWF4ID0gdGhpcy5yZXNvbHV0aW9uc19bbmVhcmVzdF07XG5cbiAgICAgIGlmIChuZWFyZXN0ID09IHRoaXMucmVzb2x1dGlvbnNfLmxlbmd0aCAtIDEpIHtcbiAgICAgICAgem9vbUZhY3RvciA9IDI7XG4gICAgICB9IGVsc2Uge1xuICAgICAgICB6b29tRmFjdG9yID0gbWF4IC8gdGhpcy5yZXNvbHV0aW9uc19bbmVhcmVzdCArIDFdO1xuICAgICAgfVxuICAgIH0gZWxzZSB7XG4gICAgICBtYXggPSB0aGlzLm1heFJlc29sdXRpb25fO1xuICAgICAgem9vbUZhY3RvciA9IHRoaXMuem9vbUZhY3Rvcl87XG4gICAgfVxuXG4gICAgcmV0dXJuIG9mZnNldCArIE1hdGgubG9nKG1heCAvIHJlc29sdXRpb24pIC8gTWF0aC5sb2coem9vbUZhY3Rvcik7XG4gIH07XG4gIC8qKlxuICAgKiBHZXQgdGhlIHJlc29sdXRpb24gZm9yIGEgem9vbSBsZXZlbC5cbiAgICogQHBhcmFtIHtudW1iZXJ9IHpvb20gWm9vbSBsZXZlbC5cbiAgICogQHJldHVybiB7bnVtYmVyfSBUaGUgdmlldyByZXNvbHV0aW9uIGZvciB0aGUgcHJvdmlkZWQgem9vbSBsZXZlbC5cbiAgICogQGFwaVxuICAgKi9cblxuXG4gIFZpZXcucHJvdG90eXBlLmdldFJlc29sdXRpb25Gb3Jab29tID0gZnVuY3Rpb24gKHpvb20pIHtcbiAgICBpZiAodGhpcy5yZXNvbHV0aW9uc18pIHtcbiAgICAgIGlmICh0aGlzLnJlc29sdXRpb25zXy5sZW5ndGggPD0gMSkge1xuICAgICAgICByZXR1cm4gMDtcbiAgICAgIH1cblxuICAgICAgdmFyIGJhc2VMZXZlbCA9IGNsYW1wKE1hdGguZmxvb3Ioem9vbSksIDAsIHRoaXMucmVzb2x1dGlvbnNfLmxlbmd0aCAtIDIpO1xuICAgICAgdmFyIHpvb21GYWN0b3IgPSB0aGlzLnJlc29sdXRpb25zX1tiYXNlTGV2ZWxdIC8gdGhpcy5yZXNvbHV0aW9uc19bYmFzZUxldmVsICsgMV07XG4gICAgICByZXR1cm4gdGhpcy5yZXNvbHV0aW9uc19bYmFzZUxldmVsXSAvIE1hdGgucG93KHpvb21GYWN0b3IsIGNsYW1wKHpvb20gLSBiYXNlTGV2ZWwsIDAsIDEpKTtcbiAgICB9IGVsc2Uge1xuICAgICAgcmV0dXJuIHRoaXMubWF4UmVzb2x1dGlvbl8gLyBNYXRoLnBvdyh0aGlzLnpvb21GYWN0b3JfLCB6b29tIC0gdGhpcy5taW5ab29tXyk7XG4gICAgfVxuICB9O1xuICAvKipcbiAgICogRml0IHRoZSBnaXZlbiBnZW9tZXRyeSBvciBleHRlbnQgYmFzZWQgb24gdGhlIGdpdmVuIG1hcCBzaXplIGFuZCBib3JkZXIuXG4gICAqIFRoZSBzaXplIGlzIHBpeGVsIGRpbWVuc2lvbnMgb2YgdGhlIGJveCB0byBmaXQgdGhlIGV4dGVudCBpbnRvLlxuICAgKiBJbiBtb3N0IGNhc2VzIHlvdSB3aWxsIHdhbnQgdG8gdXNlIHRoZSBtYXAgc2l6ZSwgdGhhdCBpcyBgbWFwLmdldFNpemUoKWAuXG4gICAqIFRha2VzIGNhcmUgb2YgdGhlIG1hcCBhbmdsZS5cbiAgICogQHBhcmFtIHtpbXBvcnQoXCIuL2dlb20vU2ltcGxlR2VvbWV0cnkuanNcIikuZGVmYXVsdHxpbXBvcnQoXCIuL2V4dGVudC5qc1wiKS5FeHRlbnR9IGdlb21ldHJ5T3JFeHRlbnQgVGhlIGdlb21ldHJ5IG9yXG4gICAqICAgICBleHRlbnQgdG8gZml0IHRoZSB2aWV3IHRvLlxuICAgKiBAcGFyYW0ge0ZpdE9wdGlvbnM9fSBvcHRfb3B0aW9ucyBPcHRpb25zLlxuICAgKiBAYXBpXG4gICAqL1xuXG5cbiAgVmlldy5wcm90b3R5cGUuZml0ID0gZnVuY3Rpb24gKGdlb21ldHJ5T3JFeHRlbnQsIG9wdF9vcHRpb25zKSB7XG4gICAgLyoqIEB0eXBlIHtpbXBvcnQoXCIuL2dlb20vU2ltcGxlR2VvbWV0cnkuanNcIikuZGVmYXVsdH0gKi9cbiAgICB2YXIgZ2VvbWV0cnk7XG4gICAgYXNzZXJ0KEFycmF5LmlzQXJyYXkoZ2VvbWV0cnlPckV4dGVudCkgfHwgdHlwZW9mXG4gICAgLyoqIEB0eXBlIHs/fSAqL1xuICAgIGdlb21ldHJ5T3JFeHRlbnQuZ2V0U2ltcGxpZmllZEdlb21ldHJ5ID09PSAnZnVuY3Rpb24nLCAyNCk7IC8vIEludmFsaWQgZXh0ZW50IG9yIGdlb21ldHJ5IHByb3ZpZGVkIGFzIGBnZW9tZXRyeWBcblxuICAgIGlmIChBcnJheS5pc0FycmF5KGdlb21ldHJ5T3JFeHRlbnQpKSB7XG4gICAgICBhc3NlcnQoIWlzRW1wdHkoZ2VvbWV0cnlPckV4dGVudCksIDI1KTsgLy8gQ2Fubm90IGZpdCBlbXB0eSBleHRlbnQgcHJvdmlkZWQgYXMgYGdlb21ldHJ5YFxuXG4gICAgICB2YXIgZXh0ZW50ID0gZnJvbVVzZXJFeHRlbnQoZ2VvbWV0cnlPckV4dGVudCwgdGhpcy5nZXRQcm9qZWN0aW9uKCkpO1xuICAgICAgZ2VvbWV0cnkgPSBwb2x5Z29uRnJvbUV4dGVudChleHRlbnQpO1xuICAgIH0gZWxzZSBpZiAoZ2VvbWV0cnlPckV4dGVudC5nZXRUeXBlKCkgPT09IEdlb21ldHJ5VHlwZS5DSVJDTEUpIHtcbiAgICAgIHZhciBleHRlbnQgPSBmcm9tVXNlckV4dGVudChnZW9tZXRyeU9yRXh0ZW50LmdldEV4dGVudCgpLCB0aGlzLmdldFByb2plY3Rpb24oKSk7XG4gICAgICBnZW9tZXRyeSA9IHBvbHlnb25Gcm9tRXh0ZW50KGV4dGVudCk7XG4gICAgICBnZW9tZXRyeS5yb3RhdGUodGhpcy5nZXRSb3RhdGlvbigpLCBnZXRDZW50ZXIoZXh0ZW50KSk7XG4gICAgfSBlbHNlIHtcbiAgICAgIHZhciB1c2VyUHJvamVjdGlvbiA9IGdldFVzZXJQcm9qZWN0aW9uKCk7XG5cbiAgICAgIGlmICh1c2VyUHJvamVjdGlvbikge1xuICAgICAgICBnZW9tZXRyeSA9XG4gICAgICAgIC8qKiBAdHlwZSB7aW1wb3J0KFwiLi9nZW9tL1NpbXBsZUdlb21ldHJ5LmpzXCIpLmRlZmF1bHR9ICovXG4gICAgICAgIGdlb21ldHJ5T3JFeHRlbnQuY2xvbmUoKS50cmFuc2Zvcm0odXNlclByb2plY3Rpb24sIHRoaXMuZ2V0UHJvamVjdGlvbigpKTtcbiAgICAgIH0gZWxzZSB7XG4gICAgICAgIGdlb21ldHJ5ID0gZ2VvbWV0cnlPckV4dGVudDtcbiAgICAgIH1cbiAgICB9XG5cbiAgICB0aGlzLmZpdEludGVybmFsKGdlb21ldHJ5LCBvcHRfb3B0aW9ucyk7XG4gIH07XG4gIC8qKlxuICAgKiBAcGFyYW0ge2ltcG9ydChcIi4vZ2VvbS9TaW1wbGVHZW9tZXRyeS5qc1wiKS5kZWZhdWx0fSBnZW9tZXRyeSBUaGUgZ2VvbWV0cnkuXG4gICAqIEBwYXJhbSB7Rml0T3B0aW9ucz19IG9wdF9vcHRpb25zIE9wdGlvbnMuXG4gICAqL1xuXG5cbiAgVmlldy5wcm90b3R5cGUuZml0SW50ZXJuYWwgPSBmdW5jdGlvbiAoZ2VvbWV0cnksIG9wdF9vcHRpb25zKSB7XG4gICAgdmFyIG9wdGlvbnMgPSBvcHRfb3B0aW9ucyB8fCB7fTtcbiAgICB2YXIgc2l6ZSA9IG9wdGlvbnMuc2l6ZTtcblxuICAgIGlmICghc2l6ZSkge1xuICAgICAgc2l6ZSA9IHRoaXMuZ2V0Vmlld3BvcnRTaXplTWludXNQYWRkaW5nXygpO1xuICAgIH1cblxuICAgIHZhciBwYWRkaW5nID0gb3B0aW9ucy5wYWRkaW5nICE9PSB1bmRlZmluZWQgPyBvcHRpb25zLnBhZGRpbmcgOiBbMCwgMCwgMCwgMF07XG4gICAgdmFyIG5lYXJlc3QgPSBvcHRpb25zLm5lYXJlc3QgIT09IHVuZGVmaW5lZCA/IG9wdGlvbnMubmVhcmVzdCA6IGZhbHNlO1xuICAgIHZhciBtaW5SZXNvbHV0aW9uO1xuXG4gICAgaWYgKG9wdGlvbnMubWluUmVzb2x1dGlvbiAhPT0gdW5kZWZpbmVkKSB7XG4gICAgICBtaW5SZXNvbHV0aW9uID0gb3B0aW9ucy5taW5SZXNvbHV0aW9uO1xuICAgIH0gZWxzZSBpZiAob3B0aW9ucy5tYXhab29tICE9PSB1bmRlZmluZWQpIHtcbiAgICAgIG1pblJlc29sdXRpb24gPSB0aGlzLmdldFJlc29sdXRpb25Gb3Jab29tKG9wdGlvbnMubWF4Wm9vbSk7XG4gICAgfSBlbHNlIHtcbiAgICAgIG1pblJlc29sdXRpb24gPSAwO1xuICAgIH1cblxuICAgIHZhciBjb29yZHMgPSBnZW9tZXRyeS5nZXRGbGF0Q29vcmRpbmF0ZXMoKTsgLy8gY2FsY3VsYXRlIHJvdGF0ZWQgZXh0ZW50XG5cbiAgICB2YXIgcm90YXRpb24gPSB0aGlzLmdldFJvdGF0aW9uKCk7XG4gICAgdmFyIGNvc0FuZ2xlID0gTWF0aC5jb3MoLXJvdGF0aW9uKTtcbiAgICB2YXIgc2luQW5nbGUgPSBNYXRoLnNpbigtcm90YXRpb24pO1xuICAgIHZhciBtaW5Sb3RYID0gK0luZmluaXR5O1xuICAgIHZhciBtaW5Sb3RZID0gK0luZmluaXR5O1xuICAgIHZhciBtYXhSb3RYID0gLUluZmluaXR5O1xuICAgIHZhciBtYXhSb3RZID0gLUluZmluaXR5O1xuICAgIHZhciBzdHJpZGUgPSBnZW9tZXRyeS5nZXRTdHJpZGUoKTtcblxuICAgIGZvciAodmFyIGkgPSAwLCBpaSA9IGNvb3Jkcy5sZW5ndGg7IGkgPCBpaTsgaSArPSBzdHJpZGUpIHtcbiAgICAgIHZhciByb3RYID0gY29vcmRzW2ldICogY29zQW5nbGUgLSBjb29yZHNbaSArIDFdICogc2luQW5nbGU7XG4gICAgICB2YXIgcm90WSA9IGNvb3Jkc1tpXSAqIHNpbkFuZ2xlICsgY29vcmRzW2kgKyAxXSAqIGNvc0FuZ2xlO1xuICAgICAgbWluUm90WCA9IE1hdGgubWluKG1pblJvdFgsIHJvdFgpO1xuICAgICAgbWluUm90WSA9IE1hdGgubWluKG1pblJvdFksIHJvdFkpO1xuICAgICAgbWF4Um90WCA9IE1hdGgubWF4KG1heFJvdFgsIHJvdFgpO1xuICAgICAgbWF4Um90WSA9IE1hdGgubWF4KG1heFJvdFksIHJvdFkpO1xuICAgIH0gLy8gY2FsY3VsYXRlIHJlc29sdXRpb25cblxuXG4gICAgdmFyIHJlc29sdXRpb24gPSB0aGlzLmdldFJlc29sdXRpb25Gb3JFeHRlbnRJbnRlcm5hbChbbWluUm90WCwgbWluUm90WSwgbWF4Um90WCwgbWF4Um90WV0sIFtzaXplWzBdIC0gcGFkZGluZ1sxXSAtIHBhZGRpbmdbM10sIHNpemVbMV0gLSBwYWRkaW5nWzBdIC0gcGFkZGluZ1syXV0pO1xuICAgIHJlc29sdXRpb24gPSBpc05hTihyZXNvbHV0aW9uKSA/IG1pblJlc29sdXRpb24gOiBNYXRoLm1heChyZXNvbHV0aW9uLCBtaW5SZXNvbHV0aW9uKTtcbiAgICByZXNvbHV0aW9uID0gdGhpcy5nZXRDb25zdHJhaW5lZFJlc29sdXRpb24ocmVzb2x1dGlvbiwgbmVhcmVzdCA/IDAgOiAxKTsgLy8gY2FsY3VsYXRlIGNlbnRlclxuXG4gICAgc2luQW5nbGUgPSAtc2luQW5nbGU7IC8vIGdvIGJhY2sgdG8gb3JpZ2luYWwgcm90YXRpb25cblxuICAgIHZhciBjZW50ZXJSb3RYID0gKG1pblJvdFggKyBtYXhSb3RYKSAvIDI7XG4gICAgdmFyIGNlbnRlclJvdFkgPSAobWluUm90WSArIG1heFJvdFkpIC8gMjtcbiAgICBjZW50ZXJSb3RYICs9IChwYWRkaW5nWzFdIC0gcGFkZGluZ1szXSkgLyAyICogcmVzb2x1dGlvbjtcbiAgICBjZW50ZXJSb3RZICs9IChwYWRkaW5nWzBdIC0gcGFkZGluZ1syXSkgLyAyICogcmVzb2x1dGlvbjtcbiAgICB2YXIgY2VudGVyWCA9IGNlbnRlclJvdFggKiBjb3NBbmdsZSAtIGNlbnRlclJvdFkgKiBzaW5BbmdsZTtcbiAgICB2YXIgY2VudGVyWSA9IGNlbnRlclJvdFkgKiBjb3NBbmdsZSArIGNlbnRlclJvdFggKiBzaW5BbmdsZTtcbiAgICB2YXIgY2VudGVyID0gdGhpcy5nZXRDb25zdHJhaW5lZENlbnRlcihbY2VudGVyWCwgY2VudGVyWV0sIHJlc29sdXRpb24pO1xuICAgIHZhciBjYWxsYmFjayA9IG9wdGlvbnMuY2FsbGJhY2sgPyBvcHRpb25zLmNhbGxiYWNrIDogVk9JRDtcblxuICAgIGlmIChvcHRpb25zLmR1cmF0aW9uICE9PSB1bmRlZmluZWQpIHtcbiAgICAgIHRoaXMuYW5pbWF0ZUludGVybmFsKHtcbiAgICAgICAgcmVzb2x1dGlvbjogcmVzb2x1dGlvbixcbiAgICAgICAgY2VudGVyOiBjZW50ZXIsXG4gICAgICAgIGR1cmF0aW9uOiBvcHRpb25zLmR1cmF0aW9uLFxuICAgICAgICBlYXNpbmc6IG9wdGlvbnMuZWFzaW5nXG4gICAgICB9LCBjYWxsYmFjayk7XG4gICAgfSBlbHNlIHtcbiAgICAgIHRoaXMudGFyZ2V0UmVzb2x1dGlvbl8gPSByZXNvbHV0aW9uO1xuICAgICAgdGhpcy50YXJnZXRDZW50ZXJfID0gY2VudGVyO1xuICAgICAgdGhpcy5hcHBseVRhcmdldFN0YXRlXyhmYWxzZSwgdHJ1ZSk7XG4gICAgICBhbmltYXRpb25DYWxsYmFjayhjYWxsYmFjaywgdHJ1ZSk7XG4gICAgfVxuICB9O1xuICAvKipcbiAgICogQ2VudGVyIG9uIGNvb3JkaW5hdGUgYW5kIHZpZXcgcG9zaXRpb24uXG4gICAqIEBwYXJhbSB7aW1wb3J0KFwiLi9jb29yZGluYXRlLmpzXCIpLkNvb3JkaW5hdGV9IGNvb3JkaW5hdGUgQ29vcmRpbmF0ZS5cbiAgICogQHBhcmFtIHtpbXBvcnQoXCIuL3NpemUuanNcIikuU2l6ZX0gc2l6ZSBCb3ggcGl4ZWwgc2l6ZS5cbiAgICogQHBhcmFtIHtpbXBvcnQoXCIuL3BpeGVsLmpzXCIpLlBpeGVsfSBwb3NpdGlvbiBQb3NpdGlvbiBvbiB0aGUgdmlldyB0byBjZW50ZXIgb24uXG4gICAqIEBhcGlcbiAgICovXG5cblxuICBWaWV3LnByb3RvdHlwZS5jZW50ZXJPbiA9IGZ1bmN0aW9uIChjb29yZGluYXRlLCBzaXplLCBwb3NpdGlvbikge1xuICAgIHRoaXMuY2VudGVyT25JbnRlcm5hbChmcm9tVXNlckNvb3JkaW5hdGUoY29vcmRpbmF0ZSwgdGhpcy5nZXRQcm9qZWN0aW9uKCkpLCBzaXplLCBwb3NpdGlvbik7XG4gIH07XG4gIC8qKlxuICAgKiBAcGFyYW0ge2ltcG9ydChcIi4vY29vcmRpbmF0ZS5qc1wiKS5Db29yZGluYXRlfSBjb29yZGluYXRlIENvb3JkaW5hdGUuXG4gICAqIEBwYXJhbSB7aW1wb3J0KFwiLi9zaXplLmpzXCIpLlNpemV9IHNpemUgQm94IHBpeGVsIHNpemUuXG4gICAqIEBwYXJhbSB7aW1wb3J0KFwiLi9waXhlbC5qc1wiKS5QaXhlbH0gcG9zaXRpb24gUG9zaXRpb24gb24gdGhlIHZpZXcgdG8gY2VudGVyIG9uLlxuICAgKi9cblxuXG4gIFZpZXcucHJvdG90eXBlLmNlbnRlck9uSW50ZXJuYWwgPSBmdW5jdGlvbiAoY29vcmRpbmF0ZSwgc2l6ZSwgcG9zaXRpb24pIHtcbiAgICB0aGlzLnNldENlbnRlckludGVybmFsKGNhbGN1bGF0ZUNlbnRlck9uKGNvb3JkaW5hdGUsIHNpemUsIHBvc2l0aW9uLCB0aGlzLmdldFJlc29sdXRpb24oKSwgdGhpcy5nZXRSb3RhdGlvbigpKSk7XG4gIH07XG4gIC8qKlxuICAgKiBDYWxjdWxhdGVzIHRoZSBzaGlmdCBiZXR3ZWVuIG1hcCBhbmQgdmlld3BvcnQgY2VudGVyLlxuICAgKiBAcGFyYW0ge2ltcG9ydChcIi4vY29vcmRpbmF0ZS5qc1wiKS5Db29yZGluYXRlfSBjZW50ZXIgQ2VudGVyLlxuICAgKiBAcGFyYW0ge251bWJlcn0gcmVzb2x1dGlvbiBSZXNvbHV0aW9uLlxuICAgKiBAcGFyYW0ge251bWJlcn0gcm90YXRpb24gUm90YXRpb24uXG4gICAqIEBwYXJhbSB7aW1wb3J0KFwiLi9zaXplLmpzXCIpLlNpemV9IHNpemUgU2l6ZS5cbiAgICogQHJldHVybiB7QXJyYXk8bnVtYmVyPnx1bmRlZmluZWR9IENlbnRlciBzaGlmdC5cbiAgICovXG5cblxuICBWaWV3LnByb3RvdHlwZS5jYWxjdWxhdGVDZW50ZXJTaGlmdCA9IGZ1bmN0aW9uIChjZW50ZXIsIHJlc29sdXRpb24sIHJvdGF0aW9uLCBzaXplKSB7XG4gICAgdmFyIGNlbnRlclNoaWZ0O1xuICAgIHZhciBwYWRkaW5nID0gdGhpcy5wYWRkaW5nO1xuXG4gICAgaWYgKHBhZGRpbmcgJiYgY2VudGVyKSB7XG4gICAgICB2YXIgcmVkdWNlZFNpemUgPSB0aGlzLmdldFZpZXdwb3J0U2l6ZU1pbnVzUGFkZGluZ18oLXJvdGF0aW9uKTtcbiAgICAgIHZhciBzaGlmdGVkQ2VudGVyID0gY2FsY3VsYXRlQ2VudGVyT24oY2VudGVyLCBzaXplLCBbcmVkdWNlZFNpemVbMF0gLyAyICsgcGFkZGluZ1szXSwgcmVkdWNlZFNpemVbMV0gLyAyICsgcGFkZGluZ1swXV0sIHJlc29sdXRpb24sIHJvdGF0aW9uKTtcbiAgICAgIGNlbnRlclNoaWZ0ID0gW2NlbnRlclswXSAtIHNoaWZ0ZWRDZW50ZXJbMF0sIGNlbnRlclsxXSAtIHNoaWZ0ZWRDZW50ZXJbMV1dO1xuICAgIH1cblxuICAgIHJldHVybiBjZW50ZXJTaGlmdDtcbiAgfTtcbiAgLyoqXG4gICAqIEByZXR1cm4ge2Jvb2xlYW59IElzIGRlZmluZWQuXG4gICAqL1xuXG5cbiAgVmlldy5wcm90b3R5cGUuaXNEZWYgPSBmdW5jdGlvbiAoKSB7XG4gICAgcmV0dXJuICEhdGhpcy5nZXRDZW50ZXJJbnRlcm5hbCgpICYmIHRoaXMuZ2V0UmVzb2x1dGlvbigpICE9PSB1bmRlZmluZWQ7XG4gIH07XG4gIC8qKlxuICAgKiBBZGRzIHJlbGF0aXZlIGNvb3JkaW5hdGVzIHRvIHRoZSBjZW50ZXIgb2YgdGhlIHZpZXcuIEFueSBleHRlbnQgY29uc3RyYWludCB3aWxsIGFwcGx5LlxuICAgKiBAcGFyYW0ge2ltcG9ydChcIi4vY29vcmRpbmF0ZS5qc1wiKS5Db29yZGluYXRlfSBkZWx0YUNvb3JkaW5hdGVzIFJlbGF0aXZlIHZhbHVlIHRvIGFkZC5cbiAgICogQGFwaVxuICAgKi9cblxuXG4gIFZpZXcucHJvdG90eXBlLmFkanVzdENlbnRlciA9IGZ1bmN0aW9uIChkZWx0YUNvb3JkaW5hdGVzKSB7XG4gICAgdmFyIGNlbnRlciA9IHRvVXNlckNvb3JkaW5hdGUodGhpcy50YXJnZXRDZW50ZXJfLCB0aGlzLmdldFByb2plY3Rpb24oKSk7XG4gICAgdGhpcy5zZXRDZW50ZXIoW2NlbnRlclswXSArIGRlbHRhQ29vcmRpbmF0ZXNbMF0sIGNlbnRlclsxXSArIGRlbHRhQ29vcmRpbmF0ZXNbMV1dKTtcbiAgfTtcbiAgLyoqXG4gICAqIEFkZHMgcmVsYXRpdmUgY29vcmRpbmF0ZXMgdG8gdGhlIGNlbnRlciBvZiB0aGUgdmlldy4gQW55IGV4dGVudCBjb25zdHJhaW50IHdpbGwgYXBwbHkuXG4gICAqIEBwYXJhbSB7aW1wb3J0KFwiLi9jb29yZGluYXRlLmpzXCIpLkNvb3JkaW5hdGV9IGRlbHRhQ29vcmRpbmF0ZXMgUmVsYXRpdmUgdmFsdWUgdG8gYWRkLlxuICAgKi9cblxuXG4gIFZpZXcucHJvdG90eXBlLmFkanVzdENlbnRlckludGVybmFsID0gZnVuY3Rpb24gKGRlbHRhQ29vcmRpbmF0ZXMpIHtcbiAgICB2YXIgY2VudGVyID0gdGhpcy50YXJnZXRDZW50ZXJfO1xuICAgIHRoaXMuc2V0Q2VudGVySW50ZXJuYWwoW2NlbnRlclswXSArIGRlbHRhQ29vcmRpbmF0ZXNbMF0sIGNlbnRlclsxXSArIGRlbHRhQ29vcmRpbmF0ZXNbMV1dKTtcbiAgfTtcbiAgLyoqXG4gICAqIE11bHRpcGx5IHRoZSB2aWV3IHJlc29sdXRpb24gYnkgYSByYXRpbywgb3B0aW9uYWxseSB1c2luZyBhbiBhbmNob3IuIEFueSByZXNvbHV0aW9uXG4gICAqIGNvbnN0cmFpbnQgd2lsbCBhcHBseS5cbiAgICogQHBhcmFtIHtudW1iZXJ9IHJhdGlvIFRoZSByYXRpbyB0byBhcHBseSBvbiB0aGUgdmlldyByZXNvbHV0aW9uLlxuICAgKiBAcGFyYW0ge2ltcG9ydChcIi4vY29vcmRpbmF0ZS5qc1wiKS5Db29yZGluYXRlPX0gb3B0X2FuY2hvciBUaGUgb3JpZ2luIG9mIHRoZSB0cmFuc2Zvcm1hdGlvbi5cbiAgICogQGFwaVxuICAgKi9cblxuXG4gIFZpZXcucHJvdG90eXBlLmFkanVzdFJlc29sdXRpb24gPSBmdW5jdGlvbiAocmF0aW8sIG9wdF9hbmNob3IpIHtcbiAgICB2YXIgYW5jaG9yID0gb3B0X2FuY2hvciAmJiBmcm9tVXNlckNvb3JkaW5hdGUob3B0X2FuY2hvciwgdGhpcy5nZXRQcm9qZWN0aW9uKCkpO1xuICAgIHRoaXMuYWRqdXN0UmVzb2x1dGlvbkludGVybmFsKHJhdGlvLCBhbmNob3IpO1xuICB9O1xuICAvKipcbiAgICogTXVsdGlwbHkgdGhlIHZpZXcgcmVzb2x1dGlvbiBieSBhIHJhdGlvLCBvcHRpb25hbGx5IHVzaW5nIGFuIGFuY2hvci4gQW55IHJlc29sdXRpb25cbiAgICogY29uc3RyYWludCB3aWxsIGFwcGx5LlxuICAgKiBAcGFyYW0ge251bWJlcn0gcmF0aW8gVGhlIHJhdGlvIHRvIGFwcGx5IG9uIHRoZSB2aWV3IHJlc29sdXRpb24uXG4gICAqIEBwYXJhbSB7aW1wb3J0KFwiLi9jb29yZGluYXRlLmpzXCIpLkNvb3JkaW5hdGU9fSBvcHRfYW5jaG9yIFRoZSBvcmlnaW4gb2YgdGhlIHRyYW5zZm9ybWF0aW9uLlxuICAgKi9cblxuXG4gIFZpZXcucHJvdG90eXBlLmFkanVzdFJlc29sdXRpb25JbnRlcm5hbCA9IGZ1bmN0aW9uIChyYXRpbywgb3B0X2FuY2hvcikge1xuICAgIHZhciBpc01vdmluZyA9IHRoaXMuZ2V0QW5pbWF0aW5nKCkgfHwgdGhpcy5nZXRJbnRlcmFjdGluZygpO1xuICAgIHZhciBzaXplID0gdGhpcy5nZXRWaWV3cG9ydFNpemVfKHRoaXMuZ2V0Um90YXRpb24oKSk7XG4gICAgdmFyIG5ld1Jlc29sdXRpb24gPSB0aGlzLmNvbnN0cmFpbnRzXy5yZXNvbHV0aW9uKHRoaXMudGFyZ2V0UmVzb2x1dGlvbl8gKiByYXRpbywgMCwgc2l6ZSwgaXNNb3ZpbmcpO1xuXG4gICAgaWYgKG9wdF9hbmNob3IpIHtcbiAgICAgIHRoaXMudGFyZ2V0Q2VudGVyXyA9IHRoaXMuY2FsY3VsYXRlQ2VudGVyWm9vbShuZXdSZXNvbHV0aW9uLCBvcHRfYW5jaG9yKTtcbiAgICB9XG5cbiAgICB0aGlzLnRhcmdldFJlc29sdXRpb25fICo9IHJhdGlvO1xuICAgIHRoaXMuYXBwbHlUYXJnZXRTdGF0ZV8oKTtcbiAgfTtcbiAgLyoqXG4gICAqIEFkZHMgYSB2YWx1ZSB0byB0aGUgdmlldyB6b29tIGxldmVsLCBvcHRpb25hbGx5IHVzaW5nIGFuIGFuY2hvci4gQW55IHJlc29sdXRpb25cbiAgICogY29uc3RyYWludCB3aWxsIGFwcGx5LlxuICAgKiBAcGFyYW0ge251bWJlcn0gZGVsdGEgUmVsYXRpdmUgdmFsdWUgdG8gYWRkIHRvIHRoZSB6b29tIGxldmVsLlxuICAgKiBAcGFyYW0ge2ltcG9ydChcIi4vY29vcmRpbmF0ZS5qc1wiKS5Db29yZGluYXRlPX0gb3B0X2FuY2hvciBUaGUgb3JpZ2luIG9mIHRoZSB0cmFuc2Zvcm1hdGlvbi5cbiAgICogQGFwaVxuICAgKi9cblxuXG4gIFZpZXcucHJvdG90eXBlLmFkanVzdFpvb20gPSBmdW5jdGlvbiAoZGVsdGEsIG9wdF9hbmNob3IpIHtcbiAgICB0aGlzLmFkanVzdFJlc29sdXRpb24oTWF0aC5wb3codGhpcy56b29tRmFjdG9yXywgLWRlbHRhKSwgb3B0X2FuY2hvcik7XG4gIH07XG4gIC8qKlxuICAgKiBBZGRzIGEgdmFsdWUgdG8gdGhlIHZpZXcgcm90YXRpb24sIG9wdGlvbmFsbHkgdXNpbmcgYW4gYW5jaG9yLiBBbnkgcm90YXRpb25cbiAgICogY29uc3RyYWludCB3aWxsIGFwcGx5LlxuICAgKiBAcGFyYW0ge251bWJlcn0gZGVsdGEgUmVsYXRpdmUgdmFsdWUgdG8gYWRkIHRvIHRoZSB6b29tIHJvdGF0aW9uLCBpbiByYWRpYW5zLlxuICAgKiBAcGFyYW0ge2ltcG9ydChcIi4vY29vcmRpbmF0ZS5qc1wiKS5Db29yZGluYXRlPX0gb3B0X2FuY2hvciBUaGUgcm90YXRpb24gY2VudGVyLlxuICAgKiBAYXBpXG4gICAqL1xuXG5cbiAgVmlldy5wcm90b3R5cGUuYWRqdXN0Um90YXRpb24gPSBmdW5jdGlvbiAoZGVsdGEsIG9wdF9hbmNob3IpIHtcbiAgICBpZiAob3B0X2FuY2hvcikge1xuICAgICAgb3B0X2FuY2hvciA9IGZyb21Vc2VyQ29vcmRpbmF0ZShvcHRfYW5jaG9yLCB0aGlzLmdldFByb2plY3Rpb24oKSk7XG4gICAgfVxuXG4gICAgdGhpcy5hZGp1c3RSb3RhdGlvbkludGVybmFsKGRlbHRhLCBvcHRfYW5jaG9yKTtcbiAgfTtcbiAgLyoqXG4gICAqIEBwYXJhbSB7bnVtYmVyfSBkZWx0YSBSZWxhdGl2ZSB2YWx1ZSB0byBhZGQgdG8gdGhlIHpvb20gcm90YXRpb24sIGluIHJhZGlhbnMuXG4gICAqIEBwYXJhbSB7aW1wb3J0KFwiLi9jb29yZGluYXRlLmpzXCIpLkNvb3JkaW5hdGU9fSBvcHRfYW5jaG9yIFRoZSByb3RhdGlvbiBjZW50ZXIuXG4gICAqL1xuXG5cbiAgVmlldy5wcm90b3R5cGUuYWRqdXN0Um90YXRpb25JbnRlcm5hbCA9IGZ1bmN0aW9uIChkZWx0YSwgb3B0X2FuY2hvcikge1xuICAgIHZhciBpc01vdmluZyA9IHRoaXMuZ2V0QW5pbWF0aW5nKCkgfHwgdGhpcy5nZXRJbnRlcmFjdGluZygpO1xuICAgIHZhciBuZXdSb3RhdGlvbiA9IHRoaXMuY29uc3RyYWludHNfLnJvdGF0aW9uKHRoaXMudGFyZ2V0Um90YXRpb25fICsgZGVsdGEsIGlzTW92aW5nKTtcblxuICAgIGlmIChvcHRfYW5jaG9yKSB7XG4gICAgICB0aGlzLnRhcmdldENlbnRlcl8gPSB0aGlzLmNhbGN1bGF0ZUNlbnRlclJvdGF0ZShuZXdSb3RhdGlvbiwgb3B0X2FuY2hvcik7XG4gICAgfVxuXG4gICAgdGhpcy50YXJnZXRSb3RhdGlvbl8gKz0gZGVsdGE7XG4gICAgdGhpcy5hcHBseVRhcmdldFN0YXRlXygpO1xuICB9O1xuICAvKipcbiAgICogU2V0IHRoZSBjZW50ZXIgb2YgdGhlIGN1cnJlbnQgdmlldy4gQW55IGV4dGVudCBjb25zdHJhaW50IHdpbGwgYXBwbHkuXG4gICAqIEBwYXJhbSB7aW1wb3J0KFwiLi9jb29yZGluYXRlLmpzXCIpLkNvb3JkaW5hdGV8dW5kZWZpbmVkfSBjZW50ZXIgVGhlIGNlbnRlciBvZiB0aGUgdmlldy5cbiAgICogQG9ic2VydmFibGVcbiAgICogQGFwaVxuICAgKi9cblxuXG4gIFZpZXcucHJvdG90eXBlLnNldENlbnRlciA9IGZ1bmN0aW9uIChjZW50ZXIpIHtcbiAgICB0aGlzLnNldENlbnRlckludGVybmFsKGZyb21Vc2VyQ29vcmRpbmF0ZShjZW50ZXIsIHRoaXMuZ2V0UHJvamVjdGlvbigpKSk7XG4gIH07XG4gIC8qKlxuICAgKiBTZXQgdGhlIGNlbnRlciB1c2luZyB0aGUgdmlldyBwcm9qZWN0aW9uIChub3QgdGhlIHVzZXIgcHJvamVjdGlvbikuXG4gICAqIEBwYXJhbSB7aW1wb3J0KFwiLi9jb29yZGluYXRlLmpzXCIpLkNvb3JkaW5hdGV8dW5kZWZpbmVkfSBjZW50ZXIgVGhlIGNlbnRlciBvZiB0aGUgdmlldy5cbiAgICovXG5cblxuICBWaWV3LnByb3RvdHlwZS5zZXRDZW50ZXJJbnRlcm5hbCA9IGZ1bmN0aW9uIChjZW50ZXIpIHtcbiAgICB0aGlzLnRhcmdldENlbnRlcl8gPSBjZW50ZXI7XG4gICAgdGhpcy5hcHBseVRhcmdldFN0YXRlXygpO1xuICB9O1xuICAvKipcbiAgICogQHBhcmFtIHtpbXBvcnQoXCIuL1ZpZXdIaW50LmpzXCIpLmRlZmF1bHR9IGhpbnQgSGludC5cbiAgICogQHBhcmFtIHtudW1iZXJ9IGRlbHRhIERlbHRhLlxuICAgKiBAcmV0dXJuIHtudW1iZXJ9IE5ldyB2YWx1ZS5cbiAgICovXG5cblxuICBWaWV3LnByb3RvdHlwZS5zZXRIaW50ID0gZnVuY3Rpb24gKGhpbnQsIGRlbHRhKSB7XG4gICAgdGhpcy5oaW50c19baGludF0gKz0gZGVsdGE7XG4gICAgdGhpcy5jaGFuZ2VkKCk7XG4gICAgcmV0dXJuIHRoaXMuaGludHNfW2hpbnRdO1xuICB9O1xuICAvKipcbiAgICogU2V0IHRoZSByZXNvbHV0aW9uIGZvciB0aGlzIHZpZXcuIEFueSByZXNvbHV0aW9uIGNvbnN0cmFpbnQgd2lsbCBhcHBseS5cbiAgICogQHBhcmFtIHtudW1iZXJ8dW5kZWZpbmVkfSByZXNvbHV0aW9uIFRoZSByZXNvbHV0aW9uIG9mIHRoZSB2aWV3LlxuICAgKiBAb2JzZXJ2YWJsZVxuICAgKiBAYXBpXG4gICAqL1xuXG5cbiAgVmlldy5wcm90b3R5cGUuc2V0UmVzb2x1dGlvbiA9IGZ1bmN0aW9uIChyZXNvbHV0aW9uKSB7XG4gICAgdGhpcy50YXJnZXRSZXNvbHV0aW9uXyA9IHJlc29sdXRpb247XG4gICAgdGhpcy5hcHBseVRhcmdldFN0YXRlXygpO1xuICB9O1xuICAvKipcbiAgICogU2V0IHRoZSByb3RhdGlvbiBmb3IgdGhpcyB2aWV3LiBBbnkgcm90YXRpb24gY29uc3RyYWludCB3aWxsIGFwcGx5LlxuICAgKiBAcGFyYW0ge251bWJlcn0gcm90YXRpb24gVGhlIHJvdGF0aW9uIG9mIHRoZSB2aWV3IGluIHJhZGlhbnMuXG4gICAqIEBvYnNlcnZhYmxlXG4gICAqIEBhcGlcbiAgICovXG5cblxuICBWaWV3LnByb3RvdHlwZS5zZXRSb3RhdGlvbiA9IGZ1bmN0aW9uIChyb3RhdGlvbikge1xuICAgIHRoaXMudGFyZ2V0Um90YXRpb25fID0gcm90YXRpb247XG4gICAgdGhpcy5hcHBseVRhcmdldFN0YXRlXygpO1xuICB9O1xuICAvKipcbiAgICogWm9vbSB0byBhIHNwZWNpZmljIHpvb20gbGV2ZWwuIEFueSByZXNvbHV0aW9uIGNvbnN0cmFpbiB3aWxsIGFwcGx5LlxuICAgKiBAcGFyYW0ge251bWJlcn0gem9vbSBab29tIGxldmVsLlxuICAgKiBAYXBpXG4gICAqL1xuXG5cbiAgVmlldy5wcm90b3R5cGUuc2V0Wm9vbSA9IGZ1bmN0aW9uICh6b29tKSB7XG4gICAgdGhpcy5zZXRSZXNvbHV0aW9uKHRoaXMuZ2V0UmVzb2x1dGlvbkZvclpvb20oem9vbSkpO1xuICB9O1xuICAvKipcbiAgICogUmVjb21wdXRlIHJvdGF0aW9uL3Jlc29sdXRpb24vY2VudGVyIGJhc2VkIG9uIHRhcmdldCB2YWx1ZXMuXG4gICAqIE5vdGU6IHdlIGhhdmUgdG8gY29tcHV0ZSByb3RhdGlvbiBmaXJzdCwgdGhlbiByZXNvbHV0aW9uIGFuZCBjZW50ZXIgY29uc2lkZXJpbmcgdGhhdFxuICAgKiBwYXJhbWV0ZXJzIGNhbiBpbmZsdWVuY2Ugb25lIGFub3RoZXIgaW4gY2FzZSBhIHZpZXcgZXh0ZW50IGNvbnN0cmFpbnQgaXMgcHJlc2VudC5cbiAgICogQHBhcmFtIHtib29sZWFuPX0gb3B0X2RvTm90Q2FuY2VsQW5pbXMgRG8gbm90IGNhbmNlbCBhbmltYXRpb25zLlxuICAgKiBAcGFyYW0ge2Jvb2xlYW49fSBvcHRfZm9yY2VNb3ZpbmcgQXBwbHkgY29uc3RyYWludHMgYXMgaWYgdGhlIHZpZXcgaXMgbW92aW5nLlxuICAgKiBAcHJpdmF0ZVxuICAgKi9cblxuXG4gIFZpZXcucHJvdG90eXBlLmFwcGx5VGFyZ2V0U3RhdGVfID0gZnVuY3Rpb24gKG9wdF9kb05vdENhbmNlbEFuaW1zLCBvcHRfZm9yY2VNb3ZpbmcpIHtcbiAgICB2YXIgaXNNb3ZpbmcgPSB0aGlzLmdldEFuaW1hdGluZygpIHx8IHRoaXMuZ2V0SW50ZXJhY3RpbmcoKSB8fCBvcHRfZm9yY2VNb3Zpbmc7IC8vIGNvbXB1dGUgcm90YXRpb25cblxuICAgIHZhciBuZXdSb3RhdGlvbiA9IHRoaXMuY29uc3RyYWludHNfLnJvdGF0aW9uKHRoaXMudGFyZ2V0Um90YXRpb25fLCBpc01vdmluZyk7XG4gICAgdmFyIHNpemUgPSB0aGlzLmdldFZpZXdwb3J0U2l6ZV8obmV3Um90YXRpb24pO1xuICAgIHZhciBuZXdSZXNvbHV0aW9uID0gdGhpcy5jb25zdHJhaW50c18ucmVzb2x1dGlvbih0aGlzLnRhcmdldFJlc29sdXRpb25fLCAwLCBzaXplLCBpc01vdmluZyk7XG4gICAgdmFyIG5ld0NlbnRlciA9IHRoaXMuY29uc3RyYWludHNfLmNlbnRlcih0aGlzLnRhcmdldENlbnRlcl8sIG5ld1Jlc29sdXRpb24sIHNpemUsIGlzTW92aW5nLCB0aGlzLmNhbGN1bGF0ZUNlbnRlclNoaWZ0KHRoaXMudGFyZ2V0Q2VudGVyXywgbmV3UmVzb2x1dGlvbiwgbmV3Um90YXRpb24sIHNpemUpKTtcblxuICAgIGlmICh0aGlzLmdldChWaWV3UHJvcGVydHkuUk9UQVRJT04pICE9PSBuZXdSb3RhdGlvbikge1xuICAgICAgdGhpcy5zZXQoVmlld1Byb3BlcnR5LlJPVEFUSU9OLCBuZXdSb3RhdGlvbik7XG4gICAgfVxuXG4gICAgaWYgKHRoaXMuZ2V0KFZpZXdQcm9wZXJ0eS5SRVNPTFVUSU9OKSAhPT0gbmV3UmVzb2x1dGlvbikge1xuICAgICAgdGhpcy5zZXQoVmlld1Byb3BlcnR5LlJFU09MVVRJT04sIG5ld1Jlc29sdXRpb24pO1xuICAgIH1cblxuICAgIGlmICghdGhpcy5nZXQoVmlld1Byb3BlcnR5LkNFTlRFUikgfHwgIWVxdWFscyh0aGlzLmdldChWaWV3UHJvcGVydHkuQ0VOVEVSKSwgbmV3Q2VudGVyKSkge1xuICAgICAgdGhpcy5zZXQoVmlld1Byb3BlcnR5LkNFTlRFUiwgbmV3Q2VudGVyKTtcbiAgICB9XG5cbiAgICBpZiAodGhpcy5nZXRBbmltYXRpbmcoKSAmJiAhb3B0X2RvTm90Q2FuY2VsQW5pbXMpIHtcbiAgICAgIHRoaXMuY2FuY2VsQW5pbWF0aW9ucygpO1xuICAgIH1cblxuICAgIHRoaXMuY2FuY2VsQW5jaG9yXyA9IHVuZGVmaW5lZDtcbiAgfTtcbiAgLyoqXG4gICAqIElmIGFueSBjb25zdHJhaW50cyBuZWVkIHRvIGJlIGFwcGxpZWQsIGFuIGFuaW1hdGlvbiB3aWxsIGJlIHRyaWdnZXJlZC5cbiAgICogVGhpcyBpcyB0eXBpY2FsbHkgZG9uZSBvbiBpbnRlcmFjdGlvbiBlbmQuXG4gICAqIE5vdGU6IGNhbGxpbmcgdGhpcyB3aXRoIGEgZHVyYXRpb24gb2YgMCB3aWxsIGFwcGx5IHRoZSBjb25zdHJhaW5lZCB2YWx1ZXMgc3RyYWlnaHQgYXdheSxcbiAgICogd2l0aG91dCBhbmltYXRpb24uXG4gICAqIEBwYXJhbSB7bnVtYmVyPX0gb3B0X2R1cmF0aW9uIFRoZSBhbmltYXRpb24gZHVyYXRpb24gaW4gbXMuXG4gICAqIEBwYXJhbSB7bnVtYmVyPX0gb3B0X3Jlc29sdXRpb25EaXJlY3Rpb24gV2hpY2ggZGlyZWN0aW9uIHRvIHpvb20uXG4gICAqIEBwYXJhbSB7aW1wb3J0KFwiLi9jb29yZGluYXRlLmpzXCIpLkNvb3JkaW5hdGU9fSBvcHRfYW5jaG9yIFRoZSBvcmlnaW4gb2YgdGhlIHRyYW5zZm9ybWF0aW9uLlxuICAgKi9cblxuXG4gIFZpZXcucHJvdG90eXBlLnJlc29sdmVDb25zdHJhaW50cyA9IGZ1bmN0aW9uIChvcHRfZHVyYXRpb24sIG9wdF9yZXNvbHV0aW9uRGlyZWN0aW9uLCBvcHRfYW5jaG9yKSB7XG4gICAgdmFyIGR1cmF0aW9uID0gb3B0X2R1cmF0aW9uICE9PSB1bmRlZmluZWQgPyBvcHRfZHVyYXRpb24gOiAyMDA7XG4gICAgdmFyIGRpcmVjdGlvbiA9IG9wdF9yZXNvbHV0aW9uRGlyZWN0aW9uIHx8IDA7XG4gICAgdmFyIG5ld1JvdGF0aW9uID0gdGhpcy5jb25zdHJhaW50c18ucm90YXRpb24odGhpcy50YXJnZXRSb3RhdGlvbl8pO1xuICAgIHZhciBzaXplID0gdGhpcy5nZXRWaWV3cG9ydFNpemVfKG5ld1JvdGF0aW9uKTtcbiAgICB2YXIgbmV3UmVzb2x1dGlvbiA9IHRoaXMuY29uc3RyYWludHNfLnJlc29sdXRpb24odGhpcy50YXJnZXRSZXNvbHV0aW9uXywgZGlyZWN0aW9uLCBzaXplKTtcbiAgICB2YXIgbmV3Q2VudGVyID0gdGhpcy5jb25zdHJhaW50c18uY2VudGVyKHRoaXMudGFyZ2V0Q2VudGVyXywgbmV3UmVzb2x1dGlvbiwgc2l6ZSwgZmFsc2UsIHRoaXMuY2FsY3VsYXRlQ2VudGVyU2hpZnQodGhpcy50YXJnZXRDZW50ZXJfLCBuZXdSZXNvbHV0aW9uLCBuZXdSb3RhdGlvbiwgc2l6ZSkpO1xuXG4gICAgaWYgKGR1cmF0aW9uID09PSAwICYmICF0aGlzLmNhbmNlbEFuY2hvcl8pIHtcbiAgICAgIHRoaXMudGFyZ2V0UmVzb2x1dGlvbl8gPSBuZXdSZXNvbHV0aW9uO1xuICAgICAgdGhpcy50YXJnZXRSb3RhdGlvbl8gPSBuZXdSb3RhdGlvbjtcbiAgICAgIHRoaXMudGFyZ2V0Q2VudGVyXyA9IG5ld0NlbnRlcjtcbiAgICAgIHRoaXMuYXBwbHlUYXJnZXRTdGF0ZV8oKTtcbiAgICAgIHJldHVybjtcbiAgICB9XG5cbiAgICB2YXIgYW5jaG9yID0gb3B0X2FuY2hvciB8fCAoZHVyYXRpb24gPT09IDAgPyB0aGlzLmNhbmNlbEFuY2hvcl8gOiB1bmRlZmluZWQpO1xuICAgIHRoaXMuY2FuY2VsQW5jaG9yXyA9IHVuZGVmaW5lZDtcblxuICAgIGlmICh0aGlzLmdldFJlc29sdXRpb24oKSAhPT0gbmV3UmVzb2x1dGlvbiB8fCB0aGlzLmdldFJvdGF0aW9uKCkgIT09IG5ld1JvdGF0aW9uIHx8ICF0aGlzLmdldENlbnRlckludGVybmFsKCkgfHwgIWVxdWFscyh0aGlzLmdldENlbnRlckludGVybmFsKCksIG5ld0NlbnRlcikpIHtcbiAgICAgIGlmICh0aGlzLmdldEFuaW1hdGluZygpKSB7XG4gICAgICAgIHRoaXMuY2FuY2VsQW5pbWF0aW9ucygpO1xuICAgICAgfVxuXG4gICAgICB0aGlzLmFuaW1hdGVJbnRlcm5hbCh7XG4gICAgICAgIHJvdGF0aW9uOiBuZXdSb3RhdGlvbixcbiAgICAgICAgY2VudGVyOiBuZXdDZW50ZXIsXG4gICAgICAgIHJlc29sdXRpb246IG5ld1Jlc29sdXRpb24sXG4gICAgICAgIGR1cmF0aW9uOiBkdXJhdGlvbixcbiAgICAgICAgZWFzaW5nOiBlYXNlT3V0LFxuICAgICAgICBhbmNob3I6IGFuY2hvclxuICAgICAgfSk7XG4gICAgfVxuICB9O1xuICAvKipcbiAgICogTm90aWZ5IHRoZSBWaWV3IHRoYXQgYW4gaW50ZXJhY3Rpb24gaGFzIHN0YXJ0ZWQuXG4gICAqIFRoZSB2aWV3IHN0YXRlIHdpbGwgYmUgcmVzb2x2ZWQgdG8gYSBzdGFibGUgb25lIGlmIG5lZWRlZFxuICAgKiAoZGVwZW5kaW5nIG9uIGl0cyBjb25zdHJhaW50cykuXG4gICAqIEBhcGlcbiAgICovXG5cblxuICBWaWV3LnByb3RvdHlwZS5iZWdpbkludGVyYWN0aW9uID0gZnVuY3Rpb24gKCkge1xuICAgIHRoaXMucmVzb2x2ZUNvbnN0cmFpbnRzKDApO1xuICAgIHRoaXMuc2V0SGludChWaWV3SGludC5JTlRFUkFDVElORywgMSk7XG4gIH07XG4gIC8qKlxuICAgKiBOb3RpZnkgdGhlIFZpZXcgdGhhdCBhbiBpbnRlcmFjdGlvbiBoYXMgZW5kZWQuIFRoZSB2aWV3IHN0YXRlIHdpbGwgYmUgcmVzb2x2ZWRcbiAgICogdG8gYSBzdGFibGUgb25lIGlmIG5lZWRlZCAoZGVwZW5kaW5nIG9uIGl0cyBjb25zdHJhaW50cykuXG4gICAqIEBwYXJhbSB7bnVtYmVyPX0gb3B0X2R1cmF0aW9uIEFuaW1hdGlvbiBkdXJhdGlvbiBpbiBtcy5cbiAgICogQHBhcmFtIHtudW1iZXI9fSBvcHRfcmVzb2x1dGlvbkRpcmVjdGlvbiBXaGljaCBkaXJlY3Rpb24gdG8gem9vbS5cbiAgICogQHBhcmFtIHtpbXBvcnQoXCIuL2Nvb3JkaW5hdGUuanNcIikuQ29vcmRpbmF0ZT19IG9wdF9hbmNob3IgVGhlIG9yaWdpbiBvZiB0aGUgdHJhbnNmb3JtYXRpb24uXG4gICAqIEBhcGlcbiAgICovXG5cblxuICBWaWV3LnByb3RvdHlwZS5lbmRJbnRlcmFjdGlvbiA9IGZ1bmN0aW9uIChvcHRfZHVyYXRpb24sIG9wdF9yZXNvbHV0aW9uRGlyZWN0aW9uLCBvcHRfYW5jaG9yKSB7XG4gICAgdmFyIGFuY2hvciA9IG9wdF9hbmNob3IgJiYgZnJvbVVzZXJDb29yZGluYXRlKG9wdF9hbmNob3IsIHRoaXMuZ2V0UHJvamVjdGlvbigpKTtcbiAgICB0aGlzLmVuZEludGVyYWN0aW9uSW50ZXJuYWwob3B0X2R1cmF0aW9uLCBvcHRfcmVzb2x1dGlvbkRpcmVjdGlvbiwgYW5jaG9yKTtcbiAgfTtcbiAgLyoqXG4gICAqIE5vdGlmeSB0aGUgVmlldyB0aGF0IGFuIGludGVyYWN0aW9uIGhhcyBlbmRlZC4gVGhlIHZpZXcgc3RhdGUgd2lsbCBiZSByZXNvbHZlZFxuICAgKiB0byBhIHN0YWJsZSBvbmUgaWYgbmVlZGVkIChkZXBlbmRpbmcgb24gaXRzIGNvbnN0cmFpbnRzKS5cbiAgICogQHBhcmFtIHtudW1iZXI9fSBvcHRfZHVyYXRpb24gQW5pbWF0aW9uIGR1cmF0aW9uIGluIG1zLlxuICAgKiBAcGFyYW0ge251bWJlcj19IG9wdF9yZXNvbHV0aW9uRGlyZWN0aW9uIFdoaWNoIGRpcmVjdGlvbiB0byB6b29tLlxuICAgKiBAcGFyYW0ge2ltcG9ydChcIi4vY29vcmRpbmF0ZS5qc1wiKS5Db29yZGluYXRlPX0gb3B0X2FuY2hvciBUaGUgb3JpZ2luIG9mIHRoZSB0cmFuc2Zvcm1hdGlvbi5cbiAgICovXG5cblxuICBWaWV3LnByb3RvdHlwZS5lbmRJbnRlcmFjdGlvbkludGVybmFsID0gZnVuY3Rpb24gKG9wdF9kdXJhdGlvbiwgb3B0X3Jlc29sdXRpb25EaXJlY3Rpb24sIG9wdF9hbmNob3IpIHtcbiAgICB0aGlzLnNldEhpbnQoVmlld0hpbnQuSU5URVJBQ1RJTkcsIC0xKTtcbiAgICB0aGlzLnJlc29sdmVDb25zdHJhaW50cyhvcHRfZHVyYXRpb24sIG9wdF9yZXNvbHV0aW9uRGlyZWN0aW9uLCBvcHRfYW5jaG9yKTtcbiAgfTtcbiAgLyoqXG4gICAqIEdldCBhIHZhbGlkIHBvc2l0aW9uIGZvciB0aGUgdmlldyBjZW50ZXIgYWNjb3JkaW5nIHRvIHRoZSBjdXJyZW50IGNvbnN0cmFpbnRzLlxuICAgKiBAcGFyYW0ge2ltcG9ydChcIi4vY29vcmRpbmF0ZS5qc1wiKS5Db29yZGluYXRlfHVuZGVmaW5lZH0gdGFyZ2V0Q2VudGVyIFRhcmdldCBjZW50ZXIgcG9zaXRpb24uXG4gICAqIEBwYXJhbSB7bnVtYmVyPX0gb3B0X3RhcmdldFJlc29sdXRpb24gVGFyZ2V0IHJlc29sdXRpb24uIElmIG5vdCBzdXBwbGllZCwgdGhlIGN1cnJlbnQgb25lIHdpbGwgYmUgdXNlZC5cbiAgICogVGhpcyBpcyB1c2VmdWwgdG8gZ3Vlc3MgYSB2YWxpZCBjZW50ZXIgcG9zaXRpb24gYXQgYSBkaWZmZXJlbnQgem9vbSBsZXZlbC5cbiAgICogQHJldHVybiB7aW1wb3J0KFwiLi9jb29yZGluYXRlLmpzXCIpLkNvb3JkaW5hdGV8dW5kZWZpbmVkfSBWYWxpZCBjZW50ZXIgcG9zaXRpb24uXG4gICAqL1xuXG5cbiAgVmlldy5wcm90b3R5cGUuZ2V0Q29uc3RyYWluZWRDZW50ZXIgPSBmdW5jdGlvbiAodGFyZ2V0Q2VudGVyLCBvcHRfdGFyZ2V0UmVzb2x1dGlvbikge1xuICAgIHZhciBzaXplID0gdGhpcy5nZXRWaWV3cG9ydFNpemVfKHRoaXMuZ2V0Um90YXRpb24oKSk7XG4gICAgcmV0dXJuIHRoaXMuY29uc3RyYWludHNfLmNlbnRlcih0YXJnZXRDZW50ZXIsIG9wdF90YXJnZXRSZXNvbHV0aW9uIHx8IHRoaXMuZ2V0UmVzb2x1dGlvbigpLCBzaXplKTtcbiAgfTtcbiAgLyoqXG4gICAqIEdldCBhIHZhbGlkIHpvb20gbGV2ZWwgYWNjb3JkaW5nIHRvIHRoZSBjdXJyZW50IHZpZXcgY29uc3RyYWludHMuXG4gICAqIEBwYXJhbSB7bnVtYmVyfHVuZGVmaW5lZH0gdGFyZ2V0Wm9vbSBUYXJnZXQgem9vbS5cbiAgICogQHBhcmFtIHtudW1iZXI9fSBbb3B0X2RpcmVjdGlvbj0wXSBJbmRpY2F0ZSB3aGljaCByZXNvbHV0aW9uIHNob3VsZCBiZSB1c2VkXG4gICAqIGJ5IGEgcmVuZGVyZXIgaWYgdGhlIHZpZXcgcmVzb2x1dGlvbiBkb2VzIG5vdCBtYXRjaCBhbnkgcmVzb2x1dGlvbiBvZiB0aGUgdGlsZSBzb3VyY2UuXG4gICAqIElmIDAsIHRoZSBuZWFyZXN0IHJlc29sdXRpb24gd2lsbCBiZSB1c2VkLiBJZiAxLCB0aGUgbmVhcmVzdCBsb3dlciByZXNvbHV0aW9uXG4gICAqIHdpbGwgYmUgdXNlZC4gSWYgLTEsIHRoZSBuZWFyZXN0IGhpZ2hlciByZXNvbHV0aW9uIHdpbGwgYmUgdXNlZC5cbiAgICogQHJldHVybiB7bnVtYmVyfHVuZGVmaW5lZH0gVmFsaWQgem9vbSBsZXZlbC5cbiAgICovXG5cblxuICBWaWV3LnByb3RvdHlwZS5nZXRDb25zdHJhaW5lZFpvb20gPSBmdW5jdGlvbiAodGFyZ2V0Wm9vbSwgb3B0X2RpcmVjdGlvbikge1xuICAgIHZhciB0YXJnZXRSZXMgPSB0aGlzLmdldFJlc29sdXRpb25Gb3Jab29tKHRhcmdldFpvb20pO1xuICAgIHJldHVybiB0aGlzLmdldFpvb21Gb3JSZXNvbHV0aW9uKHRoaXMuZ2V0Q29uc3RyYWluZWRSZXNvbHV0aW9uKHRhcmdldFJlcywgb3B0X2RpcmVjdGlvbikpO1xuICB9O1xuICAvKipcbiAgICogR2V0IGEgdmFsaWQgcmVzb2x1dGlvbiBhY2NvcmRpbmcgdG8gdGhlIGN1cnJlbnQgdmlldyBjb25zdHJhaW50cy5cbiAgICogQHBhcmFtIHtudW1iZXJ8dW5kZWZpbmVkfSB0YXJnZXRSZXNvbHV0aW9uIFRhcmdldCByZXNvbHV0aW9uLlxuICAgKiBAcGFyYW0ge251bWJlcj19IFtvcHRfZGlyZWN0aW9uPTBdIEluZGljYXRlIHdoaWNoIHJlc29sdXRpb24gc2hvdWxkIGJlIHVzZWRcbiAgICogYnkgYSByZW5kZXJlciBpZiB0aGUgdmlldyByZXNvbHV0aW9uIGRvZXMgbm90IG1hdGNoIGFueSByZXNvbHV0aW9uIG9mIHRoZSB0aWxlIHNvdXJjZS5cbiAgICogSWYgMCwgdGhlIG5lYXJlc3QgcmVzb2x1dGlvbiB3aWxsIGJlIHVzZWQuIElmIDEsIHRoZSBuZWFyZXN0IGxvd2VyIHJlc29sdXRpb25cbiAgICogd2lsbCBiZSB1c2VkLiBJZiAtMSwgdGhlIG5lYXJlc3QgaGlnaGVyIHJlc29sdXRpb24gd2lsbCBiZSB1c2VkLlxuICAgKiBAcmV0dXJuIHtudW1iZXJ8dW5kZWZpbmVkfSBWYWxpZCByZXNvbHV0aW9uLlxuICAgKi9cblxuXG4gIFZpZXcucHJvdG90eXBlLmdldENvbnN0cmFpbmVkUmVzb2x1dGlvbiA9IGZ1bmN0aW9uICh0YXJnZXRSZXNvbHV0aW9uLCBvcHRfZGlyZWN0aW9uKSB7XG4gICAgdmFyIGRpcmVjdGlvbiA9IG9wdF9kaXJlY3Rpb24gfHwgMDtcbiAgICB2YXIgc2l6ZSA9IHRoaXMuZ2V0Vmlld3BvcnRTaXplXyh0aGlzLmdldFJvdGF0aW9uKCkpO1xuICAgIHJldHVybiB0aGlzLmNvbnN0cmFpbnRzXy5yZXNvbHV0aW9uKHRhcmdldFJlc29sdXRpb24sIGRpcmVjdGlvbiwgc2l6ZSk7XG4gIH07XG5cbiAgcmV0dXJuIFZpZXc7XG59KEJhc2VPYmplY3QpO1xuLyoqXG4gKiBAcGFyYW0ge0Z1bmN0aW9ufSBjYWxsYmFjayBDYWxsYmFjay5cbiAqIEBwYXJhbSB7Kn0gcmV0dXJuVmFsdWUgUmV0dXJuIHZhbHVlLlxuICovXG5cblxuZnVuY3Rpb24gYW5pbWF0aW9uQ2FsbGJhY2soY2FsbGJhY2ssIHJldHVyblZhbHVlKSB7XG4gIHNldFRpbWVvdXQoZnVuY3Rpb24gKCkge1xuICAgIGNhbGxiYWNrKHJldHVyblZhbHVlKTtcbiAgfSwgMCk7XG59XG4vKipcbiAqIEBwYXJhbSB7Vmlld09wdGlvbnN9IG9wdGlvbnMgVmlldyBvcHRpb25zLlxuICogQHJldHVybiB7aW1wb3J0KFwiLi9jZW50ZXJjb25zdHJhaW50LmpzXCIpLlR5cGV9IFRoZSBjb25zdHJhaW50LlxuICovXG5cblxuZXhwb3J0IGZ1bmN0aW9uIGNyZWF0ZUNlbnRlckNvbnN0cmFpbnQob3B0aW9ucykge1xuICBpZiAob3B0aW9ucy5leHRlbnQgIT09IHVuZGVmaW5lZCkge1xuICAgIHZhciBzbW9vdGggPSBvcHRpb25zLnNtb290aEV4dGVudENvbnN0cmFpbnQgIT09IHVuZGVmaW5lZCA/IG9wdGlvbnMuc21vb3RoRXh0ZW50Q29uc3RyYWludCA6IHRydWU7XG4gICAgcmV0dXJuIGNyZWF0ZUV4dGVudChvcHRpb25zLmV4dGVudCwgb3B0aW9ucy5jb25zdHJhaW5Pbmx5Q2VudGVyLCBzbW9vdGgpO1xuICB9XG5cbiAgdmFyIHByb2plY3Rpb24gPSBjcmVhdGVQcm9qZWN0aW9uKG9wdGlvbnMucHJvamVjdGlvbiwgJ0VQU0c6Mzg1NycpO1xuXG4gIGlmIChvcHRpb25zLm11bHRpV29ybGQgIT09IHRydWUgJiYgcHJvamVjdGlvbi5pc0dsb2JhbCgpKSB7XG4gICAgdmFyIGV4dGVudCA9IHByb2plY3Rpb24uZ2V0RXh0ZW50KCkuc2xpY2UoKTtcbiAgICBleHRlbnRbMF0gPSAtSW5maW5pdHk7XG4gICAgZXh0ZW50WzJdID0gSW5maW5pdHk7XG4gICAgcmV0dXJuIGNyZWF0ZUV4dGVudChleHRlbnQsIGZhbHNlLCBmYWxzZSk7XG4gIH1cblxuICByZXR1cm4gY2VudGVyTm9uZTtcbn1cbi8qKlxuICogQHBhcmFtIHtWaWV3T3B0aW9uc30gb3B0aW9ucyBWaWV3IG9wdGlvbnMuXG4gKiBAcmV0dXJuIHt7Y29uc3RyYWludDogaW1wb3J0KFwiLi9yZXNvbHV0aW9uY29uc3RyYWludC5qc1wiKS5UeXBlLCBtYXhSZXNvbHV0aW9uOiBudW1iZXIsXG4gKiAgICAgbWluUmVzb2x1dGlvbjogbnVtYmVyLCBtaW5ab29tOiBudW1iZXIsIHpvb21GYWN0b3I6IG51bWJlcn19IFRoZSBjb25zdHJhaW50LlxuICovXG5cbmV4cG9ydCBmdW5jdGlvbiBjcmVhdGVSZXNvbHV0aW9uQ29uc3RyYWludChvcHRpb25zKSB7XG4gIHZhciByZXNvbHV0aW9uQ29uc3RyYWludDtcbiAgdmFyIG1heFJlc29sdXRpb247XG4gIHZhciBtaW5SZXNvbHV0aW9uOyAvLyBUT0RPOiBtb3ZlIHRoZXNlIHRvIGJlIG9sIGNvbnN0YW50c1xuICAvLyBzZWUgaHR0cHM6Ly9naXRodWIuY29tL29wZW5sYXllcnMvb3BlbmxheWVycy9pc3N1ZXMvMjA3NlxuXG4gIHZhciBkZWZhdWx0TWF4Wm9vbSA9IDI4O1xuICB2YXIgZGVmYXVsdFpvb21GYWN0b3IgPSAyO1xuICB2YXIgbWluWm9vbSA9IG9wdGlvbnMubWluWm9vbSAhPT0gdW5kZWZpbmVkID8gb3B0aW9ucy5taW5ab29tIDogREVGQVVMVF9NSU5fWk9PTTtcbiAgdmFyIG1heFpvb20gPSBvcHRpb25zLm1heFpvb20gIT09IHVuZGVmaW5lZCA/IG9wdGlvbnMubWF4Wm9vbSA6IGRlZmF1bHRNYXhab29tO1xuICB2YXIgem9vbUZhY3RvciA9IG9wdGlvbnMuem9vbUZhY3RvciAhPT0gdW5kZWZpbmVkID8gb3B0aW9ucy56b29tRmFjdG9yIDogZGVmYXVsdFpvb21GYWN0b3I7XG4gIHZhciBtdWx0aVdvcmxkID0gb3B0aW9ucy5tdWx0aVdvcmxkICE9PSB1bmRlZmluZWQgPyBvcHRpb25zLm11bHRpV29ybGQgOiBmYWxzZTtcbiAgdmFyIHNtb290aCA9IG9wdGlvbnMuc21vb3RoUmVzb2x1dGlvbkNvbnN0cmFpbnQgIT09IHVuZGVmaW5lZCA/IG9wdGlvbnMuc21vb3RoUmVzb2x1dGlvbkNvbnN0cmFpbnQgOiB0cnVlO1xuICB2YXIgc2hvd0Z1bGxFeHRlbnQgPSBvcHRpb25zLnNob3dGdWxsRXh0ZW50ICE9PSB1bmRlZmluZWQgPyBvcHRpb25zLnNob3dGdWxsRXh0ZW50IDogZmFsc2U7XG4gIHZhciBwcm9qZWN0aW9uID0gY3JlYXRlUHJvamVjdGlvbihvcHRpb25zLnByb2plY3Rpb24sICdFUFNHOjM4NTcnKTtcbiAgdmFyIHByb2pFeHRlbnQgPSBwcm9qZWN0aW9uLmdldEV4dGVudCgpO1xuICB2YXIgY29uc3RyYWluT25seUNlbnRlciA9IG9wdGlvbnMuY29uc3RyYWluT25seUNlbnRlcjtcbiAgdmFyIGV4dGVudCA9IG9wdGlvbnMuZXh0ZW50O1xuXG4gIGlmICghbXVsdGlXb3JsZCAmJiAhZXh0ZW50ICYmIHByb2plY3Rpb24uaXNHbG9iYWwoKSkge1xuICAgIGNvbnN0cmFpbk9ubHlDZW50ZXIgPSBmYWxzZTtcbiAgICBleHRlbnQgPSBwcm9qRXh0ZW50O1xuICB9XG5cbiAgaWYgKG9wdGlvbnMucmVzb2x1dGlvbnMgIT09IHVuZGVmaW5lZCkge1xuICAgIHZhciByZXNvbHV0aW9ucyA9IG9wdGlvbnMucmVzb2x1dGlvbnM7XG4gICAgbWF4UmVzb2x1dGlvbiA9IHJlc29sdXRpb25zW21pblpvb21dO1xuICAgIG1pblJlc29sdXRpb24gPSByZXNvbHV0aW9uc1ttYXhab29tXSAhPT0gdW5kZWZpbmVkID8gcmVzb2x1dGlvbnNbbWF4Wm9vbV0gOiByZXNvbHV0aW9uc1tyZXNvbHV0aW9ucy5sZW5ndGggLSAxXTtcblxuICAgIGlmIChvcHRpb25zLmNvbnN0cmFpblJlc29sdXRpb24pIHtcbiAgICAgIHJlc29sdXRpb25Db25zdHJhaW50ID0gY3JlYXRlU25hcFRvUmVzb2x1dGlvbnMocmVzb2x1dGlvbnMsIHNtb290aCwgIWNvbnN0cmFpbk9ubHlDZW50ZXIgJiYgZXh0ZW50LCBzaG93RnVsbEV4dGVudCk7XG4gICAgfSBlbHNlIHtcbiAgICAgIHJlc29sdXRpb25Db25zdHJhaW50ID0gY3JlYXRlTWluTWF4UmVzb2x1dGlvbihtYXhSZXNvbHV0aW9uLCBtaW5SZXNvbHV0aW9uLCBzbW9vdGgsICFjb25zdHJhaW5Pbmx5Q2VudGVyICYmIGV4dGVudCwgc2hvd0Z1bGxFeHRlbnQpO1xuICAgIH1cbiAgfSBlbHNlIHtcbiAgICAvLyBjYWxjdWxhdGUgdGhlIGRlZmF1bHQgbWluIGFuZCBtYXggcmVzb2x1dGlvblxuICAgIHZhciBzaXplID0gIXByb2pFeHRlbnQgPyAvLyB1c2UgYW4gZXh0ZW50IHRoYXQgY2FuIGZpdCB0aGUgd2hvbGUgd29ybGQgaWYgbmVlZCBiZVxuICAgIDM2MCAqIE1FVEVSU19QRVJfVU5JVFtVbml0cy5ERUdSRUVTXSAvIHByb2plY3Rpb24uZ2V0TWV0ZXJzUGVyVW5pdCgpIDogTWF0aC5tYXgoZ2V0V2lkdGgocHJvakV4dGVudCksIGdldEhlaWdodChwcm9qRXh0ZW50KSk7XG4gICAgdmFyIGRlZmF1bHRNYXhSZXNvbHV0aW9uID0gc2l6ZSAvIERFRkFVTFRfVElMRV9TSVpFIC8gTWF0aC5wb3coZGVmYXVsdFpvb21GYWN0b3IsIERFRkFVTFRfTUlOX1pPT00pO1xuICAgIHZhciBkZWZhdWx0TWluUmVzb2x1dGlvbiA9IGRlZmF1bHRNYXhSZXNvbHV0aW9uIC8gTWF0aC5wb3coZGVmYXVsdFpvb21GYWN0b3IsIGRlZmF1bHRNYXhab29tIC0gREVGQVVMVF9NSU5fWk9PTSk7IC8vIHVzZXIgcHJvdmlkZWQgbWF4UmVzb2x1dGlvbiB0YWtlcyBwcmVjZWRlbmNlXG5cbiAgICBtYXhSZXNvbHV0aW9uID0gb3B0aW9ucy5tYXhSZXNvbHV0aW9uO1xuXG4gICAgaWYgKG1heFJlc29sdXRpb24gIT09IHVuZGVmaW5lZCkge1xuICAgICAgbWluWm9vbSA9IDA7XG4gICAgfSBlbHNlIHtcbiAgICAgIG1heFJlc29sdXRpb24gPSBkZWZhdWx0TWF4UmVzb2x1dGlvbiAvIE1hdGgucG93KHpvb21GYWN0b3IsIG1pblpvb20pO1xuICAgIH0gLy8gdXNlciBwcm92aWRlZCBtaW5SZXNvbHV0aW9uIHRha2VzIHByZWNlZGVuY2VcblxuXG4gICAgbWluUmVzb2x1dGlvbiA9IG9wdGlvbnMubWluUmVzb2x1dGlvbjtcblxuICAgIGlmIChtaW5SZXNvbHV0aW9uID09PSB1bmRlZmluZWQpIHtcbiAgICAgIGlmIChvcHRpb25zLm1heFpvb20gIT09IHVuZGVmaW5lZCkge1xuICAgICAgICBpZiAob3B0aW9ucy5tYXhSZXNvbHV0aW9uICE9PSB1bmRlZmluZWQpIHtcbiAgICAgICAgICBtaW5SZXNvbHV0aW9uID0gbWF4UmVzb2x1dGlvbiAvIE1hdGgucG93KHpvb21GYWN0b3IsIG1heFpvb20pO1xuICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgIG1pblJlc29sdXRpb24gPSBkZWZhdWx0TWF4UmVzb2x1dGlvbiAvIE1hdGgucG93KHpvb21GYWN0b3IsIG1heFpvb20pO1xuICAgICAgICB9XG4gICAgICB9IGVsc2Uge1xuICAgICAgICBtaW5SZXNvbHV0aW9uID0gZGVmYXVsdE1pblJlc29sdXRpb247XG4gICAgICB9XG4gICAgfSAvLyBnaXZlbiBkaXNjcmV0ZSB6b29tIGxldmVscywgbWluUmVzb2x1dGlvbiBtYXkgYmUgZGlmZmVyZW50IHRoYW4gcHJvdmlkZWRcblxuXG4gICAgbWF4Wm9vbSA9IG1pblpvb20gKyBNYXRoLmZsb29yKE1hdGgubG9nKG1heFJlc29sdXRpb24gLyBtaW5SZXNvbHV0aW9uKSAvIE1hdGgubG9nKHpvb21GYWN0b3IpKTtcbiAgICBtaW5SZXNvbHV0aW9uID0gbWF4UmVzb2x1dGlvbiAvIE1hdGgucG93KHpvb21GYWN0b3IsIG1heFpvb20gLSBtaW5ab29tKTtcblxuICAgIGlmIChvcHRpb25zLmNvbnN0cmFpblJlc29sdXRpb24pIHtcbiAgICAgIHJlc29sdXRpb25Db25zdHJhaW50ID0gY3JlYXRlU25hcFRvUG93ZXIoem9vbUZhY3RvciwgbWF4UmVzb2x1dGlvbiwgbWluUmVzb2x1dGlvbiwgc21vb3RoLCAhY29uc3RyYWluT25seUNlbnRlciAmJiBleHRlbnQsIHNob3dGdWxsRXh0ZW50KTtcbiAgICB9IGVsc2Uge1xuICAgICAgcmVzb2x1dGlvbkNvbnN0cmFpbnQgPSBjcmVhdGVNaW5NYXhSZXNvbHV0aW9uKG1heFJlc29sdXRpb24sIG1pblJlc29sdXRpb24sIHNtb290aCwgIWNvbnN0cmFpbk9ubHlDZW50ZXIgJiYgZXh0ZW50LCBzaG93RnVsbEV4dGVudCk7XG4gICAgfVxuICB9XG5cbiAgcmV0dXJuIHtcbiAgICBjb25zdHJhaW50OiByZXNvbHV0aW9uQ29uc3RyYWludCxcbiAgICBtYXhSZXNvbHV0aW9uOiBtYXhSZXNvbHV0aW9uLFxuICAgIG1pblJlc29sdXRpb246IG1pblJlc29sdXRpb24sXG4gICAgbWluWm9vbTogbWluWm9vbSxcbiAgICB6b29tRmFjdG9yOiB6b29tRmFjdG9yXG4gIH07XG59XG4vKipcbiAqIEBwYXJhbSB7Vmlld09wdGlvbnN9IG9wdGlvbnMgVmlldyBvcHRpb25zLlxuICogQHJldHVybiB7aW1wb3J0KFwiLi9yb3RhdGlvbmNvbnN0cmFpbnQuanNcIikuVHlwZX0gUm90YXRpb24gY29uc3RyYWludC5cbiAqL1xuXG5leHBvcnQgZnVuY3Rpb24gY3JlYXRlUm90YXRpb25Db25zdHJhaW50KG9wdGlvbnMpIHtcbiAgdmFyIGVuYWJsZVJvdGF0aW9uID0gb3B0aW9ucy5lbmFibGVSb3RhdGlvbiAhPT0gdW5kZWZpbmVkID8gb3B0aW9ucy5lbmFibGVSb3RhdGlvbiA6IHRydWU7XG5cbiAgaWYgKGVuYWJsZVJvdGF0aW9uKSB7XG4gICAgdmFyIGNvbnN0cmFpblJvdGF0aW9uID0gb3B0aW9ucy5jb25zdHJhaW5Sb3RhdGlvbjtcblxuICAgIGlmIChjb25zdHJhaW5Sb3RhdGlvbiA9PT0gdW5kZWZpbmVkIHx8IGNvbnN0cmFpblJvdGF0aW9uID09PSB0cnVlKSB7XG4gICAgICByZXR1cm4gY3JlYXRlU25hcFRvWmVybygpO1xuICAgIH0gZWxzZSBpZiAoY29uc3RyYWluUm90YXRpb24gPT09IGZhbHNlKSB7XG4gICAgICByZXR1cm4gcm90YXRpb25Ob25lO1xuICAgIH0gZWxzZSBpZiAodHlwZW9mIGNvbnN0cmFpblJvdGF0aW9uID09PSAnbnVtYmVyJykge1xuICAgICAgcmV0dXJuIGNyZWF0ZVNuYXBUb04oY29uc3RyYWluUm90YXRpb24pO1xuICAgIH0gZWxzZSB7XG4gICAgICByZXR1cm4gcm90YXRpb25Ob25lO1xuICAgIH1cbiAgfSBlbHNlIHtcbiAgICByZXR1cm4gZGlzYWJsZTtcbiAgfVxufVxuLyoqXG4gKiBEZXRlcm1pbmUgaWYgYW4gYW5pbWF0aW9uIGludm9sdmVzIG5vIHZpZXcgY2hhbmdlLlxuICogQHBhcmFtIHtBbmltYXRpb259IGFuaW1hdGlvbiBUaGUgYW5pbWF0aW9uLlxuICogQHJldHVybiB7Ym9vbGVhbn0gVGhlIGFuaW1hdGlvbiBpbnZvbHZlcyBubyB2aWV3IGNoYW5nZS5cbiAqL1xuXG5leHBvcnQgZnVuY3Rpb24gaXNOb29wQW5pbWF0aW9uKGFuaW1hdGlvbikge1xuICBpZiAoYW5pbWF0aW9uLnNvdXJjZUNlbnRlciAmJiBhbmltYXRpb24udGFyZ2V0Q2VudGVyKSB7XG4gICAgaWYgKCFjb29yZGluYXRlc0VxdWFsKGFuaW1hdGlvbi5zb3VyY2VDZW50ZXIsIGFuaW1hdGlvbi50YXJnZXRDZW50ZXIpKSB7XG4gICAgICByZXR1cm4gZmFsc2U7XG4gICAgfVxuICB9XG5cbiAgaWYgKGFuaW1hdGlvbi5zb3VyY2VSZXNvbHV0aW9uICE9PSBhbmltYXRpb24udGFyZ2V0UmVzb2x1dGlvbikge1xuICAgIHJldHVybiBmYWxzZTtcbiAgfVxuXG4gIGlmIChhbmltYXRpb24uc291cmNlUm90YXRpb24gIT09IGFuaW1hdGlvbi50YXJnZXRSb3RhdGlvbikge1xuICAgIHJldHVybiBmYWxzZTtcbiAgfVxuXG4gIHJldHVybiB0cnVlO1xufVxuLyoqXG4gKiBAcGFyYW0ge2ltcG9ydChcIi4vY29vcmRpbmF0ZS5qc1wiKS5Db29yZGluYXRlfSBjb29yZGluYXRlIENvb3JkaW5hdGUuXG4gKiBAcGFyYW0ge2ltcG9ydChcIi4vc2l6ZS5qc1wiKS5TaXplfSBzaXplIEJveCBwaXhlbCBzaXplLlxuICogQHBhcmFtIHtpbXBvcnQoXCIuL3BpeGVsLmpzXCIpLlBpeGVsfSBwb3NpdGlvbiBQb3NpdGlvbiBvbiB0aGUgdmlldyB0byBjZW50ZXIgb24uXG4gKiBAcGFyYW0ge251bWJlcn0gcmVzb2x1dGlvbiBSZXNvbHV0aW9uLlxuICogQHBhcmFtIHtudW1iZXJ9IHJvdGF0aW9uIFJvdGF0aW9uLlxuICogQHJldHVybiB7aW1wb3J0KFwiLi9jb29yZGluYXRlLmpzXCIpLkNvb3JkaW5hdGV9IFNoaWZ0ZWQgY2VudGVyLlxuICovXG5cbmZ1bmN0aW9uIGNhbGN1bGF0ZUNlbnRlck9uKGNvb3JkaW5hdGUsIHNpemUsIHBvc2l0aW9uLCByZXNvbHV0aW9uLCByb3RhdGlvbikge1xuICAvLyBjYWxjdWxhdGUgcm90YXRlZCBwb3NpdGlvblxuICB2YXIgY29zQW5nbGUgPSBNYXRoLmNvcygtcm90YXRpb24pO1xuICB2YXIgc2luQW5nbGUgPSBNYXRoLnNpbigtcm90YXRpb24pO1xuICB2YXIgcm90WCA9IGNvb3JkaW5hdGVbMF0gKiBjb3NBbmdsZSAtIGNvb3JkaW5hdGVbMV0gKiBzaW5BbmdsZTtcbiAgdmFyIHJvdFkgPSBjb29yZGluYXRlWzFdICogY29zQW5nbGUgKyBjb29yZGluYXRlWzBdICogc2luQW5nbGU7XG4gIHJvdFggKz0gKHNpemVbMF0gLyAyIC0gcG9zaXRpb25bMF0pICogcmVzb2x1dGlvbjtcbiAgcm90WSArPSAocG9zaXRpb25bMV0gLSBzaXplWzFdIC8gMikgKiByZXNvbHV0aW9uOyAvLyBnbyBiYWNrIHRvIG9yaWdpbmFsIGFuZ2xlXG5cbiAgc2luQW5nbGUgPSAtc2luQW5nbGU7IC8vIGdvIGJhY2sgdG8gb3JpZ2luYWwgcm90YXRpb25cblxuICB2YXIgY2VudGVyWCA9IHJvdFggKiBjb3NBbmdsZSAtIHJvdFkgKiBzaW5BbmdsZTtcbiAgdmFyIGNlbnRlclkgPSByb3RZICogY29zQW5nbGUgKyByb3RYICogc2luQW5nbGU7XG4gIHJldHVybiBbY2VudGVyWCwgY2VudGVyWV07XG59XG5cbmV4cG9ydCBkZWZhdWx0IFZpZXc7IiwiLyoqXG4gKiBAbW9kdWxlIG9sL3NpemVcbiAqL1xuXG4vKipcbiAqIEFuIGFycmF5IG9mIG51bWJlcnMgcmVwcmVzZW50aW5nIGEgc2l6ZTogYFt3aWR0aCwgaGVpZ2h0XWAuXG4gKiBAdHlwZWRlZiB7QXJyYXk8bnVtYmVyPn0gU2l6ZVxuICogQGFwaVxuICovXG5cbi8qKlxuICogUmV0dXJucyBhIGJ1ZmZlcmVkIHNpemUuXG4gKiBAcGFyYW0ge1NpemV9IHNpemUgU2l6ZS5cbiAqIEBwYXJhbSB7bnVtYmVyfSBudW0gVGhlIGFtb3VudCBieSB3aGljaCB0byBidWZmZXIuXG4gKiBAcGFyYW0ge1NpemU9fSBvcHRfc2l6ZSBPcHRpb25hbCByZXVzYWJsZSBzaXplIGFycmF5LlxuICogQHJldHVybiB7U2l6ZX0gVGhlIGJ1ZmZlcmVkIHNpemUuXG4gKi9cbmV4cG9ydCBmdW5jdGlvbiBidWZmZXIoc2l6ZSwgbnVtLCBvcHRfc2l6ZSkge1xuICBpZiAob3B0X3NpemUgPT09IHVuZGVmaW5lZCkge1xuICAgIG9wdF9zaXplID0gWzAsIDBdO1xuICB9XG5cbiAgb3B0X3NpemVbMF0gPSBzaXplWzBdICsgMiAqIG51bTtcbiAgb3B0X3NpemVbMV0gPSBzaXplWzFdICsgMiAqIG51bTtcbiAgcmV0dXJuIG9wdF9zaXplO1xufVxuLyoqXG4gKiBEZXRlcm1pbmVzIGlmIGEgc2l6ZSBoYXMgYSBwb3NpdGl2ZSBhcmVhLlxuICogQHBhcmFtIHtTaXplfSBzaXplIFRoZSBzaXplIHRvIHRlc3QuXG4gKiBAcmV0dXJuIHtib29sZWFufSBUaGUgc2l6ZSBoYXMgYSBwb3NpdGl2ZSBhcmVhLlxuICovXG5cbmV4cG9ydCBmdW5jdGlvbiBoYXNBcmVhKHNpemUpIHtcbiAgcmV0dXJuIHNpemVbMF0gPiAwICYmIHNpemVbMV0gPiAwO1xufVxuLyoqXG4gKiBSZXR1cm5zIGEgc2l6ZSBzY2FsZWQgYnkgYSByYXRpby4gVGhlIHJlc3VsdCB3aWxsIGJlIGFuIGFycmF5IG9mIGludGVnZXJzLlxuICogQHBhcmFtIHtTaXplfSBzaXplIFNpemUuXG4gKiBAcGFyYW0ge251bWJlcn0gcmF0aW8gUmF0aW8uXG4gKiBAcGFyYW0ge1NpemU9fSBvcHRfc2l6ZSBPcHRpb25hbCByZXVzYWJsZSBzaXplIGFycmF5LlxuICogQHJldHVybiB7U2l6ZX0gVGhlIHNjYWxlZCBzaXplLlxuICovXG5cbmV4cG9ydCBmdW5jdGlvbiBzY2FsZShzaXplLCByYXRpbywgb3B0X3NpemUpIHtcbiAgaWYgKG9wdF9zaXplID09PSB1bmRlZmluZWQpIHtcbiAgICBvcHRfc2l6ZSA9IFswLCAwXTtcbiAgfVxuXG4gIG9wdF9zaXplWzBdID0gc2l6ZVswXSAqIHJhdGlvICsgMC41IHwgMDtcbiAgb3B0X3NpemVbMV0gPSBzaXplWzFdICogcmF0aW8gKyAwLjUgfCAwO1xuICByZXR1cm4gb3B0X3NpemU7XG59XG4vKipcbiAqIFJldHVybnMgYW4gYFNpemVgIGFycmF5IGZvciB0aGUgcGFzc2VkIGluIG51bWJlciAobWVhbmluZzogc3F1YXJlKSBvclxuICogYFNpemVgIGFycmF5LlxuICogKG1lYW5pbmc6IG5vbi1zcXVhcmUpLFxuICogQHBhcmFtIHtudW1iZXJ8U2l6ZX0gc2l6ZSBXaWR0aCBhbmQgaGVpZ2h0LlxuICogQHBhcmFtIHtTaXplPX0gb3B0X3NpemUgT3B0aW9uYWwgcmV1c2FibGUgc2l6ZSBhcnJheS5cbiAqIEByZXR1cm4ge1NpemV9IFNpemUuXG4gKiBAYXBpXG4gKi9cblxuZXhwb3J0IGZ1bmN0aW9uIHRvU2l6ZShzaXplLCBvcHRfc2l6ZSkge1xuICBpZiAoQXJyYXkuaXNBcnJheShzaXplKSkge1xuICAgIHJldHVybiBzaXplO1xuICB9IGVsc2Uge1xuICAgIGlmIChvcHRfc2l6ZSA9PT0gdW5kZWZpbmVkKSB7XG4gICAgICBvcHRfc2l6ZSA9IFtzaXplLCBzaXplXTtcbiAgICB9IGVsc2Uge1xuICAgICAgb3B0X3NpemVbMF0gPSBzaXplO1xuICAgICAgb3B0X3NpemVbMV0gPSBzaXplO1xuICAgIH1cblxuICAgIHJldHVybiBvcHRfc2l6ZTtcbiAgfVxufSIsInZhciBfX2V4dGVuZHMgPSB0aGlzICYmIHRoaXMuX19leHRlbmRzIHx8IGZ1bmN0aW9uICgpIHtcbiAgdmFyIF9leHRlbmRTdGF0aWNzID0gZnVuY3Rpb24gZXh0ZW5kU3RhdGljcyhkLCBiKSB7XG4gICAgX2V4dGVuZFN0YXRpY3MgPSBPYmplY3Quc2V0UHJvdG90eXBlT2YgfHwge1xuICAgICAgX19wcm90b19fOiBbXVxuICAgIH0gaW5zdGFuY2VvZiBBcnJheSAmJiBmdW5jdGlvbiAoZCwgYikge1xuICAgICAgZC5fX3Byb3RvX18gPSBiO1xuICAgIH0gfHwgZnVuY3Rpb24gKGQsIGIpIHtcbiAgICAgIGZvciAodmFyIHAgaW4gYikge1xuICAgICAgICBpZiAoT2JqZWN0LnByb3RvdHlwZS5oYXNPd25Qcm9wZXJ0eS5jYWxsKGIsIHApKSBkW3BdID0gYltwXTtcbiAgICAgIH1cbiAgICB9O1xuXG4gICAgcmV0dXJuIF9leHRlbmRTdGF0aWNzKGQsIGIpO1xuICB9O1xuXG4gIHJldHVybiBmdW5jdGlvbiAoZCwgYikge1xuICAgIF9leHRlbmRTdGF0aWNzKGQsIGIpO1xuXG4gICAgZnVuY3Rpb24gX18oKSB7XG4gICAgICB0aGlzLmNvbnN0cnVjdG9yID0gZDtcbiAgICB9XG5cbiAgICBkLnByb3RvdHlwZSA9IGIgPT09IG51bGwgPyBPYmplY3QuY3JlYXRlKGIpIDogKF9fLnByb3RvdHlwZSA9IGIucHJvdG90eXBlLCBuZXcgX18oKSk7XG4gIH07XG59KCk7XG4vKipcbiAqIEBtb2R1bGUgb2wvUGx1Z2dhYmxlTWFwXG4gKi9cblxuXG5pbXBvcnQgQmFzZU9iamVjdCwgeyBnZXRDaGFuZ2VFdmVudFR5cGUgfSBmcm9tICcuL09iamVjdC5qcyc7XG5pbXBvcnQgQ29sbGVjdGlvbiBmcm9tICcuL0NvbGxlY3Rpb24uanMnO1xuaW1wb3J0IENvbGxlY3Rpb25FdmVudFR5cGUgZnJvbSAnLi9Db2xsZWN0aW9uRXZlbnRUeXBlLmpzJztcbmltcG9ydCBFdmVudFR5cGUgZnJvbSAnLi9ldmVudHMvRXZlbnRUeXBlLmpzJztcbmltcG9ydCBMYXllckdyb3VwIGZyb20gJy4vbGF5ZXIvR3JvdXAuanMnO1xuaW1wb3J0IE1hcEJyb3dzZXJFdmVudCBmcm9tICcuL01hcEJyb3dzZXJFdmVudC5qcyc7XG5pbXBvcnQgTWFwQnJvd3NlckV2ZW50SGFuZGxlciBmcm9tICcuL01hcEJyb3dzZXJFdmVudEhhbmRsZXIuanMnO1xuaW1wb3J0IE1hcEJyb3dzZXJFdmVudFR5cGUgZnJvbSAnLi9NYXBCcm93c2VyRXZlbnRUeXBlLmpzJztcbmltcG9ydCBNYXBFdmVudCBmcm9tICcuL01hcEV2ZW50LmpzJztcbmltcG9ydCBNYXBFdmVudFR5cGUgZnJvbSAnLi9NYXBFdmVudFR5cGUuanMnO1xuaW1wb3J0IE1hcFByb3BlcnR5IGZyb20gJy4vTWFwUHJvcGVydHkuanMnO1xuaW1wb3J0IE9iamVjdEV2ZW50VHlwZSBmcm9tICcuL09iamVjdEV2ZW50VHlwZS5qcyc7XG5pbXBvcnQgUG9pbnRlckV2ZW50VHlwZSBmcm9tICcuL3BvaW50ZXIvRXZlbnRUeXBlLmpzJztcbmltcG9ydCBSZW5kZXJFdmVudFR5cGUgZnJvbSAnLi9yZW5kZXIvRXZlbnRUeXBlLmpzJztcbmltcG9ydCBUaWxlUXVldWUsIHsgZ2V0VGlsZVByaW9yaXR5IH0gZnJvbSAnLi9UaWxlUXVldWUuanMnO1xuaW1wb3J0IFZpZXcgZnJvbSAnLi9WaWV3LmpzJztcbmltcG9ydCBWaWV3SGludCBmcm9tICcuL1ZpZXdIaW50LmpzJztcbmltcG9ydCB7IERFVklDRV9QSVhFTF9SQVRJTywgSU1BR0VfREVDT0RFLCBQQVNTSVZFX0VWRU5UX0xJU1RFTkVSUyB9IGZyb20gJy4vaGFzLmpzJztcbmltcG9ydCB7IFRSVUUgfSBmcm9tICcuL2Z1bmN0aW9ucy5qcyc7XG5pbXBvcnQgeyBhcHBseSBhcyBhcHBseVRyYW5zZm9ybSwgY3JlYXRlIGFzIGNyZWF0ZVRyYW5zZm9ybSB9IGZyb20gJy4vdHJhbnNmb3JtLmpzJztcbmltcG9ydCB7IGFzc2VydCB9IGZyb20gJy4vYXNzZXJ0cy5qcyc7XG5pbXBvcnQgeyBjbG9uZSwgY3JlYXRlT3JVcGRhdGVFbXB0eSwgZXF1YWxzLCBnZXRGb3JWaWV3QW5kU2l6ZSwgaXNFbXB0eSB9IGZyb20gJy4vZXh0ZW50LmpzJztcbmltcG9ydCB7IGZyb21Vc2VyQ29vcmRpbmF0ZSwgdG9Vc2VyQ29vcmRpbmF0ZSB9IGZyb20gJy4vcHJvai5qcyc7XG5pbXBvcnQgeyBoYXNBcmVhIH0gZnJvbSAnLi9zaXplLmpzJztcbmltcG9ydCB7IGxpc3RlbiwgdW5saXN0ZW5CeUtleSB9IGZyb20gJy4vZXZlbnRzLmpzJztcbmltcG9ydCB7IHJlbW92ZU5vZGUgfSBmcm9tICcuL2RvbS5qcyc7XG4vKipcbiAqIFN0YXRlIG9mIHRoZSBjdXJyZW50IGZyYW1lLiBPbmx5IGBwaXhlbFJhdGlvYCwgYHRpbWVgIGFuZCBgdmlld1N0YXRlYCBzaG91bGRcbiAqIGJlIHVzZWQgaW4gYXBwbGljYXRpb25zLlxuICogQHR5cGVkZWYge09iamVjdH0gRnJhbWVTdGF0ZVxuICogQHByb3BlcnR5IHtudW1iZXJ9IHBpeGVsUmF0aW8gVGhlIHBpeGVsIHJhdGlvIG9mIHRoZSBmcmFtZS5cbiAqIEBwcm9wZXJ0eSB7bnVtYmVyfSB0aW1lIFRoZSB0aW1lIHdoZW4gcmVuZGVyaW5nIG9mIHRoZSBmcmFtZSB3YXMgcmVxdWVzdGVkLlxuICogQHByb3BlcnR5IHtpbXBvcnQoXCIuL1ZpZXcuanNcIikuU3RhdGV9IHZpZXdTdGF0ZSBUaGUgc3RhdGUgb2YgdGhlIGN1cnJlbnQgdmlldy5cbiAqIEBwcm9wZXJ0eSB7Ym9vbGVhbn0gYW5pbWF0ZVxuICogQHByb3BlcnR5IHtpbXBvcnQoXCIuL3RyYW5zZm9ybS5qc1wiKS5UcmFuc2Zvcm19IGNvb3JkaW5hdGVUb1BpeGVsVHJhbnNmb3JtXG4gKiBAcHJvcGVydHkge2ltcG9ydChcInJidXNoXCIpLmRlZmF1bHR9IGRlY2x1dHRlclRyZWVcbiAqIEBwcm9wZXJ0eSB7bnVsbHxpbXBvcnQoXCIuL2V4dGVudC5qc1wiKS5FeHRlbnR9IGV4dGVudFxuICogQHByb3BlcnR5IHtudW1iZXJ9IGluZGV4XG4gKiBAcHJvcGVydHkge0FycmF5PGltcG9ydChcIi4vbGF5ZXIvTGF5ZXIuanNcIikuU3RhdGU+fSBsYXllclN0YXRlc0FycmF5XG4gKiBAcHJvcGVydHkge251bWJlcn0gbGF5ZXJJbmRleFxuICogQHByb3BlcnR5IHtpbXBvcnQoXCIuL3RyYW5zZm9ybS5qc1wiKS5UcmFuc2Zvcm19IHBpeGVsVG9Db29yZGluYXRlVHJhbnNmb3JtXG4gKiBAcHJvcGVydHkge0FycmF5PFBvc3RSZW5kZXJGdW5jdGlvbj59IHBvc3RSZW5kZXJGdW5jdGlvbnNcbiAqIEBwcm9wZXJ0eSB7aW1wb3J0KFwiLi9zaXplLmpzXCIpLlNpemV9IHNpemVcbiAqIEBwcm9wZXJ0eSB7VGlsZVF1ZXVlfSB0aWxlUXVldWVcbiAqIEBwcm9wZXJ0eSB7IU9iamVjdDxzdHJpbmcsIE9iamVjdDxzdHJpbmcsIGJvb2xlYW4+Pn0gdXNlZFRpbGVzXG4gKiBAcHJvcGVydHkge0FycmF5PG51bWJlcj59IHZpZXdIaW50c1xuICogQHByb3BlcnR5IHshT2JqZWN0PHN0cmluZywgT2JqZWN0PHN0cmluZywgYm9vbGVhbj4+fSB3YW50ZWRUaWxlc1xuICovXG5cbi8qKlxuICogQHR5cGVkZWYge2Z1bmN0aW9uKFBsdWdnYWJsZU1hcCwgP0ZyYW1lU3RhdGUpOiBhbnl9IFBvc3RSZW5kZXJGdW5jdGlvblxuICovXG5cbi8qKlxuICogQHR5cGVkZWYge09iamVjdH0gQXRQaXhlbE9wdGlvbnNcbiAqIEBwcm9wZXJ0eSB7dW5kZWZpbmVkfGZ1bmN0aW9uKGltcG9ydChcIi4vbGF5ZXIvTGF5ZXIuanNcIikuZGVmYXVsdCk6IGJvb2xlYW59IFtsYXllckZpbHRlcl0gTGF5ZXIgZmlsdGVyXG4gKiBmdW5jdGlvbi4gVGhlIGZpbHRlciBmdW5jdGlvbiB3aWxsIHJlY2VpdmUgb25lIGFyZ3VtZW50LCB0aGVcbiAqIHtAbGluayBtb2R1bGU6b2wvbGF5ZXIvTGF5ZXIgbGF5ZXItY2FuZGlkYXRlfSBhbmQgaXQgc2hvdWxkIHJldHVybiBhIGJvb2xlYW4gdmFsdWUuXG4gKiBPbmx5IGxheWVycyB3aGljaCBhcmUgdmlzaWJsZSBhbmQgZm9yIHdoaWNoIHRoaXMgZnVuY3Rpb24gcmV0dXJucyBgdHJ1ZWBcbiAqIHdpbGwgYmUgdGVzdGVkIGZvciBmZWF0dXJlcy4gQnkgZGVmYXVsdCwgYWxsIHZpc2libGUgbGF5ZXJzIHdpbGwgYmUgdGVzdGVkLlxuICogQHByb3BlcnR5IHtudW1iZXJ9IFtoaXRUb2xlcmFuY2U9MF0gSGl0LWRldGVjdGlvbiB0b2xlcmFuY2UgaW4gY3NzIHBpeGVscy4gUGl4ZWxzXG4gKiBpbnNpZGUgdGhlIHJhZGl1cyBhcm91bmQgdGhlIGdpdmVuIHBvc2l0aW9uIHdpbGwgYmUgY2hlY2tlZCBmb3IgZmVhdHVyZXMuXG4gKiBAcHJvcGVydHkge2Jvb2xlYW59IFtjaGVja1dyYXBwZWQ9dHJ1ZV0gQ2hlY2stV3JhcHBlZCBXaWxsIGNoZWNrIGZvciBmb3Igd3JhcHBlZCBnZW9tZXRyaWVzIGluc2lkZSB0aGUgcmFuZ2Ugb2ZcbiAqICAgKy8tIDEgd29ybGQgd2lkdGguIFdvcmtzIG9ubHkgaWYgYSBwcm9qZWN0aW9uIGlzIHVzZWQgdGhhdCBjYW4gYmUgd3JhcHBlZC5cbiAqL1xuXG4vKipcbiAqIEB0eXBlZGVmIHtPYmplY3R9IE1hcE9wdGlvbnNJbnRlcm5hbFxuICogQHByb3BlcnR5IHtDb2xsZWN0aW9uPGltcG9ydChcIi4vY29udHJvbC9Db250cm9sLmpzXCIpLmRlZmF1bHQ+fSBbY29udHJvbHNdXG4gKiBAcHJvcGVydHkge0NvbGxlY3Rpb248aW1wb3J0KFwiLi9pbnRlcmFjdGlvbi9JbnRlcmFjdGlvbi5qc1wiKS5kZWZhdWx0Pn0gW2ludGVyYWN0aW9uc11cbiAqIEBwcm9wZXJ0eSB7SFRNTEVsZW1lbnR8RG9jdW1lbnR9IGtleWJvYXJkRXZlbnRUYXJnZXRcbiAqIEBwcm9wZXJ0eSB7Q29sbGVjdGlvbjxpbXBvcnQoXCIuL092ZXJsYXkuanNcIikuZGVmYXVsdD59IG92ZXJsYXlzXG4gKiBAcHJvcGVydHkge09iamVjdDxzdHJpbmcsICo+fSB2YWx1ZXNcbiAqL1xuXG4vKipcbiAqIE9iamVjdCBsaXRlcmFsIHdpdGggY29uZmlnIG9wdGlvbnMgZm9yIHRoZSBtYXAuXG4gKiBAdHlwZWRlZiB7T2JqZWN0fSBNYXBPcHRpb25zXG4gKiBAcHJvcGVydHkge0NvbGxlY3Rpb248aW1wb3J0KFwiLi9jb250cm9sL0NvbnRyb2wuanNcIikuZGVmYXVsdD58QXJyYXk8aW1wb3J0KFwiLi9jb250cm9sL0NvbnRyb2wuanNcIikuZGVmYXVsdD59IFtjb250cm9sc11cbiAqIENvbnRyb2xzIGluaXRpYWxseSBhZGRlZCB0byB0aGUgbWFwLiBJZiBub3Qgc3BlY2lmaWVkLFxuICoge0BsaW5rIG1vZHVsZTpvbC9jb250cm9sfmRlZmF1bHRzfSBpcyB1c2VkLlxuICogQHByb3BlcnR5IHtudW1iZXJ9IFtwaXhlbFJhdGlvPXdpbmRvdy5kZXZpY2VQaXhlbFJhdGlvXSBUaGUgcmF0aW8gYmV0d2VlblxuICogcGh5c2ljYWwgcGl4ZWxzIGFuZCBkZXZpY2UtaW5kZXBlbmRlbnQgcGl4ZWxzIChkaXBzKSBvbiB0aGUgZGV2aWNlLlxuICogQHByb3BlcnR5IHtDb2xsZWN0aW9uPGltcG9ydChcIi4vaW50ZXJhY3Rpb24vSW50ZXJhY3Rpb24uanNcIikuZGVmYXVsdD58QXJyYXk8aW1wb3J0KFwiLi9pbnRlcmFjdGlvbi9JbnRlcmFjdGlvbi5qc1wiKS5kZWZhdWx0Pn0gW2ludGVyYWN0aW9uc11cbiAqIEludGVyYWN0aW9ucyB0aGF0IGFyZSBpbml0aWFsbHkgYWRkZWQgdG8gdGhlIG1hcC4gSWYgbm90IHNwZWNpZmllZCxcbiAqIHtAbGluayBtb2R1bGU6b2wvaW50ZXJhY3Rpb25+ZGVmYXVsdHN9IGlzIHVzZWQuXG4gKiBAcHJvcGVydHkge0hUTUxFbGVtZW50fERvY3VtZW50fHN0cmluZ30gW2tleWJvYXJkRXZlbnRUYXJnZXRdIFRoZSBlbGVtZW50IHRvXG4gKiBsaXN0ZW4gdG8ga2V5Ym9hcmQgZXZlbnRzIG9uLiBUaGlzIGRldGVybWluZXMgd2hlbiB0aGUgYEtleWJvYXJkUGFuYCBhbmRcbiAqIGBLZXlib2FyZFpvb21gIGludGVyYWN0aW9ucyB0cmlnZ2VyLiBGb3IgZXhhbXBsZSwgaWYgdGhpcyBvcHRpb24gaXMgc2V0IHRvXG4gKiBgZG9jdW1lbnRgIHRoZSBrZXlib2FyZCBpbnRlcmFjdGlvbnMgd2lsbCBhbHdheXMgdHJpZ2dlci4gSWYgdGhpcyBvcHRpb24gaXNcbiAqIG5vdCBzcGVjaWZpZWQsIHRoZSBlbGVtZW50IHRoZSBsaWJyYXJ5IGxpc3RlbnMgdG8ga2V5Ym9hcmQgZXZlbnRzIG9uIGlzIHRoZVxuICogbWFwIHRhcmdldCAoaS5lLiB0aGUgdXNlci1wcm92aWRlZCBkaXYgZm9yIHRoZSBtYXApLiBJZiB0aGlzIGlzIG5vdFxuICogYGRvY3VtZW50YCwgdGhlIHRhcmdldCBlbGVtZW50IG5lZWRzIHRvIGJlIGZvY3VzZWQgZm9yIGtleSBldmVudHMgdG8gYmVcbiAqIGVtaXR0ZWQsIHJlcXVpcmluZyB0aGF0IHRoZSB0YXJnZXQgZWxlbWVudCBoYXMgYSBgdGFiaW5kZXhgIGF0dHJpYnV0ZS5cbiAqIEBwcm9wZXJ0eSB7QXJyYXk8aW1wb3J0KFwiLi9sYXllci9CYXNlLmpzXCIpLmRlZmF1bHQ+fENvbGxlY3Rpb248aW1wb3J0KFwiLi9sYXllci9CYXNlLmpzXCIpLmRlZmF1bHQ+fExheWVyR3JvdXB9IFtsYXllcnNdXG4gKiBMYXllcnMuIElmIHRoaXMgaXMgbm90IGRlZmluZWQsIGEgbWFwIHdpdGggbm8gbGF5ZXJzIHdpbGwgYmUgcmVuZGVyZWQuIE5vdGVcbiAqIHRoYXQgbGF5ZXJzIGFyZSByZW5kZXJlZCBpbiB0aGUgb3JkZXIgc3VwcGxpZWQsIHNvIGlmIHlvdSB3YW50LCBmb3IgZXhhbXBsZSxcbiAqIGEgdmVjdG9yIGxheWVyIHRvIGFwcGVhciBvbiB0b3Agb2YgYSB0aWxlIGxheWVyLCBpdCBtdXN0IGNvbWUgYWZ0ZXIgdGhlIHRpbGVcbiAqIGxheWVyLlxuICogQHByb3BlcnR5IHtudW1iZXJ9IFttYXhUaWxlc0xvYWRpbmc9MTZdIE1heGltdW0gbnVtYmVyIHRpbGVzIHRvIGxvYWRcbiAqIHNpbXVsdGFuZW91c2x5LlxuICogQHByb3BlcnR5IHtudW1iZXJ9IFttb3ZlVG9sZXJhbmNlPTFdIFRoZSBtaW5pbXVtIGRpc3RhbmNlIGluIHBpeGVscyB0aGVcbiAqIGN1cnNvciBtdXN0IG1vdmUgdG8gYmUgZGV0ZWN0ZWQgYXMgYSBtYXAgbW92ZSBldmVudCBpbnN0ZWFkIG9mIGEgY2xpY2suXG4gKiBJbmNyZWFzaW5nIHRoaXMgdmFsdWUgY2FuIG1ha2UgaXQgZWFzaWVyIHRvIGNsaWNrIG9uIHRoZSBtYXAuXG4gKiBAcHJvcGVydHkge0NvbGxlY3Rpb248aW1wb3J0KFwiLi9PdmVybGF5LmpzXCIpLmRlZmF1bHQ+fEFycmF5PGltcG9ydChcIi4vT3ZlcmxheS5qc1wiKS5kZWZhdWx0Pn0gW292ZXJsYXlzXVxuICogT3ZlcmxheXMgaW5pdGlhbGx5IGFkZGVkIHRvIHRoZSBtYXAuIEJ5IGRlZmF1bHQsIG5vIG92ZXJsYXlzIGFyZSBhZGRlZC5cbiAqIEBwcm9wZXJ0eSB7SFRNTEVsZW1lbnR8c3RyaW5nfSBbdGFyZ2V0XSBUaGUgY29udGFpbmVyIGZvciB0aGUgbWFwLCBlaXRoZXIgdGhlXG4gKiBlbGVtZW50IGl0c2VsZiBvciB0aGUgYGlkYCBvZiB0aGUgZWxlbWVudC4gSWYgbm90IHNwZWNpZmllZCBhdCBjb25zdHJ1Y3Rpb25cbiAqIHRpbWUsIHtAbGluayBtb2R1bGU6b2wvTWFwfk1hcCNzZXRUYXJnZXR9IG11c3QgYmUgY2FsbGVkIGZvciB0aGUgbWFwIHRvIGJlXG4gKiByZW5kZXJlZC4gSWYgcGFzc2VkIGJ5IGVsZW1lbnQsIHRoZSBjb250YWluZXIgY2FuIGJlIGluIGEgc2Vjb25kYXJ5IGRvY3VtZW50LlxuICogQHByb3BlcnR5IHtWaWV3fSBbdmlld10gVGhlIG1hcCdzIHZpZXcuICBObyBsYXllciBzb3VyY2VzIHdpbGwgYmVcbiAqIGZldGNoZWQgdW5sZXNzIHRoaXMgaXMgc3BlY2lmaWVkIGF0IGNvbnN0cnVjdGlvbiB0aW1lIG9yIHRocm91Z2hcbiAqIHtAbGluayBtb2R1bGU6b2wvTWFwfk1hcCNzZXRWaWV3fS5cbiAqL1xuXG4vKipcbiAqIEBmaXJlcyBpbXBvcnQoXCIuL01hcEJyb3dzZXJFdmVudC5qc1wiKS5NYXBCcm93c2VyRXZlbnRcbiAqIEBmaXJlcyBpbXBvcnQoXCIuL01hcEV2ZW50LmpzXCIpLk1hcEV2ZW50XG4gKiBAZmlyZXMgaW1wb3J0KFwiLi9yZW5kZXIvRXZlbnQuanNcIikuZGVmYXVsdCNwcmVjb21wb3NlXG4gKiBAZmlyZXMgaW1wb3J0KFwiLi9yZW5kZXIvRXZlbnQuanNcIikuZGVmYXVsdCNwb3N0Y29tcG9zZVxuICogQGZpcmVzIGltcG9ydChcIi4vcmVuZGVyL0V2ZW50LmpzXCIpLmRlZmF1bHQjcmVuZGVyY29tcGxldGVcbiAqIEBhcGlcbiAqL1xuXG52YXIgUGx1Z2dhYmxlTWFwID1cbi8qKiBAY2xhc3MgKi9cbmZ1bmN0aW9uIChfc3VwZXIpIHtcbiAgX19leHRlbmRzKFBsdWdnYWJsZU1hcCwgX3N1cGVyKTtcbiAgLyoqXG4gICAqIEBwYXJhbSB7TWFwT3B0aW9uc30gb3B0aW9ucyBNYXAgb3B0aW9ucy5cbiAgICovXG5cblxuICBmdW5jdGlvbiBQbHVnZ2FibGVNYXAob3B0aW9ucykge1xuICAgIHZhciBfdGhpcyA9IF9zdXBlci5jYWxsKHRoaXMpIHx8IHRoaXM7XG5cbiAgICB2YXIgb3B0aW9uc0ludGVybmFsID0gY3JlYXRlT3B0aW9uc0ludGVybmFsKG9wdGlvbnMpO1xuICAgIC8qKiBAcHJpdmF0ZSAqL1xuXG4gICAgX3RoaXMuYm91bmRIYW5kbGVCcm93c2VyRXZlbnRfID0gX3RoaXMuaGFuZGxlQnJvd3NlckV2ZW50LmJpbmQoX3RoaXMpO1xuICAgIC8qKlxuICAgICAqIEB0eXBlIHtudW1iZXJ9XG4gICAgICogQHByaXZhdGVcbiAgICAgKi9cblxuICAgIF90aGlzLm1heFRpbGVzTG9hZGluZ18gPSBvcHRpb25zLm1heFRpbGVzTG9hZGluZyAhPT0gdW5kZWZpbmVkID8gb3B0aW9ucy5tYXhUaWxlc0xvYWRpbmcgOiAxNjtcbiAgICAvKipcbiAgICAgKiBAcHJpdmF0ZVxuICAgICAqIEB0eXBlIHtudW1iZXJ9XG4gICAgICovXG5cbiAgICBfdGhpcy5waXhlbFJhdGlvXyA9IG9wdGlvbnMucGl4ZWxSYXRpbyAhPT0gdW5kZWZpbmVkID8gb3B0aW9ucy5waXhlbFJhdGlvIDogREVWSUNFX1BJWEVMX1JBVElPO1xuICAgIC8qKlxuICAgICAqIEBwcml2YXRlXG4gICAgICogQHR5cGUgeyp9XG4gICAgICovXG5cbiAgICBfdGhpcy5wb3N0UmVuZGVyVGltZW91dEhhbmRsZV87XG4gICAgLyoqXG4gICAgICogQHByaXZhdGVcbiAgICAgKiBAdHlwZSB7bnVtYmVyfHVuZGVmaW5lZH1cbiAgICAgKi9cblxuICAgIF90aGlzLmFuaW1hdGlvbkRlbGF5S2V5XztcbiAgICAvKipcbiAgICAgKiBAcHJpdmF0ZVxuICAgICAqL1xuXG4gICAgX3RoaXMuYW5pbWF0aW9uRGVsYXlfID1cbiAgICAvKiogQHRoaXMge1BsdWdnYWJsZU1hcH0gKi9cbiAgICBmdW5jdGlvbiAoKSB7XG4gICAgICB0aGlzLmFuaW1hdGlvbkRlbGF5S2V5XyA9IHVuZGVmaW5lZDtcbiAgICAgIHRoaXMucmVuZGVyRnJhbWVfKERhdGUubm93KCkpO1xuICAgIH0uYmluZChfdGhpcyk7XG4gICAgLyoqXG4gICAgICogQHByaXZhdGVcbiAgICAgKiBAdHlwZSB7aW1wb3J0KFwiLi90cmFuc2Zvcm0uanNcIikuVHJhbnNmb3JtfVxuICAgICAqL1xuXG5cbiAgICBfdGhpcy5jb29yZGluYXRlVG9QaXhlbFRyYW5zZm9ybV8gPSBjcmVhdGVUcmFuc2Zvcm0oKTtcbiAgICAvKipcbiAgICAgKiBAcHJpdmF0ZVxuICAgICAqIEB0eXBlIHtpbXBvcnQoXCIuL3RyYW5zZm9ybS5qc1wiKS5UcmFuc2Zvcm19XG4gICAgICovXG5cbiAgICBfdGhpcy5waXhlbFRvQ29vcmRpbmF0ZVRyYW5zZm9ybV8gPSBjcmVhdGVUcmFuc2Zvcm0oKTtcbiAgICAvKipcbiAgICAgKiBAcHJpdmF0ZVxuICAgICAqIEB0eXBlIHtudW1iZXJ9XG4gICAgICovXG5cbiAgICBfdGhpcy5mcmFtZUluZGV4XyA9IDA7XG4gICAgLyoqXG4gICAgICogQHByaXZhdGVcbiAgICAgKiBAdHlwZSB7P0ZyYW1lU3RhdGV9XG4gICAgICovXG5cbiAgICBfdGhpcy5mcmFtZVN0YXRlXyA9IG51bGw7XG4gICAgLyoqXG4gICAgICogVGhlIGV4dGVudCBhdCB0aGUgcHJldmlvdXMgJ21vdmVlbmQnIGV2ZW50LlxuICAgICAqIEBwcml2YXRlXG4gICAgICogQHR5cGUge2ltcG9ydChcIi4vZXh0ZW50LmpzXCIpLkV4dGVudH1cbiAgICAgKi9cblxuICAgIF90aGlzLnByZXZpb3VzRXh0ZW50XyA9IG51bGw7XG4gICAgLyoqXG4gICAgICogQHByaXZhdGVcbiAgICAgKiBAdHlwZSB7P2ltcG9ydChcIi4vZXZlbnRzLmpzXCIpLkV2ZW50c0tleX1cbiAgICAgKi9cblxuICAgIF90aGlzLnZpZXdQcm9wZXJ0eUxpc3RlbmVyS2V5XyA9IG51bGw7XG4gICAgLyoqXG4gICAgICogQHByaXZhdGVcbiAgICAgKiBAdHlwZSB7P2ltcG9ydChcIi4vZXZlbnRzLmpzXCIpLkV2ZW50c0tleX1cbiAgICAgKi9cblxuICAgIF90aGlzLnZpZXdDaGFuZ2VMaXN0ZW5lcktleV8gPSBudWxsO1xuICAgIC8qKlxuICAgICAqIEBwcml2YXRlXG4gICAgICogQHR5cGUgez9BcnJheTxpbXBvcnQoXCIuL2V2ZW50cy5qc1wiKS5FdmVudHNLZXk+fVxuICAgICAqL1xuXG4gICAgX3RoaXMubGF5ZXJHcm91cFByb3BlcnR5TGlzdGVuZXJLZXlzXyA9IG51bGw7XG4gICAgLyoqXG4gICAgICogQHByaXZhdGVcbiAgICAgKiBAdHlwZSB7IUhUTUxFbGVtZW50fVxuICAgICAqL1xuXG4gICAgX3RoaXMudmlld3BvcnRfID0gZG9jdW1lbnQuY3JlYXRlRWxlbWVudCgnZGl2Jyk7XG4gICAgX3RoaXMudmlld3BvcnRfLmNsYXNzTmFtZSA9ICdvbC12aWV3cG9ydCcgKyAoJ29udG91Y2hzdGFydCcgaW4gd2luZG93ID8gJyBvbC10b3VjaCcgOiAnJyk7XG4gICAgX3RoaXMudmlld3BvcnRfLnN0eWxlLnBvc2l0aW9uID0gJ3JlbGF0aXZlJztcbiAgICBfdGhpcy52aWV3cG9ydF8uc3R5bGUub3ZlcmZsb3cgPSAnaGlkZGVuJztcbiAgICBfdGhpcy52aWV3cG9ydF8uc3R5bGUud2lkdGggPSAnMTAwJSc7XG4gICAgX3RoaXMudmlld3BvcnRfLnN0eWxlLmhlaWdodCA9ICcxMDAlJztcbiAgICAvKipcbiAgICAgKiBAcHJpdmF0ZVxuICAgICAqIEB0eXBlIHshSFRNTEVsZW1lbnR9XG4gICAgICovXG5cbiAgICBfdGhpcy5vdmVybGF5Q29udGFpbmVyXyA9IGRvY3VtZW50LmNyZWF0ZUVsZW1lbnQoJ2RpdicpO1xuICAgIF90aGlzLm92ZXJsYXlDb250YWluZXJfLnN0eWxlLnBvc2l0aW9uID0gJ2Fic29sdXRlJztcbiAgICBfdGhpcy5vdmVybGF5Q29udGFpbmVyXy5zdHlsZS56SW5kZXggPSAnMCc7XG4gICAgX3RoaXMub3ZlcmxheUNvbnRhaW5lcl8uc3R5bGUud2lkdGggPSAnMTAwJSc7XG4gICAgX3RoaXMub3ZlcmxheUNvbnRhaW5lcl8uc3R5bGUuaGVpZ2h0ID0gJzEwMCUnO1xuICAgIF90aGlzLm92ZXJsYXlDb250YWluZXJfLnN0eWxlLnBvaW50ZXJFdmVudHMgPSAnbm9uZSc7XG4gICAgX3RoaXMub3ZlcmxheUNvbnRhaW5lcl8uY2xhc3NOYW1lID0gJ29sLW92ZXJsYXljb250YWluZXInO1xuXG4gICAgX3RoaXMudmlld3BvcnRfLmFwcGVuZENoaWxkKF90aGlzLm92ZXJsYXlDb250YWluZXJfKTtcbiAgICAvKipcbiAgICAgKiBAcHJpdmF0ZVxuICAgICAqIEB0eXBlIHshSFRNTEVsZW1lbnR9XG4gICAgICovXG5cblxuICAgIF90aGlzLm92ZXJsYXlDb250YWluZXJTdG9wRXZlbnRfID0gZG9jdW1lbnQuY3JlYXRlRWxlbWVudCgnZGl2Jyk7XG4gICAgX3RoaXMub3ZlcmxheUNvbnRhaW5lclN0b3BFdmVudF8uc3R5bGUucG9zaXRpb24gPSAnYWJzb2x1dGUnO1xuICAgIF90aGlzLm92ZXJsYXlDb250YWluZXJTdG9wRXZlbnRfLnN0eWxlLnpJbmRleCA9ICcwJztcbiAgICBfdGhpcy5vdmVybGF5Q29udGFpbmVyU3RvcEV2ZW50Xy5zdHlsZS53aWR0aCA9ICcxMDAlJztcbiAgICBfdGhpcy5vdmVybGF5Q29udGFpbmVyU3RvcEV2ZW50Xy5zdHlsZS5oZWlnaHQgPSAnMTAwJSc7XG4gICAgX3RoaXMub3ZlcmxheUNvbnRhaW5lclN0b3BFdmVudF8uc3R5bGUucG9pbnRlckV2ZW50cyA9ICdub25lJztcbiAgICBfdGhpcy5vdmVybGF5Q29udGFpbmVyU3RvcEV2ZW50Xy5jbGFzc05hbWUgPSAnb2wtb3ZlcmxheWNvbnRhaW5lci1zdG9wZXZlbnQnO1xuXG4gICAgX3RoaXMudmlld3BvcnRfLmFwcGVuZENoaWxkKF90aGlzLm92ZXJsYXlDb250YWluZXJTdG9wRXZlbnRfKTtcbiAgICAvKipcbiAgICAgKiBAcHJpdmF0ZVxuICAgICAqIEB0eXBlIHtNYXBCcm93c2VyRXZlbnRIYW5kbGVyfVxuICAgICAqL1xuXG5cbiAgICBfdGhpcy5tYXBCcm93c2VyRXZlbnRIYW5kbGVyXyA9IG51bGw7XG4gICAgLyoqXG4gICAgICogQHByaXZhdGVcbiAgICAgKiBAdHlwZSB7bnVtYmVyfVxuICAgICAqL1xuXG4gICAgX3RoaXMubW92ZVRvbGVyYW5jZV8gPSBvcHRpb25zLm1vdmVUb2xlcmFuY2U7XG4gICAgLyoqXG4gICAgICogQHByaXZhdGVcbiAgICAgKiBAdHlwZSB7SFRNTEVsZW1lbnR8RG9jdW1lbnR9XG4gICAgICovXG5cbiAgICBfdGhpcy5rZXlib2FyZEV2ZW50VGFyZ2V0XyA9IG9wdGlvbnNJbnRlcm5hbC5rZXlib2FyZEV2ZW50VGFyZ2V0O1xuICAgIC8qKlxuICAgICAqIEBwcml2YXRlXG4gICAgICogQHR5cGUgez9BcnJheTxpbXBvcnQoXCIuL2V2ZW50cy5qc1wiKS5FdmVudHNLZXk+fVxuICAgICAqL1xuXG4gICAgX3RoaXMua2V5SGFuZGxlcktleXNfID0gbnVsbDtcbiAgICAvKipcbiAgICAgKiBAdHlwZSB7Q29sbGVjdGlvbjxpbXBvcnQoXCIuL2NvbnRyb2wvQ29udHJvbC5qc1wiKS5kZWZhdWx0Pn1cbiAgICAgKiBAcHJvdGVjdGVkXG4gICAgICovXG5cbiAgICBfdGhpcy5jb250cm9scyA9IG9wdGlvbnNJbnRlcm5hbC5jb250cm9scyB8fCBuZXcgQ29sbGVjdGlvbigpO1xuICAgIC8qKlxuICAgICAqIEB0eXBlIHtDb2xsZWN0aW9uPGltcG9ydChcIi4vaW50ZXJhY3Rpb24vSW50ZXJhY3Rpb24uanNcIikuZGVmYXVsdD59XG4gICAgICogQHByb3RlY3RlZFxuICAgICAqL1xuXG4gICAgX3RoaXMuaW50ZXJhY3Rpb25zID0gb3B0aW9uc0ludGVybmFsLmludGVyYWN0aW9ucyB8fCBuZXcgQ29sbGVjdGlvbigpO1xuICAgIC8qKlxuICAgICAqIEB0eXBlIHtDb2xsZWN0aW9uPGltcG9ydChcIi4vT3ZlcmxheS5qc1wiKS5kZWZhdWx0Pn1cbiAgICAgKiBAcHJpdmF0ZVxuICAgICAqL1xuXG4gICAgX3RoaXMub3ZlcmxheXNfID0gb3B0aW9uc0ludGVybmFsLm92ZXJsYXlzO1xuICAgIC8qKlxuICAgICAqIEEgbG9va3VwIG9mIG92ZXJsYXlzIGJ5IGlkLlxuICAgICAqIEBwcml2YXRlXG4gICAgICogQHR5cGUge09iamVjdDxzdHJpbmcsIGltcG9ydChcIi4vT3ZlcmxheS5qc1wiKS5kZWZhdWx0Pn1cbiAgICAgKi9cblxuICAgIF90aGlzLm92ZXJsYXlJZEluZGV4XyA9IHt9O1xuICAgIC8qKlxuICAgICAqIEB0eXBlIHtpbXBvcnQoXCIuL3JlbmRlcmVyL01hcC5qc1wiKS5kZWZhdWx0fVxuICAgICAqIEBwcml2YXRlXG4gICAgICovXG5cbiAgICBfdGhpcy5yZW5kZXJlcl8gPSBudWxsO1xuICAgIC8qKlxuICAgICAqIEB0eXBlIHt1bmRlZmluZWR8ZnVuY3Rpb24oRXZlbnQpOiB2b2lkfVxuICAgICAqIEBwcml2YXRlXG4gICAgICovXG5cbiAgICBfdGhpcy5oYW5kbGVSZXNpemVfO1xuICAgIC8qKlxuICAgICAqIEBwcml2YXRlXG4gICAgICogQHR5cGUgeyFBcnJheTxQb3N0UmVuZGVyRnVuY3Rpb24+fVxuICAgICAqL1xuXG4gICAgX3RoaXMucG9zdFJlbmRlckZ1bmN0aW9uc18gPSBbXTtcbiAgICAvKipcbiAgICAgKiBAcHJpdmF0ZVxuICAgICAqIEB0eXBlIHtUaWxlUXVldWV9XG4gICAgICovXG5cbiAgICBfdGhpcy50aWxlUXVldWVfID0gbmV3IFRpbGVRdWV1ZShfdGhpcy5nZXRUaWxlUHJpb3JpdHkuYmluZChfdGhpcyksIF90aGlzLmhhbmRsZVRpbGVDaGFuZ2VfLmJpbmQoX3RoaXMpKTtcblxuICAgIF90aGlzLmFkZEV2ZW50TGlzdGVuZXIoZ2V0Q2hhbmdlRXZlbnRUeXBlKE1hcFByb3BlcnR5LkxBWUVSR1JPVVApLCBfdGhpcy5oYW5kbGVMYXllckdyb3VwQ2hhbmdlZF8pO1xuXG4gICAgX3RoaXMuYWRkRXZlbnRMaXN0ZW5lcihnZXRDaGFuZ2VFdmVudFR5cGUoTWFwUHJvcGVydHkuVklFVyksIF90aGlzLmhhbmRsZVZpZXdDaGFuZ2VkXyk7XG5cbiAgICBfdGhpcy5hZGRFdmVudExpc3RlbmVyKGdldENoYW5nZUV2ZW50VHlwZShNYXBQcm9wZXJ0eS5TSVpFKSwgX3RoaXMuaGFuZGxlU2l6ZUNoYW5nZWRfKTtcblxuICAgIF90aGlzLmFkZEV2ZW50TGlzdGVuZXIoZ2V0Q2hhbmdlRXZlbnRUeXBlKE1hcFByb3BlcnR5LlRBUkdFVCksIF90aGlzLmhhbmRsZVRhcmdldENoYW5nZWRfKTsgLy8gc2V0UHJvcGVydGllcyB3aWxsIHRyaWdnZXIgdGhlIHJlbmRlcmluZyBvZiB0aGUgbWFwIGlmIHRoZSBtYXBcbiAgICAvLyBpcyBcImRlZmluZWRcIiBhbHJlYWR5LlxuXG5cbiAgICBfdGhpcy5zZXRQcm9wZXJ0aWVzKG9wdGlvbnNJbnRlcm5hbC52YWx1ZXMpO1xuXG4gICAgX3RoaXMuY29udHJvbHMuZm9yRWFjaChcbiAgICAvKipcbiAgICAgKiBAcGFyYW0ge2ltcG9ydChcIi4vY29udHJvbC9Db250cm9sLmpzXCIpLmRlZmF1bHR9IGNvbnRyb2wgQ29udHJvbC5cbiAgICAgKiBAdGhpcyB7UGx1Z2dhYmxlTWFwfVxuICAgICAqL1xuICAgIGZ1bmN0aW9uIChjb250cm9sKSB7XG4gICAgICBjb250cm9sLnNldE1hcCh0aGlzKTtcbiAgICB9LmJpbmQoX3RoaXMpKTtcblxuICAgIF90aGlzLmNvbnRyb2xzLmFkZEV2ZW50TGlzdGVuZXIoQ29sbGVjdGlvbkV2ZW50VHlwZS5BREQsXG4gICAgLyoqXG4gICAgICogQHBhcmFtIHtpbXBvcnQoXCIuL0NvbGxlY3Rpb24uanNcIikuQ29sbGVjdGlvbkV2ZW50fSBldmVudCBDb2xsZWN0aW9uRXZlbnQuXG4gICAgICovXG4gICAgZnVuY3Rpb24gKGV2ZW50KSB7XG4gICAgICBldmVudC5lbGVtZW50LnNldE1hcCh0aGlzKTtcbiAgICB9LmJpbmQoX3RoaXMpKTtcblxuICAgIF90aGlzLmNvbnRyb2xzLmFkZEV2ZW50TGlzdGVuZXIoQ29sbGVjdGlvbkV2ZW50VHlwZS5SRU1PVkUsXG4gICAgLyoqXG4gICAgICogQHBhcmFtIHtpbXBvcnQoXCIuL0NvbGxlY3Rpb24uanNcIikuQ29sbGVjdGlvbkV2ZW50fSBldmVudCBDb2xsZWN0aW9uRXZlbnQuXG4gICAgICovXG4gICAgZnVuY3Rpb24gKGV2ZW50KSB7XG4gICAgICBldmVudC5lbGVtZW50LnNldE1hcChudWxsKTtcbiAgICB9LmJpbmQoX3RoaXMpKTtcblxuICAgIF90aGlzLmludGVyYWN0aW9ucy5mb3JFYWNoKFxuICAgIC8qKlxuICAgICAqIEBwYXJhbSB7aW1wb3J0KFwiLi9pbnRlcmFjdGlvbi9JbnRlcmFjdGlvbi5qc1wiKS5kZWZhdWx0fSBpbnRlcmFjdGlvbiBJbnRlcmFjdGlvbi5cbiAgICAgKiBAdGhpcyB7UGx1Z2dhYmxlTWFwfVxuICAgICAqL1xuICAgIGZ1bmN0aW9uIChpbnRlcmFjdGlvbikge1xuICAgICAgaW50ZXJhY3Rpb24uc2V0TWFwKHRoaXMpO1xuICAgIH0uYmluZChfdGhpcykpO1xuXG4gICAgX3RoaXMuaW50ZXJhY3Rpb25zLmFkZEV2ZW50TGlzdGVuZXIoQ29sbGVjdGlvbkV2ZW50VHlwZS5BREQsXG4gICAgLyoqXG4gICAgICogQHBhcmFtIHtpbXBvcnQoXCIuL0NvbGxlY3Rpb24uanNcIikuQ29sbGVjdGlvbkV2ZW50fSBldmVudCBDb2xsZWN0aW9uRXZlbnQuXG4gICAgICovXG4gICAgZnVuY3Rpb24gKGV2ZW50KSB7XG4gICAgICBldmVudC5lbGVtZW50LnNldE1hcCh0aGlzKTtcbiAgICB9LmJpbmQoX3RoaXMpKTtcblxuICAgIF90aGlzLmludGVyYWN0aW9ucy5hZGRFdmVudExpc3RlbmVyKENvbGxlY3Rpb25FdmVudFR5cGUuUkVNT1ZFLFxuICAgIC8qKlxuICAgICAqIEBwYXJhbSB7aW1wb3J0KFwiLi9Db2xsZWN0aW9uLmpzXCIpLkNvbGxlY3Rpb25FdmVudH0gZXZlbnQgQ29sbGVjdGlvbkV2ZW50LlxuICAgICAqL1xuICAgIGZ1bmN0aW9uIChldmVudCkge1xuICAgICAgZXZlbnQuZWxlbWVudC5zZXRNYXAobnVsbCk7XG4gICAgfS5iaW5kKF90aGlzKSk7XG5cbiAgICBfdGhpcy5vdmVybGF5c18uZm9yRWFjaChfdGhpcy5hZGRPdmVybGF5SW50ZXJuYWxfLmJpbmQoX3RoaXMpKTtcblxuICAgIF90aGlzLm92ZXJsYXlzXy5hZGRFdmVudExpc3RlbmVyKENvbGxlY3Rpb25FdmVudFR5cGUuQURELFxuICAgIC8qKlxuICAgICAqIEBwYXJhbSB7aW1wb3J0KFwiLi9Db2xsZWN0aW9uLmpzXCIpLkNvbGxlY3Rpb25FdmVudH0gZXZlbnQgQ29sbGVjdGlvbkV2ZW50LlxuICAgICAqL1xuICAgIGZ1bmN0aW9uIChldmVudCkge1xuICAgICAgdGhpcy5hZGRPdmVybGF5SW50ZXJuYWxfKFxuICAgICAgLyoqIEB0eXBlIHtpbXBvcnQoXCIuL092ZXJsYXkuanNcIikuZGVmYXVsdH0gKi9cbiAgICAgIGV2ZW50LmVsZW1lbnQpO1xuICAgIH0uYmluZChfdGhpcykpO1xuXG4gICAgX3RoaXMub3ZlcmxheXNfLmFkZEV2ZW50TGlzdGVuZXIoQ29sbGVjdGlvbkV2ZW50VHlwZS5SRU1PVkUsXG4gICAgLyoqXG4gICAgICogQHBhcmFtIHtpbXBvcnQoXCIuL0NvbGxlY3Rpb24uanNcIikuQ29sbGVjdGlvbkV2ZW50fSBldmVudCBDb2xsZWN0aW9uRXZlbnQuXG4gICAgICovXG4gICAgZnVuY3Rpb24gKGV2ZW50KSB7XG4gICAgICB2YXIgb3ZlcmxheSA9XG4gICAgICAvKiogQHR5cGUge2ltcG9ydChcIi4vT3ZlcmxheS5qc1wiKS5kZWZhdWx0fSAqL1xuICAgICAgZXZlbnQuZWxlbWVudDtcbiAgICAgIHZhciBpZCA9IG92ZXJsYXkuZ2V0SWQoKTtcblxuICAgICAgaWYgKGlkICE9PSB1bmRlZmluZWQpIHtcbiAgICAgICAgZGVsZXRlIHRoaXMub3ZlcmxheUlkSW5kZXhfW2lkLnRvU3RyaW5nKCldO1xuICAgICAgfVxuXG4gICAgICBldmVudC5lbGVtZW50LnNldE1hcChudWxsKTtcbiAgICB9LmJpbmQoX3RoaXMpKTtcblxuICAgIHJldHVybiBfdGhpcztcbiAgfVxuICAvKipcbiAgICogQGFic3RyYWN0XG4gICAqIEByZXR1cm4ge2ltcG9ydChcIi4vcmVuZGVyZXIvTWFwLmpzXCIpLmRlZmF1bHR9IFRoZSBtYXAgcmVuZGVyZXJcbiAgICovXG5cblxuICBQbHVnZ2FibGVNYXAucHJvdG90eXBlLmNyZWF0ZVJlbmRlcmVyID0gZnVuY3Rpb24gKCkge1xuICAgIHRocm93IG5ldyBFcnJvcignVXNlIGEgbWFwIHR5cGUgdGhhdCBoYXMgYSBjcmVhdGVSZW5kZXJlciBtZXRob2QnKTtcbiAgfTtcbiAgLyoqXG4gICAqIEFkZCB0aGUgZ2l2ZW4gY29udHJvbCB0byB0aGUgbWFwLlxuICAgKiBAcGFyYW0ge2ltcG9ydChcIi4vY29udHJvbC9Db250cm9sLmpzXCIpLmRlZmF1bHR9IGNvbnRyb2wgQ29udHJvbC5cbiAgICogQGFwaVxuICAgKi9cblxuXG4gIFBsdWdnYWJsZU1hcC5wcm90b3R5cGUuYWRkQ29udHJvbCA9IGZ1bmN0aW9uIChjb250cm9sKSB7XG4gICAgdGhpcy5nZXRDb250cm9scygpLnB1c2goY29udHJvbCk7XG4gIH07XG4gIC8qKlxuICAgKiBBZGQgdGhlIGdpdmVuIGludGVyYWN0aW9uIHRvIHRoZSBtYXAuIElmIHlvdSB3YW50IHRvIGFkZCBhbiBpbnRlcmFjdGlvblxuICAgKiBhdCBhbm90aGVyIHBvaW50IG9mIHRoZSBjb2xsZWN0aW9uIHVzZSBgZ2V0SW50ZXJhY3Rpb24oKWAgYW5kIHRoZSBtZXRob2RzXG4gICAqIGF2YWlsYWJsZSBvbiB7QGxpbmsgbW9kdWxlOm9sL0NvbGxlY3Rpb25+Q29sbGVjdGlvbn0uIFRoaXMgY2FuIGJlIHVzZWQgdG9cbiAgICogc3RvcCB0aGUgZXZlbnQgcHJvcGFnYXRpb24gZnJvbSB0aGUgaGFuZGxlRXZlbnQgZnVuY3Rpb24uIFRoZSBpbnRlcmFjdGlvbnNcbiAgICogZ2V0IHRvIGhhbmRsZSB0aGUgZXZlbnRzIGluIHRoZSByZXZlcnNlIG9yZGVyIG9mIHRoaXMgY29sbGVjdGlvbi5cbiAgICogQHBhcmFtIHtpbXBvcnQoXCIuL2ludGVyYWN0aW9uL0ludGVyYWN0aW9uLmpzXCIpLmRlZmF1bHR9IGludGVyYWN0aW9uIEludGVyYWN0aW9uIHRvIGFkZC5cbiAgICogQGFwaVxuICAgKi9cblxuXG4gIFBsdWdnYWJsZU1hcC5wcm90b3R5cGUuYWRkSW50ZXJhY3Rpb24gPSBmdW5jdGlvbiAoaW50ZXJhY3Rpb24pIHtcbiAgICB0aGlzLmdldEludGVyYWN0aW9ucygpLnB1c2goaW50ZXJhY3Rpb24pO1xuICB9O1xuICAvKipcbiAgICogQWRkcyB0aGUgZ2l2ZW4gbGF5ZXIgdG8gdGhlIHRvcCBvZiB0aGlzIG1hcC4gSWYgeW91IHdhbnQgdG8gYWRkIGEgbGF5ZXJcbiAgICogZWxzZXdoZXJlIGluIHRoZSBzdGFjaywgdXNlIGBnZXRMYXllcnMoKWAgYW5kIHRoZSBtZXRob2RzIGF2YWlsYWJsZSBvblxuICAgKiB7QGxpbmsgbW9kdWxlOm9sL0NvbGxlY3Rpb25+Q29sbGVjdGlvbn0uXG4gICAqIEBwYXJhbSB7aW1wb3J0KFwiLi9sYXllci9CYXNlLmpzXCIpLmRlZmF1bHR9IGxheWVyIExheWVyLlxuICAgKiBAYXBpXG4gICAqL1xuXG5cbiAgUGx1Z2dhYmxlTWFwLnByb3RvdHlwZS5hZGRMYXllciA9IGZ1bmN0aW9uIChsYXllcikge1xuICAgIHZhciBsYXllcnMgPSB0aGlzLmdldExheWVyR3JvdXAoKS5nZXRMYXllcnMoKTtcbiAgICBsYXllcnMucHVzaChsYXllcik7XG4gIH07XG4gIC8qKlxuICAgKiBBZGQgdGhlIGdpdmVuIG92ZXJsYXkgdG8gdGhlIG1hcC5cbiAgICogQHBhcmFtIHtpbXBvcnQoXCIuL092ZXJsYXkuanNcIikuZGVmYXVsdH0gb3ZlcmxheSBPdmVybGF5LlxuICAgKiBAYXBpXG4gICAqL1xuXG5cbiAgUGx1Z2dhYmxlTWFwLnByb3RvdHlwZS5hZGRPdmVybGF5ID0gZnVuY3Rpb24gKG92ZXJsYXkpIHtcbiAgICB0aGlzLmdldE92ZXJsYXlzKCkucHVzaChvdmVybGF5KTtcbiAgfTtcbiAgLyoqXG4gICAqIFRoaXMgZGVhbHMgd2l0aCBtYXAncyBvdmVybGF5IGNvbGxlY3Rpb24gY2hhbmdlcy5cbiAgICogQHBhcmFtIHtpbXBvcnQoXCIuL092ZXJsYXkuanNcIikuZGVmYXVsdH0gb3ZlcmxheSBPdmVybGF5LlxuICAgKiBAcHJpdmF0ZVxuICAgKi9cblxuXG4gIFBsdWdnYWJsZU1hcC5wcm90b3R5cGUuYWRkT3ZlcmxheUludGVybmFsXyA9IGZ1bmN0aW9uIChvdmVybGF5KSB7XG4gICAgdmFyIGlkID0gb3ZlcmxheS5nZXRJZCgpO1xuXG4gICAgaWYgKGlkICE9PSB1bmRlZmluZWQpIHtcbiAgICAgIHRoaXMub3ZlcmxheUlkSW5kZXhfW2lkLnRvU3RyaW5nKCldID0gb3ZlcmxheTtcbiAgICB9XG5cbiAgICBvdmVybGF5LnNldE1hcCh0aGlzKTtcbiAgfTtcbiAgLyoqXG4gICAqXG4gICAqIENsZWFuIHVwLlxuICAgKi9cblxuXG4gIFBsdWdnYWJsZU1hcC5wcm90b3R5cGUuZGlzcG9zZUludGVybmFsID0gZnVuY3Rpb24gKCkge1xuICAgIHRoaXMuc2V0VGFyZ2V0KG51bGwpO1xuXG4gICAgX3N1cGVyLnByb3RvdHlwZS5kaXNwb3NlSW50ZXJuYWwuY2FsbCh0aGlzKTtcbiAgfTtcbiAgLyoqXG4gICAqIERldGVjdCBmZWF0dXJlcyB0aGF0IGludGVyc2VjdCBhIHBpeGVsIG9uIHRoZSB2aWV3cG9ydCwgYW5kIGV4ZWN1dGUgYVxuICAgKiBjYWxsYmFjayB3aXRoIGVhY2ggaW50ZXJzZWN0aW5nIGZlYXR1cmUuIExheWVycyBpbmNsdWRlZCBpbiB0aGUgZGV0ZWN0aW9uIGNhblxuICAgKiBiZSBjb25maWd1cmVkIHRocm91Z2ggdGhlIGBsYXllckZpbHRlcmAgb3B0aW9uIGluIGBvcHRfb3B0aW9uc2AuXG4gICAqIEBwYXJhbSB7aW1wb3J0KFwiLi9waXhlbC5qc1wiKS5QaXhlbH0gcGl4ZWwgUGl4ZWwuXG4gICAqIEBwYXJhbSB7ZnVuY3Rpb24oaW1wb3J0KFwiLi9GZWF0dXJlLmpzXCIpLkZlYXR1cmVMaWtlLCBpbXBvcnQoXCIuL2xheWVyL0xheWVyLmpzXCIpLmRlZmF1bHQsIGltcG9ydChcIi4vZ2VvbS9TaW1wbGVHZW9tZXRyeS5qc1wiKS5kZWZhdWx0KTogVH0gY2FsbGJhY2sgRmVhdHVyZSBjYWxsYmFjay4gVGhlIGNhbGxiYWNrIHdpbGwgYmVcbiAgICogICAgIGNhbGxlZCB3aXRoIHR3byBhcmd1bWVudHMuIFRoZSBmaXJzdCBhcmd1bWVudCBpcyBvbmVcbiAgICogICAgIHtAbGluayBtb2R1bGU6b2wvRmVhdHVyZSBmZWF0dXJlfSBvclxuICAgKiAgICAge0BsaW5rIG1vZHVsZTpvbC9yZW5kZXIvRmVhdHVyZSByZW5kZXIgZmVhdHVyZX0gYXQgdGhlIHBpeGVsLCB0aGUgc2Vjb25kIGlzXG4gICAqICAgICB0aGUge0BsaW5rIG1vZHVsZTpvbC9sYXllci9MYXllciBsYXllcn0gb2YgdGhlIGZlYXR1cmUgYW5kIHdpbGwgYmUgbnVsbCBmb3JcbiAgICogICAgIHVubWFuYWdlZCBsYXllcnMuIFRvIHN0b3AgZGV0ZWN0aW9uLCBjYWxsYmFjayBmdW5jdGlvbnMgY2FuIHJldHVybiBhXG4gICAqICAgICB0cnV0aHkgdmFsdWUuXG4gICAqIEBwYXJhbSB7QXRQaXhlbE9wdGlvbnM9fSBvcHRfb3B0aW9ucyBPcHRpb25hbCBvcHRpb25zLlxuICAgKiBAcmV0dXJuIHtUfHVuZGVmaW5lZH0gQ2FsbGJhY2sgcmVzdWx0LCBpLmUuIHRoZSByZXR1cm4gdmFsdWUgb2YgbGFzdFxuICAgKiBjYWxsYmFjayBleGVjdXRpb24sIG9yIHRoZSBmaXJzdCB0cnV0aHkgY2FsbGJhY2sgcmV0dXJuIHZhbHVlLlxuICAgKiBAdGVtcGxhdGUgUyxUXG4gICAqIEBhcGlcbiAgICovXG5cblxuICBQbHVnZ2FibGVNYXAucHJvdG90eXBlLmZvckVhY2hGZWF0dXJlQXRQaXhlbCA9IGZ1bmN0aW9uIChwaXhlbCwgY2FsbGJhY2ssIG9wdF9vcHRpb25zKSB7XG4gICAgaWYgKCF0aGlzLmZyYW1lU3RhdGVfKSB7XG4gICAgICByZXR1cm47XG4gICAgfVxuXG4gICAgdmFyIGNvb3JkaW5hdGUgPSB0aGlzLmdldENvb3JkaW5hdGVGcm9tUGl4ZWxJbnRlcm5hbChwaXhlbCk7XG4gICAgb3B0X29wdGlvbnMgPSBvcHRfb3B0aW9ucyAhPT0gdW5kZWZpbmVkID8gb3B0X29wdGlvbnMgOiB7fTtcbiAgICB2YXIgaGl0VG9sZXJhbmNlID0gb3B0X29wdGlvbnMuaGl0VG9sZXJhbmNlICE9PSB1bmRlZmluZWQgPyBvcHRfb3B0aW9ucy5oaXRUb2xlcmFuY2UgOiAwO1xuICAgIHZhciBsYXllckZpbHRlciA9IG9wdF9vcHRpb25zLmxheWVyRmlsdGVyICE9PSB1bmRlZmluZWQgPyBvcHRfb3B0aW9ucy5sYXllckZpbHRlciA6IFRSVUU7XG4gICAgdmFyIGNoZWNrV3JhcHBlZCA9IG9wdF9vcHRpb25zLmNoZWNrV3JhcHBlZCAhPT0gZmFsc2U7XG4gICAgcmV0dXJuIHRoaXMucmVuZGVyZXJfLmZvckVhY2hGZWF0dXJlQXRDb29yZGluYXRlKGNvb3JkaW5hdGUsIHRoaXMuZnJhbWVTdGF0ZV8sIGhpdFRvbGVyYW5jZSwgY2hlY2tXcmFwcGVkLCBjYWxsYmFjaywgbnVsbCwgbGF5ZXJGaWx0ZXIsIG51bGwpO1xuICB9O1xuICAvKipcbiAgICogR2V0IGFsbCBmZWF0dXJlcyB0aGF0IGludGVyc2VjdCBhIHBpeGVsIG9uIHRoZSB2aWV3cG9ydC5cbiAgICogQHBhcmFtIHtpbXBvcnQoXCIuL3BpeGVsLmpzXCIpLlBpeGVsfSBwaXhlbCBQaXhlbC5cbiAgICogQHBhcmFtIHtBdFBpeGVsT3B0aW9ucz19IG9wdF9vcHRpb25zIE9wdGlvbmFsIG9wdGlvbnMuXG4gICAqIEByZXR1cm4ge0FycmF5PGltcG9ydChcIi4vRmVhdHVyZS5qc1wiKS5GZWF0dXJlTGlrZT59IFRoZSBkZXRlY3RlZCBmZWF0dXJlcyBvclxuICAgKiBhbiBlbXB0eSBhcnJheSBpZiBub25lIHdlcmUgZm91bmQuXG4gICAqIEBhcGlcbiAgICovXG5cblxuICBQbHVnZ2FibGVNYXAucHJvdG90eXBlLmdldEZlYXR1cmVzQXRQaXhlbCA9IGZ1bmN0aW9uIChwaXhlbCwgb3B0X29wdGlvbnMpIHtcbiAgICB2YXIgZmVhdHVyZXMgPSBbXTtcbiAgICB0aGlzLmZvckVhY2hGZWF0dXJlQXRQaXhlbChwaXhlbCwgZnVuY3Rpb24gKGZlYXR1cmUpIHtcbiAgICAgIGZlYXR1cmVzLnB1c2goZmVhdHVyZSk7XG4gICAgfSwgb3B0X29wdGlvbnMpO1xuICAgIHJldHVybiBmZWF0dXJlcztcbiAgfTtcbiAgLyoqXG4gICAqIERldGVjdCBsYXllcnMgdGhhdCBoYXZlIGEgY29sb3IgdmFsdWUgYXQgYSBwaXhlbCBvbiB0aGUgdmlld3BvcnQsIGFuZFxuICAgKiBleGVjdXRlIGEgY2FsbGJhY2sgd2l0aCBlYWNoIG1hdGNoaW5nIGxheWVyLiBMYXllcnMgaW5jbHVkZWQgaW4gdGhlXG4gICAqIGRldGVjdGlvbiBjYW4gYmUgY29uZmlndXJlZCB0aHJvdWdoIGBvcHRfbGF5ZXJGaWx0ZXJgLlxuICAgKlxuICAgKiBOb3RlOiB0aGlzIG1heSBnaXZlIGZhbHNlIHBvc2l0aXZlcyB1bmxlc3MgdGhlIG1hcCBsYXllcnMgaGF2ZSBoYWQgZGlmZmVyZW50IGBjbGFzc05hbWVgXG4gICAqIHByb3BlcnRpZXMgYXNzaWduZWQgdG8gdGhlbS5cbiAgICpcbiAgICogQHBhcmFtIHtpbXBvcnQoXCIuL3BpeGVsLmpzXCIpLlBpeGVsfSBwaXhlbCBQaXhlbC5cbiAgICogQHBhcmFtIHtmdW5jdGlvbih0aGlzOiBTLCBpbXBvcnQoXCIuL2xheWVyL0xheWVyLmpzXCIpLmRlZmF1bHQsIChVaW50OENsYW1wZWRBcnJheXxVaW50OEFycmF5KSk6IFR9IGNhbGxiYWNrXG4gICAqICAgICBMYXllciBjYWxsYmFjay4gVGhpcyBjYWxsYmFjayB3aWxsIHJlY2VpdmUgdHdvIGFyZ3VtZW50czogZmlyc3QgaXMgdGhlXG4gICAqICAgICB7QGxpbmsgbW9kdWxlOm9sL2xheWVyL0xheWVyIGxheWVyfSwgc2Vjb25kIGFyZ3VtZW50IGlzIGFuIGFycmF5IHJlcHJlc2VudGluZ1xuICAgKiAgICAgW1IsIEcsIEIsIEFdIHBpeGVsIHZhbHVlcyAoMCAtIDI1NSkgYW5kIHdpbGwgYmUgYG51bGxgIGZvciBsYXllciB0eXBlc1xuICAgKiAgICAgdGhhdCBkbyBub3QgY3VycmVudGx5IHN1cHBvcnQgdGhpcyBhcmd1bWVudC4gVG8gc3RvcCBkZXRlY3Rpb24sIGNhbGxiYWNrXG4gICAqICAgICBmdW5jdGlvbnMgY2FuIHJldHVybiBhIHRydXRoeSB2YWx1ZS5cbiAgICogQHBhcmFtIHtBdFBpeGVsT3B0aW9ucz19IG9wdF9vcHRpb25zIENvbmZpZ3VyYXRpb24gb3B0aW9ucy5cbiAgICogQHJldHVybiB7VHx1bmRlZmluZWR9IENhbGxiYWNrIHJlc3VsdCwgaS5lLiB0aGUgcmV0dXJuIHZhbHVlIG9mIGxhc3RcbiAgICogY2FsbGJhY2sgZXhlY3V0aW9uLCBvciB0aGUgZmlyc3QgdHJ1dGh5IGNhbGxiYWNrIHJldHVybiB2YWx1ZS5cbiAgICogQHRlbXBsYXRlIFMsVFxuICAgKiBAYXBpXG4gICAqL1xuXG5cbiAgUGx1Z2dhYmxlTWFwLnByb3RvdHlwZS5mb3JFYWNoTGF5ZXJBdFBpeGVsID0gZnVuY3Rpb24gKHBpeGVsLCBjYWxsYmFjaywgb3B0X29wdGlvbnMpIHtcbiAgICBpZiAoIXRoaXMuZnJhbWVTdGF0ZV8pIHtcbiAgICAgIHJldHVybjtcbiAgICB9XG5cbiAgICB2YXIgb3B0aW9ucyA9IG9wdF9vcHRpb25zIHx8IHt9O1xuICAgIHZhciBoaXRUb2xlcmFuY2UgPSBvcHRpb25zLmhpdFRvbGVyYW5jZSAhPT0gdW5kZWZpbmVkID8gb3B0aW9ucy5oaXRUb2xlcmFuY2UgOiAwO1xuICAgIHZhciBsYXllckZpbHRlciA9IG9wdGlvbnMubGF5ZXJGaWx0ZXIgfHwgVFJVRTtcbiAgICByZXR1cm4gdGhpcy5yZW5kZXJlcl8uZm9yRWFjaExheWVyQXRQaXhlbChwaXhlbCwgdGhpcy5mcmFtZVN0YXRlXywgaGl0VG9sZXJhbmNlLCBjYWxsYmFjaywgbGF5ZXJGaWx0ZXIpO1xuICB9O1xuICAvKipcbiAgICogRGV0ZWN0IGlmIGZlYXR1cmVzIGludGVyc2VjdCBhIHBpeGVsIG9uIHRoZSB2aWV3cG9ydC4gTGF5ZXJzIGluY2x1ZGVkIGluIHRoZVxuICAgKiBkZXRlY3Rpb24gY2FuIGJlIGNvbmZpZ3VyZWQgdGhyb3VnaCBgb3B0X2xheWVyRmlsdGVyYC5cbiAgICogQHBhcmFtIHtpbXBvcnQoXCIuL3BpeGVsLmpzXCIpLlBpeGVsfSBwaXhlbCBQaXhlbC5cbiAgICogQHBhcmFtIHtBdFBpeGVsT3B0aW9ucz19IG9wdF9vcHRpb25zIE9wdGlvbmFsIG9wdGlvbnMuXG4gICAqIEByZXR1cm4ge2Jvb2xlYW59IElzIHRoZXJlIGEgZmVhdHVyZSBhdCB0aGUgZ2l2ZW4gcGl4ZWw/XG4gICAqIEBhcGlcbiAgICovXG5cblxuICBQbHVnZ2FibGVNYXAucHJvdG90eXBlLmhhc0ZlYXR1cmVBdFBpeGVsID0gZnVuY3Rpb24gKHBpeGVsLCBvcHRfb3B0aW9ucykge1xuICAgIGlmICghdGhpcy5mcmFtZVN0YXRlXykge1xuICAgICAgcmV0dXJuIGZhbHNlO1xuICAgIH1cblxuICAgIHZhciBjb29yZGluYXRlID0gdGhpcy5nZXRDb29yZGluYXRlRnJvbVBpeGVsSW50ZXJuYWwocGl4ZWwpO1xuICAgIG9wdF9vcHRpb25zID0gb3B0X29wdGlvbnMgIT09IHVuZGVmaW5lZCA/IG9wdF9vcHRpb25zIDoge307XG4gICAgdmFyIGxheWVyRmlsdGVyID0gb3B0X29wdGlvbnMubGF5ZXJGaWx0ZXIgIT09IHVuZGVmaW5lZCA/IG9wdF9vcHRpb25zLmxheWVyRmlsdGVyIDogVFJVRTtcbiAgICB2YXIgaGl0VG9sZXJhbmNlID0gb3B0X29wdGlvbnMuaGl0VG9sZXJhbmNlICE9PSB1bmRlZmluZWQgPyBvcHRfb3B0aW9ucy5oaXRUb2xlcmFuY2UgOiAwO1xuICAgIHZhciBjaGVja1dyYXBwZWQgPSBvcHRfb3B0aW9ucy5jaGVja1dyYXBwZWQgIT09IGZhbHNlO1xuICAgIHJldHVybiB0aGlzLnJlbmRlcmVyXy5oYXNGZWF0dXJlQXRDb29yZGluYXRlKGNvb3JkaW5hdGUsIHRoaXMuZnJhbWVTdGF0ZV8sIGhpdFRvbGVyYW5jZSwgY2hlY2tXcmFwcGVkLCBsYXllckZpbHRlciwgbnVsbCk7XG4gIH07XG4gIC8qKlxuICAgKiBSZXR1cm5zIHRoZSBjb29yZGluYXRlIGluIHVzZXIgcHJvamVjdGlvbiBmb3IgYSBicm93c2VyIGV2ZW50LlxuICAgKiBAcGFyYW0ge01vdXNlRXZlbnR9IGV2ZW50IEV2ZW50LlxuICAgKiBAcmV0dXJuIHtpbXBvcnQoXCIuL2Nvb3JkaW5hdGUuanNcIikuQ29vcmRpbmF0ZX0gQ29vcmRpbmF0ZS5cbiAgICogQGFwaVxuICAgKi9cblxuXG4gIFBsdWdnYWJsZU1hcC5wcm90b3R5cGUuZ2V0RXZlbnRDb29yZGluYXRlID0gZnVuY3Rpb24gKGV2ZW50KSB7XG4gICAgcmV0dXJuIHRoaXMuZ2V0Q29vcmRpbmF0ZUZyb21QaXhlbCh0aGlzLmdldEV2ZW50UGl4ZWwoZXZlbnQpKTtcbiAgfTtcbiAgLyoqXG4gICAqIFJldHVybnMgdGhlIGNvb3JkaW5hdGUgaW4gdmlldyBwcm9qZWN0aW9uIGZvciBhIGJyb3dzZXIgZXZlbnQuXG4gICAqIEBwYXJhbSB7TW91c2VFdmVudH0gZXZlbnQgRXZlbnQuXG4gICAqIEByZXR1cm4ge2ltcG9ydChcIi4vY29vcmRpbmF0ZS5qc1wiKS5Db29yZGluYXRlfSBDb29yZGluYXRlLlxuICAgKi9cblxuXG4gIFBsdWdnYWJsZU1hcC5wcm90b3R5cGUuZ2V0RXZlbnRDb29yZGluYXRlSW50ZXJuYWwgPSBmdW5jdGlvbiAoZXZlbnQpIHtcbiAgICByZXR1cm4gdGhpcy5nZXRDb29yZGluYXRlRnJvbVBpeGVsSW50ZXJuYWwodGhpcy5nZXRFdmVudFBpeGVsKGV2ZW50KSk7XG4gIH07XG4gIC8qKlxuICAgKiBSZXR1cm5zIHRoZSBtYXAgcGl4ZWwgcG9zaXRpb24gZm9yIGEgYnJvd3NlciBldmVudCByZWxhdGl2ZSB0byB0aGUgdmlld3BvcnQuXG4gICAqIEBwYXJhbSB7VUlFdmVudH0gZXZlbnQgRXZlbnQuXG4gICAqIEByZXR1cm4ge2ltcG9ydChcIi4vcGl4ZWwuanNcIikuUGl4ZWx9IFBpeGVsLlxuICAgKiBAYXBpXG4gICAqL1xuXG5cbiAgUGx1Z2dhYmxlTWFwLnByb3RvdHlwZS5nZXRFdmVudFBpeGVsID0gZnVuY3Rpb24gKGV2ZW50KSB7XG4gICAgdmFyIHZpZXdwb3J0UG9zaXRpb24gPSB0aGlzLnZpZXdwb3J0Xy5nZXRCb3VuZGluZ0NsaWVudFJlY3QoKTtcbiAgICB2YXIgZXZlbnRQb3NpdGlvbiA9IC8vRklYTUUgQXJlIHdlIHJlYWxseSBjYWxsaW5nIHRoaXMgd2l0aCBhIFRvdWNoRXZlbnQgYW55d2hlcmU/XG4gICAgJ2NoYW5nZWRUb3VjaGVzJyBpbiBldmVudCA/XG4gICAgLyoqIEB0eXBlIHtUb3VjaEV2ZW50fSAqL1xuICAgIGV2ZW50LmNoYW5nZWRUb3VjaGVzWzBdIDpcbiAgICAvKiogQHR5cGUge01vdXNlRXZlbnR9ICovXG4gICAgZXZlbnQ7XG4gICAgcmV0dXJuIFtldmVudFBvc2l0aW9uLmNsaWVudFggLSB2aWV3cG9ydFBvc2l0aW9uLmxlZnQsIGV2ZW50UG9zaXRpb24uY2xpZW50WSAtIHZpZXdwb3J0UG9zaXRpb24udG9wXTtcbiAgfTtcbiAgLyoqXG4gICAqIEdldCB0aGUgdGFyZ2V0IGluIHdoaWNoIHRoaXMgbWFwIGlzIHJlbmRlcmVkLlxuICAgKiBOb3RlIHRoYXQgdGhpcyByZXR1cm5zIHdoYXQgaXMgZW50ZXJlZCBhcyBhbiBvcHRpb24gb3IgaW4gc2V0VGFyZ2V0OlxuICAgKiBpZiB0aGF0IHdhcyBhbiBlbGVtZW50LCBpdCByZXR1cm5zIGFuIGVsZW1lbnQ7IGlmIGEgc3RyaW5nLCBpdCByZXR1cm5zIHRoYXQuXG4gICAqIEByZXR1cm4ge0hUTUxFbGVtZW50fHN0cmluZ3x1bmRlZmluZWR9IFRoZSBFbGVtZW50IG9yIGlkIG9mIHRoZSBFbGVtZW50IHRoYXQgdGhlXG4gICAqICAgICBtYXAgaXMgcmVuZGVyZWQgaW4uXG4gICAqIEBvYnNlcnZhYmxlXG4gICAqIEBhcGlcbiAgICovXG5cblxuICBQbHVnZ2FibGVNYXAucHJvdG90eXBlLmdldFRhcmdldCA9IGZ1bmN0aW9uICgpIHtcbiAgICByZXR1cm4gKFxuICAgICAgLyoqIEB0eXBlIHtIVE1MRWxlbWVudHxzdHJpbmd8dW5kZWZpbmVkfSAqL1xuICAgICAgdGhpcy5nZXQoTWFwUHJvcGVydHkuVEFSR0VUKVxuICAgICk7XG4gIH07XG4gIC8qKlxuICAgKiBHZXQgdGhlIERPTSBlbGVtZW50IGludG8gd2hpY2ggdGhpcyBtYXAgaXMgcmVuZGVyZWQuIEluIGNvbnRyYXN0IHRvXG4gICAqIGBnZXRUYXJnZXRgIHRoaXMgbWV0aG9kIGFsd2F5cyByZXR1cm4gYW4gYEVsZW1lbnRgLCBvciBgbnVsbGAgaWYgdGhlXG4gICAqIG1hcCBoYXMgbm8gdGFyZ2V0LlxuICAgKiBAcmV0dXJuIHtIVE1MRWxlbWVudH0gVGhlIGVsZW1lbnQgdGhhdCB0aGUgbWFwIGlzIHJlbmRlcmVkIGluLlxuICAgKiBAYXBpXG4gICAqL1xuXG5cbiAgUGx1Z2dhYmxlTWFwLnByb3RvdHlwZS5nZXRUYXJnZXRFbGVtZW50ID0gZnVuY3Rpb24gKCkge1xuICAgIHZhciB0YXJnZXQgPSB0aGlzLmdldFRhcmdldCgpO1xuXG4gICAgaWYgKHRhcmdldCAhPT0gdW5kZWZpbmVkKSB7XG4gICAgICByZXR1cm4gdHlwZW9mIHRhcmdldCA9PT0gJ3N0cmluZycgPyBkb2N1bWVudC5nZXRFbGVtZW50QnlJZCh0YXJnZXQpIDogdGFyZ2V0O1xuICAgIH0gZWxzZSB7XG4gICAgICByZXR1cm4gbnVsbDtcbiAgICB9XG4gIH07XG4gIC8qKlxuICAgKiBHZXQgdGhlIGNvb3JkaW5hdGUgZm9yIGEgZ2l2ZW4gcGl4ZWwuICBUaGlzIHJldHVybnMgYSBjb29yZGluYXRlIGluIHRoZVxuICAgKiB1c2VyIHByb2plY3Rpb24uXG4gICAqIEBwYXJhbSB7aW1wb3J0KFwiLi9waXhlbC5qc1wiKS5QaXhlbH0gcGl4ZWwgUGl4ZWwgcG9zaXRpb24gaW4gdGhlIG1hcCB2aWV3cG9ydC5cbiAgICogQHJldHVybiB7aW1wb3J0KFwiLi9jb29yZGluYXRlLmpzXCIpLkNvb3JkaW5hdGV9IFRoZSBjb29yZGluYXRlIGZvciB0aGUgcGl4ZWwgcG9zaXRpb24uXG4gICAqIEBhcGlcbiAgICovXG5cblxuICBQbHVnZ2FibGVNYXAucHJvdG90eXBlLmdldENvb3JkaW5hdGVGcm9tUGl4ZWwgPSBmdW5jdGlvbiAocGl4ZWwpIHtcbiAgICByZXR1cm4gdG9Vc2VyQ29vcmRpbmF0ZSh0aGlzLmdldENvb3JkaW5hdGVGcm9tUGl4ZWxJbnRlcm5hbChwaXhlbCksIHRoaXMuZ2V0VmlldygpLmdldFByb2plY3Rpb24oKSk7XG4gIH07XG4gIC8qKlxuICAgKiBHZXQgdGhlIGNvb3JkaW5hdGUgZm9yIGEgZ2l2ZW4gcGl4ZWwuICBUaGlzIHJldHVybnMgYSBjb29yZGluYXRlIGluIHRoZVxuICAgKiBtYXAgdmlldyBwcm9qZWN0aW9uLlxuICAgKiBAcGFyYW0ge2ltcG9ydChcIi4vcGl4ZWwuanNcIikuUGl4ZWx9IHBpeGVsIFBpeGVsIHBvc2l0aW9uIGluIHRoZSBtYXAgdmlld3BvcnQuXG4gICAqIEByZXR1cm4ge2ltcG9ydChcIi4vY29vcmRpbmF0ZS5qc1wiKS5Db29yZGluYXRlfSBUaGUgY29vcmRpbmF0ZSBmb3IgdGhlIHBpeGVsIHBvc2l0aW9uLlxuICAgKi9cblxuXG4gIFBsdWdnYWJsZU1hcC5wcm90b3R5cGUuZ2V0Q29vcmRpbmF0ZUZyb21QaXhlbEludGVybmFsID0gZnVuY3Rpb24gKHBpeGVsKSB7XG4gICAgdmFyIGZyYW1lU3RhdGUgPSB0aGlzLmZyYW1lU3RhdGVfO1xuXG4gICAgaWYgKCFmcmFtZVN0YXRlKSB7XG4gICAgICByZXR1cm4gbnVsbDtcbiAgICB9IGVsc2Uge1xuICAgICAgcmV0dXJuIGFwcGx5VHJhbnNmb3JtKGZyYW1lU3RhdGUucGl4ZWxUb0Nvb3JkaW5hdGVUcmFuc2Zvcm0sIHBpeGVsLnNsaWNlKCkpO1xuICAgIH1cbiAgfTtcbiAgLyoqXG4gICAqIEdldCB0aGUgbWFwIGNvbnRyb2xzLiBNb2RpZnlpbmcgdGhpcyBjb2xsZWN0aW9uIGNoYW5nZXMgdGhlIGNvbnRyb2xzXG4gICAqIGFzc29jaWF0ZWQgd2l0aCB0aGUgbWFwLlxuICAgKiBAcmV0dXJuIHtDb2xsZWN0aW9uPGltcG9ydChcIi4vY29udHJvbC9Db250cm9sLmpzXCIpLmRlZmF1bHQ+fSBDb250cm9scy5cbiAgICogQGFwaVxuICAgKi9cblxuXG4gIFBsdWdnYWJsZU1hcC5wcm90b3R5cGUuZ2V0Q29udHJvbHMgPSBmdW5jdGlvbiAoKSB7XG4gICAgcmV0dXJuIHRoaXMuY29udHJvbHM7XG4gIH07XG4gIC8qKlxuICAgKiBHZXQgdGhlIG1hcCBvdmVybGF5cy4gTW9kaWZ5aW5nIHRoaXMgY29sbGVjdGlvbiBjaGFuZ2VzIHRoZSBvdmVybGF5c1xuICAgKiBhc3NvY2lhdGVkIHdpdGggdGhlIG1hcC5cbiAgICogQHJldHVybiB7Q29sbGVjdGlvbjxpbXBvcnQoXCIuL092ZXJsYXkuanNcIikuZGVmYXVsdD59IE92ZXJsYXlzLlxuICAgKiBAYXBpXG4gICAqL1xuXG5cbiAgUGx1Z2dhYmxlTWFwLnByb3RvdHlwZS5nZXRPdmVybGF5cyA9IGZ1bmN0aW9uICgpIHtcbiAgICByZXR1cm4gdGhpcy5vdmVybGF5c187XG4gIH07XG4gIC8qKlxuICAgKiBHZXQgYW4gb3ZlcmxheSBieSBpdHMgaWRlbnRpZmllciAodGhlIHZhbHVlIHJldHVybmVkIGJ5IG92ZXJsYXkuZ2V0SWQoKSkuXG4gICAqIE5vdGUgdGhhdCB0aGUgaW5kZXggdHJlYXRzIHN0cmluZyBhbmQgbnVtZXJpYyBpZGVudGlmaWVycyBhcyB0aGUgc2FtZS4gU29cbiAgICogYG1hcC5nZXRPdmVybGF5QnlJZCgyKWAgd2lsbCByZXR1cm4gYW4gb3ZlcmxheSB3aXRoIGlkIGAnMidgIG9yIGAyYC5cbiAgICogQHBhcmFtIHtzdHJpbmd8bnVtYmVyfSBpZCBPdmVybGF5IGlkZW50aWZpZXIuXG4gICAqIEByZXR1cm4ge2ltcG9ydChcIi4vT3ZlcmxheS5qc1wiKS5kZWZhdWx0fSBPdmVybGF5LlxuICAgKiBAYXBpXG4gICAqL1xuXG5cbiAgUGx1Z2dhYmxlTWFwLnByb3RvdHlwZS5nZXRPdmVybGF5QnlJZCA9IGZ1bmN0aW9uIChpZCkge1xuICAgIHZhciBvdmVybGF5ID0gdGhpcy5vdmVybGF5SWRJbmRleF9baWQudG9TdHJpbmcoKV07XG4gICAgcmV0dXJuIG92ZXJsYXkgIT09IHVuZGVmaW5lZCA/IG92ZXJsYXkgOiBudWxsO1xuICB9O1xuICAvKipcbiAgICogR2V0IHRoZSBtYXAgaW50ZXJhY3Rpb25zLiBNb2RpZnlpbmcgdGhpcyBjb2xsZWN0aW9uIGNoYW5nZXMgdGhlIGludGVyYWN0aW9uc1xuICAgKiBhc3NvY2lhdGVkIHdpdGggdGhlIG1hcC5cbiAgICpcbiAgICogSW50ZXJhY3Rpb25zIGFyZSB1c2VkIGZvciBlLmcuIHBhbiwgem9vbSBhbmQgcm90YXRlLlxuICAgKiBAcmV0dXJuIHtDb2xsZWN0aW9uPGltcG9ydChcIi4vaW50ZXJhY3Rpb24vSW50ZXJhY3Rpb24uanNcIikuZGVmYXVsdD59IEludGVyYWN0aW9ucy5cbiAgICogQGFwaVxuICAgKi9cblxuXG4gIFBsdWdnYWJsZU1hcC5wcm90b3R5cGUuZ2V0SW50ZXJhY3Rpb25zID0gZnVuY3Rpb24gKCkge1xuICAgIHJldHVybiB0aGlzLmludGVyYWN0aW9ucztcbiAgfTtcbiAgLyoqXG4gICAqIEdldCB0aGUgbGF5ZXJncm91cCBhc3NvY2lhdGVkIHdpdGggdGhpcyBtYXAuXG4gICAqIEByZXR1cm4ge0xheWVyR3JvdXB9IEEgbGF5ZXIgZ3JvdXAgY29udGFpbmluZyB0aGUgbGF5ZXJzIGluIHRoaXMgbWFwLlxuICAgKiBAb2JzZXJ2YWJsZVxuICAgKiBAYXBpXG4gICAqL1xuXG5cbiAgUGx1Z2dhYmxlTWFwLnByb3RvdHlwZS5nZXRMYXllckdyb3VwID0gZnVuY3Rpb24gKCkge1xuICAgIHJldHVybiAoXG4gICAgICAvKiogQHR5cGUge0xheWVyR3JvdXB9ICovXG4gICAgICB0aGlzLmdldChNYXBQcm9wZXJ0eS5MQVlFUkdST1VQKVxuICAgICk7XG4gIH07XG4gIC8qKlxuICAgKiBHZXQgdGhlIGNvbGxlY3Rpb24gb2YgbGF5ZXJzIGFzc29jaWF0ZWQgd2l0aCB0aGlzIG1hcC5cbiAgICogQHJldHVybiB7IUNvbGxlY3Rpb248aW1wb3J0KFwiLi9sYXllci9CYXNlLmpzXCIpLmRlZmF1bHQ+fSBMYXllcnMuXG4gICAqIEBhcGlcbiAgICovXG5cblxuICBQbHVnZ2FibGVNYXAucHJvdG90eXBlLmdldExheWVycyA9IGZ1bmN0aW9uICgpIHtcbiAgICB2YXIgbGF5ZXJzID0gdGhpcy5nZXRMYXllckdyb3VwKCkuZ2V0TGF5ZXJzKCk7XG4gICAgcmV0dXJuIGxheWVycztcbiAgfTtcbiAgLyoqXG4gICAqIEByZXR1cm4ge2Jvb2xlYW59IExheWVycyBoYXZlIHNvdXJjZXMgdGhhdCBhcmUgc3RpbGwgbG9hZGluZy5cbiAgICovXG5cblxuICBQbHVnZ2FibGVNYXAucHJvdG90eXBlLmdldExvYWRpbmcgPSBmdW5jdGlvbiAoKSB7XG4gICAgdmFyIGxheWVyU3RhdGVzQXJyYXkgPSB0aGlzLmdldExheWVyR3JvdXAoKS5nZXRMYXllclN0YXRlc0FycmF5KCk7XG5cbiAgICBmb3IgKHZhciBpID0gMCwgaWkgPSBsYXllclN0YXRlc0FycmF5Lmxlbmd0aDsgaSA8IGlpOyArK2kpIHtcbiAgICAgIHZhciBsYXllciA9IGxheWVyU3RhdGVzQXJyYXlbaV0ubGF5ZXI7XG4gICAgICB2YXIgc291cmNlID1cbiAgICAgIC8qKiBAdHlwZSB7aW1wb3J0KFwiLi9sYXllci9MYXllci5qc1wiKS5kZWZhdWx0fSAqL1xuICAgICAgbGF5ZXIuZ2V0U291cmNlKCk7XG5cbiAgICAgIGlmIChzb3VyY2UgJiYgc291cmNlLmxvYWRpbmcpIHtcbiAgICAgICAgcmV0dXJuIHRydWU7XG4gICAgICB9XG4gICAgfVxuXG4gICAgcmV0dXJuIGZhbHNlO1xuICB9O1xuICAvKipcbiAgICogR2V0IHRoZSBwaXhlbCBmb3IgYSBjb29yZGluYXRlLiAgVGhpcyB0YWtlcyBhIGNvb3JkaW5hdGUgaW4gdGhlIHVzZXJcbiAgICogcHJvamVjdGlvbiBhbmQgcmV0dXJucyB0aGUgY29ycmVzcG9uZGluZyBwaXhlbC5cbiAgICogQHBhcmFtIHtpbXBvcnQoXCIuL2Nvb3JkaW5hdGUuanNcIikuQ29vcmRpbmF0ZX0gY29vcmRpbmF0ZSBBIG1hcCBjb29yZGluYXRlLlxuICAgKiBAcmV0dXJuIHtpbXBvcnQoXCIuL3BpeGVsLmpzXCIpLlBpeGVsfSBBIHBpeGVsIHBvc2l0aW9uIGluIHRoZSBtYXAgdmlld3BvcnQuXG4gICAqIEBhcGlcbiAgICovXG5cblxuICBQbHVnZ2FibGVNYXAucHJvdG90eXBlLmdldFBpeGVsRnJvbUNvb3JkaW5hdGUgPSBmdW5jdGlvbiAoY29vcmRpbmF0ZSkge1xuICAgIHZhciB2aWV3Q29vcmRpbmF0ZSA9IGZyb21Vc2VyQ29vcmRpbmF0ZShjb29yZGluYXRlLCB0aGlzLmdldFZpZXcoKS5nZXRQcm9qZWN0aW9uKCkpO1xuICAgIHJldHVybiB0aGlzLmdldFBpeGVsRnJvbUNvb3JkaW5hdGVJbnRlcm5hbCh2aWV3Q29vcmRpbmF0ZSk7XG4gIH07XG4gIC8qKlxuICAgKiBHZXQgdGhlIHBpeGVsIGZvciBhIGNvb3JkaW5hdGUuICBUaGlzIHRha2VzIGEgY29vcmRpbmF0ZSBpbiB0aGUgbWFwIHZpZXdcbiAgICogcHJvamVjdGlvbiBhbmQgcmV0dXJucyB0aGUgY29ycmVzcG9uZGluZyBwaXhlbC5cbiAgICogQHBhcmFtIHtpbXBvcnQoXCIuL2Nvb3JkaW5hdGUuanNcIikuQ29vcmRpbmF0ZX0gY29vcmRpbmF0ZSBBIG1hcCBjb29yZGluYXRlLlxuICAgKiBAcmV0dXJuIHtpbXBvcnQoXCIuL3BpeGVsLmpzXCIpLlBpeGVsfSBBIHBpeGVsIHBvc2l0aW9uIGluIHRoZSBtYXAgdmlld3BvcnQuXG4gICAqL1xuXG5cbiAgUGx1Z2dhYmxlTWFwLnByb3RvdHlwZS5nZXRQaXhlbEZyb21Db29yZGluYXRlSW50ZXJuYWwgPSBmdW5jdGlvbiAoY29vcmRpbmF0ZSkge1xuICAgIHZhciBmcmFtZVN0YXRlID0gdGhpcy5mcmFtZVN0YXRlXztcblxuICAgIGlmICghZnJhbWVTdGF0ZSkge1xuICAgICAgcmV0dXJuIG51bGw7XG4gICAgfSBlbHNlIHtcbiAgICAgIHJldHVybiBhcHBseVRyYW5zZm9ybShmcmFtZVN0YXRlLmNvb3JkaW5hdGVUb1BpeGVsVHJhbnNmb3JtLCBjb29yZGluYXRlLnNsaWNlKDAsIDIpKTtcbiAgICB9XG4gIH07XG4gIC8qKlxuICAgKiBHZXQgdGhlIG1hcCByZW5kZXJlci5cbiAgICogQHJldHVybiB7aW1wb3J0KFwiLi9yZW5kZXJlci9NYXAuanNcIikuZGVmYXVsdH0gUmVuZGVyZXJcbiAgICovXG5cblxuICBQbHVnZ2FibGVNYXAucHJvdG90eXBlLmdldFJlbmRlcmVyID0gZnVuY3Rpb24gKCkge1xuICAgIHJldHVybiB0aGlzLnJlbmRlcmVyXztcbiAgfTtcbiAgLyoqXG4gICAqIEdldCB0aGUgc2l6ZSBvZiB0aGlzIG1hcC5cbiAgICogQHJldHVybiB7aW1wb3J0KFwiLi9zaXplLmpzXCIpLlNpemV8dW5kZWZpbmVkfSBUaGUgc2l6ZSBpbiBwaXhlbHMgb2YgdGhlIG1hcCBpbiB0aGUgRE9NLlxuICAgKiBAb2JzZXJ2YWJsZVxuICAgKiBAYXBpXG4gICAqL1xuXG5cbiAgUGx1Z2dhYmxlTWFwLnByb3RvdHlwZS5nZXRTaXplID0gZnVuY3Rpb24gKCkge1xuICAgIHJldHVybiAoXG4gICAgICAvKiogQHR5cGUge2ltcG9ydChcIi4vc2l6ZS5qc1wiKS5TaXplfHVuZGVmaW5lZH0gKi9cbiAgICAgIHRoaXMuZ2V0KE1hcFByb3BlcnR5LlNJWkUpXG4gICAgKTtcbiAgfTtcbiAgLyoqXG4gICAqIEdldCB0aGUgdmlldyBhc3NvY2lhdGVkIHdpdGggdGhpcyBtYXAuIEEgdmlldyBtYW5hZ2VzIHByb3BlcnRpZXMgc3VjaCBhc1xuICAgKiBjZW50ZXIgYW5kIHJlc29sdXRpb24uXG4gICAqIEByZXR1cm4ge1ZpZXd9IFRoZSB2aWV3IHRoYXQgY29udHJvbHMgdGhpcyBtYXAuXG4gICAqIEBvYnNlcnZhYmxlXG4gICAqIEBhcGlcbiAgICovXG5cblxuICBQbHVnZ2FibGVNYXAucHJvdG90eXBlLmdldFZpZXcgPSBmdW5jdGlvbiAoKSB7XG4gICAgcmV0dXJuIChcbiAgICAgIC8qKiBAdHlwZSB7Vmlld30gKi9cbiAgICAgIHRoaXMuZ2V0KE1hcFByb3BlcnR5LlZJRVcpXG4gICAgKTtcbiAgfTtcbiAgLyoqXG4gICAqIEdldCB0aGUgZWxlbWVudCB0aGF0IHNlcnZlcyBhcyB0aGUgbWFwIHZpZXdwb3J0LlxuICAgKiBAcmV0dXJuIHtIVE1MRWxlbWVudH0gVmlld3BvcnQuXG4gICAqIEBhcGlcbiAgICovXG5cblxuICBQbHVnZ2FibGVNYXAucHJvdG90eXBlLmdldFZpZXdwb3J0ID0gZnVuY3Rpb24gKCkge1xuICAgIHJldHVybiB0aGlzLnZpZXdwb3J0XztcbiAgfTtcbiAgLyoqXG4gICAqIEdldCB0aGUgZWxlbWVudCB0aGF0IHNlcnZlcyBhcyB0aGUgY29udGFpbmVyIGZvciBvdmVybGF5cy4gIEVsZW1lbnRzIGFkZGVkIHRvXG4gICAqIHRoaXMgY29udGFpbmVyIHdpbGwgbGV0IG1vdXNlZG93biBhbmQgdG91Y2hzdGFydCBldmVudHMgdGhyb3VnaCB0byB0aGUgbWFwLFxuICAgKiBzbyBjbGlja3MgYW5kIGdlc3R1cmVzIG9uIGFuIG92ZXJsYXkgd2lsbCB0cmlnZ2VyIHtAbGluayBtb2R1bGU6b2wvTWFwQnJvd3NlckV2ZW50fk1hcEJyb3dzZXJFdmVudH1cbiAgICogZXZlbnRzLlxuICAgKiBAcmV0dXJuIHshSFRNTEVsZW1lbnR9IFRoZSBtYXAncyBvdmVybGF5IGNvbnRhaW5lci5cbiAgICovXG5cblxuICBQbHVnZ2FibGVNYXAucHJvdG90eXBlLmdldE92ZXJsYXlDb250YWluZXIgPSBmdW5jdGlvbiAoKSB7XG4gICAgcmV0dXJuIHRoaXMub3ZlcmxheUNvbnRhaW5lcl87XG4gIH07XG4gIC8qKlxuICAgKiBHZXQgdGhlIGVsZW1lbnQgdGhhdCBzZXJ2ZXMgYXMgYSBjb250YWluZXIgZm9yIG92ZXJsYXlzIHRoYXQgZG9uJ3QgYWxsb3dcbiAgICogZXZlbnQgcHJvcGFnYXRpb24uIEVsZW1lbnRzIGFkZGVkIHRvIHRoaXMgY29udGFpbmVyIHdvbid0IGxldCBtb3VzZWRvd24gYW5kXG4gICAqIHRvdWNoc3RhcnQgZXZlbnRzIHRocm91Z2ggdG8gdGhlIG1hcCwgc28gY2xpY2tzIGFuZCBnZXN0dXJlcyBvbiBhbiBvdmVybGF5XG4gICAqIGRvbid0IHRyaWdnZXIgYW55IHtAbGluayBtb2R1bGU6b2wvTWFwQnJvd3NlckV2ZW50fk1hcEJyb3dzZXJFdmVudH0uXG4gICAqIEByZXR1cm4geyFIVE1MRWxlbWVudH0gVGhlIG1hcCdzIG92ZXJsYXkgY29udGFpbmVyIHRoYXQgc3RvcHMgZXZlbnRzLlxuICAgKi9cblxuXG4gIFBsdWdnYWJsZU1hcC5wcm90b3R5cGUuZ2V0T3ZlcmxheUNvbnRhaW5lclN0b3BFdmVudCA9IGZ1bmN0aW9uICgpIHtcbiAgICByZXR1cm4gdGhpcy5vdmVybGF5Q29udGFpbmVyU3RvcEV2ZW50XztcbiAgfTtcbiAgLyoqXG4gICAqIEByZXR1cm4geyFEb2N1bWVudH0gVGhlIGRvY3VtZW50IHdoZXJlIHRoZSBtYXAgaXMgZGlzcGxheWVkLlxuICAgKi9cblxuXG4gIFBsdWdnYWJsZU1hcC5wcm90b3R5cGUuZ2V0T3duZXJEb2N1bWVudCA9IGZ1bmN0aW9uICgpIHtcbiAgICByZXR1cm4gdGhpcy5nZXRUYXJnZXRFbGVtZW50KCkgPyB0aGlzLmdldFRhcmdldEVsZW1lbnQoKS5vd25lckRvY3VtZW50IDogZG9jdW1lbnQ7XG4gIH07XG4gIC8qKlxuICAgKiBAcGFyYW0ge2ltcG9ydChcIi4vVGlsZS5qc1wiKS5kZWZhdWx0fSB0aWxlIFRpbGUuXG4gICAqIEBwYXJhbSB7c3RyaW5nfSB0aWxlU291cmNlS2V5IFRpbGUgc291cmNlIGtleS5cbiAgICogQHBhcmFtIHtpbXBvcnQoXCIuL2Nvb3JkaW5hdGUuanNcIikuQ29vcmRpbmF0ZX0gdGlsZUNlbnRlciBUaWxlIGNlbnRlci5cbiAgICogQHBhcmFtIHtudW1iZXJ9IHRpbGVSZXNvbHV0aW9uIFRpbGUgcmVzb2x1dGlvbi5cbiAgICogQHJldHVybiB7bnVtYmVyfSBUaWxlIHByaW9yaXR5LlxuICAgKi9cblxuXG4gIFBsdWdnYWJsZU1hcC5wcm90b3R5cGUuZ2V0VGlsZVByaW9yaXR5ID0gZnVuY3Rpb24gKHRpbGUsIHRpbGVTb3VyY2VLZXksIHRpbGVDZW50ZXIsIHRpbGVSZXNvbHV0aW9uKSB7XG4gICAgcmV0dXJuIGdldFRpbGVQcmlvcml0eSh0aGlzLmZyYW1lU3RhdGVfLCB0aWxlLCB0aWxlU291cmNlS2V5LCB0aWxlQ2VudGVyLCB0aWxlUmVzb2x1dGlvbik7XG4gIH07XG4gIC8qKlxuICAgKiBAcGFyYW0ge1VJRXZlbnR9IGJyb3dzZXJFdmVudCBCcm93c2VyIGV2ZW50LlxuICAgKiBAcGFyYW0ge3N0cmluZz19IG9wdF90eXBlIFR5cGUuXG4gICAqL1xuXG5cbiAgUGx1Z2dhYmxlTWFwLnByb3RvdHlwZS5oYW5kbGVCcm93c2VyRXZlbnQgPSBmdW5jdGlvbiAoYnJvd3NlckV2ZW50LCBvcHRfdHlwZSkge1xuICAgIHZhciB0eXBlID0gb3B0X3R5cGUgfHwgYnJvd3NlckV2ZW50LnR5cGU7XG4gICAgdmFyIG1hcEJyb3dzZXJFdmVudCA9IG5ldyBNYXBCcm93c2VyRXZlbnQodHlwZSwgdGhpcywgYnJvd3NlckV2ZW50KTtcbiAgICB0aGlzLmhhbmRsZU1hcEJyb3dzZXJFdmVudChtYXBCcm93c2VyRXZlbnQpO1xuICB9O1xuICAvKipcbiAgICogQHBhcmFtIHtNYXBCcm93c2VyRXZlbnR9IG1hcEJyb3dzZXJFdmVudCBUaGUgZXZlbnQgdG8gaGFuZGxlLlxuICAgKi9cblxuXG4gIFBsdWdnYWJsZU1hcC5wcm90b3R5cGUuaGFuZGxlTWFwQnJvd3NlckV2ZW50ID0gZnVuY3Rpb24gKG1hcEJyb3dzZXJFdmVudCkge1xuICAgIGlmICghdGhpcy5mcmFtZVN0YXRlXykge1xuICAgICAgLy8gV2l0aCBubyB2aWV3IGRlZmluZWQsIHdlIGNhbm5vdCB0cmFuc2xhdGUgcGl4ZWxzIGludG8gZ2VvZ3JhcGhpY2FsXG4gICAgICAvLyBjb29yZGluYXRlcyBzbyBpbnRlcmFjdGlvbnMgY2Fubm90IGJlIHVzZWQuXG4gICAgICByZXR1cm47XG4gICAgfVxuXG4gICAgdmFyIG9yaWdpbmFsRXZlbnQgPVxuICAgIC8qKiBAdHlwZSB7UG9pbnRlckV2ZW50fSAqL1xuICAgIG1hcEJyb3dzZXJFdmVudC5vcmlnaW5hbEV2ZW50O1xuICAgIHZhciBldmVudFR5cGUgPSBvcmlnaW5hbEV2ZW50LnR5cGU7XG5cbiAgICBpZiAoZXZlbnRUeXBlID09PSBQb2ludGVyRXZlbnRUeXBlLlBPSU5URVJET1dOIHx8IGV2ZW50VHlwZSA9PT0gRXZlbnRUeXBlLldIRUVMIHx8IGV2ZW50VHlwZSA9PT0gRXZlbnRUeXBlLktFWURPV04pIHtcbiAgICAgIHZhciBkb2MgPSB0aGlzLmdldE93bmVyRG9jdW1lbnQoKTtcbiAgICAgIHZhciByb290Tm9kZSA9IHRoaXMudmlld3BvcnRfLmdldFJvb3ROb2RlID8gdGhpcy52aWV3cG9ydF8uZ2V0Um9vdE5vZGUoKSA6IGRvYztcbiAgICAgIHZhciB0YXJnZXQgPSAnaG9zdCcgaW4gcm9vdE5vZGUgLy8gU2hhZG93Um9vdFxuICAgICAgP1xuICAgICAgLyoqIEB0eXBlIHtTaGFkb3dSb290fSAqL1xuICAgICAgcm9vdE5vZGUuZWxlbWVudEZyb21Qb2ludChvcmlnaW5hbEV2ZW50LmNsaWVudFgsIG9yaWdpbmFsRXZlbnQuY2xpZW50WSkgOlxuICAgICAgLyoqIEB0eXBlIHtOb2RlfSAqL1xuICAgICAgb3JpZ2luYWxFdmVudC50YXJnZXQ7XG5cbiAgICAgIGlmICggLy8gQWJvcnQgaWYgdGhlIHRhcmdldCBpcyBhIGNoaWxkIG9mIHRoZSBjb250YWluZXIgZm9yIGVsZW1lbnRzIHdob3NlIGV2ZW50cyBhcmUgbm90IG1lYW50XG4gICAgICAvLyB0byBiZSBoYW5kbGVkIGJ5IG1hcCBpbnRlcmFjdGlvbnMuXG4gICAgICB0aGlzLm92ZXJsYXlDb250YWluZXJTdG9wRXZlbnRfLmNvbnRhaW5zKHRhcmdldCkgfHwgLy8gQWJvcnQgaWYgdGhlIGV2ZW50IHRhcmdldCBpcyBhIGNoaWxkIG9mIHRoZSBjb250YWluZXIgdGhhdCBpcyBubyBsb25nZXIgaW4gdGhlIHBhZ2UuXG4gICAgICAvLyBJdCdzIHBvc3NpYmxlIGZvciB0aGUgdGFyZ2V0IHRvIG5vIGxvbmdlciBiZSBpbiB0aGUgcGFnZSBpZiBpdCBoYXMgYmVlbiByZW1vdmVkIGluIGFuXG4gICAgICAvLyBldmVudCBsaXN0ZW5lciwgdGhpcyBtaWdodCBoYXBwZW4gaW4gYSBDb250cm9sIHRoYXQgcmVjcmVhdGVzIGl0J3MgY29udGVudCBiYXNlZCBvblxuICAgICAgLy8gdXNlciBpbnRlcmFjdGlvbiBlaXRoZXIgbWFudWFsbHkgb3IgdmlhIGEgcmVuZGVyIGluIHNvbWV0aGluZyBsaWtlIGh0dHBzOi8vcmVhY3Rqcy5vcmcvXG4gICAgICAhKHJvb3ROb2RlID09PSBkb2MgPyBkb2MuZG9jdW1lbnRFbGVtZW50IDogcm9vdE5vZGUpLmNvbnRhaW5zKHRhcmdldCkpIHtcbiAgICAgICAgcmV0dXJuO1xuICAgICAgfVxuICAgIH1cblxuICAgIG1hcEJyb3dzZXJFdmVudC5mcmFtZVN0YXRlID0gdGhpcy5mcmFtZVN0YXRlXztcblxuICAgIGlmICh0aGlzLmRpc3BhdGNoRXZlbnQobWFwQnJvd3NlckV2ZW50KSAhPT0gZmFsc2UpIHtcbiAgICAgIHZhciBpbnRlcmFjdGlvbnNBcnJheSA9IHRoaXMuZ2V0SW50ZXJhY3Rpb25zKCkuZ2V0QXJyYXkoKS5zbGljZSgpO1xuXG4gICAgICBmb3IgKHZhciBpID0gaW50ZXJhY3Rpb25zQXJyYXkubGVuZ3RoIC0gMTsgaSA+PSAwOyBpLS0pIHtcbiAgICAgICAgdmFyIGludGVyYWN0aW9uID0gaW50ZXJhY3Rpb25zQXJyYXlbaV07XG5cbiAgICAgICAgaWYgKGludGVyYWN0aW9uLmdldE1hcCgpICE9PSB0aGlzIHx8ICFpbnRlcmFjdGlvbi5nZXRBY3RpdmUoKSB8fCAhdGhpcy5nZXRUYXJnZXRFbGVtZW50KCkpIHtcbiAgICAgICAgICBjb250aW51ZTtcbiAgICAgICAgfVxuXG4gICAgICAgIHZhciBjb250ID0gaW50ZXJhY3Rpb24uaGFuZGxlRXZlbnQobWFwQnJvd3NlckV2ZW50KTtcblxuICAgICAgICBpZiAoIWNvbnQgfHwgbWFwQnJvd3NlckV2ZW50LnByb3BhZ2F0aW9uU3RvcHBlZCkge1xuICAgICAgICAgIGJyZWFrO1xuICAgICAgICB9XG4gICAgICB9XG4gICAgfVxuICB9O1xuICAvKipcbiAgICogQHByb3RlY3RlZFxuICAgKi9cblxuXG4gIFBsdWdnYWJsZU1hcC5wcm90b3R5cGUuaGFuZGxlUG9zdFJlbmRlciA9IGZ1bmN0aW9uICgpIHtcbiAgICB2YXIgZnJhbWVTdGF0ZSA9IHRoaXMuZnJhbWVTdGF0ZV87IC8vIE1hbmFnZSB0aGUgdGlsZSBxdWV1ZVxuICAgIC8vIEltYWdlIGxvYWRzIGFyZSBleHBlbnNpdmUgYW5kIGEgbGltaXRlZCByZXNvdXJjZSwgc28gdHJ5IHRvIHVzZSB0aGVtXG4gICAgLy8gZWZmaWNpZW50bHk6XG4gICAgLy8gKiBXaGVuIHRoZSB2aWV3IGlzIHN0YXRpYyB3ZSBhbGxvdyBhIGxhcmdlIG51bWJlciBvZiBwYXJhbGxlbCB0aWxlIGxvYWRzXG4gICAgLy8gICB0byBjb21wbGV0ZSB0aGUgZnJhbWUgYXMgcXVpY2tseSBhcyBwb3NzaWJsZS5cbiAgICAvLyAqIFdoZW4gYW5pbWF0aW5nIG9yIGludGVyYWN0aW5nLCBpbWFnZSBsb2FkcyBjYW4gY2F1c2UgamFua3MsIHNvIHdlIHJlZHVjZVxuICAgIC8vICAgdGhlIG1heGltdW0gbnVtYmVyIG9mIGxvYWRzIHBlciBmcmFtZSBhbmQgbGltaXQgdGhlIG51bWJlciBvZiBwYXJhbGxlbFxuICAgIC8vICAgdGlsZSBsb2FkcyB0byByZW1haW4gcmVhY3RpdmUgdG8gdmlldyBjaGFuZ2VzIGFuZCB0byByZWR1Y2UgdGhlIGNoYW5jZSBvZlxuICAgIC8vICAgbG9hZGluZyB0aWxlcyB0aGF0IHdpbGwgcXVpY2tseSBkaXNhcHBlYXIgZnJvbSB2aWV3LlxuXG4gICAgdmFyIHRpbGVRdWV1ZSA9IHRoaXMudGlsZVF1ZXVlXztcblxuICAgIGlmICghdGlsZVF1ZXVlLmlzRW1wdHkoKSkge1xuICAgICAgdmFyIG1heFRvdGFsTG9hZGluZyA9IHRoaXMubWF4VGlsZXNMb2FkaW5nXztcbiAgICAgIHZhciBtYXhOZXdMb2FkcyA9IG1heFRvdGFsTG9hZGluZztcblxuICAgICAgaWYgKGZyYW1lU3RhdGUpIHtcbiAgICAgICAgdmFyIGhpbnRzID0gZnJhbWVTdGF0ZS52aWV3SGludHM7XG5cbiAgICAgICAgaWYgKGhpbnRzW1ZpZXdIaW50LkFOSU1BVElOR10gfHwgaGludHNbVmlld0hpbnQuSU5URVJBQ1RJTkddKSB7XG4gICAgICAgICAgdmFyIGxvd09uRnJhbWVCdWRnZXQgPSAhSU1BR0VfREVDT0RFICYmIERhdGUubm93KCkgLSBmcmFtZVN0YXRlLnRpbWUgPiA4O1xuICAgICAgICAgIG1heFRvdGFsTG9hZGluZyA9IGxvd09uRnJhbWVCdWRnZXQgPyAwIDogODtcbiAgICAgICAgICBtYXhOZXdMb2FkcyA9IGxvd09uRnJhbWVCdWRnZXQgPyAwIDogMjtcbiAgICAgICAgfVxuICAgICAgfVxuXG4gICAgICBpZiAodGlsZVF1ZXVlLmdldFRpbGVzTG9hZGluZygpIDwgbWF4VG90YWxMb2FkaW5nKSB7XG4gICAgICAgIHRpbGVRdWV1ZS5yZXByaW9yaXRpemUoKTsgLy8gRklYTUUgb25seSBjYWxsIGlmIHZpZXcgaGFzIGNoYW5nZWRcblxuICAgICAgICB0aWxlUXVldWUubG9hZE1vcmVUaWxlcyhtYXhUb3RhbExvYWRpbmcsIG1heE5ld0xvYWRzKTtcbiAgICAgIH1cbiAgICB9XG5cbiAgICBpZiAoZnJhbWVTdGF0ZSAmJiB0aGlzLmhhc0xpc3RlbmVyKFJlbmRlckV2ZW50VHlwZS5SRU5ERVJDT01QTEVURSkgJiYgIWZyYW1lU3RhdGUuYW5pbWF0ZSAmJiAhdGhpcy50aWxlUXVldWVfLmdldFRpbGVzTG9hZGluZygpICYmICF0aGlzLmdldExvYWRpbmcoKSkge1xuICAgICAgdGhpcy5yZW5kZXJlcl8uZGlzcGF0Y2hSZW5kZXJFdmVudChSZW5kZXJFdmVudFR5cGUuUkVOREVSQ09NUExFVEUsIGZyYW1lU3RhdGUpO1xuICAgIH1cblxuICAgIHZhciBwb3N0UmVuZGVyRnVuY3Rpb25zID0gdGhpcy5wb3N0UmVuZGVyRnVuY3Rpb25zXztcblxuICAgIGZvciAodmFyIGkgPSAwLCBpaSA9IHBvc3RSZW5kZXJGdW5jdGlvbnMubGVuZ3RoOyBpIDwgaWk7ICsraSkge1xuICAgICAgcG9zdFJlbmRlckZ1bmN0aW9uc1tpXSh0aGlzLCBmcmFtZVN0YXRlKTtcbiAgICB9XG5cbiAgICBwb3N0UmVuZGVyRnVuY3Rpb25zLmxlbmd0aCA9IDA7XG4gIH07XG4gIC8qKlxuICAgKiBAcHJpdmF0ZVxuICAgKi9cblxuXG4gIFBsdWdnYWJsZU1hcC5wcm90b3R5cGUuaGFuZGxlU2l6ZUNoYW5nZWRfID0gZnVuY3Rpb24gKCkge1xuICAgIGlmICh0aGlzLmdldFZpZXcoKSAmJiAhdGhpcy5nZXRWaWV3KCkuZ2V0QW5pbWF0aW5nKCkpIHtcbiAgICAgIHRoaXMuZ2V0VmlldygpLnJlc29sdmVDb25zdHJhaW50cygwKTtcbiAgICB9XG5cbiAgICB0aGlzLnJlbmRlcigpO1xuICB9O1xuICAvKipcbiAgICogQHByaXZhdGVcbiAgICovXG5cblxuICBQbHVnZ2FibGVNYXAucHJvdG90eXBlLmhhbmRsZVRhcmdldENoYW5nZWRfID0gZnVuY3Rpb24gKCkge1xuICAgIC8vIHRhcmdldCBtYXkgYmUgdW5kZWZpbmVkLCBudWxsLCBhIHN0cmluZyBvciBhbiBFbGVtZW50LlxuICAgIC8vIElmIGl0J3MgYSBzdHJpbmcgd2UgY29udmVydCBpdCB0byBhbiBFbGVtZW50IGJlZm9yZSBwcm9jZWVkaW5nLlxuICAgIC8vIElmIGl0J3Mgbm90IG5vdyBhbiBFbGVtZW50IHdlIHJlbW92ZSB0aGUgdmlld3BvcnQgZnJvbSB0aGUgRE9NLlxuICAgIC8vIElmIGl0J3MgYW4gRWxlbWVudCB3ZSBhcHBlbmQgdGhlIHZpZXdwb3J0IGVsZW1lbnQgdG8gaXQuXG4gICAgdmFyIHRhcmdldEVsZW1lbnQ7XG5cbiAgICBpZiAodGhpcy5nZXRUYXJnZXQoKSkge1xuICAgICAgdGFyZ2V0RWxlbWVudCA9IHRoaXMuZ2V0VGFyZ2V0RWxlbWVudCgpO1xuICAgIH1cblxuICAgIGlmICh0aGlzLm1hcEJyb3dzZXJFdmVudEhhbmRsZXJfKSB7XG4gICAgICBmb3IgKHZhciBpID0gMCwgaWkgPSB0aGlzLmtleUhhbmRsZXJLZXlzXy5sZW5ndGg7IGkgPCBpaTsgKytpKSB7XG4gICAgICAgIHVubGlzdGVuQnlLZXkodGhpcy5rZXlIYW5kbGVyS2V5c19baV0pO1xuICAgICAgfVxuXG4gICAgICB0aGlzLmtleUhhbmRsZXJLZXlzXyA9IG51bGw7XG4gICAgICB0aGlzLnZpZXdwb3J0Xy5yZW1vdmVFdmVudExpc3RlbmVyKEV2ZW50VHlwZS5DT05URVhUTUVOVSwgdGhpcy5ib3VuZEhhbmRsZUJyb3dzZXJFdmVudF8pO1xuICAgICAgdGhpcy52aWV3cG9ydF8ucmVtb3ZlRXZlbnRMaXN0ZW5lcihFdmVudFR5cGUuV0hFRUwsIHRoaXMuYm91bmRIYW5kbGVCcm93c2VyRXZlbnRfKTtcblxuICAgICAgaWYgKHRoaXMuaGFuZGxlUmVzaXplXyAhPT0gdW5kZWZpbmVkKSB7XG4gICAgICAgIHJlbW92ZUV2ZW50TGlzdGVuZXIoRXZlbnRUeXBlLlJFU0laRSwgdGhpcy5oYW5kbGVSZXNpemVfLCBmYWxzZSk7XG4gICAgICAgIHRoaXMuaGFuZGxlUmVzaXplXyA9IHVuZGVmaW5lZDtcbiAgICAgIH1cblxuICAgICAgdGhpcy5tYXBCcm93c2VyRXZlbnRIYW5kbGVyXy5kaXNwb3NlKCk7XG4gICAgICB0aGlzLm1hcEJyb3dzZXJFdmVudEhhbmRsZXJfID0gbnVsbDtcbiAgICAgIHJlbW92ZU5vZGUodGhpcy52aWV3cG9ydF8pO1xuICAgIH1cblxuICAgIGlmICghdGFyZ2V0RWxlbWVudCkge1xuICAgICAgaWYgKHRoaXMucmVuZGVyZXJfKSB7XG4gICAgICAgIGNsZWFyVGltZW91dCh0aGlzLnBvc3RSZW5kZXJUaW1lb3V0SGFuZGxlXyk7XG4gICAgICAgIHRoaXMucG9zdFJlbmRlclRpbWVvdXRIYW5kbGVfID0gdW5kZWZpbmVkO1xuICAgICAgICB0aGlzLnBvc3RSZW5kZXJGdW5jdGlvbnNfLmxlbmd0aCA9IDA7XG4gICAgICAgIHRoaXMucmVuZGVyZXJfLmRpc3Bvc2UoKTtcbiAgICAgICAgdGhpcy5yZW5kZXJlcl8gPSBudWxsO1xuICAgICAgfVxuXG4gICAgICBpZiAodGhpcy5hbmltYXRpb25EZWxheUtleV8pIHtcbiAgICAgICAgY2FuY2VsQW5pbWF0aW9uRnJhbWUodGhpcy5hbmltYXRpb25EZWxheUtleV8pO1xuICAgICAgICB0aGlzLmFuaW1hdGlvbkRlbGF5S2V5XyA9IHVuZGVmaW5lZDtcbiAgICAgIH1cbiAgICB9IGVsc2Uge1xuICAgICAgdGFyZ2V0RWxlbWVudC5hcHBlbmRDaGlsZCh0aGlzLnZpZXdwb3J0Xyk7XG5cbiAgICAgIGlmICghdGhpcy5yZW5kZXJlcl8pIHtcbiAgICAgICAgdGhpcy5yZW5kZXJlcl8gPSB0aGlzLmNyZWF0ZVJlbmRlcmVyKCk7XG4gICAgICB9XG5cbiAgICAgIHRoaXMubWFwQnJvd3NlckV2ZW50SGFuZGxlcl8gPSBuZXcgTWFwQnJvd3NlckV2ZW50SGFuZGxlcih0aGlzLCB0aGlzLm1vdmVUb2xlcmFuY2VfKTtcblxuICAgICAgZm9yICh2YXIga2V5IGluIE1hcEJyb3dzZXJFdmVudFR5cGUpIHtcbiAgICAgICAgdGhpcy5tYXBCcm93c2VyRXZlbnRIYW5kbGVyXy5hZGRFdmVudExpc3RlbmVyKE1hcEJyb3dzZXJFdmVudFR5cGVba2V5XSwgdGhpcy5oYW5kbGVNYXBCcm93c2VyRXZlbnQuYmluZCh0aGlzKSk7XG4gICAgICB9XG5cbiAgICAgIHRoaXMudmlld3BvcnRfLmFkZEV2ZW50TGlzdGVuZXIoRXZlbnRUeXBlLkNPTlRFWFRNRU5VLCB0aGlzLmJvdW5kSGFuZGxlQnJvd3NlckV2ZW50XywgZmFsc2UpO1xuICAgICAgdGhpcy52aWV3cG9ydF8uYWRkRXZlbnRMaXN0ZW5lcihFdmVudFR5cGUuV0hFRUwsIHRoaXMuYm91bmRIYW5kbGVCcm93c2VyRXZlbnRfLCBQQVNTSVZFX0VWRU5UX0xJU1RFTkVSUyA/IHtcbiAgICAgICAgcGFzc2l2ZTogZmFsc2VcbiAgICAgIH0gOiBmYWxzZSk7XG4gICAgICB2YXIga2V5Ym9hcmRFdmVudFRhcmdldCA9ICF0aGlzLmtleWJvYXJkRXZlbnRUYXJnZXRfID8gdGFyZ2V0RWxlbWVudCA6IHRoaXMua2V5Ym9hcmRFdmVudFRhcmdldF87XG4gICAgICB0aGlzLmtleUhhbmRsZXJLZXlzXyA9IFtsaXN0ZW4oa2V5Ym9hcmRFdmVudFRhcmdldCwgRXZlbnRUeXBlLktFWURPV04sIHRoaXMuaGFuZGxlQnJvd3NlckV2ZW50LCB0aGlzKSwgbGlzdGVuKGtleWJvYXJkRXZlbnRUYXJnZXQsIEV2ZW50VHlwZS5LRVlQUkVTUywgdGhpcy5oYW5kbGVCcm93c2VyRXZlbnQsIHRoaXMpXTtcblxuICAgICAgaWYgKCF0aGlzLmhhbmRsZVJlc2l6ZV8pIHtcbiAgICAgICAgdGhpcy5oYW5kbGVSZXNpemVfID0gdGhpcy51cGRhdGVTaXplLmJpbmQodGhpcyk7XG4gICAgICAgIHdpbmRvdy5hZGRFdmVudExpc3RlbmVyKEV2ZW50VHlwZS5SRVNJWkUsIHRoaXMuaGFuZGxlUmVzaXplXywgZmFsc2UpO1xuICAgICAgfVxuICAgIH1cblxuICAgIHRoaXMudXBkYXRlU2l6ZSgpOyAvLyB1cGRhdGVTaXplIGNhbGxzIHNldFNpemUsIHNvIG5vIG5lZWQgdG8gY2FsbCB0aGlzLnJlbmRlclxuICAgIC8vIG91cnNlbHZlcyBoZXJlLlxuICB9O1xuICAvKipcbiAgICogQHByaXZhdGVcbiAgICovXG5cblxuICBQbHVnZ2FibGVNYXAucHJvdG90eXBlLmhhbmRsZVRpbGVDaGFuZ2VfID0gZnVuY3Rpb24gKCkge1xuICAgIHRoaXMucmVuZGVyKCk7XG4gIH07XG4gIC8qKlxuICAgKiBAcHJpdmF0ZVxuICAgKi9cblxuXG4gIFBsdWdnYWJsZU1hcC5wcm90b3R5cGUuaGFuZGxlVmlld1Byb3BlcnR5Q2hhbmdlZF8gPSBmdW5jdGlvbiAoKSB7XG4gICAgdGhpcy5yZW5kZXIoKTtcbiAgfTtcbiAgLyoqXG4gICAqIEBwcml2YXRlXG4gICAqL1xuXG5cbiAgUGx1Z2dhYmxlTWFwLnByb3RvdHlwZS5oYW5kbGVWaWV3Q2hhbmdlZF8gPSBmdW5jdGlvbiAoKSB7XG4gICAgaWYgKHRoaXMudmlld1Byb3BlcnR5TGlzdGVuZXJLZXlfKSB7XG4gICAgICB1bmxpc3RlbkJ5S2V5KHRoaXMudmlld1Byb3BlcnR5TGlzdGVuZXJLZXlfKTtcbiAgICAgIHRoaXMudmlld1Byb3BlcnR5TGlzdGVuZXJLZXlfID0gbnVsbDtcbiAgICB9XG5cbiAgICBpZiAodGhpcy52aWV3Q2hhbmdlTGlzdGVuZXJLZXlfKSB7XG4gICAgICB1bmxpc3RlbkJ5S2V5KHRoaXMudmlld0NoYW5nZUxpc3RlbmVyS2V5Xyk7XG4gICAgICB0aGlzLnZpZXdDaGFuZ2VMaXN0ZW5lcktleV8gPSBudWxsO1xuICAgIH1cblxuICAgIHZhciB2aWV3ID0gdGhpcy5nZXRWaWV3KCk7XG5cbiAgICBpZiAodmlldykge1xuICAgICAgdGhpcy51cGRhdGVWaWV3cG9ydFNpemVfKCk7XG4gICAgICB0aGlzLnZpZXdQcm9wZXJ0eUxpc3RlbmVyS2V5XyA9IGxpc3Rlbih2aWV3LCBPYmplY3RFdmVudFR5cGUuUFJPUEVSVFlDSEFOR0UsIHRoaXMuaGFuZGxlVmlld1Byb3BlcnR5Q2hhbmdlZF8sIHRoaXMpO1xuICAgICAgdGhpcy52aWV3Q2hhbmdlTGlzdGVuZXJLZXlfID0gbGlzdGVuKHZpZXcsIEV2ZW50VHlwZS5DSEFOR0UsIHRoaXMuaGFuZGxlVmlld1Byb3BlcnR5Q2hhbmdlZF8sIHRoaXMpO1xuICAgICAgdmlldy5yZXNvbHZlQ29uc3RyYWludHMoMCk7XG4gICAgfVxuXG4gICAgdGhpcy5yZW5kZXIoKTtcbiAgfTtcbiAgLyoqXG4gICAqIEBwcml2YXRlXG4gICAqL1xuXG5cbiAgUGx1Z2dhYmxlTWFwLnByb3RvdHlwZS5oYW5kbGVMYXllckdyb3VwQ2hhbmdlZF8gPSBmdW5jdGlvbiAoKSB7XG4gICAgaWYgKHRoaXMubGF5ZXJHcm91cFByb3BlcnR5TGlzdGVuZXJLZXlzXykge1xuICAgICAgdGhpcy5sYXllckdyb3VwUHJvcGVydHlMaXN0ZW5lcktleXNfLmZvckVhY2godW5saXN0ZW5CeUtleSk7XG4gICAgICB0aGlzLmxheWVyR3JvdXBQcm9wZXJ0eUxpc3RlbmVyS2V5c18gPSBudWxsO1xuICAgIH1cblxuICAgIHZhciBsYXllckdyb3VwID0gdGhpcy5nZXRMYXllckdyb3VwKCk7XG5cbiAgICBpZiAobGF5ZXJHcm91cCkge1xuICAgICAgdGhpcy5sYXllckdyb3VwUHJvcGVydHlMaXN0ZW5lcktleXNfID0gW2xpc3RlbihsYXllckdyb3VwLCBPYmplY3RFdmVudFR5cGUuUFJPUEVSVFlDSEFOR0UsIHRoaXMucmVuZGVyLCB0aGlzKSwgbGlzdGVuKGxheWVyR3JvdXAsIEV2ZW50VHlwZS5DSEFOR0UsIHRoaXMucmVuZGVyLCB0aGlzKV07XG4gICAgfVxuXG4gICAgdGhpcy5yZW5kZXIoKTtcbiAgfTtcbiAgLyoqXG4gICAqIEByZXR1cm4ge2Jvb2xlYW59IElzIHJlbmRlcmVkLlxuICAgKi9cblxuXG4gIFBsdWdnYWJsZU1hcC5wcm90b3R5cGUuaXNSZW5kZXJlZCA9IGZ1bmN0aW9uICgpIHtcbiAgICByZXR1cm4gISF0aGlzLmZyYW1lU3RhdGVfO1xuICB9O1xuICAvKipcbiAgICogUmVxdWVzdHMgYW4gaW1tZWRpYXRlIHJlbmRlciBpbiBhIHN5bmNocm9ub3VzIG1hbm5lci5cbiAgICogQGFwaVxuICAgKi9cblxuXG4gIFBsdWdnYWJsZU1hcC5wcm90b3R5cGUucmVuZGVyU3luYyA9IGZ1bmN0aW9uICgpIHtcbiAgICBpZiAodGhpcy5hbmltYXRpb25EZWxheUtleV8pIHtcbiAgICAgIGNhbmNlbEFuaW1hdGlvbkZyYW1lKHRoaXMuYW5pbWF0aW9uRGVsYXlLZXlfKTtcbiAgICB9XG5cbiAgICB0aGlzLmFuaW1hdGlvbkRlbGF5XygpO1xuICB9O1xuICAvKipcbiAgICogUmVkcmF3cyBhbGwgdGV4dCBhZnRlciBuZXcgZm9udHMgaGF2ZSBsb2FkZWRcbiAgICovXG5cblxuICBQbHVnZ2FibGVNYXAucHJvdG90eXBlLnJlZHJhd1RleHQgPSBmdW5jdGlvbiAoKSB7XG4gICAgdmFyIGxheWVyU3RhdGVzID0gdGhpcy5nZXRMYXllckdyb3VwKCkuZ2V0TGF5ZXJTdGF0ZXNBcnJheSgpO1xuXG4gICAgZm9yICh2YXIgaSA9IDAsIGlpID0gbGF5ZXJTdGF0ZXMubGVuZ3RoOyBpIDwgaWk7ICsraSkge1xuICAgICAgdmFyIGxheWVyID0gbGF5ZXJTdGF0ZXNbaV0ubGF5ZXI7XG5cbiAgICAgIGlmIChsYXllci5oYXNSZW5kZXJlcigpKSB7XG4gICAgICAgIGxheWVyLmdldFJlbmRlcmVyKCkuaGFuZGxlRm9udHNDaGFuZ2VkKCk7XG4gICAgICB9XG4gICAgfVxuICB9O1xuICAvKipcbiAgICogUmVxdWVzdCBhIG1hcCByZW5kZXJpbmcgKGF0IHRoZSBuZXh0IGFuaW1hdGlvbiBmcmFtZSkuXG4gICAqIEBhcGlcbiAgICovXG5cblxuICBQbHVnZ2FibGVNYXAucHJvdG90eXBlLnJlbmRlciA9IGZ1bmN0aW9uICgpIHtcbiAgICBpZiAodGhpcy5yZW5kZXJlcl8gJiYgdGhpcy5hbmltYXRpb25EZWxheUtleV8gPT09IHVuZGVmaW5lZCkge1xuICAgICAgdGhpcy5hbmltYXRpb25EZWxheUtleV8gPSByZXF1ZXN0QW5pbWF0aW9uRnJhbWUodGhpcy5hbmltYXRpb25EZWxheV8pO1xuICAgIH1cbiAgfTtcbiAgLyoqXG4gICAqIFJlbW92ZSB0aGUgZ2l2ZW4gY29udHJvbCBmcm9tIHRoZSBtYXAuXG4gICAqIEBwYXJhbSB7aW1wb3J0KFwiLi9jb250cm9sL0NvbnRyb2wuanNcIikuZGVmYXVsdH0gY29udHJvbCBDb250cm9sLlxuICAgKiBAcmV0dXJuIHtpbXBvcnQoXCIuL2NvbnRyb2wvQ29udHJvbC5qc1wiKS5kZWZhdWx0fHVuZGVmaW5lZH0gVGhlIHJlbW92ZWQgY29udHJvbCAob3IgdW5kZWZpbmVkXG4gICAqICAgICBpZiB0aGUgY29udHJvbCB3YXMgbm90IGZvdW5kKS5cbiAgICogQGFwaVxuICAgKi9cblxuXG4gIFBsdWdnYWJsZU1hcC5wcm90b3R5cGUucmVtb3ZlQ29udHJvbCA9IGZ1bmN0aW9uIChjb250cm9sKSB7XG4gICAgcmV0dXJuIHRoaXMuZ2V0Q29udHJvbHMoKS5yZW1vdmUoY29udHJvbCk7XG4gIH07XG4gIC8qKlxuICAgKiBSZW1vdmUgdGhlIGdpdmVuIGludGVyYWN0aW9uIGZyb20gdGhlIG1hcC5cbiAgICogQHBhcmFtIHtpbXBvcnQoXCIuL2ludGVyYWN0aW9uL0ludGVyYWN0aW9uLmpzXCIpLmRlZmF1bHR9IGludGVyYWN0aW9uIEludGVyYWN0aW9uIHRvIHJlbW92ZS5cbiAgICogQHJldHVybiB7aW1wb3J0KFwiLi9pbnRlcmFjdGlvbi9JbnRlcmFjdGlvbi5qc1wiKS5kZWZhdWx0fHVuZGVmaW5lZH0gVGhlIHJlbW92ZWQgaW50ZXJhY3Rpb24gKG9yXG4gICAqICAgICB1bmRlZmluZWQgaWYgdGhlIGludGVyYWN0aW9uIHdhcyBub3QgZm91bmQpLlxuICAgKiBAYXBpXG4gICAqL1xuXG5cbiAgUGx1Z2dhYmxlTWFwLnByb3RvdHlwZS5yZW1vdmVJbnRlcmFjdGlvbiA9IGZ1bmN0aW9uIChpbnRlcmFjdGlvbikge1xuICAgIHJldHVybiB0aGlzLmdldEludGVyYWN0aW9ucygpLnJlbW92ZShpbnRlcmFjdGlvbik7XG4gIH07XG4gIC8qKlxuICAgKiBSZW1vdmVzIHRoZSBnaXZlbiBsYXllciBmcm9tIHRoZSBtYXAuXG4gICAqIEBwYXJhbSB7aW1wb3J0KFwiLi9sYXllci9CYXNlLmpzXCIpLmRlZmF1bHR9IGxheWVyIExheWVyLlxuICAgKiBAcmV0dXJuIHtpbXBvcnQoXCIuL2xheWVyL0Jhc2UuanNcIikuZGVmYXVsdHx1bmRlZmluZWR9IFRoZSByZW1vdmVkIGxheWVyIChvciB1bmRlZmluZWQgaWYgdGhlXG4gICAqICAgICBsYXllciB3YXMgbm90IGZvdW5kKS5cbiAgICogQGFwaVxuICAgKi9cblxuXG4gIFBsdWdnYWJsZU1hcC5wcm90b3R5cGUucmVtb3ZlTGF5ZXIgPSBmdW5jdGlvbiAobGF5ZXIpIHtcbiAgICB2YXIgbGF5ZXJzID0gdGhpcy5nZXRMYXllckdyb3VwKCkuZ2V0TGF5ZXJzKCk7XG4gICAgcmV0dXJuIGxheWVycy5yZW1vdmUobGF5ZXIpO1xuICB9O1xuICAvKipcbiAgICogUmVtb3ZlIHRoZSBnaXZlbiBvdmVybGF5IGZyb20gdGhlIG1hcC5cbiAgICogQHBhcmFtIHtpbXBvcnQoXCIuL092ZXJsYXkuanNcIikuZGVmYXVsdH0gb3ZlcmxheSBPdmVybGF5LlxuICAgKiBAcmV0dXJuIHtpbXBvcnQoXCIuL092ZXJsYXkuanNcIikuZGVmYXVsdHx1bmRlZmluZWR9IFRoZSByZW1vdmVkIG92ZXJsYXkgKG9yIHVuZGVmaW5lZFxuICAgKiAgICAgaWYgdGhlIG92ZXJsYXkgd2FzIG5vdCBmb3VuZCkuXG4gICAqIEBhcGlcbiAgICovXG5cblxuICBQbHVnZ2FibGVNYXAucHJvdG90eXBlLnJlbW92ZU92ZXJsYXkgPSBmdW5jdGlvbiAob3ZlcmxheSkge1xuICAgIHJldHVybiB0aGlzLmdldE92ZXJsYXlzKCkucmVtb3ZlKG92ZXJsYXkpO1xuICB9O1xuICAvKipcbiAgICogQHBhcmFtIHtudW1iZXJ9IHRpbWUgVGltZS5cbiAgICogQHByaXZhdGVcbiAgICovXG5cblxuICBQbHVnZ2FibGVNYXAucHJvdG90eXBlLnJlbmRlckZyYW1lXyA9IGZ1bmN0aW9uICh0aW1lKSB7XG4gICAgdmFyIF90aGlzID0gdGhpcztcblxuICAgIHZhciBzaXplID0gdGhpcy5nZXRTaXplKCk7XG4gICAgdmFyIHZpZXcgPSB0aGlzLmdldFZpZXcoKTtcbiAgICB2YXIgcHJldmlvdXNGcmFtZVN0YXRlID0gdGhpcy5mcmFtZVN0YXRlXztcbiAgICAvKiogQHR5cGUgez9GcmFtZVN0YXRlfSAqL1xuXG4gICAgdmFyIGZyYW1lU3RhdGUgPSBudWxsO1xuXG4gICAgaWYgKHNpemUgIT09IHVuZGVmaW5lZCAmJiBoYXNBcmVhKHNpemUpICYmIHZpZXcgJiYgdmlldy5pc0RlZigpKSB7XG4gICAgICB2YXIgdmlld0hpbnRzID0gdmlldy5nZXRIaW50cyh0aGlzLmZyYW1lU3RhdGVfID8gdGhpcy5mcmFtZVN0YXRlXy52aWV3SGludHMgOiB1bmRlZmluZWQpO1xuICAgICAgdmFyIHZpZXdTdGF0ZSA9IHZpZXcuZ2V0U3RhdGUoKTtcbiAgICAgIGZyYW1lU3RhdGUgPSB7XG4gICAgICAgIGFuaW1hdGU6IGZhbHNlLFxuICAgICAgICBjb29yZGluYXRlVG9QaXhlbFRyYW5zZm9ybTogdGhpcy5jb29yZGluYXRlVG9QaXhlbFRyYW5zZm9ybV8sXG4gICAgICAgIGRlY2x1dHRlclRyZWU6IG51bGwsXG4gICAgICAgIGV4dGVudDogZ2V0Rm9yVmlld0FuZFNpemUodmlld1N0YXRlLmNlbnRlciwgdmlld1N0YXRlLnJlc29sdXRpb24sIHZpZXdTdGF0ZS5yb3RhdGlvbiwgc2l6ZSksXG4gICAgICAgIGluZGV4OiB0aGlzLmZyYW1lSW5kZXhfKyssXG4gICAgICAgIGxheWVySW5kZXg6IDAsXG4gICAgICAgIGxheWVyU3RhdGVzQXJyYXk6IHRoaXMuZ2V0TGF5ZXJHcm91cCgpLmdldExheWVyU3RhdGVzQXJyYXkoKSxcbiAgICAgICAgcGl4ZWxSYXRpbzogdGhpcy5waXhlbFJhdGlvXyxcbiAgICAgICAgcGl4ZWxUb0Nvb3JkaW5hdGVUcmFuc2Zvcm06IHRoaXMucGl4ZWxUb0Nvb3JkaW5hdGVUcmFuc2Zvcm1fLFxuICAgICAgICBwb3N0UmVuZGVyRnVuY3Rpb25zOiBbXSxcbiAgICAgICAgc2l6ZTogc2l6ZSxcbiAgICAgICAgdGlsZVF1ZXVlOiB0aGlzLnRpbGVRdWV1ZV8sXG4gICAgICAgIHRpbWU6IHRpbWUsXG4gICAgICAgIHVzZWRUaWxlczoge30sXG4gICAgICAgIHZpZXdTdGF0ZTogdmlld1N0YXRlLFxuICAgICAgICB2aWV3SGludHM6IHZpZXdIaW50cyxcbiAgICAgICAgd2FudGVkVGlsZXM6IHt9XG4gICAgICB9O1xuICAgIH1cblxuICAgIHRoaXMuZnJhbWVTdGF0ZV8gPSBmcmFtZVN0YXRlO1xuICAgIHRoaXMucmVuZGVyZXJfLnJlbmRlckZyYW1lKGZyYW1lU3RhdGUpO1xuXG4gICAgaWYgKGZyYW1lU3RhdGUpIHtcbiAgICAgIGlmIChmcmFtZVN0YXRlLmFuaW1hdGUpIHtcbiAgICAgICAgdGhpcy5yZW5kZXIoKTtcbiAgICAgIH1cblxuICAgICAgQXJyYXkucHJvdG90eXBlLnB1c2guYXBwbHkodGhpcy5wb3N0UmVuZGVyRnVuY3Rpb25zXywgZnJhbWVTdGF0ZS5wb3N0UmVuZGVyRnVuY3Rpb25zKTtcblxuICAgICAgaWYgKHByZXZpb3VzRnJhbWVTdGF0ZSkge1xuICAgICAgICB2YXIgbW92ZVN0YXJ0ID0gIXRoaXMucHJldmlvdXNFeHRlbnRfIHx8ICFpc0VtcHR5KHRoaXMucHJldmlvdXNFeHRlbnRfKSAmJiAhZXF1YWxzKGZyYW1lU3RhdGUuZXh0ZW50LCB0aGlzLnByZXZpb3VzRXh0ZW50Xyk7XG5cbiAgICAgICAgaWYgKG1vdmVTdGFydCkge1xuICAgICAgICAgIHRoaXMuZGlzcGF0Y2hFdmVudChuZXcgTWFwRXZlbnQoTWFwRXZlbnRUeXBlLk1PVkVTVEFSVCwgdGhpcywgcHJldmlvdXNGcmFtZVN0YXRlKSk7XG4gICAgICAgICAgdGhpcy5wcmV2aW91c0V4dGVudF8gPSBjcmVhdGVPclVwZGF0ZUVtcHR5KHRoaXMucHJldmlvdXNFeHRlbnRfKTtcbiAgICAgICAgfVxuICAgICAgfVxuXG4gICAgICB2YXIgaWRsZSA9IHRoaXMucHJldmlvdXNFeHRlbnRfICYmICFmcmFtZVN0YXRlLnZpZXdIaW50c1tWaWV3SGludC5BTklNQVRJTkddICYmICFmcmFtZVN0YXRlLnZpZXdIaW50c1tWaWV3SGludC5JTlRFUkFDVElOR10gJiYgIWVxdWFscyhmcmFtZVN0YXRlLmV4dGVudCwgdGhpcy5wcmV2aW91c0V4dGVudF8pO1xuXG4gICAgICBpZiAoaWRsZSkge1xuICAgICAgICB0aGlzLmRpc3BhdGNoRXZlbnQobmV3IE1hcEV2ZW50KE1hcEV2ZW50VHlwZS5NT1ZFRU5ELCB0aGlzLCBmcmFtZVN0YXRlKSk7XG4gICAgICAgIGNsb25lKGZyYW1lU3RhdGUuZXh0ZW50LCB0aGlzLnByZXZpb3VzRXh0ZW50Xyk7XG4gICAgICB9XG4gICAgfVxuXG4gICAgdGhpcy5kaXNwYXRjaEV2ZW50KG5ldyBNYXBFdmVudChNYXBFdmVudFR5cGUuUE9TVFJFTkRFUiwgdGhpcywgZnJhbWVTdGF0ZSkpO1xuXG4gICAgaWYgKCF0aGlzLnBvc3RSZW5kZXJUaW1lb3V0SGFuZGxlXykge1xuICAgICAgdGhpcy5wb3N0UmVuZGVyVGltZW91dEhhbmRsZV8gPSBzZXRUaW1lb3V0KGZ1bmN0aW9uICgpIHtcbiAgICAgICAgX3RoaXMucG9zdFJlbmRlclRpbWVvdXRIYW5kbGVfID0gdW5kZWZpbmVkO1xuXG4gICAgICAgIF90aGlzLmhhbmRsZVBvc3RSZW5kZXIoKTtcbiAgICAgIH0sIDApO1xuICAgIH1cbiAgfTtcbiAgLyoqXG4gICAqIFNldHMgdGhlIGxheWVyZ3JvdXAgb2YgdGhpcyBtYXAuXG4gICAqIEBwYXJhbSB7TGF5ZXJHcm91cH0gbGF5ZXJHcm91cCBBIGxheWVyIGdyb3VwIGNvbnRhaW5pbmcgdGhlIGxheWVycyBpbiB0aGlzIG1hcC5cbiAgICogQG9ic2VydmFibGVcbiAgICogQGFwaVxuICAgKi9cblxuXG4gIFBsdWdnYWJsZU1hcC5wcm90b3R5cGUuc2V0TGF5ZXJHcm91cCA9IGZ1bmN0aW9uIChsYXllckdyb3VwKSB7XG4gICAgdGhpcy5zZXQoTWFwUHJvcGVydHkuTEFZRVJHUk9VUCwgbGF5ZXJHcm91cCk7XG4gIH07XG4gIC8qKlxuICAgKiBTZXQgdGhlIHNpemUgb2YgdGhpcyBtYXAuXG4gICAqIEBwYXJhbSB7aW1wb3J0KFwiLi9zaXplLmpzXCIpLlNpemV8dW5kZWZpbmVkfSBzaXplIFRoZSBzaXplIGluIHBpeGVscyBvZiB0aGUgbWFwIGluIHRoZSBET00uXG4gICAqIEBvYnNlcnZhYmxlXG4gICAqIEBhcGlcbiAgICovXG5cblxuICBQbHVnZ2FibGVNYXAucHJvdG90eXBlLnNldFNpemUgPSBmdW5jdGlvbiAoc2l6ZSkge1xuICAgIHRoaXMuc2V0KE1hcFByb3BlcnR5LlNJWkUsIHNpemUpO1xuICB9O1xuICAvKipcbiAgICogU2V0IHRoZSB0YXJnZXQgZWxlbWVudCB0byByZW5kZXIgdGhpcyBtYXAgaW50by5cbiAgICogQHBhcmFtIHtIVE1MRWxlbWVudHxzdHJpbmd8dW5kZWZpbmVkfSB0YXJnZXQgVGhlIEVsZW1lbnQgb3IgaWQgb2YgdGhlIEVsZW1lbnRcbiAgICogICAgIHRoYXQgdGhlIG1hcCBpcyByZW5kZXJlZCBpbi5cbiAgICogQG9ic2VydmFibGVcbiAgICogQGFwaVxuICAgKi9cblxuXG4gIFBsdWdnYWJsZU1hcC5wcm90b3R5cGUuc2V0VGFyZ2V0ID0gZnVuY3Rpb24gKHRhcmdldCkge1xuICAgIHRoaXMuc2V0KE1hcFByb3BlcnR5LlRBUkdFVCwgdGFyZ2V0KTtcbiAgfTtcbiAgLyoqXG4gICAqIFNldCB0aGUgdmlldyBmb3IgdGhpcyBtYXAuXG4gICAqIEBwYXJhbSB7Vmlld30gdmlldyBUaGUgdmlldyB0aGF0IGNvbnRyb2xzIHRoaXMgbWFwLlxuICAgKiBAb2JzZXJ2YWJsZVxuICAgKiBAYXBpXG4gICAqL1xuXG5cbiAgUGx1Z2dhYmxlTWFwLnByb3RvdHlwZS5zZXRWaWV3ID0gZnVuY3Rpb24gKHZpZXcpIHtcbiAgICB0aGlzLnNldChNYXBQcm9wZXJ0eS5WSUVXLCB2aWV3KTtcbiAgfTtcbiAgLyoqXG4gICAqIEZvcmNlIGEgcmVjYWxjdWxhdGlvbiBvZiB0aGUgbWFwIHZpZXdwb3J0IHNpemUuICBUaGlzIHNob3VsZCBiZSBjYWxsZWQgd2hlblxuICAgKiB0aGlyZC1wYXJ0eSBjb2RlIGNoYW5nZXMgdGhlIHNpemUgb2YgdGhlIG1hcCB2aWV3cG9ydC5cbiAgICogQGFwaVxuICAgKi9cblxuXG4gIFBsdWdnYWJsZU1hcC5wcm90b3R5cGUudXBkYXRlU2l6ZSA9IGZ1bmN0aW9uICgpIHtcbiAgICB2YXIgdGFyZ2V0RWxlbWVudCA9IHRoaXMuZ2V0VGFyZ2V0RWxlbWVudCgpO1xuXG4gICAgaWYgKCF0YXJnZXRFbGVtZW50KSB7XG4gICAgICB0aGlzLnNldFNpemUodW5kZWZpbmVkKTtcbiAgICB9IGVsc2Uge1xuICAgICAgdmFyIGNvbXB1dGVkU3R5bGUgPSBnZXRDb21wdXRlZFN0eWxlKHRhcmdldEVsZW1lbnQpO1xuICAgICAgdGhpcy5zZXRTaXplKFt0YXJnZXRFbGVtZW50Lm9mZnNldFdpZHRoIC0gcGFyc2VGbG9hdChjb21wdXRlZFN0eWxlWydib3JkZXJMZWZ0V2lkdGgnXSkgLSBwYXJzZUZsb2F0KGNvbXB1dGVkU3R5bGVbJ3BhZGRpbmdMZWZ0J10pIC0gcGFyc2VGbG9hdChjb21wdXRlZFN0eWxlWydwYWRkaW5nUmlnaHQnXSkgLSBwYXJzZUZsb2F0KGNvbXB1dGVkU3R5bGVbJ2JvcmRlclJpZ2h0V2lkdGgnXSksIHRhcmdldEVsZW1lbnQub2Zmc2V0SGVpZ2h0IC0gcGFyc2VGbG9hdChjb21wdXRlZFN0eWxlWydib3JkZXJUb3BXaWR0aCddKSAtIHBhcnNlRmxvYXQoY29tcHV0ZWRTdHlsZVsncGFkZGluZ1RvcCddKSAtIHBhcnNlRmxvYXQoY29tcHV0ZWRTdHlsZVsncGFkZGluZ0JvdHRvbSddKSAtIHBhcnNlRmxvYXQoY29tcHV0ZWRTdHlsZVsnYm9yZGVyQm90dG9tV2lkdGgnXSldKTtcbiAgICB9XG5cbiAgICB0aGlzLnVwZGF0ZVZpZXdwb3J0U2l6ZV8oKTtcbiAgfTtcbiAgLyoqXG4gICAqIFJlY29tcHV0ZXMgdGhlIHZpZXdwb3J0IHNpemUgYW5kIHNhdmUgaXQgb24gdGhlIHZpZXcgb2JqZWN0IChpZiBhbnkpXG4gICAqIEBwcml2YXRlXG4gICAqL1xuXG5cbiAgUGx1Z2dhYmxlTWFwLnByb3RvdHlwZS51cGRhdGVWaWV3cG9ydFNpemVfID0gZnVuY3Rpb24gKCkge1xuICAgIHZhciB2aWV3ID0gdGhpcy5nZXRWaWV3KCk7XG5cbiAgICBpZiAodmlldykge1xuICAgICAgdmFyIHNpemUgPSB1bmRlZmluZWQ7XG4gICAgICB2YXIgY29tcHV0ZWRTdHlsZSA9IGdldENvbXB1dGVkU3R5bGUodGhpcy52aWV3cG9ydF8pO1xuXG4gICAgICBpZiAoY29tcHV0ZWRTdHlsZS53aWR0aCAmJiBjb21wdXRlZFN0eWxlLmhlaWdodCkge1xuICAgICAgICBzaXplID0gW3BhcnNlSW50KGNvbXB1dGVkU3R5bGUud2lkdGgsIDEwKSwgcGFyc2VJbnQoY29tcHV0ZWRTdHlsZS5oZWlnaHQsIDEwKV07XG4gICAgICB9XG5cbiAgICAgIHZpZXcuc2V0Vmlld3BvcnRTaXplKHNpemUpO1xuICAgIH1cbiAgfTtcblxuICByZXR1cm4gUGx1Z2dhYmxlTWFwO1xufShCYXNlT2JqZWN0KTtcbi8qKlxuICogQHBhcmFtIHtNYXBPcHRpb25zfSBvcHRpb25zIE1hcCBvcHRpb25zLlxuICogQHJldHVybiB7TWFwT3B0aW9uc0ludGVybmFsfSBJbnRlcm5hbCBtYXAgb3B0aW9ucy5cbiAqL1xuXG5cbmZ1bmN0aW9uIGNyZWF0ZU9wdGlvbnNJbnRlcm5hbChvcHRpb25zKSB7XG4gIC8qKlxuICAgKiBAdHlwZSB7SFRNTEVsZW1lbnR8RG9jdW1lbnR9XG4gICAqL1xuICB2YXIga2V5Ym9hcmRFdmVudFRhcmdldCA9IG51bGw7XG5cbiAgaWYgKG9wdGlvbnMua2V5Ym9hcmRFdmVudFRhcmdldCAhPT0gdW5kZWZpbmVkKSB7XG4gICAga2V5Ym9hcmRFdmVudFRhcmdldCA9IHR5cGVvZiBvcHRpb25zLmtleWJvYXJkRXZlbnRUYXJnZXQgPT09ICdzdHJpbmcnID8gZG9jdW1lbnQuZ2V0RWxlbWVudEJ5SWQob3B0aW9ucy5rZXlib2FyZEV2ZW50VGFyZ2V0KSA6IG9wdGlvbnMua2V5Ym9hcmRFdmVudFRhcmdldDtcbiAgfVxuICAvKipcbiAgICogQHR5cGUge09iamVjdDxzdHJpbmcsICo+fVxuICAgKi9cblxuXG4gIHZhciB2YWx1ZXMgPSB7fTtcbiAgdmFyIGxheWVyR3JvdXAgPSBvcHRpb25zLmxheWVycyAmJiB0eXBlb2ZcbiAgLyoqIEB0eXBlIHs/fSAqL1xuICBvcHRpb25zLmxheWVycy5nZXRMYXllcnMgPT09ICdmdW5jdGlvbicgP1xuICAvKiogQHR5cGUge0xheWVyR3JvdXB9ICovXG4gIG9wdGlvbnMubGF5ZXJzIDogbmV3IExheWVyR3JvdXAoe1xuICAgIGxheWVyczpcbiAgICAvKiogQHR5cGUge0NvbGxlY3Rpb259ICovXG4gICAgb3B0aW9ucy5sYXllcnNcbiAgfSk7XG4gIHZhbHVlc1tNYXBQcm9wZXJ0eS5MQVlFUkdST1VQXSA9IGxheWVyR3JvdXA7XG4gIHZhbHVlc1tNYXBQcm9wZXJ0eS5UQVJHRVRdID0gb3B0aW9ucy50YXJnZXQ7XG4gIHZhbHVlc1tNYXBQcm9wZXJ0eS5WSUVXXSA9IG9wdGlvbnMudmlldyAhPT0gdW5kZWZpbmVkID8gb3B0aW9ucy52aWV3IDogbmV3IFZpZXcoKTtcbiAgdmFyIGNvbnRyb2xzO1xuXG4gIGlmIChvcHRpb25zLmNvbnRyb2xzICE9PSB1bmRlZmluZWQpIHtcbiAgICBpZiAoQXJyYXkuaXNBcnJheShvcHRpb25zLmNvbnRyb2xzKSkge1xuICAgICAgY29udHJvbHMgPSBuZXcgQ29sbGVjdGlvbihvcHRpb25zLmNvbnRyb2xzLnNsaWNlKCkpO1xuICAgIH0gZWxzZSB7XG4gICAgICBhc3NlcnQodHlwZW9mXG4gICAgICAvKiogQHR5cGUgez99ICovXG4gICAgICBvcHRpb25zLmNvbnRyb2xzLmdldEFycmF5ID09PSAnZnVuY3Rpb24nLCA0Nyk7IC8vIEV4cGVjdGVkIGBjb250cm9sc2AgdG8gYmUgYW4gYXJyYXkgb3IgYW4gYGltcG9ydChcIi4vQ29sbGVjdGlvbi5qc1wiKS5Db2xsZWN0aW9uYFxuXG4gICAgICBjb250cm9scyA9XG4gICAgICAvKiogQHR5cGUge0NvbGxlY3Rpb259ICovXG4gICAgICBvcHRpb25zLmNvbnRyb2xzO1xuICAgIH1cbiAgfVxuXG4gIHZhciBpbnRlcmFjdGlvbnM7XG5cbiAgaWYgKG9wdGlvbnMuaW50ZXJhY3Rpb25zICE9PSB1bmRlZmluZWQpIHtcbiAgICBpZiAoQXJyYXkuaXNBcnJheShvcHRpb25zLmludGVyYWN0aW9ucykpIHtcbiAgICAgIGludGVyYWN0aW9ucyA9IG5ldyBDb2xsZWN0aW9uKG9wdGlvbnMuaW50ZXJhY3Rpb25zLnNsaWNlKCkpO1xuICAgIH0gZWxzZSB7XG4gICAgICBhc3NlcnQodHlwZW9mXG4gICAgICAvKiogQHR5cGUgez99ICovXG4gICAgICBvcHRpb25zLmludGVyYWN0aW9ucy5nZXRBcnJheSA9PT0gJ2Z1bmN0aW9uJywgNDgpOyAvLyBFeHBlY3RlZCBgaW50ZXJhY3Rpb25zYCB0byBiZSBhbiBhcnJheSBvciBhbiBgaW1wb3J0KFwiLi9Db2xsZWN0aW9uLmpzXCIpLkNvbGxlY3Rpb25gXG5cbiAgICAgIGludGVyYWN0aW9ucyA9XG4gICAgICAvKiogQHR5cGUge0NvbGxlY3Rpb259ICovXG4gICAgICBvcHRpb25zLmludGVyYWN0aW9ucztcbiAgICB9XG4gIH1cblxuICB2YXIgb3ZlcmxheXM7XG5cbiAgaWYgKG9wdGlvbnMub3ZlcmxheXMgIT09IHVuZGVmaW5lZCkge1xuICAgIGlmIChBcnJheS5pc0FycmF5KG9wdGlvbnMub3ZlcmxheXMpKSB7XG4gICAgICBvdmVybGF5cyA9IG5ldyBDb2xsZWN0aW9uKG9wdGlvbnMub3ZlcmxheXMuc2xpY2UoKSk7XG4gICAgfSBlbHNlIHtcbiAgICAgIGFzc2VydCh0eXBlb2ZcbiAgICAgIC8qKiBAdHlwZSB7P30gKi9cbiAgICAgIG9wdGlvbnMub3ZlcmxheXMuZ2V0QXJyYXkgPT09ICdmdW5jdGlvbicsIDQ5KTsgLy8gRXhwZWN0ZWQgYG92ZXJsYXlzYCB0byBiZSBhbiBhcnJheSBvciBhbiBgaW1wb3J0KFwiLi9Db2xsZWN0aW9uLmpzXCIpLkNvbGxlY3Rpb25gXG5cbiAgICAgIG92ZXJsYXlzID0gb3B0aW9ucy5vdmVybGF5cztcbiAgICB9XG4gIH0gZWxzZSB7XG4gICAgb3ZlcmxheXMgPSBuZXcgQ29sbGVjdGlvbigpO1xuICB9XG5cbiAgcmV0dXJuIHtcbiAgICBjb250cm9sczogY29udHJvbHMsXG4gICAgaW50ZXJhY3Rpb25zOiBpbnRlcmFjdGlvbnMsXG4gICAga2V5Ym9hcmRFdmVudFRhcmdldDoga2V5Ym9hcmRFdmVudFRhcmdldCxcbiAgICBvdmVybGF5czogb3ZlcmxheXMsXG4gICAgdmFsdWVzOiB2YWx1ZXNcbiAgfTtcbn1cblxuZXhwb3J0IGRlZmF1bHQgUGx1Z2dhYmxlTWFwOyIsInZhciBfX2V4dGVuZHMgPSB0aGlzICYmIHRoaXMuX19leHRlbmRzIHx8IGZ1bmN0aW9uICgpIHtcbiAgdmFyIF9leHRlbmRTdGF0aWNzID0gZnVuY3Rpb24gZXh0ZW5kU3RhdGljcyhkLCBiKSB7XG4gICAgX2V4dGVuZFN0YXRpY3MgPSBPYmplY3Quc2V0UHJvdG90eXBlT2YgfHwge1xuICAgICAgX19wcm90b19fOiBbXVxuICAgIH0gaW5zdGFuY2VvZiBBcnJheSAmJiBmdW5jdGlvbiAoZCwgYikge1xuICAgICAgZC5fX3Byb3RvX18gPSBiO1xuICAgIH0gfHwgZnVuY3Rpb24gKGQsIGIpIHtcbiAgICAgIGZvciAodmFyIHAgaW4gYikge1xuICAgICAgICBpZiAoT2JqZWN0LnByb3RvdHlwZS5oYXNPd25Qcm9wZXJ0eS5jYWxsKGIsIHApKSBkW3BdID0gYltwXTtcbiAgICAgIH1cbiAgICB9O1xuXG4gICAgcmV0dXJuIF9leHRlbmRTdGF0aWNzKGQsIGIpO1xuICB9O1xuXG4gIHJldHVybiBmdW5jdGlvbiAoZCwgYikge1xuICAgIF9leHRlbmRTdGF0aWNzKGQsIGIpO1xuXG4gICAgZnVuY3Rpb24gX18oKSB7XG4gICAgICB0aGlzLmNvbnN0cnVjdG9yID0gZDtcbiAgICB9XG5cbiAgICBkLnByb3RvdHlwZSA9IGIgPT09IG51bGwgPyBPYmplY3QuY3JlYXRlKGIpIDogKF9fLnByb3RvdHlwZSA9IGIucHJvdG90eXBlLCBuZXcgX18oKSk7XG4gIH07XG59KCk7XG4vKipcbiAqIEBtb2R1bGUgb2wvY29udHJvbC9Db250cm9sXG4gKi9cblxuXG5pbXBvcnQgQmFzZU9iamVjdCBmcm9tICcuLi9PYmplY3QuanMnO1xuaW1wb3J0IE1hcEV2ZW50VHlwZSBmcm9tICcuLi9NYXBFdmVudFR5cGUuanMnO1xuaW1wb3J0IHsgVk9JRCB9IGZyb20gJy4uL2Z1bmN0aW9ucy5qcyc7XG5pbXBvcnQgeyBsaXN0ZW4sIHVubGlzdGVuQnlLZXkgfSBmcm9tICcuLi9ldmVudHMuanMnO1xuaW1wb3J0IHsgcmVtb3ZlTm9kZSB9IGZyb20gJy4uL2RvbS5qcyc7XG4vKipcbiAqIEB0eXBlZGVmIHtPYmplY3R9IE9wdGlvbnNcbiAqIEBwcm9wZXJ0eSB7SFRNTEVsZW1lbnR9IFtlbGVtZW50XSBUaGUgZWxlbWVudCBpcyB0aGUgY29udHJvbCdzXG4gKiBjb250YWluZXIgZWxlbWVudC4gVGhpcyBvbmx5IG5lZWRzIHRvIGJlIHNwZWNpZmllZCBpZiB5b3UncmUgZGV2ZWxvcGluZ1xuICogYSBjdXN0b20gY29udHJvbC5cbiAqIEBwcm9wZXJ0eSB7ZnVuY3Rpb24oaW1wb3J0KFwiLi4vTWFwRXZlbnQuanNcIikuZGVmYXVsdCk6dm9pZH0gW3JlbmRlcl0gRnVuY3Rpb24gY2FsbGVkIHdoZW5cbiAqIHRoZSBjb250cm9sIHNob3VsZCBiZSByZS1yZW5kZXJlZC4gVGhpcyBpcyBjYWxsZWQgaW4gYSBgcmVxdWVzdEFuaW1hdGlvbkZyYW1lYFxuICogY2FsbGJhY2suXG4gKiBAcHJvcGVydHkge0hUTUxFbGVtZW50fHN0cmluZ30gW3RhcmdldF0gU3BlY2lmeSBhIHRhcmdldCBpZiB5b3Ugd2FudFxuICogdGhlIGNvbnRyb2wgdG8gYmUgcmVuZGVyZWQgb3V0c2lkZSBvZiB0aGUgbWFwJ3Mgdmlld3BvcnQuXG4gKi9cblxuLyoqXG4gKiBAY2xhc3NkZXNjXG4gKiBBIGNvbnRyb2wgaXMgYSB2aXNpYmxlIHdpZGdldCB3aXRoIGEgRE9NIGVsZW1lbnQgaW4gYSBmaXhlZCBwb3NpdGlvbiBvbiB0aGVcbiAqIHNjcmVlbi4gVGhleSBjYW4gaW52b2x2ZSB1c2VyIGlucHV0IChidXR0b25zKSwgb3IgYmUgaW5mb3JtYXRpb25hbCBvbmx5O1xuICogdGhlIHBvc2l0aW9uIGlzIGRldGVybWluZWQgdXNpbmcgQ1NTLiBCeSBkZWZhdWx0IHRoZXNlIGFyZSBwbGFjZWQgaW4gdGhlXG4gKiBjb250YWluZXIgd2l0aCBDU1MgY2xhc3MgbmFtZSBgb2wtb3ZlcmxheWNvbnRhaW5lci1zdG9wZXZlbnRgLCBidXQgY2FuIHVzZVxuICogYW55IG91dHNpZGUgRE9NIGVsZW1lbnQuXG4gKlxuICogVGhpcyBpcyB0aGUgYmFzZSBjbGFzcyBmb3IgY29udHJvbHMuIFlvdSBjYW4gdXNlIGl0IGZvciBzaW1wbGUgY3VzdG9tXG4gKiBjb250cm9scyBieSBjcmVhdGluZyB0aGUgZWxlbWVudCB3aXRoIGxpc3RlbmVycywgY3JlYXRpbmcgYW4gaW5zdGFuY2U6XG4gKiBgYGBqc1xuICogdmFyIG15Q29udHJvbCA9IG5ldyBDb250cm9sKHtlbGVtZW50OiBteUVsZW1lbnR9KTtcbiAqIGBgYFxuICogYW5kIHRoZW4gYWRkaW5nIHRoaXMgdG8gdGhlIG1hcC5cbiAqXG4gKiBUaGUgbWFpbiBhZHZhbnRhZ2Ugb2YgaGF2aW5nIHRoaXMgYXMgYSBjb250cm9sIHJhdGhlciB0aGFuIGEgc2ltcGxlIHNlcGFyYXRlXG4gKiBET00gZWxlbWVudCBpcyB0aGF0IHByZXZlbnRpbmcgcHJvcGFnYXRpb24gaXMgaGFuZGxlZCBmb3IgeW91LiBDb250cm9sc1xuICogd2lsbCBhbHNvIGJlIG9iamVjdHMgaW4gYSB7QGxpbmsgbW9kdWxlOm9sL0NvbGxlY3Rpb25+Q29sbGVjdGlvbn0sIHNvIHlvdSBjYW4gdXNlIHRoZWlyIG1ldGhvZHMuXG4gKlxuICogWW91IGNhbiBhbHNvIGV4dGVuZCB0aGlzIGJhc2UgZm9yIHlvdXIgb3duIGNvbnRyb2wgY2xhc3MuIFNlZVxuICogZXhhbXBsZXMvY3VzdG9tLWNvbnRyb2xzIGZvciBhbiBleGFtcGxlIG9mIGhvdyB0byBkbyB0aGlzLlxuICpcbiAqIEBhcGlcbiAqL1xuXG52YXIgQ29udHJvbCA9XG4vKiogQGNsYXNzICovXG5mdW5jdGlvbiAoX3N1cGVyKSB7XG4gIF9fZXh0ZW5kcyhDb250cm9sLCBfc3VwZXIpO1xuICAvKipcbiAgICogQHBhcmFtIHtPcHRpb25zfSBvcHRpb25zIENvbnRyb2wgb3B0aW9ucy5cbiAgICovXG5cblxuICBmdW5jdGlvbiBDb250cm9sKG9wdGlvbnMpIHtcbiAgICB2YXIgX3RoaXMgPSBfc3VwZXIuY2FsbCh0aGlzKSB8fCB0aGlzO1xuXG4gICAgdmFyIGVsZW1lbnQgPSBvcHRpb25zLmVsZW1lbnQ7XG5cbiAgICBpZiAoZWxlbWVudCAmJiAhb3B0aW9ucy50YXJnZXQgJiYgIWVsZW1lbnQuc3R5bGUucG9pbnRlckV2ZW50cykge1xuICAgICAgZWxlbWVudC5zdHlsZS5wb2ludGVyRXZlbnRzID0gJ2F1dG8nO1xuICAgIH1cbiAgICAvKipcbiAgICAgKiBAcHJvdGVjdGVkXG4gICAgICogQHR5cGUge0hUTUxFbGVtZW50fVxuICAgICAqL1xuXG5cbiAgICBfdGhpcy5lbGVtZW50ID0gZWxlbWVudCA/IGVsZW1lbnQgOiBudWxsO1xuICAgIC8qKlxuICAgICAqIEBwcml2YXRlXG4gICAgICogQHR5cGUge0hUTUxFbGVtZW50fVxuICAgICAqL1xuXG4gICAgX3RoaXMudGFyZ2V0XyA9IG51bGw7XG4gICAgLyoqXG4gICAgICogQHByaXZhdGVcbiAgICAgKiBAdHlwZSB7aW1wb3J0KFwiLi4vUGx1Z2dhYmxlTWFwLmpzXCIpLmRlZmF1bHR9XG4gICAgICovXG5cbiAgICBfdGhpcy5tYXBfID0gbnVsbDtcbiAgICAvKipcbiAgICAgKiBAcHJvdGVjdGVkXG4gICAgICogQHR5cGUgeyFBcnJheTxpbXBvcnQoXCIuLi9ldmVudHMuanNcIikuRXZlbnRzS2V5Pn1cbiAgICAgKi9cblxuICAgIF90aGlzLmxpc3RlbmVyS2V5cyA9IFtdO1xuXG4gICAgaWYgKG9wdGlvbnMucmVuZGVyKSB7XG4gICAgICBfdGhpcy5yZW5kZXIgPSBvcHRpb25zLnJlbmRlcjtcbiAgICB9XG5cbiAgICBpZiAob3B0aW9ucy50YXJnZXQpIHtcbiAgICAgIF90aGlzLnNldFRhcmdldChvcHRpb25zLnRhcmdldCk7XG4gICAgfVxuXG4gICAgcmV0dXJuIF90aGlzO1xuICB9XG4gIC8qKlxuICAgKiBDbGVhbiB1cC5cbiAgICovXG5cblxuICBDb250cm9sLnByb3RvdHlwZS5kaXNwb3NlSW50ZXJuYWwgPSBmdW5jdGlvbiAoKSB7XG4gICAgcmVtb3ZlTm9kZSh0aGlzLmVsZW1lbnQpO1xuXG4gICAgX3N1cGVyLnByb3RvdHlwZS5kaXNwb3NlSW50ZXJuYWwuY2FsbCh0aGlzKTtcbiAgfTtcbiAgLyoqXG4gICAqIEdldCB0aGUgbWFwIGFzc29jaWF0ZWQgd2l0aCB0aGlzIGNvbnRyb2wuXG4gICAqIEByZXR1cm4ge2ltcG9ydChcIi4uL1BsdWdnYWJsZU1hcC5qc1wiKS5kZWZhdWx0fSBNYXAuXG4gICAqIEBhcGlcbiAgICovXG5cblxuICBDb250cm9sLnByb3RvdHlwZS5nZXRNYXAgPSBmdW5jdGlvbiAoKSB7XG4gICAgcmV0dXJuIHRoaXMubWFwXztcbiAgfTtcbiAgLyoqXG4gICAqIFJlbW92ZSB0aGUgY29udHJvbCBmcm9tIGl0cyBjdXJyZW50IG1hcCBhbmQgYXR0YWNoIGl0IHRvIHRoZSBuZXcgbWFwLlxuICAgKiBTdWJjbGFzc2VzIG1heSBzZXQgdXAgZXZlbnQgaGFuZGxlcnMgdG8gZ2V0IG5vdGlmaWVkIGFib3V0IGNoYW5nZXMgdG9cbiAgICogdGhlIG1hcCBoZXJlLlxuICAgKiBAcGFyYW0ge2ltcG9ydChcIi4uL1BsdWdnYWJsZU1hcC5qc1wiKS5kZWZhdWx0fSBtYXAgTWFwLlxuICAgKiBAYXBpXG4gICAqL1xuXG5cbiAgQ29udHJvbC5wcm90b3R5cGUuc2V0TWFwID0gZnVuY3Rpb24gKG1hcCkge1xuICAgIGlmICh0aGlzLm1hcF8pIHtcbiAgICAgIHJlbW92ZU5vZGUodGhpcy5lbGVtZW50KTtcbiAgICB9XG5cbiAgICBmb3IgKHZhciBpID0gMCwgaWkgPSB0aGlzLmxpc3RlbmVyS2V5cy5sZW5ndGg7IGkgPCBpaTsgKytpKSB7XG4gICAgICB1bmxpc3RlbkJ5S2V5KHRoaXMubGlzdGVuZXJLZXlzW2ldKTtcbiAgICB9XG5cbiAgICB0aGlzLmxpc3RlbmVyS2V5cy5sZW5ndGggPSAwO1xuICAgIHRoaXMubWFwXyA9IG1hcDtcblxuICAgIGlmICh0aGlzLm1hcF8pIHtcbiAgICAgIHZhciB0YXJnZXQgPSB0aGlzLnRhcmdldF8gPyB0aGlzLnRhcmdldF8gOiBtYXAuZ2V0T3ZlcmxheUNvbnRhaW5lclN0b3BFdmVudCgpO1xuICAgICAgdGFyZ2V0LmFwcGVuZENoaWxkKHRoaXMuZWxlbWVudCk7XG5cbiAgICAgIGlmICh0aGlzLnJlbmRlciAhPT0gVk9JRCkge1xuICAgICAgICB0aGlzLmxpc3RlbmVyS2V5cy5wdXNoKGxpc3RlbihtYXAsIE1hcEV2ZW50VHlwZS5QT1NUUkVOREVSLCB0aGlzLnJlbmRlciwgdGhpcykpO1xuICAgICAgfVxuXG4gICAgICBtYXAucmVuZGVyKCk7XG4gICAgfVxuICB9O1xuICAvKipcbiAgICogUmVuZGVycyB0aGUgY29udHJvbC5cbiAgICogQHBhcmFtIHtpbXBvcnQoXCIuLi9NYXBFdmVudC5qc1wiKS5kZWZhdWx0fSBtYXBFdmVudCBNYXAgZXZlbnQuXG4gICAqIEBhcGlcbiAgICovXG5cblxuICBDb250cm9sLnByb3RvdHlwZS5yZW5kZXIgPSBmdW5jdGlvbiAobWFwRXZlbnQpIHt9O1xuICAvKipcbiAgICogVGhpcyBmdW5jdGlvbiBpcyB1c2VkIHRvIHNldCBhIHRhcmdldCBlbGVtZW50IGZvciB0aGUgY29udHJvbC4gSXQgaGFzIG5vXG4gICAqIGVmZmVjdCBpZiBpdCBpcyBjYWxsZWQgYWZ0ZXIgdGhlIGNvbnRyb2wgaGFzIGJlZW4gYWRkZWQgdG8gdGhlIG1hcCAoaS5lLlxuICAgKiBhZnRlciBgc2V0TWFwYCBpcyBjYWxsZWQgb24gdGhlIGNvbnRyb2wpLiBJZiBubyBgdGFyZ2V0YCBpcyBzZXQgaW4gdGhlXG4gICAqIG9wdGlvbnMgcGFzc2VkIHRvIHRoZSBjb250cm9sIGNvbnN0cnVjdG9yIGFuZCBpZiBgc2V0VGFyZ2V0YCBpcyBub3QgY2FsbGVkXG4gICAqIHRoZW4gdGhlIGNvbnRyb2wgaXMgYWRkZWQgdG8gdGhlIG1hcCdzIG92ZXJsYXkgY29udGFpbmVyLlxuICAgKiBAcGFyYW0ge0hUTUxFbGVtZW50fHN0cmluZ30gdGFyZ2V0IFRhcmdldC5cbiAgICogQGFwaVxuICAgKi9cblxuXG4gIENvbnRyb2wucHJvdG90eXBlLnNldFRhcmdldCA9IGZ1bmN0aW9uICh0YXJnZXQpIHtcbiAgICB0aGlzLnRhcmdldF8gPSB0eXBlb2YgdGFyZ2V0ID09PSAnc3RyaW5nJyA/IGRvY3VtZW50LmdldEVsZW1lbnRCeUlkKHRhcmdldCkgOiB0YXJnZXQ7XG4gIH07XG5cbiAgcmV0dXJuIENvbnRyb2w7XG59KEJhc2VPYmplY3QpO1xuXG5leHBvcnQgZGVmYXVsdCBDb250cm9sOyIsInZhciBfX2V4dGVuZHMgPSB0aGlzICYmIHRoaXMuX19leHRlbmRzIHx8IGZ1bmN0aW9uICgpIHtcbiAgdmFyIF9leHRlbmRTdGF0aWNzID0gZnVuY3Rpb24gZXh0ZW5kU3RhdGljcyhkLCBiKSB7XG4gICAgX2V4dGVuZFN0YXRpY3MgPSBPYmplY3Quc2V0UHJvdG90eXBlT2YgfHwge1xuICAgICAgX19wcm90b19fOiBbXVxuICAgIH0gaW5zdGFuY2VvZiBBcnJheSAmJiBmdW5jdGlvbiAoZCwgYikge1xuICAgICAgZC5fX3Byb3RvX18gPSBiO1xuICAgIH0gfHwgZnVuY3Rpb24gKGQsIGIpIHtcbiAgICAgIGZvciAodmFyIHAgaW4gYikge1xuICAgICAgICBpZiAoT2JqZWN0LnByb3RvdHlwZS5oYXNPd25Qcm9wZXJ0eS5jYWxsKGIsIHApKSBkW3BdID0gYltwXTtcbiAgICAgIH1cbiAgICB9O1xuXG4gICAgcmV0dXJuIF9leHRlbmRTdGF0aWNzKGQsIGIpO1xuICB9O1xuXG4gIHJldHVybiBmdW5jdGlvbiAoZCwgYikge1xuICAgIF9leHRlbmRTdGF0aWNzKGQsIGIpO1xuXG4gICAgZnVuY3Rpb24gX18oKSB7XG4gICAgICB0aGlzLmNvbnN0cnVjdG9yID0gZDtcbiAgICB9XG5cbiAgICBkLnByb3RvdHlwZSA9IGIgPT09IG51bGwgPyBPYmplY3QuY3JlYXRlKGIpIDogKF9fLnByb3RvdHlwZSA9IGIucHJvdG90eXBlLCBuZXcgX18oKSk7XG4gIH07XG59KCk7XG4vKipcbiAqIEBtb2R1bGUgb2wvY29udHJvbC9BdHRyaWJ1dGlvblxuICovXG5cblxuaW1wb3J0IENvbnRyb2wgZnJvbSAnLi9Db250cm9sLmpzJztcbmltcG9ydCBFdmVudFR5cGUgZnJvbSAnLi4vZXZlbnRzL0V2ZW50VHlwZS5qcyc7XG5pbXBvcnQgeyBDTEFTU19DT0xMQVBTRUQsIENMQVNTX0NPTlRST0wsIENMQVNTX1VOU0VMRUNUQUJMRSB9IGZyb20gJy4uL2Nzcy5qcyc7XG5pbXBvcnQgeyBlcXVhbHMgfSBmcm9tICcuLi9hcnJheS5qcyc7XG5pbXBvcnQgeyBpblZpZXcgfSBmcm9tICcuLi9sYXllci9MYXllci5qcyc7XG5pbXBvcnQgeyByZW1vdmVDaGlsZHJlbiwgcmVwbGFjZU5vZGUgfSBmcm9tICcuLi9kb20uanMnO1xuLyoqXG4gKiBAdHlwZWRlZiB7T2JqZWN0fSBPcHRpb25zXG4gKiBAcHJvcGVydHkge3N0cmluZ30gW2NsYXNzTmFtZT0nb2wtYXR0cmlidXRpb24nXSBDU1MgY2xhc3MgbmFtZS5cbiAqIEBwcm9wZXJ0eSB7SFRNTEVsZW1lbnR8c3RyaW5nfSBbdGFyZ2V0XSBTcGVjaWZ5IGEgdGFyZ2V0IGlmIHlvdVxuICogd2FudCB0aGUgY29udHJvbCB0byBiZSByZW5kZXJlZCBvdXRzaWRlIG9mIHRoZSBtYXAnc1xuICogdmlld3BvcnQuXG4gKiBAcHJvcGVydHkge2Jvb2xlYW59IFtjb2xsYXBzaWJsZV0gU3BlY2lmeSBpZiBhdHRyaWJ1dGlvbnMgY2FuXG4gKiBiZSBjb2xsYXBzZWQuIElmIG5vdCBzcGVjaWZpZWQsIHNvdXJjZXMgY29udHJvbCB0aGlzIGJlaGF2aW9yIHdpdGggdGhlaXJcbiAqIGBhdHRyaWJ1dGlvbnNDb2xsYXBzaWJsZWAgc2V0dGluZy5cbiAqIEBwcm9wZXJ0eSB7Ym9vbGVhbn0gW2NvbGxhcHNlZD10cnVlXSBTcGVjaWZ5IGlmIGF0dHJpYnV0aW9ucyBzaG91bGRcbiAqIGJlIGNvbGxhcHNlZCBhdCBzdGFydHVwLlxuICogQHByb3BlcnR5IHtzdHJpbmd9IFt0aXBMYWJlbD0nQXR0cmlidXRpb25zJ10gVGV4dCBsYWJlbCB0byB1c2UgZm9yIHRoZSBidXR0b24gdGlwLlxuICogQHByb3BlcnR5IHtzdHJpbmd9IFtsYWJlbD0naSddIFRleHQgbGFiZWwgdG8gdXNlIGZvciB0aGVcbiAqIGNvbGxhcHNlZCBhdHRyaWJ1dGlvbnMgYnV0dG9uLlxuICogSW5zdGVhZCBvZiB0ZXh0LCBhbHNvIGFuIGVsZW1lbnQgKGUuZy4gYSBgc3BhbmAgZWxlbWVudCkgY2FuIGJlIHVzZWQuXG4gKiBAcHJvcGVydHkge3N0cmluZ30gW2V4cGFuZENsYXNzTmFtZT1jbGFzc05hbWUgKyAnLWV4cGFuZCddIENTUyBjbGFzcyBuYW1lIGZvciB0aGVcbiAqIGNvbGxhcHNlZCBhdHRyaWJ1dGlvbnMgYnV0dG9uLlxuICogQHByb3BlcnR5IHtzdHJpbmd8SFRNTEVsZW1lbnR9IFtjb2xsYXBzZUxhYmVsPSfCuyddIFRleHQgbGFiZWwgdG8gdXNlXG4gKiBmb3IgdGhlIGV4cGFuZGVkIGF0dHJpYnV0aW9ucyBidXR0b24uXG4gKiBJbnN0ZWFkIG9mIHRleHQsIGFsc28gYW4gZWxlbWVudCAoZS5nLiBhIGBzcGFuYCBlbGVtZW50KSBjYW4gYmUgdXNlZC5cbiAqIEBwcm9wZXJ0eSB7c3RyaW5nfSBbY29sbGFwc2VDbGFzc05hbWU9Y2xhc3NOYW1lICsgJy1jb2xsYXBzZSddIENTUyBjbGFzcyBuYW1lIGZvciB0aGVcbiAqIGV4cGFuZGVkIGF0dHJpYnV0aW9ucyBidXR0b24uXG4gKiBAcHJvcGVydHkge2Z1bmN0aW9uKGltcG9ydChcIi4uL01hcEV2ZW50LmpzXCIpLmRlZmF1bHQpOnZvaWR9IFtyZW5kZXJdIEZ1bmN0aW9uIGNhbGxlZCB3aGVuXG4gKiB0aGUgY29udHJvbCBzaG91bGQgYmUgcmUtcmVuZGVyZWQuIFRoaXMgaXMgY2FsbGVkIGluIGEgYHJlcXVlc3RBbmltYXRpb25GcmFtZWBcbiAqIGNhbGxiYWNrLlxuICovXG5cbi8qKlxuICogQGNsYXNzZGVzY1xuICogQ29udHJvbCB0byBzaG93IGFsbCB0aGUgYXR0cmlidXRpb25zIGFzc29jaWF0ZWQgd2l0aCB0aGUgbGF5ZXIgc291cmNlc1xuICogaW4gdGhlIG1hcC4gVGhpcyBjb250cm9sIGlzIG9uZSBvZiB0aGUgZGVmYXVsdCBjb250cm9scyBpbmNsdWRlZCBpbiBtYXBzLlxuICogQnkgZGVmYXVsdCBpdCB3aWxsIHNob3cgaW4gdGhlIGJvdHRvbSByaWdodCBwb3J0aW9uIG9mIHRoZSBtYXAsIGJ1dCB0aGlzIGNhblxuICogYmUgY2hhbmdlZCBieSB1c2luZyBhIGNzcyBzZWxlY3RvciBmb3IgYC5vbC1hdHRyaWJ1dGlvbmAuXG4gKlxuICogQGFwaVxuICovXG5cbnZhciBBdHRyaWJ1dGlvbiA9XG4vKiogQGNsYXNzICovXG5mdW5jdGlvbiAoX3N1cGVyKSB7XG4gIF9fZXh0ZW5kcyhBdHRyaWJ1dGlvbiwgX3N1cGVyKTtcbiAgLyoqXG4gICAqIEBwYXJhbSB7T3B0aW9ucz19IG9wdF9vcHRpb25zIEF0dHJpYnV0aW9uIG9wdGlvbnMuXG4gICAqL1xuXG5cbiAgZnVuY3Rpb24gQXR0cmlidXRpb24ob3B0X29wdGlvbnMpIHtcbiAgICB2YXIgX3RoaXMgPSB0aGlzO1xuXG4gICAgdmFyIG9wdGlvbnMgPSBvcHRfb3B0aW9ucyA/IG9wdF9vcHRpb25zIDoge307XG4gICAgX3RoaXMgPSBfc3VwZXIuY2FsbCh0aGlzLCB7XG4gICAgICBlbGVtZW50OiBkb2N1bWVudC5jcmVhdGVFbGVtZW50KCdkaXYnKSxcbiAgICAgIHJlbmRlcjogb3B0aW9ucy5yZW5kZXIsXG4gICAgICB0YXJnZXQ6IG9wdGlvbnMudGFyZ2V0XG4gICAgfSkgfHwgdGhpcztcbiAgICAvKipcbiAgICAgKiBAcHJpdmF0ZVxuICAgICAqIEB0eXBlIHtIVE1MRWxlbWVudH1cbiAgICAgKi9cblxuICAgIF90aGlzLnVsRWxlbWVudF8gPSBkb2N1bWVudC5jcmVhdGVFbGVtZW50KCd1bCcpO1xuICAgIC8qKlxuICAgICAqIEBwcml2YXRlXG4gICAgICogQHR5cGUge2Jvb2xlYW59XG4gICAgICovXG5cbiAgICBfdGhpcy5jb2xsYXBzZWRfID0gb3B0aW9ucy5jb2xsYXBzZWQgIT09IHVuZGVmaW5lZCA/IG9wdGlvbnMuY29sbGFwc2VkIDogdHJ1ZTtcbiAgICAvKipcbiAgICAgKiBAcHJpdmF0ZVxuICAgICAqIEB0eXBlIHtib29sZWFufVxuICAgICAqL1xuXG4gICAgX3RoaXMudXNlckNvbGxhcHNlZF8gPSBfdGhpcy5jb2xsYXBzZWRfO1xuICAgIC8qKlxuICAgICAqIEBwcml2YXRlXG4gICAgICogQHR5cGUge2Jvb2xlYW59XG4gICAgICovXG5cbiAgICBfdGhpcy5vdmVycmlkZUNvbGxhcHNpYmxlXyA9IG9wdGlvbnMuY29sbGFwc2libGUgIT09IHVuZGVmaW5lZDtcbiAgICAvKipcbiAgICAgKiBAcHJpdmF0ZVxuICAgICAqIEB0eXBlIHtib29sZWFufVxuICAgICAqL1xuXG4gICAgX3RoaXMuY29sbGFwc2libGVfID0gb3B0aW9ucy5jb2xsYXBzaWJsZSAhPT0gdW5kZWZpbmVkID8gb3B0aW9ucy5jb2xsYXBzaWJsZSA6IHRydWU7XG5cbiAgICBpZiAoIV90aGlzLmNvbGxhcHNpYmxlXykge1xuICAgICAgX3RoaXMuY29sbGFwc2VkXyA9IGZhbHNlO1xuICAgIH1cblxuICAgIHZhciBjbGFzc05hbWUgPSBvcHRpb25zLmNsYXNzTmFtZSAhPT0gdW5kZWZpbmVkID8gb3B0aW9ucy5jbGFzc05hbWUgOiAnb2wtYXR0cmlidXRpb24nO1xuICAgIHZhciB0aXBMYWJlbCA9IG9wdGlvbnMudGlwTGFiZWwgIT09IHVuZGVmaW5lZCA/IG9wdGlvbnMudGlwTGFiZWwgOiAnQXR0cmlidXRpb25zJztcbiAgICB2YXIgZXhwYW5kQ2xhc3NOYW1lID0gb3B0aW9ucy5leHBhbmRDbGFzc05hbWUgIT09IHVuZGVmaW5lZCA/IG9wdGlvbnMuZXhwYW5kQ2xhc3NOYW1lIDogY2xhc3NOYW1lICsgJy1leHBhbmQnO1xuICAgIHZhciBjb2xsYXBzZUxhYmVsID0gb3B0aW9ucy5jb2xsYXBzZUxhYmVsICE9PSB1bmRlZmluZWQgPyBvcHRpb25zLmNvbGxhcHNlTGFiZWwgOiBcIlxceEJCXCI7XG4gICAgdmFyIGNvbGxhcHNlQ2xhc3NOYW1lID0gb3B0aW9ucy5jb2xsYXBzZUNsYXNzTmFtZSAhPT0gdW5kZWZpbmVkID8gb3B0aW9ucy5jb2xsYXBzZUNsYXNzTmFtZSA6IGNsYXNzTmFtZSArICctY29sbHBhc2UnO1xuXG4gICAgaWYgKHR5cGVvZiBjb2xsYXBzZUxhYmVsID09PSAnc3RyaW5nJykge1xuICAgICAgLyoqXG4gICAgICAgKiBAcHJpdmF0ZVxuICAgICAgICogQHR5cGUge0hUTUxFbGVtZW50fVxuICAgICAgICovXG4gICAgICBfdGhpcy5jb2xsYXBzZUxhYmVsXyA9IGRvY3VtZW50LmNyZWF0ZUVsZW1lbnQoJ3NwYW4nKTtcbiAgICAgIF90aGlzLmNvbGxhcHNlTGFiZWxfLnRleHRDb250ZW50ID0gY29sbGFwc2VMYWJlbDtcbiAgICAgIF90aGlzLmNvbGxhcHNlTGFiZWxfLmNsYXNzTmFtZSA9IGNvbGxhcHNlQ2xhc3NOYW1lO1xuICAgIH0gZWxzZSB7XG4gICAgICBfdGhpcy5jb2xsYXBzZUxhYmVsXyA9IGNvbGxhcHNlTGFiZWw7XG4gICAgfVxuXG4gICAgdmFyIGxhYmVsID0gb3B0aW9ucy5sYWJlbCAhPT0gdW5kZWZpbmVkID8gb3B0aW9ucy5sYWJlbCA6ICdpJztcblxuICAgIGlmICh0eXBlb2YgbGFiZWwgPT09ICdzdHJpbmcnKSB7XG4gICAgICAvKipcbiAgICAgICAqIEBwcml2YXRlXG4gICAgICAgKiBAdHlwZSB7SFRNTEVsZW1lbnR9XG4gICAgICAgKi9cbiAgICAgIF90aGlzLmxhYmVsXyA9IGRvY3VtZW50LmNyZWF0ZUVsZW1lbnQoJ3NwYW4nKTtcbiAgICAgIF90aGlzLmxhYmVsXy50ZXh0Q29udGVudCA9IGxhYmVsO1xuICAgICAgX3RoaXMubGFiZWxfLmNsYXNzTmFtZSA9IGV4cGFuZENsYXNzTmFtZTtcbiAgICB9IGVsc2Uge1xuICAgICAgX3RoaXMubGFiZWxfID0gbGFiZWw7XG4gICAgfVxuXG4gICAgdmFyIGFjdGl2ZUxhYmVsID0gX3RoaXMuY29sbGFwc2libGVfICYmICFfdGhpcy5jb2xsYXBzZWRfID8gX3RoaXMuY29sbGFwc2VMYWJlbF8gOiBfdGhpcy5sYWJlbF87XG4gICAgdmFyIGJ1dHRvbiA9IGRvY3VtZW50LmNyZWF0ZUVsZW1lbnQoJ2J1dHRvbicpO1xuICAgIGJ1dHRvbi5zZXRBdHRyaWJ1dGUoJ3R5cGUnLCAnYnV0dG9uJyk7XG4gICAgYnV0dG9uLnRpdGxlID0gdGlwTGFiZWw7XG4gICAgYnV0dG9uLmFwcGVuZENoaWxkKGFjdGl2ZUxhYmVsKTtcbiAgICBidXR0b24uYWRkRXZlbnRMaXN0ZW5lcihFdmVudFR5cGUuQ0xJQ0ssIF90aGlzLmhhbmRsZUNsaWNrXy5iaW5kKF90aGlzKSwgZmFsc2UpO1xuICAgIHZhciBjc3NDbGFzc2VzID0gY2xhc3NOYW1lICsgJyAnICsgQ0xBU1NfVU5TRUxFQ1RBQkxFICsgJyAnICsgQ0xBU1NfQ09OVFJPTCArIChfdGhpcy5jb2xsYXBzZWRfICYmIF90aGlzLmNvbGxhcHNpYmxlXyA/ICcgJyArIENMQVNTX0NPTExBUFNFRCA6ICcnKSArIChfdGhpcy5jb2xsYXBzaWJsZV8gPyAnJyA6ICcgb2wtdW5jb2xsYXBzaWJsZScpO1xuICAgIHZhciBlbGVtZW50ID0gX3RoaXMuZWxlbWVudDtcbiAgICBlbGVtZW50LmNsYXNzTmFtZSA9IGNzc0NsYXNzZXM7XG4gICAgZWxlbWVudC5hcHBlbmRDaGlsZChfdGhpcy51bEVsZW1lbnRfKTtcbiAgICBlbGVtZW50LmFwcGVuZENoaWxkKGJ1dHRvbik7XG4gICAgLyoqXG4gICAgICogQSBsaXN0IG9mIGN1cnJlbnRseSByZW5kZXJlZCByZXNvbHV0aW9ucy5cbiAgICAgKiBAdHlwZSB7QXJyYXk8c3RyaW5nPn1cbiAgICAgKiBAcHJpdmF0ZVxuICAgICAqL1xuXG4gICAgX3RoaXMucmVuZGVyZWRBdHRyaWJ1dGlvbnNfID0gW107XG4gICAgLyoqXG4gICAgICogQHByaXZhdGVcbiAgICAgKiBAdHlwZSB7Ym9vbGVhbn1cbiAgICAgKi9cblxuICAgIF90aGlzLnJlbmRlcmVkVmlzaWJsZV8gPSB0cnVlO1xuICAgIHJldHVybiBfdGhpcztcbiAgfVxuICAvKipcbiAgICogQ29sbGVjdCBhIGxpc3Qgb2YgdmlzaWJsZSBhdHRyaWJ1dGlvbnMgYW5kIHNldCB0aGUgY29sbGFwc2libGUgc3RhdGUuXG4gICAqIEBwYXJhbSB7aW1wb3J0KFwiLi4vUGx1Z2dhYmxlTWFwLmpzXCIpLkZyYW1lU3RhdGV9IGZyYW1lU3RhdGUgRnJhbWUgc3RhdGUuXG4gICAqIEByZXR1cm4ge0FycmF5PHN0cmluZz59IEF0dHJpYnV0aW9ucy5cbiAgICogQHByaXZhdGVcbiAgICovXG5cblxuICBBdHRyaWJ1dGlvbi5wcm90b3R5cGUuY29sbGVjdFNvdXJjZUF0dHJpYnV0aW9uc18gPSBmdW5jdGlvbiAoZnJhbWVTdGF0ZSkge1xuICAgIC8qKlxuICAgICAqIFVzZWQgdG8gZGV0ZXJtaW5lIGlmIGFuIGF0dHJpYnV0aW9uIGFscmVhZHkgZXhpc3RzLlxuICAgICAqIEB0eXBlIHshT2JqZWN0PHN0cmluZywgYm9vbGVhbj59XG4gICAgICovXG4gICAgdmFyIGxvb2t1cCA9IHt9O1xuICAgIC8qKlxuICAgICAqIEEgbGlzdCBvZiB2aXNpYmxlIGF0dHJpYnV0aW9ucy5cbiAgICAgKiBAdHlwZSB7QXJyYXk8c3RyaW5nPn1cbiAgICAgKi9cblxuICAgIHZhciB2aXNpYmxlQXR0cmlidXRpb25zID0gW107XG4gICAgdmFyIGNvbGxhcHNpYmxlID0gdHJ1ZTtcbiAgICB2YXIgbGF5ZXJTdGF0ZXNBcnJheSA9IGZyYW1lU3RhdGUubGF5ZXJTdGF0ZXNBcnJheTtcblxuICAgIGZvciAodmFyIGkgPSAwLCBpaSA9IGxheWVyU3RhdGVzQXJyYXkubGVuZ3RoOyBpIDwgaWk7ICsraSkge1xuICAgICAgdmFyIGxheWVyU3RhdGUgPSBsYXllclN0YXRlc0FycmF5W2ldO1xuXG4gICAgICBpZiAoIWluVmlldyhsYXllclN0YXRlLCBmcmFtZVN0YXRlLnZpZXdTdGF0ZSkpIHtcbiAgICAgICAgY29udGludWU7XG4gICAgICB9XG5cbiAgICAgIHZhciBzb3VyY2UgPVxuICAgICAgLyoqIEB0eXBlIHtpbXBvcnQoXCIuLi9sYXllci9MYXllci5qc1wiKS5kZWZhdWx0fSAqL1xuICAgICAgbGF5ZXJTdGF0ZS5sYXllci5nZXRTb3VyY2UoKTtcblxuICAgICAgaWYgKCFzb3VyY2UpIHtcbiAgICAgICAgY29udGludWU7XG4gICAgICB9XG5cbiAgICAgIHZhciBhdHRyaWJ1dGlvbkdldHRlciA9IHNvdXJjZS5nZXRBdHRyaWJ1dGlvbnMoKTtcblxuICAgICAgaWYgKCFhdHRyaWJ1dGlvbkdldHRlcikge1xuICAgICAgICBjb250aW51ZTtcbiAgICAgIH1cblxuICAgICAgdmFyIGF0dHJpYnV0aW9ucyA9IGF0dHJpYnV0aW9uR2V0dGVyKGZyYW1lU3RhdGUpO1xuXG4gICAgICBpZiAoIWF0dHJpYnV0aW9ucykge1xuICAgICAgICBjb250aW51ZTtcbiAgICAgIH1cblxuICAgICAgY29sbGFwc2libGUgPSBjb2xsYXBzaWJsZSAmJiBzb3VyY2UuZ2V0QXR0cmlidXRpb25zQ29sbGFwc2libGUoKSAhPT0gZmFsc2U7XG5cbiAgICAgIGlmIChBcnJheS5pc0FycmF5KGF0dHJpYnV0aW9ucykpIHtcbiAgICAgICAgZm9yICh2YXIgaiA9IDAsIGpqID0gYXR0cmlidXRpb25zLmxlbmd0aDsgaiA8IGpqOyArK2opIHtcbiAgICAgICAgICBpZiAoIShhdHRyaWJ1dGlvbnNbal0gaW4gbG9va3VwKSkge1xuICAgICAgICAgICAgdmlzaWJsZUF0dHJpYnV0aW9ucy5wdXNoKGF0dHJpYnV0aW9uc1tqXSk7XG4gICAgICAgICAgICBsb29rdXBbYXR0cmlidXRpb25zW2pdXSA9IHRydWU7XG4gICAgICAgICAgfVxuICAgICAgICB9XG4gICAgICB9IGVsc2Uge1xuICAgICAgICBpZiAoIShhdHRyaWJ1dGlvbnMgaW4gbG9va3VwKSkge1xuICAgICAgICAgIHZpc2libGVBdHRyaWJ1dGlvbnMucHVzaChhdHRyaWJ1dGlvbnMpO1xuICAgICAgICAgIGxvb2t1cFthdHRyaWJ1dGlvbnNdID0gdHJ1ZTtcbiAgICAgICAgfVxuICAgICAgfVxuICAgIH1cblxuICAgIGlmICghdGhpcy5vdmVycmlkZUNvbGxhcHNpYmxlXykge1xuICAgICAgdGhpcy5zZXRDb2xsYXBzaWJsZShjb2xsYXBzaWJsZSk7XG4gICAgfVxuXG4gICAgcmV0dXJuIHZpc2libGVBdHRyaWJ1dGlvbnM7XG4gIH07XG4gIC8qKlxuICAgKiBAcHJpdmF0ZVxuICAgKiBAcGFyYW0gez9pbXBvcnQoXCIuLi9QbHVnZ2FibGVNYXAuanNcIikuRnJhbWVTdGF0ZX0gZnJhbWVTdGF0ZSBGcmFtZSBzdGF0ZS5cbiAgICovXG5cblxuICBBdHRyaWJ1dGlvbi5wcm90b3R5cGUudXBkYXRlRWxlbWVudF8gPSBmdW5jdGlvbiAoZnJhbWVTdGF0ZSkge1xuICAgIGlmICghZnJhbWVTdGF0ZSkge1xuICAgICAgaWYgKHRoaXMucmVuZGVyZWRWaXNpYmxlXykge1xuICAgICAgICB0aGlzLmVsZW1lbnQuc3R5bGUuZGlzcGxheSA9ICdub25lJztcbiAgICAgICAgdGhpcy5yZW5kZXJlZFZpc2libGVfID0gZmFsc2U7XG4gICAgICB9XG5cbiAgICAgIHJldHVybjtcbiAgICB9XG5cbiAgICB2YXIgYXR0cmlidXRpb25zID0gdGhpcy5jb2xsZWN0U291cmNlQXR0cmlidXRpb25zXyhmcmFtZVN0YXRlKTtcbiAgICB2YXIgdmlzaWJsZSA9IGF0dHJpYnV0aW9ucy5sZW5ndGggPiAwO1xuXG4gICAgaWYgKHRoaXMucmVuZGVyZWRWaXNpYmxlXyAhPSB2aXNpYmxlKSB7XG4gICAgICB0aGlzLmVsZW1lbnQuc3R5bGUuZGlzcGxheSA9IHZpc2libGUgPyAnJyA6ICdub25lJztcbiAgICAgIHRoaXMucmVuZGVyZWRWaXNpYmxlXyA9IHZpc2libGU7XG4gICAgfVxuXG4gICAgaWYgKGVxdWFscyhhdHRyaWJ1dGlvbnMsIHRoaXMucmVuZGVyZWRBdHRyaWJ1dGlvbnNfKSkge1xuICAgICAgcmV0dXJuO1xuICAgIH1cblxuICAgIHJlbW92ZUNoaWxkcmVuKHRoaXMudWxFbGVtZW50Xyk7IC8vIGFwcGVuZCB0aGUgYXR0cmlidXRpb25zXG5cbiAgICBmb3IgKHZhciBpID0gMCwgaWkgPSBhdHRyaWJ1dGlvbnMubGVuZ3RoOyBpIDwgaWk7ICsraSkge1xuICAgICAgdmFyIGVsZW1lbnQgPSBkb2N1bWVudC5jcmVhdGVFbGVtZW50KCdsaScpO1xuICAgICAgZWxlbWVudC5pbm5lckhUTUwgPSBhdHRyaWJ1dGlvbnNbaV07XG4gICAgICB0aGlzLnVsRWxlbWVudF8uYXBwZW5kQ2hpbGQoZWxlbWVudCk7XG4gICAgfVxuXG4gICAgdGhpcy5yZW5kZXJlZEF0dHJpYnV0aW9uc18gPSBhdHRyaWJ1dGlvbnM7XG4gIH07XG4gIC8qKlxuICAgKiBAcGFyYW0ge01vdXNlRXZlbnR9IGV2ZW50IFRoZSBldmVudCB0byBoYW5kbGVcbiAgICogQHByaXZhdGVcbiAgICovXG5cblxuICBBdHRyaWJ1dGlvbi5wcm90b3R5cGUuaGFuZGxlQ2xpY2tfID0gZnVuY3Rpb24gKGV2ZW50KSB7XG4gICAgZXZlbnQucHJldmVudERlZmF1bHQoKTtcbiAgICB0aGlzLmhhbmRsZVRvZ2dsZV8oKTtcbiAgICB0aGlzLnVzZXJDb2xsYXBzZWRfID0gdGhpcy5jb2xsYXBzZWRfO1xuICB9O1xuICAvKipcbiAgICogQHByaXZhdGVcbiAgICovXG5cblxuICBBdHRyaWJ1dGlvbi5wcm90b3R5cGUuaGFuZGxlVG9nZ2xlXyA9IGZ1bmN0aW9uICgpIHtcbiAgICB0aGlzLmVsZW1lbnQuY2xhc3NMaXN0LnRvZ2dsZShDTEFTU19DT0xMQVBTRUQpO1xuXG4gICAgaWYgKHRoaXMuY29sbGFwc2VkXykge1xuICAgICAgcmVwbGFjZU5vZGUodGhpcy5jb2xsYXBzZUxhYmVsXywgdGhpcy5sYWJlbF8pO1xuICAgIH0gZWxzZSB7XG4gICAgICByZXBsYWNlTm9kZSh0aGlzLmxhYmVsXywgdGhpcy5jb2xsYXBzZUxhYmVsXyk7XG4gICAgfVxuXG4gICAgdGhpcy5jb2xsYXBzZWRfID0gIXRoaXMuY29sbGFwc2VkXztcbiAgfTtcbiAgLyoqXG4gICAqIFJldHVybiBgdHJ1ZWAgaWYgdGhlIGF0dHJpYnV0aW9uIGlzIGNvbGxhcHNpYmxlLCBgZmFsc2VgIG90aGVyd2lzZS5cbiAgICogQHJldHVybiB7Ym9vbGVhbn0gVHJ1ZSBpZiB0aGUgd2lkZ2V0IGlzIGNvbGxhcHNpYmxlLlxuICAgKiBAYXBpXG4gICAqL1xuXG5cbiAgQXR0cmlidXRpb24ucHJvdG90eXBlLmdldENvbGxhcHNpYmxlID0gZnVuY3Rpb24gKCkge1xuICAgIHJldHVybiB0aGlzLmNvbGxhcHNpYmxlXztcbiAgfTtcbiAgLyoqXG4gICAqIFNldCB3aGV0aGVyIHRoZSBhdHRyaWJ1dGlvbiBzaG91bGQgYmUgY29sbGFwc2libGUuXG4gICAqIEBwYXJhbSB7Ym9vbGVhbn0gY29sbGFwc2libGUgVHJ1ZSBpZiB0aGUgd2lkZ2V0IGlzIGNvbGxhcHNpYmxlLlxuICAgKiBAYXBpXG4gICAqL1xuXG5cbiAgQXR0cmlidXRpb24ucHJvdG90eXBlLnNldENvbGxhcHNpYmxlID0gZnVuY3Rpb24gKGNvbGxhcHNpYmxlKSB7XG4gICAgaWYgKHRoaXMuY29sbGFwc2libGVfID09PSBjb2xsYXBzaWJsZSkge1xuICAgICAgcmV0dXJuO1xuICAgIH1cblxuICAgIHRoaXMuY29sbGFwc2libGVfID0gY29sbGFwc2libGU7XG4gICAgdGhpcy5lbGVtZW50LmNsYXNzTGlzdC50b2dnbGUoJ29sLXVuY29sbGFwc2libGUnKTtcblxuICAgIGlmICh0aGlzLnVzZXJDb2xsYXBzZWRfKSB7XG4gICAgICB0aGlzLmhhbmRsZVRvZ2dsZV8oKTtcbiAgICB9XG4gIH07XG4gIC8qKlxuICAgKiBDb2xsYXBzZSBvciBleHBhbmQgdGhlIGF0dHJpYnV0aW9uIGFjY29yZGluZyB0byB0aGUgcGFzc2VkIHBhcmFtZXRlci4gV2lsbFxuICAgKiBub3QgZG8gYW55dGhpbmcgaWYgdGhlIGF0dHJpYnV0aW9uIGlzbid0IGNvbGxhcHNpYmxlIG9yIGlmIHRoZSBjdXJyZW50XG4gICAqIGNvbGxhcHNlZCBzdGF0ZSBpcyBhbHJlYWR5IHRoZSBvbmUgcmVxdWVzdGVkLlxuICAgKiBAcGFyYW0ge2Jvb2xlYW59IGNvbGxhcHNlZCBUcnVlIGlmIHRoZSB3aWRnZXQgaXMgY29sbGFwc2VkLlxuICAgKiBAYXBpXG4gICAqL1xuXG5cbiAgQXR0cmlidXRpb24ucHJvdG90eXBlLnNldENvbGxhcHNlZCA9IGZ1bmN0aW9uIChjb2xsYXBzZWQpIHtcbiAgICB0aGlzLnVzZXJDb2xsYXBzZWRfID0gY29sbGFwc2VkO1xuXG4gICAgaWYgKCF0aGlzLmNvbGxhcHNpYmxlXyB8fCB0aGlzLmNvbGxhcHNlZF8gPT09IGNvbGxhcHNlZCkge1xuICAgICAgcmV0dXJuO1xuICAgIH1cblxuICAgIHRoaXMuaGFuZGxlVG9nZ2xlXygpO1xuICB9O1xuICAvKipcbiAgICogUmV0dXJuIGB0cnVlYCB3aGVuIHRoZSBhdHRyaWJ1dGlvbiBpcyBjdXJyZW50bHkgY29sbGFwc2VkIG9yIGBmYWxzZWBcbiAgICogb3RoZXJ3aXNlLlxuICAgKiBAcmV0dXJuIHtib29sZWFufSBUcnVlIGlmIHRoZSB3aWRnZXQgaXMgY29sbGFwc2VkLlxuICAgKiBAYXBpXG4gICAqL1xuXG5cbiAgQXR0cmlidXRpb24ucHJvdG90eXBlLmdldENvbGxhcHNlZCA9IGZ1bmN0aW9uICgpIHtcbiAgICByZXR1cm4gdGhpcy5jb2xsYXBzZWRfO1xuICB9O1xuICAvKipcbiAgICogVXBkYXRlIHRoZSBhdHRyaWJ1dGlvbiBlbGVtZW50LlxuICAgKiBAcGFyYW0ge2ltcG9ydChcIi4uL01hcEV2ZW50LmpzXCIpLmRlZmF1bHR9IG1hcEV2ZW50IE1hcCBldmVudC5cbiAgICogQG92ZXJyaWRlXG4gICAqL1xuXG5cbiAgQXR0cmlidXRpb24ucHJvdG90eXBlLnJlbmRlciA9IGZ1bmN0aW9uIChtYXBFdmVudCkge1xuICAgIHRoaXMudXBkYXRlRWxlbWVudF8obWFwRXZlbnQuZnJhbWVTdGF0ZSk7XG4gIH07XG5cbiAgcmV0dXJuIEF0dHJpYnV0aW9uO1xufShDb250cm9sKTtcblxuZXhwb3J0IGRlZmF1bHQgQXR0cmlidXRpb247IiwidmFyIF9fZXh0ZW5kcyA9IHRoaXMgJiYgdGhpcy5fX2V4dGVuZHMgfHwgZnVuY3Rpb24gKCkge1xuICB2YXIgX2V4dGVuZFN0YXRpY3MgPSBmdW5jdGlvbiBleHRlbmRTdGF0aWNzKGQsIGIpIHtcbiAgICBfZXh0ZW5kU3RhdGljcyA9IE9iamVjdC5zZXRQcm90b3R5cGVPZiB8fCB7XG4gICAgICBfX3Byb3RvX186IFtdXG4gICAgfSBpbnN0YW5jZW9mIEFycmF5ICYmIGZ1bmN0aW9uIChkLCBiKSB7XG4gICAgICBkLl9fcHJvdG9fXyA9IGI7XG4gICAgfSB8fCBmdW5jdGlvbiAoZCwgYikge1xuICAgICAgZm9yICh2YXIgcCBpbiBiKSB7XG4gICAgICAgIGlmIChPYmplY3QucHJvdG90eXBlLmhhc093blByb3BlcnR5LmNhbGwoYiwgcCkpIGRbcF0gPSBiW3BdO1xuICAgICAgfVxuICAgIH07XG5cbiAgICByZXR1cm4gX2V4dGVuZFN0YXRpY3MoZCwgYik7XG4gIH07XG5cbiAgcmV0dXJuIGZ1bmN0aW9uIChkLCBiKSB7XG4gICAgX2V4dGVuZFN0YXRpY3MoZCwgYik7XG5cbiAgICBmdW5jdGlvbiBfXygpIHtcbiAgICAgIHRoaXMuY29uc3RydWN0b3IgPSBkO1xuICAgIH1cblxuICAgIGQucHJvdG90eXBlID0gYiA9PT0gbnVsbCA/IE9iamVjdC5jcmVhdGUoYikgOiAoX18ucHJvdG90eXBlID0gYi5wcm90b3R5cGUsIG5ldyBfXygpKTtcbiAgfTtcbn0oKTtcbi8qKlxuICogQG1vZHVsZSBvbC9jb250cm9sL1JvdGF0ZVxuICovXG5cblxuaW1wb3J0IENvbnRyb2wgZnJvbSAnLi9Db250cm9sLmpzJztcbmltcG9ydCBFdmVudFR5cGUgZnJvbSAnLi4vZXZlbnRzL0V2ZW50VHlwZS5qcyc7XG5pbXBvcnQgeyBDTEFTU19DT05UUk9MLCBDTEFTU19ISURERU4sIENMQVNTX1VOU0VMRUNUQUJMRSB9IGZyb20gJy4uL2Nzcy5qcyc7XG5pbXBvcnQgeyBlYXNlT3V0IH0gZnJvbSAnLi4vZWFzaW5nLmpzJztcbi8qKlxuICogQHR5cGVkZWYge09iamVjdH0gT3B0aW9uc1xuICogQHByb3BlcnR5IHtzdHJpbmd9IFtjbGFzc05hbWU9J29sLXJvdGF0ZSddIENTUyBjbGFzcyBuYW1lLlxuICogQHByb3BlcnR5IHtzdHJpbmd8SFRNTEVsZW1lbnR9IFtsYWJlbD0n4oenJ10gVGV4dCBsYWJlbCB0byB1c2UgZm9yIHRoZSByb3RhdGUgYnV0dG9uLlxuICogSW5zdGVhZCBvZiB0ZXh0LCBhbHNvIGFuIGVsZW1lbnQgKGUuZy4gYSBgc3BhbmAgZWxlbWVudCkgY2FuIGJlIHVzZWQuXG4gKiBAcHJvcGVydHkge3N0cmluZ30gW3RpcExhYmVsPSdSZXNldCByb3RhdGlvbiddIFRleHQgbGFiZWwgdG8gdXNlIGZvciB0aGUgcm90YXRlIHRpcC5cbiAqIEBwcm9wZXJ0eSB7c3RyaW5nfSBbY29tcGFzc0NsYXNzTmFtZT0nb2wtY29tcGFzcyddIENTUyBjbGFzcyBuYW1lIGZvciB0aGUgY29tcGFzcy5cbiAqIEBwcm9wZXJ0eSB7bnVtYmVyfSBbZHVyYXRpb249MjUwXSBBbmltYXRpb24gZHVyYXRpb24gaW4gbWlsbGlzZWNvbmRzLlxuICogQHByb3BlcnR5IHtib29sZWFufSBbYXV0b0hpZGU9dHJ1ZV0gSGlkZSB0aGUgY29udHJvbCB3aGVuIHJvdGF0aW9uIGlzIDAuXG4gKiBAcHJvcGVydHkge2Z1bmN0aW9uKGltcG9ydChcIi4uL01hcEV2ZW50LmpzXCIpLmRlZmF1bHQpOnZvaWR9IFtyZW5kZXJdIEZ1bmN0aW9uIGNhbGxlZCB3aGVuIHRoZSBjb250cm9sIHNob3VsZFxuICogYmUgcmUtcmVuZGVyZWQuIFRoaXMgaXMgY2FsbGVkIGluIGEgYHJlcXVlc3RBbmltYXRpb25GcmFtZWAgY2FsbGJhY2suXG4gKiBAcHJvcGVydHkge2Z1bmN0aW9uKCk6dm9pZH0gW3Jlc2V0Tm9ydGhdIEZ1bmN0aW9uIGNhbGxlZCB3aGVuIHRoZSBjb250cm9sIGlzIGNsaWNrZWQuXG4gKiBUaGlzIHdpbGwgb3ZlcnJpZGUgdGhlIGRlZmF1bHQgYHJlc2V0Tm9ydGhgLlxuICogQHByb3BlcnR5IHtIVE1MRWxlbWVudHxzdHJpbmd9IFt0YXJnZXRdIFNwZWNpZnkgYSB0YXJnZXQgaWYgeW91IHdhbnQgdGhlIGNvbnRyb2wgdG8gYmVcbiAqIHJlbmRlcmVkIG91dHNpZGUgb2YgdGhlIG1hcCdzIHZpZXdwb3J0LlxuICovXG5cbi8qKlxuICogQGNsYXNzZGVzY1xuICogQSBidXR0b24gY29udHJvbCB0byByZXNldCByb3RhdGlvbiB0byAwLlxuICogVG8gc3R5bGUgdGhpcyBjb250cm9sIHVzZSBjc3Mgc2VsZWN0b3IgYC5vbC1yb3RhdGVgLiBBIGAub2wtaGlkZGVuYCBjc3NcbiAqIHNlbGVjdG9yIGlzIGFkZGVkIHRvIHRoZSBidXR0b24gd2hlbiB0aGUgcm90YXRpb24gaXMgMC5cbiAqXG4gKiBAYXBpXG4gKi9cblxudmFyIFJvdGF0ZSA9XG4vKiogQGNsYXNzICovXG5mdW5jdGlvbiAoX3N1cGVyKSB7XG4gIF9fZXh0ZW5kcyhSb3RhdGUsIF9zdXBlcik7XG4gIC8qKlxuICAgKiBAcGFyYW0ge09wdGlvbnM9fSBvcHRfb3B0aW9ucyBSb3RhdGUgb3B0aW9ucy5cbiAgICovXG5cblxuICBmdW5jdGlvbiBSb3RhdGUob3B0X29wdGlvbnMpIHtcbiAgICB2YXIgX3RoaXMgPSB0aGlzO1xuXG4gICAgdmFyIG9wdGlvbnMgPSBvcHRfb3B0aW9ucyA/IG9wdF9vcHRpb25zIDoge307XG4gICAgX3RoaXMgPSBfc3VwZXIuY2FsbCh0aGlzLCB7XG4gICAgICBlbGVtZW50OiBkb2N1bWVudC5jcmVhdGVFbGVtZW50KCdkaXYnKSxcbiAgICAgIHJlbmRlcjogb3B0aW9ucy5yZW5kZXIsXG4gICAgICB0YXJnZXQ6IG9wdGlvbnMudGFyZ2V0XG4gICAgfSkgfHwgdGhpcztcbiAgICB2YXIgY2xhc3NOYW1lID0gb3B0aW9ucy5jbGFzc05hbWUgIT09IHVuZGVmaW5lZCA/IG9wdGlvbnMuY2xhc3NOYW1lIDogJ29sLXJvdGF0ZSc7XG4gICAgdmFyIGxhYmVsID0gb3B0aW9ucy5sYWJlbCAhPT0gdW5kZWZpbmVkID8gb3B0aW9ucy5sYWJlbCA6IFwiXFx1MjFFN1wiO1xuICAgIHZhciBjb21wYXNzQ2xhc3NOYW1lID0gb3B0aW9ucy5jb21wYXNzQ2xhc3NOYW1lICE9PSB1bmRlZmluZWQgPyBvcHRpb25zLmNvbXBhc3NDbGFzc05hbWUgOiAnb2wtY29tcGFzcyc7XG4gICAgLyoqXG4gICAgICogQHR5cGUge0hUTUxFbGVtZW50fVxuICAgICAqIEBwcml2YXRlXG4gICAgICovXG5cbiAgICBfdGhpcy5sYWJlbF8gPSBudWxsO1xuXG4gICAgaWYgKHR5cGVvZiBsYWJlbCA9PT0gJ3N0cmluZycpIHtcbiAgICAgIF90aGlzLmxhYmVsXyA9IGRvY3VtZW50LmNyZWF0ZUVsZW1lbnQoJ3NwYW4nKTtcbiAgICAgIF90aGlzLmxhYmVsXy5jbGFzc05hbWUgPSBjb21wYXNzQ2xhc3NOYW1lO1xuICAgICAgX3RoaXMubGFiZWxfLnRleHRDb250ZW50ID0gbGFiZWw7XG4gICAgfSBlbHNlIHtcbiAgICAgIF90aGlzLmxhYmVsXyA9IGxhYmVsO1xuXG4gICAgICBfdGhpcy5sYWJlbF8uY2xhc3NMaXN0LmFkZChjb21wYXNzQ2xhc3NOYW1lKTtcbiAgICB9XG5cbiAgICB2YXIgdGlwTGFiZWwgPSBvcHRpb25zLnRpcExhYmVsID8gb3B0aW9ucy50aXBMYWJlbCA6ICdSZXNldCByb3RhdGlvbic7XG4gICAgdmFyIGJ1dHRvbiA9IGRvY3VtZW50LmNyZWF0ZUVsZW1lbnQoJ2J1dHRvbicpO1xuICAgIGJ1dHRvbi5jbGFzc05hbWUgPSBjbGFzc05hbWUgKyAnLXJlc2V0JztcbiAgICBidXR0b24uc2V0QXR0cmlidXRlKCd0eXBlJywgJ2J1dHRvbicpO1xuICAgIGJ1dHRvbi50aXRsZSA9IHRpcExhYmVsO1xuICAgIGJ1dHRvbi5hcHBlbmRDaGlsZChfdGhpcy5sYWJlbF8pO1xuICAgIGJ1dHRvbi5hZGRFdmVudExpc3RlbmVyKEV2ZW50VHlwZS5DTElDSywgX3RoaXMuaGFuZGxlQ2xpY2tfLmJpbmQoX3RoaXMpLCBmYWxzZSk7XG4gICAgdmFyIGNzc0NsYXNzZXMgPSBjbGFzc05hbWUgKyAnICcgKyBDTEFTU19VTlNFTEVDVEFCTEUgKyAnICcgKyBDTEFTU19DT05UUk9MO1xuICAgIHZhciBlbGVtZW50ID0gX3RoaXMuZWxlbWVudDtcbiAgICBlbGVtZW50LmNsYXNzTmFtZSA9IGNzc0NsYXNzZXM7XG4gICAgZWxlbWVudC5hcHBlbmRDaGlsZChidXR0b24pO1xuICAgIF90aGlzLmNhbGxSZXNldE5vcnRoXyA9IG9wdGlvbnMucmVzZXROb3J0aCA/IG9wdGlvbnMucmVzZXROb3J0aCA6IHVuZGVmaW5lZDtcbiAgICAvKipcbiAgICAgKiBAdHlwZSB7bnVtYmVyfVxuICAgICAqIEBwcml2YXRlXG4gICAgICovXG5cbiAgICBfdGhpcy5kdXJhdGlvbl8gPSBvcHRpb25zLmR1cmF0aW9uICE9PSB1bmRlZmluZWQgPyBvcHRpb25zLmR1cmF0aW9uIDogMjUwO1xuICAgIC8qKlxuICAgICAqIEB0eXBlIHtib29sZWFufVxuICAgICAqIEBwcml2YXRlXG4gICAgICovXG5cbiAgICBfdGhpcy5hdXRvSGlkZV8gPSBvcHRpb25zLmF1dG9IaWRlICE9PSB1bmRlZmluZWQgPyBvcHRpb25zLmF1dG9IaWRlIDogdHJ1ZTtcbiAgICAvKipcbiAgICAgKiBAcHJpdmF0ZVxuICAgICAqIEB0eXBlIHtudW1iZXJ8dW5kZWZpbmVkfVxuICAgICAqL1xuXG4gICAgX3RoaXMucm90YXRpb25fID0gdW5kZWZpbmVkO1xuXG4gICAgaWYgKF90aGlzLmF1dG9IaWRlXykge1xuICAgICAgX3RoaXMuZWxlbWVudC5jbGFzc0xpc3QuYWRkKENMQVNTX0hJRERFTik7XG4gICAgfVxuXG4gICAgcmV0dXJuIF90aGlzO1xuICB9XG4gIC8qKlxuICAgKiBAcGFyYW0ge01vdXNlRXZlbnR9IGV2ZW50IFRoZSBldmVudCB0byBoYW5kbGVcbiAgICogQHByaXZhdGVcbiAgICovXG5cblxuICBSb3RhdGUucHJvdG90eXBlLmhhbmRsZUNsaWNrXyA9IGZ1bmN0aW9uIChldmVudCkge1xuICAgIGV2ZW50LnByZXZlbnREZWZhdWx0KCk7XG5cbiAgICBpZiAodGhpcy5jYWxsUmVzZXROb3J0aF8gIT09IHVuZGVmaW5lZCkge1xuICAgICAgdGhpcy5jYWxsUmVzZXROb3J0aF8oKTtcbiAgICB9IGVsc2Uge1xuICAgICAgdGhpcy5yZXNldE5vcnRoXygpO1xuICAgIH1cbiAgfTtcbiAgLyoqXG4gICAqIEBwcml2YXRlXG4gICAqL1xuXG5cbiAgUm90YXRlLnByb3RvdHlwZS5yZXNldE5vcnRoXyA9IGZ1bmN0aW9uICgpIHtcbiAgICB2YXIgbWFwID0gdGhpcy5nZXRNYXAoKTtcbiAgICB2YXIgdmlldyA9IG1hcC5nZXRWaWV3KCk7XG5cbiAgICBpZiAoIXZpZXcpIHtcbiAgICAgIC8vIHRoZSBtYXAgZG9lcyBub3QgaGF2ZSBhIHZpZXcsIHNvIHdlIGNhbid0IGFjdFxuICAgICAgLy8gdXBvbiBpdFxuICAgICAgcmV0dXJuO1xuICAgIH1cblxuICAgIHZhciByb3RhdGlvbiA9IHZpZXcuZ2V0Um90YXRpb24oKTtcblxuICAgIGlmIChyb3RhdGlvbiAhPT0gdW5kZWZpbmVkKSB7XG4gICAgICBpZiAodGhpcy5kdXJhdGlvbl8gPiAwICYmIHJvdGF0aW9uICUgKDIgKiBNYXRoLlBJKSAhPT0gMCkge1xuICAgICAgICB2aWV3LmFuaW1hdGUoe1xuICAgICAgICAgIHJvdGF0aW9uOiAwLFxuICAgICAgICAgIGR1cmF0aW9uOiB0aGlzLmR1cmF0aW9uXyxcbiAgICAgICAgICBlYXNpbmc6IGVhc2VPdXRcbiAgICAgICAgfSk7XG4gICAgICB9IGVsc2Uge1xuICAgICAgICB2aWV3LnNldFJvdGF0aW9uKDApO1xuICAgICAgfVxuICAgIH1cbiAgfTtcbiAgLyoqXG4gICAqIFVwZGF0ZSB0aGUgcm90YXRlIGNvbnRyb2wgZWxlbWVudC5cbiAgICogQHBhcmFtIHtpbXBvcnQoXCIuLi9NYXBFdmVudC5qc1wiKS5kZWZhdWx0fSBtYXBFdmVudCBNYXAgZXZlbnQuXG4gICAqIEBvdmVycmlkZVxuICAgKi9cblxuXG4gIFJvdGF0ZS5wcm90b3R5cGUucmVuZGVyID0gZnVuY3Rpb24gKG1hcEV2ZW50KSB7XG4gICAgdmFyIGZyYW1lU3RhdGUgPSBtYXBFdmVudC5mcmFtZVN0YXRlO1xuXG4gICAgaWYgKCFmcmFtZVN0YXRlKSB7XG4gICAgICByZXR1cm47XG4gICAgfVxuXG4gICAgdmFyIHJvdGF0aW9uID0gZnJhbWVTdGF0ZS52aWV3U3RhdGUucm90YXRpb247XG5cbiAgICBpZiAocm90YXRpb24gIT0gdGhpcy5yb3RhdGlvbl8pIHtcbiAgICAgIHZhciB0cmFuc2Zvcm0gPSAncm90YXRlKCcgKyByb3RhdGlvbiArICdyYWQpJztcblxuICAgICAgaWYgKHRoaXMuYXV0b0hpZGVfKSB7XG4gICAgICAgIHZhciBjb250YWlucyA9IHRoaXMuZWxlbWVudC5jbGFzc0xpc3QuY29udGFpbnMoQ0xBU1NfSElEREVOKTtcblxuICAgICAgICBpZiAoIWNvbnRhaW5zICYmIHJvdGF0aW9uID09PSAwKSB7XG4gICAgICAgICAgdGhpcy5lbGVtZW50LmNsYXNzTGlzdC5hZGQoQ0xBU1NfSElEREVOKTtcbiAgICAgICAgfSBlbHNlIGlmIChjb250YWlucyAmJiByb3RhdGlvbiAhPT0gMCkge1xuICAgICAgICAgIHRoaXMuZWxlbWVudC5jbGFzc0xpc3QucmVtb3ZlKENMQVNTX0hJRERFTik7XG4gICAgICAgIH1cbiAgICAgIH1cblxuICAgICAgdGhpcy5sYWJlbF8uc3R5bGUudHJhbnNmb3JtID0gdHJhbnNmb3JtO1xuICAgIH1cblxuICAgIHRoaXMucm90YXRpb25fID0gcm90YXRpb247XG4gIH07XG5cbiAgcmV0dXJuIFJvdGF0ZTtcbn0oQ29udHJvbCk7XG5cbmV4cG9ydCBkZWZhdWx0IFJvdGF0ZTsiLCJ2YXIgX19leHRlbmRzID0gdGhpcyAmJiB0aGlzLl9fZXh0ZW5kcyB8fCBmdW5jdGlvbiAoKSB7XG4gIHZhciBfZXh0ZW5kU3RhdGljcyA9IGZ1bmN0aW9uIGV4dGVuZFN0YXRpY3MoZCwgYikge1xuICAgIF9leHRlbmRTdGF0aWNzID0gT2JqZWN0LnNldFByb3RvdHlwZU9mIHx8IHtcbiAgICAgIF9fcHJvdG9fXzogW11cbiAgICB9IGluc3RhbmNlb2YgQXJyYXkgJiYgZnVuY3Rpb24gKGQsIGIpIHtcbiAgICAgIGQuX19wcm90b19fID0gYjtcbiAgICB9IHx8IGZ1bmN0aW9uIChkLCBiKSB7XG4gICAgICBmb3IgKHZhciBwIGluIGIpIHtcbiAgICAgICAgaWYgKE9iamVjdC5wcm90b3R5cGUuaGFzT3duUHJvcGVydHkuY2FsbChiLCBwKSkgZFtwXSA9IGJbcF07XG4gICAgICB9XG4gICAgfTtcblxuICAgIHJldHVybiBfZXh0ZW5kU3RhdGljcyhkLCBiKTtcbiAgfTtcblxuICByZXR1cm4gZnVuY3Rpb24gKGQsIGIpIHtcbiAgICBfZXh0ZW5kU3RhdGljcyhkLCBiKTtcblxuICAgIGZ1bmN0aW9uIF9fKCkge1xuICAgICAgdGhpcy5jb25zdHJ1Y3RvciA9IGQ7XG4gICAgfVxuXG4gICAgZC5wcm90b3R5cGUgPSBiID09PSBudWxsID8gT2JqZWN0LmNyZWF0ZShiKSA6IChfXy5wcm90b3R5cGUgPSBiLnByb3RvdHlwZSwgbmV3IF9fKCkpO1xuICB9O1xufSgpO1xuLyoqXG4gKiBAbW9kdWxlIG9sL2NvbnRyb2wvWm9vbVxuICovXG5cblxuaW1wb3J0IENvbnRyb2wgZnJvbSAnLi9Db250cm9sLmpzJztcbmltcG9ydCBFdmVudFR5cGUgZnJvbSAnLi4vZXZlbnRzL0V2ZW50VHlwZS5qcyc7XG5pbXBvcnQgeyBDTEFTU19DT05UUk9MLCBDTEFTU19VTlNFTEVDVEFCTEUgfSBmcm9tICcuLi9jc3MuanMnO1xuaW1wb3J0IHsgZWFzZU91dCB9IGZyb20gJy4uL2Vhc2luZy5qcyc7XG4vKipcbiAqIEB0eXBlZGVmIHtPYmplY3R9IE9wdGlvbnNcbiAqIEBwcm9wZXJ0eSB7bnVtYmVyfSBbZHVyYXRpb249MjUwXSBBbmltYXRpb24gZHVyYXRpb24gaW4gbWlsbGlzZWNvbmRzLlxuICogQHByb3BlcnR5IHtzdHJpbmd9IFtjbGFzc05hbWU9J29sLXpvb20nXSBDU1MgY2xhc3MgbmFtZS5cbiAqIEBwcm9wZXJ0eSB7c3RyaW5nfSBbem9vbUluQ2xhc3NOYW1lPWNsYXNzTmFtZSArICctaW4nXSBDU1MgY2xhc3MgbmFtZSBmb3IgdGhlIHpvb20taW4gYnV0dG9uLlxuICogQHByb3BlcnR5IHtzdHJpbmd9IFt6b29tT3V0Q2xhc3NOYW1lPWNsYXNzTmFtZSArICctb3V0J10gQ1NTIGNsYXNzIG5hbWUgZm9yIHRoZSB6b29tLW91dCBidXR0b24uXG4gKiBAcHJvcGVydHkge3N0cmluZ3xIVE1MRWxlbWVudH0gW3pvb21JbkxhYmVsPScrJ10gVGV4dCBsYWJlbCB0byB1c2UgZm9yIHRoZSB6b29tLWluXG4gKiBidXR0b24uIEluc3RlYWQgb2YgdGV4dCwgYWxzbyBhbiBlbGVtZW50IChlLmcuIGEgYHNwYW5gIGVsZW1lbnQpIGNhbiBiZSB1c2VkLlxuICogQHByb3BlcnR5IHtzdHJpbmd8SFRNTEVsZW1lbnR9IFt6b29tT3V0TGFiZWw9Jy0nXSBUZXh0IGxhYmVsIHRvIHVzZSBmb3IgdGhlIHpvb20tb3V0IGJ1dHRvbi5cbiAqIEluc3RlYWQgb2YgdGV4dCwgYWxzbyBhbiBlbGVtZW50IChlLmcuIGEgYHNwYW5gIGVsZW1lbnQpIGNhbiBiZSB1c2VkLlxuICogQHByb3BlcnR5IHtzdHJpbmd9IFt6b29tSW5UaXBMYWJlbD0nWm9vbSBpbiddIFRleHQgbGFiZWwgdG8gdXNlIGZvciB0aGUgYnV0dG9uIHRpcC5cbiAqIEBwcm9wZXJ0eSB7c3RyaW5nfSBbem9vbU91dFRpcExhYmVsPSdab29tIG91dCddIFRleHQgbGFiZWwgdG8gdXNlIGZvciB0aGUgYnV0dG9uIHRpcC5cbiAqIEBwcm9wZXJ0eSB7bnVtYmVyfSBbZGVsdGE9MV0gVGhlIHpvb20gZGVsdGEgYXBwbGllZCBvbiBlYWNoIGNsaWNrLlxuICogQHByb3BlcnR5IHtIVE1MRWxlbWVudHxzdHJpbmd9IFt0YXJnZXRdIFNwZWNpZnkgYSB0YXJnZXQgaWYgeW91IHdhbnQgdGhlIGNvbnRyb2wgdG8gYmVcbiAqIHJlbmRlcmVkIG91dHNpZGUgb2YgdGhlIG1hcCdzIHZpZXdwb3J0LlxuICovXG5cbi8qKlxuICogQGNsYXNzZGVzY1xuICogQSBjb250cm9sIHdpdGggMiBidXR0b25zLCBvbmUgZm9yIHpvb20gaW4gYW5kIG9uZSBmb3Igem9vbSBvdXQuXG4gKiBUaGlzIGNvbnRyb2wgaXMgb25lIG9mIHRoZSBkZWZhdWx0IGNvbnRyb2xzIG9mIGEgbWFwLiBUbyBzdHlsZSB0aGlzIGNvbnRyb2xcbiAqIHVzZSBjc3Mgc2VsZWN0b3JzIGAub2wtem9vbS1pbmAgYW5kIGAub2wtem9vbS1vdXRgLlxuICpcbiAqIEBhcGlcbiAqL1xuXG52YXIgWm9vbSA9XG4vKiogQGNsYXNzICovXG5mdW5jdGlvbiAoX3N1cGVyKSB7XG4gIF9fZXh0ZW5kcyhab29tLCBfc3VwZXIpO1xuICAvKipcbiAgICogQHBhcmFtIHtPcHRpb25zPX0gb3B0X29wdGlvbnMgWm9vbSBvcHRpb25zLlxuICAgKi9cblxuXG4gIGZ1bmN0aW9uIFpvb20ob3B0X29wdGlvbnMpIHtcbiAgICB2YXIgX3RoaXMgPSB0aGlzO1xuXG4gICAgdmFyIG9wdGlvbnMgPSBvcHRfb3B0aW9ucyA/IG9wdF9vcHRpb25zIDoge307XG4gICAgX3RoaXMgPSBfc3VwZXIuY2FsbCh0aGlzLCB7XG4gICAgICBlbGVtZW50OiBkb2N1bWVudC5jcmVhdGVFbGVtZW50KCdkaXYnKSxcbiAgICAgIHRhcmdldDogb3B0aW9ucy50YXJnZXRcbiAgICB9KSB8fCB0aGlzO1xuICAgIHZhciBjbGFzc05hbWUgPSBvcHRpb25zLmNsYXNzTmFtZSAhPT0gdW5kZWZpbmVkID8gb3B0aW9ucy5jbGFzc05hbWUgOiAnb2wtem9vbSc7XG4gICAgdmFyIGRlbHRhID0gb3B0aW9ucy5kZWx0YSAhPT0gdW5kZWZpbmVkID8gb3B0aW9ucy5kZWx0YSA6IDE7XG4gICAgdmFyIHpvb21JbkNsYXNzTmFtZSA9IG9wdGlvbnMuem9vbUluQ2xhc3NOYW1lICE9PSB1bmRlZmluZWQgPyBvcHRpb25zLnpvb21JbkNsYXNzTmFtZSA6IGNsYXNzTmFtZSArICctaW4nO1xuICAgIHZhciB6b29tT3V0Q2xhc3NOYW1lID0gb3B0aW9ucy56b29tT3V0Q2xhc3NOYW1lICE9PSB1bmRlZmluZWQgPyBvcHRpb25zLnpvb21PdXRDbGFzc05hbWUgOiBjbGFzc05hbWUgKyAnLW91dCc7XG4gICAgdmFyIHpvb21JbkxhYmVsID0gb3B0aW9ucy56b29tSW5MYWJlbCAhPT0gdW5kZWZpbmVkID8gb3B0aW9ucy56b29tSW5MYWJlbCA6ICcrJztcbiAgICB2YXIgem9vbU91dExhYmVsID0gb3B0aW9ucy56b29tT3V0TGFiZWwgIT09IHVuZGVmaW5lZCA/IG9wdGlvbnMuem9vbU91dExhYmVsIDogXCJcXHUyMjEyXCI7XG4gICAgdmFyIHpvb21JblRpcExhYmVsID0gb3B0aW9ucy56b29tSW5UaXBMYWJlbCAhPT0gdW5kZWZpbmVkID8gb3B0aW9ucy56b29tSW5UaXBMYWJlbCA6ICdab29tIGluJztcbiAgICB2YXIgem9vbU91dFRpcExhYmVsID0gb3B0aW9ucy56b29tT3V0VGlwTGFiZWwgIT09IHVuZGVmaW5lZCA/IG9wdGlvbnMuem9vbU91dFRpcExhYmVsIDogJ1pvb20gb3V0JztcbiAgICB2YXIgaW5FbGVtZW50ID0gZG9jdW1lbnQuY3JlYXRlRWxlbWVudCgnYnV0dG9uJyk7XG4gICAgaW5FbGVtZW50LmNsYXNzTmFtZSA9IHpvb21JbkNsYXNzTmFtZTtcbiAgICBpbkVsZW1lbnQuc2V0QXR0cmlidXRlKCd0eXBlJywgJ2J1dHRvbicpO1xuICAgIGluRWxlbWVudC50aXRsZSA9IHpvb21JblRpcExhYmVsO1xuICAgIGluRWxlbWVudC5hcHBlbmRDaGlsZCh0eXBlb2Ygem9vbUluTGFiZWwgPT09ICdzdHJpbmcnID8gZG9jdW1lbnQuY3JlYXRlVGV4dE5vZGUoem9vbUluTGFiZWwpIDogem9vbUluTGFiZWwpO1xuICAgIGluRWxlbWVudC5hZGRFdmVudExpc3RlbmVyKEV2ZW50VHlwZS5DTElDSywgX3RoaXMuaGFuZGxlQ2xpY2tfLmJpbmQoX3RoaXMsIGRlbHRhKSwgZmFsc2UpO1xuICAgIHZhciBvdXRFbGVtZW50ID0gZG9jdW1lbnQuY3JlYXRlRWxlbWVudCgnYnV0dG9uJyk7XG4gICAgb3V0RWxlbWVudC5jbGFzc05hbWUgPSB6b29tT3V0Q2xhc3NOYW1lO1xuICAgIG91dEVsZW1lbnQuc2V0QXR0cmlidXRlKCd0eXBlJywgJ2J1dHRvbicpO1xuICAgIG91dEVsZW1lbnQudGl0bGUgPSB6b29tT3V0VGlwTGFiZWw7XG4gICAgb3V0RWxlbWVudC5hcHBlbmRDaGlsZCh0eXBlb2Ygem9vbU91dExhYmVsID09PSAnc3RyaW5nJyA/IGRvY3VtZW50LmNyZWF0ZVRleHROb2RlKHpvb21PdXRMYWJlbCkgOiB6b29tT3V0TGFiZWwpO1xuICAgIG91dEVsZW1lbnQuYWRkRXZlbnRMaXN0ZW5lcihFdmVudFR5cGUuQ0xJQ0ssIF90aGlzLmhhbmRsZUNsaWNrXy5iaW5kKF90aGlzLCAtZGVsdGEpLCBmYWxzZSk7XG4gICAgdmFyIGNzc0NsYXNzZXMgPSBjbGFzc05hbWUgKyAnICcgKyBDTEFTU19VTlNFTEVDVEFCTEUgKyAnICcgKyBDTEFTU19DT05UUk9MO1xuICAgIHZhciBlbGVtZW50ID0gX3RoaXMuZWxlbWVudDtcbiAgICBlbGVtZW50LmNsYXNzTmFtZSA9IGNzc0NsYXNzZXM7XG4gICAgZWxlbWVudC5hcHBlbmRDaGlsZChpbkVsZW1lbnQpO1xuICAgIGVsZW1lbnQuYXBwZW5kQ2hpbGQob3V0RWxlbWVudCk7XG4gICAgLyoqXG4gICAgICogQHR5cGUge251bWJlcn1cbiAgICAgKiBAcHJpdmF0ZVxuICAgICAqL1xuXG4gICAgX3RoaXMuZHVyYXRpb25fID0gb3B0aW9ucy5kdXJhdGlvbiAhPT0gdW5kZWZpbmVkID8gb3B0aW9ucy5kdXJhdGlvbiA6IDI1MDtcbiAgICByZXR1cm4gX3RoaXM7XG4gIH1cbiAgLyoqXG4gICAqIEBwYXJhbSB7bnVtYmVyfSBkZWx0YSBab29tIGRlbHRhLlxuICAgKiBAcGFyYW0ge01vdXNlRXZlbnR9IGV2ZW50IFRoZSBldmVudCB0byBoYW5kbGVcbiAgICogQHByaXZhdGVcbiAgICovXG5cblxuICBab29tLnByb3RvdHlwZS5oYW5kbGVDbGlja18gPSBmdW5jdGlvbiAoZGVsdGEsIGV2ZW50KSB7XG4gICAgZXZlbnQucHJldmVudERlZmF1bHQoKTtcbiAgICB0aGlzLnpvb21CeURlbHRhXyhkZWx0YSk7XG4gIH07XG4gIC8qKlxuICAgKiBAcGFyYW0ge251bWJlcn0gZGVsdGEgWm9vbSBkZWx0YS5cbiAgICogQHByaXZhdGVcbiAgICovXG5cblxuICBab29tLnByb3RvdHlwZS56b29tQnlEZWx0YV8gPSBmdW5jdGlvbiAoZGVsdGEpIHtcbiAgICB2YXIgbWFwID0gdGhpcy5nZXRNYXAoKTtcbiAgICB2YXIgdmlldyA9IG1hcC5nZXRWaWV3KCk7XG5cbiAgICBpZiAoIXZpZXcpIHtcbiAgICAgIC8vIHRoZSBtYXAgZG9lcyBub3QgaGF2ZSBhIHZpZXcsIHNvIHdlIGNhbid0IGFjdFxuICAgICAgLy8gdXBvbiBpdFxuICAgICAgcmV0dXJuO1xuICAgIH1cblxuICAgIHZhciBjdXJyZW50Wm9vbSA9IHZpZXcuZ2V0Wm9vbSgpO1xuXG4gICAgaWYgKGN1cnJlbnRab29tICE9PSB1bmRlZmluZWQpIHtcbiAgICAgIHZhciBuZXdab29tID0gdmlldy5nZXRDb25zdHJhaW5lZFpvb20oY3VycmVudFpvb20gKyBkZWx0YSk7XG5cbiAgICAgIGlmICh0aGlzLmR1cmF0aW9uXyA+IDApIHtcbiAgICAgICAgaWYgKHZpZXcuZ2V0QW5pbWF0aW5nKCkpIHtcbiAgICAgICAgICB2aWV3LmNhbmNlbEFuaW1hdGlvbnMoKTtcbiAgICAgICAgfVxuXG4gICAgICAgIHZpZXcuYW5pbWF0ZSh7XG4gICAgICAgICAgem9vbTogbmV3Wm9vbSxcbiAgICAgICAgICBkdXJhdGlvbjogdGhpcy5kdXJhdGlvbl8sXG4gICAgICAgICAgZWFzaW5nOiBlYXNlT3V0XG4gICAgICAgIH0pO1xuICAgICAgfSBlbHNlIHtcbiAgICAgICAgdmlldy5zZXRab29tKG5ld1pvb20pO1xuICAgICAgfVxuICAgIH1cbiAgfTtcblxuICByZXR1cm4gWm9vbTtcbn0oQ29udHJvbCk7XG5cbmV4cG9ydCBkZWZhdWx0IFpvb207IiwiLyoqXG4gKiBAbW9kdWxlIG9sL2NvbnRyb2xcbiAqL1xuaW1wb3J0IEF0dHJpYnV0aW9uIGZyb20gJy4vY29udHJvbC9BdHRyaWJ1dGlvbi5qcyc7XG5pbXBvcnQgQ29sbGVjdGlvbiBmcm9tICcuL0NvbGxlY3Rpb24uanMnO1xuaW1wb3J0IFJvdGF0ZSBmcm9tICcuL2NvbnRyb2wvUm90YXRlLmpzJztcbmltcG9ydCBab29tIGZyb20gJy4vY29udHJvbC9ab29tLmpzJztcbmV4cG9ydCB7IGRlZmF1bHQgYXMgQXR0cmlidXRpb24gfSBmcm9tICcuL2NvbnRyb2wvQXR0cmlidXRpb24uanMnO1xuZXhwb3J0IHsgZGVmYXVsdCBhcyBDb250cm9sIH0gZnJvbSAnLi9jb250cm9sL0NvbnRyb2wuanMnO1xuZXhwb3J0IHsgZGVmYXVsdCBhcyBGdWxsU2NyZWVuIH0gZnJvbSAnLi9jb250cm9sL0Z1bGxTY3JlZW4uanMnO1xuZXhwb3J0IHsgZGVmYXVsdCBhcyBNb3VzZVBvc2l0aW9uIH0gZnJvbSAnLi9jb250cm9sL01vdXNlUG9zaXRpb24uanMnO1xuZXhwb3J0IHsgZGVmYXVsdCBhcyBPdmVydmlld01hcCB9IGZyb20gJy4vY29udHJvbC9PdmVydmlld01hcC5qcyc7XG5leHBvcnQgeyBkZWZhdWx0IGFzIFJvdGF0ZSB9IGZyb20gJy4vY29udHJvbC9Sb3RhdGUuanMnO1xuZXhwb3J0IHsgZGVmYXVsdCBhcyBTY2FsZUxpbmUgfSBmcm9tICcuL2NvbnRyb2wvU2NhbGVMaW5lLmpzJztcbmV4cG9ydCB7IGRlZmF1bHQgYXMgWm9vbSB9IGZyb20gJy4vY29udHJvbC9ab29tLmpzJztcbmV4cG9ydCB7IGRlZmF1bHQgYXMgWm9vbVNsaWRlciB9IGZyb20gJy4vY29udHJvbC9ab29tU2xpZGVyLmpzJztcbmV4cG9ydCB7IGRlZmF1bHQgYXMgWm9vbVRvRXh0ZW50IH0gZnJvbSAnLi9jb250cm9sL1pvb21Ub0V4dGVudC5qcyc7XG4vKipcbiAqIEB0eXBlZGVmIHtPYmplY3R9IERlZmF1bHRzT3B0aW9uc1xuICogQHByb3BlcnR5IHtib29sZWFufSBbYXR0cmlidXRpb249dHJ1ZV0gSW5jbHVkZVxuICoge0BsaW5rIG1vZHVsZTpvbC9jb250cm9sL0F0dHJpYnV0aW9ufkF0dHJpYnV0aW9ufS5cbiAqIEBwcm9wZXJ0eSB7aW1wb3J0KFwiLi9jb250cm9sL0F0dHJpYnV0aW9uLmpzXCIpLk9wdGlvbnN9IFthdHRyaWJ1dGlvbk9wdGlvbnNdXG4gKiBPcHRpb25zIGZvciB7QGxpbmsgbW9kdWxlOm9sL2NvbnRyb2wvQXR0cmlidXRpb25+QXR0cmlidXRpb259LlxuICogQHByb3BlcnR5IHtib29sZWFufSBbcm90YXRlPXRydWVdIEluY2x1ZGVcbiAqIHtAbGluayBtb2R1bGU6b2wvY29udHJvbC9Sb3RhdGV+Um90YXRlfS5cbiAqIEBwcm9wZXJ0eSB7aW1wb3J0KFwiLi9jb250cm9sL1JvdGF0ZS5qc1wiKS5PcHRpb25zfSBbcm90YXRlT3B0aW9uc10gT3B0aW9uc1xuICogZm9yIHtAbGluayBtb2R1bGU6b2wvY29udHJvbC9Sb3RhdGV+Um90YXRlfS5cbiAqIEBwcm9wZXJ0eSB7Ym9vbGVhbn0gW3pvb21dIEluY2x1ZGUge0BsaW5rIG1vZHVsZTpvbC9jb250cm9sL1pvb21+Wm9vbX0uXG4gKiBAcHJvcGVydHkge2ltcG9ydChcIi4vY29udHJvbC9ab29tLmpzXCIpLk9wdGlvbnN9IFt6b29tT3B0aW9uc10gT3B0aW9ucyBmb3JcbiAqIHtAbGluayBtb2R1bGU6b2wvY29udHJvbC9ab29tflpvb219LlxuICogQGFwaVxuICovXG5cbi8qKlxuICogU2V0IG9mIGNvbnRyb2xzIGluY2x1ZGVkIGluIG1hcHMgYnkgZGVmYXVsdC4gVW5sZXNzIGNvbmZpZ3VyZWQgb3RoZXJ3aXNlLFxuICogdGhpcyByZXR1cm5zIGEgY29sbGVjdGlvbiBjb250YWluaW5nIGFuIGluc3RhbmNlIG9mIGVhY2ggb2YgdGhlIGZvbGxvd2luZ1xuICogY29udHJvbHM6XG4gKiAqIHtAbGluayBtb2R1bGU6b2wvY29udHJvbC9ab29tflpvb219XG4gKiAqIHtAbGluayBtb2R1bGU6b2wvY29udHJvbC9Sb3RhdGV+Um90YXRlfVxuICogKiB7QGxpbmsgbW9kdWxlOm9sL2NvbnRyb2wvQXR0cmlidXRpb25+QXR0cmlidXRpb259XG4gKlxuICogQHBhcmFtIHtEZWZhdWx0c09wdGlvbnM9fSBvcHRfb3B0aW9uc1xuICogRGVmYXVsdHMgb3B0aW9ucy5cbiAqIEByZXR1cm4ge0NvbGxlY3Rpb248aW1wb3J0KFwiLi9jb250cm9sL0NvbnRyb2wuanNcIikuZGVmYXVsdD59XG4gKiBDb250cm9scy5cbiAqIEBhcGlcbiAqL1xuXG5leHBvcnQgZnVuY3Rpb24gZGVmYXVsdHMob3B0X29wdGlvbnMpIHtcbiAgdmFyIG9wdGlvbnMgPSBvcHRfb3B0aW9ucyA/IG9wdF9vcHRpb25zIDoge307XG4gIHZhciBjb250cm9scyA9IG5ldyBDb2xsZWN0aW9uKCk7XG4gIHZhciB6b29tQ29udHJvbCA9IG9wdGlvbnMuem9vbSAhPT0gdW5kZWZpbmVkID8gb3B0aW9ucy56b29tIDogdHJ1ZTtcblxuICBpZiAoem9vbUNvbnRyb2wpIHtcbiAgICBjb250cm9scy5wdXNoKG5ldyBab29tKG9wdGlvbnMuem9vbU9wdGlvbnMpKTtcbiAgfVxuXG4gIHZhciByb3RhdGVDb250cm9sID0gb3B0aW9ucy5yb3RhdGUgIT09IHVuZGVmaW5lZCA/IG9wdGlvbnMucm90YXRlIDogdHJ1ZTtcblxuICBpZiAocm90YXRlQ29udHJvbCkge1xuICAgIGNvbnRyb2xzLnB1c2gobmV3IFJvdGF0ZShvcHRpb25zLnJvdGF0ZU9wdGlvbnMpKTtcbiAgfVxuXG4gIHZhciBhdHRyaWJ1dGlvbkNvbnRyb2wgPSBvcHRpb25zLmF0dHJpYnV0aW9uICE9PSB1bmRlZmluZWQgPyBvcHRpb25zLmF0dHJpYnV0aW9uIDogdHJ1ZTtcblxuICBpZiAoYXR0cmlidXRpb25Db250cm9sKSB7XG4gICAgY29udHJvbHMucHVzaChuZXcgQXR0cmlidXRpb24ob3B0aW9ucy5hdHRyaWJ1dGlvbk9wdGlvbnMpKTtcbiAgfVxuXG4gIHJldHVybiBjb250cm9scztcbn0iLCIvKipcbiAqIEBtb2R1bGUgb2wvaW50ZXJhY3Rpb24vUHJvcGVydHlcbiAqL1xuXG4vKipcbiAqIEBlbnVtIHtzdHJpbmd9XG4gKi9cbmV4cG9ydCBkZWZhdWx0IHtcbiAgQUNUSVZFOiAnYWN0aXZlJ1xufTsiLCJ2YXIgX19leHRlbmRzID0gdGhpcyAmJiB0aGlzLl9fZXh0ZW5kcyB8fCBmdW5jdGlvbiAoKSB7XG4gIHZhciBfZXh0ZW5kU3RhdGljcyA9IGZ1bmN0aW9uIGV4dGVuZFN0YXRpY3MoZCwgYikge1xuICAgIF9leHRlbmRTdGF0aWNzID0gT2JqZWN0LnNldFByb3RvdHlwZU9mIHx8IHtcbiAgICAgIF9fcHJvdG9fXzogW11cbiAgICB9IGluc3RhbmNlb2YgQXJyYXkgJiYgZnVuY3Rpb24gKGQsIGIpIHtcbiAgICAgIGQuX19wcm90b19fID0gYjtcbiAgICB9IHx8IGZ1bmN0aW9uIChkLCBiKSB7XG4gICAgICBmb3IgKHZhciBwIGluIGIpIHtcbiAgICAgICAgaWYgKE9iamVjdC5wcm90b3R5cGUuaGFzT3duUHJvcGVydHkuY2FsbChiLCBwKSkgZFtwXSA9IGJbcF07XG4gICAgICB9XG4gICAgfTtcblxuICAgIHJldHVybiBfZXh0ZW5kU3RhdGljcyhkLCBiKTtcbiAgfTtcblxuICByZXR1cm4gZnVuY3Rpb24gKGQsIGIpIHtcbiAgICBfZXh0ZW5kU3RhdGljcyhkLCBiKTtcblxuICAgIGZ1bmN0aW9uIF9fKCkge1xuICAgICAgdGhpcy5jb25zdHJ1Y3RvciA9IGQ7XG4gICAgfVxuXG4gICAgZC5wcm90b3R5cGUgPSBiID09PSBudWxsID8gT2JqZWN0LmNyZWF0ZShiKSA6IChfXy5wcm90b3R5cGUgPSBiLnByb3RvdHlwZSwgbmV3IF9fKCkpO1xuICB9O1xufSgpO1xuLyoqXG4gKiBAbW9kdWxlIG9sL2ludGVyYWN0aW9uL0ludGVyYWN0aW9uXG4gKi9cblxuXG5pbXBvcnQgQmFzZU9iamVjdCBmcm9tICcuLi9PYmplY3QuanMnO1xuaW1wb3J0IEludGVyYWN0aW9uUHJvcGVydHkgZnJvbSAnLi9Qcm9wZXJ0eS5qcyc7XG5pbXBvcnQgeyBlYXNlT3V0LCBsaW5lYXIgfSBmcm9tICcuLi9lYXNpbmcuanMnO1xuLyoqXG4gKiBPYmplY3QgbGl0ZXJhbCB3aXRoIGNvbmZpZyBvcHRpb25zIGZvciBpbnRlcmFjdGlvbnMuXG4gKiBAdHlwZWRlZiB7T2JqZWN0fSBJbnRlcmFjdGlvbk9wdGlvbnNcbiAqIEBwcm9wZXJ0eSB7ZnVuY3Rpb24oaW1wb3J0KFwiLi4vTWFwQnJvd3NlckV2ZW50LmpzXCIpLmRlZmF1bHQpOmJvb2xlYW59IGhhbmRsZUV2ZW50XG4gKiBNZXRob2QgY2FsbGVkIGJ5IHRoZSBtYXAgdG8gbm90aWZ5IHRoZSBpbnRlcmFjdGlvbiB0aGF0IGEgYnJvd3NlciBldmVudCB3YXNcbiAqIGRpc3BhdGNoZWQgdG8gdGhlIG1hcC4gSWYgdGhlIGZ1bmN0aW9uIHJldHVybnMgYSBmYWxzeSB2YWx1ZSwgcHJvcGFnYXRpb24gb2ZcbiAqIHRoZSBldmVudCB0byBvdGhlciBpbnRlcmFjdGlvbnMgaW4gdGhlIG1hcCdzIGludGVyYWN0aW9ucyBjaGFpbiB3aWxsIGJlXG4gKiBwcmV2ZW50ZWQgKHRoaXMgaW5jbHVkZXMgZnVuY3Rpb25zIHdpdGggbm8gZXhwbGljaXQgcmV0dXJuKS4gVGhlIGludGVyYWN0aW9uc1xuICogYXJlIHRyYXZlcnNlZCBpbiByZXZlcnNlIG9yZGVyIG9mIHRoZSBpbnRlcmFjdGlvbnMgY29sbGVjdGlvbiBvZiB0aGUgbWFwLlxuICovXG5cbi8qKlxuICogQGNsYXNzZGVzY1xuICogQWJzdHJhY3QgYmFzZSBjbGFzczsgbm9ybWFsbHkgb25seSB1c2VkIGZvciBjcmVhdGluZyBzdWJjbGFzc2VzIGFuZCBub3RcbiAqIGluc3RhbnRpYXRlZCBpbiBhcHBzLlxuICogVXNlciBhY3Rpb25zIHRoYXQgY2hhbmdlIHRoZSBzdGF0ZSBvZiB0aGUgbWFwLiBTb21lIGFyZSBzaW1pbGFyIHRvIGNvbnRyb2xzLFxuICogYnV0IGFyZSBub3QgYXNzb2NpYXRlZCB3aXRoIGEgRE9NIGVsZW1lbnQuXG4gKiBGb3IgZXhhbXBsZSwge0BsaW5rIG1vZHVsZTpvbC9pbnRlcmFjdGlvbi9LZXlib2FyZFpvb21+S2V5Ym9hcmRab29tfSBpc1xuICogZnVuY3Rpb25hbGx5IHRoZSBzYW1lIGFzIHtAbGluayBtb2R1bGU6b2wvY29udHJvbC9ab29tflpvb219LCBidXQgdHJpZ2dlcmVkXG4gKiBieSBhIGtleWJvYXJkIGV2ZW50IG5vdCBhIGJ1dHRvbiBlbGVtZW50IGV2ZW50LlxuICogQWx0aG91Z2ggaW50ZXJhY3Rpb25zIGRvIG5vdCBoYXZlIGEgRE9NIGVsZW1lbnQsIHNvbWUgb2YgdGhlbSBkbyByZW5kZXJcbiAqIHZlY3RvcnMgYW5kIHNvIGFyZSB2aXNpYmxlIG9uIHRoZSBzY3JlZW4uXG4gKiBAYXBpXG4gKi9cblxudmFyIEludGVyYWN0aW9uID1cbi8qKiBAY2xhc3MgKi9cbmZ1bmN0aW9uIChfc3VwZXIpIHtcbiAgX19leHRlbmRzKEludGVyYWN0aW9uLCBfc3VwZXIpO1xuICAvKipcbiAgICogQHBhcmFtIHtJbnRlcmFjdGlvbk9wdGlvbnM9fSBvcHRfb3B0aW9ucyBPcHRpb25zLlxuICAgKi9cblxuXG4gIGZ1bmN0aW9uIEludGVyYWN0aW9uKG9wdF9vcHRpb25zKSB7XG4gICAgdmFyIF90aGlzID0gX3N1cGVyLmNhbGwodGhpcykgfHwgdGhpcztcblxuICAgIGlmIChvcHRfb3B0aW9ucyAmJiBvcHRfb3B0aW9ucy5oYW5kbGVFdmVudCkge1xuICAgICAgX3RoaXMuaGFuZGxlRXZlbnQgPSBvcHRfb3B0aW9ucy5oYW5kbGVFdmVudDtcbiAgICB9XG4gICAgLyoqXG4gICAgICogQHByaXZhdGVcbiAgICAgKiBAdHlwZSB7aW1wb3J0KFwiLi4vUGx1Z2dhYmxlTWFwLmpzXCIpLmRlZmF1bHR9XG4gICAgICovXG5cblxuICAgIF90aGlzLm1hcF8gPSBudWxsO1xuXG4gICAgX3RoaXMuc2V0QWN0aXZlKHRydWUpO1xuXG4gICAgcmV0dXJuIF90aGlzO1xuICB9XG4gIC8qKlxuICAgKiBSZXR1cm4gd2hldGhlciB0aGUgaW50ZXJhY3Rpb24gaXMgY3VycmVudGx5IGFjdGl2ZS5cbiAgICogQHJldHVybiB7Ym9vbGVhbn0gYHRydWVgIGlmIHRoZSBpbnRlcmFjdGlvbiBpcyBhY3RpdmUsIGBmYWxzZWAgb3RoZXJ3aXNlLlxuICAgKiBAb2JzZXJ2YWJsZVxuICAgKiBAYXBpXG4gICAqL1xuXG5cbiAgSW50ZXJhY3Rpb24ucHJvdG90eXBlLmdldEFjdGl2ZSA9IGZ1bmN0aW9uICgpIHtcbiAgICByZXR1cm4gKFxuICAgICAgLyoqIEB0eXBlIHtib29sZWFufSAqL1xuICAgICAgdGhpcy5nZXQoSW50ZXJhY3Rpb25Qcm9wZXJ0eS5BQ1RJVkUpXG4gICAgKTtcbiAgfTtcbiAgLyoqXG4gICAqIEdldCB0aGUgbWFwIGFzc29jaWF0ZWQgd2l0aCB0aGlzIGludGVyYWN0aW9uLlxuICAgKiBAcmV0dXJuIHtpbXBvcnQoXCIuLi9QbHVnZ2FibGVNYXAuanNcIikuZGVmYXVsdH0gTWFwLlxuICAgKiBAYXBpXG4gICAqL1xuXG5cbiAgSW50ZXJhY3Rpb24ucHJvdG90eXBlLmdldE1hcCA9IGZ1bmN0aW9uICgpIHtcbiAgICByZXR1cm4gdGhpcy5tYXBfO1xuICB9O1xuICAvKipcbiAgICogSGFuZGxlcyB0aGUge0BsaW5rIG1vZHVsZTpvbC9NYXBCcm93c2VyRXZlbnQgbWFwIGJyb3dzZXIgZXZlbnR9LlxuICAgKiBAcGFyYW0ge2ltcG9ydChcIi4uL01hcEJyb3dzZXJFdmVudC5qc1wiKS5kZWZhdWx0fSBtYXBCcm93c2VyRXZlbnQgTWFwIGJyb3dzZXIgZXZlbnQuXG4gICAqIEByZXR1cm4ge2Jvb2xlYW59IGBmYWxzZWAgdG8gc3RvcCBldmVudCBwcm9wYWdhdGlvbi5cbiAgICogQGFwaVxuICAgKi9cblxuXG4gIEludGVyYWN0aW9uLnByb3RvdHlwZS5oYW5kbGVFdmVudCA9IGZ1bmN0aW9uIChtYXBCcm93c2VyRXZlbnQpIHtcbiAgICByZXR1cm4gdHJ1ZTtcbiAgfTtcbiAgLyoqXG4gICAqIEFjdGl2YXRlIG9yIGRlYWN0aXZhdGUgdGhlIGludGVyYWN0aW9uLlxuICAgKiBAcGFyYW0ge2Jvb2xlYW59IGFjdGl2ZSBBY3RpdmUuXG4gICAqIEBvYnNlcnZhYmxlXG4gICAqIEBhcGlcbiAgICovXG5cblxuICBJbnRlcmFjdGlvbi5wcm90b3R5cGUuc2V0QWN0aXZlID0gZnVuY3Rpb24gKGFjdGl2ZSkge1xuICAgIHRoaXMuc2V0KEludGVyYWN0aW9uUHJvcGVydHkuQUNUSVZFLCBhY3RpdmUpO1xuICB9O1xuICAvKipcbiAgICogUmVtb3ZlIHRoZSBpbnRlcmFjdGlvbiBmcm9tIGl0cyBjdXJyZW50IG1hcCBhbmQgYXR0YWNoIGl0IHRvIHRoZSBuZXcgbWFwLlxuICAgKiBTdWJjbGFzc2VzIG1heSBzZXQgdXAgZXZlbnQgaGFuZGxlcnMgdG8gZ2V0IG5vdGlmaWVkIGFib3V0IGNoYW5nZXMgdG9cbiAgICogdGhlIG1hcCBoZXJlLlxuICAgKiBAcGFyYW0ge2ltcG9ydChcIi4uL1BsdWdnYWJsZU1hcC5qc1wiKS5kZWZhdWx0fSBtYXAgTWFwLlxuICAgKi9cblxuXG4gIEludGVyYWN0aW9uLnByb3RvdHlwZS5zZXRNYXAgPSBmdW5jdGlvbiAobWFwKSB7XG4gICAgdGhpcy5tYXBfID0gbWFwO1xuICB9O1xuXG4gIHJldHVybiBJbnRlcmFjdGlvbjtcbn0oQmFzZU9iamVjdCk7XG4vKipcbiAqIEBwYXJhbSB7aW1wb3J0KFwiLi4vVmlldy5qc1wiKS5kZWZhdWx0fSB2aWV3IFZpZXcuXG4gKiBAcGFyYW0ge2ltcG9ydChcIi4uL2Nvb3JkaW5hdGUuanNcIikuQ29vcmRpbmF0ZX0gZGVsdGEgRGVsdGEuXG4gKiBAcGFyYW0ge251bWJlcj19IG9wdF9kdXJhdGlvbiBEdXJhdGlvbi5cbiAqL1xuXG5cbmV4cG9ydCBmdW5jdGlvbiBwYW4odmlldywgZGVsdGEsIG9wdF9kdXJhdGlvbikge1xuICB2YXIgY3VycmVudENlbnRlciA9IHZpZXcuZ2V0Q2VudGVySW50ZXJuYWwoKTtcblxuICBpZiAoY3VycmVudENlbnRlcikge1xuICAgIHZhciBjZW50ZXIgPSBbY3VycmVudENlbnRlclswXSArIGRlbHRhWzBdLCBjdXJyZW50Q2VudGVyWzFdICsgZGVsdGFbMV1dO1xuICAgIHZpZXcuYW5pbWF0ZUludGVybmFsKHtcbiAgICAgIGR1cmF0aW9uOiBvcHRfZHVyYXRpb24gIT09IHVuZGVmaW5lZCA/IG9wdF9kdXJhdGlvbiA6IDI1MCxcbiAgICAgIGVhc2luZzogbGluZWFyLFxuICAgICAgY2VudGVyOiB2aWV3LmdldENvbnN0cmFpbmVkQ2VudGVyKGNlbnRlcilcbiAgICB9KTtcbiAgfVxufVxuLyoqXG4gKiBAcGFyYW0ge2ltcG9ydChcIi4uL1ZpZXcuanNcIikuZGVmYXVsdH0gdmlldyBWaWV3LlxuICogQHBhcmFtIHtudW1iZXJ9IGRlbHRhIERlbHRhIGZyb20gcHJldmlvdXMgem9vbSBsZXZlbC5cbiAqIEBwYXJhbSB7aW1wb3J0KFwiLi4vY29vcmRpbmF0ZS5qc1wiKS5Db29yZGluYXRlPX0gb3B0X2FuY2hvciBBbmNob3IgY29vcmRpbmF0ZSBpbiB0aGUgdXNlciBwcm9qZWN0aW9uLlxuICogQHBhcmFtIHtudW1iZXI9fSBvcHRfZHVyYXRpb24gRHVyYXRpb24uXG4gKi9cblxuZXhwb3J0IGZ1bmN0aW9uIHpvb21CeURlbHRhKHZpZXcsIGRlbHRhLCBvcHRfYW5jaG9yLCBvcHRfZHVyYXRpb24pIHtcbiAgdmFyIGN1cnJlbnRab29tID0gdmlldy5nZXRab29tKCk7XG5cbiAgaWYgKGN1cnJlbnRab29tID09PSB1bmRlZmluZWQpIHtcbiAgICByZXR1cm47XG4gIH1cblxuICB2YXIgbmV3Wm9vbSA9IHZpZXcuZ2V0Q29uc3RyYWluZWRab29tKGN1cnJlbnRab29tICsgZGVsdGEpO1xuICB2YXIgbmV3UmVzb2x1dGlvbiA9IHZpZXcuZ2V0UmVzb2x1dGlvbkZvclpvb20obmV3Wm9vbSk7XG5cbiAgaWYgKHZpZXcuZ2V0QW5pbWF0aW5nKCkpIHtcbiAgICB2aWV3LmNhbmNlbEFuaW1hdGlvbnMoKTtcbiAgfVxuXG4gIHZpZXcuYW5pbWF0ZSh7XG4gICAgcmVzb2x1dGlvbjogbmV3UmVzb2x1dGlvbixcbiAgICBhbmNob3I6IG9wdF9hbmNob3IsXG4gICAgZHVyYXRpb246IG9wdF9kdXJhdGlvbiAhPT0gdW5kZWZpbmVkID8gb3B0X2R1cmF0aW9uIDogMjUwLFxuICAgIGVhc2luZzogZWFzZU91dFxuICB9KTtcbn1cbmV4cG9ydCBkZWZhdWx0IEludGVyYWN0aW9uOyIsInZhciBfX2V4dGVuZHMgPSB0aGlzICYmIHRoaXMuX19leHRlbmRzIHx8IGZ1bmN0aW9uICgpIHtcbiAgdmFyIF9leHRlbmRTdGF0aWNzID0gZnVuY3Rpb24gZXh0ZW5kU3RhdGljcyhkLCBiKSB7XG4gICAgX2V4dGVuZFN0YXRpY3MgPSBPYmplY3Quc2V0UHJvdG90eXBlT2YgfHwge1xuICAgICAgX19wcm90b19fOiBbXVxuICAgIH0gaW5zdGFuY2VvZiBBcnJheSAmJiBmdW5jdGlvbiAoZCwgYikge1xuICAgICAgZC5fX3Byb3RvX18gPSBiO1xuICAgIH0gfHwgZnVuY3Rpb24gKGQsIGIpIHtcbiAgICAgIGZvciAodmFyIHAgaW4gYikge1xuICAgICAgICBpZiAoT2JqZWN0LnByb3RvdHlwZS5oYXNPd25Qcm9wZXJ0eS5jYWxsKGIsIHApKSBkW3BdID0gYltwXTtcbiAgICAgIH1cbiAgICB9O1xuXG4gICAgcmV0dXJuIF9leHRlbmRTdGF0aWNzKGQsIGIpO1xuICB9O1xuXG4gIHJldHVybiBmdW5jdGlvbiAoZCwgYikge1xuICAgIF9leHRlbmRTdGF0aWNzKGQsIGIpO1xuXG4gICAgZnVuY3Rpb24gX18oKSB7XG4gICAgICB0aGlzLmNvbnN0cnVjdG9yID0gZDtcbiAgICB9XG5cbiAgICBkLnByb3RvdHlwZSA9IGIgPT09IG51bGwgPyBPYmplY3QuY3JlYXRlKGIpIDogKF9fLnByb3RvdHlwZSA9IGIucHJvdG90eXBlLCBuZXcgX18oKSk7XG4gIH07XG59KCk7XG4vKipcbiAqIEBtb2R1bGUgb2wvaW50ZXJhY3Rpb24vRG91YmxlQ2xpY2tab29tXG4gKi9cblxuXG5pbXBvcnQgSW50ZXJhY3Rpb24sIHsgem9vbUJ5RGVsdGEgfSBmcm9tICcuL0ludGVyYWN0aW9uLmpzJztcbmltcG9ydCBNYXBCcm93c2VyRXZlbnRUeXBlIGZyb20gJy4uL01hcEJyb3dzZXJFdmVudFR5cGUuanMnO1xuLyoqXG4gKiBAdHlwZWRlZiB7T2JqZWN0fSBPcHRpb25zXG4gKiBAcHJvcGVydHkge251bWJlcn0gW2R1cmF0aW9uPTI1MF0gQW5pbWF0aW9uIGR1cmF0aW9uIGluIG1pbGxpc2Vjb25kcy5cbiAqIEBwcm9wZXJ0eSB7bnVtYmVyfSBbZGVsdGE9MV0gVGhlIHpvb20gZGVsdGEgYXBwbGllZCBvbiBlYWNoIGRvdWJsZSBjbGljay5cbiAqL1xuXG4vKipcbiAqIEBjbGFzc2Rlc2NcbiAqIEFsbG93cyB0aGUgdXNlciB0byB6b29tIGJ5IGRvdWJsZS1jbGlja2luZyBvbiB0aGUgbWFwLlxuICogQGFwaVxuICovXG5cbnZhciBEb3VibGVDbGlja1pvb20gPVxuLyoqIEBjbGFzcyAqL1xuZnVuY3Rpb24gKF9zdXBlcikge1xuICBfX2V4dGVuZHMoRG91YmxlQ2xpY2tab29tLCBfc3VwZXIpO1xuICAvKipcbiAgICogQHBhcmFtIHtPcHRpb25zPX0gb3B0X29wdGlvbnMgT3B0aW9ucy5cbiAgICovXG5cblxuICBmdW5jdGlvbiBEb3VibGVDbGlja1pvb20ob3B0X29wdGlvbnMpIHtcbiAgICB2YXIgX3RoaXMgPSBfc3VwZXIuY2FsbCh0aGlzKSB8fCB0aGlzO1xuXG4gICAgdmFyIG9wdGlvbnMgPSBvcHRfb3B0aW9ucyA/IG9wdF9vcHRpb25zIDoge307XG4gICAgLyoqXG4gICAgICogQHByaXZhdGVcbiAgICAgKiBAdHlwZSB7bnVtYmVyfVxuICAgICAqL1xuXG4gICAgX3RoaXMuZGVsdGFfID0gb3B0aW9ucy5kZWx0YSA/IG9wdGlvbnMuZGVsdGEgOiAxO1xuICAgIC8qKlxuICAgICAqIEBwcml2YXRlXG4gICAgICogQHR5cGUge251bWJlcn1cbiAgICAgKi9cblxuICAgIF90aGlzLmR1cmF0aW9uXyA9IG9wdGlvbnMuZHVyYXRpb24gIT09IHVuZGVmaW5lZCA/IG9wdGlvbnMuZHVyYXRpb24gOiAyNTA7XG4gICAgcmV0dXJuIF90aGlzO1xuICB9XG4gIC8qKlxuICAgKiBIYW5kbGVzIHRoZSB7QGxpbmsgbW9kdWxlOm9sL01hcEJyb3dzZXJFdmVudCBtYXAgYnJvd3NlciBldmVudH0gKGlmIGl0IHdhcyBhXG4gICAqIGRvdWJsZWNsaWNrKSBhbmQgZXZlbnR1YWxseSB6b29tcyB0aGUgbWFwLlxuICAgKiBAcGFyYW0ge2ltcG9ydChcIi4uL01hcEJyb3dzZXJFdmVudC5qc1wiKS5kZWZhdWx0fSBtYXBCcm93c2VyRXZlbnQgTWFwIGJyb3dzZXIgZXZlbnQuXG4gICAqIEByZXR1cm4ge2Jvb2xlYW59IGBmYWxzZWAgdG8gc3RvcCBldmVudCBwcm9wYWdhdGlvbi5cbiAgICovXG5cblxuICBEb3VibGVDbGlja1pvb20ucHJvdG90eXBlLmhhbmRsZUV2ZW50ID0gZnVuY3Rpb24gKG1hcEJyb3dzZXJFdmVudCkge1xuICAgIHZhciBzdG9wRXZlbnQgPSBmYWxzZTtcblxuICAgIGlmIChtYXBCcm93c2VyRXZlbnQudHlwZSA9PSBNYXBCcm93c2VyRXZlbnRUeXBlLkRCTENMSUNLKSB7XG4gICAgICB2YXIgYnJvd3NlckV2ZW50ID1cbiAgICAgIC8qKiBAdHlwZSB7TW91c2VFdmVudH0gKi9cbiAgICAgIG1hcEJyb3dzZXJFdmVudC5vcmlnaW5hbEV2ZW50O1xuICAgICAgdmFyIG1hcCA9IG1hcEJyb3dzZXJFdmVudC5tYXA7XG4gICAgICB2YXIgYW5jaG9yID0gbWFwQnJvd3NlckV2ZW50LmNvb3JkaW5hdGU7XG4gICAgICB2YXIgZGVsdGEgPSBicm93c2VyRXZlbnQuc2hpZnRLZXkgPyAtdGhpcy5kZWx0YV8gOiB0aGlzLmRlbHRhXztcbiAgICAgIHZhciB2aWV3ID0gbWFwLmdldFZpZXcoKTtcbiAgICAgIHpvb21CeURlbHRhKHZpZXcsIGRlbHRhLCBhbmNob3IsIHRoaXMuZHVyYXRpb25fKTtcbiAgICAgIGJyb3dzZXJFdmVudC5wcmV2ZW50RGVmYXVsdCgpO1xuICAgICAgc3RvcEV2ZW50ID0gdHJ1ZTtcbiAgICB9XG5cbiAgICByZXR1cm4gIXN0b3BFdmVudDtcbiAgfTtcblxuICByZXR1cm4gRG91YmxlQ2xpY2tab29tO1xufShJbnRlcmFjdGlvbik7XG5cbmV4cG9ydCBkZWZhdWx0IERvdWJsZUNsaWNrWm9vbTsiLCJ2YXIgX19leHRlbmRzID0gdGhpcyAmJiB0aGlzLl9fZXh0ZW5kcyB8fCBmdW5jdGlvbiAoKSB7XG4gIHZhciBfZXh0ZW5kU3RhdGljcyA9IGZ1bmN0aW9uIGV4dGVuZFN0YXRpY3MoZCwgYikge1xuICAgIF9leHRlbmRTdGF0aWNzID0gT2JqZWN0LnNldFByb3RvdHlwZU9mIHx8IHtcbiAgICAgIF9fcHJvdG9fXzogW11cbiAgICB9IGluc3RhbmNlb2YgQXJyYXkgJiYgZnVuY3Rpb24gKGQsIGIpIHtcbiAgICAgIGQuX19wcm90b19fID0gYjtcbiAgICB9IHx8IGZ1bmN0aW9uIChkLCBiKSB7XG4gICAgICBmb3IgKHZhciBwIGluIGIpIHtcbiAgICAgICAgaWYgKE9iamVjdC5wcm90b3R5cGUuaGFzT3duUHJvcGVydHkuY2FsbChiLCBwKSkgZFtwXSA9IGJbcF07XG4gICAgICB9XG4gICAgfTtcblxuICAgIHJldHVybiBfZXh0ZW5kU3RhdGljcyhkLCBiKTtcbiAgfTtcblxuICByZXR1cm4gZnVuY3Rpb24gKGQsIGIpIHtcbiAgICBfZXh0ZW5kU3RhdGljcyhkLCBiKTtcblxuICAgIGZ1bmN0aW9uIF9fKCkge1xuICAgICAgdGhpcy5jb25zdHJ1Y3RvciA9IGQ7XG4gICAgfVxuXG4gICAgZC5wcm90b3R5cGUgPSBiID09PSBudWxsID8gT2JqZWN0LmNyZWF0ZShiKSA6IChfXy5wcm90b3R5cGUgPSBiLnByb3RvdHlwZSwgbmV3IF9fKCkpO1xuICB9O1xufSgpO1xuLyoqXG4gKiBAbW9kdWxlIG9sL2ludGVyYWN0aW9uL1BvaW50ZXJcbiAqL1xuXG5cbmltcG9ydCBJbnRlcmFjdGlvbiBmcm9tICcuL0ludGVyYWN0aW9uLmpzJztcbmltcG9ydCBNYXBCcm93c2VyRXZlbnRUeXBlIGZyb20gJy4uL01hcEJyb3dzZXJFdmVudFR5cGUuanMnO1xuaW1wb3J0IHsgZ2V0VmFsdWVzIH0gZnJvbSAnLi4vb2JqLmpzJztcbi8qKlxuICogQHR5cGVkZWYge09iamVjdH0gT3B0aW9uc1xuICogQHByb3BlcnR5IHtmdW5jdGlvbihpbXBvcnQoXCIuLi9NYXBCcm93c2VyRXZlbnQuanNcIikuZGVmYXVsdCk6Ym9vbGVhbn0gW2hhbmRsZURvd25FdmVudF1cbiAqIEZ1bmN0aW9uIGhhbmRsaW5nIFwiZG93blwiIGV2ZW50cy4gSWYgdGhlIGZ1bmN0aW9uIHJldHVybnMgYHRydWVgIHRoZW4gYSBkcmFnXG4gKiBzZXF1ZW5jZSBpcyBzdGFydGVkLlxuICogQHByb3BlcnR5IHtmdW5jdGlvbihpbXBvcnQoXCIuLi9NYXBCcm93c2VyRXZlbnQuanNcIikuZGVmYXVsdCk6dm9pZH0gW2hhbmRsZURyYWdFdmVudF1cbiAqIEZ1bmN0aW9uIGhhbmRsaW5nIFwiZHJhZ1wiIGV2ZW50cy4gVGhpcyBmdW5jdGlvbiBpcyBjYWxsZWQgb24gXCJtb3ZlXCIgZXZlbnRzXG4gKiBkdXJpbmcgYSBkcmFnIHNlcXVlbmNlLlxuICogQHByb3BlcnR5IHtmdW5jdGlvbihpbXBvcnQoXCIuLi9NYXBCcm93c2VyRXZlbnQuanNcIikuZGVmYXVsdCk6Ym9vbGVhbn0gW2hhbmRsZUV2ZW50XVxuICogTWV0aG9kIGNhbGxlZCBieSB0aGUgbWFwIHRvIG5vdGlmeSB0aGUgaW50ZXJhY3Rpb24gdGhhdCBhIGJyb3dzZXIgZXZlbnQgd2FzXG4gKiBkaXNwYXRjaGVkIHRvIHRoZSBtYXAuIFRoZSBmdW5jdGlvbiBtYXkgcmV0dXJuIGBmYWxzZWAgdG8gcHJldmVudCB0aGVcbiAqIHByb3BhZ2F0aW9uIG9mIHRoZSBldmVudCB0byBvdGhlciBpbnRlcmFjdGlvbnMgaW4gdGhlIG1hcCdzIGludGVyYWN0aW9uc1xuICogY2hhaW4uXG4gKiBAcHJvcGVydHkge2Z1bmN0aW9uKGltcG9ydChcIi4uL01hcEJyb3dzZXJFdmVudC5qc1wiKS5kZWZhdWx0KTp2b2lkfSBbaGFuZGxlTW92ZUV2ZW50XVxuICogRnVuY3Rpb24gaGFuZGxpbmcgXCJtb3ZlXCIgZXZlbnRzLiBUaGlzIGZ1bmN0aW9uIGlzIGNhbGxlZCBvbiBcIm1vdmVcIiBldmVudHMuXG4gKiBUaGlzIGZ1bmN0aW9ucyBpcyBhbHNvIGNhbGxlZCBkdXJpbmcgYSBkcmFnIHNlcXVlbmNlLCBzbyBkdXJpbmcgYSBkcmFnXG4gKiBzZXF1ZW5jZSBib3RoIHRoZSBgaGFuZGxlRHJhZ0V2ZW50YCBmdW5jdGlvbiBhbmQgdGhpcyBmdW5jdGlvbiBhcmUgY2FsbGVkLlxuICogSWYgYGhhbmRsZURvd25FdmVudGAgaXMgZGVmaW5lZCBhbmQgaXQgcmV0dXJucyB0cnVlIHRoaXMgZnVuY3Rpb24gd2lsbCBub3RcbiAqIGJlIGNhbGxlZCBkdXJpbmcgYSBkcmFnIHNlcXVlbmNlLlxuICogQHByb3BlcnR5IHtmdW5jdGlvbihpbXBvcnQoXCIuLi9NYXBCcm93c2VyRXZlbnQuanNcIikuZGVmYXVsdCk6Ym9vbGVhbn0gW2hhbmRsZVVwRXZlbnRdXG4gKiAgRnVuY3Rpb24gaGFuZGxpbmcgXCJ1cFwiIGV2ZW50cy4gSWYgdGhlIGZ1bmN0aW9uIHJldHVybnMgYGZhbHNlYCB0aGVuIHRoZVxuICogY3VycmVudCBkcmFnIHNlcXVlbmNlIGlzIHN0b3BwZWQuXG4gKiBAcHJvcGVydHkge2Z1bmN0aW9uKGJvb2xlYW4pOmJvb2xlYW59IFtzdG9wRG93bl1cbiAqIFNob3VsZCB0aGUgZG93biBldmVudCBiZSBwcm9wYWdhdGVkIHRvIG90aGVyIGludGVyYWN0aW9ucywgb3Igc2hvdWxkIGJlXG4gKiBzdG9wcGVkP1xuICovXG5cbi8qKlxuICogQGNsYXNzZGVzY1xuICogQmFzZSBjbGFzcyB0aGF0IGNhbGxzIHVzZXItZGVmaW5lZCBmdW5jdGlvbnMgb24gYGRvd25gLCBgbW92ZWAgYW5kIGB1cGBcbiAqIGV2ZW50cy4gVGhpcyBjbGFzcyBhbHNvIG1hbmFnZXMgXCJkcmFnIHNlcXVlbmNlc1wiLlxuICpcbiAqIFdoZW4gdGhlIGBoYW5kbGVEb3duRXZlbnRgIHVzZXIgZnVuY3Rpb24gcmV0dXJucyBgdHJ1ZWAgYSBkcmFnIHNlcXVlbmNlIGlzXG4gKiBzdGFydGVkLiBEdXJpbmcgYSBkcmFnIHNlcXVlbmNlIHRoZSBgaGFuZGxlRHJhZ0V2ZW50YCB1c2VyIGZ1bmN0aW9uIGlzXG4gKiBjYWxsZWQgb24gYG1vdmVgIGV2ZW50cy4gVGhlIGRyYWcgc2VxdWVuY2UgZW5kcyB3aGVuIHRoZSBgaGFuZGxlVXBFdmVudGBcbiAqIHVzZXIgZnVuY3Rpb24gaXMgY2FsbGVkIGFuZCByZXR1cm5zIGBmYWxzZWAuXG4gKiBAYXBpXG4gKi9cblxudmFyIFBvaW50ZXJJbnRlcmFjdGlvbiA9XG4vKiogQGNsYXNzICovXG5mdW5jdGlvbiAoX3N1cGVyKSB7XG4gIF9fZXh0ZW5kcyhQb2ludGVySW50ZXJhY3Rpb24sIF9zdXBlcik7XG4gIC8qKlxuICAgKiBAcGFyYW0ge09wdGlvbnM9fSBvcHRfb3B0aW9ucyBPcHRpb25zLlxuICAgKi9cblxuXG4gIGZ1bmN0aW9uIFBvaW50ZXJJbnRlcmFjdGlvbihvcHRfb3B0aW9ucykge1xuICAgIHZhciBfdGhpcyA9IHRoaXM7XG5cbiAgICB2YXIgb3B0aW9ucyA9IG9wdF9vcHRpb25zID8gb3B0X29wdGlvbnMgOiB7fTtcbiAgICBfdGhpcyA9IF9zdXBlci5jYWxsKHRoaXMsXG4gICAgLyoqIEB0eXBlIHtpbXBvcnQoXCIuL0ludGVyYWN0aW9uLmpzXCIpLkludGVyYWN0aW9uT3B0aW9uc30gKi9cbiAgICBvcHRpb25zKSB8fCB0aGlzO1xuXG4gICAgaWYgKG9wdGlvbnMuaGFuZGxlRG93bkV2ZW50KSB7XG4gICAgICBfdGhpcy5oYW5kbGVEb3duRXZlbnQgPSBvcHRpb25zLmhhbmRsZURvd25FdmVudDtcbiAgICB9XG5cbiAgICBpZiAob3B0aW9ucy5oYW5kbGVEcmFnRXZlbnQpIHtcbiAgICAgIF90aGlzLmhhbmRsZURyYWdFdmVudCA9IG9wdGlvbnMuaGFuZGxlRHJhZ0V2ZW50O1xuICAgIH1cblxuICAgIGlmIChvcHRpb25zLmhhbmRsZU1vdmVFdmVudCkge1xuICAgICAgX3RoaXMuaGFuZGxlTW92ZUV2ZW50ID0gb3B0aW9ucy5oYW5kbGVNb3ZlRXZlbnQ7XG4gICAgfVxuXG4gICAgaWYgKG9wdGlvbnMuaGFuZGxlVXBFdmVudCkge1xuICAgICAgX3RoaXMuaGFuZGxlVXBFdmVudCA9IG9wdGlvbnMuaGFuZGxlVXBFdmVudDtcbiAgICB9XG5cbiAgICBpZiAob3B0aW9ucy5zdG9wRG93bikge1xuICAgICAgX3RoaXMuc3RvcERvd24gPSBvcHRpb25zLnN0b3BEb3duO1xuICAgIH1cbiAgICAvKipcbiAgICAgKiBAdHlwZSB7Ym9vbGVhbn1cbiAgICAgKiBAcHJvdGVjdGVkXG4gICAgICovXG5cblxuICAgIF90aGlzLmhhbmRsaW5nRG93blVwU2VxdWVuY2UgPSBmYWxzZTtcbiAgICAvKipcbiAgICAgKiBAdHlwZSB7IU9iamVjdDxzdHJpbmcsIFBvaW50ZXJFdmVudD59XG4gICAgICogQHByaXZhdGVcbiAgICAgKi9cblxuICAgIF90aGlzLnRyYWNrZWRQb2ludGVyc18gPSB7fTtcbiAgICAvKipcbiAgICAgKiBAdHlwZSB7QXJyYXk8UG9pbnRlckV2ZW50Pn1cbiAgICAgKiBAcHJvdGVjdGVkXG4gICAgICovXG5cbiAgICBfdGhpcy50YXJnZXRQb2ludGVycyA9IFtdO1xuICAgIHJldHVybiBfdGhpcztcbiAgfVxuICAvKipcbiAgICogUmV0dXJucyB0aGUgY3VycmVudCBudW1iZXIgb2YgcG9pbnRlcnMgaW52b2x2ZWQgaW4gdGhlIGludGVyYWN0aW9uLFxuICAgKiBlLmcuIGAyYCB3aGVuIHR3byBmaW5nZXJzIGFyZSB1c2VkLlxuICAgKiBAcmV0dXJuIHtudW1iZXJ9IFRoZSBudW1iZXIgb2YgcG9pbnRlcnMuXG4gICAqIEBhcGlcbiAgICovXG5cblxuICBQb2ludGVySW50ZXJhY3Rpb24ucHJvdG90eXBlLmdldFBvaW50ZXJDb3VudCA9IGZ1bmN0aW9uICgpIHtcbiAgICByZXR1cm4gdGhpcy50YXJnZXRQb2ludGVycy5sZW5ndGg7XG4gIH07XG4gIC8qKlxuICAgKiBIYW5kbGUgcG9pbnRlciBkb3duIGV2ZW50cy5cbiAgICogQHBhcmFtIHtpbXBvcnQoXCIuLi9NYXBCcm93c2VyRXZlbnQuanNcIikuZGVmYXVsdH0gbWFwQnJvd3NlckV2ZW50IEV2ZW50LlxuICAgKiBAcmV0dXJuIHtib29sZWFufSBJZiB0aGUgZXZlbnQgd2FzIGNvbnN1bWVkLlxuICAgKiBAcHJvdGVjdGVkXG4gICAqL1xuXG5cbiAgUG9pbnRlckludGVyYWN0aW9uLnByb3RvdHlwZS5oYW5kbGVEb3duRXZlbnQgPSBmdW5jdGlvbiAobWFwQnJvd3NlckV2ZW50KSB7XG4gICAgcmV0dXJuIGZhbHNlO1xuICB9O1xuICAvKipcbiAgICogSGFuZGxlIHBvaW50ZXIgZHJhZyBldmVudHMuXG4gICAqIEBwYXJhbSB7aW1wb3J0KFwiLi4vTWFwQnJvd3NlckV2ZW50LmpzXCIpLmRlZmF1bHR9IG1hcEJyb3dzZXJFdmVudCBFdmVudC5cbiAgICogQHByb3RlY3RlZFxuICAgKi9cblxuXG4gIFBvaW50ZXJJbnRlcmFjdGlvbi5wcm90b3R5cGUuaGFuZGxlRHJhZ0V2ZW50ID0gZnVuY3Rpb24gKG1hcEJyb3dzZXJFdmVudCkge307XG4gIC8qKlxuICAgKiBIYW5kbGVzIHRoZSB7QGxpbmsgbW9kdWxlOm9sL01hcEJyb3dzZXJFdmVudCBtYXAgYnJvd3NlciBldmVudH0gYW5kIG1heSBjYWxsIGludG9cbiAgICogb3RoZXIgZnVuY3Rpb25zLCBpZiBldmVudCBzZXF1ZW5jZXMgbGlrZSBlLmcuICdkcmFnJyBvciAnZG93bi11cCcgZXRjLiBhcmVcbiAgICogZGV0ZWN0ZWQuXG4gICAqIEBwYXJhbSB7aW1wb3J0KFwiLi4vTWFwQnJvd3NlckV2ZW50LmpzXCIpLmRlZmF1bHR9IG1hcEJyb3dzZXJFdmVudCBNYXAgYnJvd3NlciBldmVudC5cbiAgICogQHJldHVybiB7Ym9vbGVhbn0gYGZhbHNlYCB0byBzdG9wIGV2ZW50IHByb3BhZ2F0aW9uLlxuICAgKiBAYXBpXG4gICAqL1xuXG5cbiAgUG9pbnRlckludGVyYWN0aW9uLnByb3RvdHlwZS5oYW5kbGVFdmVudCA9IGZ1bmN0aW9uIChtYXBCcm93c2VyRXZlbnQpIHtcbiAgICBpZiAoIW1hcEJyb3dzZXJFdmVudC5vcmlnaW5hbEV2ZW50KSB7XG4gICAgICByZXR1cm4gdHJ1ZTtcbiAgICB9XG5cbiAgICB2YXIgc3RvcEV2ZW50ID0gZmFsc2U7XG4gICAgdGhpcy51cGRhdGVUcmFja2VkUG9pbnRlcnNfKG1hcEJyb3dzZXJFdmVudCk7XG5cbiAgICBpZiAodGhpcy5oYW5kbGluZ0Rvd25VcFNlcXVlbmNlKSB7XG4gICAgICBpZiAobWFwQnJvd3NlckV2ZW50LnR5cGUgPT0gTWFwQnJvd3NlckV2ZW50VHlwZS5QT0lOVEVSRFJBRykge1xuICAgICAgICB0aGlzLmhhbmRsZURyYWdFdmVudChtYXBCcm93c2VyRXZlbnQpOyAvLyBwcmV2ZW50IHBhZ2Ugc2Nyb2xsaW5nIGR1cmluZyBkcmFnZ2luZ1xuXG4gICAgICAgIG1hcEJyb3dzZXJFdmVudC5vcmlnaW5hbEV2ZW50LnByZXZlbnREZWZhdWx0KCk7XG4gICAgICB9IGVsc2UgaWYgKG1hcEJyb3dzZXJFdmVudC50eXBlID09IE1hcEJyb3dzZXJFdmVudFR5cGUuUE9JTlRFUlVQKSB7XG4gICAgICAgIHZhciBoYW5kbGVkVXAgPSB0aGlzLmhhbmRsZVVwRXZlbnQobWFwQnJvd3NlckV2ZW50KTtcbiAgICAgICAgdGhpcy5oYW5kbGluZ0Rvd25VcFNlcXVlbmNlID0gaGFuZGxlZFVwICYmIHRoaXMudGFyZ2V0UG9pbnRlcnMubGVuZ3RoID4gMDtcbiAgICAgIH1cbiAgICB9IGVsc2Uge1xuICAgICAgaWYgKG1hcEJyb3dzZXJFdmVudC50eXBlID09IE1hcEJyb3dzZXJFdmVudFR5cGUuUE9JTlRFUkRPV04pIHtcbiAgICAgICAgdmFyIGhhbmRsZWQgPSB0aGlzLmhhbmRsZURvd25FdmVudChtYXBCcm93c2VyRXZlbnQpO1xuICAgICAgICB0aGlzLmhhbmRsaW5nRG93blVwU2VxdWVuY2UgPSBoYW5kbGVkO1xuICAgICAgICBzdG9wRXZlbnQgPSB0aGlzLnN0b3BEb3duKGhhbmRsZWQpO1xuICAgICAgfSBlbHNlIGlmIChtYXBCcm93c2VyRXZlbnQudHlwZSA9PSBNYXBCcm93c2VyRXZlbnRUeXBlLlBPSU5URVJNT1ZFKSB7XG4gICAgICAgIHRoaXMuaGFuZGxlTW92ZUV2ZW50KG1hcEJyb3dzZXJFdmVudCk7XG4gICAgICB9XG4gICAgfVxuXG4gICAgcmV0dXJuICFzdG9wRXZlbnQ7XG4gIH07XG4gIC8qKlxuICAgKiBIYW5kbGUgcG9pbnRlciBtb3ZlIGV2ZW50cy5cbiAgICogQHBhcmFtIHtpbXBvcnQoXCIuLi9NYXBCcm93c2VyRXZlbnQuanNcIikuZGVmYXVsdH0gbWFwQnJvd3NlckV2ZW50IEV2ZW50LlxuICAgKiBAcHJvdGVjdGVkXG4gICAqL1xuXG5cbiAgUG9pbnRlckludGVyYWN0aW9uLnByb3RvdHlwZS5oYW5kbGVNb3ZlRXZlbnQgPSBmdW5jdGlvbiAobWFwQnJvd3NlckV2ZW50KSB7fTtcbiAgLyoqXG4gICAqIEhhbmRsZSBwb2ludGVyIHVwIGV2ZW50cy5cbiAgICogQHBhcmFtIHtpbXBvcnQoXCIuLi9NYXBCcm93c2VyRXZlbnQuanNcIikuZGVmYXVsdH0gbWFwQnJvd3NlckV2ZW50IEV2ZW50LlxuICAgKiBAcmV0dXJuIHtib29sZWFufSBJZiB0aGUgZXZlbnQgd2FzIGNvbnN1bWVkLlxuICAgKiBAcHJvdGVjdGVkXG4gICAqL1xuXG5cbiAgUG9pbnRlckludGVyYWN0aW9uLnByb3RvdHlwZS5oYW5kbGVVcEV2ZW50ID0gZnVuY3Rpb24gKG1hcEJyb3dzZXJFdmVudCkge1xuICAgIHJldHVybiBmYWxzZTtcbiAgfTtcbiAgLyoqXG4gICAqIFRoaXMgZnVuY3Rpb24gaXMgdXNlZCB0byBkZXRlcm1pbmUgaWYgXCJkb3duXCIgZXZlbnRzIHNob3VsZCBiZSBwcm9wYWdhdGVkXG4gICAqIHRvIG90aGVyIGludGVyYWN0aW9ucyBvciBzaG91bGQgYmUgc3RvcHBlZC5cbiAgICogQHBhcmFtIHtib29sZWFufSBoYW5kbGVkIFdhcyB0aGUgZXZlbnQgaGFuZGxlZCBieSB0aGUgaW50ZXJhY3Rpb24/XG4gICAqIEByZXR1cm4ge2Jvb2xlYW59IFNob3VsZCB0aGUgYGRvd25gIGV2ZW50IGJlIHN0b3BwZWQ/XG4gICAqL1xuXG5cbiAgUG9pbnRlckludGVyYWN0aW9uLnByb3RvdHlwZS5zdG9wRG93biA9IGZ1bmN0aW9uIChoYW5kbGVkKSB7XG4gICAgcmV0dXJuIGhhbmRsZWQ7XG4gIH07XG4gIC8qKlxuICAgKiBAcGFyYW0ge2ltcG9ydChcIi4uL01hcEJyb3dzZXJFdmVudC5qc1wiKS5kZWZhdWx0fSBtYXBCcm93c2VyRXZlbnQgRXZlbnQuXG4gICAqIEBwcml2YXRlXG4gICAqL1xuXG5cbiAgUG9pbnRlckludGVyYWN0aW9uLnByb3RvdHlwZS51cGRhdGVUcmFja2VkUG9pbnRlcnNfID0gZnVuY3Rpb24gKG1hcEJyb3dzZXJFdmVudCkge1xuICAgIGlmIChpc1BvaW50ZXJEcmFnZ2luZ0V2ZW50KG1hcEJyb3dzZXJFdmVudCkpIHtcbiAgICAgIHZhciBldmVudF8xID0gbWFwQnJvd3NlckV2ZW50Lm9yaWdpbmFsRXZlbnQ7XG4gICAgICB2YXIgaWQgPSBldmVudF8xLnBvaW50ZXJJZC50b1N0cmluZygpO1xuXG4gICAgICBpZiAobWFwQnJvd3NlckV2ZW50LnR5cGUgPT0gTWFwQnJvd3NlckV2ZW50VHlwZS5QT0lOVEVSVVApIHtcbiAgICAgICAgZGVsZXRlIHRoaXMudHJhY2tlZFBvaW50ZXJzX1tpZF07XG4gICAgICB9IGVsc2UgaWYgKG1hcEJyb3dzZXJFdmVudC50eXBlID09IE1hcEJyb3dzZXJFdmVudFR5cGUuUE9JTlRFUkRPV04pIHtcbiAgICAgICAgdGhpcy50cmFja2VkUG9pbnRlcnNfW2lkXSA9IGV2ZW50XzE7XG4gICAgICB9IGVsc2UgaWYgKGlkIGluIHRoaXMudHJhY2tlZFBvaW50ZXJzXykge1xuICAgICAgICAvLyB1cGRhdGUgb25seSB3aGVuIHRoZXJlIHdhcyBhIHBvaW50ZXJkb3duIGV2ZW50IGZvciB0aGlzIHBvaW50ZXJcbiAgICAgICAgdGhpcy50cmFja2VkUG9pbnRlcnNfW2lkXSA9IGV2ZW50XzE7XG4gICAgICB9XG5cbiAgICAgIHRoaXMudGFyZ2V0UG9pbnRlcnMgPSBnZXRWYWx1ZXModGhpcy50cmFja2VkUG9pbnRlcnNfKTtcbiAgICB9XG4gIH07XG5cbiAgcmV0dXJuIFBvaW50ZXJJbnRlcmFjdGlvbjtcbn0oSW50ZXJhY3Rpb24pO1xuLyoqXG4gKiBAcGFyYW0ge0FycmF5PFBvaW50ZXJFdmVudD59IHBvaW50ZXJFdmVudHMgTGlzdCBvZiBldmVudHMuXG4gKiBAcmV0dXJuIHtpbXBvcnQoXCIuLi9waXhlbC5qc1wiKS5QaXhlbH0gQ2VudHJvaWQgcGl4ZWwuXG4gKi9cblxuXG5leHBvcnQgZnVuY3Rpb24gY2VudHJvaWQocG9pbnRlckV2ZW50cykge1xuICB2YXIgbGVuZ3RoID0gcG9pbnRlckV2ZW50cy5sZW5ndGg7XG4gIHZhciBjbGllbnRYID0gMDtcbiAgdmFyIGNsaWVudFkgPSAwO1xuXG4gIGZvciAodmFyIGkgPSAwOyBpIDwgbGVuZ3RoOyBpKyspIHtcbiAgICBjbGllbnRYICs9IHBvaW50ZXJFdmVudHNbaV0uY2xpZW50WDtcbiAgICBjbGllbnRZICs9IHBvaW50ZXJFdmVudHNbaV0uY2xpZW50WTtcbiAgfVxuXG4gIHJldHVybiBbY2xpZW50WCAvIGxlbmd0aCwgY2xpZW50WSAvIGxlbmd0aF07XG59XG4vKipcbiAqIEBwYXJhbSB7aW1wb3J0KFwiLi4vTWFwQnJvd3NlckV2ZW50LmpzXCIpLmRlZmF1bHR9IG1hcEJyb3dzZXJFdmVudCBFdmVudC5cbiAqIEByZXR1cm4ge2Jvb2xlYW59IFdoZXRoZXIgdGhlIGV2ZW50IGlzIGEgcG9pbnRlcmRvd24sIHBvaW50ZXJkcmFnXG4gKiAgICAgb3IgcG9pbnRlcnVwIGV2ZW50LlxuICovXG5cbmZ1bmN0aW9uIGlzUG9pbnRlckRyYWdnaW5nRXZlbnQobWFwQnJvd3NlckV2ZW50KSB7XG4gIHZhciB0eXBlID0gbWFwQnJvd3NlckV2ZW50LnR5cGU7XG4gIHJldHVybiB0eXBlID09PSBNYXBCcm93c2VyRXZlbnRUeXBlLlBPSU5URVJET1dOIHx8IHR5cGUgPT09IE1hcEJyb3dzZXJFdmVudFR5cGUuUE9JTlRFUkRSQUcgfHwgdHlwZSA9PT0gTWFwQnJvd3NlckV2ZW50VHlwZS5QT0lOVEVSVVA7XG59XG5cbmV4cG9ydCBkZWZhdWx0IFBvaW50ZXJJbnRlcmFjdGlvbjsiLCIvKipcbiAqIEBtb2R1bGUgb2wvZXZlbnRzL2NvbmRpdGlvblxuICovXG5pbXBvcnQgTWFwQnJvd3NlckV2ZW50VHlwZSBmcm9tICcuLi9NYXBCcm93c2VyRXZlbnRUeXBlLmpzJztcbmltcG9ydCB7IEZBTFNFLCBUUlVFIH0gZnJvbSAnLi4vZnVuY3Rpb25zLmpzJztcbmltcG9ydCB7IE1BQywgV0VCS0lUIH0gZnJvbSAnLi4vaGFzLmpzJztcbmltcG9ydCB7IGFzc2VydCB9IGZyb20gJy4uL2Fzc2VydHMuanMnO1xuLyoqXG4gKiBBIGZ1bmN0aW9uIHRoYXQgdGFrZXMgYW4ge0BsaW5rIG1vZHVsZTpvbC9NYXBCcm93c2VyRXZlbnR9IGFuZCByZXR1cm5zIGFcbiAqIGB7Ym9vbGVhbn1gLiBJZiB0aGUgY29uZGl0aW9uIGlzIG1ldCwgdHJ1ZSBzaG91bGQgYmUgcmV0dXJuZWQuXG4gKlxuICogQHR5cGVkZWYge2Z1bmN0aW9uKHRoaXM6ID8sIGltcG9ydChcIi4uL01hcEJyb3dzZXJFdmVudC5qc1wiKS5kZWZhdWx0KTogYm9vbGVhbn0gQ29uZGl0aW9uXG4gKi9cblxuLyoqXG4gKiBDcmVhdGVzIGEgY29uZGl0aW9uIGZ1bmN0aW9uIHRoYXQgcGFzc2VzIHdoZW4gYWxsIHByb3ZpZGVkIGNvbmRpdGlvbnMgcGFzcy5cbiAqIEBwYXJhbSB7Li4uQ29uZGl0aW9ufSB2YXJfYXJncyBDb25kaXRpb25zIHRvIGNoZWNrLlxuICogQHJldHVybiB7Q29uZGl0aW9ufSBDb25kaXRpb24gZnVuY3Rpb24uXG4gKi9cblxuZXhwb3J0IGZ1bmN0aW9uIGFsbCh2YXJfYXJncykge1xuICB2YXIgY29uZGl0aW9ucyA9IGFyZ3VtZW50cztcbiAgLyoqXG4gICAqIEBwYXJhbSB7aW1wb3J0KFwiLi4vTWFwQnJvd3NlckV2ZW50LmpzXCIpLmRlZmF1bHR9IGV2ZW50IEV2ZW50LlxuICAgKiBAcmV0dXJuIHtib29sZWFufSBBbGwgY29uZGl0aW9ucyBwYXNzZWQuXG4gICAqL1xuXG4gIHJldHVybiBmdW5jdGlvbiAoZXZlbnQpIHtcbiAgICB2YXIgcGFzcyA9IHRydWU7XG5cbiAgICBmb3IgKHZhciBpID0gMCwgaWkgPSBjb25kaXRpb25zLmxlbmd0aDsgaSA8IGlpOyArK2kpIHtcbiAgICAgIHBhc3MgPSBwYXNzICYmIGNvbmRpdGlvbnNbaV0oZXZlbnQpO1xuXG4gICAgICBpZiAoIXBhc3MpIHtcbiAgICAgICAgYnJlYWs7XG4gICAgICB9XG4gICAgfVxuXG4gICAgcmV0dXJuIHBhc3M7XG4gIH07XG59XG4vKipcbiAqIFJldHVybiBgdHJ1ZWAgaWYgb25seSB0aGUgYWx0LWtleSBpcyBwcmVzc2VkLCBgZmFsc2VgIG90aGVyd2lzZSAoZS5nLiB3aGVuXG4gKiBhZGRpdGlvbmFsbHkgdGhlIHNoaWZ0LWtleSBpcyBwcmVzc2VkKS5cbiAqXG4gKiBAcGFyYW0ge2ltcG9ydChcIi4uL01hcEJyb3dzZXJFdmVudC5qc1wiKS5kZWZhdWx0fSBtYXBCcm93c2VyRXZlbnQgTWFwIGJyb3dzZXIgZXZlbnQuXG4gKiBAcmV0dXJuIHtib29sZWFufSBUcnVlIGlmIG9ubHkgdGhlIGFsdCBrZXkgaXMgcHJlc3NlZC5cbiAqIEBhcGlcbiAqL1xuXG5leHBvcnQgdmFyIGFsdEtleU9ubHkgPSBmdW5jdGlvbiBhbHRLZXlPbmx5KG1hcEJyb3dzZXJFdmVudCkge1xuICB2YXIgb3JpZ2luYWxFdmVudCA9XG4gIC8qKiBAdHlwZSB7S2V5Ym9hcmRFdmVudHxNb3VzZUV2ZW50fFRvdWNoRXZlbnR9ICovXG4gIG1hcEJyb3dzZXJFdmVudC5vcmlnaW5hbEV2ZW50O1xuICByZXR1cm4gb3JpZ2luYWxFdmVudC5hbHRLZXkgJiYgIShvcmlnaW5hbEV2ZW50Lm1ldGFLZXkgfHwgb3JpZ2luYWxFdmVudC5jdHJsS2V5KSAmJiAhb3JpZ2luYWxFdmVudC5zaGlmdEtleTtcbn07XG4vKipcbiAqIFJldHVybiBgdHJ1ZWAgaWYgb25seSB0aGUgYWx0LWtleSBhbmQgc2hpZnQta2V5IGlzIHByZXNzZWQsIGBmYWxzZWAgb3RoZXJ3aXNlXG4gKiAoZS5nLiB3aGVuIGFkZGl0aW9uYWxseSB0aGUgcGxhdGZvcm0tbW9kaWZpZXIta2V5IGlzIHByZXNzZWQpLlxuICpcbiAqIEBwYXJhbSB7aW1wb3J0KFwiLi4vTWFwQnJvd3NlckV2ZW50LmpzXCIpLmRlZmF1bHR9IG1hcEJyb3dzZXJFdmVudCBNYXAgYnJvd3NlciBldmVudC5cbiAqIEByZXR1cm4ge2Jvb2xlYW59IFRydWUgaWYgb25seSB0aGUgYWx0IGFuZCBzaGlmdCBrZXlzIGFyZSBwcmVzc2VkLlxuICogQGFwaVxuICovXG5cbmV4cG9ydCB2YXIgYWx0U2hpZnRLZXlzT25seSA9IGZ1bmN0aW9uIGFsdFNoaWZ0S2V5c09ubHkobWFwQnJvd3NlckV2ZW50KSB7XG4gIHZhciBvcmlnaW5hbEV2ZW50ID1cbiAgLyoqIEB0eXBlIHtLZXlib2FyZEV2ZW50fE1vdXNlRXZlbnR8VG91Y2hFdmVudH0gKi9cbiAgbWFwQnJvd3NlckV2ZW50Lm9yaWdpbmFsRXZlbnQ7XG4gIHJldHVybiBvcmlnaW5hbEV2ZW50LmFsdEtleSAmJiAhKG9yaWdpbmFsRXZlbnQubWV0YUtleSB8fCBvcmlnaW5hbEV2ZW50LmN0cmxLZXkpICYmIG9yaWdpbmFsRXZlbnQuc2hpZnRLZXk7XG59O1xuLyoqXG4gKiBSZXR1cm4gYHRydWVgIGlmIHRoZSBtYXAgaGFzIHRoZSBmb2N1cy4gVGhpcyBjb25kaXRpb24gcmVxdWlyZXMgYSBtYXAgdGFyZ2V0XG4gKiBlbGVtZW50IHdpdGggYSBgdGFiaW5kZXhgIGF0dHJpYnV0ZSwgZS5nLiBgPGRpdiBpZD1cIm1hcFwiIHRhYmluZGV4PVwiMVwiPmAuXG4gKlxuICogQHBhcmFtIHtpbXBvcnQoXCIuLi9NYXBCcm93c2VyRXZlbnQuanNcIikuZGVmYXVsdH0gZXZlbnQgTWFwIGJyb3dzZXIgZXZlbnQuXG4gKiBAcmV0dXJuIHtib29sZWFufSBUaGUgbWFwIGhhcyB0aGUgZm9jdXMuXG4gKiBAYXBpXG4gKi9cblxuZXhwb3J0IHZhciBmb2N1cyA9IGZ1bmN0aW9uIGZvY3VzKGV2ZW50KSB7XG4gIHJldHVybiBldmVudC50YXJnZXQuZ2V0VGFyZ2V0RWxlbWVudCgpLmNvbnRhaW5zKGRvY3VtZW50LmFjdGl2ZUVsZW1lbnQpO1xufTtcbi8qKlxuICogUmV0dXJuIGB0cnVlYCBpZiB0aGUgbWFwIGhhcyB0aGUgZm9jdXMgb3Igbm8gJ3RhYmluZGV4JyBhdHRyaWJ1dGUgc2V0LlxuICpcbiAqIEBwYXJhbSB7aW1wb3J0KFwiLi4vTWFwQnJvd3NlckV2ZW50LmpzXCIpLmRlZmF1bHR9IGV2ZW50IE1hcCBicm93c2VyIGV2ZW50LlxuICogQHJldHVybiB7Ym9vbGVhbn0gVGhlIG1hcCBjb250YWluZXIgaGFzIHRoZSBmb2N1cyBvciBubyAndGFiaW5kZXgnIGF0dHJpYnV0ZS5cbiAqL1xuXG5leHBvcnQgdmFyIGZvY3VzV2l0aFRhYmluZGV4ID0gZnVuY3Rpb24gZm9jdXNXaXRoVGFiaW5kZXgoZXZlbnQpIHtcbiAgcmV0dXJuIGV2ZW50Lm1hcC5nZXRUYXJnZXRFbGVtZW50KCkuaGFzQXR0cmlidXRlKCd0YWJpbmRleCcpID8gZm9jdXMoZXZlbnQpIDogdHJ1ZTtcbn07XG4vKipcbiAqIFJldHVybiBhbHdheXMgdHJ1ZS5cbiAqXG4gKiBAcGFyYW0ge2ltcG9ydChcIi4uL01hcEJyb3dzZXJFdmVudC5qc1wiKS5kZWZhdWx0fSBtYXBCcm93c2VyRXZlbnQgTWFwIGJyb3dzZXIgZXZlbnQuXG4gKiBAcmV0dXJuIHtib29sZWFufSBUcnVlLlxuICogQGFwaVxuICovXG5cbmV4cG9ydCB2YXIgYWx3YXlzID0gVFJVRTtcbi8qKlxuICogUmV0dXJuIGB0cnVlYCBpZiB0aGUgZXZlbnQgaXMgYSBgY2xpY2tgIGV2ZW50LCBgZmFsc2VgIG90aGVyd2lzZS5cbiAqXG4gKiBAcGFyYW0ge2ltcG9ydChcIi4uL01hcEJyb3dzZXJFdmVudC5qc1wiKS5kZWZhdWx0fSBtYXBCcm93c2VyRXZlbnQgTWFwIGJyb3dzZXIgZXZlbnQuXG4gKiBAcmV0dXJuIHtib29sZWFufSBUcnVlIGlmIHRoZSBldmVudCBpcyBhIG1hcCBgY2xpY2tgIGV2ZW50LlxuICogQGFwaVxuICovXG5cbmV4cG9ydCB2YXIgY2xpY2sgPSBmdW5jdGlvbiBjbGljayhtYXBCcm93c2VyRXZlbnQpIHtcbiAgcmV0dXJuIG1hcEJyb3dzZXJFdmVudC50eXBlID09IE1hcEJyb3dzZXJFdmVudFR5cGUuQ0xJQ0s7XG59O1xuLyoqXG4gKiBSZXR1cm4gYHRydWVgIGlmIHRoZSBldmVudCBoYXMgYW4gXCJhY3Rpb25cIi1wcm9kdWNpbmcgbW91c2UgYnV0dG9uLlxuICpcbiAqIEJ5IGRlZmluaXRpb24sIHRoaXMgaW5jbHVkZXMgbGVmdC1jbGljayBvbiB3aW5kb3dzL2xpbnV4LCBhbmQgbGVmdC1jbGlja1xuICogd2l0aG91dCB0aGUgY3RybCBrZXkgb24gTWFjcy5cbiAqXG4gKiBAcGFyYW0ge2ltcG9ydChcIi4uL01hcEJyb3dzZXJFdmVudC5qc1wiKS5kZWZhdWx0fSBtYXBCcm93c2VyRXZlbnQgTWFwIGJyb3dzZXIgZXZlbnQuXG4gKiBAcmV0dXJuIHtib29sZWFufSBUaGUgcmVzdWx0LlxuICovXG5cbmV4cG9ydCB2YXIgbW91c2VBY3Rpb25CdXR0b24gPSBmdW5jdGlvbiBtb3VzZUFjdGlvbkJ1dHRvbihtYXBCcm93c2VyRXZlbnQpIHtcbiAgdmFyIG9yaWdpbmFsRXZlbnQgPVxuICAvKiogQHR5cGUge01vdXNlRXZlbnR9ICovXG4gIG1hcEJyb3dzZXJFdmVudC5vcmlnaW5hbEV2ZW50O1xuICByZXR1cm4gb3JpZ2luYWxFdmVudC5idXR0b24gPT0gMCAmJiAhKFdFQktJVCAmJiBNQUMgJiYgb3JpZ2luYWxFdmVudC5jdHJsS2V5KTtcbn07XG4vKipcbiAqIFJldHVybiBhbHdheXMgZmFsc2UuXG4gKlxuICogQHBhcmFtIHtpbXBvcnQoXCIuLi9NYXBCcm93c2VyRXZlbnQuanNcIikuZGVmYXVsdH0gbWFwQnJvd3NlckV2ZW50IE1hcCBicm93c2VyIGV2ZW50LlxuICogQHJldHVybiB7Ym9vbGVhbn0gRmFsc2UuXG4gKiBAYXBpXG4gKi9cblxuZXhwb3J0IHZhciBuZXZlciA9IEZBTFNFO1xuLyoqXG4gKiBSZXR1cm4gYHRydWVgIGlmIHRoZSBicm93c2VyIGV2ZW50IGlzIGEgYHBvaW50ZXJtb3ZlYCBldmVudCwgYGZhbHNlYFxuICogb3RoZXJ3aXNlLlxuICpcbiAqIEBwYXJhbSB7aW1wb3J0KFwiLi4vTWFwQnJvd3NlckV2ZW50LmpzXCIpLmRlZmF1bHR9IG1hcEJyb3dzZXJFdmVudCBNYXAgYnJvd3NlciBldmVudC5cbiAqIEByZXR1cm4ge2Jvb2xlYW59IFRydWUgaWYgdGhlIGJyb3dzZXIgZXZlbnQgaXMgYSBgcG9pbnRlcm1vdmVgIGV2ZW50LlxuICogQGFwaVxuICovXG5cbmV4cG9ydCB2YXIgcG9pbnRlck1vdmUgPSBmdW5jdGlvbiBwb2ludGVyTW92ZShtYXBCcm93c2VyRXZlbnQpIHtcbiAgcmV0dXJuIG1hcEJyb3dzZXJFdmVudC50eXBlID09ICdwb2ludGVybW92ZSc7XG59O1xuLyoqXG4gKiBSZXR1cm4gYHRydWVgIGlmIHRoZSBldmVudCBpcyBhIG1hcCBgc2luZ2xlY2xpY2tgIGV2ZW50LCBgZmFsc2VgIG90aGVyd2lzZS5cbiAqXG4gKiBAcGFyYW0ge2ltcG9ydChcIi4uL01hcEJyb3dzZXJFdmVudC5qc1wiKS5kZWZhdWx0fSBtYXBCcm93c2VyRXZlbnQgTWFwIGJyb3dzZXIgZXZlbnQuXG4gKiBAcmV0dXJuIHtib29sZWFufSBUcnVlIGlmIHRoZSBldmVudCBpcyBhIG1hcCBgc2luZ2xlY2xpY2tgIGV2ZW50LlxuICogQGFwaVxuICovXG5cbmV4cG9ydCB2YXIgc2luZ2xlQ2xpY2sgPSBmdW5jdGlvbiBzaW5nbGVDbGljayhtYXBCcm93c2VyRXZlbnQpIHtcbiAgcmV0dXJuIG1hcEJyb3dzZXJFdmVudC50eXBlID09IE1hcEJyb3dzZXJFdmVudFR5cGUuU0lOR0xFQ0xJQ0s7XG59O1xuLyoqXG4gKiBSZXR1cm4gYHRydWVgIGlmIHRoZSBldmVudCBpcyBhIG1hcCBgZGJsY2xpY2tgIGV2ZW50LCBgZmFsc2VgIG90aGVyd2lzZS5cbiAqXG4gKiBAcGFyYW0ge2ltcG9ydChcIi4uL01hcEJyb3dzZXJFdmVudC5qc1wiKS5kZWZhdWx0fSBtYXBCcm93c2VyRXZlbnQgTWFwIGJyb3dzZXIgZXZlbnQuXG4gKiBAcmV0dXJuIHtib29sZWFufSBUcnVlIGlmIHRoZSBldmVudCBpcyBhIG1hcCBgZGJsY2xpY2tgIGV2ZW50LlxuICogQGFwaVxuICovXG5cbmV4cG9ydCB2YXIgZG91YmxlQ2xpY2sgPSBmdW5jdGlvbiBkb3VibGVDbGljayhtYXBCcm93c2VyRXZlbnQpIHtcbiAgcmV0dXJuIG1hcEJyb3dzZXJFdmVudC50eXBlID09IE1hcEJyb3dzZXJFdmVudFR5cGUuREJMQ0xJQ0s7XG59O1xuLyoqXG4gKiBSZXR1cm4gYHRydWVgIGlmIG5vIG1vZGlmaWVyIGtleSAoYWx0LSwgc2hpZnQtIG9yIHBsYXRmb3JtLW1vZGlmaWVyLWtleSkgaXNcbiAqIHByZXNzZWQuXG4gKlxuICogQHBhcmFtIHtpbXBvcnQoXCIuLi9NYXBCcm93c2VyRXZlbnQuanNcIikuZGVmYXVsdH0gbWFwQnJvd3NlckV2ZW50IE1hcCBicm93c2VyIGV2ZW50LlxuICogQHJldHVybiB7Ym9vbGVhbn0gVHJ1ZSBvbmx5IGlmIHRoZXJlIG5vIG1vZGlmaWVyIGtleXMgYXJlIHByZXNzZWQuXG4gKiBAYXBpXG4gKi9cblxuZXhwb3J0IHZhciBub01vZGlmaWVyS2V5cyA9IGZ1bmN0aW9uIG5vTW9kaWZpZXJLZXlzKG1hcEJyb3dzZXJFdmVudCkge1xuICB2YXIgb3JpZ2luYWxFdmVudCA9XG4gIC8qKiBAdHlwZSB7S2V5Ym9hcmRFdmVudHxNb3VzZUV2ZW50fFRvdWNoRXZlbnR9ICovXG4gIG1hcEJyb3dzZXJFdmVudC5vcmlnaW5hbEV2ZW50O1xuICByZXR1cm4gIW9yaWdpbmFsRXZlbnQuYWx0S2V5ICYmICEob3JpZ2luYWxFdmVudC5tZXRhS2V5IHx8IG9yaWdpbmFsRXZlbnQuY3RybEtleSkgJiYgIW9yaWdpbmFsRXZlbnQuc2hpZnRLZXk7XG59O1xuLyoqXG4gKiBSZXR1cm4gYHRydWVgIGlmIG9ubHkgdGhlIHBsYXRmb3JtLW1vZGlmaWVyLWtleSAodGhlIG1ldGEta2V5IG9uIE1hYyxcbiAqIGN0cmwta2V5IG90aGVyd2lzZSkgaXMgcHJlc3NlZCwgYGZhbHNlYCBvdGhlcndpc2UgKGUuZy4gd2hlbiBhZGRpdGlvbmFsbHlcbiAqIHRoZSBzaGlmdC1rZXkgaXMgcHJlc3NlZCkuXG4gKlxuICogQHBhcmFtIHtpbXBvcnQoXCIuLi9NYXBCcm93c2VyRXZlbnQuanNcIikuZGVmYXVsdH0gbWFwQnJvd3NlckV2ZW50IE1hcCBicm93c2VyIGV2ZW50LlxuICogQHJldHVybiB7Ym9vbGVhbn0gVHJ1ZSBpZiBvbmx5IHRoZSBwbGF0Zm9ybSBtb2RpZmllciBrZXkgaXMgcHJlc3NlZC5cbiAqIEBhcGlcbiAqL1xuXG5leHBvcnQgdmFyIHBsYXRmb3JtTW9kaWZpZXJLZXlPbmx5ID0gZnVuY3Rpb24gcGxhdGZvcm1Nb2RpZmllcktleU9ubHkobWFwQnJvd3NlckV2ZW50KSB7XG4gIHZhciBvcmlnaW5hbEV2ZW50ID1cbiAgLyoqIEB0eXBlIHtLZXlib2FyZEV2ZW50fE1vdXNlRXZlbnR8VG91Y2hFdmVudH0gKi9cbiAgbWFwQnJvd3NlckV2ZW50Lm9yaWdpbmFsRXZlbnQ7XG4gIHJldHVybiAhb3JpZ2luYWxFdmVudC5hbHRLZXkgJiYgKE1BQyA/IG9yaWdpbmFsRXZlbnQubWV0YUtleSA6IG9yaWdpbmFsRXZlbnQuY3RybEtleSkgJiYgIW9yaWdpbmFsRXZlbnQuc2hpZnRLZXk7XG59O1xuLyoqXG4gKiBSZXR1cm4gYHRydWVgIGlmIG9ubHkgdGhlIHNoaWZ0LWtleSBpcyBwcmVzc2VkLCBgZmFsc2VgIG90aGVyd2lzZSAoZS5nLiB3aGVuXG4gKiBhZGRpdGlvbmFsbHkgdGhlIGFsdC1rZXkgaXMgcHJlc3NlZCkuXG4gKlxuICogQHBhcmFtIHtpbXBvcnQoXCIuLi9NYXBCcm93c2VyRXZlbnQuanNcIikuZGVmYXVsdH0gbWFwQnJvd3NlckV2ZW50IE1hcCBicm93c2VyIGV2ZW50LlxuICogQHJldHVybiB7Ym9vbGVhbn0gVHJ1ZSBpZiBvbmx5IHRoZSBzaGlmdCBrZXkgaXMgcHJlc3NlZC5cbiAqIEBhcGlcbiAqL1xuXG5leHBvcnQgdmFyIHNoaWZ0S2V5T25seSA9IGZ1bmN0aW9uIHNoaWZ0S2V5T25seShtYXBCcm93c2VyRXZlbnQpIHtcbiAgdmFyIG9yaWdpbmFsRXZlbnQgPVxuICAvKiogQHR5cGUge0tleWJvYXJkRXZlbnR8TW91c2VFdmVudHxUb3VjaEV2ZW50fSAqL1xuICBtYXBCcm93c2VyRXZlbnQub3JpZ2luYWxFdmVudDtcbiAgcmV0dXJuICFvcmlnaW5hbEV2ZW50LmFsdEtleSAmJiAhKG9yaWdpbmFsRXZlbnQubWV0YUtleSB8fCBvcmlnaW5hbEV2ZW50LmN0cmxLZXkpICYmIG9yaWdpbmFsRXZlbnQuc2hpZnRLZXk7XG59O1xuLyoqXG4gKiBSZXR1cm4gYHRydWVgIGlmIHRoZSB0YXJnZXQgZWxlbWVudCBpcyBub3QgZWRpdGFibGUsIGkuZS4gbm90IGEgYDxpbnB1dD5gLSxcbiAqIGA8c2VsZWN0PmAtIG9yIGA8dGV4dGFyZWE+YC1lbGVtZW50LCBgZmFsc2VgIG90aGVyd2lzZS5cbiAqXG4gKiBAcGFyYW0ge2ltcG9ydChcIi4uL01hcEJyb3dzZXJFdmVudC5qc1wiKS5kZWZhdWx0fSBtYXBCcm93c2VyRXZlbnQgTWFwIGJyb3dzZXIgZXZlbnQuXG4gKiBAcmV0dXJuIHtib29sZWFufSBUcnVlIG9ubHkgaWYgdGhlIHRhcmdldCBlbGVtZW50IGlzIG5vdCBlZGl0YWJsZS5cbiAqIEBhcGlcbiAqL1xuXG5leHBvcnQgdmFyIHRhcmdldE5vdEVkaXRhYmxlID0gZnVuY3Rpb24gdGFyZ2V0Tm90RWRpdGFibGUobWFwQnJvd3NlckV2ZW50KSB7XG4gIHZhciBvcmlnaW5hbEV2ZW50ID1cbiAgLyoqIEB0eXBlIHtLZXlib2FyZEV2ZW50fE1vdXNlRXZlbnR8VG91Y2hFdmVudH0gKi9cbiAgbWFwQnJvd3NlckV2ZW50Lm9yaWdpbmFsRXZlbnQ7XG4gIHZhciB0YWdOYW1lID1cbiAgLyoqIEB0eXBlIHtFbGVtZW50fSAqL1xuICBvcmlnaW5hbEV2ZW50LnRhcmdldC50YWdOYW1lO1xuICByZXR1cm4gdGFnTmFtZSAhPT0gJ0lOUFVUJyAmJiB0YWdOYW1lICE9PSAnU0VMRUNUJyAmJiB0YWdOYW1lICE9PSAnVEVYVEFSRUEnO1xufTtcbi8qKlxuICogUmV0dXJuIGB0cnVlYCBpZiB0aGUgZXZlbnQgb3JpZ2luYXRlcyBmcm9tIGEgbW91c2UgZGV2aWNlLlxuICpcbiAqIEBwYXJhbSB7aW1wb3J0KFwiLi4vTWFwQnJvd3NlckV2ZW50LmpzXCIpLmRlZmF1bHR9IG1hcEJyb3dzZXJFdmVudCBNYXAgYnJvd3NlciBldmVudC5cbiAqIEByZXR1cm4ge2Jvb2xlYW59IFRydWUgaWYgdGhlIGV2ZW50IG9yaWdpbmF0ZXMgZnJvbSBhIG1vdXNlIGRldmljZS5cbiAqIEBhcGlcbiAqL1xuXG5leHBvcnQgdmFyIG1vdXNlT25seSA9IGZ1bmN0aW9uIG1vdXNlT25seShtYXBCcm93c2VyRXZlbnQpIHtcbiAgdmFyIHBvaW50ZXJFdmVudCA9XG4gIC8qKiBAdHlwZSB7aW1wb3J0KFwiLi4vTWFwQnJvd3NlckV2ZW50XCIpLmRlZmF1bHR9ICovXG4gIG1hcEJyb3dzZXJFdmVudC5vcmlnaW5hbEV2ZW50O1xuICBhc3NlcnQocG9pbnRlckV2ZW50ICE9PSB1bmRlZmluZWQsIDU2KTsgLy8gbWFwQnJvd3NlckV2ZW50IG11c3Qgb3JpZ2luYXRlIGZyb20gYSBwb2ludGVyIGV2ZW50XG4gIC8vIHNlZSBodHRwOi8vd3d3LnczLm9yZy9UUi9wb2ludGVyZXZlbnRzLyN3aWRsLVBvaW50ZXJFdmVudC1wb2ludGVyVHlwZVxuXG4gIHJldHVybiBwb2ludGVyRXZlbnQucG9pbnRlclR5cGUgPT0gJ21vdXNlJztcbn07XG4vKipcbiAqIFJldHVybiBgdHJ1ZWAgaWYgdGhlIGV2ZW50IG9yaWdpbmF0ZXMgZnJvbSBhIHRvdWNoYWJsZSBkZXZpY2UuXG4gKlxuICogQHBhcmFtIHtpbXBvcnQoXCIuLi9NYXBCcm93c2VyRXZlbnQuanNcIikuZGVmYXVsdH0gbWFwQnJvd3NlckV2ZW50IE1hcCBicm93c2VyIGV2ZW50LlxuICogQHJldHVybiB7Ym9vbGVhbn0gVHJ1ZSBpZiB0aGUgZXZlbnQgb3JpZ2luYXRlcyBmcm9tIGEgdG91Y2hhYmxlIGRldmljZS5cbiAqIEBhcGlcbiAqL1xuXG5leHBvcnQgdmFyIHRvdWNoT25seSA9IGZ1bmN0aW9uIHRvdWNoT25seShtYXBCcm93c2VyRXZlbnQpIHtcbiAgdmFyIHBvaW50ZXJFdnQgPVxuICAvKiogQHR5cGUge2ltcG9ydChcIi4uL01hcEJyb3dzZXJFdmVudFwiKS5kZWZhdWx0fSAqL1xuICBtYXBCcm93c2VyRXZlbnQub3JpZ2luYWxFdmVudDtcbiAgYXNzZXJ0KHBvaW50ZXJFdnQgIT09IHVuZGVmaW5lZCwgNTYpOyAvLyBtYXBCcm93c2VyRXZlbnQgbXVzdCBvcmlnaW5hdGUgZnJvbSBhIHBvaW50ZXIgZXZlbnRcbiAgLy8gc2VlIGh0dHA6Ly93d3cudzMub3JnL1RSL3BvaW50ZXJldmVudHMvI3dpZGwtUG9pbnRlckV2ZW50LXBvaW50ZXJUeXBlXG5cbiAgcmV0dXJuIHBvaW50ZXJFdnQucG9pbnRlclR5cGUgPT09ICd0b3VjaCc7XG59O1xuLyoqXG4gKiBSZXR1cm4gYHRydWVgIGlmIHRoZSBldmVudCBvcmlnaW5hdGVzIGZyb20gYSBkaWdpdGFsIHBlbi5cbiAqXG4gKiBAcGFyYW0ge2ltcG9ydChcIi4uL01hcEJyb3dzZXJFdmVudC5qc1wiKS5kZWZhdWx0fSBtYXBCcm93c2VyRXZlbnQgTWFwIGJyb3dzZXIgZXZlbnQuXG4gKiBAcmV0dXJuIHtib29sZWFufSBUcnVlIGlmIHRoZSBldmVudCBvcmlnaW5hdGVzIGZyb20gYSBkaWdpdGFsIHBlbi5cbiAqIEBhcGlcbiAqL1xuXG5leHBvcnQgdmFyIHBlbk9ubHkgPSBmdW5jdGlvbiBwZW5Pbmx5KG1hcEJyb3dzZXJFdmVudCkge1xuICB2YXIgcG9pbnRlckV2dCA9XG4gIC8qKiBAdHlwZSB7aW1wb3J0KFwiLi4vTWFwQnJvd3NlckV2ZW50XCIpLmRlZmF1bHR9ICovXG4gIG1hcEJyb3dzZXJFdmVudC5vcmlnaW5hbEV2ZW50O1xuICBhc3NlcnQocG9pbnRlckV2dCAhPT0gdW5kZWZpbmVkLCA1Nik7IC8vIG1hcEJyb3dzZXJFdmVudCBtdXN0IG9yaWdpbmF0ZSBmcm9tIGEgcG9pbnRlciBldmVudFxuICAvLyBzZWUgaHR0cDovL3d3dy53My5vcmcvVFIvcG9pbnRlcmV2ZW50cy8jd2lkbC1Qb2ludGVyRXZlbnQtcG9pbnRlclR5cGVcblxuICByZXR1cm4gcG9pbnRlckV2dC5wb2ludGVyVHlwZSA9PT0gJ3Blbic7XG59O1xuLyoqXG4gKiBSZXR1cm4gYHRydWVgIGlmIHRoZSBldmVudCBvcmlnaW5hdGVzIGZyb20gYSBwcmltYXJ5IHBvaW50ZXIgaW5cbiAqIGNvbnRhY3Qgd2l0aCB0aGUgc3VyZmFjZSBvciBpZiB0aGUgbGVmdCBtb3VzZSBidXR0b24gaXMgcHJlc3NlZC5cbiAqIFNlZSBodHRwOi8vd3d3LnczLm9yZy9UUi9wb2ludGVyZXZlbnRzLyNidXR0b24tc3RhdGVzLlxuICpcbiAqIEBwYXJhbSB7aW1wb3J0KFwiLi4vTWFwQnJvd3NlckV2ZW50LmpzXCIpLmRlZmF1bHR9IG1hcEJyb3dzZXJFdmVudCBNYXAgYnJvd3NlciBldmVudC5cbiAqIEByZXR1cm4ge2Jvb2xlYW59IFRydWUgaWYgdGhlIGV2ZW50IG9yaWdpbmF0ZXMgZnJvbSBhIHByaW1hcnkgcG9pbnRlci5cbiAqIEBhcGlcbiAqL1xuXG5leHBvcnQgdmFyIHByaW1hcnlBY3Rpb24gPSBmdW5jdGlvbiBwcmltYXJ5QWN0aW9uKG1hcEJyb3dzZXJFdmVudCkge1xuICB2YXIgcG9pbnRlckV2ZW50ID1cbiAgLyoqIEB0eXBlIHtpbXBvcnQoXCIuLi9NYXBCcm93c2VyRXZlbnRcIikuZGVmYXVsdH0gKi9cbiAgbWFwQnJvd3NlckV2ZW50Lm9yaWdpbmFsRXZlbnQ7XG4gIGFzc2VydChwb2ludGVyRXZlbnQgIT09IHVuZGVmaW5lZCwgNTYpOyAvLyBtYXBCcm93c2VyRXZlbnQgbXVzdCBvcmlnaW5hdGUgZnJvbSBhIHBvaW50ZXIgZXZlbnRcblxuICByZXR1cm4gcG9pbnRlckV2ZW50LmlzUHJpbWFyeSAmJiBwb2ludGVyRXZlbnQuYnV0dG9uID09PSAwO1xufTsiLCJ2YXIgX19leHRlbmRzID0gdGhpcyAmJiB0aGlzLl9fZXh0ZW5kcyB8fCBmdW5jdGlvbiAoKSB7XG4gIHZhciBfZXh0ZW5kU3RhdGljcyA9IGZ1bmN0aW9uIGV4dGVuZFN0YXRpY3MoZCwgYikge1xuICAgIF9leHRlbmRTdGF0aWNzID0gT2JqZWN0LnNldFByb3RvdHlwZU9mIHx8IHtcbiAgICAgIF9fcHJvdG9fXzogW11cbiAgICB9IGluc3RhbmNlb2YgQXJyYXkgJiYgZnVuY3Rpb24gKGQsIGIpIHtcbiAgICAgIGQuX19wcm90b19fID0gYjtcbiAgICB9IHx8IGZ1bmN0aW9uIChkLCBiKSB7XG4gICAgICBmb3IgKHZhciBwIGluIGIpIHtcbiAgICAgICAgaWYgKE9iamVjdC5wcm90b3R5cGUuaGFzT3duUHJvcGVydHkuY2FsbChiLCBwKSkgZFtwXSA9IGJbcF07XG4gICAgICB9XG4gICAgfTtcblxuICAgIHJldHVybiBfZXh0ZW5kU3RhdGljcyhkLCBiKTtcbiAgfTtcblxuICByZXR1cm4gZnVuY3Rpb24gKGQsIGIpIHtcbiAgICBfZXh0ZW5kU3RhdGljcyhkLCBiKTtcblxuICAgIGZ1bmN0aW9uIF9fKCkge1xuICAgICAgdGhpcy5jb25zdHJ1Y3RvciA9IGQ7XG4gICAgfVxuXG4gICAgZC5wcm90b3R5cGUgPSBiID09PSBudWxsID8gT2JqZWN0LmNyZWF0ZShiKSA6IChfXy5wcm90b3R5cGUgPSBiLnByb3RvdHlwZSwgbmV3IF9fKCkpO1xuICB9O1xufSgpO1xuLyoqXG4gKiBAbW9kdWxlIG9sL2ludGVyYWN0aW9uL0RyYWdQYW5cbiAqL1xuXG5cbmltcG9ydCBQb2ludGVySW50ZXJhY3Rpb24sIHsgY2VudHJvaWQgYXMgY2VudHJvaWRGcm9tUG9pbnRlcnMgfSBmcm9tICcuL1BvaW50ZXIuanMnO1xuaW1wb3J0IHsgRkFMU0UgfSBmcm9tICcuLi9mdW5jdGlvbnMuanMnO1xuaW1wb3J0IHsgYWxsLCBmb2N1c1dpdGhUYWJpbmRleCwgbm9Nb2RpZmllcktleXMsIHByaW1hcnlBY3Rpb24gfSBmcm9tICcuLi9ldmVudHMvY29uZGl0aW9uLmpzJztcbmltcG9ydCB7IGVhc2VPdXQgfSBmcm9tICcuLi9lYXNpbmcuanMnO1xuaW1wb3J0IHsgcm90YXRlIGFzIHJvdGF0ZUNvb3JkaW5hdGUsIHNjYWxlIGFzIHNjYWxlQ29vcmRpbmF0ZSB9IGZyb20gJy4uL2Nvb3JkaW5hdGUuanMnO1xuLyoqXG4gKiBAdHlwZWRlZiB7T2JqZWN0fSBPcHRpb25zXG4gKiBAcHJvcGVydHkge2ltcG9ydChcIi4uL2V2ZW50cy9jb25kaXRpb24uanNcIikuQ29uZGl0aW9ufSBbY29uZGl0aW9uXSBBIGZ1bmN0aW9uIHRoYXQgdGFrZXMgYW4ge0BsaW5rIG1vZHVsZTpvbC9NYXBCcm93c2VyRXZlbnR+TWFwQnJvd3NlckV2ZW50fSBhbmQgcmV0dXJucyBhIGJvb2xlYW5cbiAqIHRvIGluZGljYXRlIHdoZXRoZXIgdGhhdCBldmVudCBzaG91bGQgYmUgaGFuZGxlZC5cbiAqIERlZmF1bHQgaXMge0BsaW5rIG1vZHVsZTpvbC9ldmVudHMvY29uZGl0aW9ufm5vTW9kaWZpZXJLZXlzfSBhbmQge0BsaW5rIG1vZHVsZTpvbC9ldmVudHMvY29uZGl0aW9ufnByaW1hcnlBY3Rpb259LlxuICogQHByb3BlcnR5IHtib29sZWFufSBbb25Gb2N1c09ubHk9ZmFsc2VdIFdoZW4gdGhlIG1hcCdzIHRhcmdldCBoYXMgYSBgdGFiaW5kZXhgIGF0dHJpYnV0ZSBzZXQsXG4gKiB0aGUgaW50ZXJhY3Rpb24gd2lsbCBvbmx5IGhhbmRsZSBldmVudHMgd2hlbiB0aGUgbWFwIGhhcyB0aGUgZm9jdXMuXG4gKiBAcHJvcGVydHkge2ltcG9ydChcIi4uL0tpbmV0aWMuanNcIikuZGVmYXVsdH0gW2tpbmV0aWNdIEtpbmV0aWMgaW5lcnRpYSB0byBhcHBseSB0byB0aGUgcGFuLlxuICovXG5cbi8qKlxuICogQGNsYXNzZGVzY1xuICogQWxsb3dzIHRoZSB1c2VyIHRvIHBhbiB0aGUgbWFwIGJ5IGRyYWdnaW5nIHRoZSBtYXAuXG4gKiBAYXBpXG4gKi9cblxudmFyIERyYWdQYW4gPVxuLyoqIEBjbGFzcyAqL1xuZnVuY3Rpb24gKF9zdXBlcikge1xuICBfX2V4dGVuZHMoRHJhZ1BhbiwgX3N1cGVyKTtcbiAgLyoqXG4gICAqIEBwYXJhbSB7T3B0aW9ucz19IG9wdF9vcHRpb25zIE9wdGlvbnMuXG4gICAqL1xuXG5cbiAgZnVuY3Rpb24gRHJhZ1BhbihvcHRfb3B0aW9ucykge1xuICAgIHZhciBfdGhpcyA9IF9zdXBlci5jYWxsKHRoaXMsIHtcbiAgICAgIHN0b3BEb3duOiBGQUxTRVxuICAgIH0pIHx8IHRoaXM7XG5cbiAgICB2YXIgb3B0aW9ucyA9IG9wdF9vcHRpb25zID8gb3B0X29wdGlvbnMgOiB7fTtcbiAgICAvKipcbiAgICAgKiBAcHJpdmF0ZVxuICAgICAqIEB0eXBlIHtpbXBvcnQoXCIuLi9LaW5ldGljLmpzXCIpLmRlZmF1bHR8dW5kZWZpbmVkfVxuICAgICAqL1xuXG4gICAgX3RoaXMua2luZXRpY18gPSBvcHRpb25zLmtpbmV0aWM7XG4gICAgLyoqXG4gICAgICogQHR5cGUge2ltcG9ydChcIi4uL3BpeGVsLmpzXCIpLlBpeGVsfVxuICAgICAqL1xuXG4gICAgX3RoaXMubGFzdENlbnRyb2lkID0gbnVsbDtcbiAgICAvKipcbiAgICAgKiBAdHlwZSB7bnVtYmVyfVxuICAgICAqL1xuXG4gICAgX3RoaXMubGFzdFBvaW50ZXJzQ291bnRfO1xuICAgIC8qKlxuICAgICAqIEB0eXBlIHtib29sZWFufVxuICAgICAqL1xuXG4gICAgX3RoaXMucGFubmluZ18gPSBmYWxzZTtcbiAgICB2YXIgY29uZGl0aW9uID0gb3B0aW9ucy5jb25kaXRpb24gPyBvcHRpb25zLmNvbmRpdGlvbiA6IGFsbChub01vZGlmaWVyS2V5cywgcHJpbWFyeUFjdGlvbik7XG4gICAgLyoqXG4gICAgICogQHByaXZhdGVcbiAgICAgKiBAdHlwZSB7aW1wb3J0KFwiLi4vZXZlbnRzL2NvbmRpdGlvbi5qc1wiKS5Db25kaXRpb259XG4gICAgICovXG5cbiAgICBfdGhpcy5jb25kaXRpb25fID0gb3B0aW9ucy5vbkZvY3VzT25seSA/IGFsbChmb2N1c1dpdGhUYWJpbmRleCwgY29uZGl0aW9uKSA6IGNvbmRpdGlvbjtcbiAgICAvKipcbiAgICAgKiBAcHJpdmF0ZVxuICAgICAqIEB0eXBlIHtib29sZWFufVxuICAgICAqL1xuXG4gICAgX3RoaXMubm9LaW5ldGljXyA9IGZhbHNlO1xuICAgIHJldHVybiBfdGhpcztcbiAgfVxuICAvKipcbiAgICogSGFuZGxlIHBvaW50ZXIgZHJhZyBldmVudHMuXG4gICAqIEBwYXJhbSB7aW1wb3J0KFwiLi4vTWFwQnJvd3NlckV2ZW50LmpzXCIpLmRlZmF1bHR9IG1hcEJyb3dzZXJFdmVudCBFdmVudC5cbiAgICovXG5cblxuICBEcmFnUGFuLnByb3RvdHlwZS5oYW5kbGVEcmFnRXZlbnQgPSBmdW5jdGlvbiAobWFwQnJvd3NlckV2ZW50KSB7XG4gICAgaWYgKCF0aGlzLnBhbm5pbmdfKSB7XG4gICAgICB0aGlzLnBhbm5pbmdfID0gdHJ1ZTtcbiAgICAgIHRoaXMuZ2V0TWFwKCkuZ2V0VmlldygpLmJlZ2luSW50ZXJhY3Rpb24oKTtcbiAgICB9XG5cbiAgICB2YXIgdGFyZ2V0UG9pbnRlcnMgPSB0aGlzLnRhcmdldFBvaW50ZXJzO1xuICAgIHZhciBjZW50cm9pZCA9IGNlbnRyb2lkRnJvbVBvaW50ZXJzKHRhcmdldFBvaW50ZXJzKTtcblxuICAgIGlmICh0YXJnZXRQb2ludGVycy5sZW5ndGggPT0gdGhpcy5sYXN0UG9pbnRlcnNDb3VudF8pIHtcbiAgICAgIGlmICh0aGlzLmtpbmV0aWNfKSB7XG4gICAgICAgIHRoaXMua2luZXRpY18udXBkYXRlKGNlbnRyb2lkWzBdLCBjZW50cm9pZFsxXSk7XG4gICAgICB9XG5cbiAgICAgIGlmICh0aGlzLmxhc3RDZW50cm9pZCkge1xuICAgICAgICB2YXIgZGVsdGEgPSBbdGhpcy5sYXN0Q2VudHJvaWRbMF0gLSBjZW50cm9pZFswXSwgY2VudHJvaWRbMV0gLSB0aGlzLmxhc3RDZW50cm9pZFsxXV07XG4gICAgICAgIHZhciBtYXAgPSBtYXBCcm93c2VyRXZlbnQubWFwO1xuICAgICAgICB2YXIgdmlldyA9IG1hcC5nZXRWaWV3KCk7XG4gICAgICAgIHNjYWxlQ29vcmRpbmF0ZShkZWx0YSwgdmlldy5nZXRSZXNvbHV0aW9uKCkpO1xuICAgICAgICByb3RhdGVDb29yZGluYXRlKGRlbHRhLCB2aWV3LmdldFJvdGF0aW9uKCkpO1xuICAgICAgICB2aWV3LmFkanVzdENlbnRlckludGVybmFsKGRlbHRhKTtcbiAgICAgIH1cbiAgICB9IGVsc2UgaWYgKHRoaXMua2luZXRpY18pIHtcbiAgICAgIC8vIHJlc2V0IHNvIHdlIGRvbid0IG92ZXJlc3RpbWF0ZSB0aGUga2luZXRpYyBlbmVyZ3kgYWZ0ZXJcbiAgICAgIC8vIGFmdGVyIG9uZSBmaW5nZXIgZG93biwgdGlueSBkcmFnLCBzZWNvbmQgZmluZ2VyIGRvd25cbiAgICAgIHRoaXMua2luZXRpY18uYmVnaW4oKTtcbiAgICB9XG5cbiAgICB0aGlzLmxhc3RDZW50cm9pZCA9IGNlbnRyb2lkO1xuICAgIHRoaXMubGFzdFBvaW50ZXJzQ291bnRfID0gdGFyZ2V0UG9pbnRlcnMubGVuZ3RoO1xuICAgIG1hcEJyb3dzZXJFdmVudC5vcmlnaW5hbEV2ZW50LnByZXZlbnREZWZhdWx0KCk7XG4gIH07XG4gIC8qKlxuICAgKiBIYW5kbGUgcG9pbnRlciB1cCBldmVudHMuXG4gICAqIEBwYXJhbSB7aW1wb3J0KFwiLi4vTWFwQnJvd3NlckV2ZW50LmpzXCIpLmRlZmF1bHR9IG1hcEJyb3dzZXJFdmVudCBFdmVudC5cbiAgICogQHJldHVybiB7Ym9vbGVhbn0gSWYgdGhlIGV2ZW50IHdhcyBjb25zdW1lZC5cbiAgICovXG5cblxuICBEcmFnUGFuLnByb3RvdHlwZS5oYW5kbGVVcEV2ZW50ID0gZnVuY3Rpb24gKG1hcEJyb3dzZXJFdmVudCkge1xuICAgIHZhciBtYXAgPSBtYXBCcm93c2VyRXZlbnQubWFwO1xuICAgIHZhciB2aWV3ID0gbWFwLmdldFZpZXcoKTtcblxuICAgIGlmICh0aGlzLnRhcmdldFBvaW50ZXJzLmxlbmd0aCA9PT0gMCkge1xuICAgICAgaWYgKCF0aGlzLm5vS2luZXRpY18gJiYgdGhpcy5raW5ldGljXyAmJiB0aGlzLmtpbmV0aWNfLmVuZCgpKSB7XG4gICAgICAgIHZhciBkaXN0YW5jZSA9IHRoaXMua2luZXRpY18uZ2V0RGlzdGFuY2UoKTtcbiAgICAgICAgdmFyIGFuZ2xlID0gdGhpcy5raW5ldGljXy5nZXRBbmdsZSgpO1xuICAgICAgICB2YXIgY2VudGVyID0gdmlldy5nZXRDZW50ZXJJbnRlcm5hbCgpO1xuICAgICAgICB2YXIgY2VudGVycHggPSBtYXAuZ2V0UGl4ZWxGcm9tQ29vcmRpbmF0ZUludGVybmFsKGNlbnRlcik7XG4gICAgICAgIHZhciBkZXN0ID0gbWFwLmdldENvb3JkaW5hdGVGcm9tUGl4ZWxJbnRlcm5hbChbY2VudGVycHhbMF0gLSBkaXN0YW5jZSAqIE1hdGguY29zKGFuZ2xlKSwgY2VudGVycHhbMV0gLSBkaXN0YW5jZSAqIE1hdGguc2luKGFuZ2xlKV0pO1xuICAgICAgICB2aWV3LmFuaW1hdGVJbnRlcm5hbCh7XG4gICAgICAgICAgY2VudGVyOiB2aWV3LmdldENvbnN0cmFpbmVkQ2VudGVyKGRlc3QpLFxuICAgICAgICAgIGR1cmF0aW9uOiA1MDAsXG4gICAgICAgICAgZWFzaW5nOiBlYXNlT3V0XG4gICAgICAgIH0pO1xuICAgICAgfVxuXG4gICAgICBpZiAodGhpcy5wYW5uaW5nXykge1xuICAgICAgICB0aGlzLnBhbm5pbmdfID0gZmFsc2U7XG4gICAgICAgIHZpZXcuZW5kSW50ZXJhY3Rpb24oKTtcbiAgICAgIH1cblxuICAgICAgcmV0dXJuIGZhbHNlO1xuICAgIH0gZWxzZSB7XG4gICAgICBpZiAodGhpcy5raW5ldGljXykge1xuICAgICAgICAvLyByZXNldCBzbyB3ZSBkb24ndCBvdmVyZXN0aW1hdGUgdGhlIGtpbmV0aWMgZW5lcmd5IGFmdGVyXG4gICAgICAgIC8vIGFmdGVyIG9uZSBmaW5nZXIgdXAsIHRpbnkgZHJhZywgc2Vjb25kIGZpbmdlciB1cFxuICAgICAgICB0aGlzLmtpbmV0aWNfLmJlZ2luKCk7XG4gICAgICB9XG5cbiAgICAgIHRoaXMubGFzdENlbnRyb2lkID0gbnVsbDtcbiAgICAgIHJldHVybiB0cnVlO1xuICAgIH1cbiAgfTtcbiAgLyoqXG4gICAqIEhhbmRsZSBwb2ludGVyIGRvd24gZXZlbnRzLlxuICAgKiBAcGFyYW0ge2ltcG9ydChcIi4uL01hcEJyb3dzZXJFdmVudC5qc1wiKS5kZWZhdWx0fSBtYXBCcm93c2VyRXZlbnQgRXZlbnQuXG4gICAqIEByZXR1cm4ge2Jvb2xlYW59IElmIHRoZSBldmVudCB3YXMgY29uc3VtZWQuXG4gICAqL1xuXG5cbiAgRHJhZ1Bhbi5wcm90b3R5cGUuaGFuZGxlRG93bkV2ZW50ID0gZnVuY3Rpb24gKG1hcEJyb3dzZXJFdmVudCkge1xuICAgIGlmICh0aGlzLnRhcmdldFBvaW50ZXJzLmxlbmd0aCA+IDAgJiYgdGhpcy5jb25kaXRpb25fKG1hcEJyb3dzZXJFdmVudCkpIHtcbiAgICAgIHZhciBtYXAgPSBtYXBCcm93c2VyRXZlbnQubWFwO1xuICAgICAgdmFyIHZpZXcgPSBtYXAuZ2V0VmlldygpO1xuICAgICAgdGhpcy5sYXN0Q2VudHJvaWQgPSBudWxsOyAvLyBzdG9wIGFueSBjdXJyZW50IGFuaW1hdGlvblxuXG4gICAgICBpZiAodmlldy5nZXRBbmltYXRpbmcoKSkge1xuICAgICAgICB2aWV3LmNhbmNlbEFuaW1hdGlvbnMoKTtcbiAgICAgIH1cblxuICAgICAgaWYgKHRoaXMua2luZXRpY18pIHtcbiAgICAgICAgdGhpcy5raW5ldGljXy5iZWdpbigpO1xuICAgICAgfSAvLyBObyBraW5ldGljIGFzIHNvb24gYXMgbW9yZSB0aGFuIG9uZSBwb2ludGVyIG9uIHRoZSBzY3JlZW4gaXNcbiAgICAgIC8vIGRldGVjdGVkLiBUaGlzIGlzIHRvIHByZXZlbnQgbmFzdHkgcGFucyBhZnRlciBwaW5jaC5cblxuXG4gICAgICB0aGlzLm5vS2luZXRpY18gPSB0aGlzLnRhcmdldFBvaW50ZXJzLmxlbmd0aCA+IDE7XG4gICAgICByZXR1cm4gdHJ1ZTtcbiAgICB9IGVsc2Uge1xuICAgICAgcmV0dXJuIGZhbHNlO1xuICAgIH1cbiAgfTtcblxuICByZXR1cm4gRHJhZ1Bhbjtcbn0oUG9pbnRlckludGVyYWN0aW9uKTtcblxuZXhwb3J0IGRlZmF1bHQgRHJhZ1BhbjsiLCJ2YXIgX19leHRlbmRzID0gdGhpcyAmJiB0aGlzLl9fZXh0ZW5kcyB8fCBmdW5jdGlvbiAoKSB7XG4gIHZhciBfZXh0ZW5kU3RhdGljcyA9IGZ1bmN0aW9uIGV4dGVuZFN0YXRpY3MoZCwgYikge1xuICAgIF9leHRlbmRTdGF0aWNzID0gT2JqZWN0LnNldFByb3RvdHlwZU9mIHx8IHtcbiAgICAgIF9fcHJvdG9fXzogW11cbiAgICB9IGluc3RhbmNlb2YgQXJyYXkgJiYgZnVuY3Rpb24gKGQsIGIpIHtcbiAgICAgIGQuX19wcm90b19fID0gYjtcbiAgICB9IHx8IGZ1bmN0aW9uIChkLCBiKSB7XG4gICAgICBmb3IgKHZhciBwIGluIGIpIHtcbiAgICAgICAgaWYgKE9iamVjdC5wcm90b3R5cGUuaGFzT3duUHJvcGVydHkuY2FsbChiLCBwKSkgZFtwXSA9IGJbcF07XG4gICAgICB9XG4gICAgfTtcblxuICAgIHJldHVybiBfZXh0ZW5kU3RhdGljcyhkLCBiKTtcbiAgfTtcblxuICByZXR1cm4gZnVuY3Rpb24gKGQsIGIpIHtcbiAgICBfZXh0ZW5kU3RhdGljcyhkLCBiKTtcblxuICAgIGZ1bmN0aW9uIF9fKCkge1xuICAgICAgdGhpcy5jb25zdHJ1Y3RvciA9IGQ7XG4gICAgfVxuXG4gICAgZC5wcm90b3R5cGUgPSBiID09PSBudWxsID8gT2JqZWN0LmNyZWF0ZShiKSA6IChfXy5wcm90b3R5cGUgPSBiLnByb3RvdHlwZSwgbmV3IF9fKCkpO1xuICB9O1xufSgpO1xuLyoqXG4gKiBAbW9kdWxlIG9sL2ludGVyYWN0aW9uL0RyYWdSb3RhdGVcbiAqL1xuXG5cbmltcG9ydCBQb2ludGVySW50ZXJhY3Rpb24gZnJvbSAnLi9Qb2ludGVyLmpzJztcbmltcG9ydCB7IEZBTFNFIH0gZnJvbSAnLi4vZnVuY3Rpb25zLmpzJztcbmltcG9ydCB7IGFsdFNoaWZ0S2V5c09ubHksIG1vdXNlQWN0aW9uQnV0dG9uLCBtb3VzZU9ubHkgfSBmcm9tICcuLi9ldmVudHMvY29uZGl0aW9uLmpzJztcbmltcG9ydCB7IGRpc2FibGUgfSBmcm9tICcuLi9yb3RhdGlvbmNvbnN0cmFpbnQuanMnO1xuLyoqXG4gKiBAdHlwZWRlZiB7T2JqZWN0fSBPcHRpb25zXG4gKiBAcHJvcGVydHkge2ltcG9ydChcIi4uL2V2ZW50cy9jb25kaXRpb24uanNcIikuQ29uZGl0aW9ufSBbY29uZGl0aW9uXSBBIGZ1bmN0aW9uIHRoYXQgdGFrZXMgYW5cbiAqIHtAbGluayBtb2R1bGU6b2wvTWFwQnJvd3NlckV2ZW50fk1hcEJyb3dzZXJFdmVudH0gYW5kIHJldHVybnMgYSBib29sZWFuXG4gKiB0byBpbmRpY2F0ZSB3aGV0aGVyIHRoYXQgZXZlbnQgc2hvdWxkIGJlIGhhbmRsZWQuXG4gKiBEZWZhdWx0IGlzIHtAbGluayBtb2R1bGU6b2wvZXZlbnRzL2NvbmRpdGlvbn5hbHRTaGlmdEtleXNPbmx5fS5cbiAqIEBwcm9wZXJ0eSB7bnVtYmVyfSBbZHVyYXRpb249MjUwXSBBbmltYXRpb24gZHVyYXRpb24gaW4gbWlsbGlzZWNvbmRzLlxuICovXG5cbi8qKlxuICogQGNsYXNzZGVzY1xuICogQWxsb3dzIHRoZSB1c2VyIHRvIHJvdGF0ZSB0aGUgbWFwIGJ5IGNsaWNraW5nIGFuZCBkcmFnZ2luZyBvbiB0aGUgbWFwLFxuICogbm9ybWFsbHkgY29tYmluZWQgd2l0aCBhbiB7QGxpbmsgbW9kdWxlOm9sL2V2ZW50cy9jb25kaXRpb259IHRoYXQgbGltaXRzXG4gKiBpdCB0byB3aGVuIHRoZSBhbHQgYW5kIHNoaWZ0IGtleXMgYXJlIGhlbGQgZG93bi5cbiAqXG4gKiBUaGlzIGludGVyYWN0aW9uIGlzIG9ubHkgc3VwcG9ydGVkIGZvciBtb3VzZSBkZXZpY2VzLlxuICogQGFwaVxuICovXG5cbnZhciBEcmFnUm90YXRlID1cbi8qKiBAY2xhc3MgKi9cbmZ1bmN0aW9uIChfc3VwZXIpIHtcbiAgX19leHRlbmRzKERyYWdSb3RhdGUsIF9zdXBlcik7XG4gIC8qKlxuICAgKiBAcGFyYW0ge09wdGlvbnM9fSBvcHRfb3B0aW9ucyBPcHRpb25zLlxuICAgKi9cblxuXG4gIGZ1bmN0aW9uIERyYWdSb3RhdGUob3B0X29wdGlvbnMpIHtcbiAgICB2YXIgX3RoaXMgPSB0aGlzO1xuXG4gICAgdmFyIG9wdGlvbnMgPSBvcHRfb3B0aW9ucyA/IG9wdF9vcHRpb25zIDoge307XG4gICAgX3RoaXMgPSBfc3VwZXIuY2FsbCh0aGlzLCB7XG4gICAgICBzdG9wRG93bjogRkFMU0VcbiAgICB9KSB8fCB0aGlzO1xuICAgIC8qKlxuICAgICAqIEBwcml2YXRlXG4gICAgICogQHR5cGUge2ltcG9ydChcIi4uL2V2ZW50cy9jb25kaXRpb24uanNcIikuQ29uZGl0aW9ufVxuICAgICAqL1xuXG4gICAgX3RoaXMuY29uZGl0aW9uXyA9IG9wdGlvbnMuY29uZGl0aW9uID8gb3B0aW9ucy5jb25kaXRpb24gOiBhbHRTaGlmdEtleXNPbmx5O1xuICAgIC8qKlxuICAgICAqIEBwcml2YXRlXG4gICAgICogQHR5cGUge251bWJlcnx1bmRlZmluZWR9XG4gICAgICovXG5cbiAgICBfdGhpcy5sYXN0QW5nbGVfID0gdW5kZWZpbmVkO1xuICAgIC8qKlxuICAgICAqIEBwcml2YXRlXG4gICAgICogQHR5cGUge251bWJlcn1cbiAgICAgKi9cblxuICAgIF90aGlzLmR1cmF0aW9uXyA9IG9wdGlvbnMuZHVyYXRpb24gIT09IHVuZGVmaW5lZCA/IG9wdGlvbnMuZHVyYXRpb24gOiAyNTA7XG4gICAgcmV0dXJuIF90aGlzO1xuICB9XG4gIC8qKlxuICAgKiBIYW5kbGUgcG9pbnRlciBkcmFnIGV2ZW50cy5cbiAgICogQHBhcmFtIHtpbXBvcnQoXCIuLi9NYXBCcm93c2VyRXZlbnQuanNcIikuZGVmYXVsdH0gbWFwQnJvd3NlckV2ZW50IEV2ZW50LlxuICAgKi9cblxuXG4gIERyYWdSb3RhdGUucHJvdG90eXBlLmhhbmRsZURyYWdFdmVudCA9IGZ1bmN0aW9uIChtYXBCcm93c2VyRXZlbnQpIHtcbiAgICBpZiAoIW1vdXNlT25seShtYXBCcm93c2VyRXZlbnQpKSB7XG4gICAgICByZXR1cm47XG4gICAgfVxuXG4gICAgdmFyIG1hcCA9IG1hcEJyb3dzZXJFdmVudC5tYXA7XG4gICAgdmFyIHZpZXcgPSBtYXAuZ2V0VmlldygpO1xuXG4gICAgaWYgKHZpZXcuZ2V0Q29uc3RyYWludHMoKS5yb3RhdGlvbiA9PT0gZGlzYWJsZSkge1xuICAgICAgcmV0dXJuO1xuICAgIH1cblxuICAgIHZhciBzaXplID0gbWFwLmdldFNpemUoKTtcbiAgICB2YXIgb2Zmc2V0ID0gbWFwQnJvd3NlckV2ZW50LnBpeGVsO1xuICAgIHZhciB0aGV0YSA9IE1hdGguYXRhbjIoc2l6ZVsxXSAvIDIgLSBvZmZzZXRbMV0sIG9mZnNldFswXSAtIHNpemVbMF0gLyAyKTtcblxuICAgIGlmICh0aGlzLmxhc3RBbmdsZV8gIT09IHVuZGVmaW5lZCkge1xuICAgICAgdmFyIGRlbHRhID0gdGhldGEgLSB0aGlzLmxhc3RBbmdsZV87XG4gICAgICB2aWV3LmFkanVzdFJvdGF0aW9uSW50ZXJuYWwoLWRlbHRhKTtcbiAgICB9XG5cbiAgICB0aGlzLmxhc3RBbmdsZV8gPSB0aGV0YTtcbiAgfTtcbiAgLyoqXG4gICAqIEhhbmRsZSBwb2ludGVyIHVwIGV2ZW50cy5cbiAgICogQHBhcmFtIHtpbXBvcnQoXCIuLi9NYXBCcm93c2VyRXZlbnQuanNcIikuZGVmYXVsdH0gbWFwQnJvd3NlckV2ZW50IEV2ZW50LlxuICAgKiBAcmV0dXJuIHtib29sZWFufSBJZiB0aGUgZXZlbnQgd2FzIGNvbnN1bWVkLlxuICAgKi9cblxuXG4gIERyYWdSb3RhdGUucHJvdG90eXBlLmhhbmRsZVVwRXZlbnQgPSBmdW5jdGlvbiAobWFwQnJvd3NlckV2ZW50KSB7XG4gICAgaWYgKCFtb3VzZU9ubHkobWFwQnJvd3NlckV2ZW50KSkge1xuICAgICAgcmV0dXJuIHRydWU7XG4gICAgfVxuXG4gICAgdmFyIG1hcCA9IG1hcEJyb3dzZXJFdmVudC5tYXA7XG4gICAgdmFyIHZpZXcgPSBtYXAuZ2V0VmlldygpO1xuICAgIHZpZXcuZW5kSW50ZXJhY3Rpb24odGhpcy5kdXJhdGlvbl8pO1xuICAgIHJldHVybiBmYWxzZTtcbiAgfTtcbiAgLyoqXG4gICAqIEhhbmRsZSBwb2ludGVyIGRvd24gZXZlbnRzLlxuICAgKiBAcGFyYW0ge2ltcG9ydChcIi4uL01hcEJyb3dzZXJFdmVudC5qc1wiKS5kZWZhdWx0fSBtYXBCcm93c2VyRXZlbnQgRXZlbnQuXG4gICAqIEByZXR1cm4ge2Jvb2xlYW59IElmIHRoZSBldmVudCB3YXMgY29uc3VtZWQuXG4gICAqL1xuXG5cbiAgRHJhZ1JvdGF0ZS5wcm90b3R5cGUuaGFuZGxlRG93bkV2ZW50ID0gZnVuY3Rpb24gKG1hcEJyb3dzZXJFdmVudCkge1xuICAgIGlmICghbW91c2VPbmx5KG1hcEJyb3dzZXJFdmVudCkpIHtcbiAgICAgIHJldHVybiBmYWxzZTtcbiAgICB9XG5cbiAgICBpZiAobW91c2VBY3Rpb25CdXR0b24obWFwQnJvd3NlckV2ZW50KSAmJiB0aGlzLmNvbmRpdGlvbl8obWFwQnJvd3NlckV2ZW50KSkge1xuICAgICAgdmFyIG1hcCA9IG1hcEJyb3dzZXJFdmVudC5tYXA7XG4gICAgICBtYXAuZ2V0VmlldygpLmJlZ2luSW50ZXJhY3Rpb24oKTtcbiAgICAgIHRoaXMubGFzdEFuZ2xlXyA9IHVuZGVmaW5lZDtcbiAgICAgIHJldHVybiB0cnVlO1xuICAgIH0gZWxzZSB7XG4gICAgICByZXR1cm4gZmFsc2U7XG4gICAgfVxuICB9O1xuXG4gIHJldHVybiBEcmFnUm90YXRlO1xufShQb2ludGVySW50ZXJhY3Rpb24pO1xuXG5leHBvcnQgZGVmYXVsdCBEcmFnUm90YXRlOyIsIi8qKlxuICogQG1vZHVsZSBvbC9yZW5kZXIvQm94XG4gKi9cbnZhciBfX2V4dGVuZHMgPSB0aGlzICYmIHRoaXMuX19leHRlbmRzIHx8IGZ1bmN0aW9uICgpIHtcbiAgdmFyIF9leHRlbmRTdGF0aWNzID0gZnVuY3Rpb24gZXh0ZW5kU3RhdGljcyhkLCBiKSB7XG4gICAgX2V4dGVuZFN0YXRpY3MgPSBPYmplY3Quc2V0UHJvdG90eXBlT2YgfHwge1xuICAgICAgX19wcm90b19fOiBbXVxuICAgIH0gaW5zdGFuY2VvZiBBcnJheSAmJiBmdW5jdGlvbiAoZCwgYikge1xuICAgICAgZC5fX3Byb3RvX18gPSBiO1xuICAgIH0gfHwgZnVuY3Rpb24gKGQsIGIpIHtcbiAgICAgIGZvciAodmFyIHAgaW4gYikge1xuICAgICAgICBpZiAoT2JqZWN0LnByb3RvdHlwZS5oYXNPd25Qcm9wZXJ0eS5jYWxsKGIsIHApKSBkW3BdID0gYltwXTtcbiAgICAgIH1cbiAgICB9O1xuXG4gICAgcmV0dXJuIF9leHRlbmRTdGF0aWNzKGQsIGIpO1xuICB9O1xuXG4gIHJldHVybiBmdW5jdGlvbiAoZCwgYikge1xuICAgIF9leHRlbmRTdGF0aWNzKGQsIGIpO1xuXG4gICAgZnVuY3Rpb24gX18oKSB7XG4gICAgICB0aGlzLmNvbnN0cnVjdG9yID0gZDtcbiAgICB9XG5cbiAgICBkLnByb3RvdHlwZSA9IGIgPT09IG51bGwgPyBPYmplY3QuY3JlYXRlKGIpIDogKF9fLnByb3RvdHlwZSA9IGIucHJvdG90eXBlLCBuZXcgX18oKSk7XG4gIH07XG59KCk7XG5cbmltcG9ydCBEaXNwb3NhYmxlIGZyb20gJy4uL0Rpc3Bvc2FibGUuanMnO1xuaW1wb3J0IFBvbHlnb24gZnJvbSAnLi4vZ2VvbS9Qb2x5Z29uLmpzJztcblxudmFyIFJlbmRlckJveCA9XG4vKiogQGNsYXNzICovXG5mdW5jdGlvbiAoX3N1cGVyKSB7XG4gIF9fZXh0ZW5kcyhSZW5kZXJCb3gsIF9zdXBlcik7XG4gIC8qKlxuICAgKiBAcGFyYW0ge3N0cmluZ30gY2xhc3NOYW1lIENTUyBjbGFzcyBuYW1lLlxuICAgKi9cblxuXG4gIGZ1bmN0aW9uIFJlbmRlckJveChjbGFzc05hbWUpIHtcbiAgICB2YXIgX3RoaXMgPSBfc3VwZXIuY2FsbCh0aGlzKSB8fCB0aGlzO1xuICAgIC8qKlxuICAgICAqIEB0eXBlIHtpbXBvcnQoXCIuLi9nZW9tL1BvbHlnb24uanNcIikuZGVmYXVsdH1cbiAgICAgKiBAcHJpdmF0ZVxuICAgICAqL1xuXG5cbiAgICBfdGhpcy5nZW9tZXRyeV8gPSBudWxsO1xuICAgIC8qKlxuICAgICAqIEB0eXBlIHtIVE1MRGl2RWxlbWVudH1cbiAgICAgKiBAcHJpdmF0ZVxuICAgICAqL1xuXG4gICAgX3RoaXMuZWxlbWVudF8gPSBkb2N1bWVudC5jcmVhdGVFbGVtZW50KCdkaXYnKTtcbiAgICBfdGhpcy5lbGVtZW50Xy5zdHlsZS5wb3NpdGlvbiA9ICdhYnNvbHV0ZSc7XG4gICAgX3RoaXMuZWxlbWVudF8uc3R5bGUucG9pbnRlckV2ZW50cyA9ICdhdXRvJztcbiAgICBfdGhpcy5lbGVtZW50Xy5jbGFzc05hbWUgPSAnb2wtYm94ICcgKyBjbGFzc05hbWU7XG4gICAgLyoqXG4gICAgICogQHByaXZhdGVcbiAgICAgKiBAdHlwZSB7aW1wb3J0KFwiLi4vUGx1Z2dhYmxlTWFwLmpzXCIpLmRlZmF1bHR9XG4gICAgICovXG5cbiAgICBfdGhpcy5tYXBfID0gbnVsbDtcbiAgICAvKipcbiAgICAgKiBAcHJpdmF0ZVxuICAgICAqIEB0eXBlIHtpbXBvcnQoXCIuLi9waXhlbC5qc1wiKS5QaXhlbH1cbiAgICAgKi9cblxuICAgIF90aGlzLnN0YXJ0UGl4ZWxfID0gbnVsbDtcbiAgICAvKipcbiAgICAgKiBAcHJpdmF0ZVxuICAgICAqIEB0eXBlIHtpbXBvcnQoXCIuLi9waXhlbC5qc1wiKS5QaXhlbH1cbiAgICAgKi9cblxuICAgIF90aGlzLmVuZFBpeGVsXyA9IG51bGw7XG4gICAgcmV0dXJuIF90aGlzO1xuICB9XG4gIC8qKlxuICAgKiBDbGVhbiB1cC5cbiAgICovXG5cblxuICBSZW5kZXJCb3gucHJvdG90eXBlLmRpc3Bvc2VJbnRlcm5hbCA9IGZ1bmN0aW9uICgpIHtcbiAgICB0aGlzLnNldE1hcChudWxsKTtcbiAgfTtcbiAgLyoqXG4gICAqIEBwcml2YXRlXG4gICAqL1xuXG5cbiAgUmVuZGVyQm94LnByb3RvdHlwZS5yZW5kZXJfID0gZnVuY3Rpb24gKCkge1xuICAgIHZhciBzdGFydFBpeGVsID0gdGhpcy5zdGFydFBpeGVsXztcbiAgICB2YXIgZW5kUGl4ZWwgPSB0aGlzLmVuZFBpeGVsXztcbiAgICB2YXIgcHggPSAncHgnO1xuICAgIHZhciBzdHlsZSA9IHRoaXMuZWxlbWVudF8uc3R5bGU7XG4gICAgc3R5bGUubGVmdCA9IE1hdGgubWluKHN0YXJ0UGl4ZWxbMF0sIGVuZFBpeGVsWzBdKSArIHB4O1xuICAgIHN0eWxlLnRvcCA9IE1hdGgubWluKHN0YXJ0UGl4ZWxbMV0sIGVuZFBpeGVsWzFdKSArIHB4O1xuICAgIHN0eWxlLndpZHRoID0gTWF0aC5hYnMoZW5kUGl4ZWxbMF0gLSBzdGFydFBpeGVsWzBdKSArIHB4O1xuICAgIHN0eWxlLmhlaWdodCA9IE1hdGguYWJzKGVuZFBpeGVsWzFdIC0gc3RhcnRQaXhlbFsxXSkgKyBweDtcbiAgfTtcbiAgLyoqXG4gICAqIEBwYXJhbSB7aW1wb3J0KFwiLi4vUGx1Z2dhYmxlTWFwLmpzXCIpLmRlZmF1bHR9IG1hcCBNYXAuXG4gICAqL1xuXG5cbiAgUmVuZGVyQm94LnByb3RvdHlwZS5zZXRNYXAgPSBmdW5jdGlvbiAobWFwKSB7XG4gICAgaWYgKHRoaXMubWFwXykge1xuICAgICAgdGhpcy5tYXBfLmdldE92ZXJsYXlDb250YWluZXIoKS5yZW1vdmVDaGlsZCh0aGlzLmVsZW1lbnRfKTtcbiAgICAgIHZhciBzdHlsZSA9IHRoaXMuZWxlbWVudF8uc3R5bGU7XG4gICAgICBzdHlsZS5sZWZ0ID0gJ2luaGVyaXQnO1xuICAgICAgc3R5bGUudG9wID0gJ2luaGVyaXQnO1xuICAgICAgc3R5bGUud2lkdGggPSAnaW5oZXJpdCc7XG4gICAgICBzdHlsZS5oZWlnaHQgPSAnaW5oZXJpdCc7XG4gICAgfVxuXG4gICAgdGhpcy5tYXBfID0gbWFwO1xuXG4gICAgaWYgKHRoaXMubWFwXykge1xuICAgICAgdGhpcy5tYXBfLmdldE92ZXJsYXlDb250YWluZXIoKS5hcHBlbmRDaGlsZCh0aGlzLmVsZW1lbnRfKTtcbiAgICB9XG4gIH07XG4gIC8qKlxuICAgKiBAcGFyYW0ge2ltcG9ydChcIi4uL3BpeGVsLmpzXCIpLlBpeGVsfSBzdGFydFBpeGVsIFN0YXJ0IHBpeGVsLlxuICAgKiBAcGFyYW0ge2ltcG9ydChcIi4uL3BpeGVsLmpzXCIpLlBpeGVsfSBlbmRQaXhlbCBFbmQgcGl4ZWwuXG4gICAqL1xuXG5cbiAgUmVuZGVyQm94LnByb3RvdHlwZS5zZXRQaXhlbHMgPSBmdW5jdGlvbiAoc3RhcnRQaXhlbCwgZW5kUGl4ZWwpIHtcbiAgICB0aGlzLnN0YXJ0UGl4ZWxfID0gc3RhcnRQaXhlbDtcbiAgICB0aGlzLmVuZFBpeGVsXyA9IGVuZFBpeGVsO1xuICAgIHRoaXMuY3JlYXRlT3JVcGRhdGVHZW9tZXRyeSgpO1xuICAgIHRoaXMucmVuZGVyXygpO1xuICB9O1xuICAvKipcbiAgICogQ3JlYXRlcyBvciB1cGRhdGVzIHRoZSBjYWNoZWQgZ2VvbWV0cnkuXG4gICAqL1xuXG5cbiAgUmVuZGVyQm94LnByb3RvdHlwZS5jcmVhdGVPclVwZGF0ZUdlb21ldHJ5ID0gZnVuY3Rpb24gKCkge1xuICAgIHZhciBzdGFydFBpeGVsID0gdGhpcy5zdGFydFBpeGVsXztcbiAgICB2YXIgZW5kUGl4ZWwgPSB0aGlzLmVuZFBpeGVsXztcbiAgICB2YXIgcGl4ZWxzID0gW3N0YXJ0UGl4ZWwsIFtzdGFydFBpeGVsWzBdLCBlbmRQaXhlbFsxXV0sIGVuZFBpeGVsLCBbZW5kUGl4ZWxbMF0sIHN0YXJ0UGl4ZWxbMV1dXTtcbiAgICB2YXIgY29vcmRpbmF0ZXMgPSBwaXhlbHMubWFwKHRoaXMubWFwXy5nZXRDb29yZGluYXRlRnJvbVBpeGVsSW50ZXJuYWwsIHRoaXMubWFwXyk7IC8vIGNsb3NlIHRoZSBwb2x5Z29uXG5cbiAgICBjb29yZGluYXRlc1s0XSA9IGNvb3JkaW5hdGVzWzBdLnNsaWNlKCk7XG5cbiAgICBpZiAoIXRoaXMuZ2VvbWV0cnlfKSB7XG4gICAgICB0aGlzLmdlb21ldHJ5XyA9IG5ldyBQb2x5Z29uKFtjb29yZGluYXRlc10pO1xuICAgIH0gZWxzZSB7XG4gICAgICB0aGlzLmdlb21ldHJ5Xy5zZXRDb29yZGluYXRlcyhbY29vcmRpbmF0ZXNdKTtcbiAgICB9XG4gIH07XG4gIC8qKlxuICAgKiBAcmV0dXJuIHtpbXBvcnQoXCIuLi9nZW9tL1BvbHlnb24uanNcIikuZGVmYXVsdH0gR2VvbWV0cnkuXG4gICAqL1xuXG5cbiAgUmVuZGVyQm94LnByb3RvdHlwZS5nZXRHZW9tZXRyeSA9IGZ1bmN0aW9uICgpIHtcbiAgICByZXR1cm4gdGhpcy5nZW9tZXRyeV87XG4gIH07XG5cbiAgcmV0dXJuIFJlbmRlckJveDtcbn0oRGlzcG9zYWJsZSk7XG5cbmV4cG9ydCBkZWZhdWx0IFJlbmRlckJveDsiLCJ2YXIgX19leHRlbmRzID0gdGhpcyAmJiB0aGlzLl9fZXh0ZW5kcyB8fCBmdW5jdGlvbiAoKSB7XG4gIHZhciBfZXh0ZW5kU3RhdGljcyA9IGZ1bmN0aW9uIGV4dGVuZFN0YXRpY3MoZCwgYikge1xuICAgIF9leHRlbmRTdGF0aWNzID0gT2JqZWN0LnNldFByb3RvdHlwZU9mIHx8IHtcbiAgICAgIF9fcHJvdG9fXzogW11cbiAgICB9IGluc3RhbmNlb2YgQXJyYXkgJiYgZnVuY3Rpb24gKGQsIGIpIHtcbiAgICAgIGQuX19wcm90b19fID0gYjtcbiAgICB9IHx8IGZ1bmN0aW9uIChkLCBiKSB7XG4gICAgICBmb3IgKHZhciBwIGluIGIpIHtcbiAgICAgICAgaWYgKE9iamVjdC5wcm90b3R5cGUuaGFzT3duUHJvcGVydHkuY2FsbChiLCBwKSkgZFtwXSA9IGJbcF07XG4gICAgICB9XG4gICAgfTtcblxuICAgIHJldHVybiBfZXh0ZW5kU3RhdGljcyhkLCBiKTtcbiAgfTtcblxuICByZXR1cm4gZnVuY3Rpb24gKGQsIGIpIHtcbiAgICBfZXh0ZW5kU3RhdGljcyhkLCBiKTtcblxuICAgIGZ1bmN0aW9uIF9fKCkge1xuICAgICAgdGhpcy5jb25zdHJ1Y3RvciA9IGQ7XG4gICAgfVxuXG4gICAgZC5wcm90b3R5cGUgPSBiID09PSBudWxsID8gT2JqZWN0LmNyZWF0ZShiKSA6IChfXy5wcm90b3R5cGUgPSBiLnByb3RvdHlwZSwgbmV3IF9fKCkpO1xuICB9O1xufSgpO1xuLyoqXG4gKiBAbW9kdWxlIG9sL2ludGVyYWN0aW9uL0RyYWdCb3hcbiAqL1xuLy8gRklYTUUgZHJhdyBkcmFnIGJveFxuXG5cbmltcG9ydCBFdmVudCBmcm9tICcuLi9ldmVudHMvRXZlbnQuanMnO1xuaW1wb3J0IFBvaW50ZXJJbnRlcmFjdGlvbiBmcm9tICcuL1BvaW50ZXIuanMnO1xuaW1wb3J0IFJlbmRlckJveCBmcm9tICcuLi9yZW5kZXIvQm94LmpzJztcbmltcG9ydCB7IG1vdXNlQWN0aW9uQnV0dG9uIH0gZnJvbSAnLi4vZXZlbnRzL2NvbmRpdGlvbi5qcyc7XG4vKipcbiAqIEEgZnVuY3Rpb24gdGhhdCB0YWtlcyBhIHtAbGluayBtb2R1bGU6b2wvTWFwQnJvd3NlckV2ZW50fSBhbmQgdHdvXG4gKiB7QGxpbmsgbW9kdWxlOm9sL3BpeGVsflBpeGVsfXMgYW5kIHJldHVybnMgYSBge2Jvb2xlYW59YC4gSWYgdGhlIGNvbmRpdGlvbiBpcyBtZXQsXG4gKiB0cnVlIHNob3VsZCBiZSByZXR1cm5lZC5cbiAqIEB0eXBlZGVmIHtmdW5jdGlvbih0aGlzOiA/LCBpbXBvcnQoXCIuLi9NYXBCcm93c2VyRXZlbnQuanNcIikuZGVmYXVsdCwgaW1wb3J0KFwiLi4vcGl4ZWwuanNcIikuUGl4ZWwsIGltcG9ydChcIi4uL3BpeGVsLmpzXCIpLlBpeGVsKTpib29sZWFufSBFbmRDb25kaXRpb25cbiAqL1xuXG4vKipcbiAqIEB0eXBlZGVmIHtPYmplY3R9IE9wdGlvbnNcbiAqIEBwcm9wZXJ0eSB7c3RyaW5nfSBbY2xhc3NOYW1lPSdvbC1kcmFnYm94J10gQ1NTIGNsYXNzIG5hbWUgZm9yIHN0eWxpbmcgdGhlIGJveC5cbiAqIEBwcm9wZXJ0eSB7aW1wb3J0KFwiLi4vZXZlbnRzL2NvbmRpdGlvbi5qc1wiKS5Db25kaXRpb259IFtjb25kaXRpb25dIEEgZnVuY3Rpb24gdGhhdCB0YWtlcyBhbiB7QGxpbmsgbW9kdWxlOm9sL01hcEJyb3dzZXJFdmVudH5NYXBCcm93c2VyRXZlbnR9IGFuZCByZXR1cm5zIGEgYm9vbGVhblxuICogdG8gaW5kaWNhdGUgd2hldGhlciB0aGF0IGV2ZW50IHNob3VsZCBiZSBoYW5kbGVkLlxuICogRGVmYXVsdCBpcyB7QGxpbmsgb2wvZXZlbnRzL2NvbmRpdGlvbn5tb3VzZUFjdGlvbkJ1dHRvbn0uXG4gKiBAcHJvcGVydHkge251bWJlcn0gW21pbkFyZWE9NjRdIFRoZSBtaW5pbXVtIGFyZWEgb2YgdGhlIGJveCBpbiBwaXhlbCwgdGhpcyB2YWx1ZSBpcyB1c2VkIGJ5IHRoZSBkZWZhdWx0XG4gKiBgYm94RW5kQ29uZGl0aW9uYCBmdW5jdGlvbi5cbiAqIEBwcm9wZXJ0eSB7RW5kQ29uZGl0aW9ufSBbYm94RW5kQ29uZGl0aW9uXSBBIGZ1bmN0aW9uIHRoYXQgdGFrZXMgYSB7QGxpbmsgbW9kdWxlOm9sL01hcEJyb3dzZXJFdmVudH5NYXBCcm93c2VyRXZlbnR9IGFuZCB0d29cbiAqIHtAbGluayBtb2R1bGU6b2wvcGl4ZWx+UGl4ZWx9cyB0byBpbmRpY2F0ZSB3aGV0aGVyIGEgYGJveGVuZGAgZXZlbnQgc2hvdWxkIGJlIGZpcmVkLlxuICogRGVmYXVsdCBpcyBgdHJ1ZWAgaWYgdGhlIGFyZWEgb2YgdGhlIGJveCBpcyBiaWdnZXIgdGhhbiB0aGUgYG1pbkFyZWFgIG9wdGlvbi5cbiAqIEBwcm9wZXJ0eSB7ZnVuY3Rpb24odGhpczpEcmFnQm94LCBpbXBvcnQoXCIuLi9NYXBCcm93c2VyRXZlbnQuanNcIikuZGVmYXVsdCk6dm9pZH0gW29uQm94RW5kXSBDb2RlIHRvIGV4ZWN1dGUganVzdFxuICogYmVmb3JlIGBib3hlbmRgIGlzIGZpcmVkLlxuICovXG5cbi8qKlxuICogQGVudW0ge3N0cmluZ31cbiAqL1xuXG52YXIgRHJhZ0JveEV2ZW50VHlwZSA9IHtcbiAgLyoqXG4gICAqIFRyaWdnZXJlZCB1cG9uIGRyYWcgYm94IHN0YXJ0LlxuICAgKiBAZXZlbnQgRHJhZ0JveEV2ZW50I2JveHN0YXJ0XG4gICAqIEBhcGlcbiAgICovXG4gIEJPWFNUQVJUOiAnYm94c3RhcnQnLFxuXG4gIC8qKlxuICAgKiBUcmlnZ2VyZWQgb24gZHJhZyB3aGVuIGJveCBpcyBhY3RpdmUuXG4gICAqIEBldmVudCBEcmFnQm94RXZlbnQjYm94ZHJhZ1xuICAgKiBAYXBpXG4gICAqL1xuICBCT1hEUkFHOiAnYm94ZHJhZycsXG5cbiAgLyoqXG4gICAqIFRyaWdnZXJlZCB1cG9uIGRyYWcgYm94IGVuZC5cbiAgICogQGV2ZW50IERyYWdCb3hFdmVudCNib3hlbmRcbiAgICogQGFwaVxuICAgKi9cbiAgQk9YRU5EOiAnYm94ZW5kJyxcblxuICAvKipcbiAgICogVHJpZ2dlcmVkIHVwb24gZHJhZyBib3ggY2FuY2VsZWQuXG4gICAqIEBldmVudCBEcmFnQm94RXZlbnQjYm94Y2FuY2VsXG4gICAqIEBhcGlcbiAgICovXG4gIEJPWENBTkNFTDogJ2JveGNhbmNlbCdcbn07XG4vKipcbiAqIEBjbGFzc2Rlc2NcbiAqIEV2ZW50cyBlbWl0dGVkIGJ5IHtAbGluayBtb2R1bGU6b2wvaW50ZXJhY3Rpb24vRHJhZ0JveH5EcmFnQm94fSBpbnN0YW5jZXMgYXJlIGluc3RhbmNlcyBvZlxuICogdGhpcyB0eXBlLlxuICovXG5cbnZhciBEcmFnQm94RXZlbnQgPVxuLyoqIEBjbGFzcyAqL1xuZnVuY3Rpb24gKF9zdXBlcikge1xuICBfX2V4dGVuZHMoRHJhZ0JveEV2ZW50LCBfc3VwZXIpO1xuICAvKipcbiAgICogQHBhcmFtIHtzdHJpbmd9IHR5cGUgVGhlIGV2ZW50IHR5cGUuXG4gICAqIEBwYXJhbSB7aW1wb3J0KFwiLi4vY29vcmRpbmF0ZS5qc1wiKS5Db29yZGluYXRlfSBjb29yZGluYXRlIFRoZSBldmVudCBjb29yZGluYXRlLlxuICAgKiBAcGFyYW0ge2ltcG9ydChcIi4uL01hcEJyb3dzZXJFdmVudC5qc1wiKS5kZWZhdWx0fSBtYXBCcm93c2VyRXZlbnQgT3JpZ2luYXRpbmcgZXZlbnQuXG4gICAqL1xuXG5cbiAgZnVuY3Rpb24gRHJhZ0JveEV2ZW50KHR5cGUsIGNvb3JkaW5hdGUsIG1hcEJyb3dzZXJFdmVudCkge1xuICAgIHZhciBfdGhpcyA9IF9zdXBlci5jYWxsKHRoaXMsIHR5cGUpIHx8IHRoaXM7XG4gICAgLyoqXG4gICAgICogVGhlIGNvb3JkaW5hdGUgb2YgdGhlIGRyYWcgZXZlbnQuXG4gICAgICogQGNvbnN0XG4gICAgICogQHR5cGUge2ltcG9ydChcIi4uL2Nvb3JkaW5hdGUuanNcIikuQ29vcmRpbmF0ZX1cbiAgICAgKiBAYXBpXG4gICAgICovXG5cblxuICAgIF90aGlzLmNvb3JkaW5hdGUgPSBjb29yZGluYXRlO1xuICAgIC8qKlxuICAgICAqIEBjb25zdFxuICAgICAqIEB0eXBlIHtpbXBvcnQoXCIuLi9NYXBCcm93c2VyRXZlbnQuanNcIikuZGVmYXVsdH1cbiAgICAgKiBAYXBpXG4gICAgICovXG5cbiAgICBfdGhpcy5tYXBCcm93c2VyRXZlbnQgPSBtYXBCcm93c2VyRXZlbnQ7XG4gICAgcmV0dXJuIF90aGlzO1xuICB9XG5cbiAgcmV0dXJuIERyYWdCb3hFdmVudDtcbn0oRXZlbnQpO1xuXG5leHBvcnQgeyBEcmFnQm94RXZlbnQgfTtcbi8qKlxuICogQGNsYXNzZGVzY1xuICogQWxsb3dzIHRoZSB1c2VyIHRvIGRyYXcgYSB2ZWN0b3IgYm94IGJ5IGNsaWNraW5nIGFuZCBkcmFnZ2luZyBvbiB0aGUgbWFwLFxuICogbm9ybWFsbHkgY29tYmluZWQgd2l0aCBhbiB7QGxpbmsgbW9kdWxlOm9sL2V2ZW50cy9jb25kaXRpb259IHRoYXQgbGltaXRzXG4gKiBpdCB0byB3aGVuIHRoZSBzaGlmdCBvciBvdGhlciBrZXkgaXMgaGVsZCBkb3duLiBUaGlzIGlzIHVzZWQsIGZvciBleGFtcGxlLFxuICogZm9yIHpvb21pbmcgdG8gYSBzcGVjaWZpYyBhcmVhIG9mIHRoZSBtYXBcbiAqIChzZWUge0BsaW5rIG1vZHVsZTpvbC9pbnRlcmFjdGlvbi9EcmFnWm9vbX5EcmFnWm9vbX0gYW5kXG4gKiB7QGxpbmsgbW9kdWxlOm9sL2ludGVyYWN0aW9uL0RyYWdSb3RhdGVBbmRab29tfSkuXG4gKlxuICogQGZpcmVzIERyYWdCb3hFdmVudFxuICogQGFwaVxuICovXG5cbnZhciBEcmFnQm94ID1cbi8qKiBAY2xhc3MgKi9cbmZ1bmN0aW9uIChfc3VwZXIpIHtcbiAgX19leHRlbmRzKERyYWdCb3gsIF9zdXBlcik7XG4gIC8qKlxuICAgKiBAcGFyYW0ge09wdGlvbnM9fSBvcHRfb3B0aW9ucyBPcHRpb25zLlxuICAgKi9cblxuXG4gIGZ1bmN0aW9uIERyYWdCb3gob3B0X29wdGlvbnMpIHtcbiAgICB2YXIgX3RoaXMgPSBfc3VwZXIuY2FsbCh0aGlzKSB8fCB0aGlzO1xuXG4gICAgdmFyIG9wdGlvbnMgPSBvcHRfb3B0aW9ucyA/IG9wdF9vcHRpb25zIDoge307XG4gICAgLyoqXG4gICAgICogQHR5cGUge2ltcG9ydChcIi4uL3JlbmRlci9Cb3guanNcIikuZGVmYXVsdH1cbiAgICAgKiBAcHJpdmF0ZVxuICAgICAqL1xuXG4gICAgX3RoaXMuYm94XyA9IG5ldyBSZW5kZXJCb3gob3B0aW9ucy5jbGFzc05hbWUgfHwgJ29sLWRyYWdib3gnKTtcbiAgICAvKipcbiAgICAgKiBAdHlwZSB7bnVtYmVyfVxuICAgICAqIEBwcml2YXRlXG4gICAgICovXG5cbiAgICBfdGhpcy5taW5BcmVhXyA9IG9wdGlvbnMubWluQXJlYSAhPT0gdW5kZWZpbmVkID8gb3B0aW9ucy5taW5BcmVhIDogNjQ7XG5cbiAgICBpZiAob3B0aW9ucy5vbkJveEVuZCkge1xuICAgICAgX3RoaXMub25Cb3hFbmQgPSBvcHRpb25zLm9uQm94RW5kO1xuICAgIH1cbiAgICAvKipcbiAgICAgKiBAdHlwZSB7aW1wb3J0KFwiLi4vcGl4ZWwuanNcIikuUGl4ZWx9XG4gICAgICogQHByaXZhdGVcbiAgICAgKi9cblxuXG4gICAgX3RoaXMuc3RhcnRQaXhlbF8gPSBudWxsO1xuICAgIC8qKlxuICAgICAqIEBwcml2YXRlXG4gICAgICogQHR5cGUge2ltcG9ydChcIi4uL2V2ZW50cy9jb25kaXRpb24uanNcIikuQ29uZGl0aW9ufVxuICAgICAqL1xuXG4gICAgX3RoaXMuY29uZGl0aW9uXyA9IG9wdGlvbnMuY29uZGl0aW9uID8gb3B0aW9ucy5jb25kaXRpb24gOiBtb3VzZUFjdGlvbkJ1dHRvbjtcbiAgICAvKipcbiAgICAgKiBAcHJpdmF0ZVxuICAgICAqIEB0eXBlIHtFbmRDb25kaXRpb259XG4gICAgICovXG5cbiAgICBfdGhpcy5ib3hFbmRDb25kaXRpb25fID0gb3B0aW9ucy5ib3hFbmRDb25kaXRpb24gPyBvcHRpb25zLmJveEVuZENvbmRpdGlvbiA6IF90aGlzLmRlZmF1bHRCb3hFbmRDb25kaXRpb247XG4gICAgcmV0dXJuIF90aGlzO1xuICB9XG4gIC8qKlxuICAgKiBUaGUgZGVmYXVsdCBjb25kaXRpb24gZm9yIGRldGVybWluaW5nIHdoZXRoZXIgdGhlIGJveGVuZCBldmVudFxuICAgKiBzaG91bGQgZmlyZS5cbiAgICogQHBhcmFtIHtpbXBvcnQoXCIuLi9NYXBCcm93c2VyRXZlbnQuanNcIikuZGVmYXVsdH0gbWFwQnJvd3NlckV2ZW50IFRoZSBvcmlnaW5hdGluZyBNYXBCcm93c2VyRXZlbnRcbiAgICogICAgIGxlYWRpbmcgdG8gdGhlIGJveCBlbmQuXG4gICAqIEBwYXJhbSB7aW1wb3J0KFwiLi4vcGl4ZWwuanNcIikuUGl4ZWx9IHN0YXJ0UGl4ZWwgVGhlIHN0YXJ0aW5nIHBpeGVsIG9mIHRoZSBib3guXG4gICAqIEBwYXJhbSB7aW1wb3J0KFwiLi4vcGl4ZWwuanNcIikuUGl4ZWx9IGVuZFBpeGVsIFRoZSBlbmQgcGl4ZWwgb2YgdGhlIGJveC5cbiAgICogQHJldHVybiB7Ym9vbGVhbn0gV2hldGhlciBvciBub3QgdGhlIGJveGVuZCBjb25kaXRpb24gc2hvdWxkIGJlIGZpcmVkLlxuICAgKi9cblxuXG4gIERyYWdCb3gucHJvdG90eXBlLmRlZmF1bHRCb3hFbmRDb25kaXRpb24gPSBmdW5jdGlvbiAobWFwQnJvd3NlckV2ZW50LCBzdGFydFBpeGVsLCBlbmRQaXhlbCkge1xuICAgIHZhciB3aWR0aCA9IGVuZFBpeGVsWzBdIC0gc3RhcnRQaXhlbFswXTtcbiAgICB2YXIgaGVpZ2h0ID0gZW5kUGl4ZWxbMV0gLSBzdGFydFBpeGVsWzFdO1xuICAgIHJldHVybiB3aWR0aCAqIHdpZHRoICsgaGVpZ2h0ICogaGVpZ2h0ID49IHRoaXMubWluQXJlYV87XG4gIH07XG4gIC8qKlxuICAgKiBSZXR1cm5zIGdlb21ldHJ5IG9mIGxhc3QgZHJhd24gYm94LlxuICAgKiBAcmV0dXJuIHtpbXBvcnQoXCIuLi9nZW9tL1BvbHlnb24uanNcIikuZGVmYXVsdH0gR2VvbWV0cnkuXG4gICAqIEBhcGlcbiAgICovXG5cblxuICBEcmFnQm94LnByb3RvdHlwZS5nZXRHZW9tZXRyeSA9IGZ1bmN0aW9uICgpIHtcbiAgICByZXR1cm4gdGhpcy5ib3hfLmdldEdlb21ldHJ5KCk7XG4gIH07XG4gIC8qKlxuICAgKiBIYW5kbGUgcG9pbnRlciBkcmFnIGV2ZW50cy5cbiAgICogQHBhcmFtIHtpbXBvcnQoXCIuLi9NYXBCcm93c2VyRXZlbnQuanNcIikuZGVmYXVsdH0gbWFwQnJvd3NlckV2ZW50IEV2ZW50LlxuICAgKi9cblxuXG4gIERyYWdCb3gucHJvdG90eXBlLmhhbmRsZURyYWdFdmVudCA9IGZ1bmN0aW9uIChtYXBCcm93c2VyRXZlbnQpIHtcbiAgICB0aGlzLmJveF8uc2V0UGl4ZWxzKHRoaXMuc3RhcnRQaXhlbF8sIG1hcEJyb3dzZXJFdmVudC5waXhlbCk7XG4gICAgdGhpcy5kaXNwYXRjaEV2ZW50KG5ldyBEcmFnQm94RXZlbnQoRHJhZ0JveEV2ZW50VHlwZS5CT1hEUkFHLCBtYXBCcm93c2VyRXZlbnQuY29vcmRpbmF0ZSwgbWFwQnJvd3NlckV2ZW50KSk7XG4gIH07XG4gIC8qKlxuICAgKiBIYW5kbGUgcG9pbnRlciB1cCBldmVudHMuXG4gICAqIEBwYXJhbSB7aW1wb3J0KFwiLi4vTWFwQnJvd3NlckV2ZW50LmpzXCIpLmRlZmF1bHR9IG1hcEJyb3dzZXJFdmVudCBFdmVudC5cbiAgICogQHJldHVybiB7Ym9vbGVhbn0gSWYgdGhlIGV2ZW50IHdhcyBjb25zdW1lZC5cbiAgICovXG5cblxuICBEcmFnQm94LnByb3RvdHlwZS5oYW5kbGVVcEV2ZW50ID0gZnVuY3Rpb24gKG1hcEJyb3dzZXJFdmVudCkge1xuICAgIHRoaXMuYm94Xy5zZXRNYXAobnVsbCk7XG4gICAgdmFyIGNvbXBsZXRlQm94ID0gdGhpcy5ib3hFbmRDb25kaXRpb25fKG1hcEJyb3dzZXJFdmVudCwgdGhpcy5zdGFydFBpeGVsXywgbWFwQnJvd3NlckV2ZW50LnBpeGVsKTtcblxuICAgIGlmIChjb21wbGV0ZUJveCkge1xuICAgICAgdGhpcy5vbkJveEVuZChtYXBCcm93c2VyRXZlbnQpO1xuICAgIH1cblxuICAgIHRoaXMuZGlzcGF0Y2hFdmVudChuZXcgRHJhZ0JveEV2ZW50KGNvbXBsZXRlQm94ID8gRHJhZ0JveEV2ZW50VHlwZS5CT1hFTkQgOiBEcmFnQm94RXZlbnRUeXBlLkJPWENBTkNFTCwgbWFwQnJvd3NlckV2ZW50LmNvb3JkaW5hdGUsIG1hcEJyb3dzZXJFdmVudCkpO1xuICAgIHJldHVybiBmYWxzZTtcbiAgfTtcbiAgLyoqXG4gICAqIEhhbmRsZSBwb2ludGVyIGRvd24gZXZlbnRzLlxuICAgKiBAcGFyYW0ge2ltcG9ydChcIi4uL01hcEJyb3dzZXJFdmVudC5qc1wiKS5kZWZhdWx0fSBtYXBCcm93c2VyRXZlbnQgRXZlbnQuXG4gICAqIEByZXR1cm4ge2Jvb2xlYW59IElmIHRoZSBldmVudCB3YXMgY29uc3VtZWQuXG4gICAqL1xuXG5cbiAgRHJhZ0JveC5wcm90b3R5cGUuaGFuZGxlRG93bkV2ZW50ID0gZnVuY3Rpb24gKG1hcEJyb3dzZXJFdmVudCkge1xuICAgIGlmICh0aGlzLmNvbmRpdGlvbl8obWFwQnJvd3NlckV2ZW50KSkge1xuICAgICAgdGhpcy5zdGFydFBpeGVsXyA9IG1hcEJyb3dzZXJFdmVudC5waXhlbDtcbiAgICAgIHRoaXMuYm94Xy5zZXRNYXAobWFwQnJvd3NlckV2ZW50Lm1hcCk7XG4gICAgICB0aGlzLmJveF8uc2V0UGl4ZWxzKHRoaXMuc3RhcnRQaXhlbF8sIHRoaXMuc3RhcnRQaXhlbF8pO1xuICAgICAgdGhpcy5kaXNwYXRjaEV2ZW50KG5ldyBEcmFnQm94RXZlbnQoRHJhZ0JveEV2ZW50VHlwZS5CT1hTVEFSVCwgbWFwQnJvd3NlckV2ZW50LmNvb3JkaW5hdGUsIG1hcEJyb3dzZXJFdmVudCkpO1xuICAgICAgcmV0dXJuIHRydWU7XG4gICAgfSBlbHNlIHtcbiAgICAgIHJldHVybiBmYWxzZTtcbiAgICB9XG4gIH07XG4gIC8qKlxuICAgKiBGdW5jdGlvbiB0byBleGVjdXRlIGp1c3QgYmVmb3JlIGBvbmJveGVuZGAgaXMgZmlyZWRcbiAgICogQHBhcmFtIHtpbXBvcnQoXCIuLi9NYXBCcm93c2VyRXZlbnQuanNcIikuZGVmYXVsdH0gZXZlbnQgRXZlbnQuXG4gICAqL1xuXG5cbiAgRHJhZ0JveC5wcm90b3R5cGUub25Cb3hFbmQgPSBmdW5jdGlvbiAoZXZlbnQpIHt9O1xuXG4gIHJldHVybiBEcmFnQm94O1xufShQb2ludGVySW50ZXJhY3Rpb24pO1xuXG5leHBvcnQgZGVmYXVsdCBEcmFnQm94OyIsInZhciBfX2V4dGVuZHMgPSB0aGlzICYmIHRoaXMuX19leHRlbmRzIHx8IGZ1bmN0aW9uICgpIHtcbiAgdmFyIF9leHRlbmRTdGF0aWNzID0gZnVuY3Rpb24gZXh0ZW5kU3RhdGljcyhkLCBiKSB7XG4gICAgX2V4dGVuZFN0YXRpY3MgPSBPYmplY3Quc2V0UHJvdG90eXBlT2YgfHwge1xuICAgICAgX19wcm90b19fOiBbXVxuICAgIH0gaW5zdGFuY2VvZiBBcnJheSAmJiBmdW5jdGlvbiAoZCwgYikge1xuICAgICAgZC5fX3Byb3RvX18gPSBiO1xuICAgIH0gfHwgZnVuY3Rpb24gKGQsIGIpIHtcbiAgICAgIGZvciAodmFyIHAgaW4gYikge1xuICAgICAgICBpZiAoT2JqZWN0LnByb3RvdHlwZS5oYXNPd25Qcm9wZXJ0eS5jYWxsKGIsIHApKSBkW3BdID0gYltwXTtcbiAgICAgIH1cbiAgICB9O1xuXG4gICAgcmV0dXJuIF9leHRlbmRTdGF0aWNzKGQsIGIpO1xuICB9O1xuXG4gIHJldHVybiBmdW5jdGlvbiAoZCwgYikge1xuICAgIF9leHRlbmRTdGF0aWNzKGQsIGIpO1xuXG4gICAgZnVuY3Rpb24gX18oKSB7XG4gICAgICB0aGlzLmNvbnN0cnVjdG9yID0gZDtcbiAgICB9XG5cbiAgICBkLnByb3RvdHlwZSA9IGIgPT09IG51bGwgPyBPYmplY3QuY3JlYXRlKGIpIDogKF9fLnByb3RvdHlwZSA9IGIucHJvdG90eXBlLCBuZXcgX18oKSk7XG4gIH07XG59KCk7XG4vKipcbiAqIEBtb2R1bGUgb2wvaW50ZXJhY3Rpb24vRHJhZ1pvb21cbiAqL1xuXG5cbmltcG9ydCBEcmFnQm94IGZyb20gJy4vRHJhZ0JveC5qcyc7XG5pbXBvcnQgeyBjcmVhdGVPclVwZGF0ZUZyb21Db29yZGluYXRlcywgZ2V0Qm90dG9tTGVmdCwgZ2V0Q2VudGVyLCBnZXRUb3BSaWdodCwgc2NhbGVGcm9tQ2VudGVyIH0gZnJvbSAnLi4vZXh0ZW50LmpzJztcbmltcG9ydCB7IGVhc2VPdXQgfSBmcm9tICcuLi9lYXNpbmcuanMnO1xuaW1wb3J0IHsgc2hpZnRLZXlPbmx5IH0gZnJvbSAnLi4vZXZlbnRzL2NvbmRpdGlvbi5qcyc7XG4vKipcbiAqIEB0eXBlZGVmIHtPYmplY3R9IE9wdGlvbnNcbiAqIEBwcm9wZXJ0eSB7c3RyaW5nfSBbY2xhc3NOYW1lPSdvbC1kcmFnem9vbSddIENTUyBjbGFzcyBuYW1lIGZvciBzdHlsaW5nIHRoZVxuICogYm94LlxuICogQHByb3BlcnR5IHtpbXBvcnQoXCIuLi9ldmVudHMvY29uZGl0aW9uLmpzXCIpLkNvbmRpdGlvbn0gW2NvbmRpdGlvbl0gQSBmdW5jdGlvbiB0aGF0XG4gKiB0YWtlcyBhbiB7QGxpbmsgbW9kdWxlOm9sL01hcEJyb3dzZXJFdmVudH5NYXBCcm93c2VyRXZlbnR9IGFuZCByZXR1cm5zIGFcbiAqIGJvb2xlYW4gdG8gaW5kaWNhdGUgd2hldGhlciB0aGF0IGV2ZW50IHNob3VsZCBiZSBoYW5kbGVkLlxuICogRGVmYXVsdCBpcyB7QGxpbmsgbW9kdWxlOm9sL2V2ZW50cy9jb25kaXRpb25+c2hpZnRLZXlPbmx5fS5cbiAqIEBwcm9wZXJ0eSB7bnVtYmVyfSBbZHVyYXRpb249MjAwXSBBbmltYXRpb24gZHVyYXRpb24gaW4gbWlsbGlzZWNvbmRzLlxuICogQHByb3BlcnR5IHtib29sZWFufSBbb3V0PWZhbHNlXSBVc2UgaW50ZXJhY3Rpb24gZm9yIHpvb21pbmcgb3V0LlxuICogQHByb3BlcnR5IHtudW1iZXJ9IFttaW5BcmVhPTY0XSBUaGUgbWluaW11bSBhcmVhIG9mIHRoZSBib3ggaW4gcGl4ZWwsIHRoaXMgdmFsdWUgaXMgdXNlZCBieSB0aGUgcGFyZW50IGRlZmF1bHRcbiAqIGBib3hFbmRDb25kaXRpb25gIGZ1bmN0aW9uLlxuICovXG5cbi8qKlxuICogQGNsYXNzZGVzY1xuICogQWxsb3dzIHRoZSB1c2VyIHRvIHpvb20gdGhlIG1hcCBieSBjbGlja2luZyBhbmQgZHJhZ2dpbmcgb24gdGhlIG1hcCxcbiAqIG5vcm1hbGx5IGNvbWJpbmVkIHdpdGggYW4ge0BsaW5rIG1vZHVsZTpvbC9ldmVudHMvY29uZGl0aW9ufSB0aGF0IGxpbWl0c1xuICogaXQgdG8gd2hlbiBhIGtleSwgc2hpZnQgYnkgZGVmYXVsdCwgaXMgaGVsZCBkb3duLlxuICpcbiAqIFRvIGNoYW5nZSB0aGUgc3R5bGUgb2YgdGhlIGJveCwgdXNlIENTUyBhbmQgdGhlIGAub2wtZHJhZ3pvb21gIHNlbGVjdG9yLCBvclxuICogeW91ciBjdXN0b20gb25lIGNvbmZpZ3VyZWQgd2l0aCBgY2xhc3NOYW1lYC5cbiAqIEBhcGlcbiAqL1xuXG52YXIgRHJhZ1pvb20gPVxuLyoqIEBjbGFzcyAqL1xuZnVuY3Rpb24gKF9zdXBlcikge1xuICBfX2V4dGVuZHMoRHJhZ1pvb20sIF9zdXBlcik7XG4gIC8qKlxuICAgKiBAcGFyYW0ge09wdGlvbnM9fSBvcHRfb3B0aW9ucyBPcHRpb25zLlxuICAgKi9cblxuXG4gIGZ1bmN0aW9uIERyYWdab29tKG9wdF9vcHRpb25zKSB7XG4gICAgdmFyIF90aGlzID0gdGhpcztcblxuICAgIHZhciBvcHRpb25zID0gb3B0X29wdGlvbnMgPyBvcHRfb3B0aW9ucyA6IHt9O1xuICAgIHZhciBjb25kaXRpb24gPSBvcHRpb25zLmNvbmRpdGlvbiA/IG9wdGlvbnMuY29uZGl0aW9uIDogc2hpZnRLZXlPbmx5O1xuICAgIF90aGlzID0gX3N1cGVyLmNhbGwodGhpcywge1xuICAgICAgY29uZGl0aW9uOiBjb25kaXRpb24sXG4gICAgICBjbGFzc05hbWU6IG9wdGlvbnMuY2xhc3NOYW1lIHx8ICdvbC1kcmFnem9vbScsXG4gICAgICBtaW5BcmVhOiBvcHRpb25zLm1pbkFyZWFcbiAgICB9KSB8fCB0aGlzO1xuICAgIC8qKlxuICAgICAqIEBwcml2YXRlXG4gICAgICogQHR5cGUge251bWJlcn1cbiAgICAgKi9cblxuICAgIF90aGlzLmR1cmF0aW9uXyA9IG9wdGlvbnMuZHVyYXRpb24gIT09IHVuZGVmaW5lZCA/IG9wdGlvbnMuZHVyYXRpb24gOiAyMDA7XG4gICAgLyoqXG4gICAgICogQHByaXZhdGVcbiAgICAgKiBAdHlwZSB7Ym9vbGVhbn1cbiAgICAgKi9cblxuICAgIF90aGlzLm91dF8gPSBvcHRpb25zLm91dCAhPT0gdW5kZWZpbmVkID8gb3B0aW9ucy5vdXQgOiBmYWxzZTtcbiAgICByZXR1cm4gX3RoaXM7XG4gIH1cbiAgLyoqXG4gICAqIEZ1bmN0aW9uIHRvIGV4ZWN1dGUganVzdCBiZWZvcmUgYG9uYm94ZW5kYCBpcyBmaXJlZFxuICAgKiBAcGFyYW0ge2ltcG9ydChcIi4uL01hcEJyb3dzZXJFdmVudC5qc1wiKS5kZWZhdWx0fSBldmVudCBFdmVudC5cbiAgICovXG5cblxuICBEcmFnWm9vbS5wcm90b3R5cGUub25Cb3hFbmQgPSBmdW5jdGlvbiAoZXZlbnQpIHtcbiAgICB2YXIgbWFwID0gdGhpcy5nZXRNYXAoKTtcbiAgICB2YXIgdmlldyA9XG4gICAgLyoqIEB0eXBlIHshaW1wb3J0KFwiLi4vVmlldy5qc1wiKS5kZWZhdWx0fSAqL1xuICAgIG1hcC5nZXRWaWV3KCk7XG4gICAgdmFyIHNpemUgPVxuICAgIC8qKiBAdHlwZSB7IWltcG9ydChcIi4uL3NpemUuanNcIikuU2l6ZX0gKi9cbiAgICBtYXAuZ2V0U2l6ZSgpO1xuICAgIHZhciBleHRlbnQgPSB0aGlzLmdldEdlb21ldHJ5KCkuZ2V0RXh0ZW50KCk7XG5cbiAgICBpZiAodGhpcy5vdXRfKSB7XG4gICAgICB2YXIgbWFwRXh0ZW50ID0gdmlldy5jYWxjdWxhdGVFeHRlbnRJbnRlcm5hbChzaXplKTtcbiAgICAgIHZhciBib3hQaXhlbEV4dGVudCA9IGNyZWF0ZU9yVXBkYXRlRnJvbUNvb3JkaW5hdGVzKFttYXAuZ2V0UGl4ZWxGcm9tQ29vcmRpbmF0ZUludGVybmFsKGdldEJvdHRvbUxlZnQoZXh0ZW50KSksIG1hcC5nZXRQaXhlbEZyb21Db29yZGluYXRlSW50ZXJuYWwoZ2V0VG9wUmlnaHQoZXh0ZW50KSldKTtcbiAgICAgIHZhciBmYWN0b3IgPSB2aWV3LmdldFJlc29sdXRpb25Gb3JFeHRlbnRJbnRlcm5hbChib3hQaXhlbEV4dGVudCwgc2l6ZSk7XG4gICAgICBzY2FsZUZyb21DZW50ZXIobWFwRXh0ZW50LCAxIC8gZmFjdG9yKTtcbiAgICAgIGV4dGVudCA9IG1hcEV4dGVudDtcbiAgICB9XG5cbiAgICB2YXIgcmVzb2x1dGlvbiA9IHZpZXcuZ2V0Q29uc3RyYWluZWRSZXNvbHV0aW9uKHZpZXcuZ2V0UmVzb2x1dGlvbkZvckV4dGVudEludGVybmFsKGV4dGVudCwgc2l6ZSkpO1xuICAgIHZhciBjZW50ZXIgPSB2aWV3LmdldENvbnN0cmFpbmVkQ2VudGVyKGdldENlbnRlcihleHRlbnQpLCByZXNvbHV0aW9uKTtcbiAgICB2aWV3LmFuaW1hdGVJbnRlcm5hbCh7XG4gICAgICByZXNvbHV0aW9uOiByZXNvbHV0aW9uLFxuICAgICAgY2VudGVyOiBjZW50ZXIsXG4gICAgICBkdXJhdGlvbjogdGhpcy5kdXJhdGlvbl8sXG4gICAgICBlYXNpbmc6IGVhc2VPdXRcbiAgICB9KTtcbiAgfTtcblxuICByZXR1cm4gRHJhZ1pvb207XG59KERyYWdCb3gpO1xuXG5leHBvcnQgZGVmYXVsdCBEcmFnWm9vbTsiLCIvKipcbiAqIEBtb2R1bGUgb2wvZXZlbnRzL0tleUNvZGVcbiAqL1xuXG4vKipcbiAqIEBlbnVtIHtudW1iZXJ9XG4gKiBAY29uc3RcbiAqL1xuZXhwb3J0IGRlZmF1bHQge1xuICBMRUZUOiAzNyxcbiAgVVA6IDM4LFxuICBSSUdIVDogMzksXG4gIERPV046IDQwXG59OyIsInZhciBfX2V4dGVuZHMgPSB0aGlzICYmIHRoaXMuX19leHRlbmRzIHx8IGZ1bmN0aW9uICgpIHtcbiAgdmFyIF9leHRlbmRTdGF0aWNzID0gZnVuY3Rpb24gZXh0ZW5kU3RhdGljcyhkLCBiKSB7XG4gICAgX2V4dGVuZFN0YXRpY3MgPSBPYmplY3Quc2V0UHJvdG90eXBlT2YgfHwge1xuICAgICAgX19wcm90b19fOiBbXVxuICAgIH0gaW5zdGFuY2VvZiBBcnJheSAmJiBmdW5jdGlvbiAoZCwgYikge1xuICAgICAgZC5fX3Byb3RvX18gPSBiO1xuICAgIH0gfHwgZnVuY3Rpb24gKGQsIGIpIHtcbiAgICAgIGZvciAodmFyIHAgaW4gYikge1xuICAgICAgICBpZiAoT2JqZWN0LnByb3RvdHlwZS5oYXNPd25Qcm9wZXJ0eS5jYWxsKGIsIHApKSBkW3BdID0gYltwXTtcbiAgICAgIH1cbiAgICB9O1xuXG4gICAgcmV0dXJuIF9leHRlbmRTdGF0aWNzKGQsIGIpO1xuICB9O1xuXG4gIHJldHVybiBmdW5jdGlvbiAoZCwgYikge1xuICAgIF9leHRlbmRTdGF0aWNzKGQsIGIpO1xuXG4gICAgZnVuY3Rpb24gX18oKSB7XG4gICAgICB0aGlzLmNvbnN0cnVjdG9yID0gZDtcbiAgICB9XG5cbiAgICBkLnByb3RvdHlwZSA9IGIgPT09IG51bGwgPyBPYmplY3QuY3JlYXRlKGIpIDogKF9fLnByb3RvdHlwZSA9IGIucHJvdG90eXBlLCBuZXcgX18oKSk7XG4gIH07XG59KCk7XG4vKipcbiAqIEBtb2R1bGUgb2wvaW50ZXJhY3Rpb24vS2V5Ym9hcmRQYW5cbiAqL1xuXG5cbmltcG9ydCBFdmVudFR5cGUgZnJvbSAnLi4vZXZlbnRzL0V2ZW50VHlwZS5qcyc7XG5pbXBvcnQgSW50ZXJhY3Rpb24sIHsgcGFuIH0gZnJvbSAnLi9JbnRlcmFjdGlvbi5qcyc7XG5pbXBvcnQgS2V5Q29kZSBmcm9tICcuLi9ldmVudHMvS2V5Q29kZS5qcyc7XG5pbXBvcnQgeyBub01vZGlmaWVyS2V5cywgdGFyZ2V0Tm90RWRpdGFibGUgfSBmcm9tICcuLi9ldmVudHMvY29uZGl0aW9uLmpzJztcbmltcG9ydCB7IHJvdGF0ZSBhcyByb3RhdGVDb29yZGluYXRlIH0gZnJvbSAnLi4vY29vcmRpbmF0ZS5qcyc7XG4vKipcbiAqIEB0eXBlZGVmIHtPYmplY3R9IE9wdGlvbnNcbiAqIEBwcm9wZXJ0eSB7aW1wb3J0KFwiLi4vZXZlbnRzL2NvbmRpdGlvbi5qc1wiKS5Db25kaXRpb259IFtjb25kaXRpb25dIEEgZnVuY3Rpb24gdGhhdFxuICogdGFrZXMgYW4ge0BsaW5rIG1vZHVsZTpvbC9NYXBCcm93c2VyRXZlbnR+TWFwQnJvd3NlckV2ZW50fSBhbmQgcmV0dXJucyBhXG4gKiBib29sZWFuIHRvIGluZGljYXRlIHdoZXRoZXIgdGhhdCBldmVudCBzaG91bGQgYmUgaGFuZGxlZC4gRGVmYXVsdCBpc1xuICoge0BsaW5rIG1vZHVsZTpvbC9ldmVudHMvY29uZGl0aW9ufm5vTW9kaWZpZXJLZXlzfSBhbmRcbiAqIHtAbGluayBtb2R1bGU6b2wvZXZlbnRzL2NvbmRpdGlvbn50YXJnZXROb3RFZGl0YWJsZX0uXG4gKiBAcHJvcGVydHkge251bWJlcn0gW2R1cmF0aW9uPTEwMF0gQW5pbWF0aW9uIGR1cmF0aW9uIGluIG1pbGxpc2Vjb25kcy5cbiAqIEBwcm9wZXJ0eSB7bnVtYmVyfSBbcGl4ZWxEZWx0YT0xMjhdIFRoZSBhbW91bnQgb2YgcGl4ZWxzIHRvIHBhbiBvbiBlYWNoIGtleVxuICogcHJlc3MuXG4gKi9cblxuLyoqXG4gKiBAY2xhc3NkZXNjXG4gKiBBbGxvd3MgdGhlIHVzZXIgdG8gcGFuIHRoZSBtYXAgdXNpbmcga2V5Ym9hcmQgYXJyb3dzLlxuICogTm90ZSB0aGF0LCBhbHRob3VnaCB0aGlzIGludGVyYWN0aW9uIGlzIGJ5IGRlZmF1bHQgaW5jbHVkZWQgaW4gbWFwcyxcbiAqIHRoZSBrZXlzIGNhbiBvbmx5IGJlIHVzZWQgd2hlbiBicm93c2VyIGZvY3VzIGlzIG9uIHRoZSBlbGVtZW50IHRvIHdoaWNoXG4gKiB0aGUga2V5Ym9hcmQgZXZlbnRzIGFyZSBhdHRhY2hlZC4gQnkgZGVmYXVsdCwgdGhpcyBpcyB0aGUgbWFwIGRpdixcbiAqIHRob3VnaCB5b3UgY2FuIGNoYW5nZSB0aGlzIHdpdGggdGhlIGBrZXlib2FyZEV2ZW50VGFyZ2V0YCBpblxuICoge0BsaW5rIG1vZHVsZTpvbC9NYXB+TWFwfS4gYGRvY3VtZW50YCBuZXZlciBsb3NlcyBmb2N1cyBidXQsIGZvciBhbnkgb3RoZXJcbiAqIGVsZW1lbnQsIGZvY3VzIHdpbGwgaGF2ZSB0byBiZSBvbiwgYW5kIHJldHVybmVkIHRvLCB0aGlzIGVsZW1lbnQgaWYgdGhlIGtleXNcbiAqIGFyZSB0byBmdW5jdGlvbi5cbiAqIFNlZSBhbHNvIHtAbGluayBtb2R1bGU6b2wvaW50ZXJhY3Rpb24vS2V5Ym9hcmRab29tfktleWJvYXJkWm9vbX0uXG4gKiBAYXBpXG4gKi9cblxudmFyIEtleWJvYXJkUGFuID1cbi8qKiBAY2xhc3MgKi9cbmZ1bmN0aW9uIChfc3VwZXIpIHtcbiAgX19leHRlbmRzKEtleWJvYXJkUGFuLCBfc3VwZXIpO1xuICAvKipcbiAgICogQHBhcmFtIHtPcHRpb25zPX0gb3B0X29wdGlvbnMgT3B0aW9ucy5cbiAgICovXG5cblxuICBmdW5jdGlvbiBLZXlib2FyZFBhbihvcHRfb3B0aW9ucykge1xuICAgIHZhciBfdGhpcyA9IF9zdXBlci5jYWxsKHRoaXMpIHx8IHRoaXM7XG5cbiAgICB2YXIgb3B0aW9ucyA9IG9wdF9vcHRpb25zIHx8IHt9O1xuICAgIC8qKlxuICAgICAqIEBwcml2YXRlXG4gICAgICogQHBhcmFtIHtpbXBvcnQoXCIuLi9NYXBCcm93c2VyRXZlbnQuanNcIikuZGVmYXVsdH0gbWFwQnJvd3NlckV2ZW50IEJyb3dzZXIgZXZlbnQuXG4gICAgICogQHJldHVybiB7Ym9vbGVhbn0gQ29tYmluZWQgY29uZGl0aW9uIHJlc3VsdC5cbiAgICAgKi9cblxuICAgIF90aGlzLmRlZmF1bHRDb25kaXRpb25fID0gZnVuY3Rpb24gKG1hcEJyb3dzZXJFdmVudCkge1xuICAgICAgcmV0dXJuIG5vTW9kaWZpZXJLZXlzKG1hcEJyb3dzZXJFdmVudCkgJiYgdGFyZ2V0Tm90RWRpdGFibGUobWFwQnJvd3NlckV2ZW50KTtcbiAgICB9O1xuICAgIC8qKlxuICAgICAqIEBwcml2YXRlXG4gICAgICogQHR5cGUge2ltcG9ydChcIi4uL2V2ZW50cy9jb25kaXRpb24uanNcIikuQ29uZGl0aW9ufVxuICAgICAqL1xuXG5cbiAgICBfdGhpcy5jb25kaXRpb25fID0gb3B0aW9ucy5jb25kaXRpb24gIT09IHVuZGVmaW5lZCA/IG9wdGlvbnMuY29uZGl0aW9uIDogX3RoaXMuZGVmYXVsdENvbmRpdGlvbl87XG4gICAgLyoqXG4gICAgICogQHByaXZhdGVcbiAgICAgKiBAdHlwZSB7bnVtYmVyfVxuICAgICAqL1xuXG4gICAgX3RoaXMuZHVyYXRpb25fID0gb3B0aW9ucy5kdXJhdGlvbiAhPT0gdW5kZWZpbmVkID8gb3B0aW9ucy5kdXJhdGlvbiA6IDEwMDtcbiAgICAvKipcbiAgICAgKiBAcHJpdmF0ZVxuICAgICAqIEB0eXBlIHtudW1iZXJ9XG4gICAgICovXG5cbiAgICBfdGhpcy5waXhlbERlbHRhXyA9IG9wdGlvbnMucGl4ZWxEZWx0YSAhPT0gdW5kZWZpbmVkID8gb3B0aW9ucy5waXhlbERlbHRhIDogMTI4O1xuICAgIHJldHVybiBfdGhpcztcbiAgfVxuICAvKipcbiAgICogSGFuZGxlcyB0aGUge0BsaW5rIG1vZHVsZTpvbC9NYXBCcm93c2VyRXZlbnQgbWFwIGJyb3dzZXIgZXZlbnR9IGlmIGl0IHdhcyBhXG4gICAqIGBLZXlFdmVudGAsIGFuZCBkZWNpZGVzIHRoZSBkaXJlY3Rpb24gdG8gcGFuIHRvIChpZiBhbiBhcnJvdyBrZXkgd2FzXG4gICAqIHByZXNzZWQpLlxuICAgKiBAcGFyYW0ge2ltcG9ydChcIi4uL01hcEJyb3dzZXJFdmVudC5qc1wiKS5kZWZhdWx0fSBtYXBCcm93c2VyRXZlbnQgTWFwIGJyb3dzZXIgZXZlbnQuXG4gICAqIEByZXR1cm4ge2Jvb2xlYW59IGBmYWxzZWAgdG8gc3RvcCBldmVudCBwcm9wYWdhdGlvbi5cbiAgICogQHRoaXMge0tleWJvYXJkUGFufVxuICAgKi9cblxuXG4gIEtleWJvYXJkUGFuLnByb3RvdHlwZS5oYW5kbGVFdmVudCA9IGZ1bmN0aW9uIChtYXBCcm93c2VyRXZlbnQpIHtcbiAgICB2YXIgc3RvcEV2ZW50ID0gZmFsc2U7XG5cbiAgICBpZiAobWFwQnJvd3NlckV2ZW50LnR5cGUgPT0gRXZlbnRUeXBlLktFWURPV04pIHtcbiAgICAgIHZhciBrZXlFdmVudCA9XG4gICAgICAvKiogQHR5cGUge0tleWJvYXJkRXZlbnR9ICovXG4gICAgICBtYXBCcm93c2VyRXZlbnQub3JpZ2luYWxFdmVudDtcbiAgICAgIHZhciBrZXlDb2RlID0ga2V5RXZlbnQua2V5Q29kZTtcblxuICAgICAgaWYgKHRoaXMuY29uZGl0aW9uXyhtYXBCcm93c2VyRXZlbnQpICYmIChrZXlDb2RlID09IEtleUNvZGUuRE9XTiB8fCBrZXlDb2RlID09IEtleUNvZGUuTEVGVCB8fCBrZXlDb2RlID09IEtleUNvZGUuUklHSFQgfHwga2V5Q29kZSA9PSBLZXlDb2RlLlVQKSkge1xuICAgICAgICB2YXIgbWFwID0gbWFwQnJvd3NlckV2ZW50Lm1hcDtcbiAgICAgICAgdmFyIHZpZXcgPSBtYXAuZ2V0VmlldygpO1xuICAgICAgICB2YXIgbWFwVW5pdHNEZWx0YSA9IHZpZXcuZ2V0UmVzb2x1dGlvbigpICogdGhpcy5waXhlbERlbHRhXztcbiAgICAgICAgdmFyIGRlbHRhWCA9IDAsXG4gICAgICAgICAgICBkZWx0YVkgPSAwO1xuXG4gICAgICAgIGlmIChrZXlDb2RlID09IEtleUNvZGUuRE9XTikge1xuICAgICAgICAgIGRlbHRhWSA9IC1tYXBVbml0c0RlbHRhO1xuICAgICAgICB9IGVsc2UgaWYgKGtleUNvZGUgPT0gS2V5Q29kZS5MRUZUKSB7XG4gICAgICAgICAgZGVsdGFYID0gLW1hcFVuaXRzRGVsdGE7XG4gICAgICAgIH0gZWxzZSBpZiAoa2V5Q29kZSA9PSBLZXlDb2RlLlJJR0hUKSB7XG4gICAgICAgICAgZGVsdGFYID0gbWFwVW5pdHNEZWx0YTtcbiAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICBkZWx0YVkgPSBtYXBVbml0c0RlbHRhO1xuICAgICAgICB9XG5cbiAgICAgICAgdmFyIGRlbHRhID0gW2RlbHRhWCwgZGVsdGFZXTtcbiAgICAgICAgcm90YXRlQ29vcmRpbmF0ZShkZWx0YSwgdmlldy5nZXRSb3RhdGlvbigpKTtcbiAgICAgICAgcGFuKHZpZXcsIGRlbHRhLCB0aGlzLmR1cmF0aW9uXyk7XG4gICAgICAgIGtleUV2ZW50LnByZXZlbnREZWZhdWx0KCk7XG4gICAgICAgIHN0b3BFdmVudCA9IHRydWU7XG4gICAgICB9XG4gICAgfVxuXG4gICAgcmV0dXJuICFzdG9wRXZlbnQ7XG4gIH07XG5cbiAgcmV0dXJuIEtleWJvYXJkUGFuO1xufShJbnRlcmFjdGlvbik7XG5cbmV4cG9ydCBkZWZhdWx0IEtleWJvYXJkUGFuOyIsInZhciBfX2V4dGVuZHMgPSB0aGlzICYmIHRoaXMuX19leHRlbmRzIHx8IGZ1bmN0aW9uICgpIHtcbiAgdmFyIF9leHRlbmRTdGF0aWNzID0gZnVuY3Rpb24gZXh0ZW5kU3RhdGljcyhkLCBiKSB7XG4gICAgX2V4dGVuZFN0YXRpY3MgPSBPYmplY3Quc2V0UHJvdG90eXBlT2YgfHwge1xuICAgICAgX19wcm90b19fOiBbXVxuICAgIH0gaW5zdGFuY2VvZiBBcnJheSAmJiBmdW5jdGlvbiAoZCwgYikge1xuICAgICAgZC5fX3Byb3RvX18gPSBiO1xuICAgIH0gfHwgZnVuY3Rpb24gKGQsIGIpIHtcbiAgICAgIGZvciAodmFyIHAgaW4gYikge1xuICAgICAgICBpZiAoT2JqZWN0LnByb3RvdHlwZS5oYXNPd25Qcm9wZXJ0eS5jYWxsKGIsIHApKSBkW3BdID0gYltwXTtcbiAgICAgIH1cbiAgICB9O1xuXG4gICAgcmV0dXJuIF9leHRlbmRTdGF0aWNzKGQsIGIpO1xuICB9O1xuXG4gIHJldHVybiBmdW5jdGlvbiAoZCwgYikge1xuICAgIF9leHRlbmRTdGF0aWNzKGQsIGIpO1xuXG4gICAgZnVuY3Rpb24gX18oKSB7XG4gICAgICB0aGlzLmNvbnN0cnVjdG9yID0gZDtcbiAgICB9XG5cbiAgICBkLnByb3RvdHlwZSA9IGIgPT09IG51bGwgPyBPYmplY3QuY3JlYXRlKGIpIDogKF9fLnByb3RvdHlwZSA9IGIucHJvdG90eXBlLCBuZXcgX18oKSk7XG4gIH07XG59KCk7XG4vKipcbiAqIEBtb2R1bGUgb2wvaW50ZXJhY3Rpb24vS2V5Ym9hcmRab29tXG4gKi9cblxuXG5pbXBvcnQgRXZlbnRUeXBlIGZyb20gJy4uL2V2ZW50cy9FdmVudFR5cGUuanMnO1xuaW1wb3J0IEludGVyYWN0aW9uLCB7IHpvb21CeURlbHRhIH0gZnJvbSAnLi9JbnRlcmFjdGlvbi5qcyc7XG5pbXBvcnQgeyB0YXJnZXROb3RFZGl0YWJsZSB9IGZyb20gJy4uL2V2ZW50cy9jb25kaXRpb24uanMnO1xuLyoqXG4gKiBAdHlwZWRlZiB7T2JqZWN0fSBPcHRpb25zXG4gKiBAcHJvcGVydHkge251bWJlcn0gW2R1cmF0aW9uPTEwMF0gQW5pbWF0aW9uIGR1cmF0aW9uIGluIG1pbGxpc2Vjb25kcy5cbiAqIEBwcm9wZXJ0eSB7aW1wb3J0KFwiLi4vZXZlbnRzL2NvbmRpdGlvbi5qc1wiKS5Db25kaXRpb259IFtjb25kaXRpb25dIEEgZnVuY3Rpb24gdGhhdFxuICogdGFrZXMgYW4ge0BsaW5rIG1vZHVsZTpvbC9NYXBCcm93c2VyRXZlbnR+TWFwQnJvd3NlckV2ZW50fSBhbmQgcmV0dXJucyBhXG4gKiBib29sZWFuIHRvIGluZGljYXRlIHdoZXRoZXIgdGhhdCBldmVudCBzaG91bGQgYmUgaGFuZGxlZC4gRGVmYXVsdCBpc1xuICoge0BsaW5rIG1vZHVsZTpvbC9ldmVudHMvY29uZGl0aW9ufnRhcmdldE5vdEVkaXRhYmxlfS5cbiAqIEBwcm9wZXJ0eSB7bnVtYmVyfSBbZGVsdGE9MV0gVGhlIHpvb20gbGV2ZWwgZGVsdGEgb24gZWFjaCBrZXkgcHJlc3MuXG4gKi9cblxuLyoqXG4gKiBAY2xhc3NkZXNjXG4gKiBBbGxvd3MgdGhlIHVzZXIgdG8gem9vbSB0aGUgbWFwIHVzaW5nIGtleWJvYXJkICsgYW5kIC0uXG4gKiBOb3RlIHRoYXQsIGFsdGhvdWdoIHRoaXMgaW50ZXJhY3Rpb24gaXMgYnkgZGVmYXVsdCBpbmNsdWRlZCBpbiBtYXBzLFxuICogdGhlIGtleXMgY2FuIG9ubHkgYmUgdXNlZCB3aGVuIGJyb3dzZXIgZm9jdXMgaXMgb24gdGhlIGVsZW1lbnQgdG8gd2hpY2hcbiAqIHRoZSBrZXlib2FyZCBldmVudHMgYXJlIGF0dGFjaGVkLiBCeSBkZWZhdWx0LCB0aGlzIGlzIHRoZSBtYXAgZGl2LFxuICogdGhvdWdoIHlvdSBjYW4gY2hhbmdlIHRoaXMgd2l0aCB0aGUgYGtleWJvYXJkRXZlbnRUYXJnZXRgIGluXG4gKiB7QGxpbmsgbW9kdWxlOm9sL01hcH5NYXB9LiBgZG9jdW1lbnRgIG5ldmVyIGxvc2VzIGZvY3VzIGJ1dCwgZm9yIGFueSBvdGhlclxuICogZWxlbWVudCwgZm9jdXMgd2lsbCBoYXZlIHRvIGJlIG9uLCBhbmQgcmV0dXJuZWQgdG8sIHRoaXMgZWxlbWVudCBpZiB0aGUga2V5c1xuICogYXJlIHRvIGZ1bmN0aW9uLlxuICogU2VlIGFsc28ge0BsaW5rIG1vZHVsZTpvbC9pbnRlcmFjdGlvbi9LZXlib2FyZFBhbn5LZXlib2FyZFBhbn0uXG4gKiBAYXBpXG4gKi9cblxudmFyIEtleWJvYXJkWm9vbSA9XG4vKiogQGNsYXNzICovXG5mdW5jdGlvbiAoX3N1cGVyKSB7XG4gIF9fZXh0ZW5kcyhLZXlib2FyZFpvb20sIF9zdXBlcik7XG4gIC8qKlxuICAgKiBAcGFyYW0ge09wdGlvbnM9fSBvcHRfb3B0aW9ucyBPcHRpb25zLlxuICAgKi9cblxuXG4gIGZ1bmN0aW9uIEtleWJvYXJkWm9vbShvcHRfb3B0aW9ucykge1xuICAgIHZhciBfdGhpcyA9IF9zdXBlci5jYWxsKHRoaXMpIHx8IHRoaXM7XG5cbiAgICB2YXIgb3B0aW9ucyA9IG9wdF9vcHRpb25zID8gb3B0X29wdGlvbnMgOiB7fTtcbiAgICAvKipcbiAgICAgKiBAcHJpdmF0ZVxuICAgICAqIEB0eXBlIHtpbXBvcnQoXCIuLi9ldmVudHMvY29uZGl0aW9uLmpzXCIpLkNvbmRpdGlvbn1cbiAgICAgKi9cblxuICAgIF90aGlzLmNvbmRpdGlvbl8gPSBvcHRpb25zLmNvbmRpdGlvbiA/IG9wdGlvbnMuY29uZGl0aW9uIDogdGFyZ2V0Tm90RWRpdGFibGU7XG4gICAgLyoqXG4gICAgICogQHByaXZhdGVcbiAgICAgKiBAdHlwZSB7bnVtYmVyfVxuICAgICAqL1xuXG4gICAgX3RoaXMuZGVsdGFfID0gb3B0aW9ucy5kZWx0YSA/IG9wdGlvbnMuZGVsdGEgOiAxO1xuICAgIC8qKlxuICAgICAqIEBwcml2YXRlXG4gICAgICogQHR5cGUge251bWJlcn1cbiAgICAgKi9cblxuICAgIF90aGlzLmR1cmF0aW9uXyA9IG9wdGlvbnMuZHVyYXRpb24gIT09IHVuZGVmaW5lZCA/IG9wdGlvbnMuZHVyYXRpb24gOiAxMDA7XG4gICAgcmV0dXJuIF90aGlzO1xuICB9XG4gIC8qKlxuICAgKiBIYW5kbGVzIHRoZSB7QGxpbmsgbW9kdWxlOm9sL01hcEJyb3dzZXJFdmVudCBtYXAgYnJvd3NlciBldmVudH0gaWYgaXQgd2FzIGFcbiAgICogYEtleUV2ZW50YCwgYW5kIGRlY2lkZXMgd2hldGhlciB0byB6b29tIGluIG9yIG91dCAoZGVwZW5kaW5nIG9uIHdoZXRoZXIgdGhlXG4gICAqIGtleSBwcmVzc2VkIHdhcyAnKycgb3IgJy0nKS5cbiAgICogQHBhcmFtIHtpbXBvcnQoXCIuLi9NYXBCcm93c2VyRXZlbnQuanNcIikuZGVmYXVsdH0gbWFwQnJvd3NlckV2ZW50IE1hcCBicm93c2VyIGV2ZW50LlxuICAgKiBAcmV0dXJuIHtib29sZWFufSBgZmFsc2VgIHRvIHN0b3AgZXZlbnQgcHJvcGFnYXRpb24uXG4gICAqIEB0aGlzIHtLZXlib2FyZFpvb219XG4gICAqL1xuXG5cbiAgS2V5Ym9hcmRab29tLnByb3RvdHlwZS5oYW5kbGVFdmVudCA9IGZ1bmN0aW9uIChtYXBCcm93c2VyRXZlbnQpIHtcbiAgICB2YXIgc3RvcEV2ZW50ID0gZmFsc2U7XG5cbiAgICBpZiAobWFwQnJvd3NlckV2ZW50LnR5cGUgPT0gRXZlbnRUeXBlLktFWURPV04gfHwgbWFwQnJvd3NlckV2ZW50LnR5cGUgPT0gRXZlbnRUeXBlLktFWVBSRVNTKSB7XG4gICAgICB2YXIga2V5RXZlbnQgPVxuICAgICAgLyoqIEB0eXBlIHtLZXlib2FyZEV2ZW50fSAqL1xuICAgICAgbWFwQnJvd3NlckV2ZW50Lm9yaWdpbmFsRXZlbnQ7XG4gICAgICB2YXIgY2hhckNvZGUgPSBrZXlFdmVudC5jaGFyQ29kZTtcblxuICAgICAgaWYgKHRoaXMuY29uZGl0aW9uXyhtYXBCcm93c2VyRXZlbnQpICYmIChjaGFyQ29kZSA9PSAnKycuY2hhckNvZGVBdCgwKSB8fCBjaGFyQ29kZSA9PSAnLScuY2hhckNvZGVBdCgwKSkpIHtcbiAgICAgICAgdmFyIG1hcCA9IG1hcEJyb3dzZXJFdmVudC5tYXA7XG4gICAgICAgIHZhciBkZWx0YSA9IGNoYXJDb2RlID09ICcrJy5jaGFyQ29kZUF0KDApID8gdGhpcy5kZWx0YV8gOiAtdGhpcy5kZWx0YV87XG4gICAgICAgIHZhciB2aWV3ID0gbWFwLmdldFZpZXcoKTtcbiAgICAgICAgem9vbUJ5RGVsdGEodmlldywgZGVsdGEsIHVuZGVmaW5lZCwgdGhpcy5kdXJhdGlvbl8pO1xuICAgICAgICBrZXlFdmVudC5wcmV2ZW50RGVmYXVsdCgpO1xuICAgICAgICBzdG9wRXZlbnQgPSB0cnVlO1xuICAgICAgfVxuICAgIH1cblxuICAgIHJldHVybiAhc3RvcEV2ZW50O1xuICB9O1xuXG4gIHJldHVybiBLZXlib2FyZFpvb207XG59KEludGVyYWN0aW9uKTtcblxuZXhwb3J0IGRlZmF1bHQgS2V5Ym9hcmRab29tOyIsIi8qKlxuICogQG1vZHVsZSBvbC9LaW5ldGljXG4gKi9cblxuLyoqXG4gKiBAY2xhc3NkZXNjXG4gKiBJbXBsZW1lbnRhdGlvbiBvZiBpbmVydGlhbCBkZWNlbGVyYXRpb24gZm9yIG1hcCBtb3ZlbWVudC5cbiAqXG4gKiBAYXBpXG4gKi9cbnZhciBLaW5ldGljID1cbi8qKiBAY2xhc3MgKi9cbmZ1bmN0aW9uICgpIHtcbiAgLyoqXG4gICAqIEBwYXJhbSB7bnVtYmVyfSBkZWNheSBSYXRlIG9mIGRlY2F5IChtdXN0IGJlIG5lZ2F0aXZlKS5cbiAgICogQHBhcmFtIHtudW1iZXJ9IG1pblZlbG9jaXR5IE1pbmltdW0gdmVsb2NpdHkgKHBpeGVscy9taWxsaXNlY29uZCkuXG4gICAqIEBwYXJhbSB7bnVtYmVyfSBkZWxheSBEZWxheSB0byBjb25zaWRlciB0byBjYWxjdWxhdGUgdGhlIGtpbmV0aWNcbiAgICogICAgIGluaXRpYWwgdmFsdWVzIChtaWxsaXNlY29uZHMpLlxuICAgKi9cbiAgZnVuY3Rpb24gS2luZXRpYyhkZWNheSwgbWluVmVsb2NpdHksIGRlbGF5KSB7XG4gICAgLyoqXG4gICAgICogQHByaXZhdGVcbiAgICAgKiBAdHlwZSB7bnVtYmVyfVxuICAgICAqL1xuICAgIHRoaXMuZGVjYXlfID0gZGVjYXk7XG4gICAgLyoqXG4gICAgICogQHByaXZhdGVcbiAgICAgKiBAdHlwZSB7bnVtYmVyfVxuICAgICAqL1xuXG4gICAgdGhpcy5taW5WZWxvY2l0eV8gPSBtaW5WZWxvY2l0eTtcbiAgICAvKipcbiAgICAgKiBAcHJpdmF0ZVxuICAgICAqIEB0eXBlIHtudW1iZXJ9XG4gICAgICovXG5cbiAgICB0aGlzLmRlbGF5XyA9IGRlbGF5O1xuICAgIC8qKlxuICAgICAqIEBwcml2YXRlXG4gICAgICogQHR5cGUge0FycmF5PG51bWJlcj59XG4gICAgICovXG5cbiAgICB0aGlzLnBvaW50c18gPSBbXTtcbiAgICAvKipcbiAgICAgKiBAcHJpdmF0ZVxuICAgICAqIEB0eXBlIHtudW1iZXJ9XG4gICAgICovXG5cbiAgICB0aGlzLmFuZ2xlXyA9IDA7XG4gICAgLyoqXG4gICAgICogQHByaXZhdGVcbiAgICAgKiBAdHlwZSB7bnVtYmVyfVxuICAgICAqL1xuXG4gICAgdGhpcy5pbml0aWFsVmVsb2NpdHlfID0gMDtcbiAgfVxuICAvKipcbiAgICogRklYTUUgZW1wdHkgZGVzY3JpcHRpb24gZm9yIGpzZG9jXG4gICAqL1xuXG5cbiAgS2luZXRpYy5wcm90b3R5cGUuYmVnaW4gPSBmdW5jdGlvbiAoKSB7XG4gICAgdGhpcy5wb2ludHNfLmxlbmd0aCA9IDA7XG4gICAgdGhpcy5hbmdsZV8gPSAwO1xuICAgIHRoaXMuaW5pdGlhbFZlbG9jaXR5XyA9IDA7XG4gIH07XG4gIC8qKlxuICAgKiBAcGFyYW0ge251bWJlcn0geCBYLlxuICAgKiBAcGFyYW0ge251bWJlcn0geSBZLlxuICAgKi9cblxuXG4gIEtpbmV0aWMucHJvdG90eXBlLnVwZGF0ZSA9IGZ1bmN0aW9uICh4LCB5KSB7XG4gICAgdGhpcy5wb2ludHNfLnB1c2goeCwgeSwgRGF0ZS5ub3coKSk7XG4gIH07XG4gIC8qKlxuICAgKiBAcmV0dXJuIHtib29sZWFufSBXaGV0aGVyIHdlIHNob3VsZCBkbyBraW5ldGljIGFuaW1hdGlvbi5cbiAgICovXG5cblxuICBLaW5ldGljLnByb3RvdHlwZS5lbmQgPSBmdW5jdGlvbiAoKSB7XG4gICAgaWYgKHRoaXMucG9pbnRzXy5sZW5ndGggPCA2KSB7XG4gICAgICAvLyBhdCBsZWFzdCAyIHBvaW50cyBhcmUgcmVxdWlyZWQgKGkuZS4gdGhlcmUgbXVzdCBiZSBhdCBsZWFzdCA2IGVsZW1lbnRzXG4gICAgICAvLyBpbiB0aGUgYXJyYXkpXG4gICAgICByZXR1cm4gZmFsc2U7XG4gICAgfVxuXG4gICAgdmFyIGRlbGF5ID0gRGF0ZS5ub3coKSAtIHRoaXMuZGVsYXlfO1xuICAgIHZhciBsYXN0SW5kZXggPSB0aGlzLnBvaW50c18ubGVuZ3RoIC0gMztcblxuICAgIGlmICh0aGlzLnBvaW50c19bbGFzdEluZGV4ICsgMl0gPCBkZWxheSkge1xuICAgICAgLy8gdGhlIGxhc3QgdHJhY2tlZCBwb2ludCBpcyB0b28gb2xkLCB3aGljaCBtZWFucyB0aGF0IHRoZSB1c2VyIHN0b3BwZWRcbiAgICAgIC8vIHBhbm5pbmcgYmVmb3JlIHJlbGVhc2luZyB0aGUgbWFwXG4gICAgICByZXR1cm4gZmFsc2U7XG4gICAgfSAvLyBnZXQgdGhlIGZpcnN0IHBvaW50IHdoaWNoIHN0aWxsIGZhbGxzIGludG8gdGhlIGRlbGF5IHRpbWVcblxuXG4gICAgdmFyIGZpcnN0SW5kZXggPSBsYXN0SW5kZXggLSAzO1xuXG4gICAgd2hpbGUgKGZpcnN0SW5kZXggPiAwICYmIHRoaXMucG9pbnRzX1tmaXJzdEluZGV4ICsgMl0gPiBkZWxheSkge1xuICAgICAgZmlyc3RJbmRleCAtPSAzO1xuICAgIH1cblxuICAgIHZhciBkdXJhdGlvbiA9IHRoaXMucG9pbnRzX1tsYXN0SW5kZXggKyAyXSAtIHRoaXMucG9pbnRzX1tmaXJzdEluZGV4ICsgMl07IC8vIHdlIGRvbid0IHdhbnQgYSBkdXJhdGlvbiBvZiAwIChkaXZpZGUgYnkgemVybylcbiAgICAvLyB3ZSBhbHNvIG1ha2Ugc3VyZSB0aGUgdXNlciBwYW5uZWQgZm9yIGEgZHVyYXRpb24gb2YgYXQgbGVhc3Qgb25lIGZyYW1lXG4gICAgLy8gKDEvNjBzKSB0byBjb21wdXRlIHNhbmUgZGlzcGxhY2VtZW50IHZhbHVlc1xuXG4gICAgaWYgKGR1cmF0aW9uIDwgMTAwMCAvIDYwKSB7XG4gICAgICByZXR1cm4gZmFsc2U7XG4gICAgfVxuXG4gICAgdmFyIGR4ID0gdGhpcy5wb2ludHNfW2xhc3RJbmRleF0gLSB0aGlzLnBvaW50c19bZmlyc3RJbmRleF07XG4gICAgdmFyIGR5ID0gdGhpcy5wb2ludHNfW2xhc3RJbmRleCArIDFdIC0gdGhpcy5wb2ludHNfW2ZpcnN0SW5kZXggKyAxXTtcbiAgICB0aGlzLmFuZ2xlXyA9IE1hdGguYXRhbjIoZHksIGR4KTtcbiAgICB0aGlzLmluaXRpYWxWZWxvY2l0eV8gPSBNYXRoLnNxcnQoZHggKiBkeCArIGR5ICogZHkpIC8gZHVyYXRpb247XG4gICAgcmV0dXJuIHRoaXMuaW5pdGlhbFZlbG9jaXR5XyA+IHRoaXMubWluVmVsb2NpdHlfO1xuICB9O1xuICAvKipcbiAgICogQHJldHVybiB7bnVtYmVyfSBUb3RhbCBkaXN0YW5jZSB0cmF2ZWxsZWQgKHBpeGVscykuXG4gICAqL1xuXG5cbiAgS2luZXRpYy5wcm90b3R5cGUuZ2V0RGlzdGFuY2UgPSBmdW5jdGlvbiAoKSB7XG4gICAgcmV0dXJuICh0aGlzLm1pblZlbG9jaXR5XyAtIHRoaXMuaW5pdGlhbFZlbG9jaXR5XykgLyB0aGlzLmRlY2F5XztcbiAgfTtcbiAgLyoqXG4gICAqIEByZXR1cm4ge251bWJlcn0gQW5nbGUgb2YgdGhlIGtpbmV0aWMgcGFubmluZyBhbmltYXRpb24gKHJhZGlhbnMpLlxuICAgKi9cblxuXG4gIEtpbmV0aWMucHJvdG90eXBlLmdldEFuZ2xlID0gZnVuY3Rpb24gKCkge1xuICAgIHJldHVybiB0aGlzLmFuZ2xlXztcbiAgfTtcblxuICByZXR1cm4gS2luZXRpYztcbn0oKTtcblxuZXhwb3J0IGRlZmF1bHQgS2luZXRpYzsiLCJ2YXIgX19leHRlbmRzID0gdGhpcyAmJiB0aGlzLl9fZXh0ZW5kcyB8fCBmdW5jdGlvbiAoKSB7XG4gIHZhciBfZXh0ZW5kU3RhdGljcyA9IGZ1bmN0aW9uIGV4dGVuZFN0YXRpY3MoZCwgYikge1xuICAgIF9leHRlbmRTdGF0aWNzID0gT2JqZWN0LnNldFByb3RvdHlwZU9mIHx8IHtcbiAgICAgIF9fcHJvdG9fXzogW11cbiAgICB9IGluc3RhbmNlb2YgQXJyYXkgJiYgZnVuY3Rpb24gKGQsIGIpIHtcbiAgICAgIGQuX19wcm90b19fID0gYjtcbiAgICB9IHx8IGZ1bmN0aW9uIChkLCBiKSB7XG4gICAgICBmb3IgKHZhciBwIGluIGIpIHtcbiAgICAgICAgaWYgKE9iamVjdC5wcm90b3R5cGUuaGFzT3duUHJvcGVydHkuY2FsbChiLCBwKSkgZFtwXSA9IGJbcF07XG4gICAgICB9XG4gICAgfTtcblxuICAgIHJldHVybiBfZXh0ZW5kU3RhdGljcyhkLCBiKTtcbiAgfTtcblxuICByZXR1cm4gZnVuY3Rpb24gKGQsIGIpIHtcbiAgICBfZXh0ZW5kU3RhdGljcyhkLCBiKTtcblxuICAgIGZ1bmN0aW9uIF9fKCkge1xuICAgICAgdGhpcy5jb25zdHJ1Y3RvciA9IGQ7XG4gICAgfVxuXG4gICAgZC5wcm90b3R5cGUgPSBiID09PSBudWxsID8gT2JqZWN0LmNyZWF0ZShiKSA6IChfXy5wcm90b3R5cGUgPSBiLnByb3RvdHlwZSwgbmV3IF9fKCkpO1xuICB9O1xufSgpO1xuLyoqXG4gKiBAbW9kdWxlIG9sL2ludGVyYWN0aW9uL01vdXNlV2hlZWxab29tXG4gKi9cblxuXG5pbXBvcnQgRXZlbnRUeXBlIGZyb20gJy4uL2V2ZW50cy9FdmVudFR5cGUuanMnO1xuaW1wb3J0IEludGVyYWN0aW9uLCB7IHpvb21CeURlbHRhIH0gZnJvbSAnLi9JbnRlcmFjdGlvbi5qcyc7XG5pbXBvcnQgeyBERVZJQ0VfUElYRUxfUkFUSU8sIEZJUkVGT1ggfSBmcm9tICcuLi9oYXMuanMnO1xuaW1wb3J0IHsgYWxsLCBhbHdheXMsIGZvY3VzV2l0aFRhYmluZGV4IH0gZnJvbSAnLi4vZXZlbnRzL2NvbmRpdGlvbi5qcyc7XG5pbXBvcnQgeyBjbGFtcCB9IGZyb20gJy4uL21hdGguanMnO1xuLyoqXG4gKiBAZW51bSB7c3RyaW5nfVxuICovXG5cbmV4cG9ydCB2YXIgTW9kZSA9IHtcbiAgVFJBQ0tQQUQ6ICd0cmFja3BhZCcsXG4gIFdIRUVMOiAnd2hlZWwnXG59O1xuLyoqXG4gKiBAdHlwZWRlZiB7T2JqZWN0fSBPcHRpb25zXG4gKiBAcHJvcGVydHkge2ltcG9ydChcIi4uL2V2ZW50cy9jb25kaXRpb24uanNcIikuQ29uZGl0aW9ufSBbY29uZGl0aW9uXSBBIGZ1bmN0aW9uIHRoYXRcbiAqIHRha2VzIGFuIHtAbGluayBtb2R1bGU6b2wvTWFwQnJvd3NlckV2ZW50fk1hcEJyb3dzZXJFdmVudH0gYW5kIHJldHVybnMgYVxuICogYm9vbGVhbiB0byBpbmRpY2F0ZSB3aGV0aGVyIHRoYXQgZXZlbnQgc2hvdWxkIGJlIGhhbmRsZWQuIERlZmF1bHQgaXNcbiAqIHtAbGluayBtb2R1bGU6b2wvZXZlbnRzL2NvbmRpdGlvbn5hbHdheXN9LlxuICogQHByb3BlcnR5IHtib29sZWFufSBbb25Gb2N1c09ubHk9ZmFsc2VdIFdoZW4gdGhlIG1hcCdzIHRhcmdldCBoYXMgYSBgdGFiaW5kZXhgIGF0dHJpYnV0ZSBzZXQsXG4gKiB0aGUgaW50ZXJhY3Rpb24gd2lsbCBvbmx5IGhhbmRsZSBldmVudHMgd2hlbiB0aGUgbWFwIGhhcyB0aGUgZm9jdXMuXG4gKiBAcHJvcGVydHkge251bWJlcn0gW21heERlbHRhPTFdIE1heGltdW0gbW91c2Ugd2hlZWwgZGVsdGEuXG4gKiBAcHJvcGVydHkge251bWJlcn0gW2R1cmF0aW9uPTI1MF0gQW5pbWF0aW9uIGR1cmF0aW9uIGluIG1pbGxpc2Vjb25kcy5cbiAqIEBwcm9wZXJ0eSB7bnVtYmVyfSBbdGltZW91dD04MF0gTW91c2Ugd2hlZWwgdGltZW91dCBkdXJhdGlvbiBpbiBtaWxsaXNlY29uZHMuXG4gKiBAcHJvcGVydHkge2Jvb2xlYW59IFt1c2VBbmNob3I9dHJ1ZV0gRW5hYmxlIHpvb21pbmcgdXNpbmcgdGhlIG1vdXNlJ3NcbiAqIGxvY2F0aW9uIGFzIHRoZSBhbmNob3IuIFdoZW4gc2V0IHRvIGBmYWxzZWAsIHpvb21pbmcgaW4gYW5kIG91dCB3aWxsIHpvb20gdG9cbiAqIHRoZSBjZW50ZXIgb2YgdGhlIHNjcmVlbiBpbnN0ZWFkIG9mIHpvb21pbmcgb24gdGhlIG1vdXNlJ3MgbG9jYXRpb24uXG4gKiBAcHJvcGVydHkge2Jvb2xlYW59IFtjb25zdHJhaW5SZXNvbHV0aW9uPWZhbHNlXSBJZiB0cnVlLCB0aGUgbW91c2Ugd2hlZWwgem9vbVxuICogZXZlbnQgd2lsbCBhbHdheXMgYW5pbWF0ZSB0byB0aGUgY2xvc2VzdCB6b29tIGxldmVsIGFmdGVyIGFuIGludGVyYWN0aW9uO1xuICogZmFsc2UgbWVhbnMgaW50ZXJtZWRpYXJ5IHpvb20gbGV2ZWxzIGFyZSBhbGxvd2VkLlxuICovXG5cbi8qKlxuICogQGNsYXNzZGVzY1xuICogQWxsb3dzIHRoZSB1c2VyIHRvIHpvb20gdGhlIG1hcCBieSBzY3JvbGxpbmcgdGhlIG1vdXNlIHdoZWVsLlxuICogQGFwaVxuICovXG5cbnZhciBNb3VzZVdoZWVsWm9vbSA9XG4vKiogQGNsYXNzICovXG5mdW5jdGlvbiAoX3N1cGVyKSB7XG4gIF9fZXh0ZW5kcyhNb3VzZVdoZWVsWm9vbSwgX3N1cGVyKTtcbiAgLyoqXG4gICAqIEBwYXJhbSB7T3B0aW9ucz19IG9wdF9vcHRpb25zIE9wdGlvbnMuXG4gICAqL1xuXG5cbiAgZnVuY3Rpb24gTW91c2VXaGVlbFpvb20ob3B0X29wdGlvbnMpIHtcbiAgICB2YXIgX3RoaXMgPSB0aGlzO1xuXG4gICAgdmFyIG9wdGlvbnMgPSBvcHRfb3B0aW9ucyA/IG9wdF9vcHRpb25zIDoge307XG4gICAgX3RoaXMgPSBfc3VwZXIuY2FsbCh0aGlzLFxuICAgIC8qKiBAdHlwZSB7aW1wb3J0KFwiLi9JbnRlcmFjdGlvbi5qc1wiKS5JbnRlcmFjdGlvbk9wdGlvbnN9ICovXG4gICAgb3B0aW9ucykgfHwgdGhpcztcbiAgICAvKipcbiAgICAgKiBAcHJpdmF0ZVxuICAgICAqIEB0eXBlIHtudW1iZXJ9XG4gICAgICovXG5cbiAgICBfdGhpcy50b3RhbERlbHRhXyA9IDA7XG4gICAgLyoqXG4gICAgICogQHByaXZhdGVcbiAgICAgKiBAdHlwZSB7bnVtYmVyfVxuICAgICAqL1xuXG4gICAgX3RoaXMubGFzdERlbHRhXyA9IDA7XG4gICAgLyoqXG4gICAgICogQHByaXZhdGVcbiAgICAgKiBAdHlwZSB7bnVtYmVyfVxuICAgICAqL1xuXG4gICAgX3RoaXMubWF4RGVsdGFfID0gb3B0aW9ucy5tYXhEZWx0YSAhPT0gdW5kZWZpbmVkID8gb3B0aW9ucy5tYXhEZWx0YSA6IDE7XG4gICAgLyoqXG4gICAgICogQHByaXZhdGVcbiAgICAgKiBAdHlwZSB7bnVtYmVyfVxuICAgICAqL1xuXG4gICAgX3RoaXMuZHVyYXRpb25fID0gb3B0aW9ucy5kdXJhdGlvbiAhPT0gdW5kZWZpbmVkID8gb3B0aW9ucy5kdXJhdGlvbiA6IDI1MDtcbiAgICAvKipcbiAgICAgKiBAcHJpdmF0ZVxuICAgICAqIEB0eXBlIHtudW1iZXJ9XG4gICAgICovXG5cbiAgICBfdGhpcy50aW1lb3V0XyA9IG9wdGlvbnMudGltZW91dCAhPT0gdW5kZWZpbmVkID8gb3B0aW9ucy50aW1lb3V0IDogODA7XG4gICAgLyoqXG4gICAgICogQHByaXZhdGVcbiAgICAgKiBAdHlwZSB7Ym9vbGVhbn1cbiAgICAgKi9cblxuICAgIF90aGlzLnVzZUFuY2hvcl8gPSBvcHRpb25zLnVzZUFuY2hvciAhPT0gdW5kZWZpbmVkID8gb3B0aW9ucy51c2VBbmNob3IgOiB0cnVlO1xuICAgIC8qKlxuICAgICAqIEBwcml2YXRlXG4gICAgICogQHR5cGUge2Jvb2xlYW59XG4gICAgICovXG5cbiAgICBfdGhpcy5jb25zdHJhaW5SZXNvbHV0aW9uXyA9IG9wdGlvbnMuY29uc3RyYWluUmVzb2x1dGlvbiAhPT0gdW5kZWZpbmVkID8gb3B0aW9ucy5jb25zdHJhaW5SZXNvbHV0aW9uIDogZmFsc2U7XG4gICAgdmFyIGNvbmRpdGlvbiA9IG9wdGlvbnMuY29uZGl0aW9uID8gb3B0aW9ucy5jb25kaXRpb24gOiBhbHdheXM7XG4gICAgLyoqXG4gICAgICogQHByaXZhdGVcbiAgICAgKiBAdHlwZSB7aW1wb3J0KFwiLi4vZXZlbnRzL2NvbmRpdGlvbi5qc1wiKS5Db25kaXRpb259XG4gICAgICovXG5cbiAgICBfdGhpcy5jb25kaXRpb25fID0gb3B0aW9ucy5vbkZvY3VzT25seSA/IGFsbChmb2N1c1dpdGhUYWJpbmRleCwgY29uZGl0aW9uKSA6IGNvbmRpdGlvbjtcbiAgICAvKipcbiAgICAgKiBAcHJpdmF0ZVxuICAgICAqIEB0eXBlIHs/aW1wb3J0KFwiLi4vY29vcmRpbmF0ZS5qc1wiKS5Db29yZGluYXRlfVxuICAgICAqL1xuXG4gICAgX3RoaXMubGFzdEFuY2hvcl8gPSBudWxsO1xuICAgIC8qKlxuICAgICAqIEBwcml2YXRlXG4gICAgICogQHR5cGUge251bWJlcnx1bmRlZmluZWR9XG4gICAgICovXG5cbiAgICBfdGhpcy5zdGFydFRpbWVfID0gdW5kZWZpbmVkO1xuICAgIC8qKlxuICAgICAqIEBwcml2YXRlXG4gICAgICogQHR5cGUgez99XG4gICAgICovXG5cbiAgICBfdGhpcy50aW1lb3V0SWRfO1xuICAgIC8qKlxuICAgICAqIEBwcml2YXRlXG4gICAgICogQHR5cGUge01vZGV8dW5kZWZpbmVkfVxuICAgICAqL1xuXG4gICAgX3RoaXMubW9kZV8gPSB1bmRlZmluZWQ7XG4gICAgLyoqXG4gICAgICogVHJhY2twYWQgZXZlbnRzIHNlcGFyYXRlZCBieSB0aGlzIGRlbGF5IHdpbGwgYmUgY29uc2lkZXJlZCBzZXBhcmF0ZVxuICAgICAqIGludGVyYWN0aW9ucy5cbiAgICAgKiBAdHlwZSB7bnVtYmVyfVxuICAgICAqL1xuXG4gICAgX3RoaXMudHJhY2twYWRFdmVudEdhcF8gPSA0MDA7XG4gICAgLyoqXG4gICAgICogQHR5cGUgez99XG4gICAgICovXG5cbiAgICBfdGhpcy50cmFja3BhZFRpbWVvdXRJZF87XG4gICAgLyoqXG4gICAgICogVGhlIG51bWJlciBvZiBkZWx0YSB2YWx1ZXMgcGVyIHpvb20gbGV2ZWxcbiAgICAgKiBAcHJpdmF0ZVxuICAgICAqIEB0eXBlIHtudW1iZXJ9XG4gICAgICovXG5cbiAgICBfdGhpcy5kZWx0YVBlclpvb21fID0gMzAwO1xuICAgIHJldHVybiBfdGhpcztcbiAgfVxuICAvKipcbiAgICogQHByaXZhdGVcbiAgICovXG5cblxuICBNb3VzZVdoZWVsWm9vbS5wcm90b3R5cGUuZW5kSW50ZXJhY3Rpb25fID0gZnVuY3Rpb24gKCkge1xuICAgIHRoaXMudHJhY2twYWRUaW1lb3V0SWRfID0gdW5kZWZpbmVkO1xuICAgIHZhciB2aWV3ID0gdGhpcy5nZXRNYXAoKS5nZXRWaWV3KCk7XG4gICAgdmlldy5lbmRJbnRlcmFjdGlvbih1bmRlZmluZWQsIHRoaXMubGFzdERlbHRhXyA/IHRoaXMubGFzdERlbHRhXyA+IDAgPyAxIDogLTEgOiAwLCB0aGlzLmxhc3RBbmNob3JfKTtcbiAgfTtcbiAgLyoqXG4gICAqIEhhbmRsZXMgdGhlIHtAbGluayBtb2R1bGU6b2wvTWFwQnJvd3NlckV2ZW50IG1hcCBicm93c2VyIGV2ZW50fSAoaWYgaXQgd2FzIGEgbW91c2V3aGVlbC1ldmVudCkgYW5kIGV2ZW50dWFsbHlcbiAgICogem9vbXMgdGhlIG1hcC5cbiAgICogQHBhcmFtIHtpbXBvcnQoXCIuLi9NYXBCcm93c2VyRXZlbnQuanNcIikuZGVmYXVsdH0gbWFwQnJvd3NlckV2ZW50IE1hcCBicm93c2VyIGV2ZW50LlxuICAgKiBAcmV0dXJuIHtib29sZWFufSBgZmFsc2VgIHRvIHN0b3AgZXZlbnQgcHJvcGFnYXRpb24uXG4gICAqL1xuXG5cbiAgTW91c2VXaGVlbFpvb20ucHJvdG90eXBlLmhhbmRsZUV2ZW50ID0gZnVuY3Rpb24gKG1hcEJyb3dzZXJFdmVudCkge1xuICAgIGlmICghdGhpcy5jb25kaXRpb25fKG1hcEJyb3dzZXJFdmVudCkpIHtcbiAgICAgIHJldHVybiB0cnVlO1xuICAgIH1cblxuICAgIHZhciB0eXBlID0gbWFwQnJvd3NlckV2ZW50LnR5cGU7XG5cbiAgICBpZiAodHlwZSAhPT0gRXZlbnRUeXBlLldIRUVMKSB7XG4gICAgICByZXR1cm4gdHJ1ZTtcbiAgICB9XG5cbiAgICB2YXIgbWFwID0gbWFwQnJvd3NlckV2ZW50Lm1hcDtcbiAgICB2YXIgd2hlZWxFdmVudCA9XG4gICAgLyoqIEB0eXBlIHtXaGVlbEV2ZW50fSAqL1xuICAgIG1hcEJyb3dzZXJFdmVudC5vcmlnaW5hbEV2ZW50O1xuICAgIHdoZWVsRXZlbnQucHJldmVudERlZmF1bHQoKTtcblxuICAgIGlmICh0aGlzLnVzZUFuY2hvcl8pIHtcbiAgICAgIHRoaXMubGFzdEFuY2hvcl8gPSBtYXBCcm93c2VyRXZlbnQuY29vcmRpbmF0ZTtcbiAgICB9IC8vIERlbHRhIG5vcm1hbGlzYXRpb24gaW5zcGlyZWQgYnlcbiAgICAvLyBodHRwczovL2dpdGh1Yi5jb20vbWFwYm94L21hcGJveC1nbC1qcy9ibG9iLzAwMWM3YjkvanMvdWkvaGFuZGxlci9zY3JvbGxfem9vbS5qc1xuXG5cbiAgICB2YXIgZGVsdGE7XG5cbiAgICBpZiAobWFwQnJvd3NlckV2ZW50LnR5cGUgPT0gRXZlbnRUeXBlLldIRUVMKSB7XG4gICAgICBkZWx0YSA9IHdoZWVsRXZlbnQuZGVsdGFZO1xuXG4gICAgICBpZiAoRklSRUZPWCAmJiB3aGVlbEV2ZW50LmRlbHRhTW9kZSA9PT0gV2hlZWxFdmVudC5ET01fREVMVEFfUElYRUwpIHtcbiAgICAgICAgZGVsdGEgLz0gREVWSUNFX1BJWEVMX1JBVElPO1xuICAgICAgfVxuXG4gICAgICBpZiAod2hlZWxFdmVudC5kZWx0YU1vZGUgPT09IFdoZWVsRXZlbnQuRE9NX0RFTFRBX0xJTkUpIHtcbiAgICAgICAgZGVsdGEgKj0gNDA7XG4gICAgICB9XG4gICAgfVxuXG4gICAgaWYgKGRlbHRhID09PSAwKSB7XG4gICAgICByZXR1cm4gZmFsc2U7XG4gICAgfSBlbHNlIHtcbiAgICAgIHRoaXMubGFzdERlbHRhXyA9IGRlbHRhO1xuICAgIH1cblxuICAgIHZhciBub3cgPSBEYXRlLm5vdygpO1xuXG4gICAgaWYgKHRoaXMuc3RhcnRUaW1lXyA9PT0gdW5kZWZpbmVkKSB7XG4gICAgICB0aGlzLnN0YXJ0VGltZV8gPSBub3c7XG4gICAgfVxuXG4gICAgaWYgKCF0aGlzLm1vZGVfIHx8IG5vdyAtIHRoaXMuc3RhcnRUaW1lXyA+IHRoaXMudHJhY2twYWRFdmVudEdhcF8pIHtcbiAgICAgIHRoaXMubW9kZV8gPSBNYXRoLmFicyhkZWx0YSkgPCA0ID8gTW9kZS5UUkFDS1BBRCA6IE1vZGUuV0hFRUw7XG4gICAgfVxuXG4gICAgdmFyIHZpZXcgPSBtYXAuZ2V0VmlldygpO1xuXG4gICAgaWYgKHRoaXMubW9kZV8gPT09IE1vZGUuVFJBQ0tQQUQgJiYgISh2aWV3LmdldENvbnN0cmFpblJlc29sdXRpb24oKSB8fCB0aGlzLmNvbnN0cmFpblJlc29sdXRpb25fKSkge1xuICAgICAgaWYgKHRoaXMudHJhY2twYWRUaW1lb3V0SWRfKSB7XG4gICAgICAgIGNsZWFyVGltZW91dCh0aGlzLnRyYWNrcGFkVGltZW91dElkXyk7XG4gICAgICB9IGVsc2Uge1xuICAgICAgICBpZiAodmlldy5nZXRBbmltYXRpbmcoKSkge1xuICAgICAgICAgIHZpZXcuY2FuY2VsQW5pbWF0aW9ucygpO1xuICAgICAgICB9XG5cbiAgICAgICAgdmlldy5iZWdpbkludGVyYWN0aW9uKCk7XG4gICAgICB9XG5cbiAgICAgIHRoaXMudHJhY2twYWRUaW1lb3V0SWRfID0gc2V0VGltZW91dCh0aGlzLmVuZEludGVyYWN0aW9uXy5iaW5kKHRoaXMpLCB0aGlzLnRpbWVvdXRfKTtcbiAgICAgIHZpZXcuYWRqdXN0Wm9vbSgtZGVsdGEgLyB0aGlzLmRlbHRhUGVyWm9vbV8sIHRoaXMubGFzdEFuY2hvcl8pO1xuICAgICAgdGhpcy5zdGFydFRpbWVfID0gbm93O1xuICAgICAgcmV0dXJuIGZhbHNlO1xuICAgIH1cblxuICAgIHRoaXMudG90YWxEZWx0YV8gKz0gZGVsdGE7XG4gICAgdmFyIHRpbWVMZWZ0ID0gTWF0aC5tYXgodGhpcy50aW1lb3V0XyAtIChub3cgLSB0aGlzLnN0YXJ0VGltZV8pLCAwKTtcbiAgICBjbGVhclRpbWVvdXQodGhpcy50aW1lb3V0SWRfKTtcbiAgICB0aGlzLnRpbWVvdXRJZF8gPSBzZXRUaW1lb3V0KHRoaXMuaGFuZGxlV2hlZWxab29tXy5iaW5kKHRoaXMsIG1hcCksIHRpbWVMZWZ0KTtcbiAgICByZXR1cm4gZmFsc2U7XG4gIH07XG4gIC8qKlxuICAgKiBAcHJpdmF0ZVxuICAgKiBAcGFyYW0ge2ltcG9ydChcIi4uL1BsdWdnYWJsZU1hcC5qc1wiKS5kZWZhdWx0fSBtYXAgTWFwLlxuICAgKi9cblxuXG4gIE1vdXNlV2hlZWxab29tLnByb3RvdHlwZS5oYW5kbGVXaGVlbFpvb21fID0gZnVuY3Rpb24gKG1hcCkge1xuICAgIHZhciB2aWV3ID0gbWFwLmdldFZpZXcoKTtcblxuICAgIGlmICh2aWV3LmdldEFuaW1hdGluZygpKSB7XG4gICAgICB2aWV3LmNhbmNlbEFuaW1hdGlvbnMoKTtcbiAgICB9XG5cbiAgICB2YXIgZGVsdGEgPSAtY2xhbXAodGhpcy50b3RhbERlbHRhXywgLXRoaXMubWF4RGVsdGFfICogdGhpcy5kZWx0YVBlclpvb21fLCB0aGlzLm1heERlbHRhXyAqIHRoaXMuZGVsdGFQZXJab29tXykgLyB0aGlzLmRlbHRhUGVyWm9vbV87XG5cbiAgICBpZiAodmlldy5nZXRDb25zdHJhaW5SZXNvbHV0aW9uKCkgfHwgdGhpcy5jb25zdHJhaW5SZXNvbHV0aW9uXykge1xuICAgICAgLy8gdmlldyBoYXMgYSB6b29tIGNvbnN0cmFpbnQsIHpvb20gYnkgMVxuICAgICAgZGVsdGEgPSBkZWx0YSA/IGRlbHRhID4gMCA/IDEgOiAtMSA6IDA7XG4gICAgfVxuXG4gICAgem9vbUJ5RGVsdGEodmlldywgZGVsdGEsIHRoaXMubGFzdEFuY2hvcl8sIHRoaXMuZHVyYXRpb25fKTtcbiAgICB0aGlzLm1vZGVfID0gdW5kZWZpbmVkO1xuICAgIHRoaXMudG90YWxEZWx0YV8gPSAwO1xuICAgIHRoaXMubGFzdEFuY2hvcl8gPSBudWxsO1xuICAgIHRoaXMuc3RhcnRUaW1lXyA9IHVuZGVmaW5lZDtcbiAgICB0aGlzLnRpbWVvdXRJZF8gPSB1bmRlZmluZWQ7XG4gIH07XG4gIC8qKlxuICAgKiBFbmFibGUgb3IgZGlzYWJsZSB1c2luZyB0aGUgbW91c2UncyBsb2NhdGlvbiBhcyBhbiBhbmNob3Igd2hlbiB6b29taW5nXG4gICAqIEBwYXJhbSB7Ym9vbGVhbn0gdXNlQW5jaG9yIHRydWUgdG8gem9vbSB0byB0aGUgbW91c2UncyBsb2NhdGlvbiwgZmFsc2VcbiAgICogdG8gem9vbSB0byB0aGUgY2VudGVyIG9mIHRoZSBtYXBcbiAgICogQGFwaVxuICAgKi9cblxuXG4gIE1vdXNlV2hlZWxab29tLnByb3RvdHlwZS5zZXRNb3VzZUFuY2hvciA9IGZ1bmN0aW9uICh1c2VBbmNob3IpIHtcbiAgICB0aGlzLnVzZUFuY2hvcl8gPSB1c2VBbmNob3I7XG5cbiAgICBpZiAoIXVzZUFuY2hvcikge1xuICAgICAgdGhpcy5sYXN0QW5jaG9yXyA9IG51bGw7XG4gICAgfVxuICB9O1xuXG4gIHJldHVybiBNb3VzZVdoZWVsWm9vbTtcbn0oSW50ZXJhY3Rpb24pO1xuXG5leHBvcnQgZGVmYXVsdCBNb3VzZVdoZWVsWm9vbTsiLCJ2YXIgX19leHRlbmRzID0gdGhpcyAmJiB0aGlzLl9fZXh0ZW5kcyB8fCBmdW5jdGlvbiAoKSB7XG4gIHZhciBfZXh0ZW5kU3RhdGljcyA9IGZ1bmN0aW9uIGV4dGVuZFN0YXRpY3MoZCwgYikge1xuICAgIF9leHRlbmRTdGF0aWNzID0gT2JqZWN0LnNldFByb3RvdHlwZU9mIHx8IHtcbiAgICAgIF9fcHJvdG9fXzogW11cbiAgICB9IGluc3RhbmNlb2YgQXJyYXkgJiYgZnVuY3Rpb24gKGQsIGIpIHtcbiAgICAgIGQuX19wcm90b19fID0gYjtcbiAgICB9IHx8IGZ1bmN0aW9uIChkLCBiKSB7XG4gICAgICBmb3IgKHZhciBwIGluIGIpIHtcbiAgICAgICAgaWYgKE9iamVjdC5wcm90b3R5cGUuaGFzT3duUHJvcGVydHkuY2FsbChiLCBwKSkgZFtwXSA9IGJbcF07XG4gICAgICB9XG4gICAgfTtcblxuICAgIHJldHVybiBfZXh0ZW5kU3RhdGljcyhkLCBiKTtcbiAgfTtcblxuICByZXR1cm4gZnVuY3Rpb24gKGQsIGIpIHtcbiAgICBfZXh0ZW5kU3RhdGljcyhkLCBiKTtcblxuICAgIGZ1bmN0aW9uIF9fKCkge1xuICAgICAgdGhpcy5jb25zdHJ1Y3RvciA9IGQ7XG4gICAgfVxuXG4gICAgZC5wcm90b3R5cGUgPSBiID09PSBudWxsID8gT2JqZWN0LmNyZWF0ZShiKSA6IChfXy5wcm90b3R5cGUgPSBiLnByb3RvdHlwZSwgbmV3IF9fKCkpO1xuICB9O1xufSgpO1xuLyoqXG4gKiBAbW9kdWxlIG9sL2ludGVyYWN0aW9uL1BpbmNoUm90YXRlXG4gKi9cblxuXG5pbXBvcnQgUG9pbnRlckludGVyYWN0aW9uLCB7IGNlbnRyb2lkIGFzIGNlbnRyb2lkRnJvbVBvaW50ZXJzIH0gZnJvbSAnLi9Qb2ludGVyLmpzJztcbmltcG9ydCB7IEZBTFNFIH0gZnJvbSAnLi4vZnVuY3Rpb25zLmpzJztcbmltcG9ydCB7IGRpc2FibGUgfSBmcm9tICcuLi9yb3RhdGlvbmNvbnN0cmFpbnQuanMnO1xuLyoqXG4gKiBAdHlwZWRlZiB7T2JqZWN0fSBPcHRpb25zXG4gKiBAcHJvcGVydHkge251bWJlcn0gW2R1cmF0aW9uPTI1MF0gVGhlIGR1cmF0aW9uIG9mIHRoZSBhbmltYXRpb24gaW5cbiAqIG1pbGxpc2Vjb25kcy5cbiAqIEBwcm9wZXJ0eSB7bnVtYmVyfSBbdGhyZXNob2xkPTAuM10gTWluaW1hbCBhbmdsZSBpbiByYWRpYW5zIHRvIHN0YXJ0IGEgcm90YXRpb24uXG4gKi9cblxuLyoqXG4gKiBAY2xhc3NkZXNjXG4gKiBBbGxvd3MgdGhlIHVzZXIgdG8gcm90YXRlIHRoZSBtYXAgYnkgdHdpc3Rpbmcgd2l0aCB0d28gZmluZ2Vyc1xuICogb24gYSB0b3VjaCBzY3JlZW4uXG4gKiBAYXBpXG4gKi9cblxudmFyIFBpbmNoUm90YXRlID1cbi8qKiBAY2xhc3MgKi9cbmZ1bmN0aW9uIChfc3VwZXIpIHtcbiAgX19leHRlbmRzKFBpbmNoUm90YXRlLCBfc3VwZXIpO1xuICAvKipcbiAgICogQHBhcmFtIHtPcHRpb25zPX0gb3B0X29wdGlvbnMgT3B0aW9ucy5cbiAgICovXG5cblxuICBmdW5jdGlvbiBQaW5jaFJvdGF0ZShvcHRfb3B0aW9ucykge1xuICAgIHZhciBfdGhpcyA9IHRoaXM7XG5cbiAgICB2YXIgb3B0aW9ucyA9IG9wdF9vcHRpb25zID8gb3B0X29wdGlvbnMgOiB7fTtcbiAgICB2YXIgcG9pbnRlck9wdGlvbnMgPVxuICAgIC8qKiBAdHlwZSB7aW1wb3J0KFwiLi9Qb2ludGVyLmpzXCIpLk9wdGlvbnN9ICovXG4gICAgb3B0aW9ucztcblxuICAgIGlmICghcG9pbnRlck9wdGlvbnMuc3RvcERvd24pIHtcbiAgICAgIHBvaW50ZXJPcHRpb25zLnN0b3BEb3duID0gRkFMU0U7XG4gICAgfVxuXG4gICAgX3RoaXMgPSBfc3VwZXIuY2FsbCh0aGlzLCBwb2ludGVyT3B0aW9ucykgfHwgdGhpcztcbiAgICAvKipcbiAgICAgKiBAcHJpdmF0ZVxuICAgICAqIEB0eXBlIHtpbXBvcnQoXCIuLi9jb29yZGluYXRlLmpzXCIpLkNvb3JkaW5hdGV9XG4gICAgICovXG5cbiAgICBfdGhpcy5hbmNob3JfID0gbnVsbDtcbiAgICAvKipcbiAgICAgKiBAcHJpdmF0ZVxuICAgICAqIEB0eXBlIHtudW1iZXJ8dW5kZWZpbmVkfVxuICAgICAqL1xuXG4gICAgX3RoaXMubGFzdEFuZ2xlXyA9IHVuZGVmaW5lZDtcbiAgICAvKipcbiAgICAgKiBAcHJpdmF0ZVxuICAgICAqIEB0eXBlIHtib29sZWFufVxuICAgICAqL1xuXG4gICAgX3RoaXMucm90YXRpbmdfID0gZmFsc2U7XG4gICAgLyoqXG4gICAgICogQHByaXZhdGVcbiAgICAgKiBAdHlwZSB7bnVtYmVyfVxuICAgICAqL1xuXG4gICAgX3RoaXMucm90YXRpb25EZWx0YV8gPSAwLjA7XG4gICAgLyoqXG4gICAgICogQHByaXZhdGVcbiAgICAgKiBAdHlwZSB7bnVtYmVyfVxuICAgICAqL1xuXG4gICAgX3RoaXMudGhyZXNob2xkXyA9IG9wdGlvbnMudGhyZXNob2xkICE9PSB1bmRlZmluZWQgPyBvcHRpb25zLnRocmVzaG9sZCA6IDAuMztcbiAgICAvKipcbiAgICAgKiBAcHJpdmF0ZVxuICAgICAqIEB0eXBlIHtudW1iZXJ9XG4gICAgICovXG5cbiAgICBfdGhpcy5kdXJhdGlvbl8gPSBvcHRpb25zLmR1cmF0aW9uICE9PSB1bmRlZmluZWQgPyBvcHRpb25zLmR1cmF0aW9uIDogMjUwO1xuICAgIHJldHVybiBfdGhpcztcbiAgfVxuICAvKipcbiAgICogSGFuZGxlIHBvaW50ZXIgZHJhZyBldmVudHMuXG4gICAqIEBwYXJhbSB7aW1wb3J0KFwiLi4vTWFwQnJvd3NlckV2ZW50LmpzXCIpLmRlZmF1bHR9IG1hcEJyb3dzZXJFdmVudCBFdmVudC5cbiAgICovXG5cblxuICBQaW5jaFJvdGF0ZS5wcm90b3R5cGUuaGFuZGxlRHJhZ0V2ZW50ID0gZnVuY3Rpb24gKG1hcEJyb3dzZXJFdmVudCkge1xuICAgIHZhciByb3RhdGlvbkRlbHRhID0gMC4wO1xuICAgIHZhciB0b3VjaDAgPSB0aGlzLnRhcmdldFBvaW50ZXJzWzBdO1xuICAgIHZhciB0b3VjaDEgPSB0aGlzLnRhcmdldFBvaW50ZXJzWzFdOyAvLyBhbmdsZSBiZXR3ZWVuIHRvdWNoZXNcblxuICAgIHZhciBhbmdsZSA9IE1hdGguYXRhbjIodG91Y2gxLmNsaWVudFkgLSB0b3VjaDAuY2xpZW50WSwgdG91Y2gxLmNsaWVudFggLSB0b3VjaDAuY2xpZW50WCk7XG5cbiAgICBpZiAodGhpcy5sYXN0QW5nbGVfICE9PSB1bmRlZmluZWQpIHtcbiAgICAgIHZhciBkZWx0YSA9IGFuZ2xlIC0gdGhpcy5sYXN0QW5nbGVfO1xuICAgICAgdGhpcy5yb3RhdGlvbkRlbHRhXyArPSBkZWx0YTtcblxuICAgICAgaWYgKCF0aGlzLnJvdGF0aW5nXyAmJiBNYXRoLmFicyh0aGlzLnJvdGF0aW9uRGVsdGFfKSA+IHRoaXMudGhyZXNob2xkXykge1xuICAgICAgICB0aGlzLnJvdGF0aW5nXyA9IHRydWU7XG4gICAgICB9XG5cbiAgICAgIHJvdGF0aW9uRGVsdGEgPSBkZWx0YTtcbiAgICB9XG5cbiAgICB0aGlzLmxhc3RBbmdsZV8gPSBhbmdsZTtcbiAgICB2YXIgbWFwID0gbWFwQnJvd3NlckV2ZW50Lm1hcDtcbiAgICB2YXIgdmlldyA9IG1hcC5nZXRWaWV3KCk7XG5cbiAgICBpZiAodmlldy5nZXRDb25zdHJhaW50cygpLnJvdGF0aW9uID09PSBkaXNhYmxlKSB7XG4gICAgICByZXR1cm47XG4gICAgfSAvLyByb3RhdGUgYW5jaG9yIHBvaW50LlxuICAgIC8vIEZJWE1FOiBzaG91bGQgYmUgdGhlIGludGVyc2VjdGlvbiBwb2ludCBiZXR3ZWVuIHRoZSBsaW5lczpcbiAgICAvLyAgICAgdG91Y2gwLHRvdWNoMSBhbmQgcHJldmlvdXNUb3VjaDAscHJldmlvdXNUb3VjaDFcblxuXG4gICAgdmFyIHZpZXdwb3J0UG9zaXRpb24gPSBtYXAuZ2V0Vmlld3BvcnQoKS5nZXRCb3VuZGluZ0NsaWVudFJlY3QoKTtcbiAgICB2YXIgY2VudHJvaWQgPSBjZW50cm9pZEZyb21Qb2ludGVycyh0aGlzLnRhcmdldFBvaW50ZXJzKTtcbiAgICBjZW50cm9pZFswXSAtPSB2aWV3cG9ydFBvc2l0aW9uLmxlZnQ7XG4gICAgY2VudHJvaWRbMV0gLT0gdmlld3BvcnRQb3NpdGlvbi50b3A7XG4gICAgdGhpcy5hbmNob3JfID0gbWFwLmdldENvb3JkaW5hdGVGcm9tUGl4ZWxJbnRlcm5hbChjZW50cm9pZCk7IC8vIHJvdGF0ZVxuXG4gICAgaWYgKHRoaXMucm90YXRpbmdfKSB7XG4gICAgICBtYXAucmVuZGVyKCk7XG4gICAgICB2aWV3LmFkanVzdFJvdGF0aW9uSW50ZXJuYWwocm90YXRpb25EZWx0YSwgdGhpcy5hbmNob3JfKTtcbiAgICB9XG4gIH07XG4gIC8qKlxuICAgKiBIYW5kbGUgcG9pbnRlciB1cCBldmVudHMuXG4gICAqIEBwYXJhbSB7aW1wb3J0KFwiLi4vTWFwQnJvd3NlckV2ZW50LmpzXCIpLmRlZmF1bHR9IG1hcEJyb3dzZXJFdmVudCBFdmVudC5cbiAgICogQHJldHVybiB7Ym9vbGVhbn0gSWYgdGhlIGV2ZW50IHdhcyBjb25zdW1lZC5cbiAgICovXG5cblxuICBQaW5jaFJvdGF0ZS5wcm90b3R5cGUuaGFuZGxlVXBFdmVudCA9IGZ1bmN0aW9uIChtYXBCcm93c2VyRXZlbnQpIHtcbiAgICBpZiAodGhpcy50YXJnZXRQb2ludGVycy5sZW5ndGggPCAyKSB7XG4gICAgICB2YXIgbWFwID0gbWFwQnJvd3NlckV2ZW50Lm1hcDtcbiAgICAgIHZhciB2aWV3ID0gbWFwLmdldFZpZXcoKTtcbiAgICAgIHZpZXcuZW5kSW50ZXJhY3Rpb24odGhpcy5kdXJhdGlvbl8pO1xuICAgICAgcmV0dXJuIGZhbHNlO1xuICAgIH0gZWxzZSB7XG4gICAgICByZXR1cm4gdHJ1ZTtcbiAgICB9XG4gIH07XG4gIC8qKlxuICAgKiBIYW5kbGUgcG9pbnRlciBkb3duIGV2ZW50cy5cbiAgICogQHBhcmFtIHtpbXBvcnQoXCIuLi9NYXBCcm93c2VyRXZlbnQuanNcIikuZGVmYXVsdH0gbWFwQnJvd3NlckV2ZW50IEV2ZW50LlxuICAgKiBAcmV0dXJuIHtib29sZWFufSBJZiB0aGUgZXZlbnQgd2FzIGNvbnN1bWVkLlxuICAgKi9cblxuXG4gIFBpbmNoUm90YXRlLnByb3RvdHlwZS5oYW5kbGVEb3duRXZlbnQgPSBmdW5jdGlvbiAobWFwQnJvd3NlckV2ZW50KSB7XG4gICAgaWYgKHRoaXMudGFyZ2V0UG9pbnRlcnMubGVuZ3RoID49IDIpIHtcbiAgICAgIHZhciBtYXAgPSBtYXBCcm93c2VyRXZlbnQubWFwO1xuICAgICAgdGhpcy5hbmNob3JfID0gbnVsbDtcbiAgICAgIHRoaXMubGFzdEFuZ2xlXyA9IHVuZGVmaW5lZDtcbiAgICAgIHRoaXMucm90YXRpbmdfID0gZmFsc2U7XG4gICAgICB0aGlzLnJvdGF0aW9uRGVsdGFfID0gMC4wO1xuXG4gICAgICBpZiAoIXRoaXMuaGFuZGxpbmdEb3duVXBTZXF1ZW5jZSkge1xuICAgICAgICBtYXAuZ2V0VmlldygpLmJlZ2luSW50ZXJhY3Rpb24oKTtcbiAgICAgIH1cblxuICAgICAgcmV0dXJuIHRydWU7XG4gICAgfSBlbHNlIHtcbiAgICAgIHJldHVybiBmYWxzZTtcbiAgICB9XG4gIH07XG5cbiAgcmV0dXJuIFBpbmNoUm90YXRlO1xufShQb2ludGVySW50ZXJhY3Rpb24pO1xuXG5leHBvcnQgZGVmYXVsdCBQaW5jaFJvdGF0ZTsiLCJ2YXIgX19leHRlbmRzID0gdGhpcyAmJiB0aGlzLl9fZXh0ZW5kcyB8fCBmdW5jdGlvbiAoKSB7XG4gIHZhciBfZXh0ZW5kU3RhdGljcyA9IGZ1bmN0aW9uIGV4dGVuZFN0YXRpY3MoZCwgYikge1xuICAgIF9leHRlbmRTdGF0aWNzID0gT2JqZWN0LnNldFByb3RvdHlwZU9mIHx8IHtcbiAgICAgIF9fcHJvdG9fXzogW11cbiAgICB9IGluc3RhbmNlb2YgQXJyYXkgJiYgZnVuY3Rpb24gKGQsIGIpIHtcbiAgICAgIGQuX19wcm90b19fID0gYjtcbiAgICB9IHx8IGZ1bmN0aW9uIChkLCBiKSB7XG4gICAgICBmb3IgKHZhciBwIGluIGIpIHtcbiAgICAgICAgaWYgKE9iamVjdC5wcm90b3R5cGUuaGFzT3duUHJvcGVydHkuY2FsbChiLCBwKSkgZFtwXSA9IGJbcF07XG4gICAgICB9XG4gICAgfTtcblxuICAgIHJldHVybiBfZXh0ZW5kU3RhdGljcyhkLCBiKTtcbiAgfTtcblxuICByZXR1cm4gZnVuY3Rpb24gKGQsIGIpIHtcbiAgICBfZXh0ZW5kU3RhdGljcyhkLCBiKTtcblxuICAgIGZ1bmN0aW9uIF9fKCkge1xuICAgICAgdGhpcy5jb25zdHJ1Y3RvciA9IGQ7XG4gICAgfVxuXG4gICAgZC5wcm90b3R5cGUgPSBiID09PSBudWxsID8gT2JqZWN0LmNyZWF0ZShiKSA6IChfXy5wcm90b3R5cGUgPSBiLnByb3RvdHlwZSwgbmV3IF9fKCkpO1xuICB9O1xufSgpO1xuLyoqXG4gKiBAbW9kdWxlIG9sL2ludGVyYWN0aW9uL1BpbmNoWm9vbVxuICovXG5cblxuaW1wb3J0IFBvaW50ZXJJbnRlcmFjdGlvbiwgeyBjZW50cm9pZCBhcyBjZW50cm9pZEZyb21Qb2ludGVycyB9IGZyb20gJy4vUG9pbnRlci5qcyc7XG5pbXBvcnQgeyBGQUxTRSB9IGZyb20gJy4uL2Z1bmN0aW9ucy5qcyc7XG4vKipcbiAqIEB0eXBlZGVmIHtPYmplY3R9IE9wdGlvbnNcbiAqIEBwcm9wZXJ0eSB7bnVtYmVyfSBbZHVyYXRpb249NDAwXSBBbmltYXRpb24gZHVyYXRpb24gaW4gbWlsbGlzZWNvbmRzLlxuICovXG5cbi8qKlxuICogQGNsYXNzZGVzY1xuICogQWxsb3dzIHRoZSB1c2VyIHRvIHpvb20gdGhlIG1hcCBieSBwaW5jaGluZyB3aXRoIHR3byBmaW5nZXJzXG4gKiBvbiBhIHRvdWNoIHNjcmVlbi5cbiAqIEBhcGlcbiAqL1xuXG52YXIgUGluY2hab29tID1cbi8qKiBAY2xhc3MgKi9cbmZ1bmN0aW9uIChfc3VwZXIpIHtcbiAgX19leHRlbmRzKFBpbmNoWm9vbSwgX3N1cGVyKTtcbiAgLyoqXG4gICAqIEBwYXJhbSB7T3B0aW9ucz19IG9wdF9vcHRpb25zIE9wdGlvbnMuXG4gICAqL1xuXG5cbiAgZnVuY3Rpb24gUGluY2hab29tKG9wdF9vcHRpb25zKSB7XG4gICAgdmFyIF90aGlzID0gdGhpcztcblxuICAgIHZhciBvcHRpb25zID0gb3B0X29wdGlvbnMgPyBvcHRfb3B0aW9ucyA6IHt9O1xuICAgIHZhciBwb2ludGVyT3B0aW9ucyA9XG4gICAgLyoqIEB0eXBlIHtpbXBvcnQoXCIuL1BvaW50ZXIuanNcIikuT3B0aW9uc30gKi9cbiAgICBvcHRpb25zO1xuXG4gICAgaWYgKCFwb2ludGVyT3B0aW9ucy5zdG9wRG93bikge1xuICAgICAgcG9pbnRlck9wdGlvbnMuc3RvcERvd24gPSBGQUxTRTtcbiAgICB9XG5cbiAgICBfdGhpcyA9IF9zdXBlci5jYWxsKHRoaXMsIHBvaW50ZXJPcHRpb25zKSB8fCB0aGlzO1xuICAgIC8qKlxuICAgICAqIEBwcml2YXRlXG4gICAgICogQHR5cGUge2ltcG9ydChcIi4uL2Nvb3JkaW5hdGUuanNcIikuQ29vcmRpbmF0ZX1cbiAgICAgKi9cblxuICAgIF90aGlzLmFuY2hvcl8gPSBudWxsO1xuICAgIC8qKlxuICAgICAqIEBwcml2YXRlXG4gICAgICogQHR5cGUge251bWJlcn1cbiAgICAgKi9cblxuICAgIF90aGlzLmR1cmF0aW9uXyA9IG9wdGlvbnMuZHVyYXRpb24gIT09IHVuZGVmaW5lZCA/IG9wdGlvbnMuZHVyYXRpb24gOiA0MDA7XG4gICAgLyoqXG4gICAgICogQHByaXZhdGVcbiAgICAgKiBAdHlwZSB7bnVtYmVyfHVuZGVmaW5lZH1cbiAgICAgKi9cblxuICAgIF90aGlzLmxhc3REaXN0YW5jZV8gPSB1bmRlZmluZWQ7XG4gICAgLyoqXG4gICAgICogQHByaXZhdGVcbiAgICAgKiBAdHlwZSB7bnVtYmVyfVxuICAgICAqL1xuXG4gICAgX3RoaXMubGFzdFNjYWxlRGVsdGFfID0gMTtcbiAgICByZXR1cm4gX3RoaXM7XG4gIH1cbiAgLyoqXG4gICAqIEhhbmRsZSBwb2ludGVyIGRyYWcgZXZlbnRzLlxuICAgKiBAcGFyYW0ge2ltcG9ydChcIi4uL01hcEJyb3dzZXJFdmVudC5qc1wiKS5kZWZhdWx0fSBtYXBCcm93c2VyRXZlbnQgRXZlbnQuXG4gICAqL1xuXG5cbiAgUGluY2hab29tLnByb3RvdHlwZS5oYW5kbGVEcmFnRXZlbnQgPSBmdW5jdGlvbiAobWFwQnJvd3NlckV2ZW50KSB7XG4gICAgdmFyIHNjYWxlRGVsdGEgPSAxLjA7XG4gICAgdmFyIHRvdWNoMCA9IHRoaXMudGFyZ2V0UG9pbnRlcnNbMF07XG4gICAgdmFyIHRvdWNoMSA9IHRoaXMudGFyZ2V0UG9pbnRlcnNbMV07XG4gICAgdmFyIGR4ID0gdG91Y2gwLmNsaWVudFggLSB0b3VjaDEuY2xpZW50WDtcbiAgICB2YXIgZHkgPSB0b3VjaDAuY2xpZW50WSAtIHRvdWNoMS5jbGllbnRZOyAvLyBkaXN0YW5jZSBiZXR3ZWVuIHRvdWNoZXNcblxuICAgIHZhciBkaXN0YW5jZSA9IE1hdGguc3FydChkeCAqIGR4ICsgZHkgKiBkeSk7XG5cbiAgICBpZiAodGhpcy5sYXN0RGlzdGFuY2VfICE9PSB1bmRlZmluZWQpIHtcbiAgICAgIHNjYWxlRGVsdGEgPSB0aGlzLmxhc3REaXN0YW5jZV8gLyBkaXN0YW5jZTtcbiAgICB9XG5cbiAgICB0aGlzLmxhc3REaXN0YW5jZV8gPSBkaXN0YW5jZTtcbiAgICB2YXIgbWFwID0gbWFwQnJvd3NlckV2ZW50Lm1hcDtcbiAgICB2YXIgdmlldyA9IG1hcC5nZXRWaWV3KCk7XG5cbiAgICBpZiAoc2NhbGVEZWx0YSAhPSAxLjApIHtcbiAgICAgIHRoaXMubGFzdFNjYWxlRGVsdGFfID0gc2NhbGVEZWx0YTtcbiAgICB9IC8vIHNjYWxlIGFuY2hvciBwb2ludC5cblxuXG4gICAgdmFyIHZpZXdwb3J0UG9zaXRpb24gPSBtYXAuZ2V0Vmlld3BvcnQoKS5nZXRCb3VuZGluZ0NsaWVudFJlY3QoKTtcbiAgICB2YXIgY2VudHJvaWQgPSBjZW50cm9pZEZyb21Qb2ludGVycyh0aGlzLnRhcmdldFBvaW50ZXJzKTtcbiAgICBjZW50cm9pZFswXSAtPSB2aWV3cG9ydFBvc2l0aW9uLmxlZnQ7XG4gICAgY2VudHJvaWRbMV0gLT0gdmlld3BvcnRQb3NpdGlvbi50b3A7XG4gICAgdGhpcy5hbmNob3JfID0gbWFwLmdldENvb3JkaW5hdGVGcm9tUGl4ZWxJbnRlcm5hbChjZW50cm9pZCk7IC8vIHNjYWxlLCBieXBhc3MgdGhlIHJlc29sdXRpb24gY29uc3RyYWludFxuXG4gICAgbWFwLnJlbmRlcigpO1xuICAgIHZpZXcuYWRqdXN0UmVzb2x1dGlvbkludGVybmFsKHNjYWxlRGVsdGEsIHRoaXMuYW5jaG9yXyk7XG4gIH07XG4gIC8qKlxuICAgKiBIYW5kbGUgcG9pbnRlciB1cCBldmVudHMuXG4gICAqIEBwYXJhbSB7aW1wb3J0KFwiLi4vTWFwQnJvd3NlckV2ZW50LmpzXCIpLmRlZmF1bHR9IG1hcEJyb3dzZXJFdmVudCBFdmVudC5cbiAgICogQHJldHVybiB7Ym9vbGVhbn0gSWYgdGhlIGV2ZW50IHdhcyBjb25zdW1lZC5cbiAgICovXG5cblxuICBQaW5jaFpvb20ucHJvdG90eXBlLmhhbmRsZVVwRXZlbnQgPSBmdW5jdGlvbiAobWFwQnJvd3NlckV2ZW50KSB7XG4gICAgaWYgKHRoaXMudGFyZ2V0UG9pbnRlcnMubGVuZ3RoIDwgMikge1xuICAgICAgdmFyIG1hcCA9IG1hcEJyb3dzZXJFdmVudC5tYXA7XG4gICAgICB2YXIgdmlldyA9IG1hcC5nZXRWaWV3KCk7XG4gICAgICB2YXIgZGlyZWN0aW9uID0gdGhpcy5sYXN0U2NhbGVEZWx0YV8gPiAxID8gMSA6IC0xO1xuICAgICAgdmlldy5lbmRJbnRlcmFjdGlvbih0aGlzLmR1cmF0aW9uXywgZGlyZWN0aW9uKTtcbiAgICAgIHJldHVybiBmYWxzZTtcbiAgICB9IGVsc2Uge1xuICAgICAgcmV0dXJuIHRydWU7XG4gICAgfVxuICB9O1xuICAvKipcbiAgICogSGFuZGxlIHBvaW50ZXIgZG93biBldmVudHMuXG4gICAqIEBwYXJhbSB7aW1wb3J0KFwiLi4vTWFwQnJvd3NlckV2ZW50LmpzXCIpLmRlZmF1bHR9IG1hcEJyb3dzZXJFdmVudCBFdmVudC5cbiAgICogQHJldHVybiB7Ym9vbGVhbn0gSWYgdGhlIGV2ZW50IHdhcyBjb25zdW1lZC5cbiAgICovXG5cblxuICBQaW5jaFpvb20ucHJvdG90eXBlLmhhbmRsZURvd25FdmVudCA9IGZ1bmN0aW9uIChtYXBCcm93c2VyRXZlbnQpIHtcbiAgICBpZiAodGhpcy50YXJnZXRQb2ludGVycy5sZW5ndGggPj0gMikge1xuICAgICAgdmFyIG1hcCA9IG1hcEJyb3dzZXJFdmVudC5tYXA7XG4gICAgICB0aGlzLmFuY2hvcl8gPSBudWxsO1xuICAgICAgdGhpcy5sYXN0RGlzdGFuY2VfID0gdW5kZWZpbmVkO1xuICAgICAgdGhpcy5sYXN0U2NhbGVEZWx0YV8gPSAxO1xuXG4gICAgICBpZiAoIXRoaXMuaGFuZGxpbmdEb3duVXBTZXF1ZW5jZSkge1xuICAgICAgICBtYXAuZ2V0VmlldygpLmJlZ2luSW50ZXJhY3Rpb24oKTtcbiAgICAgIH1cblxuICAgICAgcmV0dXJuIHRydWU7XG4gICAgfSBlbHNlIHtcbiAgICAgIHJldHVybiBmYWxzZTtcbiAgICB9XG4gIH07XG5cbiAgcmV0dXJuIFBpbmNoWm9vbTtcbn0oUG9pbnRlckludGVyYWN0aW9uKTtcblxuZXhwb3J0IGRlZmF1bHQgUGluY2hab29tOyIsIi8qKlxuICogQG1vZHVsZSBvbC9pbnRlcmFjdGlvblxuICovXG5pbXBvcnQgQ29sbGVjdGlvbiBmcm9tICcuL0NvbGxlY3Rpb24uanMnO1xuaW1wb3J0IERvdWJsZUNsaWNrWm9vbSBmcm9tICcuL2ludGVyYWN0aW9uL0RvdWJsZUNsaWNrWm9vbS5qcyc7XG5pbXBvcnQgRHJhZ1BhbiBmcm9tICcuL2ludGVyYWN0aW9uL0RyYWdQYW4uanMnO1xuaW1wb3J0IERyYWdSb3RhdGUgZnJvbSAnLi9pbnRlcmFjdGlvbi9EcmFnUm90YXRlLmpzJztcbmltcG9ydCBEcmFnWm9vbSBmcm9tICcuL2ludGVyYWN0aW9uL0RyYWdab29tLmpzJztcbmltcG9ydCBLZXlib2FyZFBhbiBmcm9tICcuL2ludGVyYWN0aW9uL0tleWJvYXJkUGFuLmpzJztcbmltcG9ydCBLZXlib2FyZFpvb20gZnJvbSAnLi9pbnRlcmFjdGlvbi9LZXlib2FyZFpvb20uanMnO1xuaW1wb3J0IEtpbmV0aWMgZnJvbSAnLi9LaW5ldGljLmpzJztcbmltcG9ydCBNb3VzZVdoZWVsWm9vbSBmcm9tICcuL2ludGVyYWN0aW9uL01vdXNlV2hlZWxab29tLmpzJztcbmltcG9ydCBQaW5jaFJvdGF0ZSBmcm9tICcuL2ludGVyYWN0aW9uL1BpbmNoUm90YXRlLmpzJztcbmltcG9ydCBQaW5jaFpvb20gZnJvbSAnLi9pbnRlcmFjdGlvbi9QaW5jaFpvb20uanMnO1xuZXhwb3J0IHsgZGVmYXVsdCBhcyBEb3VibGVDbGlja1pvb20gfSBmcm9tICcuL2ludGVyYWN0aW9uL0RvdWJsZUNsaWNrWm9vbS5qcyc7XG5leHBvcnQgeyBkZWZhdWx0IGFzIERyYWdBbmREcm9wIH0gZnJvbSAnLi9pbnRlcmFjdGlvbi9EcmFnQW5kRHJvcC5qcyc7XG5leHBvcnQgeyBkZWZhdWx0IGFzIERyYWdCb3ggfSBmcm9tICcuL2ludGVyYWN0aW9uL0RyYWdCb3guanMnO1xuZXhwb3J0IHsgZGVmYXVsdCBhcyBEcmFnUGFuIH0gZnJvbSAnLi9pbnRlcmFjdGlvbi9EcmFnUGFuLmpzJztcbmV4cG9ydCB7IGRlZmF1bHQgYXMgRHJhZ1JvdGF0ZSB9IGZyb20gJy4vaW50ZXJhY3Rpb24vRHJhZ1JvdGF0ZS5qcyc7XG5leHBvcnQgeyBkZWZhdWx0IGFzIERyYWdSb3RhdGVBbmRab29tIH0gZnJvbSAnLi9pbnRlcmFjdGlvbi9EcmFnUm90YXRlQW5kWm9vbS5qcyc7XG5leHBvcnQgeyBkZWZhdWx0IGFzIERyYWdab29tIH0gZnJvbSAnLi9pbnRlcmFjdGlvbi9EcmFnWm9vbS5qcyc7XG5leHBvcnQgeyBkZWZhdWx0IGFzIERyYXcgfSBmcm9tICcuL2ludGVyYWN0aW9uL0RyYXcuanMnO1xuZXhwb3J0IHsgZGVmYXVsdCBhcyBFeHRlbnQgfSBmcm9tICcuL2ludGVyYWN0aW9uL0V4dGVudC5qcyc7XG5leHBvcnQgeyBkZWZhdWx0IGFzIEludGVyYWN0aW9uIH0gZnJvbSAnLi9pbnRlcmFjdGlvbi9JbnRlcmFjdGlvbi5qcyc7XG5leHBvcnQgeyBkZWZhdWx0IGFzIEtleWJvYXJkUGFuIH0gZnJvbSAnLi9pbnRlcmFjdGlvbi9LZXlib2FyZFBhbi5qcyc7XG5leHBvcnQgeyBkZWZhdWx0IGFzIEtleWJvYXJkWm9vbSB9IGZyb20gJy4vaW50ZXJhY3Rpb24vS2V5Ym9hcmRab29tLmpzJztcbmV4cG9ydCB7IGRlZmF1bHQgYXMgTW9kaWZ5IH0gZnJvbSAnLi9pbnRlcmFjdGlvbi9Nb2RpZnkuanMnO1xuZXhwb3J0IHsgZGVmYXVsdCBhcyBNb3VzZVdoZWVsWm9vbSB9IGZyb20gJy4vaW50ZXJhY3Rpb24vTW91c2VXaGVlbFpvb20uanMnO1xuZXhwb3J0IHsgZGVmYXVsdCBhcyBQaW5jaFJvdGF0ZSB9IGZyb20gJy4vaW50ZXJhY3Rpb24vUGluY2hSb3RhdGUuanMnO1xuZXhwb3J0IHsgZGVmYXVsdCBhcyBQaW5jaFpvb20gfSBmcm9tICcuL2ludGVyYWN0aW9uL1BpbmNoWm9vbS5qcyc7XG5leHBvcnQgeyBkZWZhdWx0IGFzIFBvaW50ZXIgfSBmcm9tICcuL2ludGVyYWN0aW9uL1BvaW50ZXIuanMnO1xuZXhwb3J0IHsgZGVmYXVsdCBhcyBTZWxlY3QgfSBmcm9tICcuL2ludGVyYWN0aW9uL1NlbGVjdC5qcyc7XG5leHBvcnQgeyBkZWZhdWx0IGFzIFNuYXAgfSBmcm9tICcuL2ludGVyYWN0aW9uL1NuYXAuanMnO1xuZXhwb3J0IHsgZGVmYXVsdCBhcyBUcmFuc2xhdGUgfSBmcm9tICcuL2ludGVyYWN0aW9uL1RyYW5zbGF0ZS5qcyc7XG4vKipcbiAqIEB0eXBlZGVmIHtPYmplY3R9IERlZmF1bHRzT3B0aW9uc1xuICogQHByb3BlcnR5IHtib29sZWFufSBbYWx0U2hpZnREcmFnUm90YXRlPXRydWVdIFdoZXRoZXIgQWx0LVNoaWZ0LWRyYWcgcm90YXRlIGlzXG4gKiBkZXNpcmVkLlxuICogQHByb3BlcnR5IHtib29sZWFufSBbb25Gb2N1c09ubHk9ZmFsc2VdIEludGVyYWN0IG9ubHkgd2hlbiB0aGUgbWFwIGhhcyB0aGVcbiAqIGZvY3VzLiBUaGlzIGFmZmVjdHMgdGhlIGBNb3VzZVdoZWVsWm9vbWAgYW5kIGBEcmFnUGFuYCBpbnRlcmFjdGlvbnMgYW5kIGlzXG4gKiB1c2VmdWwgd2hlbiBwYWdlIHNjcm9sbCBpcyBkZXNpcmVkIGZvciBtYXBzIHRoYXQgZG8gbm90IGhhdmUgdGhlIGJyb3dzZXInc1xuICogZm9jdXMuXG4gKiBAcHJvcGVydHkge2Jvb2xlYW59IFtkb3VibGVDbGlja1pvb209dHJ1ZV0gV2hldGhlciBkb3VibGUgY2xpY2sgem9vbSBpc1xuICogZGVzaXJlZC5cbiAqIEBwcm9wZXJ0eSB7Ym9vbGVhbn0gW2tleWJvYXJkPXRydWVdIFdoZXRoZXIga2V5Ym9hcmQgaW50ZXJhY3Rpb24gaXMgZGVzaXJlZC5cbiAqIEBwcm9wZXJ0eSB7Ym9vbGVhbn0gW21vdXNlV2hlZWxab29tPXRydWVdIFdoZXRoZXIgbW91c2V3aGVlbCB6b29tIGlzIGRlc2lyZWQuXG4gKiBAcHJvcGVydHkge2Jvb2xlYW59IFtzaGlmdERyYWdab29tPXRydWVdIFdoZXRoZXIgU2hpZnQtZHJhZyB6b29tIGlzIGRlc2lyZWQuXG4gKiBAcHJvcGVydHkge2Jvb2xlYW59IFtkcmFnUGFuPXRydWVdIFdoZXRoZXIgZHJhZyBwYW4gaXMgZGVzaXJlZC5cbiAqIEBwcm9wZXJ0eSB7Ym9vbGVhbn0gW3BpbmNoUm90YXRlPXRydWVdIFdoZXRoZXIgcGluY2ggcm90YXRlIGlzIGRlc2lyZWQuXG4gKiBAcHJvcGVydHkge2Jvb2xlYW59IFtwaW5jaFpvb209dHJ1ZV0gV2hldGhlciBwaW5jaCB6b29tIGlzIGRlc2lyZWQuXG4gKiBAcHJvcGVydHkge251bWJlcn0gW3pvb21EZWx0YV0gWm9vbSBsZXZlbCBkZWx0YSB3aGVuIHVzaW5nIGtleWJvYXJkIG9yIGRvdWJsZSBjbGljayB6b29tLlxuICogQHByb3BlcnR5IHtudW1iZXJ9IFt6b29tRHVyYXRpb25dIER1cmF0aW9uIG9mIHRoZSB6b29tIGFuaW1hdGlvbiBpblxuICogbWlsbGlzZWNvbmRzLlxuICovXG5cbi8qKlxuICogU2V0IG9mIGludGVyYWN0aW9ucyBpbmNsdWRlZCBpbiBtYXBzIGJ5IGRlZmF1bHQuIFNwZWNpZmljIGludGVyYWN0aW9ucyBjYW4gYmVcbiAqIGV4Y2x1ZGVkIGJ5IHNldHRpbmcgdGhlIGFwcHJvcHJpYXRlIG9wdGlvbiB0byBmYWxzZSBpbiB0aGUgY29uc3RydWN0b3JcbiAqIG9wdGlvbnMsIGJ1dCB0aGUgb3JkZXIgb2YgdGhlIGludGVyYWN0aW9ucyBpcyBmaXhlZC4gIElmIHlvdSB3YW50IHRvIHNwZWNpZnlcbiAqIGEgZGlmZmVyZW50IG9yZGVyIGZvciBpbnRlcmFjdGlvbnMsIHlvdSB3aWxsIG5lZWQgdG8gY3JlYXRlIHlvdXIgb3duXG4gKiB7QGxpbmsgbW9kdWxlOm9sL2ludGVyYWN0aW9uL0ludGVyYWN0aW9ufSBpbnN0YW5jZXMgYW5kIGluc2VydFxuICogdGhlbSBpbnRvIGEge0BsaW5rIG1vZHVsZTpvbC9Db2xsZWN0aW9ufSBpbiB0aGUgb3JkZXIgeW91IHdhbnRcbiAqIGJlZm9yZSBjcmVhdGluZyB5b3VyIHtAbGluayBtb2R1bGU6b2wvTWFwfk1hcH0gaW5zdGFuY2UuIENoYW5naW5nIHRoZSBvcmRlciBjYW5cbiAqIGJlIG9mIGludGVyZXN0IGlmIHRoZSBldmVudCBwcm9wYWdhdGlvbiBuZWVkcyB0byBiZSBzdG9wcGVkIGF0IGEgcG9pbnQuXG4gKiBUaGUgZGVmYXVsdCBzZXQgb2YgaW50ZXJhY3Rpb25zLCBpbiBzZXF1ZW5jZSwgaXM6XG4gKiAqIHtAbGluayBtb2R1bGU6b2wvaW50ZXJhY3Rpb24vRHJhZ1JvdGF0ZX5EcmFnUm90YXRlfVxuICogKiB7QGxpbmsgbW9kdWxlOm9sL2ludGVyYWN0aW9uL0RvdWJsZUNsaWNrWm9vbX5Eb3VibGVDbGlja1pvb219XG4gKiAqIHtAbGluayBtb2R1bGU6b2wvaW50ZXJhY3Rpb24vRHJhZ1Bhbn5EcmFnUGFufVxuICogKiB7QGxpbmsgbW9kdWxlOm9sL2ludGVyYWN0aW9uL1BpbmNoUm90YXRlflBpbmNoUm90YXRlfVxuICogKiB7QGxpbmsgbW9kdWxlOm9sL2ludGVyYWN0aW9uL1BpbmNoWm9vbX5QaW5jaFpvb219XG4gKiAqIHtAbGluayBtb2R1bGU6b2wvaW50ZXJhY3Rpb24vS2V5Ym9hcmRQYW5+S2V5Ym9hcmRQYW59XG4gKiAqIHtAbGluayBtb2R1bGU6b2wvaW50ZXJhY3Rpb24vS2V5Ym9hcmRab29tfktleWJvYXJkWm9vbX1cbiAqICoge0BsaW5rIG1vZHVsZTpvbC9pbnRlcmFjdGlvbi9Nb3VzZVdoZWVsWm9vbX5Nb3VzZVdoZWVsWm9vbX1cbiAqICoge0BsaW5rIG1vZHVsZTpvbC9pbnRlcmFjdGlvbi9EcmFnWm9vbX5EcmFnWm9vbX1cbiAqXG4gKiBAcGFyYW0ge0RlZmF1bHRzT3B0aW9ucz19IG9wdF9vcHRpb25zIERlZmF1bHRzIG9wdGlvbnMuXG4gKiBAcmV0dXJuIHtpbXBvcnQoXCIuL0NvbGxlY3Rpb24uanNcIikuZGVmYXVsdDxpbXBvcnQoXCIuL2ludGVyYWN0aW9uL0ludGVyYWN0aW9uLmpzXCIpLmRlZmF1bHQ+fVxuICogQSBjb2xsZWN0aW9uIG9mIGludGVyYWN0aW9ucyB0byBiZSB1c2VkIHdpdGggdGhlIHtAbGluayBtb2R1bGU6b2wvTWFwfk1hcH1cbiAqIGNvbnN0cnVjdG9yJ3MgYGludGVyYWN0aW9uc2Agb3B0aW9uLlxuICogQGFwaVxuICovXG5cbmV4cG9ydCBmdW5jdGlvbiBkZWZhdWx0cyhvcHRfb3B0aW9ucykge1xuICB2YXIgb3B0aW9ucyA9IG9wdF9vcHRpb25zID8gb3B0X29wdGlvbnMgOiB7fTtcbiAgdmFyIGludGVyYWN0aW9ucyA9IG5ldyBDb2xsZWN0aW9uKCk7XG4gIHZhciBraW5ldGljID0gbmV3IEtpbmV0aWMoLTAuMDA1LCAwLjA1LCAxMDApO1xuICB2YXIgYWx0U2hpZnREcmFnUm90YXRlID0gb3B0aW9ucy5hbHRTaGlmdERyYWdSb3RhdGUgIT09IHVuZGVmaW5lZCA/IG9wdGlvbnMuYWx0U2hpZnREcmFnUm90YXRlIDogdHJ1ZTtcblxuICBpZiAoYWx0U2hpZnREcmFnUm90YXRlKSB7XG4gICAgaW50ZXJhY3Rpb25zLnB1c2gobmV3IERyYWdSb3RhdGUoKSk7XG4gIH1cblxuICB2YXIgZG91YmxlQ2xpY2tab29tID0gb3B0aW9ucy5kb3VibGVDbGlja1pvb20gIT09IHVuZGVmaW5lZCA/IG9wdGlvbnMuZG91YmxlQ2xpY2tab29tIDogdHJ1ZTtcblxuICBpZiAoZG91YmxlQ2xpY2tab29tKSB7XG4gICAgaW50ZXJhY3Rpb25zLnB1c2gobmV3IERvdWJsZUNsaWNrWm9vbSh7XG4gICAgICBkZWx0YTogb3B0aW9ucy56b29tRGVsdGEsXG4gICAgICBkdXJhdGlvbjogb3B0aW9ucy56b29tRHVyYXRpb25cbiAgICB9KSk7XG4gIH1cblxuICB2YXIgZHJhZ1BhbiA9IG9wdGlvbnMuZHJhZ1BhbiAhPT0gdW5kZWZpbmVkID8gb3B0aW9ucy5kcmFnUGFuIDogdHJ1ZTtcblxuICBpZiAoZHJhZ1Bhbikge1xuICAgIGludGVyYWN0aW9ucy5wdXNoKG5ldyBEcmFnUGFuKHtcbiAgICAgIG9uRm9jdXNPbmx5OiBvcHRpb25zLm9uRm9jdXNPbmx5LFxuICAgICAga2luZXRpYzoga2luZXRpY1xuICAgIH0pKTtcbiAgfVxuXG4gIHZhciBwaW5jaFJvdGF0ZSA9IG9wdGlvbnMucGluY2hSb3RhdGUgIT09IHVuZGVmaW5lZCA/IG9wdGlvbnMucGluY2hSb3RhdGUgOiB0cnVlO1xuXG4gIGlmIChwaW5jaFJvdGF0ZSkge1xuICAgIGludGVyYWN0aW9ucy5wdXNoKG5ldyBQaW5jaFJvdGF0ZSgpKTtcbiAgfVxuXG4gIHZhciBwaW5jaFpvb20gPSBvcHRpb25zLnBpbmNoWm9vbSAhPT0gdW5kZWZpbmVkID8gb3B0aW9ucy5waW5jaFpvb20gOiB0cnVlO1xuXG4gIGlmIChwaW5jaFpvb20pIHtcbiAgICBpbnRlcmFjdGlvbnMucHVzaChuZXcgUGluY2hab29tKHtcbiAgICAgIGR1cmF0aW9uOiBvcHRpb25zLnpvb21EdXJhdGlvblxuICAgIH0pKTtcbiAgfVxuXG4gIHZhciBrZXlib2FyZCA9IG9wdGlvbnMua2V5Ym9hcmQgIT09IHVuZGVmaW5lZCA/IG9wdGlvbnMua2V5Ym9hcmQgOiB0cnVlO1xuXG4gIGlmIChrZXlib2FyZCkge1xuICAgIGludGVyYWN0aW9ucy5wdXNoKG5ldyBLZXlib2FyZFBhbigpKTtcbiAgICBpbnRlcmFjdGlvbnMucHVzaChuZXcgS2V5Ym9hcmRab29tKHtcbiAgICAgIGRlbHRhOiBvcHRpb25zLnpvb21EZWx0YSxcbiAgICAgIGR1cmF0aW9uOiBvcHRpb25zLnpvb21EdXJhdGlvblxuICAgIH0pKTtcbiAgfVxuXG4gIHZhciBtb3VzZVdoZWVsWm9vbSA9IG9wdGlvbnMubW91c2VXaGVlbFpvb20gIT09IHVuZGVmaW5lZCA/IG9wdGlvbnMubW91c2VXaGVlbFpvb20gOiB0cnVlO1xuXG4gIGlmIChtb3VzZVdoZWVsWm9vbSkge1xuICAgIGludGVyYWN0aW9ucy5wdXNoKG5ldyBNb3VzZVdoZWVsWm9vbSh7XG4gICAgICBvbkZvY3VzT25seTogb3B0aW9ucy5vbkZvY3VzT25seSxcbiAgICAgIGR1cmF0aW9uOiBvcHRpb25zLnpvb21EdXJhdGlvblxuICAgIH0pKTtcbiAgfVxuXG4gIHZhciBzaGlmdERyYWdab29tID0gb3B0aW9ucy5zaGlmdERyYWdab29tICE9PSB1bmRlZmluZWQgPyBvcHRpb25zLnNoaWZ0RHJhZ1pvb20gOiB0cnVlO1xuXG4gIGlmIChzaGlmdERyYWdab29tKSB7XG4gICAgaW50ZXJhY3Rpb25zLnB1c2gobmV3IERyYWdab29tKHtcbiAgICAgIGR1cmF0aW9uOiBvcHRpb25zLnpvb21EdXJhdGlvblxuICAgIH0pKTtcbiAgfVxuXG4gIHJldHVybiBpbnRlcmFjdGlvbnM7XG59IiwidmFyIF9fZXh0ZW5kcyA9IHRoaXMgJiYgdGhpcy5fX2V4dGVuZHMgfHwgZnVuY3Rpb24gKCkge1xuICB2YXIgX2V4dGVuZFN0YXRpY3MgPSBmdW5jdGlvbiBleHRlbmRTdGF0aWNzKGQsIGIpIHtcbiAgICBfZXh0ZW5kU3RhdGljcyA9IE9iamVjdC5zZXRQcm90b3R5cGVPZiB8fCB7XG4gICAgICBfX3Byb3RvX186IFtdXG4gICAgfSBpbnN0YW5jZW9mIEFycmF5ICYmIGZ1bmN0aW9uIChkLCBiKSB7XG4gICAgICBkLl9fcHJvdG9fXyA9IGI7XG4gICAgfSB8fCBmdW5jdGlvbiAoZCwgYikge1xuICAgICAgZm9yICh2YXIgcCBpbiBiKSB7XG4gICAgICAgIGlmIChPYmplY3QucHJvdG90eXBlLmhhc093blByb3BlcnR5LmNhbGwoYiwgcCkpIGRbcF0gPSBiW3BdO1xuICAgICAgfVxuICAgIH07XG5cbiAgICByZXR1cm4gX2V4dGVuZFN0YXRpY3MoZCwgYik7XG4gIH07XG5cbiAgcmV0dXJuIGZ1bmN0aW9uIChkLCBiKSB7XG4gICAgX2V4dGVuZFN0YXRpY3MoZCwgYik7XG5cbiAgICBmdW5jdGlvbiBfXygpIHtcbiAgICAgIHRoaXMuY29uc3RydWN0b3IgPSBkO1xuICAgIH1cblxuICAgIGQucHJvdG90eXBlID0gYiA9PT0gbnVsbCA/IE9iamVjdC5jcmVhdGUoYikgOiAoX18ucHJvdG90eXBlID0gYi5wcm90b3R5cGUsIG5ldyBfXygpKTtcbiAgfTtcbn0oKTtcbi8qKlxuICogQG1vZHVsZSBvbC9NYXBcbiAqL1xuXG5cbmltcG9ydCBDb21wb3NpdGVNYXBSZW5kZXJlciBmcm9tICcuL3JlbmRlcmVyL0NvbXBvc2l0ZS5qcyc7XG5pbXBvcnQgUGx1Z2dhYmxlTWFwIGZyb20gJy4vUGx1Z2dhYmxlTWFwLmpzJztcbmltcG9ydCB7IGFzc2lnbiB9IGZyb20gJy4vb2JqLmpzJztcbmltcG9ydCB7IGRlZmF1bHRzIGFzIGRlZmF1bHRDb250cm9scyB9IGZyb20gJy4vY29udHJvbC5qcyc7XG5pbXBvcnQgeyBkZWZhdWx0cyBhcyBkZWZhdWx0SW50ZXJhY3Rpb25zIH0gZnJvbSAnLi9pbnRlcmFjdGlvbi5qcyc7XG4vKipcbiAqIEBjbGFzc2Rlc2NcbiAqIFRoZSBtYXAgaXMgdGhlIGNvcmUgY29tcG9uZW50IG9mIE9wZW5MYXllcnMuIEZvciBhIG1hcCB0byByZW5kZXIsIGEgdmlldyxcbiAqIG9uZSBvciBtb3JlIGxheWVycywgYW5kIGEgdGFyZ2V0IGNvbnRhaW5lciBhcmUgbmVlZGVkOlxuICpcbiAqICAgICBpbXBvcnQgTWFwIGZyb20gJ29sL01hcCc7XG4gKiAgICAgaW1wb3J0IFZpZXcgZnJvbSAnb2wvVmlldyc7XG4gKiAgICAgaW1wb3J0IFRpbGVMYXllciBmcm9tICdvbC9sYXllci9UaWxlJztcbiAqICAgICBpbXBvcnQgT1NNIGZyb20gJ29sL3NvdXJjZS9PU00nO1xuICpcbiAqICAgICB2YXIgbWFwID0gbmV3IE1hcCh7XG4gKiAgICAgICB2aWV3OiBuZXcgVmlldyh7XG4gKiAgICAgICAgIGNlbnRlcjogWzAsIDBdLFxuICogICAgICAgICB6b29tOiAxXG4gKiAgICAgICB9KSxcbiAqICAgICAgIGxheWVyczogW1xuICogICAgICAgICBuZXcgVGlsZUxheWVyKHtcbiAqICAgICAgICAgICBzb3VyY2U6IG5ldyBPU00oKVxuICogICAgICAgICB9KVxuICogICAgICAgXSxcbiAqICAgICAgIHRhcmdldDogJ21hcCdcbiAqICAgICB9KTtcbiAqXG4gKiBUaGUgYWJvdmUgc25pcHBldCBjcmVhdGVzIGEgbWFwIHVzaW5nIGEge0BsaW5rIG1vZHVsZTpvbC9sYXllci9UaWxlfSB0b1xuICogZGlzcGxheSB7QGxpbmsgbW9kdWxlOm9sL3NvdXJjZS9PU01+T1NNfSBPU00gZGF0YSBhbmQgcmVuZGVyIGl0IHRvIGEgRE9NXG4gKiBlbGVtZW50IHdpdGggdGhlIGlkIGBtYXBgLlxuICpcbiAqIFRoZSBjb25zdHJ1Y3RvciBwbGFjZXMgYSB2aWV3cG9ydCBjb250YWluZXIgKHdpdGggQ1NTIGNsYXNzIG5hbWVcbiAqIGBvbC12aWV3cG9ydGApIGluIHRoZSB0YXJnZXQgZWxlbWVudCAoc2VlIGBnZXRWaWV3cG9ydCgpYCksIGFuZCB0aGVuIHR3b1xuICogZnVydGhlciBlbGVtZW50cyB3aXRoaW4gdGhlIHZpZXdwb3J0OiBvbmUgd2l0aCBDU1MgY2xhc3MgbmFtZVxuICogYG9sLW92ZXJsYXljb250YWluZXItc3RvcGV2ZW50YCBmb3IgY29udHJvbHMgYW5kIHNvbWUgb3ZlcmxheXMsIGFuZCBvbmUgd2l0aFxuICogQ1NTIGNsYXNzIG5hbWUgYG9sLW92ZXJsYXljb250YWluZXJgIGZvciBvdGhlciBvdmVybGF5cyAoc2VlIHRoZSBgc3RvcEV2ZW50YFxuICogb3B0aW9uIG9mIHtAbGluayBtb2R1bGU6b2wvT3ZlcmxheX5PdmVybGF5fSBmb3IgdGhlIGRpZmZlcmVuY2UpLiBUaGUgbWFwXG4gKiBpdHNlbGYgaXMgcGxhY2VkIGluIGEgZnVydGhlciBlbGVtZW50IHdpdGhpbiB0aGUgdmlld3BvcnQuXG4gKlxuICogTGF5ZXJzIGFyZSBzdG9yZWQgYXMgYSB7QGxpbmsgbW9kdWxlOm9sL0NvbGxlY3Rpb25+Q29sbGVjdGlvbn0gaW5cbiAqIGxheWVyR3JvdXBzLiBBIHRvcC1sZXZlbCBncm91cCBpcyBwcm92aWRlZCBieSB0aGUgbGlicmFyeS4gVGhpcyBpcyB3aGF0IGlzXG4gKiBhY2Nlc3NlZCBieSBgZ2V0TGF5ZXJHcm91cGAgYW5kIGBzZXRMYXllckdyb3VwYC4gTGF5ZXJzIGVudGVyZWQgaW4gdGhlXG4gKiBvcHRpb25zIGFyZSBhZGRlZCB0byB0aGlzIGdyb3VwLCBhbmQgYGFkZExheWVyYCBhbmQgYHJlbW92ZUxheWVyYCBjaGFuZ2UgdGhlXG4gKiBsYXllciBjb2xsZWN0aW9uIGluIHRoZSBncm91cC4gYGdldExheWVyc2AgaXMgYSBjb252ZW5pZW5jZSBmdW5jdGlvbiBmb3JcbiAqIGBnZXRMYXllckdyb3VwKCkuZ2V0TGF5ZXJzKClgLiBOb3RlIHRoYXQge0BsaW5rIG1vZHVsZTpvbC9sYXllci9Hcm91cH5Hcm91cH1cbiAqIGlzIGEgc3ViY2xhc3Mgb2Yge0BsaW5rIG1vZHVsZTpvbC9sYXllci9CYXNlfSwgc28gbGF5ZXJzIGVudGVyZWQgaW4gdGhlXG4gKiBvcHRpb25zIG9yIGFkZGVkIHdpdGggYGFkZExheWVyYCBjYW4gYmUgZ3JvdXBzLCB3aGljaCBjYW4gY29udGFpbiBmdXJ0aGVyXG4gKiBncm91cHMsIGFuZCBzbyBvbi5cbiAqXG4gKiBAYXBpXG4gKi9cblxudmFyIE1hcCA9XG4vKiogQGNsYXNzICovXG5mdW5jdGlvbiAoX3N1cGVyKSB7XG4gIF9fZXh0ZW5kcyhNYXAsIF9zdXBlcik7XG4gIC8qKlxuICAgKiBAcGFyYW0ge2ltcG9ydChcIi4vUGx1Z2dhYmxlTWFwLmpzXCIpLk1hcE9wdGlvbnN9IG9wdGlvbnMgTWFwIG9wdGlvbnMuXG4gICAqL1xuXG5cbiAgZnVuY3Rpb24gTWFwKG9wdGlvbnMpIHtcbiAgICB2YXIgX3RoaXMgPSB0aGlzO1xuXG4gICAgb3B0aW9ucyA9IGFzc2lnbih7fSwgb3B0aW9ucyk7XG5cbiAgICBpZiAoIW9wdGlvbnMuY29udHJvbHMpIHtcbiAgICAgIG9wdGlvbnMuY29udHJvbHMgPSBkZWZhdWx0Q29udHJvbHMoKTtcbiAgICB9XG5cbiAgICBpZiAoIW9wdGlvbnMuaW50ZXJhY3Rpb25zKSB7XG4gICAgICBvcHRpb25zLmludGVyYWN0aW9ucyA9IGRlZmF1bHRJbnRlcmFjdGlvbnMoe1xuICAgICAgICBvbkZvY3VzT25seTogdHJ1ZVxuICAgICAgfSk7XG4gICAgfVxuXG4gICAgX3RoaXMgPSBfc3VwZXIuY2FsbCh0aGlzLCBvcHRpb25zKSB8fCB0aGlzO1xuICAgIHJldHVybiBfdGhpcztcbiAgfVxuXG4gIE1hcC5wcm90b3R5cGUuY3JlYXRlUmVuZGVyZXIgPSBmdW5jdGlvbiAoKSB7XG4gICAgcmV0dXJuIG5ldyBDb21wb3NpdGVNYXBSZW5kZXJlcih0aGlzKTtcbiAgfTtcblxuICByZXR1cm4gTWFwO1xufShQbHVnZ2FibGVNYXApO1xuXG5leHBvcnQgZGVmYXVsdCBNYXA7IiwiLyoqXG4gKiBAbW9kdWxlIG9sL2xheWVyL1RpbGVQcm9wZXJ0eVxuICovXG5cbi8qKlxuICogQGVudW0ge3N0cmluZ31cbiAqL1xuZXhwb3J0IGRlZmF1bHQge1xuICBQUkVMT0FEOiAncHJlbG9hZCcsXG4gIFVTRV9JTlRFUklNX1RJTEVTX09OX0VSUk9SOiAndXNlSW50ZXJpbVRpbGVzT25FcnJvcidcbn07IiwidmFyIF9fZXh0ZW5kcyA9IHRoaXMgJiYgdGhpcy5fX2V4dGVuZHMgfHwgZnVuY3Rpb24gKCkge1xuICB2YXIgX2V4dGVuZFN0YXRpY3MgPSBmdW5jdGlvbiBleHRlbmRTdGF0aWNzKGQsIGIpIHtcbiAgICBfZXh0ZW5kU3RhdGljcyA9IE9iamVjdC5zZXRQcm90b3R5cGVPZiB8fCB7XG4gICAgICBfX3Byb3RvX186IFtdXG4gICAgfSBpbnN0YW5jZW9mIEFycmF5ICYmIGZ1bmN0aW9uIChkLCBiKSB7XG4gICAgICBkLl9fcHJvdG9fXyA9IGI7XG4gICAgfSB8fCBmdW5jdGlvbiAoZCwgYikge1xuICAgICAgZm9yICh2YXIgcCBpbiBiKSB7XG4gICAgICAgIGlmIChPYmplY3QucHJvdG90eXBlLmhhc093blByb3BlcnR5LmNhbGwoYiwgcCkpIGRbcF0gPSBiW3BdO1xuICAgICAgfVxuICAgIH07XG5cbiAgICByZXR1cm4gX2V4dGVuZFN0YXRpY3MoZCwgYik7XG4gIH07XG5cbiAgcmV0dXJuIGZ1bmN0aW9uIChkLCBiKSB7XG4gICAgX2V4dGVuZFN0YXRpY3MoZCwgYik7XG5cbiAgICBmdW5jdGlvbiBfXygpIHtcbiAgICAgIHRoaXMuY29uc3RydWN0b3IgPSBkO1xuICAgIH1cblxuICAgIGQucHJvdG90eXBlID0gYiA9PT0gbnVsbCA/IE9iamVjdC5jcmVhdGUoYikgOiAoX18ucHJvdG90eXBlID0gYi5wcm90b3R5cGUsIG5ldyBfXygpKTtcbiAgfTtcbn0oKTtcbi8qKlxuICogQG1vZHVsZSBvbC9sYXllci9CYXNlVGlsZVxuICovXG5cblxuaW1wb3J0IExheWVyIGZyb20gJy4vTGF5ZXIuanMnO1xuaW1wb3J0IFRpbGVQcm9wZXJ0eSBmcm9tICcuL1RpbGVQcm9wZXJ0eS5qcyc7XG5pbXBvcnQgeyBhc3NpZ24gfSBmcm9tICcuLi9vYmouanMnO1xuLyoqXG4gKiBAdHlwZWRlZiB7T2JqZWN0fSBPcHRpb25zXG4gKiBAcHJvcGVydHkge3N0cmluZ30gW2NsYXNzTmFtZT0nb2wtbGF5ZXInXSBBIENTUyBjbGFzcyBuYW1lIHRvIHNldCB0byB0aGUgbGF5ZXIgZWxlbWVudC5cbiAqIEBwcm9wZXJ0eSB7bnVtYmVyfSBbb3BhY2l0eT0xXSBPcGFjaXR5ICgwLCAxKS5cbiAqIEBwcm9wZXJ0eSB7Ym9vbGVhbn0gW3Zpc2libGU9dHJ1ZV0gVmlzaWJpbGl0eS5cbiAqIEBwcm9wZXJ0eSB7aW1wb3J0KFwiLi4vZXh0ZW50LmpzXCIpLkV4dGVudH0gW2V4dGVudF0gVGhlIGJvdW5kaW5nIGV4dGVudCBmb3IgbGF5ZXIgcmVuZGVyaW5nLiAgVGhlIGxheWVyIHdpbGwgbm90IGJlXG4gKiByZW5kZXJlZCBvdXRzaWRlIG9mIHRoaXMgZXh0ZW50LlxuICogQHByb3BlcnR5IHtudW1iZXJ9IFt6SW5kZXhdIFRoZSB6LWluZGV4IGZvciBsYXllciByZW5kZXJpbmcuICBBdCByZW5kZXJpbmcgdGltZSwgdGhlIGxheWVyc1xuICogd2lsbCBiZSBvcmRlcmVkLCBmaXJzdCBieSBaLWluZGV4IGFuZCB0aGVuIGJ5IHBvc2l0aW9uLiBXaGVuIGB1bmRlZmluZWRgLCBhIGB6SW5kZXhgIG9mIDAgaXMgYXNzdW1lZFxuICogZm9yIGxheWVycyB0aGF0IGFyZSBhZGRlZCB0byB0aGUgbWFwJ3MgYGxheWVyc2AgY29sbGVjdGlvbiwgb3IgYEluZmluaXR5YCB3aGVuIHRoZSBsYXllcidzIGBzZXRNYXAoKWBcbiAqIG1ldGhvZCB3YXMgdXNlZC5cbiAqIEBwcm9wZXJ0eSB7bnVtYmVyfSBbbWluUmVzb2x1dGlvbl0gVGhlIG1pbmltdW0gcmVzb2x1dGlvbiAoaW5jbHVzaXZlKSBhdCB3aGljaCB0aGlzIGxheWVyIHdpbGwgYmVcbiAqIHZpc2libGUuXG4gKiBAcHJvcGVydHkge251bWJlcn0gW21heFJlc29sdXRpb25dIFRoZSBtYXhpbXVtIHJlc29sdXRpb24gKGV4Y2x1c2l2ZSkgYmVsb3cgd2hpY2ggdGhpcyBsYXllciB3aWxsXG4gKiBiZSB2aXNpYmxlLlxuICogQHByb3BlcnR5IHtudW1iZXJ9IFttaW5ab29tXSBUaGUgbWluaW11bSB2aWV3IHpvb20gbGV2ZWwgKGV4Y2x1c2l2ZSkgYWJvdmUgd2hpY2ggdGhpcyBsYXllciB3aWxsIGJlXG4gKiB2aXNpYmxlLlxuICogQHByb3BlcnR5IHtudW1iZXJ9IFttYXhab29tXSBUaGUgbWF4aW11bSB2aWV3IHpvb20gbGV2ZWwgKGluY2x1c2l2ZSkgYXQgd2hpY2ggdGhpcyBsYXllciB3aWxsXG4gKiBiZSB2aXNpYmxlLlxuICogQHByb3BlcnR5IHtudW1iZXJ9IFtwcmVsb2FkPTBdIFByZWxvYWQuIExvYWQgbG93LXJlc29sdXRpb24gdGlsZXMgdXAgdG8gYHByZWxvYWRgIGxldmVscy4gYDBgXG4gKiBtZWFucyBubyBwcmVsb2FkaW5nLlxuICogQHByb3BlcnR5IHtpbXBvcnQoXCIuLi9zb3VyY2UvVGlsZS5qc1wiKS5kZWZhdWx0fSBbc291cmNlXSBTb3VyY2UgZm9yIHRoaXMgbGF5ZXIuXG4gKiBAcHJvcGVydHkge2ltcG9ydChcIi4uL1BsdWdnYWJsZU1hcC5qc1wiKS5kZWZhdWx0fSBbbWFwXSBTZXRzIHRoZSBsYXllciBhcyBvdmVybGF5IG9uIGEgbWFwLiBUaGUgbWFwIHdpbGwgbm90IG1hbmFnZVxuICogdGhpcyBsYXllciBpbiBpdHMgbGF5ZXJzIGNvbGxlY3Rpb24sIGFuZCB0aGUgbGF5ZXIgd2lsbCBiZSByZW5kZXJlZCBvbiB0b3AuIFRoaXMgaXMgdXNlZnVsIGZvclxuICogdGVtcG9yYXJ5IGxheWVycy4gVGhlIHN0YW5kYXJkIHdheSB0byBhZGQgYSBsYXllciB0byBhIG1hcCBhbmQgaGF2ZSBpdCBtYW5hZ2VkIGJ5IHRoZSBtYXAgaXMgdG9cbiAqIHVzZSB7QGxpbmsgbW9kdWxlOm9sL01hcCNhZGRMYXllcn0uXG4gKiBAcHJvcGVydHkge2Jvb2xlYW59IFt1c2VJbnRlcmltVGlsZXNPbkVycm9yPXRydWVdIFVzZSBpbnRlcmltIHRpbGVzIG9uIGVycm9yLlxuICovXG5cbi8qKlxuICogQGNsYXNzZGVzY1xuICogRm9yIGxheWVyIHNvdXJjZXMgdGhhdCBwcm92aWRlIHByZS1yZW5kZXJlZCwgdGlsZWQgaW1hZ2VzIGluIGdyaWRzIHRoYXQgYXJlXG4gKiBvcmdhbml6ZWQgYnkgem9vbSBsZXZlbHMgZm9yIHNwZWNpZmljIHJlc29sdXRpb25zLlxuICogTm90ZSB0aGF0IGFueSBwcm9wZXJ0eSBzZXQgaW4gdGhlIG9wdGlvbnMgaXMgc2V0IGFzIGEge0BsaW5rIG1vZHVsZTpvbC9PYmplY3R+QmFzZU9iamVjdH1cbiAqIHByb3BlcnR5IG9uIHRoZSBsYXllciBvYmplY3Q7IGZvciBleGFtcGxlLCBzZXR0aW5nIGB0aXRsZTogJ015IFRpdGxlJ2AgaW4gdGhlXG4gKiBvcHRpb25zIG1lYW5zIHRoYXQgYHRpdGxlYCBpcyBvYnNlcnZhYmxlLCBhbmQgaGFzIGdldC9zZXQgYWNjZXNzb3JzLlxuICpcbiAqIEBleHRlbmRzIHtMYXllcjxpbXBvcnQoXCIuLi9zb3VyY2UvVGlsZS5qc1wiKS5kZWZhdWx0Pn1cbiAqIEBhcGlcbiAqL1xuXG52YXIgQmFzZVRpbGVMYXllciA9XG4vKiogQGNsYXNzICovXG5mdW5jdGlvbiAoX3N1cGVyKSB7XG4gIF9fZXh0ZW5kcyhCYXNlVGlsZUxheWVyLCBfc3VwZXIpO1xuICAvKipcbiAgICogQHBhcmFtIHtPcHRpb25zPX0gb3B0X29wdGlvbnMgVGlsZSBsYXllciBvcHRpb25zLlxuICAgKi9cblxuXG4gIGZ1bmN0aW9uIEJhc2VUaWxlTGF5ZXIob3B0X29wdGlvbnMpIHtcbiAgICB2YXIgX3RoaXMgPSB0aGlzO1xuXG4gICAgdmFyIG9wdGlvbnMgPSBvcHRfb3B0aW9ucyA/IG9wdF9vcHRpb25zIDoge307XG4gICAgdmFyIGJhc2VPcHRpb25zID0gYXNzaWduKHt9LCBvcHRpb25zKTtcbiAgICBkZWxldGUgYmFzZU9wdGlvbnMucHJlbG9hZDtcbiAgICBkZWxldGUgYmFzZU9wdGlvbnMudXNlSW50ZXJpbVRpbGVzT25FcnJvcjtcbiAgICBfdGhpcyA9IF9zdXBlci5jYWxsKHRoaXMsIGJhc2VPcHRpb25zKSB8fCB0aGlzO1xuXG4gICAgX3RoaXMuc2V0UHJlbG9hZChvcHRpb25zLnByZWxvYWQgIT09IHVuZGVmaW5lZCA/IG9wdGlvbnMucHJlbG9hZCA6IDApO1xuXG4gICAgX3RoaXMuc2V0VXNlSW50ZXJpbVRpbGVzT25FcnJvcihvcHRpb25zLnVzZUludGVyaW1UaWxlc09uRXJyb3IgIT09IHVuZGVmaW5lZCA/IG9wdGlvbnMudXNlSW50ZXJpbVRpbGVzT25FcnJvciA6IHRydWUpO1xuXG4gICAgcmV0dXJuIF90aGlzO1xuICB9XG4gIC8qKlxuICAgKiBSZXR1cm4gdGhlIGxldmVsIGFzIG51bWJlciB0byB3aGljaCB3ZSB3aWxsIHByZWxvYWQgdGlsZXMgdXAgdG8uXG4gICAqIEByZXR1cm4ge251bWJlcn0gVGhlIGxldmVsIHRvIHByZWxvYWQgdGlsZXMgdXAgdG8uXG4gICAqIEBvYnNlcnZhYmxlXG4gICAqIEBhcGlcbiAgICovXG5cblxuICBCYXNlVGlsZUxheWVyLnByb3RvdHlwZS5nZXRQcmVsb2FkID0gZnVuY3Rpb24gKCkge1xuICAgIHJldHVybiAoXG4gICAgICAvKiogQHR5cGUge251bWJlcn0gKi9cbiAgICAgIHRoaXMuZ2V0KFRpbGVQcm9wZXJ0eS5QUkVMT0FEKVxuICAgICk7XG4gIH07XG4gIC8qKlxuICAgKiBTZXQgdGhlIGxldmVsIGFzIG51bWJlciB0byB3aGljaCB3ZSB3aWxsIHByZWxvYWQgdGlsZXMgdXAgdG8uXG4gICAqIEBwYXJhbSB7bnVtYmVyfSBwcmVsb2FkIFRoZSBsZXZlbCB0byBwcmVsb2FkIHRpbGVzIHVwIHRvLlxuICAgKiBAb2JzZXJ2YWJsZVxuICAgKiBAYXBpXG4gICAqL1xuXG5cbiAgQmFzZVRpbGVMYXllci5wcm90b3R5cGUuc2V0UHJlbG9hZCA9IGZ1bmN0aW9uIChwcmVsb2FkKSB7XG4gICAgdGhpcy5zZXQoVGlsZVByb3BlcnR5LlBSRUxPQUQsIHByZWxvYWQpO1xuICB9O1xuICAvKipcbiAgICogV2hldGhlciB3ZSB1c2UgaW50ZXJpbSB0aWxlcyBvbiBlcnJvci5cbiAgICogQHJldHVybiB7Ym9vbGVhbn0gVXNlIGludGVyaW0gdGlsZXMgb24gZXJyb3IuXG4gICAqIEBvYnNlcnZhYmxlXG4gICAqIEBhcGlcbiAgICovXG5cblxuICBCYXNlVGlsZUxheWVyLnByb3RvdHlwZS5nZXRVc2VJbnRlcmltVGlsZXNPbkVycm9yID0gZnVuY3Rpb24gKCkge1xuICAgIHJldHVybiAoXG4gICAgICAvKiogQHR5cGUge2Jvb2xlYW59ICovXG4gICAgICB0aGlzLmdldChUaWxlUHJvcGVydHkuVVNFX0lOVEVSSU1fVElMRVNfT05fRVJST1IpXG4gICAgKTtcbiAgfTtcbiAgLyoqXG4gICAqIFNldCB3aGV0aGVyIHdlIHVzZSBpbnRlcmltIHRpbGVzIG9uIGVycm9yLlxuICAgKiBAcGFyYW0ge2Jvb2xlYW59IHVzZUludGVyaW1UaWxlc09uRXJyb3IgVXNlIGludGVyaW0gdGlsZXMgb24gZXJyb3IuXG4gICAqIEBvYnNlcnZhYmxlXG4gICAqIEBhcGlcbiAgICovXG5cblxuICBCYXNlVGlsZUxheWVyLnByb3RvdHlwZS5zZXRVc2VJbnRlcmltVGlsZXNPbkVycm9yID0gZnVuY3Rpb24gKHVzZUludGVyaW1UaWxlc09uRXJyb3IpIHtcbiAgICB0aGlzLnNldChUaWxlUHJvcGVydHkuVVNFX0lOVEVSSU1fVElMRVNfT05fRVJST1IsIHVzZUludGVyaW1UaWxlc09uRXJyb3IpO1xuICB9O1xuXG4gIHJldHVybiBCYXNlVGlsZUxheWVyO1xufShMYXllcik7XG5cbmV4cG9ydCBkZWZhdWx0IEJhc2VUaWxlTGF5ZXI7IiwiLyoqXG4gKiBAbW9kdWxlIG9sL0ltYWdlU3RhdGVcbiAqL1xuXG4vKipcbiAqIEBlbnVtIHtudW1iZXJ9XG4gKi9cbmV4cG9ydCBkZWZhdWx0IHtcbiAgSURMRTogMCxcbiAgTE9BRElORzogMSxcbiAgTE9BREVEOiAyLFxuICBFUlJPUjogMyxcbiAgRU1QVFk6IDRcbn07IiwidmFyIF9fZXh0ZW5kcyA9IHRoaXMgJiYgdGhpcy5fX2V4dGVuZHMgfHwgZnVuY3Rpb24gKCkge1xuICB2YXIgX2V4dGVuZFN0YXRpY3MgPSBmdW5jdGlvbiBleHRlbmRTdGF0aWNzKGQsIGIpIHtcbiAgICBfZXh0ZW5kU3RhdGljcyA9IE9iamVjdC5zZXRQcm90b3R5cGVPZiB8fCB7XG4gICAgICBfX3Byb3RvX186IFtdXG4gICAgfSBpbnN0YW5jZW9mIEFycmF5ICYmIGZ1bmN0aW9uIChkLCBiKSB7XG4gICAgICBkLl9fcHJvdG9fXyA9IGI7XG4gICAgfSB8fCBmdW5jdGlvbiAoZCwgYikge1xuICAgICAgZm9yICh2YXIgcCBpbiBiKSB7XG4gICAgICAgIGlmIChPYmplY3QucHJvdG90eXBlLmhhc093blByb3BlcnR5LmNhbGwoYiwgcCkpIGRbcF0gPSBiW3BdO1xuICAgICAgfVxuICAgIH07XG5cbiAgICByZXR1cm4gX2V4dGVuZFN0YXRpY3MoZCwgYik7XG4gIH07XG5cbiAgcmV0dXJuIGZ1bmN0aW9uIChkLCBiKSB7XG4gICAgX2V4dGVuZFN0YXRpY3MoZCwgYik7XG5cbiAgICBmdW5jdGlvbiBfXygpIHtcbiAgICAgIHRoaXMuY29uc3RydWN0b3IgPSBkO1xuICAgIH1cblxuICAgIGQucHJvdG90eXBlID0gYiA9PT0gbnVsbCA/IE9iamVjdC5jcmVhdGUoYikgOiAoX18ucHJvdG90eXBlID0gYi5wcm90b3R5cGUsIG5ldyBfXygpKTtcbiAgfTtcbn0oKTtcbi8qKlxuICogQG1vZHVsZSBvbC9yZW5kZXJlci9MYXllclxuICovXG5cblxuaW1wb3J0IEV2ZW50VHlwZSBmcm9tICcuLi9ldmVudHMvRXZlbnRUeXBlLmpzJztcbmltcG9ydCBJbWFnZVN0YXRlIGZyb20gJy4uL0ltYWdlU3RhdGUuanMnO1xuaW1wb3J0IE9ic2VydmFibGUgZnJvbSAnLi4vT2JzZXJ2YWJsZS5qcyc7XG5pbXBvcnQgU291cmNlU3RhdGUgZnJvbSAnLi4vc291cmNlL1N0YXRlLmpzJztcbmltcG9ydCB7IGFic3RyYWN0IH0gZnJvbSAnLi4vdXRpbC5qcyc7XG4vKipcbiAqIEB0ZW1wbGF0ZSB7aW1wb3J0KFwiLi4vbGF5ZXIvTGF5ZXIuanNcIikuZGVmYXVsdH0gTGF5ZXJUeXBlXG4gKi9cblxudmFyIExheWVyUmVuZGVyZXIgPVxuLyoqIEBjbGFzcyAqL1xuZnVuY3Rpb24gKF9zdXBlcikge1xuICBfX2V4dGVuZHMoTGF5ZXJSZW5kZXJlciwgX3N1cGVyKTtcbiAgLyoqXG4gICAqIEBwYXJhbSB7TGF5ZXJUeXBlfSBsYXllciBMYXllci5cbiAgICovXG5cblxuICBmdW5jdGlvbiBMYXllclJlbmRlcmVyKGxheWVyKSB7XG4gICAgdmFyIF90aGlzID0gX3N1cGVyLmNhbGwodGhpcykgfHwgdGhpcztcbiAgICAvKiogQHByaXZhdGUgKi9cblxuXG4gICAgX3RoaXMuYm91bmRIYW5kbGVJbWFnZUNoYW5nZV8gPSBfdGhpcy5oYW5kbGVJbWFnZUNoYW5nZV8uYmluZChfdGhpcyk7XG4gICAgLyoqXG4gICAgICogQHByb3RlY3RlZFxuICAgICAqIEB0eXBlIHtMYXllclR5cGV9XG4gICAgICovXG5cbiAgICBfdGhpcy5sYXllcl8gPSBsYXllcjtcbiAgICAvKipcbiAgICAgKiBAdHlwZSB7aW1wb3J0KFwiLi4vcmVuZGVyL2NhbnZhcy9FeGVjdXRvckdyb3VwXCIpLmRlZmF1bHR9XG4gICAgICovXG5cbiAgICBfdGhpcy5kZWNsdXR0ZXJFeGVjdXRvckdyb3VwID0gbnVsbDtcbiAgICByZXR1cm4gX3RoaXM7XG4gIH1cbiAgLyoqXG4gICAqIEFzeW5jaHJvbm91cyBsYXllciBsZXZlbCBoaXQgZGV0ZWN0aW9uLlxuICAgKiBAcGFyYW0ge2ltcG9ydChcIi4uL3BpeGVsLmpzXCIpLlBpeGVsfSBwaXhlbCBQaXhlbC5cbiAgICogQHJldHVybiB7UHJvbWlzZTxBcnJheTxpbXBvcnQoXCIuLi9GZWF0dXJlXCIpLmRlZmF1bHQ+Pn0gUHJvbWlzZSB0aGF0IHJlc29sdmVzIHdpdGhcbiAgICogYW4gYXJyYXkgb2YgZmVhdHVyZXMuXG4gICAqL1xuXG5cbiAgTGF5ZXJSZW5kZXJlci5wcm90b3R5cGUuZ2V0RmVhdHVyZXMgPSBmdW5jdGlvbiAocGl4ZWwpIHtcbiAgICByZXR1cm4gYWJzdHJhY3QoKTtcbiAgfTtcbiAgLyoqXG4gICAqIERldGVybWluZSB3aGV0aGVyIHJlbmRlciBzaG91bGQgYmUgY2FsbGVkLlxuICAgKiBAYWJzdHJhY3RcbiAgICogQHBhcmFtIHtpbXBvcnQoXCIuLi9QbHVnZ2FibGVNYXAuanNcIikuRnJhbWVTdGF0ZX0gZnJhbWVTdGF0ZSBGcmFtZSBzdGF0ZS5cbiAgICogQHJldHVybiB7Ym9vbGVhbn0gTGF5ZXIgaXMgcmVhZHkgdG8gYmUgcmVuZGVyZWQuXG4gICAqL1xuXG5cbiAgTGF5ZXJSZW5kZXJlci5wcm90b3R5cGUucHJlcGFyZUZyYW1lID0gZnVuY3Rpb24gKGZyYW1lU3RhdGUpIHtcbiAgICByZXR1cm4gYWJzdHJhY3QoKTtcbiAgfTtcbiAgLyoqXG4gICAqIFJlbmRlciB0aGUgbGF5ZXIuXG4gICAqIEBhYnN0cmFjdFxuICAgKiBAcGFyYW0ge2ltcG9ydChcIi4uL1BsdWdnYWJsZU1hcC5qc1wiKS5GcmFtZVN0YXRlfSBmcmFtZVN0YXRlIEZyYW1lIHN0YXRlLlxuICAgKiBAcGFyYW0ge0hUTUxFbGVtZW50fSB0YXJnZXQgVGFyZ2V0IHRoYXQgbWF5IGJlIHVzZWQgdG8gcmVuZGVyIGNvbnRlbnQgdG8uXG4gICAqIEByZXR1cm4ge0hUTUxFbGVtZW50fSBUaGUgcmVuZGVyZWQgZWxlbWVudC5cbiAgICovXG5cblxuICBMYXllclJlbmRlcmVyLnByb3RvdHlwZS5yZW5kZXJGcmFtZSA9IGZ1bmN0aW9uIChmcmFtZVN0YXRlLCB0YXJnZXQpIHtcbiAgICByZXR1cm4gYWJzdHJhY3QoKTtcbiAgfTtcbiAgLyoqXG4gICAqIEBwYXJhbSB7T2JqZWN0PG51bWJlciwgT2JqZWN0PHN0cmluZywgaW1wb3J0KFwiLi4vVGlsZS5qc1wiKS5kZWZhdWx0Pj59IHRpbGVzIExvb2t1cCBvZiBsb2FkZWQgdGlsZXMgYnkgem9vbSBsZXZlbC5cbiAgICogQHBhcmFtIHtudW1iZXJ9IHpvb20gWm9vbSBsZXZlbC5cbiAgICogQHBhcmFtIHtpbXBvcnQoXCIuLi9UaWxlLmpzXCIpLmRlZmF1bHR9IHRpbGUgVGlsZS5cbiAgICogQHJldHVybiB7Ym9vbGVhbnx2b2lkfSBJZiBgZmFsc2VgLCB0aGUgdGlsZSB3aWxsIG5vdCBiZSBjb25zaWRlcmVkIGxvYWRlZC5cbiAgICovXG5cblxuICBMYXllclJlbmRlcmVyLnByb3RvdHlwZS5sb2FkZWRUaWxlQ2FsbGJhY2sgPSBmdW5jdGlvbiAodGlsZXMsIHpvb20sIHRpbGUpIHtcbiAgICBpZiAoIXRpbGVzW3pvb21dKSB7XG4gICAgICB0aWxlc1t6b29tXSA9IHt9O1xuICAgIH1cblxuICAgIHRpbGVzW3pvb21dW3RpbGUudGlsZUNvb3JkLnRvU3RyaW5nKCldID0gdGlsZTtcbiAgICByZXR1cm4gdW5kZWZpbmVkO1xuICB9O1xuICAvKipcbiAgICogQ3JlYXRlIGEgZnVuY3Rpb24gdGhhdCBhZGRzIGxvYWRlZCB0aWxlcyB0byB0aGUgdGlsZSBsb29rdXAuXG4gICAqIEBwYXJhbSB7aW1wb3J0KFwiLi4vc291cmNlL1RpbGUuanNcIikuZGVmYXVsdH0gc291cmNlIFRpbGUgc291cmNlLlxuICAgKiBAcGFyYW0ge2ltcG9ydChcIi4uL3Byb2ovUHJvamVjdGlvbi5qc1wiKS5kZWZhdWx0fSBwcm9qZWN0aW9uIFByb2plY3Rpb24gb2YgdGhlIHRpbGVzLlxuICAgKiBAcGFyYW0ge09iamVjdDxudW1iZXIsIE9iamVjdDxzdHJpbmcsIGltcG9ydChcIi4uL1RpbGUuanNcIikuZGVmYXVsdD4+fSB0aWxlcyBMb29rdXAgb2YgbG9hZGVkIHRpbGVzIGJ5IHpvb20gbGV2ZWwuXG4gICAqIEByZXR1cm4ge2Z1bmN0aW9uKG51bWJlciwgaW1wb3J0KFwiLi4vVGlsZVJhbmdlLmpzXCIpLmRlZmF1bHQpOmJvb2xlYW59IEEgZnVuY3Rpb24gdGhhdCBjYW4gYmVcbiAgICogICAgIGNhbGxlZCB3aXRoIGEgem9vbSBsZXZlbCBhbmQgYSB0aWxlIHJhbmdlIHRvIGFkZCBsb2FkZWQgdGlsZXMgdG8gdGhlIGxvb2t1cC5cbiAgICogQHByb3RlY3RlZFxuICAgKi9cblxuXG4gIExheWVyUmVuZGVyZXIucHJvdG90eXBlLmNyZWF0ZUxvYWRlZFRpbGVGaW5kZXIgPSBmdW5jdGlvbiAoc291cmNlLCBwcm9qZWN0aW9uLCB0aWxlcykge1xuICAgIHJldHVybiAoXG4gICAgICAvKipcbiAgICAgICAqIEBwYXJhbSB7bnVtYmVyfSB6b29tIFpvb20gbGV2ZWwuXG4gICAgICAgKiBAcGFyYW0ge2ltcG9ydChcIi4uL1RpbGVSYW5nZS5qc1wiKS5kZWZhdWx0fSB0aWxlUmFuZ2UgVGlsZSByYW5nZS5cbiAgICAgICAqIEByZXR1cm4ge2Jvb2xlYW59IFRoZSB0aWxlIHJhbmdlIGlzIGZ1bGx5IGxvYWRlZC5cbiAgICAgICAqIEB0aGlzIHtMYXllclJlbmRlcmVyfVxuICAgICAgICovXG4gICAgICBmdW5jdGlvbiAoem9vbSwgdGlsZVJhbmdlKSB7XG4gICAgICAgIHZhciBjYWxsYmFjayA9IHRoaXMubG9hZGVkVGlsZUNhbGxiYWNrLmJpbmQodGhpcywgdGlsZXMsIHpvb20pO1xuICAgICAgICByZXR1cm4gc291cmNlLmZvckVhY2hMb2FkZWRUaWxlKHByb2plY3Rpb24sIHpvb20sIHRpbGVSYW5nZSwgY2FsbGJhY2spO1xuICAgICAgfS5iaW5kKHRoaXMpXG4gICAgKTtcbiAgfTtcbiAgLyoqXG4gICAqIEBhYnN0cmFjdFxuICAgKiBAcGFyYW0ge2ltcG9ydChcIi4uL2Nvb3JkaW5hdGUuanNcIikuQ29vcmRpbmF0ZX0gY29vcmRpbmF0ZSBDb29yZGluYXRlLlxuICAgKiBAcGFyYW0ge2ltcG9ydChcIi4uL1BsdWdnYWJsZU1hcC5qc1wiKS5GcmFtZVN0YXRlfSBmcmFtZVN0YXRlIEZyYW1lIHN0YXRlLlxuICAgKiBAcGFyYW0ge251bWJlcn0gaGl0VG9sZXJhbmNlIEhpdCB0b2xlcmFuY2UgaW4gcGl4ZWxzLlxuICAgKiBAcGFyYW0ge2ltcG9ydChcIi4vdmVjdG9yLmpzXCIpLkZlYXR1cmVDYWxsYmFjazxUPn0gY2FsbGJhY2sgRmVhdHVyZSBjYWxsYmFjay5cbiAgICogQHBhcmFtIHtBcnJheTxpbXBvcnQoXCIuL01hcC5qc1wiKS5IaXRNYXRjaDxUPj59IG1hdGNoZXMgVGhlIGhpdCBkZXRlY3RlZCBtYXRjaGVzIHdpdGggdG9sZXJhbmNlLlxuICAgKiBAcmV0dXJuIHtUfHVuZGVmaW5lZH0gQ2FsbGJhY2sgcmVzdWx0LlxuICAgKiBAdGVtcGxhdGUgVFxuICAgKi9cblxuXG4gIExheWVyUmVuZGVyZXIucHJvdG90eXBlLmZvckVhY2hGZWF0dXJlQXRDb29yZGluYXRlID0gZnVuY3Rpb24gKGNvb3JkaW5hdGUsIGZyYW1lU3RhdGUsIGhpdFRvbGVyYW5jZSwgY2FsbGJhY2ssIG1hdGNoZXMpIHtcbiAgICByZXR1cm4gdW5kZWZpbmVkO1xuICB9O1xuICAvKipcbiAgICogQGFic3RyYWN0XG4gICAqIEBwYXJhbSB7aW1wb3J0KFwiLi4vcGl4ZWwuanNcIikuUGl4ZWx9IHBpeGVsIFBpeGVsLlxuICAgKiBAcGFyYW0ge2ltcG9ydChcIi4uL1BsdWdnYWJsZU1hcC5qc1wiKS5GcmFtZVN0YXRlfSBmcmFtZVN0YXRlIEZyYW1lU3RhdGUuXG4gICAqIEBwYXJhbSB7bnVtYmVyfSBoaXRUb2xlcmFuY2UgSGl0IHRvbGVyYW5jZSBpbiBwaXhlbHMuXG4gICAqIEByZXR1cm4ge1VpbnQ4Q2xhbXBlZEFycmF5fFVpbnQ4QXJyYXl9IFRoZSByZXN1bHQuICBJZiB0aGVyZSBpcyBubyBkYXRhIGF0IHRoZSBwaXhlbFxuICAgKiAgICBsb2NhdGlvbiwgbnVsbCB3aWxsIGJlIHJldHVybmVkLiAgSWYgdGhlcmUgaXMgZGF0YSwgYnV0IHBpeGVsIHZhbHVlcyBjYW5ub3QgYmVcbiAgICogICAgcmV0dXJuZWQsIGFuZCBlbXB0eSBhcnJheSB3aWxsIGJlIHJldHVybmVkLlxuICAgKi9cblxuXG4gIExheWVyUmVuZGVyZXIucHJvdG90eXBlLmdldERhdGFBdFBpeGVsID0gZnVuY3Rpb24gKHBpeGVsLCBmcmFtZVN0YXRlLCBoaXRUb2xlcmFuY2UpIHtcbiAgICByZXR1cm4gYWJzdHJhY3QoKTtcbiAgfTtcbiAgLyoqXG4gICAqIEByZXR1cm4ge0xheWVyVHlwZX0gTGF5ZXIuXG4gICAqL1xuXG5cbiAgTGF5ZXJSZW5kZXJlci5wcm90b3R5cGUuZ2V0TGF5ZXIgPSBmdW5jdGlvbiAoKSB7XG4gICAgcmV0dXJuIHRoaXMubGF5ZXJfO1xuICB9O1xuICAvKipcbiAgICogUGVyZm9ybSBhY3Rpb24gbmVjZXNzYXJ5IHRvIGdldCB0aGUgbGF5ZXIgcmVuZGVyZWQgYWZ0ZXIgbmV3IGZvbnRzIGhhdmUgbG9hZGVkXG4gICAqIEBhYnN0cmFjdFxuICAgKi9cblxuXG4gIExheWVyUmVuZGVyZXIucHJvdG90eXBlLmhhbmRsZUZvbnRzQ2hhbmdlZCA9IGZ1bmN0aW9uICgpIHt9O1xuICAvKipcbiAgICogSGFuZGxlIGNoYW5nZXMgaW4gaW1hZ2Ugc3RhdGUuXG4gICAqIEBwYXJhbSB7aW1wb3J0KFwiLi4vZXZlbnRzL0V2ZW50LmpzXCIpLmRlZmF1bHR9IGV2ZW50IEltYWdlIGNoYW5nZSBldmVudC5cbiAgICogQHByaXZhdGVcbiAgICovXG5cblxuICBMYXllclJlbmRlcmVyLnByb3RvdHlwZS5oYW5kbGVJbWFnZUNoYW5nZV8gPSBmdW5jdGlvbiAoZXZlbnQpIHtcbiAgICB2YXIgaW1hZ2UgPVxuICAgIC8qKiBAdHlwZSB7aW1wb3J0KFwiLi4vSW1hZ2UuanNcIikuZGVmYXVsdH0gKi9cbiAgICBldmVudC50YXJnZXQ7XG5cbiAgICBpZiAoaW1hZ2UuZ2V0U3RhdGUoKSA9PT0gSW1hZ2VTdGF0ZS5MT0FERUQpIHtcbiAgICAgIHRoaXMucmVuZGVySWZSZWFkeUFuZFZpc2libGUoKTtcbiAgICB9XG4gIH07XG4gIC8qKlxuICAgKiBMb2FkIHRoZSBpbWFnZSBpZiBub3QgYWxyZWFkeSBsb2FkZWQsIGFuZCByZWdpc3RlciB0aGUgaW1hZ2UgY2hhbmdlXG4gICAqIGxpc3RlbmVyIGlmIG5lZWRlZC5cbiAgICogQHBhcmFtIHtpbXBvcnQoXCIuLi9JbWFnZUJhc2UuanNcIikuZGVmYXVsdH0gaW1hZ2UgSW1hZ2UuXG4gICAqIEByZXR1cm4ge2Jvb2xlYW59IGB0cnVlYCBpZiB0aGUgaW1hZ2UgaXMgYWxyZWFkeSBsb2FkZWQsIGBmYWxzZWAgb3RoZXJ3aXNlLlxuICAgKiBAcHJvdGVjdGVkXG4gICAqL1xuXG5cbiAgTGF5ZXJSZW5kZXJlci5wcm90b3R5cGUubG9hZEltYWdlID0gZnVuY3Rpb24gKGltYWdlKSB7XG4gICAgdmFyIGltYWdlU3RhdGUgPSBpbWFnZS5nZXRTdGF0ZSgpO1xuXG4gICAgaWYgKGltYWdlU3RhdGUgIT0gSW1hZ2VTdGF0ZS5MT0FERUQgJiYgaW1hZ2VTdGF0ZSAhPSBJbWFnZVN0YXRlLkVSUk9SKSB7XG4gICAgICBpbWFnZS5hZGRFdmVudExpc3RlbmVyKEV2ZW50VHlwZS5DSEFOR0UsIHRoaXMuYm91bmRIYW5kbGVJbWFnZUNoYW5nZV8pO1xuICAgIH1cblxuICAgIGlmIChpbWFnZVN0YXRlID09IEltYWdlU3RhdGUuSURMRSkge1xuICAgICAgaW1hZ2UubG9hZCgpO1xuICAgICAgaW1hZ2VTdGF0ZSA9IGltYWdlLmdldFN0YXRlKCk7XG4gICAgfVxuXG4gICAgcmV0dXJuIGltYWdlU3RhdGUgPT0gSW1hZ2VTdGF0ZS5MT0FERUQ7XG4gIH07XG4gIC8qKlxuICAgKiBAcHJvdGVjdGVkXG4gICAqL1xuXG5cbiAgTGF5ZXJSZW5kZXJlci5wcm90b3R5cGUucmVuZGVySWZSZWFkeUFuZFZpc2libGUgPSBmdW5jdGlvbiAoKSB7XG4gICAgdmFyIGxheWVyID0gdGhpcy5nZXRMYXllcigpO1xuXG4gICAgaWYgKGxheWVyLmdldFZpc2libGUoKSAmJiBsYXllci5nZXRTb3VyY2VTdGF0ZSgpID09IFNvdXJjZVN0YXRlLlJFQURZKSB7XG4gICAgICBsYXllci5jaGFuZ2VkKCk7XG4gICAgfVxuICB9O1xuXG4gIHJldHVybiBMYXllclJlbmRlcmVyO1xufShPYnNlcnZhYmxlKTtcblxuZXhwb3J0IGRlZmF1bHQgTGF5ZXJSZW5kZXJlcjsiLCJ2YXIgX19leHRlbmRzID0gdGhpcyAmJiB0aGlzLl9fZXh0ZW5kcyB8fCBmdW5jdGlvbiAoKSB7XG4gIHZhciBfZXh0ZW5kU3RhdGljcyA9IGZ1bmN0aW9uIGV4dGVuZFN0YXRpY3MoZCwgYikge1xuICAgIF9leHRlbmRTdGF0aWNzID0gT2JqZWN0LnNldFByb3RvdHlwZU9mIHx8IHtcbiAgICAgIF9fcHJvdG9fXzogW11cbiAgICB9IGluc3RhbmNlb2YgQXJyYXkgJiYgZnVuY3Rpb24gKGQsIGIpIHtcbiAgICAgIGQuX19wcm90b19fID0gYjtcbiAgICB9IHx8IGZ1bmN0aW9uIChkLCBiKSB7XG4gICAgICBmb3IgKHZhciBwIGluIGIpIHtcbiAgICAgICAgaWYgKE9iamVjdC5wcm90b3R5cGUuaGFzT3duUHJvcGVydHkuY2FsbChiLCBwKSkgZFtwXSA9IGJbcF07XG4gICAgICB9XG4gICAgfTtcblxuICAgIHJldHVybiBfZXh0ZW5kU3RhdGljcyhkLCBiKTtcbiAgfTtcblxuICByZXR1cm4gZnVuY3Rpb24gKGQsIGIpIHtcbiAgICBfZXh0ZW5kU3RhdGljcyhkLCBiKTtcblxuICAgIGZ1bmN0aW9uIF9fKCkge1xuICAgICAgdGhpcy5jb25zdHJ1Y3RvciA9IGQ7XG4gICAgfVxuXG4gICAgZC5wcm90b3R5cGUgPSBiID09PSBudWxsID8gT2JqZWN0LmNyZWF0ZShiKSA6IChfXy5wcm90b3R5cGUgPSBiLnByb3RvdHlwZSwgbmV3IF9fKCkpO1xuICB9O1xufSgpO1xuLyoqXG4gKiBAbW9kdWxlIG9sL3JlbmRlcmVyL2NhbnZhcy9MYXllclxuICovXG5cblxuaW1wb3J0IExheWVyUmVuZGVyZXIgZnJvbSAnLi4vTGF5ZXIuanMnO1xuaW1wb3J0IFJlbmRlckV2ZW50IGZyb20gJy4uLy4uL3JlbmRlci9FdmVudC5qcyc7XG5pbXBvcnQgUmVuZGVyRXZlbnRUeXBlIGZyb20gJy4uLy4uL3JlbmRlci9FdmVudFR5cGUuanMnO1xuaW1wb3J0IHsgYXBwbHkgYXMgYXBwbHlUcmFuc2Zvcm0sIGNvbXBvc2UgYXMgY29tcG9zZVRyYW5zZm9ybSwgY3JlYXRlIGFzIGNyZWF0ZVRyYW5zZm9ybSB9IGZyb20gJy4uLy4uL3RyYW5zZm9ybS5qcyc7XG5pbXBvcnQgeyBjb250YWluc0Nvb3JkaW5hdGUsIGdldEJvdHRvbUxlZnQsIGdldEJvdHRvbVJpZ2h0LCBnZXRUb3BMZWZ0LCBnZXRUb3BSaWdodCB9IGZyb20gJy4uLy4uL2V4dGVudC5qcyc7XG5pbXBvcnQgeyBjcmVhdGVDYW52YXNDb250ZXh0MkQgfSBmcm9tICcuLi8uLi9kb20uanMnO1xuaW1wb3J0IHsgcm90YXRlQXRPZmZzZXQgfSBmcm9tICcuLi8uLi9yZW5kZXIvY2FudmFzLmpzJztcbi8qKlxuICogQGFic3RyYWN0XG4gKiBAdGVtcGxhdGUge2ltcG9ydChcIi4uLy4uL2xheWVyL0xheWVyLmpzXCIpLmRlZmF1bHR9IExheWVyVHlwZVxuICovXG5cbnZhciBDYW52YXNMYXllclJlbmRlcmVyID1cbi8qKiBAY2xhc3MgKi9cbmZ1bmN0aW9uIChfc3VwZXIpIHtcbiAgX19leHRlbmRzKENhbnZhc0xheWVyUmVuZGVyZXIsIF9zdXBlcik7XG4gIC8qKlxuICAgKiBAcGFyYW0ge0xheWVyVHlwZX0gbGF5ZXIgTGF5ZXIuXG4gICAqL1xuXG5cbiAgZnVuY3Rpb24gQ2FudmFzTGF5ZXJSZW5kZXJlcihsYXllcikge1xuICAgIHZhciBfdGhpcyA9IF9zdXBlci5jYWxsKHRoaXMsIGxheWVyKSB8fCB0aGlzO1xuICAgIC8qKlxuICAgICAqIEBwcm90ZWN0ZWRcbiAgICAgKiBAdHlwZSB7SFRNTEVsZW1lbnR9XG4gICAgICovXG5cblxuICAgIF90aGlzLmNvbnRhaW5lciA9IG51bGw7XG4gICAgLyoqXG4gICAgICogQHByb3RlY3RlZFxuICAgICAqIEB0eXBlIHtudW1iZXJ9XG4gICAgICovXG5cbiAgICBfdGhpcy5yZW5kZXJlZFJlc29sdXRpb247XG4gICAgLyoqXG4gICAgICogQSB0ZW1wb3JhcnkgdHJhbnNmb3JtLiAgVGhlIHZhbHVlcyBpbiB0aGlzIHRyYW5zZm9ybSBzaG91bGQgb25seSBiZSB1c2VkIGluIGFcbiAgICAgKiBmdW5jdGlvbiB0aGF0IHNldHMgdGhlIHZhbHVlcy5cbiAgICAgKiBAcHJvdGVjdGVkXG4gICAgICogQHR5cGUge2ltcG9ydChcIi4uLy4uL3RyYW5zZm9ybS5qc1wiKS5UcmFuc2Zvcm19XG4gICAgICovXG5cbiAgICBfdGhpcy50ZW1wVHJhbnNmb3JtID0gY3JlYXRlVHJhbnNmb3JtKCk7XG4gICAgLyoqXG4gICAgICogVGhlIHRyYW5zZm9ybSBmb3IgcmVuZGVyZWQgcGl4ZWxzIHRvIHZpZXdwb3J0IENTUyBwaXhlbHMuICBUaGlzIHRyYW5zZm9ybSBtdXN0XG4gICAgICogYmUgc2V0IHdoZW4gcmVuZGVyaW5nIGEgZnJhbWUgYW5kIG1heSBiZSB1c2VkIGJ5IG90aGVyIGZ1bmN0aW9ucyBhZnRlciByZW5kZXJpbmcuXG4gICAgICogQHByb3RlY3RlZFxuICAgICAqIEB0eXBlIHtpbXBvcnQoXCIuLi8uLi90cmFuc2Zvcm0uanNcIikuVHJhbnNmb3JtfVxuICAgICAqL1xuXG4gICAgX3RoaXMucGl4ZWxUcmFuc2Zvcm0gPSBjcmVhdGVUcmFuc2Zvcm0oKTtcbiAgICAvKipcbiAgICAgKiBUaGUgdHJhbnNmb3JtIGZvciB2aWV3cG9ydCBDU1MgcGl4ZWxzIHRvIHJlbmRlcmVkIHBpeGVscy4gIFRoaXMgdHJhbnNmb3JtIG11c3RcbiAgICAgKiBiZSBzZXQgd2hlbiByZW5kZXJpbmcgYSBmcmFtZSBhbmQgbWF5IGJlIHVzZWQgYnkgb3RoZXIgZnVuY3Rpb25zIGFmdGVyIHJlbmRlcmluZy5cbiAgICAgKiBAcHJvdGVjdGVkXG4gICAgICogQHR5cGUge2ltcG9ydChcIi4uLy4uL3RyYW5zZm9ybS5qc1wiKS5UcmFuc2Zvcm19XG4gICAgICovXG5cbiAgICBfdGhpcy5pbnZlcnNlUGl4ZWxUcmFuc2Zvcm0gPSBjcmVhdGVUcmFuc2Zvcm0oKTtcbiAgICAvKipcbiAgICAgKiBAdHlwZSB7Q2FudmFzUmVuZGVyaW5nQ29udGV4dDJEfVxuICAgICAqL1xuXG4gICAgX3RoaXMuY29udGV4dCA9IG51bGw7XG4gICAgLyoqXG4gICAgICogQHR5cGUge2Jvb2xlYW59XG4gICAgICovXG5cbiAgICBfdGhpcy5jb250YWluZXJSZXVzZWQgPSBmYWxzZTtcbiAgICByZXR1cm4gX3RoaXM7XG4gIH1cbiAgLyoqXG4gICAqIEdldCBhIHJlbmRlcmluZyBjb250YWluZXIgZnJvbSBhbiBleGlzdGluZyB0YXJnZXQsIGlmIGNvbXBhdGlibGUuXG4gICAqIEBwYXJhbSB7SFRNTEVsZW1lbnR9IHRhcmdldCBQb3RlbnRpYWwgcmVuZGVyIHRhcmdldC5cbiAgICogQHBhcmFtIHtzdHJpbmd9IHRyYW5zZm9ybSBDU1MgVHJhbnNmb3JtLlxuICAgKiBAcGFyYW0ge251bWJlcn0gb3BhY2l0eSBPcGFjaXR5LlxuICAgKi9cblxuXG4gIENhbnZhc0xheWVyUmVuZGVyZXIucHJvdG90eXBlLnVzZUNvbnRhaW5lciA9IGZ1bmN0aW9uICh0YXJnZXQsIHRyYW5zZm9ybSwgb3BhY2l0eSkge1xuICAgIHZhciBsYXllckNsYXNzTmFtZSA9IHRoaXMuZ2V0TGF5ZXIoKS5nZXRDbGFzc05hbWUoKTtcbiAgICB2YXIgY29udGFpbmVyLCBjb250ZXh0O1xuXG4gICAgaWYgKHRhcmdldCAmJiB0YXJnZXQuc3R5bGUub3BhY2l0eSA9PT0gJycgJiYgdGFyZ2V0LmNsYXNzTmFtZSA9PT0gbGF5ZXJDbGFzc05hbWUpIHtcbiAgICAgIHZhciBjYW52YXMgPSB0YXJnZXQuZmlyc3RFbGVtZW50Q2hpbGQ7XG5cbiAgICAgIGlmIChjYW52YXMgaW5zdGFuY2VvZiBIVE1MQ2FudmFzRWxlbWVudCkge1xuICAgICAgICBjb250ZXh0ID0gY2FudmFzLmdldENvbnRleHQoJzJkJyk7XG4gICAgICB9XG4gICAgfVxuXG4gICAgaWYgKGNvbnRleHQgJiYgKGNvbnRleHQuY2FudmFzLndpZHRoID09PSAwIHx8IGNvbnRleHQuY2FudmFzLnN0eWxlLnRyYW5zZm9ybSA9PT0gdHJhbnNmb3JtKSkge1xuICAgICAgLy8gQ29udGFpbmVyIG9mIHRoZSBwcmV2aW91cyBsYXllciByZW5kZXJlciBjYW4gYmUgdXNlZC5cbiAgICAgIHRoaXMuY29udGFpbmVyID0gdGFyZ2V0O1xuICAgICAgdGhpcy5jb250ZXh0ID0gY29udGV4dDtcbiAgICAgIHRoaXMuY29udGFpbmVyUmV1c2VkID0gdHJ1ZTtcbiAgICB9IGVsc2UgaWYgKHRoaXMuY29udGFpbmVyUmV1c2VkKSB7XG4gICAgICAvLyBQcmV2aW91c2x5IHJldXNlZCBjb250YWluZXIgY2Fubm90IGJlIHVzZWQgYW55IG1vcmUuXG4gICAgICB0aGlzLmNvbnRhaW5lciA9IG51bGw7XG4gICAgICB0aGlzLmNvbnRleHQgPSBudWxsO1xuICAgICAgdGhpcy5jb250YWluZXJSZXVzZWQgPSBmYWxzZTtcbiAgICB9XG5cbiAgICBpZiAoIXRoaXMuY29udGFpbmVyKSB7XG4gICAgICBjb250YWluZXIgPSBkb2N1bWVudC5jcmVhdGVFbGVtZW50KCdkaXYnKTtcbiAgICAgIGNvbnRhaW5lci5jbGFzc05hbWUgPSBsYXllckNsYXNzTmFtZTtcbiAgICAgIHZhciBzdHlsZSA9IGNvbnRhaW5lci5zdHlsZTtcbiAgICAgIHN0eWxlLnBvc2l0aW9uID0gJ2Fic29sdXRlJztcbiAgICAgIHN0eWxlLndpZHRoID0gJzEwMCUnO1xuICAgICAgc3R5bGUuaGVpZ2h0ID0gJzEwMCUnO1xuICAgICAgY29udGV4dCA9IGNyZWF0ZUNhbnZhc0NvbnRleHQyRCgpO1xuICAgICAgdmFyIGNhbnZhcyA9IGNvbnRleHQuY2FudmFzO1xuICAgICAgY29udGFpbmVyLmFwcGVuZENoaWxkKGNhbnZhcyk7XG4gICAgICBzdHlsZSA9IGNhbnZhcy5zdHlsZTtcbiAgICAgIHN0eWxlLnBvc2l0aW9uID0gJ2Fic29sdXRlJztcbiAgICAgIHN0eWxlLmxlZnQgPSAnMCc7XG4gICAgICBzdHlsZS50cmFuc2Zvcm1PcmlnaW4gPSAndG9wIGxlZnQnO1xuICAgICAgdGhpcy5jb250YWluZXIgPSBjb250YWluZXI7XG4gICAgICB0aGlzLmNvbnRleHQgPSBjb250ZXh0O1xuICAgIH1cbiAgfTtcbiAgLyoqXG4gICAqIEBwYXJhbSB7Q2FudmFzUmVuZGVyaW5nQ29udGV4dDJEfSBjb250ZXh0IENvbnRleHQuXG4gICAqIEBwYXJhbSB7aW1wb3J0KFwiLi4vLi4vUGx1Z2dhYmxlTWFwLmpzXCIpLkZyYW1lU3RhdGV9IGZyYW1lU3RhdGUgRnJhbWUgc3RhdGUuXG4gICAqIEBwYXJhbSB7aW1wb3J0KFwiLi4vLi4vZXh0ZW50LmpzXCIpLkV4dGVudH0gZXh0ZW50IENsaXAgZXh0ZW50LlxuICAgKiBAcHJvdGVjdGVkXG4gICAqL1xuXG5cbiAgQ2FudmFzTGF5ZXJSZW5kZXJlci5wcm90b3R5cGUuY2xpcCA9IGZ1bmN0aW9uIChjb250ZXh0LCBmcmFtZVN0YXRlLCBleHRlbnQpIHtcbiAgICB2YXIgcGl4ZWxSYXRpbyA9IGZyYW1lU3RhdGUucGl4ZWxSYXRpbztcbiAgICB2YXIgaGFsZldpZHRoID0gZnJhbWVTdGF0ZS5zaXplWzBdICogcGl4ZWxSYXRpbyAvIDI7XG4gICAgdmFyIGhhbGZIZWlnaHQgPSBmcmFtZVN0YXRlLnNpemVbMV0gKiBwaXhlbFJhdGlvIC8gMjtcbiAgICB2YXIgcm90YXRpb24gPSBmcmFtZVN0YXRlLnZpZXdTdGF0ZS5yb3RhdGlvbjtcbiAgICB2YXIgdG9wTGVmdCA9IGdldFRvcExlZnQoZXh0ZW50KTtcbiAgICB2YXIgdG9wUmlnaHQgPSBnZXRUb3BSaWdodChleHRlbnQpO1xuICAgIHZhciBib3R0b21SaWdodCA9IGdldEJvdHRvbVJpZ2h0KGV4dGVudCk7XG4gICAgdmFyIGJvdHRvbUxlZnQgPSBnZXRCb3R0b21MZWZ0KGV4dGVudCk7XG4gICAgYXBwbHlUcmFuc2Zvcm0oZnJhbWVTdGF0ZS5jb29yZGluYXRlVG9QaXhlbFRyYW5zZm9ybSwgdG9wTGVmdCk7XG4gICAgYXBwbHlUcmFuc2Zvcm0oZnJhbWVTdGF0ZS5jb29yZGluYXRlVG9QaXhlbFRyYW5zZm9ybSwgdG9wUmlnaHQpO1xuICAgIGFwcGx5VHJhbnNmb3JtKGZyYW1lU3RhdGUuY29vcmRpbmF0ZVRvUGl4ZWxUcmFuc2Zvcm0sIGJvdHRvbVJpZ2h0KTtcbiAgICBhcHBseVRyYW5zZm9ybShmcmFtZVN0YXRlLmNvb3JkaW5hdGVUb1BpeGVsVHJhbnNmb3JtLCBib3R0b21MZWZ0KTtcbiAgICBjb250ZXh0LnNhdmUoKTtcbiAgICByb3RhdGVBdE9mZnNldChjb250ZXh0LCAtcm90YXRpb24sIGhhbGZXaWR0aCwgaGFsZkhlaWdodCk7XG4gICAgY29udGV4dC5iZWdpblBhdGgoKTtcbiAgICBjb250ZXh0Lm1vdmVUbyh0b3BMZWZ0WzBdICogcGl4ZWxSYXRpbywgdG9wTGVmdFsxXSAqIHBpeGVsUmF0aW8pO1xuICAgIGNvbnRleHQubGluZVRvKHRvcFJpZ2h0WzBdICogcGl4ZWxSYXRpbywgdG9wUmlnaHRbMV0gKiBwaXhlbFJhdGlvKTtcbiAgICBjb250ZXh0LmxpbmVUbyhib3R0b21SaWdodFswXSAqIHBpeGVsUmF0aW8sIGJvdHRvbVJpZ2h0WzFdICogcGl4ZWxSYXRpbyk7XG4gICAgY29udGV4dC5saW5lVG8oYm90dG9tTGVmdFswXSAqIHBpeGVsUmF0aW8sIGJvdHRvbUxlZnRbMV0gKiBwaXhlbFJhdGlvKTtcbiAgICBjb250ZXh0LmNsaXAoKTtcbiAgICByb3RhdGVBdE9mZnNldChjb250ZXh0LCByb3RhdGlvbiwgaGFsZldpZHRoLCBoYWxmSGVpZ2h0KTtcbiAgfTtcbiAgLyoqXG4gICAqIEBwYXJhbSB7Q2FudmFzUmVuZGVyaW5nQ29udGV4dDJEfSBjb250ZXh0IENvbnRleHQuXG4gICAqIEBwYXJhbSB7aW1wb3J0KFwiLi4vLi4vUGx1Z2dhYmxlTWFwLmpzXCIpLkZyYW1lU3RhdGV9IGZyYW1lU3RhdGUgRnJhbWUgc3RhdGUuXG4gICAqIEBwYXJhbSB7aW1wb3J0KFwiLi4vLi4vZXh0ZW50LmpzXCIpLkV4dGVudH0gZXh0ZW50IENsaXAgZXh0ZW50LlxuICAgKiBAcHJvdGVjdGVkXG4gICAqL1xuXG5cbiAgQ2FudmFzTGF5ZXJSZW5kZXJlci5wcm90b3R5cGUuY2xpcFVucm90YXRlZCA9IGZ1bmN0aW9uIChjb250ZXh0LCBmcmFtZVN0YXRlLCBleHRlbnQpIHtcbiAgICB2YXIgdG9wTGVmdCA9IGdldFRvcExlZnQoZXh0ZW50KTtcbiAgICB2YXIgdG9wUmlnaHQgPSBnZXRUb3BSaWdodChleHRlbnQpO1xuICAgIHZhciBib3R0b21SaWdodCA9IGdldEJvdHRvbVJpZ2h0KGV4dGVudCk7XG4gICAgdmFyIGJvdHRvbUxlZnQgPSBnZXRCb3R0b21MZWZ0KGV4dGVudCk7XG4gICAgYXBwbHlUcmFuc2Zvcm0oZnJhbWVTdGF0ZS5jb29yZGluYXRlVG9QaXhlbFRyYW5zZm9ybSwgdG9wTGVmdCk7XG4gICAgYXBwbHlUcmFuc2Zvcm0oZnJhbWVTdGF0ZS5jb29yZGluYXRlVG9QaXhlbFRyYW5zZm9ybSwgdG9wUmlnaHQpO1xuICAgIGFwcGx5VHJhbnNmb3JtKGZyYW1lU3RhdGUuY29vcmRpbmF0ZVRvUGl4ZWxUcmFuc2Zvcm0sIGJvdHRvbVJpZ2h0KTtcbiAgICBhcHBseVRyYW5zZm9ybShmcmFtZVN0YXRlLmNvb3JkaW5hdGVUb1BpeGVsVHJhbnNmb3JtLCBib3R0b21MZWZ0KTtcbiAgICB2YXIgaW52ZXJ0ZWQgPSB0aGlzLmludmVyc2VQaXhlbFRyYW5zZm9ybTtcbiAgICBhcHBseVRyYW5zZm9ybShpbnZlcnRlZCwgdG9wTGVmdCk7XG4gICAgYXBwbHlUcmFuc2Zvcm0oaW52ZXJ0ZWQsIHRvcFJpZ2h0KTtcbiAgICBhcHBseVRyYW5zZm9ybShpbnZlcnRlZCwgYm90dG9tUmlnaHQpO1xuICAgIGFwcGx5VHJhbnNmb3JtKGludmVydGVkLCBib3R0b21MZWZ0KTtcbiAgICBjb250ZXh0LnNhdmUoKTtcbiAgICBjb250ZXh0LmJlZ2luUGF0aCgpO1xuICAgIGNvbnRleHQubW92ZVRvKE1hdGgucm91bmQodG9wTGVmdFswXSksIE1hdGgucm91bmQodG9wTGVmdFsxXSkpO1xuICAgIGNvbnRleHQubGluZVRvKE1hdGgucm91bmQodG9wUmlnaHRbMF0pLCBNYXRoLnJvdW5kKHRvcFJpZ2h0WzFdKSk7XG4gICAgY29udGV4dC5saW5lVG8oTWF0aC5yb3VuZChib3R0b21SaWdodFswXSksIE1hdGgucm91bmQoYm90dG9tUmlnaHRbMV0pKTtcbiAgICBjb250ZXh0LmxpbmVUbyhNYXRoLnJvdW5kKGJvdHRvbUxlZnRbMF0pLCBNYXRoLnJvdW5kKGJvdHRvbUxlZnRbMV0pKTtcbiAgICBjb250ZXh0LmNsaXAoKTtcbiAgfTtcbiAgLyoqXG4gICAqIEBwYXJhbSB7aW1wb3J0KFwiLi4vLi4vcmVuZGVyL0V2ZW50VHlwZS5qc1wiKS5kZWZhdWx0fSB0eXBlIEV2ZW50IHR5cGUuXG4gICAqIEBwYXJhbSB7Q2FudmFzUmVuZGVyaW5nQ29udGV4dDJEfSBjb250ZXh0IENvbnRleHQuXG4gICAqIEBwYXJhbSB7aW1wb3J0KFwiLi4vLi4vUGx1Z2dhYmxlTWFwLmpzXCIpLkZyYW1lU3RhdGV9IGZyYW1lU3RhdGUgRnJhbWUgc3RhdGUuXG4gICAqIEBwcml2YXRlXG4gICAqL1xuXG5cbiAgQ2FudmFzTGF5ZXJSZW5kZXJlci5wcm90b3R5cGUuZGlzcGF0Y2hSZW5kZXJFdmVudF8gPSBmdW5jdGlvbiAodHlwZSwgY29udGV4dCwgZnJhbWVTdGF0ZSkge1xuICAgIHZhciBsYXllciA9IHRoaXMuZ2V0TGF5ZXIoKTtcblxuICAgIGlmIChsYXllci5oYXNMaXN0ZW5lcih0eXBlKSkge1xuICAgICAgdmFyIGV2ZW50XzEgPSBuZXcgUmVuZGVyRXZlbnQodHlwZSwgdGhpcy5pbnZlcnNlUGl4ZWxUcmFuc2Zvcm0sIGZyYW1lU3RhdGUsIGNvbnRleHQpO1xuICAgICAgbGF5ZXIuZGlzcGF0Y2hFdmVudChldmVudF8xKTtcbiAgICB9XG4gIH07XG4gIC8qKlxuICAgKiBAcGFyYW0ge0NhbnZhc1JlbmRlcmluZ0NvbnRleHQyRH0gY29udGV4dCBDb250ZXh0LlxuICAgKiBAcGFyYW0ge2ltcG9ydChcIi4uLy4uL1BsdWdnYWJsZU1hcC5qc1wiKS5GcmFtZVN0YXRlfSBmcmFtZVN0YXRlIEZyYW1lIHN0YXRlLlxuICAgKiBAcHJvdGVjdGVkXG4gICAqL1xuXG5cbiAgQ2FudmFzTGF5ZXJSZW5kZXJlci5wcm90b3R5cGUucHJlUmVuZGVyID0gZnVuY3Rpb24gKGNvbnRleHQsIGZyYW1lU3RhdGUpIHtcbiAgICB0aGlzLmRpc3BhdGNoUmVuZGVyRXZlbnRfKFJlbmRlckV2ZW50VHlwZS5QUkVSRU5ERVIsIGNvbnRleHQsIGZyYW1lU3RhdGUpO1xuICB9O1xuICAvKipcbiAgICogQHBhcmFtIHtDYW52YXNSZW5kZXJpbmdDb250ZXh0MkR9IGNvbnRleHQgQ29udGV4dC5cbiAgICogQHBhcmFtIHtpbXBvcnQoXCIuLi8uLi9QbHVnZ2FibGVNYXAuanNcIikuRnJhbWVTdGF0ZX0gZnJhbWVTdGF0ZSBGcmFtZSBzdGF0ZS5cbiAgICogQHByb3RlY3RlZFxuICAgKi9cblxuXG4gIENhbnZhc0xheWVyUmVuZGVyZXIucHJvdG90eXBlLnBvc3RSZW5kZXIgPSBmdW5jdGlvbiAoY29udGV4dCwgZnJhbWVTdGF0ZSkge1xuICAgIHRoaXMuZGlzcGF0Y2hSZW5kZXJFdmVudF8oUmVuZGVyRXZlbnRUeXBlLlBPU1RSRU5ERVIsIGNvbnRleHQsIGZyYW1lU3RhdGUpO1xuICB9O1xuICAvKipcbiAgICogQ3JlYXRlcyBhIHRyYW5zZm9ybSBmb3IgcmVuZGVyaW5nIHRvIGFuIGVsZW1lbnQgdGhhdCB3aWxsIGJlIHJvdGF0ZWQgYWZ0ZXIgcmVuZGVyaW5nLlxuICAgKiBAcGFyYW0ge2ltcG9ydChcIi4uLy4uL2Nvb3JkaW5hdGUuanNcIikuQ29vcmRpbmF0ZX0gY2VudGVyIENlbnRlci5cbiAgICogQHBhcmFtIHtudW1iZXJ9IHJlc29sdXRpb24gUmVzb2x1dGlvbi5cbiAgICogQHBhcmFtIHtudW1iZXJ9IHJvdGF0aW9uIFJvdGF0aW9uLlxuICAgKiBAcGFyYW0ge251bWJlcn0gcGl4ZWxSYXRpbyBQaXhlbCByYXRpby5cbiAgICogQHBhcmFtIHtudW1iZXJ9IHdpZHRoIFdpZHRoIG9mIHRoZSByZW5kZXJlZCBlbGVtZW50IChpbiBwaXhlbHMpLlxuICAgKiBAcGFyYW0ge251bWJlcn0gaGVpZ2h0IEhlaWdodCBvZiB0aGUgcmVuZGVyZWQgZWxlbWVudCAoaW4gcGl4ZWxzKS5cbiAgICogQHBhcmFtIHtudW1iZXJ9IG9mZnNldFggT2Zmc2V0IG9uIHRoZSB4LWF4aXMgaW4gdmlldyBjb29yZGluYXRlcy5cbiAgICogQHByb3RlY3RlZFxuICAgKiBAcmV0dXJuIHshaW1wb3J0KFwiLi4vLi4vdHJhbnNmb3JtLmpzXCIpLlRyYW5zZm9ybX0gVHJhbnNmb3JtLlxuICAgKi9cblxuXG4gIENhbnZhc0xheWVyUmVuZGVyZXIucHJvdG90eXBlLmdldFJlbmRlclRyYW5zZm9ybSA9IGZ1bmN0aW9uIChjZW50ZXIsIHJlc29sdXRpb24sIHJvdGF0aW9uLCBwaXhlbFJhdGlvLCB3aWR0aCwgaGVpZ2h0LCBvZmZzZXRYKSB7XG4gICAgdmFyIGR4MSA9IHdpZHRoIC8gMjtcbiAgICB2YXIgZHkxID0gaGVpZ2h0IC8gMjtcbiAgICB2YXIgc3ggPSBwaXhlbFJhdGlvIC8gcmVzb2x1dGlvbjtcbiAgICB2YXIgc3kgPSAtc3g7XG4gICAgdmFyIGR4MiA9IC1jZW50ZXJbMF0gKyBvZmZzZXRYO1xuICAgIHZhciBkeTIgPSAtY2VudGVyWzFdO1xuICAgIHJldHVybiBjb21wb3NlVHJhbnNmb3JtKHRoaXMudGVtcFRyYW5zZm9ybSwgZHgxLCBkeTEsIHN4LCBzeSwgLXJvdGF0aW9uLCBkeDIsIGR5Mik7XG4gIH07XG4gIC8qKlxuICAgKiBAcGFyYW0ge2ltcG9ydChcIi4uLy4uL3BpeGVsLmpzXCIpLlBpeGVsfSBwaXhlbCBQaXhlbC5cbiAgICogQHBhcmFtIHtpbXBvcnQoXCIuLi8uLi9QbHVnZ2FibGVNYXAuanNcIikuRnJhbWVTdGF0ZX0gZnJhbWVTdGF0ZSBGcmFtZVN0YXRlLlxuICAgKiBAcGFyYW0ge251bWJlcn0gaGl0VG9sZXJhbmNlIEhpdCB0b2xlcmFuY2UgaW4gcGl4ZWxzLlxuICAgKiBAcmV0dXJuIHtVaW50OENsYW1wZWRBcnJheXxVaW50OEFycmF5fSBUaGUgcmVzdWx0LiAgSWYgdGhlcmUgaXMgbm8gZGF0YSBhdCB0aGUgcGl4ZWxcbiAgICogICAgbG9jYXRpb24sIG51bGwgd2lsbCBiZSByZXR1cm5lZC4gIElmIHRoZXJlIGlzIGRhdGEsIGJ1dCBwaXhlbCB2YWx1ZXMgY2Fubm90IGJlXG4gICAqICAgIHJldHVybmVkLCBhbmQgZW1wdHkgYXJyYXkgd2lsbCBiZSByZXR1cm5lZC5cbiAgICovXG5cblxuICBDYW52YXNMYXllclJlbmRlcmVyLnByb3RvdHlwZS5nZXREYXRhQXRQaXhlbCA9IGZ1bmN0aW9uIChwaXhlbCwgZnJhbWVTdGF0ZSwgaGl0VG9sZXJhbmNlKSB7XG4gICAgdmFyIHJlbmRlclBpeGVsID0gYXBwbHlUcmFuc2Zvcm0odGhpcy5pbnZlcnNlUGl4ZWxUcmFuc2Zvcm0sIHBpeGVsLnNsaWNlKCkpO1xuICAgIHZhciBjb250ZXh0ID0gdGhpcy5jb250ZXh0O1xuICAgIHZhciBsYXllciA9IHRoaXMuZ2V0TGF5ZXIoKTtcbiAgICB2YXIgbGF5ZXJFeHRlbnQgPSBsYXllci5nZXRFeHRlbnQoKTtcblxuICAgIGlmIChsYXllckV4dGVudCkge1xuICAgICAgdmFyIHJlbmRlckNvb3JkaW5hdGUgPSBhcHBseVRyYW5zZm9ybShmcmFtZVN0YXRlLnBpeGVsVG9Db29yZGluYXRlVHJhbnNmb3JtLCBwaXhlbC5zbGljZSgpKTtcbiAgICAgIC8qKiBnZXQgb25seSBkYXRhIGluc2lkZSBvZiB0aGUgbGF5ZXIgZXh0ZW50ICovXG5cbiAgICAgIGlmICghY29udGFpbnNDb29yZGluYXRlKGxheWVyRXh0ZW50LCByZW5kZXJDb29yZGluYXRlKSkge1xuICAgICAgICByZXR1cm4gbnVsbDtcbiAgICAgIH1cbiAgICB9XG5cbiAgICB2YXIgZGF0YTtcblxuICAgIHRyeSB7XG4gICAgICB2YXIgeCA9IE1hdGgucm91bmQocmVuZGVyUGl4ZWxbMF0pO1xuICAgICAgdmFyIHkgPSBNYXRoLnJvdW5kKHJlbmRlclBpeGVsWzFdKTtcbiAgICAgIHZhciBuZXdDYW52YXMgPSBkb2N1bWVudC5jcmVhdGVFbGVtZW50KCdjYW52YXMnKTtcbiAgICAgIHZhciBuZXdDb250ZXh0ID0gbmV3Q2FudmFzLmdldENvbnRleHQoJzJkJyk7XG4gICAgICBuZXdDYW52YXMud2lkdGggPSAxO1xuICAgICAgbmV3Q2FudmFzLmhlaWdodCA9IDE7XG4gICAgICBuZXdDb250ZXh0LmNsZWFyUmVjdCgwLCAwLCAxLCAxKTtcbiAgICAgIG5ld0NvbnRleHQuZHJhd0ltYWdlKGNvbnRleHQuY2FudmFzLCB4LCB5LCAxLCAxLCAwLCAwLCAxLCAxKTtcbiAgICAgIGRhdGEgPSBuZXdDb250ZXh0LmdldEltYWdlRGF0YSgwLCAwLCAxLCAxKS5kYXRhO1xuICAgIH0gY2F0Y2ggKGVycikge1xuICAgICAgaWYgKGVyci5uYW1lID09PSAnU2VjdXJpdHlFcnJvcicpIHtcbiAgICAgICAgLy8gdGFpbnRlZCBjYW52YXMsIHdlIGFzc3VtZSB0aGVyZSBpcyBkYXRhIGF0IHRoZSBnaXZlbiBwaXhlbCAoYWx0aG91Z2ggdGhlcmUgbWlnaHQgbm90IGJlKVxuICAgICAgICByZXR1cm4gbmV3IFVpbnQ4QXJyYXkoKTtcbiAgICAgIH1cblxuICAgICAgcmV0dXJuIGRhdGE7XG4gICAgfVxuXG4gICAgaWYgKGRhdGFbM10gPT09IDApIHtcbiAgICAgIHJldHVybiBudWxsO1xuICAgIH1cblxuICAgIHJldHVybiBkYXRhO1xuICB9O1xuXG4gIHJldHVybiBDYW52YXNMYXllclJlbmRlcmVyO1xufShMYXllclJlbmRlcmVyKTtcblxuZXhwb3J0IGRlZmF1bHQgQ2FudmFzTGF5ZXJSZW5kZXJlcjsiLCIvKipcbiAqIEBtb2R1bGUgb2wvVGlsZVJhbmdlXG4gKi9cblxuLyoqXG4gKiBBIHJlcHJlc2VudGF0aW9uIG9mIGEgY29udGlndW91cyBibG9jayBvZiB0aWxlcy4gIEEgdGlsZSByYW5nZSBpcyBzcGVjaWZpZWRcbiAqIGJ5IGl0cyBtaW4vbWF4IHRpbGUgY29vcmRpbmF0ZXMgYW5kIGlzIGluY2x1c2l2ZSBvZiBjb29yZGluYXRlcy5cbiAqL1xudmFyIFRpbGVSYW5nZSA9XG4vKiogQGNsYXNzICovXG5mdW5jdGlvbiAoKSB7XG4gIC8qKlxuICAgKiBAcGFyYW0ge251bWJlcn0gbWluWCBNaW5pbXVtIFguXG4gICAqIEBwYXJhbSB7bnVtYmVyfSBtYXhYIE1heGltdW0gWC5cbiAgICogQHBhcmFtIHtudW1iZXJ9IG1pblkgTWluaW11bSBZLlxuICAgKiBAcGFyYW0ge251bWJlcn0gbWF4WSBNYXhpbXVtIFkuXG4gICAqL1xuICBmdW5jdGlvbiBUaWxlUmFuZ2UobWluWCwgbWF4WCwgbWluWSwgbWF4WSkge1xuICAgIC8qKlxuICAgICAqIEB0eXBlIHtudW1iZXJ9XG4gICAgICovXG4gICAgdGhpcy5taW5YID0gbWluWDtcbiAgICAvKipcbiAgICAgKiBAdHlwZSB7bnVtYmVyfVxuICAgICAqL1xuXG4gICAgdGhpcy5tYXhYID0gbWF4WDtcbiAgICAvKipcbiAgICAgKiBAdHlwZSB7bnVtYmVyfVxuICAgICAqL1xuXG4gICAgdGhpcy5taW5ZID0gbWluWTtcbiAgICAvKipcbiAgICAgKiBAdHlwZSB7bnVtYmVyfVxuICAgICAqL1xuXG4gICAgdGhpcy5tYXhZID0gbWF4WTtcbiAgfVxuICAvKipcbiAgICogQHBhcmFtIHtpbXBvcnQoXCIuL3RpbGVjb29yZC5qc1wiKS5UaWxlQ29vcmR9IHRpbGVDb29yZCBUaWxlIGNvb3JkaW5hdGUuXG4gICAqIEByZXR1cm4ge2Jvb2xlYW59IENvbnRhaW5zIHRpbGUgY29vcmRpbmF0ZS5cbiAgICovXG5cblxuICBUaWxlUmFuZ2UucHJvdG90eXBlLmNvbnRhaW5zID0gZnVuY3Rpb24gKHRpbGVDb29yZCkge1xuICAgIHJldHVybiB0aGlzLmNvbnRhaW5zWFkodGlsZUNvb3JkWzFdLCB0aWxlQ29vcmRbMl0pO1xuICB9O1xuICAvKipcbiAgICogQHBhcmFtIHtUaWxlUmFuZ2V9IHRpbGVSYW5nZSBUaWxlIHJhbmdlLlxuICAgKiBAcmV0dXJuIHtib29sZWFufSBDb250YWlucy5cbiAgICovXG5cblxuICBUaWxlUmFuZ2UucHJvdG90eXBlLmNvbnRhaW5zVGlsZVJhbmdlID0gZnVuY3Rpb24gKHRpbGVSYW5nZSkge1xuICAgIHJldHVybiB0aGlzLm1pblggPD0gdGlsZVJhbmdlLm1pblggJiYgdGlsZVJhbmdlLm1heFggPD0gdGhpcy5tYXhYICYmIHRoaXMubWluWSA8PSB0aWxlUmFuZ2UubWluWSAmJiB0aWxlUmFuZ2UubWF4WSA8PSB0aGlzLm1heFk7XG4gIH07XG4gIC8qKlxuICAgKiBAcGFyYW0ge251bWJlcn0geCBUaWxlIGNvb3JkaW5hdGUgeC5cbiAgICogQHBhcmFtIHtudW1iZXJ9IHkgVGlsZSBjb29yZGluYXRlIHkuXG4gICAqIEByZXR1cm4ge2Jvb2xlYW59IENvbnRhaW5zIGNvb3JkaW5hdGUuXG4gICAqL1xuXG5cbiAgVGlsZVJhbmdlLnByb3RvdHlwZS5jb250YWluc1hZID0gZnVuY3Rpb24gKHgsIHkpIHtcbiAgICByZXR1cm4gdGhpcy5taW5YIDw9IHggJiYgeCA8PSB0aGlzLm1heFggJiYgdGhpcy5taW5ZIDw9IHkgJiYgeSA8PSB0aGlzLm1heFk7XG4gIH07XG4gIC8qKlxuICAgKiBAcGFyYW0ge1RpbGVSYW5nZX0gdGlsZVJhbmdlIFRpbGUgcmFuZ2UuXG4gICAqIEByZXR1cm4ge2Jvb2xlYW59IEVxdWFscy5cbiAgICovXG5cblxuICBUaWxlUmFuZ2UucHJvdG90eXBlLmVxdWFscyA9IGZ1bmN0aW9uICh0aWxlUmFuZ2UpIHtcbiAgICByZXR1cm4gdGhpcy5taW5YID09IHRpbGVSYW5nZS5taW5YICYmIHRoaXMubWluWSA9PSB0aWxlUmFuZ2UubWluWSAmJiB0aGlzLm1heFggPT0gdGlsZVJhbmdlLm1heFggJiYgdGhpcy5tYXhZID09IHRpbGVSYW5nZS5tYXhZO1xuICB9O1xuICAvKipcbiAgICogQHBhcmFtIHtUaWxlUmFuZ2V9IHRpbGVSYW5nZSBUaWxlIHJhbmdlLlxuICAgKi9cblxuXG4gIFRpbGVSYW5nZS5wcm90b3R5cGUuZXh0ZW5kID0gZnVuY3Rpb24gKHRpbGVSYW5nZSkge1xuICAgIGlmICh0aWxlUmFuZ2UubWluWCA8IHRoaXMubWluWCkge1xuICAgICAgdGhpcy5taW5YID0gdGlsZVJhbmdlLm1pblg7XG4gICAgfVxuXG4gICAgaWYgKHRpbGVSYW5nZS5tYXhYID4gdGhpcy5tYXhYKSB7XG4gICAgICB0aGlzLm1heFggPSB0aWxlUmFuZ2UubWF4WDtcbiAgICB9XG5cbiAgICBpZiAodGlsZVJhbmdlLm1pblkgPCB0aGlzLm1pblkpIHtcbiAgICAgIHRoaXMubWluWSA9IHRpbGVSYW5nZS5taW5ZO1xuICAgIH1cblxuICAgIGlmICh0aWxlUmFuZ2UubWF4WSA+IHRoaXMubWF4WSkge1xuICAgICAgdGhpcy5tYXhZID0gdGlsZVJhbmdlLm1heFk7XG4gICAgfVxuICB9O1xuICAvKipcbiAgICogQHJldHVybiB7bnVtYmVyfSBIZWlnaHQuXG4gICAqL1xuXG5cbiAgVGlsZVJhbmdlLnByb3RvdHlwZS5nZXRIZWlnaHQgPSBmdW5jdGlvbiAoKSB7XG4gICAgcmV0dXJuIHRoaXMubWF4WSAtIHRoaXMubWluWSArIDE7XG4gIH07XG4gIC8qKlxuICAgKiBAcmV0dXJuIHtpbXBvcnQoXCIuL3NpemUuanNcIikuU2l6ZX0gU2l6ZS5cbiAgICovXG5cblxuICBUaWxlUmFuZ2UucHJvdG90eXBlLmdldFNpemUgPSBmdW5jdGlvbiAoKSB7XG4gICAgcmV0dXJuIFt0aGlzLmdldFdpZHRoKCksIHRoaXMuZ2V0SGVpZ2h0KCldO1xuICB9O1xuICAvKipcbiAgICogQHJldHVybiB7bnVtYmVyfSBXaWR0aC5cbiAgICovXG5cblxuICBUaWxlUmFuZ2UucHJvdG90eXBlLmdldFdpZHRoID0gZnVuY3Rpb24gKCkge1xuICAgIHJldHVybiB0aGlzLm1heFggLSB0aGlzLm1pblggKyAxO1xuICB9O1xuICAvKipcbiAgICogQHBhcmFtIHtUaWxlUmFuZ2V9IHRpbGVSYW5nZSBUaWxlIHJhbmdlLlxuICAgKiBAcmV0dXJuIHtib29sZWFufSBJbnRlcnNlY3RzLlxuICAgKi9cblxuXG4gIFRpbGVSYW5nZS5wcm90b3R5cGUuaW50ZXJzZWN0cyA9IGZ1bmN0aW9uICh0aWxlUmFuZ2UpIHtcbiAgICByZXR1cm4gdGhpcy5taW5YIDw9IHRpbGVSYW5nZS5tYXhYICYmIHRoaXMubWF4WCA+PSB0aWxlUmFuZ2UubWluWCAmJiB0aGlzLm1pblkgPD0gdGlsZVJhbmdlLm1heFkgJiYgdGhpcy5tYXhZID49IHRpbGVSYW5nZS5taW5ZO1xuICB9O1xuXG4gIHJldHVybiBUaWxlUmFuZ2U7XG59KCk7XG4vKipcbiAqIEBwYXJhbSB7bnVtYmVyfSBtaW5YIE1pbmltdW0gWC5cbiAqIEBwYXJhbSB7bnVtYmVyfSBtYXhYIE1heGltdW0gWC5cbiAqIEBwYXJhbSB7bnVtYmVyfSBtaW5ZIE1pbmltdW0gWS5cbiAqIEBwYXJhbSB7bnVtYmVyfSBtYXhZIE1heGltdW0gWS5cbiAqIEBwYXJhbSB7VGlsZVJhbmdlPX0gdGlsZVJhbmdlIFRpbGVSYW5nZS5cbiAqIEByZXR1cm4ge1RpbGVSYW5nZX0gVGlsZSByYW5nZS5cbiAqL1xuXG5cbmV4cG9ydCBmdW5jdGlvbiBjcmVhdGVPclVwZGF0ZShtaW5YLCBtYXhYLCBtaW5ZLCBtYXhZLCB0aWxlUmFuZ2UpIHtcbiAgaWYgKHRpbGVSYW5nZSAhPT0gdW5kZWZpbmVkKSB7XG4gICAgdGlsZVJhbmdlLm1pblggPSBtaW5YO1xuICAgIHRpbGVSYW5nZS5tYXhYID0gbWF4WDtcbiAgICB0aWxlUmFuZ2UubWluWSA9IG1pblk7XG4gICAgdGlsZVJhbmdlLm1heFkgPSBtYXhZO1xuICAgIHJldHVybiB0aWxlUmFuZ2U7XG4gIH0gZWxzZSB7XG4gICAgcmV0dXJuIG5ldyBUaWxlUmFuZ2UobWluWCwgbWF4WCwgbWluWSwgbWF4WSk7XG4gIH1cbn1cbmV4cG9ydCBkZWZhdWx0IFRpbGVSYW5nZTsiLCJ2YXIgX19leHRlbmRzID0gdGhpcyAmJiB0aGlzLl9fZXh0ZW5kcyB8fCBmdW5jdGlvbiAoKSB7XG4gIHZhciBfZXh0ZW5kU3RhdGljcyA9IGZ1bmN0aW9uIGV4dGVuZFN0YXRpY3MoZCwgYikge1xuICAgIF9leHRlbmRTdGF0aWNzID0gT2JqZWN0LnNldFByb3RvdHlwZU9mIHx8IHtcbiAgICAgIF9fcHJvdG9fXzogW11cbiAgICB9IGluc3RhbmNlb2YgQXJyYXkgJiYgZnVuY3Rpb24gKGQsIGIpIHtcbiAgICAgIGQuX19wcm90b19fID0gYjtcbiAgICB9IHx8IGZ1bmN0aW9uIChkLCBiKSB7XG4gICAgICBmb3IgKHZhciBwIGluIGIpIHtcbiAgICAgICAgaWYgKE9iamVjdC5wcm90b3R5cGUuaGFzT3duUHJvcGVydHkuY2FsbChiLCBwKSkgZFtwXSA9IGJbcF07XG4gICAgICB9XG4gICAgfTtcblxuICAgIHJldHVybiBfZXh0ZW5kU3RhdGljcyhkLCBiKTtcbiAgfTtcblxuICByZXR1cm4gZnVuY3Rpb24gKGQsIGIpIHtcbiAgICBfZXh0ZW5kU3RhdGljcyhkLCBiKTtcblxuICAgIGZ1bmN0aW9uIF9fKCkge1xuICAgICAgdGhpcy5jb25zdHJ1Y3RvciA9IGQ7XG4gICAgfVxuXG4gICAgZC5wcm90b3R5cGUgPSBiID09PSBudWxsID8gT2JqZWN0LmNyZWF0ZShiKSA6IChfXy5wcm90b3R5cGUgPSBiLnByb3RvdHlwZSwgbmV3IF9fKCkpO1xuICB9O1xufSgpO1xuLyoqXG4gKiBAbW9kdWxlIG9sL3JlbmRlcmVyL2NhbnZhcy9UaWxlTGF5ZXJcbiAqL1xuXG5cbmltcG9ydCBDYW52YXNMYXllclJlbmRlcmVyIGZyb20gJy4vTGF5ZXIuanMnO1xuaW1wb3J0IFRpbGVSYW5nZSBmcm9tICcuLi8uLi9UaWxlUmFuZ2UuanMnO1xuaW1wb3J0IFRpbGVTdGF0ZSBmcm9tICcuLi8uLi9UaWxlU3RhdGUuanMnO1xuaW1wb3J0IHsgYXBwbHkgYXMgYXBwbHlUcmFuc2Zvcm0sIGNvbXBvc2UgYXMgY29tcG9zZVRyYW5zZm9ybSwgbWFrZUludmVyc2UgfSBmcm9tICcuLi8uLi90cmFuc2Zvcm0uanMnO1xuaW1wb3J0IHsgYXNzaWduIH0gZnJvbSAnLi4vLi4vb2JqLmpzJztcbmltcG9ydCB7IGNyZWF0ZUVtcHR5LCBlcXVhbHMsIGdldEludGVyc2VjdGlvbiwgZ2V0VG9wTGVmdCB9IGZyb20gJy4uLy4uL2V4dGVudC5qcyc7XG5pbXBvcnQgeyBjcmVhdGVUcmFuc2Zvcm1TdHJpbmcgfSBmcm9tICcuLi8uLi9yZW5kZXIvY2FudmFzLmpzJztcbmltcG9ydCB7IGZyb21Vc2VyRXh0ZW50IH0gZnJvbSAnLi4vLi4vcHJvai5qcyc7XG5pbXBvcnQgeyBnZXRVaWQgfSBmcm9tICcuLi8uLi91dGlsLmpzJztcbmltcG9ydCB7IG51bWJlclNhZmVDb21wYXJlRnVuY3Rpb24gfSBmcm9tICcuLi8uLi9hcnJheS5qcyc7XG4vKipcbiAqIEBjbGFzc2Rlc2NcbiAqIENhbnZhcyByZW5kZXJlciBmb3IgdGlsZSBsYXllcnMuXG4gKiBAYXBpXG4gKi9cblxudmFyIENhbnZhc1RpbGVMYXllclJlbmRlcmVyID1cbi8qKiBAY2xhc3MgKi9cbmZ1bmN0aW9uIChfc3VwZXIpIHtcbiAgX19leHRlbmRzKENhbnZhc1RpbGVMYXllclJlbmRlcmVyLCBfc3VwZXIpO1xuICAvKipcbiAgICogQHBhcmFtIHtpbXBvcnQoXCIuLi8uLi9sYXllci9UaWxlLmpzXCIpLmRlZmF1bHR8aW1wb3J0KFwiLi4vLi4vbGF5ZXIvVmVjdG9yVGlsZS5qc1wiKS5kZWZhdWx0fSB0aWxlTGF5ZXIgVGlsZSBsYXllci5cbiAgICovXG5cblxuICBmdW5jdGlvbiBDYW52YXNUaWxlTGF5ZXJSZW5kZXJlcih0aWxlTGF5ZXIpIHtcbiAgICB2YXIgX3RoaXMgPSBfc3VwZXIuY2FsbCh0aGlzLCB0aWxlTGF5ZXIpIHx8IHRoaXM7XG4gICAgLyoqXG4gICAgICogUmVuZGVyZWQgZXh0ZW50IGhhcyBjaGFuZ2VkIHNpbmNlIHRoZSBwcmV2aW91cyBgcmVuZGVyRnJhbWUoKWAgY2FsbFxuICAgICAqIEB0eXBlIHtib29sZWFufVxuICAgICAqL1xuXG5cbiAgICBfdGhpcy5leHRlbnRDaGFuZ2VkID0gdHJ1ZTtcbiAgICAvKipcbiAgICAgKiBAcHJpdmF0ZVxuICAgICAqIEB0eXBlIHs/aW1wb3J0KFwiLi4vLi4vZXh0ZW50LmpzXCIpLkV4dGVudH1cbiAgICAgKi9cblxuICAgIF90aGlzLnJlbmRlcmVkRXh0ZW50XyA9IG51bGw7XG4gICAgLyoqXG4gICAgICogQHByb3RlY3RlZFxuICAgICAqIEB0eXBlIHtudW1iZXJ9XG4gICAgICovXG5cbiAgICBfdGhpcy5yZW5kZXJlZFBpeGVsUmF0aW87XG4gICAgLyoqXG4gICAgICogQHByb3RlY3RlZFxuICAgICAqIEB0eXBlIHtpbXBvcnQoXCIuLi8uLi9wcm9qL1Byb2plY3Rpb24uanNcIikuZGVmYXVsdH1cbiAgICAgKi9cblxuICAgIF90aGlzLnJlbmRlcmVkUHJvamVjdGlvbiA9IG51bGw7XG4gICAgLyoqXG4gICAgICogQHByb3RlY3RlZFxuICAgICAqIEB0eXBlIHtudW1iZXJ9XG4gICAgICovXG5cbiAgICBfdGhpcy5yZW5kZXJlZFJldmlzaW9uO1xuICAgIC8qKlxuICAgICAqIEBwcm90ZWN0ZWRcbiAgICAgKiBAdHlwZSB7IUFycmF5PGltcG9ydChcIi4uLy4uL1RpbGUuanNcIikuZGVmYXVsdD59XG4gICAgICovXG5cbiAgICBfdGhpcy5yZW5kZXJlZFRpbGVzID0gW107XG4gICAgLyoqXG4gICAgICogQHByaXZhdGVcbiAgICAgKiBAdHlwZSB7Ym9vbGVhbn1cbiAgICAgKi9cblxuICAgIF90aGlzLm5ld1RpbGVzXyA9IGZhbHNlO1xuICAgIC8qKlxuICAgICAqIEBwcm90ZWN0ZWRcbiAgICAgKiBAdHlwZSB7aW1wb3J0KFwiLi4vLi4vZXh0ZW50LmpzXCIpLkV4dGVudH1cbiAgICAgKi9cblxuICAgIF90aGlzLnRtcEV4dGVudCA9IGNyZWF0ZUVtcHR5KCk7XG4gICAgLyoqXG4gICAgICogQHByaXZhdGVcbiAgICAgKiBAdHlwZSB7aW1wb3J0KFwiLi4vLi4vVGlsZVJhbmdlLmpzXCIpLmRlZmF1bHR9XG4gICAgICovXG5cbiAgICBfdGhpcy50bXBUaWxlUmFuZ2VfID0gbmV3IFRpbGVSYW5nZSgwLCAwLCAwLCAwKTtcbiAgICByZXR1cm4gX3RoaXM7XG4gIH1cbiAgLyoqXG4gICAqIEBwcm90ZWN0ZWRcbiAgICogQHBhcmFtIHtpbXBvcnQoXCIuLi8uLi9UaWxlLmpzXCIpLmRlZmF1bHR9IHRpbGUgVGlsZS5cbiAgICogQHJldHVybiB7Ym9vbGVhbn0gVGlsZSBpcyBkcmF3YWJsZS5cbiAgICovXG5cblxuICBDYW52YXNUaWxlTGF5ZXJSZW5kZXJlci5wcm90b3R5cGUuaXNEcmF3YWJsZVRpbGUgPSBmdW5jdGlvbiAodGlsZSkge1xuICAgIHZhciB0aWxlTGF5ZXIgPSB0aGlzLmdldExheWVyKCk7XG4gICAgdmFyIHRpbGVTdGF0ZSA9IHRpbGUuZ2V0U3RhdGUoKTtcbiAgICB2YXIgdXNlSW50ZXJpbVRpbGVzT25FcnJvciA9IHRpbGVMYXllci5nZXRVc2VJbnRlcmltVGlsZXNPbkVycm9yKCk7XG4gICAgcmV0dXJuIHRpbGVTdGF0ZSA9PSBUaWxlU3RhdGUuTE9BREVEIHx8IHRpbGVTdGF0ZSA9PSBUaWxlU3RhdGUuRU1QVFkgfHwgdGlsZVN0YXRlID09IFRpbGVTdGF0ZS5FUlJPUiAmJiAhdXNlSW50ZXJpbVRpbGVzT25FcnJvcjtcbiAgfTtcbiAgLyoqXG4gICAqIEBwYXJhbSB7bnVtYmVyfSB6IFRpbGUgY29vcmRpbmF0ZSB6LlxuICAgKiBAcGFyYW0ge251bWJlcn0geCBUaWxlIGNvb3JkaW5hdGUgeC5cbiAgICogQHBhcmFtIHtudW1iZXJ9IHkgVGlsZSBjb29yZGluYXRlIHkuXG4gICAqIEBwYXJhbSB7aW1wb3J0KFwiLi4vLi4vUGx1Z2dhYmxlTWFwLmpzXCIpLkZyYW1lU3RhdGV9IGZyYW1lU3RhdGUgRnJhbWUgc3RhdGUuXG4gICAqIEByZXR1cm4geyFpbXBvcnQoXCIuLi8uLi9UaWxlLmpzXCIpLmRlZmF1bHR9IFRpbGUuXG4gICAqL1xuXG5cbiAgQ2FudmFzVGlsZUxheWVyUmVuZGVyZXIucHJvdG90eXBlLmdldFRpbGUgPSBmdW5jdGlvbiAoeiwgeCwgeSwgZnJhbWVTdGF0ZSkge1xuICAgIHZhciBwaXhlbFJhdGlvID0gZnJhbWVTdGF0ZS5waXhlbFJhdGlvO1xuICAgIHZhciBwcm9qZWN0aW9uID0gZnJhbWVTdGF0ZS52aWV3U3RhdGUucHJvamVjdGlvbjtcbiAgICB2YXIgdGlsZUxheWVyID0gdGhpcy5nZXRMYXllcigpO1xuICAgIHZhciB0aWxlU291cmNlID0gdGlsZUxheWVyLmdldFNvdXJjZSgpO1xuICAgIHZhciB0aWxlID0gdGlsZVNvdXJjZS5nZXRUaWxlKHosIHgsIHksIHBpeGVsUmF0aW8sIHByb2plY3Rpb24pO1xuXG4gICAgaWYgKHRpbGUuZ2V0U3RhdGUoKSA9PSBUaWxlU3RhdGUuRVJST1IpIHtcbiAgICAgIGlmICghdGlsZUxheWVyLmdldFVzZUludGVyaW1UaWxlc09uRXJyb3IoKSkge1xuICAgICAgICAvLyBXaGVuIHVzZUludGVyaW1UaWxlc09uRXJyb3IgaXMgZmFsc2UsIHdlIGNvbnNpZGVyIHRoZSBlcnJvciB0aWxlIGFzIGxvYWRlZC5cbiAgICAgICAgdGlsZS5zZXRTdGF0ZShUaWxlU3RhdGUuTE9BREVEKTtcbiAgICAgIH0gZWxzZSBpZiAodGlsZUxheWVyLmdldFByZWxvYWQoKSA+IDApIHtcbiAgICAgICAgLy8gUHJlbG9hZGVkIHRpbGVzIGZvciBsb3dlciByZXNvbHV0aW9ucyBtaWdodCBoYXZlIGZpbmlzaGVkIGxvYWRpbmcuXG4gICAgICAgIHRoaXMubmV3VGlsZXNfID0gdHJ1ZTtcbiAgICAgIH1cbiAgICB9XG5cbiAgICBpZiAoIXRoaXMuaXNEcmF3YWJsZVRpbGUodGlsZSkpIHtcbiAgICAgIHRpbGUgPSB0aWxlLmdldEludGVyaW1UaWxlKCk7XG4gICAgfVxuXG4gICAgcmV0dXJuIHRpbGU7XG4gIH07XG4gIC8qKlxuICAgKiBAcGFyYW0ge09iamVjdDxudW1iZXIsIE9iamVjdDxzdHJpbmcsIGltcG9ydChcIi4uLy4uL1RpbGUuanNcIikuZGVmYXVsdD4+fSB0aWxlcyBMb29rdXAgb2YgbG9hZGVkIHRpbGVzIGJ5IHpvb20gbGV2ZWwuXG4gICAqIEBwYXJhbSB7bnVtYmVyfSB6b29tIFpvb20gbGV2ZWwuXG4gICAqIEBwYXJhbSB7aW1wb3J0KFwiLi4vLi4vVGlsZS5qc1wiKS5kZWZhdWx0fSB0aWxlIFRpbGUuXG4gICAqIEByZXR1cm4ge2Jvb2xlYW58dm9pZH0gSWYgYGZhbHNlYCwgdGhlIHRpbGUgd2lsbCBub3QgYmUgY29uc2lkZXJlZCBsb2FkZWQuXG4gICAqL1xuXG5cbiAgQ2FudmFzVGlsZUxheWVyUmVuZGVyZXIucHJvdG90eXBlLmxvYWRlZFRpbGVDYWxsYmFjayA9IGZ1bmN0aW9uICh0aWxlcywgem9vbSwgdGlsZSkge1xuICAgIGlmICh0aGlzLmlzRHJhd2FibGVUaWxlKHRpbGUpKSB7XG4gICAgICByZXR1cm4gX3N1cGVyLnByb3RvdHlwZS5sb2FkZWRUaWxlQ2FsbGJhY2suY2FsbCh0aGlzLCB0aWxlcywgem9vbSwgdGlsZSk7XG4gICAgfVxuXG4gICAgcmV0dXJuIGZhbHNlO1xuICB9O1xuICAvKipcbiAgICogRGV0ZXJtaW5lIHdoZXRoZXIgcmVuZGVyIHNob3VsZCBiZSBjYWxsZWQuXG4gICAqIEBwYXJhbSB7aW1wb3J0KFwiLi4vLi4vUGx1Z2dhYmxlTWFwLmpzXCIpLkZyYW1lU3RhdGV9IGZyYW1lU3RhdGUgRnJhbWUgc3RhdGUuXG4gICAqIEByZXR1cm4ge2Jvb2xlYW59IExheWVyIGlzIHJlYWR5IHRvIGJlIHJlbmRlcmVkLlxuICAgKi9cblxuXG4gIENhbnZhc1RpbGVMYXllclJlbmRlcmVyLnByb3RvdHlwZS5wcmVwYXJlRnJhbWUgPSBmdW5jdGlvbiAoZnJhbWVTdGF0ZSkge1xuICAgIHJldHVybiAhIXRoaXMuZ2V0TGF5ZXIoKS5nZXRTb3VyY2UoKTtcbiAgfTtcbiAgLyoqXG4gICAqIFJlbmRlciB0aGUgbGF5ZXIuXG4gICAqIEBwYXJhbSB7aW1wb3J0KFwiLi4vLi4vUGx1Z2dhYmxlTWFwLmpzXCIpLkZyYW1lU3RhdGV9IGZyYW1lU3RhdGUgRnJhbWUgc3RhdGUuXG4gICAqIEBwYXJhbSB7SFRNTEVsZW1lbnR9IHRhcmdldCBUYXJnZXQgdGhhdCBtYXkgYmUgdXNlZCB0byByZW5kZXIgY29udGVudCB0by5cbiAgICogQHJldHVybiB7SFRNTEVsZW1lbnR9IFRoZSByZW5kZXJlZCBlbGVtZW50LlxuICAgKi9cblxuXG4gIENhbnZhc1RpbGVMYXllclJlbmRlcmVyLnByb3RvdHlwZS5yZW5kZXJGcmFtZSA9IGZ1bmN0aW9uIChmcmFtZVN0YXRlLCB0YXJnZXQpIHtcbiAgICB2YXIgbGF5ZXJTdGF0ZSA9IGZyYW1lU3RhdGUubGF5ZXJTdGF0ZXNBcnJheVtmcmFtZVN0YXRlLmxheWVySW5kZXhdO1xuICAgIHZhciB2aWV3U3RhdGUgPSBmcmFtZVN0YXRlLnZpZXdTdGF0ZTtcbiAgICB2YXIgcHJvamVjdGlvbiA9IHZpZXdTdGF0ZS5wcm9qZWN0aW9uO1xuICAgIHZhciB2aWV3UmVzb2x1dGlvbiA9IHZpZXdTdGF0ZS5yZXNvbHV0aW9uO1xuICAgIHZhciB2aWV3Q2VudGVyID0gdmlld1N0YXRlLmNlbnRlcjtcbiAgICB2YXIgcm90YXRpb24gPSB2aWV3U3RhdGUucm90YXRpb247XG4gICAgdmFyIHBpeGVsUmF0aW8gPSBmcmFtZVN0YXRlLnBpeGVsUmF0aW87XG4gICAgdmFyIHRpbGVMYXllciA9IHRoaXMuZ2V0TGF5ZXIoKTtcbiAgICB2YXIgdGlsZVNvdXJjZSA9IHRpbGVMYXllci5nZXRTb3VyY2UoKTtcbiAgICB2YXIgc291cmNlUmV2aXNpb24gPSB0aWxlU291cmNlLmdldFJldmlzaW9uKCk7XG4gICAgdmFyIHRpbGVHcmlkID0gdGlsZVNvdXJjZS5nZXRUaWxlR3JpZEZvclByb2plY3Rpb24ocHJvamVjdGlvbik7XG4gICAgdmFyIHogPSB0aWxlR3JpZC5nZXRaRm9yUmVzb2x1dGlvbih2aWV3UmVzb2x1dGlvbiwgdGlsZVNvdXJjZS56RGlyZWN0aW9uKTtcbiAgICB2YXIgdGlsZVJlc29sdXRpb24gPSB0aWxlR3JpZC5nZXRSZXNvbHV0aW9uKHopO1xuICAgIHZhciBleHRlbnQgPSBmcmFtZVN0YXRlLmV4dGVudDtcbiAgICB2YXIgbGF5ZXJFeHRlbnQgPSBsYXllclN0YXRlLmV4dGVudCAmJiBmcm9tVXNlckV4dGVudChsYXllclN0YXRlLmV4dGVudCwgcHJvamVjdGlvbik7XG5cbiAgICBpZiAobGF5ZXJFeHRlbnQpIHtcbiAgICAgIGV4dGVudCA9IGdldEludGVyc2VjdGlvbihleHRlbnQsIGZyb21Vc2VyRXh0ZW50KGxheWVyU3RhdGUuZXh0ZW50LCBwcm9qZWN0aW9uKSk7XG4gICAgfVxuXG4gICAgdmFyIHRpbGVQaXhlbFJhdGlvID0gdGlsZVNvdXJjZS5nZXRUaWxlUGl4ZWxSYXRpbyhwaXhlbFJhdGlvKTsgLy8gZGVzaXJlZCBkaW1lbnNpb25zIG9mIHRoZSBjYW52YXMgaW4gcGl4ZWxzXG5cbiAgICB2YXIgd2lkdGggPSBNYXRoLnJvdW5kKGZyYW1lU3RhdGUuc2l6ZVswXSAqIHRpbGVQaXhlbFJhdGlvKTtcbiAgICB2YXIgaGVpZ2h0ID0gTWF0aC5yb3VuZChmcmFtZVN0YXRlLnNpemVbMV0gKiB0aWxlUGl4ZWxSYXRpbyk7XG5cbiAgICBpZiAocm90YXRpb24pIHtcbiAgICAgIHZhciBzaXplID0gTWF0aC5yb3VuZChNYXRoLnNxcnQod2lkdGggKiB3aWR0aCArIGhlaWdodCAqIGhlaWdodCkpO1xuICAgICAgd2lkdGggPSBzaXplO1xuICAgICAgaGVpZ2h0ID0gc2l6ZTtcbiAgICB9XG5cbiAgICB2YXIgZHggPSB0aWxlUmVzb2x1dGlvbiAqIHdpZHRoIC8gMiAvIHRpbGVQaXhlbFJhdGlvO1xuICAgIHZhciBkeSA9IHRpbGVSZXNvbHV0aW9uICogaGVpZ2h0IC8gMiAvIHRpbGVQaXhlbFJhdGlvO1xuICAgIHZhciBjYW52YXNFeHRlbnQgPSBbdmlld0NlbnRlclswXSAtIGR4LCB2aWV3Q2VudGVyWzFdIC0gZHksIHZpZXdDZW50ZXJbMF0gKyBkeCwgdmlld0NlbnRlclsxXSArIGR5XTtcbiAgICB2YXIgdGlsZVJhbmdlID0gdGlsZUdyaWQuZ2V0VGlsZVJhbmdlRm9yRXh0ZW50QW5kWihleHRlbnQsIHopO1xuICAgIC8qKlxuICAgICAqIEB0eXBlIHtPYmplY3Q8bnVtYmVyLCBPYmplY3Q8c3RyaW5nLCBpbXBvcnQoXCIuLi8uLi9UaWxlLmpzXCIpLmRlZmF1bHQ+Pn1cbiAgICAgKi9cblxuICAgIHZhciB0aWxlc1RvRHJhd0J5WiA9IHt9O1xuICAgIHRpbGVzVG9EcmF3QnlaW3pdID0ge307XG4gICAgdmFyIGZpbmRMb2FkZWRUaWxlcyA9IHRoaXMuY3JlYXRlTG9hZGVkVGlsZUZpbmRlcih0aWxlU291cmNlLCBwcm9qZWN0aW9uLCB0aWxlc1RvRHJhd0J5Wik7XG4gICAgdmFyIHRtcEV4dGVudCA9IHRoaXMudG1wRXh0ZW50O1xuICAgIHZhciB0bXBUaWxlUmFuZ2UgPSB0aGlzLnRtcFRpbGVSYW5nZV87XG4gICAgdGhpcy5uZXdUaWxlc18gPSBmYWxzZTtcblxuICAgIGZvciAodmFyIHggPSB0aWxlUmFuZ2UubWluWDsgeCA8PSB0aWxlUmFuZ2UubWF4WDsgKyt4KSB7XG4gICAgICBmb3IgKHZhciB5ID0gdGlsZVJhbmdlLm1pblk7IHkgPD0gdGlsZVJhbmdlLm1heFk7ICsreSkge1xuICAgICAgICB2YXIgdGlsZSA9IHRoaXMuZ2V0VGlsZSh6LCB4LCB5LCBmcmFtZVN0YXRlKTtcblxuICAgICAgICBpZiAodGhpcy5pc0RyYXdhYmxlVGlsZSh0aWxlKSkge1xuICAgICAgICAgIHZhciB1aWQgPSBnZXRVaWQodGhpcyk7XG5cbiAgICAgICAgICBpZiAodGlsZS5nZXRTdGF0ZSgpID09IFRpbGVTdGF0ZS5MT0FERUQpIHtcbiAgICAgICAgICAgIHRpbGVzVG9EcmF3QnlaW3pdW3RpbGUudGlsZUNvb3JkLnRvU3RyaW5nKCldID0gdGlsZTtcbiAgICAgICAgICAgIHZhciBpblRyYW5zaXRpb24gPSB0aWxlLmluVHJhbnNpdGlvbih1aWQpO1xuXG4gICAgICAgICAgICBpZiAoIXRoaXMubmV3VGlsZXNfICYmIChpblRyYW5zaXRpb24gfHwgdGhpcy5yZW5kZXJlZFRpbGVzLmluZGV4T2YodGlsZSkgPT09IC0xKSkge1xuICAgICAgICAgICAgICB0aGlzLm5ld1RpbGVzXyA9IHRydWU7XG4gICAgICAgICAgICB9XG4gICAgICAgICAgfVxuXG4gICAgICAgICAgaWYgKHRpbGUuZ2V0QWxwaGEodWlkLCBmcmFtZVN0YXRlLnRpbWUpID09PSAxKSB7XG4gICAgICAgICAgICAvLyBkb24ndCBsb29rIGZvciBhbHQgdGlsZXMgaWYgYWxwaGEgaXMgMVxuICAgICAgICAgICAgY29udGludWU7XG4gICAgICAgICAgfVxuICAgICAgICB9XG5cbiAgICAgICAgdmFyIGNoaWxkVGlsZVJhbmdlID0gdGlsZUdyaWQuZ2V0VGlsZUNvb3JkQ2hpbGRUaWxlUmFuZ2UodGlsZS50aWxlQ29vcmQsIHRtcFRpbGVSYW5nZSwgdG1wRXh0ZW50KTtcbiAgICAgICAgdmFyIGNvdmVyZWQgPSBmYWxzZTtcblxuICAgICAgICBpZiAoY2hpbGRUaWxlUmFuZ2UpIHtcbiAgICAgICAgICBjb3ZlcmVkID0gZmluZExvYWRlZFRpbGVzKHogKyAxLCBjaGlsZFRpbGVSYW5nZSk7XG4gICAgICAgIH1cblxuICAgICAgICBpZiAoIWNvdmVyZWQpIHtcbiAgICAgICAgICB0aWxlR3JpZC5mb3JFYWNoVGlsZUNvb3JkUGFyZW50VGlsZVJhbmdlKHRpbGUudGlsZUNvb3JkLCBmaW5kTG9hZGVkVGlsZXMsIHRtcFRpbGVSYW5nZSwgdG1wRXh0ZW50KTtcbiAgICAgICAgfVxuICAgICAgfVxuICAgIH1cblxuICAgIHZhciBjYW52YXNTY2FsZSA9IHRpbGVSZXNvbHV0aW9uIC8gdmlld1Jlc29sdXRpb247IC8vIHNldCBmb3J3YXJkIGFuZCBpbnZlcnNlIHBpeGVsIHRyYW5zZm9ybXNcblxuICAgIGNvbXBvc2VUcmFuc2Zvcm0odGhpcy5waXhlbFRyYW5zZm9ybSwgZnJhbWVTdGF0ZS5zaXplWzBdIC8gMiwgZnJhbWVTdGF0ZS5zaXplWzFdIC8gMiwgMSAvIHRpbGVQaXhlbFJhdGlvLCAxIC8gdGlsZVBpeGVsUmF0aW8sIHJvdGF0aW9uLCAtd2lkdGggLyAyLCAtaGVpZ2h0IC8gMik7XG4gICAgdmFyIGNhbnZhc1RyYW5zZm9ybSA9IGNyZWF0ZVRyYW5zZm9ybVN0cmluZyh0aGlzLnBpeGVsVHJhbnNmb3JtKTtcbiAgICB0aGlzLnVzZUNvbnRhaW5lcih0YXJnZXQsIGNhbnZhc1RyYW5zZm9ybSwgbGF5ZXJTdGF0ZS5vcGFjaXR5KTtcbiAgICB2YXIgY29udGV4dCA9IHRoaXMuY29udGV4dDtcbiAgICB2YXIgY2FudmFzID0gY29udGV4dC5jYW52YXM7XG4gICAgbWFrZUludmVyc2UodGhpcy5pbnZlcnNlUGl4ZWxUcmFuc2Zvcm0sIHRoaXMucGl4ZWxUcmFuc2Zvcm0pOyAvLyBzZXQgc2NhbGUgdHJhbnNmb3JtIGZvciBjYWxjdWxhdGluZyB0aWxlIHBvc2l0aW9ucyBvbiB0aGUgY2FudmFzXG5cbiAgICBjb21wb3NlVHJhbnNmb3JtKHRoaXMudGVtcFRyYW5zZm9ybSwgd2lkdGggLyAyLCBoZWlnaHQgLyAyLCBjYW52YXNTY2FsZSwgY2FudmFzU2NhbGUsIDAsIC13aWR0aCAvIDIsIC1oZWlnaHQgLyAyKTtcblxuICAgIGlmIChjYW52YXMud2lkdGggIT0gd2lkdGggfHwgY2FudmFzLmhlaWdodCAhPSBoZWlnaHQpIHtcbiAgICAgIGNhbnZhcy53aWR0aCA9IHdpZHRoO1xuICAgICAgY2FudmFzLmhlaWdodCA9IGhlaWdodDtcbiAgICB9IGVsc2UgaWYgKCF0aGlzLmNvbnRhaW5lclJldXNlZCkge1xuICAgICAgY29udGV4dC5jbGVhclJlY3QoMCwgMCwgd2lkdGgsIGhlaWdodCk7XG4gICAgfVxuXG4gICAgaWYgKGxheWVyRXh0ZW50KSB7XG4gICAgICB0aGlzLmNsaXBVbnJvdGF0ZWQoY29udGV4dCwgZnJhbWVTdGF0ZSwgbGF5ZXJFeHRlbnQpO1xuICAgIH1cblxuICAgIGFzc2lnbihjb250ZXh0LCB0aWxlU291cmNlLmdldENvbnRleHRPcHRpb25zKCkpO1xuICAgIHRoaXMucHJlUmVuZGVyKGNvbnRleHQsIGZyYW1lU3RhdGUpO1xuICAgIHRoaXMucmVuZGVyZWRUaWxlcy5sZW5ndGggPSAwO1xuICAgIC8qKiBAdHlwZSB7QXJyYXk8bnVtYmVyPn0gKi9cblxuICAgIHZhciB6cyA9IE9iamVjdC5rZXlzKHRpbGVzVG9EcmF3QnlaKS5tYXAoTnVtYmVyKTtcbiAgICB6cy5zb3J0KG51bWJlclNhZmVDb21wYXJlRnVuY3Rpb24pO1xuICAgIHZhciBjbGlwcywgY2xpcFpzLCBjdXJyZW50Q2xpcDtcblxuICAgIGlmIChsYXllclN0YXRlLm9wYWNpdHkgPT09IDEgJiYgKCF0aGlzLmNvbnRhaW5lclJldXNlZCB8fCB0aWxlU291cmNlLmdldE9wYXF1ZShmcmFtZVN0YXRlLnZpZXdTdGF0ZS5wcm9qZWN0aW9uKSkpIHtcbiAgICAgIHpzID0genMucmV2ZXJzZSgpO1xuICAgIH0gZWxzZSB7XG4gICAgICBjbGlwcyA9IFtdO1xuICAgICAgY2xpcFpzID0gW107XG4gICAgfVxuXG4gICAgZm9yICh2YXIgaSA9IHpzLmxlbmd0aCAtIDE7IGkgPj0gMDsgLS1pKSB7XG4gICAgICB2YXIgY3VycmVudFogPSB6c1tpXTtcbiAgICAgIHZhciBjdXJyZW50VGlsZVBpeGVsU2l6ZSA9IHRpbGVTb3VyY2UuZ2V0VGlsZVBpeGVsU2l6ZShjdXJyZW50WiwgcGl4ZWxSYXRpbywgcHJvamVjdGlvbik7XG4gICAgICB2YXIgY3VycmVudFJlc29sdXRpb24gPSB0aWxlR3JpZC5nZXRSZXNvbHV0aW9uKGN1cnJlbnRaKTtcbiAgICAgIHZhciBjdXJyZW50U2NhbGUgPSBjdXJyZW50UmVzb2x1dGlvbiAvIHRpbGVSZXNvbHV0aW9uO1xuICAgICAgdmFyIGR4XzEgPSBjdXJyZW50VGlsZVBpeGVsU2l6ZVswXSAqIGN1cnJlbnRTY2FsZSAqIGNhbnZhc1NjYWxlO1xuICAgICAgdmFyIGR5XzEgPSBjdXJyZW50VGlsZVBpeGVsU2l6ZVsxXSAqIGN1cnJlbnRTY2FsZSAqIGNhbnZhc1NjYWxlO1xuICAgICAgdmFyIG9yaWdpblRpbGVDb29yZCA9IHRpbGVHcmlkLmdldFRpbGVDb29yZEZvckNvb3JkQW5kWihnZXRUb3BMZWZ0KGNhbnZhc0V4dGVudCksIGN1cnJlbnRaKTtcbiAgICAgIHZhciBvcmlnaW5UaWxlRXh0ZW50ID0gdGlsZUdyaWQuZ2V0VGlsZUNvb3JkRXh0ZW50KG9yaWdpblRpbGVDb29yZCk7XG4gICAgICB2YXIgb3JpZ2luXzEgPSBhcHBseVRyYW5zZm9ybSh0aGlzLnRlbXBUcmFuc2Zvcm0sIFt0aWxlUGl4ZWxSYXRpbyAqIChvcmlnaW5UaWxlRXh0ZW50WzBdIC0gY2FudmFzRXh0ZW50WzBdKSAvIHRpbGVSZXNvbHV0aW9uLCB0aWxlUGl4ZWxSYXRpbyAqIChjYW52YXNFeHRlbnRbM10gLSBvcmlnaW5UaWxlRXh0ZW50WzNdKSAvIHRpbGVSZXNvbHV0aW9uXSk7XG4gICAgICB2YXIgdGlsZUd1dHRlciA9IHRpbGVQaXhlbFJhdGlvICogdGlsZVNvdXJjZS5nZXRHdXR0ZXJGb3JQcm9qZWN0aW9uKHByb2plY3Rpb24pO1xuICAgICAgdmFyIHRpbGVzVG9EcmF3ID0gdGlsZXNUb0RyYXdCeVpbY3VycmVudFpdO1xuXG4gICAgICBmb3IgKHZhciB0aWxlQ29vcmRLZXkgaW4gdGlsZXNUb0RyYXcpIHtcbiAgICAgICAgdmFyIHRpbGUgPVxuICAgICAgICAvKiogQHR5cGUge2ltcG9ydChcIi4uLy4uL0ltYWdlVGlsZS5qc1wiKS5kZWZhdWx0fSAqL1xuICAgICAgICB0aWxlc1RvRHJhd1t0aWxlQ29vcmRLZXldO1xuICAgICAgICB2YXIgdGlsZUNvb3JkID0gdGlsZS50aWxlQ29vcmQ7IC8vIENhbGN1bGF0ZSBpbnRlZ2VyIHBvc2l0aW9ucyBhbmQgc2l6ZXMgc28gdGhhdCB0aWxlcyBhbGlnblxuXG4gICAgICAgIHZhciBmbG9hdFggPSBvcmlnaW5fMVswXSAtIChvcmlnaW5UaWxlQ29vcmRbMV0gLSB0aWxlQ29vcmRbMV0pICogZHhfMTtcbiAgICAgICAgdmFyIG5leHRYID0gTWF0aC5yb3VuZChmbG9hdFggKyBkeF8xKTtcbiAgICAgICAgdmFyIGZsb2F0WSA9IG9yaWdpbl8xWzFdIC0gKG9yaWdpblRpbGVDb29yZFsyXSAtIHRpbGVDb29yZFsyXSkgKiBkeV8xO1xuICAgICAgICB2YXIgbmV4dFkgPSBNYXRoLnJvdW5kKGZsb2F0WSArIGR5XzEpO1xuICAgICAgICB2YXIgeCA9IE1hdGgucm91bmQoZmxvYXRYKTtcbiAgICAgICAgdmFyIHkgPSBNYXRoLnJvdW5kKGZsb2F0WSk7XG4gICAgICAgIHZhciB3ID0gbmV4dFggLSB4O1xuICAgICAgICB2YXIgaCA9IG5leHRZIC0geTtcbiAgICAgICAgdmFyIHRyYW5zaXRpb24gPSB6ID09PSBjdXJyZW50WjtcbiAgICAgICAgdmFyIGluVHJhbnNpdGlvbiA9IHRyYW5zaXRpb24gJiYgdGlsZS5nZXRBbHBoYShnZXRVaWQodGhpcyksIGZyYW1lU3RhdGUudGltZSkgIT09IDE7XG5cbiAgICAgICAgaWYgKCFpblRyYW5zaXRpb24pIHtcbiAgICAgICAgICBpZiAoY2xpcHMpIHtcbiAgICAgICAgICAgIC8vIENsaXAgbWFzayBmb3IgcmVnaW9ucyBpbiB0aGlzIHRpbGUgdGhhdCBhbHJlYWR5IGZpbGxlZCBieSBhIGhpZ2hlciB6IHRpbGVcbiAgICAgICAgICAgIGNvbnRleHQuc2F2ZSgpO1xuICAgICAgICAgICAgY3VycmVudENsaXAgPSBbeCwgeSwgeCArIHcsIHksIHggKyB3LCB5ICsgaCwgeCwgeSArIGhdO1xuXG4gICAgICAgICAgICBmb3IgKHZhciBpXzEgPSAwLCBpaSA9IGNsaXBzLmxlbmd0aDsgaV8xIDwgaWk7ICsraV8xKSB7XG4gICAgICAgICAgICAgIGlmICh6ICE9PSBjdXJyZW50WiAmJiBjdXJyZW50WiA8IGNsaXBac1tpXzFdKSB7XG4gICAgICAgICAgICAgICAgdmFyIGNsaXAgPSBjbGlwc1tpXzFdO1xuICAgICAgICAgICAgICAgIGNvbnRleHQuYmVnaW5QYXRoKCk7IC8vIGNvdW50ZXItY2xvY2t3aXNlIChvdXRlciByaW5nKSBmb3IgY3VycmVudCB0aWxlXG5cbiAgICAgICAgICAgICAgICBjb250ZXh0Lm1vdmVUbyhjdXJyZW50Q2xpcFswXSwgY3VycmVudENsaXBbMV0pO1xuICAgICAgICAgICAgICAgIGNvbnRleHQubGluZVRvKGN1cnJlbnRDbGlwWzJdLCBjdXJyZW50Q2xpcFszXSk7XG4gICAgICAgICAgICAgICAgY29udGV4dC5saW5lVG8oY3VycmVudENsaXBbNF0sIGN1cnJlbnRDbGlwWzVdKTtcbiAgICAgICAgICAgICAgICBjb250ZXh0LmxpbmVUbyhjdXJyZW50Q2xpcFs2XSwgY3VycmVudENsaXBbN10pOyAvLyBjbG9ja3dpc2UgKGlubmVyIHJpbmcpIGZvciBoaWdoZXIgeiB0aWxlXG5cbiAgICAgICAgICAgICAgICBjb250ZXh0Lm1vdmVUbyhjbGlwWzZdLCBjbGlwWzddKTtcbiAgICAgICAgICAgICAgICBjb250ZXh0LmxpbmVUbyhjbGlwWzRdLCBjbGlwWzVdKTtcbiAgICAgICAgICAgICAgICBjb250ZXh0LmxpbmVUbyhjbGlwWzJdLCBjbGlwWzNdKTtcbiAgICAgICAgICAgICAgICBjb250ZXh0LmxpbmVUbyhjbGlwWzBdLCBjbGlwWzFdKTtcbiAgICAgICAgICAgICAgICBjb250ZXh0LmNsaXAoKTtcbiAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICBjbGlwcy5wdXNoKGN1cnJlbnRDbGlwKTtcbiAgICAgICAgICAgIGNsaXBacy5wdXNoKGN1cnJlbnRaKTtcbiAgICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgY29udGV4dC5jbGVhclJlY3QoeCwgeSwgdywgaCk7XG4gICAgICAgICAgfVxuICAgICAgICB9XG5cbiAgICAgICAgdGhpcy5kcmF3VGlsZUltYWdlKHRpbGUsIGZyYW1lU3RhdGUsIHgsIHksIHcsIGgsIHRpbGVHdXR0ZXIsIHRyYW5zaXRpb24sIGxheWVyU3RhdGUub3BhY2l0eSk7XG5cbiAgICAgICAgaWYgKGNsaXBzICYmICFpblRyYW5zaXRpb24pIHtcbiAgICAgICAgICBjb250ZXh0LnJlc3RvcmUoKTtcbiAgICAgICAgfVxuXG4gICAgICAgIHRoaXMucmVuZGVyZWRUaWxlcy5wdXNoKHRpbGUpO1xuICAgICAgICB0aGlzLnVwZGF0ZVVzZWRUaWxlcyhmcmFtZVN0YXRlLnVzZWRUaWxlcywgdGlsZVNvdXJjZSwgdGlsZSk7XG4gICAgICB9XG4gICAgfVxuXG4gICAgdGhpcy5yZW5kZXJlZFJldmlzaW9uID0gc291cmNlUmV2aXNpb247XG4gICAgdGhpcy5yZW5kZXJlZFJlc29sdXRpb24gPSB0aWxlUmVzb2x1dGlvbjtcbiAgICB0aGlzLmV4dGVudENoYW5nZWQgPSAhdGhpcy5yZW5kZXJlZEV4dGVudF8gfHwgIWVxdWFscyh0aGlzLnJlbmRlcmVkRXh0ZW50XywgY2FudmFzRXh0ZW50KTtcbiAgICB0aGlzLnJlbmRlcmVkRXh0ZW50XyA9IGNhbnZhc0V4dGVudDtcbiAgICB0aGlzLnJlbmRlcmVkUGl4ZWxSYXRpbyA9IHBpeGVsUmF0aW87XG4gICAgdGhpcy5yZW5kZXJlZFByb2plY3Rpb24gPSBwcm9qZWN0aW9uO1xuICAgIHRoaXMubWFuYWdlVGlsZVB5cmFtaWQoZnJhbWVTdGF0ZSwgdGlsZVNvdXJjZSwgdGlsZUdyaWQsIHBpeGVsUmF0aW8sIHByb2plY3Rpb24sIGV4dGVudCwgeiwgdGlsZUxheWVyLmdldFByZWxvYWQoKSk7XG4gICAgdGhpcy5zY2hlZHVsZUV4cGlyZUNhY2hlKGZyYW1lU3RhdGUsIHRpbGVTb3VyY2UpO1xuICAgIHRoaXMucG9zdFJlbmRlcihjb250ZXh0LCBmcmFtZVN0YXRlKTtcblxuICAgIGlmIChsYXllclN0YXRlLmV4dGVudCkge1xuICAgICAgY29udGV4dC5yZXN0b3JlKCk7XG4gICAgfVxuXG4gICAgaWYgKGNhbnZhc1RyYW5zZm9ybSAhPT0gY2FudmFzLnN0eWxlLnRyYW5zZm9ybSkge1xuICAgICAgY2FudmFzLnN0eWxlLnRyYW5zZm9ybSA9IGNhbnZhc1RyYW5zZm9ybTtcbiAgICB9XG5cbiAgICByZXR1cm4gdGhpcy5jb250YWluZXI7XG4gIH07XG4gIC8qKlxuICAgKiBAcGFyYW0ge2ltcG9ydChcIi4uLy4uL0ltYWdlVGlsZS5qc1wiKS5kZWZhdWx0fSB0aWxlIFRpbGUuXG4gICAqIEBwYXJhbSB7aW1wb3J0KFwiLi4vLi4vUGx1Z2dhYmxlTWFwLmpzXCIpLkZyYW1lU3RhdGV9IGZyYW1lU3RhdGUgRnJhbWUgc3RhdGUuXG4gICAqIEBwYXJhbSB7bnVtYmVyfSB4IExlZnQgb2YgdGhlIHRpbGUuXG4gICAqIEBwYXJhbSB7bnVtYmVyfSB5IFRvcCBvZiB0aGUgdGlsZS5cbiAgICogQHBhcmFtIHtudW1iZXJ9IHcgV2lkdGggb2YgdGhlIHRpbGUuXG4gICAqIEBwYXJhbSB7bnVtYmVyfSBoIEhlaWdodCBvZiB0aGUgdGlsZS5cbiAgICogQHBhcmFtIHtudW1iZXJ9IGd1dHRlciBUaWxlIGd1dHRlci5cbiAgICogQHBhcmFtIHtib29sZWFufSB0cmFuc2l0aW9uIEFwcGx5IGFuIGFscGhhIHRyYW5zaXRpb24uXG4gICAqIEBwYXJhbSB7bnVtYmVyfSBvcGFjaXR5IE9wYWNpdHkuXG4gICAqL1xuXG5cbiAgQ2FudmFzVGlsZUxheWVyUmVuZGVyZXIucHJvdG90eXBlLmRyYXdUaWxlSW1hZ2UgPSBmdW5jdGlvbiAodGlsZSwgZnJhbWVTdGF0ZSwgeCwgeSwgdywgaCwgZ3V0dGVyLCB0cmFuc2l0aW9uLCBvcGFjaXR5KSB7XG4gICAgdmFyIGltYWdlID0gdGhpcy5nZXRUaWxlSW1hZ2UodGlsZSk7XG5cbiAgICBpZiAoIWltYWdlKSB7XG4gICAgICByZXR1cm47XG4gICAgfVxuXG4gICAgdmFyIHVpZCA9IGdldFVpZCh0aGlzKTtcbiAgICB2YXIgdGlsZUFscGhhID0gdHJhbnNpdGlvbiA/IHRpbGUuZ2V0QWxwaGEodWlkLCBmcmFtZVN0YXRlLnRpbWUpIDogMTtcbiAgICB2YXIgYWxwaGEgPSBvcGFjaXR5ICogdGlsZUFscGhhO1xuICAgIHZhciBhbHBoYUNoYW5nZWQgPSBhbHBoYSAhPT0gdGhpcy5jb250ZXh0Lmdsb2JhbEFscGhhO1xuXG4gICAgaWYgKGFscGhhQ2hhbmdlZCkge1xuICAgICAgdGhpcy5jb250ZXh0LnNhdmUoKTtcbiAgICAgIHRoaXMuY29udGV4dC5nbG9iYWxBbHBoYSA9IGFscGhhO1xuICAgIH1cblxuICAgIHRoaXMuY29udGV4dC5kcmF3SW1hZ2UoaW1hZ2UsIGd1dHRlciwgZ3V0dGVyLCBpbWFnZS53aWR0aCAtIDIgKiBndXR0ZXIsIGltYWdlLmhlaWdodCAtIDIgKiBndXR0ZXIsIHgsIHksIHcsIGgpO1xuXG4gICAgaWYgKGFscGhhQ2hhbmdlZCkge1xuICAgICAgdGhpcy5jb250ZXh0LnJlc3RvcmUoKTtcbiAgICB9XG5cbiAgICBpZiAodGlsZUFscGhhICE9PSAxKSB7XG4gICAgICBmcmFtZVN0YXRlLmFuaW1hdGUgPSB0cnVlO1xuICAgIH0gZWxzZSBpZiAodHJhbnNpdGlvbikge1xuICAgICAgdGlsZS5lbmRUcmFuc2l0aW9uKHVpZCk7XG4gICAgfVxuICB9O1xuICAvKipcbiAgICogQHJldHVybiB7SFRNTENhbnZhc0VsZW1lbnR9IEltYWdlXG4gICAqL1xuXG5cbiAgQ2FudmFzVGlsZUxheWVyUmVuZGVyZXIucHJvdG90eXBlLmdldEltYWdlID0gZnVuY3Rpb24gKCkge1xuICAgIHZhciBjb250ZXh0ID0gdGhpcy5jb250ZXh0O1xuICAgIHJldHVybiBjb250ZXh0ID8gY29udGV4dC5jYW52YXMgOiBudWxsO1xuICB9O1xuICAvKipcbiAgICogR2V0IHRoZSBpbWFnZSBmcm9tIGEgdGlsZS5cbiAgICogQHBhcmFtIHtpbXBvcnQoXCIuLi8uLi9JbWFnZVRpbGUuanNcIikuZGVmYXVsdH0gdGlsZSBUaWxlLlxuICAgKiBAcmV0dXJuIHtIVE1MQ2FudmFzRWxlbWVudHxIVE1MSW1hZ2VFbGVtZW50fEhUTUxWaWRlb0VsZW1lbnR9IEltYWdlLlxuICAgKiBAcHJvdGVjdGVkXG4gICAqL1xuXG5cbiAgQ2FudmFzVGlsZUxheWVyUmVuZGVyZXIucHJvdG90eXBlLmdldFRpbGVJbWFnZSA9IGZ1bmN0aW9uICh0aWxlKSB7XG4gICAgcmV0dXJuIHRpbGUuZ2V0SW1hZ2UoKTtcbiAgfTtcbiAgLyoqXG4gICAqIEBwYXJhbSB7aW1wb3J0KFwiLi4vLi4vUGx1Z2dhYmxlTWFwLmpzXCIpLkZyYW1lU3RhdGV9IGZyYW1lU3RhdGUgRnJhbWUgc3RhdGUuXG4gICAqIEBwYXJhbSB7aW1wb3J0KFwiLi4vLi4vc291cmNlL1RpbGUuanNcIikuZGVmYXVsdH0gdGlsZVNvdXJjZSBUaWxlIHNvdXJjZS5cbiAgICogQHByb3RlY3RlZFxuICAgKi9cblxuXG4gIENhbnZhc1RpbGVMYXllclJlbmRlcmVyLnByb3RvdHlwZS5zY2hlZHVsZUV4cGlyZUNhY2hlID0gZnVuY3Rpb24gKGZyYW1lU3RhdGUsIHRpbGVTb3VyY2UpIHtcbiAgICBpZiAodGlsZVNvdXJjZS5jYW5FeHBpcmVDYWNoZSgpKSB7XG4gICAgICAvKipcbiAgICAgICAqIEBwYXJhbSB7aW1wb3J0KFwiLi4vLi4vc291cmNlL1RpbGUuanNcIikuZGVmYXVsdH0gdGlsZVNvdXJjZSBUaWxlIHNvdXJjZS5cbiAgICAgICAqIEBwYXJhbSB7aW1wb3J0KFwiLi4vLi4vUGx1Z2dhYmxlTWFwLmpzXCIpLmRlZmF1bHR9IG1hcCBNYXAuXG4gICAgICAgKiBAcGFyYW0ge2ltcG9ydChcIi4uLy4uL1BsdWdnYWJsZU1hcC5qc1wiKS5GcmFtZVN0YXRlfSBmcmFtZVN0YXRlIEZyYW1lIHN0YXRlLlxuICAgICAgICovXG4gICAgICB2YXIgcG9zdFJlbmRlckZ1bmN0aW9uID0gZnVuY3Rpb24gKHRpbGVTb3VyY2UsIG1hcCwgZnJhbWVTdGF0ZSkge1xuICAgICAgICB2YXIgdGlsZVNvdXJjZUtleSA9IGdldFVpZCh0aWxlU291cmNlKTtcblxuICAgICAgICBpZiAodGlsZVNvdXJjZUtleSBpbiBmcmFtZVN0YXRlLnVzZWRUaWxlcykge1xuICAgICAgICAgIHRpbGVTb3VyY2UuZXhwaXJlQ2FjaGUoZnJhbWVTdGF0ZS52aWV3U3RhdGUucHJvamVjdGlvbiwgZnJhbWVTdGF0ZS51c2VkVGlsZXNbdGlsZVNvdXJjZUtleV0pO1xuICAgICAgICB9XG4gICAgICB9LmJpbmQobnVsbCwgdGlsZVNvdXJjZSk7XG5cbiAgICAgIGZyYW1lU3RhdGUucG9zdFJlbmRlckZ1bmN0aW9ucy5wdXNoKFxuICAgICAgLyoqIEB0eXBlIHtpbXBvcnQoXCIuLi8uLi9QbHVnZ2FibGVNYXAuanNcIikuUG9zdFJlbmRlckZ1bmN0aW9ufSAqL1xuICAgICAgcG9zdFJlbmRlckZ1bmN0aW9uKTtcbiAgICB9XG4gIH07XG4gIC8qKlxuICAgKiBAcGFyYW0geyFPYmplY3Q8c3RyaW5nLCAhT2JqZWN0PHN0cmluZywgYm9vbGVhbj4+fSB1c2VkVGlsZXMgVXNlZCB0aWxlcy5cbiAgICogQHBhcmFtIHtpbXBvcnQoXCIuLi8uLi9zb3VyY2UvVGlsZS5qc1wiKS5kZWZhdWx0fSB0aWxlU291cmNlIFRpbGUgc291cmNlLlxuICAgKiBAcGFyYW0ge2ltcG9ydCgnLi4vLi4vVGlsZS5qcycpLmRlZmF1bHR9IHRpbGUgVGlsZS5cbiAgICogQHByb3RlY3RlZFxuICAgKi9cblxuXG4gIENhbnZhc1RpbGVMYXllclJlbmRlcmVyLnByb3RvdHlwZS51cGRhdGVVc2VkVGlsZXMgPSBmdW5jdGlvbiAodXNlZFRpbGVzLCB0aWxlU291cmNlLCB0aWxlKSB7XG4gICAgLy8gRklYTUUgc2hvdWxkIHdlIHVzZSB0aWxlc1RvRHJhd0J5WiBpbnN0ZWFkP1xuICAgIHZhciB0aWxlU291cmNlS2V5ID0gZ2V0VWlkKHRpbGVTb3VyY2UpO1xuXG4gICAgaWYgKCEodGlsZVNvdXJjZUtleSBpbiB1c2VkVGlsZXMpKSB7XG4gICAgICB1c2VkVGlsZXNbdGlsZVNvdXJjZUtleV0gPSB7fTtcbiAgICB9XG5cbiAgICB1c2VkVGlsZXNbdGlsZVNvdXJjZUtleV1bdGlsZS5nZXRLZXkoKV0gPSB0cnVlO1xuICB9O1xuICAvKipcbiAgICogTWFuYWdlIHRpbGUgcHlyYW1pZC5cbiAgICogVGhpcyBmdW5jdGlvbiBwZXJmb3JtcyBhIG51bWJlciBvZiBmdW5jdGlvbnMgcmVsYXRlZCB0byB0aGUgdGlsZXMgYXQgdGhlXG4gICAqIGN1cnJlbnQgem9vbSBhbmQgbG93ZXIgem9vbSBsZXZlbHM6XG4gICAqIC0gcmVnaXN0ZXJzIGlkbGUgdGlsZXMgaW4gZnJhbWVTdGF0ZS53YW50ZWRUaWxlcyBzbyB0aGF0IHRoZXkgYXJlIG5vdFxuICAgKiAgIGRpc2NhcmRlZCBieSB0aGUgdGlsZSBxdWV1ZVxuICAgKiAtIGVucXVldWVzIG1pc3NpbmcgdGlsZXNcbiAgICogQHBhcmFtIHtpbXBvcnQoXCIuLi8uLi9QbHVnZ2FibGVNYXAuanNcIikuRnJhbWVTdGF0ZX0gZnJhbWVTdGF0ZSBGcmFtZSBzdGF0ZS5cbiAgICogQHBhcmFtIHtpbXBvcnQoXCIuLi8uLi9zb3VyY2UvVGlsZS5qc1wiKS5kZWZhdWx0fSB0aWxlU291cmNlIFRpbGUgc291cmNlLlxuICAgKiBAcGFyYW0ge2ltcG9ydChcIi4uLy4uL3RpbGVncmlkL1RpbGVHcmlkLmpzXCIpLmRlZmF1bHR9IHRpbGVHcmlkIFRpbGUgZ3JpZC5cbiAgICogQHBhcmFtIHtudW1iZXJ9IHBpeGVsUmF0aW8gUGl4ZWwgcmF0aW8uXG4gICAqIEBwYXJhbSB7aW1wb3J0KFwiLi4vLi4vcHJvai9Qcm9qZWN0aW9uLmpzXCIpLmRlZmF1bHR9IHByb2plY3Rpb24gUHJvamVjdGlvbi5cbiAgICogQHBhcmFtIHtpbXBvcnQoXCIuLi8uLi9leHRlbnQuanNcIikuRXh0ZW50fSBleHRlbnQgRXh0ZW50LlxuICAgKiBAcGFyYW0ge251bWJlcn0gY3VycmVudFogQ3VycmVudCBaLlxuICAgKiBAcGFyYW0ge251bWJlcn0gcHJlbG9hZCBMb2FkIGxvdyByZXNvbHV0aW9uIHRpbGVzIHVwIHRvICdwcmVsb2FkJyBsZXZlbHMuXG4gICAqIEBwYXJhbSB7ZnVuY3Rpb24oaW1wb3J0KFwiLi4vLi4vVGlsZS5qc1wiKS5kZWZhdWx0KT19IG9wdF90aWxlQ2FsbGJhY2sgVGlsZSBjYWxsYmFjay5cbiAgICogQHByb3RlY3RlZFxuICAgKi9cblxuXG4gIENhbnZhc1RpbGVMYXllclJlbmRlcmVyLnByb3RvdHlwZS5tYW5hZ2VUaWxlUHlyYW1pZCA9IGZ1bmN0aW9uIChmcmFtZVN0YXRlLCB0aWxlU291cmNlLCB0aWxlR3JpZCwgcGl4ZWxSYXRpbywgcHJvamVjdGlvbiwgZXh0ZW50LCBjdXJyZW50WiwgcHJlbG9hZCwgb3B0X3RpbGVDYWxsYmFjaykge1xuICAgIHZhciB0aWxlU291cmNlS2V5ID0gZ2V0VWlkKHRpbGVTb3VyY2UpO1xuXG4gICAgaWYgKCEodGlsZVNvdXJjZUtleSBpbiBmcmFtZVN0YXRlLndhbnRlZFRpbGVzKSkge1xuICAgICAgZnJhbWVTdGF0ZS53YW50ZWRUaWxlc1t0aWxlU291cmNlS2V5XSA9IHt9O1xuICAgIH1cblxuICAgIHZhciB3YW50ZWRUaWxlcyA9IGZyYW1lU3RhdGUud2FudGVkVGlsZXNbdGlsZVNvdXJjZUtleV07XG4gICAgdmFyIHRpbGVRdWV1ZSA9IGZyYW1lU3RhdGUudGlsZVF1ZXVlO1xuICAgIHZhciBtaW5ab29tID0gdGlsZUdyaWQuZ2V0TWluWm9vbSgpO1xuICAgIHZhciB0aWxlQ291bnQgPSAwO1xuICAgIHZhciB0aWxlLCB0aWxlUmFuZ2UsIHRpbGVSZXNvbHV0aW9uLCB4LCB5LCB6O1xuXG4gICAgZm9yICh6ID0gbWluWm9vbTsgeiA8PSBjdXJyZW50WjsgKyt6KSB7XG4gICAgICB0aWxlUmFuZ2UgPSB0aWxlR3JpZC5nZXRUaWxlUmFuZ2VGb3JFeHRlbnRBbmRaKGV4dGVudCwgeiwgdGlsZVJhbmdlKTtcbiAgICAgIHRpbGVSZXNvbHV0aW9uID0gdGlsZUdyaWQuZ2V0UmVzb2x1dGlvbih6KTtcblxuICAgICAgZm9yICh4ID0gdGlsZVJhbmdlLm1pblg7IHggPD0gdGlsZVJhbmdlLm1heFg7ICsreCkge1xuICAgICAgICBmb3IgKHkgPSB0aWxlUmFuZ2UubWluWTsgeSA8PSB0aWxlUmFuZ2UubWF4WTsgKyt5KSB7XG4gICAgICAgICAgaWYgKGN1cnJlbnRaIC0geiA8PSBwcmVsb2FkKSB7XG4gICAgICAgICAgICArK3RpbGVDb3VudDtcbiAgICAgICAgICAgIHRpbGUgPSB0aWxlU291cmNlLmdldFRpbGUoeiwgeCwgeSwgcGl4ZWxSYXRpbywgcHJvamVjdGlvbik7XG5cbiAgICAgICAgICAgIGlmICh0aWxlLmdldFN0YXRlKCkgPT0gVGlsZVN0YXRlLklETEUpIHtcbiAgICAgICAgICAgICAgd2FudGVkVGlsZXNbdGlsZS5nZXRLZXkoKV0gPSB0cnVlO1xuXG4gICAgICAgICAgICAgIGlmICghdGlsZVF1ZXVlLmlzS2V5UXVldWVkKHRpbGUuZ2V0S2V5KCkpKSB7XG4gICAgICAgICAgICAgICAgdGlsZVF1ZXVlLmVucXVldWUoW3RpbGUsIHRpbGVTb3VyY2VLZXksIHRpbGVHcmlkLmdldFRpbGVDb29yZENlbnRlcih0aWxlLnRpbGVDb29yZCksIHRpbGVSZXNvbHV0aW9uXSk7XG4gICAgICAgICAgICAgIH1cbiAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgaWYgKG9wdF90aWxlQ2FsbGJhY2sgIT09IHVuZGVmaW5lZCkge1xuICAgICAgICAgICAgICBvcHRfdGlsZUNhbGxiYWNrKHRpbGUpO1xuICAgICAgICAgICAgfVxuICAgICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICB0aWxlU291cmNlLnVzZVRpbGUoeiwgeCwgeSwgcHJvamVjdGlvbik7XG4gICAgICAgICAgfVxuICAgICAgICB9XG4gICAgICB9XG4gICAgfVxuXG4gICAgdGlsZVNvdXJjZS51cGRhdGVDYWNoZVNpemUodGlsZUNvdW50LCBwcm9qZWN0aW9uKTtcbiAgfTtcblxuICByZXR1cm4gQ2FudmFzVGlsZUxheWVyUmVuZGVyZXI7XG59KENhbnZhc0xheWVyUmVuZGVyZXIpO1xuLyoqXG4gKiBAZnVuY3Rpb25cbiAqIEByZXR1cm4ge2ltcG9ydChcIi4uLy4uL2xheWVyL1RpbGUuanNcIikuZGVmYXVsdHxpbXBvcnQoXCIuLi8uLi9sYXllci9WZWN0b3JUaWxlLmpzXCIpLmRlZmF1bHR9XG4gKi9cblxuXG5DYW52YXNUaWxlTGF5ZXJSZW5kZXJlci5wcm90b3R5cGUuZ2V0TGF5ZXI7XG5leHBvcnQgZGVmYXVsdCBDYW52YXNUaWxlTGF5ZXJSZW5kZXJlcjsiLCJ2YXIgX19leHRlbmRzID0gdGhpcyAmJiB0aGlzLl9fZXh0ZW5kcyB8fCBmdW5jdGlvbiAoKSB7XG4gIHZhciBfZXh0ZW5kU3RhdGljcyA9IGZ1bmN0aW9uIGV4dGVuZFN0YXRpY3MoZCwgYikge1xuICAgIF9leHRlbmRTdGF0aWNzID0gT2JqZWN0LnNldFByb3RvdHlwZU9mIHx8IHtcbiAgICAgIF9fcHJvdG9fXzogW11cbiAgICB9IGluc3RhbmNlb2YgQXJyYXkgJiYgZnVuY3Rpb24gKGQsIGIpIHtcbiAgICAgIGQuX19wcm90b19fID0gYjtcbiAgICB9IHx8IGZ1bmN0aW9uIChkLCBiKSB7XG4gICAgICBmb3IgKHZhciBwIGluIGIpIHtcbiAgICAgICAgaWYgKE9iamVjdC5wcm90b3R5cGUuaGFzT3duUHJvcGVydHkuY2FsbChiLCBwKSkgZFtwXSA9IGJbcF07XG4gICAgICB9XG4gICAgfTtcblxuICAgIHJldHVybiBfZXh0ZW5kU3RhdGljcyhkLCBiKTtcbiAgfTtcblxuICByZXR1cm4gZnVuY3Rpb24gKGQsIGIpIHtcbiAgICBfZXh0ZW5kU3RhdGljcyhkLCBiKTtcblxuICAgIGZ1bmN0aW9uIF9fKCkge1xuICAgICAgdGhpcy5jb25zdHJ1Y3RvciA9IGQ7XG4gICAgfVxuXG4gICAgZC5wcm90b3R5cGUgPSBiID09PSBudWxsID8gT2JqZWN0LmNyZWF0ZShiKSA6IChfXy5wcm90b3R5cGUgPSBiLnByb3RvdHlwZSwgbmV3IF9fKCkpO1xuICB9O1xufSgpO1xuLyoqXG4gKiBAbW9kdWxlIG9sL2xheWVyL1RpbGVcbiAqL1xuXG5cbmltcG9ydCBCYXNlVGlsZUxheWVyIGZyb20gJy4vQmFzZVRpbGUuanMnO1xuaW1wb3J0IENhbnZhc1RpbGVMYXllclJlbmRlcmVyIGZyb20gJy4uL3JlbmRlcmVyL2NhbnZhcy9UaWxlTGF5ZXIuanMnO1xuLyoqXG4gKiBAY2xhc3NkZXNjXG4gKiBGb3IgbGF5ZXIgc291cmNlcyB0aGF0IHByb3ZpZGUgcHJlLXJlbmRlcmVkLCB0aWxlZCBpbWFnZXMgaW4gZ3JpZHMgdGhhdCBhcmVcbiAqIG9yZ2FuaXplZCBieSB6b29tIGxldmVscyBmb3Igc3BlY2lmaWMgcmVzb2x1dGlvbnMuXG4gKiBOb3RlIHRoYXQgYW55IHByb3BlcnR5IHNldCBpbiB0aGUgb3B0aW9ucyBpcyBzZXQgYXMgYSB7QGxpbmsgbW9kdWxlOm9sL09iamVjdH5CYXNlT2JqZWN0fVxuICogcHJvcGVydHkgb24gdGhlIGxheWVyIG9iamVjdDsgZm9yIGV4YW1wbGUsIHNldHRpbmcgYHRpdGxlOiAnTXkgVGl0bGUnYCBpbiB0aGVcbiAqIG9wdGlvbnMgbWVhbnMgdGhhdCBgdGl0bGVgIGlzIG9ic2VydmFibGUsIGFuZCBoYXMgZ2V0L3NldCBhY2Nlc3NvcnMuXG4gKlxuICogQGFwaVxuICovXG5cbnZhciBUaWxlTGF5ZXIgPVxuLyoqIEBjbGFzcyAqL1xuZnVuY3Rpb24gKF9zdXBlcikge1xuICBfX2V4dGVuZHMoVGlsZUxheWVyLCBfc3VwZXIpO1xuICAvKipcbiAgICogQHBhcmFtIHtpbXBvcnQoXCIuL0Jhc2VUaWxlLmpzXCIpLk9wdGlvbnM9fSBvcHRfb3B0aW9ucyBUaWxlIGxheWVyIG9wdGlvbnMuXG4gICAqL1xuXG5cbiAgZnVuY3Rpb24gVGlsZUxheWVyKG9wdF9vcHRpb25zKSB7XG4gICAgcmV0dXJuIF9zdXBlci5jYWxsKHRoaXMsIG9wdF9vcHRpb25zKSB8fCB0aGlzO1xuICB9XG4gIC8qKlxuICAgKiBDcmVhdGUgYSByZW5kZXJlciBmb3IgdGhpcyBsYXllci5cbiAgICogQHJldHVybiB7aW1wb3J0KFwiLi4vcmVuZGVyZXIvTGF5ZXIuanNcIikuZGVmYXVsdH0gQSBsYXllciByZW5kZXJlci5cbiAgICogQHByb3RlY3RlZFxuICAgKi9cblxuXG4gIFRpbGVMYXllci5wcm90b3R5cGUuY3JlYXRlUmVuZGVyZXIgPSBmdW5jdGlvbiAoKSB7XG4gICAgcmV0dXJuIG5ldyBDYW52YXNUaWxlTGF5ZXJSZW5kZXJlcih0aGlzKTtcbiAgfTtcblxuICByZXR1cm4gVGlsZUxheWVyO1xufShCYXNlVGlsZUxheWVyKTtcblxuZXhwb3J0IGRlZmF1bHQgVGlsZUxheWVyOyIsInZhciBfX2V4dGVuZHMgPSB0aGlzICYmIHRoaXMuX19leHRlbmRzIHx8IGZ1bmN0aW9uICgpIHtcbiAgdmFyIF9leHRlbmRTdGF0aWNzID0gZnVuY3Rpb24gZXh0ZW5kU3RhdGljcyhkLCBiKSB7XG4gICAgX2V4dGVuZFN0YXRpY3MgPSBPYmplY3Quc2V0UHJvdG90eXBlT2YgfHwge1xuICAgICAgX19wcm90b19fOiBbXVxuICAgIH0gaW5zdGFuY2VvZiBBcnJheSAmJiBmdW5jdGlvbiAoZCwgYikge1xuICAgICAgZC5fX3Byb3RvX18gPSBiO1xuICAgIH0gfHwgZnVuY3Rpb24gKGQsIGIpIHtcbiAgICAgIGZvciAodmFyIHAgaW4gYikge1xuICAgICAgICBpZiAoT2JqZWN0LnByb3RvdHlwZS5oYXNPd25Qcm9wZXJ0eS5jYWxsKGIsIHApKSBkW3BdID0gYltwXTtcbiAgICAgIH1cbiAgICB9O1xuXG4gICAgcmV0dXJuIF9leHRlbmRTdGF0aWNzKGQsIGIpO1xuICB9O1xuXG4gIHJldHVybiBmdW5jdGlvbiAoZCwgYikge1xuICAgIF9leHRlbmRTdGF0aWNzKGQsIGIpO1xuXG4gICAgZnVuY3Rpb24gX18oKSB7XG4gICAgICB0aGlzLmNvbnN0cnVjdG9yID0gZDtcbiAgICB9XG5cbiAgICBkLnByb3RvdHlwZSA9IGIgPT09IG51bGwgPyBPYmplY3QuY3JlYXRlKGIpIDogKF9fLnByb3RvdHlwZSA9IGIucHJvdG90eXBlLCBuZXcgX18oKSk7XG4gIH07XG59KCk7XG4vKipcbiAqIEBtb2R1bGUgb2wvVGlsZVxuICovXG5cblxuaW1wb3J0IEV2ZW50VGFyZ2V0IGZyb20gJy4vZXZlbnRzL1RhcmdldC5qcyc7XG5pbXBvcnQgRXZlbnRUeXBlIGZyb20gJy4vZXZlbnRzL0V2ZW50VHlwZS5qcyc7XG5pbXBvcnQgVGlsZVN0YXRlIGZyb20gJy4vVGlsZVN0YXRlLmpzJztcbmltcG9ydCB7IGFic3RyYWN0IH0gZnJvbSAnLi91dGlsLmpzJztcbmltcG9ydCB7IGVhc2VJbiB9IGZyb20gJy4vZWFzaW5nLmpzJztcbi8qKlxuICogQSBmdW5jdGlvbiB0aGF0IHRha2VzIGFuIHtAbGluayBtb2R1bGU6b2wvVGlsZX0gZm9yIHRoZSB0aWxlIGFuZCBhXG4gKiBge3N0cmluZ31gIGZvciB0aGUgdXJsIGFzIGFyZ3VtZW50cy4gVGhlIGRlZmF1bHQgaXNcbiAqIGBgYGpzXG4gKiBzb3VyY2Uuc2V0VGlsZUxvYWRGdW5jdGlvbihmdW5jdGlvbih0aWxlLCBzcmMpIHtcbiAqICAgdGlsZS5nZXRJbWFnZSgpLnNyYyA9IHNyYztcbiAqIH0pO1xuICogYGBgXG4gKiBGb3IgbW9yZSBmaW5lIGdyYWluZWQgY29udHJvbCwgdGhlIGxvYWQgZnVuY3Rpb24gY2FuIHVzZSBmZXRjaCBvciBYTUxIdHRwUmVxdWVzdCBhbmQgaW52b2x2ZVxuICogZXJyb3IgaGFuZGxpbmc6XG4gKlxuICogYGBganNcbiAqIGltcG9ydCBUaWxlU3RhdGUgZnJvbSAnb2wvVGlsZVN0YXRlJztcbiAqXG4gKiBzb3VyY2Uuc2V0VGlsZUxvYWRGdW5jdGlvbihmdW5jdGlvbih0aWxlLCBzcmMpIHtcbiAqICAgdmFyIHhociA9IG5ldyBYTUxIdHRwUmVxdWVzdCgpO1xuICogICB4aHIucmVzcG9uc2VUeXBlID0gJ2Jsb2InO1xuICogICB4aHIuYWRkRXZlbnRMaXN0ZW5lcignbG9hZGVuZCcsIGZ1bmN0aW9uIChldnQpIHtcbiAqICAgICB2YXIgZGF0YSA9IHRoaXMucmVzcG9uc2U7XG4gKiAgICAgaWYgKGRhdGEgIT09IHVuZGVmaW5lZCkge1xuICogICAgICAgdGlsZS5nZXRJbWFnZSgpLnNyYyA9IFVSTC5jcmVhdGVPYmplY3RVUkwoZGF0YSk7XG4gKiAgICAgfSBlbHNlIHtcbiAqICAgICAgIHRpbGUuc2V0U3RhdGUoVGlsZVN0YXRlLkVSUk9SKTtcbiAqICAgICB9XG4gKiAgIH0pO1xuICogICB4aHIuYWRkRXZlbnRMaXN0ZW5lcignZXJyb3InLCBmdW5jdGlvbiAoKSB7XG4gKiAgICAgdGlsZS5zZXRTdGF0ZShUaWxlU3RhdGUuRVJST1IpO1xuICogICB9KTtcbiAqICAgeGhyLm9wZW4oJ0dFVCcsIHNyYyk7XG4gKiAgIHhoci5zZW5kKCk7XG4gKiB9KTtcbiAqIGBgYFxuICpcbiAqIEB0eXBlZGVmIHtmdW5jdGlvbihUaWxlLCBzdHJpbmcpOiB2b2lkfSBMb2FkRnVuY3Rpb25cbiAqIEBhcGlcbiAqL1xuXG4vKipcbiAqIHtAbGluayBtb2R1bGU6b2wvc291cmNlL1RpbGV+VGlsZX0gc291cmNlcyB1c2UgYSBmdW5jdGlvbiBvZiB0aGlzIHR5cGUgdG8gZ2V0XG4gKiB0aGUgdXJsIHRoYXQgcHJvdmlkZXMgYSB0aWxlIGZvciBhIGdpdmVuIHRpbGUgY29vcmRpbmF0ZS5cbiAqXG4gKiBUaGlzIGZ1bmN0aW9uIHRha2VzIGFuIHtAbGluayBtb2R1bGU6b2wvdGlsZWNvb3JkflRpbGVDb29yZH0gZm9yIHRoZSB0aWxlXG4gKiBjb29yZGluYXRlLCBhIGB7bnVtYmVyfWAgcmVwcmVzZW50aW5nIHRoZSBwaXhlbCByYXRpbyBhbmQgYVxuICoge0BsaW5rIG1vZHVsZTpvbC9wcm9qL1Byb2plY3Rpb259IGZvciB0aGUgcHJvamVjdGlvbiAgYXMgYXJndW1lbnRzXG4gKiBhbmQgcmV0dXJucyBhIGB7c3RyaW5nfWAgcmVwcmVzZW50aW5nIHRoZSB0aWxlIFVSTCwgb3IgdW5kZWZpbmVkIGlmIG5vIHRpbGVcbiAqIHNob3VsZCBiZSByZXF1ZXN0ZWQgZm9yIHRoZSBwYXNzZWQgdGlsZSBjb29yZGluYXRlLlxuICpcbiAqIEB0eXBlZGVmIHtmdW5jdGlvbihpbXBvcnQoXCIuL3RpbGVjb29yZC5qc1wiKS5UaWxlQ29vcmQsIG51bWJlcixcbiAqICAgICAgICAgICBpbXBvcnQoXCIuL3Byb2ovUHJvamVjdGlvbi5qc1wiKS5kZWZhdWx0KTogKHN0cmluZ3x1bmRlZmluZWQpfSBVcmxGdW5jdGlvblxuICogQGFwaVxuICovXG5cbi8qKlxuICogQHR5cGVkZWYge09iamVjdH0gT3B0aW9uc1xuICogQHByb3BlcnR5IHtudW1iZXJ9IFt0cmFuc2l0aW9uPTI1MF0gQSBkdXJhdGlvbiBmb3IgdGlsZSBvcGFjaXR5XG4gKiB0cmFuc2l0aW9ucyBpbiBtaWxsaXNlY29uZHMuIEEgZHVyYXRpb24gb2YgMCBkaXNhYmxlcyB0aGUgb3BhY2l0eSB0cmFuc2l0aW9uLlxuICogQGFwaVxuICovXG5cbi8qKlxuICogQGNsYXNzZGVzY1xuICogQmFzZSBjbGFzcyBmb3IgdGlsZXMuXG4gKlxuICogQGFic3RyYWN0XG4gKi9cblxudmFyIFRpbGUgPVxuLyoqIEBjbGFzcyAqL1xuZnVuY3Rpb24gKF9zdXBlcikge1xuICBfX2V4dGVuZHMoVGlsZSwgX3N1cGVyKTtcbiAgLyoqXG4gICAqIEBwYXJhbSB7aW1wb3J0KFwiLi90aWxlY29vcmQuanNcIikuVGlsZUNvb3JkfSB0aWxlQ29vcmQgVGlsZSBjb29yZGluYXRlLlxuICAgKiBAcGFyYW0ge2ltcG9ydChcIi4vVGlsZVN0YXRlLmpzXCIpLmRlZmF1bHR9IHN0YXRlIFN0YXRlLlxuICAgKiBAcGFyYW0ge09wdGlvbnM9fSBvcHRfb3B0aW9ucyBUaWxlIG9wdGlvbnMuXG4gICAqL1xuXG5cbiAgZnVuY3Rpb24gVGlsZSh0aWxlQ29vcmQsIHN0YXRlLCBvcHRfb3B0aW9ucykge1xuICAgIHZhciBfdGhpcyA9IF9zdXBlci5jYWxsKHRoaXMpIHx8IHRoaXM7XG5cbiAgICB2YXIgb3B0aW9ucyA9IG9wdF9vcHRpb25zID8gb3B0X29wdGlvbnMgOiB7fTtcbiAgICAvKipcbiAgICAgKiBAdHlwZSB7aW1wb3J0KFwiLi90aWxlY29vcmQuanNcIikuVGlsZUNvb3JkfVxuICAgICAqL1xuXG4gICAgX3RoaXMudGlsZUNvb3JkID0gdGlsZUNvb3JkO1xuICAgIC8qKlxuICAgICAqIEBwcm90ZWN0ZWRcbiAgICAgKiBAdHlwZSB7aW1wb3J0KFwiLi9UaWxlU3RhdGUuanNcIikuZGVmYXVsdH1cbiAgICAgKi9cblxuICAgIF90aGlzLnN0YXRlID0gc3RhdGU7XG4gICAgLyoqXG4gICAgICogQW4gXCJpbnRlcmltXCIgdGlsZSBmb3IgdGhpcyB0aWxlLiBUaGUgaW50ZXJpbSB0aWxlIG1heSBiZSB1c2VkIHdoaWxlIHRoaXNcbiAgICAgKiBvbmUgaXMgbG9hZGluZywgZm9yIFwic21vb3RoXCIgdHJhbnNpdGlvbnMgd2hlbiBjaGFuZ2luZyBwYXJhbXMvZGltZW5zaW9uc1xuICAgICAqIG9uIHRoZSBzb3VyY2UuXG4gICAgICogQHR5cGUge1RpbGV9XG4gICAgICovXG5cbiAgICBfdGhpcy5pbnRlcmltVGlsZSA9IG51bGw7XG4gICAgLyoqXG4gICAgICogVGhlIHRpbGUgaXMgYXZhaWxhYmxlIGF0IHRoZSBoaWdoZXN0IHBvc3NpYmxlIHJlc29sdXRpb24uIFN1YmNsYXNzZXMgY2FuXG4gICAgICogc2V0IHRoaXMgdG8gYGZhbHNlYCBpbml0aWFsbHkuIFRpbGUgbG9hZCBsaXN0ZW5lcnMgd2lsbCBub3QgYmVcbiAgICAgKiB1bnJlZ2lzdGVyZWQgYmVmb3JlIHRoaXMgaXMgc2V0IHRvIGB0cnVlYCBhbmQgYSBgI2NoYW5nZWQoKWAgaXMgY2FsbGVkLlxuICAgICAqIEB0eXBlIHtib29sZWFufVxuICAgICAqL1xuXG4gICAgX3RoaXMuaGlmaSA9IHRydWU7XG4gICAgLyoqXG4gICAgICogQSBrZXkgYXNzaWduZWQgdG8gdGhlIHRpbGUuIFRoaXMgaXMgdXNlZCBieSB0aGUgdGlsZSBzb3VyY2UgdG8gZGV0ZXJtaW5lXG4gICAgICogaWYgdGhpcyB0aWxlIGNhbiBlZmZlY3RpdmVseSBiZSB1c2VkLCBvciBpZiBhIG5ldyB0aWxlIHNob3VsZCBiZSBjcmVhdGVkXG4gICAgICogYW5kIHRoaXMgb25lIGJlIHVzZWQgYXMgYW4gaW50ZXJpbSB0aWxlIGZvciB0aGlzIG5ldyB0aWxlLlxuICAgICAqIEB0eXBlIHtzdHJpbmd9XG4gICAgICovXG5cbiAgICBfdGhpcy5rZXkgPSAnJztcbiAgICAvKipcbiAgICAgKiBUaGUgZHVyYXRpb24gZm9yIHRoZSBvcGFjaXR5IHRyYW5zaXRpb24uXG4gICAgICogQHR5cGUge251bWJlcn1cbiAgICAgKi9cblxuICAgIF90aGlzLnRyYW5zaXRpb25fID0gb3B0aW9ucy50cmFuc2l0aW9uID09PSB1bmRlZmluZWQgPyAyNTAgOiBvcHRpb25zLnRyYW5zaXRpb247XG4gICAgLyoqXG4gICAgICogTG9va3VwIG9mIHN0YXJ0IHRpbWVzIGZvciByZW5kZXJpbmcgdHJhbnNpdGlvbnMuICBJZiB0aGUgc3RhcnQgdGltZSBpc1xuICAgICAqIGVxdWFsIHRvIC0xLCB0aGUgdHJhbnNpdGlvbiBpcyBjb21wbGV0ZS5cbiAgICAgKiBAdHlwZSB7T2JqZWN0PHN0cmluZywgbnVtYmVyPn1cbiAgICAgKi9cblxuICAgIF90aGlzLnRyYW5zaXRpb25TdGFydHNfID0ge307XG4gICAgcmV0dXJuIF90aGlzO1xuICB9XG4gIC8qKlxuICAgKiBAcHJvdGVjdGVkXG4gICAqL1xuXG5cbiAgVGlsZS5wcm90b3R5cGUuY2hhbmdlZCA9IGZ1bmN0aW9uICgpIHtcbiAgICB0aGlzLmRpc3BhdGNoRXZlbnQoRXZlbnRUeXBlLkNIQU5HRSk7XG4gIH07XG4gIC8qKlxuICAgKiBDYWxsZWQgYnkgdGhlIHRpbGUgY2FjaGUgd2hlbiB0aGUgdGlsZSBpcyByZW1vdmVkIGZyb20gdGhlIGNhY2hlIGR1ZSB0byBleHBpcnlcbiAgICovXG5cblxuICBUaWxlLnByb3RvdHlwZS5yZWxlYXNlID0gZnVuY3Rpb24gKCkge307XG4gIC8qKlxuICAgKiBAcmV0dXJuIHtzdHJpbmd9IEtleS5cbiAgICovXG5cblxuICBUaWxlLnByb3RvdHlwZS5nZXRLZXkgPSBmdW5jdGlvbiAoKSB7XG4gICAgcmV0dXJuIHRoaXMua2V5ICsgJy8nICsgdGhpcy50aWxlQ29vcmQ7XG4gIH07XG4gIC8qKlxuICAgKiBHZXQgdGhlIGludGVyaW0gdGlsZSBtb3N0IHN1aXRhYmxlIGZvciByZW5kZXJpbmcgdXNpbmcgdGhlIGNoYWluIG9mIGludGVyaW1cbiAgICogdGlsZXMuIFRoaXMgY29ycmVzcG9uZHMgdG8gdGhlICBtb3N0IHJlY2VudCB0aWxlIHRoYXQgaGFzIGJlZW4gbG9hZGVkLCBpZiBub1xuICAgKiBzdWNoIHRpbGUgZXhpc3RzLCB0aGUgb3JpZ2luYWwgdGlsZSBpcyByZXR1cm5lZC5cbiAgICogQHJldHVybiB7IVRpbGV9IEJlc3QgdGlsZSBmb3IgcmVuZGVyaW5nLlxuICAgKi9cblxuXG4gIFRpbGUucHJvdG90eXBlLmdldEludGVyaW1UaWxlID0gZnVuY3Rpb24gKCkge1xuICAgIGlmICghdGhpcy5pbnRlcmltVGlsZSkge1xuICAgICAgLy9lbXB0eSBjaGFpblxuICAgICAgcmV0dXJuIHRoaXM7XG4gICAgfVxuXG4gICAgdmFyIHRpbGUgPSB0aGlzLmludGVyaW1UaWxlOyAvLyBmaW5kIHRoZSBmaXJzdCBsb2FkZWQgdGlsZSBhbmQgcmV0dXJuIGl0LiBTaW5jZSB0aGUgY2hhaW4gaXMgc29ydGVkIGluXG4gICAgLy8gZGVjcmVhc2luZyBvcmRlciBvZiBjcmVhdGlvbiB0aW1lLCB0aGVyZSBpcyBubyBuZWVkIHRvIHNlYXJjaCB0aGUgcmVtYWluZGVyXG4gICAgLy8gb2YgdGhlIGxpc3QgKGFsbCB0aG9zZSB0aWxlcyBjb3JyZXNwb25kIHRvIG9sZGVyIHJlcXVlc3RzIGFuZCB3aWxsIGJlXG4gICAgLy8gY2xlYW5lZCB1cCBieSByZWZyZXNoSW50ZXJpbUNoYWluKVxuXG4gICAgZG8ge1xuICAgICAgaWYgKHRpbGUuZ2V0U3RhdGUoKSA9PSBUaWxlU3RhdGUuTE9BREVEKSB7XG4gICAgICAgIC8vIFNob3cgdGlsZSBpbW1lZGlhdGVseSBpbnN0ZWFkIG9mIGZhZGluZyBpdCBpbiBhZnRlciBsb2FkaW5nLCBiZWNhdXNlXG4gICAgICAgIC8vIHRoZSBpbnRlcmltIHRpbGUgaXMgaW4gcGxhY2UgYWxyZWFkeVxuICAgICAgICB0aGlzLnRyYW5zaXRpb25fID0gMDtcbiAgICAgICAgcmV0dXJuIHRpbGU7XG4gICAgICB9XG5cbiAgICAgIHRpbGUgPSB0aWxlLmludGVyaW1UaWxlO1xuICAgIH0gd2hpbGUgKHRpbGUpOyAvLyB3ZSBjYW4gbm90IGZpbmQgYSBiZXR0ZXIgdGlsZVxuXG5cbiAgICByZXR1cm4gdGhpcztcbiAgfTtcbiAgLyoqXG4gICAqIEdvZXMgdGhyb3VnaCB0aGUgY2hhaW4gb2YgaW50ZXJpbSB0aWxlcyBhbmQgZGlzY2FyZHMgc2VjdGlvbnMgb2YgdGhlIGNoYWluXG4gICAqIHRoYXQgYXJlIG5vIGxvbmdlciByZWxldmFudC5cbiAgICovXG5cblxuICBUaWxlLnByb3RvdHlwZS5yZWZyZXNoSW50ZXJpbUNoYWluID0gZnVuY3Rpb24gKCkge1xuICAgIGlmICghdGhpcy5pbnRlcmltVGlsZSkge1xuICAgICAgcmV0dXJuO1xuICAgIH1cblxuICAgIHZhciB0aWxlID0gdGhpcy5pbnRlcmltVGlsZTtcbiAgICB2YXIgcHJldiA9XG4gICAgLyoqIEB0eXBlIHtUaWxlfSAqL1xuICAgIHRoaXM7XG5cbiAgICBkbyB7XG4gICAgICBpZiAodGlsZS5nZXRTdGF0ZSgpID09IFRpbGVTdGF0ZS5MT0FERUQpIHtcbiAgICAgICAgLy93ZSBoYXZlIGEgbG9hZGVkIHRpbGUsIHdlIGNhbiBkaXNjYXJkIHRoZSByZXN0IG9mIHRoZSBsaXN0XG4gICAgICAgIC8vd2Ugd291bGQgY291bGQgYWJvcnQgYW55IExPQURJTkcgdGlsZSByZXF1ZXN0XG4gICAgICAgIC8vb2xkZXIgdGhhbiB0aGlzIHRpbGUgKGkuZS4gYW55IExPQURJTkcgdGlsZSBmb2xsb3dpbmcgdGhpcyBlbnRyeSBpbiB0aGUgY2hhaW4pXG4gICAgICAgIHRpbGUuaW50ZXJpbVRpbGUgPSBudWxsO1xuICAgICAgICBicmVhaztcbiAgICAgIH0gZWxzZSBpZiAodGlsZS5nZXRTdGF0ZSgpID09IFRpbGVTdGF0ZS5MT0FESU5HKSB7XG4gICAgICAgIC8va2VlcCB0aGlzIExPQURJTkcgdGlsZSBhbnkgbG9hZGVkIHRpbGVzIGxhdGVyIGluIHRoZSBjaGFpbiBhcmVcbiAgICAgICAgLy9vbGRlciB0aGFuIHRoaXMgdGlsZSwgc28gd2UncmUgc3RpbGwgaW50ZXJlc3RlZCBpbiB0aGUgcmVxdWVzdFxuICAgICAgICBwcmV2ID0gdGlsZTtcbiAgICAgIH0gZWxzZSBpZiAodGlsZS5nZXRTdGF0ZSgpID09IFRpbGVTdGF0ZS5JRExFKSB7XG4gICAgICAgIC8vdGhlIGhlYWQgb2YgdGhlIGxpc3QgaXMgdGhlIG1vc3QgY3VycmVudCB0aWxlLCB3ZSBkb24ndCBuZWVkXG4gICAgICAgIC8vdG8gc3RhcnQgYW55IG90aGVyIHJlcXVlc3RzIGZvciB0aGlzIGNoYWluXG4gICAgICAgIHByZXYuaW50ZXJpbVRpbGUgPSB0aWxlLmludGVyaW1UaWxlO1xuICAgICAgfSBlbHNlIHtcbiAgICAgICAgcHJldiA9IHRpbGU7XG4gICAgICB9XG5cbiAgICAgIHRpbGUgPSBwcmV2LmludGVyaW1UaWxlO1xuICAgIH0gd2hpbGUgKHRpbGUpO1xuICB9O1xuICAvKipcbiAgICogR2V0IHRoZSB0aWxlIGNvb3JkaW5hdGUgZm9yIHRoaXMgdGlsZS5cbiAgICogQHJldHVybiB7aW1wb3J0KFwiLi90aWxlY29vcmQuanNcIikuVGlsZUNvb3JkfSBUaGUgdGlsZSBjb29yZGluYXRlLlxuICAgKiBAYXBpXG4gICAqL1xuXG5cbiAgVGlsZS5wcm90b3R5cGUuZ2V0VGlsZUNvb3JkID0gZnVuY3Rpb24gKCkge1xuICAgIHJldHVybiB0aGlzLnRpbGVDb29yZDtcbiAgfTtcbiAgLyoqXG4gICAqIEByZXR1cm4ge2ltcG9ydChcIi4vVGlsZVN0YXRlLmpzXCIpLmRlZmF1bHR9IFN0YXRlLlxuICAgKi9cblxuXG4gIFRpbGUucHJvdG90eXBlLmdldFN0YXRlID0gZnVuY3Rpb24gKCkge1xuICAgIHJldHVybiB0aGlzLnN0YXRlO1xuICB9O1xuICAvKipcbiAgICogU2V0cyB0aGUgc3RhdGUgb2YgdGhpcyB0aWxlLiBJZiB5b3Ugd3JpdGUgeW91ciBvd24ge0BsaW5rIG1vZHVsZTpvbC9UaWxlfkxvYWRGdW5jdGlvbiB0aWxlTG9hZEZ1bmN0aW9ufSAsXG4gICAqIGl0IGlzIGltcG9ydGFudCB0byBzZXQgdGhlIHN0YXRlIGNvcnJlY3RseSB0byB7QGxpbmsgbW9kdWxlOm9sL1RpbGVTdGF0ZX5FUlJPUn1cbiAgICogd2hlbiB0aGUgdGlsZSBjYW5ub3QgYmUgbG9hZGVkLiBPdGhlcndpc2UgdGhlIHRpbGUgY2Fubm90IGJlIHJlbW92ZWQgZnJvbVxuICAgKiB0aGUgdGlsZSBxdWV1ZSBhbmQgd2lsbCBibG9jayBvdGhlciByZXF1ZXN0cy5cbiAgICogQHBhcmFtIHtpbXBvcnQoXCIuL1RpbGVTdGF0ZS5qc1wiKS5kZWZhdWx0fSBzdGF0ZSBTdGF0ZS5cbiAgICogQGFwaVxuICAgKi9cblxuXG4gIFRpbGUucHJvdG90eXBlLnNldFN0YXRlID0gZnVuY3Rpb24gKHN0YXRlKSB7XG4gICAgaWYgKHRoaXMuc3RhdGUgIT09IFRpbGVTdGF0ZS5FUlJPUiAmJiB0aGlzLnN0YXRlID4gc3RhdGUpIHtcbiAgICAgIHRocm93IG5ldyBFcnJvcignVGlsZSBsb2FkIHNlcXVlbmNlIHZpb2xhdGlvbicpO1xuICAgIH1cblxuICAgIHRoaXMuc3RhdGUgPSBzdGF0ZTtcbiAgICB0aGlzLmNoYW5nZWQoKTtcbiAgfTtcbiAgLyoqXG4gICAqIExvYWQgdGhlIGltYWdlIG9yIHJldHJ5IGlmIGxvYWRpbmcgcHJldmlvdXNseSBmYWlsZWQuXG4gICAqIExvYWRpbmcgaXMgdGFrZW4gY2FyZSBvZiBieSB0aGUgdGlsZSBxdWV1ZSwgYW5kIGNhbGxpbmcgdGhpcyBtZXRob2QgaXNcbiAgICogb25seSBuZWVkZWQgZm9yIHByZWxvYWRpbmcgb3IgZm9yIHJlbG9hZGluZyBpbiBjYXNlIG9mIGFuIGVycm9yLlxuICAgKiBAYWJzdHJhY3RcbiAgICogQGFwaVxuICAgKi9cblxuXG4gIFRpbGUucHJvdG90eXBlLmxvYWQgPSBmdW5jdGlvbiAoKSB7XG4gICAgYWJzdHJhY3QoKTtcbiAgfTtcbiAgLyoqXG4gICAqIEdldCB0aGUgYWxwaGEgdmFsdWUgZm9yIHJlbmRlcmluZy5cbiAgICogQHBhcmFtIHtzdHJpbmd9IGlkIEFuIGlkIGZvciB0aGUgcmVuZGVyZXIuXG4gICAqIEBwYXJhbSB7bnVtYmVyfSB0aW1lIFRoZSByZW5kZXIgZnJhbWUgdGltZS5cbiAgICogQHJldHVybiB7bnVtYmVyfSBBIG51bWJlciBiZXR3ZWVuIDAgYW5kIDEuXG4gICAqL1xuXG5cbiAgVGlsZS5wcm90b3R5cGUuZ2V0QWxwaGEgPSBmdW5jdGlvbiAoaWQsIHRpbWUpIHtcbiAgICBpZiAoIXRoaXMudHJhbnNpdGlvbl8pIHtcbiAgICAgIHJldHVybiAxO1xuICAgIH1cblxuICAgIHZhciBzdGFydCA9IHRoaXMudHJhbnNpdGlvblN0YXJ0c19baWRdO1xuXG4gICAgaWYgKCFzdGFydCkge1xuICAgICAgc3RhcnQgPSB0aW1lO1xuICAgICAgdGhpcy50cmFuc2l0aW9uU3RhcnRzX1tpZF0gPSBzdGFydDtcbiAgICB9IGVsc2UgaWYgKHN0YXJ0ID09PSAtMSkge1xuICAgICAgcmV0dXJuIDE7XG4gICAgfVxuXG4gICAgdmFyIGRlbHRhID0gdGltZSAtIHN0YXJ0ICsgMTAwMCAvIDYwOyAvLyBhdm9pZCByZW5kZXJpbmcgYXQgMFxuXG4gICAgaWYgKGRlbHRhID49IHRoaXMudHJhbnNpdGlvbl8pIHtcbiAgICAgIHJldHVybiAxO1xuICAgIH1cblxuICAgIHJldHVybiBlYXNlSW4oZGVsdGEgLyB0aGlzLnRyYW5zaXRpb25fKTtcbiAgfTtcbiAgLyoqXG4gICAqIERldGVybWluZSBpZiBhIHRpbGUgaXMgaW4gYW4gYWxwaGEgdHJhbnNpdGlvbi4gIEEgdGlsZSBpcyBjb25zaWRlcmVkIGluXG4gICAqIHRyYW5zaXRpb24gaWYgdGlsZS5nZXRBbHBoYSgpIGhhcyBub3QgeWV0IGJlZW4gY2FsbGVkIG9yIGhhcyBiZWVuIGNhbGxlZFxuICAgKiBhbmQgcmV0dXJuZWQgMS5cbiAgICogQHBhcmFtIHtzdHJpbmd9IGlkIEFuIGlkIGZvciB0aGUgcmVuZGVyZXIuXG4gICAqIEByZXR1cm4ge2Jvb2xlYW59IFRoZSB0aWxlIGlzIGluIHRyYW5zaXRpb24uXG4gICAqL1xuXG5cbiAgVGlsZS5wcm90b3R5cGUuaW5UcmFuc2l0aW9uID0gZnVuY3Rpb24gKGlkKSB7XG4gICAgaWYgKCF0aGlzLnRyYW5zaXRpb25fKSB7XG4gICAgICByZXR1cm4gZmFsc2U7XG4gICAgfVxuXG4gICAgcmV0dXJuIHRoaXMudHJhbnNpdGlvblN0YXJ0c19baWRdICE9PSAtMTtcbiAgfTtcbiAgLyoqXG4gICAqIE1hcmsgYSB0cmFuc2l0aW9uIGFzIGNvbXBsZXRlLlxuICAgKiBAcGFyYW0ge3N0cmluZ30gaWQgQW4gaWQgZm9yIHRoZSByZW5kZXJlci5cbiAgICovXG5cblxuICBUaWxlLnByb3RvdHlwZS5lbmRUcmFuc2l0aW9uID0gZnVuY3Rpb24gKGlkKSB7XG4gICAgaWYgKHRoaXMudHJhbnNpdGlvbl8pIHtcbiAgICAgIHRoaXMudHJhbnNpdGlvblN0YXJ0c19baWRdID0gLTE7XG4gICAgfVxuICB9O1xuXG4gIHJldHVybiBUaWxlO1xufShFdmVudFRhcmdldCk7XG5cbmV4cG9ydCBkZWZhdWx0IFRpbGU7IiwidmFyIF9fZXh0ZW5kcyA9IHRoaXMgJiYgdGhpcy5fX2V4dGVuZHMgfHwgZnVuY3Rpb24gKCkge1xuICB2YXIgX2V4dGVuZFN0YXRpY3MgPSBmdW5jdGlvbiBleHRlbmRTdGF0aWNzKGQsIGIpIHtcbiAgICBfZXh0ZW5kU3RhdGljcyA9IE9iamVjdC5zZXRQcm90b3R5cGVPZiB8fCB7XG4gICAgICBfX3Byb3RvX186IFtdXG4gICAgfSBpbnN0YW5jZW9mIEFycmF5ICYmIGZ1bmN0aW9uIChkLCBiKSB7XG4gICAgICBkLl9fcHJvdG9fXyA9IGI7XG4gICAgfSB8fCBmdW5jdGlvbiAoZCwgYikge1xuICAgICAgZm9yICh2YXIgcCBpbiBiKSB7XG4gICAgICAgIGlmIChPYmplY3QucHJvdG90eXBlLmhhc093blByb3BlcnR5LmNhbGwoYiwgcCkpIGRbcF0gPSBiW3BdO1xuICAgICAgfVxuICAgIH07XG5cbiAgICByZXR1cm4gX2V4dGVuZFN0YXRpY3MoZCwgYik7XG4gIH07XG5cbiAgcmV0dXJuIGZ1bmN0aW9uIChkLCBiKSB7XG4gICAgX2V4dGVuZFN0YXRpY3MoZCwgYik7XG5cbiAgICBmdW5jdGlvbiBfXygpIHtcbiAgICAgIHRoaXMuY29uc3RydWN0b3IgPSBkO1xuICAgIH1cblxuICAgIGQucHJvdG90eXBlID0gYiA9PT0gbnVsbCA/IE9iamVjdC5jcmVhdGUoYikgOiAoX18ucHJvdG90eXBlID0gYi5wcm90b3R5cGUsIG5ldyBfXygpKTtcbiAgfTtcbn0oKTtcbi8qKlxuICogQG1vZHVsZSBvbC9WZWN0b3JUaWxlXG4gKi9cblxuXG5pbXBvcnQgVGlsZSBmcm9tICcuL1RpbGUuanMnO1xuaW1wb3J0IFRpbGVTdGF0ZSBmcm9tICcuL1RpbGVTdGF0ZS5qcyc7XG5cbnZhciBWZWN0b3JUaWxlID1cbi8qKiBAY2xhc3MgKi9cbmZ1bmN0aW9uIChfc3VwZXIpIHtcbiAgX19leHRlbmRzKFZlY3RvclRpbGUsIF9zdXBlcik7XG4gIC8qKlxuICAgKiBAcGFyYW0ge2ltcG9ydChcIi4vdGlsZWNvb3JkLmpzXCIpLlRpbGVDb29yZH0gdGlsZUNvb3JkIFRpbGUgY29vcmRpbmF0ZS5cbiAgICogQHBhcmFtIHtpbXBvcnQoXCIuL1RpbGVTdGF0ZS5qc1wiKS5kZWZhdWx0fSBzdGF0ZSBTdGF0ZS5cbiAgICogQHBhcmFtIHtzdHJpbmd9IHNyYyBEYXRhIHNvdXJjZSB1cmwuXG4gICAqIEBwYXJhbSB7aW1wb3J0KFwiLi9mb3JtYXQvRmVhdHVyZS5qc1wiKS5kZWZhdWx0fSBmb3JtYXQgRmVhdHVyZSBmb3JtYXQuXG4gICAqIEBwYXJhbSB7aW1wb3J0KFwiLi9UaWxlLmpzXCIpLkxvYWRGdW5jdGlvbn0gdGlsZUxvYWRGdW5jdGlvbiBUaWxlIGxvYWQgZnVuY3Rpb24uXG4gICAqIEBwYXJhbSB7aW1wb3J0KFwiLi9UaWxlLmpzXCIpLk9wdGlvbnM9fSBvcHRfb3B0aW9ucyBUaWxlIG9wdGlvbnMuXG4gICAqL1xuXG5cbiAgZnVuY3Rpb24gVmVjdG9yVGlsZSh0aWxlQ29vcmQsIHN0YXRlLCBzcmMsIGZvcm1hdCwgdGlsZUxvYWRGdW5jdGlvbiwgb3B0X29wdGlvbnMpIHtcbiAgICB2YXIgX3RoaXMgPSBfc3VwZXIuY2FsbCh0aGlzLCB0aWxlQ29vcmQsIHN0YXRlLCBvcHRfb3B0aW9ucykgfHwgdGhpcztcbiAgICAvKipcbiAgICAgKiBFeHRlbnQgb2YgdGhpcyB0aWxlOyBzZXQgYnkgdGhlIHNvdXJjZS5cbiAgICAgKiBAdHlwZSB7aW1wb3J0KFwiLi9leHRlbnQuanNcIikuRXh0ZW50fVxuICAgICAqL1xuXG5cbiAgICBfdGhpcy5leHRlbnQgPSBudWxsO1xuICAgIC8qKlxuICAgICAqIEBwcml2YXRlXG4gICAgICogQHR5cGUge2ltcG9ydChcIi4vZm9ybWF0L0ZlYXR1cmUuanNcIikuZGVmYXVsdH1cbiAgICAgKi9cblxuICAgIF90aGlzLmZvcm1hdF8gPSBmb3JtYXQ7XG4gICAgLyoqXG4gICAgICogQHByaXZhdGVcbiAgICAgKiBAdHlwZSB7QXJyYXk8aW1wb3J0KFwiLi9GZWF0dXJlLmpzXCIpLmRlZmF1bHQ+fVxuICAgICAqL1xuXG4gICAgX3RoaXMuZmVhdHVyZXNfID0gbnVsbDtcbiAgICAvKipcbiAgICAgKiBAcHJpdmF0ZVxuICAgICAqIEB0eXBlIHtpbXBvcnQoXCIuL2ZlYXR1cmVsb2FkZXIuanNcIikuRmVhdHVyZUxvYWRlcn1cbiAgICAgKi9cblxuICAgIF90aGlzLmxvYWRlcl87XG4gICAgLyoqXG4gICAgICogRmVhdHVyZSBwcm9qZWN0aW9uIG9mIHRoaXMgdGlsZTsgc2V0IGJ5IHRoZSBzb3VyY2UuXG4gICAgICogQHR5cGUge2ltcG9ydChcIi4vcHJvai9Qcm9qZWN0aW9uLmpzXCIpLmRlZmF1bHR9XG4gICAgICovXG5cbiAgICBfdGhpcy5wcm9qZWN0aW9uID0gbnVsbDtcbiAgICAvKipcbiAgICAgKiBSZXNvbHV0aW9uIG9mIHRoaXMgdGlsZTsgc2V0IGJ5IHRoZSBzb3VyY2UuXG4gICAgICogQHR5cGUge251bWJlcn1cbiAgICAgKi9cblxuICAgIF90aGlzLnJlc29sdXRpb247XG4gICAgLyoqXG4gICAgICogQHByaXZhdGVcbiAgICAgKiBAdHlwZSB7aW1wb3J0KFwiLi9UaWxlLmpzXCIpLkxvYWRGdW5jdGlvbn1cbiAgICAgKi9cblxuICAgIF90aGlzLnRpbGVMb2FkRnVuY3Rpb25fID0gdGlsZUxvYWRGdW5jdGlvbjtcbiAgICAvKipcbiAgICAgKiBAcHJpdmF0ZVxuICAgICAqIEB0eXBlIHtzdHJpbmd9XG4gICAgICovXG5cbiAgICBfdGhpcy51cmxfID0gc3JjO1xuICAgIF90aGlzLmtleSA9IHNyYztcbiAgICByZXR1cm4gX3RoaXM7XG4gIH1cbiAgLyoqXG4gICAqIEdldCB0aGUgZmVhdHVyZSBmb3JtYXQgYXNzaWduZWQgZm9yIHJlYWRpbmcgdGhpcyB0aWxlJ3MgZmVhdHVyZXMuXG4gICAqIEByZXR1cm4ge2ltcG9ydChcIi4vZm9ybWF0L0ZlYXR1cmUuanNcIikuZGVmYXVsdH0gRmVhdHVyZSBmb3JtYXQuXG4gICAqIEBhcGlcbiAgICovXG5cblxuICBWZWN0b3JUaWxlLnByb3RvdHlwZS5nZXRGb3JtYXQgPSBmdW5jdGlvbiAoKSB7XG4gICAgcmV0dXJuIHRoaXMuZm9ybWF0XztcbiAgfTtcbiAgLyoqXG4gICAqIEdldCB0aGUgZmVhdHVyZXMgZm9yIHRoaXMgdGlsZS4gR2VvbWV0cmllcyB3aWxsIGJlIGluIHRoZSB2aWV3IHByb2plY3Rpb24uXG4gICAqIEByZXR1cm4ge0FycmF5PGltcG9ydChcIi4vRmVhdHVyZS5qc1wiKS5GZWF0dXJlTGlrZT59IEZlYXR1cmVzLlxuICAgKiBAYXBpXG4gICAqL1xuXG5cbiAgVmVjdG9yVGlsZS5wcm90b3R5cGUuZ2V0RmVhdHVyZXMgPSBmdW5jdGlvbiAoKSB7XG4gICAgcmV0dXJuIHRoaXMuZmVhdHVyZXNfO1xuICB9O1xuICAvKipcbiAgICogTG9hZCBub3QgeWV0IGxvYWRlZCBVUkkuXG4gICAqL1xuXG5cbiAgVmVjdG9yVGlsZS5wcm90b3R5cGUubG9hZCA9IGZ1bmN0aW9uICgpIHtcbiAgICBpZiAodGhpcy5zdGF0ZSA9PSBUaWxlU3RhdGUuSURMRSkge1xuICAgICAgdGhpcy5zZXRTdGF0ZShUaWxlU3RhdGUuTE9BRElORyk7XG4gICAgICB0aGlzLnRpbGVMb2FkRnVuY3Rpb25fKHRoaXMsIHRoaXMudXJsXyk7XG5cbiAgICAgIGlmICh0aGlzLmxvYWRlcl8pIHtcbiAgICAgICAgdGhpcy5sb2FkZXJfKHRoaXMuZXh0ZW50LCB0aGlzLnJlc29sdXRpb24sIHRoaXMucHJvamVjdGlvbik7XG4gICAgICB9XG4gICAgfVxuICB9O1xuICAvKipcbiAgICogSGFuZGxlciBmb3Igc3VjY2Vzc2Z1bCB0aWxlIGxvYWQuXG4gICAqIEBwYXJhbSB7QXJyYXk8aW1wb3J0KFwiLi9GZWF0dXJlLmpzXCIpLmRlZmF1bHQ+fSBmZWF0dXJlcyBUaGUgbG9hZGVkIGZlYXR1cmVzLlxuICAgKiBAcGFyYW0ge2ltcG9ydChcIi4vcHJvai9Qcm9qZWN0aW9uLmpzXCIpLmRlZmF1bHR9IGRhdGFQcm9qZWN0aW9uIERhdGEgcHJvamVjdGlvbi5cbiAgICovXG5cblxuICBWZWN0b3JUaWxlLnByb3RvdHlwZS5vbkxvYWQgPSBmdW5jdGlvbiAoZmVhdHVyZXMsIGRhdGFQcm9qZWN0aW9uKSB7XG4gICAgdGhpcy5zZXRGZWF0dXJlcyhmZWF0dXJlcyk7XG4gIH07XG4gIC8qKlxuICAgKiBIYW5kbGVyIGZvciB0aWxlIGxvYWQgZXJyb3JzLlxuICAgKi9cblxuXG4gIFZlY3RvclRpbGUucHJvdG90eXBlLm9uRXJyb3IgPSBmdW5jdGlvbiAoKSB7XG4gICAgdGhpcy5zZXRTdGF0ZShUaWxlU3RhdGUuRVJST1IpO1xuICB9O1xuICAvKipcbiAgICogRnVuY3Rpb24gZm9yIHVzZSBpbiBhbiB7QGxpbmsgbW9kdWxlOm9sL3NvdXJjZS9WZWN0b3JUaWxlflZlY3RvclRpbGV9J3MgYHRpbGVMb2FkRnVuY3Rpb25gLlxuICAgKiBTZXRzIHRoZSBmZWF0dXJlcyBmb3IgdGhlIHRpbGUuXG4gICAqIEBwYXJhbSB7QXJyYXk8aW1wb3J0KFwiLi9GZWF0dXJlLmpzXCIpLmRlZmF1bHQ+fSBmZWF0dXJlcyBGZWF0dXJlcy5cbiAgICogQGFwaVxuICAgKi9cblxuXG4gIFZlY3RvclRpbGUucHJvdG90eXBlLnNldEZlYXR1cmVzID0gZnVuY3Rpb24gKGZlYXR1cmVzKSB7XG4gICAgdGhpcy5mZWF0dXJlc18gPSBmZWF0dXJlcztcbiAgICB0aGlzLnNldFN0YXRlKFRpbGVTdGF0ZS5MT0FERUQpO1xuICB9O1xuICAvKipcbiAgICogU2V0IHRoZSBmZWF0dXJlIGxvYWRlciBmb3IgcmVhZGluZyB0aGlzIHRpbGUncyBmZWF0dXJlcy5cbiAgICogQHBhcmFtIHtpbXBvcnQoXCIuL2ZlYXR1cmVsb2FkZXIuanNcIikuRmVhdHVyZUxvYWRlcn0gbG9hZGVyIEZlYXR1cmUgbG9hZGVyLlxuICAgKiBAYXBpXG4gICAqL1xuXG5cbiAgVmVjdG9yVGlsZS5wcm90b3R5cGUuc2V0TG9hZGVyID0gZnVuY3Rpb24gKGxvYWRlcikge1xuICAgIHRoaXMubG9hZGVyXyA9IGxvYWRlcjtcbiAgfTtcblxuICByZXR1cm4gVmVjdG9yVGlsZTtcbn0oVGlsZSk7XG5cbmV4cG9ydCBkZWZhdWx0IFZlY3RvclRpbGU7IiwiLyoqXG4gKiBAbW9kdWxlIG9sL3N0cnVjdHMvTFJVQ2FjaGVcbiAqL1xuaW1wb3J0IHsgYXNzZXJ0IH0gZnJvbSAnLi4vYXNzZXJ0cy5qcyc7XG4vKipcbiAqIEB0eXBlZGVmIHtPYmplY3R9IEVudHJ5XG4gKiBAcHJvcGVydHkge3N0cmluZ30ga2V5X1xuICogQHByb3BlcnR5IHtPYmplY3R9IG5ld2VyXG4gKiBAcHJvcGVydHkge09iamVjdH0gb2xkZXJcbiAqIEBwcm9wZXJ0eSB7Kn0gdmFsdWVfXG4gKi9cblxuLyoqXG4gKiBAY2xhc3NkZXNjXG4gKiBJbXBsZW1lbnRzIGEgTGVhc3QtUmVjZW50bHktVXNlZCBjYWNoZSB3aGVyZSB0aGUga2V5cyBkbyBub3QgY29uZmxpY3Qgd2l0aFxuICogT2JqZWN0J3MgcHJvcGVydGllcyAoZS5nLiAnaGFzT3duUHJvcGVydHknIGlzIG5vdCBhbGxvd2VkIGFzIGEga2V5KS4gRXhwaXJpbmdcbiAqIGl0ZW1zIGZyb20gdGhlIGNhY2hlIGlzIHRoZSByZXNwb25zaWJpbGl0eSBvZiB0aGUgdXNlci5cbiAqXG4gKiBAZmlyZXMgaW1wb3J0KFwiLi4vZXZlbnRzL0V2ZW50LmpzXCIpLmRlZmF1bHRcbiAqIEB0ZW1wbGF0ZSBUXG4gKi9cblxudmFyIExSVUNhY2hlID1cbi8qKiBAY2xhc3MgKi9cbmZ1bmN0aW9uICgpIHtcbiAgLyoqXG4gICAqIEBwYXJhbSB7bnVtYmVyPX0gb3B0X2hpZ2hXYXRlck1hcmsgSGlnaCB3YXRlciBtYXJrLlxuICAgKi9cbiAgZnVuY3Rpb24gTFJVQ2FjaGUob3B0X2hpZ2hXYXRlck1hcmspIHtcbiAgICAvKipcbiAgICAgKiBEZXNpcmVkIG1heCBjYWNoZSBzaXplIGFmdGVyIGV4cGlyZUNhY2hlKCkuIElmIHNldCB0byAwLCBubyBjYWNoZSBlbnRyaWVzXG4gICAgICogd2lsbCBiZSBwcnVuZWQgYXQgYWxsLlxuICAgICAqIEB0eXBlIHtudW1iZXJ9XG4gICAgICovXG4gICAgdGhpcy5oaWdoV2F0ZXJNYXJrID0gb3B0X2hpZ2hXYXRlck1hcmsgIT09IHVuZGVmaW5lZCA/IG9wdF9oaWdoV2F0ZXJNYXJrIDogMjA0ODtcbiAgICAvKipcbiAgICAgKiBAcHJpdmF0ZVxuICAgICAqIEB0eXBlIHtudW1iZXJ9XG4gICAgICovXG5cbiAgICB0aGlzLmNvdW50XyA9IDA7XG4gICAgLyoqXG4gICAgICogQHByaXZhdGVcbiAgICAgKiBAdHlwZSB7IU9iamVjdDxzdHJpbmcsIEVudHJ5Pn1cbiAgICAgKi9cblxuICAgIHRoaXMuZW50cmllc18gPSB7fTtcbiAgICAvKipcbiAgICAgKiBAcHJpdmF0ZVxuICAgICAqIEB0eXBlIHs/RW50cnl9XG4gICAgICovXG5cbiAgICB0aGlzLm9sZGVzdF8gPSBudWxsO1xuICAgIC8qKlxuICAgICAqIEBwcml2YXRlXG4gICAgICogQHR5cGUgez9FbnRyeX1cbiAgICAgKi9cblxuICAgIHRoaXMubmV3ZXN0XyA9IG51bGw7XG4gIH1cbiAgLyoqXG4gICAqIEByZXR1cm4ge2Jvb2xlYW59IENhbiBleHBpcmUgY2FjaGUuXG4gICAqL1xuXG5cbiAgTFJVQ2FjaGUucHJvdG90eXBlLmNhbkV4cGlyZUNhY2hlID0gZnVuY3Rpb24gKCkge1xuICAgIHJldHVybiB0aGlzLmhpZ2hXYXRlck1hcmsgPiAwICYmIHRoaXMuZ2V0Q291bnQoKSA+IHRoaXMuaGlnaFdhdGVyTWFyaztcbiAgfTtcbiAgLyoqXG4gICAqIEZJWE1FIGVtcHR5IGRlc2NyaXB0aW9uIGZvciBqc2RvY1xuICAgKi9cblxuXG4gIExSVUNhY2hlLnByb3RvdHlwZS5jbGVhciA9IGZ1bmN0aW9uICgpIHtcbiAgICB0aGlzLmNvdW50XyA9IDA7XG4gICAgdGhpcy5lbnRyaWVzXyA9IHt9O1xuICAgIHRoaXMub2xkZXN0XyA9IG51bGw7XG4gICAgdGhpcy5uZXdlc3RfID0gbnVsbDtcbiAgfTtcbiAgLyoqXG4gICAqIEBwYXJhbSB7c3RyaW5nfSBrZXkgS2V5LlxuICAgKiBAcmV0dXJuIHtib29sZWFufSBDb250YWlucyBrZXkuXG4gICAqL1xuXG5cbiAgTFJVQ2FjaGUucHJvdG90eXBlLmNvbnRhaW5zS2V5ID0gZnVuY3Rpb24gKGtleSkge1xuICAgIHJldHVybiB0aGlzLmVudHJpZXNfLmhhc093blByb3BlcnR5KGtleSk7XG4gIH07XG4gIC8qKlxuICAgKiBAcGFyYW0ge2Z1bmN0aW9uKFQsIHN0cmluZywgTFJVQ2FjaGU8VD4pOiA/fSBmIFRoZSBmdW5jdGlvblxuICAgKiAgICAgdG8gY2FsbCBmb3IgZXZlcnkgZW50cnkgZnJvbSB0aGUgb2xkZXN0IHRvIHRoZSBuZXdlci4gVGhpcyBmdW5jdGlvbiB0YWtlc1xuICAgKiAgICAgMyBhcmd1bWVudHMgKHRoZSBlbnRyeSB2YWx1ZSwgdGhlIGVudHJ5IGtleSBhbmQgdGhlIExSVUNhY2hlIG9iamVjdCkuXG4gICAqICAgICBUaGUgcmV0dXJuIHZhbHVlIGlzIGlnbm9yZWQuXG4gICAqL1xuXG5cbiAgTFJVQ2FjaGUucHJvdG90eXBlLmZvckVhY2ggPSBmdW5jdGlvbiAoZikge1xuICAgIHZhciBlbnRyeSA9IHRoaXMub2xkZXN0XztcblxuICAgIHdoaWxlIChlbnRyeSkge1xuICAgICAgZihlbnRyeS52YWx1ZV8sIGVudHJ5LmtleV8sIHRoaXMpO1xuICAgICAgZW50cnkgPSBlbnRyeS5uZXdlcjtcbiAgICB9XG4gIH07XG4gIC8qKlxuICAgKiBAcGFyYW0ge3N0cmluZ30ga2V5IEtleS5cbiAgICogQHBhcmFtIHsqPX0gb3B0X29wdGlvbnMgT3B0aW9ucyAocmVzZXJ2ZXJkIGZvciBzdWJjbGFzc2VzKS5cbiAgICogQHJldHVybiB7VH0gVmFsdWUuXG4gICAqL1xuXG5cbiAgTFJVQ2FjaGUucHJvdG90eXBlLmdldCA9IGZ1bmN0aW9uIChrZXksIG9wdF9vcHRpb25zKSB7XG4gICAgdmFyIGVudHJ5ID0gdGhpcy5lbnRyaWVzX1trZXldO1xuICAgIGFzc2VydChlbnRyeSAhPT0gdW5kZWZpbmVkLCAxNSk7IC8vIFRyaWVkIHRvIGdldCBhIHZhbHVlIGZvciBhIGtleSB0aGF0IGRvZXMgbm90IGV4aXN0IGluIHRoZSBjYWNoZVxuXG4gICAgaWYgKGVudHJ5ID09PSB0aGlzLm5ld2VzdF8pIHtcbiAgICAgIHJldHVybiBlbnRyeS52YWx1ZV87XG4gICAgfSBlbHNlIGlmIChlbnRyeSA9PT0gdGhpcy5vbGRlc3RfKSB7XG4gICAgICB0aGlzLm9sZGVzdF8gPVxuICAgICAgLyoqIEB0eXBlIHtFbnRyeX0gKi9cbiAgICAgIHRoaXMub2xkZXN0Xy5uZXdlcjtcbiAgICAgIHRoaXMub2xkZXN0Xy5vbGRlciA9IG51bGw7XG4gICAgfSBlbHNlIHtcbiAgICAgIGVudHJ5Lm5ld2VyLm9sZGVyID0gZW50cnkub2xkZXI7XG4gICAgICBlbnRyeS5vbGRlci5uZXdlciA9IGVudHJ5Lm5ld2VyO1xuICAgIH1cblxuICAgIGVudHJ5Lm5ld2VyID0gbnVsbDtcbiAgICBlbnRyeS5vbGRlciA9IHRoaXMubmV3ZXN0XztcbiAgICB0aGlzLm5ld2VzdF8ubmV3ZXIgPSBlbnRyeTtcbiAgICB0aGlzLm5ld2VzdF8gPSBlbnRyeTtcbiAgICByZXR1cm4gZW50cnkudmFsdWVfO1xuICB9O1xuICAvKipcbiAgICogUmVtb3ZlIGFuIGVudHJ5IGZyb20gdGhlIGNhY2hlLlxuICAgKiBAcGFyYW0ge3N0cmluZ30ga2V5IFRoZSBlbnRyeSBrZXkuXG4gICAqIEByZXR1cm4ge1R9IFRoZSByZW1vdmVkIGVudHJ5LlxuICAgKi9cblxuXG4gIExSVUNhY2hlLnByb3RvdHlwZS5yZW1vdmUgPSBmdW5jdGlvbiAoa2V5KSB7XG4gICAgdmFyIGVudHJ5ID0gdGhpcy5lbnRyaWVzX1trZXldO1xuICAgIGFzc2VydChlbnRyeSAhPT0gdW5kZWZpbmVkLCAxNSk7IC8vIFRyaWVkIHRvIGdldCBhIHZhbHVlIGZvciBhIGtleSB0aGF0IGRvZXMgbm90IGV4aXN0IGluIHRoZSBjYWNoZVxuXG4gICAgaWYgKGVudHJ5ID09PSB0aGlzLm5ld2VzdF8pIHtcbiAgICAgIHRoaXMubmV3ZXN0XyA9XG4gICAgICAvKiogQHR5cGUge0VudHJ5fSAqL1xuICAgICAgZW50cnkub2xkZXI7XG5cbiAgICAgIGlmICh0aGlzLm5ld2VzdF8pIHtcbiAgICAgICAgdGhpcy5uZXdlc3RfLm5ld2VyID0gbnVsbDtcbiAgICAgIH1cbiAgICB9IGVsc2UgaWYgKGVudHJ5ID09PSB0aGlzLm9sZGVzdF8pIHtcbiAgICAgIHRoaXMub2xkZXN0XyA9XG4gICAgICAvKiogQHR5cGUge0VudHJ5fSAqL1xuICAgICAgZW50cnkubmV3ZXI7XG5cbiAgICAgIGlmICh0aGlzLm9sZGVzdF8pIHtcbiAgICAgICAgdGhpcy5vbGRlc3RfLm9sZGVyID0gbnVsbDtcbiAgICAgIH1cbiAgICB9IGVsc2Uge1xuICAgICAgZW50cnkubmV3ZXIub2xkZXIgPSBlbnRyeS5vbGRlcjtcbiAgICAgIGVudHJ5Lm9sZGVyLm5ld2VyID0gZW50cnkubmV3ZXI7XG4gICAgfVxuXG4gICAgZGVsZXRlIHRoaXMuZW50cmllc19ba2V5XTtcbiAgICAtLXRoaXMuY291bnRfO1xuICAgIHJldHVybiBlbnRyeS52YWx1ZV87XG4gIH07XG4gIC8qKlxuICAgKiBAcmV0dXJuIHtudW1iZXJ9IENvdW50LlxuICAgKi9cblxuXG4gIExSVUNhY2hlLnByb3RvdHlwZS5nZXRDb3VudCA9IGZ1bmN0aW9uICgpIHtcbiAgICByZXR1cm4gdGhpcy5jb3VudF87XG4gIH07XG4gIC8qKlxuICAgKiBAcmV0dXJuIHtBcnJheTxzdHJpbmc+fSBLZXlzLlxuICAgKi9cblxuXG4gIExSVUNhY2hlLnByb3RvdHlwZS5nZXRLZXlzID0gZnVuY3Rpb24gKCkge1xuICAgIHZhciBrZXlzID0gbmV3IEFycmF5KHRoaXMuY291bnRfKTtcbiAgICB2YXIgaSA9IDA7XG4gICAgdmFyIGVudHJ5O1xuXG4gICAgZm9yIChlbnRyeSA9IHRoaXMubmV3ZXN0XzsgZW50cnk7IGVudHJ5ID0gZW50cnkub2xkZXIpIHtcbiAgICAgIGtleXNbaSsrXSA9IGVudHJ5LmtleV87XG4gICAgfVxuXG4gICAgcmV0dXJuIGtleXM7XG4gIH07XG4gIC8qKlxuICAgKiBAcmV0dXJuIHtBcnJheTxUPn0gVmFsdWVzLlxuICAgKi9cblxuXG4gIExSVUNhY2hlLnByb3RvdHlwZS5nZXRWYWx1ZXMgPSBmdW5jdGlvbiAoKSB7XG4gICAgdmFyIHZhbHVlcyA9IG5ldyBBcnJheSh0aGlzLmNvdW50Xyk7XG4gICAgdmFyIGkgPSAwO1xuICAgIHZhciBlbnRyeTtcblxuICAgIGZvciAoZW50cnkgPSB0aGlzLm5ld2VzdF87IGVudHJ5OyBlbnRyeSA9IGVudHJ5Lm9sZGVyKSB7XG4gICAgICB2YWx1ZXNbaSsrXSA9IGVudHJ5LnZhbHVlXztcbiAgICB9XG5cbiAgICByZXR1cm4gdmFsdWVzO1xuICB9O1xuICAvKipcbiAgICogQHJldHVybiB7VH0gTGFzdCB2YWx1ZS5cbiAgICovXG5cblxuICBMUlVDYWNoZS5wcm90b3R5cGUucGVla0xhc3QgPSBmdW5jdGlvbiAoKSB7XG4gICAgcmV0dXJuIHRoaXMub2xkZXN0Xy52YWx1ZV87XG4gIH07XG4gIC8qKlxuICAgKiBAcmV0dXJuIHtzdHJpbmd9IExhc3Qga2V5LlxuICAgKi9cblxuXG4gIExSVUNhY2hlLnByb3RvdHlwZS5wZWVrTGFzdEtleSA9IGZ1bmN0aW9uICgpIHtcbiAgICByZXR1cm4gdGhpcy5vbGRlc3RfLmtleV87XG4gIH07XG4gIC8qKlxuICAgKiBHZXQgdGhlIGtleSBvZiB0aGUgbmV3ZXN0IGl0ZW0gaW4gdGhlIGNhY2hlLiAgVGhyb3dzIGlmIHRoZSBjYWNoZSBpcyBlbXB0eS5cbiAgICogQHJldHVybiB7c3RyaW5nfSBUaGUgbmV3ZXN0IGtleS5cbiAgICovXG5cblxuICBMUlVDYWNoZS5wcm90b3R5cGUucGVla0ZpcnN0S2V5ID0gZnVuY3Rpb24gKCkge1xuICAgIHJldHVybiB0aGlzLm5ld2VzdF8ua2V5XztcbiAgfTtcbiAgLyoqXG4gICAqIEByZXR1cm4ge1R9IHZhbHVlIFZhbHVlLlxuICAgKi9cblxuXG4gIExSVUNhY2hlLnByb3RvdHlwZS5wb3AgPSBmdW5jdGlvbiAoKSB7XG4gICAgdmFyIGVudHJ5ID0gdGhpcy5vbGRlc3RfO1xuICAgIGRlbGV0ZSB0aGlzLmVudHJpZXNfW2VudHJ5LmtleV9dO1xuXG4gICAgaWYgKGVudHJ5Lm5ld2VyKSB7XG4gICAgICBlbnRyeS5uZXdlci5vbGRlciA9IG51bGw7XG4gICAgfVxuXG4gICAgdGhpcy5vbGRlc3RfID1cbiAgICAvKiogQHR5cGUge0VudHJ5fSAqL1xuICAgIGVudHJ5Lm5ld2VyO1xuXG4gICAgaWYgKCF0aGlzLm9sZGVzdF8pIHtcbiAgICAgIHRoaXMubmV3ZXN0XyA9IG51bGw7XG4gICAgfVxuXG4gICAgLS10aGlzLmNvdW50XztcbiAgICByZXR1cm4gZW50cnkudmFsdWVfO1xuICB9O1xuICAvKipcbiAgICogQHBhcmFtIHtzdHJpbmd9IGtleSBLZXkuXG4gICAqIEBwYXJhbSB7VH0gdmFsdWUgVmFsdWUuXG4gICAqL1xuXG5cbiAgTFJVQ2FjaGUucHJvdG90eXBlLnJlcGxhY2UgPSBmdW5jdGlvbiAoa2V5LCB2YWx1ZSkge1xuICAgIHRoaXMuZ2V0KGtleSk7IC8vIHVwZGF0ZSBgbmV3ZXN0X2BcblxuICAgIHRoaXMuZW50cmllc19ba2V5XS52YWx1ZV8gPSB2YWx1ZTtcbiAgfTtcbiAgLyoqXG4gICAqIEBwYXJhbSB7c3RyaW5nfSBrZXkgS2V5LlxuICAgKiBAcGFyYW0ge1R9IHZhbHVlIFZhbHVlLlxuICAgKi9cblxuXG4gIExSVUNhY2hlLnByb3RvdHlwZS5zZXQgPSBmdW5jdGlvbiAoa2V5LCB2YWx1ZSkge1xuICAgIGFzc2VydCghKGtleSBpbiB0aGlzLmVudHJpZXNfKSwgMTYpOyAvLyBUcmllZCB0byBzZXQgYSB2YWx1ZSBmb3IgYSBrZXkgdGhhdCBpcyB1c2VkIGFscmVhZHlcblxuICAgIHZhciBlbnRyeSA9IHtcbiAgICAgIGtleV86IGtleSxcbiAgICAgIG5ld2VyOiBudWxsLFxuICAgICAgb2xkZXI6IHRoaXMubmV3ZXN0XyxcbiAgICAgIHZhbHVlXzogdmFsdWVcbiAgICB9O1xuXG4gICAgaWYgKCF0aGlzLm5ld2VzdF8pIHtcbiAgICAgIHRoaXMub2xkZXN0XyA9IGVudHJ5O1xuICAgIH0gZWxzZSB7XG4gICAgICB0aGlzLm5ld2VzdF8ubmV3ZXIgPSBlbnRyeTtcbiAgICB9XG5cbiAgICB0aGlzLm5ld2VzdF8gPSBlbnRyeTtcbiAgICB0aGlzLmVudHJpZXNfW2tleV0gPSBlbnRyeTtcbiAgICArK3RoaXMuY291bnRfO1xuICB9O1xuICAvKipcbiAgICogU2V0IGEgbWF4aW11bSBudW1iZXIgb2YgZW50cmllcyBmb3IgdGhlIGNhY2hlLlxuICAgKiBAcGFyYW0ge251bWJlcn0gc2l6ZSBDYWNoZSBzaXplLlxuICAgKiBAYXBpXG4gICAqL1xuXG5cbiAgTFJVQ2FjaGUucHJvdG90eXBlLnNldFNpemUgPSBmdW5jdGlvbiAoc2l6ZSkge1xuICAgIHRoaXMuaGlnaFdhdGVyTWFyayA9IHNpemU7XG4gIH07XG5cbiAgcmV0dXJuIExSVUNhY2hlO1xufSgpO1xuXG5leHBvcnQgZGVmYXVsdCBMUlVDYWNoZTsiLCIvKipcbiAqIEBtb2R1bGUgb2wvdGlsZWNvb3JkXG4gKi9cblxuLyoqXG4gKiBBbiBhcnJheSBvZiB0aHJlZSBudW1iZXJzIHJlcHJlc2VudGluZyB0aGUgbG9jYXRpb24gb2YgYSB0aWxlIGluIGEgdGlsZVxuICogZ3JpZC4gVGhlIG9yZGVyIGlzIGB6YCAoem9vbSBsZXZlbCksIGB4YCAoY29sdW1uKSwgYW5kIGB5YCAocm93KS5cbiAqIEB0eXBlZGVmIHtBcnJheTxudW1iZXI+fSBUaWxlQ29vcmRcbiAqIEBhcGlcbiAqL1xuXG4vKipcbiAqIEBwYXJhbSB7bnVtYmVyfSB6IFouXG4gKiBAcGFyYW0ge251bWJlcn0geCBYLlxuICogQHBhcmFtIHtudW1iZXJ9IHkgWS5cbiAqIEBwYXJhbSB7VGlsZUNvb3JkPX0gb3B0X3RpbGVDb29yZCBUaWxlIGNvb3JkaW5hdGUuXG4gKiBAcmV0dXJuIHtUaWxlQ29vcmR9IFRpbGUgY29vcmRpbmF0ZS5cbiAqL1xuZXhwb3J0IGZ1bmN0aW9uIGNyZWF0ZU9yVXBkYXRlKHosIHgsIHksIG9wdF90aWxlQ29vcmQpIHtcbiAgaWYgKG9wdF90aWxlQ29vcmQgIT09IHVuZGVmaW5lZCkge1xuICAgIG9wdF90aWxlQ29vcmRbMF0gPSB6O1xuICAgIG9wdF90aWxlQ29vcmRbMV0gPSB4O1xuICAgIG9wdF90aWxlQ29vcmRbMl0gPSB5O1xuICAgIHJldHVybiBvcHRfdGlsZUNvb3JkO1xuICB9IGVsc2Uge1xuICAgIHJldHVybiBbeiwgeCwgeV07XG4gIH1cbn1cbi8qKlxuICogQHBhcmFtIHtudW1iZXJ9IHogWi5cbiAqIEBwYXJhbSB7bnVtYmVyfSB4IFguXG4gKiBAcGFyYW0ge251bWJlcn0geSBZLlxuICogQHJldHVybiB7c3RyaW5nfSBLZXkuXG4gKi9cblxuZXhwb3J0IGZ1bmN0aW9uIGdldEtleVpYWSh6LCB4LCB5KSB7XG4gIHJldHVybiB6ICsgJy8nICsgeCArICcvJyArIHk7XG59XG4vKipcbiAqIEdldCB0aGUga2V5IGZvciBhIHRpbGUgY29vcmQuXG4gKiBAcGFyYW0ge1RpbGVDb29yZH0gdGlsZUNvb3JkIFRoZSB0aWxlIGNvb3JkLlxuICogQHJldHVybiB7c3RyaW5nfSBLZXkuXG4gKi9cblxuZXhwb3J0IGZ1bmN0aW9uIGdldEtleSh0aWxlQ29vcmQpIHtcbiAgcmV0dXJuIGdldEtleVpYWSh0aWxlQ29vcmRbMF0sIHRpbGVDb29yZFsxXSwgdGlsZUNvb3JkWzJdKTtcbn1cbi8qKlxuICogR2V0IGEgdGlsZSBjb29yZCBnaXZlbiBhIGtleS5cbiAqIEBwYXJhbSB7c3RyaW5nfSBrZXkgVGhlIHRpbGUgY29vcmQga2V5LlxuICogQHJldHVybiB7VGlsZUNvb3JkfSBUaGUgdGlsZSBjb29yZC5cbiAqL1xuXG5leHBvcnQgZnVuY3Rpb24gZnJvbUtleShrZXkpIHtcbiAgcmV0dXJuIGtleS5zcGxpdCgnLycpLm1hcChOdW1iZXIpO1xufVxuLyoqXG4gKiBAcGFyYW0ge1RpbGVDb29yZH0gdGlsZUNvb3JkIFRpbGUgY29vcmQuXG4gKiBAcmV0dXJuIHtudW1iZXJ9IEhhc2guXG4gKi9cblxuZXhwb3J0IGZ1bmN0aW9uIGhhc2godGlsZUNvb3JkKSB7XG4gIHJldHVybiAodGlsZUNvb3JkWzFdIDw8IHRpbGVDb29yZFswXSkgKyB0aWxlQ29vcmRbMl07XG59XG4vKipcbiAqIEBwYXJhbSB7VGlsZUNvb3JkfSB0aWxlQ29vcmQgVGlsZSBjb29yZGluYXRlLlxuICogQHBhcmFtIHshaW1wb3J0KFwiLi90aWxlZ3JpZC9UaWxlR3JpZC5qc1wiKS5kZWZhdWx0fSB0aWxlR3JpZCBUaWxlIGdyaWQuXG4gKiBAcmV0dXJuIHtib29sZWFufSBUaWxlIGNvb3JkaW5hdGUgaXMgd2l0aGluIGV4dGVudCBhbmQgem9vbSBsZXZlbCByYW5nZS5cbiAqL1xuXG5leHBvcnQgZnVuY3Rpb24gd2l0aGluRXh0ZW50QW5kWih0aWxlQ29vcmQsIHRpbGVHcmlkKSB7XG4gIHZhciB6ID0gdGlsZUNvb3JkWzBdO1xuICB2YXIgeCA9IHRpbGVDb29yZFsxXTtcbiAgdmFyIHkgPSB0aWxlQ29vcmRbMl07XG5cbiAgaWYgKHRpbGVHcmlkLmdldE1pblpvb20oKSA+IHogfHwgeiA+IHRpbGVHcmlkLmdldE1heFpvb20oKSkge1xuICAgIHJldHVybiBmYWxzZTtcbiAgfVxuXG4gIHZhciB0aWxlUmFuZ2UgPSB0aWxlR3JpZC5nZXRGdWxsVGlsZVJhbmdlKHopO1xuXG4gIGlmICghdGlsZVJhbmdlKSB7XG4gICAgcmV0dXJuIHRydWU7XG4gIH0gZWxzZSB7XG4gICAgcmV0dXJuIHRpbGVSYW5nZS5jb250YWluc1hZKHgsIHkpO1xuICB9XG59IiwidmFyIF9fZXh0ZW5kcyA9IHRoaXMgJiYgdGhpcy5fX2V4dGVuZHMgfHwgZnVuY3Rpb24gKCkge1xuICB2YXIgX2V4dGVuZFN0YXRpY3MgPSBmdW5jdGlvbiBleHRlbmRTdGF0aWNzKGQsIGIpIHtcbiAgICBfZXh0ZW5kU3RhdGljcyA9IE9iamVjdC5zZXRQcm90b3R5cGVPZiB8fCB7XG4gICAgICBfX3Byb3RvX186IFtdXG4gICAgfSBpbnN0YW5jZW9mIEFycmF5ICYmIGZ1bmN0aW9uIChkLCBiKSB7XG4gICAgICBkLl9fcHJvdG9fXyA9IGI7XG4gICAgfSB8fCBmdW5jdGlvbiAoZCwgYikge1xuICAgICAgZm9yICh2YXIgcCBpbiBiKSB7XG4gICAgICAgIGlmIChPYmplY3QucHJvdG90eXBlLmhhc093blByb3BlcnR5LmNhbGwoYiwgcCkpIGRbcF0gPSBiW3BdO1xuICAgICAgfVxuICAgIH07XG5cbiAgICByZXR1cm4gX2V4dGVuZFN0YXRpY3MoZCwgYik7XG4gIH07XG5cbiAgcmV0dXJuIGZ1bmN0aW9uIChkLCBiKSB7XG4gICAgX2V4dGVuZFN0YXRpY3MoZCwgYik7XG5cbiAgICBmdW5jdGlvbiBfXygpIHtcbiAgICAgIHRoaXMuY29uc3RydWN0b3IgPSBkO1xuICAgIH1cblxuICAgIGQucHJvdG90eXBlID0gYiA9PT0gbnVsbCA/IE9iamVjdC5jcmVhdGUoYikgOiAoX18ucHJvdG90eXBlID0gYi5wcm90b3R5cGUsIG5ldyBfXygpKTtcbiAgfTtcbn0oKTtcbi8qKlxuICogQG1vZHVsZSBvbC9UaWxlQ2FjaGVcbiAqL1xuXG5cbmltcG9ydCBMUlVDYWNoZSBmcm9tICcuL3N0cnVjdHMvTFJVQ2FjaGUuanMnO1xuaW1wb3J0IHsgZnJvbUtleSwgZ2V0S2V5IH0gZnJvbSAnLi90aWxlY29vcmQuanMnO1xuXG52YXIgVGlsZUNhY2hlID1cbi8qKiBAY2xhc3MgKi9cbmZ1bmN0aW9uIChfc3VwZXIpIHtcbiAgX19leHRlbmRzKFRpbGVDYWNoZSwgX3N1cGVyKTtcblxuICBmdW5jdGlvbiBUaWxlQ2FjaGUoKSB7XG4gICAgcmV0dXJuIF9zdXBlciAhPT0gbnVsbCAmJiBfc3VwZXIuYXBwbHkodGhpcywgYXJndW1lbnRzKSB8fCB0aGlzO1xuICB9XG4gIC8qKlxuICAgKiBAcGFyYW0geyFPYmplY3Q8c3RyaW5nLCBib29sZWFuPn0gdXNlZFRpbGVzIFVzZWQgdGlsZXMuXG4gICAqL1xuXG5cbiAgVGlsZUNhY2hlLnByb3RvdHlwZS5leHBpcmVDYWNoZSA9IGZ1bmN0aW9uICh1c2VkVGlsZXMpIHtcbiAgICB3aGlsZSAodGhpcy5jYW5FeHBpcmVDYWNoZSgpKSB7XG4gICAgICB2YXIgdGlsZSA9IHRoaXMucGVla0xhc3QoKTtcblxuICAgICAgaWYgKHRpbGUuZ2V0S2V5KCkgaW4gdXNlZFRpbGVzKSB7XG4gICAgICAgIGJyZWFrO1xuICAgICAgfSBlbHNlIHtcbiAgICAgICAgdGhpcy5wb3AoKS5yZWxlYXNlKCk7XG4gICAgICB9XG4gICAgfVxuICB9O1xuICAvKipcbiAgICogUHJ1bmUgYWxsIHRpbGVzIGZyb20gdGhlIGNhY2hlIHRoYXQgZG9uJ3QgaGF2ZSB0aGUgc2FtZSB6IGFzIHRoZSBuZXdlc3QgdGlsZS5cbiAgICovXG5cblxuICBUaWxlQ2FjaGUucHJvdG90eXBlLnBydW5lRXhjZXB0TmV3ZXN0WiA9IGZ1bmN0aW9uICgpIHtcbiAgICBpZiAodGhpcy5nZXRDb3VudCgpID09PSAwKSB7XG4gICAgICByZXR1cm47XG4gICAgfVxuXG4gICAgdmFyIGtleSA9IHRoaXMucGVla0ZpcnN0S2V5KCk7XG4gICAgdmFyIHRpbGVDb29yZCA9IGZyb21LZXkoa2V5KTtcbiAgICB2YXIgeiA9IHRpbGVDb29yZFswXTtcbiAgICB0aGlzLmZvckVhY2goZnVuY3Rpb24gKHRpbGUpIHtcbiAgICAgIGlmICh0aWxlLnRpbGVDb29yZFswXSAhPT0geikge1xuICAgICAgICB0aGlzLnJlbW92ZShnZXRLZXkodGlsZS50aWxlQ29vcmQpKTtcbiAgICAgICAgdGlsZS5yZWxlYXNlKCk7XG4gICAgICB9XG4gICAgfS5iaW5kKHRoaXMpKTtcbiAgfTtcblxuICByZXR1cm4gVGlsZUNhY2hlO1xufShMUlVDYWNoZSk7XG5cbmV4cG9ydCBkZWZhdWx0IFRpbGVDYWNoZTsiLCIvKipcbiAqIEBtb2R1bGUgb2wvc291cmNlL1RpbGVFdmVudFR5cGVcbiAqL1xuXG4vKipcbiAqIEBlbnVtIHtzdHJpbmd9XG4gKi9cbmV4cG9ydCBkZWZhdWx0IHtcbiAgLyoqXG4gICAqIFRyaWdnZXJlZCB3aGVuIGEgdGlsZSBzdGFydHMgbG9hZGluZy5cbiAgICogQGV2ZW50IG1vZHVsZTpvbC9zb3VyY2UvVGlsZS5UaWxlU291cmNlRXZlbnQjdGlsZWxvYWRzdGFydFxuICAgKiBAYXBpXG4gICAqL1xuICBUSUxFTE9BRFNUQVJUOiAndGlsZWxvYWRzdGFydCcsXG5cbiAgLyoqXG4gICAqIFRyaWdnZXJlZCB3aGVuIGEgdGlsZSBmaW5pc2hlcyBsb2FkaW5nLCBlaXRoZXIgd2hlbiBpdHMgZGF0YSBpcyBsb2FkZWQsXG4gICAqIG9yIHdoZW4gbG9hZGluZyB3YXMgYWJvcnRlZCBiZWNhdXNlIHRoZSB0aWxlIGlzIG5vIGxvbmdlciBuZWVkZWQuXG4gICAqIEBldmVudCBtb2R1bGU6b2wvc291cmNlL1RpbGUuVGlsZVNvdXJjZUV2ZW50I3RpbGVsb2FkZW5kXG4gICAqIEBhcGlcbiAgICovXG4gIFRJTEVMT0FERU5EOiAndGlsZWxvYWRlbmQnLFxuXG4gIC8qKlxuICAgKiBUcmlnZ2VyZWQgaWYgdGlsZSBsb2FkaW5nIHJlc3VsdHMgaW4gYW4gZXJyb3IuXG4gICAqIEBldmVudCBtb2R1bGU6b2wvc291cmNlL1RpbGUuVGlsZVNvdXJjZUV2ZW50I3RpbGVsb2FkZXJyb3JcbiAgICogQGFwaVxuICAgKi9cbiAgVElMRUxPQURFUlJPUjogJ3RpbGVsb2FkZXJyb3InXG59OyIsInZhciBfX2V4dGVuZHMgPSB0aGlzICYmIHRoaXMuX19leHRlbmRzIHx8IGZ1bmN0aW9uICgpIHtcbiAgdmFyIF9leHRlbmRTdGF0aWNzID0gZnVuY3Rpb24gZXh0ZW5kU3RhdGljcyhkLCBiKSB7XG4gICAgX2V4dGVuZFN0YXRpY3MgPSBPYmplY3Quc2V0UHJvdG90eXBlT2YgfHwge1xuICAgICAgX19wcm90b19fOiBbXVxuICAgIH0gaW5zdGFuY2VvZiBBcnJheSAmJiBmdW5jdGlvbiAoZCwgYikge1xuICAgICAgZC5fX3Byb3RvX18gPSBiO1xuICAgIH0gfHwgZnVuY3Rpb24gKGQsIGIpIHtcbiAgICAgIGZvciAodmFyIHAgaW4gYikge1xuICAgICAgICBpZiAoT2JqZWN0LnByb3RvdHlwZS5oYXNPd25Qcm9wZXJ0eS5jYWxsKGIsIHApKSBkW3BdID0gYltwXTtcbiAgICAgIH1cbiAgICB9O1xuXG4gICAgcmV0dXJuIF9leHRlbmRTdGF0aWNzKGQsIGIpO1xuICB9O1xuXG4gIHJldHVybiBmdW5jdGlvbiAoZCwgYikge1xuICAgIF9leHRlbmRTdGF0aWNzKGQsIGIpO1xuXG4gICAgZnVuY3Rpb24gX18oKSB7XG4gICAgICB0aGlzLmNvbnN0cnVjdG9yID0gZDtcbiAgICB9XG5cbiAgICBkLnByb3RvdHlwZSA9IGIgPT09IG51bGwgPyBPYmplY3QuY3JlYXRlKGIpIDogKF9fLnByb3RvdHlwZSA9IGIucHJvdG90eXBlLCBuZXcgX18oKSk7XG4gIH07XG59KCk7XG4vKipcbiAqIEBtb2R1bGUgb2wvc291cmNlL1NvdXJjZVxuICovXG5cblxuaW1wb3J0IEJhc2VPYmplY3QgZnJvbSAnLi4vT2JqZWN0LmpzJztcbmltcG9ydCBTb3VyY2VTdGF0ZSBmcm9tICcuL1N0YXRlLmpzJztcbmltcG9ydCB7IGFic3RyYWN0IH0gZnJvbSAnLi4vdXRpbC5qcyc7XG5pbXBvcnQgeyBnZXQgYXMgZ2V0UHJvamVjdGlvbiB9IGZyb20gJy4uL3Byb2ouanMnO1xuLyoqXG4gKiBBIGZ1bmN0aW9uIHRoYXQgcmV0dXJucyBhIHN0cmluZyBvciBhbiBhcnJheSBvZiBzdHJpbmdzIHJlcHJlc2VudGluZyBzb3VyY2VcbiAqIGF0dHJpYnV0aW9ucy5cbiAqXG4gKiBAdHlwZWRlZiB7ZnVuY3Rpb24oaW1wb3J0KFwiLi4vUGx1Z2dhYmxlTWFwLmpzXCIpLkZyYW1lU3RhdGUpOiAoc3RyaW5nfEFycmF5PHN0cmluZz4pfSBBdHRyaWJ1dGlvblxuICovXG5cbi8qKlxuICogQSB0eXBlIHRoYXQgY2FuIGJlIHVzZWQgdG8gcHJvdmlkZSBhdHRyaWJ1dGlvbiBpbmZvcm1hdGlvbiBmb3IgZGF0YSBzb3VyY2VzLlxuICpcbiAqIEl0IHJlcHJlc2VudHMgZWl0aGVyXG4gKiAqIGEgc2ltcGxlIHN0cmluZyAoZS5nLiBgJ8KpIEFjbWUgSW5jLidgKVxuICogKiBhbiBhcnJheSBvZiBzaW1wbGUgc3RyaW5ncyAoZS5nLiBgWyfCqSBBY21lIEluYy4nLCAnwqkgQmFjbWUgSW5jLiddYClcbiAqICogYSBmdW5jdGlvbiB0aGF0IHJldHVybnMgYSBzdHJpbmcgb3IgYXJyYXkgb2Ygc3RyaW5ncyAoe0BsaW5rIG1vZHVsZTpvbC9zb3VyY2UvU291cmNlfkF0dHJpYnV0aW9ufSlcbiAqXG4gKiBAdHlwZWRlZiB7c3RyaW5nfEFycmF5PHN0cmluZz58QXR0cmlidXRpb259IEF0dHJpYnV0aW9uTGlrZVxuICovXG5cbi8qKlxuICogQHR5cGVkZWYge09iamVjdH0gT3B0aW9uc1xuICogQHByb3BlcnR5IHtBdHRyaWJ1dGlvbkxpa2V9IFthdHRyaWJ1dGlvbnNdXG4gKiBAcHJvcGVydHkge2Jvb2xlYW59IFthdHRyaWJ1dGlvbnNDb2xsYXBzaWJsZT10cnVlXSBBdHRyaWJ1dGlvbnMgYXJlIGNvbGxhcHNpYmxlLlxuICogQHByb3BlcnR5IHtpbXBvcnQoXCIuLi9wcm9qLmpzXCIpLlByb2plY3Rpb25MaWtlfSBbcHJvamVjdGlvbl0gUHJvamVjdGlvbi4gRGVmYXVsdCBpcyB0aGUgdmlldyBwcm9qZWN0aW9uLlxuICogQHByb3BlcnR5IHtpbXBvcnQoXCIuL1N0YXRlLmpzXCIpLmRlZmF1bHR9IFtzdGF0ZT0ncmVhZHknXVxuICogQHByb3BlcnR5IHtib29sZWFufSBbd3JhcFg9ZmFsc2VdXG4gKi9cblxuLyoqXG4gKiBAY2xhc3NkZXNjXG4gKiBBYnN0cmFjdCBiYXNlIGNsYXNzOyBub3JtYWxseSBvbmx5IHVzZWQgZm9yIGNyZWF0aW5nIHN1YmNsYXNzZXMgYW5kIG5vdFxuICogaW5zdGFudGlhdGVkIGluIGFwcHMuXG4gKiBCYXNlIGNsYXNzIGZvciB7QGxpbmsgbW9kdWxlOm9sL2xheWVyL0xheWVyfkxheWVyfSBzb3VyY2VzLlxuICpcbiAqIEEgZ2VuZXJpYyBgY2hhbmdlYCBldmVudCBpcyB0cmlnZ2VyZWQgd2hlbiB0aGUgc3RhdGUgb2YgdGhlIHNvdXJjZSBjaGFuZ2VzLlxuICogQGFic3RyYWN0XG4gKiBAYXBpXG4gKi9cblxudmFyIFNvdXJjZSA9XG4vKiogQGNsYXNzICovXG5mdW5jdGlvbiAoX3N1cGVyKSB7XG4gIF9fZXh0ZW5kcyhTb3VyY2UsIF9zdXBlcik7XG4gIC8qKlxuICAgKiBAcGFyYW0ge09wdGlvbnN9IG9wdGlvbnMgU291cmNlIG9wdGlvbnMuXG4gICAqL1xuXG5cbiAgZnVuY3Rpb24gU291cmNlKG9wdGlvbnMpIHtcbiAgICB2YXIgX3RoaXMgPSBfc3VwZXIuY2FsbCh0aGlzKSB8fCB0aGlzO1xuICAgIC8qKlxuICAgICAqIEBwcml2YXRlXG4gICAgICogQHR5cGUge2ltcG9ydChcIi4uL3Byb2ovUHJvamVjdGlvbi5qc1wiKS5kZWZhdWx0fVxuICAgICAqL1xuXG5cbiAgICBfdGhpcy5wcm9qZWN0aW9uXyA9IGdldFByb2plY3Rpb24ob3B0aW9ucy5wcm9qZWN0aW9uKTtcbiAgICAvKipcbiAgICAgKiBAcHJpdmF0ZVxuICAgICAqIEB0eXBlIHs/QXR0cmlidXRpb259XG4gICAgICovXG5cbiAgICBfdGhpcy5hdHRyaWJ1dGlvbnNfID0gYWRhcHRBdHRyaWJ1dGlvbnMob3B0aW9ucy5hdHRyaWJ1dGlvbnMpO1xuICAgIC8qKlxuICAgICAqIEBwcml2YXRlXG4gICAgICogQHR5cGUge2Jvb2xlYW59XG4gICAgICovXG5cbiAgICBfdGhpcy5hdHRyaWJ1dGlvbnNDb2xsYXBzaWJsZV8gPSBvcHRpb25zLmF0dHJpYnV0aW9uc0NvbGxhcHNpYmxlICE9PSB1bmRlZmluZWQgPyBvcHRpb25zLmF0dHJpYnV0aW9uc0NvbGxhcHNpYmxlIDogdHJ1ZTtcbiAgICAvKipcbiAgICAgKiBUaGlzIHNvdXJjZSBpcyBjdXJyZW50bHkgbG9hZGluZyBkYXRhLiBTb3VyY2VzIHRoYXQgZGVmZXIgbG9hZGluZyB0byB0aGVcbiAgICAgKiBtYXAncyB0aWxlIHF1ZXVlIG5ldmVyIHNldCB0aGlzIHRvIGB0cnVlYC5cbiAgICAgKiBAdHlwZSB7Ym9vbGVhbn1cbiAgICAgKi9cblxuICAgIF90aGlzLmxvYWRpbmcgPSBmYWxzZTtcbiAgICAvKipcbiAgICAgKiBAcHJpdmF0ZVxuICAgICAqIEB0eXBlIHtpbXBvcnQoXCIuL1N0YXRlLmpzXCIpLmRlZmF1bHR9XG4gICAgICovXG5cbiAgICBfdGhpcy5zdGF0ZV8gPSBvcHRpb25zLnN0YXRlICE9PSB1bmRlZmluZWQgPyBvcHRpb25zLnN0YXRlIDogU291cmNlU3RhdGUuUkVBRFk7XG4gICAgLyoqXG4gICAgICogQHByaXZhdGVcbiAgICAgKiBAdHlwZSB7Ym9vbGVhbn1cbiAgICAgKi9cblxuICAgIF90aGlzLndyYXBYXyA9IG9wdGlvbnMud3JhcFggIT09IHVuZGVmaW5lZCA/IG9wdGlvbnMud3JhcFggOiBmYWxzZTtcbiAgICByZXR1cm4gX3RoaXM7XG4gIH1cbiAgLyoqXG4gICAqIEdldCB0aGUgYXR0cmlidXRpb24gZnVuY3Rpb24gZm9yIHRoZSBzb3VyY2UuXG4gICAqIEByZXR1cm4gez9BdHRyaWJ1dGlvbn0gQXR0cmlidXRpb24gZnVuY3Rpb24uXG4gICAqL1xuXG5cbiAgU291cmNlLnByb3RvdHlwZS5nZXRBdHRyaWJ1dGlvbnMgPSBmdW5jdGlvbiAoKSB7XG4gICAgcmV0dXJuIHRoaXMuYXR0cmlidXRpb25zXztcbiAgfTtcbiAgLyoqXG4gICAqIEByZXR1cm4ge2Jvb2xlYW59IEF0dHJpYnV0aW9ucyBhcmUgY29sbGFwc2libGUuXG4gICAqL1xuXG5cbiAgU291cmNlLnByb3RvdHlwZS5nZXRBdHRyaWJ1dGlvbnNDb2xsYXBzaWJsZSA9IGZ1bmN0aW9uICgpIHtcbiAgICByZXR1cm4gdGhpcy5hdHRyaWJ1dGlvbnNDb2xsYXBzaWJsZV87XG4gIH07XG4gIC8qKlxuICAgKiBHZXQgdGhlIHByb2plY3Rpb24gb2YgdGhlIHNvdXJjZS5cbiAgICogQHJldHVybiB7aW1wb3J0KFwiLi4vcHJvai9Qcm9qZWN0aW9uLmpzXCIpLmRlZmF1bHR9IFByb2plY3Rpb24uXG4gICAqIEBhcGlcbiAgICovXG5cblxuICBTb3VyY2UucHJvdG90eXBlLmdldFByb2plY3Rpb24gPSBmdW5jdGlvbiAoKSB7XG4gICAgcmV0dXJuIHRoaXMucHJvamVjdGlvbl87XG4gIH07XG4gIC8qKlxuICAgKiBAYWJzdHJhY3RcbiAgICogQHJldHVybiB7QXJyYXk8bnVtYmVyPnx1bmRlZmluZWR9IFJlc29sdXRpb25zLlxuICAgKi9cblxuXG4gIFNvdXJjZS5wcm90b3R5cGUuZ2V0UmVzb2x1dGlvbnMgPSBmdW5jdGlvbiAoKSB7XG4gICAgcmV0dXJuIGFic3RyYWN0KCk7XG4gIH07XG4gIC8qKlxuICAgKiBHZXQgdGhlIHN0YXRlIG9mIHRoZSBzb3VyY2UsIHNlZSB7QGxpbmsgbW9kdWxlOm9sL3NvdXJjZS9TdGF0ZX5TdGF0ZX0gZm9yIHBvc3NpYmxlIHN0YXRlcy5cbiAgICogQHJldHVybiB7aW1wb3J0KFwiLi9TdGF0ZS5qc1wiKS5kZWZhdWx0fSBTdGF0ZS5cbiAgICogQGFwaVxuICAgKi9cblxuXG4gIFNvdXJjZS5wcm90b3R5cGUuZ2V0U3RhdGUgPSBmdW5jdGlvbiAoKSB7XG4gICAgcmV0dXJuIHRoaXMuc3RhdGVfO1xuICB9O1xuICAvKipcbiAgICogQHJldHVybiB7Ym9vbGVhbnx1bmRlZmluZWR9IFdyYXAgWC5cbiAgICovXG5cblxuICBTb3VyY2UucHJvdG90eXBlLmdldFdyYXBYID0gZnVuY3Rpb24gKCkge1xuICAgIHJldHVybiB0aGlzLndyYXBYXztcbiAgfTtcbiAgLyoqXG4gICAqIEByZXR1cm4ge09iamVjdHx1bmRlZmluZWR9IENvbnRleHQgb3B0aW9ucy5cbiAgICovXG5cblxuICBTb3VyY2UucHJvdG90eXBlLmdldENvbnRleHRPcHRpb25zID0gZnVuY3Rpb24gKCkge1xuICAgIHJldHVybiB1bmRlZmluZWQ7XG4gIH07XG4gIC8qKlxuICAgKiBSZWZyZXNoZXMgdGhlIHNvdXJjZS4gVGhlIHNvdXJjZSB3aWxsIGJlIGNsZWFyZWQsIGFuZCBkYXRhIGZyb20gdGhlIHNlcnZlciB3aWxsIGJlIHJlbG9hZGVkLlxuICAgKiBAYXBpXG4gICAqL1xuXG5cbiAgU291cmNlLnByb3RvdHlwZS5yZWZyZXNoID0gZnVuY3Rpb24gKCkge1xuICAgIHRoaXMuY2hhbmdlZCgpO1xuICB9O1xuICAvKipcbiAgICogU2V0IHRoZSBhdHRyaWJ1dGlvbnMgb2YgdGhlIHNvdXJjZS5cbiAgICogQHBhcmFtIHtBdHRyaWJ1dGlvbkxpa2V8dW5kZWZpbmVkfSBhdHRyaWJ1dGlvbnMgQXR0cmlidXRpb25zLlxuICAgKiAgICAgQ2FuIGJlIHBhc3NlZCBhcyBgc3RyaW5nYCwgYEFycmF5PHN0cmluZz5gLCB7QGxpbmsgbW9kdWxlOm9sL3NvdXJjZS9Tb3VyY2V+QXR0cmlidXRpb259LFxuICAgKiAgICAgb3IgYHVuZGVmaW5lZGAuXG4gICAqIEBhcGlcbiAgICovXG5cblxuICBTb3VyY2UucHJvdG90eXBlLnNldEF0dHJpYnV0aW9ucyA9IGZ1bmN0aW9uIChhdHRyaWJ1dGlvbnMpIHtcbiAgICB0aGlzLmF0dHJpYnV0aW9uc18gPSBhZGFwdEF0dHJpYnV0aW9ucyhhdHRyaWJ1dGlvbnMpO1xuICAgIHRoaXMuY2hhbmdlZCgpO1xuICB9O1xuICAvKipcbiAgICogU2V0IHRoZSBzdGF0ZSBvZiB0aGUgc291cmNlLlxuICAgKiBAcGFyYW0ge2ltcG9ydChcIi4vU3RhdGUuanNcIikuZGVmYXVsdH0gc3RhdGUgU3RhdGUuXG4gICAqL1xuXG5cbiAgU291cmNlLnByb3RvdHlwZS5zZXRTdGF0ZSA9IGZ1bmN0aW9uIChzdGF0ZSkge1xuICAgIHRoaXMuc3RhdGVfID0gc3RhdGU7XG4gICAgdGhpcy5jaGFuZ2VkKCk7XG4gIH07XG5cbiAgcmV0dXJuIFNvdXJjZTtcbn0oQmFzZU9iamVjdCk7XG4vKipcbiAqIFR1cm5zIHRoZSBhdHRyaWJ1dGlvbnMgb3B0aW9uIGludG8gYW4gYXR0cmlidXRpb25zIGZ1bmN0aW9uLlxuICogQHBhcmFtIHtBdHRyaWJ1dGlvbkxpa2V8dW5kZWZpbmVkfSBhdHRyaWJ1dGlvbkxpa2UgVGhlIGF0dHJpYnV0aW9uIG9wdGlvbi5cbiAqIEByZXR1cm4gez9BdHRyaWJ1dGlvbn0gQW4gYXR0cmlidXRpb24gZnVuY3Rpb24gKG9yIG51bGwpLlxuICovXG5cblxuZnVuY3Rpb24gYWRhcHRBdHRyaWJ1dGlvbnMoYXR0cmlidXRpb25MaWtlKSB7XG4gIGlmICghYXR0cmlidXRpb25MaWtlKSB7XG4gICAgcmV0dXJuIG51bGw7XG4gIH1cblxuICBpZiAoQXJyYXkuaXNBcnJheShhdHRyaWJ1dGlvbkxpa2UpKSB7XG4gICAgcmV0dXJuIGZ1bmN0aW9uIChmcmFtZVN0YXRlKSB7XG4gICAgICByZXR1cm4gYXR0cmlidXRpb25MaWtlO1xuICAgIH07XG4gIH1cblxuICBpZiAodHlwZW9mIGF0dHJpYnV0aW9uTGlrZSA9PT0gJ2Z1bmN0aW9uJykge1xuICAgIHJldHVybiBhdHRyaWJ1dGlvbkxpa2U7XG4gIH1cblxuICByZXR1cm4gZnVuY3Rpb24gKGZyYW1lU3RhdGUpIHtcbiAgICByZXR1cm4gW2F0dHJpYnV0aW9uTGlrZV07XG4gIH07XG59XG5cbmV4cG9ydCBkZWZhdWx0IFNvdXJjZTsiLCIvKipcbiAqIEBtb2R1bGUgb2wvdGlsZWdyaWQvVGlsZUdyaWRcbiAqL1xuaW1wb3J0IFRpbGVSYW5nZSwgeyBjcmVhdGVPclVwZGF0ZSBhcyBjcmVhdGVPclVwZGF0ZVRpbGVSYW5nZSB9IGZyb20gJy4uL1RpbGVSYW5nZS5qcyc7XG5pbXBvcnQgeyBERUZBVUxUX1RJTEVfU0laRSB9IGZyb20gJy4vY29tbW9uLmpzJztcbmltcG9ydCB7IGFzc2VydCB9IGZyb20gJy4uL2Fzc2VydHMuanMnO1xuaW1wb3J0IHsgY2xhbXAgfSBmcm9tICcuLi9tYXRoLmpzJztcbmltcG9ydCB7IGNyZWF0ZU9yVXBkYXRlLCBnZXRUb3BMZWZ0IH0gZnJvbSAnLi4vZXh0ZW50LmpzJztcbmltcG9ydCB7IGNyZWF0ZU9yVXBkYXRlIGFzIGNyZWF0ZU9yVXBkYXRlVGlsZUNvb3JkIH0gZnJvbSAnLi4vdGlsZWNvb3JkLmpzJztcbmltcG9ydCB7IGlzU29ydGVkLCBsaW5lYXJGaW5kTmVhcmVzdCB9IGZyb20gJy4uL2FycmF5LmpzJztcbmltcG9ydCB7IHRvU2l6ZSB9IGZyb20gJy4uL3NpemUuanMnO1xuLyoqXG4gKiBAcHJpdmF0ZVxuICogQHR5cGUge2ltcG9ydChcIi4uL3RpbGVjb29yZC5qc1wiKS5UaWxlQ29vcmR9XG4gKi9cblxudmFyIHRtcFRpbGVDb29yZCA9IFswLCAwLCAwXTtcbi8qKlxuICogQHR5cGVkZWYge09iamVjdH0gT3B0aW9uc1xuICogQHByb3BlcnR5IHtpbXBvcnQoXCIuLi9leHRlbnQuanNcIikuRXh0ZW50fSBbZXh0ZW50XSBFeHRlbnQgZm9yIHRoZSB0aWxlIGdyaWQuIE5vIHRpbGVzIG91dHNpZGUgdGhpc1xuICogZXh0ZW50IHdpbGwgYmUgcmVxdWVzdGVkIGJ5IHtAbGluayBtb2R1bGU6b2wvc291cmNlL1RpbGV9IHNvdXJjZXMuIFdoZW4gbm8gYG9yaWdpbmAgb3JcbiAqIGBvcmlnaW5zYCBhcmUgY29uZmlndXJlZCwgdGhlIGBvcmlnaW5gIHdpbGwgYmUgc2V0IHRvIHRoZSB0b3AtbGVmdCBjb3JuZXIgb2YgdGhlIGV4dGVudC5cbiAqIEBwcm9wZXJ0eSB7bnVtYmVyfSBbbWluWm9vbT0wXSBNaW5pbXVtIHpvb20uXG4gKiBAcHJvcGVydHkge2ltcG9ydChcIi4uL2Nvb3JkaW5hdGUuanNcIikuQ29vcmRpbmF0ZX0gW29yaWdpbl0gVGhlIHRpbGUgZ3JpZCBvcmlnaW4sIGkuZS4gd2hlcmUgdGhlIGB4YFxuICogYW5kIGB5YCBheGVzIG1lZXQgKGBbeiwgMCwgMF1gKS4gVGlsZSBjb29yZGluYXRlcyBpbmNyZWFzZSBsZWZ0IHRvIHJpZ2h0IGFuZCBkb3dud2FyZHMuIElmIG5vdFxuICogc3BlY2lmaWVkLCBgZXh0ZW50YCBvciBgb3JpZ2luc2AgbXVzdCBiZSBwcm92aWRlZC5cbiAqIEBwcm9wZXJ0eSB7QXJyYXk8aW1wb3J0KFwiLi4vY29vcmRpbmF0ZS5qc1wiKS5Db29yZGluYXRlPn0gW29yaWdpbnNdIFRpbGUgZ3JpZCBvcmlnaW5zLCBpLmUuIHdoZXJlXG4gKiB0aGUgYHhgIGFuZCBgeWAgYXhlcyBtZWV0IChgW3osIDAsIDBdYCksIGZvciBlYWNoIHpvb20gbGV2ZWwuIElmIGdpdmVuLCB0aGUgYXJyYXkgbGVuZ3RoXG4gKiBzaG91bGQgbWF0Y2ggdGhlIGxlbmd0aCBvZiB0aGUgYHJlc29sdXRpb25zYCBhcnJheSwgaS5lLiBlYWNoIHJlc29sdXRpb24gY2FuIGhhdmUgYSBkaWZmZXJlbnRcbiAqIG9yaWdpbi4gVGlsZSBjb29yZGluYXRlcyBpbmNyZWFzZSBsZWZ0IHRvIHJpZ2h0IGFuZCBkb3dud2FyZHMuIElmIG5vdCBzcGVjaWZpZWQsIGBleHRlbnRgIG9yXG4gKiBgb3JpZ2luYCBtdXN0IGJlIHByb3ZpZGVkLlxuICogQHByb3BlcnR5IHshQXJyYXk8bnVtYmVyPn0gcmVzb2x1dGlvbnMgUmVzb2x1dGlvbnMuIFRoZSBhcnJheSBpbmRleCBvZiBlYWNoIHJlc29sdXRpb24gbmVlZHNcbiAqIHRvIG1hdGNoIHRoZSB6b29tIGxldmVsLiBUaGlzIG1lYW5zIHRoYXQgZXZlbiBpZiBhIGBtaW5ab29tYCBpcyBjb25maWd1cmVkLCB0aGUgcmVzb2x1dGlvbnNcbiAqIGFycmF5IHdpbGwgaGF2ZSBhIGxlbmd0aCBvZiBgbWF4Wm9vbSArIDFgLlxuICogQHByb3BlcnR5IHtBcnJheTxpbXBvcnQoXCIuLi9zaXplLmpzXCIpLlNpemU+fSBbc2l6ZXNdIE51bWJlciBvZiB0aWxlIHJvd3MgYW5kIGNvbHVtbnNcbiAqIG9mIHRoZSBncmlkIGZvciBlYWNoIHpvb20gbGV2ZWwuIElmIHNwZWNpZmllZCB0aGUgdmFsdWVzXG4gKiBkZWZpbmUgZWFjaCB6b29tIGxldmVsJ3MgZXh0ZW50IHRvZ2V0aGVyIHdpdGggdGhlIGBvcmlnaW5gIG9yIGBvcmlnaW5zYC5cbiAqIEEgZ3JpZCBgZXh0ZW50YCBjYW4gYmUgY29uZmlndXJlZCBpbiBhZGRpdGlvbiwgYW5kIHdpbGwgZnVydGhlciBsaW1pdCB0aGUgZXh0ZW50XG4gKiBmb3Igd2hpY2ggdGlsZSByZXF1ZXN0cyBhcmUgbWFkZSBieSBzb3VyY2VzLiBJZiB0aGUgYm90dG9tLWxlZnQgY29ybmVyIG9mXG4gKiBhbiBleHRlbnQgaXMgdXNlZCBhcyBgb3JpZ2luYCBvciBgb3JpZ2luc2AsIHRoZW4gdGhlIGB5YCB2YWx1ZSBtdXN0IGJlXG4gKiBuZWdhdGl2ZSBiZWNhdXNlIE9wZW5MYXllcnMgdGlsZSBjb29yZGluYXRlcyB1c2UgdGhlIHRvcCBsZWZ0IGFzIHRoZSBvcmlnaW4uXG4gKiBAcHJvcGVydHkge251bWJlcnxpbXBvcnQoXCIuLi9zaXplLmpzXCIpLlNpemV9IFt0aWxlU2l6ZV0gVGlsZSBzaXplLlxuICogRGVmYXVsdCBpcyBgWzI1NiwgMjU2XWAuXG4gKiBAcHJvcGVydHkge0FycmF5PGltcG9ydChcIi4uL3NpemUuanNcIikuU2l6ZT59IFt0aWxlU2l6ZXNdIFRpbGUgc2l6ZXMuIElmIGdpdmVuLCB0aGUgYXJyYXkgbGVuZ3RoXG4gKiBzaG91bGQgbWF0Y2ggdGhlIGxlbmd0aCBvZiB0aGUgYHJlc29sdXRpb25zYCBhcnJheSwgaS5lLiBlYWNoIHJlc29sdXRpb24gY2FuIGhhdmUgYSBkaWZmZXJlbnRcbiAqIHRpbGUgc2l6ZS5cbiAqL1xuXG4vKipcbiAqIEBjbGFzc2Rlc2NcbiAqIEJhc2UgY2xhc3MgZm9yIHNldHRpbmcgdGhlIGdyaWQgcGF0dGVybiBmb3Igc291cmNlcyBhY2Nlc3NpbmcgdGlsZWQtaW1hZ2VcbiAqIHNlcnZlcnMuXG4gKiBAYXBpXG4gKi9cblxudmFyIFRpbGVHcmlkID1cbi8qKiBAY2xhc3MgKi9cbmZ1bmN0aW9uICgpIHtcbiAgLyoqXG4gICAqIEBwYXJhbSB7T3B0aW9uc30gb3B0aW9ucyBUaWxlIGdyaWQgb3B0aW9ucy5cbiAgICovXG4gIGZ1bmN0aW9uIFRpbGVHcmlkKG9wdGlvbnMpIHtcbiAgICAvKipcbiAgICAgKiBAcHJvdGVjdGVkXG4gICAgICogQHR5cGUge251bWJlcn1cbiAgICAgKi9cbiAgICB0aGlzLm1pblpvb20gPSBvcHRpb25zLm1pblpvb20gIT09IHVuZGVmaW5lZCA/IG9wdGlvbnMubWluWm9vbSA6IDA7XG4gICAgLyoqXG4gICAgICogQHByaXZhdGVcbiAgICAgKiBAdHlwZSB7IUFycmF5PG51bWJlcj59XG4gICAgICovXG5cbiAgICB0aGlzLnJlc29sdXRpb25zXyA9IG9wdGlvbnMucmVzb2x1dGlvbnM7XG4gICAgYXNzZXJ0KGlzU29ydGVkKHRoaXMucmVzb2x1dGlvbnNfLCBmdW5jdGlvbiAoYSwgYikge1xuICAgICAgcmV0dXJuIGIgLSBhO1xuICAgIH0sIHRydWUpLCAxNyk7IC8vIGByZXNvbHV0aW9uc2AgbXVzdCBiZSBzb3J0ZWQgaW4gZGVzY2VuZGluZyBvcmRlclxuICAgIC8vIGNoZWNrIGlmIHdlJ3ZlIGdvdCBhIGNvbnNpc3RlbnQgem9vbSBmYWN0b3IgYW5kIG9yaWdpblxuXG4gICAgdmFyIHpvb21GYWN0b3I7XG5cbiAgICBpZiAoIW9wdGlvbnMub3JpZ2lucykge1xuICAgICAgZm9yICh2YXIgaSA9IDAsIGlpID0gdGhpcy5yZXNvbHV0aW9uc18ubGVuZ3RoIC0gMTsgaSA8IGlpOyArK2kpIHtcbiAgICAgICAgaWYgKCF6b29tRmFjdG9yKSB7XG4gICAgICAgICAgem9vbUZhY3RvciA9IHRoaXMucmVzb2x1dGlvbnNfW2ldIC8gdGhpcy5yZXNvbHV0aW9uc19baSArIDFdO1xuICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgIGlmICh0aGlzLnJlc29sdXRpb25zX1tpXSAvIHRoaXMucmVzb2x1dGlvbnNfW2kgKyAxXSAhPT0gem9vbUZhY3Rvcikge1xuICAgICAgICAgICAgem9vbUZhY3RvciA9IHVuZGVmaW5lZDtcbiAgICAgICAgICAgIGJyZWFrO1xuICAgICAgICAgIH1cbiAgICAgICAgfVxuICAgICAgfVxuICAgIH1cbiAgICAvKipcbiAgICAgKiBAcHJpdmF0ZVxuICAgICAqIEB0eXBlIHtudW1iZXJ8dW5kZWZpbmVkfVxuICAgICAqL1xuXG5cbiAgICB0aGlzLnpvb21GYWN0b3JfID0gem9vbUZhY3RvcjtcbiAgICAvKipcbiAgICAgKiBAcHJvdGVjdGVkXG4gICAgICogQHR5cGUge251bWJlcn1cbiAgICAgKi9cblxuICAgIHRoaXMubWF4Wm9vbSA9IHRoaXMucmVzb2x1dGlvbnNfLmxlbmd0aCAtIDE7XG4gICAgLyoqXG4gICAgICogQHByaXZhdGVcbiAgICAgKiBAdHlwZSB7aW1wb3J0KFwiLi4vY29vcmRpbmF0ZS5qc1wiKS5Db29yZGluYXRlfVxuICAgICAqL1xuXG4gICAgdGhpcy5vcmlnaW5fID0gb3B0aW9ucy5vcmlnaW4gIT09IHVuZGVmaW5lZCA/IG9wdGlvbnMub3JpZ2luIDogbnVsbDtcbiAgICAvKipcbiAgICAgKiBAcHJpdmF0ZVxuICAgICAqIEB0eXBlIHtBcnJheTxpbXBvcnQoXCIuLi9jb29yZGluYXRlLmpzXCIpLkNvb3JkaW5hdGU+fVxuICAgICAqL1xuXG4gICAgdGhpcy5vcmlnaW5zXyA9IG51bGw7XG5cbiAgICBpZiAob3B0aW9ucy5vcmlnaW5zICE9PSB1bmRlZmluZWQpIHtcbiAgICAgIHRoaXMub3JpZ2luc18gPSBvcHRpb25zLm9yaWdpbnM7XG4gICAgICBhc3NlcnQodGhpcy5vcmlnaW5zXy5sZW5ndGggPT0gdGhpcy5yZXNvbHV0aW9uc18ubGVuZ3RoLCAyMCk7IC8vIE51bWJlciBvZiBgb3JpZ2luc2AgYW5kIGByZXNvbHV0aW9uc2AgbXVzdCBiZSBlcXVhbFxuICAgIH1cblxuICAgIHZhciBleHRlbnQgPSBvcHRpb25zLmV4dGVudDtcblxuICAgIGlmIChleHRlbnQgIT09IHVuZGVmaW5lZCAmJiAhdGhpcy5vcmlnaW5fICYmICF0aGlzLm9yaWdpbnNfKSB7XG4gICAgICB0aGlzLm9yaWdpbl8gPSBnZXRUb3BMZWZ0KGV4dGVudCk7XG4gICAgfVxuXG4gICAgYXNzZXJ0KCF0aGlzLm9yaWdpbl8gJiYgdGhpcy5vcmlnaW5zXyB8fCB0aGlzLm9yaWdpbl8gJiYgIXRoaXMub3JpZ2luc18sIDE4KTsgLy8gRWl0aGVyIGBvcmlnaW5gIG9yIGBvcmlnaW5zYCBtdXN0IGJlIGNvbmZpZ3VyZWQsIG5ldmVyIGJvdGhcblxuICAgIC8qKlxuICAgICAqIEBwcml2YXRlXG4gICAgICogQHR5cGUge0FycmF5PG51bWJlcnxpbXBvcnQoXCIuLi9zaXplLmpzXCIpLlNpemU+fVxuICAgICAqL1xuXG4gICAgdGhpcy50aWxlU2l6ZXNfID0gbnVsbDtcblxuICAgIGlmIChvcHRpb25zLnRpbGVTaXplcyAhPT0gdW5kZWZpbmVkKSB7XG4gICAgICB0aGlzLnRpbGVTaXplc18gPSBvcHRpb25zLnRpbGVTaXplcztcbiAgICAgIGFzc2VydCh0aGlzLnRpbGVTaXplc18ubGVuZ3RoID09IHRoaXMucmVzb2x1dGlvbnNfLmxlbmd0aCwgMTkpOyAvLyBOdW1iZXIgb2YgYHRpbGVTaXplc2AgYW5kIGByZXNvbHV0aW9uc2AgbXVzdCBiZSBlcXVhbFxuICAgIH1cbiAgICAvKipcbiAgICAgKiBAcHJpdmF0ZVxuICAgICAqIEB0eXBlIHtudW1iZXJ8aW1wb3J0KFwiLi4vc2l6ZS5qc1wiKS5TaXplfVxuICAgICAqL1xuXG5cbiAgICB0aGlzLnRpbGVTaXplXyA9IG9wdGlvbnMudGlsZVNpemUgIT09IHVuZGVmaW5lZCA/IG9wdGlvbnMudGlsZVNpemUgOiAhdGhpcy50aWxlU2l6ZXNfID8gREVGQVVMVF9USUxFX1NJWkUgOiBudWxsO1xuICAgIGFzc2VydCghdGhpcy50aWxlU2l6ZV8gJiYgdGhpcy50aWxlU2l6ZXNfIHx8IHRoaXMudGlsZVNpemVfICYmICF0aGlzLnRpbGVTaXplc18sIDIyKTsgLy8gRWl0aGVyIGB0aWxlU2l6ZWAgb3IgYHRpbGVTaXplc2AgbXVzdCBiZSBjb25maWd1cmVkLCBuZXZlciBib3RoXG5cbiAgICAvKipcbiAgICAgKiBAcHJpdmF0ZVxuICAgICAqIEB0eXBlIHtpbXBvcnQoXCIuLi9leHRlbnQuanNcIikuRXh0ZW50fVxuICAgICAqL1xuXG4gICAgdGhpcy5leHRlbnRfID0gZXh0ZW50ICE9PSB1bmRlZmluZWQgPyBleHRlbnQgOiBudWxsO1xuICAgIC8qKlxuICAgICAqIEBwcml2YXRlXG4gICAgICogQHR5cGUge0FycmF5PGltcG9ydChcIi4uL1RpbGVSYW5nZS5qc1wiKS5kZWZhdWx0Pn1cbiAgICAgKi9cblxuICAgIHRoaXMuZnVsbFRpbGVSYW5nZXNfID0gbnVsbDtcbiAgICAvKipcbiAgICAgKiBAcHJpdmF0ZVxuICAgICAqIEB0eXBlIHtpbXBvcnQoXCIuLi9zaXplLmpzXCIpLlNpemV9XG4gICAgICovXG5cbiAgICB0aGlzLnRtcFNpemVfID0gWzAsIDBdO1xuXG4gICAgaWYgKG9wdGlvbnMuc2l6ZXMgIT09IHVuZGVmaW5lZCkge1xuICAgICAgdGhpcy5mdWxsVGlsZVJhbmdlc18gPSBvcHRpb25zLnNpemVzLm1hcChmdW5jdGlvbiAoc2l6ZSwgeikge1xuICAgICAgICB2YXIgdGlsZVJhbmdlID0gbmV3IFRpbGVSYW5nZShNYXRoLm1pbigwLCBzaXplWzBdKSwgTWF0aC5tYXgoc2l6ZVswXSAtIDEsIC0xKSwgTWF0aC5taW4oMCwgc2l6ZVsxXSksIE1hdGgubWF4KHNpemVbMV0gLSAxLCAtMSkpO1xuXG4gICAgICAgIGlmIChleHRlbnQpIHtcbiAgICAgICAgICB2YXIgcmVzdHJpY3RlZFRpbGVSYW5nZSA9IHRoaXMuZ2V0VGlsZVJhbmdlRm9yRXh0ZW50QW5kWihleHRlbnQsIHopO1xuICAgICAgICAgIHRpbGVSYW5nZS5taW5YID0gTWF0aC5tYXgocmVzdHJpY3RlZFRpbGVSYW5nZS5taW5YLCB0aWxlUmFuZ2UubWluWCk7XG4gICAgICAgICAgdGlsZVJhbmdlLm1heFggPSBNYXRoLm1pbihyZXN0cmljdGVkVGlsZVJhbmdlLm1heFgsIHRpbGVSYW5nZS5tYXhYKTtcbiAgICAgICAgICB0aWxlUmFuZ2UubWluWSA9IE1hdGgubWF4KHJlc3RyaWN0ZWRUaWxlUmFuZ2UubWluWSwgdGlsZVJhbmdlLm1pblkpO1xuICAgICAgICAgIHRpbGVSYW5nZS5tYXhZID0gTWF0aC5taW4ocmVzdHJpY3RlZFRpbGVSYW5nZS5tYXhZLCB0aWxlUmFuZ2UubWF4WSk7XG4gICAgICAgIH1cblxuICAgICAgICByZXR1cm4gdGlsZVJhbmdlO1xuICAgICAgfSwgdGhpcyk7XG4gICAgfSBlbHNlIGlmIChleHRlbnQpIHtcbiAgICAgIHRoaXMuY2FsY3VsYXRlVGlsZVJhbmdlc18oZXh0ZW50KTtcbiAgICB9XG4gIH1cbiAgLyoqXG4gICAqIENhbGwgYSBmdW5jdGlvbiB3aXRoIGVhY2ggdGlsZSBjb29yZGluYXRlIGZvciBhIGdpdmVuIGV4dGVudCBhbmQgem9vbSBsZXZlbC5cbiAgICpcbiAgICogQHBhcmFtIHtpbXBvcnQoXCIuLi9leHRlbnQuanNcIikuRXh0ZW50fSBleHRlbnQgRXh0ZW50LlxuICAgKiBAcGFyYW0ge251bWJlcn0gem9vbSBJbnRlZ2VyIHpvb20gbGV2ZWwuXG4gICAqIEBwYXJhbSB7ZnVuY3Rpb24oaW1wb3J0KFwiLi4vdGlsZWNvb3JkLmpzXCIpLlRpbGVDb29yZCk6IHZvaWR9IGNhbGxiYWNrIEZ1bmN0aW9uIGNhbGxlZCB3aXRoIGVhY2ggdGlsZSBjb29yZGluYXRlLlxuICAgKiBAYXBpXG4gICAqL1xuXG5cbiAgVGlsZUdyaWQucHJvdG90eXBlLmZvckVhY2hUaWxlQ29vcmQgPSBmdW5jdGlvbiAoZXh0ZW50LCB6b29tLCBjYWxsYmFjaykge1xuICAgIHZhciB0aWxlUmFuZ2UgPSB0aGlzLmdldFRpbGVSYW5nZUZvckV4dGVudEFuZFooZXh0ZW50LCB6b29tKTtcblxuICAgIGZvciAodmFyIGkgPSB0aWxlUmFuZ2UubWluWCwgaWkgPSB0aWxlUmFuZ2UubWF4WDsgaSA8PSBpaTsgKytpKSB7XG4gICAgICBmb3IgKHZhciBqID0gdGlsZVJhbmdlLm1pblksIGpqID0gdGlsZVJhbmdlLm1heFk7IGogPD0gamo7ICsraikge1xuICAgICAgICBjYWxsYmFjayhbem9vbSwgaSwgal0pO1xuICAgICAgfVxuICAgIH1cbiAgfTtcbiAgLyoqXG4gICAqIEBwYXJhbSB7aW1wb3J0KFwiLi4vdGlsZWNvb3JkLmpzXCIpLlRpbGVDb29yZH0gdGlsZUNvb3JkIFRpbGUgY29vcmRpbmF0ZS5cbiAgICogQHBhcmFtIHtmdW5jdGlvbihudW1iZXIsIGltcG9ydChcIi4uL1RpbGVSYW5nZS5qc1wiKS5kZWZhdWx0KTogYm9vbGVhbn0gY2FsbGJhY2sgQ2FsbGJhY2suXG4gICAqIEBwYXJhbSB7aW1wb3J0KFwiLi4vVGlsZVJhbmdlLmpzXCIpLmRlZmF1bHQ9fSBvcHRfdGlsZVJhbmdlIFRlbXBvcmFyeSBpbXBvcnQoXCIuLi9UaWxlUmFuZ2UuanNcIikuZGVmYXVsdCBvYmplY3QuXG4gICAqIEBwYXJhbSB7aW1wb3J0KFwiLi4vZXh0ZW50LmpzXCIpLkV4dGVudD19IG9wdF9leHRlbnQgVGVtcG9yYXJ5IGltcG9ydChcIi4uL2V4dGVudC5qc1wiKS5FeHRlbnQgb2JqZWN0LlxuICAgKiBAcmV0dXJuIHtib29sZWFufSBDYWxsYmFjayBzdWNjZWVkZWQuXG4gICAqL1xuXG5cbiAgVGlsZUdyaWQucHJvdG90eXBlLmZvckVhY2hUaWxlQ29vcmRQYXJlbnRUaWxlUmFuZ2UgPSBmdW5jdGlvbiAodGlsZUNvb3JkLCBjYWxsYmFjaywgb3B0X3RpbGVSYW5nZSwgb3B0X2V4dGVudCkge1xuICAgIHZhciB0aWxlUmFuZ2UsIHgsIHk7XG4gICAgdmFyIHRpbGVDb29yZEV4dGVudCA9IG51bGw7XG4gICAgdmFyIHogPSB0aWxlQ29vcmRbMF0gLSAxO1xuXG4gICAgaWYgKHRoaXMuem9vbUZhY3Rvcl8gPT09IDIpIHtcbiAgICAgIHggPSB0aWxlQ29vcmRbMV07XG4gICAgICB5ID0gdGlsZUNvb3JkWzJdO1xuICAgIH0gZWxzZSB7XG4gICAgICB0aWxlQ29vcmRFeHRlbnQgPSB0aGlzLmdldFRpbGVDb29yZEV4dGVudCh0aWxlQ29vcmQsIG9wdF9leHRlbnQpO1xuICAgIH1cblxuICAgIHdoaWxlICh6ID49IHRoaXMubWluWm9vbSkge1xuICAgICAgaWYgKHRoaXMuem9vbUZhY3Rvcl8gPT09IDIpIHtcbiAgICAgICAgeCA9IE1hdGguZmxvb3IoeCAvIDIpO1xuICAgICAgICB5ID0gTWF0aC5mbG9vcih5IC8gMik7XG4gICAgICAgIHRpbGVSYW5nZSA9IGNyZWF0ZU9yVXBkYXRlVGlsZVJhbmdlKHgsIHgsIHksIHksIG9wdF90aWxlUmFuZ2UpO1xuICAgICAgfSBlbHNlIHtcbiAgICAgICAgdGlsZVJhbmdlID0gdGhpcy5nZXRUaWxlUmFuZ2VGb3JFeHRlbnRBbmRaKHRpbGVDb29yZEV4dGVudCwgeiwgb3B0X3RpbGVSYW5nZSk7XG4gICAgICB9XG5cbiAgICAgIGlmIChjYWxsYmFjayh6LCB0aWxlUmFuZ2UpKSB7XG4gICAgICAgIHJldHVybiB0cnVlO1xuICAgICAgfVxuXG4gICAgICAtLXo7XG4gICAgfVxuXG4gICAgcmV0dXJuIGZhbHNlO1xuICB9O1xuICAvKipcbiAgICogR2V0IHRoZSBleHRlbnQgZm9yIHRoaXMgdGlsZSBncmlkLCBpZiBpdCB3YXMgY29uZmlndXJlZC5cbiAgICogQHJldHVybiB7aW1wb3J0KFwiLi4vZXh0ZW50LmpzXCIpLkV4dGVudH0gRXh0ZW50LlxuICAgKiBAYXBpXG4gICAqL1xuXG5cbiAgVGlsZUdyaWQucHJvdG90eXBlLmdldEV4dGVudCA9IGZ1bmN0aW9uICgpIHtcbiAgICByZXR1cm4gdGhpcy5leHRlbnRfO1xuICB9O1xuICAvKipcbiAgICogR2V0IHRoZSBtYXhpbXVtIHpvb20gbGV2ZWwgZm9yIHRoZSBncmlkLlxuICAgKiBAcmV0dXJuIHtudW1iZXJ9IE1heCB6b29tLlxuICAgKiBAYXBpXG4gICAqL1xuXG5cbiAgVGlsZUdyaWQucHJvdG90eXBlLmdldE1heFpvb20gPSBmdW5jdGlvbiAoKSB7XG4gICAgcmV0dXJuIHRoaXMubWF4Wm9vbTtcbiAgfTtcbiAgLyoqXG4gICAqIEdldCB0aGUgbWluaW11bSB6b29tIGxldmVsIGZvciB0aGUgZ3JpZC5cbiAgICogQHJldHVybiB7bnVtYmVyfSBNaW4gem9vbS5cbiAgICogQGFwaVxuICAgKi9cblxuXG4gIFRpbGVHcmlkLnByb3RvdHlwZS5nZXRNaW5ab29tID0gZnVuY3Rpb24gKCkge1xuICAgIHJldHVybiB0aGlzLm1pblpvb207XG4gIH07XG4gIC8qKlxuICAgKiBHZXQgdGhlIG9yaWdpbiBmb3IgdGhlIGdyaWQgYXQgdGhlIGdpdmVuIHpvb20gbGV2ZWwuXG4gICAqIEBwYXJhbSB7bnVtYmVyfSB6IEludGVnZXIgem9vbSBsZXZlbC5cbiAgICogQHJldHVybiB7aW1wb3J0KFwiLi4vY29vcmRpbmF0ZS5qc1wiKS5Db29yZGluYXRlfSBPcmlnaW4uXG4gICAqIEBhcGlcbiAgICovXG5cblxuICBUaWxlR3JpZC5wcm90b3R5cGUuZ2V0T3JpZ2luID0gZnVuY3Rpb24gKHopIHtcbiAgICBpZiAodGhpcy5vcmlnaW5fKSB7XG4gICAgICByZXR1cm4gdGhpcy5vcmlnaW5fO1xuICAgIH0gZWxzZSB7XG4gICAgICByZXR1cm4gdGhpcy5vcmlnaW5zX1t6XTtcbiAgICB9XG4gIH07XG4gIC8qKlxuICAgKiBHZXQgdGhlIHJlc29sdXRpb24gZm9yIHRoZSBnaXZlbiB6b29tIGxldmVsLlxuICAgKiBAcGFyYW0ge251bWJlcn0geiBJbnRlZ2VyIHpvb20gbGV2ZWwuXG4gICAqIEByZXR1cm4ge251bWJlcn0gUmVzb2x1dGlvbi5cbiAgICogQGFwaVxuICAgKi9cblxuXG4gIFRpbGVHcmlkLnByb3RvdHlwZS5nZXRSZXNvbHV0aW9uID0gZnVuY3Rpb24gKHopIHtcbiAgICByZXR1cm4gdGhpcy5yZXNvbHV0aW9uc19bel07XG4gIH07XG4gIC8qKlxuICAgKiBHZXQgdGhlIGxpc3Qgb2YgcmVzb2x1dGlvbnMgZm9yIHRoZSB0aWxlIGdyaWQuXG4gICAqIEByZXR1cm4ge0FycmF5PG51bWJlcj59IFJlc29sdXRpb25zLlxuICAgKiBAYXBpXG4gICAqL1xuXG5cbiAgVGlsZUdyaWQucHJvdG90eXBlLmdldFJlc29sdXRpb25zID0gZnVuY3Rpb24gKCkge1xuICAgIHJldHVybiB0aGlzLnJlc29sdXRpb25zXztcbiAgfTtcbiAgLyoqXG4gICAqIEBwYXJhbSB7aW1wb3J0KFwiLi4vdGlsZWNvb3JkLmpzXCIpLlRpbGVDb29yZH0gdGlsZUNvb3JkIFRpbGUgY29vcmRpbmF0ZS5cbiAgICogQHBhcmFtIHtpbXBvcnQoXCIuLi9UaWxlUmFuZ2UuanNcIikuZGVmYXVsdD19IG9wdF90aWxlUmFuZ2UgVGVtcG9yYXJ5IGltcG9ydChcIi4uL1RpbGVSYW5nZS5qc1wiKS5kZWZhdWx0IG9iamVjdC5cbiAgICogQHBhcmFtIHtpbXBvcnQoXCIuLi9leHRlbnQuanNcIikuRXh0ZW50PX0gb3B0X2V4dGVudCBUZW1wb3JhcnkgaW1wb3J0KFwiLi4vZXh0ZW50LmpzXCIpLkV4dGVudCBvYmplY3QuXG4gICAqIEByZXR1cm4ge2ltcG9ydChcIi4uL1RpbGVSYW5nZS5qc1wiKS5kZWZhdWx0fSBUaWxlIHJhbmdlLlxuICAgKi9cblxuXG4gIFRpbGVHcmlkLnByb3RvdHlwZS5nZXRUaWxlQ29vcmRDaGlsZFRpbGVSYW5nZSA9IGZ1bmN0aW9uICh0aWxlQ29vcmQsIG9wdF90aWxlUmFuZ2UsIG9wdF9leHRlbnQpIHtcbiAgICBpZiAodGlsZUNvb3JkWzBdIDwgdGhpcy5tYXhab29tKSB7XG4gICAgICBpZiAodGhpcy56b29tRmFjdG9yXyA9PT0gMikge1xuICAgICAgICB2YXIgbWluWCA9IHRpbGVDb29yZFsxXSAqIDI7XG4gICAgICAgIHZhciBtaW5ZID0gdGlsZUNvb3JkWzJdICogMjtcbiAgICAgICAgcmV0dXJuIGNyZWF0ZU9yVXBkYXRlVGlsZVJhbmdlKG1pblgsIG1pblggKyAxLCBtaW5ZLCBtaW5ZICsgMSwgb3B0X3RpbGVSYW5nZSk7XG4gICAgICB9XG5cbiAgICAgIHZhciB0aWxlQ29vcmRFeHRlbnQgPSB0aGlzLmdldFRpbGVDb29yZEV4dGVudCh0aWxlQ29vcmQsIG9wdF9leHRlbnQpO1xuICAgICAgcmV0dXJuIHRoaXMuZ2V0VGlsZVJhbmdlRm9yRXh0ZW50QW5kWih0aWxlQ29vcmRFeHRlbnQsIHRpbGVDb29yZFswXSArIDEsIG9wdF90aWxlUmFuZ2UpO1xuICAgIH1cblxuICAgIHJldHVybiBudWxsO1xuICB9O1xuICAvKipcbiAgICogR2V0IHRoZSBleHRlbnQgZm9yIGEgdGlsZSByYW5nZS5cbiAgICogQHBhcmFtIHtudW1iZXJ9IHogSW50ZWdlciB6b29tIGxldmVsLlxuICAgKiBAcGFyYW0ge2ltcG9ydChcIi4uL1RpbGVSYW5nZS5qc1wiKS5kZWZhdWx0fSB0aWxlUmFuZ2UgVGlsZSByYW5nZS5cbiAgICogQHBhcmFtIHtpbXBvcnQoXCIuLi9leHRlbnQuanNcIikuRXh0ZW50PX0gb3B0X2V4dGVudCBUZW1wb3JhcnkgaW1wb3J0KFwiLi4vZXh0ZW50LmpzXCIpLkV4dGVudCBvYmplY3QuXG4gICAqIEByZXR1cm4ge2ltcG9ydChcIi4uL2V4dGVudC5qc1wiKS5FeHRlbnR9IEV4dGVudC5cbiAgICovXG5cblxuICBUaWxlR3JpZC5wcm90b3R5cGUuZ2V0VGlsZVJhbmdlRXh0ZW50ID0gZnVuY3Rpb24gKHosIHRpbGVSYW5nZSwgb3B0X2V4dGVudCkge1xuICAgIHZhciBvcmlnaW4gPSB0aGlzLmdldE9yaWdpbih6KTtcbiAgICB2YXIgcmVzb2x1dGlvbiA9IHRoaXMuZ2V0UmVzb2x1dGlvbih6KTtcbiAgICB2YXIgdGlsZVNpemUgPSB0b1NpemUodGhpcy5nZXRUaWxlU2l6ZSh6KSwgdGhpcy50bXBTaXplXyk7XG4gICAgdmFyIG1pblggPSBvcmlnaW5bMF0gKyB0aWxlUmFuZ2UubWluWCAqIHRpbGVTaXplWzBdICogcmVzb2x1dGlvbjtcbiAgICB2YXIgbWF4WCA9IG9yaWdpblswXSArICh0aWxlUmFuZ2UubWF4WCArIDEpICogdGlsZVNpemVbMF0gKiByZXNvbHV0aW9uO1xuICAgIHZhciBtaW5ZID0gb3JpZ2luWzFdICsgdGlsZVJhbmdlLm1pblkgKiB0aWxlU2l6ZVsxXSAqIHJlc29sdXRpb247XG4gICAgdmFyIG1heFkgPSBvcmlnaW5bMV0gKyAodGlsZVJhbmdlLm1heFkgKyAxKSAqIHRpbGVTaXplWzFdICogcmVzb2x1dGlvbjtcbiAgICByZXR1cm4gY3JlYXRlT3JVcGRhdGUobWluWCwgbWluWSwgbWF4WCwgbWF4WSwgb3B0X2V4dGVudCk7XG4gIH07XG4gIC8qKlxuICAgKiBHZXQgYSB0aWxlIHJhbmdlIGZvciB0aGUgZ2l2ZW4gZXh0ZW50IGFuZCBpbnRlZ2VyIHpvb20gbGV2ZWwuXG4gICAqIEBwYXJhbSB7aW1wb3J0KFwiLi4vZXh0ZW50LmpzXCIpLkV4dGVudH0gZXh0ZW50IEV4dGVudC5cbiAgICogQHBhcmFtIHtudW1iZXJ9IHogSW50ZWdlciB6b29tIGxldmVsLlxuICAgKiBAcGFyYW0ge2ltcG9ydChcIi4uL1RpbGVSYW5nZS5qc1wiKS5kZWZhdWx0PX0gb3B0X3RpbGVSYW5nZSBUZW1wb3JhcnkgdGlsZSByYW5nZSBvYmplY3QuXG4gICAqIEByZXR1cm4ge2ltcG9ydChcIi4uL1RpbGVSYW5nZS5qc1wiKS5kZWZhdWx0fSBUaWxlIHJhbmdlLlxuICAgKi9cblxuXG4gIFRpbGVHcmlkLnByb3RvdHlwZS5nZXRUaWxlUmFuZ2VGb3JFeHRlbnRBbmRaID0gZnVuY3Rpb24gKGV4dGVudCwgeiwgb3B0X3RpbGVSYW5nZSkge1xuICAgIHZhciB0aWxlQ29vcmQgPSB0bXBUaWxlQ29vcmQ7XG4gICAgdGhpcy5nZXRUaWxlQ29vcmRGb3JYWUFuZFpfKGV4dGVudFswXSwgZXh0ZW50WzNdLCB6LCBmYWxzZSwgdGlsZUNvb3JkKTtcbiAgICB2YXIgbWluWCA9IHRpbGVDb29yZFsxXTtcbiAgICB2YXIgbWluWSA9IHRpbGVDb29yZFsyXTtcbiAgICB0aGlzLmdldFRpbGVDb29yZEZvclhZQW5kWl8oZXh0ZW50WzJdLCBleHRlbnRbMV0sIHosIHRydWUsIHRpbGVDb29yZCk7XG4gICAgcmV0dXJuIGNyZWF0ZU9yVXBkYXRlVGlsZVJhbmdlKG1pblgsIHRpbGVDb29yZFsxXSwgbWluWSwgdGlsZUNvb3JkWzJdLCBvcHRfdGlsZVJhbmdlKTtcbiAgfTtcbiAgLyoqXG4gICAqIEBwYXJhbSB7aW1wb3J0KFwiLi4vdGlsZWNvb3JkLmpzXCIpLlRpbGVDb29yZH0gdGlsZUNvb3JkIFRpbGUgY29vcmRpbmF0ZS5cbiAgICogQHJldHVybiB7aW1wb3J0KFwiLi4vY29vcmRpbmF0ZS5qc1wiKS5Db29yZGluYXRlfSBUaWxlIGNlbnRlci5cbiAgICovXG5cblxuICBUaWxlR3JpZC5wcm90b3R5cGUuZ2V0VGlsZUNvb3JkQ2VudGVyID0gZnVuY3Rpb24gKHRpbGVDb29yZCkge1xuICAgIHZhciBvcmlnaW4gPSB0aGlzLmdldE9yaWdpbih0aWxlQ29vcmRbMF0pO1xuICAgIHZhciByZXNvbHV0aW9uID0gdGhpcy5nZXRSZXNvbHV0aW9uKHRpbGVDb29yZFswXSk7XG4gICAgdmFyIHRpbGVTaXplID0gdG9TaXplKHRoaXMuZ2V0VGlsZVNpemUodGlsZUNvb3JkWzBdKSwgdGhpcy50bXBTaXplXyk7XG4gICAgcmV0dXJuIFtvcmlnaW5bMF0gKyAodGlsZUNvb3JkWzFdICsgMC41KSAqIHRpbGVTaXplWzBdICogcmVzb2x1dGlvbiwgb3JpZ2luWzFdIC0gKHRpbGVDb29yZFsyXSArIDAuNSkgKiB0aWxlU2l6ZVsxXSAqIHJlc29sdXRpb25dO1xuICB9O1xuICAvKipcbiAgICogR2V0IHRoZSBleHRlbnQgb2YgYSB0aWxlIGNvb3JkaW5hdGUuXG4gICAqXG4gICAqIEBwYXJhbSB7aW1wb3J0KFwiLi4vdGlsZWNvb3JkLmpzXCIpLlRpbGVDb29yZH0gdGlsZUNvb3JkIFRpbGUgY29vcmRpbmF0ZS5cbiAgICogQHBhcmFtIHtpbXBvcnQoXCIuLi9leHRlbnQuanNcIikuRXh0ZW50PX0gb3B0X2V4dGVudCBUZW1wb3JhcnkgZXh0ZW50IG9iamVjdC5cbiAgICogQHJldHVybiB7aW1wb3J0KFwiLi4vZXh0ZW50LmpzXCIpLkV4dGVudH0gRXh0ZW50LlxuICAgKiBAYXBpXG4gICAqL1xuXG5cbiAgVGlsZUdyaWQucHJvdG90eXBlLmdldFRpbGVDb29yZEV4dGVudCA9IGZ1bmN0aW9uICh0aWxlQ29vcmQsIG9wdF9leHRlbnQpIHtcbiAgICB2YXIgb3JpZ2luID0gdGhpcy5nZXRPcmlnaW4odGlsZUNvb3JkWzBdKTtcbiAgICB2YXIgcmVzb2x1dGlvbiA9IHRoaXMuZ2V0UmVzb2x1dGlvbih0aWxlQ29vcmRbMF0pO1xuICAgIHZhciB0aWxlU2l6ZSA9IHRvU2l6ZSh0aGlzLmdldFRpbGVTaXplKHRpbGVDb29yZFswXSksIHRoaXMudG1wU2l6ZV8pO1xuICAgIHZhciBtaW5YID0gb3JpZ2luWzBdICsgdGlsZUNvb3JkWzFdICogdGlsZVNpemVbMF0gKiByZXNvbHV0aW9uO1xuICAgIHZhciBtaW5ZID0gb3JpZ2luWzFdIC0gKHRpbGVDb29yZFsyXSArIDEpICogdGlsZVNpemVbMV0gKiByZXNvbHV0aW9uO1xuICAgIHZhciBtYXhYID0gbWluWCArIHRpbGVTaXplWzBdICogcmVzb2x1dGlvbjtcbiAgICB2YXIgbWF4WSA9IG1pblkgKyB0aWxlU2l6ZVsxXSAqIHJlc29sdXRpb247XG4gICAgcmV0dXJuIGNyZWF0ZU9yVXBkYXRlKG1pblgsIG1pblksIG1heFgsIG1heFksIG9wdF9leHRlbnQpO1xuICB9O1xuICAvKipcbiAgICogR2V0IHRoZSB0aWxlIGNvb3JkaW5hdGUgZm9yIHRoZSBnaXZlbiBtYXAgY29vcmRpbmF0ZSBhbmQgcmVzb2x1dGlvbi4gIFRoaXNcbiAgICogbWV0aG9kIGNvbnNpZGVycyB0aGF0IGNvb3JkaW5hdGVzIHRoYXQgaW50ZXJzZWN0IHRpbGUgYm91bmRhcmllcyBzaG91bGQgYmVcbiAgICogYXNzaWduZWQgdGhlIGhpZ2hlciB0aWxlIGNvb3JkaW5hdGUuXG4gICAqXG4gICAqIEBwYXJhbSB7aW1wb3J0KFwiLi4vY29vcmRpbmF0ZS5qc1wiKS5Db29yZGluYXRlfSBjb29yZGluYXRlIENvb3JkaW5hdGUuXG4gICAqIEBwYXJhbSB7bnVtYmVyfSByZXNvbHV0aW9uIFJlc29sdXRpb24uXG4gICAqIEBwYXJhbSB7aW1wb3J0KFwiLi4vdGlsZWNvb3JkLmpzXCIpLlRpbGVDb29yZD19IG9wdF90aWxlQ29vcmQgRGVzdGluYXRpb24gaW1wb3J0KFwiLi4vdGlsZWNvb3JkLmpzXCIpLlRpbGVDb29yZCBvYmplY3QuXG4gICAqIEByZXR1cm4ge2ltcG9ydChcIi4uL3RpbGVjb29yZC5qc1wiKS5UaWxlQ29vcmR9IFRpbGUgY29vcmRpbmF0ZS5cbiAgICogQGFwaVxuICAgKi9cblxuXG4gIFRpbGVHcmlkLnByb3RvdHlwZS5nZXRUaWxlQ29vcmRGb3JDb29yZEFuZFJlc29sdXRpb24gPSBmdW5jdGlvbiAoY29vcmRpbmF0ZSwgcmVzb2x1dGlvbiwgb3B0X3RpbGVDb29yZCkge1xuICAgIHJldHVybiB0aGlzLmdldFRpbGVDb29yZEZvclhZQW5kUmVzb2x1dGlvbl8oY29vcmRpbmF0ZVswXSwgY29vcmRpbmF0ZVsxXSwgcmVzb2x1dGlvbiwgZmFsc2UsIG9wdF90aWxlQ29vcmQpO1xuICB9O1xuICAvKipcbiAgICogTm90ZSB0aGF0IHRoaXMgbWV0aG9kIHNob3VsZCBub3QgYmUgY2FsbGVkIGZvciByZXNvbHV0aW9ucyB0aGF0IGNvcnJlc3BvbmRcbiAgICogdG8gYW4gaW50ZWdlciB6b29tIGxldmVsLiAgSW5zdGVhZCBjYWxsIHRoZSBgZ2V0VGlsZUNvb3JkRm9yWFlBbmRaX2AgbWV0aG9kLlxuICAgKiBAcGFyYW0ge251bWJlcn0geCBYLlxuICAgKiBAcGFyYW0ge251bWJlcn0geSBZLlxuICAgKiBAcGFyYW0ge251bWJlcn0gcmVzb2x1dGlvbiBSZXNvbHV0aW9uIChmb3IgYSBub24taW50ZWdlciB6b29tIGxldmVsKS5cbiAgICogQHBhcmFtIHtib29sZWFufSByZXZlcnNlSW50ZXJzZWN0aW9uUG9saWN5IEluc3RlYWQgb2YgbGV0dGluZyBlZGdlXG4gICAqICAgICBpbnRlcnNlY3Rpb25zIGdvIHRvIHRoZSBoaWdoZXIgdGlsZSBjb29yZGluYXRlLCBsZXQgZWRnZSBpbnRlcnNlY3Rpb25zXG4gICAqICAgICBnbyB0byB0aGUgbG93ZXIgdGlsZSBjb29yZGluYXRlLlxuICAgKiBAcGFyYW0ge2ltcG9ydChcIi4uL3RpbGVjb29yZC5qc1wiKS5UaWxlQ29vcmQ9fSBvcHRfdGlsZUNvb3JkIFRlbXBvcmFyeSBpbXBvcnQoXCIuLi90aWxlY29vcmQuanNcIikuVGlsZUNvb3JkIG9iamVjdC5cbiAgICogQHJldHVybiB7aW1wb3J0KFwiLi4vdGlsZWNvb3JkLmpzXCIpLlRpbGVDb29yZH0gVGlsZSBjb29yZGluYXRlLlxuICAgKiBAcHJpdmF0ZVxuICAgKi9cblxuXG4gIFRpbGVHcmlkLnByb3RvdHlwZS5nZXRUaWxlQ29vcmRGb3JYWUFuZFJlc29sdXRpb25fID0gZnVuY3Rpb24gKHgsIHksIHJlc29sdXRpb24sIHJldmVyc2VJbnRlcnNlY3Rpb25Qb2xpY3ksIG9wdF90aWxlQ29vcmQpIHtcbiAgICB2YXIgeiA9IHRoaXMuZ2V0WkZvclJlc29sdXRpb24ocmVzb2x1dGlvbik7XG4gICAgdmFyIHNjYWxlID0gcmVzb2x1dGlvbiAvIHRoaXMuZ2V0UmVzb2x1dGlvbih6KTtcbiAgICB2YXIgb3JpZ2luID0gdGhpcy5nZXRPcmlnaW4oeik7XG4gICAgdmFyIHRpbGVTaXplID0gdG9TaXplKHRoaXMuZ2V0VGlsZVNpemUoeiksIHRoaXMudG1wU2l6ZV8pO1xuICAgIHZhciBhZGp1c3RYID0gcmV2ZXJzZUludGVyc2VjdGlvblBvbGljeSA/IDAuNSA6IDA7XG4gICAgdmFyIGFkanVzdFkgPSByZXZlcnNlSW50ZXJzZWN0aW9uUG9saWN5ID8gMC41IDogMDtcbiAgICB2YXIgeEZyb21PcmlnaW4gPSBNYXRoLmZsb29yKCh4IC0gb3JpZ2luWzBdKSAvIHJlc29sdXRpb24gKyBhZGp1c3RYKTtcbiAgICB2YXIgeUZyb21PcmlnaW4gPSBNYXRoLmZsb29yKChvcmlnaW5bMV0gLSB5KSAvIHJlc29sdXRpb24gKyBhZGp1c3RZKTtcbiAgICB2YXIgdGlsZUNvb3JkWCA9IHNjYWxlICogeEZyb21PcmlnaW4gLyB0aWxlU2l6ZVswXTtcbiAgICB2YXIgdGlsZUNvb3JkWSA9IHNjYWxlICogeUZyb21PcmlnaW4gLyB0aWxlU2l6ZVsxXTtcblxuICAgIGlmIChyZXZlcnNlSW50ZXJzZWN0aW9uUG9saWN5KSB7XG4gICAgICB0aWxlQ29vcmRYID0gTWF0aC5jZWlsKHRpbGVDb29yZFgpIC0gMTtcbiAgICAgIHRpbGVDb29yZFkgPSBNYXRoLmNlaWwodGlsZUNvb3JkWSkgLSAxO1xuICAgIH0gZWxzZSB7XG4gICAgICB0aWxlQ29vcmRYID0gTWF0aC5mbG9vcih0aWxlQ29vcmRYKTtcbiAgICAgIHRpbGVDb29yZFkgPSBNYXRoLmZsb29yKHRpbGVDb29yZFkpO1xuICAgIH1cblxuICAgIHJldHVybiBjcmVhdGVPclVwZGF0ZVRpbGVDb29yZCh6LCB0aWxlQ29vcmRYLCB0aWxlQ29vcmRZLCBvcHRfdGlsZUNvb3JkKTtcbiAgfTtcbiAgLyoqXG4gICAqIEFsdGhvdWdoIHRoZXJlIGlzIHJlcGV0aXRpb24gYmV0d2VlbiB0aGlzIG1ldGhvZCBhbmQgYGdldFRpbGVDb29yZEZvclhZQW5kUmVzb2x1dGlvbl9gLFxuICAgKiB0aGV5IHNob3VsZCBoYXZlIHNlcGFyYXRlIGltcGxlbWVudGF0aW9ucy4gIFRoaXMgbWV0aG9kIGlzIGZvciBpbnRlZ2VyIHpvb21cbiAgICogbGV2ZWxzLiAgVGhlIG90aGVyIG1ldGhvZCBzaG91bGQgb25seSBiZSBjYWxsZWQgZm9yIHJlc29sdXRpb25zIGNvcnJlc3BvbmRpbmdcbiAgICogdG8gbm9uLWludGVnZXIgem9vbSBsZXZlbHMuXG4gICAqIEBwYXJhbSB7bnVtYmVyfSB4IE1hcCB4IGNvb3JkaW5hdGUuXG4gICAqIEBwYXJhbSB7bnVtYmVyfSB5IE1hcCB5IGNvb3JkaW5hdGUuXG4gICAqIEBwYXJhbSB7bnVtYmVyfSB6IEludGVnZXIgem9vbSBsZXZlbC5cbiAgICogQHBhcmFtIHtib29sZWFufSByZXZlcnNlSW50ZXJzZWN0aW9uUG9saWN5IEluc3RlYWQgb2YgbGV0dGluZyBlZGdlXG4gICAqICAgICBpbnRlcnNlY3Rpb25zIGdvIHRvIHRoZSBoaWdoZXIgdGlsZSBjb29yZGluYXRlLCBsZXQgZWRnZSBpbnRlcnNlY3Rpb25zXG4gICAqICAgICBnbyB0byB0aGUgbG93ZXIgdGlsZSBjb29yZGluYXRlLlxuICAgKiBAcGFyYW0ge2ltcG9ydChcIi4uL3RpbGVjb29yZC5qc1wiKS5UaWxlQ29vcmQ9fSBvcHRfdGlsZUNvb3JkIFRlbXBvcmFyeSBpbXBvcnQoXCIuLi90aWxlY29vcmQuanNcIikuVGlsZUNvb3JkIG9iamVjdC5cbiAgICogQHJldHVybiB7aW1wb3J0KFwiLi4vdGlsZWNvb3JkLmpzXCIpLlRpbGVDb29yZH0gVGlsZSBjb29yZGluYXRlLlxuICAgKiBAcHJpdmF0ZVxuICAgKi9cblxuXG4gIFRpbGVHcmlkLnByb3RvdHlwZS5nZXRUaWxlQ29vcmRGb3JYWUFuZFpfID0gZnVuY3Rpb24gKHgsIHksIHosIHJldmVyc2VJbnRlcnNlY3Rpb25Qb2xpY3ksIG9wdF90aWxlQ29vcmQpIHtcbiAgICB2YXIgb3JpZ2luID0gdGhpcy5nZXRPcmlnaW4oeik7XG4gICAgdmFyIHJlc29sdXRpb24gPSB0aGlzLmdldFJlc29sdXRpb24oeik7XG4gICAgdmFyIHRpbGVTaXplID0gdG9TaXplKHRoaXMuZ2V0VGlsZVNpemUoeiksIHRoaXMudG1wU2l6ZV8pO1xuICAgIHZhciBhZGp1c3RYID0gcmV2ZXJzZUludGVyc2VjdGlvblBvbGljeSA/IDAuNSA6IDA7XG4gICAgdmFyIGFkanVzdFkgPSByZXZlcnNlSW50ZXJzZWN0aW9uUG9saWN5ID8gMC41IDogMDtcbiAgICB2YXIgeEZyb21PcmlnaW4gPSBNYXRoLmZsb29yKCh4IC0gb3JpZ2luWzBdKSAvIHJlc29sdXRpb24gKyBhZGp1c3RYKTtcbiAgICB2YXIgeUZyb21PcmlnaW4gPSBNYXRoLmZsb29yKChvcmlnaW5bMV0gLSB5KSAvIHJlc29sdXRpb24gKyBhZGp1c3RZKTtcbiAgICB2YXIgdGlsZUNvb3JkWCA9IHhGcm9tT3JpZ2luIC8gdGlsZVNpemVbMF07XG4gICAgdmFyIHRpbGVDb29yZFkgPSB5RnJvbU9yaWdpbiAvIHRpbGVTaXplWzFdO1xuXG4gICAgaWYgKHJldmVyc2VJbnRlcnNlY3Rpb25Qb2xpY3kpIHtcbiAgICAgIHRpbGVDb29yZFggPSBNYXRoLmNlaWwodGlsZUNvb3JkWCkgLSAxO1xuICAgICAgdGlsZUNvb3JkWSA9IE1hdGguY2VpbCh0aWxlQ29vcmRZKSAtIDE7XG4gICAgfSBlbHNlIHtcbiAgICAgIHRpbGVDb29yZFggPSBNYXRoLmZsb29yKHRpbGVDb29yZFgpO1xuICAgICAgdGlsZUNvb3JkWSA9IE1hdGguZmxvb3IodGlsZUNvb3JkWSk7XG4gICAgfVxuXG4gICAgcmV0dXJuIGNyZWF0ZU9yVXBkYXRlVGlsZUNvb3JkKHosIHRpbGVDb29yZFgsIHRpbGVDb29yZFksIG9wdF90aWxlQ29vcmQpO1xuICB9O1xuICAvKipcbiAgICogR2V0IGEgdGlsZSBjb29yZGluYXRlIGdpdmVuIGEgbWFwIGNvb3JkaW5hdGUgYW5kIHpvb20gbGV2ZWwuXG4gICAqIEBwYXJhbSB7aW1wb3J0KFwiLi4vY29vcmRpbmF0ZS5qc1wiKS5Db29yZGluYXRlfSBjb29yZGluYXRlIENvb3JkaW5hdGUuXG4gICAqIEBwYXJhbSB7bnVtYmVyfSB6IFpvb20gbGV2ZWwuXG4gICAqIEBwYXJhbSB7aW1wb3J0KFwiLi4vdGlsZWNvb3JkLmpzXCIpLlRpbGVDb29yZD19IG9wdF90aWxlQ29vcmQgRGVzdGluYXRpb24gaW1wb3J0KFwiLi4vdGlsZWNvb3JkLmpzXCIpLlRpbGVDb29yZCBvYmplY3QuXG4gICAqIEByZXR1cm4ge2ltcG9ydChcIi4uL3RpbGVjb29yZC5qc1wiKS5UaWxlQ29vcmR9IFRpbGUgY29vcmRpbmF0ZS5cbiAgICogQGFwaVxuICAgKi9cblxuXG4gIFRpbGVHcmlkLnByb3RvdHlwZS5nZXRUaWxlQ29vcmRGb3JDb29yZEFuZFogPSBmdW5jdGlvbiAoY29vcmRpbmF0ZSwgeiwgb3B0X3RpbGVDb29yZCkge1xuICAgIHJldHVybiB0aGlzLmdldFRpbGVDb29yZEZvclhZQW5kWl8oY29vcmRpbmF0ZVswXSwgY29vcmRpbmF0ZVsxXSwgeiwgZmFsc2UsIG9wdF90aWxlQ29vcmQpO1xuICB9O1xuICAvKipcbiAgICogQHBhcmFtIHtpbXBvcnQoXCIuLi90aWxlY29vcmQuanNcIikuVGlsZUNvb3JkfSB0aWxlQ29vcmQgVGlsZSBjb29yZGluYXRlLlxuICAgKiBAcmV0dXJuIHtudW1iZXJ9IFRpbGUgcmVzb2x1dGlvbi5cbiAgICovXG5cblxuICBUaWxlR3JpZC5wcm90b3R5cGUuZ2V0VGlsZUNvb3JkUmVzb2x1dGlvbiA9IGZ1bmN0aW9uICh0aWxlQ29vcmQpIHtcbiAgICByZXR1cm4gdGhpcy5yZXNvbHV0aW9uc19bdGlsZUNvb3JkWzBdXTtcbiAgfTtcbiAgLyoqXG4gICAqIEdldCB0aGUgdGlsZSBzaXplIGZvciBhIHpvb20gbGV2ZWwuIFRoZSB0eXBlIG9mIHRoZSByZXR1cm4gdmFsdWUgbWF0Y2hlcyB0aGVcbiAgICogYHRpbGVTaXplYCBvciBgdGlsZVNpemVzYCB0aGF0IHRoZSB0aWxlIGdyaWQgd2FzIGNvbmZpZ3VyZWQgd2l0aC4gVG8gYWx3YXlzXG4gICAqIGdldCBhbiBgaW1wb3J0KFwiLi4vc2l6ZS5qc1wiKS5TaXplYCwgcnVuIHRoZSByZXN1bHQgdGhyb3VnaCBgaW1wb3J0KFwiLi4vc2l6ZS5qc1wiKS5TaXplLnRvU2l6ZSgpYC5cbiAgICogQHBhcmFtIHtudW1iZXJ9IHogWi5cbiAgICogQHJldHVybiB7bnVtYmVyfGltcG9ydChcIi4uL3NpemUuanNcIikuU2l6ZX0gVGlsZSBzaXplLlxuICAgKiBAYXBpXG4gICAqL1xuXG5cbiAgVGlsZUdyaWQucHJvdG90eXBlLmdldFRpbGVTaXplID0gZnVuY3Rpb24gKHopIHtcbiAgICBpZiAodGhpcy50aWxlU2l6ZV8pIHtcbiAgICAgIHJldHVybiB0aGlzLnRpbGVTaXplXztcbiAgICB9IGVsc2Uge1xuICAgICAgcmV0dXJuIHRoaXMudGlsZVNpemVzX1t6XTtcbiAgICB9XG4gIH07XG4gIC8qKlxuICAgKiBAcGFyYW0ge251bWJlcn0geiBab29tIGxldmVsLlxuICAgKiBAcmV0dXJuIHtpbXBvcnQoXCIuLi9UaWxlUmFuZ2UuanNcIikuZGVmYXVsdH0gRXh0ZW50IHRpbGUgcmFuZ2UgZm9yIHRoZSBzcGVjaWZpZWQgem9vbSBsZXZlbC5cbiAgICovXG5cblxuICBUaWxlR3JpZC5wcm90b3R5cGUuZ2V0RnVsbFRpbGVSYW5nZSA9IGZ1bmN0aW9uICh6KSB7XG4gICAgaWYgKCF0aGlzLmZ1bGxUaWxlUmFuZ2VzXykge1xuICAgICAgcmV0dXJuIHRoaXMuZXh0ZW50XyA/IHRoaXMuZ2V0VGlsZVJhbmdlRm9yRXh0ZW50QW5kWih0aGlzLmV4dGVudF8sIHopIDogbnVsbDtcbiAgICB9IGVsc2Uge1xuICAgICAgcmV0dXJuIHRoaXMuZnVsbFRpbGVSYW5nZXNfW3pdO1xuICAgIH1cbiAgfTtcbiAgLyoqXG4gICAqIEBwYXJhbSB7bnVtYmVyfSByZXNvbHV0aW9uIFJlc29sdXRpb24uXG4gICAqIEBwYXJhbSB7bnVtYmVyPX0gb3B0X2RpcmVjdGlvbiBJZiAwLCB0aGUgbmVhcmVzdCByZXNvbHV0aW9uIHdpbGwgYmUgdXNlZC5cbiAgICogICAgIElmIDEsIHRoZSBuZWFyZXN0IGxvd2VyIHJlc29sdXRpb24gd2lsbCBiZSB1c2VkLiBJZiAtMSwgdGhlIG5lYXJlc3RcbiAgICogICAgIGhpZ2hlciByZXNvbHV0aW9uIHdpbGwgYmUgdXNlZC4gRGVmYXVsdCBpcyAwLlxuICAgKiBAcmV0dXJuIHtudW1iZXJ9IFouXG4gICAqIEBhcGlcbiAgICovXG5cblxuICBUaWxlR3JpZC5wcm90b3R5cGUuZ2V0WkZvclJlc29sdXRpb24gPSBmdW5jdGlvbiAocmVzb2x1dGlvbiwgb3B0X2RpcmVjdGlvbikge1xuICAgIHZhciB6ID0gbGluZWFyRmluZE5lYXJlc3QodGhpcy5yZXNvbHV0aW9uc18sIHJlc29sdXRpb24sIG9wdF9kaXJlY3Rpb24gfHwgMCk7XG4gICAgcmV0dXJuIGNsYW1wKHosIHRoaXMubWluWm9vbSwgdGhpcy5tYXhab29tKTtcbiAgfTtcbiAgLyoqXG4gICAqIEBwYXJhbSB7IWltcG9ydChcIi4uL2V4dGVudC5qc1wiKS5FeHRlbnR9IGV4dGVudCBFeHRlbnQgZm9yIHRoaXMgdGlsZSBncmlkLlxuICAgKiBAcHJpdmF0ZVxuICAgKi9cblxuXG4gIFRpbGVHcmlkLnByb3RvdHlwZS5jYWxjdWxhdGVUaWxlUmFuZ2VzXyA9IGZ1bmN0aW9uIChleHRlbnQpIHtcbiAgICB2YXIgbGVuZ3RoID0gdGhpcy5yZXNvbHV0aW9uc18ubGVuZ3RoO1xuICAgIHZhciBmdWxsVGlsZVJhbmdlcyA9IG5ldyBBcnJheShsZW5ndGgpO1xuXG4gICAgZm9yICh2YXIgeiA9IHRoaXMubWluWm9vbTsgeiA8IGxlbmd0aDsgKyt6KSB7XG4gICAgICBmdWxsVGlsZVJhbmdlc1t6XSA9IHRoaXMuZ2V0VGlsZVJhbmdlRm9yRXh0ZW50QW5kWihleHRlbnQsIHopO1xuICAgIH1cblxuICAgIHRoaXMuZnVsbFRpbGVSYW5nZXNfID0gZnVsbFRpbGVSYW5nZXM7XG4gIH07XG5cbiAgcmV0dXJuIFRpbGVHcmlkO1xufSgpO1xuXG5leHBvcnQgZGVmYXVsdCBUaWxlR3JpZDsiLCIvKipcbiAqIEBtb2R1bGUgb2wvdGlsZWdyaWRcbiAqL1xuaW1wb3J0IENvcm5lciBmcm9tICcuL2V4dGVudC9Db3JuZXIuanMnO1xuaW1wb3J0IFRpbGVHcmlkIGZyb20gJy4vdGlsZWdyaWQvVGlsZUdyaWQuanMnO1xuaW1wb3J0IFVuaXRzIGZyb20gJy4vcHJvai9Vbml0cy5qcyc7XG5pbXBvcnQgeyBERUZBVUxUX01BWF9aT09NLCBERUZBVUxUX1RJTEVfU0laRSB9IGZyb20gJy4vdGlsZWdyaWQvY29tbW9uLmpzJztcbmltcG9ydCB7IE1FVEVSU19QRVJfVU5JVCwgZ2V0IGFzIGdldFByb2plY3Rpb24gfSBmcm9tICcuL3Byb2ouanMnO1xuaW1wb3J0IHsgY29udGFpbnNDb29yZGluYXRlLCBjcmVhdGVPclVwZGF0ZSwgZ2V0Q29ybmVyLCBnZXRIZWlnaHQsIGdldFdpZHRoIH0gZnJvbSAnLi9leHRlbnQuanMnO1xuaW1wb3J0IHsgdG9TaXplIH0gZnJvbSAnLi9zaXplLmpzJztcbi8qKlxuICogQHBhcmFtIHtpbXBvcnQoXCIuL3Byb2ovUHJvamVjdGlvbi5qc1wiKS5kZWZhdWx0fSBwcm9qZWN0aW9uIFByb2plY3Rpb24uXG4gKiBAcmV0dXJuIHshVGlsZUdyaWR9IERlZmF1bHQgdGlsZSBncmlkIGZvciB0aGVcbiAqIHBhc3NlZCBwcm9qZWN0aW9uLlxuICovXG5cbmV4cG9ydCBmdW5jdGlvbiBnZXRGb3JQcm9qZWN0aW9uKHByb2plY3Rpb24pIHtcbiAgdmFyIHRpbGVHcmlkID0gcHJvamVjdGlvbi5nZXREZWZhdWx0VGlsZUdyaWQoKTtcblxuICBpZiAoIXRpbGVHcmlkKSB7XG4gICAgdGlsZUdyaWQgPSBjcmVhdGVGb3JQcm9qZWN0aW9uKHByb2plY3Rpb24pO1xuICAgIHByb2plY3Rpb24uc2V0RGVmYXVsdFRpbGVHcmlkKHRpbGVHcmlkKTtcbiAgfVxuXG4gIHJldHVybiB0aWxlR3JpZDtcbn1cbi8qKlxuICogQHBhcmFtIHtUaWxlR3JpZH0gdGlsZUdyaWQgVGlsZSBncmlkLlxuICogQHBhcmFtIHtpbXBvcnQoXCIuL3RpbGVjb29yZC5qc1wiKS5UaWxlQ29vcmR9IHRpbGVDb29yZCBUaWxlIGNvb3JkaW5hdGUuXG4gKiBAcGFyYW0ge2ltcG9ydChcIi4vcHJvai9Qcm9qZWN0aW9uLmpzXCIpLmRlZmF1bHR9IHByb2plY3Rpb24gUHJvamVjdGlvbi5cbiAqIEByZXR1cm4ge2ltcG9ydChcIi4vdGlsZWNvb3JkLmpzXCIpLlRpbGVDb29yZH0gVGlsZSBjb29yZGluYXRlLlxuICovXG5cbmV4cG9ydCBmdW5jdGlvbiB3cmFwWCh0aWxlR3JpZCwgdGlsZUNvb3JkLCBwcm9qZWN0aW9uKSB7XG4gIHZhciB6ID0gdGlsZUNvb3JkWzBdO1xuICB2YXIgY2VudGVyID0gdGlsZUdyaWQuZ2V0VGlsZUNvb3JkQ2VudGVyKHRpbGVDb29yZCk7XG4gIHZhciBwcm9qZWN0aW9uRXh0ZW50ID0gZXh0ZW50RnJvbVByb2plY3Rpb24ocHJvamVjdGlvbik7XG5cbiAgaWYgKCFjb250YWluc0Nvb3JkaW5hdGUocHJvamVjdGlvbkV4dGVudCwgY2VudGVyKSkge1xuICAgIHZhciB3b3JsZFdpZHRoID0gZ2V0V2lkdGgocHJvamVjdGlvbkV4dGVudCk7XG4gICAgdmFyIHdvcmxkc0F3YXkgPSBNYXRoLmNlaWwoKHByb2plY3Rpb25FeHRlbnRbMF0gLSBjZW50ZXJbMF0pIC8gd29ybGRXaWR0aCk7XG4gICAgY2VudGVyWzBdICs9IHdvcmxkV2lkdGggKiB3b3JsZHNBd2F5O1xuICAgIHJldHVybiB0aWxlR3JpZC5nZXRUaWxlQ29vcmRGb3JDb29yZEFuZFooY2VudGVyLCB6KTtcbiAgfSBlbHNlIHtcbiAgICByZXR1cm4gdGlsZUNvb3JkO1xuICB9XG59XG4vKipcbiAqIEBwYXJhbSB7aW1wb3J0KFwiLi9leHRlbnQuanNcIikuRXh0ZW50fSBleHRlbnQgRXh0ZW50LlxuICogQHBhcmFtIHtudW1iZXI9fSBvcHRfbWF4Wm9vbSBNYXhpbXVtIHpvb20gbGV2ZWwgKGRlZmF1bHQgaXNcbiAqICAgICBERUZBVUxUX01BWF9aT09NKS5cbiAqIEBwYXJhbSB7bnVtYmVyfGltcG9ydChcIi4vc2l6ZS5qc1wiKS5TaXplPX0gb3B0X3RpbGVTaXplIFRpbGUgc2l6ZSAoZGVmYXVsdCB1c2VzXG4gKiAgICAgREVGQVVMVF9USUxFX1NJWkUpLlxuICogQHBhcmFtIHtpbXBvcnQoXCIuL2V4dGVudC9Db3JuZXIuanNcIikuZGVmYXVsdD19IG9wdF9jb3JuZXIgRXh0ZW50IGNvcm5lciAoZGVmYXVsdCBpcyBgJ3RvcC1sZWZ0J2ApLlxuICogQHJldHVybiB7IVRpbGVHcmlkfSBUaWxlR3JpZCBpbnN0YW5jZS5cbiAqL1xuXG5leHBvcnQgZnVuY3Rpb24gY3JlYXRlRm9yRXh0ZW50KGV4dGVudCwgb3B0X21heFpvb20sIG9wdF90aWxlU2l6ZSwgb3B0X2Nvcm5lcikge1xuICB2YXIgY29ybmVyID0gb3B0X2Nvcm5lciAhPT0gdW5kZWZpbmVkID8gb3B0X2Nvcm5lciA6IENvcm5lci5UT1BfTEVGVDtcbiAgdmFyIHJlc29sdXRpb25zID0gcmVzb2x1dGlvbnNGcm9tRXh0ZW50KGV4dGVudCwgb3B0X21heFpvb20sIG9wdF90aWxlU2l6ZSk7XG4gIHJldHVybiBuZXcgVGlsZUdyaWQoe1xuICAgIGV4dGVudDogZXh0ZW50LFxuICAgIG9yaWdpbjogZ2V0Q29ybmVyKGV4dGVudCwgY29ybmVyKSxcbiAgICByZXNvbHV0aW9uczogcmVzb2x1dGlvbnMsXG4gICAgdGlsZVNpemU6IG9wdF90aWxlU2l6ZVxuICB9KTtcbn1cbi8qKlxuICogQHR5cGVkZWYge09iamVjdH0gWFlaT3B0aW9uc1xuICogQHByb3BlcnR5IHtpbXBvcnQoXCIuL2V4dGVudC5qc1wiKS5FeHRlbnR9IFtleHRlbnRdIEV4dGVudCBmb3IgdGhlIHRpbGUgZ3JpZC4gVGhlIG9yaWdpbiBmb3IgYW4gWFlaIHRpbGUgZ3JpZCBpcyB0aGVcbiAqIHRvcC1sZWZ0IGNvcm5lciBvZiB0aGUgZXh0ZW50LiBJZiBgbWF4UmVzb2x1dGlvbmAgaXMgbm90IHByb3ZpZGVkIHRoZSB6ZXJvIGxldmVsIG9mIHRoZSBncmlkIGlzIGRlZmluZWQgYnkgdGhlIHJlc29sdXRpb25cbiAqIGF0IHdoaWNoIG9uZSB0aWxlIGZpdHMgaW4gdGhlIHByb3ZpZGVkIGV4dGVudC4gSWYgbm90IHByb3ZpZGVkLCB0aGUgZXh0ZW50IG9mIHRoZSBFUFNHOjM4NTcgcHJvamVjdGlvbiBpcyB1c2VkLlxuICogQHByb3BlcnR5IHtudW1iZXJ9IFttYXhSZXNvbHV0aW9uXSBSZXNvbHV0aW9uIGF0IGxldmVsIHplcm8uXG4gKiBAcHJvcGVydHkge251bWJlcn0gW21heFpvb21dIE1heGltdW0gem9vbS4gVGhlIGRlZmF1bHQgaXMgYDQyYC4gVGhpcyBkZXRlcm1pbmVzIHRoZSBudW1iZXIgb2YgbGV2ZWxzXG4gKiBpbiB0aGUgZ3JpZCBzZXQuIEZvciBleGFtcGxlLCBhIGBtYXhab29tYCBvZiAyMSBtZWFucyB0aGVyZSBhcmUgMjIgbGV2ZWxzIGluIHRoZSBncmlkIHNldC5cbiAqIEBwcm9wZXJ0eSB7bnVtYmVyfSBbbWluWm9vbT0wXSBNaW5pbXVtIHpvb20uXG4gKiBAcHJvcGVydHkge251bWJlcnxpbXBvcnQoXCIuL3NpemUuanNcIikuU2l6ZX0gW3RpbGVTaXplPVsyNTYsIDI1Nl1dIFRpbGUgc2l6ZSBpbiBwaXhlbHMuXG4gKi9cblxuLyoqXG4gKiBDcmVhdGVzIGEgdGlsZSBncmlkIHdpdGggYSBzdGFuZGFyZCBYWVogdGlsaW5nIHNjaGVtZS5cbiAqIEBwYXJhbSB7WFlaT3B0aW9ucz19IG9wdF9vcHRpb25zIFRpbGUgZ3JpZCBvcHRpb25zLlxuICogQHJldHVybiB7IVRpbGVHcmlkfSBUaWxlIGdyaWQgaW5zdGFuY2UuXG4gKiBAYXBpXG4gKi9cblxuZXhwb3J0IGZ1bmN0aW9uIGNyZWF0ZVhZWihvcHRfb3B0aW9ucykge1xuICB2YXIgeHl6T3B0aW9ucyA9IG9wdF9vcHRpb25zIHx8IHt9O1xuICB2YXIgZXh0ZW50ID0geHl6T3B0aW9ucy5leHRlbnQgfHwgZ2V0UHJvamVjdGlvbignRVBTRzozODU3JykuZ2V0RXh0ZW50KCk7XG4gIHZhciBncmlkT3B0aW9ucyA9IHtcbiAgICBleHRlbnQ6IGV4dGVudCxcbiAgICBtaW5ab29tOiB4eXpPcHRpb25zLm1pblpvb20sXG4gICAgdGlsZVNpemU6IHh5ek9wdGlvbnMudGlsZVNpemUsXG4gICAgcmVzb2x1dGlvbnM6IHJlc29sdXRpb25zRnJvbUV4dGVudChleHRlbnQsIHh5ek9wdGlvbnMubWF4Wm9vbSwgeHl6T3B0aW9ucy50aWxlU2l6ZSwgeHl6T3B0aW9ucy5tYXhSZXNvbHV0aW9uKVxuICB9O1xuICByZXR1cm4gbmV3IFRpbGVHcmlkKGdyaWRPcHRpb25zKTtcbn1cbi8qKlxuICogQ3JlYXRlIGEgcmVzb2x1dGlvbnMgYXJyYXkgZnJvbSBhbiBleHRlbnQuICBBIHpvb20gZmFjdG9yIG9mIDIgaXMgYXNzdW1lZC5cbiAqIEBwYXJhbSB7aW1wb3J0KFwiLi9leHRlbnQuanNcIikuRXh0ZW50fSBleHRlbnQgRXh0ZW50LlxuICogQHBhcmFtIHtudW1iZXI9fSBvcHRfbWF4Wm9vbSBNYXhpbXVtIHpvb20gbGV2ZWwgKGRlZmF1bHQgaXNcbiAqICAgICBERUZBVUxUX01BWF9aT09NKS5cbiAqIEBwYXJhbSB7bnVtYmVyfGltcG9ydChcIi4vc2l6ZS5qc1wiKS5TaXplPX0gb3B0X3RpbGVTaXplIFRpbGUgc2l6ZSAoZGVmYXVsdCB1c2VzXG4gKiAgICAgREVGQVVMVF9USUxFX1NJWkUpLlxuICogQHBhcmFtIHtudW1iZXI9fSBvcHRfbWF4UmVzb2x1dGlvbiBSZXNvbHV0aW9uIGF0IGxldmVsIHplcm8uXG4gKiBAcmV0dXJuIHshQXJyYXk8bnVtYmVyPn0gUmVzb2x1dGlvbnMgYXJyYXkuXG4gKi9cblxuZnVuY3Rpb24gcmVzb2x1dGlvbnNGcm9tRXh0ZW50KGV4dGVudCwgb3B0X21heFpvb20sIG9wdF90aWxlU2l6ZSwgb3B0X21heFJlc29sdXRpb24pIHtcbiAgdmFyIG1heFpvb20gPSBvcHRfbWF4Wm9vbSAhPT0gdW5kZWZpbmVkID8gb3B0X21heFpvb20gOiBERUZBVUxUX01BWF9aT09NO1xuICB2YXIgaGVpZ2h0ID0gZ2V0SGVpZ2h0KGV4dGVudCk7XG4gIHZhciB3aWR0aCA9IGdldFdpZHRoKGV4dGVudCk7XG4gIHZhciB0aWxlU2l6ZSA9IHRvU2l6ZShvcHRfdGlsZVNpemUgIT09IHVuZGVmaW5lZCA/IG9wdF90aWxlU2l6ZSA6IERFRkFVTFRfVElMRV9TSVpFKTtcbiAgdmFyIG1heFJlc29sdXRpb24gPSBvcHRfbWF4UmVzb2x1dGlvbiA+IDAgPyBvcHRfbWF4UmVzb2x1dGlvbiA6IE1hdGgubWF4KHdpZHRoIC8gdGlsZVNpemVbMF0sIGhlaWdodCAvIHRpbGVTaXplWzFdKTtcbiAgdmFyIGxlbmd0aCA9IG1heFpvb20gKyAxO1xuICB2YXIgcmVzb2x1dGlvbnMgPSBuZXcgQXJyYXkobGVuZ3RoKTtcblxuICBmb3IgKHZhciB6ID0gMDsgeiA8IGxlbmd0aDsgKyt6KSB7XG4gICAgcmVzb2x1dGlvbnNbel0gPSBtYXhSZXNvbHV0aW9uIC8gTWF0aC5wb3coMiwgeik7XG4gIH1cblxuICByZXR1cm4gcmVzb2x1dGlvbnM7XG59XG4vKipcbiAqIEBwYXJhbSB7aW1wb3J0KFwiLi9wcm9qLmpzXCIpLlByb2plY3Rpb25MaWtlfSBwcm9qZWN0aW9uIFByb2plY3Rpb24uXG4gKiBAcGFyYW0ge251bWJlcj19IG9wdF9tYXhab29tIE1heGltdW0gem9vbSBsZXZlbCAoZGVmYXVsdCBpc1xuICogICAgIERFRkFVTFRfTUFYX1pPT00pLlxuICogQHBhcmFtIHtudW1iZXJ8aW1wb3J0KFwiLi9zaXplLmpzXCIpLlNpemU9fSBvcHRfdGlsZVNpemUgVGlsZSBzaXplIChkZWZhdWx0IHVzZXNcbiAqICAgICBERUZBVUxUX1RJTEVfU0laRSkuXG4gKiBAcGFyYW0ge2ltcG9ydChcIi4vZXh0ZW50L0Nvcm5lci5qc1wiKS5kZWZhdWx0PX0gb3B0X2Nvcm5lciBFeHRlbnQgY29ybmVyIChkZWZhdWx0IGlzIGAndG9wLWxlZnQnYCkuXG4gKiBAcmV0dXJuIHshVGlsZUdyaWR9IFRpbGVHcmlkIGluc3RhbmNlLlxuICovXG5cblxuZXhwb3J0IGZ1bmN0aW9uIGNyZWF0ZUZvclByb2plY3Rpb24ocHJvamVjdGlvbiwgb3B0X21heFpvb20sIG9wdF90aWxlU2l6ZSwgb3B0X2Nvcm5lcikge1xuICB2YXIgZXh0ZW50ID0gZXh0ZW50RnJvbVByb2plY3Rpb24ocHJvamVjdGlvbik7XG4gIHJldHVybiBjcmVhdGVGb3JFeHRlbnQoZXh0ZW50LCBvcHRfbWF4Wm9vbSwgb3B0X3RpbGVTaXplLCBvcHRfY29ybmVyKTtcbn1cbi8qKlxuICogR2VuZXJhdGUgYSB0aWxlIGdyaWQgZXh0ZW50IGZyb20gYSBwcm9qZWN0aW9uLiAgSWYgdGhlIHByb2plY3Rpb24gaGFzIGFuXG4gKiBleHRlbnQsIGl0IGlzIHVzZWQuICBJZiBub3QsIGEgZ2xvYmFsIGV4dGVudCBpcyBhc3N1bWVkLlxuICogQHBhcmFtIHtpbXBvcnQoXCIuL3Byb2ouanNcIikuUHJvamVjdGlvbkxpa2V9IHByb2plY3Rpb24gUHJvamVjdGlvbi5cbiAqIEByZXR1cm4ge2ltcG9ydChcIi4vZXh0ZW50LmpzXCIpLkV4dGVudH0gRXh0ZW50LlxuICovXG5cbmV4cG9ydCBmdW5jdGlvbiBleHRlbnRGcm9tUHJvamVjdGlvbihwcm9qZWN0aW9uKSB7XG4gIHByb2plY3Rpb24gPSBnZXRQcm9qZWN0aW9uKHByb2plY3Rpb24pO1xuICB2YXIgZXh0ZW50ID0gcHJvamVjdGlvbi5nZXRFeHRlbnQoKTtcblxuICBpZiAoIWV4dGVudCkge1xuICAgIHZhciBoYWxmID0gMTgwICogTUVURVJTX1BFUl9VTklUW1VuaXRzLkRFR1JFRVNdIC8gcHJvamVjdGlvbi5nZXRNZXRlcnNQZXJVbml0KCk7XG4gICAgZXh0ZW50ID0gY3JlYXRlT3JVcGRhdGUoLWhhbGYsIC1oYWxmLCBoYWxmLCBoYWxmKTtcbiAgfVxuXG4gIHJldHVybiBleHRlbnQ7XG59IiwidmFyIF9fZXh0ZW5kcyA9IHRoaXMgJiYgdGhpcy5fX2V4dGVuZHMgfHwgZnVuY3Rpb24gKCkge1xuICB2YXIgX2V4dGVuZFN0YXRpY3MgPSBmdW5jdGlvbiBleHRlbmRTdGF0aWNzKGQsIGIpIHtcbiAgICBfZXh0ZW5kU3RhdGljcyA9IE9iamVjdC5zZXRQcm90b3R5cGVPZiB8fCB7XG4gICAgICBfX3Byb3RvX186IFtdXG4gICAgfSBpbnN0YW5jZW9mIEFycmF5ICYmIGZ1bmN0aW9uIChkLCBiKSB7XG4gICAgICBkLl9fcHJvdG9fXyA9IGI7XG4gICAgfSB8fCBmdW5jdGlvbiAoZCwgYikge1xuICAgICAgZm9yICh2YXIgcCBpbiBiKSB7XG4gICAgICAgIGlmIChPYmplY3QucHJvdG90eXBlLmhhc093blByb3BlcnR5LmNhbGwoYiwgcCkpIGRbcF0gPSBiW3BdO1xuICAgICAgfVxuICAgIH07XG5cbiAgICByZXR1cm4gX2V4dGVuZFN0YXRpY3MoZCwgYik7XG4gIH07XG5cbiAgcmV0dXJuIGZ1bmN0aW9uIChkLCBiKSB7XG4gICAgX2V4dGVuZFN0YXRpY3MoZCwgYik7XG5cbiAgICBmdW5jdGlvbiBfXygpIHtcbiAgICAgIHRoaXMuY29uc3RydWN0b3IgPSBkO1xuICAgIH1cblxuICAgIGQucHJvdG90eXBlID0gYiA9PT0gbnVsbCA/IE9iamVjdC5jcmVhdGUoYikgOiAoX18ucHJvdG90eXBlID0gYi5wcm90b3R5cGUsIG5ldyBfXygpKTtcbiAgfTtcbn0oKTtcbi8qKlxuICogQG1vZHVsZSBvbC9zb3VyY2UvVGlsZVxuICovXG5cblxuaW1wb3J0IEV2ZW50IGZyb20gJy4uL2V2ZW50cy9FdmVudC5qcyc7XG5pbXBvcnQgU291cmNlIGZyb20gJy4vU291cmNlLmpzJztcbmltcG9ydCBUaWxlQ2FjaGUgZnJvbSAnLi4vVGlsZUNhY2hlLmpzJztcbmltcG9ydCBUaWxlU3RhdGUgZnJvbSAnLi4vVGlsZVN0YXRlLmpzJztcbmltcG9ydCB7IGFic3RyYWN0IH0gZnJvbSAnLi4vdXRpbC5qcyc7XG5pbXBvcnQgeyBhc3NlcnQgfSBmcm9tICcuLi9hc3NlcnRzLmpzJztcbmltcG9ydCB7IGVxdWl2YWxlbnQgfSBmcm9tICcuLi9wcm9qLmpzJztcbmltcG9ydCB7IGdldEtleVpYWSwgd2l0aGluRXh0ZW50QW5kWiB9IGZyb20gJy4uL3RpbGVjb29yZC5qcyc7XG5pbXBvcnQgeyBnZXRGb3JQcm9qZWN0aW9uIGFzIGdldFRpbGVHcmlkRm9yUHJvamVjdGlvbiwgd3JhcFggfSBmcm9tICcuLi90aWxlZ3JpZC5qcyc7XG5pbXBvcnQgeyBzY2FsZSBhcyBzY2FsZVNpemUsIHRvU2l6ZSB9IGZyb20gJy4uL3NpemUuanMnO1xuLyoqXG4gKiBAdHlwZWRlZiB7T2JqZWN0fSBPcHRpb25zXG4gKiBAcHJvcGVydHkge2ltcG9ydChcIi4vU291cmNlLmpzXCIpLkF0dHJpYnV0aW9uTGlrZX0gW2F0dHJpYnV0aW9uc11cbiAqIEBwcm9wZXJ0eSB7Ym9vbGVhbn0gW2F0dHJpYnV0aW9uc0NvbGxhcHNpYmxlPXRydWVdIEF0dHJpYnV0aW9ucyBhcmUgY29sbGFwc2libGUuXG4gKiBAcHJvcGVydHkge251bWJlcn0gW2NhY2hlU2l6ZV1cbiAqIEBwcm9wZXJ0eSB7Ym9vbGVhbn0gW29wYXF1ZT1mYWxzZV0gV2hldGhlciB0aGUgbGF5ZXIgaXMgb3BhcXVlLlxuICogQHByb3BlcnR5IHtudW1iZXJ9IFt0aWxlUGl4ZWxSYXRpb11cbiAqIEBwcm9wZXJ0eSB7aW1wb3J0KFwiLi4vcHJvai5qc1wiKS5Qcm9qZWN0aW9uTGlrZX0gW3Byb2plY3Rpb25dXG4gKiBAcHJvcGVydHkge2ltcG9ydChcIi4vU3RhdGUuanNcIikuZGVmYXVsdH0gW3N0YXRlXVxuICogQHByb3BlcnR5IHtpbXBvcnQoXCIuLi90aWxlZ3JpZC9UaWxlR3JpZC5qc1wiKS5kZWZhdWx0fSBbdGlsZUdyaWRdXG4gKiBAcHJvcGVydHkge2Jvb2xlYW59IFt3cmFwWD10cnVlXVxuICogQHByb3BlcnR5IHtudW1iZXJ9IFt0cmFuc2l0aW9uXVxuICogQHByb3BlcnR5IHtzdHJpbmd9IFtrZXldXG4gKiBAcHJvcGVydHkge251bWJlcn0gW3pEaXJlY3Rpb249MF1cbiAqL1xuXG4vKipcbiAqIEBjbGFzc2Rlc2NcbiAqIEFic3RyYWN0IGJhc2UgY2xhc3M7IG5vcm1hbGx5IG9ubHkgdXNlZCBmb3IgY3JlYXRpbmcgc3ViY2xhc3NlcyBhbmQgbm90XG4gKiBpbnN0YW50aWF0ZWQgaW4gYXBwcy5cbiAqIEJhc2UgY2xhc3MgZm9yIHNvdXJjZXMgcHJvdmlkaW5nIGltYWdlcyBkaXZpZGVkIGludG8gYSB0aWxlIGdyaWQuXG4gKiBAYWJzdHJhY3RcbiAqIEBhcGlcbiAqL1xuXG52YXIgVGlsZVNvdXJjZSA9XG4vKiogQGNsYXNzICovXG5mdW5jdGlvbiAoX3N1cGVyKSB7XG4gIF9fZXh0ZW5kcyhUaWxlU291cmNlLCBfc3VwZXIpO1xuICAvKipcbiAgICogQHBhcmFtIHtPcHRpb25zfSBvcHRpb25zIFNvdXJjZVRpbGUgc291cmNlIG9wdGlvbnMuXG4gICAqL1xuXG5cbiAgZnVuY3Rpb24gVGlsZVNvdXJjZShvcHRpb25zKSB7XG4gICAgdmFyIF90aGlzID0gX3N1cGVyLmNhbGwodGhpcywge1xuICAgICAgYXR0cmlidXRpb25zOiBvcHRpb25zLmF0dHJpYnV0aW9ucyxcbiAgICAgIGF0dHJpYnV0aW9uc0NvbGxhcHNpYmxlOiBvcHRpb25zLmF0dHJpYnV0aW9uc0NvbGxhcHNpYmxlLFxuICAgICAgcHJvamVjdGlvbjogb3B0aW9ucy5wcm9qZWN0aW9uLFxuICAgICAgc3RhdGU6IG9wdGlvbnMuc3RhdGUsXG4gICAgICB3cmFwWDogb3B0aW9ucy53cmFwWFxuICAgIH0pIHx8IHRoaXM7XG4gICAgLyoqXG4gICAgICogQHByaXZhdGVcbiAgICAgKiBAdHlwZSB7Ym9vbGVhbn1cbiAgICAgKi9cblxuXG4gICAgX3RoaXMub3BhcXVlXyA9IG9wdGlvbnMub3BhcXVlICE9PSB1bmRlZmluZWQgPyBvcHRpb25zLm9wYXF1ZSA6IGZhbHNlO1xuICAgIC8qKlxuICAgICAqIEBwcml2YXRlXG4gICAgICogQHR5cGUge251bWJlcn1cbiAgICAgKi9cblxuICAgIF90aGlzLnRpbGVQaXhlbFJhdGlvXyA9IG9wdGlvbnMudGlsZVBpeGVsUmF0aW8gIT09IHVuZGVmaW5lZCA/IG9wdGlvbnMudGlsZVBpeGVsUmF0aW8gOiAxO1xuICAgIC8qKlxuICAgICAqIEBwcm90ZWN0ZWRcbiAgICAgKiBAdHlwZSB7aW1wb3J0KFwiLi4vdGlsZWdyaWQvVGlsZUdyaWQuanNcIikuZGVmYXVsdH1cbiAgICAgKi9cblxuICAgIF90aGlzLnRpbGVHcmlkID0gb3B0aW9ucy50aWxlR3JpZCAhPT0gdW5kZWZpbmVkID8gb3B0aW9ucy50aWxlR3JpZCA6IG51bGw7XG4gICAgdmFyIHRpbGVTaXplID0gWzI1NiwgMjU2XTtcbiAgICB2YXIgdGlsZUdyaWQgPSBvcHRpb25zLnRpbGVHcmlkO1xuXG4gICAgaWYgKHRpbGVHcmlkKSB7XG4gICAgICB0b1NpemUodGlsZUdyaWQuZ2V0VGlsZVNpemUodGlsZUdyaWQuZ2V0TWluWm9vbSgpKSwgdGlsZVNpemUpO1xuICAgIH1cbiAgICAvKipcbiAgICAgKiBAcHJvdGVjdGVkXG4gICAgICogQHR5cGUge2ltcG9ydChcIi4uL1RpbGVDYWNoZS5qc1wiKS5kZWZhdWx0fVxuICAgICAqL1xuXG5cbiAgICBfdGhpcy50aWxlQ2FjaGUgPSBuZXcgVGlsZUNhY2hlKG9wdGlvbnMuY2FjaGVTaXplIHx8IDApO1xuICAgIC8qKlxuICAgICAqIEBwcm90ZWN0ZWRcbiAgICAgKiBAdHlwZSB7aW1wb3J0KFwiLi4vc2l6ZS5qc1wiKS5TaXplfVxuICAgICAqL1xuXG4gICAgX3RoaXMudG1wU2l6ZSA9IFswLCAwXTtcbiAgICAvKipcbiAgICAgKiBAcHJpdmF0ZVxuICAgICAqIEB0eXBlIHtzdHJpbmd9XG4gICAgICovXG5cbiAgICBfdGhpcy5rZXlfID0gb3B0aW9ucy5rZXkgfHwgJyc7XG4gICAgLyoqXG4gICAgICogQHByb3RlY3RlZFxuICAgICAqIEB0eXBlIHtpbXBvcnQoXCIuLi9UaWxlLmpzXCIpLk9wdGlvbnN9XG4gICAgICovXG5cbiAgICBfdGhpcy50aWxlT3B0aW9ucyA9IHtcbiAgICAgIHRyYW5zaXRpb246IG9wdGlvbnMudHJhbnNpdGlvblxuICAgIH07XG4gICAgLyoqXG4gICAgICogekRpcmVjdGlvbiBoaW50LCByZWFkIGJ5IHRoZSByZW5kZXJlci4gSW5kaWNhdGVzIHdoaWNoIHJlc29sdXRpb24gc2hvdWxkIGJlIHVzZWRcbiAgICAgKiBieSBhIHJlbmRlcmVyIGlmIHRoZSB2aWV3cyByZXNvbHV0aW9uIGRvZXMgbm90IG1hdGNoIGFueSByZXNvbHV0aW9uIG9mIHRoZSB0aWxlIHNvdXJjZS5cbiAgICAgKiBJZiAwLCB0aGUgbmVhcmVzdCByZXNvbHV0aW9uIHdpbGwgYmUgdXNlZC4gSWYgMSwgdGhlIG5lYXJlc3QgbG93ZXIgcmVzb2x1dGlvblxuICAgICAqIHdpbGwgYmUgdXNlZC4gSWYgLTEsIHRoZSBuZWFyZXN0IGhpZ2hlciByZXNvbHV0aW9uIHdpbGwgYmUgdXNlZC5cbiAgICAgKiBAdHlwZSB7bnVtYmVyfVxuICAgICAqL1xuXG4gICAgX3RoaXMuekRpcmVjdGlvbiA9IG9wdGlvbnMuekRpcmVjdGlvbiA/IG9wdGlvbnMuekRpcmVjdGlvbiA6IDA7XG4gICAgcmV0dXJuIF90aGlzO1xuICB9XG4gIC8qKlxuICAgKiBAcmV0dXJuIHtib29sZWFufSBDYW4gZXhwaXJlIGNhY2hlLlxuICAgKi9cblxuXG4gIFRpbGVTb3VyY2UucHJvdG90eXBlLmNhbkV4cGlyZUNhY2hlID0gZnVuY3Rpb24gKCkge1xuICAgIHJldHVybiB0aGlzLnRpbGVDYWNoZS5jYW5FeHBpcmVDYWNoZSgpO1xuICB9O1xuICAvKipcbiAgICogQHBhcmFtIHtpbXBvcnQoXCIuLi9wcm9qL1Byb2plY3Rpb24uanNcIikuZGVmYXVsdH0gcHJvamVjdGlvbiBQcm9qZWN0aW9uLlxuICAgKiBAcGFyYW0geyFPYmplY3Q8c3RyaW5nLCBib29sZWFuPn0gdXNlZFRpbGVzIFVzZWQgdGlsZXMuXG4gICAqL1xuXG5cbiAgVGlsZVNvdXJjZS5wcm90b3R5cGUuZXhwaXJlQ2FjaGUgPSBmdW5jdGlvbiAocHJvamVjdGlvbiwgdXNlZFRpbGVzKSB7XG4gICAgdmFyIHRpbGVDYWNoZSA9IHRoaXMuZ2V0VGlsZUNhY2hlRm9yUHJvamVjdGlvbihwcm9qZWN0aW9uKTtcblxuICAgIGlmICh0aWxlQ2FjaGUpIHtcbiAgICAgIHRpbGVDYWNoZS5leHBpcmVDYWNoZSh1c2VkVGlsZXMpO1xuICAgIH1cbiAgfTtcbiAgLyoqXG4gICAqIEBwYXJhbSB7aW1wb3J0KFwiLi4vcHJvai9Qcm9qZWN0aW9uLmpzXCIpLmRlZmF1bHR9IHByb2plY3Rpb24gUHJvamVjdGlvbi5cbiAgICogQHBhcmFtIHtudW1iZXJ9IHogWm9vbSBsZXZlbC5cbiAgICogQHBhcmFtIHtpbXBvcnQoXCIuLi9UaWxlUmFuZ2UuanNcIikuZGVmYXVsdH0gdGlsZVJhbmdlIFRpbGUgcmFuZ2UuXG4gICAqIEBwYXJhbSB7ZnVuY3Rpb24oaW1wb3J0KFwiLi4vVGlsZS5qc1wiKS5kZWZhdWx0KTooYm9vbGVhbnx2b2lkKX0gY2FsbGJhY2sgQ2FsbGVkIHdpdGggZWFjaFxuICAgKiAgICAgbG9hZGVkIHRpbGUuICBJZiB0aGUgY2FsbGJhY2sgcmV0dXJucyBgZmFsc2VgLCB0aGUgdGlsZSB3aWxsIG5vdCBiZVxuICAgKiAgICAgY29uc2lkZXJlZCBsb2FkZWQuXG4gICAqIEByZXR1cm4ge2Jvb2xlYW59IFRoZSB0aWxlIHJhbmdlIGlzIGZ1bGx5IGNvdmVyZWQgd2l0aCBsb2FkZWQgdGlsZXMuXG4gICAqL1xuXG5cbiAgVGlsZVNvdXJjZS5wcm90b3R5cGUuZm9yRWFjaExvYWRlZFRpbGUgPSBmdW5jdGlvbiAocHJvamVjdGlvbiwgeiwgdGlsZVJhbmdlLCBjYWxsYmFjaykge1xuICAgIHZhciB0aWxlQ2FjaGUgPSB0aGlzLmdldFRpbGVDYWNoZUZvclByb2plY3Rpb24ocHJvamVjdGlvbik7XG5cbiAgICBpZiAoIXRpbGVDYWNoZSkge1xuICAgICAgcmV0dXJuIGZhbHNlO1xuICAgIH1cblxuICAgIHZhciBjb3ZlcmVkID0gdHJ1ZTtcbiAgICB2YXIgdGlsZSwgdGlsZUNvb3JkS2V5LCBsb2FkZWQ7XG5cbiAgICBmb3IgKHZhciB4ID0gdGlsZVJhbmdlLm1pblg7IHggPD0gdGlsZVJhbmdlLm1heFg7ICsreCkge1xuICAgICAgZm9yICh2YXIgeSA9IHRpbGVSYW5nZS5taW5ZOyB5IDw9IHRpbGVSYW5nZS5tYXhZOyArK3kpIHtcbiAgICAgICAgdGlsZUNvb3JkS2V5ID0gZ2V0S2V5WlhZKHosIHgsIHkpO1xuICAgICAgICBsb2FkZWQgPSBmYWxzZTtcblxuICAgICAgICBpZiAodGlsZUNhY2hlLmNvbnRhaW5zS2V5KHRpbGVDb29yZEtleSkpIHtcbiAgICAgICAgICB0aWxlID1cbiAgICAgICAgICAvKiogQHR5cGUgeyFpbXBvcnQoXCIuLi9UaWxlLmpzXCIpLmRlZmF1bHR9ICovXG4gICAgICAgICAgdGlsZUNhY2hlLmdldCh0aWxlQ29vcmRLZXkpO1xuICAgICAgICAgIGxvYWRlZCA9IHRpbGUuZ2V0U3RhdGUoKSA9PT0gVGlsZVN0YXRlLkxPQURFRDtcblxuICAgICAgICAgIGlmIChsb2FkZWQpIHtcbiAgICAgICAgICAgIGxvYWRlZCA9IGNhbGxiYWNrKHRpbGUpICE9PSBmYWxzZTtcbiAgICAgICAgICB9XG4gICAgICAgIH1cblxuICAgICAgICBpZiAoIWxvYWRlZCkge1xuICAgICAgICAgIGNvdmVyZWQgPSBmYWxzZTtcbiAgICAgICAgfVxuICAgICAgfVxuICAgIH1cblxuICAgIHJldHVybiBjb3ZlcmVkO1xuICB9O1xuICAvKipcbiAgICogQHBhcmFtIHtpbXBvcnQoXCIuLi9wcm9qL1Byb2plY3Rpb24uanNcIikuZGVmYXVsdH0gcHJvamVjdGlvbiBQcm9qZWN0aW9uLlxuICAgKiBAcmV0dXJuIHtudW1iZXJ9IEd1dHRlci5cbiAgICovXG5cblxuICBUaWxlU291cmNlLnByb3RvdHlwZS5nZXRHdXR0ZXJGb3JQcm9qZWN0aW9uID0gZnVuY3Rpb24gKHByb2plY3Rpb24pIHtcbiAgICByZXR1cm4gMDtcbiAgfTtcbiAgLyoqXG4gICAqIFJldHVybiB0aGUga2V5IHRvIGJlIHVzZWQgZm9yIGFsbCB0aWxlcyBpbiB0aGUgc291cmNlLlxuICAgKiBAcmV0dXJuIHtzdHJpbmd9IFRoZSBrZXkgZm9yIGFsbCB0aWxlcy5cbiAgICogQHByb3RlY3RlZFxuICAgKi9cblxuXG4gIFRpbGVTb3VyY2UucHJvdG90eXBlLmdldEtleSA9IGZ1bmN0aW9uICgpIHtcbiAgICByZXR1cm4gdGhpcy5rZXlfO1xuICB9O1xuICAvKipcbiAgICogU2V0IHRoZSB2YWx1ZSB0byBiZSB1c2VkIGFzIHRoZSBrZXkgZm9yIGFsbCB0aWxlcyBpbiB0aGUgc291cmNlLlxuICAgKiBAcGFyYW0ge3N0cmluZ30ga2V5IFRoZSBrZXkgZm9yIHRpbGVzLlxuICAgKiBAcHJvdGVjdGVkXG4gICAqL1xuXG5cbiAgVGlsZVNvdXJjZS5wcm90b3R5cGUuc2V0S2V5ID0gZnVuY3Rpb24gKGtleSkge1xuICAgIGlmICh0aGlzLmtleV8gIT09IGtleSkge1xuICAgICAgdGhpcy5rZXlfID0ga2V5O1xuICAgICAgdGhpcy5jaGFuZ2VkKCk7XG4gICAgfVxuICB9O1xuICAvKipcbiAgICogQHBhcmFtIHtpbXBvcnQoXCIuLi9wcm9qL1Byb2plY3Rpb24uanNcIikuZGVmYXVsdH0gcHJvamVjdGlvbiBQcm9qZWN0aW9uLlxuICAgKiBAcmV0dXJuIHtib29sZWFufSBPcGFxdWUuXG4gICAqL1xuXG5cbiAgVGlsZVNvdXJjZS5wcm90b3R5cGUuZ2V0T3BhcXVlID0gZnVuY3Rpb24gKHByb2plY3Rpb24pIHtcbiAgICByZXR1cm4gdGhpcy5vcGFxdWVfO1xuICB9O1xuICAvKipcbiAgICogQHJldHVybiB7QXJyYXk8bnVtYmVyPn0gUmVzb2x1dGlvbnMuXG4gICAqL1xuXG5cbiAgVGlsZVNvdXJjZS5wcm90b3R5cGUuZ2V0UmVzb2x1dGlvbnMgPSBmdW5jdGlvbiAoKSB7XG4gICAgcmV0dXJuIHRoaXMudGlsZUdyaWQuZ2V0UmVzb2x1dGlvbnMoKTtcbiAgfTtcbiAgLyoqXG4gICAqIEBhYnN0cmFjdFxuICAgKiBAcGFyYW0ge251bWJlcn0geiBUaWxlIGNvb3JkaW5hdGUgei5cbiAgICogQHBhcmFtIHtudW1iZXJ9IHggVGlsZSBjb29yZGluYXRlIHguXG4gICAqIEBwYXJhbSB7bnVtYmVyfSB5IFRpbGUgY29vcmRpbmF0ZSB5LlxuICAgKiBAcGFyYW0ge251bWJlcn0gcGl4ZWxSYXRpbyBQaXhlbCByYXRpby5cbiAgICogQHBhcmFtIHtpbXBvcnQoXCIuLi9wcm9qL1Byb2plY3Rpb24uanNcIikuZGVmYXVsdH0gcHJvamVjdGlvbiBQcm9qZWN0aW9uLlxuICAgKiBAcmV0dXJuIHshaW1wb3J0KFwiLi4vVGlsZS5qc1wiKS5kZWZhdWx0fSBUaWxlLlxuICAgKi9cblxuXG4gIFRpbGVTb3VyY2UucHJvdG90eXBlLmdldFRpbGUgPSBmdW5jdGlvbiAoeiwgeCwgeSwgcGl4ZWxSYXRpbywgcHJvamVjdGlvbikge1xuICAgIHJldHVybiBhYnN0cmFjdCgpO1xuICB9O1xuICAvKipcbiAgICogUmV0dXJuIHRoZSB0aWxlIGdyaWQgb2YgdGhlIHRpbGUgc291cmNlLlxuICAgKiBAcmV0dXJuIHtpbXBvcnQoXCIuLi90aWxlZ3JpZC9UaWxlR3JpZC5qc1wiKS5kZWZhdWx0fSBUaWxlIGdyaWQuXG4gICAqIEBhcGlcbiAgICovXG5cblxuICBUaWxlU291cmNlLnByb3RvdHlwZS5nZXRUaWxlR3JpZCA9IGZ1bmN0aW9uICgpIHtcbiAgICByZXR1cm4gdGhpcy50aWxlR3JpZDtcbiAgfTtcbiAgLyoqXG4gICAqIEBwYXJhbSB7aW1wb3J0KFwiLi4vcHJvai9Qcm9qZWN0aW9uLmpzXCIpLmRlZmF1bHR9IHByb2plY3Rpb24gUHJvamVjdGlvbi5cbiAgICogQHJldHVybiB7IWltcG9ydChcIi4uL3RpbGVncmlkL1RpbGVHcmlkLmpzXCIpLmRlZmF1bHR9IFRpbGUgZ3JpZC5cbiAgICovXG5cblxuICBUaWxlU291cmNlLnByb3RvdHlwZS5nZXRUaWxlR3JpZEZvclByb2plY3Rpb24gPSBmdW5jdGlvbiAocHJvamVjdGlvbikge1xuICAgIGlmICghdGhpcy50aWxlR3JpZCkge1xuICAgICAgcmV0dXJuIGdldFRpbGVHcmlkRm9yUHJvamVjdGlvbihwcm9qZWN0aW9uKTtcbiAgICB9IGVsc2Uge1xuICAgICAgcmV0dXJuIHRoaXMudGlsZUdyaWQ7XG4gICAgfVxuICB9O1xuICAvKipcbiAgICogQHBhcmFtIHtpbXBvcnQoXCIuLi9wcm9qL1Byb2plY3Rpb24uanNcIikuZGVmYXVsdH0gcHJvamVjdGlvbiBQcm9qZWN0aW9uLlxuICAgKiBAcmV0dXJuIHtpbXBvcnQoXCIuLi9UaWxlQ2FjaGUuanNcIikuZGVmYXVsdH0gVGlsZSBjYWNoZS5cbiAgICogQHByb3RlY3RlZFxuICAgKi9cblxuXG4gIFRpbGVTb3VyY2UucHJvdG90eXBlLmdldFRpbGVDYWNoZUZvclByb2plY3Rpb24gPSBmdW5jdGlvbiAocHJvamVjdGlvbikge1xuICAgIGFzc2VydChlcXVpdmFsZW50KHRoaXMuZ2V0UHJvamVjdGlvbigpLCBwcm9qZWN0aW9uKSwgNjggLy8gQSBWZWN0b3JUaWxlIHNvdXJjZSBjYW4gb25seSBiZSByZW5kZXJlZCBpZiBpdCBoYXMgYSBwcm9qZWN0aW9uIGNvbXBhdGlibGUgd2l0aCB0aGUgdmlldyBwcm9qZWN0aW9uLlxuICAgICk7XG4gICAgcmV0dXJuIHRoaXMudGlsZUNhY2hlO1xuICB9O1xuICAvKipcbiAgICogR2V0IHRoZSB0aWxlIHBpeGVsIHJhdGlvIGZvciB0aGlzIHNvdXJjZS4gU3ViY2xhc3NlcyBtYXkgb3ZlcnJpZGUgdGhpc1xuICAgKiBtZXRob2QsIHdoaWNoIGlzIG1lYW50IHRvIHJldHVybiBhIHN1cHBvcnRlZCBwaXhlbCByYXRpbyB0aGF0IG1hdGNoZXMgdGhlXG4gICAqIHByb3ZpZGVkIGBwaXhlbFJhdGlvYCBhcyBjbG9zZSBhcyBwb3NzaWJsZS5cbiAgICogQHBhcmFtIHtudW1iZXJ9IHBpeGVsUmF0aW8gUGl4ZWwgcmF0aW8uXG4gICAqIEByZXR1cm4ge251bWJlcn0gVGlsZSBwaXhlbCByYXRpby5cbiAgICovXG5cblxuICBUaWxlU291cmNlLnByb3RvdHlwZS5nZXRUaWxlUGl4ZWxSYXRpbyA9IGZ1bmN0aW9uIChwaXhlbFJhdGlvKSB7XG4gICAgcmV0dXJuIHRoaXMudGlsZVBpeGVsUmF0aW9fO1xuICB9O1xuICAvKipcbiAgICogQHBhcmFtIHtudW1iZXJ9IHogWi5cbiAgICogQHBhcmFtIHtudW1iZXJ9IHBpeGVsUmF0aW8gUGl4ZWwgcmF0aW8uXG4gICAqIEBwYXJhbSB7aW1wb3J0KFwiLi4vcHJvai9Qcm9qZWN0aW9uLmpzXCIpLmRlZmF1bHR9IHByb2plY3Rpb24gUHJvamVjdGlvbi5cbiAgICogQHJldHVybiB7aW1wb3J0KFwiLi4vc2l6ZS5qc1wiKS5TaXplfSBUaWxlIHNpemUuXG4gICAqL1xuXG5cbiAgVGlsZVNvdXJjZS5wcm90b3R5cGUuZ2V0VGlsZVBpeGVsU2l6ZSA9IGZ1bmN0aW9uICh6LCBwaXhlbFJhdGlvLCBwcm9qZWN0aW9uKSB7XG4gICAgdmFyIHRpbGVHcmlkID0gdGhpcy5nZXRUaWxlR3JpZEZvclByb2plY3Rpb24ocHJvamVjdGlvbik7XG4gICAgdmFyIHRpbGVQaXhlbFJhdGlvID0gdGhpcy5nZXRUaWxlUGl4ZWxSYXRpbyhwaXhlbFJhdGlvKTtcbiAgICB2YXIgdGlsZVNpemUgPSB0b1NpemUodGlsZUdyaWQuZ2V0VGlsZVNpemUoeiksIHRoaXMudG1wU2l6ZSk7XG5cbiAgICBpZiAodGlsZVBpeGVsUmF0aW8gPT0gMSkge1xuICAgICAgcmV0dXJuIHRpbGVTaXplO1xuICAgIH0gZWxzZSB7XG4gICAgICByZXR1cm4gc2NhbGVTaXplKHRpbGVTaXplLCB0aWxlUGl4ZWxSYXRpbywgdGhpcy50bXBTaXplKTtcbiAgICB9XG4gIH07XG4gIC8qKlxuICAgKiBSZXR1cm5zIGEgdGlsZSBjb29yZGluYXRlIHdyYXBwZWQgYXJvdW5kIHRoZSB4LWF4aXMuIFdoZW4gdGhlIHRpbGUgY29vcmRpbmF0ZVxuICAgKiBpcyBvdXRzaWRlIHRoZSByZXNvbHV0aW9uIGFuZCBleHRlbnQgcmFuZ2Ugb2YgdGhlIHRpbGUgZ3JpZCwgYG51bGxgIHdpbGwgYmVcbiAgICogcmV0dXJuZWQuXG4gICAqIEBwYXJhbSB7aW1wb3J0KFwiLi4vdGlsZWNvb3JkLmpzXCIpLlRpbGVDb29yZH0gdGlsZUNvb3JkIFRpbGUgY29vcmRpbmF0ZS5cbiAgICogQHBhcmFtIHtpbXBvcnQoXCIuLi9wcm9qL1Byb2plY3Rpb24uanNcIikuZGVmYXVsdD19IG9wdF9wcm9qZWN0aW9uIFByb2plY3Rpb24uXG4gICAqIEByZXR1cm4ge2ltcG9ydChcIi4uL3RpbGVjb29yZC5qc1wiKS5UaWxlQ29vcmR9IFRpbGUgY29vcmRpbmF0ZSB0byBiZSBwYXNzZWQgdG8gdGhlIHRpbGVVcmxGdW5jdGlvbiBvclxuICAgKiAgICAgbnVsbCBpZiBubyB0aWxlIFVSTCBzaG91bGQgYmUgY3JlYXRlZCBmb3IgdGhlIHBhc3NlZCBgdGlsZUNvb3JkYC5cbiAgICovXG5cblxuICBUaWxlU291cmNlLnByb3RvdHlwZS5nZXRUaWxlQ29vcmRGb3JUaWxlVXJsRnVuY3Rpb24gPSBmdW5jdGlvbiAodGlsZUNvb3JkLCBvcHRfcHJvamVjdGlvbikge1xuICAgIHZhciBwcm9qZWN0aW9uID0gb3B0X3Byb2plY3Rpb24gIT09IHVuZGVmaW5lZCA/IG9wdF9wcm9qZWN0aW9uIDogdGhpcy5nZXRQcm9qZWN0aW9uKCk7XG4gICAgdmFyIHRpbGVHcmlkID0gdGhpcy5nZXRUaWxlR3JpZEZvclByb2plY3Rpb24ocHJvamVjdGlvbik7XG5cbiAgICBpZiAodGhpcy5nZXRXcmFwWCgpICYmIHByb2plY3Rpb24uaXNHbG9iYWwoKSkge1xuICAgICAgdGlsZUNvb3JkID0gd3JhcFgodGlsZUdyaWQsIHRpbGVDb29yZCwgcHJvamVjdGlvbik7XG4gICAgfVxuXG4gICAgcmV0dXJuIHdpdGhpbkV4dGVudEFuZFoodGlsZUNvb3JkLCB0aWxlR3JpZCkgPyB0aWxlQ29vcmQgOiBudWxsO1xuICB9O1xuICAvKipcbiAgICogUmVtb3ZlIGFsbCBjYWNoZWQgdGlsZXMgZnJvbSB0aGUgc291cmNlLiBUaGUgbmV4dCByZW5kZXIgY3ljbGUgd2lsbCBmZXRjaCBuZXcgdGlsZXMuXG4gICAqIEBhcGlcbiAgICovXG5cblxuICBUaWxlU291cmNlLnByb3RvdHlwZS5jbGVhciA9IGZ1bmN0aW9uICgpIHtcbiAgICB0aGlzLnRpbGVDYWNoZS5jbGVhcigpO1xuICB9O1xuXG4gIFRpbGVTb3VyY2UucHJvdG90eXBlLnJlZnJlc2ggPSBmdW5jdGlvbiAoKSB7XG4gICAgdGhpcy5jbGVhcigpO1xuXG4gICAgX3N1cGVyLnByb3RvdHlwZS5yZWZyZXNoLmNhbGwodGhpcyk7XG4gIH07XG4gIC8qKlxuICAgKiBJbmNyZWFzZXMgdGhlIGNhY2hlIHNpemUgaWYgbmVlZGVkXG4gICAqIEBwYXJhbSB7bnVtYmVyfSB0aWxlQ291bnQgTWluaW11bSBudW1iZXIgb2YgdGlsZXMgbmVlZGVkLlxuICAgKiBAcGFyYW0ge2ltcG9ydChcIi4uL3Byb2ovUHJvamVjdGlvbi5qc1wiKS5kZWZhdWx0fSBwcm9qZWN0aW9uIFByb2plY3Rpb24uXG4gICAqL1xuXG5cbiAgVGlsZVNvdXJjZS5wcm90b3R5cGUudXBkYXRlQ2FjaGVTaXplID0gZnVuY3Rpb24gKHRpbGVDb3VudCwgcHJvamVjdGlvbikge1xuICAgIHZhciB0aWxlQ2FjaGUgPSB0aGlzLmdldFRpbGVDYWNoZUZvclByb2plY3Rpb24ocHJvamVjdGlvbik7XG5cbiAgICBpZiAodGlsZUNvdW50ID4gdGlsZUNhY2hlLmhpZ2hXYXRlck1hcmspIHtcbiAgICAgIHRpbGVDYWNoZS5oaWdoV2F0ZXJNYXJrID0gdGlsZUNvdW50O1xuICAgIH1cbiAgfTtcbiAgLyoqXG4gICAqIE1hcmtzIGEgdGlsZSBjb29yZCBhcyBiZWluZyB1c2VkLCB3aXRob3V0IHRyaWdnZXJpbmcgYSBsb2FkLlxuICAgKiBAYWJzdHJhY3RcbiAgICogQHBhcmFtIHtudW1iZXJ9IHogVGlsZSBjb29yZGluYXRlIHouXG4gICAqIEBwYXJhbSB7bnVtYmVyfSB4IFRpbGUgY29vcmRpbmF0ZSB4LlxuICAgKiBAcGFyYW0ge251bWJlcn0geSBUaWxlIGNvb3JkaW5hdGUgeS5cbiAgICogQHBhcmFtIHtpbXBvcnQoXCIuLi9wcm9qL1Byb2plY3Rpb24uanNcIikuZGVmYXVsdH0gcHJvamVjdGlvbiBQcm9qZWN0aW9uLlxuICAgKi9cblxuXG4gIFRpbGVTb3VyY2UucHJvdG90eXBlLnVzZVRpbGUgPSBmdW5jdGlvbiAoeiwgeCwgeSwgcHJvamVjdGlvbikge307XG5cbiAgcmV0dXJuIFRpbGVTb3VyY2U7XG59KFNvdXJjZSk7XG4vKipcbiAqIEBjbGFzc2Rlc2NcbiAqIEV2ZW50cyBlbWl0dGVkIGJ5IHtAbGluayBtb2R1bGU6b2wvc291cmNlL1RpbGV+VGlsZVNvdXJjZX0gaW5zdGFuY2VzIGFyZSBpbnN0YW5jZXMgb2YgdGhpc1xuICogdHlwZS5cbiAqL1xuXG5cbnZhciBUaWxlU291cmNlRXZlbnQgPVxuLyoqIEBjbGFzcyAqL1xuZnVuY3Rpb24gKF9zdXBlcikge1xuICBfX2V4dGVuZHMoVGlsZVNvdXJjZUV2ZW50LCBfc3VwZXIpO1xuICAvKipcbiAgICogQHBhcmFtIHtzdHJpbmd9IHR5cGUgVHlwZS5cbiAgICogQHBhcmFtIHtpbXBvcnQoXCIuLi9UaWxlLmpzXCIpLmRlZmF1bHR9IHRpbGUgVGhlIHRpbGUuXG4gICAqL1xuXG5cbiAgZnVuY3Rpb24gVGlsZVNvdXJjZUV2ZW50KHR5cGUsIHRpbGUpIHtcbiAgICB2YXIgX3RoaXMgPSBfc3VwZXIuY2FsbCh0aGlzLCB0eXBlKSB8fCB0aGlzO1xuICAgIC8qKlxuICAgICAqIFRoZSB0aWxlIHJlbGF0ZWQgdG8gdGhlIGV2ZW50LlxuICAgICAqIEB0eXBlIHtpbXBvcnQoXCIuLi9UaWxlLmpzXCIpLmRlZmF1bHR9XG4gICAgICogQGFwaVxuICAgICAqL1xuXG5cbiAgICBfdGhpcy50aWxlID0gdGlsZTtcbiAgICByZXR1cm4gX3RoaXM7XG4gIH1cblxuICByZXR1cm4gVGlsZVNvdXJjZUV2ZW50O1xufShFdmVudCk7XG5cbmV4cG9ydCB7IFRpbGVTb3VyY2VFdmVudCB9O1xuZXhwb3J0IGRlZmF1bHQgVGlsZVNvdXJjZTsiLCIvKipcbiAqIEBtb2R1bGUgb2wvdGlsZXVybGZ1bmN0aW9uXG4gKi9cbmltcG9ydCB7IGFzc2VydCB9IGZyb20gJy4vYXNzZXJ0cy5qcyc7XG5pbXBvcnQgeyBtb2R1bG8gfSBmcm9tICcuL21hdGguanMnO1xuaW1wb3J0IHsgaGFzaCBhcyB0aWxlQ29vcmRIYXNoIH0gZnJvbSAnLi90aWxlY29vcmQuanMnO1xuLyoqXG4gKiBAcGFyYW0ge3N0cmluZ30gdGVtcGxhdGUgVGVtcGxhdGUuXG4gKiBAcGFyYW0ge2ltcG9ydChcIi4vdGlsZWdyaWQvVGlsZUdyaWQuanNcIikuZGVmYXVsdH0gdGlsZUdyaWQgVGlsZSBncmlkLlxuICogQHJldHVybiB7aW1wb3J0KFwiLi9UaWxlLmpzXCIpLlVybEZ1bmN0aW9ufSBUaWxlIFVSTCBmdW5jdGlvbi5cbiAqL1xuXG5leHBvcnQgZnVuY3Rpb24gY3JlYXRlRnJvbVRlbXBsYXRlKHRlbXBsYXRlLCB0aWxlR3JpZCkge1xuICB2YXIgelJlZ0V4ID0gL1xce3pcXH0vZztcbiAgdmFyIHhSZWdFeCA9IC9cXHt4XFx9L2c7XG4gIHZhciB5UmVnRXggPSAvXFx7eVxcfS9nO1xuICB2YXIgZGFzaFlSZWdFeCA9IC9cXHsteVxcfS9nO1xuICByZXR1cm4gKFxuICAgIC8qKlxuICAgICAqIEBwYXJhbSB7aW1wb3J0KFwiLi90aWxlY29vcmQuanNcIikuVGlsZUNvb3JkfSB0aWxlQ29vcmQgVGlsZSBDb29yZGluYXRlLlxuICAgICAqIEBwYXJhbSB7bnVtYmVyfSBwaXhlbFJhdGlvIFBpeGVsIHJhdGlvLlxuICAgICAqIEBwYXJhbSB7aW1wb3J0KFwiLi9wcm9qL1Byb2plY3Rpb24uanNcIikuZGVmYXVsdH0gcHJvamVjdGlvbiBQcm9qZWN0aW9uLlxuICAgICAqIEByZXR1cm4ge3N0cmluZ3x1bmRlZmluZWR9IFRpbGUgVVJMLlxuICAgICAqL1xuICAgIGZ1bmN0aW9uICh0aWxlQ29vcmQsIHBpeGVsUmF0aW8sIHByb2plY3Rpb24pIHtcbiAgICAgIGlmICghdGlsZUNvb3JkKSB7XG4gICAgICAgIHJldHVybiB1bmRlZmluZWQ7XG4gICAgICB9IGVsc2Uge1xuICAgICAgICByZXR1cm4gdGVtcGxhdGUucmVwbGFjZSh6UmVnRXgsIHRpbGVDb29yZFswXS50b1N0cmluZygpKS5yZXBsYWNlKHhSZWdFeCwgdGlsZUNvb3JkWzFdLnRvU3RyaW5nKCkpLnJlcGxhY2UoeVJlZ0V4LCB0aWxlQ29vcmRbMl0udG9TdHJpbmcoKSkucmVwbGFjZShkYXNoWVJlZ0V4LCBmdW5jdGlvbiAoKSB7XG4gICAgICAgICAgdmFyIHogPSB0aWxlQ29vcmRbMF07XG4gICAgICAgICAgdmFyIHJhbmdlID0gdGlsZUdyaWQuZ2V0RnVsbFRpbGVSYW5nZSh6KTtcbiAgICAgICAgICBhc3NlcnQocmFuZ2UsIDU1KTsgLy8gVGhlIHsteX0gcGxhY2Vob2xkZXIgcmVxdWlyZXMgYSB0aWxlIGdyaWQgd2l0aCBleHRlbnRcblxuICAgICAgICAgIHZhciB5ID0gcmFuZ2UuZ2V0SGVpZ2h0KCkgLSB0aWxlQ29vcmRbMl0gLSAxO1xuICAgICAgICAgIHJldHVybiB5LnRvU3RyaW5nKCk7XG4gICAgICAgIH0pO1xuICAgICAgfVxuICAgIH1cbiAgKTtcbn1cbi8qKlxuICogQHBhcmFtIHtBcnJheTxzdHJpbmc+fSB0ZW1wbGF0ZXMgVGVtcGxhdGVzLlxuICogQHBhcmFtIHtpbXBvcnQoXCIuL3RpbGVncmlkL1RpbGVHcmlkLmpzXCIpLmRlZmF1bHR9IHRpbGVHcmlkIFRpbGUgZ3JpZC5cbiAqIEByZXR1cm4ge2ltcG9ydChcIi4vVGlsZS5qc1wiKS5VcmxGdW5jdGlvbn0gVGlsZSBVUkwgZnVuY3Rpb24uXG4gKi9cblxuZXhwb3J0IGZ1bmN0aW9uIGNyZWF0ZUZyb21UZW1wbGF0ZXModGVtcGxhdGVzLCB0aWxlR3JpZCkge1xuICB2YXIgbGVuID0gdGVtcGxhdGVzLmxlbmd0aDtcbiAgdmFyIHRpbGVVcmxGdW5jdGlvbnMgPSBuZXcgQXJyYXkobGVuKTtcblxuICBmb3IgKHZhciBpID0gMDsgaSA8IGxlbjsgKytpKSB7XG4gICAgdGlsZVVybEZ1bmN0aW9uc1tpXSA9IGNyZWF0ZUZyb21UZW1wbGF0ZSh0ZW1wbGF0ZXNbaV0sIHRpbGVHcmlkKTtcbiAgfVxuXG4gIHJldHVybiBjcmVhdGVGcm9tVGlsZVVybEZ1bmN0aW9ucyh0aWxlVXJsRnVuY3Rpb25zKTtcbn1cbi8qKlxuICogQHBhcmFtIHtBcnJheTxpbXBvcnQoXCIuL1RpbGUuanNcIikuVXJsRnVuY3Rpb24+fSB0aWxlVXJsRnVuY3Rpb25zIFRpbGUgVVJMIEZ1bmN0aW9ucy5cbiAqIEByZXR1cm4ge2ltcG9ydChcIi4vVGlsZS5qc1wiKS5VcmxGdW5jdGlvbn0gVGlsZSBVUkwgZnVuY3Rpb24uXG4gKi9cblxuZXhwb3J0IGZ1bmN0aW9uIGNyZWF0ZUZyb21UaWxlVXJsRnVuY3Rpb25zKHRpbGVVcmxGdW5jdGlvbnMpIHtcbiAgaWYgKHRpbGVVcmxGdW5jdGlvbnMubGVuZ3RoID09PSAxKSB7XG4gICAgcmV0dXJuIHRpbGVVcmxGdW5jdGlvbnNbMF07XG4gIH1cblxuICByZXR1cm4gKFxuICAgIC8qKlxuICAgICAqIEBwYXJhbSB7aW1wb3J0KFwiLi90aWxlY29vcmQuanNcIikuVGlsZUNvb3JkfSB0aWxlQ29vcmQgVGlsZSBDb29yZGluYXRlLlxuICAgICAqIEBwYXJhbSB7bnVtYmVyfSBwaXhlbFJhdGlvIFBpeGVsIHJhdGlvLlxuICAgICAqIEBwYXJhbSB7aW1wb3J0KFwiLi9wcm9qL1Byb2plY3Rpb24uanNcIikuZGVmYXVsdH0gcHJvamVjdGlvbiBQcm9qZWN0aW9uLlxuICAgICAqIEByZXR1cm4ge3N0cmluZ3x1bmRlZmluZWR9IFRpbGUgVVJMLlxuICAgICAqL1xuICAgIGZ1bmN0aW9uICh0aWxlQ29vcmQsIHBpeGVsUmF0aW8sIHByb2plY3Rpb24pIHtcbiAgICAgIGlmICghdGlsZUNvb3JkKSB7XG4gICAgICAgIHJldHVybiB1bmRlZmluZWQ7XG4gICAgICB9IGVsc2Uge1xuICAgICAgICB2YXIgaCA9IHRpbGVDb29yZEhhc2godGlsZUNvb3JkKTtcbiAgICAgICAgdmFyIGluZGV4ID0gbW9kdWxvKGgsIHRpbGVVcmxGdW5jdGlvbnMubGVuZ3RoKTtcbiAgICAgICAgcmV0dXJuIHRpbGVVcmxGdW5jdGlvbnNbaW5kZXhdKHRpbGVDb29yZCwgcGl4ZWxSYXRpbywgcHJvamVjdGlvbik7XG4gICAgICB9XG4gICAgfVxuICApO1xufVxuLyoqXG4gKiBAcGFyYW0ge2ltcG9ydChcIi4vdGlsZWNvb3JkLmpzXCIpLlRpbGVDb29yZH0gdGlsZUNvb3JkIFRpbGUgY29vcmRpbmF0ZS5cbiAqIEBwYXJhbSB7bnVtYmVyfSBwaXhlbFJhdGlvIFBpeGVsIHJhdGlvLlxuICogQHBhcmFtIHtpbXBvcnQoXCIuL3Byb2ovUHJvamVjdGlvbi5qc1wiKS5kZWZhdWx0fSBwcm9qZWN0aW9uIFByb2plY3Rpb24uXG4gKiBAcmV0dXJuIHtzdHJpbmd8dW5kZWZpbmVkfSBUaWxlIFVSTC5cbiAqL1xuXG5leHBvcnQgZnVuY3Rpb24gbnVsbFRpbGVVcmxGdW5jdGlvbih0aWxlQ29vcmQsIHBpeGVsUmF0aW8sIHByb2plY3Rpb24pIHtcbiAgcmV0dXJuIHVuZGVmaW5lZDtcbn1cbi8qKlxuICogQHBhcmFtIHtzdHJpbmd9IHVybCBVUkwuXG4gKiBAcmV0dXJuIHtBcnJheTxzdHJpbmc+fSBBcnJheSBvZiB1cmxzLlxuICovXG5cbmV4cG9ydCBmdW5jdGlvbiBleHBhbmRVcmwodXJsKSB7XG4gIHZhciB1cmxzID0gW107XG4gIHZhciBtYXRjaCA9IC9cXHsoW2Etel0pLShbYS16XSlcXH0vLmV4ZWModXJsKTtcblxuICBpZiAobWF0Y2gpIHtcbiAgICAvLyBjaGFyIHJhbmdlXG4gICAgdmFyIHN0YXJ0Q2hhckNvZGUgPSBtYXRjaFsxXS5jaGFyQ29kZUF0KDApO1xuICAgIHZhciBzdG9wQ2hhckNvZGUgPSBtYXRjaFsyXS5jaGFyQ29kZUF0KDApO1xuICAgIHZhciBjaGFyQ29kZSA9IHZvaWQgMDtcblxuICAgIGZvciAoY2hhckNvZGUgPSBzdGFydENoYXJDb2RlOyBjaGFyQ29kZSA8PSBzdG9wQ2hhckNvZGU7ICsrY2hhckNvZGUpIHtcbiAgICAgIHVybHMucHVzaCh1cmwucmVwbGFjZShtYXRjaFswXSwgU3RyaW5nLmZyb21DaGFyQ29kZShjaGFyQ29kZSkpKTtcbiAgICB9XG5cbiAgICByZXR1cm4gdXJscztcbiAgfVxuXG4gIG1hdGNoID0gL1xceyhcXGQrKS0oXFxkKylcXH0vLmV4ZWModXJsKTtcblxuICBpZiAobWF0Y2gpIHtcbiAgICAvLyBudW1iZXIgcmFuZ2VcbiAgICB2YXIgc3RvcF8xID0gcGFyc2VJbnQobWF0Y2hbMl0sIDEwKTtcblxuICAgIGZvciAodmFyIGkgPSBwYXJzZUludChtYXRjaFsxXSwgMTApOyBpIDw9IHN0b3BfMTsgaSsrKSB7XG4gICAgICB1cmxzLnB1c2godXJsLnJlcGxhY2UobWF0Y2hbMF0sIGkudG9TdHJpbmcoKSkpO1xuICAgIH1cblxuICAgIHJldHVybiB1cmxzO1xuICB9XG5cbiAgdXJscy5wdXNoKHVybCk7XG4gIHJldHVybiB1cmxzO1xufSIsInZhciBfX2V4dGVuZHMgPSB0aGlzICYmIHRoaXMuX19leHRlbmRzIHx8IGZ1bmN0aW9uICgpIHtcbiAgdmFyIF9leHRlbmRTdGF0aWNzID0gZnVuY3Rpb24gZXh0ZW5kU3RhdGljcyhkLCBiKSB7XG4gICAgX2V4dGVuZFN0YXRpY3MgPSBPYmplY3Quc2V0UHJvdG90eXBlT2YgfHwge1xuICAgICAgX19wcm90b19fOiBbXVxuICAgIH0gaW5zdGFuY2VvZiBBcnJheSAmJiBmdW5jdGlvbiAoZCwgYikge1xuICAgICAgZC5fX3Byb3RvX18gPSBiO1xuICAgIH0gfHwgZnVuY3Rpb24gKGQsIGIpIHtcbiAgICAgIGZvciAodmFyIHAgaW4gYikge1xuICAgICAgICBpZiAoT2JqZWN0LnByb3RvdHlwZS5oYXNPd25Qcm9wZXJ0eS5jYWxsKGIsIHApKSBkW3BdID0gYltwXTtcbiAgICAgIH1cbiAgICB9O1xuXG4gICAgcmV0dXJuIF9leHRlbmRTdGF0aWNzKGQsIGIpO1xuICB9O1xuXG4gIHJldHVybiBmdW5jdGlvbiAoZCwgYikge1xuICAgIF9leHRlbmRTdGF0aWNzKGQsIGIpO1xuXG4gICAgZnVuY3Rpb24gX18oKSB7XG4gICAgICB0aGlzLmNvbnN0cnVjdG9yID0gZDtcbiAgICB9XG5cbiAgICBkLnByb3RvdHlwZSA9IGIgPT09IG51bGwgPyBPYmplY3QuY3JlYXRlKGIpIDogKF9fLnByb3RvdHlwZSA9IGIucHJvdG90eXBlLCBuZXcgX18oKSk7XG4gIH07XG59KCk7XG4vKipcbiAqIEBtb2R1bGUgb2wvc291cmNlL1VybFRpbGVcbiAqL1xuXG5cbmltcG9ydCBUaWxlRXZlbnRUeXBlIGZyb20gJy4vVGlsZUV2ZW50VHlwZS5qcyc7XG5pbXBvcnQgVGlsZVNvdXJjZSwgeyBUaWxlU291cmNlRXZlbnQgfSBmcm9tICcuL1RpbGUuanMnO1xuaW1wb3J0IFRpbGVTdGF0ZSBmcm9tICcuLi9UaWxlU3RhdGUuanMnO1xuaW1wb3J0IHsgY3JlYXRlRnJvbVRlbXBsYXRlcywgZXhwYW5kVXJsIH0gZnJvbSAnLi4vdGlsZXVybGZ1bmN0aW9uLmpzJztcbmltcG9ydCB7IGdldEtleVpYWSB9IGZyb20gJy4uL3RpbGVjb29yZC5qcyc7XG5pbXBvcnQgeyBnZXRVaWQgfSBmcm9tICcuLi91dGlsLmpzJztcbi8qKlxuICogQHR5cGVkZWYge09iamVjdH0gT3B0aW9uc1xuICogQHByb3BlcnR5IHtpbXBvcnQoXCIuL1NvdXJjZS5qc1wiKS5BdHRyaWJ1dGlvbkxpa2V9IFthdHRyaWJ1dGlvbnNdXG4gKiBAcHJvcGVydHkge2Jvb2xlYW59IFthdHRyaWJ1dGlvbnNDb2xsYXBzaWJsZT10cnVlXSBBdHRyaWJ1dGlvbnMgYXJlIGNvbGxhcHNpYmxlLlxuICogQHByb3BlcnR5IHtudW1iZXJ9IFtjYWNoZVNpemVdXG4gKiBAcHJvcGVydHkge2Jvb2xlYW59IFtvcGFxdWU9ZmFsc2VdIFdoZXRoZXIgdGhlIGxheWVyIGlzIG9wYXF1ZS5cbiAqIEBwcm9wZXJ0eSB7aW1wb3J0KFwiLi4vcHJvai5qc1wiKS5Qcm9qZWN0aW9uTGlrZX0gW3Byb2plY3Rpb25dXG4gKiBAcHJvcGVydHkge2ltcG9ydChcIi4vU3RhdGUuanNcIikuZGVmYXVsdH0gW3N0YXRlXVxuICogQHByb3BlcnR5IHtpbXBvcnQoXCIuLi90aWxlZ3JpZC9UaWxlR3JpZC5qc1wiKS5kZWZhdWx0fSBbdGlsZUdyaWRdXG4gKiBAcHJvcGVydHkge2ltcG9ydChcIi4uL1RpbGUuanNcIikuTG9hZEZ1bmN0aW9ufSB0aWxlTG9hZEZ1bmN0aW9uXG4gKiBAcHJvcGVydHkge251bWJlcn0gW3RpbGVQaXhlbFJhdGlvXVxuICogQHByb3BlcnR5IHtpbXBvcnQoXCIuLi9UaWxlLmpzXCIpLlVybEZ1bmN0aW9ufSBbdGlsZVVybEZ1bmN0aW9uXVxuICogQHByb3BlcnR5IHtzdHJpbmd9IFt1cmxdXG4gKiBAcHJvcGVydHkge0FycmF5PHN0cmluZz59IFt1cmxzXVxuICogQHByb3BlcnR5IHtib29sZWFufSBbd3JhcFg9dHJ1ZV1cbiAqIEBwcm9wZXJ0eSB7bnVtYmVyfSBbdHJhbnNpdGlvbl1cbiAqIEBwcm9wZXJ0eSB7c3RyaW5nfSBba2V5XVxuICogQHByb3BlcnR5IHtudW1iZXJ9IFt6RGlyZWN0aW9uPTBdXG4gKi9cblxuLyoqXG4gKiBAY2xhc3NkZXNjXG4gKiBCYXNlIGNsYXNzIGZvciBzb3VyY2VzIHByb3ZpZGluZyB0aWxlcyBkaXZpZGVkIGludG8gYSB0aWxlIGdyaWQgb3ZlciBodHRwLlxuICpcbiAqIEBmaXJlcyBpbXBvcnQoXCIuL1RpbGUuanNcIikuVGlsZVNvdXJjZUV2ZW50XG4gKi9cblxudmFyIFVybFRpbGUgPVxuLyoqIEBjbGFzcyAqL1xuZnVuY3Rpb24gKF9zdXBlcikge1xuICBfX2V4dGVuZHMoVXJsVGlsZSwgX3N1cGVyKTtcbiAgLyoqXG4gICAqIEBwYXJhbSB7T3B0aW9uc30gb3B0aW9ucyBJbWFnZSB0aWxlIG9wdGlvbnMuXG4gICAqL1xuXG5cbiAgZnVuY3Rpb24gVXJsVGlsZShvcHRpb25zKSB7XG4gICAgdmFyIF90aGlzID0gX3N1cGVyLmNhbGwodGhpcywge1xuICAgICAgYXR0cmlidXRpb25zOiBvcHRpb25zLmF0dHJpYnV0aW9ucyxcbiAgICAgIGNhY2hlU2l6ZTogb3B0aW9ucy5jYWNoZVNpemUsXG4gICAgICBvcGFxdWU6IG9wdGlvbnMub3BhcXVlLFxuICAgICAgcHJvamVjdGlvbjogb3B0aW9ucy5wcm9qZWN0aW9uLFxuICAgICAgc3RhdGU6IG9wdGlvbnMuc3RhdGUsXG4gICAgICB0aWxlR3JpZDogb3B0aW9ucy50aWxlR3JpZCxcbiAgICAgIHRpbGVQaXhlbFJhdGlvOiBvcHRpb25zLnRpbGVQaXhlbFJhdGlvLFxuICAgICAgd3JhcFg6IG9wdGlvbnMud3JhcFgsXG4gICAgICB0cmFuc2l0aW9uOiBvcHRpb25zLnRyYW5zaXRpb24sXG4gICAgICBrZXk6IG9wdGlvbnMua2V5LFxuICAgICAgYXR0cmlidXRpb25zQ29sbGFwc2libGU6IG9wdGlvbnMuYXR0cmlidXRpb25zQ29sbGFwc2libGUsXG4gICAgICB6RGlyZWN0aW9uOiBvcHRpb25zLnpEaXJlY3Rpb25cbiAgICB9KSB8fCB0aGlzO1xuICAgIC8qKlxuICAgICAqIEBwcml2YXRlXG4gICAgICogQHR5cGUge2Jvb2xlYW59XG4gICAgICovXG5cblxuICAgIF90aGlzLmdlbmVyYXRlVGlsZVVybEZ1bmN0aW9uXyA9IF90aGlzLnRpbGVVcmxGdW5jdGlvbiA9PT0gVXJsVGlsZS5wcm90b3R5cGUudGlsZVVybEZ1bmN0aW9uO1xuICAgIC8qKlxuICAgICAqIEBwcm90ZWN0ZWRcbiAgICAgKiBAdHlwZSB7aW1wb3J0KFwiLi4vVGlsZS5qc1wiKS5Mb2FkRnVuY3Rpb259XG4gICAgICovXG5cbiAgICBfdGhpcy50aWxlTG9hZEZ1bmN0aW9uID0gb3B0aW9ucy50aWxlTG9hZEZ1bmN0aW9uO1xuXG4gICAgaWYgKG9wdGlvbnMudGlsZVVybEZ1bmN0aW9uKSB7XG4gICAgICBfdGhpcy50aWxlVXJsRnVuY3Rpb24gPSBvcHRpb25zLnRpbGVVcmxGdW5jdGlvbjtcbiAgICB9XG4gICAgLyoqXG4gICAgICogQHByb3RlY3RlZFxuICAgICAqIEB0eXBlIHshQXJyYXk8c3RyaW5nPnxudWxsfVxuICAgICAqL1xuXG5cbiAgICBfdGhpcy51cmxzID0gbnVsbDtcblxuICAgIGlmIChvcHRpb25zLnVybHMpIHtcbiAgICAgIF90aGlzLnNldFVybHMob3B0aW9ucy51cmxzKTtcbiAgICB9IGVsc2UgaWYgKG9wdGlvbnMudXJsKSB7XG4gICAgICBfdGhpcy5zZXRVcmwob3B0aW9ucy51cmwpO1xuICAgIH1cbiAgICAvKipcbiAgICAgKiBAcHJpdmF0ZVxuICAgICAqIEB0eXBlIHshT2JqZWN0PHN0cmluZywgYm9vbGVhbj59XG4gICAgICovXG5cblxuICAgIF90aGlzLnRpbGVMb2FkaW5nS2V5c18gPSB7fTtcbiAgICByZXR1cm4gX3RoaXM7XG4gIH1cbiAgLyoqXG4gICAqIFJldHVybiB0aGUgdGlsZSBsb2FkIGZ1bmN0aW9uIG9mIHRoZSBzb3VyY2UuXG4gICAqIEByZXR1cm4ge2ltcG9ydChcIi4uL1RpbGUuanNcIikuTG9hZEZ1bmN0aW9ufSBUaWxlTG9hZEZ1bmN0aW9uXG4gICAqIEBhcGlcbiAgICovXG5cblxuICBVcmxUaWxlLnByb3RvdHlwZS5nZXRUaWxlTG9hZEZ1bmN0aW9uID0gZnVuY3Rpb24gKCkge1xuICAgIHJldHVybiB0aGlzLnRpbGVMb2FkRnVuY3Rpb247XG4gIH07XG4gIC8qKlxuICAgKiBSZXR1cm4gdGhlIHRpbGUgVVJMIGZ1bmN0aW9uIG9mIHRoZSBzb3VyY2UuXG4gICAqIEByZXR1cm4ge2ltcG9ydChcIi4uL1RpbGUuanNcIikuVXJsRnVuY3Rpb259IFRpbGVVcmxGdW5jdGlvblxuICAgKiBAYXBpXG4gICAqL1xuXG5cbiAgVXJsVGlsZS5wcm90b3R5cGUuZ2V0VGlsZVVybEZ1bmN0aW9uID0gZnVuY3Rpb24gKCkge1xuICAgIHJldHVybiBPYmplY3QuZ2V0UHJvdG90eXBlT2YodGhpcykudGlsZVVybEZ1bmN0aW9uID09PSB0aGlzLnRpbGVVcmxGdW5jdGlvbiA/IHRoaXMudGlsZVVybEZ1bmN0aW9uLmJpbmQodGhpcykgOiB0aGlzLnRpbGVVcmxGdW5jdGlvbjtcbiAgfTtcbiAgLyoqXG4gICAqIFJldHVybiB0aGUgVVJMcyB1c2VkIGZvciB0aGlzIHNvdXJjZS5cbiAgICogV2hlbiBhIHRpbGVVcmxGdW5jdGlvbiBpcyB1c2VkIGluc3RlYWQgb2YgdXJsIG9yIHVybHMsXG4gICAqIG51bGwgd2lsbCBiZSByZXR1cm5lZC5cbiAgICogQHJldHVybiB7IUFycmF5PHN0cmluZz58bnVsbH0gVVJMcy5cbiAgICogQGFwaVxuICAgKi9cblxuXG4gIFVybFRpbGUucHJvdG90eXBlLmdldFVybHMgPSBmdW5jdGlvbiAoKSB7XG4gICAgcmV0dXJuIHRoaXMudXJscztcbiAgfTtcbiAgLyoqXG4gICAqIEhhbmRsZSB0aWxlIGNoYW5nZSBldmVudHMuXG4gICAqIEBwYXJhbSB7aW1wb3J0KFwiLi4vZXZlbnRzL0V2ZW50LmpzXCIpLmRlZmF1bHR9IGV2ZW50IEV2ZW50LlxuICAgKiBAcHJvdGVjdGVkXG4gICAqL1xuXG5cbiAgVXJsVGlsZS5wcm90b3R5cGUuaGFuZGxlVGlsZUNoYW5nZSA9IGZ1bmN0aW9uIChldmVudCkge1xuICAgIHZhciB0aWxlID1cbiAgICAvKiogQHR5cGUge2ltcG9ydChcIi4uL1RpbGUuanNcIikuZGVmYXVsdH0gKi9cbiAgICBldmVudC50YXJnZXQ7XG4gICAgdmFyIHVpZCA9IGdldFVpZCh0aWxlKTtcbiAgICB2YXIgdGlsZVN0YXRlID0gdGlsZS5nZXRTdGF0ZSgpO1xuICAgIHZhciB0eXBlO1xuXG4gICAgaWYgKHRpbGVTdGF0ZSA9PSBUaWxlU3RhdGUuTE9BRElORykge1xuICAgICAgdGhpcy50aWxlTG9hZGluZ0tleXNfW3VpZF0gPSB0cnVlO1xuICAgICAgdHlwZSA9IFRpbGVFdmVudFR5cGUuVElMRUxPQURTVEFSVDtcbiAgICB9IGVsc2UgaWYgKHVpZCBpbiB0aGlzLnRpbGVMb2FkaW5nS2V5c18pIHtcbiAgICAgIGRlbGV0ZSB0aGlzLnRpbGVMb2FkaW5nS2V5c19bdWlkXTtcbiAgICAgIHR5cGUgPSB0aWxlU3RhdGUgPT0gVGlsZVN0YXRlLkVSUk9SID8gVGlsZUV2ZW50VHlwZS5USUxFTE9BREVSUk9SIDogdGlsZVN0YXRlID09IFRpbGVTdGF0ZS5MT0FERUQgPyBUaWxlRXZlbnRUeXBlLlRJTEVMT0FERU5EIDogdW5kZWZpbmVkO1xuICAgIH1cblxuICAgIGlmICh0eXBlICE9IHVuZGVmaW5lZCkge1xuICAgICAgdGhpcy5kaXNwYXRjaEV2ZW50KG5ldyBUaWxlU291cmNlRXZlbnQodHlwZSwgdGlsZSkpO1xuICAgIH1cbiAgfTtcbiAgLyoqXG4gICAqIFNldCB0aGUgdGlsZSBsb2FkIGZ1bmN0aW9uIG9mIHRoZSBzb3VyY2UuXG4gICAqIEBwYXJhbSB7aW1wb3J0KFwiLi4vVGlsZS5qc1wiKS5Mb2FkRnVuY3Rpb259IHRpbGVMb2FkRnVuY3Rpb24gVGlsZSBsb2FkIGZ1bmN0aW9uLlxuICAgKiBAYXBpXG4gICAqL1xuXG5cbiAgVXJsVGlsZS5wcm90b3R5cGUuc2V0VGlsZUxvYWRGdW5jdGlvbiA9IGZ1bmN0aW9uICh0aWxlTG9hZEZ1bmN0aW9uKSB7XG4gICAgdGhpcy50aWxlQ2FjaGUuY2xlYXIoKTtcbiAgICB0aGlzLnRpbGVMb2FkRnVuY3Rpb24gPSB0aWxlTG9hZEZ1bmN0aW9uO1xuICAgIHRoaXMuY2hhbmdlZCgpO1xuICB9O1xuICAvKipcbiAgICogU2V0IHRoZSB0aWxlIFVSTCBmdW5jdGlvbiBvZiB0aGUgc291cmNlLlxuICAgKiBAcGFyYW0ge2ltcG9ydChcIi4uL1RpbGUuanNcIikuVXJsRnVuY3Rpb259IHRpbGVVcmxGdW5jdGlvbiBUaWxlIFVSTCBmdW5jdGlvbi5cbiAgICogQHBhcmFtIHtzdHJpbmc9fSBrZXkgT3B0aW9uYWwgbmV3IHRpbGUga2V5IGZvciB0aGUgc291cmNlLlxuICAgKiBAYXBpXG4gICAqL1xuXG5cbiAgVXJsVGlsZS5wcm90b3R5cGUuc2V0VGlsZVVybEZ1bmN0aW9uID0gZnVuY3Rpb24gKHRpbGVVcmxGdW5jdGlvbiwga2V5KSB7XG4gICAgdGhpcy50aWxlVXJsRnVuY3Rpb24gPSB0aWxlVXJsRnVuY3Rpb247XG4gICAgdGhpcy50aWxlQ2FjaGUucHJ1bmVFeGNlcHROZXdlc3RaKCk7XG5cbiAgICBpZiAodHlwZW9mIGtleSAhPT0gJ3VuZGVmaW5lZCcpIHtcbiAgICAgIHRoaXMuc2V0S2V5KGtleSk7XG4gICAgfSBlbHNlIHtcbiAgICAgIHRoaXMuY2hhbmdlZCgpO1xuICAgIH1cbiAgfTtcbiAgLyoqXG4gICAqIFNldCB0aGUgVVJMIHRvIHVzZSBmb3IgcmVxdWVzdHMuXG4gICAqIEBwYXJhbSB7c3RyaW5nfSB1cmwgVVJMLlxuICAgKiBAYXBpXG4gICAqL1xuXG5cbiAgVXJsVGlsZS5wcm90b3R5cGUuc2V0VXJsID0gZnVuY3Rpb24gKHVybCkge1xuICAgIHZhciB1cmxzID0gZXhwYW5kVXJsKHVybCk7XG4gICAgdGhpcy51cmxzID0gdXJscztcbiAgICB0aGlzLnNldFVybHModXJscyk7XG4gIH07XG4gIC8qKlxuICAgKiBTZXQgdGhlIFVSTHMgdG8gdXNlIGZvciByZXF1ZXN0cy5cbiAgICogQHBhcmFtIHtBcnJheTxzdHJpbmc+fSB1cmxzIFVSTHMuXG4gICAqIEBhcGlcbiAgICovXG5cblxuICBVcmxUaWxlLnByb3RvdHlwZS5zZXRVcmxzID0gZnVuY3Rpb24gKHVybHMpIHtcbiAgICB0aGlzLnVybHMgPSB1cmxzO1xuICAgIHZhciBrZXkgPSB1cmxzLmpvaW4oJ1xcbicpO1xuXG4gICAgaWYgKHRoaXMuZ2VuZXJhdGVUaWxlVXJsRnVuY3Rpb25fKSB7XG4gICAgICB0aGlzLnNldFRpbGVVcmxGdW5jdGlvbihjcmVhdGVGcm9tVGVtcGxhdGVzKHVybHMsIHRoaXMudGlsZUdyaWQpLCBrZXkpO1xuICAgIH0gZWxzZSB7XG4gICAgICB0aGlzLnNldEtleShrZXkpO1xuICAgIH1cbiAgfTtcbiAgLyoqXG4gICAqIEBwYXJhbSB7aW1wb3J0KFwiLi4vdGlsZWNvb3JkLmpzXCIpLlRpbGVDb29yZH0gdGlsZUNvb3JkIFRpbGUgY29vcmRpbmF0ZS5cbiAgICogQHBhcmFtIHtudW1iZXJ9IHBpeGVsUmF0aW8gUGl4ZWwgcmF0aW8uXG4gICAqIEBwYXJhbSB7aW1wb3J0KFwiLi4vcHJvai9Qcm9qZWN0aW9uLmpzXCIpLmRlZmF1bHR9IHByb2plY3Rpb24gUHJvamVjdGlvbi5cbiAgICogQHJldHVybiB7c3RyaW5nfHVuZGVmaW5lZH0gVGlsZSBVUkwuXG4gICAqL1xuXG5cbiAgVXJsVGlsZS5wcm90b3R5cGUudGlsZVVybEZ1bmN0aW9uID0gZnVuY3Rpb24gKHRpbGVDb29yZCwgcGl4ZWxSYXRpbywgcHJvamVjdGlvbikge1xuICAgIHJldHVybiB1bmRlZmluZWQ7XG4gIH07XG4gIC8qKlxuICAgKiBNYXJrcyBhIHRpbGUgY29vcmQgYXMgYmVpbmcgdXNlZCwgd2l0aG91dCB0cmlnZ2VyaW5nIGEgbG9hZC5cbiAgICogQHBhcmFtIHtudW1iZXJ9IHogVGlsZSBjb29yZGluYXRlIHouXG4gICAqIEBwYXJhbSB7bnVtYmVyfSB4IFRpbGUgY29vcmRpbmF0ZSB4LlxuICAgKiBAcGFyYW0ge251bWJlcn0geSBUaWxlIGNvb3JkaW5hdGUgeS5cbiAgICovXG5cblxuICBVcmxUaWxlLnByb3RvdHlwZS51c2VUaWxlID0gZnVuY3Rpb24gKHosIHgsIHkpIHtcbiAgICB2YXIgdGlsZUNvb3JkS2V5ID0gZ2V0S2V5WlhZKHosIHgsIHkpO1xuXG4gICAgaWYgKHRoaXMudGlsZUNhY2hlLmNvbnRhaW5zS2V5KHRpbGVDb29yZEtleSkpIHtcbiAgICAgIHRoaXMudGlsZUNhY2hlLmdldCh0aWxlQ29vcmRLZXkpO1xuICAgIH1cbiAgfTtcblxuICByZXR1cm4gVXJsVGlsZTtcbn0oVGlsZVNvdXJjZSk7XG5cbmV4cG9ydCBkZWZhdWx0IFVybFRpbGU7IiwidmFyIF9fZXh0ZW5kcyA9IHRoaXMgJiYgdGhpcy5fX2V4dGVuZHMgfHwgZnVuY3Rpb24gKCkge1xuICB2YXIgX2V4dGVuZFN0YXRpY3MgPSBmdW5jdGlvbiBleHRlbmRTdGF0aWNzKGQsIGIpIHtcbiAgICBfZXh0ZW5kU3RhdGljcyA9IE9iamVjdC5zZXRQcm90b3R5cGVPZiB8fCB7XG4gICAgICBfX3Byb3RvX186IFtdXG4gICAgfSBpbnN0YW5jZW9mIEFycmF5ICYmIGZ1bmN0aW9uIChkLCBiKSB7XG4gICAgICBkLl9fcHJvdG9fXyA9IGI7XG4gICAgfSB8fCBmdW5jdGlvbiAoZCwgYikge1xuICAgICAgZm9yICh2YXIgcCBpbiBiKSB7XG4gICAgICAgIGlmIChPYmplY3QucHJvdG90eXBlLmhhc093blByb3BlcnR5LmNhbGwoYiwgcCkpIGRbcF0gPSBiW3BdO1xuICAgICAgfVxuICAgIH07XG5cbiAgICByZXR1cm4gX2V4dGVuZFN0YXRpY3MoZCwgYik7XG4gIH07XG5cbiAgcmV0dXJuIGZ1bmN0aW9uIChkLCBiKSB7XG4gICAgX2V4dGVuZFN0YXRpY3MoZCwgYik7XG5cbiAgICBmdW5jdGlvbiBfXygpIHtcbiAgICAgIHRoaXMuY29uc3RydWN0b3IgPSBkO1xuICAgIH1cblxuICAgIGQucHJvdG90eXBlID0gYiA9PT0gbnVsbCA/IE9iamVjdC5jcmVhdGUoYikgOiAoX18ucHJvdG90eXBlID0gYi5wcm90b3R5cGUsIG5ldyBfXygpKTtcbiAgfTtcbn0oKTtcbi8qKlxuICogQG1vZHVsZSBvbC9WZWN0b3JSZW5kZXJUaWxlXG4gKi9cblxuXG5pbXBvcnQgVGlsZSBmcm9tICcuL1RpbGUuanMnO1xuaW1wb3J0IHsgY3JlYXRlQ2FudmFzQ29udGV4dDJEIH0gZnJvbSAnLi9kb20uanMnO1xuaW1wb3J0IHsgZ2V0VWlkIH0gZnJvbSAnLi91dGlsLmpzJztcbi8qKlxuICogQHR5cGVkZWYge09iamVjdH0gUmVwbGF5U3RhdGVcbiAqIEBwcm9wZXJ0eSB7Ym9vbGVhbn0gZGlydHlcbiAqIEBwcm9wZXJ0eSB7bnVsbHxpbXBvcnQoXCIuL3JlbmRlci5qc1wiKS5PcmRlckZ1bmN0aW9ufSByZW5kZXJlZFJlbmRlck9yZGVyXG4gKiBAcHJvcGVydHkge251bWJlcn0gcmVuZGVyZWRUaWxlUmV2aXNpb25cbiAqIEBwcm9wZXJ0eSB7bnVtYmVyfSByZW5kZXJlZFJlc29sdXRpb25cbiAqIEBwcm9wZXJ0eSB7bnVtYmVyfSByZW5kZXJlZFJldmlzaW9uXG4gKiBAcHJvcGVydHkge251bWJlcn0gcmVuZGVyZWRaXG4gKiBAcHJvcGVydHkge251bWJlcn0gcmVuZGVyZWRUaWxlUmVzb2x1dGlvblxuICogQHByb3BlcnR5IHtudW1iZXJ9IHJlbmRlcmVkVGlsZVpcbiAqL1xuXG4vKipcbiAqIEB0eXBlIHtBcnJheTxIVE1MQ2FudmFzRWxlbWVudD59XG4gKi9cblxudmFyIGNhbnZhc1Bvb2wgPSBbXTtcblxudmFyIFZlY3RvclJlbmRlclRpbGUgPVxuLyoqIEBjbGFzcyAqL1xuZnVuY3Rpb24gKF9zdXBlcikge1xuICBfX2V4dGVuZHMoVmVjdG9yUmVuZGVyVGlsZSwgX3N1cGVyKTtcbiAgLyoqXG4gICAqIEBwYXJhbSB7aW1wb3J0KFwiLi90aWxlY29vcmQuanNcIikuVGlsZUNvb3JkfSB0aWxlQ29vcmQgVGlsZSBjb29yZGluYXRlLlxuICAgKiBAcGFyYW0ge2ltcG9ydChcIi4vVGlsZVN0YXRlLmpzXCIpLmRlZmF1bHR9IHN0YXRlIFN0YXRlLlxuICAgKiBAcGFyYW0ge2ltcG9ydChcIi4vdGlsZWNvb3JkLmpzXCIpLlRpbGVDb29yZH0gdXJsVGlsZUNvb3JkIFdyYXBwZWQgdGlsZSBjb29yZGluYXRlIGZvciBzb3VyY2UgdXJscy5cbiAgICogQHBhcmFtIHtmdW5jdGlvbihWZWN0b3JSZW5kZXJUaWxlKTpBcnJheTxpbXBvcnQoXCIuL1ZlY3RvclRpbGVcIikuZGVmYXVsdD59IGdldFNvdXJjZVRpbGVzIEZ1bmN0aW9uXG4gICAqIHRvIGdldCBzb3VyY2UgdGlsZXMgZm9yIHRoaXMgdGlsZS5cbiAgICovXG5cblxuICBmdW5jdGlvbiBWZWN0b3JSZW5kZXJUaWxlKHRpbGVDb29yZCwgc3RhdGUsIHVybFRpbGVDb29yZCwgZ2V0U291cmNlVGlsZXMpIHtcbiAgICB2YXIgX3RoaXMgPSBfc3VwZXIuY2FsbCh0aGlzLCB0aWxlQ29vcmQsIHN0YXRlLCB7XG4gICAgICB0cmFuc2l0aW9uOiAwXG4gICAgfSkgfHwgdGhpcztcbiAgICAvKipcbiAgICAgKiBAcHJpdmF0ZVxuICAgICAqIEB0eXBlIHshT2JqZWN0PHN0cmluZywgQ2FudmFzUmVuZGVyaW5nQ29udGV4dDJEPn1cbiAgICAgKi9cblxuXG4gICAgX3RoaXMuY29udGV4dF8gPSB7fTtcbiAgICAvKipcbiAgICAgKiBFeGVjdXRvciBncm91cHMgYnkgbGF5ZXIgdWlkLiBFbnRyaWVzIGFyZSByZWFkL3dyaXR0ZW4gYnkgdGhlIHJlbmRlcmVyLlxuICAgICAqIEB0eXBlIHtPYmplY3Q8c3RyaW5nLCBBcnJheTxpbXBvcnQoXCIuL3JlbmRlci9jYW52YXMvRXhlY3V0b3JHcm91cC5qc1wiKS5kZWZhdWx0Pj59XG4gICAgICovXG5cbiAgICBfdGhpcy5leGVjdXRvckdyb3VwcyA9IHt9O1xuICAgIC8qKlxuICAgICAqIEV4ZWN1dG9yIGdyb3VwcyBmb3IgZGVjbHV0dGVyaW5nLCBieSBsYXllciB1aWQuIEVudHJpZXMgYXJlIHJlYWQvd3JpdHRlbiBieSB0aGUgcmVuZGVyZXIuXG4gICAgICogQHR5cGUge09iamVjdDxzdHJpbmcsIEFycmF5PGltcG9ydChcIi4vcmVuZGVyL2NhbnZhcy9FeGVjdXRvckdyb3VwLmpzXCIpLmRlZmF1bHQ+Pn1cbiAgICAgKi9cblxuICAgIF90aGlzLmRlY2x1dHRlckV4ZWN1dG9yR3JvdXBzID0ge307XG4gICAgLyoqXG4gICAgICogTnVtYmVyIG9mIGxvYWRpbmcgc291cmNlIHRpbGVzLiBSZWFkL3dyaXR0ZW4gYnkgdGhlIHNvdXJjZS5cbiAgICAgKiBAdHlwZSB7bnVtYmVyfVxuICAgICAqL1xuXG4gICAgX3RoaXMubG9hZGluZ1NvdXJjZVRpbGVzID0gMDtcbiAgICAvKipcbiAgICAgKiBUaWxlIGtleXMgb2YgZXJyb3Igc291cmNlIHRpbGVzLiBSZWFkL3dyaXR0ZW4gYnkgdGhlIHNvdXJjZS5cbiAgICAgKiBAdHlwZSB7T2JqZWN0PHN0cmluZywgYm9vbGVhbj59XG4gICAgICovXG5cbiAgICBfdGhpcy5lcnJvclNvdXJjZVRpbGVLZXlzID0ge307XG4gICAgLyoqXG4gICAgICogQHR5cGUge09iamVjdDxudW1iZXIsIEltYWdlRGF0YT59XG4gICAgICovXG5cbiAgICBfdGhpcy5oaXREZXRlY3Rpb25JbWFnZURhdGEgPSB7fTtcbiAgICAvKipcbiAgICAgKiBAcHJpdmF0ZVxuICAgICAqIEB0eXBlIHshT2JqZWN0PHN0cmluZywgUmVwbGF5U3RhdGU+fVxuICAgICAqL1xuXG4gICAgX3RoaXMucmVwbGF5U3RhdGVfID0ge307XG4gICAgLyoqXG4gICAgICogQHR5cGUge0FycmF5PGltcG9ydChcIi4vVmVjdG9yVGlsZS5qc1wiKS5kZWZhdWx0Pn1cbiAgICAgKi9cblxuICAgIF90aGlzLnNvdXJjZVRpbGVzID0gbnVsbDtcbiAgICAvKipcbiAgICAgKiBAdHlwZSB7bnVtYmVyfVxuICAgICAqL1xuXG4gICAgX3RoaXMud2FudGVkUmVzb2x1dGlvbjtcbiAgICAvKipcbiAgICAgKiBAdHlwZSB7IWZ1bmN0aW9uKCk6QXJyYXk8aW1wb3J0KFwiLi9WZWN0b3JUaWxlLmpzXCIpLmRlZmF1bHQ+fVxuICAgICAqL1xuXG4gICAgX3RoaXMuZ2V0U291cmNlVGlsZXMgPSBnZXRTb3VyY2VUaWxlcy5iaW5kKHVuZGVmaW5lZCwgX3RoaXMpO1xuICAgIC8qKlxuICAgICAqIHogb2YgdGhlIHNvdXJjZSB0aWxlcyBvZiB0aGUgbGFzdCBnZXRTb3VyY2VUaWxlcyBjYWxsLlxuICAgICAqIEB0eXBlIHtudW1iZXJ9XG4gICAgICovXG5cbiAgICBfdGhpcy5zb3VyY2VaID0gLTE7XG4gICAgLyoqXG4gICAgICogVHJ1ZSB3aGVuIGFsbCB0aWxlcyBmb3IgdGhpcyB0aWxlJ3Mgbm9taW5hbCByZXNvbHV0aW9uIGFyZSBhdmFpbGFibGUuXG4gICAgICogQHR5cGUge2Jvb2xlYW59XG4gICAgICovXG5cbiAgICBfdGhpcy5oaWZpID0gZmFsc2U7XG4gICAgLyoqXG4gICAgICogQHR5cGUge2ltcG9ydChcIi4vdGlsZWNvb3JkLmpzXCIpLlRpbGVDb29yZH1cbiAgICAgKi9cblxuICAgIF90aGlzLndyYXBwZWRUaWxlQ29vcmQgPSB1cmxUaWxlQ29vcmQ7XG4gICAgcmV0dXJuIF90aGlzO1xuICB9XG4gIC8qKlxuICAgKiBAcGFyYW0ge2ltcG9ydChcIi4vbGF5ZXIvTGF5ZXIuanNcIikuZGVmYXVsdH0gbGF5ZXIgTGF5ZXIuXG4gICAqIEByZXR1cm4ge0NhbnZhc1JlbmRlcmluZ0NvbnRleHQyRH0gVGhlIHJlbmRlcmluZyBjb250ZXh0LlxuICAgKi9cblxuXG4gIFZlY3RvclJlbmRlclRpbGUucHJvdG90eXBlLmdldENvbnRleHQgPSBmdW5jdGlvbiAobGF5ZXIpIHtcbiAgICB2YXIga2V5ID0gZ2V0VWlkKGxheWVyKTtcblxuICAgIGlmICghKGtleSBpbiB0aGlzLmNvbnRleHRfKSkge1xuICAgICAgdGhpcy5jb250ZXh0X1trZXldID0gY3JlYXRlQ2FudmFzQ29udGV4dDJEKDEsIDEsIGNhbnZhc1Bvb2wpO1xuICAgIH1cblxuICAgIHJldHVybiB0aGlzLmNvbnRleHRfW2tleV07XG4gIH07XG4gIC8qKlxuICAgKiBAcGFyYW0ge2ltcG9ydChcIi4vbGF5ZXIvTGF5ZXIuanNcIikuZGVmYXVsdH0gbGF5ZXIgTGF5ZXIuXG4gICAqIEByZXR1cm4ge2Jvb2xlYW59IFRpbGUgaGFzIGEgcmVuZGVyaW5nIGNvbnRleHQgZm9yIHRoZSBnaXZlbiBsYXllci5cbiAgICovXG5cblxuICBWZWN0b3JSZW5kZXJUaWxlLnByb3RvdHlwZS5oYXNDb250ZXh0ID0gZnVuY3Rpb24gKGxheWVyKSB7XG4gICAgcmV0dXJuIGdldFVpZChsYXllcikgaW4gdGhpcy5jb250ZXh0XztcbiAgfTtcbiAgLyoqXG4gICAqIEdldCB0aGUgQ2FudmFzIGZvciB0aGlzIHRpbGUuXG4gICAqIEBwYXJhbSB7aW1wb3J0KFwiLi9sYXllci9MYXllci5qc1wiKS5kZWZhdWx0fSBsYXllciBMYXllci5cbiAgICogQHJldHVybiB7SFRNTENhbnZhc0VsZW1lbnR9IENhbnZhcy5cbiAgICovXG5cblxuICBWZWN0b3JSZW5kZXJUaWxlLnByb3RvdHlwZS5nZXRJbWFnZSA9IGZ1bmN0aW9uIChsYXllcikge1xuICAgIHJldHVybiB0aGlzLmhhc0NvbnRleHQobGF5ZXIpID8gdGhpcy5nZXRDb250ZXh0KGxheWVyKS5jYW52YXMgOiBudWxsO1xuICB9O1xuICAvKipcbiAgICogQHBhcmFtIHtpbXBvcnQoXCIuL2xheWVyL0xheWVyLmpzXCIpLmRlZmF1bHR9IGxheWVyIExheWVyLlxuICAgKiBAcmV0dXJuIHtSZXBsYXlTdGF0ZX0gVGhlIHJlcGxheSBzdGF0ZS5cbiAgICovXG5cblxuICBWZWN0b3JSZW5kZXJUaWxlLnByb3RvdHlwZS5nZXRSZXBsYXlTdGF0ZSA9IGZ1bmN0aW9uIChsYXllcikge1xuICAgIHZhciBrZXkgPSBnZXRVaWQobGF5ZXIpO1xuXG4gICAgaWYgKCEoa2V5IGluIHRoaXMucmVwbGF5U3RhdGVfKSkge1xuICAgICAgdGhpcy5yZXBsYXlTdGF0ZV9ba2V5XSA9IHtcbiAgICAgICAgZGlydHk6IGZhbHNlLFxuICAgICAgICByZW5kZXJlZFJlbmRlck9yZGVyOiBudWxsLFxuICAgICAgICByZW5kZXJlZFJlc29sdXRpb246IE5hTixcbiAgICAgICAgcmVuZGVyZWRSZXZpc2lvbjogLTEsXG4gICAgICAgIHJlbmRlcmVkVGlsZVJlc29sdXRpb246IE5hTixcbiAgICAgICAgcmVuZGVyZWRUaWxlUmV2aXNpb246IC0xLFxuICAgICAgICByZW5kZXJlZFo6IC0xLFxuICAgICAgICByZW5kZXJlZFRpbGVaOiAtMVxuICAgICAgfTtcbiAgICB9XG5cbiAgICByZXR1cm4gdGhpcy5yZXBsYXlTdGF0ZV9ba2V5XTtcbiAgfTtcbiAgLyoqXG4gICAqIExvYWQgdGhlIHRpbGUuXG4gICAqL1xuXG5cbiAgVmVjdG9yUmVuZGVyVGlsZS5wcm90b3R5cGUubG9hZCA9IGZ1bmN0aW9uICgpIHtcbiAgICB0aGlzLmdldFNvdXJjZVRpbGVzKCk7XG4gIH07XG4gIC8qKlxuICAgKiBSZW1vdmUgZnJvbSB0aGUgY2FjaGUgZHVlIHRvIGV4cGlyeVxuICAgKi9cblxuXG4gIFZlY3RvclJlbmRlclRpbGUucHJvdG90eXBlLnJlbGVhc2UgPSBmdW5jdGlvbiAoKSB7XG4gICAgZm9yICh2YXIga2V5IGluIHRoaXMuY29udGV4dF8pIHtcbiAgICAgIGNhbnZhc1Bvb2wucHVzaCh0aGlzLmNvbnRleHRfW2tleV0uY2FudmFzKTtcbiAgICAgIGRlbGV0ZSB0aGlzLmNvbnRleHRfW2tleV07XG4gICAgfVxuXG4gICAgX3N1cGVyLnByb3RvdHlwZS5yZWxlYXNlLmNhbGwodGhpcyk7XG4gIH07XG5cbiAgcmV0dXJuIFZlY3RvclJlbmRlclRpbGU7XG59KFRpbGUpO1xuXG5leHBvcnQgZGVmYXVsdCBWZWN0b3JSZW5kZXJUaWxlOyIsIi8qKlxuICogQG1vZHVsZSBvbC9mb3JtYXQvRm9ybWF0VHlwZVxuICovXG5cbi8qKlxuICogQGVudW0ge3N0cmluZ31cbiAqL1xuZXhwb3J0IGRlZmF1bHQge1xuICBBUlJBWV9CVUZGRVI6ICdhcnJheWJ1ZmZlcicsXG4gIEpTT046ICdqc29uJyxcbiAgVEVYVDogJ3RleHQnLFxuICBYTUw6ICd4bWwnXG59OyIsIi8qKlxuICogQG1vZHVsZSBvbC9mZWF0dXJlbG9hZGVyXG4gKi9cbmltcG9ydCBGb3JtYXRUeXBlIGZyb20gJy4vZm9ybWF0L0Zvcm1hdFR5cGUuanMnO1xuaW1wb3J0IHsgVk9JRCB9IGZyb20gJy4vZnVuY3Rpb25zLmpzJztcbi8qKlxuICpcbiAqIEB0eXBlIHtib29sZWFufVxuICogQHByaXZhdGVcbiAqL1xuXG52YXIgd2l0aENyZWRlbnRpYWxzID0gZmFsc2U7XG4vKipcbiAqIHtAbGluayBtb2R1bGU6b2wvc291cmNlL1ZlY3Rvcn0gc291cmNlcyB1c2UgYSBmdW5jdGlvbiBvZiB0aGlzIHR5cGUgdG9cbiAqIGxvYWQgZmVhdHVyZXMuXG4gKlxuICogVGhpcyBmdW5jdGlvbiB0YWtlcyBhbiB7QGxpbmsgbW9kdWxlOm9sL2V4dGVudH5FeHRlbnR9IHJlcHJlc2VudGluZyB0aGUgYXJlYSB0byBiZSBsb2FkZWQsXG4gKiBhIGB7bnVtYmVyfWAgcmVwcmVzZW50aW5nIHRoZSByZXNvbHV0aW9uIChtYXAgdW5pdHMgcGVyIHBpeGVsKSwgYW5cbiAqIHtAbGluayBtb2R1bGU6b2wvcHJvai9Qcm9qZWN0aW9ufSBmb3IgdGhlIHByb2plY3Rpb24gYW5kIHN1Y2Nlc3MgYW5kIGZhaWx1cmUgY2FsbGJhY2tzIGFzXG4gKiBhcmd1bWVudHMuIGB0aGlzYCB3aXRoaW4gdGhlIGZ1bmN0aW9uIGlzIGJvdW5kIHRvIHRoZVxuICoge0BsaW5rIG1vZHVsZTpvbC9zb3VyY2UvVmVjdG9yfSBpdCdzIGNhbGxlZCBmcm9tLlxuICpcbiAqIFRoZSBmdW5jdGlvbiBpcyByZXNwb25zaWJsZSBmb3IgbG9hZGluZyB0aGUgZmVhdHVyZXMgYW5kIGFkZGluZyB0aGVtIHRvIHRoZVxuICogc291cmNlLlxuICogQHR5cGVkZWYge2Z1bmN0aW9uKHRoaXM6KGltcG9ydChcIi4vc291cmNlL1ZlY3RvclwiKS5kZWZhdWx0fGltcG9ydChcIi4vVmVjdG9yVGlsZS5qc1wiKS5kZWZhdWx0KSxcbiAqICAgICAgICAgICBpbXBvcnQoXCIuL2V4dGVudC5qc1wiKS5FeHRlbnQsXG4gKiAgICAgICAgICAgbnVtYmVyLFxuICogICAgICAgICAgIGltcG9ydChcIi4vcHJvai9Qcm9qZWN0aW9uLmpzXCIpLmRlZmF1bHQsXG4gKiAgICAgICAgICAgZnVuY3Rpb24oQXJyYXk8aW1wb3J0KFwiLi9GZWF0dXJlLmpzXCIpLmRlZmF1bHQ+KTogdm9pZD0sXG4gKiAgICAgICAgICAgZnVuY3Rpb24oKTogdm9pZD0pOiB2b2lkfSBGZWF0dXJlTG9hZGVyXG4gKiBAYXBpXG4gKi9cblxuLyoqXG4gKiB7QGxpbmsgbW9kdWxlOm9sL3NvdXJjZS9WZWN0b3J9IHNvdXJjZXMgdXNlIGEgZnVuY3Rpb24gb2YgdGhpcyB0eXBlIHRvXG4gKiBnZXQgdGhlIHVybCB0byBsb2FkIGZlYXR1cmVzIGZyb20uXG4gKlxuICogVGhpcyBmdW5jdGlvbiB0YWtlcyBhbiB7QGxpbmsgbW9kdWxlOm9sL2V4dGVudH5FeHRlbnR9IHJlcHJlc2VudGluZyB0aGUgYXJlYVxuICogdG8gYmUgbG9hZGVkLCBhIGB7bnVtYmVyfWAgcmVwcmVzZW50aW5nIHRoZSByZXNvbHV0aW9uIChtYXAgdW5pdHMgcGVyIHBpeGVsKVxuICogYW5kIGFuIHtAbGluayBtb2R1bGU6b2wvcHJvai9Qcm9qZWN0aW9ufSBmb3IgdGhlIHByb2plY3Rpb24gIGFzXG4gKiBhcmd1bWVudHMgYW5kIHJldHVybnMgYSBge3N0cmluZ31gIHJlcHJlc2VudGluZyB0aGUgVVJMLlxuICogQHR5cGVkZWYge2Z1bmN0aW9uKGltcG9ydChcIi4vZXh0ZW50LmpzXCIpLkV4dGVudCwgbnVtYmVyLCBpbXBvcnQoXCIuL3Byb2ovUHJvamVjdGlvbi5qc1wiKS5kZWZhdWx0KTogc3RyaW5nfSBGZWF0dXJlVXJsRnVuY3Rpb25cbiAqIEBhcGlcbiAqL1xuXG4vKipcbiAqIEBwYXJhbSB7c3RyaW5nfEZlYXR1cmVVcmxGdW5jdGlvbn0gdXJsIEZlYXR1cmUgVVJMIHNlcnZpY2UuXG4gKiBAcGFyYW0ge2ltcG9ydChcIi4vZm9ybWF0L0ZlYXR1cmUuanNcIikuZGVmYXVsdH0gZm9ybWF0IEZlYXR1cmUgZm9ybWF0LlxuICogQHBhcmFtIHtpbXBvcnQoXCIuL2V4dGVudC5qc1wiKS5FeHRlbnR9IGV4dGVudCBFeHRlbnQuXG4gKiBAcGFyYW0ge251bWJlcn0gcmVzb2x1dGlvbiBSZXNvbHV0aW9uLlxuICogQHBhcmFtIHtpbXBvcnQoXCIuL3Byb2ovUHJvamVjdGlvbi5qc1wiKS5kZWZhdWx0fSBwcm9qZWN0aW9uIFByb2plY3Rpb24uXG4gKiBAcGFyYW0ge2Z1bmN0aW9uKEFycmF5PGltcG9ydChcIi4vRmVhdHVyZS5qc1wiKS5kZWZhdWx0PiwgaW1wb3J0KFwiLi9wcm9qL1Byb2plY3Rpb24uanNcIikuZGVmYXVsdCk6IHZvaWR9IHN1Y2Nlc3MgU3VjY2Vzc1xuICogICAgICBGdW5jdGlvbiBjYWxsZWQgd2l0aCB0aGUgbG9hZGVkIGZlYXR1cmVzIGFuZCBvcHRpb25hbGx5IHdpdGggdGhlIGRhdGEgcHJvamVjdGlvbi5cbiAqIEBwYXJhbSB7ZnVuY3Rpb24oKTogdm9pZH0gZmFpbHVyZSBGYWlsdXJlXG4gKiAgICAgIEZ1bmN0aW9uIGNhbGxlZCB3aGVuIGxvYWRpbmcgZmFpbGVkLlxuICovXG5cbmV4cG9ydCBmdW5jdGlvbiBsb2FkRmVhdHVyZXNYaHIodXJsLCBmb3JtYXQsIGV4dGVudCwgcmVzb2x1dGlvbiwgcHJvamVjdGlvbiwgc3VjY2VzcywgZmFpbHVyZSkge1xuICB2YXIgeGhyID0gbmV3IFhNTEh0dHBSZXF1ZXN0KCk7XG4gIHhoci5vcGVuKCdHRVQnLCB0eXBlb2YgdXJsID09PSAnZnVuY3Rpb24nID8gdXJsKGV4dGVudCwgcmVzb2x1dGlvbiwgcHJvamVjdGlvbikgOiB1cmwsIHRydWUpO1xuXG4gIGlmIChmb3JtYXQuZ2V0VHlwZSgpID09IEZvcm1hdFR5cGUuQVJSQVlfQlVGRkVSKSB7XG4gICAgeGhyLnJlc3BvbnNlVHlwZSA9ICdhcnJheWJ1ZmZlcic7XG4gIH1cblxuICB4aHIud2l0aENyZWRlbnRpYWxzID0gd2l0aENyZWRlbnRpYWxzO1xuICAvKipcbiAgICogQHBhcmFtIHtFdmVudH0gZXZlbnQgRXZlbnQuXG4gICAqIEBwcml2YXRlXG4gICAqL1xuXG4gIHhoci5vbmxvYWQgPSBmdW5jdGlvbiAoZXZlbnQpIHtcbiAgICAvLyBzdGF0dXMgd2lsbCBiZSAwIGZvciBmaWxlOi8vIHVybHNcbiAgICBpZiAoIXhoci5zdGF0dXMgfHwgeGhyLnN0YXR1cyA+PSAyMDAgJiYgeGhyLnN0YXR1cyA8IDMwMCkge1xuICAgICAgdmFyIHR5cGUgPSBmb3JtYXQuZ2V0VHlwZSgpO1xuICAgICAgLyoqIEB0eXBlIHtEb2N1bWVudHxOb2RlfE9iamVjdHxzdHJpbmd8dW5kZWZpbmVkfSAqL1xuXG4gICAgICB2YXIgc291cmNlID0gdm9pZCAwO1xuXG4gICAgICBpZiAodHlwZSA9PSBGb3JtYXRUeXBlLkpTT04gfHwgdHlwZSA9PSBGb3JtYXRUeXBlLlRFWFQpIHtcbiAgICAgICAgc291cmNlID0geGhyLnJlc3BvbnNlVGV4dDtcbiAgICAgIH0gZWxzZSBpZiAodHlwZSA9PSBGb3JtYXRUeXBlLlhNTCkge1xuICAgICAgICBzb3VyY2UgPSB4aHIucmVzcG9uc2VYTUw7XG5cbiAgICAgICAgaWYgKCFzb3VyY2UpIHtcbiAgICAgICAgICBzb3VyY2UgPSBuZXcgRE9NUGFyc2VyKCkucGFyc2VGcm9tU3RyaW5nKHhoci5yZXNwb25zZVRleHQsICdhcHBsaWNhdGlvbi94bWwnKTtcbiAgICAgICAgfVxuICAgICAgfSBlbHNlIGlmICh0eXBlID09IEZvcm1hdFR5cGUuQVJSQVlfQlVGRkVSKSB7XG4gICAgICAgIHNvdXJjZSA9XG4gICAgICAgIC8qKiBAdHlwZSB7QXJyYXlCdWZmZXJ9ICovXG4gICAgICAgIHhoci5yZXNwb25zZTtcbiAgICAgIH1cblxuICAgICAgaWYgKHNvdXJjZSkge1xuICAgICAgICBzdWNjZXNzKFxuICAgICAgICAvKiogQHR5cGUge0FycmF5PGltcG9ydChcIi4vRmVhdHVyZS5qc1wiKS5kZWZhdWx0Pn0gKi9cbiAgICAgICAgZm9ybWF0LnJlYWRGZWF0dXJlcyhzb3VyY2UsIHtcbiAgICAgICAgICBleHRlbnQ6IGV4dGVudCxcbiAgICAgICAgICBmZWF0dXJlUHJvamVjdGlvbjogcHJvamVjdGlvblxuICAgICAgICB9KSwgZm9ybWF0LnJlYWRQcm9qZWN0aW9uKHNvdXJjZSkpO1xuICAgICAgfSBlbHNlIHtcbiAgICAgICAgZmFpbHVyZSgpO1xuICAgICAgfVxuICAgIH0gZWxzZSB7XG4gICAgICBmYWlsdXJlKCk7XG4gICAgfVxuICB9O1xuICAvKipcbiAgICogQHByaXZhdGVcbiAgICovXG5cblxuICB4aHIub25lcnJvciA9IGZhaWx1cmU7XG4gIHhoci5zZW5kKCk7XG59XG4vKipcbiAqIENyZWF0ZSBhbiBYSFIgZmVhdHVyZSBsb2FkZXIgZm9yIGEgYHVybGAgYW5kIGBmb3JtYXRgLiBUaGUgZmVhdHVyZSBsb2FkZXJcbiAqIGxvYWRzIGZlYXR1cmVzICh3aXRoIFhIUiksIHBhcnNlcyB0aGUgZmVhdHVyZXMsIGFuZCBhZGRzIHRoZW0gdG8gdGhlXG4gKiB2ZWN0b3Igc291cmNlLlxuICogQHBhcmFtIHtzdHJpbmd8RmVhdHVyZVVybEZ1bmN0aW9ufSB1cmwgRmVhdHVyZSBVUkwgc2VydmljZS5cbiAqIEBwYXJhbSB7aW1wb3J0KFwiLi9mb3JtYXQvRmVhdHVyZS5qc1wiKS5kZWZhdWx0fSBmb3JtYXQgRmVhdHVyZSBmb3JtYXQuXG4gKiBAcmV0dXJuIHtGZWF0dXJlTG9hZGVyfSBUaGUgZmVhdHVyZSBsb2FkZXIuXG4gKiBAYXBpXG4gKi9cblxuZXhwb3J0IGZ1bmN0aW9uIHhocih1cmwsIGZvcm1hdCkge1xuICAvKipcbiAgICogQHBhcmFtIHtpbXBvcnQoXCIuL2V4dGVudC5qc1wiKS5FeHRlbnR9IGV4dGVudCBFeHRlbnQuXG4gICAqIEBwYXJhbSB7bnVtYmVyfSByZXNvbHV0aW9uIFJlc29sdXRpb24uXG4gICAqIEBwYXJhbSB7aW1wb3J0KFwiLi9wcm9qL1Byb2plY3Rpb24uanNcIikuZGVmYXVsdH0gcHJvamVjdGlvbiBQcm9qZWN0aW9uLlxuICAgKiBAcGFyYW0ge2Z1bmN0aW9uKCk6IHZvaWQ9fSBzdWNjZXNzIFN1Y2Nlc3NcbiAgICogICAgICBGdW5jdGlvbiBjYWxsZWQgd2hlbiBsb2FkaW5nIHN1Y2NlZWRlZC5cbiAgICogQHBhcmFtIHtmdW5jdGlvbigpOiB2b2lkPX0gZmFpbHVyZSBGYWlsdXJlXG4gICAqICAgICAgRnVuY3Rpb24gY2FsbGVkIHdoZW4gbG9hZGluZyBmYWlsZWQuXG4gICAqIEB0aGlzIHtpbXBvcnQoXCIuL3NvdXJjZS9WZWN0b3JcIikuZGVmYXVsdH1cbiAgICovXG4gIHJldHVybiBmdW5jdGlvbiAoZXh0ZW50LCByZXNvbHV0aW9uLCBwcm9qZWN0aW9uLCBzdWNjZXNzLCBmYWlsdXJlKSB7XG4gICAgdmFyIHNvdXJjZSA9XG4gICAgLyoqIEB0eXBlIHtpbXBvcnQoXCIuL3NvdXJjZS9WZWN0b3JcIikuZGVmYXVsdH0gKi9cbiAgICB0aGlzO1xuICAgIGxvYWRGZWF0dXJlc1hocih1cmwsIGZvcm1hdCwgZXh0ZW50LCByZXNvbHV0aW9uLCBwcm9qZWN0aW9uLFxuICAgIC8qKlxuICAgICAqIEBwYXJhbSB7QXJyYXk8aW1wb3J0KFwiLi9GZWF0dXJlLmpzXCIpLmRlZmF1bHQ+fSBmZWF0dXJlcyBUaGUgbG9hZGVkIGZlYXR1cmVzLlxuICAgICAqIEBwYXJhbSB7aW1wb3J0KFwiLi9wcm9qL1Byb2plY3Rpb24uanNcIikuZGVmYXVsdH0gZGF0YVByb2plY3Rpb24gRGF0YVxuICAgICAqIHByb2plY3Rpb24uXG4gICAgICovXG4gICAgZnVuY3Rpb24gKGZlYXR1cmVzLCBkYXRhUHJvamVjdGlvbikge1xuICAgICAgaWYgKHN1Y2Nlc3MgIT09IHVuZGVmaW5lZCkge1xuICAgICAgICBzdWNjZXNzKGZlYXR1cmVzKTtcbiAgICAgIH1cblxuICAgICAgc291cmNlLmFkZEZlYXR1cmVzKGZlYXR1cmVzKTtcbiAgICB9LFxuICAgIC8qIEZJWE1FIGhhbmRsZSBlcnJvciAqL1xuICAgIGZhaWx1cmUgPyBmYWlsdXJlIDogVk9JRCk7XG4gIH07XG59XG4vKipcbiAqIFNldHRlciBmb3IgdGhlIHdpdGhDcmVkZW50aWFscyBjb25maWd1cmF0aW9uIGZvciB0aGUgWEhSLlxuICpcbiAqIEBwYXJhbSB7Ym9vbGVhbn0geGhyV2l0aENyZWRlbnRpYWxzIFRoZSB2YWx1ZSBvZiB3aXRoQ3JlZGVudGlhbHMgdG8gc2V0LlxuICogQ29tcGFyZSBodHRwczovL2RldmVsb3Blci5tb3ppbGxhLm9yZy9lbi1VUy9kb2NzL1dlYi9BUEkvWE1MSHR0cFJlcXVlc3QvXG4gKiBAYXBpXG4gKi9cblxuZXhwb3J0IGZ1bmN0aW9uIHNldFdpdGhDcmVkZW50aWFscyh4aHJXaXRoQ3JlZGVudGlhbHMpIHtcbiAgd2l0aENyZWRlbnRpYWxzID0geGhyV2l0aENyZWRlbnRpYWxzO1xufSIsIi8qKlxuICogQG1vZHVsZSBvbC9zb3VyY2UvVmVjdG9yVGlsZVxuICovXG52YXIgX19leHRlbmRzID0gdGhpcyAmJiB0aGlzLl9fZXh0ZW5kcyB8fCBmdW5jdGlvbiAoKSB7XG4gIHZhciBfZXh0ZW5kU3RhdGljcyA9IGZ1bmN0aW9uIGV4dGVuZFN0YXRpY3MoZCwgYikge1xuICAgIF9leHRlbmRTdGF0aWNzID0gT2JqZWN0LnNldFByb3RvdHlwZU9mIHx8IHtcbiAgICAgIF9fcHJvdG9fXzogW11cbiAgICB9IGluc3RhbmNlb2YgQXJyYXkgJiYgZnVuY3Rpb24gKGQsIGIpIHtcbiAgICAgIGQuX19wcm90b19fID0gYjtcbiAgICB9IHx8IGZ1bmN0aW9uIChkLCBiKSB7XG4gICAgICBmb3IgKHZhciBwIGluIGIpIHtcbiAgICAgICAgaWYgKE9iamVjdC5wcm90b3R5cGUuaGFzT3duUHJvcGVydHkuY2FsbChiLCBwKSkgZFtwXSA9IGJbcF07XG4gICAgICB9XG4gICAgfTtcblxuICAgIHJldHVybiBfZXh0ZW5kU3RhdGljcyhkLCBiKTtcbiAgfTtcblxuICByZXR1cm4gZnVuY3Rpb24gKGQsIGIpIHtcbiAgICBfZXh0ZW5kU3RhdGljcyhkLCBiKTtcblxuICAgIGZ1bmN0aW9uIF9fKCkge1xuICAgICAgdGhpcy5jb25zdHJ1Y3RvciA9IGQ7XG4gICAgfVxuXG4gICAgZC5wcm90b3R5cGUgPSBiID09PSBudWxsID8gT2JqZWN0LmNyZWF0ZShiKSA6IChfXy5wcm90b3R5cGUgPSBiLnByb3RvdHlwZSwgbmV3IF9fKCkpO1xuICB9O1xufSgpO1xuXG5pbXBvcnQgRXZlbnRUeXBlIGZyb20gJy4uL2V2ZW50cy9FdmVudFR5cGUuanMnO1xuaW1wb3J0IFRpbGUgZnJvbSAnLi4vVmVjdG9yVGlsZS5qcyc7XG5pbXBvcnQgVGlsZUNhY2hlIGZyb20gJy4uL1RpbGVDYWNoZS5qcyc7XG5pbXBvcnQgVGlsZVN0YXRlIGZyb20gJy4uL1RpbGVTdGF0ZS5qcyc7XG5pbXBvcnQgVXJsVGlsZSBmcm9tICcuL1VybFRpbGUuanMnO1xuaW1wb3J0IFZlY3RvclJlbmRlclRpbGUgZnJvbSAnLi4vVmVjdG9yUmVuZGVyVGlsZS5qcyc7XG5pbXBvcnQgeyBidWZmZXIgYXMgYnVmZmVyRXh0ZW50LCBnZXRJbnRlcnNlY3Rpb24sIGludGVyc2VjdHMgfSBmcm9tICcuLi9leHRlbnQuanMnO1xuaW1wb3J0IHsgY3JlYXRlRm9yUHJvamVjdGlvbiwgY3JlYXRlWFlaLCBleHRlbnRGcm9tUHJvamVjdGlvbiB9IGZyb20gJy4uL3RpbGVncmlkLmpzJztcbmltcG9ydCB7IGVxdWFscyB9IGZyb20gJy4uL2FycmF5LmpzJztcbmltcG9ydCB7IGZyb21LZXksIGdldEtleVpYWSB9IGZyb20gJy4uL3RpbGVjb29yZC5qcyc7XG5pbXBvcnQgeyBsb2FkRmVhdHVyZXNYaHIgfSBmcm9tICcuLi9mZWF0dXJlbG9hZGVyLmpzJztcbmltcG9ydCB7IHRvU2l6ZSB9IGZyb20gJy4uL3NpemUuanMnO1xuLyoqXG4gKiBAdHlwZWRlZiB7T2JqZWN0fSBPcHRpb25zXG4gKiBAcHJvcGVydHkge2ltcG9ydChcIi4vU291cmNlLmpzXCIpLkF0dHJpYnV0aW9uTGlrZX0gW2F0dHJpYnV0aW9uc10gQXR0cmlidXRpb25zLlxuICogQHByb3BlcnR5IHtib29sZWFufSBbYXR0cmlidXRpb25zQ29sbGFwc2libGU9dHJ1ZV0gQXR0cmlidXRpb25zIGFyZSBjb2xsYXBzaWJsZS5cbiAqIEBwcm9wZXJ0eSB7bnVtYmVyfSBbY2FjaGVTaXplXSBJbml0aWFsIHRpbGUgY2FjaGUgc2l6ZS4gV2lsbCBhdXRvLWdyb3cgdG8gaG9sZCBhdCBsZWFzdCB0d2ljZSB0aGUgbnVtYmVyIG9mIHRpbGVzIGluIHRoZSB2aWV3cG9ydC5cbiAqIEBwcm9wZXJ0eSB7aW1wb3J0KFwiLi4vZXh0ZW50LmpzXCIpLkV4dGVudH0gW2V4dGVudF1cbiAqIEBwcm9wZXJ0eSB7aW1wb3J0KFwiLi4vZm9ybWF0L0ZlYXR1cmUuanNcIikuZGVmYXVsdH0gW2Zvcm1hdF0gRmVhdHVyZSBmb3JtYXQgZm9yIHRpbGVzLiBVc2VkIGFuZCByZXF1aXJlZCBieSB0aGUgZGVmYXVsdC5cbiAqIEBwcm9wZXJ0eSB7Ym9vbGVhbn0gW292ZXJsYXBzPXRydWVdIFRoaXMgc291cmNlIG1heSBoYXZlIG92ZXJsYXBwaW5nIGdlb21ldHJpZXMuIFNldHRpbmcgdGhpc1xuICogdG8gYGZhbHNlYCAoZS5nLiBmb3Igc291cmNlcyB3aXRoIHBvbHlnb25zIHRoYXQgcmVwcmVzZW50IGFkbWluaXN0cmF0aXZlXG4gKiBib3VuZGFyaWVzIG9yIFRvcG9KU09OIHNvdXJjZXMpIGFsbG93cyB0aGUgcmVuZGVyZXIgdG8gb3B0aW1pc2UgZmlsbCBhbmRcbiAqIHN0cm9rZSBvcGVyYXRpb25zLlxuICogQHByb3BlcnR5IHtpbXBvcnQoXCIuLi9wcm9qLmpzXCIpLlByb2plY3Rpb25MaWtlfSBbcHJvamVjdGlvbj0nRVBTRzozODU3J10gUHJvamVjdGlvbiBvZiB0aGUgdGlsZSBncmlkLlxuICogQHByb3BlcnR5IHtpbXBvcnQoXCIuL1N0YXRlLmpzXCIpLmRlZmF1bHR9IFtzdGF0ZV0gU291cmNlIHN0YXRlLlxuICogQHByb3BlcnR5IHt0eXBlb2YgaW1wb3J0KFwiLi4vVmVjdG9yVGlsZS5qc1wiKS5kZWZhdWx0fSBbdGlsZUNsYXNzXSBDbGFzcyB1c2VkIHRvIGluc3RhbnRpYXRlIGltYWdlIHRpbGVzLlxuICogRGVmYXVsdCBpcyB7QGxpbmsgbW9kdWxlOm9sL1ZlY3RvclRpbGV9LlxuICogQHByb3BlcnR5IHtudW1iZXJ9IFttYXhab29tPTIyXSBPcHRpb25hbCBtYXggem9vbSBsZXZlbC4gTm90IHVzZWQgaWYgYHRpbGVHcmlkYCBpcyBwcm92aWRlZC5cbiAqIEBwcm9wZXJ0eSB7bnVtYmVyfSBbbWluWm9vbV0gT3B0aW9uYWwgbWluIHpvb20gbGV2ZWwuIE5vdCB1c2VkIGlmIGB0aWxlR3JpZGAgaXMgcHJvdmlkZWQuXG4gKiBAcHJvcGVydHkge251bWJlcnxpbXBvcnQoXCIuLi9zaXplLmpzXCIpLlNpemV9IFt0aWxlU2l6ZT01MTJdIE9wdGlvbmFsIHRpbGUgc2l6ZS4gTm90IHVzZWQgaWYgYHRpbGVHcmlkYCBpcyBwcm92aWRlZC5cbiAqIEBwcm9wZXJ0eSB7bnVtYmVyfSBbbWF4UmVzb2x1dGlvbl0gT3B0aW9uYWwgdGlsZSBncmlkIHJlc29sdXRpb24gYXQgbGV2ZWwgemVyby4gTm90IHVzZWQgaWYgYHRpbGVHcmlkYCBpcyBwcm92aWRlZC5cbiAqIEBwcm9wZXJ0eSB7aW1wb3J0KFwiLi4vdGlsZWdyaWQvVGlsZUdyaWQuanNcIikuZGVmYXVsdH0gW3RpbGVHcmlkXSBUaWxlIGdyaWQuXG4gKiBAcHJvcGVydHkge2ltcG9ydChcIi4uL1RpbGUuanNcIikuTG9hZEZ1bmN0aW9ufSBbdGlsZUxvYWRGdW5jdGlvbl1cbiAqIE9wdGlvbmFsIGZ1bmN0aW9uIHRvIGxvYWQgYSB0aWxlIGdpdmVuIGEgVVJMLiBDb3VsZCBsb29rIGxpa2UgdGhpcyBmb3IgcGJmIHRpbGVzOlxuICogYGBganNcbiAqIGZ1bmN0aW9uKHRpbGUsIHVybCkge1xuICogICB0aWxlLnNldExvYWRlcihmdW5jdGlvbihleHRlbnQsIHJlc29sdXRpb24sIHByb2plY3Rpb24pIHtcbiAqICAgICBmZXRjaCh1cmwpLnRoZW4oZnVuY3Rpb24ocmVzcG9uc2UpIHtcbiAqICAgICAgIHJlc3BvbnNlLmFycmF5QnVmZmVyKCkudGhlbihmdW5jdGlvbihkYXRhKSB7XG4gKiAgICAgICAgIGNvbnN0IGZvcm1hdCA9IHRpbGUuZ2V0Rm9ybWF0KCkgLy8gb2wvZm9ybWF0L01WVCBjb25maWd1cmVkIGFzIHNvdXJjZSBmb3JtYXRcbiAqICAgICAgICAgY29uc3QgZmVhdHVyZXMgPSBmb3JtYXQucmVhZEZlYXR1cmVzKGRhdGEsIHtcbiAqICAgICAgICAgICBleHRlbnQ6IGV4dGVudCxcbiAqICAgICAgICAgICBmZWF0dXJlUHJvamVjdGlvbjogcHJvamVjdGlvblxuICogICAgICAgICB9KTtcbiAqICAgICAgICAgdGlsZS5zZXRGZWF0dXJlcyhmZWF0dXJlcyk7XG4gKiAgICAgICB9KTtcbiAqICAgICB9KTtcbiAqICAgfSk7XG4gKiB9XG4gKiBgYGBcbiAqIElmIHlvdSBkbyBub3QgbmVlZCBleHRlbnQsIHJlc29sdXRpb24gYW5kIHByb2plY3Rpb24gdG8gZ2V0IHRoZSBmZWF0dXJlcyBmb3IgYSB0aWxlIChlLmcuXG4gKiBmb3IgR2VvSlNPTiB0aWxlcyksIHlvdXIgYHRpbGVMb2FkRnVuY3Rpb25gIGRvZXMgbm90IG5lZWQgYSBgc2V0TG9hZGVyKClgIGNhbGwuIE9ubHkgbWFrZSBzdXJlXG4gKiB0byBjYWxsIGBzZXRGZWF0dXJlcygpYCBvbiB0aGUgdGlsZTpcbiAqIGBgYGpzXG4gKiBjb25zdCBmb3JtYXQgPSBuZXcgR2VvSlNPTih7ZmVhdHVyZVByb2plY3Rpb246IG1hcC5nZXRWaWV3KCkuZ2V0UHJvamVjdGlvbigpfSk7XG4gKiBhc3luYyBmdW5jdGlvbiB0aWxlTG9hZEZ1bmN0aW9uKHRpbGUsIHVybCkge1xuICogICBjb25zdCByZXNwb25zZSA9IGF3YWl0IGZldGNoKHVybCk7XG4gKiAgIGNvbnN0IGRhdGEgPSBhd2FpdCByZXNwb25zZS5qc29uKCk7XG4gKiAgIHRpbGUuc2V0RmVhdHVyZXMoZm9ybWF0LnJlYWRGZWF0dXJlcyhkYXRhKSk7XG4gKiB9XG4gKiBgYGBcbiAqIEBwcm9wZXJ0eSB7aW1wb3J0KFwiLi4vVGlsZS5qc1wiKS5VcmxGdW5jdGlvbn0gW3RpbGVVcmxGdW5jdGlvbl0gT3B0aW9uYWwgZnVuY3Rpb24gdG8gZ2V0IHRpbGUgVVJMIGdpdmVuIGEgdGlsZSBjb29yZGluYXRlIGFuZCB0aGUgcHJvamVjdGlvbi5cbiAqIEBwcm9wZXJ0eSB7c3RyaW5nfSBbdXJsXSBVUkwgdGVtcGxhdGUuIE11c3QgaW5jbHVkZSBge3h9YCwgYHt5fWAgb3IgYHsteX1gLCBhbmQgYHt6fWAgcGxhY2Vob2xkZXJzLlxuICogQSBgez8tP31gIHRlbXBsYXRlIHBhdHRlcm4sIGZvciBleGFtcGxlIGBzdWJkb21haW57YS1mfS5kb21haW4uY29tYCwgbWF5IGJlXG4gKiB1c2VkIGluc3RlYWQgb2YgZGVmaW5pbmcgZWFjaCBvbmUgc2VwYXJhdGVseSBpbiB0aGUgYHVybHNgIG9wdGlvbi5cbiAqIEBwcm9wZXJ0eSB7bnVtYmVyfSBbdHJhbnNpdGlvbl0gQSBkdXJhdGlvbiBmb3IgdGlsZSBvcGFjaXR5XG4gKiB0cmFuc2l0aW9ucyBpbiBtaWxsaXNlY29uZHMuIEEgZHVyYXRpb24gb2YgMCBkaXNhYmxlcyB0aGUgb3BhY2l0eSB0cmFuc2l0aW9uLlxuICogQHByb3BlcnR5IHtBcnJheTxzdHJpbmc+fSBbdXJsc10gQW4gYXJyYXkgb2YgVVJMIHRlbXBsYXRlcy5cbiAqIEBwcm9wZXJ0eSB7Ym9vbGVhbn0gW3dyYXBYPXRydWVdIFdoZXRoZXIgdG8gd3JhcCB0aGUgd29ybGQgaG9yaXpvbnRhbGx5LlxuICogV2hlbiBzZXQgdG8gYGZhbHNlYCwgb25seSBvbmUgd29ybGRcbiAqIHdpbGwgYmUgcmVuZGVyZWQuIFdoZW4gc2V0IHRvIGB0cnVlYCwgdGlsZXMgd2lsbCBiZSB3cmFwcGVkIGhvcml6b250YWxseSB0b1xuICogcmVuZGVyIG11bHRpcGxlIHdvcmxkcy5cbiAqIEBwcm9wZXJ0eSB7bnVtYmVyfSBbekRpcmVjdGlvbj0xXSBJbmRpY2F0ZSB3aGljaCByZXNvbHV0aW9uIHNob3VsZCBiZSB1c2VkXG4gKiBieSBhIHJlbmRlcmVyIGlmIHRoZSB2aWV3IHJlc29sdXRpb24gZG9lcyBub3QgbWF0Y2ggYW55IHJlc29sdXRpb24gb2YgdGhlIHRpbGUgc291cmNlLlxuICogSWYgMCwgdGhlIG5lYXJlc3QgcmVzb2x1dGlvbiB3aWxsIGJlIHVzZWQuIElmIDEsIHRoZSBuZWFyZXN0IGxvd2VyIHJlc29sdXRpb25cbiAqIHdpbGwgYmUgdXNlZC4gSWYgLTEsIHRoZSBuZWFyZXN0IGhpZ2hlciByZXNvbHV0aW9uIHdpbGwgYmUgdXNlZC5cbiAqL1xuXG4vKipcbiAqIEBjbGFzc2Rlc2NcbiAqIENsYXNzIGZvciBsYXllciBzb3VyY2VzIHByb3ZpZGluZyB2ZWN0b3IgZGF0YSBkaXZpZGVkIGludG8gYSB0aWxlIGdyaWQsIHRvIGJlXG4gKiB1c2VkIHdpdGgge0BsaW5rIG1vZHVsZTpvbC9sYXllci9WZWN0b3JUaWxlflZlY3RvclRpbGV9LiBBbHRob3VnaCB0aGlzIHNvdXJjZSByZWNlaXZlcyB0aWxlc1xuICogd2l0aCB2ZWN0b3IgZmVhdHVyZXMgZnJvbSB0aGUgc2VydmVyLCBpdCBpcyBub3QgbWVhbnQgZm9yIGZlYXR1cmUgZWRpdGluZy5cbiAqIEZlYXR1cmVzIGFyZSBvcHRpbWl6ZWQgZm9yIHJlbmRlcmluZywgdGhlaXIgZ2VvbWV0cmllcyBhcmUgY2xpcHBlZCBhdCBvciBuZWFyXG4gKiB0aWxlIGJvdW5kYXJpZXMgYW5kIHNpbXBsaWZpZWQgZm9yIGEgdmlldyByZXNvbHV0aW9uLiBTZWVcbiAqIHtAbGluayBtb2R1bGU6b2wvc291cmNlL1ZlY3Rvcn0gZm9yIHZlY3RvciBzb3VyY2VzIHRoYXQgYXJlIHN1aXRhYmxlIGZvciBmZWF0dXJlXG4gKiBlZGl0aW5nLlxuICpcbiAqIEBmaXJlcyBpbXBvcnQoXCIuL1RpbGUuanNcIikuVGlsZVNvdXJjZUV2ZW50XG4gKiBAYXBpXG4gKi9cblxudmFyIFZlY3RvclRpbGUgPVxuLyoqIEBjbGFzcyAqL1xuZnVuY3Rpb24gKF9zdXBlcikge1xuICBfX2V4dGVuZHMoVmVjdG9yVGlsZSwgX3N1cGVyKTtcbiAgLyoqXG4gICAqIEBwYXJhbSB7IU9wdGlvbnN9IG9wdGlvbnMgVmVjdG9yIHRpbGUgb3B0aW9ucy5cbiAgICovXG5cblxuICBmdW5jdGlvbiBWZWN0b3JUaWxlKG9wdGlvbnMpIHtcbiAgICB2YXIgX3RoaXMgPSB0aGlzO1xuXG4gICAgdmFyIHByb2plY3Rpb24gPSBvcHRpb25zLnByb2plY3Rpb24gfHwgJ0VQU0c6Mzg1Nyc7XG4gICAgdmFyIGV4dGVudCA9IG9wdGlvbnMuZXh0ZW50IHx8IGV4dGVudEZyb21Qcm9qZWN0aW9uKHByb2plY3Rpb24pO1xuICAgIHZhciB0aWxlR3JpZCA9IG9wdGlvbnMudGlsZUdyaWQgfHwgY3JlYXRlWFlaKHtcbiAgICAgIGV4dGVudDogZXh0ZW50LFxuICAgICAgbWF4UmVzb2x1dGlvbjogb3B0aW9ucy5tYXhSZXNvbHV0aW9uLFxuICAgICAgbWF4Wm9vbTogb3B0aW9ucy5tYXhab29tICE9PSB1bmRlZmluZWQgPyBvcHRpb25zLm1heFpvb20gOiAyMixcbiAgICAgIG1pblpvb206IG9wdGlvbnMubWluWm9vbSxcbiAgICAgIHRpbGVTaXplOiBvcHRpb25zLnRpbGVTaXplIHx8IDUxMlxuICAgIH0pO1xuICAgIF90aGlzID0gX3N1cGVyLmNhbGwodGhpcywge1xuICAgICAgYXR0cmlidXRpb25zOiBvcHRpb25zLmF0dHJpYnV0aW9ucyxcbiAgICAgIGF0dHJpYnV0aW9uc0NvbGxhcHNpYmxlOiBvcHRpb25zLmF0dHJpYnV0aW9uc0NvbGxhcHNpYmxlLFxuICAgICAgY2FjaGVTaXplOiBvcHRpb25zLmNhY2hlU2l6ZSxcbiAgICAgIG9wYXF1ZTogZmFsc2UsXG4gICAgICBwcm9qZWN0aW9uOiBwcm9qZWN0aW9uLFxuICAgICAgc3RhdGU6IG9wdGlvbnMuc3RhdGUsXG4gICAgICB0aWxlR3JpZDogdGlsZUdyaWQsXG4gICAgICB0aWxlTG9hZEZ1bmN0aW9uOiBvcHRpb25zLnRpbGVMb2FkRnVuY3Rpb24gPyBvcHRpb25zLnRpbGVMb2FkRnVuY3Rpb24gOiBkZWZhdWx0TG9hZEZ1bmN0aW9uLFxuICAgICAgdGlsZVVybEZ1bmN0aW9uOiBvcHRpb25zLnRpbGVVcmxGdW5jdGlvbixcbiAgICAgIHVybDogb3B0aW9ucy51cmwsXG4gICAgICB1cmxzOiBvcHRpb25zLnVybHMsXG4gICAgICB3cmFwWDogb3B0aW9ucy53cmFwWCA9PT0gdW5kZWZpbmVkID8gdHJ1ZSA6IG9wdGlvbnMud3JhcFgsXG4gICAgICB0cmFuc2l0aW9uOiBvcHRpb25zLnRyYW5zaXRpb24sXG4gICAgICB6RGlyZWN0aW9uOiBvcHRpb25zLnpEaXJlY3Rpb24gPT09IHVuZGVmaW5lZCA/IDEgOiBvcHRpb25zLnpEaXJlY3Rpb25cbiAgICB9KSB8fCB0aGlzO1xuICAgIC8qKlxuICAgICAqIEBwcml2YXRlXG4gICAgICogQHR5cGUge2ltcG9ydChcIi4uL2Zvcm1hdC9GZWF0dXJlLmpzXCIpLmRlZmF1bHR9XG4gICAgICovXG5cbiAgICBfdGhpcy5mb3JtYXRfID0gb3B0aW9ucy5mb3JtYXQgPyBvcHRpb25zLmZvcm1hdCA6IG51bGw7XG4gICAgLyoqXG4gICAgICogQHR5cGUge09iamVjdDxzdHJpbmcsIGltcG9ydChcIi4vVmVjdG9yVGlsZVwiKS5kZWZhdWx0Pn1cbiAgICAgKi9cblxuICAgIF90aGlzLmxvYWRpbmdUaWxlc18gPSB7fTtcbiAgICAvKipcbiAgICAgKiBAcHJpdmF0ZVxuICAgICAqIEB0eXBlIHtUaWxlQ2FjaGV9XG4gICAgICovXG5cbiAgICBfdGhpcy5zb3VyY2VUaWxlQ2FjaGUgPSBuZXcgVGlsZUNhY2hlKF90aGlzLnRpbGVDYWNoZS5oaWdoV2F0ZXJNYXJrKTtcbiAgICAvKipcbiAgICAgKiBAcHJpdmF0ZVxuICAgICAqIEB0eXBlIHtib29sZWFufVxuICAgICAqL1xuXG4gICAgX3RoaXMub3ZlcmxhcHNfID0gb3B0aW9ucy5vdmVybGFwcyA9PSB1bmRlZmluZWQgPyB0cnVlIDogb3B0aW9ucy5vdmVybGFwcztcbiAgICAvKipcbiAgICAgKiBAcHJvdGVjdGVkXG4gICAgICogQHR5cGUge3R5cGVvZiBpbXBvcnQoXCIuLi9WZWN0b3JUaWxlLmpzXCIpLmRlZmF1bHR9XG4gICAgICovXG5cbiAgICBfdGhpcy50aWxlQ2xhc3MgPSBvcHRpb25zLnRpbGVDbGFzcyA/IG9wdGlvbnMudGlsZUNsYXNzIDogVGlsZTtcbiAgICAvKipcbiAgICAgKiBAcHJpdmF0ZVxuICAgICAqIEB0eXBlIHtPYmplY3Q8c3RyaW5nLCBpbXBvcnQoXCIuLi90aWxlZ3JpZC9UaWxlR3JpZC5qc1wiKS5kZWZhdWx0Pn1cbiAgICAgKi9cblxuICAgIF90aGlzLnRpbGVHcmlkc18gPSB7fTtcbiAgICByZXR1cm4gX3RoaXM7XG4gIH1cbiAgLyoqXG4gICAqIEdldCBmZWF0dXJlcyB3aG9zZSBib3VuZGluZyBib3ggaW50ZXJzZWN0cyB0aGUgcHJvdmlkZWQgZXh0ZW50LiBPbmx5IGZlYXR1cmVzIGZvciBjYWNoZWRcbiAgICogdGlsZXMgZm9yIHRoZSBsYXN0IHJlbmRlcmVkIHpvb20gbGV2ZWwgYXJlIGF2YWlsYWJsZSBpbiB0aGUgc291cmNlLiBTbyB0aGlzIG1ldGhvZCBpcyBvbmx5XG4gICAqIHN1aXRhYmxlIGZvciByZXF1ZXN0aW5nIHRpbGVzIGZvciBleHRlbnRzIHRoYXQgYXJlIGN1cnJlbnRseSByZW5kZXJlZC5cbiAgICpcbiAgICogRmVhdHVyZXMgYXJlIHJldHVybmVkIGluIHJhbmRvbSB0aWxlIG9yZGVyIGFuZCBhcyB0aGV5IGFyZSBpbmNsdWRlZCBpbiB0aGUgdGlsZXMuIFRoaXMgbWVhbnNcbiAgICogdGhleSBjYW4gYmUgY2xpcHBlZCwgZHVwbGljYXRlZCBhY3Jvc3MgdGlsZXMsIGFuZCBzaW1wbGlmaWVkIHRvIHRoZSByZW5kZXIgcmVzb2x1dGlvbi5cbiAgICpcbiAgICogQHBhcmFtIHtpbXBvcnQoXCIuLi9leHRlbnQuanNcIikuRXh0ZW50fSBleHRlbnQgRXh0ZW50LlxuICAgKiBAcmV0dXJuIHtBcnJheTxpbXBvcnQoXCIuLi9GZWF0dXJlLmpzXCIpLkZlYXR1cmVMaWtlPn0gRmVhdHVyZXMuXG4gICAqIEBhcGlcbiAgICovXG5cblxuICBWZWN0b3JUaWxlLnByb3RvdHlwZS5nZXRGZWF0dXJlc0luRXh0ZW50ID0gZnVuY3Rpb24gKGV4dGVudCkge1xuICAgIHZhciBmZWF0dXJlcyA9IFtdO1xuICAgIHZhciB0aWxlQ2FjaGUgPSB0aGlzLnRpbGVDYWNoZTtcblxuICAgIGlmICh0aWxlQ2FjaGUuZ2V0Q291bnQoKSA9PT0gMCkge1xuICAgICAgcmV0dXJuIGZlYXR1cmVzO1xuICAgIH1cblxuICAgIHZhciB6ID0gZnJvbUtleSh0aWxlQ2FjaGUucGVla0ZpcnN0S2V5KCkpWzBdO1xuICAgIHZhciB0aWxlR3JpZCA9IHRoaXMudGlsZUdyaWQ7XG4gICAgdGlsZUNhY2hlLmZvckVhY2goZnVuY3Rpb24gKHRpbGUpIHtcbiAgICAgIGlmICh0aWxlLnRpbGVDb29yZFswXSAhPT0geiB8fCB0aWxlLmdldFN0YXRlKCkgIT09IFRpbGVTdGF0ZS5MT0FERUQpIHtcbiAgICAgICAgcmV0dXJuO1xuICAgICAgfVxuXG4gICAgICB2YXIgc291cmNlVGlsZXMgPSB0aWxlLmdldFNvdXJjZVRpbGVzKCk7XG5cbiAgICAgIGZvciAodmFyIGkgPSAwLCBpaSA9IHNvdXJjZVRpbGVzLmxlbmd0aDsgaSA8IGlpOyArK2kpIHtcbiAgICAgICAgdmFyIHNvdXJjZVRpbGUgPSBzb3VyY2VUaWxlc1tpXTtcbiAgICAgICAgdmFyIHRpbGVDb29yZCA9IHNvdXJjZVRpbGUudGlsZUNvb3JkO1xuXG4gICAgICAgIGlmIChpbnRlcnNlY3RzKGV4dGVudCwgdGlsZUdyaWQuZ2V0VGlsZUNvb3JkRXh0ZW50KHRpbGVDb29yZCkpKSB7XG4gICAgICAgICAgdmFyIHRpbGVGZWF0dXJlcyA9IHNvdXJjZVRpbGUuZ2V0RmVhdHVyZXMoKTtcblxuICAgICAgICAgIGlmICh0aWxlRmVhdHVyZXMpIHtcbiAgICAgICAgICAgIGZvciAodmFyIGogPSAwLCBqaiA9IHRpbGVGZWF0dXJlcy5sZW5ndGg7IGogPCBqajsgKytqKSB7XG4gICAgICAgICAgICAgIHZhciBjYW5kaWRhdGUgPSB0aWxlRmVhdHVyZXNbal07XG4gICAgICAgICAgICAgIHZhciBnZW9tZXRyeSA9IGNhbmRpZGF0ZS5nZXRHZW9tZXRyeSgpO1xuXG4gICAgICAgICAgICAgIGlmIChpbnRlcnNlY3RzKGV4dGVudCwgZ2VvbWV0cnkuZ2V0RXh0ZW50KCkpKSB7XG4gICAgICAgICAgICAgICAgZmVhdHVyZXMucHVzaChjYW5kaWRhdGUpO1xuICAgICAgICAgICAgICB9XG4gICAgICAgICAgICB9XG4gICAgICAgICAgfVxuICAgICAgICB9XG4gICAgICB9XG4gICAgfSk7XG4gICAgcmV0dXJuIGZlYXR1cmVzO1xuICB9O1xuICAvKipcbiAgICogQHJldHVybiB7Ym9vbGVhbn0gVGhlIHNvdXJjZSBjYW4gaGF2ZSBvdmVybGFwcGluZyBnZW9tZXRyaWVzLlxuICAgKi9cblxuXG4gIFZlY3RvclRpbGUucHJvdG90eXBlLmdldE92ZXJsYXBzID0gZnVuY3Rpb24gKCkge1xuICAgIHJldHVybiB0aGlzLm92ZXJsYXBzXztcbiAgfTtcbiAgLyoqXG4gICAqIGNsZWFyIHtAbGluayBtb2R1bGU6b2wvVGlsZUNhY2hlflRpbGVDYWNoZX0gYW5kIGRlbGV0ZSBhbGwgc291cmNlIHRpbGVzXG4gICAqIEBhcGlcbiAgICovXG5cblxuICBWZWN0b3JUaWxlLnByb3RvdHlwZS5jbGVhciA9IGZ1bmN0aW9uICgpIHtcbiAgICB0aGlzLnRpbGVDYWNoZS5jbGVhcigpO1xuICAgIHRoaXMuc291cmNlVGlsZUNhY2hlLmNsZWFyKCk7XG4gIH07XG4gIC8qKlxuICAgKiBAcGFyYW0ge2ltcG9ydChcIi4uL3Byb2ovUHJvamVjdGlvbi5qc1wiKS5kZWZhdWx0fSBwcm9qZWN0aW9uIFByb2plY3Rpb24uXG4gICAqIEBwYXJhbSB7IU9iamVjdDxzdHJpbmcsIGJvb2xlYW4+fSB1c2VkVGlsZXMgVXNlZCB0aWxlcy5cbiAgICovXG5cblxuICBWZWN0b3JUaWxlLnByb3RvdHlwZS5leHBpcmVDYWNoZSA9IGZ1bmN0aW9uIChwcm9qZWN0aW9uLCB1c2VkVGlsZXMpIHtcbiAgICBfc3VwZXIucHJvdG90eXBlLmV4cGlyZUNhY2hlLmNhbGwodGhpcywgcHJvamVjdGlvbiwgdXNlZFRpbGVzKTtcblxuICAgIHRoaXMuc291cmNlVGlsZUNhY2hlLmV4cGlyZUNhY2hlKHt9KTtcbiAgfTtcbiAgLyoqXG4gICAqIEBwYXJhbSB7bnVtYmVyfSBwaXhlbFJhdGlvIFBpeGVsIHJhdGlvLlxuICAgKiBAcGFyYW0ge2ltcG9ydChcIi4uL3Byb2ovUHJvamVjdGlvblwiKS5kZWZhdWx0fSBwcm9qZWN0aW9uIFByb2plY3Rpb24uXG4gICAqIEBwYXJhbSB7VmVjdG9yUmVuZGVyVGlsZX0gdGlsZSBWZWN0b3IgaW1hZ2UgdGlsZS5cbiAgICogQHJldHVybiB7QXJyYXk8aW1wb3J0KFwiLi4vVmVjdG9yVGlsZVwiKS5kZWZhdWx0Pn0gVGlsZSBrZXlzLlxuICAgKi9cblxuXG4gIFZlY3RvclRpbGUucHJvdG90eXBlLmdldFNvdXJjZVRpbGVzID0gZnVuY3Rpb24gKHBpeGVsUmF0aW8sIHByb2plY3Rpb24sIHRpbGUpIHtcbiAgICB2YXIgdXJsVGlsZUNvb3JkID0gdGlsZS53cmFwcGVkVGlsZUNvb3JkO1xuICAgIHZhciB0aWxlR3JpZCA9IHRoaXMuZ2V0VGlsZUdyaWRGb3JQcm9qZWN0aW9uKHByb2plY3Rpb24pO1xuICAgIHZhciBleHRlbnQgPSB0aWxlR3JpZC5nZXRUaWxlQ29vcmRFeHRlbnQodXJsVGlsZUNvb3JkKTtcbiAgICB2YXIgeiA9IHVybFRpbGVDb29yZFswXTtcbiAgICB2YXIgcmVzb2x1dGlvbiA9IHRpbGVHcmlkLmdldFJlc29sdXRpb24oeik7IC8vIG1ha2UgZXh0ZW50IDEgcGl4ZWwgc21hbGxlciBzbyB3ZSBkb24ndCBsb2FkIHRpbGVzIGZvciA8IDAuNSBwaXhlbCByZW5kZXIgc3BhY2VcblxuICAgIGJ1ZmZlckV4dGVudChleHRlbnQsIC1yZXNvbHV0aW9uLCBleHRlbnQpO1xuICAgIHZhciBzb3VyY2VUaWxlR3JpZCA9IHRoaXMudGlsZUdyaWQ7XG4gICAgdmFyIHNvdXJjZUV4dGVudCA9IHNvdXJjZVRpbGVHcmlkLmdldEV4dGVudCgpO1xuXG4gICAgaWYgKHNvdXJjZUV4dGVudCkge1xuICAgICAgZ2V0SW50ZXJzZWN0aW9uKGV4dGVudCwgc291cmNlRXh0ZW50LCBleHRlbnQpO1xuICAgIH1cblxuICAgIHZhciBzb3VyY2VaID0gc291cmNlVGlsZUdyaWQuZ2V0WkZvclJlc29sdXRpb24ocmVzb2x1dGlvbiwgMSk7XG4gICAgdmFyIG1pblpvb20gPSBzb3VyY2VUaWxlR3JpZC5nZXRNaW5ab29tKCk7XG4gICAgdmFyIHByZXZpb3VzU291cmNlVGlsZXMgPSB0aWxlLnNvdXJjZVRpbGVzO1xuICAgIHZhciBzb3VyY2VUaWxlcywgY292ZXJlZCwgbG9hZGVkWjtcblxuICAgIGlmIChwcmV2aW91c1NvdXJjZVRpbGVzICYmIHByZXZpb3VzU291cmNlVGlsZXMubGVuZ3RoID4gMCAmJiBwcmV2aW91c1NvdXJjZVRpbGVzWzBdLnRpbGVDb29yZFswXSA9PT0gc291cmNlWikge1xuICAgICAgc291cmNlVGlsZXMgPSBwcmV2aW91c1NvdXJjZVRpbGVzO1xuICAgICAgY292ZXJlZCA9IHRydWU7XG4gICAgICBsb2FkZWRaID0gc291cmNlWjtcbiAgICB9IGVsc2Uge1xuICAgICAgc291cmNlVGlsZXMgPSBbXTtcbiAgICAgIGxvYWRlZFogPSBzb3VyY2VaICsgMTtcblxuICAgICAgZG8ge1xuICAgICAgICAtLWxvYWRlZFo7XG4gICAgICAgIGNvdmVyZWQgPSB0cnVlO1xuICAgICAgICBzb3VyY2VUaWxlR3JpZC5mb3JFYWNoVGlsZUNvb3JkKGV4dGVudCwgbG9hZGVkWiwgZnVuY3Rpb24gKHNvdXJjZVRpbGVDb29yZCkge1xuICAgICAgICAgIHZhciB0aWxlVXJsID0gdGhpcy50aWxlVXJsRnVuY3Rpb24oc291cmNlVGlsZUNvb3JkLCBwaXhlbFJhdGlvLCBwcm9qZWN0aW9uKTtcbiAgICAgICAgICB2YXIgc291cmNlVGlsZTtcblxuICAgICAgICAgIGlmICh0aWxlVXJsICE9PSB1bmRlZmluZWQpIHtcbiAgICAgICAgICAgIGlmICh0aGlzLnNvdXJjZVRpbGVDYWNoZS5jb250YWluc0tleSh0aWxlVXJsKSkge1xuICAgICAgICAgICAgICBzb3VyY2VUaWxlID0gdGhpcy5zb3VyY2VUaWxlQ2FjaGUuZ2V0KHRpbGVVcmwpO1xuICAgICAgICAgICAgICB2YXIgc3RhdGUgPSBzb3VyY2VUaWxlLmdldFN0YXRlKCk7XG5cbiAgICAgICAgICAgICAgaWYgKHN0YXRlID09PSBUaWxlU3RhdGUuTE9BREVEIHx8IHN0YXRlID09PSBUaWxlU3RhdGUuRVJST1IgfHwgc3RhdGUgPT09IFRpbGVTdGF0ZS5FTVBUWSkge1xuICAgICAgICAgICAgICAgIHNvdXJjZVRpbGVzLnB1c2goc291cmNlVGlsZSk7XG4gICAgICAgICAgICAgICAgcmV0dXJuO1xuICAgICAgICAgICAgICB9XG4gICAgICAgICAgICB9IGVsc2UgaWYgKGxvYWRlZFogPT09IHNvdXJjZVopIHtcbiAgICAgICAgICAgICAgc291cmNlVGlsZSA9IG5ldyB0aGlzLnRpbGVDbGFzcyhzb3VyY2VUaWxlQ29vcmQsIFRpbGVTdGF0ZS5JRExFLCB0aWxlVXJsLCB0aGlzLmZvcm1hdF8sIHRoaXMudGlsZUxvYWRGdW5jdGlvbik7XG4gICAgICAgICAgICAgIHNvdXJjZVRpbGUuZXh0ZW50ID0gc291cmNlVGlsZUdyaWQuZ2V0VGlsZUNvb3JkRXh0ZW50KHNvdXJjZVRpbGVDb29yZCk7XG4gICAgICAgICAgICAgIHNvdXJjZVRpbGUucHJvamVjdGlvbiA9IHByb2plY3Rpb247XG4gICAgICAgICAgICAgIHNvdXJjZVRpbGUucmVzb2x1dGlvbiA9IHNvdXJjZVRpbGVHcmlkLmdldFJlc29sdXRpb24oc291cmNlVGlsZUNvb3JkWzBdKTtcbiAgICAgICAgICAgICAgdGhpcy5zb3VyY2VUaWxlQ2FjaGUuc2V0KHRpbGVVcmwsIHNvdXJjZVRpbGUpO1xuICAgICAgICAgICAgICBzb3VyY2VUaWxlLmFkZEV2ZW50TGlzdGVuZXIoRXZlbnRUeXBlLkNIQU5HRSwgdGhpcy5oYW5kbGVUaWxlQ2hhbmdlLmJpbmQodGhpcykpO1xuICAgICAgICAgICAgICBzb3VyY2VUaWxlLmxvYWQoKTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgICB9XG5cbiAgICAgICAgICBjb3ZlcmVkID0gY292ZXJlZCAmJiBzb3VyY2VUaWxlICYmIHNvdXJjZVRpbGUuZ2V0U3RhdGUoKSA9PT0gVGlsZVN0YXRlLkxPQURFRDtcblxuICAgICAgICAgIGlmICghc291cmNlVGlsZSkge1xuICAgICAgICAgICAgcmV0dXJuO1xuICAgICAgICAgIH1cblxuICAgICAgICAgIGlmIChzb3VyY2VUaWxlLmdldFN0YXRlKCkgIT09IFRpbGVTdGF0ZS5FTVBUWSAmJiB0aWxlLmdldFN0YXRlKCkgPT09IFRpbGVTdGF0ZS5JRExFKSB7XG4gICAgICAgICAgICB0aWxlLmxvYWRpbmdTb3VyY2VUaWxlcysrO1xuICAgICAgICAgICAgc291cmNlVGlsZS5hZGRFdmVudExpc3RlbmVyKEV2ZW50VHlwZS5DSEFOR0UsIGZ1bmN0aW9uIGxpc3RlbkNoYW5nZSgpIHtcbiAgICAgICAgICAgICAgdmFyIHN0YXRlID0gc291cmNlVGlsZS5nZXRTdGF0ZSgpO1xuICAgICAgICAgICAgICB2YXIgc291cmNlVGlsZUtleSA9IHNvdXJjZVRpbGUuZ2V0S2V5KCk7XG5cbiAgICAgICAgICAgICAgaWYgKHN0YXRlID09PSBUaWxlU3RhdGUuTE9BREVEIHx8IHN0YXRlID09PSBUaWxlU3RhdGUuRVJST1IpIHtcbiAgICAgICAgICAgICAgICBpZiAoc3RhdGUgPT09IFRpbGVTdGF0ZS5MT0FERUQpIHtcbiAgICAgICAgICAgICAgICAgIHNvdXJjZVRpbGUucmVtb3ZlRXZlbnRMaXN0ZW5lcihFdmVudFR5cGUuQ0hBTkdFLCBsaXN0ZW5DaGFuZ2UpO1xuICAgICAgICAgICAgICAgICAgdGlsZS5sb2FkaW5nU291cmNlVGlsZXMtLTtcbiAgICAgICAgICAgICAgICAgIGRlbGV0ZSB0aWxlLmVycm9yU291cmNlVGlsZUtleXNbc291cmNlVGlsZUtleV07XG4gICAgICAgICAgICAgICAgfSBlbHNlIGlmIChzdGF0ZSA9PT0gVGlsZVN0YXRlLkVSUk9SKSB7XG4gICAgICAgICAgICAgICAgICB0aWxlLmVycm9yU291cmNlVGlsZUtleXNbc291cmNlVGlsZUtleV0gPSB0cnVlO1xuICAgICAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgICAgIHZhciBlcnJvclRpbGVDb3VudCA9IE9iamVjdC5rZXlzKHRpbGUuZXJyb3JTb3VyY2VUaWxlS2V5cykubGVuZ3RoO1xuXG4gICAgICAgICAgICAgICAgaWYgKHRpbGUubG9hZGluZ1NvdXJjZVRpbGVzIC0gZXJyb3JUaWxlQ291bnQgPT09IDApIHtcbiAgICAgICAgICAgICAgICAgIHRpbGUuaGlmaSA9IGVycm9yVGlsZUNvdW50ID09PSAwO1xuICAgICAgICAgICAgICAgICAgdGlsZS5zb3VyY2VaID0gc291cmNlWjtcbiAgICAgICAgICAgICAgICAgIHRpbGUuc2V0U3RhdGUoVGlsZVN0YXRlLkxPQURFRCk7XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICB9XG4gICAgICAgICAgICB9KTtcbiAgICAgICAgICB9XG4gICAgICAgIH0uYmluZCh0aGlzKSk7XG5cbiAgICAgICAgaWYgKCFjb3ZlcmVkKSB7XG4gICAgICAgICAgc291cmNlVGlsZXMubGVuZ3RoID0gMDtcbiAgICAgICAgfVxuICAgICAgfSB3aGlsZSAoIWNvdmVyZWQgJiYgbG9hZGVkWiA+IG1pblpvb20pO1xuICAgIH1cblxuICAgIGlmICh0aWxlLmdldFN0YXRlKCkgPT09IFRpbGVTdGF0ZS5JRExFKSB7XG4gICAgICB0aWxlLnNldFN0YXRlKFRpbGVTdGF0ZS5MT0FESU5HKTtcbiAgICB9XG5cbiAgICBpZiAoY292ZXJlZCkge1xuICAgICAgdGlsZS5oaWZpID0gc291cmNlWiA9PT0gbG9hZGVkWjtcbiAgICAgIHRpbGUuc291cmNlWiA9IGxvYWRlZFo7XG5cbiAgICAgIGlmICh0aWxlLmdldFN0YXRlKCkgPCBUaWxlU3RhdGUuTE9BREVEKSB7XG4gICAgICAgIHRpbGUuc2V0U3RhdGUoVGlsZVN0YXRlLkxPQURFRCk7XG4gICAgICB9IGVsc2UgaWYgKCFwcmV2aW91c1NvdXJjZVRpbGVzIHx8ICFlcXVhbHMoc291cmNlVGlsZXMsIHByZXZpb3VzU291cmNlVGlsZXMpKSB7XG4gICAgICAgIHRpbGUuc291cmNlVGlsZXMgPSBzb3VyY2VUaWxlcztcbiAgICAgIH1cbiAgICB9XG5cbiAgICByZXR1cm4gc291cmNlVGlsZXM7XG4gIH07XG4gIC8qKlxuICAgKiBAcGFyYW0ge251bWJlcn0geiBUaWxlIGNvb3JkaW5hdGUgei5cbiAgICogQHBhcmFtIHtudW1iZXJ9IHggVGlsZSBjb29yZGluYXRlIHguXG4gICAqIEBwYXJhbSB7bnVtYmVyfSB5IFRpbGUgY29vcmRpbmF0ZSB5LlxuICAgKiBAcGFyYW0ge251bWJlcn0gcGl4ZWxSYXRpbyBQaXhlbCByYXRpby5cbiAgICogQHBhcmFtIHtpbXBvcnQoXCIuLi9wcm9qL1Byb2plY3Rpb24uanNcIikuZGVmYXVsdH0gcHJvamVjdGlvbiBQcm9qZWN0aW9uLlxuICAgKiBAcmV0dXJuIHshVmVjdG9yUmVuZGVyVGlsZX0gVGlsZS5cbiAgICovXG5cblxuICBWZWN0b3JUaWxlLnByb3RvdHlwZS5nZXRUaWxlID0gZnVuY3Rpb24gKHosIHgsIHksIHBpeGVsUmF0aW8sIHByb2plY3Rpb24pIHtcbiAgICB2YXIgY29vcmRLZXkgPSBnZXRLZXlaWFkoeiwgeCwgeSk7XG4gICAgdmFyIGtleSA9IHRoaXMuZ2V0S2V5KCk7XG4gICAgdmFyIHRpbGU7XG5cbiAgICBpZiAodGhpcy50aWxlQ2FjaGUuY29udGFpbnNLZXkoY29vcmRLZXkpKSB7XG4gICAgICB0aWxlID0gdGhpcy50aWxlQ2FjaGUuZ2V0KGNvb3JkS2V5KTtcblxuICAgICAgaWYgKHRpbGUua2V5ID09PSBrZXkpIHtcbiAgICAgICAgcmV0dXJuIHRpbGU7XG4gICAgICB9XG4gICAgfVxuXG4gICAgdmFyIHRpbGVDb29yZCA9IFt6LCB4LCB5XTtcbiAgICB2YXIgdXJsVGlsZUNvb3JkID0gdGhpcy5nZXRUaWxlQ29vcmRGb3JUaWxlVXJsRnVuY3Rpb24odGlsZUNvb3JkLCBwcm9qZWN0aW9uKTtcbiAgICB2YXIgc291cmNlRXh0ZW50ID0gdGhpcy5nZXRUaWxlR3JpZCgpLmdldEV4dGVudCgpO1xuICAgIHZhciB0aWxlR3JpZCA9IHRoaXMuZ2V0VGlsZUdyaWRGb3JQcm9qZWN0aW9uKHByb2plY3Rpb24pO1xuXG4gICAgaWYgKHVybFRpbGVDb29yZCAmJiBzb3VyY2VFeHRlbnQpIHtcbiAgICAgIHZhciB0aWxlRXh0ZW50ID0gdGlsZUdyaWQuZ2V0VGlsZUNvb3JkRXh0ZW50KHVybFRpbGVDb29yZCk7IC8vIG1ha2UgZXh0ZW50IDEgcGl4ZWwgc21hbGxlciBzbyB3ZSBkb24ndCBsb2FkIHRpbGVzIGZvciA8IDAuNSBwaXhlbCByZW5kZXIgc3BhY2VcblxuICAgICAgYnVmZmVyRXh0ZW50KHRpbGVFeHRlbnQsIC10aWxlR3JpZC5nZXRSZXNvbHV0aW9uKHopLCB0aWxlRXh0ZW50KTtcblxuICAgICAgaWYgKCFpbnRlcnNlY3RzKHNvdXJjZUV4dGVudCwgdGlsZUV4dGVudCkpIHtcbiAgICAgICAgdXJsVGlsZUNvb3JkID0gbnVsbDtcbiAgICAgIH1cbiAgICB9XG5cbiAgICB2YXIgZW1wdHkgPSB0cnVlO1xuXG4gICAgaWYgKHVybFRpbGVDb29yZCAhPT0gbnVsbCkge1xuICAgICAgdmFyIHNvdXJjZVRpbGVHcmlkID0gdGhpcy50aWxlR3JpZDtcbiAgICAgIHZhciByZXNvbHV0aW9uID0gdGlsZUdyaWQuZ2V0UmVzb2x1dGlvbih6KTtcbiAgICAgIHZhciBzb3VyY2VaID0gc291cmNlVGlsZUdyaWQuZ2V0WkZvclJlc29sdXRpb24ocmVzb2x1dGlvbiwgMSk7IC8vIG1ha2UgZXh0ZW50IDEgcGl4ZWwgc21hbGxlciBzbyB3ZSBkb24ndCBsb2FkIHRpbGVzIGZvciA8IDAuNSBwaXhlbCByZW5kZXIgc3BhY2VcblxuICAgICAgdmFyIGV4dGVudCA9IHRpbGVHcmlkLmdldFRpbGVDb29yZEV4dGVudCh1cmxUaWxlQ29vcmQpO1xuICAgICAgYnVmZmVyRXh0ZW50KGV4dGVudCwgLXJlc29sdXRpb24sIGV4dGVudCk7XG4gICAgICBzb3VyY2VUaWxlR3JpZC5mb3JFYWNoVGlsZUNvb3JkKGV4dGVudCwgc291cmNlWiwgZnVuY3Rpb24gKHNvdXJjZVRpbGVDb29yZCkge1xuICAgICAgICBlbXB0eSA9IGVtcHR5ICYmICF0aGlzLnRpbGVVcmxGdW5jdGlvbihzb3VyY2VUaWxlQ29vcmQsIHBpeGVsUmF0aW8sIHByb2plY3Rpb24pO1xuICAgICAgfS5iaW5kKHRoaXMpKTtcbiAgICB9XG5cbiAgICB2YXIgbmV3VGlsZSA9IG5ldyBWZWN0b3JSZW5kZXJUaWxlKHRpbGVDb29yZCwgZW1wdHkgPyBUaWxlU3RhdGUuRU1QVFkgOiBUaWxlU3RhdGUuSURMRSwgdXJsVGlsZUNvb3JkLCB0aGlzLmdldFNvdXJjZVRpbGVzLmJpbmQodGhpcywgcGl4ZWxSYXRpbywgcHJvamVjdGlvbikpO1xuICAgIG5ld1RpbGUua2V5ID0ga2V5O1xuXG4gICAgaWYgKHRpbGUpIHtcbiAgICAgIG5ld1RpbGUuaW50ZXJpbVRpbGUgPSB0aWxlO1xuICAgICAgbmV3VGlsZS5yZWZyZXNoSW50ZXJpbUNoYWluKCk7XG4gICAgICB0aGlzLnRpbGVDYWNoZS5yZXBsYWNlKGNvb3JkS2V5LCBuZXdUaWxlKTtcbiAgICB9IGVsc2Uge1xuICAgICAgdGhpcy50aWxlQ2FjaGUuc2V0KGNvb3JkS2V5LCBuZXdUaWxlKTtcbiAgICB9XG5cbiAgICByZXR1cm4gbmV3VGlsZTtcbiAgfTtcbiAgLyoqXG4gICAqIEBwYXJhbSB7aW1wb3J0KFwiLi4vcHJvai9Qcm9qZWN0aW9uLmpzXCIpLmRlZmF1bHR9IHByb2plY3Rpb24gUHJvamVjdGlvbi5cbiAgICogQHJldHVybiB7IWltcG9ydChcIi4uL3RpbGVncmlkL1RpbGVHcmlkLmpzXCIpLmRlZmF1bHR9IFRpbGUgZ3JpZC5cbiAgICovXG5cblxuICBWZWN0b3JUaWxlLnByb3RvdHlwZS5nZXRUaWxlR3JpZEZvclByb2plY3Rpb24gPSBmdW5jdGlvbiAocHJvamVjdGlvbikge1xuICAgIHZhciBjb2RlID0gcHJvamVjdGlvbi5nZXRDb2RlKCk7XG4gICAgdmFyIHRpbGVHcmlkID0gdGhpcy50aWxlR3JpZHNfW2NvZGVdO1xuXG4gICAgaWYgKCF0aWxlR3JpZCkge1xuICAgICAgLy8gQSB0aWxlIGdyaWQgdGhhdCBtYXRjaGVzIHRoZSB0aWxlIHNpemUgb2YgdGhlIHNvdXJjZSB0aWxlIGdyaWQgaXMgbW9yZVxuICAgICAgLy8gbGlrZWx5IHRvIGhhdmUgMToxIHJlbGF0aW9uc2hpcHMgYmV0d2VlbiBzb3VyY2UgdGlsZXMgYW5kIHJlbmRlcmVkIHRpbGVzLlxuICAgICAgdmFyIHNvdXJjZVRpbGVHcmlkID0gdGhpcy50aWxlR3JpZDtcbiAgICAgIHRpbGVHcmlkID0gY3JlYXRlRm9yUHJvamVjdGlvbihwcm9qZWN0aW9uLCB1bmRlZmluZWQsIHNvdXJjZVRpbGVHcmlkID8gc291cmNlVGlsZUdyaWQuZ2V0VGlsZVNpemUoc291cmNlVGlsZUdyaWQuZ2V0TWluWm9vbSgpKSA6IHVuZGVmaW5lZCk7XG4gICAgICB0aGlzLnRpbGVHcmlkc19bY29kZV0gPSB0aWxlR3JpZDtcbiAgICB9XG5cbiAgICByZXR1cm4gdGlsZUdyaWQ7XG4gIH07XG4gIC8qKlxuICAgKiBHZXQgdGhlIHRpbGUgcGl4ZWwgcmF0aW8gZm9yIHRoaXMgc291cmNlLlxuICAgKiBAcGFyYW0ge251bWJlcn0gcGl4ZWxSYXRpbyBQaXhlbCByYXRpby5cbiAgICogQHJldHVybiB7bnVtYmVyfSBUaWxlIHBpeGVsIHJhdGlvLlxuICAgKi9cblxuXG4gIFZlY3RvclRpbGUucHJvdG90eXBlLmdldFRpbGVQaXhlbFJhdGlvID0gZnVuY3Rpb24gKHBpeGVsUmF0aW8pIHtcbiAgICByZXR1cm4gcGl4ZWxSYXRpbztcbiAgfTtcbiAgLyoqXG4gICAqIEBwYXJhbSB7bnVtYmVyfSB6IFouXG4gICAqIEBwYXJhbSB7bnVtYmVyfSBwaXhlbFJhdGlvIFBpeGVsIHJhdGlvLlxuICAgKiBAcGFyYW0ge2ltcG9ydChcIi4uL3Byb2ovUHJvamVjdGlvbi5qc1wiKS5kZWZhdWx0fSBwcm9qZWN0aW9uIFByb2plY3Rpb24uXG4gICAqIEByZXR1cm4ge2ltcG9ydChcIi4uL3NpemUuanNcIikuU2l6ZX0gVGlsZSBzaXplLlxuICAgKi9cblxuXG4gIFZlY3RvclRpbGUucHJvdG90eXBlLmdldFRpbGVQaXhlbFNpemUgPSBmdW5jdGlvbiAoeiwgcGl4ZWxSYXRpbywgcHJvamVjdGlvbikge1xuICAgIHZhciB0aWxlR3JpZCA9IHRoaXMuZ2V0VGlsZUdyaWRGb3JQcm9qZWN0aW9uKHByb2plY3Rpb24pO1xuICAgIHZhciB0aWxlU2l6ZSA9IHRvU2l6ZSh0aWxlR3JpZC5nZXRUaWxlU2l6ZSh6KSwgdGhpcy50bXBTaXplKTtcbiAgICByZXR1cm4gW01hdGgucm91bmQodGlsZVNpemVbMF0gKiBwaXhlbFJhdGlvKSwgTWF0aC5yb3VuZCh0aWxlU2l6ZVsxXSAqIHBpeGVsUmF0aW8pXTtcbiAgfTtcbiAgLyoqXG4gICAqIEluY3JlYXNlcyB0aGUgY2FjaGUgc2l6ZSBpZiBuZWVkZWRcbiAgICogQHBhcmFtIHtudW1iZXJ9IHRpbGVDb3VudCBNaW5pbXVtIG51bWJlciBvZiB0aWxlcyBuZWVkZWQuXG4gICAqIEBwYXJhbSB7aW1wb3J0KFwiLi4vcHJvai9Qcm9qZWN0aW9uLmpzXCIpLmRlZmF1bHR9IHByb2plY3Rpb24gUHJvamVjdGlvbi5cbiAgICovXG5cblxuICBWZWN0b3JUaWxlLnByb3RvdHlwZS51cGRhdGVDYWNoZVNpemUgPSBmdW5jdGlvbiAodGlsZUNvdW50LCBwcm9qZWN0aW9uKSB7XG4gICAgX3N1cGVyLnByb3RvdHlwZS51cGRhdGVDYWNoZVNpemUuY2FsbCh0aGlzLCB0aWxlQ291bnQgKiAyLCBwcm9qZWN0aW9uKTtcbiAgfTtcblxuICByZXR1cm4gVmVjdG9yVGlsZTtcbn0oVXJsVGlsZSk7XG5cbmV4cG9ydCBkZWZhdWx0IFZlY3RvclRpbGU7XG4vKipcbiAqIFNldHMgdGhlIGxvYWRlciBmb3IgYSB0aWxlLlxuICogQHBhcmFtIHtpbXBvcnQoXCIuLi9WZWN0b3JUaWxlLmpzXCIpLmRlZmF1bHR9IHRpbGUgVmVjdG9yIHRpbGUuXG4gKiBAcGFyYW0ge3N0cmluZ30gdXJsIFVSTC5cbiAqL1xuXG5leHBvcnQgZnVuY3Rpb24gZGVmYXVsdExvYWRGdW5jdGlvbih0aWxlLCB1cmwpIHtcbiAgdGlsZS5zZXRMb2FkZXIoXG4gIC8qKlxuICAgKiBAcGFyYW0ge2ltcG9ydChcIi4uL2V4dGVudC5qc1wiKS5FeHRlbnR9IGV4dGVudCBFeHRlbnQuXG4gICAqIEBwYXJhbSB7bnVtYmVyfSByZXNvbHV0aW9uIFJlc29sdXRpb24uXG4gICAqIEBwYXJhbSB7aW1wb3J0KFwiLi4vcHJvai9Qcm9qZWN0aW9uLmpzXCIpLmRlZmF1bHR9IHByb2plY3Rpb24gUHJvamVjdGlvbi5cbiAgICovXG4gIGZ1bmN0aW9uIChleHRlbnQsIHJlc29sdXRpb24sIHByb2plY3Rpb24pIHtcbiAgICBsb2FkRmVhdHVyZXNYaHIodXJsLCB0aWxlLmdldEZvcm1hdCgpLCBleHRlbnQsIHJlc29sdXRpb24sIHByb2plY3Rpb24sIHRpbGUub25Mb2FkLmJpbmQodGlsZSksIHRpbGUub25FcnJvci5iaW5kKHRpbGUpKTtcbiAgfSk7XG59IiwiLyoqXG4gKiBAbW9kdWxlIG9sL3N0eWxlL0ltYWdlXG4gKi9cbmltcG9ydCB7IGFic3RyYWN0IH0gZnJvbSAnLi4vdXRpbC5qcyc7XG5pbXBvcnQgeyB0b1NpemUgfSBmcm9tICcuLi9zaXplLmpzJztcbi8qKlxuICogQHR5cGVkZWYge09iamVjdH0gT3B0aW9uc1xuICogQHByb3BlcnR5IHtudW1iZXJ9IG9wYWNpdHlcbiAqIEBwcm9wZXJ0eSB7Ym9vbGVhbn0gcm90YXRlV2l0aFZpZXdcbiAqIEBwcm9wZXJ0eSB7bnVtYmVyfSByb3RhdGlvblxuICogQHByb3BlcnR5IHtudW1iZXJ8aW1wb3J0KFwiLi4vc2l6ZS5qc1wiKS5TaXplfSBzY2FsZVxuICogQHByb3BlcnR5IHtBcnJheTxudW1iZXI+fSBkaXNwbGFjZW1lbnRcbiAqL1xuXG4vKipcbiAqIEBjbGFzc2Rlc2NcbiAqIEEgYmFzZSBjbGFzcyB1c2VkIGZvciBjcmVhdGluZyBzdWJjbGFzc2VzIGFuZCBub3QgaW5zdGFudGlhdGVkIGluXG4gKiBhcHBzLiBCYXNlIGNsYXNzIGZvciB7QGxpbmsgbW9kdWxlOm9sL3N0eWxlL0ljb25+SWNvbn0sIHtAbGluayBtb2R1bGU6b2wvc3R5bGUvQ2lyY2xlfkNpcmNsZVN0eWxlfSBhbmRcbiAqIHtAbGluayBtb2R1bGU6b2wvc3R5bGUvUmVndWxhclNoYXBlflJlZ3VsYXJTaGFwZX0uXG4gKiBAYWJzdHJhY3RcbiAqIEBhcGlcbiAqL1xuXG52YXIgSW1hZ2VTdHlsZSA9XG4vKiogQGNsYXNzICovXG5mdW5jdGlvbiAoKSB7XG4gIC8qKlxuICAgKiBAcGFyYW0ge09wdGlvbnN9IG9wdGlvbnMgT3B0aW9ucy5cbiAgICovXG4gIGZ1bmN0aW9uIEltYWdlU3R5bGUob3B0aW9ucykge1xuICAgIC8qKlxuICAgICAqIEBwcml2YXRlXG4gICAgICogQHR5cGUge251bWJlcn1cbiAgICAgKi9cbiAgICB0aGlzLm9wYWNpdHlfID0gb3B0aW9ucy5vcGFjaXR5O1xuICAgIC8qKlxuICAgICAqIEBwcml2YXRlXG4gICAgICogQHR5cGUge2Jvb2xlYW59XG4gICAgICovXG5cbiAgICB0aGlzLnJvdGF0ZVdpdGhWaWV3XyA9IG9wdGlvbnMucm90YXRlV2l0aFZpZXc7XG4gICAgLyoqXG4gICAgICogQHByaXZhdGVcbiAgICAgKiBAdHlwZSB7bnVtYmVyfVxuICAgICAqL1xuXG4gICAgdGhpcy5yb3RhdGlvbl8gPSBvcHRpb25zLnJvdGF0aW9uO1xuICAgIC8qKlxuICAgICAqIEBwcml2YXRlXG4gICAgICogQHR5cGUge251bWJlcnxpbXBvcnQoXCIuLi9zaXplLmpzXCIpLlNpemV9XG4gICAgICovXG5cbiAgICB0aGlzLnNjYWxlXyA9IG9wdGlvbnMuc2NhbGU7XG4gICAgLyoqXG4gICAgICogQHByaXZhdGVcbiAgICAgKiBAdHlwZSB7aW1wb3J0KFwiLi4vc2l6ZS5qc1wiKS5TaXplfVxuICAgICAqL1xuXG4gICAgdGhpcy5zY2FsZUFycmF5XyA9IHRvU2l6ZShvcHRpb25zLnNjYWxlKTtcbiAgICAvKipcbiAgICAgKiBAcHJpdmF0ZVxuICAgICAqIEB0eXBlIHtBcnJheTxudW1iZXI+fVxuICAgICAqL1xuXG4gICAgdGhpcy5kaXNwbGFjZW1lbnRfID0gb3B0aW9ucy5kaXNwbGFjZW1lbnQ7XG4gIH1cbiAgLyoqXG4gICAqIENsb25lcyB0aGUgc3R5bGUuXG4gICAqIEByZXR1cm4ge0ltYWdlU3R5bGV9IFRoZSBjbG9uZWQgc3R5bGUuXG4gICAqIEBhcGlcbiAgICovXG5cblxuICBJbWFnZVN0eWxlLnByb3RvdHlwZS5jbG9uZSA9IGZ1bmN0aW9uICgpIHtcbiAgICB2YXIgc2NhbGUgPSB0aGlzLmdldFNjYWxlKCk7XG4gICAgcmV0dXJuIG5ldyBJbWFnZVN0eWxlKHtcbiAgICAgIG9wYWNpdHk6IHRoaXMuZ2V0T3BhY2l0eSgpLFxuICAgICAgc2NhbGU6IEFycmF5LmlzQXJyYXkoc2NhbGUpID8gc2NhbGUuc2xpY2UoKSA6IHNjYWxlLFxuICAgICAgcm90YXRpb246IHRoaXMuZ2V0Um90YXRpb24oKSxcbiAgICAgIHJvdGF0ZVdpdGhWaWV3OiB0aGlzLmdldFJvdGF0ZVdpdGhWaWV3KCksXG4gICAgICBkaXNwbGFjZW1lbnQ6IHRoaXMuZ2V0RGlzcGxhY2VtZW50KCkuc2xpY2UoKVxuICAgIH0pO1xuICB9O1xuICAvKipcbiAgICogR2V0IHRoZSBzeW1ib2xpemVyIG9wYWNpdHkuXG4gICAqIEByZXR1cm4ge251bWJlcn0gT3BhY2l0eS5cbiAgICogQGFwaVxuICAgKi9cblxuXG4gIEltYWdlU3R5bGUucHJvdG90eXBlLmdldE9wYWNpdHkgPSBmdW5jdGlvbiAoKSB7XG4gICAgcmV0dXJuIHRoaXMub3BhY2l0eV87XG4gIH07XG4gIC8qKlxuICAgKiBEZXRlcm1pbmUgd2hldGhlciB0aGUgc3ltYm9saXplciByb3RhdGVzIHdpdGggdGhlIG1hcC5cbiAgICogQHJldHVybiB7Ym9vbGVhbn0gUm90YXRlIHdpdGggbWFwLlxuICAgKiBAYXBpXG4gICAqL1xuXG5cbiAgSW1hZ2VTdHlsZS5wcm90b3R5cGUuZ2V0Um90YXRlV2l0aFZpZXcgPSBmdW5jdGlvbiAoKSB7XG4gICAgcmV0dXJuIHRoaXMucm90YXRlV2l0aFZpZXdfO1xuICB9O1xuICAvKipcbiAgICogR2V0IHRoZSBzeW1vYmxpemVyIHJvdGF0aW9uLlxuICAgKiBAcmV0dXJuIHtudW1iZXJ9IFJvdGF0aW9uLlxuICAgKiBAYXBpXG4gICAqL1xuXG5cbiAgSW1hZ2VTdHlsZS5wcm90b3R5cGUuZ2V0Um90YXRpb24gPSBmdW5jdGlvbiAoKSB7XG4gICAgcmV0dXJuIHRoaXMucm90YXRpb25fO1xuICB9O1xuICAvKipcbiAgICogR2V0IHRoZSBzeW1ib2xpemVyIHNjYWxlLlxuICAgKiBAcmV0dXJuIHtudW1iZXJ8aW1wb3J0KFwiLi4vc2l6ZS5qc1wiKS5TaXplfSBTY2FsZS5cbiAgICogQGFwaVxuICAgKi9cblxuXG4gIEltYWdlU3R5bGUucHJvdG90eXBlLmdldFNjYWxlID0gZnVuY3Rpb24gKCkge1xuICAgIHJldHVybiB0aGlzLnNjYWxlXztcbiAgfTtcbiAgLyoqXG4gICAqIEdldCB0aGUgc3ltYm9saXplciBzY2FsZSBhcnJheS5cbiAgICogQHJldHVybiB7aW1wb3J0KFwiLi4vc2l6ZS5qc1wiKS5TaXplfSBTY2FsZSBhcnJheS5cbiAgICovXG5cblxuICBJbWFnZVN0eWxlLnByb3RvdHlwZS5nZXRTY2FsZUFycmF5ID0gZnVuY3Rpb24gKCkge1xuICAgIHJldHVybiB0aGlzLnNjYWxlQXJyYXlfO1xuICB9O1xuICAvKipcbiAgICogR2V0IHRoZSBkaXNwbGFjZW1lbnQgb2YgdGhlIHNoYXBlXG4gICAqIEByZXR1cm4ge0FycmF5PG51bWJlcj59IFNoYXBlJ3MgY2VudGVyIGRpc3BsYWNlbWVudFxuICAgKiBAYXBpXG4gICAqL1xuXG5cbiAgSW1hZ2VTdHlsZS5wcm90b3R5cGUuZ2V0RGlzcGxhY2VtZW50ID0gZnVuY3Rpb24gKCkge1xuICAgIHJldHVybiB0aGlzLmRpc3BsYWNlbWVudF87XG4gIH07XG4gIC8qKlxuICAgKiBHZXQgdGhlIGFuY2hvciBwb2ludCBpbiBwaXhlbHMuIFRoZSBhbmNob3IgZGV0ZXJtaW5lcyB0aGUgY2VudGVyIHBvaW50IGZvciB0aGVcbiAgICogc3ltYm9saXplci5cbiAgICogQGFic3RyYWN0XG4gICAqIEByZXR1cm4ge0FycmF5PG51bWJlcj59IEFuY2hvci5cbiAgICovXG5cblxuICBJbWFnZVN0eWxlLnByb3RvdHlwZS5nZXRBbmNob3IgPSBmdW5jdGlvbiAoKSB7XG4gICAgcmV0dXJuIGFic3RyYWN0KCk7XG4gIH07XG4gIC8qKlxuICAgKiBHZXQgdGhlIGltYWdlIGVsZW1lbnQgZm9yIHRoZSBzeW1ib2xpemVyLlxuICAgKiBAYWJzdHJhY3RcbiAgICogQHBhcmFtIHtudW1iZXJ9IHBpeGVsUmF0aW8gUGl4ZWwgcmF0aW8uXG4gICAqIEByZXR1cm4ge0hUTUxDYW52YXNFbGVtZW50fEhUTUxWaWRlb0VsZW1lbnR8SFRNTEltYWdlRWxlbWVudH0gSW1hZ2UgZWxlbWVudC5cbiAgICovXG5cblxuICBJbWFnZVN0eWxlLnByb3RvdHlwZS5nZXRJbWFnZSA9IGZ1bmN0aW9uIChwaXhlbFJhdGlvKSB7XG4gICAgcmV0dXJuIGFic3RyYWN0KCk7XG4gIH07XG4gIC8qKlxuICAgKiBAYWJzdHJhY3RcbiAgICogQHJldHVybiB7SFRNTENhbnZhc0VsZW1lbnR8SFRNTFZpZGVvRWxlbWVudHxIVE1MSW1hZ2VFbGVtZW50fSBJbWFnZSBlbGVtZW50LlxuICAgKi9cblxuXG4gIEltYWdlU3R5bGUucHJvdG90eXBlLmdldEhpdERldGVjdGlvbkltYWdlID0gZnVuY3Rpb24gKCkge1xuICAgIHJldHVybiBhYnN0cmFjdCgpO1xuICB9O1xuICAvKlxuICAgKiBHZXQgdGhlIGltYWdlIHBpeGVsIHJhdGlvLlxuICAgKiBAcGFyYW0ge251bWJlcn0gcGl4ZWxSYXRpbyBQaXhlbCByYXRpby5cbiAgICogKi9cblxuXG4gIEltYWdlU3R5bGUucHJvdG90eXBlLmdldFBpeGVsUmF0aW8gPSBmdW5jdGlvbiAocGl4ZWxSYXRpbykge1xuICAgIHJldHVybiAxO1xuICB9O1xuICAvKipcbiAgICogQGFic3RyYWN0XG4gICAqIEByZXR1cm4ge2ltcG9ydChcIi4uL0ltYWdlU3RhdGUuanNcIikuZGVmYXVsdH0gSW1hZ2Ugc3RhdGUuXG4gICAqL1xuXG5cbiAgSW1hZ2VTdHlsZS5wcm90b3R5cGUuZ2V0SW1hZ2VTdGF0ZSA9IGZ1bmN0aW9uICgpIHtcbiAgICByZXR1cm4gYWJzdHJhY3QoKTtcbiAgfTtcbiAgLyoqXG4gICAqIEBhYnN0cmFjdFxuICAgKiBAcmV0dXJuIHtpbXBvcnQoXCIuLi9zaXplLmpzXCIpLlNpemV9IEltYWdlIHNpemUuXG4gICAqL1xuXG5cbiAgSW1hZ2VTdHlsZS5wcm90b3R5cGUuZ2V0SW1hZ2VTaXplID0gZnVuY3Rpb24gKCkge1xuICAgIHJldHVybiBhYnN0cmFjdCgpO1xuICB9O1xuICAvKipcbiAgICogQGFic3RyYWN0XG4gICAqIEByZXR1cm4ge2ltcG9ydChcIi4uL3NpemUuanNcIikuU2l6ZX0gU2l6ZSBvZiB0aGUgaGl0LWRldGVjdGlvbiBpbWFnZS5cbiAgICovXG5cblxuICBJbWFnZVN0eWxlLnByb3RvdHlwZS5nZXRIaXREZXRlY3Rpb25JbWFnZVNpemUgPSBmdW5jdGlvbiAoKSB7XG4gICAgcmV0dXJuIGFic3RyYWN0KCk7XG4gIH07XG4gIC8qKlxuICAgKiBHZXQgdGhlIG9yaWdpbiBvZiB0aGUgc3ltYm9saXplci5cbiAgICogQGFic3RyYWN0XG4gICAqIEByZXR1cm4ge0FycmF5PG51bWJlcj59IE9yaWdpbi5cbiAgICovXG5cblxuICBJbWFnZVN0eWxlLnByb3RvdHlwZS5nZXRPcmlnaW4gPSBmdW5jdGlvbiAoKSB7XG4gICAgcmV0dXJuIGFic3RyYWN0KCk7XG4gIH07XG4gIC8qKlxuICAgKiBHZXQgdGhlIHNpemUgb2YgdGhlIHN5bWJvbGl6ZXIgKGluIHBpeGVscykuXG4gICAqIEBhYnN0cmFjdFxuICAgKiBAcmV0dXJuIHtpbXBvcnQoXCIuLi9zaXplLmpzXCIpLlNpemV9IFNpemUuXG4gICAqL1xuXG5cbiAgSW1hZ2VTdHlsZS5wcm90b3R5cGUuZ2V0U2l6ZSA9IGZ1bmN0aW9uICgpIHtcbiAgICByZXR1cm4gYWJzdHJhY3QoKTtcbiAgfTtcbiAgLyoqXG4gICAqIFNldCB0aGUgb3BhY2l0eS5cbiAgICpcbiAgICogQHBhcmFtIHtudW1iZXJ9IG9wYWNpdHkgT3BhY2l0eS5cbiAgICogQGFwaVxuICAgKi9cblxuXG4gIEltYWdlU3R5bGUucHJvdG90eXBlLnNldE9wYWNpdHkgPSBmdW5jdGlvbiAob3BhY2l0eSkge1xuICAgIHRoaXMub3BhY2l0eV8gPSBvcGFjaXR5O1xuICB9O1xuICAvKipcbiAgICogU2V0IHdoZXRoZXIgdG8gcm90YXRlIHRoZSBzdHlsZSB3aXRoIHRoZSB2aWV3LlxuICAgKlxuICAgKiBAcGFyYW0ge2Jvb2xlYW59IHJvdGF0ZVdpdGhWaWV3IFJvdGF0ZSB3aXRoIG1hcC5cbiAgICogQGFwaVxuICAgKi9cblxuXG4gIEltYWdlU3R5bGUucHJvdG90eXBlLnNldFJvdGF0ZVdpdGhWaWV3ID0gZnVuY3Rpb24gKHJvdGF0ZVdpdGhWaWV3KSB7XG4gICAgdGhpcy5yb3RhdGVXaXRoVmlld18gPSByb3RhdGVXaXRoVmlldztcbiAgfTtcbiAgLyoqXG4gICAqIFNldCB0aGUgcm90YXRpb24uXG4gICAqXG4gICAqIEBwYXJhbSB7bnVtYmVyfSByb3RhdGlvbiBSb3RhdGlvbi5cbiAgICogQGFwaVxuICAgKi9cblxuXG4gIEltYWdlU3R5bGUucHJvdG90eXBlLnNldFJvdGF0aW9uID0gZnVuY3Rpb24gKHJvdGF0aW9uKSB7XG4gICAgdGhpcy5yb3RhdGlvbl8gPSByb3RhdGlvbjtcbiAgfTtcbiAgLyoqXG4gICAqIFNldCB0aGUgc2NhbGUuXG4gICAqXG4gICAqIEBwYXJhbSB7bnVtYmVyfGltcG9ydChcIi4uL3NpemUuanNcIikuU2l6ZX0gc2NhbGUgU2NhbGUuXG4gICAqIEBhcGlcbiAgICovXG5cblxuICBJbWFnZVN0eWxlLnByb3RvdHlwZS5zZXRTY2FsZSA9IGZ1bmN0aW9uIChzY2FsZSkge1xuICAgIHRoaXMuc2NhbGVfID0gc2NhbGU7XG4gICAgdGhpcy5zY2FsZUFycmF5XyA9IHRvU2l6ZShzY2FsZSk7XG4gIH07XG4gIC8qKlxuICAgKiBAYWJzdHJhY3RcbiAgICogQHBhcmFtIHtmdW5jdGlvbihpbXBvcnQoXCIuLi9ldmVudHMvRXZlbnQuanNcIikuZGVmYXVsdCk6IHZvaWR9IGxpc3RlbmVyIExpc3RlbmVyIGZ1bmN0aW9uLlxuICAgKi9cblxuXG4gIEltYWdlU3R5bGUucHJvdG90eXBlLmxpc3RlbkltYWdlQ2hhbmdlID0gZnVuY3Rpb24gKGxpc3RlbmVyKSB7XG4gICAgYWJzdHJhY3QoKTtcbiAgfTtcbiAgLyoqXG4gICAqIExvYWQgbm90IHlldCBsb2FkZWQgVVJJLlxuICAgKiBAYWJzdHJhY3RcbiAgICovXG5cblxuICBJbWFnZVN0eWxlLnByb3RvdHlwZS5sb2FkID0gZnVuY3Rpb24gKCkge1xuICAgIGFic3RyYWN0KCk7XG4gIH07XG4gIC8qKlxuICAgKiBAYWJzdHJhY3RcbiAgICogQHBhcmFtIHtmdW5jdGlvbihpbXBvcnQoXCIuLi9ldmVudHMvRXZlbnQuanNcIikuZGVmYXVsdCk6IHZvaWR9IGxpc3RlbmVyIExpc3RlbmVyIGZ1bmN0aW9uLlxuICAgKi9cblxuXG4gIEltYWdlU3R5bGUucHJvdG90eXBlLnVubGlzdGVuSW1hZ2VDaGFuZ2UgPSBmdW5jdGlvbiAobGlzdGVuZXIpIHtcbiAgICBhYnN0cmFjdCgpO1xuICB9O1xuXG4gIHJldHVybiBJbWFnZVN0eWxlO1xufSgpO1xuXG5leHBvcnQgZGVmYXVsdCBJbWFnZVN0eWxlOyIsIi8qKlxuICogQG1vZHVsZSBvbC9jb2xvcmxpa2VcbiAqL1xuaW1wb3J0IHsgdG9TdHJpbmcgfSBmcm9tICcuL2NvbG9yLmpzJztcbi8qKlxuICogQSB0eXBlIGFjY2VwdGVkIGJ5IENhbnZhc1JlbmRlcmluZ0NvbnRleHQyRC5maWxsU3R5bGVcbiAqIG9yIENhbnZhc1JlbmRlcmluZ0NvbnRleHQyRC5zdHJva2VTdHlsZS5cbiAqIFJlcHJlc2VudHMgYSBjb2xvciwgcGF0dGVybiwgb3IgZ3JhZGllbnQuIFRoZSBvcmlnaW4gZm9yIHBhdHRlcm5zIGFuZFxuICogZ3JhZGllbnRzIGFzIGZpbGwgc3R5bGUgaXMgYW4gaW5jcmVtZW50IG9mIDUxMiBjc3MgcGl4ZWxzIGZyb20gbWFwIGNvb3JkaW5hdGVcbiAqIGBbMCwgMF1gLiBGb3Igc2VhbWxlc3MgcmVwZWF0IHBhdHRlcm5zLCB3aWR0aCBhbmQgaGVpZ2h0IG9mIHRoZSBwYXR0ZXJuIGltYWdlXG4gKiBtdXN0IGJlIGEgZmFjdG9yIG9mIHR3byAoMiwgNCwgOCwgLi4uLCA1MTIpLlxuICpcbiAqIEB0eXBlZGVmIHtzdHJpbmd8Q2FudmFzUGF0dGVybnxDYW52YXNHcmFkaWVudH0gQ29sb3JMaWtlXG4gKiBAYXBpXG4gKi9cblxuLyoqXG4gKiBAcGFyYW0ge2ltcG9ydChcIi4vY29sb3IuanNcIikuQ29sb3J8Q29sb3JMaWtlfSBjb2xvciBDb2xvci5cbiAqIEByZXR1cm4ge0NvbG9yTGlrZX0gVGhlIGNvbG9yIGFzIGFuIHtAbGluayBvbC9jb2xvcmxpa2V+Q29sb3JMaWtlfS5cbiAqIEBhcGlcbiAqL1xuXG5leHBvcnQgZnVuY3Rpb24gYXNDb2xvckxpa2UoY29sb3IpIHtcbiAgaWYgKEFycmF5LmlzQXJyYXkoY29sb3IpKSB7XG4gICAgcmV0dXJuIHRvU3RyaW5nKGNvbG9yKTtcbiAgfSBlbHNlIHtcbiAgICByZXR1cm4gY29sb3I7XG4gIH1cbn0iLCIvKipcbiAqIEBtb2R1bGUgb2wvc3R5bGUvUmVndWxhclNoYXBlXG4gKi9cbnZhciBfX2V4dGVuZHMgPSB0aGlzICYmIHRoaXMuX19leHRlbmRzIHx8IGZ1bmN0aW9uICgpIHtcbiAgdmFyIF9leHRlbmRTdGF0aWNzID0gZnVuY3Rpb24gZXh0ZW5kU3RhdGljcyhkLCBiKSB7XG4gICAgX2V4dGVuZFN0YXRpY3MgPSBPYmplY3Quc2V0UHJvdG90eXBlT2YgfHwge1xuICAgICAgX19wcm90b19fOiBbXVxuICAgIH0gaW5zdGFuY2VvZiBBcnJheSAmJiBmdW5jdGlvbiAoZCwgYikge1xuICAgICAgZC5fX3Byb3RvX18gPSBiO1xuICAgIH0gfHwgZnVuY3Rpb24gKGQsIGIpIHtcbiAgICAgIGZvciAodmFyIHAgaW4gYikge1xuICAgICAgICBpZiAoT2JqZWN0LnByb3RvdHlwZS5oYXNPd25Qcm9wZXJ0eS5jYWxsKGIsIHApKSBkW3BdID0gYltwXTtcbiAgICAgIH1cbiAgICB9O1xuXG4gICAgcmV0dXJuIF9leHRlbmRTdGF0aWNzKGQsIGIpO1xuICB9O1xuXG4gIHJldHVybiBmdW5jdGlvbiAoZCwgYikge1xuICAgIF9leHRlbmRTdGF0aWNzKGQsIGIpO1xuXG4gICAgZnVuY3Rpb24gX18oKSB7XG4gICAgICB0aGlzLmNvbnN0cnVjdG9yID0gZDtcbiAgICB9XG5cbiAgICBkLnByb3RvdHlwZSA9IGIgPT09IG51bGwgPyBPYmplY3QuY3JlYXRlKGIpIDogKF9fLnByb3RvdHlwZSA9IGIucHJvdG90eXBlLCBuZXcgX18oKSk7XG4gIH07XG59KCk7XG5cbmltcG9ydCBJbWFnZVN0YXRlIGZyb20gJy4uL0ltYWdlU3RhdGUuanMnO1xuaW1wb3J0IEltYWdlU3R5bGUgZnJvbSAnLi9JbWFnZS5qcyc7XG5pbXBvcnQgeyBhc0FycmF5IH0gZnJvbSAnLi4vY29sb3IuanMnO1xuaW1wb3J0IHsgYXNDb2xvckxpa2UgfSBmcm9tICcuLi9jb2xvcmxpa2UuanMnO1xuaW1wb3J0IHsgY3JlYXRlQ2FudmFzQ29udGV4dDJEIH0gZnJvbSAnLi4vZG9tLmpzJztcbmltcG9ydCB7IGRlZmF1bHRGaWxsU3R5bGUsIGRlZmF1bHRMaW5lQ2FwLCBkZWZhdWx0TGluZUpvaW4sIGRlZmF1bHRMaW5lV2lkdGgsIGRlZmF1bHRNaXRlckxpbWl0LCBkZWZhdWx0U3Ryb2tlU3R5bGUgfSBmcm9tICcuLi9yZW5kZXIvY2FudmFzLmpzJztcbi8qKlxuICogU3BlY2lmeSByYWRpdXMgZm9yIHJlZ3VsYXIgcG9seWdvbnMsIG9yIHJhZGl1czEgYW5kIHJhZGl1czIgZm9yIHN0YXJzLlxuICogQHR5cGVkZWYge09iamVjdH0gT3B0aW9uc1xuICogQHByb3BlcnR5IHtpbXBvcnQoXCIuL0ZpbGwuanNcIikuZGVmYXVsdH0gW2ZpbGxdIEZpbGwgc3R5bGUuXG4gKiBAcHJvcGVydHkge251bWJlcn0gcG9pbnRzIE51bWJlciBvZiBwb2ludHMgZm9yIHN0YXJzIGFuZCByZWd1bGFyIHBvbHlnb25zLiBJbiBjYXNlIG9mIGEgcG9seWdvbiwgdGhlIG51bWJlciBvZiBwb2ludHNcbiAqIGlzIHRoZSBudW1iZXIgb2Ygc2lkZXMuXG4gKiBAcHJvcGVydHkge251bWJlcn0gW3JhZGl1c10gUmFkaXVzIG9mIGEgcmVndWxhciBwb2x5Z29uLlxuICogQHByb3BlcnR5IHtudW1iZXJ9IFtyYWRpdXMxXSBPdXRlciByYWRpdXMgb2YgYSBzdGFyLlxuICogQHByb3BlcnR5IHtudW1iZXJ9IFtyYWRpdXMyXSBJbm5lciByYWRpdXMgb2YgYSBzdGFyLlxuICogQHByb3BlcnR5IHtudW1iZXJ9IFthbmdsZT0wXSBTaGFwZSdzIGFuZ2xlIGluIHJhZGlhbnMuIEEgdmFsdWUgb2YgMCB3aWxsIGhhdmUgb25lIG9mIHRoZSBzaGFwZSdzIHBvaW50IGZhY2luZyB1cC5cbiAqIEBwcm9wZXJ0eSB7QXJyYXk8bnVtYmVyPn0gW2Rpc3BsYWNlbWVudD1bMCwwXV0gRGlzcGxhY2VtZW50IG9mIHRoZSBzaGFwZVxuICogQHByb3BlcnR5IHtpbXBvcnQoXCIuL1N0cm9rZS5qc1wiKS5kZWZhdWx0fSBbc3Ryb2tlXSBTdHJva2Ugc3R5bGUuXG4gKiBAcHJvcGVydHkge251bWJlcn0gW3JvdGF0aW9uPTBdIFJvdGF0aW9uIGluIHJhZGlhbnMgKHBvc2l0aXZlIHJvdGF0aW9uIGNsb2Nrd2lzZSkuXG4gKiBAcHJvcGVydHkge2Jvb2xlYW59IFtyb3RhdGVXaXRoVmlldz1mYWxzZV0gV2hldGhlciB0byByb3RhdGUgdGhlIHNoYXBlIHdpdGggdGhlIHZpZXcuXG4gKiBAcHJvcGVydHkge251bWJlcnxpbXBvcnQoXCIuLi9zaXplLmpzXCIpLlNpemV9IFtzY2FsZT0xXSBTY2FsZS4gVW5sZXNzIHR3byBkaW1lbnNpb25hbCBzY2FsaW5nIGlzIHJlcXVpcmVkIGEgYmV0dGVyXG4gKiByZXN1bHQgbWF5IGJlIG9idGFpbmVkIHdpdGggYXBwcm9wcmlhdGUgc2V0dGluZ3MgZm9yIGByYWRpdXNgLCBgcmFkaXVzMWAgYW5kIGByYWRpdXMyYC5cbiAqL1xuXG4vKipcbiAqIEB0eXBlZGVmIHtPYmplY3R9IFJlbmRlck9wdGlvbnNcbiAqIEBwcm9wZXJ0eSB7aW1wb3J0KFwiLi4vY29sb3JsaWtlLmpzXCIpLkNvbG9yTGlrZX0gW3N0cm9rZVN0eWxlXVxuICogQHByb3BlcnR5IHtudW1iZXJ9IHN0cm9rZVdpZHRoXG4gKiBAcHJvcGVydHkge251bWJlcn0gc2l6ZVxuICogQHByb3BlcnR5IHtDYW52YXNMaW5lQ2FwfSBsaW5lQ2FwXG4gKiBAcHJvcGVydHkge0FycmF5PG51bWJlcj59IGxpbmVEYXNoXG4gKiBAcHJvcGVydHkge251bWJlcn0gbGluZURhc2hPZmZzZXRcbiAqIEBwcm9wZXJ0eSB7Q2FudmFzTGluZUpvaW59IGxpbmVKb2luXG4gKiBAcHJvcGVydHkge251bWJlcn0gbWl0ZXJMaW1pdFxuICovXG5cbi8qKlxuICogQGNsYXNzZGVzY1xuICogU2V0IHJlZ3VsYXIgc2hhcGUgc3R5bGUgZm9yIHZlY3RvciBmZWF0dXJlcy4gVGhlIHJlc3VsdGluZyBzaGFwZSB3aWxsIGJlXG4gKiBhIHJlZ3VsYXIgcG9seWdvbiB3aGVuIGByYWRpdXNgIGlzIHByb3ZpZGVkLCBvciBhIHN0YXIgd2hlbiBgcmFkaXVzMWAgYW5kXG4gKiBgcmFkaXVzMmAgYXJlIHByb3ZpZGVkLlxuICogQGFwaVxuICovXG5cbnZhciBSZWd1bGFyU2hhcGUgPVxuLyoqIEBjbGFzcyAqL1xuZnVuY3Rpb24gKF9zdXBlcikge1xuICBfX2V4dGVuZHMoUmVndWxhclNoYXBlLCBfc3VwZXIpO1xuICAvKipcbiAgICogQHBhcmFtIHtPcHRpb25zfSBvcHRpb25zIE9wdGlvbnMuXG4gICAqL1xuXG5cbiAgZnVuY3Rpb24gUmVndWxhclNoYXBlKG9wdGlvbnMpIHtcbiAgICB2YXIgX3RoaXMgPSB0aGlzO1xuICAgIC8qKlxuICAgICAqIEB0eXBlIHtib29sZWFufVxuICAgICAqL1xuXG5cbiAgICB2YXIgcm90YXRlV2l0aFZpZXcgPSBvcHRpb25zLnJvdGF0ZVdpdGhWaWV3ICE9PSB1bmRlZmluZWQgPyBvcHRpb25zLnJvdGF0ZVdpdGhWaWV3IDogZmFsc2U7XG4gICAgX3RoaXMgPSBfc3VwZXIuY2FsbCh0aGlzLCB7XG4gICAgICBvcGFjaXR5OiAxLFxuICAgICAgcm90YXRlV2l0aFZpZXc6IHJvdGF0ZVdpdGhWaWV3LFxuICAgICAgcm90YXRpb246IG9wdGlvbnMucm90YXRpb24gIT09IHVuZGVmaW5lZCA/IG9wdGlvbnMucm90YXRpb24gOiAwLFxuICAgICAgc2NhbGU6IG9wdGlvbnMuc2NhbGUgIT09IHVuZGVmaW5lZCA/IG9wdGlvbnMuc2NhbGUgOiAxLFxuICAgICAgZGlzcGxhY2VtZW50OiBvcHRpb25zLmRpc3BsYWNlbWVudCAhPT0gdW5kZWZpbmVkID8gb3B0aW9ucy5kaXNwbGFjZW1lbnQgOiBbMCwgMF1cbiAgICB9KSB8fCB0aGlzO1xuICAgIC8qKlxuICAgICAqIEBwcml2YXRlXG4gICAgICogQHR5cGUge09iamVjdDxudW1iZXIsIEhUTUxDYW52YXNFbGVtZW50Pn1cbiAgICAgKi9cblxuICAgIF90aGlzLmNhbnZhc18gPSB7fTtcbiAgICAvKipcbiAgICAgKiBAcHJpdmF0ZVxuICAgICAqIEB0eXBlIHtIVE1MQ2FudmFzRWxlbWVudH1cbiAgICAgKi9cblxuICAgIF90aGlzLmhpdERldGVjdGlvbkNhbnZhc18gPSBudWxsO1xuICAgIC8qKlxuICAgICAqIEBwcml2YXRlXG4gICAgICogQHR5cGUge2ltcG9ydChcIi4vRmlsbC5qc1wiKS5kZWZhdWx0fVxuICAgICAqL1xuXG4gICAgX3RoaXMuZmlsbF8gPSBvcHRpb25zLmZpbGwgIT09IHVuZGVmaW5lZCA/IG9wdGlvbnMuZmlsbCA6IG51bGw7XG4gICAgLyoqXG4gICAgICogQHByaXZhdGVcbiAgICAgKiBAdHlwZSB7QXJyYXk8bnVtYmVyPn1cbiAgICAgKi9cblxuICAgIF90aGlzLm9yaWdpbl8gPSBbMCwgMF07XG4gICAgLyoqXG4gICAgICogQHByaXZhdGVcbiAgICAgKiBAdHlwZSB7bnVtYmVyfVxuICAgICAqL1xuXG4gICAgX3RoaXMucG9pbnRzXyA9IG9wdGlvbnMucG9pbnRzO1xuICAgIC8qKlxuICAgICAqIEBwcm90ZWN0ZWRcbiAgICAgKiBAdHlwZSB7bnVtYmVyfVxuICAgICAqL1xuXG4gICAgX3RoaXMucmFkaXVzXyA9IG9wdGlvbnMucmFkaXVzICE9PSB1bmRlZmluZWQgPyBvcHRpb25zLnJhZGl1cyA6IG9wdGlvbnMucmFkaXVzMTtcbiAgICAvKipcbiAgICAgKiBAcHJpdmF0ZVxuICAgICAqIEB0eXBlIHtudW1iZXJ8dW5kZWZpbmVkfVxuICAgICAqL1xuXG4gICAgX3RoaXMucmFkaXVzMl8gPSBvcHRpb25zLnJhZGl1czI7XG4gICAgLyoqXG4gICAgICogQHByaXZhdGVcbiAgICAgKiBAdHlwZSB7bnVtYmVyfVxuICAgICAqL1xuXG4gICAgX3RoaXMuYW5nbGVfID0gb3B0aW9ucy5hbmdsZSAhPT0gdW5kZWZpbmVkID8gb3B0aW9ucy5hbmdsZSA6IDA7XG4gICAgLyoqXG4gICAgICogQHByaXZhdGVcbiAgICAgKiBAdHlwZSB7aW1wb3J0KFwiLi9TdHJva2UuanNcIikuZGVmYXVsdH1cbiAgICAgKi9cblxuICAgIF90aGlzLnN0cm9rZV8gPSBvcHRpb25zLnN0cm9rZSAhPT0gdW5kZWZpbmVkID8gb3B0aW9ucy5zdHJva2UgOiBudWxsO1xuICAgIC8qKlxuICAgICAqIEBwcml2YXRlXG4gICAgICogQHR5cGUge0FycmF5PG51bWJlcj59XG4gICAgICovXG5cbiAgICBfdGhpcy5hbmNob3JfID0gbnVsbDtcbiAgICAvKipcbiAgICAgKiBAcHJpdmF0ZVxuICAgICAqIEB0eXBlIHtpbXBvcnQoXCIuLi9zaXplLmpzXCIpLlNpemV9XG4gICAgICovXG5cbiAgICBfdGhpcy5zaXplXyA9IG51bGw7XG4gICAgLyoqXG4gICAgICogQHByaXZhdGVcbiAgICAgKiBAdHlwZSB7aW1wb3J0KFwiLi4vc2l6ZS5qc1wiKS5TaXplfVxuICAgICAqL1xuXG4gICAgX3RoaXMuaW1hZ2VTaXplXyA9IG51bGw7XG4gICAgLyoqXG4gICAgICogQHByaXZhdGVcbiAgICAgKiBAdHlwZSB7aW1wb3J0KFwiLi4vc2l6ZS5qc1wiKS5TaXplfVxuICAgICAqL1xuXG4gICAgX3RoaXMuaGl0RGV0ZWN0aW9uSW1hZ2VTaXplXyA9IG51bGw7XG5cbiAgICBfdGhpcy5yZW5kZXIoKTtcblxuICAgIHJldHVybiBfdGhpcztcbiAgfVxuICAvKipcbiAgICogQ2xvbmVzIHRoZSBzdHlsZS5cbiAgICogQHJldHVybiB7UmVndWxhclNoYXBlfSBUaGUgY2xvbmVkIHN0eWxlLlxuICAgKiBAYXBpXG4gICAqL1xuXG5cbiAgUmVndWxhclNoYXBlLnByb3RvdHlwZS5jbG9uZSA9IGZ1bmN0aW9uICgpIHtcbiAgICB2YXIgc2NhbGUgPSB0aGlzLmdldFNjYWxlKCk7XG4gICAgdmFyIHN0eWxlID0gbmV3IFJlZ3VsYXJTaGFwZSh7XG4gICAgICBmaWxsOiB0aGlzLmdldEZpbGwoKSA/IHRoaXMuZ2V0RmlsbCgpLmNsb25lKCkgOiB1bmRlZmluZWQsXG4gICAgICBwb2ludHM6IHRoaXMuZ2V0UG9pbnRzKCksXG4gICAgICByYWRpdXM6IHRoaXMuZ2V0UmFkaXVzKCksXG4gICAgICByYWRpdXMyOiB0aGlzLmdldFJhZGl1czIoKSxcbiAgICAgIGFuZ2xlOiB0aGlzLmdldEFuZ2xlKCksXG4gICAgICBzdHJva2U6IHRoaXMuZ2V0U3Ryb2tlKCkgPyB0aGlzLmdldFN0cm9rZSgpLmNsb25lKCkgOiB1bmRlZmluZWQsXG4gICAgICByb3RhdGlvbjogdGhpcy5nZXRSb3RhdGlvbigpLFxuICAgICAgcm90YXRlV2l0aFZpZXc6IHRoaXMuZ2V0Um90YXRlV2l0aFZpZXcoKSxcbiAgICAgIHNjYWxlOiBBcnJheS5pc0FycmF5KHNjYWxlKSA/IHNjYWxlLnNsaWNlKCkgOiBzY2FsZSxcbiAgICAgIGRpc3BsYWNlbWVudDogdGhpcy5nZXREaXNwbGFjZW1lbnQoKS5zbGljZSgpXG4gICAgfSk7XG4gICAgc3R5bGUuc2V0T3BhY2l0eSh0aGlzLmdldE9wYWNpdHkoKSk7XG4gICAgcmV0dXJuIHN0eWxlO1xuICB9O1xuICAvKipcbiAgICogR2V0IHRoZSBhbmNob3IgcG9pbnQgaW4gcGl4ZWxzLiBUaGUgYW5jaG9yIGRldGVybWluZXMgdGhlIGNlbnRlciBwb2ludCBmb3IgdGhlXG4gICAqIHN5bWJvbGl6ZXIuXG4gICAqIEByZXR1cm4ge0FycmF5PG51bWJlcj59IEFuY2hvci5cbiAgICogQGFwaVxuICAgKi9cblxuXG4gIFJlZ3VsYXJTaGFwZS5wcm90b3R5cGUuZ2V0QW5jaG9yID0gZnVuY3Rpb24gKCkge1xuICAgIHJldHVybiB0aGlzLmFuY2hvcl87XG4gIH07XG4gIC8qKlxuICAgKiBHZXQgdGhlIGFuZ2xlIHVzZWQgaW4gZ2VuZXJhdGluZyB0aGUgc2hhcGUuXG4gICAqIEByZXR1cm4ge251bWJlcn0gU2hhcGUncyByb3RhdGlvbiBpbiByYWRpYW5zLlxuICAgKiBAYXBpXG4gICAqL1xuXG5cbiAgUmVndWxhclNoYXBlLnByb3RvdHlwZS5nZXRBbmdsZSA9IGZ1bmN0aW9uICgpIHtcbiAgICByZXR1cm4gdGhpcy5hbmdsZV87XG4gIH07XG4gIC8qKlxuICAgKiBHZXQgdGhlIGZpbGwgc3R5bGUgZm9yIHRoZSBzaGFwZS5cbiAgICogQHJldHVybiB7aW1wb3J0KFwiLi9GaWxsLmpzXCIpLmRlZmF1bHR9IEZpbGwgc3R5bGUuXG4gICAqIEBhcGlcbiAgICovXG5cblxuICBSZWd1bGFyU2hhcGUucHJvdG90eXBlLmdldEZpbGwgPSBmdW5jdGlvbiAoKSB7XG4gICAgcmV0dXJuIHRoaXMuZmlsbF87XG4gIH07XG4gIC8qKlxuICAgKiBAcmV0dXJuIHtIVE1MQ2FudmFzRWxlbWVudH0gSW1hZ2UgZWxlbWVudC5cbiAgICovXG5cblxuICBSZWd1bGFyU2hhcGUucHJvdG90eXBlLmdldEhpdERldGVjdGlvbkltYWdlID0gZnVuY3Rpb24gKCkge1xuICAgIGlmICghdGhpcy5oaXREZXRlY3Rpb25DYW52YXNfKSB7XG4gICAgICB2YXIgcmVuZGVyT3B0aW9ucyA9IHRoaXMuY3JlYXRlUmVuZGVyT3B0aW9ucygpO1xuICAgICAgdGhpcy5jcmVhdGVIaXREZXRlY3Rpb25DYW52YXNfKHJlbmRlck9wdGlvbnMpO1xuICAgIH1cblxuICAgIHJldHVybiB0aGlzLmhpdERldGVjdGlvbkNhbnZhc187XG4gIH07XG4gIC8qKlxuICAgKiBHZXQgdGhlIGltYWdlIGljb24uXG4gICAqIEBwYXJhbSB7bnVtYmVyfSBwaXhlbFJhdGlvIFBpeGVsIHJhdGlvLlxuICAgKiBAcmV0dXJuIHtIVE1MQ2FudmFzRWxlbWVudH0gSW1hZ2Ugb3IgQ2FudmFzIGVsZW1lbnQuXG4gICAqIEBhcGlcbiAgICovXG5cblxuICBSZWd1bGFyU2hhcGUucHJvdG90eXBlLmdldEltYWdlID0gZnVuY3Rpb24gKHBpeGVsUmF0aW8pIHtcbiAgICBpZiAoIXRoaXMuY2FudmFzX1twaXhlbFJhdGlvIHx8IDFdKSB7XG4gICAgICB2YXIgcmVuZGVyT3B0aW9ucyA9IHRoaXMuY3JlYXRlUmVuZGVyT3B0aW9ucygpO1xuICAgICAgdmFyIGNvbnRleHQgPSBjcmVhdGVDYW52YXNDb250ZXh0MkQocmVuZGVyT3B0aW9ucy5zaXplICogcGl4ZWxSYXRpbyB8fCAxLCByZW5kZXJPcHRpb25zLnNpemUgKiBwaXhlbFJhdGlvIHx8IDEpO1xuICAgICAgdGhpcy5kcmF3XyhyZW5kZXJPcHRpb25zLCBjb250ZXh0LCAwLCAwLCBwaXhlbFJhdGlvIHx8IDEpO1xuICAgICAgdGhpcy5jYW52YXNfW3BpeGVsUmF0aW8gfHwgMV0gPSBjb250ZXh0LmNhbnZhcztcbiAgICB9XG5cbiAgICByZXR1cm4gdGhpcy5jYW52YXNfW3BpeGVsUmF0aW8gfHwgMV07XG4gIH07XG4gIC8qXG4gICAqIEdldCB0aGUgaW1hZ2UgcGl4ZWwgcmF0aW8uXG4gICAqIEBwYXJhbSB7bnVtYmVyfSBwaXhlbFJhdGlvIFBpeGVsIHJhdGlvLlxuICAgKiAqL1xuXG5cbiAgUmVndWxhclNoYXBlLnByb3RvdHlwZS5nZXRQaXhlbFJhdGlvID0gZnVuY3Rpb24gKHBpeGVsUmF0aW8pIHtcbiAgICByZXR1cm4gcGl4ZWxSYXRpbztcbiAgfTtcbiAgLyoqXG4gICAqIEByZXR1cm4ge2ltcG9ydChcIi4uL3NpemUuanNcIikuU2l6ZX0gSW1hZ2Ugc2l6ZS5cbiAgICovXG5cblxuICBSZWd1bGFyU2hhcGUucHJvdG90eXBlLmdldEltYWdlU2l6ZSA9IGZ1bmN0aW9uICgpIHtcbiAgICByZXR1cm4gdGhpcy5pbWFnZVNpemVfO1xuICB9O1xuICAvKipcbiAgICogQHJldHVybiB7aW1wb3J0KFwiLi4vc2l6ZS5qc1wiKS5TaXplfSBTaXplIG9mIHRoZSBoaXQtZGV0ZWN0aW9uIGltYWdlLlxuICAgKi9cblxuXG4gIFJlZ3VsYXJTaGFwZS5wcm90b3R5cGUuZ2V0SGl0RGV0ZWN0aW9uSW1hZ2VTaXplID0gZnVuY3Rpb24gKCkge1xuICAgIHJldHVybiB0aGlzLmhpdERldGVjdGlvbkltYWdlU2l6ZV87XG4gIH07XG4gIC8qKlxuICAgKiBAcmV0dXJuIHtpbXBvcnQoXCIuLi9JbWFnZVN0YXRlLmpzXCIpLmRlZmF1bHR9IEltYWdlIHN0YXRlLlxuICAgKi9cblxuXG4gIFJlZ3VsYXJTaGFwZS5wcm90b3R5cGUuZ2V0SW1hZ2VTdGF0ZSA9IGZ1bmN0aW9uICgpIHtcbiAgICByZXR1cm4gSW1hZ2VTdGF0ZS5MT0FERUQ7XG4gIH07XG4gIC8qKlxuICAgKiBHZXQgdGhlIG9yaWdpbiBvZiB0aGUgc3ltYm9saXplci5cbiAgICogQHJldHVybiB7QXJyYXk8bnVtYmVyPn0gT3JpZ2luLlxuICAgKiBAYXBpXG4gICAqL1xuXG5cbiAgUmVndWxhclNoYXBlLnByb3RvdHlwZS5nZXRPcmlnaW4gPSBmdW5jdGlvbiAoKSB7XG4gICAgcmV0dXJuIHRoaXMub3JpZ2luXztcbiAgfTtcbiAgLyoqXG4gICAqIEdldCB0aGUgbnVtYmVyIG9mIHBvaW50cyBmb3IgZ2VuZXJhdGluZyB0aGUgc2hhcGUuXG4gICAqIEByZXR1cm4ge251bWJlcn0gTnVtYmVyIG9mIHBvaW50cyBmb3Igc3RhcnMgYW5kIHJlZ3VsYXIgcG9seWdvbnMuXG4gICAqIEBhcGlcbiAgICovXG5cblxuICBSZWd1bGFyU2hhcGUucHJvdG90eXBlLmdldFBvaW50cyA9IGZ1bmN0aW9uICgpIHtcbiAgICByZXR1cm4gdGhpcy5wb2ludHNfO1xuICB9O1xuICAvKipcbiAgICogR2V0IHRoZSAocHJpbWFyeSkgcmFkaXVzIGZvciB0aGUgc2hhcGUuXG4gICAqIEByZXR1cm4ge251bWJlcn0gUmFkaXVzLlxuICAgKiBAYXBpXG4gICAqL1xuXG5cbiAgUmVndWxhclNoYXBlLnByb3RvdHlwZS5nZXRSYWRpdXMgPSBmdW5jdGlvbiAoKSB7XG4gICAgcmV0dXJuIHRoaXMucmFkaXVzXztcbiAgfTtcbiAgLyoqXG4gICAqIEdldCB0aGUgc2Vjb25kYXJ5IHJhZGl1cyBmb3IgdGhlIHNoYXBlLlxuICAgKiBAcmV0dXJuIHtudW1iZXJ8dW5kZWZpbmVkfSBSYWRpdXMyLlxuICAgKiBAYXBpXG4gICAqL1xuXG5cbiAgUmVndWxhclNoYXBlLnByb3RvdHlwZS5nZXRSYWRpdXMyID0gZnVuY3Rpb24gKCkge1xuICAgIHJldHVybiB0aGlzLnJhZGl1czJfO1xuICB9O1xuICAvKipcbiAgICogR2V0IHRoZSBzaXplIG9mIHRoZSBzeW1ib2xpemVyIChpbiBwaXhlbHMpLlxuICAgKiBAcmV0dXJuIHtpbXBvcnQoXCIuLi9zaXplLmpzXCIpLlNpemV9IFNpemUuXG4gICAqIEBhcGlcbiAgICovXG5cblxuICBSZWd1bGFyU2hhcGUucHJvdG90eXBlLmdldFNpemUgPSBmdW5jdGlvbiAoKSB7XG4gICAgcmV0dXJuIHRoaXMuc2l6ZV87XG4gIH07XG4gIC8qKlxuICAgKiBHZXQgdGhlIHN0cm9rZSBzdHlsZSBmb3IgdGhlIHNoYXBlLlxuICAgKiBAcmV0dXJuIHtpbXBvcnQoXCIuL1N0cm9rZS5qc1wiKS5kZWZhdWx0fSBTdHJva2Ugc3R5bGUuXG4gICAqIEBhcGlcbiAgICovXG5cblxuICBSZWd1bGFyU2hhcGUucHJvdG90eXBlLmdldFN0cm9rZSA9IGZ1bmN0aW9uICgpIHtcbiAgICByZXR1cm4gdGhpcy5zdHJva2VfO1xuICB9O1xuICAvKipcbiAgICogQHBhcmFtIHtmdW5jdGlvbihpbXBvcnQoXCIuLi9ldmVudHMvRXZlbnQuanNcIikuZGVmYXVsdCk6IHZvaWR9IGxpc3RlbmVyIExpc3RlbmVyIGZ1bmN0aW9uLlxuICAgKi9cblxuXG4gIFJlZ3VsYXJTaGFwZS5wcm90b3R5cGUubGlzdGVuSW1hZ2VDaGFuZ2UgPSBmdW5jdGlvbiAobGlzdGVuZXIpIHt9O1xuICAvKipcbiAgICogTG9hZCBub3QgeWV0IGxvYWRlZCBVUkkuXG4gICAqL1xuXG5cbiAgUmVndWxhclNoYXBlLnByb3RvdHlwZS5sb2FkID0gZnVuY3Rpb24gKCkge307XG4gIC8qKlxuICAgKiBAcGFyYW0ge2Z1bmN0aW9uKGltcG9ydChcIi4uL2V2ZW50cy9FdmVudC5qc1wiKS5kZWZhdWx0KTogdm9pZH0gbGlzdGVuZXIgTGlzdGVuZXIgZnVuY3Rpb24uXG4gICAqL1xuXG5cbiAgUmVndWxhclNoYXBlLnByb3RvdHlwZS51bmxpc3RlbkltYWdlQ2hhbmdlID0gZnVuY3Rpb24gKGxpc3RlbmVyKSB7fTtcbiAgLyoqXG4gICAqIEByZXR1cm5zIHtSZW5kZXJPcHRpb25zfSAgVGhlIHJlbmRlciBvcHRpb25zXG4gICAqIEBwcm90ZWN0ZWRcbiAgICovXG5cblxuICBSZWd1bGFyU2hhcGUucHJvdG90eXBlLmNyZWF0ZVJlbmRlck9wdGlvbnMgPSBmdW5jdGlvbiAoKSB7XG4gICAgdmFyIGxpbmVDYXAgPSBkZWZhdWx0TGluZUNhcDtcbiAgICB2YXIgbGluZUpvaW4gPSBkZWZhdWx0TGluZUpvaW47XG4gICAgdmFyIG1pdGVyTGltaXQgPSAwO1xuICAgIHZhciBsaW5lRGFzaCA9IG51bGw7XG4gICAgdmFyIGxpbmVEYXNoT2Zmc2V0ID0gMDtcbiAgICB2YXIgc3Ryb2tlU3R5bGU7XG4gICAgdmFyIHN0cm9rZVdpZHRoID0gMDtcblxuICAgIGlmICh0aGlzLnN0cm9rZV8pIHtcbiAgICAgIHN0cm9rZVN0eWxlID0gdGhpcy5zdHJva2VfLmdldENvbG9yKCk7XG5cbiAgICAgIGlmIChzdHJva2VTdHlsZSA9PT0gbnVsbCkge1xuICAgICAgICBzdHJva2VTdHlsZSA9IGRlZmF1bHRTdHJva2VTdHlsZTtcbiAgICAgIH1cblxuICAgICAgc3Ryb2tlU3R5bGUgPSBhc0NvbG9yTGlrZShzdHJva2VTdHlsZSk7XG4gICAgICBzdHJva2VXaWR0aCA9IHRoaXMuc3Ryb2tlXy5nZXRXaWR0aCgpO1xuXG4gICAgICBpZiAoc3Ryb2tlV2lkdGggPT09IHVuZGVmaW5lZCkge1xuICAgICAgICBzdHJva2VXaWR0aCA9IGRlZmF1bHRMaW5lV2lkdGg7XG4gICAgICB9XG5cbiAgICAgIGxpbmVEYXNoID0gdGhpcy5zdHJva2VfLmdldExpbmVEYXNoKCk7XG4gICAgICBsaW5lRGFzaE9mZnNldCA9IHRoaXMuc3Ryb2tlXy5nZXRMaW5lRGFzaE9mZnNldCgpO1xuICAgICAgbGluZUpvaW4gPSB0aGlzLnN0cm9rZV8uZ2V0TGluZUpvaW4oKTtcblxuICAgICAgaWYgKGxpbmVKb2luID09PSB1bmRlZmluZWQpIHtcbiAgICAgICAgbGluZUpvaW4gPSBkZWZhdWx0TGluZUpvaW47XG4gICAgICB9XG5cbiAgICAgIGxpbmVDYXAgPSB0aGlzLnN0cm9rZV8uZ2V0TGluZUNhcCgpO1xuXG4gICAgICBpZiAobGluZUNhcCA9PT0gdW5kZWZpbmVkKSB7XG4gICAgICAgIGxpbmVDYXAgPSBkZWZhdWx0TGluZUNhcDtcbiAgICAgIH1cblxuICAgICAgbWl0ZXJMaW1pdCA9IHRoaXMuc3Ryb2tlXy5nZXRNaXRlckxpbWl0KCk7XG5cbiAgICAgIGlmIChtaXRlckxpbWl0ID09PSB1bmRlZmluZWQpIHtcbiAgICAgICAgbWl0ZXJMaW1pdCA9IGRlZmF1bHRNaXRlckxpbWl0O1xuICAgICAgfVxuICAgIH1cblxuICAgIHZhciBzaXplID0gMiAqICh0aGlzLnJhZGl1c18gKyBzdHJva2VXaWR0aCkgKyAxO1xuICAgIHJldHVybiB7XG4gICAgICBzdHJva2VTdHlsZTogc3Ryb2tlU3R5bGUsXG4gICAgICBzdHJva2VXaWR0aDogc3Ryb2tlV2lkdGgsXG4gICAgICBzaXplOiBzaXplLFxuICAgICAgbGluZUNhcDogbGluZUNhcCxcbiAgICAgIGxpbmVEYXNoOiBsaW5lRGFzaCxcbiAgICAgIGxpbmVEYXNoT2Zmc2V0OiBsaW5lRGFzaE9mZnNldCxcbiAgICAgIGxpbmVKb2luOiBsaW5lSm9pbixcbiAgICAgIG1pdGVyTGltaXQ6IG1pdGVyTGltaXRcbiAgICB9O1xuICB9O1xuICAvKipcbiAgICogQHByb3RlY3RlZFxuICAgKi9cblxuXG4gIFJlZ3VsYXJTaGFwZS5wcm90b3R5cGUucmVuZGVyID0gZnVuY3Rpb24gKCkge1xuICAgIHZhciByZW5kZXJPcHRpb25zID0gdGhpcy5jcmVhdGVSZW5kZXJPcHRpb25zKCk7XG4gICAgdmFyIGNvbnRleHQgPSBjcmVhdGVDYW52YXNDb250ZXh0MkQocmVuZGVyT3B0aW9ucy5zaXplLCByZW5kZXJPcHRpb25zLnNpemUpO1xuICAgIHRoaXMuZHJhd18ocmVuZGVyT3B0aW9ucywgY29udGV4dCwgMCwgMCwgMSk7XG4gICAgdGhpcy5jYW52YXNfID0ge307XG4gICAgdGhpcy5jYW52YXNfWzFdID0gY29udGV4dC5jYW52YXM7IC8vIGNhbnZhcy53aWR0aCBhbmQgaGVpZ2h0IGFyZSByb3VuZGVkIHRvIHRoZSBjbG9zZXN0IGludGVnZXJcblxuICAgIHZhciBzaXplID0gY29udGV4dC5jYW52YXMud2lkdGg7XG4gICAgdmFyIGltYWdlU2l6ZSA9IHNpemU7XG4gICAgdmFyIGRpc3BsYWNlbWVudCA9IHRoaXMuZ2V0RGlzcGxhY2VtZW50KCk7XG4gICAgdGhpcy5oaXREZXRlY3Rpb25JbWFnZVNpemVfID0gW3JlbmRlck9wdGlvbnMuc2l6ZSwgcmVuZGVyT3B0aW9ucy5zaXplXTtcbiAgICB0aGlzLmNyZWF0ZUhpdERldGVjdGlvbkNhbnZhc18ocmVuZGVyT3B0aW9ucyk7XG4gICAgdGhpcy5hbmNob3JfID0gW3NpemUgLyAyIC0gZGlzcGxhY2VtZW50WzBdLCBzaXplIC8gMiArIGRpc3BsYWNlbWVudFsxXV07XG4gICAgdGhpcy5zaXplXyA9IFtzaXplLCBzaXplXTtcbiAgICB0aGlzLmltYWdlU2l6ZV8gPSBbaW1hZ2VTaXplLCBpbWFnZVNpemVdO1xuICB9O1xuICAvKipcbiAgICogQHByaXZhdGVcbiAgICogQHBhcmFtIHtSZW5kZXJPcHRpb25zfSByZW5kZXJPcHRpb25zIFJlbmRlciBvcHRpb25zLlxuICAgKiBAcGFyYW0ge0NhbnZhc1JlbmRlcmluZ0NvbnRleHQyRH0gY29udGV4dCBUaGUgcmVuZGVyaW5nIGNvbnRleHQuXG4gICAqIEBwYXJhbSB7bnVtYmVyfSB4IFRoZSBvcmlnaW4gZm9yIHRoZSBzeW1ib2wgKHgpLlxuICAgKiBAcGFyYW0ge251bWJlcn0geSBUaGUgb3JpZ2luIGZvciB0aGUgc3ltYm9sICh5KS5cbiAgICogQHBhcmFtIHtudW1iZXJ9IHBpeGVsUmF0aW8gVGhlIHBpeGVsIHJhdGlvLlxuICAgKi9cblxuXG4gIFJlZ3VsYXJTaGFwZS5wcm90b3R5cGUuZHJhd18gPSBmdW5jdGlvbiAocmVuZGVyT3B0aW9ucywgY29udGV4dCwgeCwgeSwgcGl4ZWxSYXRpbykge1xuICAgIHZhciBpLCBhbmdsZTAsIHJhZGl1c0M7IC8vIHJlc2V0IHRyYW5zZm9ybVxuXG4gICAgY29udGV4dC5zZXRUcmFuc2Zvcm0ocGl4ZWxSYXRpbywgMCwgMCwgcGl4ZWxSYXRpbywgMCwgMCk7IC8vIHRoZW4gbW92ZSB0byAoeCwgeSlcblxuICAgIGNvbnRleHQudHJhbnNsYXRlKHgsIHkpO1xuICAgIGNvbnRleHQuYmVnaW5QYXRoKCk7XG4gICAgdmFyIHBvaW50cyA9IHRoaXMucG9pbnRzXztcblxuICAgIGlmIChwb2ludHMgPT09IEluZmluaXR5KSB7XG4gICAgICBjb250ZXh0LmFyYyhyZW5kZXJPcHRpb25zLnNpemUgLyAyLCByZW5kZXJPcHRpb25zLnNpemUgLyAyLCB0aGlzLnJhZGl1c18sIDAsIDIgKiBNYXRoLlBJLCB0cnVlKTtcbiAgICB9IGVsc2Uge1xuICAgICAgdmFyIHJhZGl1czIgPSB0aGlzLnJhZGl1czJfICE9PSB1bmRlZmluZWQgPyB0aGlzLnJhZGl1czJfIDogdGhpcy5yYWRpdXNfO1xuXG4gICAgICBpZiAocmFkaXVzMiAhPT0gdGhpcy5yYWRpdXNfKSB7XG4gICAgICAgIHBvaW50cyA9IDIgKiBwb2ludHM7XG4gICAgICB9XG5cbiAgICAgIGZvciAoaSA9IDA7IGkgPD0gcG9pbnRzOyBpKyspIHtcbiAgICAgICAgYW5nbGUwID0gaSAqIDIgKiBNYXRoLlBJIC8gcG9pbnRzIC0gTWF0aC5QSSAvIDIgKyB0aGlzLmFuZ2xlXztcbiAgICAgICAgcmFkaXVzQyA9IGkgJSAyID09PSAwID8gdGhpcy5yYWRpdXNfIDogcmFkaXVzMjtcbiAgICAgICAgY29udGV4dC5saW5lVG8ocmVuZGVyT3B0aW9ucy5zaXplIC8gMiArIHJhZGl1c0MgKiBNYXRoLmNvcyhhbmdsZTApLCByZW5kZXJPcHRpb25zLnNpemUgLyAyICsgcmFkaXVzQyAqIE1hdGguc2luKGFuZ2xlMCkpO1xuICAgICAgfVxuICAgIH1cblxuICAgIGlmICh0aGlzLmZpbGxfKSB7XG4gICAgICB2YXIgY29sb3IgPSB0aGlzLmZpbGxfLmdldENvbG9yKCk7XG5cbiAgICAgIGlmIChjb2xvciA9PT0gbnVsbCkge1xuICAgICAgICBjb2xvciA9IGRlZmF1bHRGaWxsU3R5bGU7XG4gICAgICB9XG5cbiAgICAgIGNvbnRleHQuZmlsbFN0eWxlID0gYXNDb2xvckxpa2UoY29sb3IpO1xuICAgICAgY29udGV4dC5maWxsKCk7XG4gICAgfVxuXG4gICAgaWYgKHRoaXMuc3Ryb2tlXykge1xuICAgICAgY29udGV4dC5zdHJva2VTdHlsZSA9IHJlbmRlck9wdGlvbnMuc3Ryb2tlU3R5bGU7XG4gICAgICBjb250ZXh0LmxpbmVXaWR0aCA9IHJlbmRlck9wdGlvbnMuc3Ryb2tlV2lkdGg7XG5cbiAgICAgIGlmIChjb250ZXh0LnNldExpbmVEYXNoICYmIHJlbmRlck9wdGlvbnMubGluZURhc2gpIHtcbiAgICAgICAgY29udGV4dC5zZXRMaW5lRGFzaChyZW5kZXJPcHRpb25zLmxpbmVEYXNoKTtcbiAgICAgICAgY29udGV4dC5saW5lRGFzaE9mZnNldCA9IHJlbmRlck9wdGlvbnMubGluZURhc2hPZmZzZXQ7XG4gICAgICB9XG5cbiAgICAgIGNvbnRleHQubGluZUNhcCA9IHJlbmRlck9wdGlvbnMubGluZUNhcDtcbiAgICAgIGNvbnRleHQubGluZUpvaW4gPSByZW5kZXJPcHRpb25zLmxpbmVKb2luO1xuICAgICAgY29udGV4dC5taXRlckxpbWl0ID0gcmVuZGVyT3B0aW9ucy5taXRlckxpbWl0O1xuICAgICAgY29udGV4dC5zdHJva2UoKTtcbiAgICB9XG5cbiAgICBjb250ZXh0LmNsb3NlUGF0aCgpO1xuICB9O1xuICAvKipcbiAgICogQHByaXZhdGVcbiAgICogQHBhcmFtIHtSZW5kZXJPcHRpb25zfSByZW5kZXJPcHRpb25zIFJlbmRlciBvcHRpb25zLlxuICAgKi9cblxuXG4gIFJlZ3VsYXJTaGFwZS5wcm90b3R5cGUuY3JlYXRlSGl0RGV0ZWN0aW9uQ2FudmFzXyA9IGZ1bmN0aW9uIChyZW5kZXJPcHRpb25zKSB7XG4gICAgdGhpcy5oaXREZXRlY3Rpb25DYW52YXNfID0gdGhpcy5nZXRJbWFnZSgxKTtcblxuICAgIGlmICh0aGlzLmZpbGxfKSB7XG4gICAgICB2YXIgY29sb3IgPSB0aGlzLmZpbGxfLmdldENvbG9yKCk7IC8vIGRldGVybWluZSBpZiBmaWxsIGlzIHRyYW5zcGFyZW50IChvciBwYXR0ZXJuIG9yIGdyYWRpZW50KVxuXG4gICAgICB2YXIgb3BhY2l0eSA9IDA7XG5cbiAgICAgIGlmICh0eXBlb2YgY29sb3IgPT09ICdzdHJpbmcnKSB7XG4gICAgICAgIGNvbG9yID0gYXNBcnJheShjb2xvcik7XG4gICAgICB9XG5cbiAgICAgIGlmIChjb2xvciA9PT0gbnVsbCkge1xuICAgICAgICBvcGFjaXR5ID0gMTtcbiAgICAgIH0gZWxzZSBpZiAoQXJyYXkuaXNBcnJheShjb2xvcikpIHtcbiAgICAgICAgb3BhY2l0eSA9IGNvbG9yLmxlbmd0aCA9PT0gNCA/IGNvbG9yWzNdIDogMTtcbiAgICAgIH1cblxuICAgICAgaWYgKG9wYWNpdHkgPT09IDApIHtcbiAgICAgICAgLy8gaWYgYSB0cmFuc3BhcmVudCBmaWxsIHN0eWxlIGlzIHNldCwgY3JlYXRlIGFuIGV4dHJhIGhpdC1kZXRlY3Rpb24gaW1hZ2VcbiAgICAgICAgLy8gd2l0aCBhIGRlZmF1bHQgZmlsbCBzdHlsZVxuICAgICAgICB2YXIgY29udGV4dCA9IGNyZWF0ZUNhbnZhc0NvbnRleHQyRChyZW5kZXJPcHRpb25zLnNpemUsIHJlbmRlck9wdGlvbnMuc2l6ZSk7XG4gICAgICAgIHRoaXMuaGl0RGV0ZWN0aW9uQ2FudmFzXyA9IGNvbnRleHQuY2FudmFzO1xuICAgICAgICB0aGlzLmRyYXdIaXREZXRlY3Rpb25DYW52YXNfKHJlbmRlck9wdGlvbnMsIGNvbnRleHQsIDAsIDApO1xuICAgICAgfVxuICAgIH1cbiAgfTtcbiAgLyoqXG4gICAqIEBwcml2YXRlXG4gICAqIEBwYXJhbSB7UmVuZGVyT3B0aW9uc30gcmVuZGVyT3B0aW9ucyBSZW5kZXIgb3B0aW9ucy5cbiAgICogQHBhcmFtIHtDYW52YXNSZW5kZXJpbmdDb250ZXh0MkR9IGNvbnRleHQgVGhlIGNvbnRleHQuXG4gICAqIEBwYXJhbSB7bnVtYmVyfSB4IFRoZSBvcmlnaW4gZm9yIHRoZSBzeW1ib2wgKHgpLlxuICAgKiBAcGFyYW0ge251bWJlcn0geSBUaGUgb3JpZ2luIGZvciB0aGUgc3ltYm9sICh5KS5cbiAgICovXG5cblxuICBSZWd1bGFyU2hhcGUucHJvdG90eXBlLmRyYXdIaXREZXRlY3Rpb25DYW52YXNfID0gZnVuY3Rpb24gKHJlbmRlck9wdGlvbnMsIGNvbnRleHQsIHgsIHkpIHtcbiAgICAvLyBtb3ZlIHRvICh4LCB5KVxuICAgIGNvbnRleHQudHJhbnNsYXRlKHgsIHkpO1xuICAgIGNvbnRleHQuYmVnaW5QYXRoKCk7XG4gICAgdmFyIHBvaW50cyA9IHRoaXMucG9pbnRzXztcblxuICAgIGlmIChwb2ludHMgPT09IEluZmluaXR5KSB7XG4gICAgICBjb250ZXh0LmFyYyhyZW5kZXJPcHRpb25zLnNpemUgLyAyLCByZW5kZXJPcHRpb25zLnNpemUgLyAyLCB0aGlzLnJhZGl1c18sIDAsIDIgKiBNYXRoLlBJLCB0cnVlKTtcbiAgICB9IGVsc2Uge1xuICAgICAgdmFyIHJhZGl1czIgPSB0aGlzLnJhZGl1czJfICE9PSB1bmRlZmluZWQgPyB0aGlzLnJhZGl1czJfIDogdGhpcy5yYWRpdXNfO1xuXG4gICAgICBpZiAocmFkaXVzMiAhPT0gdGhpcy5yYWRpdXNfKSB7XG4gICAgICAgIHBvaW50cyA9IDIgKiBwb2ludHM7XG4gICAgICB9XG5cbiAgICAgIHZhciBpID0gdm9pZCAwLFxuICAgICAgICAgIHJhZGl1c0MgPSB2b2lkIDAsXG4gICAgICAgICAgYW5nbGUwID0gdm9pZCAwO1xuXG4gICAgICBmb3IgKGkgPSAwOyBpIDw9IHBvaW50czsgaSsrKSB7XG4gICAgICAgIGFuZ2xlMCA9IGkgKiAyICogTWF0aC5QSSAvIHBvaW50cyAtIE1hdGguUEkgLyAyICsgdGhpcy5hbmdsZV87XG4gICAgICAgIHJhZGl1c0MgPSBpICUgMiA9PT0gMCA/IHRoaXMucmFkaXVzXyA6IHJhZGl1czI7XG4gICAgICAgIGNvbnRleHQubGluZVRvKHJlbmRlck9wdGlvbnMuc2l6ZSAvIDIgKyByYWRpdXNDICogTWF0aC5jb3MoYW5nbGUwKSwgcmVuZGVyT3B0aW9ucy5zaXplIC8gMiArIHJhZGl1c0MgKiBNYXRoLnNpbihhbmdsZTApKTtcbiAgICAgIH1cbiAgICB9XG5cbiAgICBjb250ZXh0LmZpbGxTdHlsZSA9IGRlZmF1bHRGaWxsU3R5bGU7XG4gICAgY29udGV4dC5maWxsKCk7XG5cbiAgICBpZiAodGhpcy5zdHJva2VfKSB7XG4gICAgICBjb250ZXh0LnN0cm9rZVN0eWxlID0gcmVuZGVyT3B0aW9ucy5zdHJva2VTdHlsZTtcbiAgICAgIGNvbnRleHQubGluZVdpZHRoID0gcmVuZGVyT3B0aW9ucy5zdHJva2VXaWR0aDtcblxuICAgICAgaWYgKHJlbmRlck9wdGlvbnMubGluZURhc2gpIHtcbiAgICAgICAgY29udGV4dC5zZXRMaW5lRGFzaChyZW5kZXJPcHRpb25zLmxpbmVEYXNoKTtcbiAgICAgICAgY29udGV4dC5saW5lRGFzaE9mZnNldCA9IHJlbmRlck9wdGlvbnMubGluZURhc2hPZmZzZXQ7XG4gICAgICB9XG5cbiAgICAgIGNvbnRleHQuc3Ryb2tlKCk7XG4gICAgfVxuXG4gICAgY29udGV4dC5jbG9zZVBhdGgoKTtcbiAgfTtcblxuICByZXR1cm4gUmVndWxhclNoYXBlO1xufShJbWFnZVN0eWxlKTtcblxuZXhwb3J0IGRlZmF1bHQgUmVndWxhclNoYXBlOyIsIi8qKlxuICogQG1vZHVsZSBvbC9zdHlsZS9DaXJjbGVcbiAqL1xudmFyIF9fZXh0ZW5kcyA9IHRoaXMgJiYgdGhpcy5fX2V4dGVuZHMgfHwgZnVuY3Rpb24gKCkge1xuICB2YXIgX2V4dGVuZFN0YXRpY3MgPSBmdW5jdGlvbiBleHRlbmRTdGF0aWNzKGQsIGIpIHtcbiAgICBfZXh0ZW5kU3RhdGljcyA9IE9iamVjdC5zZXRQcm90b3R5cGVPZiB8fCB7XG4gICAgICBfX3Byb3RvX186IFtdXG4gICAgfSBpbnN0YW5jZW9mIEFycmF5ICYmIGZ1bmN0aW9uIChkLCBiKSB7XG4gICAgICBkLl9fcHJvdG9fXyA9IGI7XG4gICAgfSB8fCBmdW5jdGlvbiAoZCwgYikge1xuICAgICAgZm9yICh2YXIgcCBpbiBiKSB7XG4gICAgICAgIGlmIChPYmplY3QucHJvdG90eXBlLmhhc093blByb3BlcnR5LmNhbGwoYiwgcCkpIGRbcF0gPSBiW3BdO1xuICAgICAgfVxuICAgIH07XG5cbiAgICByZXR1cm4gX2V4dGVuZFN0YXRpY3MoZCwgYik7XG4gIH07XG5cbiAgcmV0dXJuIGZ1bmN0aW9uIChkLCBiKSB7XG4gICAgX2V4dGVuZFN0YXRpY3MoZCwgYik7XG5cbiAgICBmdW5jdGlvbiBfXygpIHtcbiAgICAgIHRoaXMuY29uc3RydWN0b3IgPSBkO1xuICAgIH1cblxuICAgIGQucHJvdG90eXBlID0gYiA9PT0gbnVsbCA/IE9iamVjdC5jcmVhdGUoYikgOiAoX18ucHJvdG90eXBlID0gYi5wcm90b3R5cGUsIG5ldyBfXygpKTtcbiAgfTtcbn0oKTtcblxuaW1wb3J0IFJlZ3VsYXJTaGFwZSBmcm9tICcuL1JlZ3VsYXJTaGFwZS5qcyc7XG4vKipcbiAqIEB0eXBlZGVmIHtPYmplY3R9IE9wdGlvbnNcbiAqIEBwcm9wZXJ0eSB7aW1wb3J0KFwiLi9GaWxsLmpzXCIpLmRlZmF1bHR9IFtmaWxsXSBGaWxsIHN0eWxlLlxuICogQHByb3BlcnR5IHtudW1iZXJ9IHJhZGl1cyBDaXJjbGUgcmFkaXVzLlxuICogQHByb3BlcnR5IHtpbXBvcnQoXCIuL1N0cm9rZS5qc1wiKS5kZWZhdWx0fSBbc3Ryb2tlXSBTdHJva2Ugc3R5bGUuXG4gKiBAcHJvcGVydHkge0FycmF5PG51bWJlcj59IFtkaXNwbGFjZW1lbnQ9WzAsMF1dIGRpc3BsYWNlbWVudFxuICogQHByb3BlcnR5IHtudW1iZXJ8aW1wb3J0KFwiLi4vc2l6ZS5qc1wiKS5TaXplfSBbc2NhbGU9MV0gU2NhbGUuIEEgdHdvIGRpbWVuc2lvbmFsIHNjYWxlIHdpbGwgcHJvZHVjZSBhbiBlbGxpcHNlLlxuICogVW5sZXNzIHR3byBkaW1lbnNpb25hbCBzY2FsaW5nIGlzIHJlcXVpcmVkIGEgYmV0dGVyIHJlc3VsdCBtYXkgYmUgb2J0YWluZWQgd2l0aCBhbiBhcHByb3ByaWF0ZSBzZXR0aW5nIGZvciBgcmFkaXVzYC5cbiAqIEBwcm9wZXJ0eSB7bnVtYmVyfSBbcm90YXRpb249MF0gUm90YXRpb24gaW4gcmFkaWFuc1xuICogKHBvc2l0aXZlIHJvdGF0aW9uIGNsb2Nrd2lzZSwgbWVhbmluZ2Z1bCBvbmx5IHdoZW4gdXNlZCBpbiBjb25qdW5jdGlvbiB3aXRoIGEgdHdvIGRpbWVuc2lvbmFsIHNjYWxlKS5cbiAqIEBwcm9wZXJ0eSB7Ym9vbGVhbn0gW3JvdGF0ZVdpdGhWaWV3PWZhbHNlXSBXaGV0aGVyIHRvIHJvdGF0ZSB0aGUgc2hhcGUgd2l0aCB0aGUgdmlld1xuICogKG1lYW5pbmdmdWwgb25seSB3aGVuIHVzZWQgaW4gY29uanVuY3Rpb24gd2l0aCBhIHR3byBkaW1lbnNpb25hbCBzY2FsZSkuXG4gKi9cblxuLyoqXG4gKiBAY2xhc3NkZXNjXG4gKiBTZXQgY2lyY2xlIHN0eWxlIGZvciB2ZWN0b3IgZmVhdHVyZXMuXG4gKiBAYXBpXG4gKi9cblxudmFyIENpcmNsZVN0eWxlID1cbi8qKiBAY2xhc3MgKi9cbmZ1bmN0aW9uIChfc3VwZXIpIHtcbiAgX19leHRlbmRzKENpcmNsZVN0eWxlLCBfc3VwZXIpO1xuICAvKipcbiAgICogQHBhcmFtIHtPcHRpb25zPX0gb3B0X29wdGlvbnMgT3B0aW9ucy5cbiAgICovXG5cblxuICBmdW5jdGlvbiBDaXJjbGVTdHlsZShvcHRfb3B0aW9ucykge1xuICAgIHZhciBfdGhpcyA9IHRoaXM7XG5cbiAgICB2YXIgb3B0aW9ucyA9IG9wdF9vcHRpb25zID8gb3B0X29wdGlvbnMgOiB7fTtcbiAgICBfdGhpcyA9IF9zdXBlci5jYWxsKHRoaXMsIHtcbiAgICAgIHBvaW50czogSW5maW5pdHksXG4gICAgICBmaWxsOiBvcHRpb25zLmZpbGwsXG4gICAgICByYWRpdXM6IG9wdGlvbnMucmFkaXVzLFxuICAgICAgc3Ryb2tlOiBvcHRpb25zLnN0cm9rZSxcbiAgICAgIHNjYWxlOiBvcHRpb25zLnNjYWxlICE9PSB1bmRlZmluZWQgPyBvcHRpb25zLnNjYWxlIDogMSxcbiAgICAgIHJvdGF0aW9uOiBvcHRpb25zLnJvdGF0aW9uICE9PSB1bmRlZmluZWQgPyBvcHRpb25zLnJvdGF0aW9uIDogMCxcbiAgICAgIHJvdGF0ZVdpdGhWaWV3OiBvcHRpb25zLnJvdGF0ZVdpdGhWaWV3ICE9PSB1bmRlZmluZWQgPyBvcHRpb25zLnJvdGF0ZVdpdGhWaWV3IDogZmFsc2UsXG4gICAgICBkaXNwbGFjZW1lbnQ6IG9wdGlvbnMuZGlzcGxhY2VtZW50ICE9PSB1bmRlZmluZWQgPyBvcHRpb25zLmRpc3BsYWNlbWVudCA6IFswLCAwXVxuICAgIH0pIHx8IHRoaXM7XG4gICAgcmV0dXJuIF90aGlzO1xuICB9XG4gIC8qKlxuICAgKiBDbG9uZXMgdGhlIHN0eWxlLlxuICAgKiBAcmV0dXJuIHtDaXJjbGVTdHlsZX0gVGhlIGNsb25lZCBzdHlsZS5cbiAgICogQGFwaVxuICAgKi9cblxuXG4gIENpcmNsZVN0eWxlLnByb3RvdHlwZS5jbG9uZSA9IGZ1bmN0aW9uICgpIHtcbiAgICB2YXIgc2NhbGUgPSB0aGlzLmdldFNjYWxlKCk7XG4gICAgdmFyIHN0eWxlID0gbmV3IENpcmNsZVN0eWxlKHtcbiAgICAgIGZpbGw6IHRoaXMuZ2V0RmlsbCgpID8gdGhpcy5nZXRGaWxsKCkuY2xvbmUoKSA6IHVuZGVmaW5lZCxcbiAgICAgIHN0cm9rZTogdGhpcy5nZXRTdHJva2UoKSA/IHRoaXMuZ2V0U3Ryb2tlKCkuY2xvbmUoKSA6IHVuZGVmaW5lZCxcbiAgICAgIHJhZGl1czogdGhpcy5nZXRSYWRpdXMoKSxcbiAgICAgIHNjYWxlOiBBcnJheS5pc0FycmF5KHNjYWxlKSA/IHNjYWxlLnNsaWNlKCkgOiBzY2FsZSxcbiAgICAgIHJvdGF0aW9uOiB0aGlzLmdldFJvdGF0aW9uKCksXG4gICAgICByb3RhdGVXaXRoVmlldzogdGhpcy5nZXRSb3RhdGVXaXRoVmlldygpLFxuICAgICAgZGlzcGxhY2VtZW50OiB0aGlzLmdldERpc3BsYWNlbWVudCgpLnNsaWNlKClcbiAgICB9KTtcbiAgICBzdHlsZS5zZXRPcGFjaXR5KHRoaXMuZ2V0T3BhY2l0eSgpKTtcbiAgICByZXR1cm4gc3R5bGU7XG4gIH07XG4gIC8qKlxuICAgKiBTZXQgdGhlIGNpcmNsZSByYWRpdXMuXG4gICAqXG4gICAqIEBwYXJhbSB7bnVtYmVyfSByYWRpdXMgQ2lyY2xlIHJhZGl1cy5cbiAgICogQGFwaVxuICAgKi9cblxuXG4gIENpcmNsZVN0eWxlLnByb3RvdHlwZS5zZXRSYWRpdXMgPSBmdW5jdGlvbiAocmFkaXVzKSB7XG4gICAgdGhpcy5yYWRpdXNfID0gcmFkaXVzO1xuICAgIHRoaXMucmVuZGVyKCk7XG4gIH07XG5cbiAgcmV0dXJuIENpcmNsZVN0eWxlO1xufShSZWd1bGFyU2hhcGUpO1xuXG5leHBvcnQgZGVmYXVsdCBDaXJjbGVTdHlsZTsiLCIvKipcbiAqIEBtb2R1bGUgb2wvc3R5bGUvRmlsbFxuICovXG5cbi8qKlxuICogQHR5cGVkZWYge09iamVjdH0gT3B0aW9uc1xuICogQHByb3BlcnR5IHtpbXBvcnQoXCIuLi9jb2xvci5qc1wiKS5Db2xvcnxpbXBvcnQoXCIuLi9jb2xvcmxpa2UuanNcIikuQ29sb3JMaWtlfSBbY29sb3I9bnVsbF0gQSBjb2xvciwgZ3JhZGllbnQgb3IgcGF0dGVybi5cbiAqIFNlZSB7QGxpbmsgbW9kdWxlOm9sL2NvbG9yfkNvbG9yfSBhbmQge0BsaW5rIG1vZHVsZTpvbC9jb2xvcmxpa2V+Q29sb3JMaWtlfSBmb3IgcG9zc2libGUgZm9ybWF0cy5cbiAqIERlZmF1bHQgbnVsbDsgaWYgbnVsbCwgdGhlIENhbnZhcy9yZW5kZXJlciBkZWZhdWx0IGJsYWNrIHdpbGwgYmUgdXNlZC5cbiAqL1xuXG4vKipcbiAqIEBjbGFzc2Rlc2NcbiAqIFNldCBmaWxsIHN0eWxlIGZvciB2ZWN0b3IgZmVhdHVyZXMuXG4gKiBAYXBpXG4gKi9cbnZhciBGaWxsID1cbi8qKiBAY2xhc3MgKi9cbmZ1bmN0aW9uICgpIHtcbiAgLyoqXG4gICAqIEBwYXJhbSB7T3B0aW9ucz19IG9wdF9vcHRpb25zIE9wdGlvbnMuXG4gICAqL1xuICBmdW5jdGlvbiBGaWxsKG9wdF9vcHRpb25zKSB7XG4gICAgdmFyIG9wdGlvbnMgPSBvcHRfb3B0aW9ucyB8fCB7fTtcbiAgICAvKipcbiAgICAgKiBAcHJpdmF0ZVxuICAgICAqIEB0eXBlIHtpbXBvcnQoXCIuLi9jb2xvci5qc1wiKS5Db2xvcnxpbXBvcnQoXCIuLi9jb2xvcmxpa2UuanNcIikuQ29sb3JMaWtlfVxuICAgICAqL1xuXG4gICAgdGhpcy5jb2xvcl8gPSBvcHRpb25zLmNvbG9yICE9PSB1bmRlZmluZWQgPyBvcHRpb25zLmNvbG9yIDogbnVsbDtcbiAgfVxuICAvKipcbiAgICogQ2xvbmVzIHRoZSBzdHlsZS4gVGhlIGNvbG9yIGlzIG5vdCBjbG9uZWQgaWYgaXQgaXMgYW4ge0BsaW5rIG1vZHVsZTpvbC9jb2xvcmxpa2V+Q29sb3JMaWtlfS5cbiAgICogQHJldHVybiB7RmlsbH0gVGhlIGNsb25lZCBzdHlsZS5cbiAgICogQGFwaVxuICAgKi9cblxuXG4gIEZpbGwucHJvdG90eXBlLmNsb25lID0gZnVuY3Rpb24gKCkge1xuICAgIHZhciBjb2xvciA9IHRoaXMuZ2V0Q29sb3IoKTtcbiAgICByZXR1cm4gbmV3IEZpbGwoe1xuICAgICAgY29sb3I6IEFycmF5LmlzQXJyYXkoY29sb3IpID8gY29sb3Iuc2xpY2UoKSA6IGNvbG9yIHx8IHVuZGVmaW5lZFxuICAgIH0pO1xuICB9O1xuICAvKipcbiAgICogR2V0IHRoZSBmaWxsIGNvbG9yLlxuICAgKiBAcmV0dXJuIHtpbXBvcnQoXCIuLi9jb2xvci5qc1wiKS5Db2xvcnxpbXBvcnQoXCIuLi9jb2xvcmxpa2UuanNcIikuQ29sb3JMaWtlfSBDb2xvci5cbiAgICogQGFwaVxuICAgKi9cblxuXG4gIEZpbGwucHJvdG90eXBlLmdldENvbG9yID0gZnVuY3Rpb24gKCkge1xuICAgIHJldHVybiB0aGlzLmNvbG9yXztcbiAgfTtcbiAgLyoqXG4gICAqIFNldCB0aGUgY29sb3IuXG4gICAqXG4gICAqIEBwYXJhbSB7aW1wb3J0KFwiLi4vY29sb3IuanNcIikuQ29sb3J8aW1wb3J0KFwiLi4vY29sb3JsaWtlLmpzXCIpLkNvbG9yTGlrZX0gY29sb3IgQ29sb3IuXG4gICAqIEBhcGlcbiAgICovXG5cblxuICBGaWxsLnByb3RvdHlwZS5zZXRDb2xvciA9IGZ1bmN0aW9uIChjb2xvcikge1xuICAgIHRoaXMuY29sb3JfID0gY29sb3I7XG4gIH07XG5cbiAgcmV0dXJuIEZpbGw7XG59KCk7XG5cbmV4cG9ydCBkZWZhdWx0IEZpbGw7IiwiLyoqXG4gKiBAbW9kdWxlIG9sL3N0eWxlL1N0cm9rZVxuICovXG5cbi8qKlxuICogQHR5cGVkZWYge09iamVjdH0gT3B0aW9uc1xuICogQHByb3BlcnR5IHtpbXBvcnQoXCIuLi9jb2xvci5qc1wiKS5Db2xvcnxpbXBvcnQoXCIuLi9jb2xvcmxpa2UuanNcIikuQ29sb3JMaWtlfSBbY29sb3JdIEEgY29sb3IsIGdyYWRpZW50IG9yIHBhdHRlcm4uXG4gKiBTZWUge0BsaW5rIG1vZHVsZTpvbC9jb2xvcn5Db2xvcn0gYW5kIHtAbGluayBtb2R1bGU6b2wvY29sb3JsaWtlfkNvbG9yTGlrZX0gZm9yIHBvc3NpYmxlIGZvcm1hdHMuXG4gKiBEZWZhdWx0IG51bGw7IGlmIG51bGwsIHRoZSBDYW52YXMvcmVuZGVyZXIgZGVmYXVsdCBibGFjayB3aWxsIGJlIHVzZWQuXG4gKiBAcHJvcGVydHkge0NhbnZhc0xpbmVDYXB9IFtsaW5lQ2FwPSdyb3VuZCddIExpbmUgY2FwIHN0eWxlOiBgYnV0dGAsIGByb3VuZGAsIG9yIGBzcXVhcmVgLlxuICogQHByb3BlcnR5IHtDYW52YXNMaW5lSm9pbn0gW2xpbmVKb2luPSdyb3VuZCddIExpbmUgam9pbiBzdHlsZTogYGJldmVsYCwgYHJvdW5kYCwgb3IgYG1pdGVyYC5cbiAqIEBwcm9wZXJ0eSB7QXJyYXk8bnVtYmVyPn0gW2xpbmVEYXNoXSBMaW5lIGRhc2ggcGF0dGVybi4gRGVmYXVsdCBpcyBgbnVsbGAgKG5vIGRhc2gpLlxuICogUGxlYXNlIG5vdGUgdGhhdCBJbnRlcm5ldCBFeHBsb3JlciAxMCBhbmQgbG93ZXIgZG8gbm90IHN1cHBvcnQgdGhlIGBzZXRMaW5lRGFzaGAgbWV0aG9kIG9uXG4gKiB0aGUgYENhbnZhc1JlbmRlcmluZ0NvbnRleHQyRGAgYW5kIHRoZXJlZm9yZSB0aGlzIG9wdGlvbiB3aWxsIGhhdmUgbm8gdmlzdWFsIGVmZmVjdCBpbiB0aGVzZSBicm93c2Vycy5cbiAqIEBwcm9wZXJ0eSB7bnVtYmVyfSBbbGluZURhc2hPZmZzZXQ9MF0gTGluZSBkYXNoIG9mZnNldC5cbiAqIEBwcm9wZXJ0eSB7bnVtYmVyfSBbbWl0ZXJMaW1pdD0xMF0gTWl0ZXIgbGltaXQuXG4gKiBAcHJvcGVydHkge251bWJlcn0gW3dpZHRoXSBXaWR0aC5cbiAqL1xuXG4vKipcbiAqIEBjbGFzc2Rlc2NcbiAqIFNldCBzdHJva2Ugc3R5bGUgZm9yIHZlY3RvciBmZWF0dXJlcy5cbiAqIE5vdGUgdGhhdCB0aGUgZGVmYXVsdHMgZ2l2ZW4gYXJlIHRoZSBDYW52YXMgZGVmYXVsdHMsIHdoaWNoIHdpbGwgYmUgdXNlZCBpZlxuICogb3B0aW9uIGlzIG5vdCBkZWZpbmVkLiBUaGUgYGdldGAgZnVuY3Rpb25zIHJldHVybiB3aGF0ZXZlciB3YXMgZW50ZXJlZCBpblxuICogdGhlIG9wdGlvbnM7IHRoZXkgd2lsbCBub3QgcmV0dXJuIHRoZSBkZWZhdWx0LlxuICogQGFwaVxuICovXG52YXIgU3Ryb2tlID1cbi8qKiBAY2xhc3MgKi9cbmZ1bmN0aW9uICgpIHtcbiAgLyoqXG4gICAqIEBwYXJhbSB7T3B0aW9ucz19IG9wdF9vcHRpb25zIE9wdGlvbnMuXG4gICAqL1xuICBmdW5jdGlvbiBTdHJva2Uob3B0X29wdGlvbnMpIHtcbiAgICB2YXIgb3B0aW9ucyA9IG9wdF9vcHRpb25zIHx8IHt9O1xuICAgIC8qKlxuICAgICAqIEBwcml2YXRlXG4gICAgICogQHR5cGUge2ltcG9ydChcIi4uL2NvbG9yLmpzXCIpLkNvbG9yfGltcG9ydChcIi4uL2NvbG9ybGlrZS5qc1wiKS5Db2xvckxpa2V9XG4gICAgICovXG5cbiAgICB0aGlzLmNvbG9yXyA9IG9wdGlvbnMuY29sb3IgIT09IHVuZGVmaW5lZCA/IG9wdGlvbnMuY29sb3IgOiBudWxsO1xuICAgIC8qKlxuICAgICAqIEBwcml2YXRlXG4gICAgICogQHR5cGUge0NhbnZhc0xpbmVDYXB8dW5kZWZpbmVkfVxuICAgICAqL1xuXG4gICAgdGhpcy5saW5lQ2FwXyA9IG9wdGlvbnMubGluZUNhcDtcbiAgICAvKipcbiAgICAgKiBAcHJpdmF0ZVxuICAgICAqIEB0eXBlIHtBcnJheTxudW1iZXI+fVxuICAgICAqL1xuXG4gICAgdGhpcy5saW5lRGFzaF8gPSBvcHRpb25zLmxpbmVEYXNoICE9PSB1bmRlZmluZWQgPyBvcHRpb25zLmxpbmVEYXNoIDogbnVsbDtcbiAgICAvKipcbiAgICAgKiBAcHJpdmF0ZVxuICAgICAqIEB0eXBlIHtudW1iZXJ8dW5kZWZpbmVkfVxuICAgICAqL1xuXG4gICAgdGhpcy5saW5lRGFzaE9mZnNldF8gPSBvcHRpb25zLmxpbmVEYXNoT2Zmc2V0O1xuICAgIC8qKlxuICAgICAqIEBwcml2YXRlXG4gICAgICogQHR5cGUge0NhbnZhc0xpbmVKb2lufHVuZGVmaW5lZH1cbiAgICAgKi9cblxuICAgIHRoaXMubGluZUpvaW5fID0gb3B0aW9ucy5saW5lSm9pbjtcbiAgICAvKipcbiAgICAgKiBAcHJpdmF0ZVxuICAgICAqIEB0eXBlIHtudW1iZXJ8dW5kZWZpbmVkfVxuICAgICAqL1xuXG4gICAgdGhpcy5taXRlckxpbWl0XyA9IG9wdGlvbnMubWl0ZXJMaW1pdDtcbiAgICAvKipcbiAgICAgKiBAcHJpdmF0ZVxuICAgICAqIEB0eXBlIHtudW1iZXJ8dW5kZWZpbmVkfVxuICAgICAqL1xuXG4gICAgdGhpcy53aWR0aF8gPSBvcHRpb25zLndpZHRoO1xuICB9XG4gIC8qKlxuICAgKiBDbG9uZXMgdGhlIHN0eWxlLlxuICAgKiBAcmV0dXJuIHtTdHJva2V9IFRoZSBjbG9uZWQgc3R5bGUuXG4gICAqIEBhcGlcbiAgICovXG5cblxuICBTdHJva2UucHJvdG90eXBlLmNsb25lID0gZnVuY3Rpb24gKCkge1xuICAgIHZhciBjb2xvciA9IHRoaXMuZ2V0Q29sb3IoKTtcbiAgICByZXR1cm4gbmV3IFN0cm9rZSh7XG4gICAgICBjb2xvcjogQXJyYXkuaXNBcnJheShjb2xvcikgPyBjb2xvci5zbGljZSgpIDogY29sb3IgfHwgdW5kZWZpbmVkLFxuICAgICAgbGluZUNhcDogdGhpcy5nZXRMaW5lQ2FwKCksXG4gICAgICBsaW5lRGFzaDogdGhpcy5nZXRMaW5lRGFzaCgpID8gdGhpcy5nZXRMaW5lRGFzaCgpLnNsaWNlKCkgOiB1bmRlZmluZWQsXG4gICAgICBsaW5lRGFzaE9mZnNldDogdGhpcy5nZXRMaW5lRGFzaE9mZnNldCgpLFxuICAgICAgbGluZUpvaW46IHRoaXMuZ2V0TGluZUpvaW4oKSxcbiAgICAgIG1pdGVyTGltaXQ6IHRoaXMuZ2V0TWl0ZXJMaW1pdCgpLFxuICAgICAgd2lkdGg6IHRoaXMuZ2V0V2lkdGgoKVxuICAgIH0pO1xuICB9O1xuICAvKipcbiAgICogR2V0IHRoZSBzdHJva2UgY29sb3IuXG4gICAqIEByZXR1cm4ge2ltcG9ydChcIi4uL2NvbG9yLmpzXCIpLkNvbG9yfGltcG9ydChcIi4uL2NvbG9ybGlrZS5qc1wiKS5Db2xvckxpa2V9IENvbG9yLlxuICAgKiBAYXBpXG4gICAqL1xuXG5cbiAgU3Ryb2tlLnByb3RvdHlwZS5nZXRDb2xvciA9IGZ1bmN0aW9uICgpIHtcbiAgICByZXR1cm4gdGhpcy5jb2xvcl87XG4gIH07XG4gIC8qKlxuICAgKiBHZXQgdGhlIGxpbmUgY2FwIHR5cGUgZm9yIHRoZSBzdHJva2UuXG4gICAqIEByZXR1cm4ge0NhbnZhc0xpbmVDYXB8dW5kZWZpbmVkfSBMaW5lIGNhcC5cbiAgICogQGFwaVxuICAgKi9cblxuXG4gIFN0cm9rZS5wcm90b3R5cGUuZ2V0TGluZUNhcCA9IGZ1bmN0aW9uICgpIHtcbiAgICByZXR1cm4gdGhpcy5saW5lQ2FwXztcbiAgfTtcbiAgLyoqXG4gICAqIEdldCB0aGUgbGluZSBkYXNoIHN0eWxlIGZvciB0aGUgc3Ryb2tlLlxuICAgKiBAcmV0dXJuIHtBcnJheTxudW1iZXI+fSBMaW5lIGRhc2guXG4gICAqIEBhcGlcbiAgICovXG5cblxuICBTdHJva2UucHJvdG90eXBlLmdldExpbmVEYXNoID0gZnVuY3Rpb24gKCkge1xuICAgIHJldHVybiB0aGlzLmxpbmVEYXNoXztcbiAgfTtcbiAgLyoqXG4gICAqIEdldCB0aGUgbGluZSBkYXNoIG9mZnNldCBmb3IgdGhlIHN0cm9rZS5cbiAgICogQHJldHVybiB7bnVtYmVyfHVuZGVmaW5lZH0gTGluZSBkYXNoIG9mZnNldC5cbiAgICogQGFwaVxuICAgKi9cblxuXG4gIFN0cm9rZS5wcm90b3R5cGUuZ2V0TGluZURhc2hPZmZzZXQgPSBmdW5jdGlvbiAoKSB7XG4gICAgcmV0dXJuIHRoaXMubGluZURhc2hPZmZzZXRfO1xuICB9O1xuICAvKipcbiAgICogR2V0IHRoZSBsaW5lIGpvaW4gdHlwZSBmb3IgdGhlIHN0cm9rZS5cbiAgICogQHJldHVybiB7Q2FudmFzTGluZUpvaW58dW5kZWZpbmVkfSBMaW5lIGpvaW4uXG4gICAqIEBhcGlcbiAgICovXG5cblxuICBTdHJva2UucHJvdG90eXBlLmdldExpbmVKb2luID0gZnVuY3Rpb24gKCkge1xuICAgIHJldHVybiB0aGlzLmxpbmVKb2luXztcbiAgfTtcbiAgLyoqXG4gICAqIEdldCB0aGUgbWl0ZXIgbGltaXQgZm9yIHRoZSBzdHJva2UuXG4gICAqIEByZXR1cm4ge251bWJlcnx1bmRlZmluZWR9IE1pdGVyIGxpbWl0LlxuICAgKiBAYXBpXG4gICAqL1xuXG5cbiAgU3Ryb2tlLnByb3RvdHlwZS5nZXRNaXRlckxpbWl0ID0gZnVuY3Rpb24gKCkge1xuICAgIHJldHVybiB0aGlzLm1pdGVyTGltaXRfO1xuICB9O1xuICAvKipcbiAgICogR2V0IHRoZSBzdHJva2Ugd2lkdGguXG4gICAqIEByZXR1cm4ge251bWJlcnx1bmRlZmluZWR9IFdpZHRoLlxuICAgKiBAYXBpXG4gICAqL1xuXG5cbiAgU3Ryb2tlLnByb3RvdHlwZS5nZXRXaWR0aCA9IGZ1bmN0aW9uICgpIHtcbiAgICByZXR1cm4gdGhpcy53aWR0aF87XG4gIH07XG4gIC8qKlxuICAgKiBTZXQgdGhlIGNvbG9yLlxuICAgKlxuICAgKiBAcGFyYW0ge2ltcG9ydChcIi4uL2NvbG9yLmpzXCIpLkNvbG9yfGltcG9ydChcIi4uL2NvbG9ybGlrZS5qc1wiKS5Db2xvckxpa2V9IGNvbG9yIENvbG9yLlxuICAgKiBAYXBpXG4gICAqL1xuXG5cbiAgU3Ryb2tlLnByb3RvdHlwZS5zZXRDb2xvciA9IGZ1bmN0aW9uIChjb2xvcikge1xuICAgIHRoaXMuY29sb3JfID0gY29sb3I7XG4gIH07XG4gIC8qKlxuICAgKiBTZXQgdGhlIGxpbmUgY2FwLlxuICAgKlxuICAgKiBAcGFyYW0ge0NhbnZhc0xpbmVDYXB8dW5kZWZpbmVkfSBsaW5lQ2FwIExpbmUgY2FwLlxuICAgKiBAYXBpXG4gICAqL1xuXG5cbiAgU3Ryb2tlLnByb3RvdHlwZS5zZXRMaW5lQ2FwID0gZnVuY3Rpb24gKGxpbmVDYXApIHtcbiAgICB0aGlzLmxpbmVDYXBfID0gbGluZUNhcDtcbiAgfTtcbiAgLyoqXG4gICAqIFNldCB0aGUgbGluZSBkYXNoLlxuICAgKlxuICAgKiBQbGVhc2Ugbm90ZSB0aGF0IEludGVybmV0IEV4cGxvcmVyIDEwIGFuZCBsb3dlciBbZG8gbm90IHN1cHBvcnRdW21kbl0gdGhlXG4gICAqIGBzZXRMaW5lRGFzaGAgbWV0aG9kIG9uIHRoZSBgQ2FudmFzUmVuZGVyaW5nQ29udGV4dDJEYCBhbmQgdGhlcmVmb3JlIHRoaXNcbiAgICogcHJvcGVydHkgd2lsbCBoYXZlIG5vIHZpc3VhbCBlZmZlY3QgaW4gdGhlc2UgYnJvd3NlcnMuXG4gICAqXG4gICAqIFttZG5dOiBodHRwczovL2RldmVsb3Blci5tb3ppbGxhLm9yZy9lbi1VUy9kb2NzL1dlYi9BUEkvQ2FudmFzUmVuZGVyaW5nQ29udGV4dDJEL3NldExpbmVEYXNoI0Jyb3dzZXJfY29tcGF0aWJpbGl0eVxuICAgKlxuICAgKiBAcGFyYW0ge0FycmF5PG51bWJlcj59IGxpbmVEYXNoIExpbmUgZGFzaC5cbiAgICogQGFwaVxuICAgKi9cblxuXG4gIFN0cm9rZS5wcm90b3R5cGUuc2V0TGluZURhc2ggPSBmdW5jdGlvbiAobGluZURhc2gpIHtcbiAgICB0aGlzLmxpbmVEYXNoXyA9IGxpbmVEYXNoO1xuICB9O1xuICAvKipcbiAgICogU2V0IHRoZSBsaW5lIGRhc2ggb2Zmc2V0LlxuICAgKlxuICAgKiBAcGFyYW0ge251bWJlcnx1bmRlZmluZWR9IGxpbmVEYXNoT2Zmc2V0IExpbmUgZGFzaCBvZmZzZXQuXG4gICAqIEBhcGlcbiAgICovXG5cblxuICBTdHJva2UucHJvdG90eXBlLnNldExpbmVEYXNoT2Zmc2V0ID0gZnVuY3Rpb24gKGxpbmVEYXNoT2Zmc2V0KSB7XG4gICAgdGhpcy5saW5lRGFzaE9mZnNldF8gPSBsaW5lRGFzaE9mZnNldDtcbiAgfTtcbiAgLyoqXG4gICAqIFNldCB0aGUgbGluZSBqb2luLlxuICAgKlxuICAgKiBAcGFyYW0ge0NhbnZhc0xpbmVKb2lufHVuZGVmaW5lZH0gbGluZUpvaW4gTGluZSBqb2luLlxuICAgKiBAYXBpXG4gICAqL1xuXG5cbiAgU3Ryb2tlLnByb3RvdHlwZS5zZXRMaW5lSm9pbiA9IGZ1bmN0aW9uIChsaW5lSm9pbikge1xuICAgIHRoaXMubGluZUpvaW5fID0gbGluZUpvaW47XG4gIH07XG4gIC8qKlxuICAgKiBTZXQgdGhlIG1pdGVyIGxpbWl0LlxuICAgKlxuICAgKiBAcGFyYW0ge251bWJlcnx1bmRlZmluZWR9IG1pdGVyTGltaXQgTWl0ZXIgbGltaXQuXG4gICAqIEBhcGlcbiAgICovXG5cblxuICBTdHJva2UucHJvdG90eXBlLnNldE1pdGVyTGltaXQgPSBmdW5jdGlvbiAobWl0ZXJMaW1pdCkge1xuICAgIHRoaXMubWl0ZXJMaW1pdF8gPSBtaXRlckxpbWl0O1xuICB9O1xuICAvKipcbiAgICogU2V0IHRoZSB3aWR0aC5cbiAgICpcbiAgICogQHBhcmFtIHtudW1iZXJ8dW5kZWZpbmVkfSB3aWR0aCBXaWR0aC5cbiAgICogQGFwaVxuICAgKi9cblxuXG4gIFN0cm9rZS5wcm90b3R5cGUuc2V0V2lkdGggPSBmdW5jdGlvbiAod2lkdGgpIHtcbiAgICB0aGlzLndpZHRoXyA9IHdpZHRoO1xuICB9O1xuXG4gIHJldHVybiBTdHJva2U7XG59KCk7XG5cbmV4cG9ydCBkZWZhdWx0IFN0cm9rZTsiLCIvKipcbiAqIEBtb2R1bGUgb2wvc3R5bGUvU3R5bGVcbiAqL1xuaW1wb3J0IENpcmNsZVN0eWxlIGZyb20gJy4vQ2lyY2xlLmpzJztcbmltcG9ydCBGaWxsIGZyb20gJy4vRmlsbC5qcyc7XG5pbXBvcnQgR2VvbWV0cnlUeXBlIGZyb20gJy4uL2dlb20vR2VvbWV0cnlUeXBlLmpzJztcbmltcG9ydCBTdHJva2UgZnJvbSAnLi9TdHJva2UuanMnO1xuaW1wb3J0IHsgYXNzZXJ0IH0gZnJvbSAnLi4vYXNzZXJ0cy5qcyc7XG4vKipcbiAqIEEgZnVuY3Rpb24gdGhhdCB0YWtlcyBhbiB7QGxpbmsgbW9kdWxlOm9sL0ZlYXR1cmV9IGFuZCBhIGB7bnVtYmVyfWBcbiAqIHJlcHJlc2VudGluZyB0aGUgdmlldydzIHJlc29sdXRpb24uIFRoZSBmdW5jdGlvbiBzaG91bGQgcmV0dXJuIGFcbiAqIHtAbGluayBtb2R1bGU6b2wvc3R5bGUvU3R5bGV9IG9yIGFuIGFycmF5IG9mIHRoZW0uIFRoaXMgd2F5IGUuZy4gYVxuICogdmVjdG9yIGxheWVyIGNhbiBiZSBzdHlsZWQuIElmIHRoZSBmdW5jdGlvbiByZXR1cm5zIGB1bmRlZmluZWRgLCB0aGVcbiAqIGZlYXR1cmUgd2lsbCBub3QgYmUgcmVuZGVyZWQuXG4gKlxuICogQHR5cGVkZWYge2Z1bmN0aW9uKGltcG9ydChcIi4uL0ZlYXR1cmUuanNcIikuRmVhdHVyZUxpa2UsIG51bWJlcik6KFN0eWxlfEFycmF5PFN0eWxlPnx2b2lkKX0gU3R5bGVGdW5jdGlvblxuICovXG5cbi8qKlxuICogQSB7QGxpbmsgU3R5bGV9LCBhbiBhcnJheSBvZiB7QGxpbmsgU3R5bGV9LCBvciBhIHtAbGluayBTdHlsZUZ1bmN0aW9ufS5cbiAqIEB0eXBlZGVmIHtTdHlsZXxBcnJheTxTdHlsZT58U3R5bGVGdW5jdGlvbn0gU3R5bGVMaWtlXG4gKi9cblxuLyoqXG4gKiBBIGZ1bmN0aW9uIHRoYXQgdGFrZXMgYW4ge0BsaW5rIG1vZHVsZTpvbC9GZWF0dXJlfSBhcyBhcmd1bWVudCBhbmQgcmV0dXJucyBhblxuICoge0BsaW5rIG1vZHVsZTpvbC9nZW9tL0dlb21ldHJ5fSB0aGF0IHdpbGwgYmUgcmVuZGVyZWQgYW5kIHN0eWxlZCBmb3IgdGhlIGZlYXR1cmUuXG4gKlxuICogQHR5cGVkZWYge2Z1bmN0aW9uKGltcG9ydChcIi4uL0ZlYXR1cmUuanNcIikuRmVhdHVyZUxpa2UpOlxuICogICAgIChpbXBvcnQoXCIuLi9nZW9tL0dlb21ldHJ5LmpzXCIpLmRlZmF1bHR8aW1wb3J0KFwiLi4vcmVuZGVyL0ZlYXR1cmUuanNcIikuZGVmYXVsdHx1bmRlZmluZWQpfSBHZW9tZXRyeUZ1bmN0aW9uXG4gKi9cblxuLyoqXG4gKiBDdXN0b20gcmVuZGVyZXIgZnVuY3Rpb24uIFRha2VzIHR3byBhcmd1bWVudHM6XG4gKlxuICogMS4gVGhlIHBpeGVsIGNvb3JkaW5hdGVzIG9mIHRoZSBnZW9tZXRyeSBpbiBHZW9KU09OIG5vdGF0aW9uLlxuICogMi4gVGhlIHtAbGluayBtb2R1bGU6b2wvcmVuZGVyflN0YXRlfSBvZiB0aGUgbGF5ZXIgcmVuZGVyZXIuXG4gKlxuICogQHR5cGVkZWYge2Z1bmN0aW9uKChpbXBvcnQoXCIuLi9jb29yZGluYXRlLmpzXCIpLkNvb3JkaW5hdGV8QXJyYXk8aW1wb3J0KFwiLi4vY29vcmRpbmF0ZS5qc1wiKS5Db29yZGluYXRlPnxBcnJheTxBcnJheTxpbXBvcnQoXCIuLi9jb29yZGluYXRlLmpzXCIpLkNvb3JkaW5hdGU+PiksaW1wb3J0KFwiLi4vcmVuZGVyLmpzXCIpLlN0YXRlKTogdm9pZH1cbiAqIFJlbmRlckZ1bmN0aW9uXG4gKi9cblxuLyoqXG4gKiBAdHlwZWRlZiB7T2JqZWN0fSBPcHRpb25zXG4gKiBAcHJvcGVydHkge3N0cmluZ3xpbXBvcnQoXCIuLi9nZW9tL0dlb21ldHJ5LmpzXCIpLmRlZmF1bHR8R2VvbWV0cnlGdW5jdGlvbn0gW2dlb21ldHJ5XSBGZWF0dXJlIHByb3BlcnR5IG9yIGdlb21ldHJ5XG4gKiBvciBmdW5jdGlvbiByZXR1cm5pbmcgYSBnZW9tZXRyeSB0byByZW5kZXIgZm9yIHRoaXMgc3R5bGUuXG4gKiBAcHJvcGVydHkge2ltcG9ydChcIi4vRmlsbC5qc1wiKS5kZWZhdWx0fSBbZmlsbF0gRmlsbCBzdHlsZS5cbiAqIEBwcm9wZXJ0eSB7aW1wb3J0KFwiLi9JbWFnZS5qc1wiKS5kZWZhdWx0fSBbaW1hZ2VdIEltYWdlIHN0eWxlLlxuICogQHByb3BlcnR5IHtSZW5kZXJGdW5jdGlvbn0gW3JlbmRlcmVyXSBDdXN0b20gcmVuZGVyZXIuIFdoZW4gY29uZmlndXJlZCwgYGZpbGxgLCBgc3Ryb2tlYCBhbmQgYGltYWdlYCB3aWxsIGJlXG4gKiBpZ25vcmVkLCBhbmQgdGhlIHByb3ZpZGVkIGZ1bmN0aW9uIHdpbGwgYmUgY2FsbGVkIHdpdGggZWFjaCByZW5kZXIgZnJhbWUgZm9yIGVhY2ggZ2VvbWV0cnkuXG4gKiBAcHJvcGVydHkge2ltcG9ydChcIi4vU3Ryb2tlLmpzXCIpLmRlZmF1bHR9IFtzdHJva2VdIFN0cm9rZSBzdHlsZS5cbiAqIEBwcm9wZXJ0eSB7aW1wb3J0KFwiLi9UZXh0LmpzXCIpLmRlZmF1bHR9IFt0ZXh0XSBUZXh0IHN0eWxlLlxuICogQHByb3BlcnR5IHtudW1iZXJ9IFt6SW5kZXhdIFogaW5kZXguXG4gKi9cblxuLyoqXG4gKiBAY2xhc3NkZXNjXG4gKiBDb250YWluZXIgZm9yIHZlY3RvciBmZWF0dXJlIHJlbmRlcmluZyBzdHlsZXMuIEFueSBjaGFuZ2VzIG1hZGUgdG8gdGhlIHN0eWxlXG4gKiBvciBpdHMgY2hpbGRyZW4gdGhyb3VnaCBgc2V0KigpYCBtZXRob2RzIHdpbGwgbm90IHRha2UgZWZmZWN0IHVudGlsIHRoZVxuICogZmVhdHVyZSBvciBsYXllciB0aGF0IHVzZXMgdGhlIHN0eWxlIGlzIHJlLXJlbmRlcmVkLlxuICpcbiAqICMjIEZlYXR1cmUgc3R5bGVzXG4gKlxuICogSWYgbm8gc3R5bGUgaXMgZGVmaW5lZCwgdGhlIGZvbGxvd2luZyBkZWZhdWx0IHN0eWxlIGlzIHVzZWQ6XG4gKiBgYGBqc1xuICogIGltcG9ydCB7RmlsbCwgU3Ryb2tlLCBDaXJjbGUsIFN0eWxlfSBmcm9tICdvbC9zdHlsZSc7XG4gKlxuICogIHZhciBmaWxsID0gbmV3IEZpbGwoe1xuICogICAgY29sb3I6ICdyZ2JhKDI1NSwyNTUsMjU1LDAuNCknXG4gKiAgfSk7XG4gKiAgdmFyIHN0cm9rZSA9IG5ldyBTdHJva2Uoe1xuICogICAgY29sb3I6ICcjMzM5OUNDJyxcbiAqICAgIHdpZHRoOiAxLjI1XG4gKiAgfSk7XG4gKiAgdmFyIHN0eWxlcyA9IFtcbiAqICAgIG5ldyBTdHlsZSh7XG4gKiAgICAgIGltYWdlOiBuZXcgQ2lyY2xlKHtcbiAqICAgICAgICBmaWxsOiBmaWxsLFxuICogICAgICAgIHN0cm9rZTogc3Ryb2tlLFxuICogICAgICAgIHJhZGl1czogNVxuICogICAgICB9KSxcbiAqICAgICAgZmlsbDogZmlsbCxcbiAqICAgICAgc3Ryb2tlOiBzdHJva2VcbiAqICAgIH0pXG4gKiAgXTtcbiAqIGBgYFxuICpcbiAqIEEgc2VwYXJhdGUgZWRpdGluZyBzdHlsZSBoYXMgdGhlIGZvbGxvd2luZyBkZWZhdWx0czpcbiAqIGBgYGpzXG4gKiAgaW1wb3J0IHtGaWxsLCBTdHJva2UsIENpcmNsZSwgU3R5bGV9IGZyb20gJ29sL3N0eWxlJztcbiAqICBpbXBvcnQgR2VvbWV0cnlUeXBlIGZyb20gJ29sL2dlb20vR2VvbWV0cnlUeXBlJztcbiAqXG4gKiAgdmFyIHdoaXRlID0gWzI1NSwgMjU1LCAyNTUsIDFdO1xuICogIHZhciBibHVlID0gWzAsIDE1MywgMjU1LCAxXTtcbiAqICB2YXIgd2lkdGggPSAzO1xuICogIHN0eWxlc1tHZW9tZXRyeVR5cGUuUE9MWUdPTl0gPSBbXG4gKiAgICBuZXcgU3R5bGUoe1xuICogICAgICBmaWxsOiBuZXcgRmlsbCh7XG4gKiAgICAgICAgY29sb3I6IFsyNTUsIDI1NSwgMjU1LCAwLjVdXG4gKiAgICAgIH0pXG4gKiAgICB9KVxuICogIF07XG4gKiAgc3R5bGVzW0dlb21ldHJ5VHlwZS5NVUxUSV9QT0xZR09OXSA9XG4gKiAgICAgIHN0eWxlc1tHZW9tZXRyeVR5cGUuUE9MWUdPTl07XG4gKiAgc3R5bGVzW0dlb21ldHJ5VHlwZS5MSU5FX1NUUklOR10gPSBbXG4gKiAgICBuZXcgU3R5bGUoe1xuICogICAgICBzdHJva2U6IG5ldyBTdHJva2Uoe1xuICogICAgICAgIGNvbG9yOiB3aGl0ZSxcbiAqICAgICAgICB3aWR0aDogd2lkdGggKyAyXG4gKiAgICAgIH0pXG4gKiAgICB9KSxcbiAqICAgIG5ldyBTdHlsZSh7XG4gKiAgICAgIHN0cm9rZTogbmV3IFN0cm9rZSh7XG4gKiAgICAgICAgY29sb3I6IGJsdWUsXG4gKiAgICAgICAgd2lkdGg6IHdpZHRoXG4gKiAgICAgIH0pXG4gKiAgICB9KVxuICogIF07XG4gKiAgc3R5bGVzW0dlb21ldHJ5VHlwZS5NVUxUSV9MSU5FX1NUUklOR10gPVxuICogICAgICBzdHlsZXNbR2VvbWV0cnlUeXBlLkxJTkVfU1RSSU5HXTtcbiAqICBzdHlsZXNbR2VvbWV0cnlUeXBlLlBPSU5UXSA9IFtcbiAqICAgIG5ldyBTdHlsZSh7XG4gKiAgICAgIGltYWdlOiBuZXcgQ2lyY2xlKHtcbiAqICAgICAgICByYWRpdXM6IHdpZHRoICogMixcbiAqICAgICAgICBmaWxsOiBuZXcgRmlsbCh7XG4gKiAgICAgICAgICBjb2xvcjogYmx1ZVxuICogICAgICAgIH0pLFxuICogICAgICAgIHN0cm9rZTogbmV3IFN0cm9rZSh7XG4gKiAgICAgICAgICBjb2xvcjogd2hpdGUsXG4gKiAgICAgICAgICB3aWR0aDogd2lkdGggLyAyXG4gKiAgICAgICAgfSlcbiAqICAgICAgfSksXG4gKiAgICAgIHpJbmRleDogSW5maW5pdHlcbiAqICAgIH0pXG4gKiAgXTtcbiAqICBzdHlsZXNbR2VvbWV0cnlUeXBlLk1VTFRJX1BPSU5UXSA9XG4gKiAgICAgIHN0eWxlc1tHZW9tZXRyeVR5cGUuUE9JTlRdO1xuICogIHN0eWxlc1tHZW9tZXRyeVR5cGUuR0VPTUVUUllfQ09MTEVDVElPTl0gPVxuICogICAgICBzdHlsZXNbR2VvbWV0cnlUeXBlLlBPTFlHT05dLmNvbmNhdChcbiAqICAgICAgICAgIHN0eWxlc1tHZW9tZXRyeVR5cGUuTElORV9TVFJJTkddLFxuICogICAgICAgICAgc3R5bGVzW0dlb21ldHJ5VHlwZS5QT0lOVF1cbiAqICAgICAgKTtcbiAqIGBgYFxuICpcbiAqIEBhcGlcbiAqL1xuXG52YXIgU3R5bGUgPVxuLyoqIEBjbGFzcyAqL1xuZnVuY3Rpb24gKCkge1xuICAvKipcbiAgICogQHBhcmFtIHtPcHRpb25zPX0gb3B0X29wdGlvbnMgU3R5bGUgb3B0aW9ucy5cbiAgICovXG4gIGZ1bmN0aW9uIFN0eWxlKG9wdF9vcHRpb25zKSB7XG4gICAgdmFyIG9wdGlvbnMgPSBvcHRfb3B0aW9ucyB8fCB7fTtcbiAgICAvKipcbiAgICAgKiBAcHJpdmF0ZVxuICAgICAqIEB0eXBlIHtzdHJpbmd8aW1wb3J0KFwiLi4vZ2VvbS9HZW9tZXRyeS5qc1wiKS5kZWZhdWx0fEdlb21ldHJ5RnVuY3Rpb259XG4gICAgICovXG5cbiAgICB0aGlzLmdlb21ldHJ5XyA9IG51bGw7XG4gICAgLyoqXG4gICAgICogQHByaXZhdGVcbiAgICAgKiBAdHlwZSB7IUdlb21ldHJ5RnVuY3Rpb259XG4gICAgICovXG5cbiAgICB0aGlzLmdlb21ldHJ5RnVuY3Rpb25fID0gZGVmYXVsdEdlb21ldHJ5RnVuY3Rpb247XG5cbiAgICBpZiAob3B0aW9ucy5nZW9tZXRyeSAhPT0gdW5kZWZpbmVkKSB7XG4gICAgICB0aGlzLnNldEdlb21ldHJ5KG9wdGlvbnMuZ2VvbWV0cnkpO1xuICAgIH1cbiAgICAvKipcbiAgICAgKiBAcHJpdmF0ZVxuICAgICAqIEB0eXBlIHtpbXBvcnQoXCIuL0ZpbGwuanNcIikuZGVmYXVsdH1cbiAgICAgKi9cblxuXG4gICAgdGhpcy5maWxsXyA9IG9wdGlvbnMuZmlsbCAhPT0gdW5kZWZpbmVkID8gb3B0aW9ucy5maWxsIDogbnVsbDtcbiAgICAvKipcbiAgICAgKiBAcHJpdmF0ZVxuICAgICAqIEB0eXBlIHtpbXBvcnQoXCIuL0ltYWdlLmpzXCIpLmRlZmF1bHR9XG4gICAgICovXG5cbiAgICB0aGlzLmltYWdlXyA9IG9wdGlvbnMuaW1hZ2UgIT09IHVuZGVmaW5lZCA/IG9wdGlvbnMuaW1hZ2UgOiBudWxsO1xuICAgIC8qKlxuICAgICAqIEBwcml2YXRlXG4gICAgICogQHR5cGUge1JlbmRlckZ1bmN0aW9ufG51bGx9XG4gICAgICovXG5cbiAgICB0aGlzLnJlbmRlcmVyXyA9IG9wdGlvbnMucmVuZGVyZXIgIT09IHVuZGVmaW5lZCA/IG9wdGlvbnMucmVuZGVyZXIgOiBudWxsO1xuICAgIC8qKlxuICAgICAqIEBwcml2YXRlXG4gICAgICogQHR5cGUge2ltcG9ydChcIi4vU3Ryb2tlLmpzXCIpLmRlZmF1bHR9XG4gICAgICovXG5cbiAgICB0aGlzLnN0cm9rZV8gPSBvcHRpb25zLnN0cm9rZSAhPT0gdW5kZWZpbmVkID8gb3B0aW9ucy5zdHJva2UgOiBudWxsO1xuICAgIC8qKlxuICAgICAqIEBwcml2YXRlXG4gICAgICogQHR5cGUge2ltcG9ydChcIi4vVGV4dC5qc1wiKS5kZWZhdWx0fVxuICAgICAqL1xuXG4gICAgdGhpcy50ZXh0XyA9IG9wdGlvbnMudGV4dCAhPT0gdW5kZWZpbmVkID8gb3B0aW9ucy50ZXh0IDogbnVsbDtcbiAgICAvKipcbiAgICAgKiBAcHJpdmF0ZVxuICAgICAqIEB0eXBlIHtudW1iZXJ8dW5kZWZpbmVkfVxuICAgICAqL1xuXG4gICAgdGhpcy56SW5kZXhfID0gb3B0aW9ucy56SW5kZXg7XG4gIH1cbiAgLyoqXG4gICAqIENsb25lcyB0aGUgc3R5bGUuXG4gICAqIEByZXR1cm4ge1N0eWxlfSBUaGUgY2xvbmVkIHN0eWxlLlxuICAgKiBAYXBpXG4gICAqL1xuXG5cbiAgU3R5bGUucHJvdG90eXBlLmNsb25lID0gZnVuY3Rpb24gKCkge1xuICAgIHZhciBnZW9tZXRyeSA9IHRoaXMuZ2V0R2VvbWV0cnkoKTtcblxuICAgIGlmIChnZW9tZXRyeSAmJiB0eXBlb2YgZ2VvbWV0cnkgPT09ICdvYmplY3QnKSB7XG4gICAgICBnZW9tZXRyeSA9XG4gICAgICAvKiogQHR5cGUge2ltcG9ydChcIi4uL2dlb20vR2VvbWV0cnkuanNcIikuZGVmYXVsdH0gKi9cbiAgICAgIGdlb21ldHJ5LmNsb25lKCk7XG4gICAgfVxuXG4gICAgcmV0dXJuIG5ldyBTdHlsZSh7XG4gICAgICBnZW9tZXRyeTogZ2VvbWV0cnksXG4gICAgICBmaWxsOiB0aGlzLmdldEZpbGwoKSA/IHRoaXMuZ2V0RmlsbCgpLmNsb25lKCkgOiB1bmRlZmluZWQsXG4gICAgICBpbWFnZTogdGhpcy5nZXRJbWFnZSgpID8gdGhpcy5nZXRJbWFnZSgpLmNsb25lKCkgOiB1bmRlZmluZWQsXG4gICAgICBzdHJva2U6IHRoaXMuZ2V0U3Ryb2tlKCkgPyB0aGlzLmdldFN0cm9rZSgpLmNsb25lKCkgOiB1bmRlZmluZWQsXG4gICAgICB0ZXh0OiB0aGlzLmdldFRleHQoKSA/IHRoaXMuZ2V0VGV4dCgpLmNsb25lKCkgOiB1bmRlZmluZWQsXG4gICAgICB6SW5kZXg6IHRoaXMuZ2V0WkluZGV4KClcbiAgICB9KTtcbiAgfTtcbiAgLyoqXG4gICAqIEdldCB0aGUgY3VzdG9tIHJlbmRlcmVyIGZ1bmN0aW9uIHRoYXQgd2FzIGNvbmZpZ3VyZWQgd2l0aFxuICAgKiB7QGxpbmsgI3NldFJlbmRlcmVyfSBvciB0aGUgYHJlbmRlcmVyYCBjb25zdHJ1Y3RvciBvcHRpb24uXG4gICAqIEByZXR1cm4ge1JlbmRlckZ1bmN0aW9ufG51bGx9IEN1c3RvbSByZW5kZXJlciBmdW5jdGlvbi5cbiAgICogQGFwaVxuICAgKi9cblxuXG4gIFN0eWxlLnByb3RvdHlwZS5nZXRSZW5kZXJlciA9IGZ1bmN0aW9uICgpIHtcbiAgICByZXR1cm4gdGhpcy5yZW5kZXJlcl87XG4gIH07XG4gIC8qKlxuICAgKiBTZXRzIGEgY3VzdG9tIHJlbmRlcmVyIGZ1bmN0aW9uIGZvciB0aGlzIHN0eWxlLiBXaGVuIHNldCwgYGZpbGxgLCBgc3Ryb2tlYFxuICAgKiBhbmQgYGltYWdlYCBvcHRpb25zIG9mIHRoZSBzdHlsZSB3aWxsIGJlIGlnbm9yZWQuXG4gICAqIEBwYXJhbSB7UmVuZGVyRnVuY3Rpb258bnVsbH0gcmVuZGVyZXIgQ3VzdG9tIHJlbmRlcmVyIGZ1bmN0aW9uLlxuICAgKiBAYXBpXG4gICAqL1xuXG5cbiAgU3R5bGUucHJvdG90eXBlLnNldFJlbmRlcmVyID0gZnVuY3Rpb24gKHJlbmRlcmVyKSB7XG4gICAgdGhpcy5yZW5kZXJlcl8gPSByZW5kZXJlcjtcbiAgfTtcbiAgLyoqXG4gICAqIEdldCB0aGUgZ2VvbWV0cnkgdG8gYmUgcmVuZGVyZWQuXG4gICAqIEByZXR1cm4ge3N0cmluZ3xpbXBvcnQoXCIuLi9nZW9tL0dlb21ldHJ5LmpzXCIpLmRlZmF1bHR8R2VvbWV0cnlGdW5jdGlvbn1cbiAgICogRmVhdHVyZSBwcm9wZXJ0eSBvciBnZW9tZXRyeSBvciBmdW5jdGlvbiB0aGF0IHJldHVybnMgdGhlIGdlb21ldHJ5IHRoYXQgd2lsbFxuICAgKiBiZSByZW5kZXJlZCB3aXRoIHRoaXMgc3R5bGUuXG4gICAqIEBhcGlcbiAgICovXG5cblxuICBTdHlsZS5wcm90b3R5cGUuZ2V0R2VvbWV0cnkgPSBmdW5jdGlvbiAoKSB7XG4gICAgcmV0dXJuIHRoaXMuZ2VvbWV0cnlfO1xuICB9O1xuICAvKipcbiAgICogR2V0IHRoZSBmdW5jdGlvbiB1c2VkIHRvIGdlbmVyYXRlIGEgZ2VvbWV0cnkgZm9yIHJlbmRlcmluZy5cbiAgICogQHJldHVybiB7IUdlb21ldHJ5RnVuY3Rpb259IEZ1bmN0aW9uIHRoYXQgaXMgY2FsbGVkIHdpdGggYSBmZWF0dXJlXG4gICAqIGFuZCByZXR1cm5zIHRoZSBnZW9tZXRyeSB0byByZW5kZXIgaW5zdGVhZCBvZiB0aGUgZmVhdHVyZSdzIGdlb21ldHJ5LlxuICAgKiBAYXBpXG4gICAqL1xuXG5cbiAgU3R5bGUucHJvdG90eXBlLmdldEdlb21ldHJ5RnVuY3Rpb24gPSBmdW5jdGlvbiAoKSB7XG4gICAgcmV0dXJuIHRoaXMuZ2VvbWV0cnlGdW5jdGlvbl87XG4gIH07XG4gIC8qKlxuICAgKiBHZXQgdGhlIGZpbGwgc3R5bGUuXG4gICAqIEByZXR1cm4ge2ltcG9ydChcIi4vRmlsbC5qc1wiKS5kZWZhdWx0fSBGaWxsIHN0eWxlLlxuICAgKiBAYXBpXG4gICAqL1xuXG5cbiAgU3R5bGUucHJvdG90eXBlLmdldEZpbGwgPSBmdW5jdGlvbiAoKSB7XG4gICAgcmV0dXJuIHRoaXMuZmlsbF87XG4gIH07XG4gIC8qKlxuICAgKiBTZXQgdGhlIGZpbGwgc3R5bGUuXG4gICAqIEBwYXJhbSB7aW1wb3J0KFwiLi9GaWxsLmpzXCIpLmRlZmF1bHR9IGZpbGwgRmlsbCBzdHlsZS5cbiAgICogQGFwaVxuICAgKi9cblxuXG4gIFN0eWxlLnByb3RvdHlwZS5zZXRGaWxsID0gZnVuY3Rpb24gKGZpbGwpIHtcbiAgICB0aGlzLmZpbGxfID0gZmlsbDtcbiAgfTtcbiAgLyoqXG4gICAqIEdldCB0aGUgaW1hZ2Ugc3R5bGUuXG4gICAqIEByZXR1cm4ge2ltcG9ydChcIi4vSW1hZ2UuanNcIikuZGVmYXVsdH0gSW1hZ2Ugc3R5bGUuXG4gICAqIEBhcGlcbiAgICovXG5cblxuICBTdHlsZS5wcm90b3R5cGUuZ2V0SW1hZ2UgPSBmdW5jdGlvbiAoKSB7XG4gICAgcmV0dXJuIHRoaXMuaW1hZ2VfO1xuICB9O1xuICAvKipcbiAgICogU2V0IHRoZSBpbWFnZSBzdHlsZS5cbiAgICogQHBhcmFtIHtpbXBvcnQoXCIuL0ltYWdlLmpzXCIpLmRlZmF1bHR9IGltYWdlIEltYWdlIHN0eWxlLlxuICAgKiBAYXBpXG4gICAqL1xuXG5cbiAgU3R5bGUucHJvdG90eXBlLnNldEltYWdlID0gZnVuY3Rpb24gKGltYWdlKSB7XG4gICAgdGhpcy5pbWFnZV8gPSBpbWFnZTtcbiAgfTtcbiAgLyoqXG4gICAqIEdldCB0aGUgc3Ryb2tlIHN0eWxlLlxuICAgKiBAcmV0dXJuIHtpbXBvcnQoXCIuL1N0cm9rZS5qc1wiKS5kZWZhdWx0fSBTdHJva2Ugc3R5bGUuXG4gICAqIEBhcGlcbiAgICovXG5cblxuICBTdHlsZS5wcm90b3R5cGUuZ2V0U3Ryb2tlID0gZnVuY3Rpb24gKCkge1xuICAgIHJldHVybiB0aGlzLnN0cm9rZV87XG4gIH07XG4gIC8qKlxuICAgKiBTZXQgdGhlIHN0cm9rZSBzdHlsZS5cbiAgICogQHBhcmFtIHtpbXBvcnQoXCIuL1N0cm9rZS5qc1wiKS5kZWZhdWx0fSBzdHJva2UgU3Ryb2tlIHN0eWxlLlxuICAgKiBAYXBpXG4gICAqL1xuXG5cbiAgU3R5bGUucHJvdG90eXBlLnNldFN0cm9rZSA9IGZ1bmN0aW9uIChzdHJva2UpIHtcbiAgICB0aGlzLnN0cm9rZV8gPSBzdHJva2U7XG4gIH07XG4gIC8qKlxuICAgKiBHZXQgdGhlIHRleHQgc3R5bGUuXG4gICAqIEByZXR1cm4ge2ltcG9ydChcIi4vVGV4dC5qc1wiKS5kZWZhdWx0fSBUZXh0IHN0eWxlLlxuICAgKiBAYXBpXG4gICAqL1xuXG5cbiAgU3R5bGUucHJvdG90eXBlLmdldFRleHQgPSBmdW5jdGlvbiAoKSB7XG4gICAgcmV0dXJuIHRoaXMudGV4dF87XG4gIH07XG4gIC8qKlxuICAgKiBTZXQgdGhlIHRleHQgc3R5bGUuXG4gICAqIEBwYXJhbSB7aW1wb3J0KFwiLi9UZXh0LmpzXCIpLmRlZmF1bHR9IHRleHQgVGV4dCBzdHlsZS5cbiAgICogQGFwaVxuICAgKi9cblxuXG4gIFN0eWxlLnByb3RvdHlwZS5zZXRUZXh0ID0gZnVuY3Rpb24gKHRleHQpIHtcbiAgICB0aGlzLnRleHRfID0gdGV4dDtcbiAgfTtcbiAgLyoqXG4gICAqIEdldCB0aGUgei1pbmRleCBmb3IgdGhlIHN0eWxlLlxuICAgKiBAcmV0dXJuIHtudW1iZXJ8dW5kZWZpbmVkfSBaSW5kZXguXG4gICAqIEBhcGlcbiAgICovXG5cblxuICBTdHlsZS5wcm90b3R5cGUuZ2V0WkluZGV4ID0gZnVuY3Rpb24gKCkge1xuICAgIHJldHVybiB0aGlzLnpJbmRleF87XG4gIH07XG4gIC8qKlxuICAgKiBTZXQgYSBnZW9tZXRyeSB0aGF0IGlzIHJlbmRlcmVkIGluc3RlYWQgb2YgdGhlIGZlYXR1cmUncyBnZW9tZXRyeS5cbiAgICpcbiAgICogQHBhcmFtIHtzdHJpbmd8aW1wb3J0KFwiLi4vZ2VvbS9HZW9tZXRyeS5qc1wiKS5kZWZhdWx0fEdlb21ldHJ5RnVuY3Rpb259IGdlb21ldHJ5XG4gICAqICAgICBGZWF0dXJlIHByb3BlcnR5IG9yIGdlb21ldHJ5IG9yIGZ1bmN0aW9uIHJldHVybmluZyBhIGdlb21ldHJ5IHRvIHJlbmRlclxuICAgKiAgICAgZm9yIHRoaXMgc3R5bGUuXG4gICAqIEBhcGlcbiAgICovXG5cblxuICBTdHlsZS5wcm90b3R5cGUuc2V0R2VvbWV0cnkgPSBmdW5jdGlvbiAoZ2VvbWV0cnkpIHtcbiAgICBpZiAodHlwZW9mIGdlb21ldHJ5ID09PSAnZnVuY3Rpb24nKSB7XG4gICAgICB0aGlzLmdlb21ldHJ5RnVuY3Rpb25fID0gZ2VvbWV0cnk7XG4gICAgfSBlbHNlIGlmICh0eXBlb2YgZ2VvbWV0cnkgPT09ICdzdHJpbmcnKSB7XG4gICAgICB0aGlzLmdlb21ldHJ5RnVuY3Rpb25fID0gZnVuY3Rpb24gKGZlYXR1cmUpIHtcbiAgICAgICAgcmV0dXJuIChcbiAgICAgICAgICAvKiogQHR5cGUge2ltcG9ydChcIi4uL2dlb20vR2VvbWV0cnkuanNcIikuZGVmYXVsdH0gKi9cbiAgICAgICAgICBmZWF0dXJlLmdldChnZW9tZXRyeSlcbiAgICAgICAgKTtcbiAgICAgIH07XG4gICAgfSBlbHNlIGlmICghZ2VvbWV0cnkpIHtcbiAgICAgIHRoaXMuZ2VvbWV0cnlGdW5jdGlvbl8gPSBkZWZhdWx0R2VvbWV0cnlGdW5jdGlvbjtcbiAgICB9IGVsc2UgaWYgKGdlb21ldHJ5ICE9PSB1bmRlZmluZWQpIHtcbiAgICAgIHRoaXMuZ2VvbWV0cnlGdW5jdGlvbl8gPSBmdW5jdGlvbiAoKSB7XG4gICAgICAgIHJldHVybiAoXG4gICAgICAgICAgLyoqIEB0eXBlIHtpbXBvcnQoXCIuLi9nZW9tL0dlb21ldHJ5LmpzXCIpLmRlZmF1bHR9ICovXG4gICAgICAgICAgZ2VvbWV0cnlcbiAgICAgICAgKTtcbiAgICAgIH07XG4gICAgfVxuXG4gICAgdGhpcy5nZW9tZXRyeV8gPSBnZW9tZXRyeTtcbiAgfTtcbiAgLyoqXG4gICAqIFNldCB0aGUgei1pbmRleC5cbiAgICpcbiAgICogQHBhcmFtIHtudW1iZXJ8dW5kZWZpbmVkfSB6SW5kZXggWkluZGV4LlxuICAgKiBAYXBpXG4gICAqL1xuXG5cbiAgU3R5bGUucHJvdG90eXBlLnNldFpJbmRleCA9IGZ1bmN0aW9uICh6SW5kZXgpIHtcbiAgICB0aGlzLnpJbmRleF8gPSB6SW5kZXg7XG4gIH07XG5cbiAgcmV0dXJuIFN0eWxlO1xufSgpO1xuLyoqXG4gKiBDb252ZXJ0IHRoZSBwcm92aWRlZCBvYmplY3QgaW50byBhIHN0eWxlIGZ1bmN0aW9uLiAgRnVuY3Rpb25zIHBhc3NlZCB0aHJvdWdoXG4gKiB1bmNoYW5nZWQuICBBcnJheXMgb2YgU3R5bGUgb3Igc2luZ2xlIHN0eWxlIG9iamVjdHMgd3JhcHBlZCBpbiBhXG4gKiBuZXcgc3R5bGUgZnVuY3Rpb24uXG4gKiBAcGFyYW0ge1N0eWxlRnVuY3Rpb258QXJyYXk8U3R5bGU+fFN0eWxlfSBvYmpcbiAqICAgICBBIHN0eWxlIGZ1bmN0aW9uLCBhIHNpbmdsZSBzdHlsZSwgb3IgYW4gYXJyYXkgb2Ygc3R5bGVzLlxuICogQHJldHVybiB7U3R5bGVGdW5jdGlvbn0gQSBzdHlsZSBmdW5jdGlvbi5cbiAqL1xuXG5cbmV4cG9ydCBmdW5jdGlvbiB0b0Z1bmN0aW9uKG9iaikge1xuICB2YXIgc3R5bGVGdW5jdGlvbjtcblxuICBpZiAodHlwZW9mIG9iaiA9PT0gJ2Z1bmN0aW9uJykge1xuICAgIHN0eWxlRnVuY3Rpb24gPSBvYmo7XG4gIH0gZWxzZSB7XG4gICAgLyoqXG4gICAgICogQHR5cGUge0FycmF5PFN0eWxlPn1cbiAgICAgKi9cbiAgICB2YXIgc3R5bGVzXzE7XG5cbiAgICBpZiAoQXJyYXkuaXNBcnJheShvYmopKSB7XG4gICAgICBzdHlsZXNfMSA9IG9iajtcbiAgICB9IGVsc2Uge1xuICAgICAgYXNzZXJ0KHR5cGVvZlxuICAgICAgLyoqIEB0eXBlIHs/fSAqL1xuICAgICAgb2JqLmdldFpJbmRleCA9PT0gJ2Z1bmN0aW9uJywgNDEpOyAvLyBFeHBlY3RlZCBhbiBgU3R5bGVgIG9yIGFuIGFycmF5IG9mIGBTdHlsZWBcblxuICAgICAgdmFyIHN0eWxlID1cbiAgICAgIC8qKiBAdHlwZSB7U3R5bGV9ICovXG4gICAgICBvYmo7XG4gICAgICBzdHlsZXNfMSA9IFtzdHlsZV07XG4gICAgfVxuXG4gICAgc3R5bGVGdW5jdGlvbiA9IGZ1bmN0aW9uIHN0eWxlRnVuY3Rpb24oKSB7XG4gICAgICByZXR1cm4gc3R5bGVzXzE7XG4gICAgfTtcbiAgfVxuXG4gIHJldHVybiBzdHlsZUZ1bmN0aW9uO1xufVxuLyoqXG4gKiBAdHlwZSB7QXJyYXk8U3R5bGU+fVxuICovXG5cbnZhciBkZWZhdWx0U3R5bGVzID0gbnVsbDtcbi8qKlxuICogQHBhcmFtIHtpbXBvcnQoXCIuLi9GZWF0dXJlLmpzXCIpLkZlYXR1cmVMaWtlfSBmZWF0dXJlIEZlYXR1cmUuXG4gKiBAcGFyYW0ge251bWJlcn0gcmVzb2x1dGlvbiBSZXNvbHV0aW9uLlxuICogQHJldHVybiB7QXJyYXk8U3R5bGU+fSBTdHlsZS5cbiAqL1xuXG5leHBvcnQgZnVuY3Rpb24gY3JlYXRlRGVmYXVsdFN0eWxlKGZlYXR1cmUsIHJlc29sdXRpb24pIHtcbiAgLy8gV2UgZG9uJ3QgdXNlIGFuIGltbWVkaWF0ZWx5LWludm9rZWQgZnVuY3Rpb25cbiAgLy8gYW5kIGEgY2xvc3VyZSBzbyB3ZSBkb24ndCBnZXQgYW4gZXJyb3IgYXQgc2NyaXB0IGV2YWx1YXRpb24gdGltZSBpblxuICAvLyBicm93c2VycyB0aGF0IGRvIG5vdCBzdXBwb3J0IENhbnZhcy4gKGltcG9ydChcIi4vQ2lyY2xlLmpzXCIpLkNpcmNsZVN0eWxlIGRvZXNcbiAgLy8gY2FudmFzLmdldENvbnRleHQoJzJkJykgYXQgY29uc3RydWN0aW9uIHRpbWUsIHdoaWNoIHdpbGwgY2F1c2UgYW4uZXJyb3JcbiAgLy8gaW4gc3VjaCBicm93c2Vycy4pXG4gIGlmICghZGVmYXVsdFN0eWxlcykge1xuICAgIHZhciBmaWxsID0gbmV3IEZpbGwoe1xuICAgICAgY29sb3I6ICdyZ2JhKDI1NSwyNTUsMjU1LDAuNCknXG4gICAgfSk7XG4gICAgdmFyIHN0cm9rZSA9IG5ldyBTdHJva2Uoe1xuICAgICAgY29sb3I6ICcjMzM5OUNDJyxcbiAgICAgIHdpZHRoOiAxLjI1XG4gICAgfSk7XG4gICAgZGVmYXVsdFN0eWxlcyA9IFtuZXcgU3R5bGUoe1xuICAgICAgaW1hZ2U6IG5ldyBDaXJjbGVTdHlsZSh7XG4gICAgICAgIGZpbGw6IGZpbGwsXG4gICAgICAgIHN0cm9rZTogc3Ryb2tlLFxuICAgICAgICByYWRpdXM6IDVcbiAgICAgIH0pLFxuICAgICAgZmlsbDogZmlsbCxcbiAgICAgIHN0cm9rZTogc3Ryb2tlXG4gICAgfSldO1xuICB9XG5cbiAgcmV0dXJuIGRlZmF1bHRTdHlsZXM7XG59XG4vKipcbiAqIERlZmF1bHQgc3R5bGVzIGZvciBlZGl0aW5nIGZlYXR1cmVzLlxuICogQHJldHVybiB7T2JqZWN0PGltcG9ydChcIi4uL2dlb20vR2VvbWV0cnlUeXBlLmpzXCIpLmRlZmF1bHQsIEFycmF5PFN0eWxlPj59IFN0eWxlc1xuICovXG5cbmV4cG9ydCBmdW5jdGlvbiBjcmVhdGVFZGl0aW5nU3R5bGUoKSB7XG4gIC8qKiBAdHlwZSB7T2JqZWN0PGltcG9ydChcIi4uL2dlb20vR2VvbWV0cnlUeXBlLmpzXCIpLmRlZmF1bHQsIEFycmF5PFN0eWxlPj59ICovXG4gIHZhciBzdHlsZXMgPSB7fTtcbiAgdmFyIHdoaXRlID0gWzI1NSwgMjU1LCAyNTUsIDFdO1xuICB2YXIgYmx1ZSA9IFswLCAxNTMsIDI1NSwgMV07XG4gIHZhciB3aWR0aCA9IDM7XG4gIHN0eWxlc1tHZW9tZXRyeVR5cGUuUE9MWUdPTl0gPSBbbmV3IFN0eWxlKHtcbiAgICBmaWxsOiBuZXcgRmlsbCh7XG4gICAgICBjb2xvcjogWzI1NSwgMjU1LCAyNTUsIDAuNV1cbiAgICB9KVxuICB9KV07XG4gIHN0eWxlc1tHZW9tZXRyeVR5cGUuTVVMVElfUE9MWUdPTl0gPSBzdHlsZXNbR2VvbWV0cnlUeXBlLlBPTFlHT05dO1xuICBzdHlsZXNbR2VvbWV0cnlUeXBlLkxJTkVfU1RSSU5HXSA9IFtuZXcgU3R5bGUoe1xuICAgIHN0cm9rZTogbmV3IFN0cm9rZSh7XG4gICAgICBjb2xvcjogd2hpdGUsXG4gICAgICB3aWR0aDogd2lkdGggKyAyXG4gICAgfSlcbiAgfSksIG5ldyBTdHlsZSh7XG4gICAgc3Ryb2tlOiBuZXcgU3Ryb2tlKHtcbiAgICAgIGNvbG9yOiBibHVlLFxuICAgICAgd2lkdGg6IHdpZHRoXG4gICAgfSlcbiAgfSldO1xuICBzdHlsZXNbR2VvbWV0cnlUeXBlLk1VTFRJX0xJTkVfU1RSSU5HXSA9IHN0eWxlc1tHZW9tZXRyeVR5cGUuTElORV9TVFJJTkddO1xuICBzdHlsZXNbR2VvbWV0cnlUeXBlLkNJUkNMRV0gPSBzdHlsZXNbR2VvbWV0cnlUeXBlLlBPTFlHT05dLmNvbmNhdChzdHlsZXNbR2VvbWV0cnlUeXBlLkxJTkVfU1RSSU5HXSk7XG4gIHN0eWxlc1tHZW9tZXRyeVR5cGUuUE9JTlRdID0gW25ldyBTdHlsZSh7XG4gICAgaW1hZ2U6IG5ldyBDaXJjbGVTdHlsZSh7XG4gICAgICByYWRpdXM6IHdpZHRoICogMixcbiAgICAgIGZpbGw6IG5ldyBGaWxsKHtcbiAgICAgICAgY29sb3I6IGJsdWVcbiAgICAgIH0pLFxuICAgICAgc3Ryb2tlOiBuZXcgU3Ryb2tlKHtcbiAgICAgICAgY29sb3I6IHdoaXRlLFxuICAgICAgICB3aWR0aDogd2lkdGggLyAyXG4gICAgICB9KVxuICAgIH0pLFxuICAgIHpJbmRleDogSW5maW5pdHlcbiAgfSldO1xuICBzdHlsZXNbR2VvbWV0cnlUeXBlLk1VTFRJX1BPSU5UXSA9IHN0eWxlc1tHZW9tZXRyeVR5cGUuUE9JTlRdO1xuICBzdHlsZXNbR2VvbWV0cnlUeXBlLkdFT01FVFJZX0NPTExFQ1RJT05dID0gc3R5bGVzW0dlb21ldHJ5VHlwZS5QT0xZR09OXS5jb25jYXQoc3R5bGVzW0dlb21ldHJ5VHlwZS5MSU5FX1NUUklOR10sIHN0eWxlc1tHZW9tZXRyeVR5cGUuUE9JTlRdKTtcbiAgcmV0dXJuIHN0eWxlcztcbn1cbi8qKlxuICogRnVuY3Rpb24gdGhhdCBpcyBjYWxsZWQgd2l0aCBhIGZlYXR1cmUgYW5kIHJldHVybnMgaXRzIGRlZmF1bHQgZ2VvbWV0cnkuXG4gKiBAcGFyYW0ge2ltcG9ydChcIi4uL0ZlYXR1cmUuanNcIikuRmVhdHVyZUxpa2V9IGZlYXR1cmUgRmVhdHVyZSB0byBnZXQgdGhlIGdlb21ldHJ5IGZvci5cbiAqIEByZXR1cm4ge2ltcG9ydChcIi4uL2dlb20vR2VvbWV0cnkuanNcIikuZGVmYXVsdHxpbXBvcnQoXCIuLi9yZW5kZXIvRmVhdHVyZS5qc1wiKS5kZWZhdWx0fHVuZGVmaW5lZH0gR2VvbWV0cnkgdG8gcmVuZGVyLlxuICovXG5cbmZ1bmN0aW9uIGRlZmF1bHRHZW9tZXRyeUZ1bmN0aW9uKGZlYXR1cmUpIHtcbiAgcmV0dXJuIGZlYXR1cmUuZ2V0R2VvbWV0cnkoKTtcbn1cblxuZXhwb3J0IGRlZmF1bHQgU3R5bGU7IiwidmFyIF9fZXh0ZW5kcyA9IHRoaXMgJiYgdGhpcy5fX2V4dGVuZHMgfHwgZnVuY3Rpb24gKCkge1xuICB2YXIgX2V4dGVuZFN0YXRpY3MgPSBmdW5jdGlvbiBleHRlbmRTdGF0aWNzKGQsIGIpIHtcbiAgICBfZXh0ZW5kU3RhdGljcyA9IE9iamVjdC5zZXRQcm90b3R5cGVPZiB8fCB7XG4gICAgICBfX3Byb3RvX186IFtdXG4gICAgfSBpbnN0YW5jZW9mIEFycmF5ICYmIGZ1bmN0aW9uIChkLCBiKSB7XG4gICAgICBkLl9fcHJvdG9fXyA9IGI7XG4gICAgfSB8fCBmdW5jdGlvbiAoZCwgYikge1xuICAgICAgZm9yICh2YXIgcCBpbiBiKSB7XG4gICAgICAgIGlmIChPYmplY3QucHJvdG90eXBlLmhhc093blByb3BlcnR5LmNhbGwoYiwgcCkpIGRbcF0gPSBiW3BdO1xuICAgICAgfVxuICAgIH07XG5cbiAgICByZXR1cm4gX2V4dGVuZFN0YXRpY3MoZCwgYik7XG4gIH07XG5cbiAgcmV0dXJuIGZ1bmN0aW9uIChkLCBiKSB7XG4gICAgX2V4dGVuZFN0YXRpY3MoZCwgYik7XG5cbiAgICBmdW5jdGlvbiBfXygpIHtcbiAgICAgIHRoaXMuY29uc3RydWN0b3IgPSBkO1xuICAgIH1cblxuICAgIGQucHJvdG90eXBlID0gYiA9PT0gbnVsbCA/IE9iamVjdC5jcmVhdGUoYikgOiAoX18ucHJvdG90eXBlID0gYi5wcm90b3R5cGUsIG5ldyBfXygpKTtcbiAgfTtcbn0oKTtcbi8qKlxuICogQG1vZHVsZSBvbC9sYXllci9CYXNlVmVjdG9yXG4gKi9cblxuXG5pbXBvcnQgTGF5ZXIgZnJvbSAnLi9MYXllci5qcyc7XG5pbXBvcnQgUkJ1c2ggZnJvbSAncmJ1c2gnO1xuaW1wb3J0IHsgYXNzaWduIH0gZnJvbSAnLi4vb2JqLmpzJztcbmltcG9ydCB7IGNyZWF0ZURlZmF1bHRTdHlsZSwgdG9GdW5jdGlvbiBhcyB0b1N0eWxlRnVuY3Rpb24gfSBmcm9tICcuLi9zdHlsZS9TdHlsZS5qcyc7XG4vKipcbiAqIEB0eXBlZGVmIHtPYmplY3R9IE9wdGlvbnNcbiAqIEBwcm9wZXJ0eSB7c3RyaW5nfSBbY2xhc3NOYW1lPSdvbC1sYXllciddIEEgQ1NTIGNsYXNzIG5hbWUgdG8gc2V0IHRvIHRoZSBsYXllciBlbGVtZW50LlxuICogQHByb3BlcnR5IHtudW1iZXJ9IFtvcGFjaXR5PTFdIE9wYWNpdHkgKDAsIDEpLlxuICogQHByb3BlcnR5IHtib29sZWFufSBbdmlzaWJsZT10cnVlXSBWaXNpYmlsaXR5LlxuICogQHByb3BlcnR5IHtpbXBvcnQoXCIuLi9leHRlbnQuanNcIikuRXh0ZW50fSBbZXh0ZW50XSBUaGUgYm91bmRpbmcgZXh0ZW50IGZvciBsYXllciByZW5kZXJpbmcuICBUaGUgbGF5ZXIgd2lsbCBub3QgYmVcbiAqIHJlbmRlcmVkIG91dHNpZGUgb2YgdGhpcyBleHRlbnQuXG4gKiBAcHJvcGVydHkge251bWJlcn0gW3pJbmRleF0gVGhlIHotaW5kZXggZm9yIGxheWVyIHJlbmRlcmluZy4gIEF0IHJlbmRlcmluZyB0aW1lLCB0aGUgbGF5ZXJzXG4gKiB3aWxsIGJlIG9yZGVyZWQsIGZpcnN0IGJ5IFotaW5kZXggYW5kIHRoZW4gYnkgcG9zaXRpb24uIFdoZW4gYHVuZGVmaW5lZGAsIGEgYHpJbmRleGAgb2YgMCBpcyBhc3N1bWVkXG4gKiBmb3IgbGF5ZXJzIHRoYXQgYXJlIGFkZGVkIHRvIHRoZSBtYXAncyBgbGF5ZXJzYCBjb2xsZWN0aW9uLCBvciBgSW5maW5pdHlgIHdoZW4gdGhlIGxheWVyJ3MgYHNldE1hcCgpYFxuICogbWV0aG9kIHdhcyB1c2VkLlxuICogQHByb3BlcnR5IHtudW1iZXJ9IFttaW5SZXNvbHV0aW9uXSBUaGUgbWluaW11bSByZXNvbHV0aW9uIChpbmNsdXNpdmUpIGF0IHdoaWNoIHRoaXMgbGF5ZXIgd2lsbCBiZVxuICogdmlzaWJsZS5cbiAqIEBwcm9wZXJ0eSB7bnVtYmVyfSBbbWF4UmVzb2x1dGlvbl0gVGhlIG1heGltdW0gcmVzb2x1dGlvbiAoZXhjbHVzaXZlKSBiZWxvdyB3aGljaCB0aGlzIGxheWVyIHdpbGxcbiAqIGJlIHZpc2libGUuXG4gKiBAcHJvcGVydHkge251bWJlcn0gW21pblpvb21dIFRoZSBtaW5pbXVtIHZpZXcgem9vbSBsZXZlbCAoZXhjbHVzaXZlKSBhYm92ZSB3aGljaCB0aGlzIGxheWVyIHdpbGwgYmVcbiAqIHZpc2libGUuXG4gKiBAcHJvcGVydHkge251bWJlcn0gW21heFpvb21dIFRoZSBtYXhpbXVtIHZpZXcgem9vbSBsZXZlbCAoaW5jbHVzaXZlKSBhdCB3aGljaCB0aGlzIGxheWVyIHdpbGxcbiAqIGJlIHZpc2libGUuXG4gKiBAcHJvcGVydHkge2ltcG9ydChcIi4uL3JlbmRlci5qc1wiKS5PcmRlckZ1bmN0aW9ufSBbcmVuZGVyT3JkZXJdIFJlbmRlciBvcmRlci4gRnVuY3Rpb24gdG8gYmUgdXNlZCB3aGVuIHNvcnRpbmdcbiAqIGZlYXR1cmVzIGJlZm9yZSByZW5kZXJpbmcuIEJ5IGRlZmF1bHQgZmVhdHVyZXMgYXJlIGRyYXduIGluIHRoZSBvcmRlciB0aGF0IHRoZXkgYXJlIGNyZWF0ZWQuIFVzZVxuICogYG51bGxgIHRvIGF2b2lkIHRoZSBzb3J0LCBidXQgZ2V0IGFuIHVuZGVmaW5lZCBkcmF3IG9yZGVyLlxuICogQHByb3BlcnR5IHtudW1iZXJ9IFtyZW5kZXJCdWZmZXI9MTAwXSBUaGUgYnVmZmVyIGluIHBpeGVscyBhcm91bmQgdGhlIHZpZXdwb3J0IGV4dGVudCB1c2VkIGJ5IHRoZVxuICogcmVuZGVyZXIgd2hlbiBnZXR0aW5nIGZlYXR1cmVzIGZyb20gdGhlIHZlY3RvciBzb3VyY2UgZm9yIHRoZSByZW5kZXJpbmcgb3IgaGl0LWRldGVjdGlvbi5cbiAqIFJlY29tbWVuZGVkIHZhbHVlOiB0aGUgc2l6ZSBvZiB0aGUgbGFyZ2VzdCBzeW1ib2wsIGxpbmUgd2lkdGggb3IgbGFiZWwuXG4gKiBAcHJvcGVydHkge2ltcG9ydChcIi4uL3NvdXJjZS9WZWN0b3IuanNcIikuZGVmYXVsdH0gW3NvdXJjZV0gU291cmNlLlxuICogQHByb3BlcnR5IHtpbXBvcnQoXCIuLi9QbHVnZ2FibGVNYXAuanNcIikuZGVmYXVsdH0gW21hcF0gU2V0cyB0aGUgbGF5ZXIgYXMgb3ZlcmxheSBvbiBhIG1hcC4gVGhlIG1hcCB3aWxsIG5vdCBtYW5hZ2VcbiAqIHRoaXMgbGF5ZXIgaW4gaXRzIGxheWVycyBjb2xsZWN0aW9uLCBhbmQgdGhlIGxheWVyIHdpbGwgYmUgcmVuZGVyZWQgb24gdG9wLiBUaGlzIGlzIHVzZWZ1bCBmb3JcbiAqIHRlbXBvcmFyeSBsYXllcnMuIFRoZSBzdGFuZGFyZCB3YXkgdG8gYWRkIGEgbGF5ZXIgdG8gYSBtYXAgYW5kIGhhdmUgaXQgbWFuYWdlZCBieSB0aGUgbWFwIGlzIHRvXG4gKiB1c2Uge0BsaW5rIG1vZHVsZTpvbC9NYXAjYWRkTGF5ZXJ9LlxuICogQHByb3BlcnR5IHtib29sZWFufSBbZGVjbHV0dGVyPWZhbHNlXSBEZWNsdXR0ZXIgaW1hZ2VzIGFuZCB0ZXh0LiBEZWNsdXR0ZXJpbmcgaXMgYXBwbGllZCB0byBhbGxcbiAqIGltYWdlIGFuZCB0ZXh0IHN0eWxlcyBvZiBhbGwgVmVjdG9yIGFuZCBWZWN0b3JUaWxlIGxheWVycyB0aGF0IGhhdmUgc2V0IHRoaXMgdG8gYHRydWVgLiBUaGUgcHJpb3JpdHlcbiAqIGlzIGRlZmluZWQgYnkgdGhlIHotaW5kZXggb2YgdGhlIGxheWVyLCB0aGUgYHpJbmRleGAgb2YgdGhlIHN0eWxlIGFuZCB0aGUgcmVuZGVyIG9yZGVyIG9mIGZlYXR1cmVzLlxuICogSGlnaGVyIHotaW5kZXggbWVhbnMgaGlnaGVyIHByaW9yaXR5LiBXaXRoaW4gdGhlIHNhbWUgei1pbmRleCwgYSBmZWF0dXJlIHJlbmRlcmVkIGJlZm9yZSBhbm90aGVyIGhhc1xuICogaGlnaGVyIHByaW9yaXR5LlxuICogQHByb3BlcnR5IHtpbXBvcnQoXCIuLi9zdHlsZS9TdHlsZS5qc1wiKS5TdHlsZUxpa2V8bnVsbH0gW3N0eWxlXSBMYXllciBzdHlsZS4gV2hlbiBzZXQgdG8gYG51bGxgLCBvbmx5XG4gKiBmZWF0dXJlcyB0aGF0IGhhdmUgdGhlaXIgb3duIHN0eWxlIHdpbGwgYmUgcmVuZGVyZWQuIFNlZSB7QGxpbmsgbW9kdWxlOm9sL3N0eWxlfSBmb3IgZGVmYXVsdCBzdHlsZVxuICogd2hpY2ggd2lsbCBiZSB1c2VkIGlmIHRoaXMgaXMgbm90IHNldC5cbiAqIEBwcm9wZXJ0eSB7Ym9vbGVhbn0gW3VwZGF0ZVdoaWxlQW5pbWF0aW5nPWZhbHNlXSBXaGVuIHNldCB0byBgdHJ1ZWAsIGZlYXR1cmUgYmF0Y2hlcyB3aWxsXG4gKiBiZSByZWNyZWF0ZWQgZHVyaW5nIGFuaW1hdGlvbnMuIFRoaXMgbWVhbnMgdGhhdCBubyB2ZWN0b3JzIHdpbGwgYmUgc2hvd24gY2xpcHBlZCwgYnV0IHRoZVxuICogc2V0dGluZyB3aWxsIGhhdmUgYSBwZXJmb3JtYW5jZSBpbXBhY3QgZm9yIGxhcmdlIGFtb3VudHMgb2YgdmVjdG9yIGRhdGEuIFdoZW4gc2V0IHRvIGBmYWxzZWAsXG4gKiBiYXRjaGVzIHdpbGwgYmUgcmVjcmVhdGVkIHdoZW4gbm8gYW5pbWF0aW9uIGlzIGFjdGl2ZS5cbiAqIEBwcm9wZXJ0eSB7Ym9vbGVhbn0gW3VwZGF0ZVdoaWxlSW50ZXJhY3Rpbmc9ZmFsc2VdIFdoZW4gc2V0IHRvIGB0cnVlYCwgZmVhdHVyZSBiYXRjaGVzIHdpbGxcbiAqIGJlIHJlY3JlYXRlZCBkdXJpbmcgaW50ZXJhY3Rpb25zLiBTZWUgYWxzbyBgdXBkYXRlV2hpbGVBbmltYXRpbmdgLlxuICovXG5cbi8qKlxuICogQGVudW0ge3N0cmluZ31cbiAqIEBwcml2YXRlXG4gKi9cblxudmFyIFByb3BlcnR5ID0ge1xuICBSRU5ERVJfT1JERVI6ICdyZW5kZXJPcmRlcidcbn07XG4vKipcbiAqIEBjbGFzc2Rlc2NcbiAqIFZlY3RvciBkYXRhIHRoYXQgaXMgcmVuZGVyZWQgY2xpZW50LXNpZGUuXG4gKiBOb3RlIHRoYXQgYW55IHByb3BlcnR5IHNldCBpbiB0aGUgb3B0aW9ucyBpcyBzZXQgYXMgYSB7QGxpbmsgbW9kdWxlOm9sL09iamVjdH5CYXNlT2JqZWN0fVxuICogcHJvcGVydHkgb24gdGhlIGxheWVyIG9iamVjdDsgZm9yIGV4YW1wbGUsIHNldHRpbmcgYHRpdGxlOiAnTXkgVGl0bGUnYCBpbiB0aGVcbiAqIG9wdGlvbnMgbWVhbnMgdGhhdCBgdGl0bGVgIGlzIG9ic2VydmFibGUsIGFuZCBoYXMgZ2V0L3NldCBhY2Nlc3NvcnMuXG4gKlxuICogQHRlbXBsYXRlIHtpbXBvcnQoXCIuLi9zb3VyY2UvVmVjdG9yLmpzXCIpLmRlZmF1bHR8aW1wb3J0KFwiLi4vc291cmNlL1ZlY3RvclRpbGUuanNcIikuZGVmYXVsdH0gVmVjdG9yU291cmNlVHlwZVxuICogQGV4dGVuZHMge0xheWVyPFZlY3RvclNvdXJjZVR5cGU+fVxuICogQGFwaVxuICovXG5cbnZhciBCYXNlVmVjdG9yTGF5ZXIgPVxuLyoqIEBjbGFzcyAqL1xuZnVuY3Rpb24gKF9zdXBlcikge1xuICBfX2V4dGVuZHMoQmFzZVZlY3RvckxheWVyLCBfc3VwZXIpO1xuICAvKipcbiAgICogQHBhcmFtIHtPcHRpb25zPX0gb3B0X29wdGlvbnMgT3B0aW9ucy5cbiAgICovXG5cblxuICBmdW5jdGlvbiBCYXNlVmVjdG9yTGF5ZXIob3B0X29wdGlvbnMpIHtcbiAgICB2YXIgX3RoaXMgPSB0aGlzO1xuXG4gICAgdmFyIG9wdGlvbnMgPSBvcHRfb3B0aW9ucyA/IG9wdF9vcHRpb25zIDoge307XG4gICAgdmFyIGJhc2VPcHRpb25zID0gYXNzaWduKHt9LCBvcHRpb25zKTtcbiAgICBkZWxldGUgYmFzZU9wdGlvbnMuc3R5bGU7XG4gICAgZGVsZXRlIGJhc2VPcHRpb25zLnJlbmRlckJ1ZmZlcjtcbiAgICBkZWxldGUgYmFzZU9wdGlvbnMudXBkYXRlV2hpbGVBbmltYXRpbmc7XG4gICAgZGVsZXRlIGJhc2VPcHRpb25zLnVwZGF0ZVdoaWxlSW50ZXJhY3Rpbmc7XG4gICAgX3RoaXMgPSBfc3VwZXIuY2FsbCh0aGlzLCBiYXNlT3B0aW9ucykgfHwgdGhpcztcbiAgICAvKipcbiAgICAgKiBAcHJpdmF0ZVxuICAgICAqIEB0eXBlIHtib29sZWFufVxuICAgICAqL1xuXG4gICAgX3RoaXMuZGVjbHV0dGVyXyA9IG9wdGlvbnMuZGVjbHV0dGVyICE9PSB1bmRlZmluZWQgPyBvcHRpb25zLmRlY2x1dHRlciA6IGZhbHNlO1xuICAgIC8qKlxuICAgICAqIEB0eXBlIHtudW1iZXJ9XG4gICAgICogQHByaXZhdGVcbiAgICAgKi9cblxuICAgIF90aGlzLnJlbmRlckJ1ZmZlcl8gPSBvcHRpb25zLnJlbmRlckJ1ZmZlciAhPT0gdW5kZWZpbmVkID8gb3B0aW9ucy5yZW5kZXJCdWZmZXIgOiAxMDA7XG4gICAgLyoqXG4gICAgICogVXNlciBwcm92aWRlZCBzdHlsZS5cbiAgICAgKiBAdHlwZSB7aW1wb3J0KFwiLi4vc3R5bGUvU3R5bGUuanNcIikuU3R5bGVMaWtlfVxuICAgICAqIEBwcml2YXRlXG4gICAgICovXG5cbiAgICBfdGhpcy5zdHlsZV8gPSBudWxsO1xuICAgIC8qKlxuICAgICAqIFN0eWxlIGZ1bmN0aW9uIGZvciB1c2Ugd2l0aGluIHRoZSBsaWJyYXJ5LlxuICAgICAqIEB0eXBlIHtpbXBvcnQoXCIuLi9zdHlsZS9TdHlsZS5qc1wiKS5TdHlsZUZ1bmN0aW9ufHVuZGVmaW5lZH1cbiAgICAgKiBAcHJpdmF0ZVxuICAgICAqL1xuXG4gICAgX3RoaXMuc3R5bGVGdW5jdGlvbl8gPSB1bmRlZmluZWQ7XG5cbiAgICBfdGhpcy5zZXRTdHlsZShvcHRpb25zLnN0eWxlKTtcbiAgICAvKipcbiAgICAgKiBAdHlwZSB7Ym9vbGVhbn1cbiAgICAgKiBAcHJpdmF0ZVxuICAgICAqL1xuXG5cbiAgICBfdGhpcy51cGRhdGVXaGlsZUFuaW1hdGluZ18gPSBvcHRpb25zLnVwZGF0ZVdoaWxlQW5pbWF0aW5nICE9PSB1bmRlZmluZWQgPyBvcHRpb25zLnVwZGF0ZVdoaWxlQW5pbWF0aW5nIDogZmFsc2U7XG4gICAgLyoqXG4gICAgICogQHR5cGUge2Jvb2xlYW59XG4gICAgICogQHByaXZhdGVcbiAgICAgKi9cblxuICAgIF90aGlzLnVwZGF0ZVdoaWxlSW50ZXJhY3RpbmdfID0gb3B0aW9ucy51cGRhdGVXaGlsZUludGVyYWN0aW5nICE9PSB1bmRlZmluZWQgPyBvcHRpb25zLnVwZGF0ZVdoaWxlSW50ZXJhY3RpbmcgOiBmYWxzZTtcbiAgICByZXR1cm4gX3RoaXM7XG4gIH1cbiAgLyoqXG4gICAqIEByZXR1cm4ge2Jvb2xlYW59IERlY2x1dHRlci5cbiAgICovXG5cblxuICBCYXNlVmVjdG9yTGF5ZXIucHJvdG90eXBlLmdldERlY2x1dHRlciA9IGZ1bmN0aW9uICgpIHtcbiAgICByZXR1cm4gdGhpcy5kZWNsdXR0ZXJfO1xuICB9O1xuICAvKipcbiAgICogR2V0IHRoZSB0b3Btb3N0IGZlYXR1cmUgdGhhdCBpbnRlcnNlY3RzIHRoZSBnaXZlbiBwaXhlbCBvbiB0aGUgdmlld3BvcnQuIFJldHVybnMgYSBwcm9taXNlXG4gICAqIHRoYXQgcmVzb2x2ZXMgd2l0aCBhbiBhcnJheSBvZiBmZWF0dXJlcy4gVGhlIGFycmF5IHdpbGwgZWl0aGVyIGNvbnRhaW4gdGhlIHRvcG1vc3QgZmVhdHVyZVxuICAgKiB3aGVuIGEgaGl0IHdhcyBkZXRlY3RlZCwgb3IgaXQgd2lsbCBiZSBlbXB0eS5cbiAgICpcbiAgICogVGhlIGhpdCBkZXRlY3Rpb24gYWxnb3JpdGhtIHVzZWQgZm9yIHRoaXMgbWV0aG9kIGlzIG9wdGltaXplZCBmb3IgcGVyZm9ybWFuY2UsIGJ1dCBpcyBsZXNzXG4gICAqIGFjY3VyYXRlIHRoYW4gdGhlIG9uZSB1c2VkIGluIHtAbGluayBpbXBvcnQoXCIuLi9QbHVnZ2FibGVNYXAuanNcIikuZGVmYXVsdCNnZXRGZWF0dXJlc0F0UGl4ZWx9OiBUZXh0XG4gICAqIGlzIG5vdCBjb25zaWRlcmVkLCBhbmQgaWNvbnMgYXJlIG9ubHkgcmVwcmVzZW50ZWQgYnkgdGhlaXIgYm91bmRpbmcgYm94IGluc3RlYWQgb2YgdGhlIGV4YWN0XG4gICAqIGltYWdlLlxuICAgKlxuICAgKiBAcGFyYW0ge2ltcG9ydChcIi4uL3BpeGVsLmpzXCIpLlBpeGVsfSBwaXhlbCBQaXhlbC5cbiAgICogQHJldHVybiB7UHJvbWlzZTxBcnJheTxpbXBvcnQoXCIuLi9GZWF0dXJlXCIpLmRlZmF1bHQ+Pn0gUHJvbWlzZSB0aGF0IHJlc29sdmVzIHdpdGggYW4gYXJyYXkgb2YgZmVhdHVyZXMuXG4gICAqIEBhcGlcbiAgICovXG5cblxuICBCYXNlVmVjdG9yTGF5ZXIucHJvdG90eXBlLmdldEZlYXR1cmVzID0gZnVuY3Rpb24gKHBpeGVsKSB7XG4gICAgcmV0dXJuIF9zdXBlci5wcm90b3R5cGUuZ2V0RmVhdHVyZXMuY2FsbCh0aGlzLCBwaXhlbCk7XG4gIH07XG4gIC8qKlxuICAgKiBAcmV0dXJuIHtudW1iZXJ8dW5kZWZpbmVkfSBSZW5kZXIgYnVmZmVyLlxuICAgKi9cblxuXG4gIEJhc2VWZWN0b3JMYXllci5wcm90b3R5cGUuZ2V0UmVuZGVyQnVmZmVyID0gZnVuY3Rpb24gKCkge1xuICAgIHJldHVybiB0aGlzLnJlbmRlckJ1ZmZlcl87XG4gIH07XG4gIC8qKlxuICAgKiBAcmV0dXJuIHtmdW5jdGlvbihpbXBvcnQoXCIuLi9GZWF0dXJlLmpzXCIpLmRlZmF1bHQsIGltcG9ydChcIi4uL0ZlYXR1cmUuanNcIikuZGVmYXVsdCk6IG51bWJlcnxudWxsfHVuZGVmaW5lZH0gUmVuZGVyXG4gICAqICAgICBvcmRlci5cbiAgICovXG5cblxuICBCYXNlVmVjdG9yTGF5ZXIucHJvdG90eXBlLmdldFJlbmRlck9yZGVyID0gZnVuY3Rpb24gKCkge1xuICAgIHJldHVybiAoXG4gICAgICAvKiogQHR5cGUge2ltcG9ydChcIi4uL3JlbmRlci5qc1wiKS5PcmRlckZ1bmN0aW9ufG51bGx8dW5kZWZpbmVkfSAqL1xuICAgICAgdGhpcy5nZXQoUHJvcGVydHkuUkVOREVSX09SREVSKVxuICAgICk7XG4gIH07XG4gIC8qKlxuICAgKiBHZXQgdGhlIHN0eWxlIGZvciBmZWF0dXJlcy4gIFRoaXMgcmV0dXJucyB3aGF0ZXZlciB3YXMgcGFzc2VkIHRvIHRoZSBgc3R5bGVgXG4gICAqIG9wdGlvbiBhdCBjb25zdHJ1Y3Rpb24gb3IgdG8gdGhlIGBzZXRTdHlsZWAgbWV0aG9kLlxuICAgKiBAcmV0dXJuIHtpbXBvcnQoXCIuLi9zdHlsZS9TdHlsZS5qc1wiKS5TdHlsZUxpa2V8bnVsbHx1bmRlZmluZWR9IExheWVyIHN0eWxlLlxuICAgKiBAYXBpXG4gICAqL1xuXG5cbiAgQmFzZVZlY3RvckxheWVyLnByb3RvdHlwZS5nZXRTdHlsZSA9IGZ1bmN0aW9uICgpIHtcbiAgICByZXR1cm4gdGhpcy5zdHlsZV87XG4gIH07XG4gIC8qKlxuICAgKiBHZXQgdGhlIHN0eWxlIGZ1bmN0aW9uLlxuICAgKiBAcmV0dXJuIHtpbXBvcnQoXCIuLi9zdHlsZS9TdHlsZS5qc1wiKS5TdHlsZUZ1bmN0aW9ufHVuZGVmaW5lZH0gTGF5ZXIgc3R5bGUgZnVuY3Rpb24uXG4gICAqIEBhcGlcbiAgICovXG5cblxuICBCYXNlVmVjdG9yTGF5ZXIucHJvdG90eXBlLmdldFN0eWxlRnVuY3Rpb24gPSBmdW5jdGlvbiAoKSB7XG4gICAgcmV0dXJuIHRoaXMuc3R5bGVGdW5jdGlvbl87XG4gIH07XG4gIC8qKlxuICAgKiBAcmV0dXJuIHtib29sZWFufSBXaGV0aGVyIHRoZSByZW5kZXJlZCBsYXllciBzaG91bGQgYmUgdXBkYXRlZCB3aGlsZVxuICAgKiAgICAgYW5pbWF0aW5nLlxuICAgKi9cblxuXG4gIEJhc2VWZWN0b3JMYXllci5wcm90b3R5cGUuZ2V0VXBkYXRlV2hpbGVBbmltYXRpbmcgPSBmdW5jdGlvbiAoKSB7XG4gICAgcmV0dXJuIHRoaXMudXBkYXRlV2hpbGVBbmltYXRpbmdfO1xuICB9O1xuICAvKipcbiAgICogQHJldHVybiB7Ym9vbGVhbn0gV2hldGhlciB0aGUgcmVuZGVyZWQgbGF5ZXIgc2hvdWxkIGJlIHVwZGF0ZWQgd2hpbGVcbiAgICogICAgIGludGVyYWN0aW5nLlxuICAgKi9cblxuXG4gIEJhc2VWZWN0b3JMYXllci5wcm90b3R5cGUuZ2V0VXBkYXRlV2hpbGVJbnRlcmFjdGluZyA9IGZ1bmN0aW9uICgpIHtcbiAgICByZXR1cm4gdGhpcy51cGRhdGVXaGlsZUludGVyYWN0aW5nXztcbiAgfTtcbiAgLyoqXG4gICAqIFJlbmRlciBkZWNsdXR0ZXIgaXRlbXMgZm9yIHRoaXMgbGF5ZXJcbiAgICogQHBhcmFtIHtpbXBvcnQoXCIuLi9QbHVnZ2FibGVNYXAuanNcIikuRnJhbWVTdGF0ZX0gZnJhbWVTdGF0ZSBGcmFtZSBzdGF0ZS5cbiAgICovXG5cblxuICBCYXNlVmVjdG9yTGF5ZXIucHJvdG90eXBlLnJlbmRlckRlY2x1dHRlciA9IGZ1bmN0aW9uIChmcmFtZVN0YXRlKSB7XG4gICAgaWYgKCFmcmFtZVN0YXRlLmRlY2x1dHRlclRyZWUpIHtcbiAgICAgIGZyYW1lU3RhdGUuZGVjbHV0dGVyVHJlZSA9IG5ldyBSQnVzaCg5KTtcbiAgICB9XG4gICAgLyoqIEB0eXBlIHsqfSAqL1xuXG5cbiAgICB0aGlzLmdldFJlbmRlcmVyKCkucmVuZGVyRGVjbHV0dGVyKGZyYW1lU3RhdGUpO1xuICB9O1xuICAvKipcbiAgICogQHBhcmFtIHtpbXBvcnQoXCIuLi9yZW5kZXIuanNcIikuT3JkZXJGdW5jdGlvbnxudWxsfHVuZGVmaW5lZH0gcmVuZGVyT3JkZXJcbiAgICogICAgIFJlbmRlciBvcmRlci5cbiAgICovXG5cblxuICBCYXNlVmVjdG9yTGF5ZXIucHJvdG90eXBlLnNldFJlbmRlck9yZGVyID0gZnVuY3Rpb24gKHJlbmRlck9yZGVyKSB7XG4gICAgdGhpcy5zZXQoUHJvcGVydHkuUkVOREVSX09SREVSLCByZW5kZXJPcmRlcik7XG4gIH07XG4gIC8qKlxuICAgKiBTZXQgdGhlIHN0eWxlIGZvciBmZWF0dXJlcy4gIFRoaXMgY2FuIGJlIGEgc2luZ2xlIHN0eWxlIG9iamVjdCwgYW4gYXJyYXlcbiAgICogb2Ygc3R5bGVzLCBvciBhIGZ1bmN0aW9uIHRoYXQgdGFrZXMgYSBmZWF0dXJlIGFuZCByZXNvbHV0aW9uIGFuZCByZXR1cm5zXG4gICAqIGFuIGFycmF5IG9mIHN0eWxlcy4gSWYgc2V0IHRvIGBudWxsYCwgdGhlIGxheWVyIGhhcyBubyBzdHlsZSAoYSBgbnVsbGAgc3R5bGUpLFxuICAgKiBzbyBvbmx5IGZlYXR1cmVzIHRoYXQgaGF2ZSB0aGVpciBvd24gc3R5bGVzIHdpbGwgYmUgcmVuZGVyZWQgaW4gdGhlIGxheWVyLiBDYWxsXG4gICAqIGBzZXRTdHlsZSgpYCB3aXRob3V0IGFyZ3VtZW50cyB0byByZXNldCB0byB0aGUgZGVmYXVsdCBzdHlsZS4gU2VlXG4gICAqIHtAbGluayBtb2R1bGU6b2wvc3R5bGV9IGZvciBpbmZvcm1hdGlvbiBvbiB0aGUgZGVmYXVsdCBzdHlsZS5cbiAgICogQHBhcmFtIHsoaW1wb3J0KFwiLi4vc3R5bGUvU3R5bGUuanNcIikuU3R5bGVMaWtlfG51bGwpPX0gb3B0X3N0eWxlIExheWVyIHN0eWxlLlxuICAgKiBAYXBpXG4gICAqL1xuXG5cbiAgQmFzZVZlY3RvckxheWVyLnByb3RvdHlwZS5zZXRTdHlsZSA9IGZ1bmN0aW9uIChvcHRfc3R5bGUpIHtcbiAgICB0aGlzLnN0eWxlXyA9IG9wdF9zdHlsZSAhPT0gdW5kZWZpbmVkID8gb3B0X3N0eWxlIDogY3JlYXRlRGVmYXVsdFN0eWxlO1xuICAgIHRoaXMuc3R5bGVGdW5jdGlvbl8gPSBvcHRfc3R5bGUgPT09IG51bGwgPyB1bmRlZmluZWQgOiB0b1N0eWxlRnVuY3Rpb24odGhpcy5zdHlsZV8pO1xuICAgIHRoaXMuY2hhbmdlZCgpO1xuICB9O1xuXG4gIHJldHVybiBCYXNlVmVjdG9yTGF5ZXI7XG59KExheWVyKTtcblxuZXhwb3J0IGRlZmF1bHQgQmFzZVZlY3RvckxheWVyOyIsIi8qKlxuICogQG1vZHVsZSBvbC9yZW5kZXIvY2FudmFzL0luc3RydWN0aW9uXG4gKi9cblxuLyoqXG4gKiBAZW51bSB7bnVtYmVyfVxuICovXG52YXIgSW5zdHJ1Y3Rpb24gPSB7XG4gIEJFR0lOX0dFT01FVFJZOiAwLFxuICBCRUdJTl9QQVRIOiAxLFxuICBDSVJDTEU6IDIsXG4gIENMT1NFX1BBVEg6IDMsXG4gIENVU1RPTTogNCxcbiAgRFJBV19DSEFSUzogNSxcbiAgRFJBV19JTUFHRTogNixcbiAgRU5EX0dFT01FVFJZOiA3LFxuICBGSUxMOiA4LFxuICBNT1ZFX1RPX0xJTkVfVE86IDksXG4gIFNFVF9GSUxMX1NUWUxFOiAxMCxcbiAgU0VUX1NUUk9LRV9TVFlMRTogMTEsXG4gIFNUUk9LRTogMTJcbn07XG4vKipcbiAqIEB0eXBlIHtBcnJheTxJbnN0cnVjdGlvbj59XG4gKi9cblxuZXhwb3J0IHZhciBmaWxsSW5zdHJ1Y3Rpb24gPSBbSW5zdHJ1Y3Rpb24uRklMTF07XG4vKipcbiAqIEB0eXBlIHtBcnJheTxJbnN0cnVjdGlvbj59XG4gKi9cblxuZXhwb3J0IHZhciBzdHJva2VJbnN0cnVjdGlvbiA9IFtJbnN0cnVjdGlvbi5TVFJPS0VdO1xuLyoqXG4gKiBAdHlwZSB7QXJyYXk8SW5zdHJ1Y3Rpb24+fVxuICovXG5cbmV4cG9ydCB2YXIgYmVnaW5QYXRoSW5zdHJ1Y3Rpb24gPSBbSW5zdHJ1Y3Rpb24uQkVHSU5fUEFUSF07XG4vKipcbiAqIEB0eXBlIHtBcnJheTxJbnN0cnVjdGlvbj59XG4gKi9cblxuZXhwb3J0IHZhciBjbG9zZVBhdGhJbnN0cnVjdGlvbiA9IFtJbnN0cnVjdGlvbi5DTE9TRV9QQVRIXTtcbmV4cG9ydCBkZWZhdWx0IEluc3RydWN0aW9uOyIsIi8qKlxuICogQG1vZHVsZSBvbC9yZW5kZXIvVmVjdG9yQ29udGV4dFxuICovXG5cbi8qKlxuICogQGNsYXNzZGVzY1xuICogQ29udGV4dCBmb3IgZHJhd2luZyBnZW9tZXRyaWVzLiAgQSB2ZWN0b3IgY29udGV4dCBpcyBhdmFpbGFibGUgb24gcmVuZGVyXG4gKiBldmVudHMgYW5kIGRvZXMgbm90IG5lZWQgdG8gYmUgY29uc3RydWN0ZWQgZGlyZWN0bHkuXG4gKiBAYXBpXG4gKi9cbnZhciBWZWN0b3JDb250ZXh0ID1cbi8qKiBAY2xhc3MgKi9cbmZ1bmN0aW9uICgpIHtcbiAgZnVuY3Rpb24gVmVjdG9yQ29udGV4dCgpIHt9XG4gIC8qKlxuICAgKiBSZW5kZXIgYSBnZW9tZXRyeSB3aXRoIGEgY3VzdG9tIHJlbmRlcmVyLlxuICAgKlxuICAgKiBAcGFyYW0ge2ltcG9ydChcIi4uL2dlb20vU2ltcGxlR2VvbWV0cnkuanNcIikuZGVmYXVsdH0gZ2VvbWV0cnkgR2VvbWV0cnkuXG4gICAqIEBwYXJhbSB7aW1wb3J0KFwiLi4vRmVhdHVyZS5qc1wiKS5GZWF0dXJlTGlrZX0gZmVhdHVyZSBGZWF0dXJlLlxuICAgKiBAcGFyYW0ge0Z1bmN0aW9ufSByZW5kZXJlciBSZW5kZXJlci5cbiAgICovXG5cblxuICBWZWN0b3JDb250ZXh0LnByb3RvdHlwZS5kcmF3Q3VzdG9tID0gZnVuY3Rpb24gKGdlb21ldHJ5LCBmZWF0dXJlLCByZW5kZXJlcikge307XG4gIC8qKlxuICAgKiBSZW5kZXIgYSBnZW9tZXRyeS5cbiAgICpcbiAgICogQHBhcmFtIHtpbXBvcnQoXCIuLi9nZW9tL0dlb21ldHJ5LmpzXCIpLmRlZmF1bHR9IGdlb21ldHJ5IFRoZSBnZW9tZXRyeSB0byByZW5kZXIuXG4gICAqL1xuXG5cbiAgVmVjdG9yQ29udGV4dC5wcm90b3R5cGUuZHJhd0dlb21ldHJ5ID0gZnVuY3Rpb24gKGdlb21ldHJ5KSB7fTtcbiAgLyoqXG4gICAqIFNldCB0aGUgcmVuZGVyaW5nIHN0eWxlLlxuICAgKlxuICAgKiBAcGFyYW0ge2ltcG9ydChcIi4uL3N0eWxlL1N0eWxlLmpzXCIpLmRlZmF1bHR9IHN0eWxlIFRoZSByZW5kZXJpbmcgc3R5bGUuXG4gICAqL1xuXG5cbiAgVmVjdG9yQ29udGV4dC5wcm90b3R5cGUuc2V0U3R5bGUgPSBmdW5jdGlvbiAoc3R5bGUpIHt9O1xuICAvKipcbiAgICogQHBhcmFtIHtpbXBvcnQoXCIuLi9nZW9tL0NpcmNsZS5qc1wiKS5kZWZhdWx0fSBjaXJjbGVHZW9tZXRyeSBDaXJjbGUgZ2VvbWV0cnkuXG4gICAqIEBwYXJhbSB7aW1wb3J0KFwiLi4vRmVhdHVyZS5qc1wiKS5kZWZhdWx0fSBmZWF0dXJlIEZlYXR1cmUuXG4gICAqL1xuXG5cbiAgVmVjdG9yQ29udGV4dC5wcm90b3R5cGUuZHJhd0NpcmNsZSA9IGZ1bmN0aW9uIChjaXJjbGVHZW9tZXRyeSwgZmVhdHVyZSkge307XG4gIC8qKlxuICAgKiBAcGFyYW0ge2ltcG9ydChcIi4uL0ZlYXR1cmUuanNcIikuZGVmYXVsdH0gZmVhdHVyZSBGZWF0dXJlLlxuICAgKiBAcGFyYW0ge2ltcG9ydChcIi4uL3N0eWxlL1N0eWxlLmpzXCIpLmRlZmF1bHR9IHN0eWxlIFN0eWxlLlxuICAgKi9cblxuXG4gIFZlY3RvckNvbnRleHQucHJvdG90eXBlLmRyYXdGZWF0dXJlID0gZnVuY3Rpb24gKGZlYXR1cmUsIHN0eWxlKSB7fTtcbiAgLyoqXG4gICAqIEBwYXJhbSB7aW1wb3J0KFwiLi4vZ2VvbS9HZW9tZXRyeUNvbGxlY3Rpb24uanNcIikuZGVmYXVsdH0gZ2VvbWV0cnlDb2xsZWN0aW9uR2VvbWV0cnkgR2VvbWV0cnkgY29sbGVjdGlvbi5cbiAgICogQHBhcmFtIHtpbXBvcnQoXCIuLi9GZWF0dXJlLmpzXCIpLmRlZmF1bHR9IGZlYXR1cmUgRmVhdHVyZS5cbiAgICovXG5cblxuICBWZWN0b3JDb250ZXh0LnByb3RvdHlwZS5kcmF3R2VvbWV0cnlDb2xsZWN0aW9uID0gZnVuY3Rpb24gKGdlb21ldHJ5Q29sbGVjdGlvbkdlb21ldHJ5LCBmZWF0dXJlKSB7fTtcbiAgLyoqXG4gICAqIEBwYXJhbSB7aW1wb3J0KFwiLi4vZ2VvbS9MaW5lU3RyaW5nLmpzXCIpLmRlZmF1bHR8aW1wb3J0KFwiLi9GZWF0dXJlLmpzXCIpLmRlZmF1bHR9IGxpbmVTdHJpbmdHZW9tZXRyeSBMaW5lIHN0cmluZyBnZW9tZXRyeS5cbiAgICogQHBhcmFtIHtpbXBvcnQoXCIuLi9GZWF0dXJlLmpzXCIpLkZlYXR1cmVMaWtlfSBmZWF0dXJlIEZlYXR1cmUuXG4gICAqL1xuXG5cbiAgVmVjdG9yQ29udGV4dC5wcm90b3R5cGUuZHJhd0xpbmVTdHJpbmcgPSBmdW5jdGlvbiAobGluZVN0cmluZ0dlb21ldHJ5LCBmZWF0dXJlKSB7fTtcbiAgLyoqXG4gICAqIEBwYXJhbSB7aW1wb3J0KFwiLi4vZ2VvbS9NdWx0aUxpbmVTdHJpbmcuanNcIikuZGVmYXVsdHxpbXBvcnQoXCIuL0ZlYXR1cmUuanNcIikuZGVmYXVsdH0gbXVsdGlMaW5lU3RyaW5nR2VvbWV0cnkgTXVsdGlMaW5lU3RyaW5nIGdlb21ldHJ5LlxuICAgKiBAcGFyYW0ge2ltcG9ydChcIi4uL0ZlYXR1cmUuanNcIikuRmVhdHVyZUxpa2V9IGZlYXR1cmUgRmVhdHVyZS5cbiAgICovXG5cblxuICBWZWN0b3JDb250ZXh0LnByb3RvdHlwZS5kcmF3TXVsdGlMaW5lU3RyaW5nID0gZnVuY3Rpb24gKG11bHRpTGluZVN0cmluZ0dlb21ldHJ5LCBmZWF0dXJlKSB7fTtcbiAgLyoqXG4gICAqIEBwYXJhbSB7aW1wb3J0KFwiLi4vZ2VvbS9NdWx0aVBvaW50LmpzXCIpLmRlZmF1bHR8aW1wb3J0KFwiLi9GZWF0dXJlLmpzXCIpLmRlZmF1bHR9IG11bHRpUG9pbnRHZW9tZXRyeSBNdWx0aVBvaW50IGdlb21ldHJ5LlxuICAgKiBAcGFyYW0ge2ltcG9ydChcIi4uL0ZlYXR1cmUuanNcIikuRmVhdHVyZUxpa2V9IGZlYXR1cmUgRmVhdHVyZS5cbiAgICovXG5cblxuICBWZWN0b3JDb250ZXh0LnByb3RvdHlwZS5kcmF3TXVsdGlQb2ludCA9IGZ1bmN0aW9uIChtdWx0aVBvaW50R2VvbWV0cnksIGZlYXR1cmUpIHt9O1xuICAvKipcbiAgICogQHBhcmFtIHtpbXBvcnQoXCIuLi9nZW9tL011bHRpUG9seWdvbi5qc1wiKS5kZWZhdWx0fSBtdWx0aVBvbHlnb25HZW9tZXRyeSBNdWx0aVBvbHlnb24gZ2VvbWV0cnkuXG4gICAqIEBwYXJhbSB7aW1wb3J0KFwiLi4vRmVhdHVyZS5qc1wiKS5GZWF0dXJlTGlrZX0gZmVhdHVyZSBGZWF0dXJlLlxuICAgKi9cblxuXG4gIFZlY3RvckNvbnRleHQucHJvdG90eXBlLmRyYXdNdWx0aVBvbHlnb24gPSBmdW5jdGlvbiAobXVsdGlQb2x5Z29uR2VvbWV0cnksIGZlYXR1cmUpIHt9O1xuICAvKipcbiAgICogQHBhcmFtIHtpbXBvcnQoXCIuLi9nZW9tL1BvaW50LmpzXCIpLmRlZmF1bHR8aW1wb3J0KFwiLi9GZWF0dXJlLmpzXCIpLmRlZmF1bHR9IHBvaW50R2VvbWV0cnkgUG9pbnQgZ2VvbWV0cnkuXG4gICAqIEBwYXJhbSB7aW1wb3J0KFwiLi4vRmVhdHVyZS5qc1wiKS5GZWF0dXJlTGlrZX0gZmVhdHVyZSBGZWF0dXJlLlxuICAgKi9cblxuXG4gIFZlY3RvckNvbnRleHQucHJvdG90eXBlLmRyYXdQb2ludCA9IGZ1bmN0aW9uIChwb2ludEdlb21ldHJ5LCBmZWF0dXJlKSB7fTtcbiAgLyoqXG4gICAqIEBwYXJhbSB7aW1wb3J0KFwiLi4vZ2VvbS9Qb2x5Z29uLmpzXCIpLmRlZmF1bHR8aW1wb3J0KFwiLi9GZWF0dXJlLmpzXCIpLmRlZmF1bHR9IHBvbHlnb25HZW9tZXRyeSBQb2x5Z29uIGdlb21ldHJ5LlxuICAgKiBAcGFyYW0ge2ltcG9ydChcIi4uL0ZlYXR1cmUuanNcIikuRmVhdHVyZUxpa2V9IGZlYXR1cmUgRmVhdHVyZS5cbiAgICovXG5cblxuICBWZWN0b3JDb250ZXh0LnByb3RvdHlwZS5kcmF3UG9seWdvbiA9IGZ1bmN0aW9uIChwb2x5Z29uR2VvbWV0cnksIGZlYXR1cmUpIHt9O1xuICAvKipcbiAgICogQHBhcmFtIHtpbXBvcnQoXCIuLi9nZW9tL1NpbXBsZUdlb21ldHJ5LmpzXCIpLmRlZmF1bHR8aW1wb3J0KFwiLi9GZWF0dXJlLmpzXCIpLmRlZmF1bHR9IGdlb21ldHJ5IEdlb21ldHJ5LlxuICAgKiBAcGFyYW0ge2ltcG9ydChcIi4uL0ZlYXR1cmUuanNcIikuRmVhdHVyZUxpa2V9IGZlYXR1cmUgRmVhdHVyZS5cbiAgICovXG5cblxuICBWZWN0b3JDb250ZXh0LnByb3RvdHlwZS5kcmF3VGV4dCA9IGZ1bmN0aW9uIChnZW9tZXRyeSwgZmVhdHVyZSkge307XG4gIC8qKlxuICAgKiBAcGFyYW0ge2ltcG9ydChcIi4uL3N0eWxlL0ZpbGwuanNcIikuZGVmYXVsdH0gZmlsbFN0eWxlIEZpbGwgc3R5bGUuXG4gICAqIEBwYXJhbSB7aW1wb3J0KFwiLi4vc3R5bGUvU3Ryb2tlLmpzXCIpLmRlZmF1bHR9IHN0cm9rZVN0eWxlIFN0cm9rZSBzdHlsZS5cbiAgICovXG5cblxuICBWZWN0b3JDb250ZXh0LnByb3RvdHlwZS5zZXRGaWxsU3Ryb2tlU3R5bGUgPSBmdW5jdGlvbiAoZmlsbFN0eWxlLCBzdHJva2VTdHlsZSkge307XG4gIC8qKlxuICAgKiBAcGFyYW0ge2ltcG9ydChcIi4uL3N0eWxlL0ltYWdlLmpzXCIpLmRlZmF1bHR9IGltYWdlU3R5bGUgSW1hZ2Ugc3R5bGUuXG4gICAqIEBwYXJhbSB7aW1wb3J0KFwiLi4vcmVuZGVyL2NhbnZhcy5qc1wiKS5EZWNsdXR0ZXJJbWFnZVdpdGhUZXh0PX0gb3B0X2RlY2x1dHRlckltYWdlV2l0aFRleHQgU2hhcmVkIGRhdGEgZm9yIGNvbWJpbmVkIGRlY2x1dHRlcmluZyB3aXRoIGEgdGV4dCBzdHlsZS5cbiAgICovXG5cblxuICBWZWN0b3JDb250ZXh0LnByb3RvdHlwZS5zZXRJbWFnZVN0eWxlID0gZnVuY3Rpb24gKGltYWdlU3R5bGUsIG9wdF9kZWNsdXR0ZXJJbWFnZVdpdGhUZXh0KSB7fTtcbiAgLyoqXG4gICAqIEBwYXJhbSB7aW1wb3J0KFwiLi4vc3R5bGUvVGV4dC5qc1wiKS5kZWZhdWx0fSB0ZXh0U3R5bGUgVGV4dCBzdHlsZS5cbiAgICogQHBhcmFtIHtpbXBvcnQoXCIuLi9yZW5kZXIvY2FudmFzLmpzXCIpLkRlY2x1dHRlckltYWdlV2l0aFRleHQ9fSBvcHRfZGVjbHV0dGVySW1hZ2VXaXRoVGV4dCBTaGFyZWQgZGF0YSBmb3IgY29tYmluZWQgZGVjbHV0dGVyaW5nIHdpdGggYW4gaW1hZ2Ugc3R5bGUuXG4gICAqL1xuXG5cbiAgVmVjdG9yQ29udGV4dC5wcm90b3R5cGUuc2V0VGV4dFN0eWxlID0gZnVuY3Rpb24gKHRleHRTdHlsZSwgb3B0X2RlY2x1dHRlckltYWdlV2l0aFRleHQpIHt9O1xuXG4gIHJldHVybiBWZWN0b3JDb250ZXh0O1xufSgpO1xuXG5leHBvcnQgZGVmYXVsdCBWZWN0b3JDb250ZXh0OyIsInZhciBfX2V4dGVuZHMgPSB0aGlzICYmIHRoaXMuX19leHRlbmRzIHx8IGZ1bmN0aW9uICgpIHtcbiAgdmFyIF9leHRlbmRTdGF0aWNzID0gZnVuY3Rpb24gZXh0ZW5kU3RhdGljcyhkLCBiKSB7XG4gICAgX2V4dGVuZFN0YXRpY3MgPSBPYmplY3Quc2V0UHJvdG90eXBlT2YgfHwge1xuICAgICAgX19wcm90b19fOiBbXVxuICAgIH0gaW5zdGFuY2VvZiBBcnJheSAmJiBmdW5jdGlvbiAoZCwgYikge1xuICAgICAgZC5fX3Byb3RvX18gPSBiO1xuICAgIH0gfHwgZnVuY3Rpb24gKGQsIGIpIHtcbiAgICAgIGZvciAodmFyIHAgaW4gYikge1xuICAgICAgICBpZiAoT2JqZWN0LnByb3RvdHlwZS5oYXNPd25Qcm9wZXJ0eS5jYWxsKGIsIHApKSBkW3BdID0gYltwXTtcbiAgICAgIH1cbiAgICB9O1xuXG4gICAgcmV0dXJuIF9leHRlbmRTdGF0aWNzKGQsIGIpO1xuICB9O1xuXG4gIHJldHVybiBmdW5jdGlvbiAoZCwgYikge1xuICAgIF9leHRlbmRTdGF0aWNzKGQsIGIpO1xuXG4gICAgZnVuY3Rpb24gX18oKSB7XG4gICAgICB0aGlzLmNvbnN0cnVjdG9yID0gZDtcbiAgICB9XG5cbiAgICBkLnByb3RvdHlwZSA9IGIgPT09IG51bGwgPyBPYmplY3QuY3JlYXRlKGIpIDogKF9fLnByb3RvdHlwZSA9IGIucHJvdG90eXBlLCBuZXcgX18oKSk7XG4gIH07XG59KCk7XG4vKipcbiAqIEBtb2R1bGUgb2wvcmVuZGVyL2NhbnZhcy9CdWlsZGVyXG4gKi9cblxuXG5pbXBvcnQgQ2FudmFzSW5zdHJ1Y3Rpb24gZnJvbSAnLi9JbnN0cnVjdGlvbi5qcyc7XG5pbXBvcnQgR2VvbWV0cnlUeXBlIGZyb20gJy4uLy4uL2dlb20vR2VvbWV0cnlUeXBlLmpzJztcbmltcG9ydCBSZWxhdGlvbnNoaXAgZnJvbSAnLi4vLi4vZXh0ZW50L1JlbGF0aW9uc2hpcC5qcyc7XG5pbXBvcnQgVmVjdG9yQ29udGV4dCBmcm9tICcuLi9WZWN0b3JDb250ZXh0LmpzJztcbmltcG9ydCB7IGFzQ29sb3JMaWtlIH0gZnJvbSAnLi4vLi4vY29sb3JsaWtlLmpzJztcbmltcG9ydCB7IGJ1ZmZlciwgY2xvbmUsIGNvbnRhaW5zQ29vcmRpbmF0ZSwgY29vcmRpbmF0ZVJlbGF0aW9uc2hpcCB9IGZyb20gJy4uLy4uL2V4dGVudC5qcyc7XG5pbXBvcnQgeyBkZWZhdWx0RmlsbFN0eWxlLCBkZWZhdWx0TGluZUNhcCwgZGVmYXVsdExpbmVEYXNoLCBkZWZhdWx0TGluZURhc2hPZmZzZXQsIGRlZmF1bHRMaW5lSm9pbiwgZGVmYXVsdExpbmVXaWR0aCwgZGVmYXVsdE1pdGVyTGltaXQsIGRlZmF1bHRTdHJva2VTdHlsZSB9IGZyb20gJy4uL2NhbnZhcy5qcyc7XG5pbXBvcnQgeyBlcXVhbHMsIHJldmVyc2VTdWJBcnJheSB9IGZyb20gJy4uLy4uL2FycmF5LmpzJztcbmltcG9ydCB7IGluZmxhdGVDb29yZGluYXRlcywgaW5mbGF0ZUNvb3JkaW5hdGVzQXJyYXksIGluZmxhdGVNdWx0aUNvb3JkaW5hdGVzQXJyYXkgfSBmcm9tICcuLi8uLi9nZW9tL2ZsYXQvaW5mbGF0ZS5qcyc7XG5cbnZhciBDYW52YXNCdWlsZGVyID1cbi8qKiBAY2xhc3MgKi9cbmZ1bmN0aW9uIChfc3VwZXIpIHtcbiAgX19leHRlbmRzKENhbnZhc0J1aWxkZXIsIF9zdXBlcik7XG4gIC8qKlxuICAgKiBAcGFyYW0ge251bWJlcn0gdG9sZXJhbmNlIFRvbGVyYW5jZS5cbiAgICogQHBhcmFtIHtpbXBvcnQoXCIuLi8uLi9leHRlbnQuanNcIikuRXh0ZW50fSBtYXhFeHRlbnQgTWF4aW11bSBleHRlbnQuXG4gICAqIEBwYXJhbSB7bnVtYmVyfSByZXNvbHV0aW9uIFJlc29sdXRpb24uXG4gICAqIEBwYXJhbSB7bnVtYmVyfSBwaXhlbFJhdGlvIFBpeGVsIHJhdGlvLlxuICAgKi9cblxuXG4gIGZ1bmN0aW9uIENhbnZhc0J1aWxkZXIodG9sZXJhbmNlLCBtYXhFeHRlbnQsIHJlc29sdXRpb24sIHBpeGVsUmF0aW8pIHtcbiAgICB2YXIgX3RoaXMgPSBfc3VwZXIuY2FsbCh0aGlzKSB8fCB0aGlzO1xuICAgIC8qKlxuICAgICAqIEBwcm90ZWN0ZWRcbiAgICAgKiBAdHlwZSB7bnVtYmVyfVxuICAgICAqL1xuXG5cbiAgICBfdGhpcy50b2xlcmFuY2UgPSB0b2xlcmFuY2U7XG4gICAgLyoqXG4gICAgICogQHByb3RlY3RlZFxuICAgICAqIEBjb25zdFxuICAgICAqIEB0eXBlIHtpbXBvcnQoXCIuLi8uLi9leHRlbnQuanNcIikuRXh0ZW50fVxuICAgICAqL1xuXG4gICAgX3RoaXMubWF4RXh0ZW50ID0gbWF4RXh0ZW50O1xuICAgIC8qKlxuICAgICAqIEBwcm90ZWN0ZWRcbiAgICAgKiBAdHlwZSB7bnVtYmVyfVxuICAgICAqL1xuXG4gICAgX3RoaXMucGl4ZWxSYXRpbyA9IHBpeGVsUmF0aW87XG4gICAgLyoqXG4gICAgICogQHByb3RlY3RlZFxuICAgICAqIEB0eXBlIHtudW1iZXJ9XG4gICAgICovXG5cbiAgICBfdGhpcy5tYXhMaW5lV2lkdGggPSAwO1xuICAgIC8qKlxuICAgICAqIEBwcm90ZWN0ZWRcbiAgICAgKiBAY29uc3RcbiAgICAgKiBAdHlwZSB7bnVtYmVyfVxuICAgICAqL1xuXG4gICAgX3RoaXMucmVzb2x1dGlvbiA9IHJlc29sdXRpb247XG4gICAgLyoqXG4gICAgICogQHByaXZhdGVcbiAgICAgKiBAdHlwZSB7QXJyYXk8Kj59XG4gICAgICovXG5cbiAgICBfdGhpcy5iZWdpbkdlb21ldHJ5SW5zdHJ1Y3Rpb24xXyA9IG51bGw7XG4gICAgLyoqXG4gICAgICogQHByaXZhdGVcbiAgICAgKiBAdHlwZSB7QXJyYXk8Kj59XG4gICAgICovXG5cbiAgICBfdGhpcy5iZWdpbkdlb21ldHJ5SW5zdHJ1Y3Rpb24yXyA9IG51bGw7XG4gICAgLyoqXG4gICAgICogQHByaXZhdGVcbiAgICAgKiBAdHlwZSB7aW1wb3J0KFwiLi4vLi4vZXh0ZW50LmpzXCIpLkV4dGVudH1cbiAgICAgKi9cblxuICAgIF90aGlzLmJ1ZmZlcmVkTWF4RXh0ZW50XyA9IG51bGw7XG4gICAgLyoqXG4gICAgICogQHByb3RlY3RlZFxuICAgICAqIEB0eXBlIHtBcnJheTwqPn1cbiAgICAgKi9cblxuICAgIF90aGlzLmluc3RydWN0aW9ucyA9IFtdO1xuICAgIC8qKlxuICAgICAqIEBwcm90ZWN0ZWRcbiAgICAgKiBAdHlwZSB7QXJyYXk8bnVtYmVyPn1cbiAgICAgKi9cblxuICAgIF90aGlzLmNvb3JkaW5hdGVzID0gW107XG4gICAgLyoqXG4gICAgICogQHByaXZhdGVcbiAgICAgKiBAdHlwZSB7aW1wb3J0KFwiLi4vLi4vY29vcmRpbmF0ZS5qc1wiKS5Db29yZGluYXRlfVxuICAgICAqL1xuXG4gICAgX3RoaXMudG1wQ29vcmRpbmF0ZV8gPSBbXTtcbiAgICAvKipcbiAgICAgKiBAcHJvdGVjdGVkXG4gICAgICogQHR5cGUge0FycmF5PCo+fVxuICAgICAqL1xuXG4gICAgX3RoaXMuaGl0RGV0ZWN0aW9uSW5zdHJ1Y3Rpb25zID0gW107XG4gICAgLyoqXG4gICAgICogQHByb3RlY3RlZFxuICAgICAqIEB0eXBlIHtpbXBvcnQoXCIuLi9jYW52YXMuanNcIikuRmlsbFN0cm9rZVN0YXRlfVxuICAgICAqL1xuXG4gICAgX3RoaXMuc3RhdGUgPVxuICAgIC8qKiBAdHlwZSB7aW1wb3J0KFwiLi4vY2FudmFzLmpzXCIpLkZpbGxTdHJva2VTdGF0ZX0gKi9cbiAgICB7fTtcbiAgICByZXR1cm4gX3RoaXM7XG4gIH1cbiAgLyoqXG4gICAqIEBwcm90ZWN0ZWRcbiAgICogQHBhcmFtIHtBcnJheTxudW1iZXI+fSBkYXNoQXJyYXkgRGFzaCBhcnJheS5cbiAgICogQHJldHVybiB7QXJyYXk8bnVtYmVyPn0gRGFzaCBhcnJheSB3aXRoIHBpeGVsIHJhdGlvIGFwcGxpZWRcbiAgICovXG5cblxuICBDYW52YXNCdWlsZGVyLnByb3RvdHlwZS5hcHBseVBpeGVsUmF0aW8gPSBmdW5jdGlvbiAoZGFzaEFycmF5KSB7XG4gICAgdmFyIHBpeGVsUmF0aW8gPSB0aGlzLnBpeGVsUmF0aW87XG4gICAgcmV0dXJuIHBpeGVsUmF0aW8gPT0gMSA/IGRhc2hBcnJheSA6IGRhc2hBcnJheS5tYXAoZnVuY3Rpb24gKGRhc2gpIHtcbiAgICAgIHJldHVybiBkYXNoICogcGl4ZWxSYXRpbztcbiAgICB9KTtcbiAgfTtcbiAgLyoqXG4gICAqIEBwYXJhbSB7QXJyYXk8bnVtYmVyPn0gZmxhdENvb3JkaW5hdGVzIEZsYXQgY29vcmRpbmF0ZXMuXG4gICAqIEBwYXJhbSB7bnVtYmVyfSBzdHJpZGUgU3RyaWRlLlxuICAgKiBAcHJvdGVjdGVkXG4gICAqIEByZXR1cm4ge251bWJlcn0gTXkgZW5kXG4gICAqL1xuXG5cbiAgQ2FudmFzQnVpbGRlci5wcm90b3R5cGUuYXBwZW5kRmxhdFBvaW50Q29vcmRpbmF0ZXMgPSBmdW5jdGlvbiAoZmxhdENvb3JkaW5hdGVzLCBzdHJpZGUpIHtcbiAgICB2YXIgZXh0ZW50ID0gdGhpcy5nZXRCdWZmZXJlZE1heEV4dGVudCgpO1xuICAgIHZhciB0bXBDb29yZCA9IHRoaXMudG1wQ29vcmRpbmF0ZV87XG4gICAgdmFyIGNvb3JkaW5hdGVzID0gdGhpcy5jb29yZGluYXRlcztcbiAgICB2YXIgbXlFbmQgPSBjb29yZGluYXRlcy5sZW5ndGg7XG5cbiAgICBmb3IgKHZhciBpID0gMCwgaWkgPSBmbGF0Q29vcmRpbmF0ZXMubGVuZ3RoOyBpIDwgaWk7IGkgKz0gc3RyaWRlKSB7XG4gICAgICB0bXBDb29yZFswXSA9IGZsYXRDb29yZGluYXRlc1tpXTtcbiAgICAgIHRtcENvb3JkWzFdID0gZmxhdENvb3JkaW5hdGVzW2kgKyAxXTtcblxuICAgICAgaWYgKGNvbnRhaW5zQ29vcmRpbmF0ZShleHRlbnQsIHRtcENvb3JkKSkge1xuICAgICAgICBjb29yZGluYXRlc1tteUVuZCsrXSA9IHRtcENvb3JkWzBdO1xuICAgICAgICBjb29yZGluYXRlc1tteUVuZCsrXSA9IHRtcENvb3JkWzFdO1xuICAgICAgfVxuICAgIH1cblxuICAgIHJldHVybiBteUVuZDtcbiAgfTtcbiAgLyoqXG4gICAqIEBwYXJhbSB7QXJyYXk8bnVtYmVyPn0gZmxhdENvb3JkaW5hdGVzIEZsYXQgY29vcmRpbmF0ZXMuXG4gICAqIEBwYXJhbSB7bnVtYmVyfSBvZmZzZXQgT2Zmc2V0LlxuICAgKiBAcGFyYW0ge251bWJlcn0gZW5kIEVuZC5cbiAgICogQHBhcmFtIHtudW1iZXJ9IHN0cmlkZSBTdHJpZGUuXG4gICAqIEBwYXJhbSB7Ym9vbGVhbn0gY2xvc2VkIExhc3QgaW5wdXQgY29vcmRpbmF0ZSBlcXVhbHMgZmlyc3QuXG4gICAqIEBwYXJhbSB7Ym9vbGVhbn0gc2tpcEZpcnN0IFNraXAgZmlyc3QgY29vcmRpbmF0ZS5cbiAgICogQHByb3RlY3RlZFxuICAgKiBAcmV0dXJuIHtudW1iZXJ9IE15IGVuZC5cbiAgICovXG5cblxuICBDYW52YXNCdWlsZGVyLnByb3RvdHlwZS5hcHBlbmRGbGF0TGluZUNvb3JkaW5hdGVzID0gZnVuY3Rpb24gKGZsYXRDb29yZGluYXRlcywgb2Zmc2V0LCBlbmQsIHN0cmlkZSwgY2xvc2VkLCBza2lwRmlyc3QpIHtcbiAgICB2YXIgY29vcmRpbmF0ZXMgPSB0aGlzLmNvb3JkaW5hdGVzO1xuICAgIHZhciBteUVuZCA9IGNvb3JkaW5hdGVzLmxlbmd0aDtcbiAgICB2YXIgZXh0ZW50ID0gdGhpcy5nZXRCdWZmZXJlZE1heEV4dGVudCgpO1xuXG4gICAgaWYgKHNraXBGaXJzdCkge1xuICAgICAgb2Zmc2V0ICs9IHN0cmlkZTtcbiAgICB9XG5cbiAgICB2YXIgbGFzdFhDb29yZCA9IGZsYXRDb29yZGluYXRlc1tvZmZzZXRdO1xuICAgIHZhciBsYXN0WUNvb3JkID0gZmxhdENvb3JkaW5hdGVzW29mZnNldCArIDFdO1xuICAgIHZhciBuZXh0Q29vcmQgPSB0aGlzLnRtcENvb3JkaW5hdGVfO1xuICAgIHZhciBza2lwcGVkID0gdHJ1ZTtcbiAgICB2YXIgaSwgbGFzdFJlbCwgbmV4dFJlbDtcblxuICAgIGZvciAoaSA9IG9mZnNldCArIHN0cmlkZTsgaSA8IGVuZDsgaSArPSBzdHJpZGUpIHtcbiAgICAgIG5leHRDb29yZFswXSA9IGZsYXRDb29yZGluYXRlc1tpXTtcbiAgICAgIG5leHRDb29yZFsxXSA9IGZsYXRDb29yZGluYXRlc1tpICsgMV07XG4gICAgICBuZXh0UmVsID0gY29vcmRpbmF0ZVJlbGF0aW9uc2hpcChleHRlbnQsIG5leHRDb29yZCk7XG5cbiAgICAgIGlmIChuZXh0UmVsICE9PSBsYXN0UmVsKSB7XG4gICAgICAgIGlmIChza2lwcGVkKSB7XG4gICAgICAgICAgY29vcmRpbmF0ZXNbbXlFbmQrK10gPSBsYXN0WENvb3JkO1xuICAgICAgICAgIGNvb3JkaW5hdGVzW215RW5kKytdID0gbGFzdFlDb29yZDtcbiAgICAgICAgICBza2lwcGVkID0gZmFsc2U7XG4gICAgICAgIH1cblxuICAgICAgICBjb29yZGluYXRlc1tteUVuZCsrXSA9IG5leHRDb29yZFswXTtcbiAgICAgICAgY29vcmRpbmF0ZXNbbXlFbmQrK10gPSBuZXh0Q29vcmRbMV07XG4gICAgICB9IGVsc2UgaWYgKG5leHRSZWwgPT09IFJlbGF0aW9uc2hpcC5JTlRFUlNFQ1RJTkcpIHtcbiAgICAgICAgY29vcmRpbmF0ZXNbbXlFbmQrK10gPSBuZXh0Q29vcmRbMF07XG4gICAgICAgIGNvb3JkaW5hdGVzW215RW5kKytdID0gbmV4dENvb3JkWzFdO1xuICAgICAgICBza2lwcGVkID0gZmFsc2U7XG4gICAgICB9IGVsc2Uge1xuICAgICAgICBza2lwcGVkID0gdHJ1ZTtcbiAgICAgIH1cblxuICAgICAgbGFzdFhDb29yZCA9IG5leHRDb29yZFswXTtcbiAgICAgIGxhc3RZQ29vcmQgPSBuZXh0Q29vcmRbMV07XG4gICAgICBsYXN0UmVsID0gbmV4dFJlbDtcbiAgICB9IC8vIExhc3QgY29vcmRpbmF0ZSBlcXVhbHMgZmlyc3Qgb3Igb25seSBvbmUgcG9pbnQgdG8gYXBwZW5kOlxuXG5cbiAgICBpZiAoY2xvc2VkICYmIHNraXBwZWQgfHwgaSA9PT0gb2Zmc2V0ICsgc3RyaWRlKSB7XG4gICAgICBjb29yZGluYXRlc1tteUVuZCsrXSA9IGxhc3RYQ29vcmQ7XG4gICAgICBjb29yZGluYXRlc1tteUVuZCsrXSA9IGxhc3RZQ29vcmQ7XG4gICAgfVxuXG4gICAgcmV0dXJuIG15RW5kO1xuICB9O1xuICAvKipcbiAgICogQHBhcmFtIHtBcnJheTxudW1iZXI+fSBmbGF0Q29vcmRpbmF0ZXMgRmxhdCBjb29yZGluYXRlcy5cbiAgICogQHBhcmFtIHtudW1iZXJ9IG9mZnNldCBPZmZzZXQuXG4gICAqIEBwYXJhbSB7QXJyYXk8bnVtYmVyPn0gZW5kcyBFbmRzLlxuICAgKiBAcGFyYW0ge251bWJlcn0gc3RyaWRlIFN0cmlkZS5cbiAgICogQHBhcmFtIHtBcnJheTxudW1iZXI+fSBidWlsZGVyRW5kcyBCdWlsZGVyIGVuZHMuXG4gICAqIEByZXR1cm4ge251bWJlcn0gT2Zmc2V0LlxuICAgKi9cblxuXG4gIENhbnZhc0J1aWxkZXIucHJvdG90eXBlLmRyYXdDdXN0b21Db29yZGluYXRlc18gPSBmdW5jdGlvbiAoZmxhdENvb3JkaW5hdGVzLCBvZmZzZXQsIGVuZHMsIHN0cmlkZSwgYnVpbGRlckVuZHMpIHtcbiAgICBmb3IgKHZhciBpID0gMCwgaWkgPSBlbmRzLmxlbmd0aDsgaSA8IGlpOyArK2kpIHtcbiAgICAgIHZhciBlbmQgPSBlbmRzW2ldO1xuICAgICAgdmFyIGJ1aWxkZXJFbmQgPSB0aGlzLmFwcGVuZEZsYXRMaW5lQ29vcmRpbmF0ZXMoZmxhdENvb3JkaW5hdGVzLCBvZmZzZXQsIGVuZCwgc3RyaWRlLCBmYWxzZSwgZmFsc2UpO1xuICAgICAgYnVpbGRlckVuZHMucHVzaChidWlsZGVyRW5kKTtcbiAgICAgIG9mZnNldCA9IGVuZDtcbiAgICB9XG5cbiAgICByZXR1cm4gb2Zmc2V0O1xuICB9O1xuICAvKipcbiAgICogQHBhcmFtIHtpbXBvcnQoXCIuLi8uLi9nZW9tL1NpbXBsZUdlb21ldHJ5LmpzXCIpLmRlZmF1bHR9IGdlb21ldHJ5IEdlb21ldHJ5LlxuICAgKiBAcGFyYW0ge2ltcG9ydChcIi4uLy4uL0ZlYXR1cmUuanNcIikuRmVhdHVyZUxpa2V9IGZlYXR1cmUgRmVhdHVyZS5cbiAgICogQHBhcmFtIHtGdW5jdGlvbn0gcmVuZGVyZXIgUmVuZGVyZXIuXG4gICAqL1xuXG5cbiAgQ2FudmFzQnVpbGRlci5wcm90b3R5cGUuZHJhd0N1c3RvbSA9IGZ1bmN0aW9uIChnZW9tZXRyeSwgZmVhdHVyZSwgcmVuZGVyZXIpIHtcbiAgICB0aGlzLmJlZ2luR2VvbWV0cnkoZ2VvbWV0cnksIGZlYXR1cmUpO1xuICAgIHZhciB0eXBlID0gZ2VvbWV0cnkuZ2V0VHlwZSgpO1xuICAgIHZhciBzdHJpZGUgPSBnZW9tZXRyeS5nZXRTdHJpZGUoKTtcbiAgICB2YXIgYnVpbGRlckJlZ2luID0gdGhpcy5jb29yZGluYXRlcy5sZW5ndGg7XG4gICAgdmFyIGZsYXRDb29yZGluYXRlcywgYnVpbGRlckVuZCwgYnVpbGRlckVuZHMsIGJ1aWxkZXJFbmRzcztcbiAgICB2YXIgb2Zmc2V0O1xuXG4gICAgaWYgKHR5cGUgPT0gR2VvbWV0cnlUeXBlLk1VTFRJX1BPTFlHT04pIHtcbiAgICAgIGZsYXRDb29yZGluYXRlcyA9XG4gICAgICAvKiogQHR5cGUge2ltcG9ydChcIi4uLy4uL2dlb20vTXVsdGlQb2x5Z29uLmpzXCIpLmRlZmF1bHR9ICovXG4gICAgICBnZW9tZXRyeS5nZXRPcmllbnRlZEZsYXRDb29yZGluYXRlcygpO1xuICAgICAgYnVpbGRlckVuZHNzID0gW107XG4gICAgICB2YXIgZW5kc3MgPVxuICAgICAgLyoqIEB0eXBlIHtpbXBvcnQoXCIuLi8uLi9nZW9tL011bHRpUG9seWdvbi5qc1wiKS5kZWZhdWx0fSAqL1xuICAgICAgZ2VvbWV0cnkuZ2V0RW5kc3MoKTtcbiAgICAgIG9mZnNldCA9IDA7XG5cbiAgICAgIGZvciAodmFyIGkgPSAwLCBpaSA9IGVuZHNzLmxlbmd0aDsgaSA8IGlpOyArK2kpIHtcbiAgICAgICAgdmFyIG15RW5kcyA9IFtdO1xuICAgICAgICBvZmZzZXQgPSB0aGlzLmRyYXdDdXN0b21Db29yZGluYXRlc18oZmxhdENvb3JkaW5hdGVzLCBvZmZzZXQsIGVuZHNzW2ldLCBzdHJpZGUsIG15RW5kcyk7XG4gICAgICAgIGJ1aWxkZXJFbmRzcy5wdXNoKG15RW5kcyk7XG4gICAgICB9XG5cbiAgICAgIHRoaXMuaW5zdHJ1Y3Rpb25zLnB1c2goW0NhbnZhc0luc3RydWN0aW9uLkNVU1RPTSwgYnVpbGRlckJlZ2luLCBidWlsZGVyRW5kc3MsIGdlb21ldHJ5LCByZW5kZXJlciwgaW5mbGF0ZU11bHRpQ29vcmRpbmF0ZXNBcnJheV0pO1xuICAgIH0gZWxzZSBpZiAodHlwZSA9PSBHZW9tZXRyeVR5cGUuUE9MWUdPTiB8fCB0eXBlID09IEdlb21ldHJ5VHlwZS5NVUxUSV9MSU5FX1NUUklORykge1xuICAgICAgYnVpbGRlckVuZHMgPSBbXTtcbiAgICAgIGZsYXRDb29yZGluYXRlcyA9IHR5cGUgPT0gR2VvbWV0cnlUeXBlLlBPTFlHT04gP1xuICAgICAgLyoqIEB0eXBlIHtpbXBvcnQoXCIuLi8uLi9nZW9tL1BvbHlnb24uanNcIikuZGVmYXVsdH0gKi9cbiAgICAgIGdlb21ldHJ5LmdldE9yaWVudGVkRmxhdENvb3JkaW5hdGVzKCkgOiBnZW9tZXRyeS5nZXRGbGF0Q29vcmRpbmF0ZXMoKTtcbiAgICAgIG9mZnNldCA9IHRoaXMuZHJhd0N1c3RvbUNvb3JkaW5hdGVzXyhmbGF0Q29vcmRpbmF0ZXMsIDAsXG4gICAgICAvKiogQHR5cGUge2ltcG9ydChcIi4uLy4uL2dlb20vUG9seWdvbi5qc1wiKS5kZWZhdWx0fGltcG9ydChcIi4uLy4uL2dlb20vTXVsdGlMaW5lU3RyaW5nLmpzXCIpLmRlZmF1bHR9ICovXG4gICAgICBnZW9tZXRyeS5nZXRFbmRzKCksIHN0cmlkZSwgYnVpbGRlckVuZHMpO1xuICAgICAgdGhpcy5pbnN0cnVjdGlvbnMucHVzaChbQ2FudmFzSW5zdHJ1Y3Rpb24uQ1VTVE9NLCBidWlsZGVyQmVnaW4sIGJ1aWxkZXJFbmRzLCBnZW9tZXRyeSwgcmVuZGVyZXIsIGluZmxhdGVDb29yZGluYXRlc0FycmF5XSk7XG4gICAgfSBlbHNlIGlmICh0eXBlID09IEdlb21ldHJ5VHlwZS5MSU5FX1NUUklORyB8fCB0eXBlID09IEdlb21ldHJ5VHlwZS5DSVJDTEUpIHtcbiAgICAgIGZsYXRDb29yZGluYXRlcyA9IGdlb21ldHJ5LmdldEZsYXRDb29yZGluYXRlcygpO1xuICAgICAgYnVpbGRlckVuZCA9IHRoaXMuYXBwZW5kRmxhdExpbmVDb29yZGluYXRlcyhmbGF0Q29vcmRpbmF0ZXMsIDAsIGZsYXRDb29yZGluYXRlcy5sZW5ndGgsIHN0cmlkZSwgZmFsc2UsIGZhbHNlKTtcbiAgICAgIHRoaXMuaW5zdHJ1Y3Rpb25zLnB1c2goW0NhbnZhc0luc3RydWN0aW9uLkNVU1RPTSwgYnVpbGRlckJlZ2luLCBidWlsZGVyRW5kLCBnZW9tZXRyeSwgcmVuZGVyZXIsIGluZmxhdGVDb29yZGluYXRlc10pO1xuICAgIH0gZWxzZSBpZiAodHlwZSA9PSBHZW9tZXRyeVR5cGUuTVVMVElfUE9JTlQpIHtcbiAgICAgIGZsYXRDb29yZGluYXRlcyA9IGdlb21ldHJ5LmdldEZsYXRDb29yZGluYXRlcygpO1xuICAgICAgYnVpbGRlckVuZCA9IHRoaXMuYXBwZW5kRmxhdFBvaW50Q29vcmRpbmF0ZXMoZmxhdENvb3JkaW5hdGVzLCBzdHJpZGUpO1xuXG4gICAgICBpZiAoYnVpbGRlckVuZCA+IGJ1aWxkZXJCZWdpbikge1xuICAgICAgICB0aGlzLmluc3RydWN0aW9ucy5wdXNoKFtDYW52YXNJbnN0cnVjdGlvbi5DVVNUT00sIGJ1aWxkZXJCZWdpbiwgYnVpbGRlckVuZCwgZ2VvbWV0cnksIHJlbmRlcmVyLCBpbmZsYXRlQ29vcmRpbmF0ZXNdKTtcbiAgICAgIH1cbiAgICB9IGVsc2UgaWYgKHR5cGUgPT0gR2VvbWV0cnlUeXBlLlBPSU5UKSB7XG4gICAgICBmbGF0Q29vcmRpbmF0ZXMgPSBnZW9tZXRyeS5nZXRGbGF0Q29vcmRpbmF0ZXMoKTtcbiAgICAgIHRoaXMuY29vcmRpbmF0ZXMucHVzaChmbGF0Q29vcmRpbmF0ZXNbMF0sIGZsYXRDb29yZGluYXRlc1sxXSk7XG4gICAgICBidWlsZGVyRW5kID0gdGhpcy5jb29yZGluYXRlcy5sZW5ndGg7XG4gICAgICB0aGlzLmluc3RydWN0aW9ucy5wdXNoKFtDYW52YXNJbnN0cnVjdGlvbi5DVVNUT00sIGJ1aWxkZXJCZWdpbiwgYnVpbGRlckVuZCwgZ2VvbWV0cnksIHJlbmRlcmVyXSk7XG4gICAgfVxuXG4gICAgdGhpcy5lbmRHZW9tZXRyeShmZWF0dXJlKTtcbiAgfTtcbiAgLyoqXG4gICAqIEBwcm90ZWN0ZWRcbiAgICogQHBhcmFtIHtpbXBvcnQoXCIuLi8uLi9nZW9tL0dlb21ldHJ5XCIpLmRlZmF1bHR8aW1wb3J0KFwiLi4vRmVhdHVyZS5qc1wiKS5kZWZhdWx0fSBnZW9tZXRyeSBUaGUgZ2VvbWV0cnkuXG4gICAqIEBwYXJhbSB7aW1wb3J0KFwiLi4vLi4vRmVhdHVyZS5qc1wiKS5GZWF0dXJlTGlrZX0gZmVhdHVyZSBGZWF0dXJlLlxuICAgKi9cblxuXG4gIENhbnZhc0J1aWxkZXIucHJvdG90eXBlLmJlZ2luR2VvbWV0cnkgPSBmdW5jdGlvbiAoZ2VvbWV0cnksIGZlYXR1cmUpIHtcbiAgICB0aGlzLmJlZ2luR2VvbWV0cnlJbnN0cnVjdGlvbjFfID0gW0NhbnZhc0luc3RydWN0aW9uLkJFR0lOX0dFT01FVFJZLCBmZWF0dXJlLCAwLCBnZW9tZXRyeV07XG4gICAgdGhpcy5pbnN0cnVjdGlvbnMucHVzaCh0aGlzLmJlZ2luR2VvbWV0cnlJbnN0cnVjdGlvbjFfKTtcbiAgICB0aGlzLmJlZ2luR2VvbWV0cnlJbnN0cnVjdGlvbjJfID0gW0NhbnZhc0luc3RydWN0aW9uLkJFR0lOX0dFT01FVFJZLCBmZWF0dXJlLCAwLCBnZW9tZXRyeV07XG4gICAgdGhpcy5oaXREZXRlY3Rpb25JbnN0cnVjdGlvbnMucHVzaCh0aGlzLmJlZ2luR2VvbWV0cnlJbnN0cnVjdGlvbjJfKTtcbiAgfTtcbiAgLyoqXG4gICAqIEByZXR1cm4ge2ltcG9ydChcIi4uL2NhbnZhcy5qc1wiKS5TZXJpYWxpemFibGVJbnN0cnVjdGlvbnN9IHRoZSBzZXJpYWxpemFibGUgaW5zdHJ1Y3Rpb25zLlxuICAgKi9cblxuXG4gIENhbnZhc0J1aWxkZXIucHJvdG90eXBlLmZpbmlzaCA9IGZ1bmN0aW9uICgpIHtcbiAgICByZXR1cm4ge1xuICAgICAgaW5zdHJ1Y3Rpb25zOiB0aGlzLmluc3RydWN0aW9ucyxcbiAgICAgIGhpdERldGVjdGlvbkluc3RydWN0aW9uczogdGhpcy5oaXREZXRlY3Rpb25JbnN0cnVjdGlvbnMsXG4gICAgICBjb29yZGluYXRlczogdGhpcy5jb29yZGluYXRlc1xuICAgIH07XG4gIH07XG4gIC8qKlxuICAgKiBSZXZlcnNlIHRoZSBoaXQgZGV0ZWN0aW9uIGluc3RydWN0aW9ucy5cbiAgICovXG5cblxuICBDYW52YXNCdWlsZGVyLnByb3RvdHlwZS5yZXZlcnNlSGl0RGV0ZWN0aW9uSW5zdHJ1Y3Rpb25zID0gZnVuY3Rpb24gKCkge1xuICAgIHZhciBoaXREZXRlY3Rpb25JbnN0cnVjdGlvbnMgPSB0aGlzLmhpdERldGVjdGlvbkluc3RydWN0aW9uczsgLy8gc3RlcCAxIC0gcmV2ZXJzZSBhcnJheVxuXG4gICAgaGl0RGV0ZWN0aW9uSW5zdHJ1Y3Rpb25zLnJldmVyc2UoKTsgLy8gc3RlcCAyIC0gcmV2ZXJzZSBpbnN0cnVjdGlvbnMgd2l0aGluIGdlb21ldHJ5IGJsb2Nrc1xuXG4gICAgdmFyIGk7XG4gICAgdmFyIG4gPSBoaXREZXRlY3Rpb25JbnN0cnVjdGlvbnMubGVuZ3RoO1xuICAgIHZhciBpbnN0cnVjdGlvbjtcbiAgICB2YXIgdHlwZTtcbiAgICB2YXIgYmVnaW4gPSAtMTtcblxuICAgIGZvciAoaSA9IDA7IGkgPCBuOyArK2kpIHtcbiAgICAgIGluc3RydWN0aW9uID0gaGl0RGV0ZWN0aW9uSW5zdHJ1Y3Rpb25zW2ldO1xuICAgICAgdHlwZSA9XG4gICAgICAvKiogQHR5cGUge2ltcG9ydChcIi4vSW5zdHJ1Y3Rpb24uanNcIikuZGVmYXVsdH0gKi9cbiAgICAgIGluc3RydWN0aW9uWzBdO1xuXG4gICAgICBpZiAodHlwZSA9PSBDYW52YXNJbnN0cnVjdGlvbi5FTkRfR0VPTUVUUlkpIHtcbiAgICAgICAgYmVnaW4gPSBpO1xuICAgICAgfSBlbHNlIGlmICh0eXBlID09IENhbnZhc0luc3RydWN0aW9uLkJFR0lOX0dFT01FVFJZKSB7XG4gICAgICAgIGluc3RydWN0aW9uWzJdID0gaTtcbiAgICAgICAgcmV2ZXJzZVN1YkFycmF5KHRoaXMuaGl0RGV0ZWN0aW9uSW5zdHJ1Y3Rpb25zLCBiZWdpbiwgaSk7XG4gICAgICAgIGJlZ2luID0gLTE7XG4gICAgICB9XG4gICAgfVxuICB9O1xuICAvKipcbiAgICogQHBhcmFtIHtpbXBvcnQoXCIuLi8uLi9zdHlsZS9GaWxsLmpzXCIpLmRlZmF1bHR9IGZpbGxTdHlsZSBGaWxsIHN0eWxlLlxuICAgKiBAcGFyYW0ge2ltcG9ydChcIi4uLy4uL3N0eWxlL1N0cm9rZS5qc1wiKS5kZWZhdWx0fSBzdHJva2VTdHlsZSBTdHJva2Ugc3R5bGUuXG4gICAqL1xuXG5cbiAgQ2FudmFzQnVpbGRlci5wcm90b3R5cGUuc2V0RmlsbFN0cm9rZVN0eWxlID0gZnVuY3Rpb24gKGZpbGxTdHlsZSwgc3Ryb2tlU3R5bGUpIHtcbiAgICB2YXIgc3RhdGUgPSB0aGlzLnN0YXRlO1xuXG4gICAgaWYgKGZpbGxTdHlsZSkge1xuICAgICAgdmFyIGZpbGxTdHlsZUNvbG9yID0gZmlsbFN0eWxlLmdldENvbG9yKCk7XG4gICAgICBzdGF0ZS5maWxsU3R5bGUgPSBhc0NvbG9yTGlrZShmaWxsU3R5bGVDb2xvciA/IGZpbGxTdHlsZUNvbG9yIDogZGVmYXVsdEZpbGxTdHlsZSk7XG4gICAgfSBlbHNlIHtcbiAgICAgIHN0YXRlLmZpbGxTdHlsZSA9IHVuZGVmaW5lZDtcbiAgICB9XG5cbiAgICBpZiAoc3Ryb2tlU3R5bGUpIHtcbiAgICAgIHZhciBzdHJva2VTdHlsZUNvbG9yID0gc3Ryb2tlU3R5bGUuZ2V0Q29sb3IoKTtcbiAgICAgIHN0YXRlLnN0cm9rZVN0eWxlID0gYXNDb2xvckxpa2Uoc3Ryb2tlU3R5bGVDb2xvciA/IHN0cm9rZVN0eWxlQ29sb3IgOiBkZWZhdWx0U3Ryb2tlU3R5bGUpO1xuICAgICAgdmFyIHN0cm9rZVN0eWxlTGluZUNhcCA9IHN0cm9rZVN0eWxlLmdldExpbmVDYXAoKTtcbiAgICAgIHN0YXRlLmxpbmVDYXAgPSBzdHJva2VTdHlsZUxpbmVDYXAgIT09IHVuZGVmaW5lZCA/IHN0cm9rZVN0eWxlTGluZUNhcCA6IGRlZmF1bHRMaW5lQ2FwO1xuICAgICAgdmFyIHN0cm9rZVN0eWxlTGluZURhc2ggPSBzdHJva2VTdHlsZS5nZXRMaW5lRGFzaCgpO1xuICAgICAgc3RhdGUubGluZURhc2ggPSBzdHJva2VTdHlsZUxpbmVEYXNoID8gc3Ryb2tlU3R5bGVMaW5lRGFzaC5zbGljZSgpIDogZGVmYXVsdExpbmVEYXNoO1xuICAgICAgdmFyIHN0cm9rZVN0eWxlTGluZURhc2hPZmZzZXQgPSBzdHJva2VTdHlsZS5nZXRMaW5lRGFzaE9mZnNldCgpO1xuICAgICAgc3RhdGUubGluZURhc2hPZmZzZXQgPSBzdHJva2VTdHlsZUxpbmVEYXNoT2Zmc2V0ID8gc3Ryb2tlU3R5bGVMaW5lRGFzaE9mZnNldCA6IGRlZmF1bHRMaW5lRGFzaE9mZnNldDtcbiAgICAgIHZhciBzdHJva2VTdHlsZUxpbmVKb2luID0gc3Ryb2tlU3R5bGUuZ2V0TGluZUpvaW4oKTtcbiAgICAgIHN0YXRlLmxpbmVKb2luID0gc3Ryb2tlU3R5bGVMaW5lSm9pbiAhPT0gdW5kZWZpbmVkID8gc3Ryb2tlU3R5bGVMaW5lSm9pbiA6IGRlZmF1bHRMaW5lSm9pbjtcbiAgICAgIHZhciBzdHJva2VTdHlsZVdpZHRoID0gc3Ryb2tlU3R5bGUuZ2V0V2lkdGgoKTtcbiAgICAgIHN0YXRlLmxpbmVXaWR0aCA9IHN0cm9rZVN0eWxlV2lkdGggIT09IHVuZGVmaW5lZCA/IHN0cm9rZVN0eWxlV2lkdGggOiBkZWZhdWx0TGluZVdpZHRoO1xuICAgICAgdmFyIHN0cm9rZVN0eWxlTWl0ZXJMaW1pdCA9IHN0cm9rZVN0eWxlLmdldE1pdGVyTGltaXQoKTtcbiAgICAgIHN0YXRlLm1pdGVyTGltaXQgPSBzdHJva2VTdHlsZU1pdGVyTGltaXQgIT09IHVuZGVmaW5lZCA/IHN0cm9rZVN0eWxlTWl0ZXJMaW1pdCA6IGRlZmF1bHRNaXRlckxpbWl0O1xuXG4gICAgICBpZiAoc3RhdGUubGluZVdpZHRoID4gdGhpcy5tYXhMaW5lV2lkdGgpIHtcbiAgICAgICAgdGhpcy5tYXhMaW5lV2lkdGggPSBzdGF0ZS5saW5lV2lkdGg7IC8vIGludmFsaWRhdGUgdGhlIGJ1ZmZlcmVkIG1heCBleHRlbnQgY2FjaGVcblxuICAgICAgICB0aGlzLmJ1ZmZlcmVkTWF4RXh0ZW50XyA9IG51bGw7XG4gICAgICB9XG4gICAgfSBlbHNlIHtcbiAgICAgIHN0YXRlLnN0cm9rZVN0eWxlID0gdW5kZWZpbmVkO1xuICAgICAgc3RhdGUubGluZUNhcCA9IHVuZGVmaW5lZDtcbiAgICAgIHN0YXRlLmxpbmVEYXNoID0gbnVsbDtcbiAgICAgIHN0YXRlLmxpbmVEYXNoT2Zmc2V0ID0gdW5kZWZpbmVkO1xuICAgICAgc3RhdGUubGluZUpvaW4gPSB1bmRlZmluZWQ7XG4gICAgICBzdGF0ZS5saW5lV2lkdGggPSB1bmRlZmluZWQ7XG4gICAgICBzdGF0ZS5taXRlckxpbWl0ID0gdW5kZWZpbmVkO1xuICAgIH1cbiAgfTtcbiAgLyoqXG4gICAqIEBwYXJhbSB7aW1wb3J0KFwiLi4vY2FudmFzLmpzXCIpLkZpbGxTdHJva2VTdGF0ZX0gc3RhdGUgU3RhdGUuXG4gICAqIEByZXR1cm4ge0FycmF5PCo+fSBGaWxsIGluc3RydWN0aW9uLlxuICAgKi9cblxuXG4gIENhbnZhc0J1aWxkZXIucHJvdG90eXBlLmNyZWF0ZUZpbGwgPSBmdW5jdGlvbiAoc3RhdGUpIHtcbiAgICB2YXIgZmlsbFN0eWxlID0gc3RhdGUuZmlsbFN0eWxlO1xuICAgIC8qKiBAdHlwZSB7QXJyYXk8Kj59ICovXG5cbiAgICB2YXIgZmlsbEluc3RydWN0aW9uID0gW0NhbnZhc0luc3RydWN0aW9uLlNFVF9GSUxMX1NUWUxFLCBmaWxsU3R5bGVdO1xuXG4gICAgaWYgKHR5cGVvZiBmaWxsU3R5bGUgIT09ICdzdHJpbmcnKSB7XG4gICAgICAvLyBGaWxsIGlzIGEgcGF0dGVybiBvciBncmFkaWVudCAtIGFsaWduIGl0IVxuICAgICAgZmlsbEluc3RydWN0aW9uLnB1c2godHJ1ZSk7XG4gICAgfVxuXG4gICAgcmV0dXJuIGZpbGxJbnN0cnVjdGlvbjtcbiAgfTtcbiAgLyoqXG4gICAqIEBwYXJhbSB7aW1wb3J0KFwiLi4vY2FudmFzLmpzXCIpLkZpbGxTdHJva2VTdGF0ZX0gc3RhdGUgU3RhdGUuXG4gICAqL1xuXG5cbiAgQ2FudmFzQnVpbGRlci5wcm90b3R5cGUuYXBwbHlTdHJva2UgPSBmdW5jdGlvbiAoc3RhdGUpIHtcbiAgICB0aGlzLmluc3RydWN0aW9ucy5wdXNoKHRoaXMuY3JlYXRlU3Ryb2tlKHN0YXRlKSk7XG4gIH07XG4gIC8qKlxuICAgKiBAcGFyYW0ge2ltcG9ydChcIi4uL2NhbnZhcy5qc1wiKS5GaWxsU3Ryb2tlU3RhdGV9IHN0YXRlIFN0YXRlLlxuICAgKiBAcmV0dXJuIHtBcnJheTwqPn0gU3Ryb2tlIGluc3RydWN0aW9uLlxuICAgKi9cblxuXG4gIENhbnZhc0J1aWxkZXIucHJvdG90eXBlLmNyZWF0ZVN0cm9rZSA9IGZ1bmN0aW9uIChzdGF0ZSkge1xuICAgIHJldHVybiBbQ2FudmFzSW5zdHJ1Y3Rpb24uU0VUX1NUUk9LRV9TVFlMRSwgc3RhdGUuc3Ryb2tlU3R5bGUsIHN0YXRlLmxpbmVXaWR0aCAqIHRoaXMucGl4ZWxSYXRpbywgc3RhdGUubGluZUNhcCwgc3RhdGUubGluZUpvaW4sIHN0YXRlLm1pdGVyTGltaXQsIHRoaXMuYXBwbHlQaXhlbFJhdGlvKHN0YXRlLmxpbmVEYXNoKSwgc3RhdGUubGluZURhc2hPZmZzZXQgKiB0aGlzLnBpeGVsUmF0aW9dO1xuICB9O1xuICAvKipcbiAgICogQHBhcmFtIHtpbXBvcnQoXCIuLi9jYW52YXMuanNcIikuRmlsbFN0cm9rZVN0YXRlfSBzdGF0ZSBTdGF0ZS5cbiAgICogQHBhcmFtIHtmdW5jdGlvbih0aGlzOkNhbnZhc0J1aWxkZXIsIGltcG9ydChcIi4uL2NhbnZhcy5qc1wiKS5GaWxsU3Ryb2tlU3RhdGUpOkFycmF5PCo+fSBjcmVhdGVGaWxsIENyZWF0ZSBmaWxsLlxuICAgKi9cblxuXG4gIENhbnZhc0J1aWxkZXIucHJvdG90eXBlLnVwZGF0ZUZpbGxTdHlsZSA9IGZ1bmN0aW9uIChzdGF0ZSwgY3JlYXRlRmlsbCkge1xuICAgIHZhciBmaWxsU3R5bGUgPSBzdGF0ZS5maWxsU3R5bGU7XG5cbiAgICBpZiAodHlwZW9mIGZpbGxTdHlsZSAhPT0gJ3N0cmluZycgfHwgc3RhdGUuY3VycmVudEZpbGxTdHlsZSAhPSBmaWxsU3R5bGUpIHtcbiAgICAgIGlmIChmaWxsU3R5bGUgIT09IHVuZGVmaW5lZCkge1xuICAgICAgICB0aGlzLmluc3RydWN0aW9ucy5wdXNoKGNyZWF0ZUZpbGwuY2FsbCh0aGlzLCBzdGF0ZSkpO1xuICAgICAgfVxuXG4gICAgICBzdGF0ZS5jdXJyZW50RmlsbFN0eWxlID0gZmlsbFN0eWxlO1xuICAgIH1cbiAgfTtcbiAgLyoqXG4gICAqIEBwYXJhbSB7aW1wb3J0KFwiLi4vY2FudmFzLmpzXCIpLkZpbGxTdHJva2VTdGF0ZX0gc3RhdGUgU3RhdGUuXG4gICAqIEBwYXJhbSB7ZnVuY3Rpb24odGhpczpDYW52YXNCdWlsZGVyLCBpbXBvcnQoXCIuLi9jYW52YXMuanNcIikuRmlsbFN0cm9rZVN0YXRlKTogdm9pZH0gYXBwbHlTdHJva2UgQXBwbHkgc3Ryb2tlLlxuICAgKi9cblxuXG4gIENhbnZhc0J1aWxkZXIucHJvdG90eXBlLnVwZGF0ZVN0cm9rZVN0eWxlID0gZnVuY3Rpb24gKHN0YXRlLCBhcHBseVN0cm9rZSkge1xuICAgIHZhciBzdHJva2VTdHlsZSA9IHN0YXRlLnN0cm9rZVN0eWxlO1xuICAgIHZhciBsaW5lQ2FwID0gc3RhdGUubGluZUNhcDtcbiAgICB2YXIgbGluZURhc2ggPSBzdGF0ZS5saW5lRGFzaDtcbiAgICB2YXIgbGluZURhc2hPZmZzZXQgPSBzdGF0ZS5saW5lRGFzaE9mZnNldDtcbiAgICB2YXIgbGluZUpvaW4gPSBzdGF0ZS5saW5lSm9pbjtcbiAgICB2YXIgbGluZVdpZHRoID0gc3RhdGUubGluZVdpZHRoO1xuICAgIHZhciBtaXRlckxpbWl0ID0gc3RhdGUubWl0ZXJMaW1pdDtcblxuICAgIGlmIChzdGF0ZS5jdXJyZW50U3Ryb2tlU3R5bGUgIT0gc3Ryb2tlU3R5bGUgfHwgc3RhdGUuY3VycmVudExpbmVDYXAgIT0gbGluZUNhcCB8fCBsaW5lRGFzaCAhPSBzdGF0ZS5jdXJyZW50TGluZURhc2ggJiYgIWVxdWFscyhzdGF0ZS5jdXJyZW50TGluZURhc2gsIGxpbmVEYXNoKSB8fCBzdGF0ZS5jdXJyZW50TGluZURhc2hPZmZzZXQgIT0gbGluZURhc2hPZmZzZXQgfHwgc3RhdGUuY3VycmVudExpbmVKb2luICE9IGxpbmVKb2luIHx8IHN0YXRlLmN1cnJlbnRMaW5lV2lkdGggIT0gbGluZVdpZHRoIHx8IHN0YXRlLmN1cnJlbnRNaXRlckxpbWl0ICE9IG1pdGVyTGltaXQpIHtcbiAgICAgIGlmIChzdHJva2VTdHlsZSAhPT0gdW5kZWZpbmVkKSB7XG4gICAgICAgIGFwcGx5U3Ryb2tlLmNhbGwodGhpcywgc3RhdGUpO1xuICAgICAgfVxuXG4gICAgICBzdGF0ZS5jdXJyZW50U3Ryb2tlU3R5bGUgPSBzdHJva2VTdHlsZTtcbiAgICAgIHN0YXRlLmN1cnJlbnRMaW5lQ2FwID0gbGluZUNhcDtcbiAgICAgIHN0YXRlLmN1cnJlbnRMaW5lRGFzaCA9IGxpbmVEYXNoO1xuICAgICAgc3RhdGUuY3VycmVudExpbmVEYXNoT2Zmc2V0ID0gbGluZURhc2hPZmZzZXQ7XG4gICAgICBzdGF0ZS5jdXJyZW50TGluZUpvaW4gPSBsaW5lSm9pbjtcbiAgICAgIHN0YXRlLmN1cnJlbnRMaW5lV2lkdGggPSBsaW5lV2lkdGg7XG4gICAgICBzdGF0ZS5jdXJyZW50TWl0ZXJMaW1pdCA9IG1pdGVyTGltaXQ7XG4gICAgfVxuICB9O1xuICAvKipcbiAgICogQHBhcmFtIHtpbXBvcnQoXCIuLi8uLi9GZWF0dXJlLmpzXCIpLkZlYXR1cmVMaWtlfSBmZWF0dXJlIEZlYXR1cmUuXG4gICAqL1xuXG5cbiAgQ2FudmFzQnVpbGRlci5wcm90b3R5cGUuZW5kR2VvbWV0cnkgPSBmdW5jdGlvbiAoZmVhdHVyZSkge1xuICAgIHRoaXMuYmVnaW5HZW9tZXRyeUluc3RydWN0aW9uMV9bMl0gPSB0aGlzLmluc3RydWN0aW9ucy5sZW5ndGg7XG4gICAgdGhpcy5iZWdpbkdlb21ldHJ5SW5zdHJ1Y3Rpb24xXyA9IG51bGw7XG4gICAgdGhpcy5iZWdpbkdlb21ldHJ5SW5zdHJ1Y3Rpb24yX1syXSA9IHRoaXMuaGl0RGV0ZWN0aW9uSW5zdHJ1Y3Rpb25zLmxlbmd0aDtcbiAgICB0aGlzLmJlZ2luR2VvbWV0cnlJbnN0cnVjdGlvbjJfID0gbnVsbDtcbiAgICB2YXIgZW5kR2VvbWV0cnlJbnN0cnVjdGlvbiA9IFtDYW52YXNJbnN0cnVjdGlvbi5FTkRfR0VPTUVUUlksIGZlYXR1cmVdO1xuICAgIHRoaXMuaW5zdHJ1Y3Rpb25zLnB1c2goZW5kR2VvbWV0cnlJbnN0cnVjdGlvbik7XG4gICAgdGhpcy5oaXREZXRlY3Rpb25JbnN0cnVjdGlvbnMucHVzaChlbmRHZW9tZXRyeUluc3RydWN0aW9uKTtcbiAgfTtcbiAgLyoqXG4gICAqIEdldCB0aGUgYnVmZmVyZWQgcmVuZGVyaW5nIGV4dGVudC4gIFJlbmRlcmluZyB3aWxsIGJlIGNsaXBwZWQgdG8gdGhlIGV4dGVudFxuICAgKiBwcm92aWRlZCB0byB0aGUgY29uc3RydWN0b3IuICBUbyBhY2NvdW50IGZvciBzeW1ib2xpemVycyB0aGF0IG1heSBpbnRlcnNlY3RcbiAgICogdGhpcyBleHRlbnQsIHdlIGNhbGN1bGF0ZSBhIGJ1ZmZlcmVkIGV4dGVudCAoZS5nLiBiYXNlZCBvbiBzdHJva2Ugd2lkdGgpLlxuICAgKiBAcmV0dXJuIHtpbXBvcnQoXCIuLi8uLi9leHRlbnQuanNcIikuRXh0ZW50fSBUaGUgYnVmZmVyZWQgcmVuZGVyaW5nIGV4dGVudC5cbiAgICogQHByb3RlY3RlZFxuICAgKi9cblxuXG4gIENhbnZhc0J1aWxkZXIucHJvdG90eXBlLmdldEJ1ZmZlcmVkTWF4RXh0ZW50ID0gZnVuY3Rpb24gKCkge1xuICAgIGlmICghdGhpcy5idWZmZXJlZE1heEV4dGVudF8pIHtcbiAgICAgIHRoaXMuYnVmZmVyZWRNYXhFeHRlbnRfID0gY2xvbmUodGhpcy5tYXhFeHRlbnQpO1xuXG4gICAgICBpZiAodGhpcy5tYXhMaW5lV2lkdGggPiAwKSB7XG4gICAgICAgIHZhciB3aWR0aCA9IHRoaXMucmVzb2x1dGlvbiAqICh0aGlzLm1heExpbmVXaWR0aCArIDEpIC8gMjtcbiAgICAgICAgYnVmZmVyKHRoaXMuYnVmZmVyZWRNYXhFeHRlbnRfLCB3aWR0aCwgdGhpcy5idWZmZXJlZE1heEV4dGVudF8pO1xuICAgICAgfVxuICAgIH1cblxuICAgIHJldHVybiB0aGlzLmJ1ZmZlcmVkTWF4RXh0ZW50XztcbiAgfTtcblxuICByZXR1cm4gQ2FudmFzQnVpbGRlcjtcbn0oVmVjdG9yQ29udGV4dCk7XG5cbmV4cG9ydCBkZWZhdWx0IENhbnZhc0J1aWxkZXI7IiwidmFyIF9fZXh0ZW5kcyA9IHRoaXMgJiYgdGhpcy5fX2V4dGVuZHMgfHwgZnVuY3Rpb24gKCkge1xuICB2YXIgX2V4dGVuZFN0YXRpY3MgPSBmdW5jdGlvbiBleHRlbmRTdGF0aWNzKGQsIGIpIHtcbiAgICBfZXh0ZW5kU3RhdGljcyA9IE9iamVjdC5zZXRQcm90b3R5cGVPZiB8fCB7XG4gICAgICBfX3Byb3RvX186IFtdXG4gICAgfSBpbnN0YW5jZW9mIEFycmF5ICYmIGZ1bmN0aW9uIChkLCBiKSB7XG4gICAgICBkLl9fcHJvdG9fXyA9IGI7XG4gICAgfSB8fCBmdW5jdGlvbiAoZCwgYikge1xuICAgICAgZm9yICh2YXIgcCBpbiBiKSB7XG4gICAgICAgIGlmIChPYmplY3QucHJvdG90eXBlLmhhc093blByb3BlcnR5LmNhbGwoYiwgcCkpIGRbcF0gPSBiW3BdO1xuICAgICAgfVxuICAgIH07XG5cbiAgICByZXR1cm4gX2V4dGVuZFN0YXRpY3MoZCwgYik7XG4gIH07XG5cbiAgcmV0dXJuIGZ1bmN0aW9uIChkLCBiKSB7XG4gICAgX2V4dGVuZFN0YXRpY3MoZCwgYik7XG5cbiAgICBmdW5jdGlvbiBfXygpIHtcbiAgICAgIHRoaXMuY29uc3RydWN0b3IgPSBkO1xuICAgIH1cblxuICAgIGQucHJvdG90eXBlID0gYiA9PT0gbnVsbCA/IE9iamVjdC5jcmVhdGUoYikgOiAoX18ucHJvdG90eXBlID0gYi5wcm90b3R5cGUsIG5ldyBfXygpKTtcbiAgfTtcbn0oKTtcbi8qKlxuICogQG1vZHVsZSBvbC9yZW5kZXIvY2FudmFzL0ltYWdlQnVpbGRlclxuICovXG5cblxuaW1wb3J0IENhbnZhc0J1aWxkZXIgZnJvbSAnLi9CdWlsZGVyLmpzJztcbmltcG9ydCBDYW52YXNJbnN0cnVjdGlvbiBmcm9tICcuL0luc3RydWN0aW9uLmpzJztcblxudmFyIENhbnZhc0ltYWdlQnVpbGRlciA9XG4vKiogQGNsYXNzICovXG5mdW5jdGlvbiAoX3N1cGVyKSB7XG4gIF9fZXh0ZW5kcyhDYW52YXNJbWFnZUJ1aWxkZXIsIF9zdXBlcik7XG4gIC8qKlxuICAgKiBAcGFyYW0ge251bWJlcn0gdG9sZXJhbmNlIFRvbGVyYW5jZS5cbiAgICogQHBhcmFtIHtpbXBvcnQoXCIuLi8uLi9leHRlbnQuanNcIikuRXh0ZW50fSBtYXhFeHRlbnQgTWF4aW11bSBleHRlbnQuXG4gICAqIEBwYXJhbSB7bnVtYmVyfSByZXNvbHV0aW9uIFJlc29sdXRpb24uXG4gICAqIEBwYXJhbSB7bnVtYmVyfSBwaXhlbFJhdGlvIFBpeGVsIHJhdGlvLlxuICAgKi9cblxuXG4gIGZ1bmN0aW9uIENhbnZhc0ltYWdlQnVpbGRlcih0b2xlcmFuY2UsIG1heEV4dGVudCwgcmVzb2x1dGlvbiwgcGl4ZWxSYXRpbykge1xuICAgIHZhciBfdGhpcyA9IF9zdXBlci5jYWxsKHRoaXMsIHRvbGVyYW5jZSwgbWF4RXh0ZW50LCByZXNvbHV0aW9uLCBwaXhlbFJhdGlvKSB8fCB0aGlzO1xuICAgIC8qKlxuICAgICAqIEBwcml2YXRlXG4gICAgICogQHR5cGUge0hUTUxDYW52YXNFbGVtZW50fEhUTUxWaWRlb0VsZW1lbnR8SFRNTEltYWdlRWxlbWVudH1cbiAgICAgKi9cblxuXG4gICAgX3RoaXMuaGl0RGV0ZWN0aW9uSW1hZ2VfID0gbnVsbDtcbiAgICAvKipcbiAgICAgKiBAcHJpdmF0ZVxuICAgICAqIEB0eXBlIHtIVE1MQ2FudmFzRWxlbWVudHxIVE1MVmlkZW9FbGVtZW50fEhUTUxJbWFnZUVsZW1lbnR9XG4gICAgICovXG5cbiAgICBfdGhpcy5pbWFnZV8gPSBudWxsO1xuICAgIC8qKlxuICAgICAqIEBwcml2YXRlXG4gICAgICogQHR5cGUge251bWJlcnx1bmRlZmluZWR9XG4gICAgICovXG5cbiAgICBfdGhpcy5pbWFnZVBpeGVsUmF0aW9fID0gdW5kZWZpbmVkO1xuICAgIC8qKlxuICAgICAqIEBwcml2YXRlXG4gICAgICogQHR5cGUge251bWJlcnx1bmRlZmluZWR9XG4gICAgICovXG5cbiAgICBfdGhpcy5hbmNob3JYXyA9IHVuZGVmaW5lZDtcbiAgICAvKipcbiAgICAgKiBAcHJpdmF0ZVxuICAgICAqIEB0eXBlIHtudW1iZXJ8dW5kZWZpbmVkfVxuICAgICAqL1xuXG4gICAgX3RoaXMuYW5jaG9yWV8gPSB1bmRlZmluZWQ7XG4gICAgLyoqXG4gICAgICogQHByaXZhdGVcbiAgICAgKiBAdHlwZSB7bnVtYmVyfHVuZGVmaW5lZH1cbiAgICAgKi9cblxuICAgIF90aGlzLmhlaWdodF8gPSB1bmRlZmluZWQ7XG4gICAgLyoqXG4gICAgICogQHByaXZhdGVcbiAgICAgKiBAdHlwZSB7bnVtYmVyfHVuZGVmaW5lZH1cbiAgICAgKi9cblxuICAgIF90aGlzLm9wYWNpdHlfID0gdW5kZWZpbmVkO1xuICAgIC8qKlxuICAgICAqIEBwcml2YXRlXG4gICAgICogQHR5cGUge251bWJlcnx1bmRlZmluZWR9XG4gICAgICovXG5cbiAgICBfdGhpcy5vcmlnaW5YXyA9IHVuZGVmaW5lZDtcbiAgICAvKipcbiAgICAgKiBAcHJpdmF0ZVxuICAgICAqIEB0eXBlIHtudW1iZXJ8dW5kZWZpbmVkfVxuICAgICAqL1xuXG4gICAgX3RoaXMub3JpZ2luWV8gPSB1bmRlZmluZWQ7XG4gICAgLyoqXG4gICAgICogQHByaXZhdGVcbiAgICAgKiBAdHlwZSB7Ym9vbGVhbnx1bmRlZmluZWR9XG4gICAgICovXG5cbiAgICBfdGhpcy5yb3RhdGVXaXRoVmlld18gPSB1bmRlZmluZWQ7XG4gICAgLyoqXG4gICAgICogQHByaXZhdGVcbiAgICAgKiBAdHlwZSB7bnVtYmVyfHVuZGVmaW5lZH1cbiAgICAgKi9cblxuICAgIF90aGlzLnJvdGF0aW9uXyA9IHVuZGVmaW5lZDtcbiAgICAvKipcbiAgICAgKiBAcHJpdmF0ZVxuICAgICAqIEB0eXBlIHtpbXBvcnQoXCIuLi8uLi9zaXplLmpzXCIpLlNpemV8dW5kZWZpbmVkfVxuICAgICAqL1xuXG4gICAgX3RoaXMuc2NhbGVfID0gdW5kZWZpbmVkO1xuICAgIC8qKlxuICAgICAqIEBwcml2YXRlXG4gICAgICogQHR5cGUge251bWJlcnx1bmRlZmluZWR9XG4gICAgICovXG5cbiAgICBfdGhpcy53aWR0aF8gPSB1bmRlZmluZWQ7XG4gICAgLyoqXG4gICAgICogRGF0YSBzaGFyZWQgd2l0aCBhIHRleHQgYnVpbGRlciBmb3IgY29tYmluZWQgZGVjbHV0dGVyaW5nLlxuICAgICAqIEBwcml2YXRlXG4gICAgICogQHR5cGUge2ltcG9ydChcIi4uL2NhbnZhcy5qc1wiKS5EZWNsdXR0ZXJJbWFnZVdpdGhUZXh0fVxuICAgICAqL1xuXG4gICAgX3RoaXMuZGVjbHV0dGVySW1hZ2VXaXRoVGV4dF8gPSB1bmRlZmluZWQ7XG4gICAgcmV0dXJuIF90aGlzO1xuICB9XG4gIC8qKlxuICAgKiBAcGFyYW0ge2ltcG9ydChcIi4uLy4uL2dlb20vUG9pbnQuanNcIikuZGVmYXVsdHxpbXBvcnQoXCIuLi9GZWF0dXJlLmpzXCIpLmRlZmF1bHR9IHBvaW50R2VvbWV0cnkgUG9pbnQgZ2VvbWV0cnkuXG4gICAqIEBwYXJhbSB7aW1wb3J0KFwiLi4vLi4vRmVhdHVyZS5qc1wiKS5GZWF0dXJlTGlrZX0gZmVhdHVyZSBGZWF0dXJlLlxuICAgKi9cblxuXG4gIENhbnZhc0ltYWdlQnVpbGRlci5wcm90b3R5cGUuZHJhd1BvaW50ID0gZnVuY3Rpb24gKHBvaW50R2VvbWV0cnksIGZlYXR1cmUpIHtcbiAgICBpZiAoIXRoaXMuaW1hZ2VfKSB7XG4gICAgICByZXR1cm47XG4gICAgfVxuXG4gICAgdGhpcy5iZWdpbkdlb21ldHJ5KHBvaW50R2VvbWV0cnksIGZlYXR1cmUpO1xuICAgIHZhciBmbGF0Q29vcmRpbmF0ZXMgPSBwb2ludEdlb21ldHJ5LmdldEZsYXRDb29yZGluYXRlcygpO1xuICAgIHZhciBzdHJpZGUgPSBwb2ludEdlb21ldHJ5LmdldFN0cmlkZSgpO1xuICAgIHZhciBteUJlZ2luID0gdGhpcy5jb29yZGluYXRlcy5sZW5ndGg7XG4gICAgdmFyIG15RW5kID0gdGhpcy5hcHBlbmRGbGF0UG9pbnRDb29yZGluYXRlcyhmbGF0Q29vcmRpbmF0ZXMsIHN0cmlkZSk7XG4gICAgdGhpcy5pbnN0cnVjdGlvbnMucHVzaChbQ2FudmFzSW5zdHJ1Y3Rpb24uRFJBV19JTUFHRSwgbXlCZWdpbiwgbXlFbmQsIHRoaXMuaW1hZ2VfLCAvLyBSZW1haW5pbmcgYXJndW1lbnRzIHRvIERSQVdfSU1BR0UgYXJlIGluIGFscGhhYmV0aWNhbCBvcmRlclxuICAgIHRoaXMuYW5jaG9yWF8gKiB0aGlzLmltYWdlUGl4ZWxSYXRpb18sIHRoaXMuYW5jaG9yWV8gKiB0aGlzLmltYWdlUGl4ZWxSYXRpb18sIE1hdGguY2VpbCh0aGlzLmhlaWdodF8gKiB0aGlzLmltYWdlUGl4ZWxSYXRpb18pLCB0aGlzLm9wYWNpdHlfLCB0aGlzLm9yaWdpblhfLCB0aGlzLm9yaWdpbllfLCB0aGlzLnJvdGF0ZVdpdGhWaWV3XywgdGhpcy5yb3RhdGlvbl8sIFt0aGlzLnNjYWxlX1swXSAqIHRoaXMucGl4ZWxSYXRpbyAvIHRoaXMuaW1hZ2VQaXhlbFJhdGlvXywgdGhpcy5zY2FsZV9bMV0gKiB0aGlzLnBpeGVsUmF0aW8gLyB0aGlzLmltYWdlUGl4ZWxSYXRpb19dLCBNYXRoLmNlaWwodGhpcy53aWR0aF8gKiB0aGlzLmltYWdlUGl4ZWxSYXRpb18pLCB0aGlzLmRlY2x1dHRlckltYWdlV2l0aFRleHRfXSk7XG4gICAgdGhpcy5oaXREZXRlY3Rpb25JbnN0cnVjdGlvbnMucHVzaChbQ2FudmFzSW5zdHJ1Y3Rpb24uRFJBV19JTUFHRSwgbXlCZWdpbiwgbXlFbmQsIHRoaXMuaGl0RGV0ZWN0aW9uSW1hZ2VfLCAvLyBSZW1haW5pbmcgYXJndW1lbnRzIHRvIERSQVdfSU1BR0UgYXJlIGluIGFscGhhYmV0aWNhbCBvcmRlclxuICAgIHRoaXMuYW5jaG9yWF8sIHRoaXMuYW5jaG9yWV8sIHRoaXMuaGVpZ2h0XywgdGhpcy5vcGFjaXR5XywgdGhpcy5vcmlnaW5YXywgdGhpcy5vcmlnaW5ZXywgdGhpcy5yb3RhdGVXaXRoVmlld18sIHRoaXMucm90YXRpb25fLCB0aGlzLnNjYWxlXywgdGhpcy53aWR0aF8sIHRoaXMuZGVjbHV0dGVySW1hZ2VXaXRoVGV4dF9dKTtcbiAgICB0aGlzLmVuZEdlb21ldHJ5KGZlYXR1cmUpO1xuICB9O1xuICAvKipcbiAgICogQHBhcmFtIHtpbXBvcnQoXCIuLi8uLi9nZW9tL011bHRpUG9pbnQuanNcIikuZGVmYXVsdHxpbXBvcnQoXCIuLi9GZWF0dXJlLmpzXCIpLmRlZmF1bHR9IG11bHRpUG9pbnRHZW9tZXRyeSBNdWx0aVBvaW50IGdlb21ldHJ5LlxuICAgKiBAcGFyYW0ge2ltcG9ydChcIi4uLy4uL0ZlYXR1cmUuanNcIikuRmVhdHVyZUxpa2V9IGZlYXR1cmUgRmVhdHVyZS5cbiAgICovXG5cblxuICBDYW52YXNJbWFnZUJ1aWxkZXIucHJvdG90eXBlLmRyYXdNdWx0aVBvaW50ID0gZnVuY3Rpb24gKG11bHRpUG9pbnRHZW9tZXRyeSwgZmVhdHVyZSkge1xuICAgIGlmICghdGhpcy5pbWFnZV8pIHtcbiAgICAgIHJldHVybjtcbiAgICB9XG5cbiAgICB0aGlzLmJlZ2luR2VvbWV0cnkobXVsdGlQb2ludEdlb21ldHJ5LCBmZWF0dXJlKTtcbiAgICB2YXIgZmxhdENvb3JkaW5hdGVzID0gbXVsdGlQb2ludEdlb21ldHJ5LmdldEZsYXRDb29yZGluYXRlcygpO1xuICAgIHZhciBzdHJpZGUgPSBtdWx0aVBvaW50R2VvbWV0cnkuZ2V0U3RyaWRlKCk7XG4gICAgdmFyIG15QmVnaW4gPSB0aGlzLmNvb3JkaW5hdGVzLmxlbmd0aDtcbiAgICB2YXIgbXlFbmQgPSB0aGlzLmFwcGVuZEZsYXRQb2ludENvb3JkaW5hdGVzKGZsYXRDb29yZGluYXRlcywgc3RyaWRlKTtcbiAgICB0aGlzLmluc3RydWN0aW9ucy5wdXNoKFtDYW52YXNJbnN0cnVjdGlvbi5EUkFXX0lNQUdFLCBteUJlZ2luLCBteUVuZCwgdGhpcy5pbWFnZV8sIC8vIFJlbWFpbmluZyBhcmd1bWVudHMgdG8gRFJBV19JTUFHRSBhcmUgaW4gYWxwaGFiZXRpY2FsIG9yZGVyXG4gICAgdGhpcy5hbmNob3JYXyAqIHRoaXMuaW1hZ2VQaXhlbFJhdGlvXywgdGhpcy5hbmNob3JZXyAqIHRoaXMuaW1hZ2VQaXhlbFJhdGlvXywgTWF0aC5jZWlsKHRoaXMuaGVpZ2h0XyAqIHRoaXMuaW1hZ2VQaXhlbFJhdGlvXyksIHRoaXMub3BhY2l0eV8sIHRoaXMub3JpZ2luWF8sIHRoaXMub3JpZ2luWV8sIHRoaXMucm90YXRlV2l0aFZpZXdfLCB0aGlzLnJvdGF0aW9uXywgW3RoaXMuc2NhbGVfWzBdICogdGhpcy5waXhlbFJhdGlvIC8gdGhpcy5pbWFnZVBpeGVsUmF0aW9fLCB0aGlzLnNjYWxlX1sxXSAqIHRoaXMucGl4ZWxSYXRpbyAvIHRoaXMuaW1hZ2VQaXhlbFJhdGlvX10sIE1hdGguY2VpbCh0aGlzLndpZHRoXyAqIHRoaXMuaW1hZ2VQaXhlbFJhdGlvXyksIHRoaXMuZGVjbHV0dGVySW1hZ2VXaXRoVGV4dF9dKTtcbiAgICB0aGlzLmhpdERldGVjdGlvbkluc3RydWN0aW9ucy5wdXNoKFtDYW52YXNJbnN0cnVjdGlvbi5EUkFXX0lNQUdFLCBteUJlZ2luLCBteUVuZCwgdGhpcy5oaXREZXRlY3Rpb25JbWFnZV8sIC8vIFJlbWFpbmluZyBhcmd1bWVudHMgdG8gRFJBV19JTUFHRSBhcmUgaW4gYWxwaGFiZXRpY2FsIG9yZGVyXG4gICAgdGhpcy5hbmNob3JYXywgdGhpcy5hbmNob3JZXywgdGhpcy5oZWlnaHRfLCB0aGlzLm9wYWNpdHlfLCB0aGlzLm9yaWdpblhfLCB0aGlzLm9yaWdpbllfLCB0aGlzLnJvdGF0ZVdpdGhWaWV3XywgdGhpcy5yb3RhdGlvbl8sIHRoaXMuc2NhbGVfLCB0aGlzLndpZHRoXywgdGhpcy5kZWNsdXR0ZXJJbWFnZVdpdGhUZXh0X10pO1xuICAgIHRoaXMuZW5kR2VvbWV0cnkoZmVhdHVyZSk7XG4gIH07XG4gIC8qKlxuICAgKiBAcmV0dXJuIHtpbXBvcnQoXCIuLi9jYW52YXMuanNcIikuU2VyaWFsaXphYmxlSW5zdHJ1Y3Rpb25zfSB0aGUgc2VyaWFsaXphYmxlIGluc3RydWN0aW9ucy5cbiAgICovXG5cblxuICBDYW52YXNJbWFnZUJ1aWxkZXIucHJvdG90eXBlLmZpbmlzaCA9IGZ1bmN0aW9uICgpIHtcbiAgICB0aGlzLnJldmVyc2VIaXREZXRlY3Rpb25JbnN0cnVjdGlvbnMoKTsgLy8gRklYTUUgdGhpcyBkb2Vzbid0IHJlYWxseSBwcm90ZWN0IHVzIGFnYWluc3QgZnVydGhlciBjYWxscyB0byBkcmF3Kkdlb21ldHJ5XG5cbiAgICB0aGlzLmFuY2hvclhfID0gdW5kZWZpbmVkO1xuICAgIHRoaXMuYW5jaG9yWV8gPSB1bmRlZmluZWQ7XG4gICAgdGhpcy5oaXREZXRlY3Rpb25JbWFnZV8gPSBudWxsO1xuICAgIHRoaXMuaW1hZ2VfID0gbnVsbDtcbiAgICB0aGlzLmltYWdlUGl4ZWxSYXRpb18gPSB1bmRlZmluZWQ7XG4gICAgdGhpcy5oZWlnaHRfID0gdW5kZWZpbmVkO1xuICAgIHRoaXMuc2NhbGVfID0gdW5kZWZpbmVkO1xuICAgIHRoaXMub3BhY2l0eV8gPSB1bmRlZmluZWQ7XG4gICAgdGhpcy5vcmlnaW5YXyA9IHVuZGVmaW5lZDtcbiAgICB0aGlzLm9yaWdpbllfID0gdW5kZWZpbmVkO1xuICAgIHRoaXMucm90YXRlV2l0aFZpZXdfID0gdW5kZWZpbmVkO1xuICAgIHRoaXMucm90YXRpb25fID0gdW5kZWZpbmVkO1xuICAgIHRoaXMud2lkdGhfID0gdW5kZWZpbmVkO1xuICAgIHJldHVybiBfc3VwZXIucHJvdG90eXBlLmZpbmlzaC5jYWxsKHRoaXMpO1xuICB9O1xuICAvKipcbiAgICogQHBhcmFtIHtpbXBvcnQoXCIuLi8uLi9zdHlsZS9JbWFnZS5qc1wiKS5kZWZhdWx0fSBpbWFnZVN0eWxlIEltYWdlIHN0eWxlLlxuICAgKiBAcGFyYW0ge09iamVjdD19IG9wdF9zaGFyZWREYXRhIFNoYXJlZCBkYXRhLlxuICAgKi9cblxuXG4gIENhbnZhc0ltYWdlQnVpbGRlci5wcm90b3R5cGUuc2V0SW1hZ2VTdHlsZSA9IGZ1bmN0aW9uIChpbWFnZVN0eWxlLCBvcHRfc2hhcmVkRGF0YSkge1xuICAgIHZhciBhbmNob3IgPSBpbWFnZVN0eWxlLmdldEFuY2hvcigpO1xuICAgIHZhciBzaXplID0gaW1hZ2VTdHlsZS5nZXRTaXplKCk7XG4gICAgdmFyIGhpdERldGVjdGlvbkltYWdlID0gaW1hZ2VTdHlsZS5nZXRIaXREZXRlY3Rpb25JbWFnZSgpO1xuICAgIHZhciBpbWFnZSA9IGltYWdlU3R5bGUuZ2V0SW1hZ2UodGhpcy5waXhlbFJhdGlvKTtcbiAgICB2YXIgb3JpZ2luID0gaW1hZ2VTdHlsZS5nZXRPcmlnaW4oKTtcbiAgICB0aGlzLmltYWdlUGl4ZWxSYXRpb18gPSBpbWFnZVN0eWxlLmdldFBpeGVsUmF0aW8odGhpcy5waXhlbFJhdGlvKTtcbiAgICB0aGlzLmFuY2hvclhfID0gYW5jaG9yWzBdO1xuICAgIHRoaXMuYW5jaG9yWV8gPSBhbmNob3JbMV07XG4gICAgdGhpcy5oaXREZXRlY3Rpb25JbWFnZV8gPSBoaXREZXRlY3Rpb25JbWFnZTtcbiAgICB0aGlzLmltYWdlXyA9IGltYWdlO1xuICAgIHRoaXMuaGVpZ2h0XyA9IHNpemVbMV07XG4gICAgdGhpcy5vcGFjaXR5XyA9IGltYWdlU3R5bGUuZ2V0T3BhY2l0eSgpO1xuICAgIHRoaXMub3JpZ2luWF8gPSBvcmlnaW5bMF07XG4gICAgdGhpcy5vcmlnaW5ZXyA9IG9yaWdpblsxXTtcbiAgICB0aGlzLnJvdGF0ZVdpdGhWaWV3XyA9IGltYWdlU3R5bGUuZ2V0Um90YXRlV2l0aFZpZXcoKTtcbiAgICB0aGlzLnJvdGF0aW9uXyA9IGltYWdlU3R5bGUuZ2V0Um90YXRpb24oKTtcbiAgICB0aGlzLnNjYWxlXyA9IGltYWdlU3R5bGUuZ2V0U2NhbGVBcnJheSgpO1xuICAgIHRoaXMud2lkdGhfID0gc2l6ZVswXTtcbiAgICB0aGlzLmRlY2x1dHRlckltYWdlV2l0aFRleHRfID0gb3B0X3NoYXJlZERhdGE7XG4gIH07XG5cbiAgcmV0dXJuIENhbnZhc0ltYWdlQnVpbGRlcjtcbn0oQ2FudmFzQnVpbGRlcik7XG5cbmV4cG9ydCBkZWZhdWx0IENhbnZhc0ltYWdlQnVpbGRlcjsiLCJ2YXIgX19leHRlbmRzID0gdGhpcyAmJiB0aGlzLl9fZXh0ZW5kcyB8fCBmdW5jdGlvbiAoKSB7XG4gIHZhciBfZXh0ZW5kU3RhdGljcyA9IGZ1bmN0aW9uIGV4dGVuZFN0YXRpY3MoZCwgYikge1xuICAgIF9leHRlbmRTdGF0aWNzID0gT2JqZWN0LnNldFByb3RvdHlwZU9mIHx8IHtcbiAgICAgIF9fcHJvdG9fXzogW11cbiAgICB9IGluc3RhbmNlb2YgQXJyYXkgJiYgZnVuY3Rpb24gKGQsIGIpIHtcbiAgICAgIGQuX19wcm90b19fID0gYjtcbiAgICB9IHx8IGZ1bmN0aW9uIChkLCBiKSB7XG4gICAgICBmb3IgKHZhciBwIGluIGIpIHtcbiAgICAgICAgaWYgKE9iamVjdC5wcm90b3R5cGUuaGFzT3duUHJvcGVydHkuY2FsbChiLCBwKSkgZFtwXSA9IGJbcF07XG4gICAgICB9XG4gICAgfTtcblxuICAgIHJldHVybiBfZXh0ZW5kU3RhdGljcyhkLCBiKTtcbiAgfTtcblxuICByZXR1cm4gZnVuY3Rpb24gKGQsIGIpIHtcbiAgICBfZXh0ZW5kU3RhdGljcyhkLCBiKTtcblxuICAgIGZ1bmN0aW9uIF9fKCkge1xuICAgICAgdGhpcy5jb25zdHJ1Y3RvciA9IGQ7XG4gICAgfVxuXG4gICAgZC5wcm90b3R5cGUgPSBiID09PSBudWxsID8gT2JqZWN0LmNyZWF0ZShiKSA6IChfXy5wcm90b3R5cGUgPSBiLnByb3RvdHlwZSwgbmV3IF9fKCkpO1xuICB9O1xufSgpO1xuLyoqXG4gKiBAbW9kdWxlIG9sL3JlbmRlci9jYW52YXMvTGluZVN0cmluZ0J1aWxkZXJcbiAqL1xuXG5cbmltcG9ydCBDYW52YXNCdWlsZGVyIGZyb20gJy4vQnVpbGRlci5qcyc7XG5pbXBvcnQgQ2FudmFzSW5zdHJ1Y3Rpb24sIHsgYmVnaW5QYXRoSW5zdHJ1Y3Rpb24sIHN0cm9rZUluc3RydWN0aW9uIH0gZnJvbSAnLi9JbnN0cnVjdGlvbi5qcyc7XG5cbnZhciBDYW52YXNMaW5lU3RyaW5nQnVpbGRlciA9XG4vKiogQGNsYXNzICovXG5mdW5jdGlvbiAoX3N1cGVyKSB7XG4gIF9fZXh0ZW5kcyhDYW52YXNMaW5lU3RyaW5nQnVpbGRlciwgX3N1cGVyKTtcbiAgLyoqXG4gICAqIEBwYXJhbSB7bnVtYmVyfSB0b2xlcmFuY2UgVG9sZXJhbmNlLlxuICAgKiBAcGFyYW0ge2ltcG9ydChcIi4uLy4uL2V4dGVudC5qc1wiKS5FeHRlbnR9IG1heEV4dGVudCBNYXhpbXVtIGV4dGVudC5cbiAgICogQHBhcmFtIHtudW1iZXJ9IHJlc29sdXRpb24gUmVzb2x1dGlvbi5cbiAgICogQHBhcmFtIHtudW1iZXJ9IHBpeGVsUmF0aW8gUGl4ZWwgcmF0aW8uXG4gICAqL1xuXG5cbiAgZnVuY3Rpb24gQ2FudmFzTGluZVN0cmluZ0J1aWxkZXIodG9sZXJhbmNlLCBtYXhFeHRlbnQsIHJlc29sdXRpb24sIHBpeGVsUmF0aW8pIHtcbiAgICByZXR1cm4gX3N1cGVyLmNhbGwodGhpcywgdG9sZXJhbmNlLCBtYXhFeHRlbnQsIHJlc29sdXRpb24sIHBpeGVsUmF0aW8pIHx8IHRoaXM7XG4gIH1cbiAgLyoqXG4gICAqIEBwYXJhbSB7QXJyYXk8bnVtYmVyPn0gZmxhdENvb3JkaW5hdGVzIEZsYXQgY29vcmRpbmF0ZXMuXG4gICAqIEBwYXJhbSB7bnVtYmVyfSBvZmZzZXQgT2Zmc2V0LlxuICAgKiBAcGFyYW0ge251bWJlcn0gZW5kIEVuZC5cbiAgICogQHBhcmFtIHtudW1iZXJ9IHN0cmlkZSBTdHJpZGUuXG4gICAqIEBwcml2YXRlXG4gICAqIEByZXR1cm4ge251bWJlcn0gZW5kLlxuICAgKi9cblxuXG4gIENhbnZhc0xpbmVTdHJpbmdCdWlsZGVyLnByb3RvdHlwZS5kcmF3RmxhdENvb3JkaW5hdGVzXyA9IGZ1bmN0aW9uIChmbGF0Q29vcmRpbmF0ZXMsIG9mZnNldCwgZW5kLCBzdHJpZGUpIHtcbiAgICB2YXIgbXlCZWdpbiA9IHRoaXMuY29vcmRpbmF0ZXMubGVuZ3RoO1xuICAgIHZhciBteUVuZCA9IHRoaXMuYXBwZW5kRmxhdExpbmVDb29yZGluYXRlcyhmbGF0Q29vcmRpbmF0ZXMsIG9mZnNldCwgZW5kLCBzdHJpZGUsIGZhbHNlLCBmYWxzZSk7XG4gICAgdmFyIG1vdmVUb0xpbmVUb0luc3RydWN0aW9uID0gW0NhbnZhc0luc3RydWN0aW9uLk1PVkVfVE9fTElORV9UTywgbXlCZWdpbiwgbXlFbmRdO1xuICAgIHRoaXMuaW5zdHJ1Y3Rpb25zLnB1c2gobW92ZVRvTGluZVRvSW5zdHJ1Y3Rpb24pO1xuICAgIHRoaXMuaGl0RGV0ZWN0aW9uSW5zdHJ1Y3Rpb25zLnB1c2gobW92ZVRvTGluZVRvSW5zdHJ1Y3Rpb24pO1xuICAgIHJldHVybiBlbmQ7XG4gIH07XG4gIC8qKlxuICAgKiBAcGFyYW0ge2ltcG9ydChcIi4uLy4uL2dlb20vTGluZVN0cmluZy5qc1wiKS5kZWZhdWx0fGltcG9ydChcIi4uL0ZlYXR1cmUuanNcIikuZGVmYXVsdH0gbGluZVN0cmluZ0dlb21ldHJ5IExpbmUgc3RyaW5nIGdlb21ldHJ5LlxuICAgKiBAcGFyYW0ge2ltcG9ydChcIi4uLy4uL0ZlYXR1cmUuanNcIikuRmVhdHVyZUxpa2V9IGZlYXR1cmUgRmVhdHVyZS5cbiAgICovXG5cblxuICBDYW52YXNMaW5lU3RyaW5nQnVpbGRlci5wcm90b3R5cGUuZHJhd0xpbmVTdHJpbmcgPSBmdW5jdGlvbiAobGluZVN0cmluZ0dlb21ldHJ5LCBmZWF0dXJlKSB7XG4gICAgdmFyIHN0YXRlID0gdGhpcy5zdGF0ZTtcbiAgICB2YXIgc3Ryb2tlU3R5bGUgPSBzdGF0ZS5zdHJva2VTdHlsZTtcbiAgICB2YXIgbGluZVdpZHRoID0gc3RhdGUubGluZVdpZHRoO1xuXG4gICAgaWYgKHN0cm9rZVN0eWxlID09PSB1bmRlZmluZWQgfHwgbGluZVdpZHRoID09PSB1bmRlZmluZWQpIHtcbiAgICAgIHJldHVybjtcbiAgICB9XG5cbiAgICB0aGlzLnVwZGF0ZVN0cm9rZVN0eWxlKHN0YXRlLCB0aGlzLmFwcGx5U3Ryb2tlKTtcbiAgICB0aGlzLmJlZ2luR2VvbWV0cnkobGluZVN0cmluZ0dlb21ldHJ5LCBmZWF0dXJlKTtcbiAgICB0aGlzLmhpdERldGVjdGlvbkluc3RydWN0aW9ucy5wdXNoKFtDYW52YXNJbnN0cnVjdGlvbi5TRVRfU1RST0tFX1NUWUxFLCBzdGF0ZS5zdHJva2VTdHlsZSwgc3RhdGUubGluZVdpZHRoLCBzdGF0ZS5saW5lQ2FwLCBzdGF0ZS5saW5lSm9pbiwgc3RhdGUubWl0ZXJMaW1pdCwgc3RhdGUubGluZURhc2gsIHN0YXRlLmxpbmVEYXNoT2Zmc2V0XSwgYmVnaW5QYXRoSW5zdHJ1Y3Rpb24pO1xuICAgIHZhciBmbGF0Q29vcmRpbmF0ZXMgPSBsaW5lU3RyaW5nR2VvbWV0cnkuZ2V0RmxhdENvb3JkaW5hdGVzKCk7XG4gICAgdmFyIHN0cmlkZSA9IGxpbmVTdHJpbmdHZW9tZXRyeS5nZXRTdHJpZGUoKTtcbiAgICB0aGlzLmRyYXdGbGF0Q29vcmRpbmF0ZXNfKGZsYXRDb29yZGluYXRlcywgMCwgZmxhdENvb3JkaW5hdGVzLmxlbmd0aCwgc3RyaWRlKTtcbiAgICB0aGlzLmhpdERldGVjdGlvbkluc3RydWN0aW9ucy5wdXNoKHN0cm9rZUluc3RydWN0aW9uKTtcbiAgICB0aGlzLmVuZEdlb21ldHJ5KGZlYXR1cmUpO1xuICB9O1xuICAvKipcbiAgICogQHBhcmFtIHtpbXBvcnQoXCIuLi8uLi9nZW9tL011bHRpTGluZVN0cmluZy5qc1wiKS5kZWZhdWx0fGltcG9ydChcIi4uL0ZlYXR1cmUuanNcIikuZGVmYXVsdH0gbXVsdGlMaW5lU3RyaW5nR2VvbWV0cnkgTXVsdGlMaW5lU3RyaW5nIGdlb21ldHJ5LlxuICAgKiBAcGFyYW0ge2ltcG9ydChcIi4uLy4uL0ZlYXR1cmUuanNcIikuRmVhdHVyZUxpa2V9IGZlYXR1cmUgRmVhdHVyZS5cbiAgICovXG5cblxuICBDYW52YXNMaW5lU3RyaW5nQnVpbGRlci5wcm90b3R5cGUuZHJhd011bHRpTGluZVN0cmluZyA9IGZ1bmN0aW9uIChtdWx0aUxpbmVTdHJpbmdHZW9tZXRyeSwgZmVhdHVyZSkge1xuICAgIHZhciBzdGF0ZSA9IHRoaXMuc3RhdGU7XG4gICAgdmFyIHN0cm9rZVN0eWxlID0gc3RhdGUuc3Ryb2tlU3R5bGU7XG4gICAgdmFyIGxpbmVXaWR0aCA9IHN0YXRlLmxpbmVXaWR0aDtcblxuICAgIGlmIChzdHJva2VTdHlsZSA9PT0gdW5kZWZpbmVkIHx8IGxpbmVXaWR0aCA9PT0gdW5kZWZpbmVkKSB7XG4gICAgICByZXR1cm47XG4gICAgfVxuXG4gICAgdGhpcy51cGRhdGVTdHJva2VTdHlsZShzdGF0ZSwgdGhpcy5hcHBseVN0cm9rZSk7XG4gICAgdGhpcy5iZWdpbkdlb21ldHJ5KG11bHRpTGluZVN0cmluZ0dlb21ldHJ5LCBmZWF0dXJlKTtcbiAgICB0aGlzLmhpdERldGVjdGlvbkluc3RydWN0aW9ucy5wdXNoKFtDYW52YXNJbnN0cnVjdGlvbi5TRVRfU1RST0tFX1NUWUxFLCBzdGF0ZS5zdHJva2VTdHlsZSwgc3RhdGUubGluZVdpZHRoLCBzdGF0ZS5saW5lQ2FwLCBzdGF0ZS5saW5lSm9pbiwgc3RhdGUubWl0ZXJMaW1pdCwgc3RhdGUubGluZURhc2gsIHN0YXRlLmxpbmVEYXNoT2Zmc2V0XSwgYmVnaW5QYXRoSW5zdHJ1Y3Rpb24pO1xuICAgIHZhciBlbmRzID0gbXVsdGlMaW5lU3RyaW5nR2VvbWV0cnkuZ2V0RW5kcygpO1xuICAgIHZhciBmbGF0Q29vcmRpbmF0ZXMgPSBtdWx0aUxpbmVTdHJpbmdHZW9tZXRyeS5nZXRGbGF0Q29vcmRpbmF0ZXMoKTtcbiAgICB2YXIgc3RyaWRlID0gbXVsdGlMaW5lU3RyaW5nR2VvbWV0cnkuZ2V0U3RyaWRlKCk7XG4gICAgdmFyIG9mZnNldCA9IDA7XG5cbiAgICBmb3IgKHZhciBpID0gMCwgaWkgPSBlbmRzLmxlbmd0aDsgaSA8IGlpOyArK2kpIHtcbiAgICAgIG9mZnNldCA9IHRoaXMuZHJhd0ZsYXRDb29yZGluYXRlc18oZmxhdENvb3JkaW5hdGVzLCBvZmZzZXQsXG4gICAgICAvKiogQHR5cGUge251bWJlcn0gKi9cbiAgICAgIGVuZHNbaV0sIHN0cmlkZSk7XG4gICAgfVxuXG4gICAgdGhpcy5oaXREZXRlY3Rpb25JbnN0cnVjdGlvbnMucHVzaChzdHJva2VJbnN0cnVjdGlvbik7XG4gICAgdGhpcy5lbmRHZW9tZXRyeShmZWF0dXJlKTtcbiAgfTtcbiAgLyoqXG4gICAqIEByZXR1cm4ge2ltcG9ydChcIi4uL2NhbnZhcy5qc1wiKS5TZXJpYWxpemFibGVJbnN0cnVjdGlvbnN9IHRoZSBzZXJpYWxpemFibGUgaW5zdHJ1Y3Rpb25zLlxuICAgKi9cblxuXG4gIENhbnZhc0xpbmVTdHJpbmdCdWlsZGVyLnByb3RvdHlwZS5maW5pc2ggPSBmdW5jdGlvbiAoKSB7XG4gICAgdmFyIHN0YXRlID0gdGhpcy5zdGF0ZTtcblxuICAgIGlmIChzdGF0ZS5sYXN0U3Ryb2tlICE9IHVuZGVmaW5lZCAmJiBzdGF0ZS5sYXN0U3Ryb2tlICE9IHRoaXMuY29vcmRpbmF0ZXMubGVuZ3RoKSB7XG4gICAgICB0aGlzLmluc3RydWN0aW9ucy5wdXNoKHN0cm9rZUluc3RydWN0aW9uKTtcbiAgICB9XG5cbiAgICB0aGlzLnJldmVyc2VIaXREZXRlY3Rpb25JbnN0cnVjdGlvbnMoKTtcbiAgICB0aGlzLnN0YXRlID0gbnVsbDtcbiAgICByZXR1cm4gX3N1cGVyLnByb3RvdHlwZS5maW5pc2guY2FsbCh0aGlzKTtcbiAgfTtcbiAgLyoqXG4gICAqIEBwYXJhbSB7aW1wb3J0KFwiLi4vY2FudmFzLmpzXCIpLkZpbGxTdHJva2VTdGF0ZX0gc3RhdGUgU3RhdGUuXG4gICAqL1xuXG5cbiAgQ2FudmFzTGluZVN0cmluZ0J1aWxkZXIucHJvdG90eXBlLmFwcGx5U3Ryb2tlID0gZnVuY3Rpb24gKHN0YXRlKSB7XG4gICAgaWYgKHN0YXRlLmxhc3RTdHJva2UgIT0gdW5kZWZpbmVkICYmIHN0YXRlLmxhc3RTdHJva2UgIT0gdGhpcy5jb29yZGluYXRlcy5sZW5ndGgpIHtcbiAgICAgIHRoaXMuaW5zdHJ1Y3Rpb25zLnB1c2goc3Ryb2tlSW5zdHJ1Y3Rpb24pO1xuICAgICAgc3RhdGUubGFzdFN0cm9rZSA9IHRoaXMuY29vcmRpbmF0ZXMubGVuZ3RoO1xuICAgIH1cblxuICAgIHN0YXRlLmxhc3RTdHJva2UgPSAwO1xuXG4gICAgX3N1cGVyLnByb3RvdHlwZS5hcHBseVN0cm9rZS5jYWxsKHRoaXMsIHN0YXRlKTtcblxuICAgIHRoaXMuaW5zdHJ1Y3Rpb25zLnB1c2goYmVnaW5QYXRoSW5zdHJ1Y3Rpb24pO1xuICB9O1xuXG4gIHJldHVybiBDYW52YXNMaW5lU3RyaW5nQnVpbGRlcjtcbn0oQ2FudmFzQnVpbGRlcik7XG5cbmV4cG9ydCBkZWZhdWx0IENhbnZhc0xpbmVTdHJpbmdCdWlsZGVyOyIsInZhciBfX2V4dGVuZHMgPSB0aGlzICYmIHRoaXMuX19leHRlbmRzIHx8IGZ1bmN0aW9uICgpIHtcbiAgdmFyIF9leHRlbmRTdGF0aWNzID0gZnVuY3Rpb24gZXh0ZW5kU3RhdGljcyhkLCBiKSB7XG4gICAgX2V4dGVuZFN0YXRpY3MgPSBPYmplY3Quc2V0UHJvdG90eXBlT2YgfHwge1xuICAgICAgX19wcm90b19fOiBbXVxuICAgIH0gaW5zdGFuY2VvZiBBcnJheSAmJiBmdW5jdGlvbiAoZCwgYikge1xuICAgICAgZC5fX3Byb3RvX18gPSBiO1xuICAgIH0gfHwgZnVuY3Rpb24gKGQsIGIpIHtcbiAgICAgIGZvciAodmFyIHAgaW4gYikge1xuICAgICAgICBpZiAoT2JqZWN0LnByb3RvdHlwZS5oYXNPd25Qcm9wZXJ0eS5jYWxsKGIsIHApKSBkW3BdID0gYltwXTtcbiAgICAgIH1cbiAgICB9O1xuXG4gICAgcmV0dXJuIF9leHRlbmRTdGF0aWNzKGQsIGIpO1xuICB9O1xuXG4gIHJldHVybiBmdW5jdGlvbiAoZCwgYikge1xuICAgIF9leHRlbmRTdGF0aWNzKGQsIGIpO1xuXG4gICAgZnVuY3Rpb24gX18oKSB7XG4gICAgICB0aGlzLmNvbnN0cnVjdG9yID0gZDtcbiAgICB9XG5cbiAgICBkLnByb3RvdHlwZSA9IGIgPT09IG51bGwgPyBPYmplY3QuY3JlYXRlKGIpIDogKF9fLnByb3RvdHlwZSA9IGIucHJvdG90eXBlLCBuZXcgX18oKSk7XG4gIH07XG59KCk7XG4vKipcbiAqIEBtb2R1bGUgb2wvcmVuZGVyL2NhbnZhcy9Qb2x5Z29uQnVpbGRlclxuICovXG5cblxuaW1wb3J0IENhbnZhc0J1aWxkZXIgZnJvbSAnLi9CdWlsZGVyLmpzJztcbmltcG9ydCBDYW52YXNJbnN0cnVjdGlvbiwgeyBiZWdpblBhdGhJbnN0cnVjdGlvbiwgY2xvc2VQYXRoSW5zdHJ1Y3Rpb24sIGZpbGxJbnN0cnVjdGlvbiwgc3Ryb2tlSW5zdHJ1Y3Rpb24gfSBmcm9tICcuL0luc3RydWN0aW9uLmpzJztcbmltcG9ydCB7IGRlZmF1bHRGaWxsU3R5bGUgfSBmcm9tICcuLi9jYW52YXMuanMnO1xuaW1wb3J0IHsgc25hcCB9IGZyb20gJy4uLy4uL2dlb20vZmxhdC9zaW1wbGlmeS5qcyc7XG5cbnZhciBDYW52YXNQb2x5Z29uQnVpbGRlciA9XG4vKiogQGNsYXNzICovXG5mdW5jdGlvbiAoX3N1cGVyKSB7XG4gIF9fZXh0ZW5kcyhDYW52YXNQb2x5Z29uQnVpbGRlciwgX3N1cGVyKTtcbiAgLyoqXG4gICAqIEBwYXJhbSB7bnVtYmVyfSB0b2xlcmFuY2UgVG9sZXJhbmNlLlxuICAgKiBAcGFyYW0ge2ltcG9ydChcIi4uLy4uL2V4dGVudC5qc1wiKS5FeHRlbnR9IG1heEV4dGVudCBNYXhpbXVtIGV4dGVudC5cbiAgICogQHBhcmFtIHtudW1iZXJ9IHJlc29sdXRpb24gUmVzb2x1dGlvbi5cbiAgICogQHBhcmFtIHtudW1iZXJ9IHBpeGVsUmF0aW8gUGl4ZWwgcmF0aW8uXG4gICAqL1xuXG5cbiAgZnVuY3Rpb24gQ2FudmFzUG9seWdvbkJ1aWxkZXIodG9sZXJhbmNlLCBtYXhFeHRlbnQsIHJlc29sdXRpb24sIHBpeGVsUmF0aW8pIHtcbiAgICByZXR1cm4gX3N1cGVyLmNhbGwodGhpcywgdG9sZXJhbmNlLCBtYXhFeHRlbnQsIHJlc29sdXRpb24sIHBpeGVsUmF0aW8pIHx8IHRoaXM7XG4gIH1cbiAgLyoqXG4gICAqIEBwYXJhbSB7QXJyYXk8bnVtYmVyPn0gZmxhdENvb3JkaW5hdGVzIEZsYXQgY29vcmRpbmF0ZXMuXG4gICAqIEBwYXJhbSB7bnVtYmVyfSBvZmZzZXQgT2Zmc2V0LlxuICAgKiBAcGFyYW0ge0FycmF5PG51bWJlcj59IGVuZHMgRW5kcy5cbiAgICogQHBhcmFtIHtudW1iZXJ9IHN0cmlkZSBTdHJpZGUuXG4gICAqIEBwcml2YXRlXG4gICAqIEByZXR1cm4ge251bWJlcn0gRW5kLlxuICAgKi9cblxuXG4gIENhbnZhc1BvbHlnb25CdWlsZGVyLnByb3RvdHlwZS5kcmF3RmxhdENvb3JkaW5hdGVzc18gPSBmdW5jdGlvbiAoZmxhdENvb3JkaW5hdGVzLCBvZmZzZXQsIGVuZHMsIHN0cmlkZSkge1xuICAgIHZhciBzdGF0ZSA9IHRoaXMuc3RhdGU7XG4gICAgdmFyIGZpbGwgPSBzdGF0ZS5maWxsU3R5bGUgIT09IHVuZGVmaW5lZDtcbiAgICB2YXIgc3Ryb2tlID0gc3RhdGUuc3Ryb2tlU3R5bGUgIT09IHVuZGVmaW5lZDtcbiAgICB2YXIgbnVtRW5kcyA9IGVuZHMubGVuZ3RoO1xuICAgIHRoaXMuaW5zdHJ1Y3Rpb25zLnB1c2goYmVnaW5QYXRoSW5zdHJ1Y3Rpb24pO1xuICAgIHRoaXMuaGl0RGV0ZWN0aW9uSW5zdHJ1Y3Rpb25zLnB1c2goYmVnaW5QYXRoSW5zdHJ1Y3Rpb24pO1xuXG4gICAgZm9yICh2YXIgaSA9IDA7IGkgPCBudW1FbmRzOyArK2kpIHtcbiAgICAgIHZhciBlbmQgPSBlbmRzW2ldO1xuICAgICAgdmFyIG15QmVnaW4gPSB0aGlzLmNvb3JkaW5hdGVzLmxlbmd0aDtcbiAgICAgIHZhciBteUVuZCA9IHRoaXMuYXBwZW5kRmxhdExpbmVDb29yZGluYXRlcyhmbGF0Q29vcmRpbmF0ZXMsIG9mZnNldCwgZW5kLCBzdHJpZGUsIHRydWUsICFzdHJva2UpO1xuICAgICAgdmFyIG1vdmVUb0xpbmVUb0luc3RydWN0aW9uID0gW0NhbnZhc0luc3RydWN0aW9uLk1PVkVfVE9fTElORV9UTywgbXlCZWdpbiwgbXlFbmRdO1xuICAgICAgdGhpcy5pbnN0cnVjdGlvbnMucHVzaChtb3ZlVG9MaW5lVG9JbnN0cnVjdGlvbik7XG4gICAgICB0aGlzLmhpdERldGVjdGlvbkluc3RydWN0aW9ucy5wdXNoKG1vdmVUb0xpbmVUb0luc3RydWN0aW9uKTtcblxuICAgICAgaWYgKHN0cm9rZSkge1xuICAgICAgICAvLyBQZXJmb3JtYW5jZSBvcHRpbWl6YXRpb246IG9ubHkgY2FsbCBjbG9zZVBhdGgoKSB3aGVuIHdlIGhhdmUgYSBzdHJva2UuXG4gICAgICAgIC8vIE90aGVyd2lzZSB0aGUgcmluZyBpcyBjbG9zZWQgYWxyZWFkeSAoc2VlIGFwcGVuZEZsYXRMaW5lQ29vcmRpbmF0ZXMgYWJvdmUpLlxuICAgICAgICB0aGlzLmluc3RydWN0aW9ucy5wdXNoKGNsb3NlUGF0aEluc3RydWN0aW9uKTtcbiAgICAgICAgdGhpcy5oaXREZXRlY3Rpb25JbnN0cnVjdGlvbnMucHVzaChjbG9zZVBhdGhJbnN0cnVjdGlvbik7XG4gICAgICB9XG5cbiAgICAgIG9mZnNldCA9IGVuZDtcbiAgICB9XG5cbiAgICBpZiAoZmlsbCkge1xuICAgICAgdGhpcy5pbnN0cnVjdGlvbnMucHVzaChmaWxsSW5zdHJ1Y3Rpb24pO1xuICAgICAgdGhpcy5oaXREZXRlY3Rpb25JbnN0cnVjdGlvbnMucHVzaChmaWxsSW5zdHJ1Y3Rpb24pO1xuICAgIH1cblxuICAgIGlmIChzdHJva2UpIHtcbiAgICAgIHRoaXMuaW5zdHJ1Y3Rpb25zLnB1c2goc3Ryb2tlSW5zdHJ1Y3Rpb24pO1xuICAgICAgdGhpcy5oaXREZXRlY3Rpb25JbnN0cnVjdGlvbnMucHVzaChzdHJva2VJbnN0cnVjdGlvbik7XG4gICAgfVxuXG4gICAgcmV0dXJuIG9mZnNldDtcbiAgfTtcbiAgLyoqXG4gICAqIEBwYXJhbSB7aW1wb3J0KFwiLi4vLi4vZ2VvbS9DaXJjbGUuanNcIikuZGVmYXVsdH0gY2lyY2xlR2VvbWV0cnkgQ2lyY2xlIGdlb21ldHJ5LlxuICAgKiBAcGFyYW0ge2ltcG9ydChcIi4uLy4uL0ZlYXR1cmUuanNcIikuZGVmYXVsdH0gZmVhdHVyZSBGZWF0dXJlLlxuICAgKi9cblxuXG4gIENhbnZhc1BvbHlnb25CdWlsZGVyLnByb3RvdHlwZS5kcmF3Q2lyY2xlID0gZnVuY3Rpb24gKGNpcmNsZUdlb21ldHJ5LCBmZWF0dXJlKSB7XG4gICAgdmFyIHN0YXRlID0gdGhpcy5zdGF0ZTtcbiAgICB2YXIgZmlsbFN0eWxlID0gc3RhdGUuZmlsbFN0eWxlO1xuICAgIHZhciBzdHJva2VTdHlsZSA9IHN0YXRlLnN0cm9rZVN0eWxlO1xuXG4gICAgaWYgKGZpbGxTdHlsZSA9PT0gdW5kZWZpbmVkICYmIHN0cm9rZVN0eWxlID09PSB1bmRlZmluZWQpIHtcbiAgICAgIHJldHVybjtcbiAgICB9XG5cbiAgICB0aGlzLnNldEZpbGxTdHJva2VTdHlsZXNfKCk7XG4gICAgdGhpcy5iZWdpbkdlb21ldHJ5KGNpcmNsZUdlb21ldHJ5LCBmZWF0dXJlKTtcblxuICAgIGlmIChzdGF0ZS5maWxsU3R5bGUgIT09IHVuZGVmaW5lZCkge1xuICAgICAgdGhpcy5oaXREZXRlY3Rpb25JbnN0cnVjdGlvbnMucHVzaChbQ2FudmFzSW5zdHJ1Y3Rpb24uU0VUX0ZJTExfU1RZTEUsIGRlZmF1bHRGaWxsU3R5bGVdKTtcbiAgICB9XG5cbiAgICBpZiAoc3RhdGUuc3Ryb2tlU3R5bGUgIT09IHVuZGVmaW5lZCkge1xuICAgICAgdGhpcy5oaXREZXRlY3Rpb25JbnN0cnVjdGlvbnMucHVzaChbQ2FudmFzSW5zdHJ1Y3Rpb24uU0VUX1NUUk9LRV9TVFlMRSwgc3RhdGUuc3Ryb2tlU3R5bGUsIHN0YXRlLmxpbmVXaWR0aCwgc3RhdGUubGluZUNhcCwgc3RhdGUubGluZUpvaW4sIHN0YXRlLm1pdGVyTGltaXQsIHN0YXRlLmxpbmVEYXNoLCBzdGF0ZS5saW5lRGFzaE9mZnNldF0pO1xuICAgIH1cblxuICAgIHZhciBmbGF0Q29vcmRpbmF0ZXMgPSBjaXJjbGVHZW9tZXRyeS5nZXRGbGF0Q29vcmRpbmF0ZXMoKTtcbiAgICB2YXIgc3RyaWRlID0gY2lyY2xlR2VvbWV0cnkuZ2V0U3RyaWRlKCk7XG4gICAgdmFyIG15QmVnaW4gPSB0aGlzLmNvb3JkaW5hdGVzLmxlbmd0aDtcbiAgICB0aGlzLmFwcGVuZEZsYXRMaW5lQ29vcmRpbmF0ZXMoZmxhdENvb3JkaW5hdGVzLCAwLCBmbGF0Q29vcmRpbmF0ZXMubGVuZ3RoLCBzdHJpZGUsIGZhbHNlLCBmYWxzZSk7XG4gICAgdmFyIGNpcmNsZUluc3RydWN0aW9uID0gW0NhbnZhc0luc3RydWN0aW9uLkNJUkNMRSwgbXlCZWdpbl07XG4gICAgdGhpcy5pbnN0cnVjdGlvbnMucHVzaChiZWdpblBhdGhJbnN0cnVjdGlvbiwgY2lyY2xlSW5zdHJ1Y3Rpb24pO1xuICAgIHRoaXMuaGl0RGV0ZWN0aW9uSW5zdHJ1Y3Rpb25zLnB1c2goYmVnaW5QYXRoSW5zdHJ1Y3Rpb24sIGNpcmNsZUluc3RydWN0aW9uKTtcblxuICAgIGlmIChzdGF0ZS5maWxsU3R5bGUgIT09IHVuZGVmaW5lZCkge1xuICAgICAgdGhpcy5pbnN0cnVjdGlvbnMucHVzaChmaWxsSW5zdHJ1Y3Rpb24pO1xuICAgICAgdGhpcy5oaXREZXRlY3Rpb25JbnN0cnVjdGlvbnMucHVzaChmaWxsSW5zdHJ1Y3Rpb24pO1xuICAgIH1cblxuICAgIGlmIChzdGF0ZS5zdHJva2VTdHlsZSAhPT0gdW5kZWZpbmVkKSB7XG4gICAgICB0aGlzLmluc3RydWN0aW9ucy5wdXNoKHN0cm9rZUluc3RydWN0aW9uKTtcbiAgICAgIHRoaXMuaGl0RGV0ZWN0aW9uSW5zdHJ1Y3Rpb25zLnB1c2goc3Ryb2tlSW5zdHJ1Y3Rpb24pO1xuICAgIH1cblxuICAgIHRoaXMuZW5kR2VvbWV0cnkoZmVhdHVyZSk7XG4gIH07XG4gIC8qKlxuICAgKiBAcGFyYW0ge2ltcG9ydChcIi4uLy4uL2dlb20vUG9seWdvbi5qc1wiKS5kZWZhdWx0fGltcG9ydChcIi4uL0ZlYXR1cmUuanNcIikuZGVmYXVsdH0gcG9seWdvbkdlb21ldHJ5IFBvbHlnb24gZ2VvbWV0cnkuXG4gICAqIEBwYXJhbSB7aW1wb3J0KFwiLi4vLi4vRmVhdHVyZS5qc1wiKS5GZWF0dXJlTGlrZX0gZmVhdHVyZSBGZWF0dXJlLlxuICAgKi9cblxuXG4gIENhbnZhc1BvbHlnb25CdWlsZGVyLnByb3RvdHlwZS5kcmF3UG9seWdvbiA9IGZ1bmN0aW9uIChwb2x5Z29uR2VvbWV0cnksIGZlYXR1cmUpIHtcbiAgICB2YXIgc3RhdGUgPSB0aGlzLnN0YXRlO1xuICAgIHZhciBmaWxsU3R5bGUgPSBzdGF0ZS5maWxsU3R5bGU7XG4gICAgdmFyIHN0cm9rZVN0eWxlID0gc3RhdGUuc3Ryb2tlU3R5bGU7XG5cbiAgICBpZiAoZmlsbFN0eWxlID09PSB1bmRlZmluZWQgJiYgc3Ryb2tlU3R5bGUgPT09IHVuZGVmaW5lZCkge1xuICAgICAgcmV0dXJuO1xuICAgIH1cblxuICAgIHRoaXMuc2V0RmlsbFN0cm9rZVN0eWxlc18oKTtcbiAgICB0aGlzLmJlZ2luR2VvbWV0cnkocG9seWdvbkdlb21ldHJ5LCBmZWF0dXJlKTtcblxuICAgIGlmIChzdGF0ZS5maWxsU3R5bGUgIT09IHVuZGVmaW5lZCkge1xuICAgICAgdGhpcy5oaXREZXRlY3Rpb25JbnN0cnVjdGlvbnMucHVzaChbQ2FudmFzSW5zdHJ1Y3Rpb24uU0VUX0ZJTExfU1RZTEUsIGRlZmF1bHRGaWxsU3R5bGVdKTtcbiAgICB9XG5cbiAgICBpZiAoc3RhdGUuc3Ryb2tlU3R5bGUgIT09IHVuZGVmaW5lZCkge1xuICAgICAgdGhpcy5oaXREZXRlY3Rpb25JbnN0cnVjdGlvbnMucHVzaChbQ2FudmFzSW5zdHJ1Y3Rpb24uU0VUX1NUUk9LRV9TVFlMRSwgc3RhdGUuc3Ryb2tlU3R5bGUsIHN0YXRlLmxpbmVXaWR0aCwgc3RhdGUubGluZUNhcCwgc3RhdGUubGluZUpvaW4sIHN0YXRlLm1pdGVyTGltaXQsIHN0YXRlLmxpbmVEYXNoLCBzdGF0ZS5saW5lRGFzaE9mZnNldF0pO1xuICAgIH1cblxuICAgIHZhciBlbmRzID0gcG9seWdvbkdlb21ldHJ5LmdldEVuZHMoKTtcbiAgICB2YXIgZmxhdENvb3JkaW5hdGVzID0gcG9seWdvbkdlb21ldHJ5LmdldE9yaWVudGVkRmxhdENvb3JkaW5hdGVzKCk7XG4gICAgdmFyIHN0cmlkZSA9IHBvbHlnb25HZW9tZXRyeS5nZXRTdHJpZGUoKTtcbiAgICB0aGlzLmRyYXdGbGF0Q29vcmRpbmF0ZXNzXyhmbGF0Q29vcmRpbmF0ZXMsIDAsXG4gICAgLyoqIEB0eXBlIHtBcnJheTxudW1iZXI+fSAqL1xuICAgIGVuZHMsIHN0cmlkZSk7XG4gICAgdGhpcy5lbmRHZW9tZXRyeShmZWF0dXJlKTtcbiAgfTtcbiAgLyoqXG4gICAqIEBwYXJhbSB7aW1wb3J0KFwiLi4vLi4vZ2VvbS9NdWx0aVBvbHlnb24uanNcIikuZGVmYXVsdH0gbXVsdGlQb2x5Z29uR2VvbWV0cnkgTXVsdGlQb2x5Z29uIGdlb21ldHJ5LlxuICAgKiBAcGFyYW0ge2ltcG9ydChcIi4uLy4uL0ZlYXR1cmUuanNcIikuRmVhdHVyZUxpa2V9IGZlYXR1cmUgRmVhdHVyZS5cbiAgICovXG5cblxuICBDYW52YXNQb2x5Z29uQnVpbGRlci5wcm90b3R5cGUuZHJhd011bHRpUG9seWdvbiA9IGZ1bmN0aW9uIChtdWx0aVBvbHlnb25HZW9tZXRyeSwgZmVhdHVyZSkge1xuICAgIHZhciBzdGF0ZSA9IHRoaXMuc3RhdGU7XG4gICAgdmFyIGZpbGxTdHlsZSA9IHN0YXRlLmZpbGxTdHlsZTtcbiAgICB2YXIgc3Ryb2tlU3R5bGUgPSBzdGF0ZS5zdHJva2VTdHlsZTtcblxuICAgIGlmIChmaWxsU3R5bGUgPT09IHVuZGVmaW5lZCAmJiBzdHJva2VTdHlsZSA9PT0gdW5kZWZpbmVkKSB7XG4gICAgICByZXR1cm47XG4gICAgfVxuXG4gICAgdGhpcy5zZXRGaWxsU3Ryb2tlU3R5bGVzXygpO1xuICAgIHRoaXMuYmVnaW5HZW9tZXRyeShtdWx0aVBvbHlnb25HZW9tZXRyeSwgZmVhdHVyZSk7XG5cbiAgICBpZiAoc3RhdGUuZmlsbFN0eWxlICE9PSB1bmRlZmluZWQpIHtcbiAgICAgIHRoaXMuaGl0RGV0ZWN0aW9uSW5zdHJ1Y3Rpb25zLnB1c2goW0NhbnZhc0luc3RydWN0aW9uLlNFVF9GSUxMX1NUWUxFLCBkZWZhdWx0RmlsbFN0eWxlXSk7XG4gICAgfVxuXG4gICAgaWYgKHN0YXRlLnN0cm9rZVN0eWxlICE9PSB1bmRlZmluZWQpIHtcbiAgICAgIHRoaXMuaGl0RGV0ZWN0aW9uSW5zdHJ1Y3Rpb25zLnB1c2goW0NhbnZhc0luc3RydWN0aW9uLlNFVF9TVFJPS0VfU1RZTEUsIHN0YXRlLnN0cm9rZVN0eWxlLCBzdGF0ZS5saW5lV2lkdGgsIHN0YXRlLmxpbmVDYXAsIHN0YXRlLmxpbmVKb2luLCBzdGF0ZS5taXRlckxpbWl0LCBzdGF0ZS5saW5lRGFzaCwgc3RhdGUubGluZURhc2hPZmZzZXRdKTtcbiAgICB9XG5cbiAgICB2YXIgZW5kc3MgPSBtdWx0aVBvbHlnb25HZW9tZXRyeS5nZXRFbmRzcygpO1xuICAgIHZhciBmbGF0Q29vcmRpbmF0ZXMgPSBtdWx0aVBvbHlnb25HZW9tZXRyeS5nZXRPcmllbnRlZEZsYXRDb29yZGluYXRlcygpO1xuICAgIHZhciBzdHJpZGUgPSBtdWx0aVBvbHlnb25HZW9tZXRyeS5nZXRTdHJpZGUoKTtcbiAgICB2YXIgb2Zmc2V0ID0gMDtcblxuICAgIGZvciAodmFyIGkgPSAwLCBpaSA9IGVuZHNzLmxlbmd0aDsgaSA8IGlpOyArK2kpIHtcbiAgICAgIG9mZnNldCA9IHRoaXMuZHJhd0ZsYXRDb29yZGluYXRlc3NfKGZsYXRDb29yZGluYXRlcywgb2Zmc2V0LCBlbmRzc1tpXSwgc3RyaWRlKTtcbiAgICB9XG5cbiAgICB0aGlzLmVuZEdlb21ldHJ5KGZlYXR1cmUpO1xuICB9O1xuICAvKipcbiAgICogQHJldHVybiB7aW1wb3J0KFwiLi4vY2FudmFzLmpzXCIpLlNlcmlhbGl6YWJsZUluc3RydWN0aW9uc30gdGhlIHNlcmlhbGl6YWJsZSBpbnN0cnVjdGlvbnMuXG4gICAqL1xuXG5cbiAgQ2FudmFzUG9seWdvbkJ1aWxkZXIucHJvdG90eXBlLmZpbmlzaCA9IGZ1bmN0aW9uICgpIHtcbiAgICB0aGlzLnJldmVyc2VIaXREZXRlY3Rpb25JbnN0cnVjdGlvbnMoKTtcbiAgICB0aGlzLnN0YXRlID0gbnVsbDsgLy8gV2Ugd2FudCB0byBwcmVzZXJ2ZSB0b3BvbG9neSB3aGVuIGRyYXdpbmcgcG9seWdvbnMuICBQb2x5Z29ucyBhcmVcbiAgICAvLyBzaW1wbGlmaWVkIHVzaW5nIHF1YW50aXphdGlvbiBhbmQgcG9pbnQgZWxpbWluYXRpb24uIEhvd2V2ZXIsIHdlIG1pZ2h0XG4gICAgLy8gaGF2ZSByZWNlaXZlZCBhIG1peCBvZiBxdWFudGl6ZWQgYW5kIG5vbi1xdWFudGl6ZWQgZ2VvbWV0cmllcywgc28gZW5zdXJlXG4gICAgLy8gdGhhdCBhbGwgYXJlIHF1YW50aXplZCBieSBxdWFudGl6aW5nIGFsbCBjb29yZGluYXRlcyBpbiB0aGUgYmF0Y2guXG5cbiAgICB2YXIgdG9sZXJhbmNlID0gdGhpcy50b2xlcmFuY2U7XG5cbiAgICBpZiAodG9sZXJhbmNlICE9PSAwKSB7XG4gICAgICB2YXIgY29vcmRpbmF0ZXMgPSB0aGlzLmNvb3JkaW5hdGVzO1xuXG4gICAgICBmb3IgKHZhciBpID0gMCwgaWkgPSBjb29yZGluYXRlcy5sZW5ndGg7IGkgPCBpaTsgKytpKSB7XG4gICAgICAgIGNvb3JkaW5hdGVzW2ldID0gc25hcChjb29yZGluYXRlc1tpXSwgdG9sZXJhbmNlKTtcbiAgICAgIH1cbiAgICB9XG5cbiAgICByZXR1cm4gX3N1cGVyLnByb3RvdHlwZS5maW5pc2guY2FsbCh0aGlzKTtcbiAgfTtcbiAgLyoqXG4gICAqIEBwcml2YXRlXG4gICAqL1xuXG5cbiAgQ2FudmFzUG9seWdvbkJ1aWxkZXIucHJvdG90eXBlLnNldEZpbGxTdHJva2VTdHlsZXNfID0gZnVuY3Rpb24gKCkge1xuICAgIHZhciBzdGF0ZSA9IHRoaXMuc3RhdGU7XG4gICAgdmFyIGZpbGxTdHlsZSA9IHN0YXRlLmZpbGxTdHlsZTtcblxuICAgIGlmIChmaWxsU3R5bGUgIT09IHVuZGVmaW5lZCkge1xuICAgICAgdGhpcy51cGRhdGVGaWxsU3R5bGUoc3RhdGUsIHRoaXMuY3JlYXRlRmlsbCk7XG4gICAgfVxuXG4gICAgaWYgKHN0YXRlLnN0cm9rZVN0eWxlICE9PSB1bmRlZmluZWQpIHtcbiAgICAgIHRoaXMudXBkYXRlU3Ryb2tlU3R5bGUoc3RhdGUsIHRoaXMuYXBwbHlTdHJva2UpO1xuICAgIH1cbiAgfTtcblxuICByZXR1cm4gQ2FudmFzUG9seWdvbkJ1aWxkZXI7XG59KENhbnZhc0J1aWxkZXIpO1xuXG5leHBvcnQgZGVmYXVsdCBDYW52YXNQb2x5Z29uQnVpbGRlcjsiLCIvKipcbiAqIEBtb2R1bGUgb2wvc3R5bGUvVGV4dFBsYWNlbWVudFxuICovXG5cbi8qKlxuICogVGV4dCBwbGFjZW1lbnQuIE9uZSBvZiBgJ3BvaW50J2AsIGAnbGluZSdgLiBEZWZhdWx0IGlzIGAncG9pbnQnYC4gTm90ZSB0aGF0XG4gKiBgJ2xpbmUnYCByZXF1aXJlcyB0aGUgdW5kZXJseWluZyBnZW9tZXRyeSB0byBiZSBhIHtAbGluayBtb2R1bGU6b2wvZ2VvbS9MaW5lU3RyaW5nfkxpbmVTdHJpbmd9LFxuICoge0BsaW5rIG1vZHVsZTpvbC9nZW9tL1BvbHlnb25+UG9seWdvbn0sIHtAbGluayBtb2R1bGU6b2wvZ2VvbS9NdWx0aUxpbmVTdHJpbmd+TXVsdGlMaW5lU3RyaW5nfSBvclxuICoge0BsaW5rIG1vZHVsZTpvbC9nZW9tL011bHRpUG9seWdvbn5NdWx0aVBvbHlnb259LlxuICogQGVudW0ge3N0cmluZ31cbiAqL1xuZXhwb3J0IGRlZmF1bHQge1xuICBQT0lOVDogJ3BvaW50JyxcbiAgTElORTogJ2xpbmUnXG59OyIsIi8qKlxuICogQG1vZHVsZSBvbC9nZW9tL2ZsYXQvc3RyYWlnaHRjaHVua1xuICovXG5cbi8qKlxuICogQHBhcmFtIHtudW1iZXJ9IG1heEFuZ2xlIE1heGltdW0gYWNjZXB0YWJsZSBhbmdsZSBkZWx0YSBiZXR3ZWVuIHNlZ21lbnRzLlxuICogQHBhcmFtIHtBcnJheTxudW1iZXI+fSBmbGF0Q29vcmRpbmF0ZXMgRmxhdCBjb29yZGluYXRlcy5cbiAqIEBwYXJhbSB7bnVtYmVyfSBvZmZzZXQgT2Zmc2V0LlxuICogQHBhcmFtIHtudW1iZXJ9IGVuZCBFbmQuXG4gKiBAcGFyYW0ge251bWJlcn0gc3RyaWRlIFN0cmlkZS5cbiAqIEByZXR1cm4ge0FycmF5PG51bWJlcj59IFN0YXJ0IGFuZCBlbmQgb2YgdGhlIGZpcnN0IHN1aXRhYmxlIGNodW5rIG9mIHRoZVxuICogZ2l2ZW4gYGZsYXRDb29yZGluYXRlc2AuXG4gKi9cbmV4cG9ydCBmdW5jdGlvbiBtYXRjaGluZ0NodW5rKG1heEFuZ2xlLCBmbGF0Q29vcmRpbmF0ZXMsIG9mZnNldCwgZW5kLCBzdHJpZGUpIHtcbiAgdmFyIGNodW5rU3RhcnQgPSBvZmZzZXQ7XG4gIHZhciBjaHVua0VuZCA9IG9mZnNldDtcbiAgdmFyIGNodW5rTSA9IDA7XG4gIHZhciBtID0gMDtcbiAgdmFyIHN0YXJ0ID0gb2Zmc2V0O1xuICB2YXIgYWNvcywgaSwgbTEyLCBtMjMsIHgxLCB5MSwgeDEyLCB5MTIsIHgyMywgeTIzO1xuXG4gIGZvciAoaSA9IG9mZnNldDsgaSA8IGVuZDsgaSArPSBzdHJpZGUpIHtcbiAgICB2YXIgeDIgPSBmbGF0Q29vcmRpbmF0ZXNbaV07XG4gICAgdmFyIHkyID0gZmxhdENvb3JkaW5hdGVzW2kgKyAxXTtcblxuICAgIGlmICh4MSAhPT0gdW5kZWZpbmVkKSB7XG4gICAgICB4MjMgPSB4MiAtIHgxO1xuICAgICAgeTIzID0geTIgLSB5MTtcbiAgICAgIG0yMyA9IE1hdGguc3FydCh4MjMgKiB4MjMgKyB5MjMgKiB5MjMpO1xuXG4gICAgICBpZiAoeDEyICE9PSB1bmRlZmluZWQpIHtcbiAgICAgICAgbSArPSBtMTI7XG4gICAgICAgIGFjb3MgPSBNYXRoLmFjb3MoKHgxMiAqIHgyMyArIHkxMiAqIHkyMykgLyAobTEyICogbTIzKSk7XG5cbiAgICAgICAgaWYgKGFjb3MgPiBtYXhBbmdsZSkge1xuICAgICAgICAgIGlmIChtID4gY2h1bmtNKSB7XG4gICAgICAgICAgICBjaHVua00gPSBtO1xuICAgICAgICAgICAgY2h1bmtTdGFydCA9IHN0YXJ0O1xuICAgICAgICAgICAgY2h1bmtFbmQgPSBpO1xuICAgICAgICAgIH1cblxuICAgICAgICAgIG0gPSAwO1xuICAgICAgICAgIHN0YXJ0ID0gaSAtIHN0cmlkZTtcbiAgICAgICAgfVxuICAgICAgfVxuXG4gICAgICBtMTIgPSBtMjM7XG4gICAgICB4MTIgPSB4MjM7XG4gICAgICB5MTIgPSB5MjM7XG4gICAgfVxuXG4gICAgeDEgPSB4MjtcbiAgICB5MSA9IHkyO1xuICB9XG5cbiAgbSArPSBtMjM7XG4gIHJldHVybiBtID4gY2h1bmtNID8gW3N0YXJ0LCBpXSA6IFtjaHVua1N0YXJ0LCBjaHVua0VuZF07XG59IiwidmFyIF9fZXh0ZW5kcyA9IHRoaXMgJiYgdGhpcy5fX2V4dGVuZHMgfHwgZnVuY3Rpb24gKCkge1xuICB2YXIgX2V4dGVuZFN0YXRpY3MgPSBmdW5jdGlvbiBleHRlbmRTdGF0aWNzKGQsIGIpIHtcbiAgICBfZXh0ZW5kU3RhdGljcyA9IE9iamVjdC5zZXRQcm90b3R5cGVPZiB8fCB7XG4gICAgICBfX3Byb3RvX186IFtdXG4gICAgfSBpbnN0YW5jZW9mIEFycmF5ICYmIGZ1bmN0aW9uIChkLCBiKSB7XG4gICAgICBkLl9fcHJvdG9fXyA9IGI7XG4gICAgfSB8fCBmdW5jdGlvbiAoZCwgYikge1xuICAgICAgZm9yICh2YXIgcCBpbiBiKSB7XG4gICAgICAgIGlmIChPYmplY3QucHJvdG90eXBlLmhhc093blByb3BlcnR5LmNhbGwoYiwgcCkpIGRbcF0gPSBiW3BdO1xuICAgICAgfVxuICAgIH07XG5cbiAgICByZXR1cm4gX2V4dGVuZFN0YXRpY3MoZCwgYik7XG4gIH07XG5cbiAgcmV0dXJuIGZ1bmN0aW9uIChkLCBiKSB7XG4gICAgX2V4dGVuZFN0YXRpY3MoZCwgYik7XG5cbiAgICBmdW5jdGlvbiBfXygpIHtcbiAgICAgIHRoaXMuY29uc3RydWN0b3IgPSBkO1xuICAgIH1cblxuICAgIGQucHJvdG90eXBlID0gYiA9PT0gbnVsbCA/IE9iamVjdC5jcmVhdGUoYikgOiAoX18ucHJvdG90eXBlID0gYi5wcm90b3R5cGUsIG5ldyBfXygpKTtcbiAgfTtcbn0oKTtcbi8qKlxuICogQG1vZHVsZSBvbC9yZW5kZXIvY2FudmFzL1RleHRCdWlsZGVyXG4gKi9cblxuXG5pbXBvcnQgQ2FudmFzQnVpbGRlciBmcm9tICcuL0J1aWxkZXIuanMnO1xuaW1wb3J0IENhbnZhc0luc3RydWN0aW9uIGZyb20gJy4vSW5zdHJ1Y3Rpb24uanMnO1xuaW1wb3J0IEdlb21ldHJ5VHlwZSBmcm9tICcuLi8uLi9nZW9tL0dlb21ldHJ5VHlwZS5qcyc7XG5pbXBvcnQgVGV4dFBsYWNlbWVudCBmcm9tICcuLi8uLi9zdHlsZS9UZXh0UGxhY2VtZW50LmpzJztcbmltcG9ydCB7IGFzQ29sb3JMaWtlIH0gZnJvbSAnLi4vLi4vY29sb3JsaWtlLmpzJztcbmltcG9ydCB7IGRlZmF1bHRGaWxsU3R5bGUsIGRlZmF1bHRGb250LCBkZWZhdWx0TGluZUNhcCwgZGVmYXVsdExpbmVEYXNoLCBkZWZhdWx0TGluZURhc2hPZmZzZXQsIGRlZmF1bHRMaW5lSm9pbiwgZGVmYXVsdExpbmVXaWR0aCwgZGVmYXVsdE1pdGVyTGltaXQsIGRlZmF1bHRQYWRkaW5nLCBkZWZhdWx0U3Ryb2tlU3R5bGUsIGRlZmF1bHRUZXh0QWxpZ24sIGRlZmF1bHRUZXh0QmFzZWxpbmUsIHJlZ2lzdGVyRm9udCB9IGZyb20gJy4uL2NhbnZhcy5qcyc7XG5pbXBvcnQgeyBnZXRVaWQgfSBmcm9tICcuLi8uLi91dGlsLmpzJztcbmltcG9ydCB7IGludGVyc2VjdHMgfSBmcm9tICcuLi8uLi9leHRlbnQuanMnO1xuaW1wb3J0IHsgbWF0Y2hpbmdDaHVuayB9IGZyb20gJy4uLy4uL2dlb20vZmxhdC9zdHJhaWdodGNodW5rLmpzJztcbi8qKlxuICogQGNvbnN0XG4gKiBAZW51bSB7bnVtYmVyfVxuICovXG5cbmV4cG9ydCB2YXIgVEVYVF9BTElHTiA9IHtcbiAgJ2xlZnQnOiAwLFxuICAnZW5kJzogMCxcbiAgJ2NlbnRlcic6IDAuNSxcbiAgJ3JpZ2h0JzogMSxcbiAgJ3N0YXJ0JzogMSxcbiAgJ3RvcCc6IDAsXG4gICdtaWRkbGUnOiAwLjUsXG4gICdoYW5naW5nJzogMC4yLFxuICAnYWxwaGFiZXRpYyc6IDAuOCxcbiAgJ2lkZW9ncmFwaGljJzogMC44LFxuICAnYm90dG9tJzogMVxufTtcblxudmFyIENhbnZhc1RleHRCdWlsZGVyID1cbi8qKiBAY2xhc3MgKi9cbmZ1bmN0aW9uIChfc3VwZXIpIHtcbiAgX19leHRlbmRzKENhbnZhc1RleHRCdWlsZGVyLCBfc3VwZXIpO1xuICAvKipcbiAgICogQHBhcmFtIHtudW1iZXJ9IHRvbGVyYW5jZSBUb2xlcmFuY2UuXG4gICAqIEBwYXJhbSB7aW1wb3J0KFwiLi4vLi4vZXh0ZW50LmpzXCIpLkV4dGVudH0gbWF4RXh0ZW50IE1heGltdW0gZXh0ZW50LlxuICAgKiBAcGFyYW0ge251bWJlcn0gcmVzb2x1dGlvbiBSZXNvbHV0aW9uLlxuICAgKiBAcGFyYW0ge251bWJlcn0gcGl4ZWxSYXRpbyBQaXhlbCByYXRpby5cbiAgICovXG5cblxuICBmdW5jdGlvbiBDYW52YXNUZXh0QnVpbGRlcih0b2xlcmFuY2UsIG1heEV4dGVudCwgcmVzb2x1dGlvbiwgcGl4ZWxSYXRpbykge1xuICAgIHZhciBfdGhpcyA9IF9zdXBlci5jYWxsKHRoaXMsIHRvbGVyYW5jZSwgbWF4RXh0ZW50LCByZXNvbHV0aW9uLCBwaXhlbFJhdGlvKSB8fCB0aGlzO1xuICAgIC8qKlxuICAgICAqIEBwcml2YXRlXG4gICAgICogQHR5cGUge0FycmF5PEhUTUxDYW52YXNFbGVtZW50Pn1cbiAgICAgKi9cblxuXG4gICAgX3RoaXMubGFiZWxzXyA9IG51bGw7XG4gICAgLyoqXG4gICAgICogQHByaXZhdGVcbiAgICAgKiBAdHlwZSB7c3RyaW5nfVxuICAgICAqL1xuXG4gICAgX3RoaXMudGV4dF8gPSAnJztcbiAgICAvKipcbiAgICAgKiBAcHJpdmF0ZVxuICAgICAqIEB0eXBlIHtudW1iZXJ9XG4gICAgICovXG5cbiAgICBfdGhpcy50ZXh0T2Zmc2V0WF8gPSAwO1xuICAgIC8qKlxuICAgICAqIEBwcml2YXRlXG4gICAgICogQHR5cGUge251bWJlcn1cbiAgICAgKi9cblxuICAgIF90aGlzLnRleHRPZmZzZXRZXyA9IDA7XG4gICAgLyoqXG4gICAgICogQHByaXZhdGVcbiAgICAgKiBAdHlwZSB7Ym9vbGVhbnx1bmRlZmluZWR9XG4gICAgICovXG5cbiAgICBfdGhpcy50ZXh0Um90YXRlV2l0aFZpZXdfID0gdW5kZWZpbmVkO1xuICAgIC8qKlxuICAgICAqIEBwcml2YXRlXG4gICAgICogQHR5cGUge251bWJlcn1cbiAgICAgKi9cblxuICAgIF90aGlzLnRleHRSb3RhdGlvbl8gPSAwO1xuICAgIC8qKlxuICAgICAqIEBwcml2YXRlXG4gICAgICogQHR5cGUgez9pbXBvcnQoXCIuLi9jYW52YXMuanNcIikuRmlsbFN0YXRlfVxuICAgICAqL1xuXG4gICAgX3RoaXMudGV4dEZpbGxTdGF0ZV8gPSBudWxsO1xuICAgIC8qKlxuICAgICAqIEB0eXBlIHshT2JqZWN0PHN0cmluZywgaW1wb3J0KFwiLi4vY2FudmFzLmpzXCIpLkZpbGxTdGF0ZT59XG4gICAgICovXG5cbiAgICBfdGhpcy5maWxsU3RhdGVzID0ge307XG4gICAgLyoqXG4gICAgICogQHByaXZhdGVcbiAgICAgKiBAdHlwZSB7P2ltcG9ydChcIi4uL2NhbnZhcy5qc1wiKS5TdHJva2VTdGF0ZX1cbiAgICAgKi9cblxuICAgIF90aGlzLnRleHRTdHJva2VTdGF0ZV8gPSBudWxsO1xuICAgIC8qKlxuICAgICAqIEB0eXBlIHshT2JqZWN0PHN0cmluZywgaW1wb3J0KFwiLi4vY2FudmFzLmpzXCIpLlN0cm9rZVN0YXRlPn1cbiAgICAgKi9cblxuICAgIF90aGlzLnN0cm9rZVN0YXRlcyA9IHt9O1xuICAgIC8qKlxuICAgICAqIEBwcml2YXRlXG4gICAgICogQHR5cGUge2ltcG9ydChcIi4uL2NhbnZhcy5qc1wiKS5UZXh0U3RhdGV9XG4gICAgICovXG5cbiAgICBfdGhpcy50ZXh0U3RhdGVfID1cbiAgICAvKiogQHR5cGUge2ltcG9ydChcIi4uL2NhbnZhcy5qc1wiKS5UZXh0U3RhdGV9ICovXG4gICAge307XG4gICAgLyoqXG4gICAgICogQHR5cGUgeyFPYmplY3Q8c3RyaW5nLCBpbXBvcnQoXCIuLi9jYW52YXMuanNcIikuVGV4dFN0YXRlPn1cbiAgICAgKi9cblxuICAgIF90aGlzLnRleHRTdGF0ZXMgPSB7fTtcbiAgICAvKipcbiAgICAgKiBAcHJpdmF0ZVxuICAgICAqIEB0eXBlIHtzdHJpbmd9XG4gICAgICovXG5cbiAgICBfdGhpcy50ZXh0S2V5XyA9ICcnO1xuICAgIC8qKlxuICAgICAqIEBwcml2YXRlXG4gICAgICogQHR5cGUge3N0cmluZ31cbiAgICAgKi9cblxuICAgIF90aGlzLmZpbGxLZXlfID0gJyc7XG4gICAgLyoqXG4gICAgICogQHByaXZhdGVcbiAgICAgKiBAdHlwZSB7c3RyaW5nfVxuICAgICAqL1xuXG4gICAgX3RoaXMuc3Ryb2tlS2V5XyA9ICcnO1xuICAgIC8qKlxuICAgICAqIERhdGEgc2hhcmVkIHdpdGggYW4gaW1hZ2UgYnVpbGRlciBmb3IgY29tYmluZWQgZGVjbHV0dGVyaW5nLlxuICAgICAqIEBwcml2YXRlXG4gICAgICogQHR5cGUge2ltcG9ydChcIi4uL2NhbnZhcy5qc1wiKS5EZWNsdXR0ZXJJbWFnZVdpdGhUZXh0fVxuICAgICAqL1xuXG4gICAgX3RoaXMuZGVjbHV0dGVySW1hZ2VXaXRoVGV4dF8gPSB1bmRlZmluZWQ7XG4gICAgcmV0dXJuIF90aGlzO1xuICB9XG4gIC8qKlxuICAgKiBAcmV0dXJuIHtpbXBvcnQoXCIuLi9jYW52YXMuanNcIikuU2VyaWFsaXphYmxlSW5zdHJ1Y3Rpb25zfSB0aGUgc2VyaWFsaXphYmxlIGluc3RydWN0aW9ucy5cbiAgICovXG5cblxuICBDYW52YXNUZXh0QnVpbGRlci5wcm90b3R5cGUuZmluaXNoID0gZnVuY3Rpb24gKCkge1xuICAgIHZhciBpbnN0cnVjdGlvbnMgPSBfc3VwZXIucHJvdG90eXBlLmZpbmlzaC5jYWxsKHRoaXMpO1xuXG4gICAgaW5zdHJ1Y3Rpb25zLnRleHRTdGF0ZXMgPSB0aGlzLnRleHRTdGF0ZXM7XG4gICAgaW5zdHJ1Y3Rpb25zLmZpbGxTdGF0ZXMgPSB0aGlzLmZpbGxTdGF0ZXM7XG4gICAgaW5zdHJ1Y3Rpb25zLnN0cm9rZVN0YXRlcyA9IHRoaXMuc3Ryb2tlU3RhdGVzO1xuICAgIHJldHVybiBpbnN0cnVjdGlvbnM7XG4gIH07XG4gIC8qKlxuICAgKiBAcGFyYW0ge2ltcG9ydChcIi4uLy4uL2dlb20vU2ltcGxlR2VvbWV0cnkuanNcIikuZGVmYXVsdHxpbXBvcnQoXCIuLi9GZWF0dXJlLmpzXCIpLmRlZmF1bHR9IGdlb21ldHJ5IEdlb21ldHJ5LlxuICAgKiBAcGFyYW0ge2ltcG9ydChcIi4uLy4uL0ZlYXR1cmUuanNcIikuRmVhdHVyZUxpa2V9IGZlYXR1cmUgRmVhdHVyZS5cbiAgICovXG5cblxuICBDYW52YXNUZXh0QnVpbGRlci5wcm90b3R5cGUuZHJhd1RleHQgPSBmdW5jdGlvbiAoZ2VvbWV0cnksIGZlYXR1cmUpIHtcbiAgICB2YXIgZmlsbFN0YXRlID0gdGhpcy50ZXh0RmlsbFN0YXRlXztcbiAgICB2YXIgc3Ryb2tlU3RhdGUgPSB0aGlzLnRleHRTdHJva2VTdGF0ZV87XG4gICAgdmFyIHRleHRTdGF0ZSA9IHRoaXMudGV4dFN0YXRlXztcblxuICAgIGlmICh0aGlzLnRleHRfID09PSAnJyB8fCAhdGV4dFN0YXRlIHx8ICFmaWxsU3RhdGUgJiYgIXN0cm9rZVN0YXRlKSB7XG4gICAgICByZXR1cm47XG4gICAgfVxuXG4gICAgdmFyIGNvb3JkaW5hdGVzID0gdGhpcy5jb29yZGluYXRlcztcbiAgICB2YXIgYmVnaW4gPSBjb29yZGluYXRlcy5sZW5ndGg7XG4gICAgdmFyIGdlb21ldHJ5VHlwZSA9IGdlb21ldHJ5LmdldFR5cGUoKTtcbiAgICB2YXIgZmxhdENvb3JkaW5hdGVzID0gbnVsbDtcbiAgICB2YXIgc3RyaWRlID0gZ2VvbWV0cnkuZ2V0U3RyaWRlKCk7XG5cbiAgICBpZiAodGV4dFN0YXRlLnBsYWNlbWVudCA9PT0gVGV4dFBsYWNlbWVudC5MSU5FICYmIChnZW9tZXRyeVR5cGUgPT0gR2VvbWV0cnlUeXBlLkxJTkVfU1RSSU5HIHx8IGdlb21ldHJ5VHlwZSA9PSBHZW9tZXRyeVR5cGUuTVVMVElfTElORV9TVFJJTkcgfHwgZ2VvbWV0cnlUeXBlID09IEdlb21ldHJ5VHlwZS5QT0xZR09OIHx8IGdlb21ldHJ5VHlwZSA9PSBHZW9tZXRyeVR5cGUuTVVMVElfUE9MWUdPTikpIHtcbiAgICAgIGlmICghaW50ZXJzZWN0cyh0aGlzLmdldEJ1ZmZlcmVkTWF4RXh0ZW50KCksIGdlb21ldHJ5LmdldEV4dGVudCgpKSkge1xuICAgICAgICByZXR1cm47XG4gICAgICB9XG5cbiAgICAgIHZhciBlbmRzID0gdm9pZCAwO1xuICAgICAgZmxhdENvb3JkaW5hdGVzID0gZ2VvbWV0cnkuZ2V0RmxhdENvb3JkaW5hdGVzKCk7XG5cbiAgICAgIGlmIChnZW9tZXRyeVR5cGUgPT0gR2VvbWV0cnlUeXBlLkxJTkVfU1RSSU5HKSB7XG4gICAgICAgIGVuZHMgPSBbZmxhdENvb3JkaW5hdGVzLmxlbmd0aF07XG4gICAgICB9IGVsc2UgaWYgKGdlb21ldHJ5VHlwZSA9PSBHZW9tZXRyeVR5cGUuTVVMVElfTElORV9TVFJJTkcpIHtcbiAgICAgICAgZW5kcyA9XG4gICAgICAgIC8qKiBAdHlwZSB7aW1wb3J0KFwiLi4vLi4vZ2VvbS9NdWx0aUxpbmVTdHJpbmcuanNcIikuZGVmYXVsdH0gKi9cbiAgICAgICAgZ2VvbWV0cnkuZ2V0RW5kcygpO1xuICAgICAgfSBlbHNlIGlmIChnZW9tZXRyeVR5cGUgPT0gR2VvbWV0cnlUeXBlLlBPTFlHT04pIHtcbiAgICAgICAgZW5kcyA9XG4gICAgICAgIC8qKiBAdHlwZSB7aW1wb3J0KFwiLi4vLi4vZ2VvbS9Qb2x5Z29uLmpzXCIpLmRlZmF1bHR9ICovXG4gICAgICAgIGdlb21ldHJ5LmdldEVuZHMoKS5zbGljZSgwLCAxKTtcbiAgICAgIH0gZWxzZSBpZiAoZ2VvbWV0cnlUeXBlID09IEdlb21ldHJ5VHlwZS5NVUxUSV9QT0xZR09OKSB7XG4gICAgICAgIHZhciBlbmRzcyA9XG4gICAgICAgIC8qKiBAdHlwZSB7aW1wb3J0KFwiLi4vLi4vZ2VvbS9NdWx0aVBvbHlnb24uanNcIikuZGVmYXVsdH0gKi9cbiAgICAgICAgZ2VvbWV0cnkuZ2V0RW5kc3MoKTtcbiAgICAgICAgZW5kcyA9IFtdO1xuXG4gICAgICAgIGZvciAodmFyIGkgPSAwLCBpaSA9IGVuZHNzLmxlbmd0aDsgaSA8IGlpOyArK2kpIHtcbiAgICAgICAgICBlbmRzLnB1c2goZW5kc3NbaV1bMF0pO1xuICAgICAgICB9XG4gICAgICB9XG5cbiAgICAgIHRoaXMuYmVnaW5HZW9tZXRyeShnZW9tZXRyeSwgZmVhdHVyZSk7XG4gICAgICB2YXIgdGV4dEFsaWduID0gdGV4dFN0YXRlLnRleHRBbGlnbjtcbiAgICAgIHZhciBmbGF0T2Zmc2V0ID0gMDtcbiAgICAgIHZhciBmbGF0RW5kID0gdm9pZCAwO1xuXG4gICAgICBmb3IgKHZhciBvID0gMCwgb28gPSBlbmRzLmxlbmd0aDsgbyA8IG9vOyArK28pIHtcbiAgICAgICAgaWYgKHRleHRBbGlnbiA9PSB1bmRlZmluZWQpIHtcbiAgICAgICAgICB2YXIgcmFuZ2UgPSBtYXRjaGluZ0NodW5rKHRleHRTdGF0ZS5tYXhBbmdsZSwgZmxhdENvb3JkaW5hdGVzLCBmbGF0T2Zmc2V0LCBlbmRzW29dLCBzdHJpZGUpO1xuICAgICAgICAgIGZsYXRPZmZzZXQgPSByYW5nZVswXTtcbiAgICAgICAgICBmbGF0RW5kID0gcmFuZ2VbMV07XG4gICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgZmxhdEVuZCA9IGVuZHNbb107XG4gICAgICAgIH1cblxuICAgICAgICBmb3IgKHZhciBpID0gZmxhdE9mZnNldDsgaSA8IGZsYXRFbmQ7IGkgKz0gc3RyaWRlKSB7XG4gICAgICAgICAgY29vcmRpbmF0ZXMucHVzaChmbGF0Q29vcmRpbmF0ZXNbaV0sIGZsYXRDb29yZGluYXRlc1tpICsgMV0pO1xuICAgICAgICB9XG5cbiAgICAgICAgdmFyIGVuZCA9IGNvb3JkaW5hdGVzLmxlbmd0aDtcbiAgICAgICAgZmxhdE9mZnNldCA9IGVuZHNbb107XG4gICAgICAgIHRoaXMuZHJhd0NoYXJzXyhiZWdpbiwgZW5kKTtcbiAgICAgICAgYmVnaW4gPSBlbmQ7XG4gICAgICB9XG5cbiAgICAgIHRoaXMuZW5kR2VvbWV0cnkoZmVhdHVyZSk7XG4gICAgfSBlbHNlIHtcbiAgICAgIHZhciBnZW9tZXRyeVdpZHRocyA9IHRleHRTdGF0ZS5vdmVyZmxvdyA/IG51bGwgOiBbXTtcblxuICAgICAgc3dpdGNoIChnZW9tZXRyeVR5cGUpIHtcbiAgICAgICAgY2FzZSBHZW9tZXRyeVR5cGUuUE9JTlQ6XG4gICAgICAgIGNhc2UgR2VvbWV0cnlUeXBlLk1VTFRJX1BPSU5UOlxuICAgICAgICAgIGZsYXRDb29yZGluYXRlcyA9XG4gICAgICAgICAgLyoqIEB0eXBlIHtpbXBvcnQoXCIuLi8uLi9nZW9tL011bHRpUG9pbnQuanNcIikuZGVmYXVsdH0gKi9cbiAgICAgICAgICBnZW9tZXRyeS5nZXRGbGF0Q29vcmRpbmF0ZXMoKTtcbiAgICAgICAgICBicmVhaztcblxuICAgICAgICBjYXNlIEdlb21ldHJ5VHlwZS5MSU5FX1NUUklORzpcbiAgICAgICAgICBmbGF0Q29vcmRpbmF0ZXMgPVxuICAgICAgICAgIC8qKiBAdHlwZSB7aW1wb3J0KFwiLi4vLi4vZ2VvbS9MaW5lU3RyaW5nLmpzXCIpLmRlZmF1bHR9ICovXG4gICAgICAgICAgZ2VvbWV0cnkuZ2V0RmxhdE1pZHBvaW50KCk7XG4gICAgICAgICAgYnJlYWs7XG5cbiAgICAgICAgY2FzZSBHZW9tZXRyeVR5cGUuQ0lSQ0xFOlxuICAgICAgICAgIGZsYXRDb29yZGluYXRlcyA9XG4gICAgICAgICAgLyoqIEB0eXBlIHtpbXBvcnQoXCIuLi8uLi9nZW9tL0NpcmNsZS5qc1wiKS5kZWZhdWx0fSAqL1xuICAgICAgICAgIGdlb21ldHJ5LmdldENlbnRlcigpO1xuICAgICAgICAgIGJyZWFrO1xuXG4gICAgICAgIGNhc2UgR2VvbWV0cnlUeXBlLk1VTFRJX0xJTkVfU1RSSU5HOlxuICAgICAgICAgIGZsYXRDb29yZGluYXRlcyA9XG4gICAgICAgICAgLyoqIEB0eXBlIHtpbXBvcnQoXCIuLi8uLi9nZW9tL011bHRpTGluZVN0cmluZy5qc1wiKS5kZWZhdWx0fSAqL1xuICAgICAgICAgIGdlb21ldHJ5LmdldEZsYXRNaWRwb2ludHMoKTtcbiAgICAgICAgICBzdHJpZGUgPSAyO1xuICAgICAgICAgIGJyZWFrO1xuXG4gICAgICAgIGNhc2UgR2VvbWV0cnlUeXBlLlBPTFlHT046XG4gICAgICAgICAgZmxhdENvb3JkaW5hdGVzID1cbiAgICAgICAgICAvKiogQHR5cGUge2ltcG9ydChcIi4uLy4uL2dlb20vUG9seWdvbi5qc1wiKS5kZWZhdWx0fSAqL1xuICAgICAgICAgIGdlb21ldHJ5LmdldEZsYXRJbnRlcmlvclBvaW50KCk7XG5cbiAgICAgICAgICBpZiAoIXRleHRTdGF0ZS5vdmVyZmxvdykge1xuICAgICAgICAgICAgZ2VvbWV0cnlXaWR0aHMucHVzaChmbGF0Q29vcmRpbmF0ZXNbMl0gLyB0aGlzLnJlc29sdXRpb24pO1xuICAgICAgICAgIH1cblxuICAgICAgICAgIHN0cmlkZSA9IDM7XG4gICAgICAgICAgYnJlYWs7XG5cbiAgICAgICAgY2FzZSBHZW9tZXRyeVR5cGUuTVVMVElfUE9MWUdPTjpcbiAgICAgICAgICB2YXIgaW50ZXJpb3JQb2ludHMgPVxuICAgICAgICAgIC8qKiBAdHlwZSB7aW1wb3J0KFwiLi4vLi4vZ2VvbS9NdWx0aVBvbHlnb24uanNcIikuZGVmYXVsdH0gKi9cbiAgICAgICAgICBnZW9tZXRyeS5nZXRGbGF0SW50ZXJpb3JQb2ludHMoKTtcbiAgICAgICAgICBmbGF0Q29vcmRpbmF0ZXMgPSBbXTtcblxuICAgICAgICAgIGZvciAodmFyIGkgPSAwLCBpaSA9IGludGVyaW9yUG9pbnRzLmxlbmd0aDsgaSA8IGlpOyBpICs9IDMpIHtcbiAgICAgICAgICAgIGlmICghdGV4dFN0YXRlLm92ZXJmbG93KSB7XG4gICAgICAgICAgICAgIGdlb21ldHJ5V2lkdGhzLnB1c2goaW50ZXJpb3JQb2ludHNbaSArIDJdIC8gdGhpcy5yZXNvbHV0aW9uKTtcbiAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgZmxhdENvb3JkaW5hdGVzLnB1c2goaW50ZXJpb3JQb2ludHNbaV0sIGludGVyaW9yUG9pbnRzW2kgKyAxXSk7XG4gICAgICAgICAgfVxuXG4gICAgICAgICAgaWYgKGZsYXRDb29yZGluYXRlcy5sZW5ndGggPT09IDApIHtcbiAgICAgICAgICAgIHJldHVybjtcbiAgICAgICAgICB9XG5cbiAgICAgICAgICBzdHJpZGUgPSAyO1xuICAgICAgICAgIGJyZWFrO1xuXG4gICAgICAgIGRlZmF1bHQ6XG4gICAgICB9XG5cbiAgICAgIHZhciBlbmQgPSB0aGlzLmFwcGVuZEZsYXRQb2ludENvb3JkaW5hdGVzKGZsYXRDb29yZGluYXRlcywgc3RyaWRlKTtcblxuICAgICAgaWYgKGVuZCA9PT0gYmVnaW4pIHtcbiAgICAgICAgcmV0dXJuO1xuICAgICAgfVxuXG4gICAgICB0aGlzLnNhdmVUZXh0U3RhdGVzXygpO1xuXG4gICAgICBpZiAodGV4dFN0YXRlLmJhY2tncm91bmRGaWxsIHx8IHRleHRTdGF0ZS5iYWNrZ3JvdW5kU3Ryb2tlKSB7XG4gICAgICAgIHRoaXMuc2V0RmlsbFN0cm9rZVN0eWxlKHRleHRTdGF0ZS5iYWNrZ3JvdW5kRmlsbCwgdGV4dFN0YXRlLmJhY2tncm91bmRTdHJva2UpO1xuXG4gICAgICAgIGlmICh0ZXh0U3RhdGUuYmFja2dyb3VuZEZpbGwpIHtcbiAgICAgICAgICB0aGlzLnVwZGF0ZUZpbGxTdHlsZSh0aGlzLnN0YXRlLCB0aGlzLmNyZWF0ZUZpbGwpO1xuICAgICAgICAgIHRoaXMuaGl0RGV0ZWN0aW9uSW5zdHJ1Y3Rpb25zLnB1c2godGhpcy5jcmVhdGVGaWxsKHRoaXMuc3RhdGUpKTtcbiAgICAgICAgfVxuXG4gICAgICAgIGlmICh0ZXh0U3RhdGUuYmFja2dyb3VuZFN0cm9rZSkge1xuICAgICAgICAgIHRoaXMudXBkYXRlU3Ryb2tlU3R5bGUodGhpcy5zdGF0ZSwgdGhpcy5hcHBseVN0cm9rZSk7XG4gICAgICAgICAgdGhpcy5oaXREZXRlY3Rpb25JbnN0cnVjdGlvbnMucHVzaCh0aGlzLmNyZWF0ZVN0cm9rZSh0aGlzLnN0YXRlKSk7XG4gICAgICAgIH1cbiAgICAgIH1cblxuICAgICAgdGhpcy5iZWdpbkdlb21ldHJ5KGdlb21ldHJ5LCBmZWF0dXJlKTsgLy8gYWRqdXN0IHBhZGRpbmcgZm9yIG5lZ2F0aXZlIHNjYWxlXG5cbiAgICAgIHZhciBwYWRkaW5nID0gdGV4dFN0YXRlLnBhZGRpbmc7XG5cbiAgICAgIGlmIChwYWRkaW5nICE9IGRlZmF1bHRQYWRkaW5nICYmICh0ZXh0U3RhdGUuc2NhbGVbMF0gPCAwIHx8IHRleHRTdGF0ZS5zY2FsZVsxXSA8IDApKSB7XG4gICAgICAgIHZhciBwMCA9IHRleHRTdGF0ZS5wYWRkaW5nWzBdO1xuICAgICAgICB2YXIgcDEgPSB0ZXh0U3RhdGUucGFkZGluZ1sxXTtcbiAgICAgICAgdmFyIHAyID0gdGV4dFN0YXRlLnBhZGRpbmdbMl07XG4gICAgICAgIHZhciBwMyA9IHRleHRTdGF0ZS5wYWRkaW5nWzNdO1xuXG4gICAgICAgIGlmICh0ZXh0U3RhdGUuc2NhbGVbMF0gPCAwKSB7XG4gICAgICAgICAgcDEgPSAtcDE7XG4gICAgICAgICAgcDMgPSAtcDM7XG4gICAgICAgIH1cblxuICAgICAgICBpZiAodGV4dFN0YXRlLnNjYWxlWzFdIDwgMCkge1xuICAgICAgICAgIHAwID0gLXAwO1xuICAgICAgICAgIHAyID0gLXAyO1xuICAgICAgICB9XG5cbiAgICAgICAgcGFkZGluZyA9IFtwMCwgcDEsIHAyLCBwM107XG4gICAgICB9IC8vIFRoZSBpbWFnZSBpcyB1bmtub3duIGF0IHRoaXMgc3RhZ2Ugc28gd2UgcGFzcyBudWxsOyBpdCB3aWxsIGJlIGNvbXB1dGVkIGF0IHJlbmRlciB0aW1lLlxuICAgICAgLy8gRm9yIGNsYXJpdHksIHdlIHBhc3MgTmFOIGZvciBvZmZzZXRYLCBvZmZzZXRZLCB3aWR0aCBhbmQgaGVpZ2h0LCB3aGljaCB3aWxsIGJlIGNvbXB1dGVkIGF0XG4gICAgICAvLyByZW5kZXIgdGltZS5cblxuXG4gICAgICB2YXIgcGl4ZWxSYXRpb18xID0gdGhpcy5waXhlbFJhdGlvO1xuICAgICAgdGhpcy5pbnN0cnVjdGlvbnMucHVzaChbQ2FudmFzSW5zdHJ1Y3Rpb24uRFJBV19JTUFHRSwgYmVnaW4sIGVuZCwgbnVsbCwgTmFOLCBOYU4sIE5hTiwgMSwgMCwgMCwgdGhpcy50ZXh0Um90YXRlV2l0aFZpZXdfLCB0aGlzLnRleHRSb3RhdGlvbl8sIFsxLCAxXSwgTmFOLCB0aGlzLmRlY2x1dHRlckltYWdlV2l0aFRleHRfLCBwYWRkaW5nID09IGRlZmF1bHRQYWRkaW5nID8gZGVmYXVsdFBhZGRpbmcgOiBwYWRkaW5nLm1hcChmdW5jdGlvbiAocCkge1xuICAgICAgICByZXR1cm4gcCAqIHBpeGVsUmF0aW9fMTtcbiAgICAgIH0pLCAhIXRleHRTdGF0ZS5iYWNrZ3JvdW5kRmlsbCwgISF0ZXh0U3RhdGUuYmFja2dyb3VuZFN0cm9rZSwgdGhpcy50ZXh0XywgdGhpcy50ZXh0S2V5XywgdGhpcy5zdHJva2VLZXlfLCB0aGlzLmZpbGxLZXlfLCB0aGlzLnRleHRPZmZzZXRYXywgdGhpcy50ZXh0T2Zmc2V0WV8sIGdlb21ldHJ5V2lkdGhzXSk7XG4gICAgICB2YXIgc2NhbGUgPSAxIC8gcGl4ZWxSYXRpb18xO1xuICAgICAgdGhpcy5oaXREZXRlY3Rpb25JbnN0cnVjdGlvbnMucHVzaChbQ2FudmFzSW5zdHJ1Y3Rpb24uRFJBV19JTUFHRSwgYmVnaW4sIGVuZCwgbnVsbCwgTmFOLCBOYU4sIE5hTiwgMSwgMCwgMCwgdGhpcy50ZXh0Um90YXRlV2l0aFZpZXdfLCB0aGlzLnRleHRSb3RhdGlvbl8sIFtzY2FsZSwgc2NhbGVdLCBOYU4sIHRoaXMuZGVjbHV0dGVySW1hZ2VXaXRoVGV4dF8sIHBhZGRpbmcsICEhdGV4dFN0YXRlLmJhY2tncm91bmRGaWxsLCAhIXRleHRTdGF0ZS5iYWNrZ3JvdW5kU3Ryb2tlLCB0aGlzLnRleHRfLCB0aGlzLnRleHRLZXlfLCB0aGlzLnN0cm9rZUtleV8sIHRoaXMuZmlsbEtleV8sIHRoaXMudGV4dE9mZnNldFhfLCB0aGlzLnRleHRPZmZzZXRZXywgZ2VvbWV0cnlXaWR0aHNdKTtcbiAgICAgIHRoaXMuZW5kR2VvbWV0cnkoZmVhdHVyZSk7XG4gICAgfVxuICB9O1xuICAvKipcbiAgICogQHByaXZhdGVcbiAgICovXG5cblxuICBDYW52YXNUZXh0QnVpbGRlci5wcm90b3R5cGUuc2F2ZVRleHRTdGF0ZXNfID0gZnVuY3Rpb24gKCkge1xuICAgIHZhciBzdHJva2VTdGF0ZSA9IHRoaXMudGV4dFN0cm9rZVN0YXRlXztcbiAgICB2YXIgdGV4dFN0YXRlID0gdGhpcy50ZXh0U3RhdGVfO1xuICAgIHZhciBmaWxsU3RhdGUgPSB0aGlzLnRleHRGaWxsU3RhdGVfO1xuICAgIHZhciBzdHJva2VLZXkgPSB0aGlzLnN0cm9rZUtleV87XG5cbiAgICBpZiAoc3Ryb2tlU3RhdGUpIHtcbiAgICAgIGlmICghKHN0cm9rZUtleSBpbiB0aGlzLnN0cm9rZVN0YXRlcykpIHtcbiAgICAgICAgdGhpcy5zdHJva2VTdGF0ZXNbc3Ryb2tlS2V5XSA9IHtcbiAgICAgICAgICBzdHJva2VTdHlsZTogc3Ryb2tlU3RhdGUuc3Ryb2tlU3R5bGUsXG4gICAgICAgICAgbGluZUNhcDogc3Ryb2tlU3RhdGUubGluZUNhcCxcbiAgICAgICAgICBsaW5lRGFzaE9mZnNldDogc3Ryb2tlU3RhdGUubGluZURhc2hPZmZzZXQsXG4gICAgICAgICAgbGluZVdpZHRoOiBzdHJva2VTdGF0ZS5saW5lV2lkdGgsXG4gICAgICAgICAgbGluZUpvaW46IHN0cm9rZVN0YXRlLmxpbmVKb2luLFxuICAgICAgICAgIG1pdGVyTGltaXQ6IHN0cm9rZVN0YXRlLm1pdGVyTGltaXQsXG4gICAgICAgICAgbGluZURhc2g6IHN0cm9rZVN0YXRlLmxpbmVEYXNoXG4gICAgICAgIH07XG4gICAgICB9XG4gICAgfVxuXG4gICAgdmFyIHRleHRLZXkgPSB0aGlzLnRleHRLZXlfO1xuXG4gICAgaWYgKCEodGV4dEtleSBpbiB0aGlzLnRleHRTdGF0ZXMpKSB7XG4gICAgICB0aGlzLnRleHRTdGF0ZXNbdGV4dEtleV0gPSB7XG4gICAgICAgIGZvbnQ6IHRleHRTdGF0ZS5mb250LFxuICAgICAgICB0ZXh0QWxpZ246IHRleHRTdGF0ZS50ZXh0QWxpZ24gfHwgZGVmYXVsdFRleHRBbGlnbixcbiAgICAgICAgdGV4dEJhc2VsaW5lOiB0ZXh0U3RhdGUudGV4dEJhc2VsaW5lIHx8IGRlZmF1bHRUZXh0QmFzZWxpbmUsXG4gICAgICAgIHNjYWxlOiB0ZXh0U3RhdGUuc2NhbGVcbiAgICAgIH07XG4gICAgfVxuXG4gICAgdmFyIGZpbGxLZXkgPSB0aGlzLmZpbGxLZXlfO1xuXG4gICAgaWYgKGZpbGxTdGF0ZSkge1xuICAgICAgaWYgKCEoZmlsbEtleSBpbiB0aGlzLmZpbGxTdGF0ZXMpKSB7XG4gICAgICAgIHRoaXMuZmlsbFN0YXRlc1tmaWxsS2V5XSA9IHtcbiAgICAgICAgICBmaWxsU3R5bGU6IGZpbGxTdGF0ZS5maWxsU3R5bGVcbiAgICAgICAgfTtcbiAgICAgIH1cbiAgICB9XG4gIH07XG4gIC8qKlxuICAgKiBAcHJpdmF0ZVxuICAgKiBAcGFyYW0ge251bWJlcn0gYmVnaW4gQmVnaW4uXG4gICAqIEBwYXJhbSB7bnVtYmVyfSBlbmQgRW5kLlxuICAgKi9cblxuXG4gIENhbnZhc1RleHRCdWlsZGVyLnByb3RvdHlwZS5kcmF3Q2hhcnNfID0gZnVuY3Rpb24gKGJlZ2luLCBlbmQpIHtcbiAgICB2YXIgc3Ryb2tlU3RhdGUgPSB0aGlzLnRleHRTdHJva2VTdGF0ZV87XG4gICAgdmFyIHRleHRTdGF0ZSA9IHRoaXMudGV4dFN0YXRlXztcbiAgICB2YXIgc3Ryb2tlS2V5ID0gdGhpcy5zdHJva2VLZXlfO1xuICAgIHZhciB0ZXh0S2V5ID0gdGhpcy50ZXh0S2V5XztcbiAgICB2YXIgZmlsbEtleSA9IHRoaXMuZmlsbEtleV87XG4gICAgdGhpcy5zYXZlVGV4dFN0YXRlc18oKTtcbiAgICB2YXIgcGl4ZWxSYXRpbyA9IHRoaXMucGl4ZWxSYXRpbztcbiAgICB2YXIgYmFzZWxpbmUgPSBURVhUX0FMSUdOW3RleHRTdGF0ZS50ZXh0QmFzZWxpbmVdO1xuICAgIHZhciBvZmZzZXRZID0gdGhpcy50ZXh0T2Zmc2V0WV8gKiBwaXhlbFJhdGlvO1xuICAgIHZhciB0ZXh0ID0gdGhpcy50ZXh0XztcbiAgICB2YXIgc3Ryb2tlV2lkdGggPSBzdHJva2VTdGF0ZSA/IHN0cm9rZVN0YXRlLmxpbmVXaWR0aCAqIE1hdGguYWJzKHRleHRTdGF0ZS5zY2FsZVswXSkgLyAyIDogMDtcbiAgICB0aGlzLmluc3RydWN0aW9ucy5wdXNoKFtDYW52YXNJbnN0cnVjdGlvbi5EUkFXX0NIQVJTLCBiZWdpbiwgZW5kLCBiYXNlbGluZSwgdGV4dFN0YXRlLm92ZXJmbG93LCBmaWxsS2V5LCB0ZXh0U3RhdGUubWF4QW5nbGUsIHBpeGVsUmF0aW8sIG9mZnNldFksIHN0cm9rZUtleSwgc3Ryb2tlV2lkdGggKiBwaXhlbFJhdGlvLCB0ZXh0LCB0ZXh0S2V5LCAxXSk7XG4gICAgdGhpcy5oaXREZXRlY3Rpb25JbnN0cnVjdGlvbnMucHVzaChbQ2FudmFzSW5zdHJ1Y3Rpb24uRFJBV19DSEFSUywgYmVnaW4sIGVuZCwgYmFzZWxpbmUsIHRleHRTdGF0ZS5vdmVyZmxvdywgZmlsbEtleSwgdGV4dFN0YXRlLm1heEFuZ2xlLCAxLCBvZmZzZXRZLCBzdHJva2VLZXksIHN0cm9rZVdpZHRoLCB0ZXh0LCB0ZXh0S2V5LCAxIC8gcGl4ZWxSYXRpb10pO1xuICB9O1xuICAvKipcbiAgICogQHBhcmFtIHtpbXBvcnQoXCIuLi8uLi9zdHlsZS9UZXh0LmpzXCIpLmRlZmF1bHR9IHRleHRTdHlsZSBUZXh0IHN0eWxlLlxuICAgKiBAcGFyYW0ge09iamVjdD19IG9wdF9zaGFyZWREYXRhIFNoYXJlZCBkYXRhLlxuICAgKi9cblxuXG4gIENhbnZhc1RleHRCdWlsZGVyLnByb3RvdHlwZS5zZXRUZXh0U3R5bGUgPSBmdW5jdGlvbiAodGV4dFN0eWxlLCBvcHRfc2hhcmVkRGF0YSkge1xuICAgIHZhciB0ZXh0U3RhdGUsIGZpbGxTdGF0ZSwgc3Ryb2tlU3RhdGU7XG5cbiAgICBpZiAoIXRleHRTdHlsZSkge1xuICAgICAgdGhpcy50ZXh0XyA9ICcnO1xuICAgIH0gZWxzZSB7XG4gICAgICB2YXIgdGV4dEZpbGxTdHlsZSA9IHRleHRTdHlsZS5nZXRGaWxsKCk7XG5cbiAgICAgIGlmICghdGV4dEZpbGxTdHlsZSkge1xuICAgICAgICBmaWxsU3RhdGUgPSBudWxsO1xuICAgICAgICB0aGlzLnRleHRGaWxsU3RhdGVfID0gZmlsbFN0YXRlO1xuICAgICAgfSBlbHNlIHtcbiAgICAgICAgZmlsbFN0YXRlID0gdGhpcy50ZXh0RmlsbFN0YXRlXztcblxuICAgICAgICBpZiAoIWZpbGxTdGF0ZSkge1xuICAgICAgICAgIGZpbGxTdGF0ZSA9XG4gICAgICAgICAgLyoqIEB0eXBlIHtpbXBvcnQoXCIuLi9jYW52YXMuanNcIikuRmlsbFN0YXRlfSAqL1xuICAgICAgICAgIHt9O1xuICAgICAgICAgIHRoaXMudGV4dEZpbGxTdGF0ZV8gPSBmaWxsU3RhdGU7XG4gICAgICAgIH1cblxuICAgICAgICBmaWxsU3RhdGUuZmlsbFN0eWxlID0gYXNDb2xvckxpa2UodGV4dEZpbGxTdHlsZS5nZXRDb2xvcigpIHx8IGRlZmF1bHRGaWxsU3R5bGUpO1xuICAgICAgfVxuXG4gICAgICB2YXIgdGV4dFN0cm9rZVN0eWxlID0gdGV4dFN0eWxlLmdldFN0cm9rZSgpO1xuXG4gICAgICBpZiAoIXRleHRTdHJva2VTdHlsZSkge1xuICAgICAgICBzdHJva2VTdGF0ZSA9IG51bGw7XG4gICAgICAgIHRoaXMudGV4dFN0cm9rZVN0YXRlXyA9IHN0cm9rZVN0YXRlO1xuICAgICAgfSBlbHNlIHtcbiAgICAgICAgc3Ryb2tlU3RhdGUgPSB0aGlzLnRleHRTdHJva2VTdGF0ZV87XG5cbiAgICAgICAgaWYgKCFzdHJva2VTdGF0ZSkge1xuICAgICAgICAgIHN0cm9rZVN0YXRlID1cbiAgICAgICAgICAvKiogQHR5cGUge2ltcG9ydChcIi4uL2NhbnZhcy5qc1wiKS5TdHJva2VTdGF0ZX0gKi9cbiAgICAgICAgICB7fTtcbiAgICAgICAgICB0aGlzLnRleHRTdHJva2VTdGF0ZV8gPSBzdHJva2VTdGF0ZTtcbiAgICAgICAgfVxuXG4gICAgICAgIHZhciBsaW5lRGFzaCA9IHRleHRTdHJva2VTdHlsZS5nZXRMaW5lRGFzaCgpO1xuICAgICAgICB2YXIgbGluZURhc2hPZmZzZXQgPSB0ZXh0U3Ryb2tlU3R5bGUuZ2V0TGluZURhc2hPZmZzZXQoKTtcbiAgICAgICAgdmFyIGxpbmVXaWR0aCA9IHRleHRTdHJva2VTdHlsZS5nZXRXaWR0aCgpO1xuICAgICAgICB2YXIgbWl0ZXJMaW1pdCA9IHRleHRTdHJva2VTdHlsZS5nZXRNaXRlckxpbWl0KCk7XG4gICAgICAgIHN0cm9rZVN0YXRlLmxpbmVDYXAgPSB0ZXh0U3Ryb2tlU3R5bGUuZ2V0TGluZUNhcCgpIHx8IGRlZmF1bHRMaW5lQ2FwO1xuICAgICAgICBzdHJva2VTdGF0ZS5saW5lRGFzaCA9IGxpbmVEYXNoID8gbGluZURhc2guc2xpY2UoKSA6IGRlZmF1bHRMaW5lRGFzaDtcbiAgICAgICAgc3Ryb2tlU3RhdGUubGluZURhc2hPZmZzZXQgPSBsaW5lRGFzaE9mZnNldCA9PT0gdW5kZWZpbmVkID8gZGVmYXVsdExpbmVEYXNoT2Zmc2V0IDogbGluZURhc2hPZmZzZXQ7XG4gICAgICAgIHN0cm9rZVN0YXRlLmxpbmVKb2luID0gdGV4dFN0cm9rZVN0eWxlLmdldExpbmVKb2luKCkgfHwgZGVmYXVsdExpbmVKb2luO1xuICAgICAgICBzdHJva2VTdGF0ZS5saW5lV2lkdGggPSBsaW5lV2lkdGggPT09IHVuZGVmaW5lZCA/IGRlZmF1bHRMaW5lV2lkdGggOiBsaW5lV2lkdGg7XG4gICAgICAgIHN0cm9rZVN0YXRlLm1pdGVyTGltaXQgPSBtaXRlckxpbWl0ID09PSB1bmRlZmluZWQgPyBkZWZhdWx0TWl0ZXJMaW1pdCA6IG1pdGVyTGltaXQ7XG4gICAgICAgIHN0cm9rZVN0YXRlLnN0cm9rZVN0eWxlID0gYXNDb2xvckxpa2UodGV4dFN0cm9rZVN0eWxlLmdldENvbG9yKCkgfHwgZGVmYXVsdFN0cm9rZVN0eWxlKTtcbiAgICAgIH1cblxuICAgICAgdGV4dFN0YXRlID0gdGhpcy50ZXh0U3RhdGVfO1xuICAgICAgdmFyIGZvbnQgPSB0ZXh0U3R5bGUuZ2V0Rm9udCgpIHx8IGRlZmF1bHRGb250O1xuICAgICAgcmVnaXN0ZXJGb250KGZvbnQpO1xuICAgICAgdmFyIHRleHRTY2FsZSA9IHRleHRTdHlsZS5nZXRTY2FsZUFycmF5KCk7XG4gICAgICB0ZXh0U3RhdGUub3ZlcmZsb3cgPSB0ZXh0U3R5bGUuZ2V0T3ZlcmZsb3coKTtcbiAgICAgIHRleHRTdGF0ZS5mb250ID0gZm9udDtcbiAgICAgIHRleHRTdGF0ZS5tYXhBbmdsZSA9IHRleHRTdHlsZS5nZXRNYXhBbmdsZSgpO1xuICAgICAgdGV4dFN0YXRlLnBsYWNlbWVudCA9IHRleHRTdHlsZS5nZXRQbGFjZW1lbnQoKTtcbiAgICAgIHRleHRTdGF0ZS50ZXh0QWxpZ24gPSB0ZXh0U3R5bGUuZ2V0VGV4dEFsaWduKCk7XG4gICAgICB0ZXh0U3RhdGUudGV4dEJhc2VsaW5lID0gdGV4dFN0eWxlLmdldFRleHRCYXNlbGluZSgpIHx8IGRlZmF1bHRUZXh0QmFzZWxpbmU7XG4gICAgICB0ZXh0U3RhdGUuYmFja2dyb3VuZEZpbGwgPSB0ZXh0U3R5bGUuZ2V0QmFja2dyb3VuZEZpbGwoKTtcbiAgICAgIHRleHRTdGF0ZS5iYWNrZ3JvdW5kU3Ryb2tlID0gdGV4dFN0eWxlLmdldEJhY2tncm91bmRTdHJva2UoKTtcbiAgICAgIHRleHRTdGF0ZS5wYWRkaW5nID0gdGV4dFN0eWxlLmdldFBhZGRpbmcoKSB8fCBkZWZhdWx0UGFkZGluZztcbiAgICAgIHRleHRTdGF0ZS5zY2FsZSA9IHRleHRTY2FsZSA9PT0gdW5kZWZpbmVkID8gWzEsIDFdIDogdGV4dFNjYWxlO1xuICAgICAgdmFyIHRleHRPZmZzZXRYID0gdGV4dFN0eWxlLmdldE9mZnNldFgoKTtcbiAgICAgIHZhciB0ZXh0T2Zmc2V0WSA9IHRleHRTdHlsZS5nZXRPZmZzZXRZKCk7XG4gICAgICB2YXIgdGV4dFJvdGF0ZVdpdGhWaWV3ID0gdGV4dFN0eWxlLmdldFJvdGF0ZVdpdGhWaWV3KCk7XG4gICAgICB2YXIgdGV4dFJvdGF0aW9uID0gdGV4dFN0eWxlLmdldFJvdGF0aW9uKCk7XG4gICAgICB0aGlzLnRleHRfID0gdGV4dFN0eWxlLmdldFRleHQoKSB8fCAnJztcbiAgICAgIHRoaXMudGV4dE9mZnNldFhfID0gdGV4dE9mZnNldFggPT09IHVuZGVmaW5lZCA/IDAgOiB0ZXh0T2Zmc2V0WDtcbiAgICAgIHRoaXMudGV4dE9mZnNldFlfID0gdGV4dE9mZnNldFkgPT09IHVuZGVmaW5lZCA/IDAgOiB0ZXh0T2Zmc2V0WTtcbiAgICAgIHRoaXMudGV4dFJvdGF0ZVdpdGhWaWV3XyA9IHRleHRSb3RhdGVXaXRoVmlldyA9PT0gdW5kZWZpbmVkID8gZmFsc2UgOiB0ZXh0Um90YXRlV2l0aFZpZXc7XG4gICAgICB0aGlzLnRleHRSb3RhdGlvbl8gPSB0ZXh0Um90YXRpb24gPT09IHVuZGVmaW5lZCA/IDAgOiB0ZXh0Um90YXRpb247XG4gICAgICB0aGlzLnN0cm9rZUtleV8gPSBzdHJva2VTdGF0ZSA/ICh0eXBlb2Ygc3Ryb2tlU3RhdGUuc3Ryb2tlU3R5bGUgPT0gJ3N0cmluZycgPyBzdHJva2VTdGF0ZS5zdHJva2VTdHlsZSA6IGdldFVpZChzdHJva2VTdGF0ZS5zdHJva2VTdHlsZSkpICsgc3Ryb2tlU3RhdGUubGluZUNhcCArIHN0cm9rZVN0YXRlLmxpbmVEYXNoT2Zmc2V0ICsgJ3wnICsgc3Ryb2tlU3RhdGUubGluZVdpZHRoICsgc3Ryb2tlU3RhdGUubGluZUpvaW4gKyBzdHJva2VTdGF0ZS5taXRlckxpbWl0ICsgJ1snICsgc3Ryb2tlU3RhdGUubGluZURhc2guam9pbigpICsgJ10nIDogJyc7XG4gICAgICB0aGlzLnRleHRLZXlfID0gdGV4dFN0YXRlLmZvbnQgKyB0ZXh0U3RhdGUuc2NhbGUgKyAodGV4dFN0YXRlLnRleHRBbGlnbiB8fCAnPycpICsgKHRleHRTdGF0ZS50ZXh0QmFzZWxpbmUgfHwgJz8nKTtcbiAgICAgIHRoaXMuZmlsbEtleV8gPSBmaWxsU3RhdGUgPyB0eXBlb2YgZmlsbFN0YXRlLmZpbGxTdHlsZSA9PSAnc3RyaW5nJyA/IGZpbGxTdGF0ZS5maWxsU3R5bGUgOiAnfCcgKyBnZXRVaWQoZmlsbFN0YXRlLmZpbGxTdHlsZSkgOiAnJztcbiAgICB9XG5cbiAgICB0aGlzLmRlY2x1dHRlckltYWdlV2l0aFRleHRfID0gb3B0X3NoYXJlZERhdGE7XG4gIH07XG5cbiAgcmV0dXJuIENhbnZhc1RleHRCdWlsZGVyO1xufShDYW52YXNCdWlsZGVyKTtcblxuZXhwb3J0IGRlZmF1bHQgQ2FudmFzVGV4dEJ1aWxkZXI7IiwiLyoqXG4gKiBAbW9kdWxlIG9sL3JlbmRlci9jYW52YXMvQnVpbGRlckdyb3VwXG4gKi9cbmltcG9ydCBCdWlsZGVyIGZyb20gJy4vQnVpbGRlci5qcyc7XG5pbXBvcnQgSW1hZ2VCdWlsZGVyIGZyb20gJy4vSW1hZ2VCdWlsZGVyLmpzJztcbmltcG9ydCBMaW5lU3RyaW5nQnVpbGRlciBmcm9tICcuL0xpbmVTdHJpbmdCdWlsZGVyLmpzJztcbmltcG9ydCBQb2x5Z29uQnVpbGRlciBmcm9tICcuL1BvbHlnb25CdWlsZGVyLmpzJztcbmltcG9ydCBUZXh0QnVpbGRlciBmcm9tICcuL1RleHRCdWlsZGVyLmpzJztcbi8qKlxuICogQHR5cGUge09iamVjdDxpbXBvcnQoXCIuL0J1aWxkZXJUeXBlXCIpLmRlZmF1bHQsIHR5cGVvZiBCdWlsZGVyPn1cbiAqL1xuXG52YXIgQkFUQ0hfQ09OU1RSVUNUT1JTID0ge1xuICAnQ2lyY2xlJzogUG9seWdvbkJ1aWxkZXIsXG4gICdEZWZhdWx0JzogQnVpbGRlcixcbiAgJ0ltYWdlJzogSW1hZ2VCdWlsZGVyLFxuICAnTGluZVN0cmluZyc6IExpbmVTdHJpbmdCdWlsZGVyLFxuICAnUG9seWdvbic6IFBvbHlnb25CdWlsZGVyLFxuICAnVGV4dCc6IFRleHRCdWlsZGVyXG59O1xuXG52YXIgQnVpbGRlckdyb3VwID1cbi8qKiBAY2xhc3MgKi9cbmZ1bmN0aW9uICgpIHtcbiAgLyoqXG4gICAqIEBwYXJhbSB7bnVtYmVyfSB0b2xlcmFuY2UgVG9sZXJhbmNlLlxuICAgKiBAcGFyYW0ge2ltcG9ydChcIi4uLy4uL2V4dGVudC5qc1wiKS5FeHRlbnR9IG1heEV4dGVudCBNYXggZXh0ZW50LlxuICAgKiBAcGFyYW0ge251bWJlcn0gcmVzb2x1dGlvbiBSZXNvbHV0aW9uLlxuICAgKiBAcGFyYW0ge251bWJlcn0gcGl4ZWxSYXRpbyBQaXhlbCByYXRpby5cbiAgICovXG4gIGZ1bmN0aW9uIEJ1aWxkZXJHcm91cCh0b2xlcmFuY2UsIG1heEV4dGVudCwgcmVzb2x1dGlvbiwgcGl4ZWxSYXRpbykge1xuICAgIC8qKlxuICAgICAqIEBwcml2YXRlXG4gICAgICogQHR5cGUge251bWJlcn1cbiAgICAgKi9cbiAgICB0aGlzLnRvbGVyYW5jZV8gPSB0b2xlcmFuY2U7XG4gICAgLyoqXG4gICAgICogQHByaXZhdGVcbiAgICAgKiBAdHlwZSB7aW1wb3J0KFwiLi4vLi4vZXh0ZW50LmpzXCIpLkV4dGVudH1cbiAgICAgKi9cblxuICAgIHRoaXMubWF4RXh0ZW50XyA9IG1heEV4dGVudDtcbiAgICAvKipcbiAgICAgKiBAcHJpdmF0ZVxuICAgICAqIEB0eXBlIHtudW1iZXJ9XG4gICAgICovXG5cbiAgICB0aGlzLnBpeGVsUmF0aW9fID0gcGl4ZWxSYXRpbztcbiAgICAvKipcbiAgICAgKiBAcHJpdmF0ZVxuICAgICAqIEB0eXBlIHtudW1iZXJ9XG4gICAgICovXG5cbiAgICB0aGlzLnJlc29sdXRpb25fID0gcmVzb2x1dGlvbjtcbiAgICAvKipcbiAgICAgKiBAcHJpdmF0ZVxuICAgICAqIEB0eXBlIHshT2JqZWN0PHN0cmluZywgIU9iamVjdDxpbXBvcnQoXCIuL0J1aWxkZXJUeXBlXCIpLmRlZmF1bHQsIEJ1aWxkZXI+Pn1cbiAgICAgKi9cblxuICAgIHRoaXMuYnVpbGRlcnNCeVpJbmRleF8gPSB7fTtcbiAgfVxuICAvKipcbiAgICogQHJldHVybiB7IU9iamVjdDxzdHJpbmcsICFPYmplY3Q8aW1wb3J0KFwiLi9CdWlsZGVyVHlwZVwiKS5kZWZhdWx0LCBpbXBvcnQoXCIuL0J1aWxkZXIuanNcIikuU2VyaWFsaXphYmxlSW5zdHJ1Y3Rpb25zPj59IFRoZSBzZXJpYWxpemFibGUgaW5zdHJ1Y3Rpb25zXG4gICAqL1xuXG5cbiAgQnVpbGRlckdyb3VwLnByb3RvdHlwZS5maW5pc2ggPSBmdW5jdGlvbiAoKSB7XG4gICAgdmFyIGJ1aWxkZXJJbnN0cnVjdGlvbnMgPSB7fTtcblxuICAgIGZvciAodmFyIHpLZXkgaW4gdGhpcy5idWlsZGVyc0J5WkluZGV4Xykge1xuICAgICAgYnVpbGRlckluc3RydWN0aW9uc1t6S2V5XSA9IGJ1aWxkZXJJbnN0cnVjdGlvbnNbektleV0gfHwge307XG4gICAgICB2YXIgYnVpbGRlcnMgPSB0aGlzLmJ1aWxkZXJzQnlaSW5kZXhfW3pLZXldO1xuXG4gICAgICBmb3IgKHZhciBidWlsZGVyS2V5IGluIGJ1aWxkZXJzKSB7XG4gICAgICAgIHZhciBidWlsZGVySW5zdHJ1Y3Rpb24gPSBidWlsZGVyc1tidWlsZGVyS2V5XS5maW5pc2goKTtcbiAgICAgICAgYnVpbGRlckluc3RydWN0aW9uc1t6S2V5XVtidWlsZGVyS2V5XSA9IGJ1aWxkZXJJbnN0cnVjdGlvbjtcbiAgICAgIH1cbiAgICB9XG5cbiAgICByZXR1cm4gYnVpbGRlckluc3RydWN0aW9ucztcbiAgfTtcbiAgLyoqXG4gICAqIEBwYXJhbSB7bnVtYmVyfHVuZGVmaW5lZH0gekluZGV4IFogaW5kZXguXG4gICAqIEBwYXJhbSB7aW1wb3J0KFwiLi9CdWlsZGVyVHlwZS5qc1wiKS5kZWZhdWx0fSBidWlsZGVyVHlwZSBSZXBsYXkgdHlwZS5cbiAgICogQHJldHVybiB7aW1wb3J0KFwiLi4vVmVjdG9yQ29udGV4dC5qc1wiKS5kZWZhdWx0fSBSZXBsYXkuXG4gICAqL1xuXG5cbiAgQnVpbGRlckdyb3VwLnByb3RvdHlwZS5nZXRCdWlsZGVyID0gZnVuY3Rpb24gKHpJbmRleCwgYnVpbGRlclR5cGUpIHtcbiAgICB2YXIgekluZGV4S2V5ID0gekluZGV4ICE9PSB1bmRlZmluZWQgPyB6SW5kZXgudG9TdHJpbmcoKSA6ICcwJztcbiAgICB2YXIgcmVwbGF5cyA9IHRoaXMuYnVpbGRlcnNCeVpJbmRleF9bekluZGV4S2V5XTtcblxuICAgIGlmIChyZXBsYXlzID09PSB1bmRlZmluZWQpIHtcbiAgICAgIHJlcGxheXMgPSB7fTtcbiAgICAgIHRoaXMuYnVpbGRlcnNCeVpJbmRleF9bekluZGV4S2V5XSA9IHJlcGxheXM7XG4gICAgfVxuXG4gICAgdmFyIHJlcGxheSA9IHJlcGxheXNbYnVpbGRlclR5cGVdO1xuXG4gICAgaWYgKHJlcGxheSA9PT0gdW5kZWZpbmVkKSB7XG4gICAgICB2YXIgQ29uc3RydWN0b3IgPSBCQVRDSF9DT05TVFJVQ1RPUlNbYnVpbGRlclR5cGVdO1xuICAgICAgcmVwbGF5ID0gbmV3IENvbnN0cnVjdG9yKHRoaXMudG9sZXJhbmNlXywgdGhpcy5tYXhFeHRlbnRfLCB0aGlzLnJlc29sdXRpb25fLCB0aGlzLnBpeGVsUmF0aW9fKTtcbiAgICAgIHJlcGxheXNbYnVpbGRlclR5cGVdID0gcmVwbGF5O1xuICAgIH1cblxuICAgIHJldHVybiByZXBsYXk7XG4gIH07XG5cbiAgcmV0dXJuIEJ1aWxkZXJHcm91cDtcbn0oKTtcblxuZXhwb3J0IGRlZmF1bHQgQnVpbGRlckdyb3VwOyIsIi8qKlxuICogQG1vZHVsZSBvbC9yZW5kZXIvY2FudmFzL0J1aWxkZXJUeXBlXG4gKi9cblxuLyoqXG4gKiBAZW51bSB7c3RyaW5nfVxuICovXG5leHBvcnQgZGVmYXVsdCB7XG4gIENJUkNMRTogJ0NpcmNsZScsXG4gIERFRkFVTFQ6ICdEZWZhdWx0JyxcbiAgSU1BR0U6ICdJbWFnZScsXG4gIExJTkVfU1RSSU5HOiAnTGluZVN0cmluZycsXG4gIFBPTFlHT046ICdQb2x5Z29uJyxcbiAgVEVYVDogJ1RleHQnXG59OyIsIi8qKlxuICogQG1vZHVsZSBvbC9nZW9tL2ZsYXQvdGV4dHBhdGhcbiAqL1xuaW1wb3J0IHsgbGVycCB9IGZyb20gJy4uLy4uL21hdGguanMnO1xuaW1wb3J0IHsgcm90YXRlIH0gZnJvbSAnLi90cmFuc2Zvcm0uanMnO1xuLyoqXG4gKiBAcGFyYW0ge0FycmF5PG51bWJlcj59IGZsYXRDb29yZGluYXRlcyBQYXRoIHRvIHB1dCB0ZXh0IG9uLlxuICogQHBhcmFtIHtudW1iZXJ9IG9mZnNldCBTdGFydCBvZmZzZXQgb2YgdGhlIGBmbGF0Q29vcmRpbmF0ZXNgLlxuICogQHBhcmFtIHtudW1iZXJ9IGVuZCBFbmQgb2Zmc2V0IG9mIHRoZSBgZmxhdENvb3JkaW5hdGVzYC5cbiAqIEBwYXJhbSB7bnVtYmVyfSBzdHJpZGUgU3RyaWRlLlxuICogQHBhcmFtIHtzdHJpbmd9IHRleHQgVGV4dCB0byBwbGFjZSBvbiB0aGUgcGF0aC5cbiAqIEBwYXJhbSB7bnVtYmVyfSBzdGFydE0gbSBhbG9uZyB0aGUgcGF0aCB3aGVyZSB0aGUgdGV4dCBzdGFydHMuXG4gKiBAcGFyYW0ge251bWJlcn0gbWF4QW5nbGUgTWF4IGFuZ2xlIGJldHdlZW4gYWRqYWNlbnQgY2hhcnMgaW4gcmFkaWFucy5cbiAqIEBwYXJhbSB7bnVtYmVyfSBzY2FsZSBUaGUgcHJvZHVjdCBvZiB0aGUgdGV4dCBzY2FsZSBhbmQgdGhlIGRldmljZSBwaXhlbCByYXRpby5cbiAqIEBwYXJhbSB7ZnVuY3Rpb24oc3RyaW5nLCBzdHJpbmcsIE9iamVjdDxzdHJpbmcsIG51bWJlcj4pOm51bWJlcn0gbWVhc3VyZUFuZENhY2hlVGV4dFdpZHRoIE1lYXN1cmUgYW5kIGNhY2hlIHRleHQgd2lkdGguXG4gKiBAcGFyYW0ge3N0cmluZ30gZm9udCBUaGUgZm9udC5cbiAqIEBwYXJhbSB7T2JqZWN0PHN0cmluZywgbnVtYmVyPn0gY2FjaGUgQSBjYWNoZSBvZiBtZWFzdXJlZCB3aWR0aHMuXG4gKiBAcGFyYW0ge251bWJlcn0gcm90YXRpb24gUm90YXRpb24gdG8gYXBwbHkgdG8gdGhlIGZsYXRDb29yZGluYXRlcyB0byBkZXRlcm1pbmUgd2hldGhlciB0ZXh0IG5lZWRzIHRvIGJlIHJldmVyc2VkLlxuICogQHJldHVybiB7QXJyYXk8QXJyYXk8Kj4+fSBUaGUgcmVzdWx0IGFycmF5IChvciBudWxsIGlmIGBtYXhBbmdsZWAgd2FzXG4gKiBleGNlZWRlZCkuIEVudHJpZXMgb2YgdGhlIGFycmF5IGFyZSB4LCB5LCBhbmNob3JYLCBhbmdsZSwgY2h1bmsuXG4gKi9cblxuZXhwb3J0IGZ1bmN0aW9uIGRyYXdUZXh0T25QYXRoKGZsYXRDb29yZGluYXRlcywgb2Zmc2V0LCBlbmQsIHN0cmlkZSwgdGV4dCwgc3RhcnRNLCBtYXhBbmdsZSwgc2NhbGUsIG1lYXN1cmVBbmRDYWNoZVRleHRXaWR0aCwgZm9udCwgY2FjaGUsIHJvdGF0aW9uKSB7XG4gIHZhciB4MiA9IGZsYXRDb29yZGluYXRlc1tvZmZzZXRdO1xuICB2YXIgeTIgPSBmbGF0Q29vcmRpbmF0ZXNbb2Zmc2V0ICsgMV07XG4gIHZhciB4MSA9IDA7XG4gIHZhciB5MSA9IDA7XG4gIHZhciBzZWdtZW50TGVuZ3RoID0gMDtcbiAgdmFyIHNlZ21lbnRNID0gMDtcblxuICBmdW5jdGlvbiBhZHZhbmNlKCkge1xuICAgIHgxID0geDI7XG4gICAgeTEgPSB5MjtcbiAgICBvZmZzZXQgKz0gc3RyaWRlO1xuICAgIHgyID0gZmxhdENvb3JkaW5hdGVzW29mZnNldF07XG4gICAgeTIgPSBmbGF0Q29vcmRpbmF0ZXNbb2Zmc2V0ICsgMV07XG4gICAgc2VnbWVudE0gKz0gc2VnbWVudExlbmd0aDtcbiAgICBzZWdtZW50TGVuZ3RoID0gTWF0aC5zcXJ0KCh4MiAtIHgxKSAqICh4MiAtIHgxKSArICh5MiAtIHkxKSAqICh5MiAtIHkxKSk7XG4gIH1cblxuICBkbyB7XG4gICAgYWR2YW5jZSgpO1xuICB9IHdoaWxlIChvZmZzZXQgPCBlbmQgLSBzdHJpZGUgJiYgc2VnbWVudE0gKyBzZWdtZW50TGVuZ3RoIDwgc3RhcnRNKTtcblxuICB2YXIgaW50ZXJwb2xhdGUgPSAoc3RhcnRNIC0gc2VnbWVudE0pIC8gc2VnbWVudExlbmd0aDtcbiAgdmFyIGJlZ2luWCA9IGxlcnAoeDEsIHgyLCBpbnRlcnBvbGF0ZSk7XG4gIHZhciBiZWdpblkgPSBsZXJwKHkxLCB5MiwgaW50ZXJwb2xhdGUpO1xuICB2YXIgc3RhcnRPZmZzZXQgPSBvZmZzZXQgLSBzdHJpZGU7XG4gIHZhciBzdGFydExlbmd0aCA9IHNlZ21lbnRNO1xuICB2YXIgZW5kTSA9IHN0YXJ0TSArIHNjYWxlICogbWVhc3VyZUFuZENhY2hlVGV4dFdpZHRoKGZvbnQsIHRleHQsIGNhY2hlKTtcblxuICB3aGlsZSAob2Zmc2V0IDwgZW5kIC0gc3RyaWRlICYmIHNlZ21lbnRNICsgc2VnbWVudExlbmd0aCA8IGVuZE0pIHtcbiAgICBhZHZhbmNlKCk7XG4gIH1cblxuICBpbnRlcnBvbGF0ZSA9IChlbmRNIC0gc2VnbWVudE0pIC8gc2VnbWVudExlbmd0aDtcbiAgdmFyIGVuZFggPSBsZXJwKHgxLCB4MiwgaW50ZXJwb2xhdGUpO1xuICB2YXIgZW5kWSA9IGxlcnAoeTEsIHkyLCBpbnRlcnBvbGF0ZSk7IC8vIEtlZXAgdGV4dCB1cHJpZ2h0XG5cbiAgdmFyIHJldmVyc2U7XG5cbiAgaWYgKHJvdGF0aW9uKSB7XG4gICAgdmFyIGZsYXQgPSBbYmVnaW5YLCBiZWdpblksIGVuZFgsIGVuZFldO1xuICAgIHJvdGF0ZShmbGF0LCAwLCA0LCAyLCByb3RhdGlvbiwgZmxhdCwgZmxhdCk7XG4gICAgcmV2ZXJzZSA9IGZsYXRbMF0gPiBmbGF0WzJdO1xuICB9IGVsc2Uge1xuICAgIHJldmVyc2UgPSBiZWdpblggPiBlbmRYO1xuICB9XG5cbiAgdmFyIFBJID0gTWF0aC5QSTtcbiAgdmFyIHJlc3VsdCA9IFtdO1xuICB2YXIgc2luZ2xlU2VnbWVudCA9IHN0YXJ0T2Zmc2V0ICsgc3RyaWRlID09PSBvZmZzZXQ7XG4gIG9mZnNldCA9IHN0YXJ0T2Zmc2V0O1xuICBzZWdtZW50TGVuZ3RoID0gMDtcbiAgc2VnbWVudE0gPSBzdGFydExlbmd0aDtcbiAgeDIgPSBmbGF0Q29vcmRpbmF0ZXNbb2Zmc2V0XTtcbiAgeTIgPSBmbGF0Q29vcmRpbmF0ZXNbb2Zmc2V0ICsgMV07IC8vIEFsbCBvbiB0aGUgc2FtZSBzZWdtZW50XG5cbiAgaWYgKHNpbmdsZVNlZ21lbnQpIHtcbiAgICBhZHZhbmNlKCk7XG4gICAgdmFyIHByZXZpb3VzQW5nbGVfMSA9IE1hdGguYXRhbjIoeTIgLSB5MSwgeDIgLSB4MSk7XG5cbiAgICBpZiAocmV2ZXJzZSkge1xuICAgICAgcHJldmlvdXNBbmdsZV8xICs9IHByZXZpb3VzQW5nbGVfMSA+IDAgPyAtUEkgOiBQSTtcbiAgICB9XG5cbiAgICB2YXIgeCA9IChlbmRYICsgYmVnaW5YKSAvIDI7XG4gICAgdmFyIHkgPSAoZW5kWSArIGJlZ2luWSkgLyAyO1xuICAgIHJlc3VsdFswXSA9IFt4LCB5LCAoZW5kTSAtIHN0YXJ0TSkgLyAyLCBwcmV2aW91c0FuZ2xlXzEsIHRleHRdO1xuICAgIHJldHVybiByZXN1bHQ7XG4gIH1cblxuICB2YXIgcHJldmlvdXNBbmdsZTtcblxuICBmb3IgKHZhciBpID0gMCwgaWkgPSB0ZXh0Lmxlbmd0aDsgaSA8IGlpOykge1xuICAgIGFkdmFuY2UoKTtcbiAgICB2YXIgYW5nbGUgPSBNYXRoLmF0YW4yKHkyIC0geTEsIHgyIC0geDEpO1xuXG4gICAgaWYgKHJldmVyc2UpIHtcbiAgICAgIGFuZ2xlICs9IGFuZ2xlID4gMCA/IC1QSSA6IFBJO1xuICAgIH1cblxuICAgIGlmIChwcmV2aW91c0FuZ2xlICE9PSB1bmRlZmluZWQpIHtcbiAgICAgIHZhciBkZWx0YSA9IGFuZ2xlIC0gcHJldmlvdXNBbmdsZTtcbiAgICAgIGRlbHRhICs9IGRlbHRhID4gUEkgPyAtMiAqIFBJIDogZGVsdGEgPCAtUEkgPyAyICogUEkgOiAwO1xuXG4gICAgICBpZiAoTWF0aC5hYnMoZGVsdGEpID4gbWF4QW5nbGUpIHtcbiAgICAgICAgcmV0dXJuIG51bGw7XG4gICAgICB9XG4gICAgfVxuXG4gICAgcHJldmlvdXNBbmdsZSA9IGFuZ2xlO1xuICAgIHZhciBpU3RhcnQgPSBpO1xuICAgIHZhciBjaGFyTGVuZ3RoID0gMDtcblxuICAgIGZvciAoOyBpIDwgaWk7ICsraSkge1xuICAgICAgdmFyIGluZGV4ID0gcmV2ZXJzZSA/IGlpIC0gaSAtIDEgOiBpO1xuICAgICAgdmFyIGxlbiA9IHNjYWxlICogbWVhc3VyZUFuZENhY2hlVGV4dFdpZHRoKGZvbnQsIHRleHRbaW5kZXhdLCBjYWNoZSk7XG5cbiAgICAgIGlmIChvZmZzZXQgKyBzdHJpZGUgPCBlbmQgJiYgc2VnbWVudE0gKyBzZWdtZW50TGVuZ3RoIDwgc3RhcnRNICsgY2hhckxlbmd0aCArIGxlbiAvIDIpIHtcbiAgICAgICAgYnJlYWs7XG4gICAgICB9XG5cbiAgICAgIGNoYXJMZW5ndGggKz0gbGVuO1xuICAgIH1cblxuICAgIGlmIChpID09PSBpU3RhcnQpIHtcbiAgICAgIGNvbnRpbnVlO1xuICAgIH1cblxuICAgIHZhciBjaGFycyA9IHJldmVyc2UgPyB0ZXh0LnN1YnN0cmluZyhpaSAtIGlTdGFydCwgaWkgLSBpKSA6IHRleHQuc3Vic3RyaW5nKGlTdGFydCwgaSk7XG4gICAgaW50ZXJwb2xhdGUgPSAoc3RhcnRNICsgY2hhckxlbmd0aCAvIDIgLSBzZWdtZW50TSkgLyBzZWdtZW50TGVuZ3RoO1xuICAgIHZhciB4ID0gbGVycCh4MSwgeDIsIGludGVycG9sYXRlKTtcbiAgICB2YXIgeSA9IGxlcnAoeTEsIHkyLCBpbnRlcnBvbGF0ZSk7XG4gICAgcmVzdWx0LnB1c2goW3gsIHksIGNoYXJMZW5ndGggLyAyLCBhbmdsZSwgY2hhcnNdKTtcbiAgICBzdGFydE0gKz0gY2hhckxlbmd0aDtcbiAgfVxuXG4gIHJldHVybiByZXN1bHQ7XG59IiwiLyoqXG4gKiBAbW9kdWxlIG9sL2dlb20vZmxhdC9sZW5ndGhcbiAqL1xuXG4vKipcbiAqIEBwYXJhbSB7QXJyYXk8bnVtYmVyPn0gZmxhdENvb3JkaW5hdGVzIEZsYXQgY29vcmRpbmF0ZXMuXG4gKiBAcGFyYW0ge251bWJlcn0gb2Zmc2V0IE9mZnNldC5cbiAqIEBwYXJhbSB7bnVtYmVyfSBlbmQgRW5kLlxuICogQHBhcmFtIHtudW1iZXJ9IHN0cmlkZSBTdHJpZGUuXG4gKiBAcmV0dXJuIHtudW1iZXJ9IExlbmd0aC5cbiAqL1xuZXhwb3J0IGZ1bmN0aW9uIGxpbmVTdHJpbmdMZW5ndGgoZmxhdENvb3JkaW5hdGVzLCBvZmZzZXQsIGVuZCwgc3RyaWRlKSB7XG4gIHZhciB4MSA9IGZsYXRDb29yZGluYXRlc1tvZmZzZXRdO1xuICB2YXIgeTEgPSBmbGF0Q29vcmRpbmF0ZXNbb2Zmc2V0ICsgMV07XG4gIHZhciBsZW5ndGggPSAwO1xuXG4gIGZvciAodmFyIGkgPSBvZmZzZXQgKyBzdHJpZGU7IGkgPCBlbmQ7IGkgKz0gc3RyaWRlKSB7XG4gICAgdmFyIHgyID0gZmxhdENvb3JkaW5hdGVzW2ldO1xuICAgIHZhciB5MiA9IGZsYXRDb29yZGluYXRlc1tpICsgMV07XG4gICAgbGVuZ3RoICs9IE1hdGguc3FydCgoeDIgLSB4MSkgKiAoeDIgLSB4MSkgKyAoeTIgLSB5MSkgKiAoeTIgLSB5MSkpO1xuICAgIHgxID0geDI7XG4gICAgeTEgPSB5MjtcbiAgfVxuXG4gIHJldHVybiBsZW5ndGg7XG59XG4vKipcbiAqIEBwYXJhbSB7QXJyYXk8bnVtYmVyPn0gZmxhdENvb3JkaW5hdGVzIEZsYXQgY29vcmRpbmF0ZXMuXG4gKiBAcGFyYW0ge251bWJlcn0gb2Zmc2V0IE9mZnNldC5cbiAqIEBwYXJhbSB7bnVtYmVyfSBlbmQgRW5kLlxuICogQHBhcmFtIHtudW1iZXJ9IHN0cmlkZSBTdHJpZGUuXG4gKiBAcmV0dXJuIHtudW1iZXJ9IFBlcmltZXRlci5cbiAqL1xuXG5leHBvcnQgZnVuY3Rpb24gbGluZWFyUmluZ0xlbmd0aChmbGF0Q29vcmRpbmF0ZXMsIG9mZnNldCwgZW5kLCBzdHJpZGUpIHtcbiAgdmFyIHBlcmltZXRlciA9IGxpbmVTdHJpbmdMZW5ndGgoZmxhdENvb3JkaW5hdGVzLCBvZmZzZXQsIGVuZCwgc3RyaWRlKTtcbiAgdmFyIGR4ID0gZmxhdENvb3JkaW5hdGVzW2VuZCAtIHN0cmlkZV0gLSBmbGF0Q29vcmRpbmF0ZXNbb2Zmc2V0XTtcbiAgdmFyIGR5ID0gZmxhdENvb3JkaW5hdGVzW2VuZCAtIHN0cmlkZSArIDFdIC0gZmxhdENvb3JkaW5hdGVzW29mZnNldCArIDFdO1xuICBwZXJpbWV0ZXIgKz0gTWF0aC5zcXJ0KGR4ICogZHggKyBkeSAqIGR5KTtcbiAgcmV0dXJuIHBlcmltZXRlcjtcbn0iLCIvKipcbiAqIEBtb2R1bGUgb2wvcmVuZGVyL2NhbnZhcy9FeGVjdXRvclxuICovXG5pbXBvcnQgQ2FudmFzSW5zdHJ1Y3Rpb24gZnJvbSAnLi9JbnN0cnVjdGlvbi5qcyc7XG5pbXBvcnQgeyBURVhUX0FMSUdOIH0gZnJvbSAnLi9UZXh0QnVpbGRlci5qcyc7XG5pbXBvcnQgeyBXT1JLRVJfT0ZGU0NSRUVOX0NBTlZBUyB9IGZyb20gJy4uLy4uL2hhcy5qcyc7XG5pbXBvcnQgeyBhcHBseSBhcyBhcHBseVRyYW5zZm9ybSwgY29tcG9zZSBhcyBjb21wb3NlVHJhbnNmb3JtLCBjcmVhdGUgYXMgY3JlYXRlVHJhbnNmb3JtLCBzZXRGcm9tQXJyYXkgYXMgdHJhbnNmb3JtU2V0RnJvbUFycmF5IH0gZnJvbSAnLi4vLi4vdHJhbnNmb3JtLmpzJztcbmltcG9ydCB7IGNyZWF0ZUVtcHR5LCBjcmVhdGVPclVwZGF0ZSwgaW50ZXJzZWN0cyB9IGZyb20gJy4uLy4uL2V4dGVudC5qcyc7XG5pbXBvcnQgeyBkZWZhdWx0UGFkZGluZywgZGVmYXVsdFRleHRCYXNlbGluZSwgZHJhd0ltYWdlT3JMYWJlbCB9IGZyb20gJy4uL2NhbnZhcy5qcyc7XG5pbXBvcnQgeyBkZWZhdWx0VGV4dEFsaWduLCBtZWFzdXJlQW5kQ2FjaGVUZXh0V2lkdGgsIG1lYXN1cmVUZXh0SGVpZ2h0LCBtZWFzdXJlVGV4dFdpZHRocyB9IGZyb20gJy4uL2NhbnZhcy5qcyc7XG5pbXBvcnQgeyBkcmF3VGV4dE9uUGF0aCB9IGZyb20gJy4uLy4uL2dlb20vZmxhdC90ZXh0cGF0aC5qcyc7XG5pbXBvcnQgeyBlcXVhbHMgfSBmcm9tICcuLi8uLi9hcnJheS5qcyc7XG5pbXBvcnQgeyBsaW5lU3RyaW5nTGVuZ3RoIH0gZnJvbSAnLi4vLi4vZ2VvbS9mbGF0L2xlbmd0aC5qcyc7XG5pbXBvcnQgeyB0cmFuc2Zvcm0yRCB9IGZyb20gJy4uLy4uL2dlb20vZmxhdC90cmFuc2Zvcm0uanMnO1xuLyoqXG4gKiBAdHlwZWRlZiB7T2JqZWN0fSBCQm94XG4gKiBAcHJvcGVydHkge251bWJlcn0gbWluWFxuICogQHByb3BlcnR5IHtudW1iZXJ9IG1pbllcbiAqIEBwcm9wZXJ0eSB7bnVtYmVyfSBtYXhYXG4gKiBAcHJvcGVydHkge251bWJlcn0gbWF4WVxuICogQHByb3BlcnR5IHsqfSB2YWx1ZVxuICovXG5cbi8qKlxuICogQHR5cGVkZWYge09iamVjdH0gSW1hZ2VPckxhYmVsRGltZW5zaW9uc1xuICogQHByb3BlcnR5IHtudW1iZXJ9IGRyYXdJbWFnZVhcbiAqIEBwcm9wZXJ0eSB7bnVtYmVyfSBkcmF3SW1hZ2VZXG4gKiBAcHJvcGVydHkge251bWJlcn0gZHJhd0ltYWdlV1xuICogQHByb3BlcnR5IHtudW1iZXJ9IGRyYXdJbWFnZUhcbiAqIEBwcm9wZXJ0eSB7bnVtYmVyfSBvcmlnaW5YXG4gKiBAcHJvcGVydHkge251bWJlcn0gb3JpZ2luWVxuICogQHByb3BlcnR5IHtBcnJheTxudW1iZXI+fSBzY2FsZVxuICogQHByb3BlcnR5IHtCQm94fSBkZWNsdXR0ZXJCb3hcbiAqIEBwcm9wZXJ0eSB7aW1wb3J0KFwiLi4vLi4vdHJhbnNmb3JtLmpzXCIpLlRyYW5zZm9ybX0gY2FudmFzVHJhbnNmb3JtXG4gKi9cblxuLyoqXG4gKiBAdHlwZWRlZiB7ezA6IENhbnZhc1JlbmRlcmluZ0NvbnRleHQyRCwgMTogbnVtYmVyLCAyOiBpbXBvcnQoXCIuLi9jYW52YXMuanNcIikuTGFiZWx8SFRNTEltYWdlRWxlbWVudHxIVE1MQ2FudmFzRWxlbWVudHxIVE1MVmlkZW9FbGVtZW50LCAzOiBJbWFnZU9yTGFiZWxEaW1lbnNpb25zLCA0OiBudW1iZXIsIDU6IEFycmF5PCo+LCA2OiBBcnJheTwqPn19IFJlcGxheUltYWdlT3JMYWJlbEFyZ3NcbiAqL1xuXG4vKipcbiAqIEB0ZW1wbGF0ZSBUXG4gKiBAdHlwZWRlZiB7ZnVuY3Rpb24oaW1wb3J0KFwiLi4vLi4vRmVhdHVyZS5qc1wiKS5GZWF0dXJlTGlrZSwgaW1wb3J0KFwiLi4vLi4vZ2VvbS9TaW1wbGVHZW9tZXRyeS5qc1wiKS5kZWZhdWx0KTogVH0gRmVhdHVyZUNhbGxiYWNrXG4gKi9cblxuLyoqXG4gKiBAdHlwZSB7aW1wb3J0KFwiLi4vLi4vZXh0ZW50LmpzXCIpLkV4dGVudH1cbiAqL1xuXG52YXIgdG1wRXh0ZW50ID0gY3JlYXRlRW1wdHkoKTtcbi8qKiBAdHlwZSB7aW1wb3J0KFwiLi4vLi4vY29vcmRpbmF0ZS5qc1wiKS5Db29yZGluYXRlfSAqL1xuXG52YXIgcDEgPSBbXTtcbi8qKiBAdHlwZSB7aW1wb3J0KFwiLi4vLi4vY29vcmRpbmF0ZS5qc1wiKS5Db29yZGluYXRlfSAqL1xuXG52YXIgcDIgPSBbXTtcbi8qKiBAdHlwZSB7aW1wb3J0KFwiLi4vLi4vY29vcmRpbmF0ZS5qc1wiKS5Db29yZGluYXRlfSAqL1xuXG52YXIgcDMgPSBbXTtcbi8qKiBAdHlwZSB7aW1wb3J0KFwiLi4vLi4vY29vcmRpbmF0ZS5qc1wiKS5Db29yZGluYXRlfSAqL1xuXG52YXIgcDQgPSBbXTtcbi8qKlxuICogQHBhcmFtIHtSZXBsYXlJbWFnZU9yTGFiZWxBcmdzfSByZXBsYXlJbWFnZU9yTGFiZWxBcmdzIEFyZ3VtZW50cyB0byByZXBsYXlJbWFnZU9yTGFiZWxcbiAqIEByZXR1cm4ge0JCb3h9IERlY2x1dHRlciBiYm94LlxuICovXG5cbmZ1bmN0aW9uIGdldERlY2x1dHRlckJveChyZXBsYXlJbWFnZU9yTGFiZWxBcmdzKSB7XG4gIHJldHVybiByZXBsYXlJbWFnZU9yTGFiZWxBcmdzWzNdLmRlY2x1dHRlckJveDtcbn1cblxudmFyIHJ0bFJlZ0V4ID0gbmV3IFJlZ0V4cChcbi8qIGVzbGludC1kaXNhYmxlIHByZXR0aWVyL3ByZXR0aWVyICovXG4nWycgKyBTdHJpbmcuZnJvbUNoYXJDb2RlKDB4MDA1OTEpICsgJy0nICsgU3RyaW5nLmZyb21DaGFyQ29kZSgweDAwOGZmKSArIFN0cmluZy5mcm9tQ2hhckNvZGUoMHgwZmIxZCkgKyAnLScgKyBTdHJpbmcuZnJvbUNoYXJDb2RlKDB4MGZkZmYpICsgU3RyaW5nLmZyb21DaGFyQ29kZSgweDBmZTcwKSArICctJyArIFN0cmluZy5mcm9tQ2hhckNvZGUoMHgwZmVmYykgKyBTdHJpbmcuZnJvbUNoYXJDb2RlKDB4MTA4MDApICsgJy0nICsgU3RyaW5nLmZyb21DaGFyQ29kZSgweDEwZmZmKSArIFN0cmluZy5mcm9tQ2hhckNvZGUoMHgxZTgwMCkgKyAnLScgKyBTdHJpbmcuZnJvbUNoYXJDb2RlKDB4MWVmZmYpICsgJ10nXG4vKiBlc2xpbnQtZW5hYmxlIHByZXR0aWVyL3ByZXR0aWVyICovXG4pO1xuLyoqXG4gKiBAcGFyYW0ge3N0cmluZ30gdGV4dCBUZXh0LlxuICogQHBhcmFtIHtzdHJpbmd9IGFsaWduIEFsaWdubWVudC5cbiAqIEByZXR1cm4ge251bWJlcn0gVGV4dCBhbGlnbm1lbnQuXG4gKi9cblxuZnVuY3Rpb24gaG9yaXpvbnRhbFRleHRBbGlnbih0ZXh0LCBhbGlnbikge1xuICBpZiAoKGFsaWduID09PSAnc3RhcnQnIHx8IGFsaWduID09PSAnZW5kJykgJiYgIXJ0bFJlZ0V4LnRlc3QodGV4dCkpIHtcbiAgICBhbGlnbiA9IGFsaWduID09PSAnc3RhcnQnID8gJ2xlZnQnIDogJ3JpZ2h0JztcbiAgfVxuXG4gIHJldHVybiBURVhUX0FMSUdOW2FsaWduXTtcbn1cblxudmFyIEV4ZWN1dG9yID1cbi8qKiBAY2xhc3MgKi9cbmZ1bmN0aW9uICgpIHtcbiAgLyoqXG4gICAqIEBwYXJhbSB7bnVtYmVyfSByZXNvbHV0aW9uIFJlc29sdXRpb24uXG4gICAqIEBwYXJhbSB7bnVtYmVyfSBwaXhlbFJhdGlvIFBpeGVsIHJhdGlvLlxuICAgKiBAcGFyYW0ge2Jvb2xlYW59IG92ZXJsYXBzIFRoZSByZXBsYXkgY2FuIGhhdmUgb3ZlcmxhcHBpbmcgZ2VvbWV0cmllcy5cbiAgICogQHBhcmFtIHtpbXBvcnQoXCIuLi9jYW52YXMuanNcIikuU2VyaWFsaXphYmxlSW5zdHJ1Y3Rpb25zfSBpbnN0cnVjdGlvbnMgVGhlIHNlcmlhbGl6YWJsZSBpbnN0cnVjdGlvbnNcbiAgICogQHBhcmFtIHtpbXBvcnQoXCIuLi8uLi9zaXplLmpzXCIpLlNpemV9IHJlbmRlckJ1ZmZlciBSZW5kZXIgYnVmZmVyICh3aWR0aC9oZWlnaHQpIGluIHBpeGVscy5cbiAgICovXG4gIGZ1bmN0aW9uIEV4ZWN1dG9yKHJlc29sdXRpb24sIHBpeGVsUmF0aW8sIG92ZXJsYXBzLCBpbnN0cnVjdGlvbnMsIHJlbmRlckJ1ZmZlcikge1xuICAgIC8qKlxuICAgICAqIEBwcm90ZWN0ZWRcbiAgICAgKiBAdHlwZSB7Ym9vbGVhbn1cbiAgICAgKi9cbiAgICB0aGlzLm92ZXJsYXBzID0gb3ZlcmxhcHM7XG4gICAgLyoqXG4gICAgICogQHByb3RlY3RlZFxuICAgICAqIEB0eXBlIHtudW1iZXJ9XG4gICAgICovXG5cbiAgICB0aGlzLnBpeGVsUmF0aW8gPSBwaXhlbFJhdGlvO1xuICAgIC8qKlxuICAgICAqIEBwcm90ZWN0ZWRcbiAgICAgKiBAY29uc3RcbiAgICAgKiBAdHlwZSB7bnVtYmVyfVxuICAgICAqL1xuXG4gICAgdGhpcy5yZXNvbHV0aW9uID0gcmVzb2x1dGlvbjtcbiAgICAvKipcbiAgICAgKiBAcHJpdmF0ZVxuICAgICAqIEB0eXBlIHtib29sZWFufVxuICAgICAqL1xuXG4gICAgdGhpcy5hbGlnbkZpbGxfO1xuICAgIC8qKlxuICAgICAqIEBwcm90ZWN0ZWRcbiAgICAgKiBAdHlwZSB7QXJyYXk8Kj59XG4gICAgICovXG5cbiAgICB0aGlzLmluc3RydWN0aW9ucyA9IGluc3RydWN0aW9ucy5pbnN0cnVjdGlvbnM7XG4gICAgLyoqXG4gICAgICogQHByb3RlY3RlZFxuICAgICAqIEB0eXBlIHtBcnJheTxudW1iZXI+fVxuICAgICAqL1xuXG4gICAgdGhpcy5jb29yZGluYXRlcyA9IGluc3RydWN0aW9ucy5jb29yZGluYXRlcztcbiAgICAvKipcbiAgICAgKiBAcHJpdmF0ZVxuICAgICAqIEB0eXBlIHshT2JqZWN0PG51bWJlcixpbXBvcnQoXCIuLi8uLi9jb29yZGluYXRlLmpzXCIpLkNvb3JkaW5hdGV8QXJyYXk8aW1wb3J0KFwiLi4vLi4vY29vcmRpbmF0ZS5qc1wiKS5Db29yZGluYXRlPnxBcnJheTxBcnJheTxpbXBvcnQoXCIuLi8uLi9jb29yZGluYXRlLmpzXCIpLkNvb3JkaW5hdGU+Pj59XG4gICAgICovXG5cbiAgICB0aGlzLmNvb3JkaW5hdGVDYWNoZV8gPSB7fTtcbiAgICAvKipcbiAgICAgKiBAcHJpdmF0ZVxuICAgICAqIEB0eXBlIHtpbXBvcnQoXCIuLi8uLi9zaXplLmpzXCIpLlNpemV9XG4gICAgICovXG5cbiAgICB0aGlzLnJlbmRlckJ1ZmZlcl8gPSByZW5kZXJCdWZmZXI7XG4gICAgLyoqXG4gICAgICogQHByaXZhdGVcbiAgICAgKiBAdHlwZSB7IWltcG9ydChcIi4uLy4uL3RyYW5zZm9ybS5qc1wiKS5UcmFuc2Zvcm19XG4gICAgICovXG5cbiAgICB0aGlzLnJlbmRlcmVkVHJhbnNmb3JtXyA9IGNyZWF0ZVRyYW5zZm9ybSgpO1xuICAgIC8qKlxuICAgICAqIEBwcm90ZWN0ZWRcbiAgICAgKiBAdHlwZSB7QXJyYXk8Kj59XG4gICAgICovXG5cbiAgICB0aGlzLmhpdERldGVjdGlvbkluc3RydWN0aW9ucyA9IGluc3RydWN0aW9ucy5oaXREZXRlY3Rpb25JbnN0cnVjdGlvbnM7XG4gICAgLyoqXG4gICAgICogQHByaXZhdGVcbiAgICAgKiBAdHlwZSB7QXJyYXk8bnVtYmVyPn1cbiAgICAgKi9cblxuICAgIHRoaXMucGl4ZWxDb29yZGluYXRlc18gPSBudWxsO1xuICAgIC8qKlxuICAgICAqIEBwcml2YXRlXG4gICAgICogQHR5cGUge251bWJlcn1cbiAgICAgKi9cblxuICAgIHRoaXMudmlld1JvdGF0aW9uXyA9IDA7XG4gICAgLyoqXG4gICAgICogQHR5cGUgeyFPYmplY3Q8c3RyaW5nLCBpbXBvcnQoXCIuLi9jYW52YXMuanNcIikuRmlsbFN0YXRlPn1cbiAgICAgKi9cblxuICAgIHRoaXMuZmlsbFN0YXRlcyA9IGluc3RydWN0aW9ucy5maWxsU3RhdGVzIHx8IHt9O1xuICAgIC8qKlxuICAgICAqIEB0eXBlIHshT2JqZWN0PHN0cmluZywgaW1wb3J0KFwiLi4vY2FudmFzLmpzXCIpLlN0cm9rZVN0YXRlPn1cbiAgICAgKi9cblxuICAgIHRoaXMuc3Ryb2tlU3RhdGVzID0gaW5zdHJ1Y3Rpb25zLnN0cm9rZVN0YXRlcyB8fCB7fTtcbiAgICAvKipcbiAgICAgKiBAdHlwZSB7IU9iamVjdDxzdHJpbmcsIGltcG9ydChcIi4uL2NhbnZhcy5qc1wiKS5UZXh0U3RhdGU+fVxuICAgICAqL1xuXG4gICAgdGhpcy50ZXh0U3RhdGVzID0gaW5zdHJ1Y3Rpb25zLnRleHRTdGF0ZXMgfHwge307XG4gICAgLyoqXG4gICAgICogQHByaXZhdGVcbiAgICAgKiBAdHlwZSB7T2JqZWN0PHN0cmluZywgT2JqZWN0PHN0cmluZywgbnVtYmVyPj59XG4gICAgICovXG5cbiAgICB0aGlzLndpZHRoc18gPSB7fTtcbiAgICAvKipcbiAgICAgKiBAcHJpdmF0ZVxuICAgICAqIEB0eXBlIHtPYmplY3Q8c3RyaW5nLCBpbXBvcnQoXCIuLi9jYW52YXMuanNcIikuTGFiZWw+fVxuICAgICAqL1xuXG4gICAgdGhpcy5sYWJlbHNfID0ge307XG4gIH1cbiAgLyoqXG4gICAqIEBwYXJhbSB7c3RyaW5nfSB0ZXh0IFRleHQuXG4gICAqIEBwYXJhbSB7c3RyaW5nfSB0ZXh0S2V5IFRleHQgc3R5bGUga2V5LlxuICAgKiBAcGFyYW0ge3N0cmluZ30gZmlsbEtleSBGaWxsIHN0eWxlIGtleS5cbiAgICogQHBhcmFtIHtzdHJpbmd9IHN0cm9rZUtleSBTdHJva2Ugc3R5bGUga2V5LlxuICAgKiBAcmV0dXJuIHtpbXBvcnQoXCIuLi9jYW52YXMuanNcIikuTGFiZWx9IExhYmVsLlxuICAgKi9cblxuXG4gIEV4ZWN1dG9yLnByb3RvdHlwZS5jcmVhdGVMYWJlbCA9IGZ1bmN0aW9uICh0ZXh0LCB0ZXh0S2V5LCBmaWxsS2V5LCBzdHJva2VLZXkpIHtcbiAgICB2YXIga2V5ID0gdGV4dCArIHRleHRLZXkgKyBmaWxsS2V5ICsgc3Ryb2tlS2V5O1xuXG4gICAgaWYgKHRoaXMubGFiZWxzX1trZXldKSB7XG4gICAgICByZXR1cm4gdGhpcy5sYWJlbHNfW2tleV07XG4gICAgfVxuXG4gICAgdmFyIHN0cm9rZVN0YXRlID0gc3Ryb2tlS2V5ID8gdGhpcy5zdHJva2VTdGF0ZXNbc3Ryb2tlS2V5XSA6IG51bGw7XG4gICAgdmFyIGZpbGxTdGF0ZSA9IGZpbGxLZXkgPyB0aGlzLmZpbGxTdGF0ZXNbZmlsbEtleV0gOiBudWxsO1xuICAgIHZhciB0ZXh0U3RhdGUgPSB0aGlzLnRleHRTdGF0ZXNbdGV4dEtleV07XG4gICAgdmFyIHBpeGVsUmF0aW8gPSB0aGlzLnBpeGVsUmF0aW87XG4gICAgdmFyIHNjYWxlID0gW3RleHRTdGF0ZS5zY2FsZVswXSAqIHBpeGVsUmF0aW8sIHRleHRTdGF0ZS5zY2FsZVsxXSAqIHBpeGVsUmF0aW9dO1xuICAgIHZhciBhbGlnbiA9IGhvcml6b250YWxUZXh0QWxpZ24odGV4dCwgdGV4dFN0YXRlLnRleHRBbGlnbiB8fCBkZWZhdWx0VGV4dEFsaWduKTtcbiAgICB2YXIgc3Ryb2tlV2lkdGggPSBzdHJva2VLZXkgJiYgc3Ryb2tlU3RhdGUubGluZVdpZHRoID8gc3Ryb2tlU3RhdGUubGluZVdpZHRoIDogMDtcbiAgICB2YXIgbGluZXMgPSB0ZXh0LnNwbGl0KCdcXG4nKTtcbiAgICB2YXIgbnVtTGluZXMgPSBsaW5lcy5sZW5ndGg7XG4gICAgdmFyIHdpZHRocyA9IFtdO1xuICAgIHZhciB3aWR0aCA9IG1lYXN1cmVUZXh0V2lkdGhzKHRleHRTdGF0ZS5mb250LCBsaW5lcywgd2lkdGhzKTtcbiAgICB2YXIgbGluZUhlaWdodCA9IG1lYXN1cmVUZXh0SGVpZ2h0KHRleHRTdGF0ZS5mb250KTtcbiAgICB2YXIgaGVpZ2h0ID0gbGluZUhlaWdodCAqIG51bUxpbmVzO1xuICAgIHZhciByZW5kZXJXaWR0aCA9IHdpZHRoICsgc3Ryb2tlV2lkdGg7XG4gICAgdmFyIGNvbnRleHRJbnN0cnVjdGlvbnMgPSBbXTsgLy8gbWFrZSBjYW52YXMgMiBwaXhlbHMgd2lkZXIgdG8gYWNjb3VudCBmb3IgaXRhbGljIHRleHQgd2lkdGggbWVhc3VyZW1lbnQgZXJyb3JzXG5cbiAgICB2YXIgdyA9IChyZW5kZXJXaWR0aCArIDIpICogc2NhbGVbMF07XG4gICAgdmFyIGggPSAoaGVpZ2h0ICsgc3Ryb2tlV2lkdGgpICogc2NhbGVbMV07XG4gICAgLyoqIEB0eXBlIHtpbXBvcnQoXCIuLi9jYW52YXMuanNcIikuTGFiZWx9ICovXG5cbiAgICB2YXIgbGFiZWwgPSB7XG4gICAgICB3aWR0aDogdyA8IDAgPyBNYXRoLmZsb29yKHcpIDogTWF0aC5jZWlsKHcpLFxuICAgICAgaGVpZ2h0OiBoIDwgMCA/IE1hdGguZmxvb3IoaCkgOiBNYXRoLmNlaWwoaCksXG4gICAgICBjb250ZXh0SW5zdHJ1Y3Rpb25zOiBjb250ZXh0SW5zdHJ1Y3Rpb25zXG4gICAgfTtcblxuICAgIGlmIChzY2FsZVswXSAhPSAxIHx8IHNjYWxlWzFdICE9IDEpIHtcbiAgICAgIGNvbnRleHRJbnN0cnVjdGlvbnMucHVzaCgnc2NhbGUnLCBzY2FsZSk7XG4gICAgfVxuXG4gICAgY29udGV4dEluc3RydWN0aW9ucy5wdXNoKCdmb250JywgdGV4dFN0YXRlLmZvbnQpO1xuXG4gICAgaWYgKHN0cm9rZUtleSkge1xuICAgICAgY29udGV4dEluc3RydWN0aW9ucy5wdXNoKCdzdHJva2VTdHlsZScsIHN0cm9rZVN0YXRlLnN0cm9rZVN0eWxlKTtcbiAgICAgIGNvbnRleHRJbnN0cnVjdGlvbnMucHVzaCgnbGluZVdpZHRoJywgc3Ryb2tlV2lkdGgpO1xuICAgICAgY29udGV4dEluc3RydWN0aW9ucy5wdXNoKCdsaW5lQ2FwJywgc3Ryb2tlU3RhdGUubGluZUNhcCk7XG4gICAgICBjb250ZXh0SW5zdHJ1Y3Rpb25zLnB1c2goJ2xpbmVKb2luJywgc3Ryb2tlU3RhdGUubGluZUpvaW4pO1xuICAgICAgY29udGV4dEluc3RydWN0aW9ucy5wdXNoKCdtaXRlckxpbWl0Jywgc3Ryb2tlU3RhdGUubWl0ZXJMaW1pdCk7IC8vIGVzbGludC1kaXNhYmxlLW5leHQtbGluZVxuXG4gICAgICB2YXIgQ29udGV4dCA9IFdPUktFUl9PRkZTQ1JFRU5fQ0FOVkFTID8gT2Zmc2NyZWVuQ2FudmFzUmVuZGVyaW5nQ29udGV4dDJEIDogQ2FudmFzUmVuZGVyaW5nQ29udGV4dDJEO1xuXG4gICAgICBpZiAoQ29udGV4dC5wcm90b3R5cGUuc2V0TGluZURhc2gpIHtcbiAgICAgICAgY29udGV4dEluc3RydWN0aW9ucy5wdXNoKCdzZXRMaW5lRGFzaCcsIFtzdHJva2VTdGF0ZS5saW5lRGFzaF0pO1xuICAgICAgICBjb250ZXh0SW5zdHJ1Y3Rpb25zLnB1c2goJ2xpbmVEYXNoT2Zmc2V0Jywgc3Ryb2tlU3RhdGUubGluZURhc2hPZmZzZXQpO1xuICAgICAgfVxuICAgIH1cblxuICAgIGlmIChmaWxsS2V5KSB7XG4gICAgICBjb250ZXh0SW5zdHJ1Y3Rpb25zLnB1c2goJ2ZpbGxTdHlsZScsIGZpbGxTdGF0ZS5maWxsU3R5bGUpO1xuICAgIH1cblxuICAgIGNvbnRleHRJbnN0cnVjdGlvbnMucHVzaCgndGV4dEJhc2VsaW5lJywgJ21pZGRsZScpO1xuICAgIGNvbnRleHRJbnN0cnVjdGlvbnMucHVzaCgndGV4dEFsaWduJywgJ2NlbnRlcicpO1xuICAgIHZhciBsZWZ0UmlnaHQgPSAwLjUgLSBhbGlnbjtcbiAgICB2YXIgeCA9IGFsaWduICogcmVuZGVyV2lkdGggKyBsZWZ0UmlnaHQgKiBzdHJva2VXaWR0aDtcbiAgICB2YXIgaTtcblxuICAgIGlmIChzdHJva2VLZXkpIHtcbiAgICAgIGZvciAoaSA9IDA7IGkgPCBudW1MaW5lczsgKytpKSB7XG4gICAgICAgIGNvbnRleHRJbnN0cnVjdGlvbnMucHVzaCgnc3Ryb2tlVGV4dCcsIFtsaW5lc1tpXSwgeCArIGxlZnRSaWdodCAqIHdpZHRoc1tpXSwgMC41ICogKHN0cm9rZVdpZHRoICsgbGluZUhlaWdodCkgKyBpICogbGluZUhlaWdodF0pO1xuICAgICAgfVxuICAgIH1cblxuICAgIGlmIChmaWxsS2V5KSB7XG4gICAgICBmb3IgKGkgPSAwOyBpIDwgbnVtTGluZXM7ICsraSkge1xuICAgICAgICBjb250ZXh0SW5zdHJ1Y3Rpb25zLnB1c2goJ2ZpbGxUZXh0JywgW2xpbmVzW2ldLCB4ICsgbGVmdFJpZ2h0ICogd2lkdGhzW2ldLCAwLjUgKiAoc3Ryb2tlV2lkdGggKyBsaW5lSGVpZ2h0KSArIGkgKiBsaW5lSGVpZ2h0XSk7XG4gICAgICB9XG4gICAgfVxuXG4gICAgdGhpcy5sYWJlbHNfW2tleV0gPSBsYWJlbDtcbiAgICByZXR1cm4gbGFiZWw7XG4gIH07XG4gIC8qKlxuICAgKiBAcGFyYW0ge0NhbnZhc1JlbmRlcmluZ0NvbnRleHQyRH0gY29udGV4dCBDb250ZXh0LlxuICAgKiBAcGFyYW0ge2ltcG9ydChcIi4uLy4uL2Nvb3JkaW5hdGUuanNcIikuQ29vcmRpbmF0ZX0gcDEgMXN0IHBvaW50IG9mIHRoZSBiYWNrZ3JvdW5kIGJveC5cbiAgICogQHBhcmFtIHtpbXBvcnQoXCIuLi8uLi9jb29yZGluYXRlLmpzXCIpLkNvb3JkaW5hdGV9IHAyIDJuZCBwb2ludCBvZiB0aGUgYmFja2dyb3VuZCBib3guXG4gICAqIEBwYXJhbSB7aW1wb3J0KFwiLi4vLi4vY29vcmRpbmF0ZS5qc1wiKS5Db29yZGluYXRlfSBwMyAzcmQgcG9pbnQgb2YgdGhlIGJhY2tncm91bmQgYm94LlxuICAgKiBAcGFyYW0ge2ltcG9ydChcIi4uLy4uL2Nvb3JkaW5hdGUuanNcIikuQ29vcmRpbmF0ZX0gcDQgNHRoIHBvaW50IG9mIHRoZSBiYWNrZ3JvdW5kIGJveC5cbiAgICogQHBhcmFtIHtBcnJheTwqPn0gZmlsbEluc3RydWN0aW9uIEZpbGwgaW5zdHJ1Y3Rpb24uXG4gICAqIEBwYXJhbSB7QXJyYXk8Kj59IHN0cm9rZUluc3RydWN0aW9uIFN0cm9rZSBpbnN0cnVjdGlvbi5cbiAgICovXG5cblxuICBFeGVjdXRvci5wcm90b3R5cGUucmVwbGF5VGV4dEJhY2tncm91bmRfID0gZnVuY3Rpb24gKGNvbnRleHQsIHAxLCBwMiwgcDMsIHA0LCBmaWxsSW5zdHJ1Y3Rpb24sIHN0cm9rZUluc3RydWN0aW9uKSB7XG4gICAgY29udGV4dC5iZWdpblBhdGgoKTtcbiAgICBjb250ZXh0Lm1vdmVUby5hcHBseShjb250ZXh0LCBwMSk7XG4gICAgY29udGV4dC5saW5lVG8uYXBwbHkoY29udGV4dCwgcDIpO1xuICAgIGNvbnRleHQubGluZVRvLmFwcGx5KGNvbnRleHQsIHAzKTtcbiAgICBjb250ZXh0LmxpbmVUby5hcHBseShjb250ZXh0LCBwNCk7XG4gICAgY29udGV4dC5saW5lVG8uYXBwbHkoY29udGV4dCwgcDEpO1xuXG4gICAgaWYgKGZpbGxJbnN0cnVjdGlvbikge1xuICAgICAgdGhpcy5hbGlnbkZpbGxfID1cbiAgICAgIC8qKiBAdHlwZSB7Ym9vbGVhbn0gKi9cbiAgICAgIGZpbGxJbnN0cnVjdGlvblsyXTtcbiAgICAgIHRoaXMuZmlsbF8oY29udGV4dCk7XG4gICAgfVxuXG4gICAgaWYgKHN0cm9rZUluc3RydWN0aW9uKSB7XG4gICAgICB0aGlzLnNldFN0cm9rZVN0eWxlXyhjb250ZXh0LFxuICAgICAgLyoqIEB0eXBlIHtBcnJheTwqPn0gKi9cbiAgICAgIHN0cm9rZUluc3RydWN0aW9uKTtcbiAgICAgIGNvbnRleHQuc3Ryb2tlKCk7XG4gICAgfVxuICB9O1xuICAvKipcbiAgICogQHByaXZhdGVcbiAgICogQHBhcmFtIHtudW1iZXJ9IHNoZWV0V2lkdGggV2lkdGggb2YgdGhlIHNwcml0ZSBzaGVldC5cbiAgICogQHBhcmFtIHtudW1iZXJ9IHNoZWV0SGVpZ2h0IEhlaWdodCBvZiB0aGUgc3ByaXRlIHNoZWV0LlxuICAgKiBAcGFyYW0ge251bWJlcn0gY2VudGVyWCBYLlxuICAgKiBAcGFyYW0ge251bWJlcn0gY2VudGVyWSBZLlxuICAgKiBAcGFyYW0ge251bWJlcn0gd2lkdGggV2lkdGguXG4gICAqIEBwYXJhbSB7bnVtYmVyfSBoZWlnaHQgSGVpZ2h0LlxuICAgKiBAcGFyYW0ge251bWJlcn0gYW5jaG9yWCBBbmNob3IgWC5cbiAgICogQHBhcmFtIHtudW1iZXJ9IGFuY2hvclkgQW5jaG9yIFkuXG4gICAqIEBwYXJhbSB7bnVtYmVyfSBvcmlnaW5YIE9yaWdpbiBYLlxuICAgKiBAcGFyYW0ge251bWJlcn0gb3JpZ2luWSBPcmlnaW4gWS5cbiAgICogQHBhcmFtIHtudW1iZXJ9IHJvdGF0aW9uIFJvdGF0aW9uLlxuICAgKiBAcGFyYW0ge2ltcG9ydChcIi4uLy4uL3NpemUuanNcIikuU2l6ZX0gc2NhbGUgU2NhbGUuXG4gICAqIEBwYXJhbSB7Ym9vbGVhbn0gc25hcFRvUGl4ZWwgU25hcCB0byBwaXhlbC5cbiAgICogQHBhcmFtIHtBcnJheTxudW1iZXI+fSBwYWRkaW5nIFBhZGRpbmcuXG4gICAqIEBwYXJhbSB7Ym9vbGVhbn0gZmlsbFN0cm9rZSBCYWNrZ3JvdW5kIGZpbGwgb3Igc3Ryb2tlLlxuICAgKiBAcGFyYW0ge2ltcG9ydChcIi4uLy4uL0ZlYXR1cmUuanNcIikuRmVhdHVyZUxpa2V9IGZlYXR1cmUgRmVhdHVyZS5cbiAgICogQHJldHVybiB7SW1hZ2VPckxhYmVsRGltZW5zaW9uc30gRGltZW5zaW9ucyBmb3IgcG9zaXRpb25pbmcgYW5kIGRlY2x1dHRlcmluZyB0aGUgaW1hZ2Ugb3IgbGFiZWwuXG4gICAqL1xuXG5cbiAgRXhlY3V0b3IucHJvdG90eXBlLmNhbGN1bGF0ZUltYWdlT3JMYWJlbERpbWVuc2lvbnNfID0gZnVuY3Rpb24gKHNoZWV0V2lkdGgsIHNoZWV0SGVpZ2h0LCBjZW50ZXJYLCBjZW50ZXJZLCB3aWR0aCwgaGVpZ2h0LCBhbmNob3JYLCBhbmNob3JZLCBvcmlnaW5YLCBvcmlnaW5ZLCByb3RhdGlvbiwgc2NhbGUsIHNuYXBUb1BpeGVsLCBwYWRkaW5nLCBmaWxsU3Ryb2tlLCBmZWF0dXJlKSB7XG4gICAgYW5jaG9yWCAqPSBzY2FsZVswXTtcbiAgICBhbmNob3JZICo9IHNjYWxlWzFdO1xuICAgIHZhciB4ID0gY2VudGVyWCAtIGFuY2hvclg7XG4gICAgdmFyIHkgPSBjZW50ZXJZIC0gYW5jaG9yWTtcbiAgICB2YXIgdyA9IHdpZHRoICsgb3JpZ2luWCA+IHNoZWV0V2lkdGggPyBzaGVldFdpZHRoIC0gb3JpZ2luWCA6IHdpZHRoO1xuICAgIHZhciBoID0gaGVpZ2h0ICsgb3JpZ2luWSA+IHNoZWV0SGVpZ2h0ID8gc2hlZXRIZWlnaHQgLSBvcmlnaW5ZIDogaGVpZ2h0O1xuICAgIHZhciBib3hXID0gcGFkZGluZ1szXSArIHcgKiBzY2FsZVswXSArIHBhZGRpbmdbMV07XG4gICAgdmFyIGJveEggPSBwYWRkaW5nWzBdICsgaCAqIHNjYWxlWzFdICsgcGFkZGluZ1syXTtcbiAgICB2YXIgYm94WCA9IHggLSBwYWRkaW5nWzNdO1xuICAgIHZhciBib3hZID0geSAtIHBhZGRpbmdbMF07XG5cbiAgICBpZiAoZmlsbFN0cm9rZSB8fCByb3RhdGlvbiAhPT0gMCkge1xuICAgICAgcDFbMF0gPSBib3hYO1xuICAgICAgcDRbMF0gPSBib3hYO1xuICAgICAgcDFbMV0gPSBib3hZO1xuICAgICAgcDJbMV0gPSBib3hZO1xuICAgICAgcDJbMF0gPSBib3hYICsgYm94VztcbiAgICAgIHAzWzBdID0gcDJbMF07XG4gICAgICBwM1sxXSA9IGJveFkgKyBib3hIO1xuICAgICAgcDRbMV0gPSBwM1sxXTtcbiAgICB9XG5cbiAgICB2YXIgdHJhbnNmb3JtO1xuXG4gICAgaWYgKHJvdGF0aW9uICE9PSAwKSB7XG4gICAgICB0cmFuc2Zvcm0gPSBjb21wb3NlVHJhbnNmb3JtKGNyZWF0ZVRyYW5zZm9ybSgpLCBjZW50ZXJYLCBjZW50ZXJZLCAxLCAxLCByb3RhdGlvbiwgLWNlbnRlclgsIC1jZW50ZXJZKTtcbiAgICAgIGFwcGx5VHJhbnNmb3JtKHRyYW5zZm9ybSwgcDEpO1xuICAgICAgYXBwbHlUcmFuc2Zvcm0odHJhbnNmb3JtLCBwMik7XG4gICAgICBhcHBseVRyYW5zZm9ybSh0cmFuc2Zvcm0sIHAzKTtcbiAgICAgIGFwcGx5VHJhbnNmb3JtKHRyYW5zZm9ybSwgcDQpO1xuICAgICAgY3JlYXRlT3JVcGRhdGUoTWF0aC5taW4ocDFbMF0sIHAyWzBdLCBwM1swXSwgcDRbMF0pLCBNYXRoLm1pbihwMVsxXSwgcDJbMV0sIHAzWzFdLCBwNFsxXSksIE1hdGgubWF4KHAxWzBdLCBwMlswXSwgcDNbMF0sIHA0WzBdKSwgTWF0aC5tYXgocDFbMV0sIHAyWzFdLCBwM1sxXSwgcDRbMV0pLCB0bXBFeHRlbnQpO1xuICAgIH0gZWxzZSB7XG4gICAgICBjcmVhdGVPclVwZGF0ZShNYXRoLm1pbihib3hYLCBib3hYICsgYm94VyksIE1hdGgubWluKGJveFksIGJveFkgKyBib3hIKSwgTWF0aC5tYXgoYm94WCwgYm94WCArIGJveFcpLCBNYXRoLm1heChib3hZLCBib3hZICsgYm94SCksIHRtcEV4dGVudCk7XG4gICAgfVxuXG4gICAgaWYgKHNuYXBUb1BpeGVsKSB7XG4gICAgICB4ID0gTWF0aC5yb3VuZCh4KTtcbiAgICAgIHkgPSBNYXRoLnJvdW5kKHkpO1xuICAgIH1cblxuICAgIHJldHVybiB7XG4gICAgICBkcmF3SW1hZ2VYOiB4LFxuICAgICAgZHJhd0ltYWdlWTogeSxcbiAgICAgIGRyYXdJbWFnZVc6IHcsXG4gICAgICBkcmF3SW1hZ2VIOiBoLFxuICAgICAgb3JpZ2luWDogb3JpZ2luWCxcbiAgICAgIG9yaWdpblk6IG9yaWdpblksXG4gICAgICBkZWNsdXR0ZXJCb3g6IHtcbiAgICAgICAgbWluWDogdG1wRXh0ZW50WzBdLFxuICAgICAgICBtaW5ZOiB0bXBFeHRlbnRbMV0sXG4gICAgICAgIG1heFg6IHRtcEV4dGVudFsyXSxcbiAgICAgICAgbWF4WTogdG1wRXh0ZW50WzNdLFxuICAgICAgICB2YWx1ZTogZmVhdHVyZVxuICAgICAgfSxcbiAgICAgIGNhbnZhc1RyYW5zZm9ybTogdHJhbnNmb3JtLFxuICAgICAgc2NhbGU6IHNjYWxlXG4gICAgfTtcbiAgfTtcbiAgLyoqXG4gICAqIEBwcml2YXRlXG4gICAqIEBwYXJhbSB7Q2FudmFzUmVuZGVyaW5nQ29udGV4dDJEfSBjb250ZXh0IENvbnRleHQuXG4gICAqIEBwYXJhbSB7bnVtYmVyfSBjb250ZXh0U2NhbGUgU2NhbGUgb2YgdGhlIGNvbnRleHQuXG4gICAqIEBwYXJhbSB7aW1wb3J0KFwiLi4vY2FudmFzLmpzXCIpLkxhYmVsfEhUTUxJbWFnZUVsZW1lbnR8SFRNTENhbnZhc0VsZW1lbnR8SFRNTFZpZGVvRWxlbWVudH0gaW1hZ2VPckxhYmVsIEltYWdlLlxuICAgKiBAcGFyYW0ge0ltYWdlT3JMYWJlbERpbWVuc2lvbnN9IGRpbWVuc2lvbnMgRGltZW5zaW9ucy5cbiAgICogQHBhcmFtIHtudW1iZXJ9IG9wYWNpdHkgT3BhY2l0eS5cbiAgICogQHBhcmFtIHtBcnJheTwqPn0gZmlsbEluc3RydWN0aW9uIEZpbGwgaW5zdHJ1Y3Rpb24uXG4gICAqIEBwYXJhbSB7QXJyYXk8Kj59IHN0cm9rZUluc3RydWN0aW9uIFN0cm9rZSBpbnN0cnVjdGlvbi5cbiAgICogQHJldHVybiB7Ym9vbGVhbn0gVGhlIGltYWdlIG9yIGxhYmVsIHdhcyByZW5kZXJlZC5cbiAgICovXG5cblxuICBFeGVjdXRvci5wcm90b3R5cGUucmVwbGF5SW1hZ2VPckxhYmVsXyA9IGZ1bmN0aW9uIChjb250ZXh0LCBjb250ZXh0U2NhbGUsIGltYWdlT3JMYWJlbCwgZGltZW5zaW9ucywgb3BhY2l0eSwgZmlsbEluc3RydWN0aW9uLCBzdHJva2VJbnN0cnVjdGlvbikge1xuICAgIHZhciBmaWxsU3Ryb2tlID0gISEoZmlsbEluc3RydWN0aW9uIHx8IHN0cm9rZUluc3RydWN0aW9uKTtcbiAgICB2YXIgYm94ID0gZGltZW5zaW9ucy5kZWNsdXR0ZXJCb3g7XG4gICAgdmFyIGNhbnZhcyA9IGNvbnRleHQuY2FudmFzO1xuICAgIHZhciBzdHJva2VQYWRkaW5nID0gc3Ryb2tlSW5zdHJ1Y3Rpb24gPyBzdHJva2VJbnN0cnVjdGlvblsyXSAqIGRpbWVuc2lvbnMuc2NhbGVbMF0gLyAyIDogMDtcbiAgICB2YXIgaW50ZXJzZWN0cyA9IGJveC5taW5YIC0gc3Ryb2tlUGFkZGluZyA8PSBjYW52YXMud2lkdGggLyBjb250ZXh0U2NhbGUgJiYgYm94Lm1heFggKyBzdHJva2VQYWRkaW5nID49IDAgJiYgYm94Lm1pblkgLSBzdHJva2VQYWRkaW5nIDw9IGNhbnZhcy5oZWlnaHQgLyBjb250ZXh0U2NhbGUgJiYgYm94Lm1heFkgKyBzdHJva2VQYWRkaW5nID49IDA7XG5cbiAgICBpZiAoaW50ZXJzZWN0cykge1xuICAgICAgaWYgKGZpbGxTdHJva2UpIHtcbiAgICAgICAgdGhpcy5yZXBsYXlUZXh0QmFja2dyb3VuZF8oY29udGV4dCwgcDEsIHAyLCBwMywgcDQsXG4gICAgICAgIC8qKiBAdHlwZSB7QXJyYXk8Kj59ICovXG4gICAgICAgIGZpbGxJbnN0cnVjdGlvbixcbiAgICAgICAgLyoqIEB0eXBlIHtBcnJheTwqPn0gKi9cbiAgICAgICAgc3Ryb2tlSW5zdHJ1Y3Rpb24pO1xuICAgICAgfVxuXG4gICAgICBkcmF3SW1hZ2VPckxhYmVsKGNvbnRleHQsIGRpbWVuc2lvbnMuY2FudmFzVHJhbnNmb3JtLCBvcGFjaXR5LCBpbWFnZU9yTGFiZWwsIGRpbWVuc2lvbnMub3JpZ2luWCwgZGltZW5zaW9ucy5vcmlnaW5ZLCBkaW1lbnNpb25zLmRyYXdJbWFnZVcsIGRpbWVuc2lvbnMuZHJhd0ltYWdlSCwgZGltZW5zaW9ucy5kcmF3SW1hZ2VYLCBkaW1lbnNpb25zLmRyYXdJbWFnZVksIGRpbWVuc2lvbnMuc2NhbGUpO1xuICAgIH1cblxuICAgIHJldHVybiB0cnVlO1xuICB9O1xuICAvKipcbiAgICogQHByaXZhdGVcbiAgICogQHBhcmFtIHtDYW52YXNSZW5kZXJpbmdDb250ZXh0MkR9IGNvbnRleHQgQ29udGV4dC5cbiAgICovXG5cblxuICBFeGVjdXRvci5wcm90b3R5cGUuZmlsbF8gPSBmdW5jdGlvbiAoY29udGV4dCkge1xuICAgIGlmICh0aGlzLmFsaWduRmlsbF8pIHtcbiAgICAgIHZhciBvcmlnaW5fMSA9IGFwcGx5VHJhbnNmb3JtKHRoaXMucmVuZGVyZWRUcmFuc2Zvcm1fLCBbMCwgMF0pO1xuICAgICAgdmFyIHJlcGVhdFNpemUgPSA1MTIgKiB0aGlzLnBpeGVsUmF0aW87XG4gICAgICBjb250ZXh0LnNhdmUoKTtcbiAgICAgIGNvbnRleHQudHJhbnNsYXRlKG9yaWdpbl8xWzBdICUgcmVwZWF0U2l6ZSwgb3JpZ2luXzFbMV0gJSByZXBlYXRTaXplKTtcbiAgICAgIGNvbnRleHQucm90YXRlKHRoaXMudmlld1JvdGF0aW9uXyk7XG4gICAgfVxuXG4gICAgY29udGV4dC5maWxsKCk7XG5cbiAgICBpZiAodGhpcy5hbGlnbkZpbGxfKSB7XG4gICAgICBjb250ZXh0LnJlc3RvcmUoKTtcbiAgICB9XG4gIH07XG4gIC8qKlxuICAgKiBAcHJpdmF0ZVxuICAgKiBAcGFyYW0ge0NhbnZhc1JlbmRlcmluZ0NvbnRleHQyRH0gY29udGV4dCBDb250ZXh0LlxuICAgKiBAcGFyYW0ge0FycmF5PCo+fSBpbnN0cnVjdGlvbiBJbnN0cnVjdGlvbi5cbiAgICovXG5cblxuICBFeGVjdXRvci5wcm90b3R5cGUuc2V0U3Ryb2tlU3R5bGVfID0gZnVuY3Rpb24gKGNvbnRleHQsIGluc3RydWN0aW9uKSB7XG4gICAgY29udGV4dFsnc3Ryb2tlU3R5bGUnXSA9XG4gICAgLyoqIEB0eXBlIHtpbXBvcnQoXCIuLi8uLi9jb2xvcmxpa2UuanNcIikuQ29sb3JMaWtlfSAqL1xuICAgIGluc3RydWN0aW9uWzFdO1xuICAgIGNvbnRleHQubGluZVdpZHRoID1cbiAgICAvKiogQHR5cGUge251bWJlcn0gKi9cbiAgICBpbnN0cnVjdGlvblsyXTtcbiAgICBjb250ZXh0LmxpbmVDYXAgPVxuICAgIC8qKiBAdHlwZSB7Q2FudmFzTGluZUNhcH0gKi9cbiAgICBpbnN0cnVjdGlvblszXTtcbiAgICBjb250ZXh0LmxpbmVKb2luID1cbiAgICAvKiogQHR5cGUge0NhbnZhc0xpbmVKb2lufSAqL1xuICAgIGluc3RydWN0aW9uWzRdO1xuICAgIGNvbnRleHQubWl0ZXJMaW1pdCA9XG4gICAgLyoqIEB0eXBlIHtudW1iZXJ9ICovXG4gICAgaW5zdHJ1Y3Rpb25bNV07XG5cbiAgICBpZiAoY29udGV4dC5zZXRMaW5lRGFzaCkge1xuICAgICAgY29udGV4dC5saW5lRGFzaE9mZnNldCA9XG4gICAgICAvKiogQHR5cGUge251bWJlcn0gKi9cbiAgICAgIGluc3RydWN0aW9uWzddO1xuICAgICAgY29udGV4dC5zZXRMaW5lRGFzaChcbiAgICAgIC8qKiBAdHlwZSB7QXJyYXk8bnVtYmVyPn0gKi9cbiAgICAgIGluc3RydWN0aW9uWzZdKTtcbiAgICB9XG4gIH07XG4gIC8qKlxuICAgKiBAcHJpdmF0ZVxuICAgKiBAcGFyYW0ge3N0cmluZ30gdGV4dCBUaGUgdGV4dCB0byBkcmF3LlxuICAgKiBAcGFyYW0ge3N0cmluZ30gdGV4dEtleSBUaGUga2V5IG9mIHRoZSB0ZXh0IHN0YXRlLlxuICAgKiBAcGFyYW0ge3N0cmluZ30gc3Ryb2tlS2V5IFRoZSBrZXkgZm9yIHRoZSBzdHJva2Ugc3RhdGUuXG4gICAqIEBwYXJhbSB7c3RyaW5nfSBmaWxsS2V5IFRoZSBrZXkgZm9yIHRoZSBmaWxsIHN0YXRlLlxuICAgKiBAcmV0dXJuIHt7bGFiZWw6IGltcG9ydChcIi4uL2NhbnZhcy5qc1wiKS5MYWJlbCwgYW5jaG9yWDogbnVtYmVyLCBhbmNob3JZOiBudW1iZXJ9fSBUaGUgdGV4dCBpbWFnZSBhbmQgaXRzIGFuY2hvci5cbiAgICovXG5cblxuICBFeGVjdXRvci5wcm90b3R5cGUuZHJhd0xhYmVsV2l0aFBvaW50UGxhY2VtZW50XyA9IGZ1bmN0aW9uICh0ZXh0LCB0ZXh0S2V5LCBzdHJva2VLZXksIGZpbGxLZXkpIHtcbiAgICB2YXIgdGV4dFN0YXRlID0gdGhpcy50ZXh0U3RhdGVzW3RleHRLZXldO1xuICAgIHZhciBsYWJlbCA9IHRoaXMuY3JlYXRlTGFiZWwodGV4dCwgdGV4dEtleSwgZmlsbEtleSwgc3Ryb2tlS2V5KTtcbiAgICB2YXIgc3Ryb2tlU3RhdGUgPSB0aGlzLnN0cm9rZVN0YXRlc1tzdHJva2VLZXldO1xuICAgIHZhciBwaXhlbFJhdGlvID0gdGhpcy5waXhlbFJhdGlvO1xuICAgIHZhciBhbGlnbiA9IGhvcml6b250YWxUZXh0QWxpZ24odGV4dCwgdGV4dFN0YXRlLnRleHRBbGlnbiB8fCBkZWZhdWx0VGV4dEFsaWduKTtcbiAgICB2YXIgYmFzZWxpbmUgPSBURVhUX0FMSUdOW3RleHRTdGF0ZS50ZXh0QmFzZWxpbmUgfHwgZGVmYXVsdFRleHRCYXNlbGluZV07XG4gICAgdmFyIHN0cm9rZVdpZHRoID0gc3Ryb2tlU3RhdGUgJiYgc3Ryb2tlU3RhdGUubGluZVdpZHRoID8gc3Ryb2tlU3RhdGUubGluZVdpZHRoIDogMDsgLy8gUmVtb3ZlIHRoZSAyIHBpeGVscyB3ZSBhZGRlZCBpbiBjcmVhdGVMYWJlbCgpIGZvciB0aGUgYW5jaG9yXG5cbiAgICB2YXIgd2lkdGggPSBsYWJlbC53aWR0aCAvIHBpeGVsUmF0aW8gLSAyICogdGV4dFN0YXRlLnNjYWxlWzBdO1xuICAgIHZhciBhbmNob3JYID0gYWxpZ24gKiB3aWR0aCArIDIgKiAoMC41IC0gYWxpZ24pICogc3Ryb2tlV2lkdGg7XG4gICAgdmFyIGFuY2hvclkgPSBiYXNlbGluZSAqIGxhYmVsLmhlaWdodCAvIHBpeGVsUmF0aW8gKyAyICogKDAuNSAtIGJhc2VsaW5lKSAqIHN0cm9rZVdpZHRoO1xuICAgIHJldHVybiB7XG4gICAgICBsYWJlbDogbGFiZWwsXG4gICAgICBhbmNob3JYOiBhbmNob3JYLFxuICAgICAgYW5jaG9yWTogYW5jaG9yWVxuICAgIH07XG4gIH07XG4gIC8qKlxuICAgKiBAcHJpdmF0ZVxuICAgKiBAcGFyYW0ge0NhbnZhc1JlbmRlcmluZ0NvbnRleHQyRH0gY29udGV4dCBDb250ZXh0LlxuICAgKiBAcGFyYW0ge251bWJlcn0gY29udGV4dFNjYWxlIFNjYWxlIG9mIHRoZSBjb250ZXh0LlxuICAgKiBAcGFyYW0ge2ltcG9ydChcIi4uLy4uL3RyYW5zZm9ybS5qc1wiKS5UcmFuc2Zvcm19IHRyYW5zZm9ybSBUcmFuc2Zvcm0uXG4gICAqIEBwYXJhbSB7QXJyYXk8Kj59IGluc3RydWN0aW9ucyBJbnN0cnVjdGlvbnMgYXJyYXkuXG4gICAqIEBwYXJhbSB7Ym9vbGVhbn0gc25hcFRvUGl4ZWwgU25hcCBwb2ludCBzeW1ib2xzIGFuZCB0ZXh0IHRvIGludGVnZXIgcGl4ZWxzLlxuICAgKiBAcGFyYW0ge0ZlYXR1cmVDYWxsYmFjazxUPj19IG9wdF9mZWF0dXJlQ2FsbGJhY2sgRmVhdHVyZSBjYWxsYmFjay5cbiAgICogQHBhcmFtIHtpbXBvcnQoXCIuLi8uLi9leHRlbnQuanNcIikuRXh0ZW50PX0gb3B0X2hpdEV4dGVudCBPbmx5IGNoZWNrXG4gICAqICAgICBmZWF0dXJlcyB0aGF0IGludGVyc2VjdCB0aGlzIGV4dGVudC5cbiAgICogQHBhcmFtIHtpbXBvcnQoXCJyYnVzaFwiKS5kZWZhdWx0PX0gb3B0X2RlY2x1dHRlclRyZWUgRGVjbHV0dGVyIHRyZWUuXG4gICAqIEByZXR1cm4ge1R8dW5kZWZpbmVkfSBDYWxsYmFjayByZXN1bHQuXG4gICAqIEB0ZW1wbGF0ZSBUXG4gICAqL1xuXG5cbiAgRXhlY3V0b3IucHJvdG90eXBlLmV4ZWN1dGVfID0gZnVuY3Rpb24gKGNvbnRleHQsIGNvbnRleHRTY2FsZSwgdHJhbnNmb3JtLCBpbnN0cnVjdGlvbnMsIHNuYXBUb1BpeGVsLCBvcHRfZmVhdHVyZUNhbGxiYWNrLCBvcHRfaGl0RXh0ZW50LCBvcHRfZGVjbHV0dGVyVHJlZSkge1xuICAgIC8qKiBAdHlwZSB7QXJyYXk8bnVtYmVyPn0gKi9cbiAgICB2YXIgcGl4ZWxDb29yZGluYXRlcztcblxuICAgIGlmICh0aGlzLnBpeGVsQ29vcmRpbmF0ZXNfICYmIGVxdWFscyh0cmFuc2Zvcm0sIHRoaXMucmVuZGVyZWRUcmFuc2Zvcm1fKSkge1xuICAgICAgcGl4ZWxDb29yZGluYXRlcyA9IHRoaXMucGl4ZWxDb29yZGluYXRlc187XG4gICAgfSBlbHNlIHtcbiAgICAgIGlmICghdGhpcy5waXhlbENvb3JkaW5hdGVzXykge1xuICAgICAgICB0aGlzLnBpeGVsQ29vcmRpbmF0ZXNfID0gW107XG4gICAgICB9XG5cbiAgICAgIHBpeGVsQ29vcmRpbmF0ZXMgPSB0cmFuc2Zvcm0yRCh0aGlzLmNvb3JkaW5hdGVzLCAwLCB0aGlzLmNvb3JkaW5hdGVzLmxlbmd0aCwgMiwgdHJhbnNmb3JtLCB0aGlzLnBpeGVsQ29vcmRpbmF0ZXNfKTtcbiAgICAgIHRyYW5zZm9ybVNldEZyb21BcnJheSh0aGlzLnJlbmRlcmVkVHJhbnNmb3JtXywgdHJhbnNmb3JtKTtcbiAgICB9XG5cbiAgICB2YXIgaSA9IDA7IC8vIGluc3RydWN0aW9uIGluZGV4XG5cbiAgICB2YXIgaWkgPSBpbnN0cnVjdGlvbnMubGVuZ3RoOyAvLyBlbmQgb2YgaW5zdHJ1Y3Rpb25zXG5cbiAgICB2YXIgZCA9IDA7IC8vIGRhdGEgaW5kZXhcblxuICAgIHZhciBkZDsgLy8gZW5kIG9mIHBlci1pbnN0cnVjdGlvbiBkYXRhXG5cbiAgICB2YXIgYW5jaG9yWCwgYW5jaG9yWSwgcHJldlgsIHByZXZZLCByb3VuZFgsIHJvdW5kWSwgaW1hZ2UsIHRleHQsIHRleHRLZXksIHN0cm9rZUtleSwgZmlsbEtleTtcbiAgICB2YXIgcGVuZGluZ0ZpbGwgPSAwO1xuICAgIHZhciBwZW5kaW5nU3Ryb2tlID0gMDtcbiAgICB2YXIgbGFzdEZpbGxJbnN0cnVjdGlvbiA9IG51bGw7XG4gICAgdmFyIGxhc3RTdHJva2VJbnN0cnVjdGlvbiA9IG51bGw7XG4gICAgdmFyIGNvb3JkaW5hdGVDYWNoZSA9IHRoaXMuY29vcmRpbmF0ZUNhY2hlXztcbiAgICB2YXIgdmlld1JvdGF0aW9uID0gdGhpcy52aWV3Um90YXRpb25fO1xuICAgIHZhciB2aWV3Um90YXRpb25Gcm9tVHJhbnNmb3JtID0gTWF0aC5yb3VuZChNYXRoLmF0YW4yKC10cmFuc2Zvcm1bMV0sIHRyYW5zZm9ybVswXSkgKiAxZTEyKSAvIDFlMTI7XG4gICAgdmFyIHN0YXRlID1cbiAgICAvKiogQHR5cGUge2ltcG9ydChcIi4uLy4uL3JlbmRlci5qc1wiKS5TdGF0ZX0gKi9cbiAgICB7XG4gICAgICBjb250ZXh0OiBjb250ZXh0LFxuICAgICAgcGl4ZWxSYXRpbzogdGhpcy5waXhlbFJhdGlvLFxuICAgICAgcmVzb2x1dGlvbjogdGhpcy5yZXNvbHV0aW9uLFxuICAgICAgcm90YXRpb246IHZpZXdSb3RhdGlvblxuICAgIH07IC8vIFdoZW4gdGhlIGJhdGNoIHNpemUgZ2V0cyB0b28gYmlnLCBwZXJmb3JtYW5jZSBkZWNyZWFzZXMuIDIwMCBpcyBhIGdvb2RcbiAgICAvLyBiYWxhbmNlIGJldHdlZW4gYmF0Y2ggc2l6ZSBhbmQgbnVtYmVyIG9mIGZpbGwvc3Ryb2tlIGluc3RydWN0aW9ucy5cblxuICAgIHZhciBiYXRjaFNpemUgPSB0aGlzLmluc3RydWN0aW9ucyAhPSBpbnN0cnVjdGlvbnMgfHwgdGhpcy5vdmVybGFwcyA/IDAgOiAyMDA7XG4gICAgdmFyXG4gICAgLyoqIEB0eXBlIHtpbXBvcnQoXCIuLi8uLi9GZWF0dXJlLmpzXCIpLkZlYXR1cmVMaWtlfSAqL1xuICAgIGZlYXR1cmU7XG4gICAgdmFyIHgsIHksIGN1cnJlbnRHZW9tZXRyeTtcblxuICAgIHdoaWxlIChpIDwgaWkpIHtcbiAgICAgIHZhciBpbnN0cnVjdGlvbiA9IGluc3RydWN0aW9uc1tpXTtcbiAgICAgIHZhciB0eXBlID1cbiAgICAgIC8qKiBAdHlwZSB7aW1wb3J0KFwiLi9JbnN0cnVjdGlvbi5qc1wiKS5kZWZhdWx0fSAqL1xuICAgICAgaW5zdHJ1Y3Rpb25bMF07XG5cbiAgICAgIHN3aXRjaCAodHlwZSkge1xuICAgICAgICBjYXNlIENhbnZhc0luc3RydWN0aW9uLkJFR0lOX0dFT01FVFJZOlxuICAgICAgICAgIGZlYXR1cmUgPVxuICAgICAgICAgIC8qKiBAdHlwZSB7aW1wb3J0KFwiLi4vLi4vRmVhdHVyZS5qc1wiKS5GZWF0dXJlTGlrZX0gKi9cbiAgICAgICAgICBpbnN0cnVjdGlvblsxXTtcbiAgICAgICAgICBjdXJyZW50R2VvbWV0cnkgPSBpbnN0cnVjdGlvblszXTtcblxuICAgICAgICAgIGlmICghZmVhdHVyZS5nZXRHZW9tZXRyeSgpKSB7XG4gICAgICAgICAgICBpID1cbiAgICAgICAgICAgIC8qKiBAdHlwZSB7bnVtYmVyfSAqL1xuICAgICAgICAgICAgaW5zdHJ1Y3Rpb25bMl07XG4gICAgICAgICAgfSBlbHNlIGlmIChvcHRfaGl0RXh0ZW50ICE9PSB1bmRlZmluZWQgJiYgIWludGVyc2VjdHMob3B0X2hpdEV4dGVudCwgY3VycmVudEdlb21ldHJ5LmdldEV4dGVudCgpKSkge1xuICAgICAgICAgICAgaSA9XG4gICAgICAgICAgICAvKiogQHR5cGUge251bWJlcn0gKi9cbiAgICAgICAgICAgIGluc3RydWN0aW9uWzJdICsgMTtcbiAgICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgKytpO1xuICAgICAgICAgIH1cblxuICAgICAgICAgIGJyZWFrO1xuXG4gICAgICAgIGNhc2UgQ2FudmFzSW5zdHJ1Y3Rpb24uQkVHSU5fUEFUSDpcbiAgICAgICAgICBpZiAocGVuZGluZ0ZpbGwgPiBiYXRjaFNpemUpIHtcbiAgICAgICAgICAgIHRoaXMuZmlsbF8oY29udGV4dCk7XG4gICAgICAgICAgICBwZW5kaW5nRmlsbCA9IDA7XG4gICAgICAgICAgfVxuXG4gICAgICAgICAgaWYgKHBlbmRpbmdTdHJva2UgPiBiYXRjaFNpemUpIHtcbiAgICAgICAgICAgIGNvbnRleHQuc3Ryb2tlKCk7XG4gICAgICAgICAgICBwZW5kaW5nU3Ryb2tlID0gMDtcbiAgICAgICAgICB9XG5cbiAgICAgICAgICBpZiAoIXBlbmRpbmdGaWxsICYmICFwZW5kaW5nU3Ryb2tlKSB7XG4gICAgICAgICAgICBjb250ZXh0LmJlZ2luUGF0aCgpO1xuICAgICAgICAgICAgcHJldlggPSBOYU47XG4gICAgICAgICAgICBwcmV2WSA9IE5hTjtcbiAgICAgICAgICB9XG5cbiAgICAgICAgICArK2k7XG4gICAgICAgICAgYnJlYWs7XG5cbiAgICAgICAgY2FzZSBDYW52YXNJbnN0cnVjdGlvbi5DSVJDTEU6XG4gICAgICAgICAgZCA9XG4gICAgICAgICAgLyoqIEB0eXBlIHtudW1iZXJ9ICovXG4gICAgICAgICAgaW5zdHJ1Y3Rpb25bMV07XG4gICAgICAgICAgdmFyIHgxID0gcGl4ZWxDb29yZGluYXRlc1tkXTtcbiAgICAgICAgICB2YXIgeTEgPSBwaXhlbENvb3JkaW5hdGVzW2QgKyAxXTtcbiAgICAgICAgICB2YXIgeDIgPSBwaXhlbENvb3JkaW5hdGVzW2QgKyAyXTtcbiAgICAgICAgICB2YXIgeTIgPSBwaXhlbENvb3JkaW5hdGVzW2QgKyAzXTtcbiAgICAgICAgICB2YXIgZHggPSB4MiAtIHgxO1xuICAgICAgICAgIHZhciBkeSA9IHkyIC0geTE7XG4gICAgICAgICAgdmFyIHIgPSBNYXRoLnNxcnQoZHggKiBkeCArIGR5ICogZHkpO1xuICAgICAgICAgIGNvbnRleHQubW92ZVRvKHgxICsgciwgeTEpO1xuICAgICAgICAgIGNvbnRleHQuYXJjKHgxLCB5MSwgciwgMCwgMiAqIE1hdGguUEksIHRydWUpO1xuICAgICAgICAgICsraTtcbiAgICAgICAgICBicmVhaztcblxuICAgICAgICBjYXNlIENhbnZhc0luc3RydWN0aW9uLkNMT1NFX1BBVEg6XG4gICAgICAgICAgY29udGV4dC5jbG9zZVBhdGgoKTtcbiAgICAgICAgICArK2k7XG4gICAgICAgICAgYnJlYWs7XG5cbiAgICAgICAgY2FzZSBDYW52YXNJbnN0cnVjdGlvbi5DVVNUT006XG4gICAgICAgICAgZCA9XG4gICAgICAgICAgLyoqIEB0eXBlIHtudW1iZXJ9ICovXG4gICAgICAgICAgaW5zdHJ1Y3Rpb25bMV07XG4gICAgICAgICAgZGQgPSBpbnN0cnVjdGlvblsyXTtcbiAgICAgICAgICB2YXIgZ2VvbWV0cnkgPVxuICAgICAgICAgIC8qKiBAdHlwZSB7aW1wb3J0KFwiLi4vLi4vZ2VvbS9TaW1wbGVHZW9tZXRyeS5qc1wiKS5kZWZhdWx0fSAqL1xuICAgICAgICAgIGluc3RydWN0aW9uWzNdO1xuICAgICAgICAgIHZhciByZW5kZXJlciA9IGluc3RydWN0aW9uWzRdO1xuICAgICAgICAgIHZhciBmbiA9IGluc3RydWN0aW9uLmxlbmd0aCA9PSA2ID8gaW5zdHJ1Y3Rpb25bNV0gOiB1bmRlZmluZWQ7XG4gICAgICAgICAgc3RhdGUuZ2VvbWV0cnkgPSBnZW9tZXRyeTtcbiAgICAgICAgICBzdGF0ZS5mZWF0dXJlID0gZmVhdHVyZTtcblxuICAgICAgICAgIGlmICghKGkgaW4gY29vcmRpbmF0ZUNhY2hlKSkge1xuICAgICAgICAgICAgY29vcmRpbmF0ZUNhY2hlW2ldID0gW107XG4gICAgICAgICAgfVxuXG4gICAgICAgICAgdmFyIGNvb3JkcyA9IGNvb3JkaW5hdGVDYWNoZVtpXTtcblxuICAgICAgICAgIGlmIChmbikge1xuICAgICAgICAgICAgZm4ocGl4ZWxDb29yZGluYXRlcywgZCwgZGQsIDIsIGNvb3Jkcyk7XG4gICAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgIGNvb3Jkc1swXSA9IHBpeGVsQ29vcmRpbmF0ZXNbZF07XG4gICAgICAgICAgICBjb29yZHNbMV0gPSBwaXhlbENvb3JkaW5hdGVzW2QgKyAxXTtcbiAgICAgICAgICAgIGNvb3Jkcy5sZW5ndGggPSAyO1xuICAgICAgICAgIH1cblxuICAgICAgICAgIHJlbmRlcmVyKGNvb3Jkcywgc3RhdGUpO1xuICAgICAgICAgICsraTtcbiAgICAgICAgICBicmVhaztcblxuICAgICAgICBjYXNlIENhbnZhc0luc3RydWN0aW9uLkRSQVdfSU1BR0U6XG4gICAgICAgICAgZCA9XG4gICAgICAgICAgLyoqIEB0eXBlIHtudW1iZXJ9ICovXG4gICAgICAgICAgaW5zdHJ1Y3Rpb25bMV07XG4gICAgICAgICAgZGQgPVxuICAgICAgICAgIC8qKiBAdHlwZSB7bnVtYmVyfSAqL1xuICAgICAgICAgIGluc3RydWN0aW9uWzJdO1xuICAgICAgICAgIGltYWdlID1cbiAgICAgICAgICAvKiogQHR5cGUge0hUTUxDYW52YXNFbGVtZW50fEhUTUxWaWRlb0VsZW1lbnR8SFRNTEltYWdlRWxlbWVudH0gKi9cbiAgICAgICAgICBpbnN0cnVjdGlvblszXTsgLy8gUmVtYWluaW5nIGFyZ3VtZW50cyBpbiBEUkFXX0lNQUdFIGFyZSBpbiBhbHBoYWJldGljYWwgb3JkZXJcblxuICAgICAgICAgIGFuY2hvclggPVxuICAgICAgICAgIC8qKiBAdHlwZSB7bnVtYmVyfSAqL1xuICAgICAgICAgIGluc3RydWN0aW9uWzRdO1xuICAgICAgICAgIGFuY2hvclkgPVxuICAgICAgICAgIC8qKiBAdHlwZSB7bnVtYmVyfSAqL1xuICAgICAgICAgIGluc3RydWN0aW9uWzVdO1xuICAgICAgICAgIHZhciBoZWlnaHQgPVxuICAgICAgICAgIC8qKiBAdHlwZSB7bnVtYmVyfSAqL1xuICAgICAgICAgIGluc3RydWN0aW9uWzZdO1xuICAgICAgICAgIHZhciBvcGFjaXR5ID1cbiAgICAgICAgICAvKiogQHR5cGUge251bWJlcn0gKi9cbiAgICAgICAgICBpbnN0cnVjdGlvbls3XTtcbiAgICAgICAgICB2YXIgb3JpZ2luWCA9XG4gICAgICAgICAgLyoqIEB0eXBlIHtudW1iZXJ9ICovXG4gICAgICAgICAgaW5zdHJ1Y3Rpb25bOF07XG4gICAgICAgICAgdmFyIG9yaWdpblkgPVxuICAgICAgICAgIC8qKiBAdHlwZSB7bnVtYmVyfSAqL1xuICAgICAgICAgIGluc3RydWN0aW9uWzldO1xuICAgICAgICAgIHZhciByb3RhdGVXaXRoVmlldyA9XG4gICAgICAgICAgLyoqIEB0eXBlIHtib29sZWFufSAqL1xuICAgICAgICAgIGluc3RydWN0aW9uWzEwXTtcbiAgICAgICAgICB2YXIgcm90YXRpb24gPVxuICAgICAgICAgIC8qKiBAdHlwZSB7bnVtYmVyfSAqL1xuICAgICAgICAgIGluc3RydWN0aW9uWzExXTtcbiAgICAgICAgICB2YXIgc2NhbGUgPVxuICAgICAgICAgIC8qKiBAdHlwZSB7aW1wb3J0KFwiLi4vLi4vc2l6ZS5qc1wiKS5TaXplfSAqL1xuICAgICAgICAgIGluc3RydWN0aW9uWzEyXTtcbiAgICAgICAgICB2YXIgd2lkdGggPVxuICAgICAgICAgIC8qKiBAdHlwZSB7bnVtYmVyfSAqL1xuICAgICAgICAgIGluc3RydWN0aW9uWzEzXTtcbiAgICAgICAgICB2YXIgZGVjbHV0dGVySW1hZ2VXaXRoVGV4dCA9XG4gICAgICAgICAgLyoqIEB0eXBlIHtpbXBvcnQoXCIuLi9jYW52YXMuanNcIikuRGVjbHV0dGVySW1hZ2VXaXRoVGV4dH0gKi9cbiAgICAgICAgICBpbnN0cnVjdGlvblsxNF07XG5cbiAgICAgICAgICBpZiAoIWltYWdlICYmIGluc3RydWN0aW9uLmxlbmd0aCA+PSAxOSkge1xuICAgICAgICAgICAgLy8gY3JlYXRlIGxhYmVsIGltYWdlc1xuICAgICAgICAgICAgdGV4dCA9XG4gICAgICAgICAgICAvKiogQHR5cGUge3N0cmluZ30gKi9cbiAgICAgICAgICAgIGluc3RydWN0aW9uWzE4XTtcbiAgICAgICAgICAgIHRleHRLZXkgPVxuICAgICAgICAgICAgLyoqIEB0eXBlIHtzdHJpbmd9ICovXG4gICAgICAgICAgICBpbnN0cnVjdGlvblsxOV07XG4gICAgICAgICAgICBzdHJva2VLZXkgPVxuICAgICAgICAgICAgLyoqIEB0eXBlIHtzdHJpbmd9ICovXG4gICAgICAgICAgICBpbnN0cnVjdGlvblsyMF07XG4gICAgICAgICAgICBmaWxsS2V5ID1cbiAgICAgICAgICAgIC8qKiBAdHlwZSB7c3RyaW5nfSAqL1xuICAgICAgICAgICAgaW5zdHJ1Y3Rpb25bMjFdO1xuICAgICAgICAgICAgdmFyIGxhYmVsV2l0aEFuY2hvciA9IHRoaXMuZHJhd0xhYmVsV2l0aFBvaW50UGxhY2VtZW50Xyh0ZXh0LCB0ZXh0S2V5LCBzdHJva2VLZXksIGZpbGxLZXkpO1xuICAgICAgICAgICAgaW1hZ2UgPSBsYWJlbFdpdGhBbmNob3IubGFiZWw7XG4gICAgICAgICAgICBpbnN0cnVjdGlvblszXSA9IGltYWdlO1xuICAgICAgICAgICAgdmFyIHRleHRPZmZzZXRYID1cbiAgICAgICAgICAgIC8qKiBAdHlwZSB7bnVtYmVyfSAqL1xuICAgICAgICAgICAgaW5zdHJ1Y3Rpb25bMjJdO1xuICAgICAgICAgICAgYW5jaG9yWCA9IChsYWJlbFdpdGhBbmNob3IuYW5jaG9yWCAtIHRleHRPZmZzZXRYKSAqIHRoaXMucGl4ZWxSYXRpbztcbiAgICAgICAgICAgIGluc3RydWN0aW9uWzRdID0gYW5jaG9yWDtcbiAgICAgICAgICAgIHZhciB0ZXh0T2Zmc2V0WSA9XG4gICAgICAgICAgICAvKiogQHR5cGUge251bWJlcn0gKi9cbiAgICAgICAgICAgIGluc3RydWN0aW9uWzIzXTtcbiAgICAgICAgICAgIGFuY2hvclkgPSAobGFiZWxXaXRoQW5jaG9yLmFuY2hvclkgLSB0ZXh0T2Zmc2V0WSkgKiB0aGlzLnBpeGVsUmF0aW87XG4gICAgICAgICAgICBpbnN0cnVjdGlvbls1XSA9IGFuY2hvclk7XG4gICAgICAgICAgICBoZWlnaHQgPSBpbWFnZS5oZWlnaHQ7XG4gICAgICAgICAgICBpbnN0cnVjdGlvbls2XSA9IGhlaWdodDtcbiAgICAgICAgICAgIHdpZHRoID0gaW1hZ2Uud2lkdGg7XG4gICAgICAgICAgICBpbnN0cnVjdGlvblsxM10gPSB3aWR0aDtcbiAgICAgICAgICB9XG5cbiAgICAgICAgICB2YXIgZ2VvbWV0cnlXaWR0aHMgPSB2b2lkIDA7XG5cbiAgICAgICAgICBpZiAoaW5zdHJ1Y3Rpb24ubGVuZ3RoID4gMjQpIHtcbiAgICAgICAgICAgIGdlb21ldHJ5V2lkdGhzID1cbiAgICAgICAgICAgIC8qKiBAdHlwZSB7bnVtYmVyfSAqL1xuICAgICAgICAgICAgaW5zdHJ1Y3Rpb25bMjRdO1xuICAgICAgICAgIH1cblxuICAgICAgICAgIHZhciBwYWRkaW5nID0gdm9pZCAwLFxuICAgICAgICAgICAgICBiYWNrZ3JvdW5kRmlsbCA9IHZvaWQgMCxcbiAgICAgICAgICAgICAgYmFja2dyb3VuZFN0cm9rZSA9IHZvaWQgMDtcblxuICAgICAgICAgIGlmIChpbnN0cnVjdGlvbi5sZW5ndGggPiAxNikge1xuICAgICAgICAgICAgcGFkZGluZyA9XG4gICAgICAgICAgICAvKiogQHR5cGUge0FycmF5PG51bWJlcj59ICovXG4gICAgICAgICAgICBpbnN0cnVjdGlvblsxNV07XG4gICAgICAgICAgICBiYWNrZ3JvdW5kRmlsbCA9XG4gICAgICAgICAgICAvKiogQHR5cGUge2Jvb2xlYW59ICovXG4gICAgICAgICAgICBpbnN0cnVjdGlvblsxNl07XG4gICAgICAgICAgICBiYWNrZ3JvdW5kU3Ryb2tlID1cbiAgICAgICAgICAgIC8qKiBAdHlwZSB7Ym9vbGVhbn0gKi9cbiAgICAgICAgICAgIGluc3RydWN0aW9uWzE3XTtcbiAgICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgcGFkZGluZyA9IGRlZmF1bHRQYWRkaW5nO1xuICAgICAgICAgICAgYmFja2dyb3VuZEZpbGwgPSBmYWxzZTtcbiAgICAgICAgICAgIGJhY2tncm91bmRTdHJva2UgPSBmYWxzZTtcbiAgICAgICAgICB9XG5cbiAgICAgICAgICBpZiAocm90YXRlV2l0aFZpZXcgJiYgdmlld1JvdGF0aW9uRnJvbVRyYW5zZm9ybSkge1xuICAgICAgICAgICAgLy8gQ2FudmFzIGlzIGV4cGVjdGVkIHRvIGJlIHJvdGF0ZWQgdG8gcmV2ZXJzZSB2aWV3IHJvdGF0aW9uLlxuICAgICAgICAgICAgcm90YXRpb24gKz0gdmlld1JvdGF0aW9uO1xuICAgICAgICAgIH0gZWxzZSBpZiAoIXJvdGF0ZVdpdGhWaWV3ICYmICF2aWV3Um90YXRpb25Gcm9tVHJhbnNmb3JtKSB7XG4gICAgICAgICAgICAvLyBDYW52YXMgaXMgbm90IHJvdGF0ZWQsIGltYWdlcyBuZWVkIHRvIGJlIHJvdGF0ZWQgYmFjayB0byBiZSBub3J0aC11cC5cbiAgICAgICAgICAgIHJvdGF0aW9uIC09IHZpZXdSb3RhdGlvbjtcbiAgICAgICAgICB9XG5cbiAgICAgICAgICB2YXIgd2lkdGhJbmRleCA9IDA7XG5cbiAgICAgICAgICBmb3IgKDsgZCA8IGRkOyBkICs9IDIpIHtcbiAgICAgICAgICAgIGlmIChnZW9tZXRyeVdpZHRocyAmJiBnZW9tZXRyeVdpZHRoc1t3aWR0aEluZGV4KytdIDwgd2lkdGggLyB0aGlzLnBpeGVsUmF0aW8pIHtcbiAgICAgICAgICAgICAgY29udGludWU7XG4gICAgICAgICAgICB9XG5cbiAgICAgICAgICAgIHZhciBkaW1lbnNpb25zID0gdGhpcy5jYWxjdWxhdGVJbWFnZU9yTGFiZWxEaW1lbnNpb25zXyhpbWFnZS53aWR0aCwgaW1hZ2UuaGVpZ2h0LCBwaXhlbENvb3JkaW5hdGVzW2RdLCBwaXhlbENvb3JkaW5hdGVzW2QgKyAxXSwgd2lkdGgsIGhlaWdodCwgYW5jaG9yWCwgYW5jaG9yWSwgb3JpZ2luWCwgb3JpZ2luWSwgcm90YXRpb24sIHNjYWxlLCBzbmFwVG9QaXhlbCwgcGFkZGluZywgYmFja2dyb3VuZEZpbGwgfHwgYmFja2dyb3VuZFN0cm9rZSwgZmVhdHVyZSk7XG4gICAgICAgICAgICAvKiogQHR5cGUge1JlcGxheUltYWdlT3JMYWJlbEFyZ3N9ICovXG5cbiAgICAgICAgICAgIHZhciBhcmdzID0gW2NvbnRleHQsIGNvbnRleHRTY2FsZSwgaW1hZ2UsIGRpbWVuc2lvbnMsIG9wYWNpdHksIGJhY2tncm91bmRGaWxsID9cbiAgICAgICAgICAgIC8qKiBAdHlwZSB7QXJyYXk8Kj59ICovXG4gICAgICAgICAgICBsYXN0RmlsbEluc3RydWN0aW9uIDogbnVsbCwgYmFja2dyb3VuZFN0cm9rZSA/XG4gICAgICAgICAgICAvKiogQHR5cGUge0FycmF5PCo+fSAqL1xuICAgICAgICAgICAgbGFzdFN0cm9rZUluc3RydWN0aW9uIDogbnVsbF07XG4gICAgICAgICAgICB2YXIgaW1hZ2VBcmdzID0gdm9pZCAwO1xuICAgICAgICAgICAgdmFyIGltYWdlRGVjbHV0dGVyQm94ID0gdm9pZCAwO1xuXG4gICAgICAgICAgICBpZiAob3B0X2RlY2x1dHRlclRyZWUgJiYgZGVjbHV0dGVySW1hZ2VXaXRoVGV4dCkge1xuICAgICAgICAgICAgICBpZiAoIWRlY2x1dHRlckltYWdlV2l0aFRleHRbZF0pIHtcbiAgICAgICAgICAgICAgICAvLyBXZSBub3cgaGF2ZSB0aGUgaW1hZ2UgZm9yIGFuIGltYWdlK3RleHQgY29tYmluYXRpb24uXG4gICAgICAgICAgICAgICAgZGVjbHV0dGVySW1hZ2VXaXRoVGV4dFtkXSA9IGFyZ3M7IC8vIERvbid0IHJlbmRlciBhbnl0aGluZyBmb3Igbm93LCB3YWl0IGZvciB0aGUgdGV4dC5cblxuICAgICAgICAgICAgICAgIGNvbnRpbnVlO1xuICAgICAgICAgICAgICB9XG5cbiAgICAgICAgICAgICAgaW1hZ2VBcmdzID0gZGVjbHV0dGVySW1hZ2VXaXRoVGV4dFtkXTtcbiAgICAgICAgICAgICAgZGVsZXRlIGRlY2x1dHRlckltYWdlV2l0aFRleHRbZF07XG4gICAgICAgICAgICAgIGltYWdlRGVjbHV0dGVyQm94ID0gZ2V0RGVjbHV0dGVyQm94KGltYWdlQXJncyk7XG5cbiAgICAgICAgICAgICAgaWYgKG9wdF9kZWNsdXR0ZXJUcmVlLmNvbGxpZGVzKGltYWdlRGVjbHV0dGVyQm94KSkge1xuICAgICAgICAgICAgICAgIGNvbnRpbnVlO1xuICAgICAgICAgICAgICB9XG4gICAgICAgICAgICB9XG5cbiAgICAgICAgICAgIGlmIChvcHRfZGVjbHV0dGVyVHJlZSAmJiBvcHRfZGVjbHV0dGVyVHJlZS5jb2xsaWRlcyhkaW1lbnNpb25zLmRlY2x1dHRlckJveCkpIHtcbiAgICAgICAgICAgICAgY29udGludWU7XG4gICAgICAgICAgICB9XG5cbiAgICAgICAgICAgIGlmIChpbWFnZUFyZ3MpIHtcbiAgICAgICAgICAgICAgLy8gV2Ugbm93IGhhdmUgaW1hZ2UgYW5kIHRleHQgZm9yIGFuIGltYWdlK3RleHQgY29tYmluYXRpb24uXG4gICAgICAgICAgICAgIGlmIChvcHRfZGVjbHV0dGVyVHJlZSkge1xuICAgICAgICAgICAgICAgIG9wdF9kZWNsdXR0ZXJUcmVlLmluc2VydChpbWFnZURlY2x1dHRlckJveCk7XG4gICAgICAgICAgICAgIH0gLy8gUmVuZGVyIHRoZSBpbWFnZSBiZWZvcmUgd2UgcmVuZGVyIHRoZSB0ZXh0LlxuXG5cbiAgICAgICAgICAgICAgdGhpcy5yZXBsYXlJbWFnZU9yTGFiZWxfLmFwcGx5KHRoaXMsIGltYWdlQXJncyk7XG4gICAgICAgICAgICB9XG5cbiAgICAgICAgICAgIGlmIChvcHRfZGVjbHV0dGVyVHJlZSkge1xuICAgICAgICAgICAgICBvcHRfZGVjbHV0dGVyVHJlZS5pbnNlcnQoZGltZW5zaW9ucy5kZWNsdXR0ZXJCb3gpO1xuICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICB0aGlzLnJlcGxheUltYWdlT3JMYWJlbF8uYXBwbHkodGhpcywgYXJncyk7XG4gICAgICAgICAgfVxuXG4gICAgICAgICAgKytpO1xuICAgICAgICAgIGJyZWFrO1xuXG4gICAgICAgIGNhc2UgQ2FudmFzSW5zdHJ1Y3Rpb24uRFJBV19DSEFSUzpcbiAgICAgICAgICB2YXIgYmVnaW4gPVxuICAgICAgICAgIC8qKiBAdHlwZSB7bnVtYmVyfSAqL1xuICAgICAgICAgIGluc3RydWN0aW9uWzFdO1xuICAgICAgICAgIHZhciBlbmQgPVxuICAgICAgICAgIC8qKiBAdHlwZSB7bnVtYmVyfSAqL1xuICAgICAgICAgIGluc3RydWN0aW9uWzJdO1xuICAgICAgICAgIHZhciBiYXNlbGluZSA9XG4gICAgICAgICAgLyoqIEB0eXBlIHtudW1iZXJ9ICovXG4gICAgICAgICAgaW5zdHJ1Y3Rpb25bM107XG4gICAgICAgICAgdmFyIG92ZXJmbG93ID1cbiAgICAgICAgICAvKiogQHR5cGUge251bWJlcn0gKi9cbiAgICAgICAgICBpbnN0cnVjdGlvbls0XTtcbiAgICAgICAgICBmaWxsS2V5ID1cbiAgICAgICAgICAvKiogQHR5cGUge3N0cmluZ30gKi9cbiAgICAgICAgICBpbnN0cnVjdGlvbls1XTtcbiAgICAgICAgICB2YXIgbWF4QW5nbGUgPVxuICAgICAgICAgIC8qKiBAdHlwZSB7bnVtYmVyfSAqL1xuICAgICAgICAgIGluc3RydWN0aW9uWzZdO1xuICAgICAgICAgIHZhciBtZWFzdXJlUGl4ZWxSYXRpbyA9XG4gICAgICAgICAgLyoqIEB0eXBlIHtudW1iZXJ9ICovXG4gICAgICAgICAgaW5zdHJ1Y3Rpb25bN107XG4gICAgICAgICAgdmFyIG9mZnNldFkgPVxuICAgICAgICAgIC8qKiBAdHlwZSB7bnVtYmVyfSAqL1xuICAgICAgICAgIGluc3RydWN0aW9uWzhdO1xuICAgICAgICAgIHN0cm9rZUtleSA9XG4gICAgICAgICAgLyoqIEB0eXBlIHtzdHJpbmd9ICovXG4gICAgICAgICAgaW5zdHJ1Y3Rpb25bOV07XG4gICAgICAgICAgdmFyIHN0cm9rZVdpZHRoID1cbiAgICAgICAgICAvKiogQHR5cGUge251bWJlcn0gKi9cbiAgICAgICAgICBpbnN0cnVjdGlvblsxMF07XG4gICAgICAgICAgdGV4dCA9XG4gICAgICAgICAgLyoqIEB0eXBlIHtzdHJpbmd9ICovXG4gICAgICAgICAgaW5zdHJ1Y3Rpb25bMTFdO1xuICAgICAgICAgIHRleHRLZXkgPVxuICAgICAgICAgIC8qKiBAdHlwZSB7c3RyaW5nfSAqL1xuICAgICAgICAgIGluc3RydWN0aW9uWzEyXTtcbiAgICAgICAgICB2YXIgcGl4ZWxSYXRpb1NjYWxlID0gW1xuICAgICAgICAgIC8qKiBAdHlwZSB7bnVtYmVyfSAqL1xuICAgICAgICAgIGluc3RydWN0aW9uWzEzXSxcbiAgICAgICAgICAvKiogQHR5cGUge251bWJlcn0gKi9cbiAgICAgICAgICBpbnN0cnVjdGlvblsxM11dO1xuICAgICAgICAgIHZhciB0ZXh0U3RhdGUgPSB0aGlzLnRleHRTdGF0ZXNbdGV4dEtleV07XG4gICAgICAgICAgdmFyIGZvbnQgPSB0ZXh0U3RhdGUuZm9udDtcbiAgICAgICAgICB2YXIgdGV4dFNjYWxlID0gW3RleHRTdGF0ZS5zY2FsZVswXSAqIG1lYXN1cmVQaXhlbFJhdGlvLCB0ZXh0U3RhdGUuc2NhbGVbMV0gKiBtZWFzdXJlUGl4ZWxSYXRpb107XG4gICAgICAgICAgdmFyIGNhY2hlZFdpZHRocyA9IHZvaWQgMDtcblxuICAgICAgICAgIGlmIChmb250IGluIHRoaXMud2lkdGhzXykge1xuICAgICAgICAgICAgY2FjaGVkV2lkdGhzID0gdGhpcy53aWR0aHNfW2ZvbnRdO1xuICAgICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICBjYWNoZWRXaWR0aHMgPSB7fTtcbiAgICAgICAgICAgIHRoaXMud2lkdGhzX1tmb250XSA9IGNhY2hlZFdpZHRocztcbiAgICAgICAgICB9XG5cbiAgICAgICAgICB2YXIgcGF0aExlbmd0aCA9IGxpbmVTdHJpbmdMZW5ndGgocGl4ZWxDb29yZGluYXRlcywgYmVnaW4sIGVuZCwgMik7XG4gICAgICAgICAgdmFyIHRleHRMZW5ndGggPSBNYXRoLmFicyh0ZXh0U2NhbGVbMF0pICogbWVhc3VyZUFuZENhY2hlVGV4dFdpZHRoKGZvbnQsIHRleHQsIGNhY2hlZFdpZHRocyk7XG5cbiAgICAgICAgICBpZiAob3ZlcmZsb3cgfHwgdGV4dExlbmd0aCA8PSBwYXRoTGVuZ3RoKSB7XG4gICAgICAgICAgICB2YXIgdGV4dEFsaWduID0gdGhpcy50ZXh0U3RhdGVzW3RleHRLZXldLnRleHRBbGlnbjtcbiAgICAgICAgICAgIHZhciBzdGFydE0gPSAocGF0aExlbmd0aCAtIHRleHRMZW5ndGgpICogVEVYVF9BTElHTlt0ZXh0QWxpZ25dO1xuICAgICAgICAgICAgdmFyIHBhcnRzID0gZHJhd1RleHRPblBhdGgocGl4ZWxDb29yZGluYXRlcywgYmVnaW4sIGVuZCwgMiwgdGV4dCwgc3RhcnRNLCBtYXhBbmdsZSwgTWF0aC5hYnModGV4dFNjYWxlWzBdKSwgbWVhc3VyZUFuZENhY2hlVGV4dFdpZHRoLCBmb250LCBjYWNoZWRXaWR0aHMsIHZpZXdSb3RhdGlvbkZyb21UcmFuc2Zvcm0gPyAwIDogdGhpcy52aWV3Um90YXRpb25fKTtcblxuICAgICAgICAgICAgZHJhd0NoYXJzOiBpZiAocGFydHMpIHtcbiAgICAgICAgICAgICAgLyoqIEB0eXBlIHtBcnJheTxSZXBsYXlJbWFnZU9yTGFiZWxBcmdzPn0gKi9cbiAgICAgICAgICAgICAgdmFyIHJlcGxheUltYWdlT3JMYWJlbEFyZ3MgPSBbXTtcbiAgICAgICAgICAgICAgdmFyIGMgPSB2b2lkIDAsXG4gICAgICAgICAgICAgICAgICBjYyA9IHZvaWQgMCxcbiAgICAgICAgICAgICAgICAgIGNoYXJzID0gdm9pZCAwLFxuICAgICAgICAgICAgICAgICAgbGFiZWwgPSB2b2lkIDAsXG4gICAgICAgICAgICAgICAgICBwYXJ0ID0gdm9pZCAwO1xuXG4gICAgICAgICAgICAgIGlmIChzdHJva2VLZXkpIHtcbiAgICAgICAgICAgICAgICBmb3IgKGMgPSAwLCBjYyA9IHBhcnRzLmxlbmd0aDsgYyA8IGNjOyArK2MpIHtcbiAgICAgICAgICAgICAgICAgIHBhcnQgPSBwYXJ0c1tjXTsgLy8geCwgeSwgYW5jaG9yWCwgcm90YXRpb24sIGNodW5rXG5cbiAgICAgICAgICAgICAgICAgIGNoYXJzID1cbiAgICAgICAgICAgICAgICAgIC8qKiBAdHlwZSB7c3RyaW5nfSAqL1xuICAgICAgICAgICAgICAgICAgcGFydFs0XTtcbiAgICAgICAgICAgICAgICAgIGxhYmVsID0gdGhpcy5jcmVhdGVMYWJlbChjaGFycywgdGV4dEtleSwgJycsIHN0cm9rZUtleSk7XG4gICAgICAgICAgICAgICAgICBhbmNob3JYID1cbiAgICAgICAgICAgICAgICAgIC8qKiBAdHlwZSB7bnVtYmVyfSAqL1xuICAgICAgICAgICAgICAgICAgcGFydFsyXSArICh0ZXh0U2NhbGVbMF0gPCAwID8gLXN0cm9rZVdpZHRoIDogc3Ryb2tlV2lkdGgpO1xuICAgICAgICAgICAgICAgICAgYW5jaG9yWSA9IGJhc2VsaW5lICogbGFiZWwuaGVpZ2h0ICsgKDAuNSAtIGJhc2VsaW5lKSAqIDIgKiBzdHJva2VXaWR0aCAqIHRleHRTY2FsZVsxXSAvIHRleHRTY2FsZVswXSAtIG9mZnNldFk7XG4gICAgICAgICAgICAgICAgICB2YXIgZGltZW5zaW9ucyA9IHRoaXMuY2FsY3VsYXRlSW1hZ2VPckxhYmVsRGltZW5zaW9uc18obGFiZWwud2lkdGgsIGxhYmVsLmhlaWdodCwgcGFydFswXSwgcGFydFsxXSwgbGFiZWwud2lkdGgsIGxhYmVsLmhlaWdodCwgYW5jaG9yWCwgYW5jaG9yWSwgMCwgMCwgcGFydFszXSwgcGl4ZWxSYXRpb1NjYWxlLCBmYWxzZSwgZGVmYXVsdFBhZGRpbmcsIGZhbHNlLCBmZWF0dXJlKTtcblxuICAgICAgICAgICAgICAgICAgaWYgKG9wdF9kZWNsdXR0ZXJUcmVlICYmIG9wdF9kZWNsdXR0ZXJUcmVlLmNvbGxpZGVzKGRpbWVuc2lvbnMuZGVjbHV0dGVyQm94KSkge1xuICAgICAgICAgICAgICAgICAgICBicmVhayBkcmF3Q2hhcnM7XG4gICAgICAgICAgICAgICAgICB9XG5cbiAgICAgICAgICAgICAgICAgIHJlcGxheUltYWdlT3JMYWJlbEFyZ3MucHVzaChbY29udGV4dCwgY29udGV4dFNjYWxlLCBsYWJlbCwgZGltZW5zaW9ucywgMSwgbnVsbCwgbnVsbF0pO1xuICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICAgIGlmIChmaWxsS2V5KSB7XG4gICAgICAgICAgICAgICAgZm9yIChjID0gMCwgY2MgPSBwYXJ0cy5sZW5ndGg7IGMgPCBjYzsgKytjKSB7XG4gICAgICAgICAgICAgICAgICBwYXJ0ID0gcGFydHNbY107IC8vIHgsIHksIGFuY2hvclgsIHJvdGF0aW9uLCBjaHVua1xuXG4gICAgICAgICAgICAgICAgICBjaGFycyA9XG4gICAgICAgICAgICAgICAgICAvKiogQHR5cGUge3N0cmluZ30gKi9cbiAgICAgICAgICAgICAgICAgIHBhcnRbNF07XG4gICAgICAgICAgICAgICAgICBsYWJlbCA9IHRoaXMuY3JlYXRlTGFiZWwoY2hhcnMsIHRleHRLZXksIGZpbGxLZXksICcnKTtcbiAgICAgICAgICAgICAgICAgIGFuY2hvclggPVxuICAgICAgICAgICAgICAgICAgLyoqIEB0eXBlIHtudW1iZXJ9ICovXG4gICAgICAgICAgICAgICAgICBwYXJ0WzJdO1xuICAgICAgICAgICAgICAgICAgYW5jaG9yWSA9IGJhc2VsaW5lICogbGFiZWwuaGVpZ2h0IC0gb2Zmc2V0WTtcbiAgICAgICAgICAgICAgICAgIHZhciBkaW1lbnNpb25zID0gdGhpcy5jYWxjdWxhdGVJbWFnZU9yTGFiZWxEaW1lbnNpb25zXyhsYWJlbC53aWR0aCwgbGFiZWwuaGVpZ2h0LCBwYXJ0WzBdLCBwYXJ0WzFdLCBsYWJlbC53aWR0aCwgbGFiZWwuaGVpZ2h0LCBhbmNob3JYLCBhbmNob3JZLCAwLCAwLCBwYXJ0WzNdLCBwaXhlbFJhdGlvU2NhbGUsIGZhbHNlLCBkZWZhdWx0UGFkZGluZywgZmFsc2UsIGZlYXR1cmUpO1xuXG4gICAgICAgICAgICAgICAgICBpZiAob3B0X2RlY2x1dHRlclRyZWUgJiYgb3B0X2RlY2x1dHRlclRyZWUuY29sbGlkZXMoZGltZW5zaW9ucy5kZWNsdXR0ZXJCb3gpKSB7XG4gICAgICAgICAgICAgICAgICAgIGJyZWFrIGRyYXdDaGFycztcbiAgICAgICAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgICAgICAgcmVwbGF5SW1hZ2VPckxhYmVsQXJncy5wdXNoKFtjb250ZXh0LCBjb250ZXh0U2NhbGUsIGxhYmVsLCBkaW1lbnNpb25zLCAxLCBudWxsLCBudWxsXSk7XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICB9XG5cbiAgICAgICAgICAgICAgaWYgKG9wdF9kZWNsdXR0ZXJUcmVlKSB7XG4gICAgICAgICAgICAgICAgb3B0X2RlY2x1dHRlclRyZWUubG9hZChyZXBsYXlJbWFnZU9yTGFiZWxBcmdzLm1hcChnZXREZWNsdXR0ZXJCb3gpKTtcbiAgICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICAgIGZvciAodmFyIGlfMSA9IDAsIGlpXzEgPSByZXBsYXlJbWFnZU9yTGFiZWxBcmdzLmxlbmd0aDsgaV8xIDwgaWlfMTsgKytpXzEpIHtcbiAgICAgICAgICAgICAgICB0aGlzLnJlcGxheUltYWdlT3JMYWJlbF8uYXBwbHkodGhpcywgcmVwbGF5SW1hZ2VPckxhYmVsQXJnc1tpXzFdKTtcbiAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgfVxuICAgICAgICAgIH1cblxuICAgICAgICAgICsraTtcbiAgICAgICAgICBicmVhaztcblxuICAgICAgICBjYXNlIENhbnZhc0luc3RydWN0aW9uLkVORF9HRU9NRVRSWTpcbiAgICAgICAgICBpZiAob3B0X2ZlYXR1cmVDYWxsYmFjayAhPT0gdW5kZWZpbmVkKSB7XG4gICAgICAgICAgICBmZWF0dXJlID1cbiAgICAgICAgICAgIC8qKiBAdHlwZSB7aW1wb3J0KFwiLi4vLi4vRmVhdHVyZS5qc1wiKS5GZWF0dXJlTGlrZX0gKi9cbiAgICAgICAgICAgIGluc3RydWN0aW9uWzFdO1xuICAgICAgICAgICAgdmFyIHJlc3VsdCA9IG9wdF9mZWF0dXJlQ2FsbGJhY2soZmVhdHVyZSwgY3VycmVudEdlb21ldHJ5KTtcblxuICAgICAgICAgICAgaWYgKHJlc3VsdCkge1xuICAgICAgICAgICAgICByZXR1cm4gcmVzdWx0O1xuICAgICAgICAgICAgfVxuICAgICAgICAgIH1cblxuICAgICAgICAgICsraTtcbiAgICAgICAgICBicmVhaztcblxuICAgICAgICBjYXNlIENhbnZhc0luc3RydWN0aW9uLkZJTEw6XG4gICAgICAgICAgaWYgKGJhdGNoU2l6ZSkge1xuICAgICAgICAgICAgcGVuZGluZ0ZpbGwrKztcbiAgICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgdGhpcy5maWxsXyhjb250ZXh0KTtcbiAgICAgICAgICB9XG5cbiAgICAgICAgICArK2k7XG4gICAgICAgICAgYnJlYWs7XG5cbiAgICAgICAgY2FzZSBDYW52YXNJbnN0cnVjdGlvbi5NT1ZFX1RPX0xJTkVfVE86XG4gICAgICAgICAgZCA9XG4gICAgICAgICAgLyoqIEB0eXBlIHtudW1iZXJ9ICovXG4gICAgICAgICAgaW5zdHJ1Y3Rpb25bMV07XG4gICAgICAgICAgZGQgPVxuICAgICAgICAgIC8qKiBAdHlwZSB7bnVtYmVyfSAqL1xuICAgICAgICAgIGluc3RydWN0aW9uWzJdO1xuICAgICAgICAgIHggPSBwaXhlbENvb3JkaW5hdGVzW2RdO1xuICAgICAgICAgIHkgPSBwaXhlbENvb3JkaW5hdGVzW2QgKyAxXTtcbiAgICAgICAgICByb3VuZFggPSB4ICsgMC41IHwgMDtcbiAgICAgICAgICByb3VuZFkgPSB5ICsgMC41IHwgMDtcblxuICAgICAgICAgIGlmIChyb3VuZFggIT09IHByZXZYIHx8IHJvdW5kWSAhPT0gcHJldlkpIHtcbiAgICAgICAgICAgIGNvbnRleHQubW92ZVRvKHgsIHkpO1xuICAgICAgICAgICAgcHJldlggPSByb3VuZFg7XG4gICAgICAgICAgICBwcmV2WSA9IHJvdW5kWTtcbiAgICAgICAgICB9XG5cbiAgICAgICAgICBmb3IgKGQgKz0gMjsgZCA8IGRkOyBkICs9IDIpIHtcbiAgICAgICAgICAgIHggPSBwaXhlbENvb3JkaW5hdGVzW2RdO1xuICAgICAgICAgICAgeSA9IHBpeGVsQ29vcmRpbmF0ZXNbZCArIDFdO1xuICAgICAgICAgICAgcm91bmRYID0geCArIDAuNSB8IDA7XG4gICAgICAgICAgICByb3VuZFkgPSB5ICsgMC41IHwgMDtcblxuICAgICAgICAgICAgaWYgKGQgPT0gZGQgLSAyIHx8IHJvdW5kWCAhPT0gcHJldlggfHwgcm91bmRZICE9PSBwcmV2WSkge1xuICAgICAgICAgICAgICBjb250ZXh0LmxpbmVUbyh4LCB5KTtcbiAgICAgICAgICAgICAgcHJldlggPSByb3VuZFg7XG4gICAgICAgICAgICAgIHByZXZZID0gcm91bmRZO1xuICAgICAgICAgICAgfVxuICAgICAgICAgIH1cblxuICAgICAgICAgICsraTtcbiAgICAgICAgICBicmVhaztcblxuICAgICAgICBjYXNlIENhbnZhc0luc3RydWN0aW9uLlNFVF9GSUxMX1NUWUxFOlxuICAgICAgICAgIGxhc3RGaWxsSW5zdHJ1Y3Rpb24gPSBpbnN0cnVjdGlvbjtcbiAgICAgICAgICB0aGlzLmFsaWduRmlsbF8gPSBpbnN0cnVjdGlvblsyXTtcblxuICAgICAgICAgIGlmIChwZW5kaW5nRmlsbCkge1xuICAgICAgICAgICAgdGhpcy5maWxsXyhjb250ZXh0KTtcbiAgICAgICAgICAgIHBlbmRpbmdGaWxsID0gMDtcblxuICAgICAgICAgICAgaWYgKHBlbmRpbmdTdHJva2UpIHtcbiAgICAgICAgICAgICAgY29udGV4dC5zdHJva2UoKTtcbiAgICAgICAgICAgICAgcGVuZGluZ1N0cm9rZSA9IDA7XG4gICAgICAgICAgICB9XG4gICAgICAgICAgfVxuXG4gICAgICAgICAgY29udGV4dC5maWxsU3R5bGUgPVxuICAgICAgICAgIC8qKiBAdHlwZSB7aW1wb3J0KFwiLi4vLi4vY29sb3JsaWtlLmpzXCIpLkNvbG9yTGlrZX0gKi9cbiAgICAgICAgICBpbnN0cnVjdGlvblsxXTtcbiAgICAgICAgICArK2k7XG4gICAgICAgICAgYnJlYWs7XG5cbiAgICAgICAgY2FzZSBDYW52YXNJbnN0cnVjdGlvbi5TRVRfU1RST0tFX1NUWUxFOlxuICAgICAgICAgIGxhc3RTdHJva2VJbnN0cnVjdGlvbiA9IGluc3RydWN0aW9uO1xuXG4gICAgICAgICAgaWYgKHBlbmRpbmdTdHJva2UpIHtcbiAgICAgICAgICAgIGNvbnRleHQuc3Ryb2tlKCk7XG4gICAgICAgICAgICBwZW5kaW5nU3Ryb2tlID0gMDtcbiAgICAgICAgICB9XG5cbiAgICAgICAgICB0aGlzLnNldFN0cm9rZVN0eWxlXyhjb250ZXh0LFxuICAgICAgICAgIC8qKiBAdHlwZSB7QXJyYXk8Kj59ICovXG4gICAgICAgICAgaW5zdHJ1Y3Rpb24pO1xuICAgICAgICAgICsraTtcbiAgICAgICAgICBicmVhaztcblxuICAgICAgICBjYXNlIENhbnZhc0luc3RydWN0aW9uLlNUUk9LRTpcbiAgICAgICAgICBpZiAoYmF0Y2hTaXplKSB7XG4gICAgICAgICAgICBwZW5kaW5nU3Ryb2tlKys7XG4gICAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgIGNvbnRleHQuc3Ryb2tlKCk7XG4gICAgICAgICAgfVxuXG4gICAgICAgICAgKytpO1xuICAgICAgICAgIGJyZWFrO1xuXG4gICAgICAgIGRlZmF1bHQ6XG4gICAgICAgICAgKytpOyAvLyBjb25zdW1lIHRoZSBpbnN0cnVjdGlvbiBhbnl3YXksIHRvIGF2b2lkIGFuIGluZmluaXRlIGxvb3BcblxuICAgICAgICAgIGJyZWFrO1xuICAgICAgfVxuICAgIH1cblxuICAgIGlmIChwZW5kaW5nRmlsbCkge1xuICAgICAgdGhpcy5maWxsXyhjb250ZXh0KTtcbiAgICB9XG5cbiAgICBpZiAocGVuZGluZ1N0cm9rZSkge1xuICAgICAgY29udGV4dC5zdHJva2UoKTtcbiAgICB9XG5cbiAgICByZXR1cm4gdW5kZWZpbmVkO1xuICB9O1xuICAvKipcbiAgICogQHBhcmFtIHtDYW52YXNSZW5kZXJpbmdDb250ZXh0MkR9IGNvbnRleHQgQ29udGV4dC5cbiAgICogQHBhcmFtIHtudW1iZXJ9IGNvbnRleHRTY2FsZSBTY2FsZSBvZiB0aGUgY29udGV4dC5cbiAgICogQHBhcmFtIHtpbXBvcnQoXCIuLi8uLi90cmFuc2Zvcm0uanNcIikuVHJhbnNmb3JtfSB0cmFuc2Zvcm0gVHJhbnNmb3JtLlxuICAgKiBAcGFyYW0ge251bWJlcn0gdmlld1JvdGF0aW9uIFZpZXcgcm90YXRpb24uXG4gICAqIEBwYXJhbSB7Ym9vbGVhbn0gc25hcFRvUGl4ZWwgU25hcCBwb2ludCBzeW1ib2xzIGFuZCB0ZXh0IHRvIGludGVnZXIgcGl4ZWxzLlxuICAgKiBAcGFyYW0ge2ltcG9ydChcInJidXNoXCIpLmRlZmF1bHQ9fSBvcHRfZGVjbHV0dGVyVHJlZSBEZWNsdXR0ZXIgdHJlZS5cbiAgICovXG5cblxuICBFeGVjdXRvci5wcm90b3R5cGUuZXhlY3V0ZSA9IGZ1bmN0aW9uIChjb250ZXh0LCBjb250ZXh0U2NhbGUsIHRyYW5zZm9ybSwgdmlld1JvdGF0aW9uLCBzbmFwVG9QaXhlbCwgb3B0X2RlY2x1dHRlclRyZWUpIHtcbiAgICB0aGlzLnZpZXdSb3RhdGlvbl8gPSB2aWV3Um90YXRpb247XG4gICAgdGhpcy5leGVjdXRlXyhjb250ZXh0LCBjb250ZXh0U2NhbGUsIHRyYW5zZm9ybSwgdGhpcy5pbnN0cnVjdGlvbnMsIHNuYXBUb1BpeGVsLCB1bmRlZmluZWQsIHVuZGVmaW5lZCwgb3B0X2RlY2x1dHRlclRyZWUpO1xuICB9O1xuICAvKipcbiAgICogQHBhcmFtIHtDYW52YXNSZW5kZXJpbmdDb250ZXh0MkR9IGNvbnRleHQgQ29udGV4dC5cbiAgICogQHBhcmFtIHtpbXBvcnQoXCIuLi8uLi90cmFuc2Zvcm0uanNcIikuVHJhbnNmb3JtfSB0cmFuc2Zvcm0gVHJhbnNmb3JtLlxuICAgKiBAcGFyYW0ge251bWJlcn0gdmlld1JvdGF0aW9uIFZpZXcgcm90YXRpb24uXG4gICAqIEBwYXJhbSB7RmVhdHVyZUNhbGxiYWNrPFQ+PX0gb3B0X2ZlYXR1cmVDYWxsYmFjayBGZWF0dXJlIGNhbGxiYWNrLlxuICAgKiBAcGFyYW0ge2ltcG9ydChcIi4uLy4uL2V4dGVudC5qc1wiKS5FeHRlbnQ9fSBvcHRfaGl0RXh0ZW50IE9ubHkgY2hlY2tcbiAgICogICAgIGZlYXR1cmVzIHRoYXQgaW50ZXJzZWN0IHRoaXMgZXh0ZW50LlxuICAgKiBAcmV0dXJuIHtUfHVuZGVmaW5lZH0gQ2FsbGJhY2sgcmVzdWx0LlxuICAgKiBAdGVtcGxhdGUgVFxuICAgKi9cblxuXG4gIEV4ZWN1dG9yLnByb3RvdHlwZS5leGVjdXRlSGl0RGV0ZWN0aW9uID0gZnVuY3Rpb24gKGNvbnRleHQsIHRyYW5zZm9ybSwgdmlld1JvdGF0aW9uLCBvcHRfZmVhdHVyZUNhbGxiYWNrLCBvcHRfaGl0RXh0ZW50KSB7XG4gICAgdGhpcy52aWV3Um90YXRpb25fID0gdmlld1JvdGF0aW9uO1xuICAgIHJldHVybiB0aGlzLmV4ZWN1dGVfKGNvbnRleHQsIDEsIHRyYW5zZm9ybSwgdGhpcy5oaXREZXRlY3Rpb25JbnN0cnVjdGlvbnMsIHRydWUsIG9wdF9mZWF0dXJlQ2FsbGJhY2ssIG9wdF9oaXRFeHRlbnQpO1xuICB9O1xuXG4gIHJldHVybiBFeGVjdXRvcjtcbn0oKTtcblxuZXhwb3J0IGRlZmF1bHQgRXhlY3V0b3I7IiwiLyoqXG4gKiBAbW9kdWxlIG9sL3JlbmRlci9jYW52YXMvRXhlY3V0b3JHcm91cFxuICovXG5pbXBvcnQgQnVpbGRlclR5cGUgZnJvbSAnLi9CdWlsZGVyVHlwZS5qcyc7XG5pbXBvcnQgRXhlY3V0b3IgZnJvbSAnLi9FeGVjdXRvci5qcyc7XG5pbXBvcnQgeyBidWZmZXIsIGNyZWF0ZUVtcHR5LCBleHRlbmRDb29yZGluYXRlIH0gZnJvbSAnLi4vLi4vZXh0ZW50LmpzJztcbmltcG9ydCB7IGNvbXBvc2UgYXMgY29tcG9zZVRyYW5zZm9ybSwgY3JlYXRlIGFzIGNyZWF0ZVRyYW5zZm9ybSB9IGZyb20gJy4uLy4uL3RyYW5zZm9ybS5qcyc7XG5pbXBvcnQgeyBjcmVhdGVDYW52YXNDb250ZXh0MkQgfSBmcm9tICcuLi8uLi9kb20uanMnO1xuaW1wb3J0IHsgaXNFbXB0eSB9IGZyb20gJy4uLy4uL29iai5qcyc7XG5pbXBvcnQgeyBudW1iZXJTYWZlQ29tcGFyZUZ1bmN0aW9uIH0gZnJvbSAnLi4vLi4vYXJyYXkuanMnO1xuaW1wb3J0IHsgdHJhbnNmb3JtMkQgfSBmcm9tICcuLi8uLi9nZW9tL2ZsYXQvdHJhbnNmb3JtLmpzJztcbi8qKlxuICogQGNvbnN0XG4gKiBAdHlwZSB7QXJyYXk8aW1wb3J0KFwiLi9CdWlsZGVyVHlwZS5qc1wiKS5kZWZhdWx0Pn1cbiAqL1xuXG52YXIgT1JERVIgPSBbQnVpbGRlclR5cGUuUE9MWUdPTiwgQnVpbGRlclR5cGUuQ0lSQ0xFLCBCdWlsZGVyVHlwZS5MSU5FX1NUUklORywgQnVpbGRlclR5cGUuSU1BR0UsIEJ1aWxkZXJUeXBlLlRFWFQsIEJ1aWxkZXJUeXBlLkRFRkFVTFRdO1xuXG52YXIgRXhlY3V0b3JHcm91cCA9XG4vKiogQGNsYXNzICovXG5mdW5jdGlvbiAoKSB7XG4gIC8qKlxuICAgKiBAcGFyYW0ge2ltcG9ydChcIi4uLy4uL2V4dGVudC5qc1wiKS5FeHRlbnR9IG1heEV4dGVudCBNYXggZXh0ZW50IGZvciBjbGlwcGluZy4gV2hlbiBhXG4gICAqIGBtYXhFeHRlbnRgIHdhcyBzZXQgb24gdGhlIEJ1aWxsZGVyIGZvciB0aGlzIGV4ZWN1dG9yIGdyb3VwLCB0aGUgc2FtZSBgbWF4RXh0ZW50YFxuICAgKiBzaG91bGQgYmUgc2V0IGhlcmUsIHVubGVzcyB0aGUgdGFyZ2V0IGNvbnRleHQgZG9lcyBub3QgZXhjZWV0IHRoYXQgZXh0ZW50ICh3aGljaFxuICAgKiBjYW4gYmUgdGhlIGNhc2Ugd2hlbiByZW5kZXJpbmcgdG8gdGlsZXMpLlxuICAgKiBAcGFyYW0ge251bWJlcn0gcmVzb2x1dGlvbiBSZXNvbHV0aW9uLlxuICAgKiBAcGFyYW0ge251bWJlcn0gcGl4ZWxSYXRpbyBQaXhlbCByYXRpby5cbiAgICogQHBhcmFtIHtib29sZWFufSBvdmVybGFwcyBUaGUgZXhlY3V0b3IgZ3JvdXAgY2FuIGhhdmUgb3ZlcmxhcHBpbmcgZ2VvbWV0cmllcy5cbiAgICogQHBhcmFtIHshT2JqZWN0PHN0cmluZywgIU9iamVjdDxpbXBvcnQoXCIuL0J1aWxkZXJUeXBlLmpzXCIpLmRlZmF1bHQsIGltcG9ydChcIi4uL2NhbnZhcy5qc1wiKS5TZXJpYWxpemFibGVJbnN0cnVjdGlvbnM+Pn0gYWxsSW5zdHJ1Y3Rpb25zXG4gICAqIFRoZSBzZXJpYWxpemFibGUgaW5zdHJ1Y3Rpb25zLlxuICAgKiBAcGFyYW0ge251bWJlcj19IG9wdF9yZW5kZXJCdWZmZXIgT3B0aW9uYWwgcmVuZGVyaW5nIGJ1ZmZlci5cbiAgICovXG4gIGZ1bmN0aW9uIEV4ZWN1dG9yR3JvdXAobWF4RXh0ZW50LCByZXNvbHV0aW9uLCBwaXhlbFJhdGlvLCBvdmVybGFwcywgYWxsSW5zdHJ1Y3Rpb25zLCBvcHRfcmVuZGVyQnVmZmVyKSB7XG4gICAgLyoqXG4gICAgICogQHByaXZhdGVcbiAgICAgKiBAdHlwZSB7aW1wb3J0KFwiLi4vLi4vZXh0ZW50LmpzXCIpLkV4dGVudH1cbiAgICAgKi9cbiAgICB0aGlzLm1heEV4dGVudF8gPSBtYXhFeHRlbnQ7XG4gICAgLyoqXG4gICAgICogQHByaXZhdGVcbiAgICAgKiBAdHlwZSB7Ym9vbGVhbn1cbiAgICAgKi9cblxuICAgIHRoaXMub3ZlcmxhcHNfID0gb3ZlcmxhcHM7XG4gICAgLyoqXG4gICAgICogQHByaXZhdGVcbiAgICAgKiBAdHlwZSB7bnVtYmVyfVxuICAgICAqL1xuXG4gICAgdGhpcy5waXhlbFJhdGlvXyA9IHBpeGVsUmF0aW87XG4gICAgLyoqXG4gICAgICogQHByaXZhdGVcbiAgICAgKiBAdHlwZSB7bnVtYmVyfVxuICAgICAqL1xuXG4gICAgdGhpcy5yZXNvbHV0aW9uXyA9IHJlc29sdXRpb247XG4gICAgLyoqXG4gICAgICogQHByaXZhdGVcbiAgICAgKiBAdHlwZSB7bnVtYmVyfHVuZGVmaW5lZH1cbiAgICAgKi9cblxuICAgIHRoaXMucmVuZGVyQnVmZmVyXyA9IG9wdF9yZW5kZXJCdWZmZXI7XG4gICAgLyoqXG4gICAgICogQHByaXZhdGVcbiAgICAgKiBAdHlwZSB7IU9iamVjdDxzdHJpbmcsICFPYmplY3Q8aW1wb3J0KFwiLi9CdWlsZGVyVHlwZS5qc1wiKS5kZWZhdWx0LCBpbXBvcnQoXCIuL0V4ZWN1dG9yXCIpLmRlZmF1bHQ+Pn1cbiAgICAgKi9cblxuICAgIHRoaXMuZXhlY3V0b3JzQnlaSW5kZXhfID0ge307XG4gICAgLyoqXG4gICAgICogQHByaXZhdGVcbiAgICAgKiBAdHlwZSB7Q2FudmFzUmVuZGVyaW5nQ29udGV4dDJEfVxuICAgICAqL1xuXG4gICAgdGhpcy5oaXREZXRlY3Rpb25Db250ZXh0XyA9IG51bGw7XG4gICAgLyoqXG4gICAgICogQHByaXZhdGVcbiAgICAgKiBAdHlwZSB7aW1wb3J0KFwiLi4vLi4vdHJhbnNmb3JtLmpzXCIpLlRyYW5zZm9ybX1cbiAgICAgKi9cblxuICAgIHRoaXMuaGl0RGV0ZWN0aW9uVHJhbnNmb3JtXyA9IGNyZWF0ZVRyYW5zZm9ybSgpO1xuICAgIHRoaXMuY3JlYXRlRXhlY3V0b3JzXyhhbGxJbnN0cnVjdGlvbnMpO1xuICB9XG4gIC8qKlxuICAgKiBAcGFyYW0ge0NhbnZhc1JlbmRlcmluZ0NvbnRleHQyRH0gY29udGV4dCBDb250ZXh0LlxuICAgKiBAcGFyYW0ge2ltcG9ydChcIi4uLy4uL3RyYW5zZm9ybS5qc1wiKS5UcmFuc2Zvcm19IHRyYW5zZm9ybSBUcmFuc2Zvcm0uXG4gICAqL1xuXG5cbiAgRXhlY3V0b3JHcm91cC5wcm90b3R5cGUuY2xpcCA9IGZ1bmN0aW9uIChjb250ZXh0LCB0cmFuc2Zvcm0pIHtcbiAgICB2YXIgZmxhdENsaXBDb29yZHMgPSB0aGlzLmdldENsaXBDb29yZHModHJhbnNmb3JtKTtcbiAgICBjb250ZXh0LmJlZ2luUGF0aCgpO1xuICAgIGNvbnRleHQubW92ZVRvKGZsYXRDbGlwQ29vcmRzWzBdLCBmbGF0Q2xpcENvb3Jkc1sxXSk7XG4gICAgY29udGV4dC5saW5lVG8oZmxhdENsaXBDb29yZHNbMl0sIGZsYXRDbGlwQ29vcmRzWzNdKTtcbiAgICBjb250ZXh0LmxpbmVUbyhmbGF0Q2xpcENvb3Jkc1s0XSwgZmxhdENsaXBDb29yZHNbNV0pO1xuICAgIGNvbnRleHQubGluZVRvKGZsYXRDbGlwQ29vcmRzWzZdLCBmbGF0Q2xpcENvb3Jkc1s3XSk7XG4gICAgY29udGV4dC5jbGlwKCk7XG4gIH07XG4gIC8qKlxuICAgKiBDcmVhdGUgZXhlY3V0b3JzIGFuZCBwb3B1bGF0ZSB0aGVtIHVzaW5nIHRoZSBwcm92aWRlZCBpbnN0cnVjdGlvbnMuXG4gICAqIEBwcml2YXRlXG4gICAqIEBwYXJhbSB7IU9iamVjdDxzdHJpbmcsICFPYmplY3Q8aW1wb3J0KFwiLi9CdWlsZGVyVHlwZS5qc1wiKS5kZWZhdWx0LCBpbXBvcnQoXCIuLi9jYW52YXMuanNcIikuU2VyaWFsaXphYmxlSW5zdHJ1Y3Rpb25zPj59IGFsbEluc3RydWN0aW9ucyBUaGUgc2VyaWFsaXphYmxlIGluc3RydWN0aW9uc1xuICAgKi9cblxuXG4gIEV4ZWN1dG9yR3JvdXAucHJvdG90eXBlLmNyZWF0ZUV4ZWN1dG9yc18gPSBmdW5jdGlvbiAoYWxsSW5zdHJ1Y3Rpb25zKSB7XG4gICAgZm9yICh2YXIgekluZGV4IGluIGFsbEluc3RydWN0aW9ucykge1xuICAgICAgdmFyIGV4ZWN1dG9ycyA9IHRoaXMuZXhlY3V0b3JzQnlaSW5kZXhfW3pJbmRleF07XG5cbiAgICAgIGlmIChleGVjdXRvcnMgPT09IHVuZGVmaW5lZCkge1xuICAgICAgICBleGVjdXRvcnMgPSB7fTtcbiAgICAgICAgdGhpcy5leGVjdXRvcnNCeVpJbmRleF9bekluZGV4XSA9IGV4ZWN1dG9ycztcbiAgICAgIH1cblxuICAgICAgdmFyIGluc3RydWN0aW9uQnlaaW5kZXggPSBhbGxJbnN0cnVjdGlvbnNbekluZGV4XTtcbiAgICAgIHZhciByZW5kZXJCdWZmZXIgPSBbdGhpcy5yZW5kZXJCdWZmZXJfIHx8IDAsIHRoaXMucmVuZGVyQnVmZmVyXyB8fCAwXTtcblxuICAgICAgZm9yICh2YXIgYnVpbGRlclR5cGUgaW4gaW5zdHJ1Y3Rpb25CeVppbmRleCkge1xuICAgICAgICB2YXIgaW5zdHJ1Y3Rpb25zID0gaW5zdHJ1Y3Rpb25CeVppbmRleFtidWlsZGVyVHlwZV07XG4gICAgICAgIGV4ZWN1dG9yc1tidWlsZGVyVHlwZV0gPSBuZXcgRXhlY3V0b3IodGhpcy5yZXNvbHV0aW9uXywgdGhpcy5waXhlbFJhdGlvXywgdGhpcy5vdmVybGFwc18sIGluc3RydWN0aW9ucywgcmVuZGVyQnVmZmVyKTtcbiAgICAgIH1cbiAgICB9XG4gIH07XG4gIC8qKlxuICAgKiBAcGFyYW0ge0FycmF5PGltcG9ydChcIi4vQnVpbGRlclR5cGUuanNcIikuZGVmYXVsdD59IGV4ZWN1dG9ycyBFeGVjdXRvcnMuXG4gICAqIEByZXR1cm4ge2Jvb2xlYW59IEhhcyBleGVjdXRvcnMgb2YgdGhlIHByb3ZpZGVkIHR5cGVzLlxuICAgKi9cblxuXG4gIEV4ZWN1dG9yR3JvdXAucHJvdG90eXBlLmhhc0V4ZWN1dG9ycyA9IGZ1bmN0aW9uIChleGVjdXRvcnMpIHtcbiAgICBmb3IgKHZhciB6SW5kZXggaW4gdGhpcy5leGVjdXRvcnNCeVpJbmRleF8pIHtcbiAgICAgIHZhciBjYW5kaWRhdGVzID0gdGhpcy5leGVjdXRvcnNCeVpJbmRleF9bekluZGV4XTtcblxuICAgICAgZm9yICh2YXIgaSA9IDAsIGlpID0gZXhlY3V0b3JzLmxlbmd0aDsgaSA8IGlpOyArK2kpIHtcbiAgICAgICAgaWYgKGV4ZWN1dG9yc1tpXSBpbiBjYW5kaWRhdGVzKSB7XG4gICAgICAgICAgcmV0dXJuIHRydWU7XG4gICAgICAgIH1cbiAgICAgIH1cbiAgICB9XG5cbiAgICByZXR1cm4gZmFsc2U7XG4gIH07XG4gIC8qKlxuICAgKiBAcGFyYW0ge2ltcG9ydChcIi4uLy4uL2Nvb3JkaW5hdGUuanNcIikuQ29vcmRpbmF0ZX0gY29vcmRpbmF0ZSBDb29yZGluYXRlLlxuICAgKiBAcGFyYW0ge251bWJlcn0gcmVzb2x1dGlvbiBSZXNvbHV0aW9uLlxuICAgKiBAcGFyYW0ge251bWJlcn0gcm90YXRpb24gUm90YXRpb24uXG4gICAqIEBwYXJhbSB7bnVtYmVyfSBoaXRUb2xlcmFuY2UgSGl0IHRvbGVyYW5jZSBpbiBwaXhlbHMuXG4gICAqIEBwYXJhbSB7ZnVuY3Rpb24oaW1wb3J0KFwiLi4vLi4vRmVhdHVyZS5qc1wiKS5GZWF0dXJlTGlrZSwgaW1wb3J0KFwiLi4vLi4vZ2VvbS9TaW1wbGVHZW9tZXRyeS5qc1wiKS5kZWZhdWx0LCBudW1iZXIpOiBUfSBjYWxsYmFjayBGZWF0dXJlIGNhbGxiYWNrLlxuICAgKiBAcGFyYW0ge0FycmF5PGltcG9ydChcIi4uLy4uL0ZlYXR1cmUuanNcIikuRmVhdHVyZUxpa2U+fSBkZWNsdXR0ZXJlZEZlYXR1cmVzIERlY2x1dHRlcmVkIGZlYXR1cmVzLlxuICAgKiBAcmV0dXJuIHtUfHVuZGVmaW5lZH0gQ2FsbGJhY2sgcmVzdWx0LlxuICAgKiBAdGVtcGxhdGUgVFxuICAgKi9cblxuXG4gIEV4ZWN1dG9yR3JvdXAucHJvdG90eXBlLmZvckVhY2hGZWF0dXJlQXRDb29yZGluYXRlID0gZnVuY3Rpb24gKGNvb3JkaW5hdGUsIHJlc29sdXRpb24sIHJvdGF0aW9uLCBoaXRUb2xlcmFuY2UsIGNhbGxiYWNrLCBkZWNsdXR0ZXJlZEZlYXR1cmVzKSB7XG4gICAgaGl0VG9sZXJhbmNlID0gTWF0aC5yb3VuZChoaXRUb2xlcmFuY2UpO1xuICAgIHZhciBjb250ZXh0U2l6ZSA9IGhpdFRvbGVyYW5jZSAqIDIgKyAxO1xuICAgIHZhciB0cmFuc2Zvcm0gPSBjb21wb3NlVHJhbnNmb3JtKHRoaXMuaGl0RGV0ZWN0aW9uVHJhbnNmb3JtXywgaGl0VG9sZXJhbmNlICsgMC41LCBoaXRUb2xlcmFuY2UgKyAwLjUsIDEgLyByZXNvbHV0aW9uLCAtMSAvIHJlc29sdXRpb24sIC1yb3RhdGlvbiwgLWNvb3JkaW5hdGVbMF0sIC1jb29yZGluYXRlWzFdKTtcbiAgICB2YXIgbmV3Q29udGV4dCA9ICF0aGlzLmhpdERldGVjdGlvbkNvbnRleHRfO1xuXG4gICAgaWYgKG5ld0NvbnRleHQpIHtcbiAgICAgIHRoaXMuaGl0RGV0ZWN0aW9uQ29udGV4dF8gPSBjcmVhdGVDYW52YXNDb250ZXh0MkQoY29udGV4dFNpemUsIGNvbnRleHRTaXplKTtcbiAgICB9XG5cbiAgICB2YXIgY29udGV4dCA9IHRoaXMuaGl0RGV0ZWN0aW9uQ29udGV4dF87XG5cbiAgICBpZiAoY29udGV4dC5jYW52YXMud2lkdGggIT09IGNvbnRleHRTaXplIHx8IGNvbnRleHQuY2FudmFzLmhlaWdodCAhPT0gY29udGV4dFNpemUpIHtcbiAgICAgIGNvbnRleHQuY2FudmFzLndpZHRoID0gY29udGV4dFNpemU7XG4gICAgICBjb250ZXh0LmNhbnZhcy5oZWlnaHQgPSBjb250ZXh0U2l6ZTtcbiAgICB9IGVsc2UgaWYgKCFuZXdDb250ZXh0KSB7XG4gICAgICBjb250ZXh0LmNsZWFyUmVjdCgwLCAwLCBjb250ZXh0U2l6ZSwgY29udGV4dFNpemUpO1xuICAgIH1cbiAgICAvKipcbiAgICAgKiBAdHlwZSB7aW1wb3J0KFwiLi4vLi4vZXh0ZW50LmpzXCIpLkV4dGVudH1cbiAgICAgKi9cblxuXG4gICAgdmFyIGhpdEV4dGVudDtcblxuICAgIGlmICh0aGlzLnJlbmRlckJ1ZmZlcl8gIT09IHVuZGVmaW5lZCkge1xuICAgICAgaGl0RXh0ZW50ID0gY3JlYXRlRW1wdHkoKTtcbiAgICAgIGV4dGVuZENvb3JkaW5hdGUoaGl0RXh0ZW50LCBjb29yZGluYXRlKTtcbiAgICAgIGJ1ZmZlcihoaXRFeHRlbnQsIHJlc29sdXRpb24gKiAodGhpcy5yZW5kZXJCdWZmZXJfICsgaGl0VG9sZXJhbmNlKSwgaGl0RXh0ZW50KTtcbiAgICB9XG5cbiAgICB2YXIgaW5kZXhlcyA9IGdldFBpeGVsSW5kZXhBcnJheShoaXRUb2xlcmFuY2UpO1xuICAgIHZhciBidWlsZGVyVHlwZTtcbiAgICAvKipcbiAgICAgKiBAcGFyYW0ge2ltcG9ydChcIi4uLy4uL0ZlYXR1cmUuanNcIikuRmVhdHVyZUxpa2V9IGZlYXR1cmUgRmVhdHVyZS5cbiAgICAgKiBAcGFyYW0ge2ltcG9ydChcIi4uLy4uL2dlb20vU2ltcGxlR2VvbWV0cnkuanNcIikuZGVmYXVsdH0gZ2VvbWV0cnkgR2VvbWV0cnkuXG4gICAgICogQHJldHVybiB7VHx1bmRlZmluZWR9IENhbGxiYWNrIHJlc3VsdC5cbiAgICAgKi9cblxuICAgIGZ1bmN0aW9uIGZlYXR1cmVDYWxsYmFjayhmZWF0dXJlLCBnZW9tZXRyeSkge1xuICAgICAgdmFyIGltYWdlRGF0YSA9IGNvbnRleHQuZ2V0SW1hZ2VEYXRhKDAsIDAsIGNvbnRleHRTaXplLCBjb250ZXh0U2l6ZSkuZGF0YTtcblxuICAgICAgZm9yICh2YXIgaV8xID0gMCwgaWkgPSBpbmRleGVzLmxlbmd0aDsgaV8xIDwgaWk7IGlfMSsrKSB7XG4gICAgICAgIGlmIChpbWFnZURhdGFbaW5kZXhlc1tpXzFdXSA+IDApIHtcbiAgICAgICAgICBpZiAoIWRlY2x1dHRlcmVkRmVhdHVyZXMgfHwgYnVpbGRlclR5cGUgIT09IEJ1aWxkZXJUeXBlLklNQUdFICYmIGJ1aWxkZXJUeXBlICE9PSBCdWlsZGVyVHlwZS5URVhUIHx8IGRlY2x1dHRlcmVkRmVhdHVyZXMuaW5kZXhPZihmZWF0dXJlKSAhPT0gLTEpIHtcbiAgICAgICAgICAgIHZhciBpZHggPSAoaW5kZXhlc1tpXzFdIC0gMykgLyA0O1xuICAgICAgICAgICAgdmFyIHggPSBoaXRUb2xlcmFuY2UgLSBpZHggJSBjb250ZXh0U2l6ZTtcbiAgICAgICAgICAgIHZhciB5ID0gaGl0VG9sZXJhbmNlIC0gKGlkeCAvIGNvbnRleHRTaXplIHwgMCk7XG4gICAgICAgICAgICB2YXIgcmVzdWx0XzEgPSBjYWxsYmFjayhmZWF0dXJlLCBnZW9tZXRyeSwgeCAqIHggKyB5ICogeSk7XG5cbiAgICAgICAgICAgIGlmIChyZXN1bHRfMSkge1xuICAgICAgICAgICAgICByZXR1cm4gcmVzdWx0XzE7XG4gICAgICAgICAgICB9XG4gICAgICAgICAgfVxuXG4gICAgICAgICAgY29udGV4dC5jbGVhclJlY3QoMCwgMCwgY29udGV4dFNpemUsIGNvbnRleHRTaXplKTtcbiAgICAgICAgICBicmVhaztcbiAgICAgICAgfVxuICAgICAgfVxuXG4gICAgICByZXR1cm4gdW5kZWZpbmVkO1xuICAgIH1cbiAgICAvKiogQHR5cGUge0FycmF5PG51bWJlcj59ICovXG5cblxuICAgIHZhciB6cyA9IE9iamVjdC5rZXlzKHRoaXMuZXhlY3V0b3JzQnlaSW5kZXhfKS5tYXAoTnVtYmVyKTtcbiAgICB6cy5zb3J0KG51bWJlclNhZmVDb21wYXJlRnVuY3Rpb24pO1xuICAgIHZhciBpLCBqLCBleGVjdXRvcnMsIGV4ZWN1dG9yLCByZXN1bHQ7XG5cbiAgICBmb3IgKGkgPSB6cy5sZW5ndGggLSAxOyBpID49IDA7IC0taSkge1xuICAgICAgdmFyIHpJbmRleEtleSA9IHpzW2ldLnRvU3RyaW5nKCk7XG4gICAgICBleGVjdXRvcnMgPSB0aGlzLmV4ZWN1dG9yc0J5WkluZGV4X1t6SW5kZXhLZXldO1xuXG4gICAgICBmb3IgKGogPSBPUkRFUi5sZW5ndGggLSAxOyBqID49IDA7IC0taikge1xuICAgICAgICBidWlsZGVyVHlwZSA9IE9SREVSW2pdO1xuICAgICAgICBleGVjdXRvciA9IGV4ZWN1dG9yc1tidWlsZGVyVHlwZV07XG5cbiAgICAgICAgaWYgKGV4ZWN1dG9yICE9PSB1bmRlZmluZWQpIHtcbiAgICAgICAgICByZXN1bHQgPSBleGVjdXRvci5leGVjdXRlSGl0RGV0ZWN0aW9uKGNvbnRleHQsIHRyYW5zZm9ybSwgcm90YXRpb24sIGZlYXR1cmVDYWxsYmFjaywgaGl0RXh0ZW50KTtcblxuICAgICAgICAgIGlmIChyZXN1bHQpIHtcbiAgICAgICAgICAgIHJldHVybiByZXN1bHQ7XG4gICAgICAgICAgfVxuICAgICAgICB9XG4gICAgICB9XG4gICAgfVxuXG4gICAgcmV0dXJuIHVuZGVmaW5lZDtcbiAgfTtcbiAgLyoqXG4gICAqIEBwYXJhbSB7aW1wb3J0KFwiLi4vLi4vdHJhbnNmb3JtLmpzXCIpLlRyYW5zZm9ybX0gdHJhbnNmb3JtIFRyYW5zZm9ybS5cbiAgICogQHJldHVybiB7QXJyYXk8bnVtYmVyPn0gQ2xpcCBjb29yZGluYXRlcy5cbiAgICovXG5cblxuICBFeGVjdXRvckdyb3VwLnByb3RvdHlwZS5nZXRDbGlwQ29vcmRzID0gZnVuY3Rpb24gKHRyYW5zZm9ybSkge1xuICAgIHZhciBtYXhFeHRlbnQgPSB0aGlzLm1heEV4dGVudF87XG5cbiAgICBpZiAoIW1heEV4dGVudCkge1xuICAgICAgcmV0dXJuIG51bGw7XG4gICAgfVxuXG4gICAgdmFyIG1pblggPSBtYXhFeHRlbnRbMF07XG4gICAgdmFyIG1pblkgPSBtYXhFeHRlbnRbMV07XG4gICAgdmFyIG1heFggPSBtYXhFeHRlbnRbMl07XG4gICAgdmFyIG1heFkgPSBtYXhFeHRlbnRbM107XG4gICAgdmFyIGZsYXRDbGlwQ29vcmRzID0gW21pblgsIG1pblksIG1pblgsIG1heFksIG1heFgsIG1heFksIG1heFgsIG1pblldO1xuICAgIHRyYW5zZm9ybTJEKGZsYXRDbGlwQ29vcmRzLCAwLCA4LCAyLCB0cmFuc2Zvcm0sIGZsYXRDbGlwQ29vcmRzKTtcbiAgICByZXR1cm4gZmxhdENsaXBDb29yZHM7XG4gIH07XG4gIC8qKlxuICAgKiBAcmV0dXJuIHtib29sZWFufSBJcyBlbXB0eS5cbiAgICovXG5cblxuICBFeGVjdXRvckdyb3VwLnByb3RvdHlwZS5pc0VtcHR5ID0gZnVuY3Rpb24gKCkge1xuICAgIHJldHVybiBpc0VtcHR5KHRoaXMuZXhlY3V0b3JzQnlaSW5kZXhfKTtcbiAgfTtcbiAgLyoqXG4gICAqIEBwYXJhbSB7Q2FudmFzUmVuZGVyaW5nQ29udGV4dDJEfSBjb250ZXh0IENvbnRleHQuXG4gICAqIEBwYXJhbSB7bnVtYmVyfSBjb250ZXh0U2NhbGUgU2NhbGUgb2YgdGhlIGNvbnRleHQuXG4gICAqIEBwYXJhbSB7aW1wb3J0KFwiLi4vLi4vdHJhbnNmb3JtLmpzXCIpLlRyYW5zZm9ybX0gdHJhbnNmb3JtIFRyYW5zZm9ybS5cbiAgICogQHBhcmFtIHtudW1iZXJ9IHZpZXdSb3RhdGlvbiBWaWV3IHJvdGF0aW9uLlxuICAgKiBAcGFyYW0ge2Jvb2xlYW59IHNuYXBUb1BpeGVsIFNuYXAgcG9pbnQgc3ltYm9scyBhbmQgdGVzdCB0byBpbnRlZ2VyIHBpeGVsLlxuICAgKiBAcGFyYW0ge0FycmF5PGltcG9ydChcIi4vQnVpbGRlclR5cGUuanNcIikuZGVmYXVsdD49fSBvcHRfYnVpbGRlclR5cGVzIE9yZGVyZWQgcmVwbGF5IHR5cGVzIHRvIHJlcGxheS5cbiAgICogICAgIERlZmF1bHQgaXMge0BsaW5rIG1vZHVsZTpvbC9yZW5kZXIvcmVwbGF5fk9SREVSfVxuICAgKiBAcGFyYW0ge2ltcG9ydChcInJidXNoXCIpLmRlZmF1bHQ9fSBvcHRfZGVjbHV0dGVyVHJlZSBEZWNsdXR0ZXIgdHJlZS5cbiAgICovXG5cblxuICBFeGVjdXRvckdyb3VwLnByb3RvdHlwZS5leGVjdXRlID0gZnVuY3Rpb24gKGNvbnRleHQsIGNvbnRleHRTY2FsZSwgdHJhbnNmb3JtLCB2aWV3Um90YXRpb24sIHNuYXBUb1BpeGVsLCBvcHRfYnVpbGRlclR5cGVzLCBvcHRfZGVjbHV0dGVyVHJlZSkge1xuICAgIC8qKiBAdHlwZSB7QXJyYXk8bnVtYmVyPn0gKi9cbiAgICB2YXIgenMgPSBPYmplY3Qua2V5cyh0aGlzLmV4ZWN1dG9yc0J5WkluZGV4XykubWFwKE51bWJlcik7XG4gICAgenMuc29ydChudW1iZXJTYWZlQ29tcGFyZUZ1bmN0aW9uKTsgLy8gc2V0dXAgY2xpcHBpbmcgc28gdGhhdCB0aGUgcGFydHMgb2Ygb3Zlci1zaW1wbGlmaWVkIGdlb21ldHJpZXMgYXJlIG5vdFxuICAgIC8vIHZpc2libGUgb3V0c2lkZSB0aGUgY3VycmVudCBleHRlbnQgd2hlbiBwYW5uaW5nXG5cbiAgICBpZiAodGhpcy5tYXhFeHRlbnRfKSB7XG4gICAgICBjb250ZXh0LnNhdmUoKTtcbiAgICAgIHRoaXMuY2xpcChjb250ZXh0LCB0cmFuc2Zvcm0pO1xuICAgIH1cblxuICAgIHZhciBidWlsZGVyVHlwZXMgPSBvcHRfYnVpbGRlclR5cGVzID8gb3B0X2J1aWxkZXJUeXBlcyA6IE9SREVSO1xuICAgIHZhciBpLCBpaSwgaiwgamosIHJlcGxheXMsIHJlcGxheTtcblxuICAgIGlmIChvcHRfZGVjbHV0dGVyVHJlZSkge1xuICAgICAgenMucmV2ZXJzZSgpO1xuICAgIH1cblxuICAgIGZvciAoaSA9IDAsIGlpID0genMubGVuZ3RoOyBpIDwgaWk7ICsraSkge1xuICAgICAgdmFyIHpJbmRleEtleSA9IHpzW2ldLnRvU3RyaW5nKCk7XG4gICAgICByZXBsYXlzID0gdGhpcy5leGVjdXRvcnNCeVpJbmRleF9bekluZGV4S2V5XTtcblxuICAgICAgZm9yIChqID0gMCwgamogPSBidWlsZGVyVHlwZXMubGVuZ3RoOyBqIDwgamo7ICsraikge1xuICAgICAgICB2YXIgYnVpbGRlclR5cGUgPSBidWlsZGVyVHlwZXNbal07XG4gICAgICAgIHJlcGxheSA9IHJlcGxheXNbYnVpbGRlclR5cGVdO1xuXG4gICAgICAgIGlmIChyZXBsYXkgIT09IHVuZGVmaW5lZCkge1xuICAgICAgICAgIHJlcGxheS5leGVjdXRlKGNvbnRleHQsIGNvbnRleHRTY2FsZSwgdHJhbnNmb3JtLCB2aWV3Um90YXRpb24sIHNuYXBUb1BpeGVsLCBvcHRfZGVjbHV0dGVyVHJlZSk7XG4gICAgICAgIH1cbiAgICAgIH1cbiAgICB9XG5cbiAgICBpZiAodGhpcy5tYXhFeHRlbnRfKSB7XG4gICAgICBjb250ZXh0LnJlc3RvcmUoKTtcbiAgICB9XG4gIH07XG5cbiAgcmV0dXJuIEV4ZWN1dG9yR3JvdXA7XG59KCk7XG4vKipcbiAqIFRoaXMgY2FjaGUgaXMgdXNlZCB0byBzdG9yZSBhcnJheXMgb2YgaW5kZXhlcyBmb3IgY2FsY3VsYXRlZCBwaXhlbCBjaXJjbGVzXG4gKiB0byBpbmNyZWFzZSBwZXJmb3JtYW5jZS5cbiAqIEl0IGlzIGEgc3RhdGljIHByb3BlcnR5IHRvIGFsbG93IGVhY2ggUmVwbGF5Z3JvdXAgdG8gYWNjZXNzIGl0LlxuICogQHR5cGUge09iamVjdDxudW1iZXIsIEFycmF5PG51bWJlcj4+fVxuICovXG5cblxudmFyIGNpcmNsZVBpeGVsSW5kZXhBcnJheUNhY2hlID0ge307XG4vKipcbiAqIFRoaXMgbWV0aG9kcyBjcmVhdGVzIGFuIGFycmF5IHdpdGggaW5kZXhlcyBvZiBhbGwgcGl4ZWxzIHdpdGhpbiBhIGNpcmNsZSxcbiAqIG9yZGVyZWQgYnkgaG93IGNsb3NlIHRoZXkgYXJlIHRvIHRoZSBjZW50ZXIuXG4gKiBBIGNhY2hlIGlzIHVzZWQgdG8gaW5jcmVhc2UgcGVyZm9ybWFuY2UuXG4gKiBAcGFyYW0ge251bWJlcn0gcmFkaXVzIFJhZGl1cy5cbiAqIEByZXR1cm5zIHtBcnJheTxudW1iZXI+fSBBbiBhcnJheSB3aXRoIGluZGV4ZXMgd2l0aGluIGEgY2lyY2xlLlxuICovXG5cbmV4cG9ydCBmdW5jdGlvbiBnZXRQaXhlbEluZGV4QXJyYXkocmFkaXVzKSB7XG4gIGlmIChjaXJjbGVQaXhlbEluZGV4QXJyYXlDYWNoZVtyYWRpdXNdICE9PSB1bmRlZmluZWQpIHtcbiAgICByZXR1cm4gY2lyY2xlUGl4ZWxJbmRleEFycmF5Q2FjaGVbcmFkaXVzXTtcbiAgfVxuXG4gIHZhciBzaXplID0gcmFkaXVzICogMiArIDE7XG4gIHZhciBtYXhEaXN0YW5jZVNxID0gcmFkaXVzICogcmFkaXVzO1xuICB2YXIgZGlzdGFuY2VzID0gbmV3IEFycmF5KG1heERpc3RhbmNlU3EgKyAxKTtcblxuICBmb3IgKHZhciBpID0gMDsgaSA8PSByYWRpdXM7ICsraSkge1xuICAgIGZvciAodmFyIGogPSAwOyBqIDw9IHJhZGl1czsgKytqKSB7XG4gICAgICB2YXIgZGlzdGFuY2VTcSA9IGkgKiBpICsgaiAqIGo7XG5cbiAgICAgIGlmIChkaXN0YW5jZVNxID4gbWF4RGlzdGFuY2VTcSkge1xuICAgICAgICBicmVhaztcbiAgICAgIH1cblxuICAgICAgdmFyIGRpc3RhbmNlID0gZGlzdGFuY2VzW2Rpc3RhbmNlU3FdO1xuXG4gICAgICBpZiAoIWRpc3RhbmNlKSB7XG4gICAgICAgIGRpc3RhbmNlID0gW107XG4gICAgICAgIGRpc3RhbmNlc1tkaXN0YW5jZVNxXSA9IGRpc3RhbmNlO1xuICAgICAgfVxuXG4gICAgICBkaXN0YW5jZS5wdXNoKCgocmFkaXVzICsgaSkgKiBzaXplICsgKHJhZGl1cyArIGopKSAqIDQgKyAzKTtcblxuICAgICAgaWYgKGkgPiAwKSB7XG4gICAgICAgIGRpc3RhbmNlLnB1c2goKChyYWRpdXMgLSBpKSAqIHNpemUgKyAocmFkaXVzICsgaikpICogNCArIDMpO1xuICAgICAgfVxuXG4gICAgICBpZiAoaiA+IDApIHtcbiAgICAgICAgZGlzdGFuY2UucHVzaCgoKHJhZGl1cyArIGkpICogc2l6ZSArIChyYWRpdXMgLSBqKSkgKiA0ICsgMyk7XG5cbiAgICAgICAgaWYgKGkgPiAwKSB7XG4gICAgICAgICAgZGlzdGFuY2UucHVzaCgoKHJhZGl1cyAtIGkpICogc2l6ZSArIChyYWRpdXMgLSBqKSkgKiA0ICsgMyk7XG4gICAgICAgIH1cbiAgICAgIH1cbiAgICB9XG4gIH1cblxuICB2YXIgcGl4ZWxJbmRleCA9IFtdO1xuXG4gIGZvciAodmFyIGkgPSAwLCBpaSA9IGRpc3RhbmNlcy5sZW5ndGg7IGkgPCBpaTsgKytpKSB7XG4gICAgaWYgKGRpc3RhbmNlc1tpXSkge1xuICAgICAgcGl4ZWxJbmRleC5wdXNoLmFwcGx5KHBpeGVsSW5kZXgsIGRpc3RhbmNlc1tpXSk7XG4gICAgfVxuICB9XG5cbiAgY2lyY2xlUGl4ZWxJbmRleEFycmF5Q2FjaGVbcmFkaXVzXSA9IHBpeGVsSW5kZXg7XG4gIHJldHVybiBwaXhlbEluZGV4O1xufVxuZXhwb3J0IGRlZmF1bHQgRXhlY3V0b3JHcm91cDsiLCIvKipcbiAqIEBtb2R1bGUgb2wvbGF5ZXIvVmVjdG9yVGlsZVJlbmRlclR5cGVcbiAqL1xuXG4vKipcbiAqIEBlbnVtIHtzdHJpbmd9XG4gKiBSZW5kZXIgbW9kZSBmb3IgdmVjdG9yIHRpbGVzOlxuICogICogYCdpbWFnZSdgOiBWZWN0b3IgdGlsZXMgYXJlIHJlbmRlcmVkIGFzIGltYWdlcy4gR3JlYXQgcGVyZm9ybWFuY2UsIGJ1dFxuICogICAgcG9pbnQgc3ltYm9scyBhbmQgdGV4dHMgYXJlIGFsd2F5cyByb3RhdGVkIHdpdGggdGhlIHZpZXcgYW5kIHBpeGVscyBhcmVcbiAqICAgIHNjYWxlZCBkdXJpbmcgem9vbSBhbmltYXRpb25zLlxuICogICogYCdoeWJyaWQnYDogUG9seWdvbiBhbmQgbGluZSBlbGVtZW50cyBhcmUgcmVuZGVyZWQgYXMgaW1hZ2VzLCBzbyBwaXhlbHNcbiAqICAgIGFyZSBzY2FsZWQgZHVyaW5nIHpvb20gYW5pbWF0aW9ucy4gUG9pbnQgc3ltYm9scyBhbmQgdGV4dHMgYXJlIGFjY3VyYXRlbHlcbiAqICAgIHJlbmRlcmVkIGFzIHZlY3RvcnMgYW5kIGNhbiBzdGF5IHVwcmlnaHQgb24gcm90YXRlZCB2aWV3cy5cbiAqICAqIGAndmVjdG9yJ2A6IEV2ZXJ5dGhpbmcgaXMgcmVuZGVyZWQgYXMgdmVjdG9ycy4gVXNlIHRoaXMgbW9kZSBmb3IgaW1wcm92ZWRcbiAqICAgIHBlcmZvcm1hbmNlIG9uIHZlY3RvciB0aWxlIGxheWVycyB3aXRoIG9ubHkgYSBmZXcgcmVuZGVyZWQgZmVhdHVyZXMgKGUuZy5cbiAqICAgIGZvciBoaWdobGlnaHRpbmcgYSBzdWJzZXQgb2YgZmVhdHVyZXMgb2YgYW5vdGhlciBsYXllciB3aXRoIHRoZSBzYW1lXG4gKiAgICBzb3VyY2UpLlxuICogQGFwaVxuICovXG5leHBvcnQgZGVmYXVsdCB7XG4gIElNQUdFOiAnaW1hZ2UnLFxuICBIWUJSSUQ6ICdoeWJyaWQnLFxuICBWRUNUT1I6ICd2ZWN0b3InXG59OyIsIi8qKlxuICogQG1vZHVsZSBvbC9yZW5kZXIvY2FudmFzL0ltbWVkaWF0ZVxuICovXG4vLyBGSVhNRSB0ZXN0LCBlc3BlY2lhbGx5IHBvbHlnb25zIHdpdGggaG9sZXMgYW5kIG11bHRpcG9seWdvbnNcbi8vIEZJWE1FIG5lZWQgdG8gaGFuZGxlIGxhcmdlIHRoaWNrIGZlYXR1cmVzICh3aGVyZSBwaXhlbCBzaXplIG1hdHRlcnMpXG4vLyBGSVhNRSBhZGQgb2Zmc2V0IGFuZCBlbmQgdG8gb2wvZ2VvbS9mbGF0L3RyYW5zZm9ybX50cmFuc2Zvcm0yRD9cbnZhciBfX2V4dGVuZHMgPSB0aGlzICYmIHRoaXMuX19leHRlbmRzIHx8IGZ1bmN0aW9uICgpIHtcbiAgdmFyIF9leHRlbmRTdGF0aWNzID0gZnVuY3Rpb24gZXh0ZW5kU3RhdGljcyhkLCBiKSB7XG4gICAgX2V4dGVuZFN0YXRpY3MgPSBPYmplY3Quc2V0UHJvdG90eXBlT2YgfHwge1xuICAgICAgX19wcm90b19fOiBbXVxuICAgIH0gaW5zdGFuY2VvZiBBcnJheSAmJiBmdW5jdGlvbiAoZCwgYikge1xuICAgICAgZC5fX3Byb3RvX18gPSBiO1xuICAgIH0gfHwgZnVuY3Rpb24gKGQsIGIpIHtcbiAgICAgIGZvciAodmFyIHAgaW4gYikge1xuICAgICAgICBpZiAoT2JqZWN0LnByb3RvdHlwZS5oYXNPd25Qcm9wZXJ0eS5jYWxsKGIsIHApKSBkW3BdID0gYltwXTtcbiAgICAgIH1cbiAgICB9O1xuXG4gICAgcmV0dXJuIF9leHRlbmRTdGF0aWNzKGQsIGIpO1xuICB9O1xuXG4gIHJldHVybiBmdW5jdGlvbiAoZCwgYikge1xuICAgIF9leHRlbmRTdGF0aWNzKGQsIGIpO1xuXG4gICAgZnVuY3Rpb24gX18oKSB7XG4gICAgICB0aGlzLmNvbnN0cnVjdG9yID0gZDtcbiAgICB9XG5cbiAgICBkLnByb3RvdHlwZSA9IGIgPT09IG51bGwgPyBPYmplY3QuY3JlYXRlKGIpIDogKF9fLnByb3RvdHlwZSA9IGIucHJvdG90eXBlLCBuZXcgX18oKSk7XG4gIH07XG59KCk7XG5cbmltcG9ydCBHZW9tZXRyeVR5cGUgZnJvbSAnLi4vLi4vZ2VvbS9HZW9tZXRyeVR5cGUuanMnO1xuaW1wb3J0IFZlY3RvckNvbnRleHQgZnJvbSAnLi4vVmVjdG9yQ29udGV4dC5qcyc7XG5pbXBvcnQgeyBhc0NvbG9yTGlrZSB9IGZyb20gJy4uLy4uL2NvbG9ybGlrZS5qcyc7XG5pbXBvcnQgeyBjb21wb3NlIGFzIGNvbXBvc2VUcmFuc2Zvcm0sIGNyZWF0ZSBhcyBjcmVhdGVUcmFuc2Zvcm0gfSBmcm9tICcuLi8uLi90cmFuc2Zvcm0uanMnO1xuaW1wb3J0IHsgZGVmYXVsdEZpbGxTdHlsZSwgZGVmYXVsdEZvbnQsIGRlZmF1bHRMaW5lQ2FwLCBkZWZhdWx0TGluZURhc2gsIGRlZmF1bHRMaW5lRGFzaE9mZnNldCwgZGVmYXVsdExpbmVKb2luLCBkZWZhdWx0TGluZVdpZHRoLCBkZWZhdWx0TWl0ZXJMaW1pdCwgZGVmYXVsdFN0cm9rZVN0eWxlLCBkZWZhdWx0VGV4dEFsaWduLCBkZWZhdWx0VGV4dEJhc2VsaW5lIH0gZnJvbSAnLi4vY2FudmFzLmpzJztcbmltcG9ydCB7IGVxdWFscyB9IGZyb20gJy4uLy4uL2FycmF5LmpzJztcbmltcG9ydCB7IGludGVyc2VjdHMgfSBmcm9tICcuLi8uLi9leHRlbnQuanMnO1xuaW1wb3J0IHsgdHJhbnNmb3JtMkQgfSBmcm9tICcuLi8uLi9nZW9tL2ZsYXQvdHJhbnNmb3JtLmpzJztcbmltcG9ydCB7IHRyYW5zZm9ybUdlb20yRCB9IGZyb20gJy4uLy4uL2dlb20vU2ltcGxlR2VvbWV0cnkuanMnO1xuLyoqXG4gKiBAY2xhc3NkZXNjXG4gKiBBIGNvbmNyZXRlIHN1YmNsYXNzIG9mIHtAbGluayBtb2R1bGU6b2wvcmVuZGVyL1ZlY3RvckNvbnRleHR9IHRoYXQgaW1wbGVtZW50c1xuICogZGlyZWN0IHJlbmRlcmluZyBvZiBmZWF0dXJlcyBhbmQgZ2VvbWV0cmllcyB0byBhbiBIVE1MNSBDYW52YXMgY29udGV4dC5cbiAqIEluc3RhbmNlcyBvZiB0aGlzIGNsYXNzIGFyZSBjcmVhdGVkIGludGVybmFsbHkgYnkgdGhlIGxpYnJhcnkgYW5kXG4gKiBwcm92aWRlZCB0byBhcHBsaWNhdGlvbiBjb2RlIGFzIHZlY3RvckNvbnRleHQgbWVtYmVyIG9mIHRoZVxuICoge0BsaW5rIG1vZHVsZTpvbC9yZW5kZXIvRXZlbnR+UmVuZGVyRXZlbnR9IG9iamVjdCBhc3NvY2lhdGVkIHdpdGggcG9zdGNvbXBvc2UsIHByZWNvbXBvc2UgYW5kXG4gKiByZW5kZXIgZXZlbnRzIGVtaXR0ZWQgYnkgbGF5ZXJzIGFuZCBtYXBzLlxuICovXG5cbnZhciBDYW52YXNJbW1lZGlhdGVSZW5kZXJlciA9XG4vKiogQGNsYXNzICovXG5mdW5jdGlvbiAoX3N1cGVyKSB7XG4gIF9fZXh0ZW5kcyhDYW52YXNJbW1lZGlhdGVSZW5kZXJlciwgX3N1cGVyKTtcbiAgLyoqXG4gICAqIEBwYXJhbSB7Q2FudmFzUmVuZGVyaW5nQ29udGV4dDJEfSBjb250ZXh0IENvbnRleHQuXG4gICAqIEBwYXJhbSB7bnVtYmVyfSBwaXhlbFJhdGlvIFBpeGVsIHJhdGlvLlxuICAgKiBAcGFyYW0ge2ltcG9ydChcIi4uLy4uL2V4dGVudC5qc1wiKS5FeHRlbnR9IGV4dGVudCBFeHRlbnQuXG4gICAqIEBwYXJhbSB7aW1wb3J0KFwiLi4vLi4vdHJhbnNmb3JtLmpzXCIpLlRyYW5zZm9ybX0gdHJhbnNmb3JtIFRyYW5zZm9ybS5cbiAgICogQHBhcmFtIHtudW1iZXJ9IHZpZXdSb3RhdGlvbiBWaWV3IHJvdGF0aW9uLlxuICAgKiBAcGFyYW0ge251bWJlcj19IG9wdF9zcXVhcmVkVG9sZXJhbmNlIE9wdGlvbmFsIHNxdWFyZWQgdG9sZXJhbmNlIGZvciBzaW1wbGlmaWNhdGlvbi5cbiAgICogQHBhcmFtIHtpbXBvcnQoXCIuLi8uLi9wcm9qLmpzXCIpLlRyYW5zZm9ybUZ1bmN0aW9uPX0gb3B0X3VzZXJUcmFuc2Zvcm0gVHJhbnNmb3JtIGZyb20gdXNlciB0byB2aWV3IHByb2plY3Rpb24uXG4gICAqL1xuXG5cbiAgZnVuY3Rpb24gQ2FudmFzSW1tZWRpYXRlUmVuZGVyZXIoY29udGV4dCwgcGl4ZWxSYXRpbywgZXh0ZW50LCB0cmFuc2Zvcm0sIHZpZXdSb3RhdGlvbiwgb3B0X3NxdWFyZWRUb2xlcmFuY2UsIG9wdF91c2VyVHJhbnNmb3JtKSB7XG4gICAgdmFyIF90aGlzID0gX3N1cGVyLmNhbGwodGhpcykgfHwgdGhpcztcbiAgICAvKipcbiAgICAgKiBAcHJpdmF0ZVxuICAgICAqIEB0eXBlIHtDYW52YXNSZW5kZXJpbmdDb250ZXh0MkR9XG4gICAgICovXG5cblxuICAgIF90aGlzLmNvbnRleHRfID0gY29udGV4dDtcbiAgICAvKipcbiAgICAgKiBAcHJpdmF0ZVxuICAgICAqIEB0eXBlIHtudW1iZXJ9XG4gICAgICovXG5cbiAgICBfdGhpcy5waXhlbFJhdGlvXyA9IHBpeGVsUmF0aW87XG4gICAgLyoqXG4gICAgICogQHByaXZhdGVcbiAgICAgKiBAdHlwZSB7aW1wb3J0KFwiLi4vLi4vZXh0ZW50LmpzXCIpLkV4dGVudH1cbiAgICAgKi9cblxuICAgIF90aGlzLmV4dGVudF8gPSBleHRlbnQ7XG4gICAgLyoqXG4gICAgICogQHByaXZhdGVcbiAgICAgKiBAdHlwZSB7aW1wb3J0KFwiLi4vLi4vdHJhbnNmb3JtLmpzXCIpLlRyYW5zZm9ybX1cbiAgICAgKi9cblxuICAgIF90aGlzLnRyYW5zZm9ybV8gPSB0cmFuc2Zvcm07XG4gICAgLyoqXG4gICAgICogQHByaXZhdGVcbiAgICAgKiBAdHlwZSB7bnVtYmVyfVxuICAgICAqL1xuXG4gICAgX3RoaXMudmlld1JvdGF0aW9uXyA9IHZpZXdSb3RhdGlvbjtcbiAgICAvKipcbiAgICAgKiBAcHJpdmF0ZVxuICAgICAqIEB0eXBlIHtudW1iZXJ9XG4gICAgICovXG5cbiAgICBfdGhpcy5zcXVhcmVkVG9sZXJhbmNlXyA9IG9wdF9zcXVhcmVkVG9sZXJhbmNlO1xuICAgIC8qKlxuICAgICAqIEBwcml2YXRlXG4gICAgICogQHR5cGUge2ltcG9ydChcIi4uLy4uL3Byb2ouanNcIikuVHJhbnNmb3JtRnVuY3Rpb259XG4gICAgICovXG5cbiAgICBfdGhpcy51c2VyVHJhbnNmb3JtXyA9IG9wdF91c2VyVHJhbnNmb3JtO1xuICAgIC8qKlxuICAgICAqIEBwcml2YXRlXG4gICAgICogQHR5cGUgez9pbXBvcnQoXCIuLi9jYW52YXMuanNcIikuRmlsbFN0YXRlfVxuICAgICAqL1xuXG4gICAgX3RoaXMuY29udGV4dEZpbGxTdGF0ZV8gPSBudWxsO1xuICAgIC8qKlxuICAgICAqIEBwcml2YXRlXG4gICAgICogQHR5cGUgez9pbXBvcnQoXCIuLi9jYW52YXMuanNcIikuU3Ryb2tlU3RhdGV9XG4gICAgICovXG5cbiAgICBfdGhpcy5jb250ZXh0U3Ryb2tlU3RhdGVfID0gbnVsbDtcbiAgICAvKipcbiAgICAgKiBAcHJpdmF0ZVxuICAgICAqIEB0eXBlIHs/aW1wb3J0KFwiLi4vY2FudmFzLmpzXCIpLlRleHRTdGF0ZX1cbiAgICAgKi9cblxuICAgIF90aGlzLmNvbnRleHRUZXh0U3RhdGVfID0gbnVsbDtcbiAgICAvKipcbiAgICAgKiBAcHJpdmF0ZVxuICAgICAqIEB0eXBlIHs/aW1wb3J0KFwiLi4vY2FudmFzLmpzXCIpLkZpbGxTdGF0ZX1cbiAgICAgKi9cblxuICAgIF90aGlzLmZpbGxTdGF0ZV8gPSBudWxsO1xuICAgIC8qKlxuICAgICAqIEBwcml2YXRlXG4gICAgICogQHR5cGUgez9pbXBvcnQoXCIuLi9jYW52YXMuanNcIikuU3Ryb2tlU3RhdGV9XG4gICAgICovXG5cbiAgICBfdGhpcy5zdHJva2VTdGF0ZV8gPSBudWxsO1xuICAgIC8qKlxuICAgICAqIEBwcml2YXRlXG4gICAgICogQHR5cGUge0hUTUxDYW52YXNFbGVtZW50fEhUTUxWaWRlb0VsZW1lbnR8SFRNTEltYWdlRWxlbWVudH1cbiAgICAgKi9cblxuICAgIF90aGlzLmltYWdlXyA9IG51bGw7XG4gICAgLyoqXG4gICAgICogQHByaXZhdGVcbiAgICAgKiBAdHlwZSB7bnVtYmVyfVxuICAgICAqL1xuXG4gICAgX3RoaXMuaW1hZ2VBbmNob3JYXyA9IDA7XG4gICAgLyoqXG4gICAgICogQHByaXZhdGVcbiAgICAgKiBAdHlwZSB7bnVtYmVyfVxuICAgICAqL1xuXG4gICAgX3RoaXMuaW1hZ2VBbmNob3JZXyA9IDA7XG4gICAgLyoqXG4gICAgICogQHByaXZhdGVcbiAgICAgKiBAdHlwZSB7bnVtYmVyfVxuICAgICAqL1xuXG4gICAgX3RoaXMuaW1hZ2VIZWlnaHRfID0gMDtcbiAgICAvKipcbiAgICAgKiBAcHJpdmF0ZVxuICAgICAqIEB0eXBlIHtudW1iZXJ9XG4gICAgICovXG5cbiAgICBfdGhpcy5pbWFnZU9wYWNpdHlfID0gMDtcbiAgICAvKipcbiAgICAgKiBAcHJpdmF0ZVxuICAgICAqIEB0eXBlIHtudW1iZXJ9XG4gICAgICovXG5cbiAgICBfdGhpcy5pbWFnZU9yaWdpblhfID0gMDtcbiAgICAvKipcbiAgICAgKiBAcHJpdmF0ZVxuICAgICAqIEB0eXBlIHtudW1iZXJ9XG4gICAgICovXG5cbiAgICBfdGhpcy5pbWFnZU9yaWdpbllfID0gMDtcbiAgICAvKipcbiAgICAgKiBAcHJpdmF0ZVxuICAgICAqIEB0eXBlIHtib29sZWFufVxuICAgICAqL1xuXG4gICAgX3RoaXMuaW1hZ2VSb3RhdGVXaXRoVmlld18gPSBmYWxzZTtcbiAgICAvKipcbiAgICAgKiBAcHJpdmF0ZVxuICAgICAqIEB0eXBlIHtudW1iZXJ9XG4gICAgICovXG5cbiAgICBfdGhpcy5pbWFnZVJvdGF0aW9uXyA9IDA7XG4gICAgLyoqXG4gICAgICogQHByaXZhdGVcbiAgICAgKiBAdHlwZSB7aW1wb3J0KFwiLi4vLi4vc2l6ZS5qc1wiKS5TaXplfVxuICAgICAqL1xuXG4gICAgX3RoaXMuaW1hZ2VTY2FsZV8gPSBbMCwgMF07XG4gICAgLyoqXG4gICAgICogQHByaXZhdGVcbiAgICAgKiBAdHlwZSB7bnVtYmVyfVxuICAgICAqL1xuXG4gICAgX3RoaXMuaW1hZ2VXaWR0aF8gPSAwO1xuICAgIC8qKlxuICAgICAqIEBwcml2YXRlXG4gICAgICogQHR5cGUge3N0cmluZ31cbiAgICAgKi9cblxuICAgIF90aGlzLnRleHRfID0gJyc7XG4gICAgLyoqXG4gICAgICogQHByaXZhdGVcbiAgICAgKiBAdHlwZSB7bnVtYmVyfVxuICAgICAqL1xuXG4gICAgX3RoaXMudGV4dE9mZnNldFhfID0gMDtcbiAgICAvKipcbiAgICAgKiBAcHJpdmF0ZVxuICAgICAqIEB0eXBlIHtudW1iZXJ9XG4gICAgICovXG5cbiAgICBfdGhpcy50ZXh0T2Zmc2V0WV8gPSAwO1xuICAgIC8qKlxuICAgICAqIEBwcml2YXRlXG4gICAgICogQHR5cGUge2Jvb2xlYW59XG4gICAgICovXG5cbiAgICBfdGhpcy50ZXh0Um90YXRlV2l0aFZpZXdfID0gZmFsc2U7XG4gICAgLyoqXG4gICAgICogQHByaXZhdGVcbiAgICAgKiBAdHlwZSB7bnVtYmVyfVxuICAgICAqL1xuXG4gICAgX3RoaXMudGV4dFJvdGF0aW9uXyA9IDA7XG4gICAgLyoqXG4gICAgICogQHByaXZhdGVcbiAgICAgKiBAdHlwZSB7aW1wb3J0KFwiLi4vLi4vc2l6ZS5qc1wiKS5TaXplfVxuICAgICAqL1xuXG4gICAgX3RoaXMudGV4dFNjYWxlXyA9IFswLCAwXTtcbiAgICAvKipcbiAgICAgKiBAcHJpdmF0ZVxuICAgICAqIEB0eXBlIHs/aW1wb3J0KFwiLi4vY2FudmFzLmpzXCIpLkZpbGxTdGF0ZX1cbiAgICAgKi9cblxuICAgIF90aGlzLnRleHRGaWxsU3RhdGVfID0gbnVsbDtcbiAgICAvKipcbiAgICAgKiBAcHJpdmF0ZVxuICAgICAqIEB0eXBlIHs/aW1wb3J0KFwiLi4vY2FudmFzLmpzXCIpLlN0cm9rZVN0YXRlfVxuICAgICAqL1xuXG4gICAgX3RoaXMudGV4dFN0cm9rZVN0YXRlXyA9IG51bGw7XG4gICAgLyoqXG4gICAgICogQHByaXZhdGVcbiAgICAgKiBAdHlwZSB7P2ltcG9ydChcIi4uL2NhbnZhcy5qc1wiKS5UZXh0U3RhdGV9XG4gICAgICovXG5cbiAgICBfdGhpcy50ZXh0U3RhdGVfID0gbnVsbDtcbiAgICAvKipcbiAgICAgKiBAcHJpdmF0ZVxuICAgICAqIEB0eXBlIHtBcnJheTxudW1iZXI+fVxuICAgICAqL1xuXG4gICAgX3RoaXMucGl4ZWxDb29yZGluYXRlc18gPSBbXTtcbiAgICAvKipcbiAgICAgKiBAcHJpdmF0ZVxuICAgICAqIEB0eXBlIHtpbXBvcnQoXCIuLi8uLi90cmFuc2Zvcm0uanNcIikuVHJhbnNmb3JtfVxuICAgICAqL1xuXG4gICAgX3RoaXMudG1wTG9jYWxUcmFuc2Zvcm1fID0gY3JlYXRlVHJhbnNmb3JtKCk7XG4gICAgcmV0dXJuIF90aGlzO1xuICB9XG4gIC8qKlxuICAgKiBAcGFyYW0ge0FycmF5PG51bWJlcj59IGZsYXRDb29yZGluYXRlcyBGbGF0IGNvb3JkaW5hdGVzLlxuICAgKiBAcGFyYW0ge251bWJlcn0gb2Zmc2V0IE9mZnNldC5cbiAgICogQHBhcmFtIHtudW1iZXJ9IGVuZCBFbmQuXG4gICAqIEBwYXJhbSB7bnVtYmVyfSBzdHJpZGUgU3RyaWRlLlxuICAgKiBAcHJpdmF0ZVxuICAgKi9cblxuXG4gIENhbnZhc0ltbWVkaWF0ZVJlbmRlcmVyLnByb3RvdHlwZS5kcmF3SW1hZ2VzXyA9IGZ1bmN0aW9uIChmbGF0Q29vcmRpbmF0ZXMsIG9mZnNldCwgZW5kLCBzdHJpZGUpIHtcbiAgICBpZiAoIXRoaXMuaW1hZ2VfKSB7XG4gICAgICByZXR1cm47XG4gICAgfVxuXG4gICAgdmFyIHBpeGVsQ29vcmRpbmF0ZXMgPSB0cmFuc2Zvcm0yRChmbGF0Q29vcmRpbmF0ZXMsIG9mZnNldCwgZW5kLCAyLCB0aGlzLnRyYW5zZm9ybV8sIHRoaXMucGl4ZWxDb29yZGluYXRlc18pO1xuICAgIHZhciBjb250ZXh0ID0gdGhpcy5jb250ZXh0XztcbiAgICB2YXIgbG9jYWxUcmFuc2Zvcm0gPSB0aGlzLnRtcExvY2FsVHJhbnNmb3JtXztcbiAgICB2YXIgYWxwaGEgPSBjb250ZXh0Lmdsb2JhbEFscGhhO1xuXG4gICAgaWYgKHRoaXMuaW1hZ2VPcGFjaXR5XyAhPSAxKSB7XG4gICAgICBjb250ZXh0Lmdsb2JhbEFscGhhID0gYWxwaGEgKiB0aGlzLmltYWdlT3BhY2l0eV87XG4gICAgfVxuXG4gICAgdmFyIHJvdGF0aW9uID0gdGhpcy5pbWFnZVJvdGF0aW9uXztcblxuICAgIGlmICh0aGlzLmltYWdlUm90YXRlV2l0aFZpZXdfKSB7XG4gICAgICByb3RhdGlvbiArPSB0aGlzLnZpZXdSb3RhdGlvbl87XG4gICAgfVxuXG4gICAgZm9yICh2YXIgaSA9IDAsIGlpID0gcGl4ZWxDb29yZGluYXRlcy5sZW5ndGg7IGkgPCBpaTsgaSArPSAyKSB7XG4gICAgICB2YXIgeCA9IHBpeGVsQ29vcmRpbmF0ZXNbaV0gLSB0aGlzLmltYWdlQW5jaG9yWF87XG4gICAgICB2YXIgeSA9IHBpeGVsQ29vcmRpbmF0ZXNbaSArIDFdIC0gdGhpcy5pbWFnZUFuY2hvcllfO1xuXG4gICAgICBpZiAocm90YXRpb24gIT09IDAgfHwgdGhpcy5pbWFnZVNjYWxlX1swXSAhPSAxIHx8IHRoaXMuaW1hZ2VTY2FsZV9bMV0gIT0gMSkge1xuICAgICAgICB2YXIgY2VudGVyWCA9IHggKyB0aGlzLmltYWdlQW5jaG9yWF87XG4gICAgICAgIHZhciBjZW50ZXJZID0geSArIHRoaXMuaW1hZ2VBbmNob3JZXztcbiAgICAgICAgY29tcG9zZVRyYW5zZm9ybShsb2NhbFRyYW5zZm9ybSwgY2VudGVyWCwgY2VudGVyWSwgMSwgMSwgcm90YXRpb24sIC1jZW50ZXJYLCAtY2VudGVyWSk7XG4gICAgICAgIGNvbnRleHQuc2V0VHJhbnNmb3JtLmFwcGx5KGNvbnRleHQsIGxvY2FsVHJhbnNmb3JtKTtcbiAgICAgICAgY29udGV4dC50cmFuc2xhdGUoY2VudGVyWCwgY2VudGVyWSk7XG4gICAgICAgIGNvbnRleHQuc2NhbGUodGhpcy5pbWFnZVNjYWxlX1swXSwgdGhpcy5pbWFnZVNjYWxlX1sxXSk7XG4gICAgICAgIGNvbnRleHQuZHJhd0ltYWdlKHRoaXMuaW1hZ2VfLCB0aGlzLmltYWdlT3JpZ2luWF8sIHRoaXMuaW1hZ2VPcmlnaW5ZXywgdGhpcy5pbWFnZVdpZHRoXywgdGhpcy5pbWFnZUhlaWdodF8sIC10aGlzLmltYWdlQW5jaG9yWF8sIC10aGlzLmltYWdlQW5jaG9yWV8sIHRoaXMuaW1hZ2VXaWR0aF8sIHRoaXMuaW1hZ2VIZWlnaHRfKTtcbiAgICAgICAgY29udGV4dC5zZXRUcmFuc2Zvcm0oMSwgMCwgMCwgMSwgMCwgMCk7XG4gICAgICB9IGVsc2Uge1xuICAgICAgICBjb250ZXh0LmRyYXdJbWFnZSh0aGlzLmltYWdlXywgdGhpcy5pbWFnZU9yaWdpblhfLCB0aGlzLmltYWdlT3JpZ2luWV8sIHRoaXMuaW1hZ2VXaWR0aF8sIHRoaXMuaW1hZ2VIZWlnaHRfLCB4LCB5LCB0aGlzLmltYWdlV2lkdGhfLCB0aGlzLmltYWdlSGVpZ2h0Xyk7XG4gICAgICB9XG4gICAgfVxuXG4gICAgaWYgKHRoaXMuaW1hZ2VPcGFjaXR5XyAhPSAxKSB7XG4gICAgICBjb250ZXh0Lmdsb2JhbEFscGhhID0gYWxwaGE7XG4gICAgfVxuICB9O1xuICAvKipcbiAgICogQHBhcmFtIHtBcnJheTxudW1iZXI+fSBmbGF0Q29vcmRpbmF0ZXMgRmxhdCBjb29yZGluYXRlcy5cbiAgICogQHBhcmFtIHtudW1iZXJ9IG9mZnNldCBPZmZzZXQuXG4gICAqIEBwYXJhbSB7bnVtYmVyfSBlbmQgRW5kLlxuICAgKiBAcGFyYW0ge251bWJlcn0gc3RyaWRlIFN0cmlkZS5cbiAgICogQHByaXZhdGVcbiAgICovXG5cblxuICBDYW52YXNJbW1lZGlhdGVSZW5kZXJlci5wcm90b3R5cGUuZHJhd1RleHRfID0gZnVuY3Rpb24gKGZsYXRDb29yZGluYXRlcywgb2Zmc2V0LCBlbmQsIHN0cmlkZSkge1xuICAgIGlmICghdGhpcy50ZXh0U3RhdGVfIHx8IHRoaXMudGV4dF8gPT09ICcnKSB7XG4gICAgICByZXR1cm47XG4gICAgfVxuXG4gICAgaWYgKHRoaXMudGV4dEZpbGxTdGF0ZV8pIHtcbiAgICAgIHRoaXMuc2V0Q29udGV4dEZpbGxTdGF0ZV8odGhpcy50ZXh0RmlsbFN0YXRlXyk7XG4gICAgfVxuXG4gICAgaWYgKHRoaXMudGV4dFN0cm9rZVN0YXRlXykge1xuICAgICAgdGhpcy5zZXRDb250ZXh0U3Ryb2tlU3RhdGVfKHRoaXMudGV4dFN0cm9rZVN0YXRlXyk7XG4gICAgfVxuXG4gICAgdGhpcy5zZXRDb250ZXh0VGV4dFN0YXRlXyh0aGlzLnRleHRTdGF0ZV8pO1xuICAgIHZhciBwaXhlbENvb3JkaW5hdGVzID0gdHJhbnNmb3JtMkQoZmxhdENvb3JkaW5hdGVzLCBvZmZzZXQsIGVuZCwgc3RyaWRlLCB0aGlzLnRyYW5zZm9ybV8sIHRoaXMucGl4ZWxDb29yZGluYXRlc18pO1xuICAgIHZhciBjb250ZXh0ID0gdGhpcy5jb250ZXh0XztcbiAgICB2YXIgcm90YXRpb24gPSB0aGlzLnRleHRSb3RhdGlvbl87XG5cbiAgICBpZiAodGhpcy50ZXh0Um90YXRlV2l0aFZpZXdfKSB7XG4gICAgICByb3RhdGlvbiArPSB0aGlzLnZpZXdSb3RhdGlvbl87XG4gICAgfVxuXG4gICAgZm9yICg7IG9mZnNldCA8IGVuZDsgb2Zmc2V0ICs9IHN0cmlkZSkge1xuICAgICAgdmFyIHggPSBwaXhlbENvb3JkaW5hdGVzW29mZnNldF0gKyB0aGlzLnRleHRPZmZzZXRYXztcbiAgICAgIHZhciB5ID0gcGl4ZWxDb29yZGluYXRlc1tvZmZzZXQgKyAxXSArIHRoaXMudGV4dE9mZnNldFlfO1xuXG4gICAgICBpZiAocm90YXRpb24gIT09IDAgfHwgdGhpcy50ZXh0U2NhbGVfWzBdICE9IDEgfHwgdGhpcy50ZXh0U2NhbGVfWzFdICE9IDEpIHtcbiAgICAgICAgdmFyIGxvY2FsVHJhbnNmb3JtID0gY29tcG9zZVRyYW5zZm9ybSh0aGlzLnRtcExvY2FsVHJhbnNmb3JtXywgeCwgeSwgMSwgMSwgcm90YXRpb24sIC14LCAteSk7XG4gICAgICAgIGNvbnRleHQuc2V0VHJhbnNmb3JtLmFwcGx5KGNvbnRleHQsIGxvY2FsVHJhbnNmb3JtKTtcbiAgICAgICAgY29udGV4dC50cmFuc2xhdGUoeCwgeSk7XG4gICAgICAgIGNvbnRleHQuc2NhbGUodGhpcy50ZXh0U2NhbGVfWzBdLCB0aGlzLnRleHRTY2FsZV9bMV0pO1xuXG4gICAgICAgIGlmICh0aGlzLnRleHRTdHJva2VTdGF0ZV8pIHtcbiAgICAgICAgICBjb250ZXh0LnN0cm9rZVRleHQodGhpcy50ZXh0XywgMCwgMCk7XG4gICAgICAgIH1cblxuICAgICAgICBpZiAodGhpcy50ZXh0RmlsbFN0YXRlXykge1xuICAgICAgICAgIGNvbnRleHQuZmlsbFRleHQodGhpcy50ZXh0XywgMCwgMCk7XG4gICAgICAgIH1cblxuICAgICAgICBjb250ZXh0LnNldFRyYW5zZm9ybSgxLCAwLCAwLCAxLCAwLCAwKTtcbiAgICAgIH0gZWxzZSB7XG4gICAgICAgIGlmICh0aGlzLnRleHRTdHJva2VTdGF0ZV8pIHtcbiAgICAgICAgICBjb250ZXh0LnN0cm9rZVRleHQodGhpcy50ZXh0XywgeCwgeSk7XG4gICAgICAgIH1cblxuICAgICAgICBpZiAodGhpcy50ZXh0RmlsbFN0YXRlXykge1xuICAgICAgICAgIGNvbnRleHQuZmlsbFRleHQodGhpcy50ZXh0XywgeCwgeSk7XG4gICAgICAgIH1cbiAgICAgIH1cbiAgICB9XG4gIH07XG4gIC8qKlxuICAgKiBAcGFyYW0ge0FycmF5PG51bWJlcj59IGZsYXRDb29yZGluYXRlcyBGbGF0IGNvb3JkaW5hdGVzLlxuICAgKiBAcGFyYW0ge251bWJlcn0gb2Zmc2V0IE9mZnNldC5cbiAgICogQHBhcmFtIHtudW1iZXJ9IGVuZCBFbmQuXG4gICAqIEBwYXJhbSB7bnVtYmVyfSBzdHJpZGUgU3RyaWRlLlxuICAgKiBAcGFyYW0ge2Jvb2xlYW59IGNsb3NlIENsb3NlLlxuICAgKiBAcHJpdmF0ZVxuICAgKiBAcmV0dXJuIHtudW1iZXJ9IGVuZCBFbmQuXG4gICAqL1xuXG5cbiAgQ2FudmFzSW1tZWRpYXRlUmVuZGVyZXIucHJvdG90eXBlLm1vdmVUb0xpbmVUb18gPSBmdW5jdGlvbiAoZmxhdENvb3JkaW5hdGVzLCBvZmZzZXQsIGVuZCwgc3RyaWRlLCBjbG9zZSkge1xuICAgIHZhciBjb250ZXh0ID0gdGhpcy5jb250ZXh0XztcbiAgICB2YXIgcGl4ZWxDb29yZGluYXRlcyA9IHRyYW5zZm9ybTJEKGZsYXRDb29yZGluYXRlcywgb2Zmc2V0LCBlbmQsIHN0cmlkZSwgdGhpcy50cmFuc2Zvcm1fLCB0aGlzLnBpeGVsQ29vcmRpbmF0ZXNfKTtcbiAgICBjb250ZXh0Lm1vdmVUbyhwaXhlbENvb3JkaW5hdGVzWzBdLCBwaXhlbENvb3JkaW5hdGVzWzFdKTtcbiAgICB2YXIgbGVuZ3RoID0gcGl4ZWxDb29yZGluYXRlcy5sZW5ndGg7XG5cbiAgICBpZiAoY2xvc2UpIHtcbiAgICAgIGxlbmd0aCAtPSAyO1xuICAgIH1cblxuICAgIGZvciAodmFyIGkgPSAyOyBpIDwgbGVuZ3RoOyBpICs9IDIpIHtcbiAgICAgIGNvbnRleHQubGluZVRvKHBpeGVsQ29vcmRpbmF0ZXNbaV0sIHBpeGVsQ29vcmRpbmF0ZXNbaSArIDFdKTtcbiAgICB9XG5cbiAgICBpZiAoY2xvc2UpIHtcbiAgICAgIGNvbnRleHQuY2xvc2VQYXRoKCk7XG4gICAgfVxuXG4gICAgcmV0dXJuIGVuZDtcbiAgfTtcbiAgLyoqXG4gICAqIEBwYXJhbSB7QXJyYXk8bnVtYmVyPn0gZmxhdENvb3JkaW5hdGVzIEZsYXQgY29vcmRpbmF0ZXMuXG4gICAqIEBwYXJhbSB7bnVtYmVyfSBvZmZzZXQgT2Zmc2V0LlxuICAgKiBAcGFyYW0ge0FycmF5PG51bWJlcj59IGVuZHMgRW5kcy5cbiAgICogQHBhcmFtIHtudW1iZXJ9IHN0cmlkZSBTdHJpZGUuXG4gICAqIEBwcml2YXRlXG4gICAqIEByZXR1cm4ge251bWJlcn0gRW5kLlxuICAgKi9cblxuXG4gIENhbnZhc0ltbWVkaWF0ZVJlbmRlcmVyLnByb3RvdHlwZS5kcmF3UmluZ3NfID0gZnVuY3Rpb24gKGZsYXRDb29yZGluYXRlcywgb2Zmc2V0LCBlbmRzLCBzdHJpZGUpIHtcbiAgICBmb3IgKHZhciBpID0gMCwgaWkgPSBlbmRzLmxlbmd0aDsgaSA8IGlpOyArK2kpIHtcbiAgICAgIG9mZnNldCA9IHRoaXMubW92ZVRvTGluZVRvXyhmbGF0Q29vcmRpbmF0ZXMsIG9mZnNldCwgZW5kc1tpXSwgc3RyaWRlLCB0cnVlKTtcbiAgICB9XG5cbiAgICByZXR1cm4gb2Zmc2V0O1xuICB9O1xuICAvKipcbiAgICogUmVuZGVyIGEgY2lyY2xlIGdlb21ldHJ5IGludG8gdGhlIGNhbnZhcy4gIFJlbmRlcmluZyBpcyBpbW1lZGlhdGUgYW5kIHVzZXNcbiAgICogdGhlIGN1cnJlbnQgZmlsbCBhbmQgc3Ryb2tlIHN0eWxlcy5cbiAgICpcbiAgICogQHBhcmFtIHtpbXBvcnQoXCIuLi8uLi9nZW9tL0NpcmNsZS5qc1wiKS5kZWZhdWx0fSBnZW9tZXRyeSBDaXJjbGUgZ2VvbWV0cnkuXG4gICAqIEBhcGlcbiAgICovXG5cblxuICBDYW52YXNJbW1lZGlhdGVSZW5kZXJlci5wcm90b3R5cGUuZHJhd0NpcmNsZSA9IGZ1bmN0aW9uIChnZW9tZXRyeSkge1xuICAgIGlmICghaW50ZXJzZWN0cyh0aGlzLmV4dGVudF8sIGdlb21ldHJ5LmdldEV4dGVudCgpKSkge1xuICAgICAgcmV0dXJuO1xuICAgIH1cblxuICAgIGlmICh0aGlzLmZpbGxTdGF0ZV8gfHwgdGhpcy5zdHJva2VTdGF0ZV8pIHtcbiAgICAgIGlmICh0aGlzLmZpbGxTdGF0ZV8pIHtcbiAgICAgICAgdGhpcy5zZXRDb250ZXh0RmlsbFN0YXRlXyh0aGlzLmZpbGxTdGF0ZV8pO1xuICAgICAgfVxuXG4gICAgICBpZiAodGhpcy5zdHJva2VTdGF0ZV8pIHtcbiAgICAgICAgdGhpcy5zZXRDb250ZXh0U3Ryb2tlU3RhdGVfKHRoaXMuc3Ryb2tlU3RhdGVfKTtcbiAgICAgIH1cblxuICAgICAgdmFyIHBpeGVsQ29vcmRpbmF0ZXMgPSB0cmFuc2Zvcm1HZW9tMkQoZ2VvbWV0cnksIHRoaXMudHJhbnNmb3JtXywgdGhpcy5waXhlbENvb3JkaW5hdGVzXyk7XG4gICAgICB2YXIgZHggPSBwaXhlbENvb3JkaW5hdGVzWzJdIC0gcGl4ZWxDb29yZGluYXRlc1swXTtcbiAgICAgIHZhciBkeSA9IHBpeGVsQ29vcmRpbmF0ZXNbM10gLSBwaXhlbENvb3JkaW5hdGVzWzFdO1xuICAgICAgdmFyIHJhZGl1cyA9IE1hdGguc3FydChkeCAqIGR4ICsgZHkgKiBkeSk7XG4gICAgICB2YXIgY29udGV4dCA9IHRoaXMuY29udGV4dF87XG4gICAgICBjb250ZXh0LmJlZ2luUGF0aCgpO1xuICAgICAgY29udGV4dC5hcmMocGl4ZWxDb29yZGluYXRlc1swXSwgcGl4ZWxDb29yZGluYXRlc1sxXSwgcmFkaXVzLCAwLCAyICogTWF0aC5QSSk7XG5cbiAgICAgIGlmICh0aGlzLmZpbGxTdGF0ZV8pIHtcbiAgICAgICAgY29udGV4dC5maWxsKCk7XG4gICAgICB9XG5cbiAgICAgIGlmICh0aGlzLnN0cm9rZVN0YXRlXykge1xuICAgICAgICBjb250ZXh0LnN0cm9rZSgpO1xuICAgICAgfVxuICAgIH1cblxuICAgIGlmICh0aGlzLnRleHRfICE9PSAnJykge1xuICAgICAgdGhpcy5kcmF3VGV4dF8oZ2VvbWV0cnkuZ2V0Q2VudGVyKCksIDAsIDIsIDIpO1xuICAgIH1cbiAgfTtcbiAgLyoqXG4gICAqIFNldCB0aGUgcmVuZGVyaW5nIHN0eWxlLiAgTm90ZSB0aGF0IHNpbmNlIHRoaXMgaXMgYW4gaW1tZWRpYXRlIHJlbmRlcmluZyBBUEksXG4gICAqIGFueSBgekluZGV4YCBvbiB0aGUgcHJvdmlkZWQgc3R5bGUgd2lsbCBiZSBpZ25vcmVkLlxuICAgKlxuICAgKiBAcGFyYW0ge2ltcG9ydChcIi4uLy4uL3N0eWxlL1N0eWxlLmpzXCIpLmRlZmF1bHR9IHN0eWxlIFRoZSByZW5kZXJpbmcgc3R5bGUuXG4gICAqIEBhcGlcbiAgICovXG5cblxuICBDYW52YXNJbW1lZGlhdGVSZW5kZXJlci5wcm90b3R5cGUuc2V0U3R5bGUgPSBmdW5jdGlvbiAoc3R5bGUpIHtcbiAgICB0aGlzLnNldEZpbGxTdHJva2VTdHlsZShzdHlsZS5nZXRGaWxsKCksIHN0eWxlLmdldFN0cm9rZSgpKTtcbiAgICB0aGlzLnNldEltYWdlU3R5bGUoc3R5bGUuZ2V0SW1hZ2UoKSk7XG4gICAgdGhpcy5zZXRUZXh0U3R5bGUoc3R5bGUuZ2V0VGV4dCgpKTtcbiAgfTtcbiAgLyoqXG4gICAqIEBwYXJhbSB7aW1wb3J0KFwiLi4vLi4vdHJhbnNmb3JtLmpzXCIpLlRyYW5zZm9ybX0gdHJhbnNmb3JtIFRyYW5zZm9ybS5cbiAgICovXG5cblxuICBDYW52YXNJbW1lZGlhdGVSZW5kZXJlci5wcm90b3R5cGUuc2V0VHJhbnNmb3JtID0gZnVuY3Rpb24gKHRyYW5zZm9ybSkge1xuICAgIHRoaXMudHJhbnNmb3JtXyA9IHRyYW5zZm9ybTtcbiAgfTtcbiAgLyoqXG4gICAqIFJlbmRlciBhIGdlb21ldHJ5IGludG8gdGhlIGNhbnZhcy4gIENhbGxcbiAgICoge0BsaW5rIG1vZHVsZTpvbC9yZW5kZXIvY2FudmFzL0ltbWVkaWF0ZSNzZXRTdHlsZX0gZmlyc3QgdG8gc2V0IHRoZSByZW5kZXJpbmcgc3R5bGUuXG4gICAqXG4gICAqIEBwYXJhbSB7aW1wb3J0KFwiLi4vLi4vZ2VvbS9HZW9tZXRyeS5qc1wiKS5kZWZhdWx0fGltcG9ydChcIi4uL0ZlYXR1cmUuanNcIikuZGVmYXVsdH0gZ2VvbWV0cnkgVGhlIGdlb21ldHJ5IHRvIHJlbmRlci5cbiAgICogQGFwaVxuICAgKi9cblxuXG4gIENhbnZhc0ltbWVkaWF0ZVJlbmRlcmVyLnByb3RvdHlwZS5kcmF3R2VvbWV0cnkgPSBmdW5jdGlvbiAoZ2VvbWV0cnkpIHtcbiAgICB2YXIgdHlwZSA9IGdlb21ldHJ5LmdldFR5cGUoKTtcblxuICAgIHN3aXRjaCAodHlwZSkge1xuICAgICAgY2FzZSBHZW9tZXRyeVR5cGUuUE9JTlQ6XG4gICAgICAgIHRoaXMuZHJhd1BvaW50KFxuICAgICAgICAvKiogQHR5cGUge2ltcG9ydChcIi4uLy4uL2dlb20vUG9pbnQuanNcIikuZGVmYXVsdH0gKi9cbiAgICAgICAgZ2VvbWV0cnkpO1xuICAgICAgICBicmVhaztcblxuICAgICAgY2FzZSBHZW9tZXRyeVR5cGUuTElORV9TVFJJTkc6XG4gICAgICAgIHRoaXMuZHJhd0xpbmVTdHJpbmcoXG4gICAgICAgIC8qKiBAdHlwZSB7aW1wb3J0KFwiLi4vLi4vZ2VvbS9MaW5lU3RyaW5nLmpzXCIpLmRlZmF1bHR9ICovXG4gICAgICAgIGdlb21ldHJ5KTtcbiAgICAgICAgYnJlYWs7XG5cbiAgICAgIGNhc2UgR2VvbWV0cnlUeXBlLlBPTFlHT046XG4gICAgICAgIHRoaXMuZHJhd1BvbHlnb24oXG4gICAgICAgIC8qKiBAdHlwZSB7aW1wb3J0KFwiLi4vLi4vZ2VvbS9Qb2x5Z29uLmpzXCIpLmRlZmF1bHR9ICovXG4gICAgICAgIGdlb21ldHJ5KTtcbiAgICAgICAgYnJlYWs7XG5cbiAgICAgIGNhc2UgR2VvbWV0cnlUeXBlLk1VTFRJX1BPSU5UOlxuICAgICAgICB0aGlzLmRyYXdNdWx0aVBvaW50KFxuICAgICAgICAvKiogQHR5cGUge2ltcG9ydChcIi4uLy4uL2dlb20vTXVsdGlQb2ludC5qc1wiKS5kZWZhdWx0fSAqL1xuICAgICAgICBnZW9tZXRyeSk7XG4gICAgICAgIGJyZWFrO1xuXG4gICAgICBjYXNlIEdlb21ldHJ5VHlwZS5NVUxUSV9MSU5FX1NUUklORzpcbiAgICAgICAgdGhpcy5kcmF3TXVsdGlMaW5lU3RyaW5nKFxuICAgICAgICAvKiogQHR5cGUge2ltcG9ydChcIi4uLy4uL2dlb20vTXVsdGlMaW5lU3RyaW5nLmpzXCIpLmRlZmF1bHR9ICovXG4gICAgICAgIGdlb21ldHJ5KTtcbiAgICAgICAgYnJlYWs7XG5cbiAgICAgIGNhc2UgR2VvbWV0cnlUeXBlLk1VTFRJX1BPTFlHT046XG4gICAgICAgIHRoaXMuZHJhd011bHRpUG9seWdvbihcbiAgICAgICAgLyoqIEB0eXBlIHtpbXBvcnQoXCIuLi8uLi9nZW9tL011bHRpUG9seWdvbi5qc1wiKS5kZWZhdWx0fSAqL1xuICAgICAgICBnZW9tZXRyeSk7XG4gICAgICAgIGJyZWFrO1xuXG4gICAgICBjYXNlIEdlb21ldHJ5VHlwZS5HRU9NRVRSWV9DT0xMRUNUSU9OOlxuICAgICAgICB0aGlzLmRyYXdHZW9tZXRyeUNvbGxlY3Rpb24oXG4gICAgICAgIC8qKiBAdHlwZSB7aW1wb3J0KFwiLi4vLi4vZ2VvbS9HZW9tZXRyeUNvbGxlY3Rpb24uanNcIikuZGVmYXVsdH0gKi9cbiAgICAgICAgZ2VvbWV0cnkpO1xuICAgICAgICBicmVhaztcblxuICAgICAgY2FzZSBHZW9tZXRyeVR5cGUuQ0lSQ0xFOlxuICAgICAgICB0aGlzLmRyYXdDaXJjbGUoXG4gICAgICAgIC8qKiBAdHlwZSB7aW1wb3J0KFwiLi4vLi4vZ2VvbS9DaXJjbGUuanNcIikuZGVmYXVsdH0gKi9cbiAgICAgICAgZ2VvbWV0cnkpO1xuICAgICAgICBicmVhaztcblxuICAgICAgZGVmYXVsdDpcbiAgICB9XG4gIH07XG4gIC8qKlxuICAgKiBSZW5kZXIgYSBmZWF0dXJlIGludG8gdGhlIGNhbnZhcy4gIE5vdGUgdGhhdCBhbnkgYHpJbmRleGAgb24gdGhlIHByb3ZpZGVkXG4gICAqIHN0eWxlIHdpbGwgYmUgaWdub3JlZCAtIGZlYXR1cmVzIGFyZSByZW5kZXJlZCBpbW1lZGlhdGVseSBpbiB0aGUgb3JkZXIgdGhhdFxuICAgKiB0aGlzIG1ldGhvZCBpcyBjYWxsZWQuICBJZiB5b3UgbmVlZCBgekluZGV4YCBzdXBwb3J0LCB5b3Ugc2hvdWxkIGJlIHVzaW5nIGFuXG4gICAqIHtAbGluayBtb2R1bGU6b2wvbGF5ZXIvVmVjdG9yflZlY3RvckxheWVyfSBpbnN0ZWFkLlxuICAgKlxuICAgKiBAcGFyYW0ge2ltcG9ydChcIi4uLy4uL0ZlYXR1cmUuanNcIikuZGVmYXVsdH0gZmVhdHVyZSBGZWF0dXJlLlxuICAgKiBAcGFyYW0ge2ltcG9ydChcIi4uLy4uL3N0eWxlL1N0eWxlLmpzXCIpLmRlZmF1bHR9IHN0eWxlIFN0eWxlLlxuICAgKiBAYXBpXG4gICAqL1xuXG5cbiAgQ2FudmFzSW1tZWRpYXRlUmVuZGVyZXIucHJvdG90eXBlLmRyYXdGZWF0dXJlID0gZnVuY3Rpb24gKGZlYXR1cmUsIHN0eWxlKSB7XG4gICAgdmFyIGdlb21ldHJ5ID0gc3R5bGUuZ2V0R2VvbWV0cnlGdW5jdGlvbigpKGZlYXR1cmUpO1xuXG4gICAgaWYgKCFnZW9tZXRyeSB8fCAhaW50ZXJzZWN0cyh0aGlzLmV4dGVudF8sIGdlb21ldHJ5LmdldEV4dGVudCgpKSkge1xuICAgICAgcmV0dXJuO1xuICAgIH1cblxuICAgIHRoaXMuc2V0U3R5bGUoc3R5bGUpO1xuICAgIHRoaXMuZHJhd0dlb21ldHJ5KGdlb21ldHJ5KTtcbiAgfTtcbiAgLyoqXG4gICAqIFJlbmRlciBhIEdlb21ldHJ5Q29sbGVjdGlvbiB0byB0aGUgY2FudmFzLiAgUmVuZGVyaW5nIGlzIGltbWVkaWF0ZSBhbmRcbiAgICogdXNlcyB0aGUgY3VycmVudCBzdHlsZXMgYXBwcm9wcmlhdGUgZm9yIGVhY2ggZ2VvbWV0cnkgaW4gdGhlIGNvbGxlY3Rpb24uXG4gICAqXG4gICAqIEBwYXJhbSB7aW1wb3J0KFwiLi4vLi4vZ2VvbS9HZW9tZXRyeUNvbGxlY3Rpb24uanNcIikuZGVmYXVsdH0gZ2VvbWV0cnkgR2VvbWV0cnkgY29sbGVjdGlvbi5cbiAgICovXG5cblxuICBDYW52YXNJbW1lZGlhdGVSZW5kZXJlci5wcm90b3R5cGUuZHJhd0dlb21ldHJ5Q29sbGVjdGlvbiA9IGZ1bmN0aW9uIChnZW9tZXRyeSkge1xuICAgIHZhciBnZW9tZXRyaWVzID0gZ2VvbWV0cnkuZ2V0R2VvbWV0cmllc0FycmF5KCk7XG5cbiAgICBmb3IgKHZhciBpID0gMCwgaWkgPSBnZW9tZXRyaWVzLmxlbmd0aDsgaSA8IGlpOyArK2kpIHtcbiAgICAgIHRoaXMuZHJhd0dlb21ldHJ5KGdlb21ldHJpZXNbaV0pO1xuICAgIH1cbiAgfTtcbiAgLyoqXG4gICAqIFJlbmRlciBhIFBvaW50IGdlb21ldHJ5IGludG8gdGhlIGNhbnZhcy4gIFJlbmRlcmluZyBpcyBpbW1lZGlhdGUgYW5kIHVzZXNcbiAgICogdGhlIGN1cnJlbnQgc3R5bGUuXG4gICAqXG4gICAqIEBwYXJhbSB7aW1wb3J0KFwiLi4vLi4vZ2VvbS9Qb2ludC5qc1wiKS5kZWZhdWx0fGltcG9ydChcIi4uL0ZlYXR1cmUuanNcIikuZGVmYXVsdH0gZ2VvbWV0cnkgUG9pbnQgZ2VvbWV0cnkuXG4gICAqL1xuXG5cbiAgQ2FudmFzSW1tZWRpYXRlUmVuZGVyZXIucHJvdG90eXBlLmRyYXdQb2ludCA9IGZ1bmN0aW9uIChnZW9tZXRyeSkge1xuICAgIGlmICh0aGlzLnNxdWFyZWRUb2xlcmFuY2VfKSB7XG4gICAgICBnZW9tZXRyeSA9XG4gICAgICAvKiogQHR5cGUge2ltcG9ydChcIi4uLy4uL2dlb20vUG9pbnQuanNcIikuZGVmYXVsdH0gKi9cbiAgICAgIGdlb21ldHJ5LnNpbXBsaWZ5VHJhbnNmb3JtZWQodGhpcy5zcXVhcmVkVG9sZXJhbmNlXywgdGhpcy51c2VyVHJhbnNmb3JtXyk7XG4gICAgfVxuXG4gICAgdmFyIGZsYXRDb29yZGluYXRlcyA9IGdlb21ldHJ5LmdldEZsYXRDb29yZGluYXRlcygpO1xuICAgIHZhciBzdHJpZGUgPSBnZW9tZXRyeS5nZXRTdHJpZGUoKTtcblxuICAgIGlmICh0aGlzLmltYWdlXykge1xuICAgICAgdGhpcy5kcmF3SW1hZ2VzXyhmbGF0Q29vcmRpbmF0ZXMsIDAsIGZsYXRDb29yZGluYXRlcy5sZW5ndGgsIHN0cmlkZSk7XG4gICAgfVxuXG4gICAgaWYgKHRoaXMudGV4dF8gIT09ICcnKSB7XG4gICAgICB0aGlzLmRyYXdUZXh0XyhmbGF0Q29vcmRpbmF0ZXMsIDAsIGZsYXRDb29yZGluYXRlcy5sZW5ndGgsIHN0cmlkZSk7XG4gICAgfVxuICB9O1xuICAvKipcbiAgICogUmVuZGVyIGEgTXVsdGlQb2ludCBnZW9tZXRyeSAgaW50byB0aGUgY2FudmFzLiAgUmVuZGVyaW5nIGlzIGltbWVkaWF0ZSBhbmRcbiAgICogdXNlcyB0aGUgY3VycmVudCBzdHlsZS5cbiAgICpcbiAgICogQHBhcmFtIHtpbXBvcnQoXCIuLi8uLi9nZW9tL011bHRpUG9pbnQuanNcIikuZGVmYXVsdHxpbXBvcnQoXCIuLi9GZWF0dXJlLmpzXCIpLmRlZmF1bHR9IGdlb21ldHJ5IE11bHRpUG9pbnQgZ2VvbWV0cnkuXG4gICAqL1xuXG5cbiAgQ2FudmFzSW1tZWRpYXRlUmVuZGVyZXIucHJvdG90eXBlLmRyYXdNdWx0aVBvaW50ID0gZnVuY3Rpb24gKGdlb21ldHJ5KSB7XG4gICAgaWYgKHRoaXMuc3F1YXJlZFRvbGVyYW5jZV8pIHtcbiAgICAgIGdlb21ldHJ5ID1cbiAgICAgIC8qKiBAdHlwZSB7aW1wb3J0KFwiLi4vLi4vZ2VvbS9NdWx0aVBvaW50LmpzXCIpLmRlZmF1bHR9ICovXG4gICAgICBnZW9tZXRyeS5zaW1wbGlmeVRyYW5zZm9ybWVkKHRoaXMuc3F1YXJlZFRvbGVyYW5jZV8sIHRoaXMudXNlclRyYW5zZm9ybV8pO1xuICAgIH1cblxuICAgIHZhciBmbGF0Q29vcmRpbmF0ZXMgPSBnZW9tZXRyeS5nZXRGbGF0Q29vcmRpbmF0ZXMoKTtcbiAgICB2YXIgc3RyaWRlID0gZ2VvbWV0cnkuZ2V0U3RyaWRlKCk7XG5cbiAgICBpZiAodGhpcy5pbWFnZV8pIHtcbiAgICAgIHRoaXMuZHJhd0ltYWdlc18oZmxhdENvb3JkaW5hdGVzLCAwLCBmbGF0Q29vcmRpbmF0ZXMubGVuZ3RoLCBzdHJpZGUpO1xuICAgIH1cblxuICAgIGlmICh0aGlzLnRleHRfICE9PSAnJykge1xuICAgICAgdGhpcy5kcmF3VGV4dF8oZmxhdENvb3JkaW5hdGVzLCAwLCBmbGF0Q29vcmRpbmF0ZXMubGVuZ3RoLCBzdHJpZGUpO1xuICAgIH1cbiAgfTtcbiAgLyoqXG4gICAqIFJlbmRlciBhIExpbmVTdHJpbmcgaW50byB0aGUgY2FudmFzLiAgUmVuZGVyaW5nIGlzIGltbWVkaWF0ZSBhbmQgdXNlc1xuICAgKiB0aGUgY3VycmVudCBzdHlsZS5cbiAgICpcbiAgICogQHBhcmFtIHtpbXBvcnQoXCIuLi8uLi9nZW9tL0xpbmVTdHJpbmcuanNcIikuZGVmYXVsdHxpbXBvcnQoXCIuLi9GZWF0dXJlLmpzXCIpLmRlZmF1bHR9IGdlb21ldHJ5IExpbmVTdHJpbmcgZ2VvbWV0cnkuXG4gICAqL1xuXG5cbiAgQ2FudmFzSW1tZWRpYXRlUmVuZGVyZXIucHJvdG90eXBlLmRyYXdMaW5lU3RyaW5nID0gZnVuY3Rpb24gKGdlb21ldHJ5KSB7XG4gICAgaWYgKHRoaXMuc3F1YXJlZFRvbGVyYW5jZV8pIHtcbiAgICAgIGdlb21ldHJ5ID1cbiAgICAgIC8qKiBAdHlwZSB7aW1wb3J0KFwiLi4vLi4vZ2VvbS9MaW5lU3RyaW5nLmpzXCIpLmRlZmF1bHR9ICovXG4gICAgICBnZW9tZXRyeS5zaW1wbGlmeVRyYW5zZm9ybWVkKHRoaXMuc3F1YXJlZFRvbGVyYW5jZV8sIHRoaXMudXNlclRyYW5zZm9ybV8pO1xuICAgIH1cblxuICAgIGlmICghaW50ZXJzZWN0cyh0aGlzLmV4dGVudF8sIGdlb21ldHJ5LmdldEV4dGVudCgpKSkge1xuICAgICAgcmV0dXJuO1xuICAgIH1cblxuICAgIGlmICh0aGlzLnN0cm9rZVN0YXRlXykge1xuICAgICAgdGhpcy5zZXRDb250ZXh0U3Ryb2tlU3RhdGVfKHRoaXMuc3Ryb2tlU3RhdGVfKTtcbiAgICAgIHZhciBjb250ZXh0ID0gdGhpcy5jb250ZXh0XztcbiAgICAgIHZhciBmbGF0Q29vcmRpbmF0ZXMgPSBnZW9tZXRyeS5nZXRGbGF0Q29vcmRpbmF0ZXMoKTtcbiAgICAgIGNvbnRleHQuYmVnaW5QYXRoKCk7XG4gICAgICB0aGlzLm1vdmVUb0xpbmVUb18oZmxhdENvb3JkaW5hdGVzLCAwLCBmbGF0Q29vcmRpbmF0ZXMubGVuZ3RoLCBnZW9tZXRyeS5nZXRTdHJpZGUoKSwgZmFsc2UpO1xuICAgICAgY29udGV4dC5zdHJva2UoKTtcbiAgICB9XG5cbiAgICBpZiAodGhpcy50ZXh0XyAhPT0gJycpIHtcbiAgICAgIHZhciBmbGF0TWlkcG9pbnQgPSBnZW9tZXRyeS5nZXRGbGF0TWlkcG9pbnQoKTtcbiAgICAgIHRoaXMuZHJhd1RleHRfKGZsYXRNaWRwb2ludCwgMCwgMiwgMik7XG4gICAgfVxuICB9O1xuICAvKipcbiAgICogUmVuZGVyIGEgTXVsdGlMaW5lU3RyaW5nIGdlb21ldHJ5IGludG8gdGhlIGNhbnZhcy4gIFJlbmRlcmluZyBpcyBpbW1lZGlhdGVcbiAgICogYW5kIHVzZXMgdGhlIGN1cnJlbnQgc3R5bGUuXG4gICAqXG4gICAqIEBwYXJhbSB7aW1wb3J0KFwiLi4vLi4vZ2VvbS9NdWx0aUxpbmVTdHJpbmcuanNcIikuZGVmYXVsdHxpbXBvcnQoXCIuLi9GZWF0dXJlLmpzXCIpLmRlZmF1bHR9IGdlb21ldHJ5IE11bHRpTGluZVN0cmluZyBnZW9tZXRyeS5cbiAgICovXG5cblxuICBDYW52YXNJbW1lZGlhdGVSZW5kZXJlci5wcm90b3R5cGUuZHJhd011bHRpTGluZVN0cmluZyA9IGZ1bmN0aW9uIChnZW9tZXRyeSkge1xuICAgIGlmICh0aGlzLnNxdWFyZWRUb2xlcmFuY2VfKSB7XG4gICAgICBnZW9tZXRyeSA9XG4gICAgICAvKiogQHR5cGUge2ltcG9ydChcIi4uLy4uL2dlb20vTXVsdGlMaW5lU3RyaW5nLmpzXCIpLmRlZmF1bHR9ICovXG4gICAgICBnZW9tZXRyeS5zaW1wbGlmeVRyYW5zZm9ybWVkKHRoaXMuc3F1YXJlZFRvbGVyYW5jZV8sIHRoaXMudXNlclRyYW5zZm9ybV8pO1xuICAgIH1cblxuICAgIHZhciBnZW9tZXRyeUV4dGVudCA9IGdlb21ldHJ5LmdldEV4dGVudCgpO1xuXG4gICAgaWYgKCFpbnRlcnNlY3RzKHRoaXMuZXh0ZW50XywgZ2VvbWV0cnlFeHRlbnQpKSB7XG4gICAgICByZXR1cm47XG4gICAgfVxuXG4gICAgaWYgKHRoaXMuc3Ryb2tlU3RhdGVfKSB7XG4gICAgICB0aGlzLnNldENvbnRleHRTdHJva2VTdGF0ZV8odGhpcy5zdHJva2VTdGF0ZV8pO1xuICAgICAgdmFyIGNvbnRleHQgPSB0aGlzLmNvbnRleHRfO1xuICAgICAgdmFyIGZsYXRDb29yZGluYXRlcyA9IGdlb21ldHJ5LmdldEZsYXRDb29yZGluYXRlcygpO1xuICAgICAgdmFyIG9mZnNldCA9IDA7XG4gICAgICB2YXIgZW5kcyA9XG4gICAgICAvKiogQHR5cGUge0FycmF5PG51bWJlcj59ICovXG4gICAgICBnZW9tZXRyeS5nZXRFbmRzKCk7XG4gICAgICB2YXIgc3RyaWRlID0gZ2VvbWV0cnkuZ2V0U3RyaWRlKCk7XG4gICAgICBjb250ZXh0LmJlZ2luUGF0aCgpO1xuXG4gICAgICBmb3IgKHZhciBpID0gMCwgaWkgPSBlbmRzLmxlbmd0aDsgaSA8IGlpOyArK2kpIHtcbiAgICAgICAgb2Zmc2V0ID0gdGhpcy5tb3ZlVG9MaW5lVG9fKGZsYXRDb29yZGluYXRlcywgb2Zmc2V0LCBlbmRzW2ldLCBzdHJpZGUsIGZhbHNlKTtcbiAgICAgIH1cblxuICAgICAgY29udGV4dC5zdHJva2UoKTtcbiAgICB9XG5cbiAgICBpZiAodGhpcy50ZXh0XyAhPT0gJycpIHtcbiAgICAgIHZhciBmbGF0TWlkcG9pbnRzID0gZ2VvbWV0cnkuZ2V0RmxhdE1pZHBvaW50cygpO1xuICAgICAgdGhpcy5kcmF3VGV4dF8oZmxhdE1pZHBvaW50cywgMCwgZmxhdE1pZHBvaW50cy5sZW5ndGgsIDIpO1xuICAgIH1cbiAgfTtcbiAgLyoqXG4gICAqIFJlbmRlciBhIFBvbHlnb24gZ2VvbWV0cnkgaW50byB0aGUgY2FudmFzLiAgUmVuZGVyaW5nIGlzIGltbWVkaWF0ZSBhbmQgdXNlc1xuICAgKiB0aGUgY3VycmVudCBzdHlsZS5cbiAgICpcbiAgICogQHBhcmFtIHtpbXBvcnQoXCIuLi8uLi9nZW9tL1BvbHlnb24uanNcIikuZGVmYXVsdHxpbXBvcnQoXCIuLi9GZWF0dXJlLmpzXCIpLmRlZmF1bHR9IGdlb21ldHJ5IFBvbHlnb24gZ2VvbWV0cnkuXG4gICAqL1xuXG5cbiAgQ2FudmFzSW1tZWRpYXRlUmVuZGVyZXIucHJvdG90eXBlLmRyYXdQb2x5Z29uID0gZnVuY3Rpb24gKGdlb21ldHJ5KSB7XG4gICAgaWYgKHRoaXMuc3F1YXJlZFRvbGVyYW5jZV8pIHtcbiAgICAgIGdlb21ldHJ5ID1cbiAgICAgIC8qKiBAdHlwZSB7aW1wb3J0KFwiLi4vLi4vZ2VvbS9Qb2x5Z29uLmpzXCIpLmRlZmF1bHR9ICovXG4gICAgICBnZW9tZXRyeS5zaW1wbGlmeVRyYW5zZm9ybWVkKHRoaXMuc3F1YXJlZFRvbGVyYW5jZV8sIHRoaXMudXNlclRyYW5zZm9ybV8pO1xuICAgIH1cblxuICAgIGlmICghaW50ZXJzZWN0cyh0aGlzLmV4dGVudF8sIGdlb21ldHJ5LmdldEV4dGVudCgpKSkge1xuICAgICAgcmV0dXJuO1xuICAgIH1cblxuICAgIGlmICh0aGlzLnN0cm9rZVN0YXRlXyB8fCB0aGlzLmZpbGxTdGF0ZV8pIHtcbiAgICAgIGlmICh0aGlzLmZpbGxTdGF0ZV8pIHtcbiAgICAgICAgdGhpcy5zZXRDb250ZXh0RmlsbFN0YXRlXyh0aGlzLmZpbGxTdGF0ZV8pO1xuICAgICAgfVxuXG4gICAgICBpZiAodGhpcy5zdHJva2VTdGF0ZV8pIHtcbiAgICAgICAgdGhpcy5zZXRDb250ZXh0U3Ryb2tlU3RhdGVfKHRoaXMuc3Ryb2tlU3RhdGVfKTtcbiAgICAgIH1cblxuICAgICAgdmFyIGNvbnRleHQgPSB0aGlzLmNvbnRleHRfO1xuICAgICAgY29udGV4dC5iZWdpblBhdGgoKTtcbiAgICAgIHRoaXMuZHJhd1JpbmdzXyhnZW9tZXRyeS5nZXRPcmllbnRlZEZsYXRDb29yZGluYXRlcygpLCAwLFxuICAgICAgLyoqIEB0eXBlIHtBcnJheTxudW1iZXI+fSAqL1xuICAgICAgZ2VvbWV0cnkuZ2V0RW5kcygpLCBnZW9tZXRyeS5nZXRTdHJpZGUoKSk7XG5cbiAgICAgIGlmICh0aGlzLmZpbGxTdGF0ZV8pIHtcbiAgICAgICAgY29udGV4dC5maWxsKCk7XG4gICAgICB9XG5cbiAgICAgIGlmICh0aGlzLnN0cm9rZVN0YXRlXykge1xuICAgICAgICBjb250ZXh0LnN0cm9rZSgpO1xuICAgICAgfVxuICAgIH1cblxuICAgIGlmICh0aGlzLnRleHRfICE9PSAnJykge1xuICAgICAgdmFyIGZsYXRJbnRlcmlvclBvaW50ID0gZ2VvbWV0cnkuZ2V0RmxhdEludGVyaW9yUG9pbnQoKTtcbiAgICAgIHRoaXMuZHJhd1RleHRfKGZsYXRJbnRlcmlvclBvaW50LCAwLCAyLCAyKTtcbiAgICB9XG4gIH07XG4gIC8qKlxuICAgKiBSZW5kZXIgTXVsdGlQb2x5Z29uIGdlb21ldHJ5IGludG8gdGhlIGNhbnZhcy4gIFJlbmRlcmluZyBpcyBpbW1lZGlhdGUgYW5kXG4gICAqIHVzZXMgdGhlIGN1cnJlbnQgc3R5bGUuXG4gICAqIEBwYXJhbSB7aW1wb3J0KFwiLi4vLi4vZ2VvbS9NdWx0aVBvbHlnb24uanNcIikuZGVmYXVsdH0gZ2VvbWV0cnkgTXVsdGlQb2x5Z29uIGdlb21ldHJ5LlxuICAgKi9cblxuXG4gIENhbnZhc0ltbWVkaWF0ZVJlbmRlcmVyLnByb3RvdHlwZS5kcmF3TXVsdGlQb2x5Z29uID0gZnVuY3Rpb24gKGdlb21ldHJ5KSB7XG4gICAgaWYgKHRoaXMuc3F1YXJlZFRvbGVyYW5jZV8pIHtcbiAgICAgIGdlb21ldHJ5ID1cbiAgICAgIC8qKiBAdHlwZSB7aW1wb3J0KFwiLi4vLi4vZ2VvbS9NdWx0aVBvbHlnb24uanNcIikuZGVmYXVsdH0gKi9cbiAgICAgIGdlb21ldHJ5LnNpbXBsaWZ5VHJhbnNmb3JtZWQodGhpcy5zcXVhcmVkVG9sZXJhbmNlXywgdGhpcy51c2VyVHJhbnNmb3JtXyk7XG4gICAgfVxuXG4gICAgaWYgKCFpbnRlcnNlY3RzKHRoaXMuZXh0ZW50XywgZ2VvbWV0cnkuZ2V0RXh0ZW50KCkpKSB7XG4gICAgICByZXR1cm47XG4gICAgfVxuXG4gICAgaWYgKHRoaXMuc3Ryb2tlU3RhdGVfIHx8IHRoaXMuZmlsbFN0YXRlXykge1xuICAgICAgaWYgKHRoaXMuZmlsbFN0YXRlXykge1xuICAgICAgICB0aGlzLnNldENvbnRleHRGaWxsU3RhdGVfKHRoaXMuZmlsbFN0YXRlXyk7XG4gICAgICB9XG5cbiAgICAgIGlmICh0aGlzLnN0cm9rZVN0YXRlXykge1xuICAgICAgICB0aGlzLnNldENvbnRleHRTdHJva2VTdGF0ZV8odGhpcy5zdHJva2VTdGF0ZV8pO1xuICAgICAgfVxuXG4gICAgICB2YXIgY29udGV4dCA9IHRoaXMuY29udGV4dF87XG4gICAgICB2YXIgZmxhdENvb3JkaW5hdGVzID0gZ2VvbWV0cnkuZ2V0T3JpZW50ZWRGbGF0Q29vcmRpbmF0ZXMoKTtcbiAgICAgIHZhciBvZmZzZXQgPSAwO1xuICAgICAgdmFyIGVuZHNzID0gZ2VvbWV0cnkuZ2V0RW5kc3MoKTtcbiAgICAgIHZhciBzdHJpZGUgPSBnZW9tZXRyeS5nZXRTdHJpZGUoKTtcbiAgICAgIGNvbnRleHQuYmVnaW5QYXRoKCk7XG5cbiAgICAgIGZvciAodmFyIGkgPSAwLCBpaSA9IGVuZHNzLmxlbmd0aDsgaSA8IGlpOyArK2kpIHtcbiAgICAgICAgdmFyIGVuZHMgPSBlbmRzc1tpXTtcbiAgICAgICAgb2Zmc2V0ID0gdGhpcy5kcmF3UmluZ3NfKGZsYXRDb29yZGluYXRlcywgb2Zmc2V0LCBlbmRzLCBzdHJpZGUpO1xuICAgICAgfVxuXG4gICAgICBpZiAodGhpcy5maWxsU3RhdGVfKSB7XG4gICAgICAgIGNvbnRleHQuZmlsbCgpO1xuICAgICAgfVxuXG4gICAgICBpZiAodGhpcy5zdHJva2VTdGF0ZV8pIHtcbiAgICAgICAgY29udGV4dC5zdHJva2UoKTtcbiAgICAgIH1cbiAgICB9XG5cbiAgICBpZiAodGhpcy50ZXh0XyAhPT0gJycpIHtcbiAgICAgIHZhciBmbGF0SW50ZXJpb3JQb2ludHMgPSBnZW9tZXRyeS5nZXRGbGF0SW50ZXJpb3JQb2ludHMoKTtcbiAgICAgIHRoaXMuZHJhd1RleHRfKGZsYXRJbnRlcmlvclBvaW50cywgMCwgZmxhdEludGVyaW9yUG9pbnRzLmxlbmd0aCwgMik7XG4gICAgfVxuICB9O1xuICAvKipcbiAgICogQHBhcmFtIHtpbXBvcnQoXCIuLi9jYW52YXMuanNcIikuRmlsbFN0YXRlfSBmaWxsU3RhdGUgRmlsbCBzdGF0ZS5cbiAgICogQHByaXZhdGVcbiAgICovXG5cblxuICBDYW52YXNJbW1lZGlhdGVSZW5kZXJlci5wcm90b3R5cGUuc2V0Q29udGV4dEZpbGxTdGF0ZV8gPSBmdW5jdGlvbiAoZmlsbFN0YXRlKSB7XG4gICAgdmFyIGNvbnRleHQgPSB0aGlzLmNvbnRleHRfO1xuICAgIHZhciBjb250ZXh0RmlsbFN0YXRlID0gdGhpcy5jb250ZXh0RmlsbFN0YXRlXztcblxuICAgIGlmICghY29udGV4dEZpbGxTdGF0ZSkge1xuICAgICAgY29udGV4dC5maWxsU3R5bGUgPSBmaWxsU3RhdGUuZmlsbFN0eWxlO1xuICAgICAgdGhpcy5jb250ZXh0RmlsbFN0YXRlXyA9IHtcbiAgICAgICAgZmlsbFN0eWxlOiBmaWxsU3RhdGUuZmlsbFN0eWxlXG4gICAgICB9O1xuICAgIH0gZWxzZSB7XG4gICAgICBpZiAoY29udGV4dEZpbGxTdGF0ZS5maWxsU3R5bGUgIT0gZmlsbFN0YXRlLmZpbGxTdHlsZSkge1xuICAgICAgICBjb250ZXh0RmlsbFN0YXRlLmZpbGxTdHlsZSA9IGZpbGxTdGF0ZS5maWxsU3R5bGU7XG4gICAgICAgIGNvbnRleHQuZmlsbFN0eWxlID0gZmlsbFN0YXRlLmZpbGxTdHlsZTtcbiAgICAgIH1cbiAgICB9XG4gIH07XG4gIC8qKlxuICAgKiBAcGFyYW0ge2ltcG9ydChcIi4uL2NhbnZhcy5qc1wiKS5TdHJva2VTdGF0ZX0gc3Ryb2tlU3RhdGUgU3Ryb2tlIHN0YXRlLlxuICAgKiBAcHJpdmF0ZVxuICAgKi9cblxuXG4gIENhbnZhc0ltbWVkaWF0ZVJlbmRlcmVyLnByb3RvdHlwZS5zZXRDb250ZXh0U3Ryb2tlU3RhdGVfID0gZnVuY3Rpb24gKHN0cm9rZVN0YXRlKSB7XG4gICAgdmFyIGNvbnRleHQgPSB0aGlzLmNvbnRleHRfO1xuICAgIHZhciBjb250ZXh0U3Ryb2tlU3RhdGUgPSB0aGlzLmNvbnRleHRTdHJva2VTdGF0ZV87XG5cbiAgICBpZiAoIWNvbnRleHRTdHJva2VTdGF0ZSkge1xuICAgICAgY29udGV4dC5saW5lQ2FwID0gc3Ryb2tlU3RhdGUubGluZUNhcDtcblxuICAgICAgaWYgKGNvbnRleHQuc2V0TGluZURhc2gpIHtcbiAgICAgICAgY29udGV4dC5zZXRMaW5lRGFzaChzdHJva2VTdGF0ZS5saW5lRGFzaCk7XG4gICAgICAgIGNvbnRleHQubGluZURhc2hPZmZzZXQgPSBzdHJva2VTdGF0ZS5saW5lRGFzaE9mZnNldDtcbiAgICAgIH1cblxuICAgICAgY29udGV4dC5saW5lSm9pbiA9IHN0cm9rZVN0YXRlLmxpbmVKb2luO1xuICAgICAgY29udGV4dC5saW5lV2lkdGggPSBzdHJva2VTdGF0ZS5saW5lV2lkdGg7XG4gICAgICBjb250ZXh0Lm1pdGVyTGltaXQgPSBzdHJva2VTdGF0ZS5taXRlckxpbWl0O1xuICAgICAgY29udGV4dC5zdHJva2VTdHlsZSA9IHN0cm9rZVN0YXRlLnN0cm9rZVN0eWxlO1xuICAgICAgdGhpcy5jb250ZXh0U3Ryb2tlU3RhdGVfID0ge1xuICAgICAgICBsaW5lQ2FwOiBzdHJva2VTdGF0ZS5saW5lQ2FwLFxuICAgICAgICBsaW5lRGFzaDogc3Ryb2tlU3RhdGUubGluZURhc2gsXG4gICAgICAgIGxpbmVEYXNoT2Zmc2V0OiBzdHJva2VTdGF0ZS5saW5lRGFzaE9mZnNldCxcbiAgICAgICAgbGluZUpvaW46IHN0cm9rZVN0YXRlLmxpbmVKb2luLFxuICAgICAgICBsaW5lV2lkdGg6IHN0cm9rZVN0YXRlLmxpbmVXaWR0aCxcbiAgICAgICAgbWl0ZXJMaW1pdDogc3Ryb2tlU3RhdGUubWl0ZXJMaW1pdCxcbiAgICAgICAgc3Ryb2tlU3R5bGU6IHN0cm9rZVN0YXRlLnN0cm9rZVN0eWxlXG4gICAgICB9O1xuICAgIH0gZWxzZSB7XG4gICAgICBpZiAoY29udGV4dFN0cm9rZVN0YXRlLmxpbmVDYXAgIT0gc3Ryb2tlU3RhdGUubGluZUNhcCkge1xuICAgICAgICBjb250ZXh0U3Ryb2tlU3RhdGUubGluZUNhcCA9IHN0cm9rZVN0YXRlLmxpbmVDYXA7XG4gICAgICAgIGNvbnRleHQubGluZUNhcCA9IHN0cm9rZVN0YXRlLmxpbmVDYXA7XG4gICAgICB9XG5cbiAgICAgIGlmIChjb250ZXh0LnNldExpbmVEYXNoKSB7XG4gICAgICAgIGlmICghZXF1YWxzKGNvbnRleHRTdHJva2VTdGF0ZS5saW5lRGFzaCwgc3Ryb2tlU3RhdGUubGluZURhc2gpKSB7XG4gICAgICAgICAgY29udGV4dC5zZXRMaW5lRGFzaChjb250ZXh0U3Ryb2tlU3RhdGUubGluZURhc2ggPSBzdHJva2VTdGF0ZS5saW5lRGFzaCk7XG4gICAgICAgIH1cblxuICAgICAgICBpZiAoY29udGV4dFN0cm9rZVN0YXRlLmxpbmVEYXNoT2Zmc2V0ICE9IHN0cm9rZVN0YXRlLmxpbmVEYXNoT2Zmc2V0KSB7XG4gICAgICAgICAgY29udGV4dFN0cm9rZVN0YXRlLmxpbmVEYXNoT2Zmc2V0ID0gc3Ryb2tlU3RhdGUubGluZURhc2hPZmZzZXQ7XG4gICAgICAgICAgY29udGV4dC5saW5lRGFzaE9mZnNldCA9IHN0cm9rZVN0YXRlLmxpbmVEYXNoT2Zmc2V0O1xuICAgICAgICB9XG4gICAgICB9XG5cbiAgICAgIGlmIChjb250ZXh0U3Ryb2tlU3RhdGUubGluZUpvaW4gIT0gc3Ryb2tlU3RhdGUubGluZUpvaW4pIHtcbiAgICAgICAgY29udGV4dFN0cm9rZVN0YXRlLmxpbmVKb2luID0gc3Ryb2tlU3RhdGUubGluZUpvaW47XG4gICAgICAgIGNvbnRleHQubGluZUpvaW4gPSBzdHJva2VTdGF0ZS5saW5lSm9pbjtcbiAgICAgIH1cblxuICAgICAgaWYgKGNvbnRleHRTdHJva2VTdGF0ZS5saW5lV2lkdGggIT0gc3Ryb2tlU3RhdGUubGluZVdpZHRoKSB7XG4gICAgICAgIGNvbnRleHRTdHJva2VTdGF0ZS5saW5lV2lkdGggPSBzdHJva2VTdGF0ZS5saW5lV2lkdGg7XG4gICAgICAgIGNvbnRleHQubGluZVdpZHRoID0gc3Ryb2tlU3RhdGUubGluZVdpZHRoO1xuICAgICAgfVxuXG4gICAgICBpZiAoY29udGV4dFN0cm9rZVN0YXRlLm1pdGVyTGltaXQgIT0gc3Ryb2tlU3RhdGUubWl0ZXJMaW1pdCkge1xuICAgICAgICBjb250ZXh0U3Ryb2tlU3RhdGUubWl0ZXJMaW1pdCA9IHN0cm9rZVN0YXRlLm1pdGVyTGltaXQ7XG4gICAgICAgIGNvbnRleHQubWl0ZXJMaW1pdCA9IHN0cm9rZVN0YXRlLm1pdGVyTGltaXQ7XG4gICAgICB9XG5cbiAgICAgIGlmIChjb250ZXh0U3Ryb2tlU3RhdGUuc3Ryb2tlU3R5bGUgIT0gc3Ryb2tlU3RhdGUuc3Ryb2tlU3R5bGUpIHtcbiAgICAgICAgY29udGV4dFN0cm9rZVN0YXRlLnN0cm9rZVN0eWxlID0gc3Ryb2tlU3RhdGUuc3Ryb2tlU3R5bGU7XG4gICAgICAgIGNvbnRleHQuc3Ryb2tlU3R5bGUgPSBzdHJva2VTdGF0ZS5zdHJva2VTdHlsZTtcbiAgICAgIH1cbiAgICB9XG4gIH07XG4gIC8qKlxuICAgKiBAcGFyYW0ge2ltcG9ydChcIi4uL2NhbnZhcy5qc1wiKS5UZXh0U3RhdGV9IHRleHRTdGF0ZSBUZXh0IHN0YXRlLlxuICAgKiBAcHJpdmF0ZVxuICAgKi9cblxuXG4gIENhbnZhc0ltbWVkaWF0ZVJlbmRlcmVyLnByb3RvdHlwZS5zZXRDb250ZXh0VGV4dFN0YXRlXyA9IGZ1bmN0aW9uICh0ZXh0U3RhdGUpIHtcbiAgICB2YXIgY29udGV4dCA9IHRoaXMuY29udGV4dF87XG4gICAgdmFyIGNvbnRleHRUZXh0U3RhdGUgPSB0aGlzLmNvbnRleHRUZXh0U3RhdGVfO1xuICAgIHZhciB0ZXh0QWxpZ24gPSB0ZXh0U3RhdGUudGV4dEFsaWduID8gdGV4dFN0YXRlLnRleHRBbGlnbiA6IGRlZmF1bHRUZXh0QWxpZ247XG5cbiAgICBpZiAoIWNvbnRleHRUZXh0U3RhdGUpIHtcbiAgICAgIGNvbnRleHQuZm9udCA9IHRleHRTdGF0ZS5mb250O1xuICAgICAgY29udGV4dC50ZXh0QWxpZ24gPVxuICAgICAgLyoqIEB0eXBlIHtDYW52YXNUZXh0QWxpZ259ICovXG4gICAgICB0ZXh0QWxpZ247XG4gICAgICBjb250ZXh0LnRleHRCYXNlbGluZSA9XG4gICAgICAvKiogQHR5cGUge0NhbnZhc1RleHRCYXNlbGluZX0gKi9cbiAgICAgIHRleHRTdGF0ZS50ZXh0QmFzZWxpbmU7XG4gICAgICB0aGlzLmNvbnRleHRUZXh0U3RhdGVfID0ge1xuICAgICAgICBmb250OiB0ZXh0U3RhdGUuZm9udCxcbiAgICAgICAgdGV4dEFsaWduOiB0ZXh0QWxpZ24sXG4gICAgICAgIHRleHRCYXNlbGluZTogdGV4dFN0YXRlLnRleHRCYXNlbGluZVxuICAgICAgfTtcbiAgICB9IGVsc2Uge1xuICAgICAgaWYgKGNvbnRleHRUZXh0U3RhdGUuZm9udCAhPSB0ZXh0U3RhdGUuZm9udCkge1xuICAgICAgICBjb250ZXh0VGV4dFN0YXRlLmZvbnQgPSB0ZXh0U3RhdGUuZm9udDtcbiAgICAgICAgY29udGV4dC5mb250ID0gdGV4dFN0YXRlLmZvbnQ7XG4gICAgICB9XG5cbiAgICAgIGlmIChjb250ZXh0VGV4dFN0YXRlLnRleHRBbGlnbiAhPSB0ZXh0QWxpZ24pIHtcbiAgICAgICAgY29udGV4dFRleHRTdGF0ZS50ZXh0QWxpZ24gPVxuICAgICAgICAvKiogQHR5cGUge0NhbnZhc1RleHRBbGlnbn0gKi9cbiAgICAgICAgdGV4dEFsaWduO1xuICAgICAgICBjb250ZXh0LnRleHRBbGlnbiA9XG4gICAgICAgIC8qKiBAdHlwZSB7Q2FudmFzVGV4dEFsaWdufSAqL1xuICAgICAgICB0ZXh0QWxpZ247XG4gICAgICB9XG5cbiAgICAgIGlmIChjb250ZXh0VGV4dFN0YXRlLnRleHRCYXNlbGluZSAhPSB0ZXh0U3RhdGUudGV4dEJhc2VsaW5lKSB7XG4gICAgICAgIGNvbnRleHRUZXh0U3RhdGUudGV4dEJhc2VsaW5lID1cbiAgICAgICAgLyoqIEB0eXBlIHtDYW52YXNUZXh0QmFzZWxpbmV9ICovXG4gICAgICAgIHRleHRTdGF0ZS50ZXh0QmFzZWxpbmU7XG4gICAgICAgIGNvbnRleHQudGV4dEJhc2VsaW5lID1cbiAgICAgICAgLyoqIEB0eXBlIHtDYW52YXNUZXh0QmFzZWxpbmV9ICovXG4gICAgICAgIHRleHRTdGF0ZS50ZXh0QmFzZWxpbmU7XG4gICAgICB9XG4gICAgfVxuICB9O1xuICAvKipcbiAgICogU2V0IHRoZSBmaWxsIGFuZCBzdHJva2Ugc3R5bGUgZm9yIHN1YnNlcXVlbnQgZHJhdyBvcGVyYXRpb25zLiAgVG8gY2xlYXJcbiAgICogZWl0aGVyIGZpbGwgb3Igc3Ryb2tlIHN0eWxlcywgcGFzcyBudWxsIGZvciB0aGUgYXBwcm9wcmlhdGUgcGFyYW1ldGVyLlxuICAgKlxuICAgKiBAcGFyYW0ge2ltcG9ydChcIi4uLy4uL3N0eWxlL0ZpbGwuanNcIikuZGVmYXVsdH0gZmlsbFN0eWxlIEZpbGwgc3R5bGUuXG4gICAqIEBwYXJhbSB7aW1wb3J0KFwiLi4vLi4vc3R5bGUvU3Ryb2tlLmpzXCIpLmRlZmF1bHR9IHN0cm9rZVN0eWxlIFN0cm9rZSBzdHlsZS5cbiAgICovXG5cblxuICBDYW52YXNJbW1lZGlhdGVSZW5kZXJlci5wcm90b3R5cGUuc2V0RmlsbFN0cm9rZVN0eWxlID0gZnVuY3Rpb24gKGZpbGxTdHlsZSwgc3Ryb2tlU3R5bGUpIHtcbiAgICBpZiAoIWZpbGxTdHlsZSkge1xuICAgICAgdGhpcy5maWxsU3RhdGVfID0gbnVsbDtcbiAgICB9IGVsc2Uge1xuICAgICAgdmFyIGZpbGxTdHlsZUNvbG9yID0gZmlsbFN0eWxlLmdldENvbG9yKCk7XG4gICAgICB0aGlzLmZpbGxTdGF0ZV8gPSB7XG4gICAgICAgIGZpbGxTdHlsZTogYXNDb2xvckxpa2UoZmlsbFN0eWxlQ29sb3IgPyBmaWxsU3R5bGVDb2xvciA6IGRlZmF1bHRGaWxsU3R5bGUpXG4gICAgICB9O1xuICAgIH1cblxuICAgIGlmICghc3Ryb2tlU3R5bGUpIHtcbiAgICAgIHRoaXMuc3Ryb2tlU3RhdGVfID0gbnVsbDtcbiAgICB9IGVsc2Uge1xuICAgICAgdmFyIHN0cm9rZVN0eWxlQ29sb3IgPSBzdHJva2VTdHlsZS5nZXRDb2xvcigpO1xuICAgICAgdmFyIHN0cm9rZVN0eWxlTGluZUNhcCA9IHN0cm9rZVN0eWxlLmdldExpbmVDYXAoKTtcbiAgICAgIHZhciBzdHJva2VTdHlsZUxpbmVEYXNoID0gc3Ryb2tlU3R5bGUuZ2V0TGluZURhc2goKTtcbiAgICAgIHZhciBzdHJva2VTdHlsZUxpbmVEYXNoT2Zmc2V0ID0gc3Ryb2tlU3R5bGUuZ2V0TGluZURhc2hPZmZzZXQoKTtcbiAgICAgIHZhciBzdHJva2VTdHlsZUxpbmVKb2luID0gc3Ryb2tlU3R5bGUuZ2V0TGluZUpvaW4oKTtcbiAgICAgIHZhciBzdHJva2VTdHlsZVdpZHRoID0gc3Ryb2tlU3R5bGUuZ2V0V2lkdGgoKTtcbiAgICAgIHZhciBzdHJva2VTdHlsZU1pdGVyTGltaXQgPSBzdHJva2VTdHlsZS5nZXRNaXRlckxpbWl0KCk7XG4gICAgICB0aGlzLnN0cm9rZVN0YXRlXyA9IHtcbiAgICAgICAgbGluZUNhcDogc3Ryb2tlU3R5bGVMaW5lQ2FwICE9PSB1bmRlZmluZWQgPyBzdHJva2VTdHlsZUxpbmVDYXAgOiBkZWZhdWx0TGluZUNhcCxcbiAgICAgICAgbGluZURhc2g6IHN0cm9rZVN0eWxlTGluZURhc2ggPyBzdHJva2VTdHlsZUxpbmVEYXNoIDogZGVmYXVsdExpbmVEYXNoLFxuICAgICAgICBsaW5lRGFzaE9mZnNldDogc3Ryb2tlU3R5bGVMaW5lRGFzaE9mZnNldCA/IHN0cm9rZVN0eWxlTGluZURhc2hPZmZzZXQgOiBkZWZhdWx0TGluZURhc2hPZmZzZXQsXG4gICAgICAgIGxpbmVKb2luOiBzdHJva2VTdHlsZUxpbmVKb2luICE9PSB1bmRlZmluZWQgPyBzdHJva2VTdHlsZUxpbmVKb2luIDogZGVmYXVsdExpbmVKb2luLFxuICAgICAgICBsaW5lV2lkdGg6IHRoaXMucGl4ZWxSYXRpb18gKiAoc3Ryb2tlU3R5bGVXaWR0aCAhPT0gdW5kZWZpbmVkID8gc3Ryb2tlU3R5bGVXaWR0aCA6IGRlZmF1bHRMaW5lV2lkdGgpLFxuICAgICAgICBtaXRlckxpbWl0OiBzdHJva2VTdHlsZU1pdGVyTGltaXQgIT09IHVuZGVmaW5lZCA/IHN0cm9rZVN0eWxlTWl0ZXJMaW1pdCA6IGRlZmF1bHRNaXRlckxpbWl0LFxuICAgICAgICBzdHJva2VTdHlsZTogYXNDb2xvckxpa2Uoc3Ryb2tlU3R5bGVDb2xvciA/IHN0cm9rZVN0eWxlQ29sb3IgOiBkZWZhdWx0U3Ryb2tlU3R5bGUpXG4gICAgICB9O1xuICAgIH1cbiAgfTtcbiAgLyoqXG4gICAqIFNldCB0aGUgaW1hZ2Ugc3R5bGUgZm9yIHN1YnNlcXVlbnQgZHJhdyBvcGVyYXRpb25zLiAgUGFzcyBudWxsIHRvIHJlbW92ZVxuICAgKiB0aGUgaW1hZ2Ugc3R5bGUuXG4gICAqXG4gICAqIEBwYXJhbSB7aW1wb3J0KFwiLi4vLi4vc3R5bGUvSW1hZ2UuanNcIikuZGVmYXVsdH0gaW1hZ2VTdHlsZSBJbWFnZSBzdHlsZS5cbiAgICovXG5cblxuICBDYW52YXNJbW1lZGlhdGVSZW5kZXJlci5wcm90b3R5cGUuc2V0SW1hZ2VTdHlsZSA9IGZ1bmN0aW9uIChpbWFnZVN0eWxlKSB7XG4gICAgaWYgKCFpbWFnZVN0eWxlKSB7XG4gICAgICB0aGlzLmltYWdlXyA9IG51bGw7XG4gICAgfSBlbHNlIHtcbiAgICAgIHZhciBpbWFnZVNpemUgPSBpbWFnZVN0eWxlLmdldFNpemUoKTtcblxuICAgICAgaWYgKCFpbWFnZVNpemUpIHtcbiAgICAgICAgdGhpcy5pbWFnZV8gPSBudWxsO1xuICAgICAgfSBlbHNlIHtcbiAgICAgICAgdmFyIGltYWdlQW5jaG9yID0gaW1hZ2VTdHlsZS5nZXRBbmNob3IoKTsgLy8gRklYTUUgcGl4ZWwgcmF0aW9cblxuICAgICAgICB2YXIgaW1hZ2VJbWFnZSA9IGltYWdlU3R5bGUuZ2V0SW1hZ2UoMSk7XG4gICAgICAgIHZhciBpbWFnZU9yaWdpbiA9IGltYWdlU3R5bGUuZ2V0T3JpZ2luKCk7XG4gICAgICAgIHZhciBpbWFnZVNjYWxlID0gaW1hZ2VTdHlsZS5nZXRTY2FsZUFycmF5KCk7XG4gICAgICAgIHRoaXMuaW1hZ2VBbmNob3JYXyA9IGltYWdlQW5jaG9yWzBdO1xuICAgICAgICB0aGlzLmltYWdlQW5jaG9yWV8gPSBpbWFnZUFuY2hvclsxXTtcbiAgICAgICAgdGhpcy5pbWFnZUhlaWdodF8gPSBpbWFnZVNpemVbMV07XG4gICAgICAgIHRoaXMuaW1hZ2VfID0gaW1hZ2VJbWFnZTtcbiAgICAgICAgdGhpcy5pbWFnZU9wYWNpdHlfID0gaW1hZ2VTdHlsZS5nZXRPcGFjaXR5KCk7XG4gICAgICAgIHRoaXMuaW1hZ2VPcmlnaW5YXyA9IGltYWdlT3JpZ2luWzBdO1xuICAgICAgICB0aGlzLmltYWdlT3JpZ2luWV8gPSBpbWFnZU9yaWdpblsxXTtcbiAgICAgICAgdGhpcy5pbWFnZVJvdGF0ZVdpdGhWaWV3XyA9IGltYWdlU3R5bGUuZ2V0Um90YXRlV2l0aFZpZXcoKTtcbiAgICAgICAgdGhpcy5pbWFnZVJvdGF0aW9uXyA9IGltYWdlU3R5bGUuZ2V0Um90YXRpb24oKTtcbiAgICAgICAgdGhpcy5pbWFnZVNjYWxlXyA9IFt0aGlzLnBpeGVsUmF0aW9fICogaW1hZ2VTY2FsZVswXSwgdGhpcy5waXhlbFJhdGlvXyAqIGltYWdlU2NhbGVbMV1dO1xuICAgICAgICB0aGlzLmltYWdlV2lkdGhfID0gaW1hZ2VTaXplWzBdO1xuICAgICAgfVxuICAgIH1cbiAgfTtcbiAgLyoqXG4gICAqIFNldCB0aGUgdGV4dCBzdHlsZSBmb3Igc3Vic2VxdWVudCBkcmF3IG9wZXJhdGlvbnMuICBQYXNzIG51bGwgdG9cbiAgICogcmVtb3ZlIHRoZSB0ZXh0IHN0eWxlLlxuICAgKlxuICAgKiBAcGFyYW0ge2ltcG9ydChcIi4uLy4uL3N0eWxlL1RleHQuanNcIikuZGVmYXVsdH0gdGV4dFN0eWxlIFRleHQgc3R5bGUuXG4gICAqL1xuXG5cbiAgQ2FudmFzSW1tZWRpYXRlUmVuZGVyZXIucHJvdG90eXBlLnNldFRleHRTdHlsZSA9IGZ1bmN0aW9uICh0ZXh0U3R5bGUpIHtcbiAgICBpZiAoIXRleHRTdHlsZSkge1xuICAgICAgdGhpcy50ZXh0XyA9ICcnO1xuICAgIH0gZWxzZSB7XG4gICAgICB2YXIgdGV4dEZpbGxTdHlsZSA9IHRleHRTdHlsZS5nZXRGaWxsKCk7XG5cbiAgICAgIGlmICghdGV4dEZpbGxTdHlsZSkge1xuICAgICAgICB0aGlzLnRleHRGaWxsU3RhdGVfID0gbnVsbDtcbiAgICAgIH0gZWxzZSB7XG4gICAgICAgIHZhciB0ZXh0RmlsbFN0eWxlQ29sb3IgPSB0ZXh0RmlsbFN0eWxlLmdldENvbG9yKCk7XG4gICAgICAgIHRoaXMudGV4dEZpbGxTdGF0ZV8gPSB7XG4gICAgICAgICAgZmlsbFN0eWxlOiBhc0NvbG9yTGlrZSh0ZXh0RmlsbFN0eWxlQ29sb3IgPyB0ZXh0RmlsbFN0eWxlQ29sb3IgOiBkZWZhdWx0RmlsbFN0eWxlKVxuICAgICAgICB9O1xuICAgICAgfVxuXG4gICAgICB2YXIgdGV4dFN0cm9rZVN0eWxlID0gdGV4dFN0eWxlLmdldFN0cm9rZSgpO1xuXG4gICAgICBpZiAoIXRleHRTdHJva2VTdHlsZSkge1xuICAgICAgICB0aGlzLnRleHRTdHJva2VTdGF0ZV8gPSBudWxsO1xuICAgICAgfSBlbHNlIHtcbiAgICAgICAgdmFyIHRleHRTdHJva2VTdHlsZUNvbG9yID0gdGV4dFN0cm9rZVN0eWxlLmdldENvbG9yKCk7XG4gICAgICAgIHZhciB0ZXh0U3Ryb2tlU3R5bGVMaW5lQ2FwID0gdGV4dFN0cm9rZVN0eWxlLmdldExpbmVDYXAoKTtcbiAgICAgICAgdmFyIHRleHRTdHJva2VTdHlsZUxpbmVEYXNoID0gdGV4dFN0cm9rZVN0eWxlLmdldExpbmVEYXNoKCk7XG4gICAgICAgIHZhciB0ZXh0U3Ryb2tlU3R5bGVMaW5lRGFzaE9mZnNldCA9IHRleHRTdHJva2VTdHlsZS5nZXRMaW5lRGFzaE9mZnNldCgpO1xuICAgICAgICB2YXIgdGV4dFN0cm9rZVN0eWxlTGluZUpvaW4gPSB0ZXh0U3Ryb2tlU3R5bGUuZ2V0TGluZUpvaW4oKTtcbiAgICAgICAgdmFyIHRleHRTdHJva2VTdHlsZVdpZHRoID0gdGV4dFN0cm9rZVN0eWxlLmdldFdpZHRoKCk7XG4gICAgICAgIHZhciB0ZXh0U3Ryb2tlU3R5bGVNaXRlckxpbWl0ID0gdGV4dFN0cm9rZVN0eWxlLmdldE1pdGVyTGltaXQoKTtcbiAgICAgICAgdGhpcy50ZXh0U3Ryb2tlU3RhdGVfID0ge1xuICAgICAgICAgIGxpbmVDYXA6IHRleHRTdHJva2VTdHlsZUxpbmVDYXAgIT09IHVuZGVmaW5lZCA/IHRleHRTdHJva2VTdHlsZUxpbmVDYXAgOiBkZWZhdWx0TGluZUNhcCxcbiAgICAgICAgICBsaW5lRGFzaDogdGV4dFN0cm9rZVN0eWxlTGluZURhc2ggPyB0ZXh0U3Ryb2tlU3R5bGVMaW5lRGFzaCA6IGRlZmF1bHRMaW5lRGFzaCxcbiAgICAgICAgICBsaW5lRGFzaE9mZnNldDogdGV4dFN0cm9rZVN0eWxlTGluZURhc2hPZmZzZXQgPyB0ZXh0U3Ryb2tlU3R5bGVMaW5lRGFzaE9mZnNldCA6IGRlZmF1bHRMaW5lRGFzaE9mZnNldCxcbiAgICAgICAgICBsaW5lSm9pbjogdGV4dFN0cm9rZVN0eWxlTGluZUpvaW4gIT09IHVuZGVmaW5lZCA/IHRleHRTdHJva2VTdHlsZUxpbmVKb2luIDogZGVmYXVsdExpbmVKb2luLFxuICAgICAgICAgIGxpbmVXaWR0aDogdGV4dFN0cm9rZVN0eWxlV2lkdGggIT09IHVuZGVmaW5lZCA/IHRleHRTdHJva2VTdHlsZVdpZHRoIDogZGVmYXVsdExpbmVXaWR0aCxcbiAgICAgICAgICBtaXRlckxpbWl0OiB0ZXh0U3Ryb2tlU3R5bGVNaXRlckxpbWl0ICE9PSB1bmRlZmluZWQgPyB0ZXh0U3Ryb2tlU3R5bGVNaXRlckxpbWl0IDogZGVmYXVsdE1pdGVyTGltaXQsXG4gICAgICAgICAgc3Ryb2tlU3R5bGU6IGFzQ29sb3JMaWtlKHRleHRTdHJva2VTdHlsZUNvbG9yID8gdGV4dFN0cm9rZVN0eWxlQ29sb3IgOiBkZWZhdWx0U3Ryb2tlU3R5bGUpXG4gICAgICAgIH07XG4gICAgICB9XG5cbiAgICAgIHZhciB0ZXh0Rm9udCA9IHRleHRTdHlsZS5nZXRGb250KCk7XG4gICAgICB2YXIgdGV4dE9mZnNldFggPSB0ZXh0U3R5bGUuZ2V0T2Zmc2V0WCgpO1xuICAgICAgdmFyIHRleHRPZmZzZXRZID0gdGV4dFN0eWxlLmdldE9mZnNldFkoKTtcbiAgICAgIHZhciB0ZXh0Um90YXRlV2l0aFZpZXcgPSB0ZXh0U3R5bGUuZ2V0Um90YXRlV2l0aFZpZXcoKTtcbiAgICAgIHZhciB0ZXh0Um90YXRpb24gPSB0ZXh0U3R5bGUuZ2V0Um90YXRpb24oKTtcbiAgICAgIHZhciB0ZXh0U2NhbGUgPSB0ZXh0U3R5bGUuZ2V0U2NhbGVBcnJheSgpO1xuICAgICAgdmFyIHRleHRUZXh0ID0gdGV4dFN0eWxlLmdldFRleHQoKTtcbiAgICAgIHZhciB0ZXh0VGV4dEFsaWduID0gdGV4dFN0eWxlLmdldFRleHRBbGlnbigpO1xuICAgICAgdmFyIHRleHRUZXh0QmFzZWxpbmUgPSB0ZXh0U3R5bGUuZ2V0VGV4dEJhc2VsaW5lKCk7XG4gICAgICB0aGlzLnRleHRTdGF0ZV8gPSB7XG4gICAgICAgIGZvbnQ6IHRleHRGb250ICE9PSB1bmRlZmluZWQgPyB0ZXh0Rm9udCA6IGRlZmF1bHRGb250LFxuICAgICAgICB0ZXh0QWxpZ246IHRleHRUZXh0QWxpZ24gIT09IHVuZGVmaW5lZCA/IHRleHRUZXh0QWxpZ24gOiBkZWZhdWx0VGV4dEFsaWduLFxuICAgICAgICB0ZXh0QmFzZWxpbmU6IHRleHRUZXh0QmFzZWxpbmUgIT09IHVuZGVmaW5lZCA/IHRleHRUZXh0QmFzZWxpbmUgOiBkZWZhdWx0VGV4dEJhc2VsaW5lXG4gICAgICB9O1xuICAgICAgdGhpcy50ZXh0XyA9IHRleHRUZXh0ICE9PSB1bmRlZmluZWQgPyB0ZXh0VGV4dCA6ICcnO1xuICAgICAgdGhpcy50ZXh0T2Zmc2V0WF8gPSB0ZXh0T2Zmc2V0WCAhPT0gdW5kZWZpbmVkID8gdGhpcy5waXhlbFJhdGlvXyAqIHRleHRPZmZzZXRYIDogMDtcbiAgICAgIHRoaXMudGV4dE9mZnNldFlfID0gdGV4dE9mZnNldFkgIT09IHVuZGVmaW5lZCA/IHRoaXMucGl4ZWxSYXRpb18gKiB0ZXh0T2Zmc2V0WSA6IDA7XG4gICAgICB0aGlzLnRleHRSb3RhdGVXaXRoVmlld18gPSB0ZXh0Um90YXRlV2l0aFZpZXcgIT09IHVuZGVmaW5lZCA/IHRleHRSb3RhdGVXaXRoVmlldyA6IGZhbHNlO1xuICAgICAgdGhpcy50ZXh0Um90YXRpb25fID0gdGV4dFJvdGF0aW9uICE9PSB1bmRlZmluZWQgPyB0ZXh0Um90YXRpb24gOiAwO1xuICAgICAgdGhpcy50ZXh0U2NhbGVfID0gW3RoaXMucGl4ZWxSYXRpb18gKiB0ZXh0U2NhbGVbMF0sIHRoaXMucGl4ZWxSYXRpb18gKiB0ZXh0U2NhbGVbMV1dO1xuICAgIH1cbiAgfTtcblxuICByZXR1cm4gQ2FudmFzSW1tZWRpYXRlUmVuZGVyZXI7XG59KFZlY3RvckNvbnRleHQpO1xuXG5leHBvcnQgZGVmYXVsdCBDYW52YXNJbW1lZGlhdGVSZW5kZXJlcjsiLCIvKipcbiAqIEBtb2R1bGUgb2wvc3R5bGUvSWNvbkFuY2hvclVuaXRzXG4gKi9cblxuLyoqXG4gKiBJY29uIGFuY2hvciB1bml0cy4gT25lIG9mICdmcmFjdGlvbicsICdwaXhlbHMnLlxuICogQGVudW0ge3N0cmluZ31cbiAqL1xuZXhwb3J0IGRlZmF1bHQge1xuICAvKipcbiAgICogQW5jaG9yIGlzIGEgZnJhY3Rpb25cbiAgICogQGFwaVxuICAgKi9cbiAgRlJBQ1RJT046ICdmcmFjdGlvbicsXG5cbiAgLyoqXG4gICAqIEFuY2hvciBpcyBpbiBwaXhlbHNcbiAgICogQGFwaVxuICAgKi9cbiAgUElYRUxTOiAncGl4ZWxzJ1xufTsiLCIvKipcbiAqIEBtb2R1bGUgb2wvc3R5bGUvSWNvbk9yaWdpblxuICovXG5cbi8qKlxuICogSWNvbiBvcmlnaW4uIE9uZSBvZiAnYm90dG9tLWxlZnQnLCAnYm90dG9tLXJpZ2h0JywgJ3RvcC1sZWZ0JywgJ3RvcC1yaWdodCcuXG4gKiBAZW51bSB7c3RyaW5nfVxuICovXG5leHBvcnQgZGVmYXVsdCB7XG4gIC8qKlxuICAgKiBPcmlnaW4gaXMgYXQgYm90dG9tIGxlZnRcbiAgICogQGFwaVxuICAgKi9cbiAgQk9UVE9NX0xFRlQ6ICdib3R0b20tbGVmdCcsXG5cbiAgLyoqXG4gICAqIE9yaWdpbiBpcyBhdCBib3R0b20gcmlnaHRcbiAgICogQGFwaVxuICAgKi9cbiAgQk9UVE9NX1JJR0hUOiAnYm90dG9tLXJpZ2h0JyxcblxuICAvKipcbiAgICogT3JpZ2luIGlzIGF0IHRvcCBsZWZ0XG4gICAqIEBhcGlcbiAgICovXG4gIFRPUF9MRUZUOiAndG9wLWxlZnQnLFxuXG4gIC8qKlxuICAgKiBPcmlnaW4gaXMgYXQgdG9wIHJpZ2h0XG4gICAqIEBhcGlcbiAgICovXG4gIFRPUF9SSUdIVDogJ3RvcC1yaWdodCdcbn07IiwidmFyIF9fZXh0ZW5kcyA9IHRoaXMgJiYgdGhpcy5fX2V4dGVuZHMgfHwgZnVuY3Rpb24gKCkge1xuICB2YXIgX2V4dGVuZFN0YXRpY3MgPSBmdW5jdGlvbiBleHRlbmRTdGF0aWNzKGQsIGIpIHtcbiAgICBfZXh0ZW5kU3RhdGljcyA9IE9iamVjdC5zZXRQcm90b3R5cGVPZiB8fCB7XG4gICAgICBfX3Byb3RvX186IFtdXG4gICAgfSBpbnN0YW5jZW9mIEFycmF5ICYmIGZ1bmN0aW9uIChkLCBiKSB7XG4gICAgICBkLl9fcHJvdG9fXyA9IGI7XG4gICAgfSB8fCBmdW5jdGlvbiAoZCwgYikge1xuICAgICAgZm9yICh2YXIgcCBpbiBiKSB7XG4gICAgICAgIGlmIChPYmplY3QucHJvdG90eXBlLmhhc093blByb3BlcnR5LmNhbGwoYiwgcCkpIGRbcF0gPSBiW3BdO1xuICAgICAgfVxuICAgIH07XG5cbiAgICByZXR1cm4gX2V4dGVuZFN0YXRpY3MoZCwgYik7XG4gIH07XG5cbiAgcmV0dXJuIGZ1bmN0aW9uIChkLCBiKSB7XG4gICAgX2V4dGVuZFN0YXRpY3MoZCwgYik7XG5cbiAgICBmdW5jdGlvbiBfXygpIHtcbiAgICAgIHRoaXMuY29uc3RydWN0b3IgPSBkO1xuICAgIH1cblxuICAgIGQucHJvdG90eXBlID0gYiA9PT0gbnVsbCA/IE9iamVjdC5jcmVhdGUoYikgOiAoX18ucHJvdG90eXBlID0gYi5wcm90b3R5cGUsIG5ldyBfXygpKTtcbiAgfTtcbn0oKTtcbi8qKlxuICogQG1vZHVsZSBvbC9JbWFnZUJhc2VcbiAqL1xuXG5cbmltcG9ydCBFdmVudFRhcmdldCBmcm9tICcuL2V2ZW50cy9UYXJnZXQuanMnO1xuaW1wb3J0IEV2ZW50VHlwZSBmcm9tICcuL2V2ZW50cy9FdmVudFR5cGUuanMnO1xuaW1wb3J0IHsgYWJzdHJhY3QgfSBmcm9tICcuL3V0aWwuanMnO1xuLyoqXG4gKiBAYWJzdHJhY3RcbiAqL1xuXG52YXIgSW1hZ2VCYXNlID1cbi8qKiBAY2xhc3MgKi9cbmZ1bmN0aW9uIChfc3VwZXIpIHtcbiAgX19leHRlbmRzKEltYWdlQmFzZSwgX3N1cGVyKTtcbiAgLyoqXG4gICAqIEBwYXJhbSB7aW1wb3J0KFwiLi9leHRlbnQuanNcIikuRXh0ZW50fSBleHRlbnQgRXh0ZW50LlxuICAgKiBAcGFyYW0ge251bWJlcnx1bmRlZmluZWR9IHJlc29sdXRpb24gUmVzb2x1dGlvbi5cbiAgICogQHBhcmFtIHtudW1iZXJ9IHBpeGVsUmF0aW8gUGl4ZWwgcmF0aW8uXG4gICAqIEBwYXJhbSB7aW1wb3J0KFwiLi9JbWFnZVN0YXRlLmpzXCIpLmRlZmF1bHR9IHN0YXRlIFN0YXRlLlxuICAgKi9cblxuXG4gIGZ1bmN0aW9uIEltYWdlQmFzZShleHRlbnQsIHJlc29sdXRpb24sIHBpeGVsUmF0aW8sIHN0YXRlKSB7XG4gICAgdmFyIF90aGlzID0gX3N1cGVyLmNhbGwodGhpcykgfHwgdGhpcztcbiAgICAvKipcbiAgICAgKiBAcHJvdGVjdGVkXG4gICAgICogQHR5cGUge2ltcG9ydChcIi4vZXh0ZW50LmpzXCIpLkV4dGVudH1cbiAgICAgKi9cblxuXG4gICAgX3RoaXMuZXh0ZW50ID0gZXh0ZW50O1xuICAgIC8qKlxuICAgICAqIEBwcml2YXRlXG4gICAgICogQHR5cGUge251bWJlcn1cbiAgICAgKi9cblxuICAgIF90aGlzLnBpeGVsUmF0aW9fID0gcGl4ZWxSYXRpbztcbiAgICAvKipcbiAgICAgKiBAcHJvdGVjdGVkXG4gICAgICogQHR5cGUge251bWJlcnx1bmRlZmluZWR9XG4gICAgICovXG5cbiAgICBfdGhpcy5yZXNvbHV0aW9uID0gcmVzb2x1dGlvbjtcbiAgICAvKipcbiAgICAgKiBAcHJvdGVjdGVkXG4gICAgICogQHR5cGUge2ltcG9ydChcIi4vSW1hZ2VTdGF0ZS5qc1wiKS5kZWZhdWx0fVxuICAgICAqL1xuXG4gICAgX3RoaXMuc3RhdGUgPSBzdGF0ZTtcbiAgICByZXR1cm4gX3RoaXM7XG4gIH1cbiAgLyoqXG4gICAqIEBwcm90ZWN0ZWRcbiAgICovXG5cblxuICBJbWFnZUJhc2UucHJvdG90eXBlLmNoYW5nZWQgPSBmdW5jdGlvbiAoKSB7XG4gICAgdGhpcy5kaXNwYXRjaEV2ZW50KEV2ZW50VHlwZS5DSEFOR0UpO1xuICB9O1xuICAvKipcbiAgICogQHJldHVybiB7aW1wb3J0KFwiLi9leHRlbnQuanNcIikuRXh0ZW50fSBFeHRlbnQuXG4gICAqL1xuXG5cbiAgSW1hZ2VCYXNlLnByb3RvdHlwZS5nZXRFeHRlbnQgPSBmdW5jdGlvbiAoKSB7XG4gICAgcmV0dXJuIHRoaXMuZXh0ZW50O1xuICB9O1xuICAvKipcbiAgICogQGFic3RyYWN0XG4gICAqIEByZXR1cm4ge0hUTUxDYW52YXNFbGVtZW50fEhUTUxJbWFnZUVsZW1lbnR8SFRNTFZpZGVvRWxlbWVudH0gSW1hZ2UuXG4gICAqL1xuXG5cbiAgSW1hZ2VCYXNlLnByb3RvdHlwZS5nZXRJbWFnZSA9IGZ1bmN0aW9uICgpIHtcbiAgICByZXR1cm4gYWJzdHJhY3QoKTtcbiAgfTtcbiAgLyoqXG4gICAqIEByZXR1cm4ge251bWJlcn0gUGl4ZWxSYXRpby5cbiAgICovXG5cblxuICBJbWFnZUJhc2UucHJvdG90eXBlLmdldFBpeGVsUmF0aW8gPSBmdW5jdGlvbiAoKSB7XG4gICAgcmV0dXJuIHRoaXMucGl4ZWxSYXRpb187XG4gIH07XG4gIC8qKlxuICAgKiBAcmV0dXJuIHtudW1iZXJ9IFJlc29sdXRpb24uXG4gICAqL1xuXG5cbiAgSW1hZ2VCYXNlLnByb3RvdHlwZS5nZXRSZXNvbHV0aW9uID0gZnVuY3Rpb24gKCkge1xuICAgIHJldHVybiAoXG4gICAgICAvKiogQHR5cGUge251bWJlcn0gKi9cbiAgICAgIHRoaXMucmVzb2x1dGlvblxuICAgICk7XG4gIH07XG4gIC8qKlxuICAgKiBAcmV0dXJuIHtpbXBvcnQoXCIuL0ltYWdlU3RhdGUuanNcIikuZGVmYXVsdH0gU3RhdGUuXG4gICAqL1xuXG5cbiAgSW1hZ2VCYXNlLnByb3RvdHlwZS5nZXRTdGF0ZSA9IGZ1bmN0aW9uICgpIHtcbiAgICByZXR1cm4gdGhpcy5zdGF0ZTtcbiAgfTtcbiAgLyoqXG4gICAqIExvYWQgbm90IHlldCBsb2FkZWQgVVJJLlxuICAgKiBAYWJzdHJhY3RcbiAgICovXG5cblxuICBJbWFnZUJhc2UucHJvdG90eXBlLmxvYWQgPSBmdW5jdGlvbiAoKSB7XG4gICAgYWJzdHJhY3QoKTtcbiAgfTtcblxuICByZXR1cm4gSW1hZ2VCYXNlO1xufShFdmVudFRhcmdldCk7XG5cbmV4cG9ydCBkZWZhdWx0IEltYWdlQmFzZTsiLCJ2YXIgX19leHRlbmRzID0gdGhpcyAmJiB0aGlzLl9fZXh0ZW5kcyB8fCBmdW5jdGlvbiAoKSB7XG4gIHZhciBfZXh0ZW5kU3RhdGljcyA9IGZ1bmN0aW9uIGV4dGVuZFN0YXRpY3MoZCwgYikge1xuICAgIF9leHRlbmRTdGF0aWNzID0gT2JqZWN0LnNldFByb3RvdHlwZU9mIHx8IHtcbiAgICAgIF9fcHJvdG9fXzogW11cbiAgICB9IGluc3RhbmNlb2YgQXJyYXkgJiYgZnVuY3Rpb24gKGQsIGIpIHtcbiAgICAgIGQuX19wcm90b19fID0gYjtcbiAgICB9IHx8IGZ1bmN0aW9uIChkLCBiKSB7XG4gICAgICBmb3IgKHZhciBwIGluIGIpIHtcbiAgICAgICAgaWYgKE9iamVjdC5wcm90b3R5cGUuaGFzT3duUHJvcGVydHkuY2FsbChiLCBwKSkgZFtwXSA9IGJbcF07XG4gICAgICB9XG4gICAgfTtcblxuICAgIHJldHVybiBfZXh0ZW5kU3RhdGljcyhkLCBiKTtcbiAgfTtcblxuICByZXR1cm4gZnVuY3Rpb24gKGQsIGIpIHtcbiAgICBfZXh0ZW5kU3RhdGljcyhkLCBiKTtcblxuICAgIGZ1bmN0aW9uIF9fKCkge1xuICAgICAgdGhpcy5jb25zdHJ1Y3RvciA9IGQ7XG4gICAgfVxuXG4gICAgZC5wcm90b3R5cGUgPSBiID09PSBudWxsID8gT2JqZWN0LmNyZWF0ZShiKSA6IChfXy5wcm90b3R5cGUgPSBiLnByb3RvdHlwZSwgbmV3IF9fKCkpO1xuICB9O1xufSgpO1xuLyoqXG4gKiBAbW9kdWxlIG9sL0ltYWdlXG4gKi9cblxuXG5pbXBvcnQgRXZlbnRUeXBlIGZyb20gJy4vZXZlbnRzL0V2ZW50VHlwZS5qcyc7XG5pbXBvcnQgSW1hZ2VCYXNlIGZyb20gJy4vSW1hZ2VCYXNlLmpzJztcbmltcG9ydCBJbWFnZVN0YXRlIGZyb20gJy4vSW1hZ2VTdGF0ZS5qcyc7XG5pbXBvcnQgeyBJTUFHRV9ERUNPREUgfSBmcm9tICcuL2hhcy5qcyc7XG5pbXBvcnQgeyBnZXRIZWlnaHQgfSBmcm9tICcuL2V4dGVudC5qcyc7XG5pbXBvcnQgeyBsaXN0ZW5PbmNlLCB1bmxpc3RlbkJ5S2V5IH0gZnJvbSAnLi9ldmVudHMuanMnO1xuLyoqXG4gKiBBIGZ1bmN0aW9uIHRoYXQgdGFrZXMgYW4ge0BsaW5rIG1vZHVsZTpvbC9JbWFnZX5JbWFnZX0gZm9yIHRoZSBpbWFnZSBhbmQgYVxuICogYHtzdHJpbmd9YCBmb3IgdGhlIHNyYyBhcyBhcmd1bWVudHMuIEl0IGlzIHN1cHBvc2VkIHRvIG1ha2UgaXQgc28gdGhlXG4gKiB1bmRlcmx5aW5nIGltYWdlIHtAbGluayBtb2R1bGU6b2wvSW1hZ2V+SW1hZ2UjZ2V0SW1hZ2V9IGlzIGFzc2lnbmVkIHRoZVxuICogY29udGVudCBzcGVjaWZpZWQgYnkgdGhlIHNyYy4gSWYgbm90IHNwZWNpZmllZCwgdGhlIGRlZmF1bHQgaXNcbiAqXG4gKiAgICAgZnVuY3Rpb24oaW1hZ2UsIHNyYykge1xuICogICAgICAgaW1hZ2UuZ2V0SW1hZ2UoKS5zcmMgPSBzcmM7XG4gKiAgICAgfVxuICpcbiAqIFByb3ZpZGluZyBhIGN1c3RvbSBgaW1hZ2VMb2FkRnVuY3Rpb25gIGNhbiBiZSB1c2VmdWwgdG8gbG9hZCBpbWFnZXMgd2l0aFxuICogcG9zdCByZXF1ZXN0cyBvciAtIGluIGdlbmVyYWwgLSB0aHJvdWdoIFhIUiByZXF1ZXN0cywgd2hlcmUgdGhlIHNyYyBvZiB0aGVcbiAqIGltYWdlIGVsZW1lbnQgd291bGQgYmUgc2V0IHRvIGEgZGF0YSBVUkkgd2hlbiB0aGUgY29udGVudCBpcyBsb2FkZWQuXG4gKlxuICogQHR5cGVkZWYge2Z1bmN0aW9uKEltYWdlV3JhcHBlciwgc3RyaW5nKTogdm9pZH0gTG9hZEZ1bmN0aW9uXG4gKiBAYXBpXG4gKi9cblxudmFyIEltYWdlV3JhcHBlciA9XG4vKiogQGNsYXNzICovXG5mdW5jdGlvbiAoX3N1cGVyKSB7XG4gIF9fZXh0ZW5kcyhJbWFnZVdyYXBwZXIsIF9zdXBlcik7XG4gIC8qKlxuICAgKiBAcGFyYW0ge2ltcG9ydChcIi4vZXh0ZW50LmpzXCIpLkV4dGVudH0gZXh0ZW50IEV4dGVudC5cbiAgICogQHBhcmFtIHtudW1iZXJ8dW5kZWZpbmVkfSByZXNvbHV0aW9uIFJlc29sdXRpb24uXG4gICAqIEBwYXJhbSB7bnVtYmVyfSBwaXhlbFJhdGlvIFBpeGVsIHJhdGlvLlxuICAgKiBAcGFyYW0ge3N0cmluZ30gc3JjIEltYWdlIHNvdXJjZSBVUkkuXG4gICAqIEBwYXJhbSB7P3N0cmluZ30gY3Jvc3NPcmlnaW4gQ3Jvc3Mgb3JpZ2luLlxuICAgKiBAcGFyYW0ge0xvYWRGdW5jdGlvbn0gaW1hZ2VMb2FkRnVuY3Rpb24gSW1hZ2UgbG9hZCBmdW5jdGlvbi5cbiAgICovXG5cblxuICBmdW5jdGlvbiBJbWFnZVdyYXBwZXIoZXh0ZW50LCByZXNvbHV0aW9uLCBwaXhlbFJhdGlvLCBzcmMsIGNyb3NzT3JpZ2luLCBpbWFnZUxvYWRGdW5jdGlvbikge1xuICAgIHZhciBfdGhpcyA9IF9zdXBlci5jYWxsKHRoaXMsIGV4dGVudCwgcmVzb2x1dGlvbiwgcGl4ZWxSYXRpbywgSW1hZ2VTdGF0ZS5JRExFKSB8fCB0aGlzO1xuICAgIC8qKlxuICAgICAqIEBwcml2YXRlXG4gICAgICogQHR5cGUge3N0cmluZ31cbiAgICAgKi9cblxuXG4gICAgX3RoaXMuc3JjXyA9IHNyYztcbiAgICAvKipcbiAgICAgKiBAcHJpdmF0ZVxuICAgICAqIEB0eXBlIHtIVE1MQ2FudmFzRWxlbWVudHxIVE1MSW1hZ2VFbGVtZW50fEhUTUxWaWRlb0VsZW1lbnR9XG4gICAgICovXG5cbiAgICBfdGhpcy5pbWFnZV8gPSBuZXcgSW1hZ2UoKTtcblxuICAgIGlmIChjcm9zc09yaWdpbiAhPT0gbnVsbCkge1xuICAgICAgX3RoaXMuaW1hZ2VfLmNyb3NzT3JpZ2luID0gY3Jvc3NPcmlnaW47XG4gICAgfVxuICAgIC8qKlxuICAgICAqIEBwcml2YXRlXG4gICAgICogQHR5cGUgez9mdW5jdGlvbigpOnZvaWR9XG4gICAgICovXG5cblxuICAgIF90aGlzLnVubGlzdGVuXyA9IG51bGw7XG4gICAgLyoqXG4gICAgICogQHByb3RlY3RlZFxuICAgICAqIEB0eXBlIHtpbXBvcnQoXCIuL0ltYWdlU3RhdGUuanNcIikuZGVmYXVsdH1cbiAgICAgKi9cblxuICAgIF90aGlzLnN0YXRlID0gSW1hZ2VTdGF0ZS5JRExFO1xuICAgIC8qKlxuICAgICAqIEBwcml2YXRlXG4gICAgICogQHR5cGUge0xvYWRGdW5jdGlvbn1cbiAgICAgKi9cblxuICAgIF90aGlzLmltYWdlTG9hZEZ1bmN0aW9uXyA9IGltYWdlTG9hZEZ1bmN0aW9uO1xuICAgIHJldHVybiBfdGhpcztcbiAgfVxuICAvKipcbiAgICogQHJldHVybiB7SFRNTENhbnZhc0VsZW1lbnR8SFRNTEltYWdlRWxlbWVudHxIVE1MVmlkZW9FbGVtZW50fSBJbWFnZS5cbiAgICogQGFwaVxuICAgKi9cblxuXG4gIEltYWdlV3JhcHBlci5wcm90b3R5cGUuZ2V0SW1hZ2UgPSBmdW5jdGlvbiAoKSB7XG4gICAgcmV0dXJuIHRoaXMuaW1hZ2VfO1xuICB9O1xuICAvKipcbiAgICogVHJhY2tzIGxvYWRpbmcgb3IgcmVhZCBlcnJvcnMuXG4gICAqXG4gICAqIEBwcml2YXRlXG4gICAqL1xuXG5cbiAgSW1hZ2VXcmFwcGVyLnByb3RvdHlwZS5oYW5kbGVJbWFnZUVycm9yXyA9IGZ1bmN0aW9uICgpIHtcbiAgICB0aGlzLnN0YXRlID0gSW1hZ2VTdGF0ZS5FUlJPUjtcbiAgICB0aGlzLnVubGlzdGVuSW1hZ2VfKCk7XG4gICAgdGhpcy5jaGFuZ2VkKCk7XG4gIH07XG4gIC8qKlxuICAgKiBUcmFja3Mgc3VjY2Vzc2Z1bCBpbWFnZSBsb2FkLlxuICAgKlxuICAgKiBAcHJpdmF0ZVxuICAgKi9cblxuXG4gIEltYWdlV3JhcHBlci5wcm90b3R5cGUuaGFuZGxlSW1hZ2VMb2FkXyA9IGZ1bmN0aW9uICgpIHtcbiAgICBpZiAodGhpcy5yZXNvbHV0aW9uID09PSB1bmRlZmluZWQpIHtcbiAgICAgIHRoaXMucmVzb2x1dGlvbiA9IGdldEhlaWdodCh0aGlzLmV4dGVudCkgLyB0aGlzLmltYWdlXy5oZWlnaHQ7XG4gICAgfVxuXG4gICAgdGhpcy5zdGF0ZSA9IEltYWdlU3RhdGUuTE9BREVEO1xuICAgIHRoaXMudW5saXN0ZW5JbWFnZV8oKTtcbiAgICB0aGlzLmNoYW5nZWQoKTtcbiAgfTtcbiAgLyoqXG4gICAqIExvYWQgdGhlIGltYWdlIG9yIHJldHJ5IGlmIGxvYWRpbmcgcHJldmlvdXNseSBmYWlsZWQuXG4gICAqIExvYWRpbmcgaXMgdGFrZW4gY2FyZSBvZiBieSB0aGUgdGlsZSBxdWV1ZSwgYW5kIGNhbGxpbmcgdGhpcyBtZXRob2QgaXNcbiAgICogb25seSBuZWVkZWQgZm9yIHByZWxvYWRpbmcgb3IgZm9yIHJlbG9hZGluZyBpbiBjYXNlIG9mIGFuIGVycm9yLlxuICAgKiBAYXBpXG4gICAqL1xuXG5cbiAgSW1hZ2VXcmFwcGVyLnByb3RvdHlwZS5sb2FkID0gZnVuY3Rpb24gKCkge1xuICAgIGlmICh0aGlzLnN0YXRlID09IEltYWdlU3RhdGUuSURMRSB8fCB0aGlzLnN0YXRlID09IEltYWdlU3RhdGUuRVJST1IpIHtcbiAgICAgIHRoaXMuc3RhdGUgPSBJbWFnZVN0YXRlLkxPQURJTkc7XG4gICAgICB0aGlzLmNoYW5nZWQoKTtcbiAgICAgIHRoaXMuaW1hZ2VMb2FkRnVuY3Rpb25fKHRoaXMsIHRoaXMuc3JjXyk7XG4gICAgICB0aGlzLnVubGlzdGVuXyA9IGxpc3RlbkltYWdlKHRoaXMuaW1hZ2VfLCB0aGlzLmhhbmRsZUltYWdlTG9hZF8uYmluZCh0aGlzKSwgdGhpcy5oYW5kbGVJbWFnZUVycm9yXy5iaW5kKHRoaXMpKTtcbiAgICB9XG4gIH07XG4gIC8qKlxuICAgKiBAcGFyYW0ge0hUTUxDYW52YXNFbGVtZW50fEhUTUxJbWFnZUVsZW1lbnR8SFRNTFZpZGVvRWxlbWVudH0gaW1hZ2UgSW1hZ2UuXG4gICAqL1xuXG5cbiAgSW1hZ2VXcmFwcGVyLnByb3RvdHlwZS5zZXRJbWFnZSA9IGZ1bmN0aW9uIChpbWFnZSkge1xuICAgIHRoaXMuaW1hZ2VfID0gaW1hZ2U7XG4gIH07XG4gIC8qKlxuICAgKiBEaXNjYXJkcyBldmVudCBoYW5kbGVycyB3aGljaCBsaXN0ZW4gZm9yIGxvYWQgY29tcGxldGlvbiBvciBlcnJvcnMuXG4gICAqXG4gICAqIEBwcml2YXRlXG4gICAqL1xuXG5cbiAgSW1hZ2VXcmFwcGVyLnByb3RvdHlwZS51bmxpc3RlbkltYWdlXyA9IGZ1bmN0aW9uICgpIHtcbiAgICBpZiAodGhpcy51bmxpc3Rlbl8pIHtcbiAgICAgIHRoaXMudW5saXN0ZW5fKCk7XG4gICAgICB0aGlzLnVubGlzdGVuXyA9IG51bGw7XG4gICAgfVxuICB9O1xuXG4gIHJldHVybiBJbWFnZVdyYXBwZXI7XG59KEltYWdlQmFzZSk7XG4vKipcbiAqIEBwYXJhbSB7SFRNTENhbnZhc0VsZW1lbnR8SFRNTEltYWdlRWxlbWVudHxIVE1MVmlkZW9FbGVtZW50fSBpbWFnZSBJbWFnZSBlbGVtZW50LlxuICogQHBhcmFtIHtmdW5jdGlvbigpOmFueX0gbG9hZEhhbmRsZXIgTG9hZCBjYWxsYmFjayBmdW5jdGlvbi5cbiAqIEBwYXJhbSB7ZnVuY3Rpb24oKTphbnl9IGVycm9ySGFuZGxlciBFcnJvciBjYWxsYmFjayBmdW5jdGlvbi5cbiAqIEByZXR1cm4ge2Z1bmN0aW9uKCk6dm9pZH0gQ2FsbGJhY2sgdG8gc3RvcCBsaXN0ZW5pbmcuXG4gKi9cblxuXG5leHBvcnQgZnVuY3Rpb24gbGlzdGVuSW1hZ2UoaW1hZ2UsIGxvYWRIYW5kbGVyLCBlcnJvckhhbmRsZXIpIHtcbiAgdmFyIGltZyA9XG4gIC8qKiBAdHlwZSB7SFRNTEltYWdlRWxlbWVudH0gKi9cbiAgaW1hZ2U7XG5cbiAgaWYgKGltZy5zcmMgJiYgSU1BR0VfREVDT0RFKSB7XG4gICAgdmFyIHByb21pc2UgPSBpbWcuZGVjb2RlKCk7XG4gICAgdmFyIGxpc3RlbmluZ18xID0gdHJ1ZTtcblxuICAgIHZhciB1bmxpc3RlbiA9IGZ1bmN0aW9uIHVubGlzdGVuKCkge1xuICAgICAgbGlzdGVuaW5nXzEgPSBmYWxzZTtcbiAgICB9O1xuXG4gICAgcHJvbWlzZS50aGVuKGZ1bmN0aW9uICgpIHtcbiAgICAgIGlmIChsaXN0ZW5pbmdfMSkge1xuICAgICAgICBsb2FkSGFuZGxlcigpO1xuICAgICAgfVxuICAgIH0pLmNhdGNoKGZ1bmN0aW9uIChlcnJvcikge1xuICAgICAgaWYgKGxpc3RlbmluZ18xKSB7XG4gICAgICAgIC8vIEZJWE1FOiBVbmNvbmRpdGlvbmFsbHkgY2FsbCBlcnJvckhhbmRsZXIoKSB3aGVuIHRoaXMgYnVnIGlzIGZpeGVkIHVwc3RyZWFtOlxuICAgICAgICAvLyAgICAgICAgaHR0cHM6Ly9idWdzLndlYmtpdC5vcmcvc2hvd19idWcuY2dpP2lkPTE5ODUyN1xuICAgICAgICBpZiAoZXJyb3IubmFtZSA9PT0gJ0VuY29kaW5nRXJyb3InICYmIGVycm9yLm1lc3NhZ2UgPT09ICdJbnZhbGlkIGltYWdlIHR5cGUuJykge1xuICAgICAgICAgIGxvYWRIYW5kbGVyKCk7XG4gICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgZXJyb3JIYW5kbGVyKCk7XG4gICAgICAgIH1cbiAgICAgIH1cbiAgICB9KTtcbiAgICByZXR1cm4gdW5saXN0ZW47XG4gIH1cblxuICB2YXIgbGlzdGVuZXJLZXlzID0gW2xpc3Rlbk9uY2UoaW1nLCBFdmVudFR5cGUuTE9BRCwgbG9hZEhhbmRsZXIpLCBsaXN0ZW5PbmNlKGltZywgRXZlbnRUeXBlLkVSUk9SLCBlcnJvckhhbmRsZXIpXTtcbiAgcmV0dXJuIGZ1bmN0aW9uIHVubGlzdGVuKCkge1xuICAgIGxpc3RlbmVyS2V5cy5mb3JFYWNoKHVubGlzdGVuQnlLZXkpO1xuICB9O1xufVxuZXhwb3J0IGRlZmF1bHQgSW1hZ2VXcmFwcGVyOyIsIi8qKlxuICogQG1vZHVsZSBvbC9zdHlsZS9JY29uSW1hZ2VcbiAqL1xudmFyIF9fZXh0ZW5kcyA9IHRoaXMgJiYgdGhpcy5fX2V4dGVuZHMgfHwgZnVuY3Rpb24gKCkge1xuICB2YXIgX2V4dGVuZFN0YXRpY3MgPSBmdW5jdGlvbiBleHRlbmRTdGF0aWNzKGQsIGIpIHtcbiAgICBfZXh0ZW5kU3RhdGljcyA9IE9iamVjdC5zZXRQcm90b3R5cGVPZiB8fCB7XG4gICAgICBfX3Byb3RvX186IFtdXG4gICAgfSBpbnN0YW5jZW9mIEFycmF5ICYmIGZ1bmN0aW9uIChkLCBiKSB7XG4gICAgICBkLl9fcHJvdG9fXyA9IGI7XG4gICAgfSB8fCBmdW5jdGlvbiAoZCwgYikge1xuICAgICAgZm9yICh2YXIgcCBpbiBiKSB7XG4gICAgICAgIGlmIChPYmplY3QucHJvdG90eXBlLmhhc093blByb3BlcnR5LmNhbGwoYiwgcCkpIGRbcF0gPSBiW3BdO1xuICAgICAgfVxuICAgIH07XG5cbiAgICByZXR1cm4gX2V4dGVuZFN0YXRpY3MoZCwgYik7XG4gIH07XG5cbiAgcmV0dXJuIGZ1bmN0aW9uIChkLCBiKSB7XG4gICAgX2V4dGVuZFN0YXRpY3MoZCwgYik7XG5cbiAgICBmdW5jdGlvbiBfXygpIHtcbiAgICAgIHRoaXMuY29uc3RydWN0b3IgPSBkO1xuICAgIH1cblxuICAgIGQucHJvdG90eXBlID0gYiA9PT0gbnVsbCA/IE9iamVjdC5jcmVhdGUoYikgOiAoX18ucHJvdG90eXBlID0gYi5wcm90b3R5cGUsIG5ldyBfXygpKTtcbiAgfTtcbn0oKTtcblxuaW1wb3J0IEV2ZW50VGFyZ2V0IGZyb20gJy4uL2V2ZW50cy9UYXJnZXQuanMnO1xuaW1wb3J0IEV2ZW50VHlwZSBmcm9tICcuLi9ldmVudHMvRXZlbnRUeXBlLmpzJztcbmltcG9ydCBJbWFnZVN0YXRlIGZyb20gJy4uL0ltYWdlU3RhdGUuanMnO1xuaW1wb3J0IHsgYXNTdHJpbmcgfSBmcm9tICcuLi9jb2xvci5qcyc7XG5pbXBvcnQgeyBjcmVhdGVDYW52YXNDb250ZXh0MkQgfSBmcm9tICcuLi9kb20uanMnO1xuaW1wb3J0IHsgc2hhcmVkIGFzIGljb25JbWFnZUNhY2hlIH0gZnJvbSAnLi9JY29uSW1hZ2VDYWNoZS5qcyc7XG5pbXBvcnQgeyBsaXN0ZW5JbWFnZSB9IGZyb20gJy4uL0ltYWdlLmpzJztcbi8qKlxuICogQHR5cGUge0NhbnZhc1JlbmRlcmluZ0NvbnRleHQyRH1cbiAqL1xuXG52YXIgdGFpbnRlZFRlc3RDb250ZXh0ID0gbnVsbDtcblxudmFyIEljb25JbWFnZSA9XG4vKiogQGNsYXNzICovXG5mdW5jdGlvbiAoX3N1cGVyKSB7XG4gIF9fZXh0ZW5kcyhJY29uSW1hZ2UsIF9zdXBlcik7XG4gIC8qKlxuICAgKiBAcGFyYW0ge0hUTUxJbWFnZUVsZW1lbnR8SFRNTENhbnZhc0VsZW1lbnR9IGltYWdlIEltYWdlLlxuICAgKiBAcGFyYW0ge3N0cmluZ3x1bmRlZmluZWR9IHNyYyBTcmMuXG4gICAqIEBwYXJhbSB7aW1wb3J0KFwiLi4vc2l6ZS5qc1wiKS5TaXplfSBzaXplIFNpemUuXG4gICAqIEBwYXJhbSB7P3N0cmluZ30gY3Jvc3NPcmlnaW4gQ3Jvc3Mgb3JpZ2luLlxuICAgKiBAcGFyYW0ge2ltcG9ydChcIi4uL0ltYWdlU3RhdGUuanNcIikuZGVmYXVsdH0gaW1hZ2VTdGF0ZSBJbWFnZSBzdGF0ZS5cbiAgICogQHBhcmFtIHtpbXBvcnQoXCIuLi9jb2xvci5qc1wiKS5Db2xvcn0gY29sb3IgQ29sb3IuXG4gICAqL1xuXG5cbiAgZnVuY3Rpb24gSWNvbkltYWdlKGltYWdlLCBzcmMsIHNpemUsIGNyb3NzT3JpZ2luLCBpbWFnZVN0YXRlLCBjb2xvcikge1xuICAgIHZhciBfdGhpcyA9IF9zdXBlci5jYWxsKHRoaXMpIHx8IHRoaXM7XG4gICAgLyoqXG4gICAgICogQHByaXZhdGVcbiAgICAgKiBAdHlwZSB7SFRNTEltYWdlRWxlbWVudHxIVE1MQ2FudmFzRWxlbWVudH1cbiAgICAgKi9cblxuXG4gICAgX3RoaXMuaGl0RGV0ZWN0aW9uSW1hZ2VfID0gbnVsbDtcbiAgICAvKipcbiAgICAgKiBAcHJpdmF0ZVxuICAgICAqIEB0eXBlIHtIVE1MSW1hZ2VFbGVtZW50fEhUTUxDYW52YXNFbGVtZW50fVxuICAgICAqL1xuXG4gICAgX3RoaXMuaW1hZ2VfID0gIWltYWdlID8gbmV3IEltYWdlKCkgOiBpbWFnZTtcblxuICAgIGlmIChjcm9zc09yaWdpbiAhPT0gbnVsbCkge1xuICAgICAgLyoqIEB0eXBlIHtIVE1MSW1hZ2VFbGVtZW50fSAqL1xuICAgICAgX3RoaXMuaW1hZ2VfLmNyb3NzT3JpZ2luID0gY3Jvc3NPcmlnaW47XG4gICAgfVxuICAgIC8qKlxuICAgICAqIEBwcml2YXRlXG4gICAgICogQHR5cGUge09iamVjdDxudW1iZXIsIEhUTUxDYW52YXNFbGVtZW50Pn1cbiAgICAgKi9cblxuXG4gICAgX3RoaXMuY2FudmFzXyA9IHt9O1xuICAgIC8qKlxuICAgICAqIEBwcml2YXRlXG4gICAgICogQHR5cGUge2ltcG9ydChcIi4uL2NvbG9yLmpzXCIpLkNvbG9yfVxuICAgICAqL1xuXG4gICAgX3RoaXMuY29sb3JfID0gY29sb3I7XG4gICAgLyoqXG4gICAgICogQHByaXZhdGVcbiAgICAgKiBAdHlwZSB7P2Z1bmN0aW9uKCk6dm9pZH1cbiAgICAgKi9cblxuICAgIF90aGlzLnVubGlzdGVuXyA9IG51bGw7XG4gICAgLyoqXG4gICAgICogQHByaXZhdGVcbiAgICAgKiBAdHlwZSB7aW1wb3J0KFwiLi4vSW1hZ2VTdGF0ZS5qc1wiKS5kZWZhdWx0fVxuICAgICAqL1xuXG4gICAgX3RoaXMuaW1hZ2VTdGF0ZV8gPSBpbWFnZVN0YXRlO1xuICAgIC8qKlxuICAgICAqIEBwcml2YXRlXG4gICAgICogQHR5cGUge2ltcG9ydChcIi4uL3NpemUuanNcIikuU2l6ZX1cbiAgICAgKi9cblxuICAgIF90aGlzLnNpemVfID0gc2l6ZTtcbiAgICAvKipcbiAgICAgKiBAcHJpdmF0ZVxuICAgICAqIEB0eXBlIHtzdHJpbmd8dW5kZWZpbmVkfVxuICAgICAqL1xuXG4gICAgX3RoaXMuc3JjXyA9IHNyYztcbiAgICAvKipcbiAgICAgKiBAcHJpdmF0ZVxuICAgICAqL1xuXG4gICAgX3RoaXMudGFpbnRlZF87XG4gICAgcmV0dXJuIF90aGlzO1xuICB9XG4gIC8qKlxuICAgKiBAcHJpdmF0ZVxuICAgKiBAcmV0dXJuIHtib29sZWFufSBUaGUgaW1hZ2UgY2FudmFzIGlzIHRhaW50ZWQuXG4gICAqL1xuXG5cbiAgSWNvbkltYWdlLnByb3RvdHlwZS5pc1RhaW50ZWRfID0gZnVuY3Rpb24gKCkge1xuICAgIGlmICh0aGlzLnRhaW50ZWRfID09PSB1bmRlZmluZWQgJiYgdGhpcy5pbWFnZVN0YXRlXyA9PT0gSW1hZ2VTdGF0ZS5MT0FERUQpIHtcbiAgICAgIGlmICghdGFpbnRlZFRlc3RDb250ZXh0KSB7XG4gICAgICAgIHRhaW50ZWRUZXN0Q29udGV4dCA9IGNyZWF0ZUNhbnZhc0NvbnRleHQyRCgxLCAxKTtcbiAgICAgIH1cblxuICAgICAgdGFpbnRlZFRlc3RDb250ZXh0LmRyYXdJbWFnZSh0aGlzLmltYWdlXywgMCwgMCk7XG5cbiAgICAgIHRyeSB7XG4gICAgICAgIHRhaW50ZWRUZXN0Q29udGV4dC5nZXRJbWFnZURhdGEoMCwgMCwgMSwgMSk7XG4gICAgICAgIHRoaXMudGFpbnRlZF8gPSBmYWxzZTtcbiAgICAgIH0gY2F0Y2ggKGUpIHtcbiAgICAgICAgdGFpbnRlZFRlc3RDb250ZXh0ID0gbnVsbDtcbiAgICAgICAgdGhpcy50YWludGVkXyA9IHRydWU7XG4gICAgICB9XG4gICAgfVxuXG4gICAgcmV0dXJuIHRoaXMudGFpbnRlZF8gPT09IHRydWU7XG4gIH07XG4gIC8qKlxuICAgKiBAcHJpdmF0ZVxuICAgKi9cblxuXG4gIEljb25JbWFnZS5wcm90b3R5cGUuZGlzcGF0Y2hDaGFuZ2VFdmVudF8gPSBmdW5jdGlvbiAoKSB7XG4gICAgdGhpcy5kaXNwYXRjaEV2ZW50KEV2ZW50VHlwZS5DSEFOR0UpO1xuICB9O1xuICAvKipcbiAgICogQHByaXZhdGVcbiAgICovXG5cblxuICBJY29uSW1hZ2UucHJvdG90eXBlLmhhbmRsZUltYWdlRXJyb3JfID0gZnVuY3Rpb24gKCkge1xuICAgIHRoaXMuaW1hZ2VTdGF0ZV8gPSBJbWFnZVN0YXRlLkVSUk9SO1xuICAgIHRoaXMudW5saXN0ZW5JbWFnZV8oKTtcbiAgICB0aGlzLmRpc3BhdGNoQ2hhbmdlRXZlbnRfKCk7XG4gIH07XG4gIC8qKlxuICAgKiBAcHJpdmF0ZVxuICAgKi9cblxuXG4gIEljb25JbWFnZS5wcm90b3R5cGUuaGFuZGxlSW1hZ2VMb2FkXyA9IGZ1bmN0aW9uICgpIHtcbiAgICB0aGlzLmltYWdlU3RhdGVfID0gSW1hZ2VTdGF0ZS5MT0FERUQ7XG5cbiAgICBpZiAodGhpcy5zaXplXykge1xuICAgICAgdGhpcy5pbWFnZV8ud2lkdGggPSB0aGlzLnNpemVfWzBdO1xuICAgICAgdGhpcy5pbWFnZV8uaGVpZ2h0ID0gdGhpcy5zaXplX1sxXTtcbiAgICB9IGVsc2Uge1xuICAgICAgdGhpcy5zaXplXyA9IFt0aGlzLmltYWdlXy53aWR0aCwgdGhpcy5pbWFnZV8uaGVpZ2h0XTtcbiAgICB9XG5cbiAgICB0aGlzLnVubGlzdGVuSW1hZ2VfKCk7XG4gICAgdGhpcy5kaXNwYXRjaENoYW5nZUV2ZW50XygpO1xuICB9O1xuICAvKipcbiAgICogQHBhcmFtIHtudW1iZXJ9IHBpeGVsUmF0aW8gUGl4ZWwgcmF0aW8uXG4gICAqIEByZXR1cm4ge0hUTUxJbWFnZUVsZW1lbnR8SFRNTENhbnZhc0VsZW1lbnR9IEltYWdlIG9yIENhbnZhcyBlbGVtZW50LlxuICAgKi9cblxuXG4gIEljb25JbWFnZS5wcm90b3R5cGUuZ2V0SW1hZ2UgPSBmdW5jdGlvbiAocGl4ZWxSYXRpbykge1xuICAgIHRoaXMucmVwbGFjZUNvbG9yXyhwaXhlbFJhdGlvKTtcbiAgICByZXR1cm4gdGhpcy5jYW52YXNfW3BpeGVsUmF0aW9dID8gdGhpcy5jYW52YXNfW3BpeGVsUmF0aW9dIDogdGhpcy5pbWFnZV87XG4gIH07XG4gIC8qKlxuICAgKiBAcGFyYW0ge251bWJlcn0gcGl4ZWxSYXRpbyBQaXhlbCByYXRpby5cbiAgICogQHJldHVybiB7bnVtYmVyfSBJbWFnZSBvciBDYW52YXMgZWxlbWVudC5cbiAgICovXG5cblxuICBJY29uSW1hZ2UucHJvdG90eXBlLmdldFBpeGVsUmF0aW8gPSBmdW5jdGlvbiAocGl4ZWxSYXRpbykge1xuICAgIHRoaXMucmVwbGFjZUNvbG9yXyhwaXhlbFJhdGlvKTtcbiAgICByZXR1cm4gdGhpcy5jYW52YXNfW3BpeGVsUmF0aW9dID8gcGl4ZWxSYXRpbyA6IDE7XG4gIH07XG4gIC8qKlxuICAgKiBAcmV0dXJuIHtpbXBvcnQoXCIuLi9JbWFnZVN0YXRlLmpzXCIpLmRlZmF1bHR9IEltYWdlIHN0YXRlLlxuICAgKi9cblxuXG4gIEljb25JbWFnZS5wcm90b3R5cGUuZ2V0SW1hZ2VTdGF0ZSA9IGZ1bmN0aW9uICgpIHtcbiAgICByZXR1cm4gdGhpcy5pbWFnZVN0YXRlXztcbiAgfTtcbiAgLyoqXG4gICAqIEByZXR1cm4ge0hUTUxJbWFnZUVsZW1lbnR8SFRNTENhbnZhc0VsZW1lbnR9IEltYWdlIGVsZW1lbnQuXG4gICAqL1xuXG5cbiAgSWNvbkltYWdlLnByb3RvdHlwZS5nZXRIaXREZXRlY3Rpb25JbWFnZSA9IGZ1bmN0aW9uICgpIHtcbiAgICBpZiAoIXRoaXMuaGl0RGV0ZWN0aW9uSW1hZ2VfKSB7XG4gICAgICBpZiAodGhpcy5pc1RhaW50ZWRfKCkpIHtcbiAgICAgICAgdmFyIHdpZHRoID0gdGhpcy5zaXplX1swXTtcbiAgICAgICAgdmFyIGhlaWdodCA9IHRoaXMuc2l6ZV9bMV07XG4gICAgICAgIHZhciBjb250ZXh0ID0gY3JlYXRlQ2FudmFzQ29udGV4dDJEKHdpZHRoLCBoZWlnaHQpO1xuICAgICAgICBjb250ZXh0LmZpbGxSZWN0KDAsIDAsIHdpZHRoLCBoZWlnaHQpO1xuICAgICAgICB0aGlzLmhpdERldGVjdGlvbkltYWdlXyA9IGNvbnRleHQuY2FudmFzO1xuICAgICAgfSBlbHNlIHtcbiAgICAgICAgdGhpcy5oaXREZXRlY3Rpb25JbWFnZV8gPSB0aGlzLmltYWdlXztcbiAgICAgIH1cbiAgICB9XG5cbiAgICByZXR1cm4gdGhpcy5oaXREZXRlY3Rpb25JbWFnZV87XG4gIH07XG4gIC8qKlxuICAgKiBHZXQgdGhlIHNpemUgb2YgdGhlIGljb24gKGluIHBpeGVscykuXG4gICAqIEByZXR1cm4ge2ltcG9ydChcIi4uL3NpemUuanNcIikuU2l6ZX0gSW1hZ2Ugc2l6ZS5cbiAgICovXG5cblxuICBJY29uSW1hZ2UucHJvdG90eXBlLmdldFNpemUgPSBmdW5jdGlvbiAoKSB7XG4gICAgcmV0dXJuIHRoaXMuc2l6ZV87XG4gIH07XG4gIC8qKlxuICAgKiBAcmV0dXJuIHtzdHJpbmd8dW5kZWZpbmVkfSBJbWFnZSBzcmMuXG4gICAqL1xuXG5cbiAgSWNvbkltYWdlLnByb3RvdHlwZS5nZXRTcmMgPSBmdW5jdGlvbiAoKSB7XG4gICAgcmV0dXJuIHRoaXMuc3JjXztcbiAgfTtcbiAgLyoqXG4gICAqIExvYWQgbm90IHlldCBsb2FkZWQgVVJJLlxuICAgKi9cblxuXG4gIEljb25JbWFnZS5wcm90b3R5cGUubG9hZCA9IGZ1bmN0aW9uICgpIHtcbiAgICBpZiAodGhpcy5pbWFnZVN0YXRlXyA9PSBJbWFnZVN0YXRlLklETEUpIHtcbiAgICAgIHRoaXMuaW1hZ2VTdGF0ZV8gPSBJbWFnZVN0YXRlLkxPQURJTkc7XG5cbiAgICAgIHRyeSB7XG4gICAgICAgIC8qKiBAdHlwZSB7SFRNTEltYWdlRWxlbWVudH0gKi9cbiAgICAgICAgdGhpcy5pbWFnZV8uc3JjID0gdGhpcy5zcmNfO1xuICAgICAgfSBjYXRjaCAoZSkge1xuICAgICAgICB0aGlzLmhhbmRsZUltYWdlRXJyb3JfKCk7XG4gICAgICB9XG5cbiAgICAgIHRoaXMudW5saXN0ZW5fID0gbGlzdGVuSW1hZ2UodGhpcy5pbWFnZV8sIHRoaXMuaGFuZGxlSW1hZ2VMb2FkXy5iaW5kKHRoaXMpLCB0aGlzLmhhbmRsZUltYWdlRXJyb3JfLmJpbmQodGhpcykpO1xuICAgIH1cbiAgfTtcbiAgLyoqXG4gICAqIEBwYXJhbSB7bnVtYmVyfSBwaXhlbFJhdGlvIFBpeGVsIHJhdGlvLlxuICAgKiBAcHJpdmF0ZVxuICAgKi9cblxuXG4gIEljb25JbWFnZS5wcm90b3R5cGUucmVwbGFjZUNvbG9yXyA9IGZ1bmN0aW9uIChwaXhlbFJhdGlvKSB7XG4gICAgaWYgKCF0aGlzLmNvbG9yXyB8fCB0aGlzLmNhbnZhc19bcGl4ZWxSYXRpb10pIHtcbiAgICAgIHJldHVybjtcbiAgICB9XG5cbiAgICB2YXIgY2FudmFzID0gZG9jdW1lbnQuY3JlYXRlRWxlbWVudCgnY2FudmFzJyk7XG4gICAgdGhpcy5jYW52YXNfW3BpeGVsUmF0aW9dID0gY2FudmFzO1xuICAgIGNhbnZhcy53aWR0aCA9IE1hdGguY2VpbCh0aGlzLmltYWdlXy53aWR0aCAqIHBpeGVsUmF0aW8pO1xuICAgIGNhbnZhcy5oZWlnaHQgPSBNYXRoLmNlaWwodGhpcy5pbWFnZV8uaGVpZ2h0ICogcGl4ZWxSYXRpbyk7XG4gICAgdmFyIGN0eCA9IGNhbnZhcy5nZXRDb250ZXh0KCcyZCcpO1xuICAgIGN0eC5zY2FsZShwaXhlbFJhdGlvLCBwaXhlbFJhdGlvKTtcbiAgICBjdHguZHJhd0ltYWdlKHRoaXMuaW1hZ2VfLCAwLCAwKTtcbiAgICBjdHguZ2xvYmFsQ29tcG9zaXRlT3BlcmF0aW9uID0gJ211bHRpcGx5JzsgLy8gSW50ZXJuZXQgRXhwbG9yZXIgMTEgZG9lcyBub3Qgc3VwcG9ydCB0aGUgbXVsdGlwbHkgb3BlcmF0aW9uLlxuICAgIC8vIElmIHRoZSBjYW52YXMgaXMgdGFpbnRlZCBpbiBJbnRlcm5ldCBFeHBsb3JlciB0aGlzIHN0aWxsIHByb2R1Y2VzXG4gICAgLy8gYSBzb2xpZCBjb2xvciBpbWFnZSB3aXRoIHRoZSBzaGFwZSBvZiB0aGUgaWNvbi5cblxuICAgIGlmIChjdHguZ2xvYmFsQ29tcG9zaXRlT3BlcmF0aW9uID09PSAnbXVsdGlwbHknIHx8IHRoaXMuaXNUYWludGVkXygpKSB7XG4gICAgICBjdHguZmlsbFN0eWxlID0gYXNTdHJpbmcodGhpcy5jb2xvcl8pO1xuICAgICAgY3R4LmZpbGxSZWN0KDAsIDAsIGNhbnZhcy53aWR0aCwgY2FudmFzLmhlaWdodCk7XG4gICAgICBjdHguZ2xvYmFsQ29tcG9zaXRlT3BlcmF0aW9uID0gJ2Rlc3RpbmF0aW9uLWluJztcbiAgICAgIGN0eC5kcmF3SW1hZ2UodGhpcy5pbWFnZV8sIDAsIDApO1xuICAgIH0gZWxzZSB7XG4gICAgICB2YXIgaW1nRGF0YSA9IGN0eC5nZXRJbWFnZURhdGEoMCwgMCwgY2FudmFzLndpZHRoLCBjYW52YXMuaGVpZ2h0KTtcbiAgICAgIHZhciBkYXRhID0gaW1nRGF0YS5kYXRhO1xuICAgICAgdmFyIHIgPSB0aGlzLmNvbG9yX1swXSAvIDI1NS4wO1xuICAgICAgdmFyIGcgPSB0aGlzLmNvbG9yX1sxXSAvIDI1NS4wO1xuICAgICAgdmFyIGIgPSB0aGlzLmNvbG9yX1syXSAvIDI1NS4wO1xuICAgICAgdmFyIGEgPSB0aGlzLmNvbG9yX1szXTtcblxuICAgICAgZm9yICh2YXIgaSA9IDAsIGlpID0gZGF0YS5sZW5ndGg7IGkgPCBpaTsgaSArPSA0KSB7XG4gICAgICAgIGRhdGFbaV0gKj0gcjtcbiAgICAgICAgZGF0YVtpICsgMV0gKj0gZztcbiAgICAgICAgZGF0YVtpICsgMl0gKj0gYjtcbiAgICAgICAgZGF0YVtpICsgM10gKj0gYTtcbiAgICAgIH1cblxuICAgICAgY3R4LnB1dEltYWdlRGF0YShpbWdEYXRhLCAwLCAwKTtcbiAgICB9XG4gIH07XG4gIC8qKlxuICAgKiBEaXNjYXJkcyBldmVudCBoYW5kbGVycyB3aGljaCBsaXN0ZW4gZm9yIGxvYWQgY29tcGxldGlvbiBvciBlcnJvcnMuXG4gICAqXG4gICAqIEBwcml2YXRlXG4gICAqL1xuXG5cbiAgSWNvbkltYWdlLnByb3RvdHlwZS51bmxpc3RlbkltYWdlXyA9IGZ1bmN0aW9uICgpIHtcbiAgICBpZiAodGhpcy51bmxpc3Rlbl8pIHtcbiAgICAgIHRoaXMudW5saXN0ZW5fKCk7XG4gICAgICB0aGlzLnVubGlzdGVuXyA9IG51bGw7XG4gICAgfVxuICB9O1xuXG4gIHJldHVybiBJY29uSW1hZ2U7XG59KEV2ZW50VGFyZ2V0KTtcbi8qKlxuICogQHBhcmFtIHtIVE1MSW1hZ2VFbGVtZW50fEhUTUxDYW52YXNFbGVtZW50fSBpbWFnZSBJbWFnZS5cbiAqIEBwYXJhbSB7c3RyaW5nfSBzcmMgU3JjLlxuICogQHBhcmFtIHtpbXBvcnQoXCIuLi9zaXplLmpzXCIpLlNpemV9IHNpemUgU2l6ZS5cbiAqIEBwYXJhbSB7P3N0cmluZ30gY3Jvc3NPcmlnaW4gQ3Jvc3Mgb3JpZ2luLlxuICogQHBhcmFtIHtpbXBvcnQoXCIuLi9JbWFnZVN0YXRlLmpzXCIpLmRlZmF1bHR9IGltYWdlU3RhdGUgSW1hZ2Ugc3RhdGUuXG4gKiBAcGFyYW0ge2ltcG9ydChcIi4uL2NvbG9yLmpzXCIpLkNvbG9yfSBjb2xvciBDb2xvci5cbiAqIEByZXR1cm4ge0ljb25JbWFnZX0gSWNvbiBpbWFnZS5cbiAqL1xuXG5cbmV4cG9ydCBmdW5jdGlvbiBnZXQoaW1hZ2UsIHNyYywgc2l6ZSwgY3Jvc3NPcmlnaW4sIGltYWdlU3RhdGUsIGNvbG9yKSB7XG4gIHZhciBpY29uSW1hZ2UgPSBpY29uSW1hZ2VDYWNoZS5nZXQoc3JjLCBjcm9zc09yaWdpbiwgY29sb3IpO1xuXG4gIGlmICghaWNvbkltYWdlKSB7XG4gICAgaWNvbkltYWdlID0gbmV3IEljb25JbWFnZShpbWFnZSwgc3JjLCBzaXplLCBjcm9zc09yaWdpbiwgaW1hZ2VTdGF0ZSwgY29sb3IpO1xuICAgIGljb25JbWFnZUNhY2hlLnNldChzcmMsIGNyb3NzT3JpZ2luLCBjb2xvciwgaWNvbkltYWdlKTtcbiAgfVxuXG4gIHJldHVybiBpY29uSW1hZ2U7XG59XG5leHBvcnQgZGVmYXVsdCBJY29uSW1hZ2U7IiwidmFyIF9fZXh0ZW5kcyA9IHRoaXMgJiYgdGhpcy5fX2V4dGVuZHMgfHwgZnVuY3Rpb24gKCkge1xuICB2YXIgX2V4dGVuZFN0YXRpY3MgPSBmdW5jdGlvbiBleHRlbmRTdGF0aWNzKGQsIGIpIHtcbiAgICBfZXh0ZW5kU3RhdGljcyA9IE9iamVjdC5zZXRQcm90b3R5cGVPZiB8fCB7XG4gICAgICBfX3Byb3RvX186IFtdXG4gICAgfSBpbnN0YW5jZW9mIEFycmF5ICYmIGZ1bmN0aW9uIChkLCBiKSB7XG4gICAgICBkLl9fcHJvdG9fXyA9IGI7XG4gICAgfSB8fCBmdW5jdGlvbiAoZCwgYikge1xuICAgICAgZm9yICh2YXIgcCBpbiBiKSB7XG4gICAgICAgIGlmIChPYmplY3QucHJvdG90eXBlLmhhc093blByb3BlcnR5LmNhbGwoYiwgcCkpIGRbcF0gPSBiW3BdO1xuICAgICAgfVxuICAgIH07XG5cbiAgICByZXR1cm4gX2V4dGVuZFN0YXRpY3MoZCwgYik7XG4gIH07XG5cbiAgcmV0dXJuIGZ1bmN0aW9uIChkLCBiKSB7XG4gICAgX2V4dGVuZFN0YXRpY3MoZCwgYik7XG5cbiAgICBmdW5jdGlvbiBfXygpIHtcbiAgICAgIHRoaXMuY29uc3RydWN0b3IgPSBkO1xuICAgIH1cblxuICAgIGQucHJvdG90eXBlID0gYiA9PT0gbnVsbCA/IE9iamVjdC5jcmVhdGUoYikgOiAoX18ucHJvdG90eXBlID0gYi5wcm90b3R5cGUsIG5ldyBfXygpKTtcbiAgfTtcbn0oKTtcbi8qKlxuICogQG1vZHVsZSBvbC9zdHlsZS9JY29uXG4gKi9cblxuXG5pbXBvcnQgRXZlbnRUeXBlIGZyb20gJy4uL2V2ZW50cy9FdmVudFR5cGUuanMnO1xuaW1wb3J0IEljb25BbmNob3JVbml0cyBmcm9tICcuL0ljb25BbmNob3JVbml0cy5qcyc7XG5pbXBvcnQgSWNvbk9yaWdpbiBmcm9tICcuL0ljb25PcmlnaW4uanMnO1xuaW1wb3J0IEltYWdlU3RhdGUgZnJvbSAnLi4vSW1hZ2VTdGF0ZS5qcyc7XG5pbXBvcnQgSW1hZ2VTdHlsZSBmcm9tICcuL0ltYWdlLmpzJztcbmltcG9ydCB7IGFzQXJyYXkgfSBmcm9tICcuLi9jb2xvci5qcyc7XG5pbXBvcnQgeyBhc3NlcnQgfSBmcm9tICcuLi9hc3NlcnRzLmpzJztcbmltcG9ydCB7IGdldCBhcyBnZXRJY29uSW1hZ2UgfSBmcm9tICcuL0ljb25JbWFnZS5qcyc7XG5pbXBvcnQgeyBnZXRVaWQgfSBmcm9tICcuLi91dGlsLmpzJztcbi8qKlxuICogQHR5cGVkZWYge09iamVjdH0gT3B0aW9uc1xuICogQHByb3BlcnR5IHtBcnJheTxudW1iZXI+fSBbYW5jaG9yPVswLjUsIDAuNV1dIEFuY2hvci4gRGVmYXVsdCB2YWx1ZSBpcyB0aGUgaWNvbiBjZW50ZXIuXG4gKiBAcHJvcGVydHkge2ltcG9ydChcIi4vSWNvbk9yaWdpbi5qc1wiKS5kZWZhdWx0fSBbYW5jaG9yT3JpZ2luPSd0b3AtbGVmdCddIE9yaWdpbiBvZiB0aGUgYW5jaG9yOiBgYm90dG9tLWxlZnRgLCBgYm90dG9tLXJpZ2h0YCxcbiAqIGB0b3AtbGVmdGAgb3IgYHRvcC1yaWdodGAuXG4gKiBAcHJvcGVydHkge2ltcG9ydChcIi4vSWNvbkFuY2hvclVuaXRzLmpzXCIpLmRlZmF1bHR9IFthbmNob3JYVW5pdHM9J2ZyYWN0aW9uJ10gVW5pdHMgaW4gd2hpY2ggdGhlIGFuY2hvciB4IHZhbHVlIGlzXG4gKiBzcGVjaWZpZWQuIEEgdmFsdWUgb2YgYCdmcmFjdGlvbidgIGluZGljYXRlcyB0aGUgeCB2YWx1ZSBpcyBhIGZyYWN0aW9uIG9mIHRoZSBpY29uLiBBIHZhbHVlIG9mIGAncGl4ZWxzJ2AgaW5kaWNhdGVzXG4gKiB0aGUgeCB2YWx1ZSBpbiBwaXhlbHMuXG4gKiBAcHJvcGVydHkge2ltcG9ydChcIi4vSWNvbkFuY2hvclVuaXRzLmpzXCIpLmRlZmF1bHR9IFthbmNob3JZVW5pdHM9J2ZyYWN0aW9uJ10gVW5pdHMgaW4gd2hpY2ggdGhlIGFuY2hvciB5IHZhbHVlIGlzXG4gKiBzcGVjaWZpZWQuIEEgdmFsdWUgb2YgYCdmcmFjdGlvbidgIGluZGljYXRlcyB0aGUgeSB2YWx1ZSBpcyBhIGZyYWN0aW9uIG9mIHRoZSBpY29uLiBBIHZhbHVlIG9mIGAncGl4ZWxzJ2AgaW5kaWNhdGVzXG4gKiB0aGUgeSB2YWx1ZSBpbiBwaXhlbHMuXG4gKiBAcHJvcGVydHkge2ltcG9ydChcIi4uL2NvbG9yLmpzXCIpLkNvbG9yfHN0cmluZ30gW2NvbG9yXSBDb2xvciB0byB0aW50IHRoZSBpY29uLiBJZiBub3Qgc3BlY2lmaWVkLFxuICogdGhlIGljb24gd2lsbCBiZSBsZWZ0IGFzIGlzLlxuICogQHByb3BlcnR5IHtudWxsfHN0cmluZ30gW2Nyb3NzT3JpZ2luXSBUaGUgYGNyb3NzT3JpZ2luYCBhdHRyaWJ1dGUgZm9yIGxvYWRlZCBpbWFnZXMuIE5vdGUgdGhhdCB5b3UgbXVzdCBwcm92aWRlIGFcbiAqIGBjcm9zc09yaWdpbmAgdmFsdWUgaWYgeW91IHdhbnQgdG8gYWNjZXNzIHBpeGVsIGRhdGEgd2l0aCB0aGUgQ2FudmFzIHJlbmRlcmVyLlxuICogU2VlIGh0dHBzOi8vZGV2ZWxvcGVyLm1vemlsbGEub3JnL2VuLVVTL2RvY3MvV2ViL0hUTUwvQ09SU19lbmFibGVkX2ltYWdlIGZvciBtb3JlIGRldGFpbC5cbiAqIEBwcm9wZXJ0eSB7SFRNTEltYWdlRWxlbWVudHxIVE1MQ2FudmFzRWxlbWVudH0gW2ltZ10gSW1hZ2Ugb2JqZWN0IGZvciB0aGUgaWNvbi4gSWYgdGhlIGBzcmNgIG9wdGlvbiBpcyBub3QgcHJvdmlkZWQgdGhlbiB0aGVcbiAqIHByb3ZpZGVkIGltYWdlIG11c3QgYWxyZWFkeSBiZSBsb2FkZWQuIEFuZCBpbiB0aGF0IGNhc2UsIGl0IGlzIHJlcXVpcmVkXG4gKiB0byBwcm92aWRlIHRoZSBzaXplIG9mIHRoZSBpbWFnZSwgd2l0aCB0aGUgYGltZ1NpemVgIG9wdGlvbi5cbiAqIEBwcm9wZXJ0eSB7QXJyYXk8bnVtYmVyPn0gW29mZnNldD1bMCwgMF1dIE9mZnNldCwgd2hpY2gsIHRvZ2V0aGVyIHdpdGggdGhlIHNpemUgYW5kIHRoZSBvZmZzZXQgb3JpZ2luLCBkZWZpbmUgdGhlXG4gKiBzdWItcmVjdGFuZ2xlIHRvIHVzZSBmcm9tIHRoZSBvcmlnaW5hbCBpY29uIGltYWdlLlxuICogQHByb3BlcnR5IHtBcnJheTxudW1iZXI+fSBbZGlzcGxhY2VtZW50PVswLDBdXSBEaXNwbGFjZW1lbnQgdGhlIGljb25cbiAqIEBwcm9wZXJ0eSB7aW1wb3J0KFwiLi9JY29uT3JpZ2luLmpzXCIpLmRlZmF1bHR9IFtvZmZzZXRPcmlnaW49J3RvcC1sZWZ0J10gT3JpZ2luIG9mIHRoZSBvZmZzZXQ6IGBib3R0b20tbGVmdGAsIGBib3R0b20tcmlnaHRgLFxuICogYHRvcC1sZWZ0YCBvciBgdG9wLXJpZ2h0YC5cbiAqIEBwcm9wZXJ0eSB7bnVtYmVyfSBbb3BhY2l0eT0xXSBPcGFjaXR5IG9mIHRoZSBpY29uLlxuICogQHByb3BlcnR5IHtudW1iZXJ8aW1wb3J0KFwiLi4vc2l6ZS5qc1wiKS5TaXplfSBbc2NhbGU9MV0gU2NhbGUuXG4gKiBAcHJvcGVydHkge2Jvb2xlYW59IFtyb3RhdGVXaXRoVmlldz1mYWxzZV0gV2hldGhlciB0byByb3RhdGUgdGhlIGljb24gd2l0aCB0aGUgdmlldy5cbiAqIEBwcm9wZXJ0eSB7bnVtYmVyfSBbcm90YXRpb249MF0gUm90YXRpb24gaW4gcmFkaWFucyAocG9zaXRpdmUgcm90YXRpb24gY2xvY2t3aXNlKS5cbiAqIEBwcm9wZXJ0eSB7aW1wb3J0KFwiLi4vc2l6ZS5qc1wiKS5TaXplfSBbc2l6ZV0gSWNvbiBzaXplIGluIHBpeGVsLiBDYW4gYmUgdXNlZCB0b2dldGhlciB3aXRoIGBvZmZzZXRgIHRvIGRlZmluZSB0aGVcbiAqIHN1Yi1yZWN0YW5nbGUgdG8gdXNlIGZyb20gdGhlIG9yaWdpbiAoc3ByaXRlKSBpY29uIGltYWdlLlxuICogQHByb3BlcnR5IHtpbXBvcnQoXCIuLi9zaXplLmpzXCIpLlNpemV9IFtpbWdTaXplXSBJbWFnZSBzaXplIGluIHBpeGVscy4gT25seSByZXF1aXJlZCBpZiBgaW1nYCBpcyBzZXQgYW5kIGBzcmNgIGlzIG5vdCwgYW5kXG4gKiBmb3IgU1ZHIGltYWdlcyBpbiBJbnRlcm5ldCBFeHBsb3JlciAxMS4gVGhlIHByb3ZpZGVkIGBpbWdTaXplYCBuZWVkcyB0byBtYXRjaCB0aGUgYWN0dWFsIHNpemUgb2YgdGhlIGltYWdlLlxuICogQHByb3BlcnR5IHtzdHJpbmd9IFtzcmNdIEltYWdlIHNvdXJjZSBVUkkuXG4gKi9cblxuLyoqXG4gKiBAY2xhc3NkZXNjXG4gKiBTZXQgaWNvbiBzdHlsZSBmb3IgdmVjdG9yIGZlYXR1cmVzLlxuICogQGFwaVxuICovXG5cbnZhciBJY29uID1cbi8qKiBAY2xhc3MgKi9cbmZ1bmN0aW9uIChfc3VwZXIpIHtcbiAgX19leHRlbmRzKEljb24sIF9zdXBlcik7XG4gIC8qKlxuICAgKiBAcGFyYW0ge09wdGlvbnM9fSBvcHRfb3B0aW9ucyBPcHRpb25zLlxuICAgKi9cblxuXG4gIGZ1bmN0aW9uIEljb24ob3B0X29wdGlvbnMpIHtcbiAgICB2YXIgX3RoaXMgPSB0aGlzO1xuXG4gICAgdmFyIG9wdGlvbnMgPSBvcHRfb3B0aW9ucyB8fCB7fTtcbiAgICAvKipcbiAgICAgKiBAdHlwZSB7bnVtYmVyfVxuICAgICAqL1xuXG4gICAgdmFyIG9wYWNpdHkgPSBvcHRpb25zLm9wYWNpdHkgIT09IHVuZGVmaW5lZCA/IG9wdGlvbnMub3BhY2l0eSA6IDE7XG4gICAgLyoqXG4gICAgICogQHR5cGUge251bWJlcn1cbiAgICAgKi9cblxuICAgIHZhciByb3RhdGlvbiA9IG9wdGlvbnMucm90YXRpb24gIT09IHVuZGVmaW5lZCA/IG9wdGlvbnMucm90YXRpb24gOiAwO1xuICAgIC8qKlxuICAgICAqIEB0eXBlIHtudW1iZXJ8aW1wb3J0KFwiLi4vc2l6ZS5qc1wiKS5TaXplfVxuICAgICAqL1xuXG4gICAgdmFyIHNjYWxlID0gb3B0aW9ucy5zY2FsZSAhPT0gdW5kZWZpbmVkID8gb3B0aW9ucy5zY2FsZSA6IDE7XG4gICAgLyoqXG4gICAgICogQHR5cGUge2Jvb2xlYW59XG4gICAgICovXG5cbiAgICB2YXIgcm90YXRlV2l0aFZpZXcgPSBvcHRpb25zLnJvdGF0ZVdpdGhWaWV3ICE9PSB1bmRlZmluZWQgPyBvcHRpb25zLnJvdGF0ZVdpdGhWaWV3IDogZmFsc2U7XG4gICAgX3RoaXMgPSBfc3VwZXIuY2FsbCh0aGlzLCB7XG4gICAgICBvcGFjaXR5OiBvcGFjaXR5LFxuICAgICAgcm90YXRpb246IHJvdGF0aW9uLFxuICAgICAgc2NhbGU6IHNjYWxlLFxuICAgICAgZGlzcGxhY2VtZW50OiBvcHRpb25zLmRpc3BsYWNlbWVudCAhPT0gdW5kZWZpbmVkID8gb3B0aW9ucy5kaXNwbGFjZW1lbnQgOiBbMCwgMF0sXG4gICAgICByb3RhdGVXaXRoVmlldzogcm90YXRlV2l0aFZpZXdcbiAgICB9KSB8fCB0aGlzO1xuICAgIC8qKlxuICAgICAqIEBwcml2YXRlXG4gICAgICogQHR5cGUge0FycmF5PG51bWJlcj59XG4gICAgICovXG5cbiAgICBfdGhpcy5hbmNob3JfID0gb3B0aW9ucy5hbmNob3IgIT09IHVuZGVmaW5lZCA/IG9wdGlvbnMuYW5jaG9yIDogWzAuNSwgMC41XTtcbiAgICAvKipcbiAgICAgKiBAcHJpdmF0ZVxuICAgICAqIEB0eXBlIHtBcnJheTxudW1iZXI+fVxuICAgICAqL1xuXG4gICAgX3RoaXMubm9ybWFsaXplZEFuY2hvcl8gPSBudWxsO1xuICAgIC8qKlxuICAgICAqIEBwcml2YXRlXG4gICAgICogQHR5cGUge2ltcG9ydChcIi4vSWNvbk9yaWdpbi5qc1wiKS5kZWZhdWx0fVxuICAgICAqL1xuXG4gICAgX3RoaXMuYW5jaG9yT3JpZ2luXyA9IG9wdGlvbnMuYW5jaG9yT3JpZ2luICE9PSB1bmRlZmluZWQgPyBvcHRpb25zLmFuY2hvck9yaWdpbiA6IEljb25PcmlnaW4uVE9QX0xFRlQ7XG4gICAgLyoqXG4gICAgICogQHByaXZhdGVcbiAgICAgKiBAdHlwZSB7aW1wb3J0KFwiLi9JY29uQW5jaG9yVW5pdHMuanNcIikuZGVmYXVsdH1cbiAgICAgKi9cblxuICAgIF90aGlzLmFuY2hvclhVbml0c18gPSBvcHRpb25zLmFuY2hvclhVbml0cyAhPT0gdW5kZWZpbmVkID8gb3B0aW9ucy5hbmNob3JYVW5pdHMgOiBJY29uQW5jaG9yVW5pdHMuRlJBQ1RJT047XG4gICAgLyoqXG4gICAgICogQHByaXZhdGVcbiAgICAgKiBAdHlwZSB7aW1wb3J0KFwiLi9JY29uQW5jaG9yVW5pdHMuanNcIikuZGVmYXVsdH1cbiAgICAgKi9cblxuICAgIF90aGlzLmFuY2hvcllVbml0c18gPSBvcHRpb25zLmFuY2hvcllVbml0cyAhPT0gdW5kZWZpbmVkID8gb3B0aW9ucy5hbmNob3JZVW5pdHMgOiBJY29uQW5jaG9yVW5pdHMuRlJBQ1RJT047XG4gICAgLyoqXG4gICAgICogQHByaXZhdGVcbiAgICAgKiBAdHlwZSB7P3N0cmluZ31cbiAgICAgKi9cblxuICAgIF90aGlzLmNyb3NzT3JpZ2luXyA9IG9wdGlvbnMuY3Jvc3NPcmlnaW4gIT09IHVuZGVmaW5lZCA/IG9wdGlvbnMuY3Jvc3NPcmlnaW4gOiBudWxsO1xuICAgIC8qKlxuICAgICAqIEB0eXBlIHtIVE1MSW1hZ2VFbGVtZW50fEhUTUxDYW52YXNFbGVtZW50fVxuICAgICAqL1xuXG4gICAgdmFyIGltYWdlID0gb3B0aW9ucy5pbWcgIT09IHVuZGVmaW5lZCA/IG9wdGlvbnMuaW1nIDogbnVsbDtcbiAgICAvKipcbiAgICAgKiBAdHlwZSB7aW1wb3J0KFwiLi4vc2l6ZS5qc1wiKS5TaXplfVxuICAgICAqL1xuXG4gICAgdmFyIGltZ1NpemUgPSBvcHRpb25zLmltZ1NpemUgIT09IHVuZGVmaW5lZCA/IG9wdGlvbnMuaW1nU2l6ZSA6IG51bGw7XG4gICAgLyoqXG4gICAgICogQHR5cGUge3N0cmluZ3x1bmRlZmluZWR9XG4gICAgICovXG5cbiAgICB2YXIgc3JjID0gb3B0aW9ucy5zcmM7XG4gICAgYXNzZXJ0KCEoc3JjICE9PSB1bmRlZmluZWQgJiYgaW1hZ2UpLCA0KTsgLy8gYGltYWdlYCBhbmQgYHNyY2AgY2Fubm90IGJlIHByb3ZpZGVkIGF0IHRoZSBzYW1lIHRpbWVcblxuICAgIGFzc2VydCghaW1hZ2UgfHwgaW1hZ2UgJiYgaW1nU2l6ZSwgNSk7IC8vIGBpbWdTaXplYCBtdXN0IGJlIHNldCB3aGVuIGBpbWFnZWAgaXMgcHJvdmlkZWRcblxuICAgIGlmICgoc3JjID09PSB1bmRlZmluZWQgfHwgc3JjLmxlbmd0aCA9PT0gMCkgJiYgaW1hZ2UpIHtcbiAgICAgIHNyYyA9XG4gICAgICAvKiogQHR5cGUge0hUTUxJbWFnZUVsZW1lbnR9ICovXG4gICAgICBpbWFnZS5zcmMgfHwgZ2V0VWlkKGltYWdlKTtcbiAgICB9XG5cbiAgICBhc3NlcnQoc3JjICE9PSB1bmRlZmluZWQgJiYgc3JjLmxlbmd0aCA+IDAsIDYpOyAvLyBBIGRlZmluZWQgYW5kIG5vbi1lbXB0eSBgc3JjYCBvciBgaW1hZ2VgIG11c3QgYmUgcHJvdmlkZWRcblxuICAgIC8qKlxuICAgICAqIEB0eXBlIHtpbXBvcnQoXCIuLi9JbWFnZVN0YXRlLmpzXCIpLmRlZmF1bHR9XG4gICAgICovXG5cbiAgICB2YXIgaW1hZ2VTdGF0ZSA9IG9wdGlvbnMuc3JjICE9PSB1bmRlZmluZWQgPyBJbWFnZVN0YXRlLklETEUgOiBJbWFnZVN0YXRlLkxPQURFRDtcbiAgICAvKipcbiAgICAgKiBAcHJpdmF0ZVxuICAgICAqIEB0eXBlIHtpbXBvcnQoXCIuLi9jb2xvci5qc1wiKS5Db2xvcn1cbiAgICAgKi9cblxuICAgIF90aGlzLmNvbG9yXyA9IG9wdGlvbnMuY29sb3IgIT09IHVuZGVmaW5lZCA/IGFzQXJyYXkob3B0aW9ucy5jb2xvcikgOiBudWxsO1xuICAgIC8qKlxuICAgICAqIEBwcml2YXRlXG4gICAgICogQHR5cGUge2ltcG9ydChcIi4vSWNvbkltYWdlLmpzXCIpLmRlZmF1bHR9XG4gICAgICovXG5cbiAgICBfdGhpcy5pY29uSW1hZ2VfID0gZ2V0SWNvbkltYWdlKGltYWdlLFxuICAgIC8qKiBAdHlwZSB7c3RyaW5nfSAqL1xuICAgIHNyYywgaW1nU2l6ZSwgX3RoaXMuY3Jvc3NPcmlnaW5fLCBpbWFnZVN0YXRlLCBfdGhpcy5jb2xvcl8pO1xuICAgIC8qKlxuICAgICAqIEBwcml2YXRlXG4gICAgICogQHR5cGUge0FycmF5PG51bWJlcj59XG4gICAgICovXG5cbiAgICBfdGhpcy5vZmZzZXRfID0gb3B0aW9ucy5vZmZzZXQgIT09IHVuZGVmaW5lZCA/IG9wdGlvbnMub2Zmc2V0IDogWzAsIDBdO1xuICAgIC8qKlxuICAgICAqIEBwcml2YXRlXG4gICAgICogQHR5cGUge2ltcG9ydChcIi4vSWNvbk9yaWdpbi5qc1wiKS5kZWZhdWx0fVxuICAgICAqL1xuXG4gICAgX3RoaXMub2Zmc2V0T3JpZ2luXyA9IG9wdGlvbnMub2Zmc2V0T3JpZ2luICE9PSB1bmRlZmluZWQgPyBvcHRpb25zLm9mZnNldE9yaWdpbiA6IEljb25PcmlnaW4uVE9QX0xFRlQ7XG4gICAgLyoqXG4gICAgICogQHByaXZhdGVcbiAgICAgKiBAdHlwZSB7QXJyYXk8bnVtYmVyPn1cbiAgICAgKi9cblxuICAgIF90aGlzLm9yaWdpbl8gPSBudWxsO1xuICAgIC8qKlxuICAgICAqIEBwcml2YXRlXG4gICAgICogQHR5cGUge2ltcG9ydChcIi4uL3NpemUuanNcIikuU2l6ZX1cbiAgICAgKi9cblxuICAgIF90aGlzLnNpemVfID0gb3B0aW9ucy5zaXplICE9PSB1bmRlZmluZWQgPyBvcHRpb25zLnNpemUgOiBudWxsO1xuICAgIHJldHVybiBfdGhpcztcbiAgfVxuICAvKipcbiAgICogQ2xvbmVzIHRoZSBzdHlsZS4gVGhlIHVuZGVybHlpbmcgSW1hZ2UvSFRNTENhbnZhc0VsZW1lbnQgaXMgbm90IGNsb25lZC5cbiAgICogQHJldHVybiB7SWNvbn0gVGhlIGNsb25lZCBzdHlsZS5cbiAgICogQGFwaVxuICAgKi9cblxuXG4gIEljb24ucHJvdG90eXBlLmNsb25lID0gZnVuY3Rpb24gKCkge1xuICAgIHZhciBzY2FsZSA9IHRoaXMuZ2V0U2NhbGUoKTtcbiAgICByZXR1cm4gbmV3IEljb24oe1xuICAgICAgYW5jaG9yOiB0aGlzLmFuY2hvcl8uc2xpY2UoKSxcbiAgICAgIGFuY2hvck9yaWdpbjogdGhpcy5hbmNob3JPcmlnaW5fLFxuICAgICAgYW5jaG9yWFVuaXRzOiB0aGlzLmFuY2hvclhVbml0c18sXG4gICAgICBhbmNob3JZVW5pdHM6IHRoaXMuYW5jaG9yWVVuaXRzXyxcbiAgICAgIGNyb3NzT3JpZ2luOiB0aGlzLmNyb3NzT3JpZ2luXyxcbiAgICAgIGNvbG9yOiB0aGlzLmNvbG9yXyAmJiB0aGlzLmNvbG9yXy5zbGljZSA/IHRoaXMuY29sb3JfLnNsaWNlKCkgOiB0aGlzLmNvbG9yXyB8fCB1bmRlZmluZWQsXG4gICAgICBzcmM6IHRoaXMuZ2V0U3JjKCksXG4gICAgICBvZmZzZXQ6IHRoaXMub2Zmc2V0Xy5zbGljZSgpLFxuICAgICAgb2Zmc2V0T3JpZ2luOiB0aGlzLm9mZnNldE9yaWdpbl8sXG4gICAgICBzaXplOiB0aGlzLnNpemVfICE9PSBudWxsID8gdGhpcy5zaXplXy5zbGljZSgpIDogdW5kZWZpbmVkLFxuICAgICAgb3BhY2l0eTogdGhpcy5nZXRPcGFjaXR5KCksXG4gICAgICBzY2FsZTogQXJyYXkuaXNBcnJheShzY2FsZSkgPyBzY2FsZS5zbGljZSgpIDogc2NhbGUsXG4gICAgICByb3RhdGlvbjogdGhpcy5nZXRSb3RhdGlvbigpLFxuICAgICAgcm90YXRlV2l0aFZpZXc6IHRoaXMuZ2V0Um90YXRlV2l0aFZpZXcoKVxuICAgIH0pO1xuICB9O1xuICAvKipcbiAgICogR2V0IHRoZSBhbmNob3IgcG9pbnQgaW4gcGl4ZWxzLiBUaGUgYW5jaG9yIGRldGVybWluZXMgdGhlIGNlbnRlciBwb2ludCBmb3IgdGhlXG4gICAqIHN5bWJvbGl6ZXIuXG4gICAqIEByZXR1cm4ge0FycmF5PG51bWJlcj59IEFuY2hvci5cbiAgICogQGFwaVxuICAgKi9cblxuXG4gIEljb24ucHJvdG90eXBlLmdldEFuY2hvciA9IGZ1bmN0aW9uICgpIHtcbiAgICBpZiAodGhpcy5ub3JtYWxpemVkQW5jaG9yXykge1xuICAgICAgcmV0dXJuIHRoaXMubm9ybWFsaXplZEFuY2hvcl87XG4gICAgfVxuXG4gICAgdmFyIGFuY2hvciA9IHRoaXMuYW5jaG9yXztcbiAgICB2YXIgc2l6ZSA9IHRoaXMuZ2V0U2l6ZSgpO1xuXG4gICAgaWYgKHRoaXMuYW5jaG9yWFVuaXRzXyA9PSBJY29uQW5jaG9yVW5pdHMuRlJBQ1RJT04gfHwgdGhpcy5hbmNob3JZVW5pdHNfID09IEljb25BbmNob3JVbml0cy5GUkFDVElPTikge1xuICAgICAgaWYgKCFzaXplKSB7XG4gICAgICAgIHJldHVybiBudWxsO1xuICAgICAgfVxuXG4gICAgICBhbmNob3IgPSB0aGlzLmFuY2hvcl8uc2xpY2UoKTtcblxuICAgICAgaWYgKHRoaXMuYW5jaG9yWFVuaXRzXyA9PSBJY29uQW5jaG9yVW5pdHMuRlJBQ1RJT04pIHtcbiAgICAgICAgYW5jaG9yWzBdICo9IHNpemVbMF07XG4gICAgICB9XG5cbiAgICAgIGlmICh0aGlzLmFuY2hvcllVbml0c18gPT0gSWNvbkFuY2hvclVuaXRzLkZSQUNUSU9OKSB7XG4gICAgICAgIGFuY2hvclsxXSAqPSBzaXplWzFdO1xuICAgICAgfVxuICAgIH1cblxuICAgIGlmICh0aGlzLmFuY2hvck9yaWdpbl8gIT0gSWNvbk9yaWdpbi5UT1BfTEVGVCkge1xuICAgICAgaWYgKCFzaXplKSB7XG4gICAgICAgIHJldHVybiBudWxsO1xuICAgICAgfVxuXG4gICAgICBpZiAoYW5jaG9yID09PSB0aGlzLmFuY2hvcl8pIHtcbiAgICAgICAgYW5jaG9yID0gdGhpcy5hbmNob3JfLnNsaWNlKCk7XG4gICAgICB9XG5cbiAgICAgIGlmICh0aGlzLmFuY2hvck9yaWdpbl8gPT0gSWNvbk9yaWdpbi5UT1BfUklHSFQgfHwgdGhpcy5hbmNob3JPcmlnaW5fID09IEljb25PcmlnaW4uQk9UVE9NX1JJR0hUKSB7XG4gICAgICAgIGFuY2hvclswXSA9IC1hbmNob3JbMF0gKyBzaXplWzBdO1xuICAgICAgfVxuXG4gICAgICBpZiAodGhpcy5hbmNob3JPcmlnaW5fID09IEljb25PcmlnaW4uQk9UVE9NX0xFRlQgfHwgdGhpcy5hbmNob3JPcmlnaW5fID09IEljb25PcmlnaW4uQk9UVE9NX1JJR0hUKSB7XG4gICAgICAgIGFuY2hvclsxXSA9IC1hbmNob3JbMV0gKyBzaXplWzFdO1xuICAgICAgfVxuICAgIH1cblxuICAgIHRoaXMubm9ybWFsaXplZEFuY2hvcl8gPSBhbmNob3I7XG4gICAgcmV0dXJuIHRoaXMubm9ybWFsaXplZEFuY2hvcl87XG4gIH07XG4gIC8qKlxuICAgKiBTZXQgdGhlIGFuY2hvciBwb2ludC4gVGhlIGFuY2hvciBkZXRlcm1pbmVzIHRoZSBjZW50ZXIgcG9pbnQgZm9yIHRoZVxuICAgKiBzeW1ib2xpemVyLlxuICAgKlxuICAgKiBAcGFyYW0ge0FycmF5PG51bWJlcj59IGFuY2hvciBBbmNob3IuXG4gICAqIEBhcGlcbiAgICovXG5cblxuICBJY29uLnByb3RvdHlwZS5zZXRBbmNob3IgPSBmdW5jdGlvbiAoYW5jaG9yKSB7XG4gICAgdGhpcy5hbmNob3JfID0gYW5jaG9yO1xuICAgIHRoaXMubm9ybWFsaXplZEFuY2hvcl8gPSBudWxsO1xuICB9O1xuICAvKipcbiAgICogR2V0IHRoZSBpY29uIGNvbG9yLlxuICAgKiBAcmV0dXJuIHtpbXBvcnQoXCIuLi9jb2xvci5qc1wiKS5Db2xvcn0gQ29sb3IuXG4gICAqIEBhcGlcbiAgICovXG5cblxuICBJY29uLnByb3RvdHlwZS5nZXRDb2xvciA9IGZ1bmN0aW9uICgpIHtcbiAgICByZXR1cm4gdGhpcy5jb2xvcl87XG4gIH07XG4gIC8qKlxuICAgKiBHZXQgdGhlIGltYWdlIGljb24uXG4gICAqIEBwYXJhbSB7bnVtYmVyfSBwaXhlbFJhdGlvIFBpeGVsIHJhdGlvLlxuICAgKiBAcmV0dXJuIHtIVE1MSW1hZ2VFbGVtZW50fEhUTUxDYW52YXNFbGVtZW50fSBJbWFnZSBvciBDYW52YXMgZWxlbWVudC5cbiAgICogQGFwaVxuICAgKi9cblxuXG4gIEljb24ucHJvdG90eXBlLmdldEltYWdlID0gZnVuY3Rpb24gKHBpeGVsUmF0aW8pIHtcbiAgICByZXR1cm4gdGhpcy5pY29uSW1hZ2VfLmdldEltYWdlKHBpeGVsUmF0aW8pO1xuICB9O1xuICAvKipcbiAgICogR2V0IHRoZSBwaXhlbCByYXRpby5cbiAgICogQHBhcmFtIHtudW1iZXJ9IHBpeGVsUmF0aW8gUGl4ZWwgcmF0aW8uXG4gICAqIEByZXR1cm4ge251bWJlcn0gVGhlIHBpeGVsIHJhdGlvbiBvZiB0aGUgaW1hZ2UuXG4gICAqIEBhcGlcbiAgICovXG5cblxuICBJY29uLnByb3RvdHlwZS5nZXRQaXhlbFJhdGlvID0gZnVuY3Rpb24gKHBpeGVsUmF0aW8pIHtcbiAgICByZXR1cm4gdGhpcy5pY29uSW1hZ2VfLmdldFBpeGVsUmF0aW8ocGl4ZWxSYXRpbyk7XG4gIH07XG4gIC8qKlxuICAgKiBAcmV0dXJuIHtpbXBvcnQoXCIuLi9zaXplLmpzXCIpLlNpemV9IEltYWdlIHNpemUuXG4gICAqL1xuXG5cbiAgSWNvbi5wcm90b3R5cGUuZ2V0SW1hZ2VTaXplID0gZnVuY3Rpb24gKCkge1xuICAgIHJldHVybiB0aGlzLmljb25JbWFnZV8uZ2V0U2l6ZSgpO1xuICB9O1xuICAvKipcbiAgICogQHJldHVybiB7aW1wb3J0KFwiLi4vc2l6ZS5qc1wiKS5TaXplfSBTaXplIG9mIHRoZSBoaXQtZGV0ZWN0aW9uIGltYWdlLlxuICAgKi9cblxuXG4gIEljb24ucHJvdG90eXBlLmdldEhpdERldGVjdGlvbkltYWdlU2l6ZSA9IGZ1bmN0aW9uICgpIHtcbiAgICByZXR1cm4gdGhpcy5nZXRJbWFnZVNpemUoKTtcbiAgfTtcbiAgLyoqXG4gICAqIEByZXR1cm4ge2ltcG9ydChcIi4uL0ltYWdlU3RhdGUuanNcIikuZGVmYXVsdH0gSW1hZ2Ugc3RhdGUuXG4gICAqL1xuXG5cbiAgSWNvbi5wcm90b3R5cGUuZ2V0SW1hZ2VTdGF0ZSA9IGZ1bmN0aW9uICgpIHtcbiAgICByZXR1cm4gdGhpcy5pY29uSW1hZ2VfLmdldEltYWdlU3RhdGUoKTtcbiAgfTtcbiAgLyoqXG4gICAqIEByZXR1cm4ge0hUTUxJbWFnZUVsZW1lbnR8SFRNTENhbnZhc0VsZW1lbnR9IEltYWdlIGVsZW1lbnQuXG4gICAqL1xuXG5cbiAgSWNvbi5wcm90b3R5cGUuZ2V0SGl0RGV0ZWN0aW9uSW1hZ2UgPSBmdW5jdGlvbiAoKSB7XG4gICAgcmV0dXJuIHRoaXMuaWNvbkltYWdlXy5nZXRIaXREZXRlY3Rpb25JbWFnZSgpO1xuICB9O1xuICAvKipcbiAgICogR2V0IHRoZSBvcmlnaW4gb2YgdGhlIHN5bWJvbGl6ZXIuXG4gICAqIEByZXR1cm4ge0FycmF5PG51bWJlcj59IE9yaWdpbi5cbiAgICogQGFwaVxuICAgKi9cblxuXG4gIEljb24ucHJvdG90eXBlLmdldE9yaWdpbiA9IGZ1bmN0aW9uICgpIHtcbiAgICBpZiAodGhpcy5vcmlnaW5fKSB7XG4gICAgICByZXR1cm4gdGhpcy5vcmlnaW5fO1xuICAgIH1cblxuICAgIHZhciBvZmZzZXQgPSB0aGlzLm9mZnNldF87XG4gICAgdmFyIGRpc3BsYWNlbWVudCA9IHRoaXMuZ2V0RGlzcGxhY2VtZW50KCk7XG5cbiAgICBpZiAodGhpcy5vZmZzZXRPcmlnaW5fICE9IEljb25PcmlnaW4uVE9QX0xFRlQpIHtcbiAgICAgIHZhciBzaXplID0gdGhpcy5nZXRTaXplKCk7XG4gICAgICB2YXIgaWNvbkltYWdlU2l6ZSA9IHRoaXMuaWNvbkltYWdlXy5nZXRTaXplKCk7XG5cbiAgICAgIGlmICghc2l6ZSB8fCAhaWNvbkltYWdlU2l6ZSkge1xuICAgICAgICByZXR1cm4gbnVsbDtcbiAgICAgIH1cblxuICAgICAgb2Zmc2V0ID0gb2Zmc2V0LnNsaWNlKCk7XG5cbiAgICAgIGlmICh0aGlzLm9mZnNldE9yaWdpbl8gPT0gSWNvbk9yaWdpbi5UT1BfUklHSFQgfHwgdGhpcy5vZmZzZXRPcmlnaW5fID09IEljb25PcmlnaW4uQk9UVE9NX1JJR0hUKSB7XG4gICAgICAgIG9mZnNldFswXSA9IGljb25JbWFnZVNpemVbMF0gLSBzaXplWzBdIC0gb2Zmc2V0WzBdO1xuICAgICAgfVxuXG4gICAgICBpZiAodGhpcy5vZmZzZXRPcmlnaW5fID09IEljb25PcmlnaW4uQk9UVE9NX0xFRlQgfHwgdGhpcy5vZmZzZXRPcmlnaW5fID09IEljb25PcmlnaW4uQk9UVE9NX1JJR0hUKSB7XG4gICAgICAgIG9mZnNldFsxXSA9IGljb25JbWFnZVNpemVbMV0gLSBzaXplWzFdIC0gb2Zmc2V0WzFdO1xuICAgICAgfVxuICAgIH1cblxuICAgIG9mZnNldFswXSArPSBkaXNwbGFjZW1lbnRbMF07XG4gICAgb2Zmc2V0WzFdICs9IGRpc3BsYWNlbWVudFsxXTtcbiAgICB0aGlzLm9yaWdpbl8gPSBvZmZzZXQ7XG4gICAgcmV0dXJuIHRoaXMub3JpZ2luXztcbiAgfTtcbiAgLyoqXG4gICAqIEdldCB0aGUgaW1hZ2UgVVJMLlxuICAgKiBAcmV0dXJuIHtzdHJpbmd8dW5kZWZpbmVkfSBJbWFnZSBzcmMuXG4gICAqIEBhcGlcbiAgICovXG5cblxuICBJY29uLnByb3RvdHlwZS5nZXRTcmMgPSBmdW5jdGlvbiAoKSB7XG4gICAgcmV0dXJuIHRoaXMuaWNvbkltYWdlXy5nZXRTcmMoKTtcbiAgfTtcbiAgLyoqXG4gICAqIEdldCB0aGUgc2l6ZSBvZiB0aGUgaWNvbiAoaW4gcGl4ZWxzKS5cbiAgICogQHJldHVybiB7aW1wb3J0KFwiLi4vc2l6ZS5qc1wiKS5TaXplfSBJbWFnZSBzaXplLlxuICAgKiBAYXBpXG4gICAqL1xuXG5cbiAgSWNvbi5wcm90b3R5cGUuZ2V0U2l6ZSA9IGZ1bmN0aW9uICgpIHtcbiAgICByZXR1cm4gIXRoaXMuc2l6ZV8gPyB0aGlzLmljb25JbWFnZV8uZ2V0U2l6ZSgpIDogdGhpcy5zaXplXztcbiAgfTtcbiAgLyoqXG4gICAqIEBwYXJhbSB7ZnVuY3Rpb24oaW1wb3J0KFwiLi4vZXZlbnRzL0V2ZW50LmpzXCIpLmRlZmF1bHQpOiB2b2lkfSBsaXN0ZW5lciBMaXN0ZW5lciBmdW5jdGlvbi5cbiAgICovXG5cblxuICBJY29uLnByb3RvdHlwZS5saXN0ZW5JbWFnZUNoYW5nZSA9IGZ1bmN0aW9uIChsaXN0ZW5lcikge1xuICAgIHRoaXMuaWNvbkltYWdlXy5hZGRFdmVudExpc3RlbmVyKEV2ZW50VHlwZS5DSEFOR0UsIGxpc3RlbmVyKTtcbiAgfTtcbiAgLyoqXG4gICAqIExvYWQgbm90IHlldCBsb2FkZWQgVVJJLlxuICAgKiBXaGVuIHJlbmRlcmluZyBhIGZlYXR1cmUgd2l0aCBhbiBpY29uIHN0eWxlLCB0aGUgdmVjdG9yIHJlbmRlcmVyIHdpbGxcbiAgICogYXV0b21hdGljYWxseSBjYWxsIHRoaXMgbWV0aG9kLiBIb3dldmVyLCB5b3UgbWlnaHQgd2FudCB0byBjYWxsIHRoaXNcbiAgICogbWV0aG9kIHlvdXJzZWxmIGZvciBwcmVsb2FkaW5nIG9yIG90aGVyIHB1cnBvc2VzLlxuICAgKiBAYXBpXG4gICAqL1xuXG5cbiAgSWNvbi5wcm90b3R5cGUubG9hZCA9IGZ1bmN0aW9uICgpIHtcbiAgICB0aGlzLmljb25JbWFnZV8ubG9hZCgpO1xuICB9O1xuICAvKipcbiAgICogQHBhcmFtIHtmdW5jdGlvbihpbXBvcnQoXCIuLi9ldmVudHMvRXZlbnQuanNcIikuZGVmYXVsdCk6IHZvaWR9IGxpc3RlbmVyIExpc3RlbmVyIGZ1bmN0aW9uLlxuICAgKi9cblxuXG4gIEljb24ucHJvdG90eXBlLnVubGlzdGVuSW1hZ2VDaGFuZ2UgPSBmdW5jdGlvbiAobGlzdGVuZXIpIHtcbiAgICB0aGlzLmljb25JbWFnZV8ucmVtb3ZlRXZlbnRMaXN0ZW5lcihFdmVudFR5cGUuQ0hBTkdFLCBsaXN0ZW5lcik7XG4gIH07XG5cbiAgcmV0dXJuIEljb247XG59KEltYWdlU3R5bGUpO1xuXG5leHBvcnQgZGVmYXVsdCBJY29uOyIsIi8qKlxuICogQG1vZHVsZSBvbC9yZW5kZXIvY2FudmFzL2hpdGRldGVjdFxuICovXG5pbXBvcnQgQ2FudmFzSW1tZWRpYXRlUmVuZGVyZXIgZnJvbSAnLi9JbW1lZGlhdGUuanMnO1xuaW1wb3J0IEdlb21ldHJ5VHlwZSBmcm9tICcuLi8uLi9nZW9tL0dlb21ldHJ5VHlwZS5qcyc7XG5pbXBvcnQgSWNvbkFuY2hvclVuaXRzIGZyb20gJy4uLy4uL3N0eWxlL0ljb25BbmNob3JVbml0cy5qcyc7XG5pbXBvcnQgeyBJY29uIH0gZnJvbSAnLi4vLi4vc3R5bGUuanMnO1xuaW1wb3J0IHsgY3JlYXRlQ2FudmFzQ29udGV4dDJEIH0gZnJvbSAnLi4vLi4vZG9tLmpzJztcbmltcG9ydCB7IGludGVyc2VjdHMgfSBmcm9tICcuLi8uLi9leHRlbnQuanMnO1xuaW1wb3J0IHsgbnVtYmVyU2FmZUNvbXBhcmVGdW5jdGlvbiB9IGZyb20gJy4uLy4uL2FycmF5LmpzJztcbi8qKlxuICogQHBhcmFtIHtpbXBvcnQoXCIuLi8uLi9zaXplLmpzXCIpLlNpemV9IHNpemUgQ2FudmFzIHNpemUgaW4gY3NzIHBpeGVscy5cbiAqIEBwYXJhbSB7QXJyYXk8aW1wb3J0KFwiLi4vLi4vdHJhbnNmb3JtLmpzXCIpLlRyYW5zZm9ybT59IHRyYW5zZm9ybXMgVHJhbnNmb3Jtc1xuICogZm9yIHJlbmRlcmluZyBmZWF0dXJlcyB0byBhbGwgd29ybGRzIG9mIHRoZSB2aWV3cG9ydCwgZnJvbSBjb29yZGluYXRlcyB0byBjc3NcbiAqIHBpeGVscy5cbiAqIEBwYXJhbSB7QXJyYXk8aW1wb3J0KFwiLi4vLi4vRmVhdHVyZS5qc1wiKS5GZWF0dXJlTGlrZT59IGZlYXR1cmVzXG4gKiBGZWF0dXJlcyB0byBjb25zaWRlciBmb3IgaGl0IGRldGVjdGlvbi5cbiAqIEBwYXJhbSB7aW1wb3J0KFwiLi4vLi4vc3R5bGUvU3R5bGUuanNcIikuU3R5bGVGdW5jdGlvbnx1bmRlZmluZWR9IHN0eWxlRnVuY3Rpb25cbiAqIExheWVyIHN0eWxlIGZ1bmN0aW9uLlxuICogQHBhcmFtIHtpbXBvcnQoXCIuLi8uLi9leHRlbnQuanNcIikuRXh0ZW50fSBleHRlbnQgRXh0ZW50LlxuICogQHBhcmFtIHtudW1iZXJ9IHJlc29sdXRpb24gUmVzb2x1dGlvbi5cbiAqIEBwYXJhbSB7bnVtYmVyfSByb3RhdGlvbiBSb3RhdGlvbi5cbiAqIEByZXR1cm4ge0ltYWdlRGF0YX0gSGl0IGRldGVjdGlvbiBpbWFnZSBkYXRhLlxuICovXG5cbmV4cG9ydCBmdW5jdGlvbiBjcmVhdGVIaXREZXRlY3Rpb25JbWFnZURhdGEoc2l6ZSwgdHJhbnNmb3JtcywgZmVhdHVyZXMsIHN0eWxlRnVuY3Rpb24sIGV4dGVudCwgcmVzb2x1dGlvbiwgcm90YXRpb24pIHtcbiAgdmFyIHdpZHRoID0gc2l6ZVswXSAvIDI7XG4gIHZhciBoZWlnaHQgPSBzaXplWzFdIC8gMjtcbiAgdmFyIGNvbnRleHQgPSBjcmVhdGVDYW52YXNDb250ZXh0MkQod2lkdGgsIGhlaWdodCk7XG4gIGNvbnRleHQuaW1hZ2VTbW9vdGhpbmdFbmFibGVkID0gZmFsc2U7XG4gIHZhciBjYW52YXMgPSBjb250ZXh0LmNhbnZhcztcbiAgdmFyIHJlbmRlcmVyID0gbmV3IENhbnZhc0ltbWVkaWF0ZVJlbmRlcmVyKGNvbnRleHQsIDAuNSwgZXh0ZW50LCBudWxsLCByb3RhdGlvbik7XG4gIHZhciBmZWF0dXJlQ291bnQgPSBmZWF0dXJlcy5sZW5ndGg7IC8vIFN0cmV0Y2ggaGl0IGRldGVjdGlvbiBpbmRleCB0byB1c2UgdGhlIHdob2xlIGF2YWlsYWJsZSBjb2xvciByYW5nZVxuXG4gIHZhciBpbmRleEZhY3RvciA9IE1hdGguZmxvb3IoKDI1NiAqIDI1NiAqIDI1NiAtIDEpIC8gZmVhdHVyZUNvdW50KTtcbiAgdmFyIGZlYXR1cmVzQnlaSW5kZXggPSB7fTtcblxuICBmb3IgKHZhciBpID0gMTsgaSA8PSBmZWF0dXJlQ291bnQ7ICsraSkge1xuICAgIHZhciBmZWF0dXJlID0gZmVhdHVyZXNbaSAtIDFdO1xuICAgIHZhciBmZWF0dXJlU3R5bGVGdW5jdGlvbiA9IGZlYXR1cmUuZ2V0U3R5bGVGdW5jdGlvbigpIHx8IHN0eWxlRnVuY3Rpb247XG5cbiAgICBpZiAoIXN0eWxlRnVuY3Rpb24pIHtcbiAgICAgIGNvbnRpbnVlO1xuICAgIH1cblxuICAgIHZhciBzdHlsZXMgPSBmZWF0dXJlU3R5bGVGdW5jdGlvbihmZWF0dXJlLCByZXNvbHV0aW9uKTtcblxuICAgIGlmICghc3R5bGVzKSB7XG4gICAgICBjb250aW51ZTtcbiAgICB9XG5cbiAgICBpZiAoIUFycmF5LmlzQXJyYXkoc3R5bGVzKSkge1xuICAgICAgc3R5bGVzID0gW3N0eWxlc107XG4gICAgfVxuXG4gICAgdmFyIGluZGV4ID0gaSAqIGluZGV4RmFjdG9yO1xuICAgIHZhciBjb2xvciA9ICcjJyArICgnMDAwMDAwJyArIGluZGV4LnRvU3RyaW5nKDE2KSkuc2xpY2UoLTYpO1xuXG4gICAgZm9yICh2YXIgaiA9IDAsIGpqID0gc3R5bGVzLmxlbmd0aDsgaiA8IGpqOyArK2opIHtcbiAgICAgIHZhciBvcmlnaW5hbFN0eWxlID0gc3R5bGVzW2pdO1xuICAgICAgdmFyIHN0eWxlID0gb3JpZ2luYWxTdHlsZS5jbG9uZSgpO1xuICAgICAgdmFyIGZpbGwgPSBzdHlsZS5nZXRGaWxsKCk7XG5cbiAgICAgIGlmIChmaWxsKSB7XG4gICAgICAgIGZpbGwuc2V0Q29sb3IoY29sb3IpO1xuICAgICAgfVxuXG4gICAgICB2YXIgc3Ryb2tlID0gc3R5bGUuZ2V0U3Ryb2tlKCk7XG5cbiAgICAgIGlmIChzdHJva2UpIHtcbiAgICAgICAgc3Ryb2tlLnNldENvbG9yKGNvbG9yKTtcbiAgICAgIH1cblxuICAgICAgc3R5bGUuc2V0VGV4dCh1bmRlZmluZWQpO1xuICAgICAgdmFyIGltYWdlID0gb3JpZ2luYWxTdHlsZS5nZXRJbWFnZSgpO1xuXG4gICAgICBpZiAoaW1hZ2UpIHtcbiAgICAgICAgdmFyIGltZ1NpemUgPSBpbWFnZS5nZXRJbWFnZVNpemUoKTtcblxuICAgICAgICBpZiAoIWltZ1NpemUpIHtcbiAgICAgICAgICBjb250aW51ZTtcbiAgICAgICAgfVxuXG4gICAgICAgIHZhciBjYW52YXNfMSA9IGRvY3VtZW50LmNyZWF0ZUVsZW1lbnQoJ2NhbnZhcycpO1xuICAgICAgICBjYW52YXNfMS53aWR0aCA9IGltZ1NpemVbMF07XG4gICAgICAgIGNhbnZhc18xLmhlaWdodCA9IGltZ1NpemVbMV07XG4gICAgICAgIHZhciBpbWdDb250ZXh0ID0gY2FudmFzXzEuZ2V0Q29udGV4dCgnMmQnLCB7XG4gICAgICAgICAgYWxwaGE6IGZhbHNlXG4gICAgICAgIH0pO1xuICAgICAgICBpbWdDb250ZXh0LmZpbGxTdHlsZSA9IGNvbG9yO1xuICAgICAgICB2YXIgaW1nID0gaW1nQ29udGV4dC5jYW52YXM7XG4gICAgICAgIGltZ0NvbnRleHQuZmlsbFJlY3QoMCwgMCwgaW1nLndpZHRoLCBpbWcuaGVpZ2h0KTtcbiAgICAgICAgdmFyIHdpZHRoXzEgPSBpbWdTaXplID8gaW1nU2l6ZVswXSA6IGltZy53aWR0aDtcbiAgICAgICAgdmFyIGhlaWdodF8xID0gaW1nU2l6ZSA/IGltZ1NpemVbMV0gOiBpbWcuaGVpZ2h0O1xuICAgICAgICB2YXIgaWNvbkNvbnRleHQgPSBjcmVhdGVDYW52YXNDb250ZXh0MkQod2lkdGhfMSwgaGVpZ2h0XzEpO1xuICAgICAgICBpY29uQ29udGV4dC5kcmF3SW1hZ2UoaW1nLCAwLCAwKTtcbiAgICAgICAgc3R5bGUuc2V0SW1hZ2UobmV3IEljb24oe1xuICAgICAgICAgIGltZzogaW1nLFxuICAgICAgICAgIGltZ1NpemU6IGltZ1NpemUsXG4gICAgICAgICAgYW5jaG9yOiBpbWFnZS5nZXRBbmNob3IoKSxcbiAgICAgICAgICBhbmNob3JYVW5pdHM6IEljb25BbmNob3JVbml0cy5QSVhFTFMsXG4gICAgICAgICAgYW5jaG9yWVVuaXRzOiBJY29uQW5jaG9yVW5pdHMuUElYRUxTLFxuICAgICAgICAgIG9mZnNldDogaW1hZ2UuZ2V0T3JpZ2luKCksXG4gICAgICAgICAgc2l6ZTogaW1hZ2UuZ2V0U2l6ZSgpLFxuICAgICAgICAgIG9wYWNpdHk6IGltYWdlLmdldE9wYWNpdHkoKSxcbiAgICAgICAgICBzY2FsZTogaW1hZ2UuZ2V0U2NhbGUoKSxcbiAgICAgICAgICByb3RhdGlvbjogaW1hZ2UuZ2V0Um90YXRpb24oKSxcbiAgICAgICAgICByb3RhdGVXaXRoVmlldzogaW1hZ2UuZ2V0Um90YXRlV2l0aFZpZXcoKVxuICAgICAgICB9KSk7XG4gICAgICB9XG5cbiAgICAgIHZhciB6SW5kZXggPSBOdW1iZXIoc3R5bGUuZ2V0WkluZGV4KCkpO1xuICAgICAgdmFyIGJ5R2VvbWV0cnlUeXBlID0gZmVhdHVyZXNCeVpJbmRleFt6SW5kZXhdO1xuXG4gICAgICBpZiAoIWJ5R2VvbWV0cnlUeXBlKSB7XG4gICAgICAgIGJ5R2VvbWV0cnlUeXBlID0ge307XG4gICAgICAgIGZlYXR1cmVzQnlaSW5kZXhbekluZGV4XSA9IGJ5R2VvbWV0cnlUeXBlO1xuICAgICAgICBieUdlb21ldHJ5VHlwZVtHZW9tZXRyeVR5cGUuUE9MWUdPTl0gPSBbXTtcbiAgICAgICAgYnlHZW9tZXRyeVR5cGVbR2VvbWV0cnlUeXBlLkNJUkNMRV0gPSBbXTtcbiAgICAgICAgYnlHZW9tZXRyeVR5cGVbR2VvbWV0cnlUeXBlLkxJTkVfU1RSSU5HXSA9IFtdO1xuICAgICAgICBieUdlb21ldHJ5VHlwZVtHZW9tZXRyeVR5cGUuUE9JTlRdID0gW107XG4gICAgICB9XG5cbiAgICAgIHZhciBnZW9tZXRyeSA9IHN0eWxlLmdldEdlb21ldHJ5RnVuY3Rpb24oKShmZWF0dXJlKTtcblxuICAgICAgaWYgKGdlb21ldHJ5ICYmIGludGVyc2VjdHMoZXh0ZW50LCBnZW9tZXRyeS5nZXRFeHRlbnQoKSkpIHtcbiAgICAgICAgYnlHZW9tZXRyeVR5cGVbZ2VvbWV0cnkuZ2V0VHlwZSgpLnJlcGxhY2UoJ011bHRpJywgJycpXS5wdXNoKGdlb21ldHJ5LCBzdHlsZSk7XG4gICAgICB9XG4gICAgfVxuICB9XG5cbiAgdmFyIHpJbmRleEtleXMgPSBPYmplY3Qua2V5cyhmZWF0dXJlc0J5WkluZGV4KS5tYXAoTnVtYmVyKS5zb3J0KG51bWJlclNhZmVDb21wYXJlRnVuY3Rpb24pO1xuXG4gIGZvciAodmFyIGkgPSAwLCBpaSA9IHpJbmRleEtleXMubGVuZ3RoOyBpIDwgaWk7ICsraSkge1xuICAgIHZhciBieUdlb21ldHJ5VHlwZSA9IGZlYXR1cmVzQnlaSW5kZXhbekluZGV4S2V5c1tpXV07XG5cbiAgICBmb3IgKHZhciB0eXBlIGluIGJ5R2VvbWV0cnlUeXBlKSB7XG4gICAgICB2YXIgZ2VvbUFuZFN0eWxlID0gYnlHZW9tZXRyeVR5cGVbdHlwZV07XG5cbiAgICAgIGZvciAodmFyIGogPSAwLCBqaiA9IGdlb21BbmRTdHlsZS5sZW5ndGg7IGogPCBqajsgaiArPSAyKSB7XG4gICAgICAgIHJlbmRlcmVyLnNldFN0eWxlKGdlb21BbmRTdHlsZVtqICsgMV0pO1xuXG4gICAgICAgIGZvciAodmFyIGsgPSAwLCBrayA9IHRyYW5zZm9ybXMubGVuZ3RoOyBrIDwga2s7ICsraykge1xuICAgICAgICAgIHJlbmRlcmVyLnNldFRyYW5zZm9ybSh0cmFuc2Zvcm1zW2tdKTtcbiAgICAgICAgICByZW5kZXJlci5kcmF3R2VvbWV0cnkoZ2VvbUFuZFN0eWxlW2pdKTtcbiAgICAgICAgfVxuICAgICAgfVxuICAgIH1cbiAgfVxuXG4gIHJldHVybiBjb250ZXh0LmdldEltYWdlRGF0YSgwLCAwLCBjYW52YXMud2lkdGgsIGNhbnZhcy5oZWlnaHQpO1xufVxuLyoqXG4gKiBAcGFyYW0ge2ltcG9ydChcIi4uLy4uL3BpeGVsXCIpLlBpeGVsfSBwaXhlbCBQaXhlbCBjb29yZGluYXRlIG9uIHRoZSBoaXRcbiAqIGRldGVjdGlvbiBjYW52YXMgaW4gY3NzIHBpeGVscy5cbiAqIEBwYXJhbSB7QXJyYXk8aW1wb3J0KFwiLi4vLi4vRmVhdHVyZVwiKS5GZWF0dXJlTGlrZT59IGZlYXR1cmVzIEZlYXR1cmVzLiBIYXMgdG9cbiAqIG1hdGNoIHRoZSBgZmVhdHVyZXNgIGFycmF5IHRoYXQgd2FzIHBhc3NlZCB0byBgY3JlYXRlSGl0RGV0ZWN0aW9uSW1hZ2VEYXRhKClgLlxuICogQHBhcmFtIHtJbWFnZURhdGF9IGltYWdlRGF0YSBIaXQgZGV0ZWN0aW9uIGltYWdlIGRhdGEgZ2VuZXJhdGVkIGJ5XG4gKiBgY3JlYXRlSGl0RGV0ZWN0aW9uSW1hZ2VEYXRhKClgLlxuICogQHJldHVybiB7QXJyYXk8aW1wb3J0KFwiLi4vLi4vRmVhdHVyZVwiKS5GZWF0dXJlTGlrZT59IGZlYXR1cmVzIEZlYXR1cmVzLlxuICovXG5cbmV4cG9ydCBmdW5jdGlvbiBoaXREZXRlY3QocGl4ZWwsIGZlYXR1cmVzLCBpbWFnZURhdGEpIHtcbiAgdmFyIHJlc3VsdEZlYXR1cmVzID0gW107XG5cbiAgaWYgKGltYWdlRGF0YSkge1xuICAgIHZhciBpbmRleCA9IChNYXRoLnJvdW5kKHBpeGVsWzBdIC8gMikgKyBNYXRoLnJvdW5kKHBpeGVsWzFdIC8gMikgKiBpbWFnZURhdGEud2lkdGgpICogNDtcbiAgICB2YXIgciA9IGltYWdlRGF0YS5kYXRhW2luZGV4XTtcbiAgICB2YXIgZyA9IGltYWdlRGF0YS5kYXRhW2luZGV4ICsgMV07XG4gICAgdmFyIGIgPSBpbWFnZURhdGEuZGF0YVtpbmRleCArIDJdO1xuICAgIHZhciBpID0gYiArIDI1NiAqIChnICsgMjU2ICogcik7XG4gICAgdmFyIGluZGV4RmFjdG9yID0gTWF0aC5mbG9vcigoMjU2ICogMjU2ICogMjU2IC0gMSkgLyBmZWF0dXJlcy5sZW5ndGgpO1xuXG4gICAgaWYgKGkgJiYgaSAlIGluZGV4RmFjdG9yID09PSAwKSB7XG4gICAgICByZXN1bHRGZWF0dXJlcy5wdXNoKGZlYXR1cmVzW2kgLyBpbmRleEZhY3RvciAtIDFdKTtcbiAgICB9XG4gIH1cblxuICByZXR1cm4gcmVzdWx0RmVhdHVyZXM7XG59IiwiLyoqXG4gKiBAbW9kdWxlIG9sL3JlbmRlcmVyL3ZlY3RvclxuICovXG5pbXBvcnQgQnVpbGRlclR5cGUgZnJvbSAnLi4vcmVuZGVyL2NhbnZhcy9CdWlsZGVyVHlwZS5qcyc7XG5pbXBvcnQgR2VvbWV0cnlUeXBlIGZyb20gJy4uL2dlb20vR2VvbWV0cnlUeXBlLmpzJztcbmltcG9ydCBJbWFnZVN0YXRlIGZyb20gJy4uL0ltYWdlU3RhdGUuanMnO1xuaW1wb3J0IHsgZ2V0VWlkIH0gZnJvbSAnLi4vdXRpbC5qcyc7XG4vKipcbiAqIEZlYXR1cmUgY2FsbGJhY2suIFRoZSBjYWxsYmFjayB3aWxsIGJlIGNhbGxlZCB3aXRoIHRocmVlIGFyZ3VtZW50cy4gVGhlIGZpcnN0XG4gKiBhcmd1bWVudCBpcyBvbmUge0BsaW5rIG1vZHVsZTpvbC9GZWF0dXJlIGZlYXR1cmV9IG9yIHtAbGluayBtb2R1bGU6b2wvcmVuZGVyL0ZlYXR1cmUgcmVuZGVyIGZlYXR1cmV9XG4gKiBhdCB0aGUgcGl4ZWwsIHRoZSBzZWNvbmQgaXMgdGhlIHtAbGluayBtb2R1bGU6b2wvbGF5ZXIvTGF5ZXIgbGF5ZXJ9IG9mIHRoZSBmZWF0dXJlIGFuZCB3aWxsIGJlIG51bGwgZm9yXG4gKiB1bm1hbmFnZWQgbGF5ZXJzLiBUaGUgdGhpcmQgaXMgdGhlIHtAbGluayBtb2R1bGU6b2wvZ2VvbS9TaW1wbGVHZW9tZXRyeX0gb2YgdGhlIGZlYXR1cmUuIEZvciBmZWF0dXJlc1xuICogd2l0aCBhIEdlb21ldHJ5Q29sbGVjdGlvbiBnZW9tZXRyeSwgaXQgd2lsbCBiZSB0aGUgZmlyc3QgZGV0ZWN0ZWQgZ2VvbWV0cnkgZnJvbSB0aGUgY29sbGVjdGlvbi5cbiAqIEB0ZW1wbGF0ZSBUXG4gKiBAdHlwZWRlZiB7ZnVuY3Rpb24oaW1wb3J0KFwiLi4vRmVhdHVyZS5qc1wiKS5GZWF0dXJlTGlrZSwgaW1wb3J0KFwiLi4vbGF5ZXIvTGF5ZXIuanNcIikuZGVmYXVsdCwgaW1wb3J0KFwiLi4vZ2VvbS9TaW1wbGVHZW9tZXRyeS5qc1wiKS5kZWZhdWx0KTogVH0gRmVhdHVyZUNhbGxiYWNrXG4gKi9cblxuLyoqXG4gKiBUb2xlcmFuY2UgZm9yIGdlb21ldHJ5IHNpbXBsaWZpY2F0aW9uIGluIGRldmljZSBwaXhlbHMuXG4gKiBAdHlwZSB7bnVtYmVyfVxuICovXG5cbnZhciBTSU1QTElGWV9UT0xFUkFOQ0UgPSAwLjU7XG4vKipcbiAqIEBjb25zdFxuICogQHR5cGUge09iamVjdDxpbXBvcnQoXCIuLi9nZW9tL0dlb21ldHJ5VHlwZS5qc1wiKS5kZWZhdWx0LFxuICogICAgICAgICAgICAgICAgZnVuY3Rpb24oaW1wb3J0KFwiLi4vcmVuZGVyL2NhbnZhcy9CdWlsZGVyR3JvdXAuanNcIikuZGVmYXVsdCwgaW1wb3J0KFwiLi4vZ2VvbS9HZW9tZXRyeS5qc1wiKS5kZWZhdWx0LFxuICogICAgICAgICAgICAgICAgICAgICAgICAgaW1wb3J0KFwiLi4vc3R5bGUvU3R5bGUuanNcIikuZGVmYXVsdCwgT2JqZWN0KTogdm9pZD59XG4gKi9cblxudmFyIEdFT01FVFJZX1JFTkRFUkVSUyA9IHtcbiAgJ1BvaW50JzogcmVuZGVyUG9pbnRHZW9tZXRyeSxcbiAgJ0xpbmVTdHJpbmcnOiByZW5kZXJMaW5lU3RyaW5nR2VvbWV0cnksXG4gICdQb2x5Z29uJzogcmVuZGVyUG9seWdvbkdlb21ldHJ5LFxuICAnTXVsdGlQb2ludCc6IHJlbmRlck11bHRpUG9pbnRHZW9tZXRyeSxcbiAgJ011bHRpTGluZVN0cmluZyc6IHJlbmRlck11bHRpTGluZVN0cmluZ0dlb21ldHJ5LFxuICAnTXVsdGlQb2x5Z29uJzogcmVuZGVyTXVsdGlQb2x5Z29uR2VvbWV0cnksXG4gICdHZW9tZXRyeUNvbGxlY3Rpb24nOiByZW5kZXJHZW9tZXRyeUNvbGxlY3Rpb25HZW9tZXRyeSxcbiAgJ0NpcmNsZSc6IHJlbmRlckNpcmNsZUdlb21ldHJ5XG59O1xuLyoqXG4gKiBAcGFyYW0ge2ltcG9ydChcIi4uL0ZlYXR1cmUuanNcIikuRmVhdHVyZUxpa2V9IGZlYXR1cmUxIEZlYXR1cmUgMS5cbiAqIEBwYXJhbSB7aW1wb3J0KFwiLi4vRmVhdHVyZS5qc1wiKS5GZWF0dXJlTGlrZX0gZmVhdHVyZTIgRmVhdHVyZSAyLlxuICogQHJldHVybiB7bnVtYmVyfSBPcmRlci5cbiAqL1xuXG5leHBvcnQgZnVuY3Rpb24gZGVmYXVsdE9yZGVyKGZlYXR1cmUxLCBmZWF0dXJlMikge1xuICByZXR1cm4gcGFyc2VJbnQoZ2V0VWlkKGZlYXR1cmUxKSwgMTApIC0gcGFyc2VJbnQoZ2V0VWlkKGZlYXR1cmUyKSwgMTApO1xufVxuLyoqXG4gKiBAcGFyYW0ge251bWJlcn0gcmVzb2x1dGlvbiBSZXNvbHV0aW9uLlxuICogQHBhcmFtIHtudW1iZXJ9IHBpeGVsUmF0aW8gUGl4ZWwgcmF0aW8uXG4gKiBAcmV0dXJuIHtudW1iZXJ9IFNxdWFyZWQgcGl4ZWwgdG9sZXJhbmNlLlxuICovXG5cbmV4cG9ydCBmdW5jdGlvbiBnZXRTcXVhcmVkVG9sZXJhbmNlKHJlc29sdXRpb24sIHBpeGVsUmF0aW8pIHtcbiAgdmFyIHRvbGVyYW5jZSA9IGdldFRvbGVyYW5jZShyZXNvbHV0aW9uLCBwaXhlbFJhdGlvKTtcbiAgcmV0dXJuIHRvbGVyYW5jZSAqIHRvbGVyYW5jZTtcbn1cbi8qKlxuICogQHBhcmFtIHtudW1iZXJ9IHJlc29sdXRpb24gUmVzb2x1dGlvbi5cbiAqIEBwYXJhbSB7bnVtYmVyfSBwaXhlbFJhdGlvIFBpeGVsIHJhdGlvLlxuICogQHJldHVybiB7bnVtYmVyfSBQaXhlbCB0b2xlcmFuY2UuXG4gKi9cblxuZXhwb3J0IGZ1bmN0aW9uIGdldFRvbGVyYW5jZShyZXNvbHV0aW9uLCBwaXhlbFJhdGlvKSB7XG4gIHJldHVybiBTSU1QTElGWV9UT0xFUkFOQ0UgKiByZXNvbHV0aW9uIC8gcGl4ZWxSYXRpbztcbn1cbi8qKlxuICogQHBhcmFtIHtpbXBvcnQoXCIuLi9yZW5kZXIvY2FudmFzL0J1aWxkZXJHcm91cC5qc1wiKS5kZWZhdWx0fSBidWlsZGVyR3JvdXAgQnVpbGRlciBncm91cC5cbiAqIEBwYXJhbSB7aW1wb3J0KFwiLi4vZ2VvbS9DaXJjbGUuanNcIikuZGVmYXVsdH0gZ2VvbWV0cnkgR2VvbWV0cnkuXG4gKiBAcGFyYW0ge2ltcG9ydChcIi4uL3N0eWxlL1N0eWxlLmpzXCIpLmRlZmF1bHR9IHN0eWxlIFN0eWxlLlxuICogQHBhcmFtIHtpbXBvcnQoXCIuLi9GZWF0dXJlLmpzXCIpLmRlZmF1bHR9IGZlYXR1cmUgRmVhdHVyZS5cbiAqIEBwYXJhbSB7aW1wb3J0KFwiLi4vcmVuZGVyL2NhbnZhcy9CdWlsZGVyR3JvdXAuanNcIikuZGVmYXVsdD19IG9wdF9kZWNsdXR0ZXJCdWlsZGVyR3JvdXAgQnVpbGRlciBmb3IgZGVjbHV0dGVyaW5nLlxuICovXG5cbmZ1bmN0aW9uIHJlbmRlckNpcmNsZUdlb21ldHJ5KGJ1aWxkZXJHcm91cCwgZ2VvbWV0cnksIHN0eWxlLCBmZWF0dXJlLCBvcHRfZGVjbHV0dGVyQnVpbGRlckdyb3VwKSB7XG4gIHZhciBmaWxsU3R5bGUgPSBzdHlsZS5nZXRGaWxsKCk7XG4gIHZhciBzdHJva2VTdHlsZSA9IHN0eWxlLmdldFN0cm9rZSgpO1xuXG4gIGlmIChmaWxsU3R5bGUgfHwgc3Ryb2tlU3R5bGUpIHtcbiAgICB2YXIgY2lyY2xlUmVwbGF5ID0gYnVpbGRlckdyb3VwLmdldEJ1aWxkZXIoc3R5bGUuZ2V0WkluZGV4KCksIEJ1aWxkZXJUeXBlLkNJUkNMRSk7XG4gICAgY2lyY2xlUmVwbGF5LnNldEZpbGxTdHJva2VTdHlsZShmaWxsU3R5bGUsIHN0cm9rZVN0eWxlKTtcbiAgICBjaXJjbGVSZXBsYXkuZHJhd0NpcmNsZShnZW9tZXRyeSwgZmVhdHVyZSk7XG4gIH1cblxuICB2YXIgdGV4dFN0eWxlID0gc3R5bGUuZ2V0VGV4dCgpO1xuXG4gIGlmICh0ZXh0U3R5bGUgJiYgdGV4dFN0eWxlLmdldFRleHQoKSkge1xuICAgIHZhciB0ZXh0UmVwbGF5ID0gKG9wdF9kZWNsdXR0ZXJCdWlsZGVyR3JvdXAgfHwgYnVpbGRlckdyb3VwKS5nZXRCdWlsZGVyKHN0eWxlLmdldFpJbmRleCgpLCBCdWlsZGVyVHlwZS5URVhUKTtcbiAgICB0ZXh0UmVwbGF5LnNldFRleHRTdHlsZSh0ZXh0U3R5bGUpO1xuICAgIHRleHRSZXBsYXkuZHJhd1RleHQoZ2VvbWV0cnksIGZlYXR1cmUpO1xuICB9XG59XG4vKipcbiAqIEBwYXJhbSB7aW1wb3J0KFwiLi4vcmVuZGVyL2NhbnZhcy9CdWlsZGVyR3JvdXAuanNcIikuZGVmYXVsdH0gcmVwbGF5R3JvdXAgUmVwbGF5IGdyb3VwLlxuICogQHBhcmFtIHtpbXBvcnQoXCIuLi9GZWF0dXJlLmpzXCIpLkZlYXR1cmVMaWtlfSBmZWF0dXJlIEZlYXR1cmUuXG4gKiBAcGFyYW0ge2ltcG9ydChcIi4uL3N0eWxlL1N0eWxlLmpzXCIpLmRlZmF1bHR9IHN0eWxlIFN0eWxlLlxuICogQHBhcmFtIHtudW1iZXJ9IHNxdWFyZWRUb2xlcmFuY2UgU3F1YXJlZCB0b2xlcmFuY2UuXG4gKiBAcGFyYW0ge2Z1bmN0aW9uKGltcG9ydChcIi4uL2V2ZW50cy9FdmVudC5qc1wiKS5kZWZhdWx0KTogdm9pZH0gbGlzdGVuZXIgTGlzdGVuZXIgZnVuY3Rpb24uXG4gKiBAcGFyYW0ge2ltcG9ydChcIi4uL3Byb2ouanNcIikuVHJhbnNmb3JtRnVuY3Rpb259IFtvcHRfdHJhbnNmb3JtXSBUcmFuc2Zvcm0gZnJvbSB1c2VyIHRvIHZpZXcgcHJvamVjdGlvbi5cbiAqIEBwYXJhbSB7aW1wb3J0KFwiLi4vcmVuZGVyL2NhbnZhcy9CdWlsZGVyR3JvdXAuanNcIikuZGVmYXVsdD19IG9wdF9kZWNsdXR0ZXJCdWlsZGVyR3JvdXAgQnVpbGRlciBmb3IgZGVjbHV0dGVyaW5nLlxuICogQHJldHVybiB7Ym9vbGVhbn0gYHRydWVgIGlmIHN0eWxlIGlzIGxvYWRpbmcuXG4gKi9cblxuXG5leHBvcnQgZnVuY3Rpb24gcmVuZGVyRmVhdHVyZShyZXBsYXlHcm91cCwgZmVhdHVyZSwgc3R5bGUsIHNxdWFyZWRUb2xlcmFuY2UsIGxpc3RlbmVyLCBvcHRfdHJhbnNmb3JtLCBvcHRfZGVjbHV0dGVyQnVpbGRlckdyb3VwKSB7XG4gIHZhciBsb2FkaW5nID0gZmFsc2U7XG4gIHZhciBpbWFnZVN0eWxlID0gc3R5bGUuZ2V0SW1hZ2UoKTtcblxuICBpZiAoaW1hZ2VTdHlsZSkge1xuICAgIHZhciBpbWFnZVN0YXRlID0gaW1hZ2VTdHlsZS5nZXRJbWFnZVN0YXRlKCk7XG5cbiAgICBpZiAoaW1hZ2VTdGF0ZSA9PSBJbWFnZVN0YXRlLkxPQURFRCB8fCBpbWFnZVN0YXRlID09IEltYWdlU3RhdGUuRVJST1IpIHtcbiAgICAgIGltYWdlU3R5bGUudW5saXN0ZW5JbWFnZUNoYW5nZShsaXN0ZW5lcik7XG4gICAgfSBlbHNlIHtcbiAgICAgIGlmIChpbWFnZVN0YXRlID09IEltYWdlU3RhdGUuSURMRSkge1xuICAgICAgICBpbWFnZVN0eWxlLmxvYWQoKTtcbiAgICAgIH1cblxuICAgICAgaW1hZ2VTdGF0ZSA9IGltYWdlU3R5bGUuZ2V0SW1hZ2VTdGF0ZSgpO1xuICAgICAgaW1hZ2VTdHlsZS5saXN0ZW5JbWFnZUNoYW5nZShsaXN0ZW5lcik7XG4gICAgICBsb2FkaW5nID0gdHJ1ZTtcbiAgICB9XG4gIH1cblxuICByZW5kZXJGZWF0dXJlSW50ZXJuYWwocmVwbGF5R3JvdXAsIGZlYXR1cmUsIHN0eWxlLCBzcXVhcmVkVG9sZXJhbmNlLCBvcHRfdHJhbnNmb3JtLCBvcHRfZGVjbHV0dGVyQnVpbGRlckdyb3VwKTtcbiAgcmV0dXJuIGxvYWRpbmc7XG59XG4vKipcbiAqIEBwYXJhbSB7aW1wb3J0KFwiLi4vcmVuZGVyL2NhbnZhcy9CdWlsZGVyR3JvdXAuanNcIikuZGVmYXVsdH0gcmVwbGF5R3JvdXAgUmVwbGF5IGdyb3VwLlxuICogQHBhcmFtIHtpbXBvcnQoXCIuLi9GZWF0dXJlLmpzXCIpLkZlYXR1cmVMaWtlfSBmZWF0dXJlIEZlYXR1cmUuXG4gKiBAcGFyYW0ge2ltcG9ydChcIi4uL3N0eWxlL1N0eWxlLmpzXCIpLmRlZmF1bHR9IHN0eWxlIFN0eWxlLlxuICogQHBhcmFtIHtudW1iZXJ9IHNxdWFyZWRUb2xlcmFuY2UgU3F1YXJlZCB0b2xlcmFuY2UuXG4gKiBAcGFyYW0ge2ltcG9ydChcIi4uL3Byb2ouanNcIikuVHJhbnNmb3JtRnVuY3Rpb259IFtvcHRfdHJhbnNmb3JtXSBPcHRpb25hbCB0cmFuc2Zvcm0gZnVuY3Rpb24uXG4gKiBAcGFyYW0ge2ltcG9ydChcIi4uL3JlbmRlci9jYW52YXMvQnVpbGRlckdyb3VwLmpzXCIpLmRlZmF1bHQ9fSBvcHRfZGVjbHV0dGVyQnVpbGRlckdyb3VwIEJ1aWxkZXIgZm9yIGRlY2x1dHRlcmluZy5cbiAqL1xuXG5mdW5jdGlvbiByZW5kZXJGZWF0dXJlSW50ZXJuYWwocmVwbGF5R3JvdXAsIGZlYXR1cmUsIHN0eWxlLCBzcXVhcmVkVG9sZXJhbmNlLCBvcHRfdHJhbnNmb3JtLCBvcHRfZGVjbHV0dGVyQnVpbGRlckdyb3VwKSB7XG4gIHZhciBnZW9tZXRyeSA9IHN0eWxlLmdldEdlb21ldHJ5RnVuY3Rpb24oKShmZWF0dXJlKTtcblxuICBpZiAoIWdlb21ldHJ5KSB7XG4gICAgcmV0dXJuO1xuICB9XG5cbiAgdmFyIHNpbXBsaWZpZWRHZW9tZXRyeSA9IGdlb21ldHJ5LnNpbXBsaWZ5VHJhbnNmb3JtZWQoc3F1YXJlZFRvbGVyYW5jZSwgb3B0X3RyYW5zZm9ybSk7XG4gIHZhciByZW5kZXJlciA9IHN0eWxlLmdldFJlbmRlcmVyKCk7XG5cbiAgaWYgKHJlbmRlcmVyKSB7XG4gICAgcmVuZGVyR2VvbWV0cnkocmVwbGF5R3JvdXAsIHNpbXBsaWZpZWRHZW9tZXRyeSwgc3R5bGUsIGZlYXR1cmUpO1xuICB9IGVsc2Uge1xuICAgIHZhciBnZW9tZXRyeVJlbmRlcmVyID0gR0VPTUVUUllfUkVOREVSRVJTW3NpbXBsaWZpZWRHZW9tZXRyeS5nZXRUeXBlKCldO1xuICAgIGdlb21ldHJ5UmVuZGVyZXIocmVwbGF5R3JvdXAsIHNpbXBsaWZpZWRHZW9tZXRyeSwgc3R5bGUsIGZlYXR1cmUsIG9wdF9kZWNsdXR0ZXJCdWlsZGVyR3JvdXApO1xuICB9XG59XG4vKipcbiAqIEBwYXJhbSB7aW1wb3J0KFwiLi4vcmVuZGVyL2NhbnZhcy9CdWlsZGVyR3JvdXAuanNcIikuZGVmYXVsdH0gcmVwbGF5R3JvdXAgUmVwbGF5IGdyb3VwLlxuICogQHBhcmFtIHtpbXBvcnQoXCIuLi9nZW9tL0dlb21ldHJ5LmpzXCIpLmRlZmF1bHR8aW1wb3J0KFwiLi4vcmVuZGVyL0ZlYXR1cmUuanNcIikuZGVmYXVsdH0gZ2VvbWV0cnkgR2VvbWV0cnkuXG4gKiBAcGFyYW0ge2ltcG9ydChcIi4uL3N0eWxlL1N0eWxlLmpzXCIpLmRlZmF1bHR9IHN0eWxlIFN0eWxlLlxuICogQHBhcmFtIHtpbXBvcnQoXCIuLi9GZWF0dXJlLmpzXCIpLkZlYXR1cmVMaWtlfSBmZWF0dXJlIEZlYXR1cmUuXG4gKi9cblxuXG5mdW5jdGlvbiByZW5kZXJHZW9tZXRyeShyZXBsYXlHcm91cCwgZ2VvbWV0cnksIHN0eWxlLCBmZWF0dXJlKSB7XG4gIGlmIChnZW9tZXRyeS5nZXRUeXBlKCkgPT0gR2VvbWV0cnlUeXBlLkdFT01FVFJZX0NPTExFQ1RJT04pIHtcbiAgICB2YXIgZ2VvbWV0cmllcyA9XG4gICAgLyoqIEB0eXBlIHtpbXBvcnQoXCIuLi9nZW9tL0dlb21ldHJ5Q29sbGVjdGlvbi5qc1wiKS5kZWZhdWx0fSAqL1xuICAgIGdlb21ldHJ5LmdldEdlb21ldHJpZXMoKTtcblxuICAgIGZvciAodmFyIGkgPSAwLCBpaSA9IGdlb21ldHJpZXMubGVuZ3RoOyBpIDwgaWk7ICsraSkge1xuICAgICAgcmVuZGVyR2VvbWV0cnkocmVwbGF5R3JvdXAsIGdlb21ldHJpZXNbaV0sIHN0eWxlLCBmZWF0dXJlKTtcbiAgICB9XG5cbiAgICByZXR1cm47XG4gIH1cblxuICB2YXIgcmVwbGF5ID0gcmVwbGF5R3JvdXAuZ2V0QnVpbGRlcihzdHlsZS5nZXRaSW5kZXgoKSwgQnVpbGRlclR5cGUuREVGQVVMVCk7XG4gIHJlcGxheS5kcmF3Q3VzdG9tKFxuICAvKiogQHR5cGUge2ltcG9ydChcIi4uL2dlb20vU2ltcGxlR2VvbWV0cnkuanNcIikuZGVmYXVsdH0gKi9cbiAgZ2VvbWV0cnksIGZlYXR1cmUsIHN0eWxlLmdldFJlbmRlcmVyKCkpO1xufVxuLyoqXG4gKiBAcGFyYW0ge2ltcG9ydChcIi4uL3JlbmRlci9jYW52YXMvQnVpbGRlckdyb3VwLmpzXCIpLmRlZmF1bHR9IHJlcGxheUdyb3VwIFJlcGxheSBncm91cC5cbiAqIEBwYXJhbSB7aW1wb3J0KFwiLi4vZ2VvbS9HZW9tZXRyeUNvbGxlY3Rpb24uanNcIikuZGVmYXVsdH0gZ2VvbWV0cnkgR2VvbWV0cnkuXG4gKiBAcGFyYW0ge2ltcG9ydChcIi4uL3N0eWxlL1N0eWxlLmpzXCIpLmRlZmF1bHR9IHN0eWxlIFN0eWxlLlxuICogQHBhcmFtIHtpbXBvcnQoXCIuLi9GZWF0dXJlLmpzXCIpLmRlZmF1bHR9IGZlYXR1cmUgRmVhdHVyZS5cbiAqIEBwYXJhbSB7aW1wb3J0KFwiLi4vcmVuZGVyL2NhbnZhcy9CdWlsZGVyR3JvdXAuanNcIikuZGVmYXVsdD19IG9wdF9kZWNsdXR0ZXJCdWlsZGVyR3JvdXAgQnVpbGRlciBmb3IgZGVjbHV0dGVyaW5nLlxuICovXG5cblxuZnVuY3Rpb24gcmVuZGVyR2VvbWV0cnlDb2xsZWN0aW9uR2VvbWV0cnkocmVwbGF5R3JvdXAsIGdlb21ldHJ5LCBzdHlsZSwgZmVhdHVyZSwgb3B0X2RlY2x1dHRlckJ1aWxkZXJHcm91cCkge1xuICB2YXIgZ2VvbWV0cmllcyA9IGdlb21ldHJ5LmdldEdlb21ldHJpZXNBcnJheSgpO1xuICB2YXIgaSwgaWk7XG5cbiAgZm9yIChpID0gMCwgaWkgPSBnZW9tZXRyaWVzLmxlbmd0aDsgaSA8IGlpOyArK2kpIHtcbiAgICB2YXIgZ2VvbWV0cnlSZW5kZXJlciA9IEdFT01FVFJZX1JFTkRFUkVSU1tnZW9tZXRyaWVzW2ldLmdldFR5cGUoKV07XG4gICAgZ2VvbWV0cnlSZW5kZXJlcihyZXBsYXlHcm91cCwgZ2VvbWV0cmllc1tpXSwgc3R5bGUsIGZlYXR1cmUsIG9wdF9kZWNsdXR0ZXJCdWlsZGVyR3JvdXApO1xuICB9XG59XG4vKipcbiAqIEBwYXJhbSB7aW1wb3J0KFwiLi4vcmVuZGVyL2NhbnZhcy9CdWlsZGVyR3JvdXAuanNcIikuZGVmYXVsdH0gYnVpbGRlckdyb3VwIFJlcGxheSBncm91cC5cbiAqIEBwYXJhbSB7aW1wb3J0KFwiLi4vZ2VvbS9MaW5lU3RyaW5nLmpzXCIpLmRlZmF1bHR8aW1wb3J0KFwiLi4vcmVuZGVyL0ZlYXR1cmUuanNcIikuZGVmYXVsdH0gZ2VvbWV0cnkgR2VvbWV0cnkuXG4gKiBAcGFyYW0ge2ltcG9ydChcIi4uL3N0eWxlL1N0eWxlLmpzXCIpLmRlZmF1bHR9IHN0eWxlIFN0eWxlLlxuICogQHBhcmFtIHtpbXBvcnQoXCIuLi9GZWF0dXJlLmpzXCIpLkZlYXR1cmVMaWtlfSBmZWF0dXJlIEZlYXR1cmUuXG4gKiBAcGFyYW0ge2ltcG9ydChcIi4uL3JlbmRlci9jYW52YXMvQnVpbGRlckdyb3VwLmpzXCIpLmRlZmF1bHQ9fSBvcHRfZGVjbHV0dGVyQnVpbGRlckdyb3VwIEJ1aWxkZXIgZm9yIGRlY2x1dHRlcmluZy5cbiAqL1xuXG5cbmZ1bmN0aW9uIHJlbmRlckxpbmVTdHJpbmdHZW9tZXRyeShidWlsZGVyR3JvdXAsIGdlb21ldHJ5LCBzdHlsZSwgZmVhdHVyZSwgb3B0X2RlY2x1dHRlckJ1aWxkZXJHcm91cCkge1xuICB2YXIgc3Ryb2tlU3R5bGUgPSBzdHlsZS5nZXRTdHJva2UoKTtcblxuICBpZiAoc3Ryb2tlU3R5bGUpIHtcbiAgICB2YXIgbGluZVN0cmluZ1JlcGxheSA9IGJ1aWxkZXJHcm91cC5nZXRCdWlsZGVyKHN0eWxlLmdldFpJbmRleCgpLCBCdWlsZGVyVHlwZS5MSU5FX1NUUklORyk7XG4gICAgbGluZVN0cmluZ1JlcGxheS5zZXRGaWxsU3Ryb2tlU3R5bGUobnVsbCwgc3Ryb2tlU3R5bGUpO1xuICAgIGxpbmVTdHJpbmdSZXBsYXkuZHJhd0xpbmVTdHJpbmcoZ2VvbWV0cnksIGZlYXR1cmUpO1xuICB9XG5cbiAgdmFyIHRleHRTdHlsZSA9IHN0eWxlLmdldFRleHQoKTtcblxuICBpZiAodGV4dFN0eWxlICYmIHRleHRTdHlsZS5nZXRUZXh0KCkpIHtcbiAgICB2YXIgdGV4dFJlcGxheSA9IChvcHRfZGVjbHV0dGVyQnVpbGRlckdyb3VwIHx8IGJ1aWxkZXJHcm91cCkuZ2V0QnVpbGRlcihzdHlsZS5nZXRaSW5kZXgoKSwgQnVpbGRlclR5cGUuVEVYVCk7XG4gICAgdGV4dFJlcGxheS5zZXRUZXh0U3R5bGUodGV4dFN0eWxlKTtcbiAgICB0ZXh0UmVwbGF5LmRyYXdUZXh0KGdlb21ldHJ5LCBmZWF0dXJlKTtcbiAgfVxufVxuLyoqXG4gKiBAcGFyYW0ge2ltcG9ydChcIi4uL3JlbmRlci9jYW52YXMvQnVpbGRlckdyb3VwLmpzXCIpLmRlZmF1bHR9IGJ1aWxkZXJHcm91cCBSZXBsYXkgZ3JvdXAuXG4gKiBAcGFyYW0ge2ltcG9ydChcIi4uL2dlb20vTXVsdGlMaW5lU3RyaW5nLmpzXCIpLmRlZmF1bHR8aW1wb3J0KFwiLi4vcmVuZGVyL0ZlYXR1cmUuanNcIikuZGVmYXVsdH0gZ2VvbWV0cnkgR2VvbWV0cnkuXG4gKiBAcGFyYW0ge2ltcG9ydChcIi4uL3N0eWxlL1N0eWxlLmpzXCIpLmRlZmF1bHR9IHN0eWxlIFN0eWxlLlxuICogQHBhcmFtIHtpbXBvcnQoXCIuLi9GZWF0dXJlLmpzXCIpLkZlYXR1cmVMaWtlfSBmZWF0dXJlIEZlYXR1cmUuXG4gKiBAcGFyYW0ge2ltcG9ydChcIi4uL3JlbmRlci9jYW52YXMvQnVpbGRlckdyb3VwLmpzXCIpLmRlZmF1bHQ9fSBvcHRfZGVjbHV0dGVyQnVpbGRlckdyb3VwIEJ1aWxkZXIgZm9yIGRlY2x1dHRlcmluZy5cbiAqL1xuXG5cbmZ1bmN0aW9uIHJlbmRlck11bHRpTGluZVN0cmluZ0dlb21ldHJ5KGJ1aWxkZXJHcm91cCwgZ2VvbWV0cnksIHN0eWxlLCBmZWF0dXJlLCBvcHRfZGVjbHV0dGVyQnVpbGRlckdyb3VwKSB7XG4gIHZhciBzdHJva2VTdHlsZSA9IHN0eWxlLmdldFN0cm9rZSgpO1xuXG4gIGlmIChzdHJva2VTdHlsZSkge1xuICAgIHZhciBsaW5lU3RyaW5nUmVwbGF5ID0gYnVpbGRlckdyb3VwLmdldEJ1aWxkZXIoc3R5bGUuZ2V0WkluZGV4KCksIEJ1aWxkZXJUeXBlLkxJTkVfU1RSSU5HKTtcbiAgICBsaW5lU3RyaW5nUmVwbGF5LnNldEZpbGxTdHJva2VTdHlsZShudWxsLCBzdHJva2VTdHlsZSk7XG4gICAgbGluZVN0cmluZ1JlcGxheS5kcmF3TXVsdGlMaW5lU3RyaW5nKGdlb21ldHJ5LCBmZWF0dXJlKTtcbiAgfVxuXG4gIHZhciB0ZXh0U3R5bGUgPSBzdHlsZS5nZXRUZXh0KCk7XG5cbiAgaWYgKHRleHRTdHlsZSAmJiB0ZXh0U3R5bGUuZ2V0VGV4dCgpKSB7XG4gICAgdmFyIHRleHRSZXBsYXkgPSAob3B0X2RlY2x1dHRlckJ1aWxkZXJHcm91cCB8fCBidWlsZGVyR3JvdXApLmdldEJ1aWxkZXIoc3R5bGUuZ2V0WkluZGV4KCksIEJ1aWxkZXJUeXBlLlRFWFQpO1xuICAgIHRleHRSZXBsYXkuc2V0VGV4dFN0eWxlKHRleHRTdHlsZSk7XG4gICAgdGV4dFJlcGxheS5kcmF3VGV4dChnZW9tZXRyeSwgZmVhdHVyZSk7XG4gIH1cbn1cbi8qKlxuICogQHBhcmFtIHtpbXBvcnQoXCIuLi9yZW5kZXIvY2FudmFzL0J1aWxkZXJHcm91cC5qc1wiKS5kZWZhdWx0fSBidWlsZGVyR3JvdXAgUmVwbGF5IGdyb3VwLlxuICogQHBhcmFtIHtpbXBvcnQoXCIuLi9nZW9tL011bHRpUG9seWdvbi5qc1wiKS5kZWZhdWx0fSBnZW9tZXRyeSBHZW9tZXRyeS5cbiAqIEBwYXJhbSB7aW1wb3J0KFwiLi4vc3R5bGUvU3R5bGUuanNcIikuZGVmYXVsdH0gc3R5bGUgU3R5bGUuXG4gKiBAcGFyYW0ge2ltcG9ydChcIi4uL0ZlYXR1cmUuanNcIikuZGVmYXVsdH0gZmVhdHVyZSBGZWF0dXJlLlxuICogQHBhcmFtIHtpbXBvcnQoXCIuLi9yZW5kZXIvY2FudmFzL0J1aWxkZXJHcm91cC5qc1wiKS5kZWZhdWx0PX0gb3B0X2RlY2x1dHRlckJ1aWxkZXJHcm91cCBCdWlsZGVyIGZvciBkZWNsdXR0ZXJpbmcuXG4gKi9cblxuXG5mdW5jdGlvbiByZW5kZXJNdWx0aVBvbHlnb25HZW9tZXRyeShidWlsZGVyR3JvdXAsIGdlb21ldHJ5LCBzdHlsZSwgZmVhdHVyZSwgb3B0X2RlY2x1dHRlckJ1aWxkZXJHcm91cCkge1xuICB2YXIgZmlsbFN0eWxlID0gc3R5bGUuZ2V0RmlsbCgpO1xuICB2YXIgc3Ryb2tlU3R5bGUgPSBzdHlsZS5nZXRTdHJva2UoKTtcblxuICBpZiAoc3Ryb2tlU3R5bGUgfHwgZmlsbFN0eWxlKSB7XG4gICAgdmFyIHBvbHlnb25SZXBsYXkgPSBidWlsZGVyR3JvdXAuZ2V0QnVpbGRlcihzdHlsZS5nZXRaSW5kZXgoKSwgQnVpbGRlclR5cGUuUE9MWUdPTik7XG4gICAgcG9seWdvblJlcGxheS5zZXRGaWxsU3Ryb2tlU3R5bGUoZmlsbFN0eWxlLCBzdHJva2VTdHlsZSk7XG4gICAgcG9seWdvblJlcGxheS5kcmF3TXVsdGlQb2x5Z29uKGdlb21ldHJ5LCBmZWF0dXJlKTtcbiAgfVxuXG4gIHZhciB0ZXh0U3R5bGUgPSBzdHlsZS5nZXRUZXh0KCk7XG5cbiAgaWYgKHRleHRTdHlsZSAmJiB0ZXh0U3R5bGUuZ2V0VGV4dCgpKSB7XG4gICAgdmFyIHRleHRSZXBsYXkgPSAob3B0X2RlY2x1dHRlckJ1aWxkZXJHcm91cCB8fCBidWlsZGVyR3JvdXApLmdldEJ1aWxkZXIoc3R5bGUuZ2V0WkluZGV4KCksIEJ1aWxkZXJUeXBlLlRFWFQpO1xuICAgIHRleHRSZXBsYXkuc2V0VGV4dFN0eWxlKHRleHRTdHlsZSk7XG4gICAgdGV4dFJlcGxheS5kcmF3VGV4dChnZW9tZXRyeSwgZmVhdHVyZSk7XG4gIH1cbn1cbi8qKlxuICogQHBhcmFtIHtpbXBvcnQoXCIuLi9yZW5kZXIvY2FudmFzL0J1aWxkZXJHcm91cC5qc1wiKS5kZWZhdWx0fSBidWlsZGVyR3JvdXAgUmVwbGF5IGdyb3VwLlxuICogQHBhcmFtIHtpbXBvcnQoXCIuLi9nZW9tL1BvaW50LmpzXCIpLmRlZmF1bHR8aW1wb3J0KFwiLi4vcmVuZGVyL0ZlYXR1cmUuanNcIikuZGVmYXVsdH0gZ2VvbWV0cnkgR2VvbWV0cnkuXG4gKiBAcGFyYW0ge2ltcG9ydChcIi4uL3N0eWxlL1N0eWxlLmpzXCIpLmRlZmF1bHR9IHN0eWxlIFN0eWxlLlxuICogQHBhcmFtIHtpbXBvcnQoXCIuLi9GZWF0dXJlLmpzXCIpLkZlYXR1cmVMaWtlfSBmZWF0dXJlIEZlYXR1cmUuXG4gKiBAcGFyYW0ge2ltcG9ydChcIi4uL3JlbmRlci9jYW52YXMvQnVpbGRlckdyb3VwLmpzXCIpLmRlZmF1bHQ9fSBvcHRfZGVjbHV0dGVyQnVpbGRlckdyb3VwIEJ1aWxkZXIgZm9yIGRlY2x1dHRlcmluZy5cbiAqL1xuXG5cbmZ1bmN0aW9uIHJlbmRlclBvaW50R2VvbWV0cnkoYnVpbGRlckdyb3VwLCBnZW9tZXRyeSwgc3R5bGUsIGZlYXR1cmUsIG9wdF9kZWNsdXR0ZXJCdWlsZGVyR3JvdXApIHtcbiAgdmFyIGltYWdlU3R5bGUgPSBzdHlsZS5nZXRJbWFnZSgpO1xuICB2YXIgdGV4dFN0eWxlID0gc3R5bGUuZ2V0VGV4dCgpO1xuICAvKiogQHR5cGUge2ltcG9ydChcIi4uL3JlbmRlci9jYW52YXMuanNcIikuRGVjbHV0dGVySW1hZ2VXaXRoVGV4dH0gKi9cblxuICB2YXIgZGVjbHV0dGVySW1hZ2VXaXRoVGV4dDtcblxuICBpZiAob3B0X2RlY2x1dHRlckJ1aWxkZXJHcm91cCkge1xuICAgIGJ1aWxkZXJHcm91cCA9IG9wdF9kZWNsdXR0ZXJCdWlsZGVyR3JvdXA7XG4gICAgZGVjbHV0dGVySW1hZ2VXaXRoVGV4dCA9IGltYWdlU3R5bGUgJiYgdGV4dFN0eWxlICYmIHRleHRTdHlsZS5nZXRUZXh0KCkgPyB7fSA6IHVuZGVmaW5lZDtcbiAgfVxuXG4gIGlmIChpbWFnZVN0eWxlKSB7XG4gICAgaWYgKGltYWdlU3R5bGUuZ2V0SW1hZ2VTdGF0ZSgpICE9IEltYWdlU3RhdGUuTE9BREVEKSB7XG4gICAgICByZXR1cm47XG4gICAgfVxuXG4gICAgdmFyIGltYWdlUmVwbGF5ID0gYnVpbGRlckdyb3VwLmdldEJ1aWxkZXIoc3R5bGUuZ2V0WkluZGV4KCksIEJ1aWxkZXJUeXBlLklNQUdFKTtcbiAgICBpbWFnZVJlcGxheS5zZXRJbWFnZVN0eWxlKGltYWdlU3R5bGUsIGRlY2x1dHRlckltYWdlV2l0aFRleHQpO1xuICAgIGltYWdlUmVwbGF5LmRyYXdQb2ludChnZW9tZXRyeSwgZmVhdHVyZSk7XG4gIH1cblxuICBpZiAodGV4dFN0eWxlICYmIHRleHRTdHlsZS5nZXRUZXh0KCkpIHtcbiAgICB2YXIgdGV4dFJlcGxheSA9IGJ1aWxkZXJHcm91cC5nZXRCdWlsZGVyKHN0eWxlLmdldFpJbmRleCgpLCBCdWlsZGVyVHlwZS5URVhUKTtcbiAgICB0ZXh0UmVwbGF5LnNldFRleHRTdHlsZSh0ZXh0U3R5bGUsIGRlY2x1dHRlckltYWdlV2l0aFRleHQpO1xuICAgIHRleHRSZXBsYXkuZHJhd1RleHQoZ2VvbWV0cnksIGZlYXR1cmUpO1xuICB9XG59XG4vKipcbiAqIEBwYXJhbSB7aW1wb3J0KFwiLi4vcmVuZGVyL2NhbnZhcy9CdWlsZGVyR3JvdXAuanNcIikuZGVmYXVsdH0gYnVpbGRlckdyb3VwIFJlcGxheSBncm91cC5cbiAqIEBwYXJhbSB7aW1wb3J0KFwiLi4vZ2VvbS9NdWx0aVBvaW50LmpzXCIpLmRlZmF1bHR8aW1wb3J0KFwiLi4vcmVuZGVyL0ZlYXR1cmUuanNcIikuZGVmYXVsdH0gZ2VvbWV0cnkgR2VvbWV0cnkuXG4gKiBAcGFyYW0ge2ltcG9ydChcIi4uL3N0eWxlL1N0eWxlLmpzXCIpLmRlZmF1bHR9IHN0eWxlIFN0eWxlLlxuICogQHBhcmFtIHtpbXBvcnQoXCIuLi9GZWF0dXJlLmpzXCIpLkZlYXR1cmVMaWtlfSBmZWF0dXJlIEZlYXR1cmUuXG4gKiBAcGFyYW0ge2ltcG9ydChcIi4uL3JlbmRlci9jYW52YXMvQnVpbGRlckdyb3VwLmpzXCIpLmRlZmF1bHQ9fSBvcHRfZGVjbHV0dGVyQnVpbGRlckdyb3VwIEJ1aWxkZXIgZm9yIGRlY2x1dHRlcmluZy5cbiAqL1xuXG5cbmZ1bmN0aW9uIHJlbmRlck11bHRpUG9pbnRHZW9tZXRyeShidWlsZGVyR3JvdXAsIGdlb21ldHJ5LCBzdHlsZSwgZmVhdHVyZSwgb3B0X2RlY2x1dHRlckJ1aWxkZXJHcm91cCkge1xuICB2YXIgaW1hZ2VTdHlsZSA9IHN0eWxlLmdldEltYWdlKCk7XG4gIHZhciB0ZXh0U3R5bGUgPSBzdHlsZS5nZXRUZXh0KCk7XG4gIC8qKiBAdHlwZSB7aW1wb3J0KFwiLi4vcmVuZGVyL2NhbnZhcy5qc1wiKS5EZWNsdXR0ZXJJbWFnZVdpdGhUZXh0fSAqL1xuXG4gIHZhciBkZWNsdXR0ZXJJbWFnZVdpdGhUZXh0O1xuXG4gIGlmIChvcHRfZGVjbHV0dGVyQnVpbGRlckdyb3VwKSB7XG4gICAgYnVpbGRlckdyb3VwID0gb3B0X2RlY2x1dHRlckJ1aWxkZXJHcm91cDtcbiAgICBkZWNsdXR0ZXJJbWFnZVdpdGhUZXh0ID0gaW1hZ2VTdHlsZSAmJiB0ZXh0U3R5bGUgJiYgdGV4dFN0eWxlLmdldFRleHQoKSA/IHt9IDogdW5kZWZpbmVkO1xuICB9XG5cbiAgaWYgKGltYWdlU3R5bGUpIHtcbiAgICBpZiAoaW1hZ2VTdHlsZS5nZXRJbWFnZVN0YXRlKCkgIT0gSW1hZ2VTdGF0ZS5MT0FERUQpIHtcbiAgICAgIHJldHVybjtcbiAgICB9XG5cbiAgICB2YXIgaW1hZ2VSZXBsYXkgPSBidWlsZGVyR3JvdXAuZ2V0QnVpbGRlcihzdHlsZS5nZXRaSW5kZXgoKSwgQnVpbGRlclR5cGUuSU1BR0UpO1xuICAgIGltYWdlUmVwbGF5LnNldEltYWdlU3R5bGUoaW1hZ2VTdHlsZSwgZGVjbHV0dGVySW1hZ2VXaXRoVGV4dCk7XG4gICAgaW1hZ2VSZXBsYXkuZHJhd011bHRpUG9pbnQoZ2VvbWV0cnksIGZlYXR1cmUpO1xuICB9XG5cbiAgaWYgKHRleHRTdHlsZSAmJiB0ZXh0U3R5bGUuZ2V0VGV4dCgpKSB7XG4gICAgdmFyIHRleHRSZXBsYXkgPSAob3B0X2RlY2x1dHRlckJ1aWxkZXJHcm91cCB8fCBidWlsZGVyR3JvdXApLmdldEJ1aWxkZXIoc3R5bGUuZ2V0WkluZGV4KCksIEJ1aWxkZXJUeXBlLlRFWFQpO1xuICAgIHRleHRSZXBsYXkuc2V0VGV4dFN0eWxlKHRleHRTdHlsZSwgZGVjbHV0dGVySW1hZ2VXaXRoVGV4dCk7XG4gICAgdGV4dFJlcGxheS5kcmF3VGV4dChnZW9tZXRyeSwgZmVhdHVyZSk7XG4gIH1cbn1cbi8qKlxuICogQHBhcmFtIHtpbXBvcnQoXCIuLi9yZW5kZXIvY2FudmFzL0J1aWxkZXJHcm91cC5qc1wiKS5kZWZhdWx0fSBidWlsZGVyR3JvdXAgUmVwbGF5IGdyb3VwLlxuICogQHBhcmFtIHtpbXBvcnQoXCIuLi9nZW9tL1BvbHlnb24uanNcIikuZGVmYXVsdHxpbXBvcnQoXCIuLi9yZW5kZXIvRmVhdHVyZS5qc1wiKS5kZWZhdWx0fSBnZW9tZXRyeSBHZW9tZXRyeS5cbiAqIEBwYXJhbSB7aW1wb3J0KFwiLi4vc3R5bGUvU3R5bGUuanNcIikuZGVmYXVsdH0gc3R5bGUgU3R5bGUuXG4gKiBAcGFyYW0ge2ltcG9ydChcIi4uL0ZlYXR1cmUuanNcIikuRmVhdHVyZUxpa2V9IGZlYXR1cmUgRmVhdHVyZS5cbiAqIEBwYXJhbSB7aW1wb3J0KFwiLi4vcmVuZGVyL2NhbnZhcy9CdWlsZGVyR3JvdXAuanNcIikuZGVmYXVsdD19IG9wdF9kZWNsdXR0ZXJCdWlsZGVyR3JvdXAgQnVpbGRlciBmb3IgZGVjbHV0dGVyaW5nLlxuICovXG5cblxuZnVuY3Rpb24gcmVuZGVyUG9seWdvbkdlb21ldHJ5KGJ1aWxkZXJHcm91cCwgZ2VvbWV0cnksIHN0eWxlLCBmZWF0dXJlLCBvcHRfZGVjbHV0dGVyQnVpbGRlckdyb3VwKSB7XG4gIHZhciBmaWxsU3R5bGUgPSBzdHlsZS5nZXRGaWxsKCk7XG4gIHZhciBzdHJva2VTdHlsZSA9IHN0eWxlLmdldFN0cm9rZSgpO1xuXG4gIGlmIChmaWxsU3R5bGUgfHwgc3Ryb2tlU3R5bGUpIHtcbiAgICB2YXIgcG9seWdvblJlcGxheSA9IGJ1aWxkZXJHcm91cC5nZXRCdWlsZGVyKHN0eWxlLmdldFpJbmRleCgpLCBCdWlsZGVyVHlwZS5QT0xZR09OKTtcbiAgICBwb2x5Z29uUmVwbGF5LnNldEZpbGxTdHJva2VTdHlsZShmaWxsU3R5bGUsIHN0cm9rZVN0eWxlKTtcbiAgICBwb2x5Z29uUmVwbGF5LmRyYXdQb2x5Z29uKGdlb21ldHJ5LCBmZWF0dXJlKTtcbiAgfVxuXG4gIHZhciB0ZXh0U3R5bGUgPSBzdHlsZS5nZXRUZXh0KCk7XG5cbiAgaWYgKHRleHRTdHlsZSAmJiB0ZXh0U3R5bGUuZ2V0VGV4dCgpKSB7XG4gICAgdmFyIHRleHRSZXBsYXkgPSAob3B0X2RlY2x1dHRlckJ1aWxkZXJHcm91cCB8fCBidWlsZGVyR3JvdXApLmdldEJ1aWxkZXIoc3R5bGUuZ2V0WkluZGV4KCksIEJ1aWxkZXJUeXBlLlRFWFQpO1xuICAgIHRleHRSZXBsYXkuc2V0VGV4dFN0eWxlKHRleHRTdHlsZSk7XG4gICAgdGV4dFJlcGxheS5kcmF3VGV4dChnZW9tZXRyeSwgZmVhdHVyZSk7XG4gIH1cbn0iLCJ2YXIgX19leHRlbmRzID0gdGhpcyAmJiB0aGlzLl9fZXh0ZW5kcyB8fCBmdW5jdGlvbiAoKSB7XG4gIHZhciBfZXh0ZW5kU3RhdGljcyA9IGZ1bmN0aW9uIGV4dGVuZFN0YXRpY3MoZCwgYikge1xuICAgIF9leHRlbmRTdGF0aWNzID0gT2JqZWN0LnNldFByb3RvdHlwZU9mIHx8IHtcbiAgICAgIF9fcHJvdG9fXzogW11cbiAgICB9IGluc3RhbmNlb2YgQXJyYXkgJiYgZnVuY3Rpb24gKGQsIGIpIHtcbiAgICAgIGQuX19wcm90b19fID0gYjtcbiAgICB9IHx8IGZ1bmN0aW9uIChkLCBiKSB7XG4gICAgICBmb3IgKHZhciBwIGluIGIpIHtcbiAgICAgICAgaWYgKE9iamVjdC5wcm90b3R5cGUuaGFzT3duUHJvcGVydHkuY2FsbChiLCBwKSkgZFtwXSA9IGJbcF07XG4gICAgICB9XG4gICAgfTtcblxuICAgIHJldHVybiBfZXh0ZW5kU3RhdGljcyhkLCBiKTtcbiAgfTtcblxuICByZXR1cm4gZnVuY3Rpb24gKGQsIGIpIHtcbiAgICBfZXh0ZW5kU3RhdGljcyhkLCBiKTtcblxuICAgIGZ1bmN0aW9uIF9fKCkge1xuICAgICAgdGhpcy5jb25zdHJ1Y3RvciA9IGQ7XG4gICAgfVxuXG4gICAgZC5wcm90b3R5cGUgPSBiID09PSBudWxsID8gT2JqZWN0LmNyZWF0ZShiKSA6IChfXy5wcm90b3R5cGUgPSBiLnByb3RvdHlwZSwgbmV3IF9fKCkpO1xuICB9O1xufSgpO1xuLyoqXG4gKiBAbW9kdWxlIG9sL3JlbmRlcmVyL2NhbnZhcy9WZWN0b3JUaWxlTGF5ZXJcbiAqL1xuXG5cbmltcG9ydCBDYW52YXNCdWlsZGVyR3JvdXAgZnJvbSAnLi4vLi4vcmVuZGVyL2NhbnZhcy9CdWlsZGVyR3JvdXAuanMnO1xuaW1wb3J0IENhbnZhc0V4ZWN1dG9yR3JvdXAgZnJvbSAnLi4vLi4vcmVuZGVyL2NhbnZhcy9FeGVjdXRvckdyb3VwLmpzJztcbmltcG9ydCBDYW52YXNUaWxlTGF5ZXJSZW5kZXJlciBmcm9tICcuL1RpbGVMYXllci5qcyc7XG5pbXBvcnQgRXZlbnRUeXBlIGZyb20gJy4uLy4uL2V2ZW50cy9FdmVudFR5cGUuanMnO1xuaW1wb3J0IFJlcGxheVR5cGUgZnJvbSAnLi4vLi4vcmVuZGVyL2NhbnZhcy9CdWlsZGVyVHlwZS5qcyc7XG5pbXBvcnQgVGlsZVN0YXRlIGZyb20gJy4uLy4uL1RpbGVTdGF0ZS5qcyc7XG5pbXBvcnQgVmVjdG9yVGlsZVJlbmRlclR5cGUgZnJvbSAnLi4vLi4vbGF5ZXIvVmVjdG9yVGlsZVJlbmRlclR5cGUuanMnO1xuaW1wb3J0IFZpZXdIaW50IGZyb20gJy4uLy4uL1ZpZXdIaW50LmpzJztcbmltcG9ydCB7IGFwcGx5IGFzIGFwcGx5VHJhbnNmb3JtLCBjcmVhdGUgYXMgY3JlYXRlVHJhbnNmb3JtLCBtdWx0aXBseSwgcmVzZXQgYXMgcmVzZXRUcmFuc2Zvcm0sIHNjYWxlLCBzY2FsZSBhcyBzY2FsZVRyYW5zZm9ybSwgdHJhbnNsYXRlIGFzIHRyYW5zbGF0ZVRyYW5zZm9ybSB9IGZyb20gJy4uLy4uL3RyYW5zZm9ybS5qcyc7XG5pbXBvcnQgeyBib3VuZGluZ0V4dGVudCwgYnVmZmVyLCBjb250YWluc0V4dGVudCwgZXF1YWxzLCBnZXRJbnRlcnNlY3Rpb24sIGdldFRvcExlZnQsIGludGVyc2VjdHMgfSBmcm9tICcuLi8uLi9leHRlbnQuanMnO1xuaW1wb3J0IHsgY2xlYXIgfSBmcm9tICcuLi8uLi9vYmouanMnO1xuaW1wb3J0IHsgY3JlYXRlSGl0RGV0ZWN0aW9uSW1hZ2VEYXRhLCBoaXREZXRlY3QgfSBmcm9tICcuLi8uLi9yZW5kZXIvY2FudmFzL2hpdGRldGVjdC5qcyc7XG5pbXBvcnQgeyBnZXRTcXVhcmVkVG9sZXJhbmNlIGFzIGdldFNxdWFyZWRSZW5kZXJUb2xlcmFuY2UsIHJlbmRlckZlYXR1cmUgfSBmcm9tICcuLi92ZWN0b3IuanMnO1xuaW1wb3J0IHsgZ2V0VWlkIH0gZnJvbSAnLi4vLi4vdXRpbC5qcyc7XG5pbXBvcnQgeyBsaXN0ZW4sIHVubGlzdGVuQnlLZXkgfSBmcm9tICcuLi8uLi9ldmVudHMuanMnO1xuaW1wb3J0IHsgdG9TaXplIH0gZnJvbSAnLi4vLi4vc2l6ZS5qcyc7XG5pbXBvcnQgeyB3cmFwWCB9IGZyb20gJy4uLy4uL2Nvb3JkaW5hdGUuanMnO1xuLyoqXG4gKiBAdHlwZSB7IU9iamVjdDxzdHJpbmcsIEFycmF5PGltcG9ydChcIi4uLy4uL3JlbmRlci9jYW52YXMvQnVpbGRlclR5cGUuanNcIikuZGVmYXVsdD4+fVxuICovXG5cbnZhciBJTUFHRV9SRVBMQVlTID0ge1xuICAnaW1hZ2UnOiBbUmVwbGF5VHlwZS5QT0xZR09OLCBSZXBsYXlUeXBlLkNJUkNMRSwgUmVwbGF5VHlwZS5MSU5FX1NUUklORywgUmVwbGF5VHlwZS5JTUFHRSwgUmVwbGF5VHlwZS5URVhUXSxcbiAgJ2h5YnJpZCc6IFtSZXBsYXlUeXBlLlBPTFlHT04sIFJlcGxheVR5cGUuTElORV9TVFJJTkddLFxuICAndmVjdG9yJzogW11cbn07XG4vKipcbiAqIEB0eXBlIHshT2JqZWN0PHN0cmluZywgQXJyYXk8aW1wb3J0KFwiLi4vLi4vcmVuZGVyL2NhbnZhcy9CdWlsZGVyVHlwZS5qc1wiKS5kZWZhdWx0Pj59XG4gKi9cblxudmFyIFZFQ1RPUl9SRVBMQVlTID0ge1xuICAnaW1hZ2UnOiBbUmVwbGF5VHlwZS5ERUZBVUxUXSxcbiAgJ2h5YnJpZCc6IFtSZXBsYXlUeXBlLklNQUdFLCBSZXBsYXlUeXBlLlRFWFQsIFJlcGxheVR5cGUuREVGQVVMVF0sXG4gICd2ZWN0b3InOiBbUmVwbGF5VHlwZS5QT0xZR09OLCBSZXBsYXlUeXBlLkNJUkNMRSwgUmVwbGF5VHlwZS5MSU5FX1NUUklORywgUmVwbGF5VHlwZS5JTUFHRSwgUmVwbGF5VHlwZS5URVhULCBSZXBsYXlUeXBlLkRFRkFVTFRdXG59O1xuLyoqXG4gKiBAY2xhc3NkZXNjXG4gKiBDYW52YXMgcmVuZGVyZXIgZm9yIHZlY3RvciB0aWxlIGxheWVycy5cbiAqIEBhcGlcbiAqL1xuXG52YXIgQ2FudmFzVmVjdG9yVGlsZUxheWVyUmVuZGVyZXIgPVxuLyoqIEBjbGFzcyAqL1xuZnVuY3Rpb24gKF9zdXBlcikge1xuICBfX2V4dGVuZHMoQ2FudmFzVmVjdG9yVGlsZUxheWVyUmVuZGVyZXIsIF9zdXBlcik7XG4gIC8qKlxuICAgKiBAcGFyYW0ge2ltcG9ydChcIi4uLy4uL2xheWVyL1ZlY3RvclRpbGUuanNcIikuZGVmYXVsdH0gbGF5ZXIgVmVjdG9yVGlsZSBsYXllci5cbiAgICovXG5cblxuICBmdW5jdGlvbiBDYW52YXNWZWN0b3JUaWxlTGF5ZXJSZW5kZXJlcihsYXllcikge1xuICAgIHZhciBfdGhpcyA9IF9zdXBlci5jYWxsKHRoaXMsIGxheWVyKSB8fCB0aGlzO1xuICAgIC8qKiBAcHJpdmF0ZSAqL1xuXG5cbiAgICBfdGhpcy5ib3VuZEhhbmRsZVN0eWxlSW1hZ2VDaGFuZ2VfID0gX3RoaXMuaGFuZGxlU3R5bGVJbWFnZUNoYW5nZV8uYmluZChfdGhpcyk7XG4gICAgLyoqXG4gICAgICogQHByaXZhdGVcbiAgICAgKiBAdHlwZSB7Ym9vbGVhbn1cbiAgICAgKi9cblxuICAgIF90aGlzLmRpcnR5XyA9IGZhbHNlO1xuICAgIC8qKlxuICAgICAqIEBwcml2YXRlXG4gICAgICogQHR5cGUge251bWJlcn1cbiAgICAgKi9cblxuICAgIF90aGlzLnJlbmRlcmVkTGF5ZXJSZXZpc2lvbl87XG4gICAgLyoqXG4gICAgICogQHByaXZhdGVcbiAgICAgKiBAdHlwZSB7aW1wb3J0KFwiLi4vLi4vdHJhbnNmb3JtXCIpLlRyYW5zZm9ybX1cbiAgICAgKi9cblxuICAgIF90aGlzLnJlbmRlcmVkUGl4ZWxUb0Nvb3JkaW5hdGVUcmFuc2Zvcm1fID0gbnVsbDtcbiAgICAvKipcbiAgICAgKiBAcHJpdmF0ZVxuICAgICAqIEB0eXBlIHtudW1iZXJ9XG4gICAgICovXG5cbiAgICBfdGhpcy5yZW5kZXJlZFJvdGF0aW9uXztcbiAgICAvKipcbiAgICAgKiBAcHJpdmF0ZVxuICAgICAqIEB0eXBlIHshT2JqZWN0PHN0cmluZywgaW1wb3J0KFwiLi4vLi4vVmVjdG9yUmVuZGVyVGlsZS5qc1wiKS5kZWZhdWx0Pn1cbiAgICAgKi9cblxuICAgIF90aGlzLnJlbmRlclRpbGVJbWFnZVF1ZXVlXyA9IHt9O1xuICAgIC8qKlxuICAgICAqIEB0eXBlIHtPYmplY3Q8c3RyaW5nLCBpbXBvcnQoXCIuLi8uLi9ldmVudHMuanNcIikuRXZlbnRzS2V5Pn1cbiAgICAgKi9cblxuICAgIF90aGlzLnRpbGVMaXN0ZW5lcktleXNfID0ge307XG4gICAgLyoqXG4gICAgICogQHByaXZhdGVcbiAgICAgKiBAdHlwZSB7aW1wb3J0KFwiLi4vLi4vdHJhbnNmb3JtLmpzXCIpLlRyYW5zZm9ybX1cbiAgICAgKi9cblxuICAgIF90aGlzLnRtcFRyYW5zZm9ybV8gPSBjcmVhdGVUcmFuc2Zvcm0oKTtcbiAgICByZXR1cm4gX3RoaXM7XG4gIH1cbiAgLyoqXG4gICAqIEBwYXJhbSB7aW1wb3J0KFwiLi4vLi4vVmVjdG9yUmVuZGVyVGlsZS5qc1wiKS5kZWZhdWx0fSB0aWxlIFRpbGUuXG4gICAqIEBwYXJhbSB7bnVtYmVyfSBwaXhlbFJhdGlvIFBpeGVsIHJhdGlvLlxuICAgKiBAcGFyYW0ge2ltcG9ydChcIi4uLy4uL3Byb2ovUHJvamVjdGlvblwiKS5kZWZhdWx0fSBwcm9qZWN0aW9uIFByb2plY3Rpb24uXG4gICAqIEBwYXJhbSB7Ym9vbGVhbn0gcXVldWUgUXVldWUgdGlsZSBmb3IgcmVuZGVyaW5nLlxuICAgKiBAcmV0dXJuIHtib29sZWFufHVuZGVmaW5lZH0gVGlsZSBuZWVkcyB0byBiZSByZW5kZXJlZC5cbiAgICovXG5cblxuICBDYW52YXNWZWN0b3JUaWxlTGF5ZXJSZW5kZXJlci5wcm90b3R5cGUucHJlcGFyZVRpbGUgPSBmdW5jdGlvbiAodGlsZSwgcGl4ZWxSYXRpbywgcHJvamVjdGlvbiwgcXVldWUpIHtcbiAgICB2YXIgcmVuZGVyO1xuICAgIHZhciB0aWxlVWlkID0gZ2V0VWlkKHRpbGUpO1xuICAgIHZhciBzdGF0ZSA9IHRpbGUuZ2V0U3RhdGUoKTtcblxuICAgIGlmICgoc3RhdGUgPT09IFRpbGVTdGF0ZS5MT0FERUQgJiYgdGlsZS5oaWZpIHx8IHN0YXRlID09PSBUaWxlU3RhdGUuRVJST1IpICYmIHRpbGVVaWQgaW4gdGhpcy50aWxlTGlzdGVuZXJLZXlzXykge1xuICAgICAgdW5saXN0ZW5CeUtleSh0aGlzLnRpbGVMaXN0ZW5lcktleXNfW3RpbGVVaWRdKTtcbiAgICAgIGRlbGV0ZSB0aGlzLnRpbGVMaXN0ZW5lcktleXNfW3RpbGVVaWRdO1xuICAgIH1cblxuICAgIGlmIChzdGF0ZSA9PT0gVGlsZVN0YXRlLkxPQURFRCB8fCBzdGF0ZSA9PT0gVGlsZVN0YXRlLkVSUk9SKSB7XG4gICAgICB0aGlzLnVwZGF0ZUV4ZWN1dG9yR3JvdXBfKHRpbGUsIHBpeGVsUmF0aW8sIHByb2plY3Rpb24pO1xuXG4gICAgICBpZiAodGhpcy50aWxlSW1hZ2VOZWVkc1JlbmRlcl8odGlsZSwgcGl4ZWxSYXRpbywgcHJvamVjdGlvbikpIHtcbiAgICAgICAgcmVuZGVyID0gdHJ1ZTtcblxuICAgICAgICBpZiAocXVldWUpIHtcbiAgICAgICAgICB0aGlzLnJlbmRlclRpbGVJbWFnZVF1ZXVlX1t0aWxlVWlkXSA9IHRpbGU7XG4gICAgICAgIH1cbiAgICAgIH1cbiAgICB9XG5cbiAgICByZXR1cm4gcmVuZGVyO1xuICB9O1xuICAvKipcbiAgICogQHBhcmFtIHtudW1iZXJ9IHogVGlsZSBjb29yZGluYXRlIHouXG4gICAqIEBwYXJhbSB7bnVtYmVyfSB4IFRpbGUgY29vcmRpbmF0ZSB4LlxuICAgKiBAcGFyYW0ge251bWJlcn0geSBUaWxlIGNvb3JkaW5hdGUgeS5cbiAgICogQHBhcmFtIHtpbXBvcnQoXCIuLi8uLi9QbHVnZ2FibGVNYXAuanNcIikuRnJhbWVTdGF0ZX0gZnJhbWVTdGF0ZSBGcmFtZSBzdGF0ZS5cbiAgICogQHJldHVybiB7IWltcG9ydChcIi4uLy4uL1RpbGUuanNcIikuZGVmYXVsdH0gVGlsZS5cbiAgICovXG5cblxuICBDYW52YXNWZWN0b3JUaWxlTGF5ZXJSZW5kZXJlci5wcm90b3R5cGUuZ2V0VGlsZSA9IGZ1bmN0aW9uICh6LCB4LCB5LCBmcmFtZVN0YXRlKSB7XG4gICAgdmFyIHBpeGVsUmF0aW8gPSBmcmFtZVN0YXRlLnBpeGVsUmF0aW87XG4gICAgdmFyIHZpZXdTdGF0ZSA9IGZyYW1lU3RhdGUudmlld1N0YXRlO1xuICAgIHZhciByZXNvbHV0aW9uID0gdmlld1N0YXRlLnJlc29sdXRpb247XG4gICAgdmFyIHByb2plY3Rpb24gPSB2aWV3U3RhdGUucHJvamVjdGlvbjtcbiAgICB2YXIgbGF5ZXIgPSB0aGlzLmdldExheWVyKCk7XG4gICAgdmFyIHRpbGUgPSBsYXllci5nZXRTb3VyY2UoKS5nZXRUaWxlKHosIHgsIHksIHBpeGVsUmF0aW8sIHByb2plY3Rpb24pO1xuXG4gICAgaWYgKHRpbGUuZ2V0U3RhdGUoKSA8IFRpbGVTdGF0ZS5MT0FERUQpIHtcbiAgICAgIHRpbGUud2FudGVkUmVzb2x1dGlvbiA9IHJlc29sdXRpb247XG4gICAgICB2YXIgdGlsZVVpZCA9IGdldFVpZCh0aWxlKTtcblxuICAgICAgaWYgKCEodGlsZVVpZCBpbiB0aGlzLnRpbGVMaXN0ZW5lcktleXNfKSkge1xuICAgICAgICB2YXIgbGlzdGVuZXJLZXkgPSBsaXN0ZW4odGlsZSwgRXZlbnRUeXBlLkNIQU5HRSwgdGhpcy5wcmVwYXJlVGlsZS5iaW5kKHRoaXMsIHRpbGUsIHBpeGVsUmF0aW8sIHByb2plY3Rpb24sIHRydWUpKTtcbiAgICAgICAgdGhpcy50aWxlTGlzdGVuZXJLZXlzX1t0aWxlVWlkXSA9IGxpc3RlbmVyS2V5O1xuICAgICAgfVxuICAgIH0gZWxzZSB7XG4gICAgICB2YXIgdmlld0hpbnRzID0gZnJhbWVTdGF0ZS52aWV3SGludHM7XG4gICAgICB2YXIgaGlmaSA9ICEodmlld0hpbnRzW1ZpZXdIaW50LkFOSU1BVElOR10gfHwgdmlld0hpbnRzW1ZpZXdIaW50LklOVEVSQUNUSU5HXSk7XG5cbiAgICAgIGlmIChoaWZpIHx8ICF0aWxlLndhbnRlZFJlc29sdXRpb24pIHtcbiAgICAgICAgdGlsZS53YW50ZWRSZXNvbHV0aW9uID0gcmVzb2x1dGlvbjtcbiAgICAgIH1cblxuICAgICAgdmFyIHJlbmRlciA9IHRoaXMucHJlcGFyZVRpbGUodGlsZSwgcGl4ZWxSYXRpbywgcHJvamVjdGlvbiwgZmFsc2UpO1xuXG4gICAgICBpZiAocmVuZGVyICYmIGxheWVyLmdldFJlbmRlck1vZGUoKSAhPT0gVmVjdG9yVGlsZVJlbmRlclR5cGUuVkVDVE9SKSB7XG4gICAgICAgIHRoaXMucmVuZGVyVGlsZUltYWdlXyh0aWxlLCBmcmFtZVN0YXRlKTtcbiAgICAgIH1cbiAgICB9XG5cbiAgICByZXR1cm4gX3N1cGVyLnByb3RvdHlwZS5nZXRUaWxlLmNhbGwodGhpcywgeiwgeCwgeSwgZnJhbWVTdGF0ZSk7XG4gIH07XG4gIC8qKlxuICAgKiBAcGFyYW0ge2ltcG9ydChcIi4uLy4uL1ZlY3RvclJlbmRlclRpbGUuanNcIikuZGVmYXVsdH0gdGlsZSBUaWxlLlxuICAgKiBAcmV0dXJuIHtib29sZWFufSBUaWxlIGlzIGRyYXdhYmxlLlxuICAgKi9cblxuXG4gIENhbnZhc1ZlY3RvclRpbGVMYXllclJlbmRlcmVyLnByb3RvdHlwZS5pc0RyYXdhYmxlVGlsZSA9IGZ1bmN0aW9uICh0aWxlKSB7XG4gICAgdmFyIGxheWVyID0gdGhpcy5nZXRMYXllcigpO1xuICAgIHJldHVybiBfc3VwZXIucHJvdG90eXBlLmlzRHJhd2FibGVUaWxlLmNhbGwodGhpcywgdGlsZSkgJiYgKGxheWVyLmdldFJlbmRlck1vZGUoKSA9PT0gVmVjdG9yVGlsZVJlbmRlclR5cGUuVkVDVE9SID8gZ2V0VWlkKGxheWVyKSBpbiB0aWxlLmV4ZWN1dG9yR3JvdXBzIDogdGlsZS5oYXNDb250ZXh0KGxheWVyKSk7XG4gIH07XG4gIC8qKlxuICAgKiBAaW5oZXJpdERvY1xuICAgKi9cblxuXG4gIENhbnZhc1ZlY3RvclRpbGVMYXllclJlbmRlcmVyLnByb3RvdHlwZS5nZXRUaWxlSW1hZ2UgPSBmdW5jdGlvbiAodGlsZSkge1xuICAgIHJldHVybiB0aWxlLmdldEltYWdlKHRoaXMuZ2V0TGF5ZXIoKSk7XG4gIH07XG4gIC8qKlxuICAgKiBEZXRlcm1pbmUgd2hldGhlciByZW5kZXIgc2hvdWxkIGJlIGNhbGxlZC5cbiAgICogQHBhcmFtIHtpbXBvcnQoXCIuLi8uLi9QbHVnZ2FibGVNYXAuanNcIikuRnJhbWVTdGF0ZX0gZnJhbWVTdGF0ZSBGcmFtZSBzdGF0ZS5cbiAgICogQHJldHVybiB7Ym9vbGVhbn0gTGF5ZXIgaXMgcmVhZHkgdG8gYmUgcmVuZGVyZWQuXG4gICAqL1xuXG5cbiAgQ2FudmFzVmVjdG9yVGlsZUxheWVyUmVuZGVyZXIucHJvdG90eXBlLnByZXBhcmVGcmFtZSA9IGZ1bmN0aW9uIChmcmFtZVN0YXRlKSB7XG4gICAgdmFyIGxheWVyUmV2aXNpb24gPSB0aGlzLmdldExheWVyKCkuZ2V0UmV2aXNpb24oKTtcblxuICAgIGlmICh0aGlzLnJlbmRlcmVkTGF5ZXJSZXZpc2lvbl8gIT0gbGF5ZXJSZXZpc2lvbikge1xuICAgICAgdGhpcy5yZW5kZXJlZFRpbGVzLmxlbmd0aCA9IDA7XG4gICAgfVxuXG4gICAgdGhpcy5yZW5kZXJlZExheWVyUmV2aXNpb25fID0gbGF5ZXJSZXZpc2lvbjtcbiAgICByZXR1cm4gX3N1cGVyLnByb3RvdHlwZS5wcmVwYXJlRnJhbWUuY2FsbCh0aGlzLCBmcmFtZVN0YXRlKTtcbiAgfTtcbiAgLyoqXG4gICAqIEBwYXJhbSB7aW1wb3J0KFwiLi4vLi4vVmVjdG9yUmVuZGVyVGlsZS5qc1wiKS5kZWZhdWx0fSB0aWxlIFRpbGUuXG4gICAqIEBwYXJhbSB7bnVtYmVyfSBwaXhlbFJhdGlvIFBpeGVsIHJhdGlvLlxuICAgKiBAcGFyYW0ge2ltcG9ydChcIi4uLy4uL3Byb2ovUHJvamVjdGlvbi5qc1wiKS5kZWZhdWx0fSBwcm9qZWN0aW9uIFByb2plY3Rpb24uXG4gICAqIEBwcml2YXRlXG4gICAqL1xuXG5cbiAgQ2FudmFzVmVjdG9yVGlsZUxheWVyUmVuZGVyZXIucHJvdG90eXBlLnVwZGF0ZUV4ZWN1dG9yR3JvdXBfID0gZnVuY3Rpb24gKHRpbGUsIHBpeGVsUmF0aW8sIHByb2plY3Rpb24pIHtcbiAgICB2YXIgbGF5ZXIgPVxuICAgIC8qKiBAdHlwZSB7aW1wb3J0KFwiLi4vLi4vbGF5ZXIvVmVjdG9yVGlsZS5qc1wiKS5kZWZhdWx0fSAqL1xuICAgIHRoaXMuZ2V0TGF5ZXIoKTtcbiAgICB2YXIgcmV2aXNpb24gPSBsYXllci5nZXRSZXZpc2lvbigpO1xuICAgIHZhciByZW5kZXJPcmRlciA9IGxheWVyLmdldFJlbmRlck9yZGVyKCkgfHwgbnVsbDtcbiAgICB2YXIgcmVzb2x1dGlvbiA9IHRpbGUud2FudGVkUmVzb2x1dGlvbjtcbiAgICB2YXIgYnVpbGRlclN0YXRlID0gdGlsZS5nZXRSZXBsYXlTdGF0ZShsYXllcik7XG5cbiAgICBpZiAoIWJ1aWxkZXJTdGF0ZS5kaXJ0eSAmJiBidWlsZGVyU3RhdGUucmVuZGVyZWRSZXNvbHV0aW9uID09PSByZXNvbHV0aW9uICYmIGJ1aWxkZXJTdGF0ZS5yZW5kZXJlZFJldmlzaW9uID09IHJldmlzaW9uICYmIGJ1aWxkZXJTdGF0ZS5yZW5kZXJlZFJlbmRlck9yZGVyID09IHJlbmRlck9yZGVyICYmIGJ1aWxkZXJTdGF0ZS5yZW5kZXJlZFogPT09IHRpbGUuc291cmNlWikge1xuICAgICAgcmV0dXJuO1xuICAgIH1cblxuICAgIHZhciBzb3VyY2UgPSBsYXllci5nZXRTb3VyY2UoKTtcbiAgICB2YXIgZGVjbHV0dGVyID0gbGF5ZXIuZ2V0RGVjbHV0dGVyKCk7XG4gICAgdmFyIHNvdXJjZVRpbGVHcmlkID0gc291cmNlLmdldFRpbGVHcmlkKCk7XG4gICAgdmFyIHRpbGVHcmlkID0gc291cmNlLmdldFRpbGVHcmlkRm9yUHJvamVjdGlvbihwcm9qZWN0aW9uKTtcbiAgICB2YXIgdGlsZUV4dGVudCA9IHRpbGVHcmlkLmdldFRpbGVDb29yZEV4dGVudCh0aWxlLndyYXBwZWRUaWxlQ29vcmQpO1xuICAgIHZhciBzb3VyY2VUaWxlcyA9IHNvdXJjZS5nZXRTb3VyY2VUaWxlcyhwaXhlbFJhdGlvLCBwcm9qZWN0aW9uLCB0aWxlKTtcbiAgICB2YXIgbGF5ZXJVaWQgPSBnZXRVaWQobGF5ZXIpO1xuICAgIGRlbGV0ZSB0aWxlLmhpdERldGVjdGlvbkltYWdlRGF0YVtsYXllclVpZF07XG4gICAgdGlsZS5leGVjdXRvckdyb3Vwc1tsYXllclVpZF0gPSBbXTtcblxuICAgIGlmIChkZWNsdXR0ZXIpIHtcbiAgICAgIHRpbGUuZGVjbHV0dGVyRXhlY3V0b3JHcm91cHNbbGF5ZXJVaWRdID0gW107XG4gICAgfVxuXG4gICAgdmFyIF9sb29wXzEgPSBmdW5jdGlvbiBfbG9vcF8xKHQsIHR0KSB7XG4gICAgICB2YXIgc291cmNlVGlsZSA9IHNvdXJjZVRpbGVzW3RdO1xuXG4gICAgICBpZiAoc291cmNlVGlsZS5nZXRTdGF0ZSgpICE9IFRpbGVTdGF0ZS5MT0FERUQpIHtcbiAgICAgICAgcmV0dXJuIFwiY29udGludWVcIjtcbiAgICAgIH1cblxuICAgICAgdmFyIHNvdXJjZVRpbGVDb29yZCA9IHNvdXJjZVRpbGUudGlsZUNvb3JkO1xuICAgICAgdmFyIHNvdXJjZVRpbGVFeHRlbnQgPSBzb3VyY2VUaWxlR3JpZC5nZXRUaWxlQ29vcmRFeHRlbnQoc291cmNlVGlsZUNvb3JkKTtcbiAgICAgIHZhciBzaGFyZWRFeHRlbnQgPSBnZXRJbnRlcnNlY3Rpb24odGlsZUV4dGVudCwgc291cmNlVGlsZUV4dGVudCk7XG4gICAgICB2YXIgYnVmZmVyZWRFeHRlbnQgPSBlcXVhbHMoc291cmNlVGlsZUV4dGVudCwgc2hhcmVkRXh0ZW50KSA/IG51bGwgOiBidWZmZXIoc2hhcmVkRXh0ZW50LCBsYXllci5nZXRSZW5kZXJCdWZmZXIoKSAqIHJlc29sdXRpb24sIHRoaXNfMS50bXBFeHRlbnQpO1xuICAgICAgYnVpbGRlclN0YXRlLmRpcnR5ID0gZmFsc2U7XG4gICAgICB2YXIgYnVpbGRlckdyb3VwID0gbmV3IENhbnZhc0J1aWxkZXJHcm91cCgwLCBzaGFyZWRFeHRlbnQsIHJlc29sdXRpb24sIHBpeGVsUmF0aW8pO1xuICAgICAgdmFyIGRlY2x1dHRlckJ1aWxkZXJHcm91cCA9IGRlY2x1dHRlciA/IG5ldyBDYW52YXNCdWlsZGVyR3JvdXAoMCwgc2hhcmVkRXh0ZW50LCByZXNvbHV0aW9uLCBwaXhlbFJhdGlvKSA6IHVuZGVmaW5lZDtcbiAgICAgIHZhciBzcXVhcmVkVG9sZXJhbmNlID0gZ2V0U3F1YXJlZFJlbmRlclRvbGVyYW5jZShyZXNvbHV0aW9uLCBwaXhlbFJhdGlvKTtcbiAgICAgIC8qKlxuICAgICAgICogQHBhcmFtIHtpbXBvcnQoXCIuLi8uLi9GZWF0dXJlLmpzXCIpLkZlYXR1cmVMaWtlfSBmZWF0dXJlIEZlYXR1cmUuXG4gICAgICAgKiBAdGhpcyB7Q2FudmFzVmVjdG9yVGlsZUxheWVyUmVuZGVyZXJ9XG4gICAgICAgKi9cblxuICAgICAgdmFyIHJlbmRlciA9IGZ1bmN0aW9uIHJlbmRlcihmZWF0dXJlKSB7XG4gICAgICAgIHZhciBzdHlsZXM7XG4gICAgICAgIHZhciBzdHlsZUZ1bmN0aW9uID0gZmVhdHVyZS5nZXRTdHlsZUZ1bmN0aW9uKCkgfHwgbGF5ZXIuZ2V0U3R5bGVGdW5jdGlvbigpO1xuXG4gICAgICAgIGlmIChzdHlsZUZ1bmN0aW9uKSB7XG4gICAgICAgICAgc3R5bGVzID0gc3R5bGVGdW5jdGlvbihmZWF0dXJlLCByZXNvbHV0aW9uKTtcbiAgICAgICAgfVxuXG4gICAgICAgIGlmIChzdHlsZXMpIHtcbiAgICAgICAgICB2YXIgZGlydHkgPSB0aGlzLnJlbmRlckZlYXR1cmUoZmVhdHVyZSwgc3F1YXJlZFRvbGVyYW5jZSwgc3R5bGVzLCBidWlsZGVyR3JvdXAsIGRlY2x1dHRlckJ1aWxkZXJHcm91cCk7XG4gICAgICAgICAgdGhpcy5kaXJ0eV8gPSB0aGlzLmRpcnR5XyB8fCBkaXJ0eTtcbiAgICAgICAgICBidWlsZGVyU3RhdGUuZGlydHkgPSBidWlsZGVyU3RhdGUuZGlydHkgfHwgZGlydHk7XG4gICAgICAgIH1cbiAgICAgIH07XG5cbiAgICAgIHZhciBmZWF0dXJlcyA9IHNvdXJjZVRpbGUuZ2V0RmVhdHVyZXMoKTtcblxuICAgICAgaWYgKHJlbmRlck9yZGVyICYmIHJlbmRlck9yZGVyICE9PSBidWlsZGVyU3RhdGUucmVuZGVyZWRSZW5kZXJPcmRlcikge1xuICAgICAgICBmZWF0dXJlcy5zb3J0KHJlbmRlck9yZGVyKTtcbiAgICAgIH1cblxuICAgICAgZm9yICh2YXIgaSA9IDAsIGlpID0gZmVhdHVyZXMubGVuZ3RoOyBpIDwgaWk7ICsraSkge1xuICAgICAgICB2YXIgZmVhdHVyZSA9IGZlYXR1cmVzW2ldO1xuXG4gICAgICAgIGlmICghYnVmZmVyZWRFeHRlbnQgfHwgaW50ZXJzZWN0cyhidWZmZXJlZEV4dGVudCwgZmVhdHVyZS5nZXRHZW9tZXRyeSgpLmdldEV4dGVudCgpKSkge1xuICAgICAgICAgIHJlbmRlci5jYWxsKHRoaXNfMSwgZmVhdHVyZSk7XG4gICAgICAgIH1cbiAgICAgIH1cblxuICAgICAgdmFyIGV4ZWN1dG9yR3JvdXBJbnN0cnVjdGlvbnMgPSBidWlsZGVyR3JvdXAuZmluaXNoKCk7IC8vIG5vIG5lZWQgdG8gY2xpcCB3aGVuIHRoZSByZW5kZXIgdGlsZSBpcyBjb3ZlcmVkIGJ5IGEgc2luZ2xlIHNvdXJjZSB0aWxlXG5cbiAgICAgIHZhciByZXBsYXlFeHRlbnQgPSBsYXllci5nZXRSZW5kZXJNb2RlKCkgIT09IFZlY3RvclRpbGVSZW5kZXJUeXBlLlZFQ1RPUiAmJiBkZWNsdXR0ZXIgJiYgc291cmNlVGlsZXMubGVuZ3RoID09PSAxID8gbnVsbCA6IHNoYXJlZEV4dGVudDtcbiAgICAgIHZhciByZW5kZXJpbmdSZXBsYXlHcm91cCA9IG5ldyBDYW52YXNFeGVjdXRvckdyb3VwKHJlcGxheUV4dGVudCwgcmVzb2x1dGlvbiwgcGl4ZWxSYXRpbywgc291cmNlLmdldE92ZXJsYXBzKCksIGV4ZWN1dG9yR3JvdXBJbnN0cnVjdGlvbnMsIGxheWVyLmdldFJlbmRlckJ1ZmZlcigpKTtcbiAgICAgIHRpbGUuZXhlY3V0b3JHcm91cHNbbGF5ZXJVaWRdLnB1c2gocmVuZGVyaW5nUmVwbGF5R3JvdXApO1xuXG4gICAgICBpZiAoZGVjbHV0dGVyQnVpbGRlckdyb3VwKSB7XG4gICAgICAgIHZhciBkZWNsdXR0ZXJFeGVjdXRvckdyb3VwID0gbmV3IENhbnZhc0V4ZWN1dG9yR3JvdXAocmVwbGF5RXh0ZW50LCByZXNvbHV0aW9uLCBwaXhlbFJhdGlvLCBzb3VyY2UuZ2V0T3ZlcmxhcHMoKSwgZGVjbHV0dGVyQnVpbGRlckdyb3VwLmZpbmlzaCgpLCBsYXllci5nZXRSZW5kZXJCdWZmZXIoKSk7XG4gICAgICAgIHRpbGUuZGVjbHV0dGVyRXhlY3V0b3JHcm91cHNbbGF5ZXJVaWRdLnB1c2goZGVjbHV0dGVyRXhlY3V0b3JHcm91cCk7XG4gICAgICB9XG4gICAgfTtcblxuICAgIHZhciB0aGlzXzEgPSB0aGlzO1xuXG4gICAgZm9yICh2YXIgdCA9IDAsIHR0ID0gc291cmNlVGlsZXMubGVuZ3RoOyB0IDwgdHQ7ICsrdCkge1xuICAgICAgX2xvb3BfMSh0LCB0dCk7XG4gICAgfVxuXG4gICAgYnVpbGRlclN0YXRlLnJlbmRlcmVkUmV2aXNpb24gPSByZXZpc2lvbjtcbiAgICBidWlsZGVyU3RhdGUucmVuZGVyZWRaID0gdGlsZS5zb3VyY2VaO1xuICAgIGJ1aWxkZXJTdGF0ZS5yZW5kZXJlZFJlbmRlck9yZGVyID0gcmVuZGVyT3JkZXI7XG4gICAgYnVpbGRlclN0YXRlLnJlbmRlcmVkUmVzb2x1dGlvbiA9IHJlc29sdXRpb247XG4gIH07XG4gIC8qKlxuICAgKiBAcGFyYW0ge2ltcG9ydChcIi4uLy4uL2Nvb3JkaW5hdGUuanNcIikuQ29vcmRpbmF0ZX0gY29vcmRpbmF0ZSBDb29yZGluYXRlLlxuICAgKiBAcGFyYW0ge2ltcG9ydChcIi4uLy4uL1BsdWdnYWJsZU1hcC5qc1wiKS5GcmFtZVN0YXRlfSBmcmFtZVN0YXRlIEZyYW1lIHN0YXRlLlxuICAgKiBAcGFyYW0ge251bWJlcn0gaGl0VG9sZXJhbmNlIEhpdCB0b2xlcmFuY2UgaW4gcGl4ZWxzLlxuICAgKiBAcGFyYW0ge2ltcG9ydChcIi4uL3ZlY3Rvci5qc1wiKS5GZWF0dXJlQ2FsbGJhY2s8VD59IGNhbGxiYWNrIEZlYXR1cmUgY2FsbGJhY2suXG4gICAqIEBwYXJhbSB7QXJyYXk8aW1wb3J0KFwiLi4vTWFwLmpzXCIpLkhpdE1hdGNoPFQ+Pn0gbWF0Y2hlcyBUaGUgaGl0IGRldGVjdGVkIG1hdGNoZXMgd2l0aCB0b2xlcmFuY2UuXG4gICAqIEByZXR1cm4ge1R8dW5kZWZpbmVkfSBDYWxsYmFjayByZXN1bHQuXG4gICAqIEB0ZW1wbGF0ZSBUXG4gICAqL1xuXG5cbiAgQ2FudmFzVmVjdG9yVGlsZUxheWVyUmVuZGVyZXIucHJvdG90eXBlLmZvckVhY2hGZWF0dXJlQXRDb29yZGluYXRlID0gZnVuY3Rpb24gKGNvb3JkaW5hdGUsIGZyYW1lU3RhdGUsIGhpdFRvbGVyYW5jZSwgY2FsbGJhY2ssIG1hdGNoZXMpIHtcbiAgICB2YXIgcmVzb2x1dGlvbiA9IGZyYW1lU3RhdGUudmlld1N0YXRlLnJlc29sdXRpb247XG4gICAgdmFyIHJvdGF0aW9uID0gZnJhbWVTdGF0ZS52aWV3U3RhdGUucm90YXRpb247XG4gICAgaGl0VG9sZXJhbmNlID0gaGl0VG9sZXJhbmNlID09IHVuZGVmaW5lZCA/IDAgOiBoaXRUb2xlcmFuY2U7XG4gICAgdmFyIGxheWVyID0gdGhpcy5nZXRMYXllcigpO1xuICAgIHZhciBzb3VyY2UgPSBsYXllci5nZXRTb3VyY2UoKTtcbiAgICB2YXIgdGlsZUdyaWQgPSBzb3VyY2UuZ2V0VGlsZUdyaWRGb3JQcm9qZWN0aW9uKGZyYW1lU3RhdGUudmlld1N0YXRlLnByb2plY3Rpb24pO1xuICAgIHZhciBoaXRFeHRlbnQgPSBib3VuZGluZ0V4dGVudChbY29vcmRpbmF0ZV0pO1xuICAgIGJ1ZmZlcihoaXRFeHRlbnQsIHJlc29sdXRpb24gKiBoaXRUb2xlcmFuY2UsIGhpdEV4dGVudCk7XG4gICAgLyoqIEB0eXBlIHshT2JqZWN0PHN0cmluZywgaW1wb3J0KFwiLi4vTWFwLmpzXCIpLkhpdE1hdGNoPFQ+fHRydWU+fSAqL1xuXG4gICAgdmFyIGZlYXR1cmVzID0ge307XG4gICAgLyoqXG4gICAgICogQHBhcmFtIHtpbXBvcnQoXCIuLi8uLi9GZWF0dXJlLmpzXCIpLkZlYXR1cmVMaWtlfSBmZWF0dXJlIEZlYXR1cmUuXG4gICAgICogQHBhcmFtIHtpbXBvcnQoXCIuLi8uLi9nZW9tL1NpbXBsZUdlb21ldHJ5LmpzXCIpLmRlZmF1bHR9IGdlb21ldHJ5IEdlb21ldHJ5LlxuICAgICAqIEBwYXJhbSB7bnVtYmVyfSBkaXN0YW5jZVNxIFRoZSBzcXVhcmVkIGRpc3RhbmNlIHRvIHRoZSBjbGljayBwb3NpdGlvbi5cbiAgICAgKiBAcmV0dXJuIHtUfHVuZGVmaW5lZH0gQ2FsbGJhY2sgcmVzdWx0LlxuICAgICAqL1xuXG4gICAgdmFyIGZlYXR1cmVDYWxsYmFjayA9IGZ1bmN0aW9uIGZlYXR1cmVDYWxsYmFjayhmZWF0dXJlLCBnZW9tZXRyeSwgZGlzdGFuY2VTcSkge1xuICAgICAgdmFyIGtleSA9IGZlYXR1cmUuZ2V0SWQoKTtcblxuICAgICAgaWYgKGtleSA9PT0gdW5kZWZpbmVkKSB7XG4gICAgICAgIGtleSA9IGdldFVpZChmZWF0dXJlKTtcbiAgICAgIH1cblxuICAgICAgdmFyIG1hdGNoID0gZmVhdHVyZXNba2V5XTtcblxuICAgICAgaWYgKCFtYXRjaCkge1xuICAgICAgICBpZiAoZGlzdGFuY2VTcSA9PT0gMCkge1xuICAgICAgICAgIGZlYXR1cmVzW2tleV0gPSB0cnVlO1xuICAgICAgICAgIHJldHVybiBjYWxsYmFjayhmZWF0dXJlLCBsYXllciwgZ2VvbWV0cnkpO1xuICAgICAgICB9XG5cbiAgICAgICAgbWF0Y2hlcy5wdXNoKGZlYXR1cmVzW2tleV0gPSB7XG4gICAgICAgICAgZmVhdHVyZTogZmVhdHVyZSxcbiAgICAgICAgICBsYXllcjogbGF5ZXIsXG4gICAgICAgICAgZ2VvbWV0cnk6IGdlb21ldHJ5LFxuICAgICAgICAgIGRpc3RhbmNlU3E6IGRpc3RhbmNlU3EsXG4gICAgICAgICAgY2FsbGJhY2s6IGNhbGxiYWNrXG4gICAgICAgIH0pO1xuICAgICAgfSBlbHNlIGlmIChtYXRjaCAhPT0gdHJ1ZSAmJiBkaXN0YW5jZVNxIDwgbWF0Y2guZGlzdGFuY2VTcSkge1xuICAgICAgICBpZiAoZGlzdGFuY2VTcSA9PT0gMCkge1xuICAgICAgICAgIGZlYXR1cmVzW2tleV0gPSB0cnVlO1xuICAgICAgICAgIG1hdGNoZXMuc3BsaWNlKG1hdGNoZXMubGFzdEluZGV4T2YobWF0Y2gpLCAxKTtcbiAgICAgICAgICByZXR1cm4gY2FsbGJhY2soZmVhdHVyZSwgbGF5ZXIsIGdlb21ldHJ5KTtcbiAgICAgICAgfVxuXG4gICAgICAgIG1hdGNoLmdlb21ldHJ5ID0gZ2VvbWV0cnk7XG4gICAgICAgIG1hdGNoLmRpc3RhbmNlU3EgPSBkaXN0YW5jZVNxO1xuICAgICAgfVxuXG4gICAgICByZXR1cm4gdW5kZWZpbmVkO1xuICAgIH07XG5cbiAgICB2YXIgcmVuZGVyZWRUaWxlcyA9XG4gICAgLyoqIEB0eXBlIHtBcnJheTxpbXBvcnQoXCIuLi8uLi9WZWN0b3JSZW5kZXJUaWxlLmpzXCIpLmRlZmF1bHQ+fSAqL1xuICAgIHRoaXMucmVuZGVyZWRUaWxlcztcbiAgICB2YXIgZm91bmQ7XG5cbiAgICB2YXIgX2xvb3BfMiA9IGZ1bmN0aW9uIF9sb29wXzIoaSwgaWkpIHtcbiAgICAgIHZhciB0aWxlID0gcmVuZGVyZWRUaWxlc1tpXTtcbiAgICAgIHZhciB0aWxlRXh0ZW50ID0gdGlsZUdyaWQuZ2V0VGlsZUNvb3JkRXh0ZW50KHRpbGUud3JhcHBlZFRpbGVDb29yZCk7XG5cbiAgICAgIGlmICghaW50ZXJzZWN0cyh0aWxlRXh0ZW50LCBoaXRFeHRlbnQpKSB7XG4gICAgICAgIHJldHVybiBcImNvbnRpbnVlXCI7XG4gICAgICB9XG5cbiAgICAgIHZhciBsYXllclVpZCA9IGdldFVpZChsYXllcik7XG4gICAgICB2YXIgZXhlY3V0b3JHcm91cHMgPSBbdGlsZS5leGVjdXRvckdyb3Vwc1tsYXllclVpZF1dO1xuICAgICAgdmFyIGRlY2x1dHRlckV4ZWN1dG9yR3JvdXBzID0gdGlsZS5kZWNsdXR0ZXJFeGVjdXRvckdyb3Vwc1tsYXllclVpZF07XG5cbiAgICAgIGlmIChkZWNsdXR0ZXJFeGVjdXRvckdyb3Vwcykge1xuICAgICAgICBleGVjdXRvckdyb3Vwcy5wdXNoKGRlY2x1dHRlckV4ZWN1dG9yR3JvdXBzKTtcbiAgICAgIH1cblxuICAgICAgZXhlY3V0b3JHcm91cHMuc29tZShmdW5jdGlvbiAoZXhlY3V0b3JHcm91cHMpIHtcbiAgICAgICAgdmFyIGRlY2x1dHRlcmVkRmVhdHVyZXMgPSBleGVjdXRvckdyb3VwcyA9PT0gZGVjbHV0dGVyRXhlY3V0b3JHcm91cHMgPyBmcmFtZVN0YXRlLmRlY2x1dHRlclRyZWUuYWxsKCkubWFwKGZ1bmN0aW9uIChpdGVtKSB7XG4gICAgICAgICAgcmV0dXJuIGl0ZW0udmFsdWU7XG4gICAgICAgIH0pIDogbnVsbDtcblxuICAgICAgICBmb3IgKHZhciB0ID0gMCwgdHQgPSBleGVjdXRvckdyb3Vwcy5sZW5ndGg7IHQgPCB0dDsgKyt0KSB7XG4gICAgICAgICAgdmFyIGV4ZWN1dG9yR3JvdXAgPSBleGVjdXRvckdyb3Vwc1t0XTtcbiAgICAgICAgICBmb3VuZCA9IGV4ZWN1dG9yR3JvdXAuZm9yRWFjaEZlYXR1cmVBdENvb3JkaW5hdGUoY29vcmRpbmF0ZSwgcmVzb2x1dGlvbiwgcm90YXRpb24sIGhpdFRvbGVyYW5jZSwgZmVhdHVyZUNhbGxiYWNrLCBkZWNsdXR0ZXJlZEZlYXR1cmVzKTtcblxuICAgICAgICAgIGlmIChmb3VuZCkge1xuICAgICAgICAgICAgcmV0dXJuIHRydWU7XG4gICAgICAgICAgfVxuICAgICAgICB9XG4gICAgICB9KTtcbiAgICB9O1xuXG4gICAgZm9yICh2YXIgaSA9IDAsIGlpID0gcmVuZGVyZWRUaWxlcy5sZW5ndGg7ICFmb3VuZCAmJiBpIDwgaWk7ICsraSkge1xuICAgICAgX2xvb3BfMihpLCBpaSk7XG4gICAgfVxuXG4gICAgcmV0dXJuIGZvdW5kO1xuICB9O1xuICAvKipcbiAgICogQXN5bmNocm9ub3VzIGxheWVyIGxldmVsIGhpdCBkZXRlY3Rpb24uXG4gICAqIEBwYXJhbSB7aW1wb3J0KFwiLi4vLi4vcGl4ZWwuanNcIikuUGl4ZWx9IHBpeGVsIFBpeGVsLlxuICAgKiBAcmV0dXJuIHtQcm9taXNlPEFycmF5PGltcG9ydChcIi4uLy4uL0ZlYXR1cmVcIikuZGVmYXVsdD4+fSBQcm9taXNlIHRoYXQgcmVzb2x2ZXMgd2l0aCBhbiBhcnJheSBvZiBmZWF0dXJlcy5cbiAgICovXG5cblxuICBDYW52YXNWZWN0b3JUaWxlTGF5ZXJSZW5kZXJlci5wcm90b3R5cGUuZ2V0RmVhdHVyZXMgPSBmdW5jdGlvbiAocGl4ZWwpIHtcbiAgICByZXR1cm4gbmV3IFByb21pc2UoZnVuY3Rpb24gKHJlc29sdmUsIHJlamVjdCkge1xuICAgICAgdmFyIGxheWVyID1cbiAgICAgIC8qKiBAdHlwZSB7aW1wb3J0KFwiLi4vLi4vbGF5ZXIvVmVjdG9yVGlsZS5qc1wiKS5kZWZhdWx0fSAqL1xuICAgICAgdGhpcy5nZXRMYXllcigpO1xuICAgICAgdmFyIGxheWVyVWlkID0gZ2V0VWlkKGxheWVyKTtcbiAgICAgIHZhciBzb3VyY2UgPSBsYXllci5nZXRTb3VyY2UoKTtcbiAgICAgIHZhciBwcm9qZWN0aW9uID0gdGhpcy5yZW5kZXJlZFByb2plY3Rpb247XG4gICAgICB2YXIgcHJvamVjdGlvbkV4dGVudCA9IHByb2plY3Rpb24uZ2V0RXh0ZW50KCk7XG4gICAgICB2YXIgcmVzb2x1dGlvbiA9IHRoaXMucmVuZGVyZWRSZXNvbHV0aW9uO1xuICAgICAgdmFyIHRpbGVHcmlkID0gc291cmNlLmdldFRpbGVHcmlkRm9yUHJvamVjdGlvbihwcm9qZWN0aW9uKTtcbiAgICAgIHZhciBjb29yZGluYXRlID0gYXBwbHlUcmFuc2Zvcm0odGhpcy5yZW5kZXJlZFBpeGVsVG9Db29yZGluYXRlVHJhbnNmb3JtXywgcGl4ZWwuc2xpY2UoKSk7XG4gICAgICB2YXIgdGlsZUNvb3JkID0gdGlsZUdyaWQuZ2V0VGlsZUNvb3JkRm9yQ29vcmRBbmRSZXNvbHV0aW9uKGNvb3JkaW5hdGUsIHJlc29sdXRpb24pO1xuICAgICAgdmFyIHRpbGU7XG5cbiAgICAgIGZvciAodmFyIGkgPSAwLCBpaSA9IHRoaXMucmVuZGVyZWRUaWxlcy5sZW5ndGg7IGkgPCBpaTsgKytpKSB7XG4gICAgICAgIGlmICh0aWxlQ29vcmQudG9TdHJpbmcoKSA9PT0gdGhpcy5yZW5kZXJlZFRpbGVzW2ldLnRpbGVDb29yZC50b1N0cmluZygpKSB7XG4gICAgICAgICAgdGlsZSA9IHRoaXMucmVuZGVyZWRUaWxlc1tpXTtcblxuICAgICAgICAgIGlmICh0aWxlLmdldFN0YXRlKCkgPT09IFRpbGVTdGF0ZS5MT0FERUQgJiYgdGlsZS5oaWZpKSB7XG4gICAgICAgICAgICB2YXIgZXh0ZW50XzEgPSB0aWxlR3JpZC5nZXRUaWxlQ29vcmRFeHRlbnQodGlsZS50aWxlQ29vcmQpO1xuXG4gICAgICAgICAgICBpZiAoc291cmNlLmdldFdyYXBYKCkgJiYgcHJvamVjdGlvbi5jYW5XcmFwWCgpICYmICFjb250YWluc0V4dGVudChwcm9qZWN0aW9uRXh0ZW50LCBleHRlbnRfMSkpIHtcbiAgICAgICAgICAgICAgd3JhcFgoY29vcmRpbmF0ZSwgcHJvamVjdGlvbik7XG4gICAgICAgICAgICB9XG5cbiAgICAgICAgICAgIGJyZWFrO1xuICAgICAgICAgIH1cblxuICAgICAgICAgIHRpbGUgPSB1bmRlZmluZWQ7XG4gICAgICAgIH1cbiAgICAgIH1cblxuICAgICAgaWYgKCF0aWxlIHx8IHRpbGUubG9hZGluZ1NvdXJjZVRpbGVzID4gMCkge1xuICAgICAgICByZXNvbHZlKFtdKTtcbiAgICAgICAgcmV0dXJuO1xuICAgICAgfVxuXG4gICAgICB2YXIgZXh0ZW50ID0gdGlsZUdyaWQuZ2V0VGlsZUNvb3JkRXh0ZW50KHRpbGUud3JhcHBlZFRpbGVDb29yZCk7XG4gICAgICB2YXIgY29ybmVyID0gZ2V0VG9wTGVmdChleHRlbnQpO1xuICAgICAgdmFyIHRpbGVQaXhlbCA9IFsoY29vcmRpbmF0ZVswXSAtIGNvcm5lclswXSkgLyByZXNvbHV0aW9uLCAoY29ybmVyWzFdIC0gY29vcmRpbmF0ZVsxXSkgLyByZXNvbHV0aW9uXTtcbiAgICAgIHZhciBmZWF0dXJlcyA9IHRpbGUuZ2V0U291cmNlVGlsZXMoKS5yZWR1Y2UoZnVuY3Rpb24gKGFjY3VtdWxhdG9yLCBzb3VyY2VUaWxlKSB7XG4gICAgICAgIHJldHVybiBhY2N1bXVsYXRvci5jb25jYXQoc291cmNlVGlsZS5nZXRGZWF0dXJlcygpKTtcbiAgICAgIH0sIFtdKTtcbiAgICAgIHZhciBoaXREZXRlY3Rpb25JbWFnZURhdGEgPSB0aWxlLmhpdERldGVjdGlvbkltYWdlRGF0YVtsYXllclVpZF07XG5cbiAgICAgIGlmICghaGl0RGV0ZWN0aW9uSW1hZ2VEYXRhICYmICF0aGlzLmFuaW1hdGluZ09ySW50ZXJhY3RpbmdfKSB7XG4gICAgICAgIHZhciB0aWxlU2l6ZSA9IHRvU2l6ZSh0aWxlR3JpZC5nZXRUaWxlU2l6ZSh0aWxlR3JpZC5nZXRaRm9yUmVzb2x1dGlvbihyZXNvbHV0aW9uKSkpO1xuICAgICAgICB2YXIgc2l6ZSA9IFt0aWxlU2l6ZVswXSAvIDIsIHRpbGVTaXplWzFdIC8gMl07XG4gICAgICAgIHZhciByb3RhdGlvbiA9IHRoaXMucmVuZGVyZWRSb3RhdGlvbl87XG4gICAgICAgIHZhciB0cmFuc2Zvcm1zID0gW3RoaXMuZ2V0UmVuZGVyVHJhbnNmb3JtKHRpbGVHcmlkLmdldFRpbGVDb29yZENlbnRlcih0aWxlLndyYXBwZWRUaWxlQ29vcmQpLCByZXNvbHV0aW9uLCAwLCAwLjUsIHNpemVbMF0sIHNpemVbMV0sIDApXTtcbiAgICAgICAgaGl0RGV0ZWN0aW9uSW1hZ2VEYXRhID0gY3JlYXRlSGl0RGV0ZWN0aW9uSW1hZ2VEYXRhKHRpbGVTaXplLCB0cmFuc2Zvcm1zLCBmZWF0dXJlcywgbGF5ZXIuZ2V0U3R5bGVGdW5jdGlvbigpLCB0aWxlR3JpZC5nZXRUaWxlQ29vcmRFeHRlbnQodGlsZS53cmFwcGVkVGlsZUNvb3JkKSwgdGlsZS5nZXRSZXBsYXlTdGF0ZShsYXllcikucmVuZGVyZWRSZXNvbHV0aW9uLCByb3RhdGlvbik7XG4gICAgICAgIHRpbGUuaGl0RGV0ZWN0aW9uSW1hZ2VEYXRhW2xheWVyVWlkXSA9IGhpdERldGVjdGlvbkltYWdlRGF0YTtcbiAgICAgIH1cblxuICAgICAgcmVzb2x2ZShoaXREZXRlY3QodGlsZVBpeGVsLCBmZWF0dXJlcywgaGl0RGV0ZWN0aW9uSW1hZ2VEYXRhKSk7XG4gICAgfS5iaW5kKHRoaXMpKTtcbiAgfTtcbiAgLyoqXG4gICAqIFBlcmZvcm0gYWN0aW9uIG5lY2Vzc2FyeSB0byBnZXQgdGhlIGxheWVyIHJlbmRlcmVkIGFmdGVyIG5ldyBmb250cyBoYXZlIGxvYWRlZFxuICAgKi9cblxuXG4gIENhbnZhc1ZlY3RvclRpbGVMYXllclJlbmRlcmVyLnByb3RvdHlwZS5oYW5kbGVGb250c0NoYW5nZWQgPSBmdW5jdGlvbiAoKSB7XG4gICAgY2xlYXIodGhpcy5yZW5kZXJUaWxlSW1hZ2VRdWV1ZV8pO1xuICAgIHZhciBsYXllciA9IHRoaXMuZ2V0TGF5ZXIoKTtcblxuICAgIGlmIChsYXllci5nZXRWaXNpYmxlKCkgJiYgdGhpcy5yZW5kZXJlZExheWVyUmV2aXNpb25fICE9PSB1bmRlZmluZWQpIHtcbiAgICAgIGxheWVyLmNoYW5nZWQoKTtcbiAgICB9XG4gIH07XG4gIC8qKlxuICAgKiBIYW5kbGUgY2hhbmdlcyBpbiBpbWFnZSBzdHlsZSBzdGF0ZS5cbiAgICogQHBhcmFtIHtpbXBvcnQoXCIuLi8uLi9ldmVudHMvRXZlbnQuanNcIikuZGVmYXVsdH0gZXZlbnQgSW1hZ2Ugc3R5bGUgY2hhbmdlIGV2ZW50LlxuICAgKiBAcHJpdmF0ZVxuICAgKi9cblxuXG4gIENhbnZhc1ZlY3RvclRpbGVMYXllclJlbmRlcmVyLnByb3RvdHlwZS5oYW5kbGVTdHlsZUltYWdlQ2hhbmdlXyA9IGZ1bmN0aW9uIChldmVudCkge1xuICAgIHRoaXMucmVuZGVySWZSZWFkeUFuZFZpc2libGUoKTtcbiAgfTtcbiAgLyoqXG4gICAqIFJlbmRlciBkZWNsdXR0ZXIgaXRlbXMgZm9yIHRoaXMgbGF5ZXJcbiAgICogQHBhcmFtIHtpbXBvcnQoXCIuLi8uLi9QbHVnZ2FibGVNYXAuanNcIikuRnJhbWVTdGF0ZX0gZnJhbWVTdGF0ZSBGcmFtZSBzdGF0ZS5cbiAgICovXG5cblxuICBDYW52YXNWZWN0b3JUaWxlTGF5ZXJSZW5kZXJlci5wcm90b3R5cGUucmVuZGVyRGVjbHV0dGVyID0gZnVuY3Rpb24gKGZyYW1lU3RhdGUpIHtcbiAgICB2YXIgdmlld0hpbnRzID0gZnJhbWVTdGF0ZS52aWV3SGludHM7XG4gICAgdmFyIGhpZmkgPSAhKHZpZXdIaW50c1tWaWV3SGludC5BTklNQVRJTkddIHx8IHZpZXdIaW50c1tWaWV3SGludC5JTlRFUkFDVElOR10pO1xuICAgIHZhciB0aWxlcyA9XG4gICAgLyoqIEB0eXBlIHtBcnJheTxpbXBvcnQoXCIuLi8uLi9WZWN0b3JSZW5kZXJUaWxlLmpzXCIpLmRlZmF1bHQ+fSAqL1xuICAgIHRoaXMucmVuZGVyZWRUaWxlcztcblxuICAgIGZvciAodmFyIGkgPSAwLCBpaSA9IHRpbGVzLmxlbmd0aDsgaSA8IGlpOyArK2kpIHtcbiAgICAgIHZhciB0aWxlID0gdGlsZXNbaV07XG4gICAgICB2YXIgZGVjbHV0dGVyRXhlY3V0b3JHcm91cHMgPSB0aWxlLmRlY2x1dHRlckV4ZWN1dG9yR3JvdXBzW2dldFVpZCh0aGlzLmdldExheWVyKCkpXTtcblxuICAgICAgaWYgKGRlY2x1dHRlckV4ZWN1dG9yR3JvdXBzKSB7XG4gICAgICAgIGZvciAodmFyIGogPSBkZWNsdXR0ZXJFeGVjdXRvckdyb3Vwcy5sZW5ndGggLSAxOyBqID49IDA7IC0taikge1xuICAgICAgICAgIGRlY2x1dHRlckV4ZWN1dG9yR3JvdXBzW2pdLmV4ZWN1dGUodGhpcy5jb250ZXh0LCAxLCB0aGlzLmdldFRpbGVSZW5kZXJUcmFuc2Zvcm0odGlsZSwgZnJhbWVTdGF0ZSksIGZyYW1lU3RhdGUudmlld1N0YXRlLnJvdGF0aW9uLCBoaWZpLCB1bmRlZmluZWQsIGZyYW1lU3RhdGUuZGVjbHV0dGVyVHJlZSk7XG4gICAgICAgIH1cbiAgICAgIH1cbiAgICB9XG4gIH07XG5cbiAgQ2FudmFzVmVjdG9yVGlsZUxheWVyUmVuZGVyZXIucHJvdG90eXBlLmdldFRpbGVSZW5kZXJUcmFuc2Zvcm0gPSBmdW5jdGlvbiAodGlsZSwgZnJhbWVTdGF0ZSkge1xuICAgIHZhciBwaXhlbFJhdGlvID0gZnJhbWVTdGF0ZS5waXhlbFJhdGlvO1xuICAgIHZhciB2aWV3U3RhdGUgPSBmcmFtZVN0YXRlLnZpZXdTdGF0ZTtcbiAgICB2YXIgY2VudGVyID0gdmlld1N0YXRlLmNlbnRlcjtcbiAgICB2YXIgcmVzb2x1dGlvbiA9IHZpZXdTdGF0ZS5yZXNvbHV0aW9uO1xuICAgIHZhciByb3RhdGlvbiA9IHZpZXdTdGF0ZS5yb3RhdGlvbjtcbiAgICB2YXIgc2l6ZSA9IGZyYW1lU3RhdGUuc2l6ZTtcbiAgICB2YXIgd2lkdGggPSBNYXRoLnJvdW5kKHNpemVbMF0gKiBwaXhlbFJhdGlvKTtcbiAgICB2YXIgaGVpZ2h0ID0gTWF0aC5yb3VuZChzaXplWzFdICogcGl4ZWxSYXRpbyk7XG4gICAgdmFyIHNvdXJjZSA9IHRoaXMuZ2V0TGF5ZXIoKS5nZXRTb3VyY2UoKTtcbiAgICB2YXIgdGlsZUdyaWQgPSBzb3VyY2UuZ2V0VGlsZUdyaWRGb3JQcm9qZWN0aW9uKGZyYW1lU3RhdGUudmlld1N0YXRlLnByb2plY3Rpb24pO1xuICAgIHZhciB0aWxlQ29vcmQgPSB0aWxlLnRpbGVDb29yZDtcbiAgICB2YXIgdGlsZUV4dGVudCA9IHRpbGVHcmlkLmdldFRpbGVDb29yZEV4dGVudCh0aWxlLndyYXBwZWRUaWxlQ29vcmQpO1xuICAgIHZhciB3b3JsZE9mZnNldCA9IHRpbGVHcmlkLmdldFRpbGVDb29yZEV4dGVudCh0aWxlQ29vcmQsIHRoaXMudG1wRXh0ZW50KVswXSAtIHRpbGVFeHRlbnRbMF07XG4gICAgdmFyIHRyYW5zZm9ybSA9IG11bHRpcGx5KHNjYWxlKHRoaXMuaW52ZXJzZVBpeGVsVHJhbnNmb3JtLnNsaWNlKCksIDEgLyBwaXhlbFJhdGlvLCAxIC8gcGl4ZWxSYXRpbyksIHRoaXMuZ2V0UmVuZGVyVHJhbnNmb3JtKGNlbnRlciwgcmVzb2x1dGlvbiwgcm90YXRpb24sIHBpeGVsUmF0aW8sIHdpZHRoLCBoZWlnaHQsIHdvcmxkT2Zmc2V0KSk7XG4gICAgcmV0dXJuIHRyYW5zZm9ybTtcbiAgfTtcbiAgLyoqXG4gICAqIFJlbmRlciB0aGUgbGF5ZXIuXG4gICAqIEBwYXJhbSB7aW1wb3J0KFwiLi4vLi4vUGx1Z2dhYmxlTWFwLmpzXCIpLkZyYW1lU3RhdGV9IGZyYW1lU3RhdGUgRnJhbWUgc3RhdGUuXG4gICAqIEBwYXJhbSB7SFRNTEVsZW1lbnR9IHRhcmdldCBUYXJnZXQgdGhhdCBtYXkgYmUgdXNlZCB0byByZW5kZXIgY29udGVudCB0by5cbiAgICogQHJldHVybiB7SFRNTEVsZW1lbnR9IFRoZSByZW5kZXJlZCBlbGVtZW50LlxuICAgKi9cblxuXG4gIENhbnZhc1ZlY3RvclRpbGVMYXllclJlbmRlcmVyLnByb3RvdHlwZS5yZW5kZXJGcmFtZSA9IGZ1bmN0aW9uIChmcmFtZVN0YXRlLCB0YXJnZXQpIHtcbiAgICB2YXIgdmlld0hpbnRzID0gZnJhbWVTdGF0ZS52aWV3SGludHM7XG4gICAgdmFyIGhpZmkgPSAhKHZpZXdIaW50c1tWaWV3SGludC5BTklNQVRJTkddIHx8IHZpZXdIaW50c1tWaWV3SGludC5JTlRFUkFDVElOR10pO1xuICAgIHRoaXMucmVuZGVyUXVldWVkVGlsZUltYWdlc18oaGlmaSwgZnJhbWVTdGF0ZSk7XG5cbiAgICBfc3VwZXIucHJvdG90eXBlLnJlbmRlckZyYW1lLmNhbGwodGhpcywgZnJhbWVTdGF0ZSwgdGFyZ2V0KTtcblxuICAgIHRoaXMucmVuZGVyZWRQaXhlbFRvQ29vcmRpbmF0ZVRyYW5zZm9ybV8gPSBmcmFtZVN0YXRlLnBpeGVsVG9Db29yZGluYXRlVHJhbnNmb3JtLnNsaWNlKCk7XG4gICAgdGhpcy5yZW5kZXJlZFJvdGF0aW9uXyA9IGZyYW1lU3RhdGUudmlld1N0YXRlLnJvdGF0aW9uO1xuICAgIHZhciBsYXllciA9XG4gICAgLyoqIEB0eXBlIHtpbXBvcnQoXCIuLi8uLi9sYXllci9WZWN0b3JUaWxlLmpzXCIpLmRlZmF1bHR9ICovXG4gICAgdGhpcy5nZXRMYXllcigpO1xuICAgIHZhciByZW5kZXJNb2RlID0gbGF5ZXIuZ2V0UmVuZGVyTW9kZSgpO1xuXG4gICAgaWYgKHJlbmRlck1vZGUgPT09IFZlY3RvclRpbGVSZW5kZXJUeXBlLklNQUdFKSB7XG4gICAgICByZXR1cm4gdGhpcy5jb250YWluZXI7XG4gICAgfVxuXG4gICAgdmFyIHNvdXJjZSA9IGxheWVyLmdldFNvdXJjZSgpOyAvLyBVbnF1ZXVlIHRpbGVzIGZyb20gdGhlIGltYWdlIHF1ZXVlIHdoZW4gd2UgZG9uJ3QgbmVlZCBhbnkgbW9yZVxuXG4gICAgdmFyIHVzZWRUaWxlcyA9IGZyYW1lU3RhdGUudXNlZFRpbGVzW2dldFVpZChzb3VyY2UpXTtcblxuICAgIGZvciAodmFyIHRpbGVVaWQgaW4gdGhpcy5yZW5kZXJUaWxlSW1hZ2VRdWV1ZV8pIHtcbiAgICAgIGlmICghdXNlZFRpbGVzIHx8ICEodGlsZVVpZCBpbiB1c2VkVGlsZXMpKSB7XG4gICAgICAgIGRlbGV0ZSB0aGlzLnJlbmRlclRpbGVJbWFnZVF1ZXVlX1t0aWxlVWlkXTtcbiAgICAgIH1cbiAgICB9XG5cbiAgICB2YXIgY29udGV4dCA9IHRoaXMuY29udGV4dDtcbiAgICB2YXIgcmVwbGF5VHlwZXMgPSBWRUNUT1JfUkVQTEFZU1tyZW5kZXJNb2RlXTtcbiAgICB2YXIgdmlld1N0YXRlID0gZnJhbWVTdGF0ZS52aWV3U3RhdGU7XG4gICAgdmFyIHJvdGF0aW9uID0gdmlld1N0YXRlLnJvdGF0aW9uO1xuICAgIHZhciB0aWxlcyA9IHRoaXMucmVuZGVyZWRUaWxlcztcbiAgICB2YXIgY2xpcHMgPSBbXTtcbiAgICB2YXIgY2xpcFpzID0gW107XG5cbiAgICBmb3IgKHZhciBpID0gdGlsZXMubGVuZ3RoIC0gMTsgaSA+PSAwOyAtLWkpIHtcbiAgICAgIHZhciB0aWxlID1cbiAgICAgIC8qKiBAdHlwZSB7aW1wb3J0KFwiLi4vLi4vVmVjdG9yUmVuZGVyVGlsZS5qc1wiKS5kZWZhdWx0fSAqL1xuICAgICAgdGlsZXNbaV07XG4gICAgICB2YXIgdHJhbnNmb3JtID0gdGhpcy5nZXRUaWxlUmVuZGVyVHJhbnNmb3JtKHRpbGUsIGZyYW1lU3RhdGUpO1xuICAgICAgdmFyIGV4ZWN1dG9yR3JvdXBzID0gdGlsZS5leGVjdXRvckdyb3Vwc1tnZXRVaWQobGF5ZXIpXTtcbiAgICAgIHZhciBjbGlwcGVkID0gZmFsc2U7XG5cbiAgICAgIGZvciAodmFyIHQgPSAwLCB0dCA9IGV4ZWN1dG9yR3JvdXBzLmxlbmd0aDsgdCA8IHR0OyArK3QpIHtcbiAgICAgICAgdmFyIGV4ZWN1dG9yR3JvdXAgPSBleGVjdXRvckdyb3Vwc1t0XTtcblxuICAgICAgICBpZiAoIWV4ZWN1dG9yR3JvdXAuaGFzRXhlY3V0b3JzKHJlcGxheVR5cGVzKSkge1xuICAgICAgICAgIC8vIHNvdXJjZVRpbGUgaGFzIG5vIGluc3RydWN0aW9ucyBvZiB0aGUgdHlwZXMgd2Ugd2FudCB0byByZW5kZXJcbiAgICAgICAgICBjb250aW51ZTtcbiAgICAgICAgfVxuXG4gICAgICAgIHZhciBjdXJyZW50WiA9IHRpbGUudGlsZUNvb3JkWzBdO1xuICAgICAgICB2YXIgY3VycmVudENsaXAgPSB2b2lkIDA7XG5cbiAgICAgICAgaWYgKCFjbGlwcGVkKSB7XG4gICAgICAgICAgY3VycmVudENsaXAgPSBleGVjdXRvckdyb3VwLmdldENsaXBDb29yZHModHJhbnNmb3JtKTtcblxuICAgICAgICAgIGlmIChjdXJyZW50Q2xpcCkge1xuICAgICAgICAgICAgY29udGV4dC5zYXZlKCk7IC8vIENyZWF0ZSBhIGNsaXAgbWFzayBmb3IgcmVnaW9ucyBpbiB0aGlzIGxvdyByZXNvbHV0aW9uIHRpbGUgdGhhdCBhcmVcbiAgICAgICAgICAgIC8vIGFscmVhZHkgZmlsbGVkIGJ5IGEgaGlnaGVyIHJlc29sdXRpb24gdGlsZVxuXG4gICAgICAgICAgICBmb3IgKHZhciBqID0gMCwgamogPSBjbGlwcy5sZW5ndGg7IGogPCBqajsgKytqKSB7XG4gICAgICAgICAgICAgIHZhciBjbGlwID0gY2xpcHNbal07XG5cbiAgICAgICAgICAgICAgaWYgKGN1cnJlbnRaIDwgY2xpcFpzW2pdKSB7XG4gICAgICAgICAgICAgICAgY29udGV4dC5iZWdpblBhdGgoKTsgLy8gY291bnRlci1jbG9ja3dpc2UgKG91dGVyIHJpbmcpIGZvciBjdXJyZW50IHRpbGVcblxuICAgICAgICAgICAgICAgIGNvbnRleHQubW92ZVRvKGN1cnJlbnRDbGlwWzBdLCBjdXJyZW50Q2xpcFsxXSk7XG4gICAgICAgICAgICAgICAgY29udGV4dC5saW5lVG8oY3VycmVudENsaXBbMl0sIGN1cnJlbnRDbGlwWzNdKTtcbiAgICAgICAgICAgICAgICBjb250ZXh0LmxpbmVUbyhjdXJyZW50Q2xpcFs0XSwgY3VycmVudENsaXBbNV0pO1xuICAgICAgICAgICAgICAgIGNvbnRleHQubGluZVRvKGN1cnJlbnRDbGlwWzZdLCBjdXJyZW50Q2xpcFs3XSk7IC8vIGNsb2Nrd2lzZSAoaW5uZXIgcmluZykgZm9yIGhpZ2hlciByZXNvbHV0aW9uIHRpbGVcblxuICAgICAgICAgICAgICAgIGNvbnRleHQubW92ZVRvKGNsaXBbNl0sIGNsaXBbN10pO1xuICAgICAgICAgICAgICAgIGNvbnRleHQubGluZVRvKGNsaXBbNF0sIGNsaXBbNV0pO1xuICAgICAgICAgICAgICAgIGNvbnRleHQubGluZVRvKGNsaXBbMl0sIGNsaXBbM10pO1xuICAgICAgICAgICAgICAgIGNvbnRleHQubGluZVRvKGNsaXBbMF0sIGNsaXBbMV0pO1xuICAgICAgICAgICAgICAgIGNvbnRleHQuY2xpcCgpO1xuICAgICAgICAgICAgICB9XG4gICAgICAgICAgICB9XG4gICAgICAgICAgfVxuICAgICAgICB9XG5cbiAgICAgICAgZXhlY3V0b3JHcm91cC5leGVjdXRlKGNvbnRleHQsIDEsIHRyYW5zZm9ybSwgcm90YXRpb24sIGhpZmksIHJlcGxheVR5cGVzKTtcblxuICAgICAgICBpZiAoIWNsaXBwZWQgJiYgY3VycmVudENsaXApIHtcbiAgICAgICAgICBjb250ZXh0LnJlc3RvcmUoKTtcbiAgICAgICAgICBjbGlwcy5wdXNoKGN1cnJlbnRDbGlwKTtcbiAgICAgICAgICBjbGlwWnMucHVzaChjdXJyZW50Wik7XG4gICAgICAgICAgY2xpcHBlZCA9IHRydWU7XG4gICAgICAgIH1cbiAgICAgIH1cbiAgICB9XG5cbiAgICByZXR1cm4gdGhpcy5jb250YWluZXI7XG4gIH07XG4gIC8qKlxuICAgKiBAcGFyYW0ge2Jvb2xlYW59IGhpZmkgV2UgaGF2ZSB0aW1lIHRvIHJlbmRlciBhIGhpZ2ggZmlkZWxpdHkgbWFwIGltYWdlLlxuICAgKiBAcGFyYW0ge2ltcG9ydCgnLi4vLi4vUGx1Z2dhYmxlTWFwLmpzJykuRnJhbWVTdGF0ZX0gZnJhbWVTdGF0ZSBGcmFtZSBzdGF0ZS5cbiAgICovXG5cblxuICBDYW52YXNWZWN0b3JUaWxlTGF5ZXJSZW5kZXJlci5wcm90b3R5cGUucmVuZGVyUXVldWVkVGlsZUltYWdlc18gPSBmdW5jdGlvbiAoaGlmaSwgZnJhbWVTdGF0ZSkge1xuICAgIC8vIFdoZW4gd2UgZG9uJ3QgaGF2ZSB0aW1lIHRvIHJlbmRlciBoaWZpLCBvbmx5IHJlbmRlciB0aWxlcyB1bnRpbCB3ZSBoYXZlIHVzZWQgdXBcbiAgICAvLyBoYWxmIG9mIHRoZSBmcmFtZSBidWRnZXQgb2YgMTYgbXNcbiAgICBmb3IgKHZhciB1aWQgaW4gdGhpcy5yZW5kZXJUaWxlSW1hZ2VRdWV1ZV8pIHtcbiAgICAgIGlmICghaGlmaSAmJiBEYXRlLm5vdygpIC0gZnJhbWVTdGF0ZS50aW1lID4gOCkge1xuICAgICAgICBmcmFtZVN0YXRlLmFuaW1hdGUgPSB0cnVlO1xuICAgICAgICBicmVhaztcbiAgICAgIH1cblxuICAgICAgdmFyIHRpbGUgPSB0aGlzLnJlbmRlclRpbGVJbWFnZVF1ZXVlX1t1aWRdO1xuICAgICAgZGVsZXRlIHRoaXMucmVuZGVyVGlsZUltYWdlUXVldWVfW3VpZF07XG4gICAgICB0aGlzLnJlbmRlclRpbGVJbWFnZV8odGlsZSwgZnJhbWVTdGF0ZSk7XG4gICAgfVxuICB9O1xuICAvKipcbiAgICogQHBhcmFtIHtpbXBvcnQoXCIuLi8uLi9GZWF0dXJlLmpzXCIpLkZlYXR1cmVMaWtlfSBmZWF0dXJlIEZlYXR1cmUuXG4gICAqIEBwYXJhbSB7bnVtYmVyfSBzcXVhcmVkVG9sZXJhbmNlIFNxdWFyZWQgdG9sZXJhbmNlLlxuICAgKiBAcGFyYW0ge2ltcG9ydChcIi4uLy4uL3N0eWxlL1N0eWxlLmpzXCIpLmRlZmF1bHR8QXJyYXk8aW1wb3J0KFwiLi4vLi4vc3R5bGUvU3R5bGUuanNcIikuZGVmYXVsdD59IHN0eWxlcyBUaGUgc3R5bGUgb3IgYXJyYXkgb2Ygc3R5bGVzLlxuICAgKiBAcGFyYW0ge2ltcG9ydChcIi4uLy4uL3JlbmRlci9jYW52YXMvQnVpbGRlckdyb3VwLmpzXCIpLmRlZmF1bHR9IGJ1aWxkZXJHcm91cCBSZXBsYXkgZ3JvdXAuXG4gICAqIEBwYXJhbSB7aW1wb3J0KFwiLi4vLi4vcmVuZGVyL2NhbnZhcy9CdWlsZGVyR3JvdXAuanNcIikuZGVmYXVsdD19IG9wdF9kZWNsdXR0ZXJCdWlsZGVyR3JvdXAgQnVpbGRlciBncm91cCBmb3IgZGVjbHV0dGVyaW5nLlxuICAgKiBAcmV0dXJuIHtib29sZWFufSBgdHJ1ZWAgaWYgYW4gaW1hZ2UgaXMgbG9hZGluZy5cbiAgICovXG5cblxuICBDYW52YXNWZWN0b3JUaWxlTGF5ZXJSZW5kZXJlci5wcm90b3R5cGUucmVuZGVyRmVhdHVyZSA9IGZ1bmN0aW9uIChmZWF0dXJlLCBzcXVhcmVkVG9sZXJhbmNlLCBzdHlsZXMsIGJ1aWxkZXJHcm91cCwgb3B0X2RlY2x1dHRlckJ1aWxkZXJHcm91cCkge1xuICAgIGlmICghc3R5bGVzKSB7XG4gICAgICByZXR1cm4gZmFsc2U7XG4gICAgfVxuXG4gICAgdmFyIGxvYWRpbmcgPSBmYWxzZTtcblxuICAgIGlmIChBcnJheS5pc0FycmF5KHN0eWxlcykpIHtcbiAgICAgIGZvciAodmFyIGkgPSAwLCBpaSA9IHN0eWxlcy5sZW5ndGg7IGkgPCBpaTsgKytpKSB7XG4gICAgICAgIGxvYWRpbmcgPSByZW5kZXJGZWF0dXJlKGJ1aWxkZXJHcm91cCwgZmVhdHVyZSwgc3R5bGVzW2ldLCBzcXVhcmVkVG9sZXJhbmNlLCB0aGlzLmJvdW5kSGFuZGxlU3R5bGVJbWFnZUNoYW5nZV8sIHVuZGVmaW5lZCwgb3B0X2RlY2x1dHRlckJ1aWxkZXJHcm91cCkgfHwgbG9hZGluZztcbiAgICAgIH1cbiAgICB9IGVsc2Uge1xuICAgICAgbG9hZGluZyA9IHJlbmRlckZlYXR1cmUoYnVpbGRlckdyb3VwLCBmZWF0dXJlLCBzdHlsZXMsIHNxdWFyZWRUb2xlcmFuY2UsIHRoaXMuYm91bmRIYW5kbGVTdHlsZUltYWdlQ2hhbmdlXywgdW5kZWZpbmVkLCBvcHRfZGVjbHV0dGVyQnVpbGRlckdyb3VwKTtcbiAgICB9XG5cbiAgICByZXR1cm4gbG9hZGluZztcbiAgfTtcbiAgLyoqXG4gICAqIEBwYXJhbSB7aW1wb3J0KFwiLi4vLi4vVmVjdG9yUmVuZGVyVGlsZS5qc1wiKS5kZWZhdWx0fSB0aWxlIFRpbGUuXG4gICAqIEBwYXJhbSB7bnVtYmVyfSBwaXhlbFJhdGlvIFBpeGVsIHJhdGlvLlxuICAgKiBAcGFyYW0ge2ltcG9ydChcIi4uLy4uL3Byb2ovUHJvamVjdGlvbi5qc1wiKS5kZWZhdWx0fSBwcm9qZWN0aW9uIFByb2plY3Rpb24uXG4gICAqIEByZXR1cm4ge2Jvb2xlYW59IEEgbmV3IHRpbGUgaW1hZ2Ugd2FzIHJlbmRlcmVkLlxuICAgKiBAcHJpdmF0ZVxuICAgKi9cblxuXG4gIENhbnZhc1ZlY3RvclRpbGVMYXllclJlbmRlcmVyLnByb3RvdHlwZS50aWxlSW1hZ2VOZWVkc1JlbmRlcl8gPSBmdW5jdGlvbiAodGlsZSwgcGl4ZWxSYXRpbywgcHJvamVjdGlvbikge1xuICAgIHZhciBsYXllciA9XG4gICAgLyoqIEB0eXBlIHtpbXBvcnQoXCIuLi8uLi9sYXllci9WZWN0b3JUaWxlLmpzXCIpLmRlZmF1bHR9ICovXG4gICAgdGhpcy5nZXRMYXllcigpO1xuICAgIHZhciByZXBsYXlTdGF0ZSA9IHRpbGUuZ2V0UmVwbGF5U3RhdGUobGF5ZXIpO1xuICAgIHZhciByZXZpc2lvbiA9IGxheWVyLmdldFJldmlzaW9uKCk7XG4gICAgdmFyIHNvdXJjZVogPSB0aWxlLnNvdXJjZVo7XG4gICAgdmFyIHJlc29sdXRpb24gPSB0aWxlLndhbnRlZFJlc29sdXRpb247XG4gICAgcmV0dXJuIHJlcGxheVN0YXRlLnJlbmRlcmVkVGlsZVJlc29sdXRpb24gIT09IHJlc29sdXRpb24gfHwgcmVwbGF5U3RhdGUucmVuZGVyZWRUaWxlUmV2aXNpb24gIT09IHJldmlzaW9uIHx8IHJlcGxheVN0YXRlLnJlbmRlcmVkVGlsZVogIT09IHNvdXJjZVo7XG4gIH07XG4gIC8qKlxuICAgKiBAcGFyYW0ge2ltcG9ydChcIi4uLy4uL1ZlY3RvclJlbmRlclRpbGUuanNcIikuZGVmYXVsdH0gdGlsZSBUaWxlLlxuICAgKiBAcGFyYW0ge2ltcG9ydChcIi4uLy4uL1BsdWdnYWJsZU1hcFwiKS5GcmFtZVN0YXRlfSBmcmFtZVN0YXRlIEZyYW1lIHN0YXRlLlxuICAgKiBAcHJpdmF0ZVxuICAgKi9cblxuXG4gIENhbnZhc1ZlY3RvclRpbGVMYXllclJlbmRlcmVyLnByb3RvdHlwZS5yZW5kZXJUaWxlSW1hZ2VfID0gZnVuY3Rpb24gKHRpbGUsIGZyYW1lU3RhdGUpIHtcbiAgICB2YXIgbGF5ZXIgPVxuICAgIC8qKiBAdHlwZSB7aW1wb3J0KFwiLi4vLi4vbGF5ZXIvVmVjdG9yVGlsZS5qc1wiKS5kZWZhdWx0fSAqL1xuICAgIHRoaXMuZ2V0TGF5ZXIoKTtcbiAgICB2YXIgcmVwbGF5U3RhdGUgPSB0aWxlLmdldFJlcGxheVN0YXRlKGxheWVyKTtcbiAgICB2YXIgcmV2aXNpb24gPSBsYXllci5nZXRSZXZpc2lvbigpO1xuICAgIHZhciBleGVjdXRvckdyb3VwcyA9IHRpbGUuZXhlY3V0b3JHcm91cHNbZ2V0VWlkKGxheWVyKV07XG4gICAgcmVwbGF5U3RhdGUucmVuZGVyZWRUaWxlUmV2aXNpb24gPSByZXZpc2lvbjtcbiAgICByZXBsYXlTdGF0ZS5yZW5kZXJlZFRpbGVaID0gdGlsZS5zb3VyY2VaO1xuICAgIHZhciB0aWxlQ29vcmQgPSB0aWxlLndyYXBwZWRUaWxlQ29vcmQ7XG4gICAgdmFyIHogPSB0aWxlQ29vcmRbMF07XG4gICAgdmFyIHNvdXJjZSA9IGxheWVyLmdldFNvdXJjZSgpO1xuICAgIHZhciBwaXhlbFJhdGlvID0gZnJhbWVTdGF0ZS5waXhlbFJhdGlvO1xuICAgIHZhciB2aWV3U3RhdGUgPSBmcmFtZVN0YXRlLnZpZXdTdGF0ZTtcbiAgICB2YXIgcHJvamVjdGlvbiA9IHZpZXdTdGF0ZS5wcm9qZWN0aW9uO1xuICAgIHZhciB0aWxlR3JpZCA9IHNvdXJjZS5nZXRUaWxlR3JpZEZvclByb2plY3Rpb24ocHJvamVjdGlvbik7XG4gICAgdmFyIHRpbGVSZXNvbHV0aW9uID0gdGlsZUdyaWQuZ2V0UmVzb2x1dGlvbih0aWxlLnRpbGVDb29yZFswXSk7XG4gICAgdmFyIHJlbmRlclBpeGVsUmF0aW8gPSBmcmFtZVN0YXRlLnBpeGVsUmF0aW8gLyB0aWxlLndhbnRlZFJlc29sdXRpb24gKiB0aWxlUmVzb2x1dGlvbjtcbiAgICB2YXIgcmVzb2x1dGlvbiA9IHRpbGVHcmlkLmdldFJlc29sdXRpb24oeik7XG4gICAgdmFyIGNvbnRleHQgPSB0aWxlLmdldENvbnRleHQobGF5ZXIpOyAvLyBJbmNyZWFzZSB0aWxlIHNpemUgd2hlbiBvdmVyem9vbWluZyBmb3IgbG93IHBpeGVsIHJhdGlvLCB0byBhdm9pZCBibHVycnkgdGlsZXNcblxuICAgIHBpeGVsUmF0aW8gPSBNYXRoLnJvdW5kKE1hdGgubWF4KHBpeGVsUmF0aW8sIHJlbmRlclBpeGVsUmF0aW8gLyBwaXhlbFJhdGlvKSk7XG4gICAgdmFyIHNpemUgPSBzb3VyY2UuZ2V0VGlsZVBpeGVsU2l6ZSh6LCBwaXhlbFJhdGlvLCBwcm9qZWN0aW9uKTtcbiAgICBjb250ZXh0LmNhbnZhcy53aWR0aCA9IHNpemVbMF07XG4gICAgY29udGV4dC5jYW52YXMuaGVpZ2h0ID0gc2l6ZVsxXTtcbiAgICB2YXIgcmVuZGVyU2NhbGUgPSBwaXhlbFJhdGlvIC8gcmVuZGVyUGl4ZWxSYXRpbztcblxuICAgIGlmIChyZW5kZXJTY2FsZSAhPT0gMSkge1xuICAgICAgdmFyIGNhbnZhc1RyYW5zZm9ybSA9IHJlc2V0VHJhbnNmb3JtKHRoaXMudG1wVHJhbnNmb3JtXyk7XG4gICAgICBzY2FsZVRyYW5zZm9ybShjYW52YXNUcmFuc2Zvcm0sIHJlbmRlclNjYWxlLCByZW5kZXJTY2FsZSk7XG4gICAgICBjb250ZXh0LnNldFRyYW5zZm9ybS5hcHBseShjb250ZXh0LCBjYW52YXNUcmFuc2Zvcm0pO1xuICAgIH1cblxuICAgIHZhciB0aWxlRXh0ZW50ID0gdGlsZUdyaWQuZ2V0VGlsZUNvb3JkRXh0ZW50KHRpbGVDb29yZCwgdGhpcy50bXBFeHRlbnQpO1xuICAgIHZhciBwaXhlbFNjYWxlID0gcmVuZGVyUGl4ZWxSYXRpbyAvIHJlc29sdXRpb247XG4gICAgdmFyIHRyYW5zZm9ybSA9IHJlc2V0VHJhbnNmb3JtKHRoaXMudG1wVHJhbnNmb3JtXyk7XG4gICAgc2NhbGVUcmFuc2Zvcm0odHJhbnNmb3JtLCBwaXhlbFNjYWxlLCAtcGl4ZWxTY2FsZSk7XG4gICAgdHJhbnNsYXRlVHJhbnNmb3JtKHRyYW5zZm9ybSwgLXRpbGVFeHRlbnRbMF0sIC10aWxlRXh0ZW50WzNdKTtcblxuICAgIGZvciAodmFyIGkgPSAwLCBpaSA9IGV4ZWN1dG9yR3JvdXBzLmxlbmd0aDsgaSA8IGlpOyArK2kpIHtcbiAgICAgIHZhciBleGVjdXRvckdyb3VwID0gZXhlY3V0b3JHcm91cHNbaV07XG4gICAgICBleGVjdXRvckdyb3VwLmV4ZWN1dGUoY29udGV4dCwgcmVuZGVyU2NhbGUsIHRyYW5zZm9ybSwgMCwgdHJ1ZSwgSU1BR0VfUkVQTEFZU1tsYXllci5nZXRSZW5kZXJNb2RlKCldKTtcbiAgICB9XG5cbiAgICByZXBsYXlTdGF0ZS5yZW5kZXJlZFRpbGVSZXNvbHV0aW9uID0gdGlsZS53YW50ZWRSZXNvbHV0aW9uO1xuICB9O1xuXG4gIHJldHVybiBDYW52YXNWZWN0b3JUaWxlTGF5ZXJSZW5kZXJlcjtcbn0oQ2FudmFzVGlsZUxheWVyUmVuZGVyZXIpO1xuXG5leHBvcnQgZGVmYXVsdCBDYW52YXNWZWN0b3JUaWxlTGF5ZXJSZW5kZXJlcjsiLCJ2YXIgX19leHRlbmRzID0gdGhpcyAmJiB0aGlzLl9fZXh0ZW5kcyB8fCBmdW5jdGlvbiAoKSB7XG4gIHZhciBfZXh0ZW5kU3RhdGljcyA9IGZ1bmN0aW9uIGV4dGVuZFN0YXRpY3MoZCwgYikge1xuICAgIF9leHRlbmRTdGF0aWNzID0gT2JqZWN0LnNldFByb3RvdHlwZU9mIHx8IHtcbiAgICAgIF9fcHJvdG9fXzogW11cbiAgICB9IGluc3RhbmNlb2YgQXJyYXkgJiYgZnVuY3Rpb24gKGQsIGIpIHtcbiAgICAgIGQuX19wcm90b19fID0gYjtcbiAgICB9IHx8IGZ1bmN0aW9uIChkLCBiKSB7XG4gICAgICBmb3IgKHZhciBwIGluIGIpIHtcbiAgICAgICAgaWYgKE9iamVjdC5wcm90b3R5cGUuaGFzT3duUHJvcGVydHkuY2FsbChiLCBwKSkgZFtwXSA9IGJbcF07XG4gICAgICB9XG4gICAgfTtcblxuICAgIHJldHVybiBfZXh0ZW5kU3RhdGljcyhkLCBiKTtcbiAgfTtcblxuICByZXR1cm4gZnVuY3Rpb24gKGQsIGIpIHtcbiAgICBfZXh0ZW5kU3RhdGljcyhkLCBiKTtcblxuICAgIGZ1bmN0aW9uIF9fKCkge1xuICAgICAgdGhpcy5jb25zdHJ1Y3RvciA9IGQ7XG4gICAgfVxuXG4gICAgZC5wcm90b3R5cGUgPSBiID09PSBudWxsID8gT2JqZWN0LmNyZWF0ZShiKSA6IChfXy5wcm90b3R5cGUgPSBiLnByb3RvdHlwZSwgbmV3IF9fKCkpO1xuICB9O1xufSgpO1xuLyoqXG4gKiBAbW9kdWxlIG9sL2xheWVyL1ZlY3RvclRpbGVcbiAqL1xuXG5cbmltcG9ydCBCYXNlVmVjdG9yTGF5ZXIgZnJvbSAnLi9CYXNlVmVjdG9yLmpzJztcbmltcG9ydCBDYW52YXNWZWN0b3JUaWxlTGF5ZXJSZW5kZXJlciBmcm9tICcuLi9yZW5kZXJlci9jYW52YXMvVmVjdG9yVGlsZUxheWVyLmpzJztcbmltcG9ydCBUaWxlUHJvcGVydHkgZnJvbSAnLi9UaWxlUHJvcGVydHkuanMnO1xuaW1wb3J0IFZlY3RvclRpbGVSZW5kZXJUeXBlIGZyb20gJy4vVmVjdG9yVGlsZVJlbmRlclR5cGUuanMnO1xuaW1wb3J0IHsgYXNzZXJ0IH0gZnJvbSAnLi4vYXNzZXJ0cy5qcyc7XG5pbXBvcnQgeyBhc3NpZ24gfSBmcm9tICcuLi9vYmouanMnO1xuLyoqXG4gKiBAdHlwZWRlZiB7T2JqZWN0fSBPcHRpb25zXG4gKiBAcHJvcGVydHkge3N0cmluZ30gW2NsYXNzTmFtZT0nb2wtbGF5ZXInXSBBIENTUyBjbGFzcyBuYW1lIHRvIHNldCB0byB0aGUgbGF5ZXIgZWxlbWVudC5cbiAqIEBwcm9wZXJ0eSB7bnVtYmVyfSBbb3BhY2l0eT0xXSBPcGFjaXR5ICgwLCAxKS5cbiAqIEBwcm9wZXJ0eSB7Ym9vbGVhbn0gW3Zpc2libGU9dHJ1ZV0gVmlzaWJpbGl0eS5cbiAqIEBwcm9wZXJ0eSB7aW1wb3J0KFwiLi4vZXh0ZW50LmpzXCIpLkV4dGVudH0gW2V4dGVudF0gVGhlIGJvdW5kaW5nIGV4dGVudCBmb3IgbGF5ZXIgcmVuZGVyaW5nLiAgVGhlIGxheWVyIHdpbGwgbm90IGJlXG4gKiByZW5kZXJlZCBvdXRzaWRlIG9mIHRoaXMgZXh0ZW50LlxuICogQHByb3BlcnR5IHtudW1iZXJ9IFt6SW5kZXhdIFRoZSB6LWluZGV4IGZvciBsYXllciByZW5kZXJpbmcuICBBdCByZW5kZXJpbmcgdGltZSwgdGhlIGxheWVyc1xuICogd2lsbCBiZSBvcmRlcmVkLCBmaXJzdCBieSBaLWluZGV4IGFuZCB0aGVuIGJ5IHBvc2l0aW9uLiBXaGVuIGB1bmRlZmluZWRgLCBhIGB6SW5kZXhgIG9mIDAgaXMgYXNzdW1lZFxuICogZm9yIGxheWVycyB0aGF0IGFyZSBhZGRlZCB0byB0aGUgbWFwJ3MgYGxheWVyc2AgY29sbGVjdGlvbiwgb3IgYEluZmluaXR5YCB3aGVuIHRoZSBsYXllcidzIGBzZXRNYXAoKWBcbiAqIG1ldGhvZCB3YXMgdXNlZC5cbiAqIEBwcm9wZXJ0eSB7bnVtYmVyfSBbbWluUmVzb2x1dGlvbl0gVGhlIG1pbmltdW0gcmVzb2x1dGlvbiAoaW5jbHVzaXZlKSBhdCB3aGljaCB0aGlzIGxheWVyIHdpbGwgYmVcbiAqIHZpc2libGUuXG4gKiBAcHJvcGVydHkge251bWJlcn0gW21heFJlc29sdXRpb25dIFRoZSBtYXhpbXVtIHJlc29sdXRpb24gKGV4Y2x1c2l2ZSkgYmVsb3cgd2hpY2ggdGhpcyBsYXllciB3aWxsXG4gKiBiZSB2aXNpYmxlLlxuICogQHByb3BlcnR5IHtudW1iZXJ9IFttaW5ab29tXSBUaGUgbWluaW11bSB2aWV3IHpvb20gbGV2ZWwgKGV4Y2x1c2l2ZSkgYWJvdmUgd2hpY2ggdGhpcyBsYXllciB3aWxsIGJlXG4gKiB2aXNpYmxlLlxuICogQHByb3BlcnR5IHtudW1iZXJ9IFttYXhab29tXSBUaGUgbWF4aW11bSB2aWV3IHpvb20gbGV2ZWwgKGluY2x1c2l2ZSkgYXQgd2hpY2ggdGhpcyBsYXllciB3aWxsXG4gKiBiZSB2aXNpYmxlLlxuICogQHByb3BlcnR5IHtpbXBvcnQoXCIuLi9yZW5kZXIuanNcIikuT3JkZXJGdW5jdGlvbn0gW3JlbmRlck9yZGVyXSBSZW5kZXIgb3JkZXIuIEZ1bmN0aW9uIHRvIGJlIHVzZWQgd2hlbiBzb3J0aW5nXG4gKiBmZWF0dXJlcyBiZWZvcmUgcmVuZGVyaW5nLiBCeSBkZWZhdWx0IGZlYXR1cmVzIGFyZSBkcmF3biBpbiB0aGUgb3JkZXIgdGhhdCB0aGV5IGFyZSBjcmVhdGVkLiBVc2VcbiAqIGBudWxsYCB0byBhdm9pZCB0aGUgc29ydCwgYnV0IGdldCBhbiB1bmRlZmluZWQgZHJhdyBvcmRlci5cbiAqIEBwcm9wZXJ0eSB7bnVtYmVyfSBbcmVuZGVyQnVmZmVyPTEwMF0gVGhlIGJ1ZmZlciBpbiBwaXhlbHMgYXJvdW5kIHRoZSB0aWxlIGV4dGVudCB1c2VkIGJ5IHRoZVxuICogcmVuZGVyZXIgd2hlbiBnZXR0aW5nIGZlYXR1cmVzIGZyb20gdGhlIHZlY3RvciB0aWxlIGZvciB0aGUgcmVuZGVyaW5nIG9yIGhpdC1kZXRlY3Rpb24uXG4gKiBSZWNvbW1lbmRlZCB2YWx1ZTogVmVjdG9yIHRpbGVzIGFyZSB1c3VhbGx5IGdlbmVyYXRlZCB3aXRoIGEgYnVmZmVyLCBzbyB0aGlzIHZhbHVlIHNob3VsZCBtYXRjaFxuICogdGhlIGxhcmdlc3QgcG9zc2libGUgYnVmZmVyIG9mIHRoZSB1c2VkIHRpbGVzLiBJdCBzaG91bGQgYmUgYXQgbGVhc3QgdGhlIHNpemUgb2YgdGhlIGxhcmdlc3RcbiAqIHBvaW50IHN5bWJvbCBvciBsaW5lIHdpZHRoLlxuICogQHByb3BlcnR5IHtpbXBvcnQoXCIuL1ZlY3RvclRpbGVSZW5kZXJUeXBlLmpzXCIpLmRlZmF1bHR8c3RyaW5nfSBbcmVuZGVyTW9kZT0naHlicmlkJ10gUmVuZGVyIG1vZGUgZm9yIHZlY3RvciB0aWxlczpcbiAqICAqIGAnaW1hZ2UnYDogVmVjdG9yIHRpbGVzIGFyZSByZW5kZXJlZCBhcyBpbWFnZXMuIE9ubHkgYXZhaWxhYmxlIHdoZW4gYGRlY2x1dHRlcmAgaXMgc2V0IHRvIGBmYWxzZWAgKGRlZmF1bHQpLlxuICogICAgT3RoZXJ3aXNlLCBgJ2h5YnJpZCdgIG1vZGUgd2lsbCB1c2VkIGluc3RlYWQuIEdyZWF0IHBlcmZvcm1hbmNlLCBidXQgcG9pbnQgc3ltYm9scyBhbmQgdGV4dHNcbiAqICAgIGFyZSBhbHdheXMgcm90YXRlZCB3aXRoIHRoZSB2aWV3IGFuZCBwaXhlbHMgYXJlIHNjYWxlZCBkdXJpbmcgem9vbSBhbmltYXRpb25zLiBMYWJlbHMgYW5kIHBvaW50IHN5bWJvbHMgd2lsbFxuICogICAgZ2V0IGN1dCBvZmYgYXQgdGlsZSBib3VuZGFyaWVzLlxuICogICogYCdoeWJyaWQnYDogUG9seWdvbiBhbmQgbGluZSBlbGVtZW50cyBhcmUgcmVuZGVyZWQgYXMgaW1hZ2VzLCBzbyBwaXhlbHMgYXJlIHNjYWxlZCBkdXJpbmcgem9vbVxuICogICAgYW5pbWF0aW9ucy4gUG9pbnQgc3ltYm9scyBhbmQgdGV4dHMgYXJlIGFjY3VyYXRlbHkgcmVuZGVyZWQgYXMgdmVjdG9ycyBhbmQgY2FuIHN0YXkgdXByaWdodCBvblxuICogICAgcm90YXRlZCB2aWV3cy5cbiAqICAqIGAndmVjdG9yJ2A6IEV2ZXJ5dGhpbmcgaXMgcmVuZGVyZWQgYXMgdmVjdG9ycy4gVXNlIHRoaXMgbW9kZSBmb3IgaW1wcm92ZWQgcGVyZm9ybWFuY2Ugb24gdmVjdG9yXG4gKiAgICB0aWxlIGxheWVycyB3aXRoIG9ubHkgYSBmZXcgcmVuZGVyZWQgZmVhdHVyZXMgKGUuZy4gZm9yIGhpZ2hsaWdodGluZyBhIHN1YnNldCBvZiBmZWF0dXJlcyBvZlxuICogICAgYW5vdGhlciBsYXllciB3aXRoIHRoZSBzYW1lIHNvdXJjZSkuXG4gKiBAcHJvcGVydHkge2ltcG9ydChcIi4uL3NvdXJjZS9WZWN0b3JUaWxlLmpzXCIpLmRlZmF1bHR9IFtzb3VyY2VdIFNvdXJjZS5cbiAqIEBwcm9wZXJ0eSB7aW1wb3J0KFwiLi4vUGx1Z2dhYmxlTWFwLmpzXCIpLmRlZmF1bHR9IFttYXBdIFNldHMgdGhlIGxheWVyIGFzIG92ZXJsYXkgb24gYSBtYXAuIFRoZSBtYXAgd2lsbCBub3QgbWFuYWdlXG4gKiB0aGlzIGxheWVyIGluIGl0cyBsYXllcnMgY29sbGVjdGlvbiwgYW5kIHRoZSBsYXllciB3aWxsIGJlIHJlbmRlcmVkIG9uIHRvcC4gVGhpcyBpcyB1c2VmdWwgZm9yXG4gKiB0ZW1wb3JhcnkgbGF5ZXJzLiBUaGUgc3RhbmRhcmQgd2F5IHRvIGFkZCBhIGxheWVyIHRvIGEgbWFwIGFuZCBoYXZlIGl0IG1hbmFnZWQgYnkgdGhlIG1hcCBpcyB0b1xuICogdXNlIHtAbGluayBtb2R1bGU6b2wvTWFwI2FkZExheWVyfS5cbiAqIEBwcm9wZXJ0eSB7Ym9vbGVhbn0gW2RlY2x1dHRlcj1mYWxzZV0gRGVjbHV0dGVyIGltYWdlcyBhbmQgdGV4dC4gRGVjbHV0dGVyaW5nIGlzIGFwcGxpZWQgdG8gYWxsXG4gKiBpbWFnZSBhbmQgdGV4dCBzdHlsZXMgb2YgYWxsIFZlY3RvciBhbmQgVmVjdG9yVGlsZSBsYXllcnMgdGhhdCBoYXZlIHNldCB0aGlzIHRvIGB0cnVlYC4gVGhlIHByaW9yaXR5XG4gKiBpcyBkZWZpbmVkIGJ5IHRoZSB6LWluZGV4IG9mIHRoZSBsYXllciwgdGhlIGB6SW5kZXhgIG9mIHRoZSBzdHlsZSBhbmQgdGhlIHJlbmRlciBvcmRlciBvZiBmZWF0dXJlcy5cbiAqIEhpZ2hlciB6LWluZGV4IG1lYW5zIGhpZ2hlciBwcmlvcml0eS4gV2l0aGluIHRoZSBzYW1lIHotaW5kZXgsIGEgZmVhdHVyZSByZW5kZXJlZCBiZWZvcmUgYW5vdGhlciBoYXNcbiAqIGhpZ2hlciBwcmlvcml0eS5cbiAqIEBwcm9wZXJ0eSB7aW1wb3J0KFwiLi4vc3R5bGUvU3R5bGUuanNcIikuU3R5bGVMaWtlfSBbc3R5bGVdIExheWVyIHN0eWxlLiBTZWVcbiAqIHtAbGluayBtb2R1bGU6b2wvc3R5bGV9IGZvciBkZWZhdWx0IHN0eWxlIHdoaWNoIHdpbGwgYmUgdXNlZCBpZiB0aGlzIGlzIG5vdCBkZWZpbmVkLlxuICogQHByb3BlcnR5IHtib29sZWFufSBbdXBkYXRlV2hpbGVBbmltYXRpbmc9ZmFsc2VdIFdoZW4gc2V0IHRvIGB0cnVlYCwgZmVhdHVyZSBiYXRjaGVzIHdpbGwgYmVcbiAqIHJlY3JlYXRlZCBkdXJpbmcgYW5pbWF0aW9ucy4gVGhpcyBtZWFucyB0aGF0IG5vIHZlY3RvcnMgd2lsbCBiZSBzaG93biBjbGlwcGVkLCBidXQgdGhlIHNldHRpbmdcbiAqIHdpbGwgaGF2ZSBhIHBlcmZvcm1hbmNlIGltcGFjdCBmb3IgbGFyZ2UgYW1vdW50cyBvZiB2ZWN0b3IgZGF0YS4gV2hlbiBzZXQgdG8gYGZhbHNlYCwgYmF0Y2hlc1xuICogd2lsbCBiZSByZWNyZWF0ZWQgd2hlbiBubyBhbmltYXRpb24gaXMgYWN0aXZlLlxuICogQHByb3BlcnR5IHtib29sZWFufSBbdXBkYXRlV2hpbGVJbnRlcmFjdGluZz1mYWxzZV0gV2hlbiBzZXQgdG8gYHRydWVgLCBmZWF0dXJlIGJhdGNoZXMgd2lsbCBiZVxuICogcmVjcmVhdGVkIGR1cmluZyBpbnRlcmFjdGlvbnMuIFNlZSBhbHNvIGB1cGRhdGVXaGlsZUFuaW1hdGluZ2AuXG4gKiBAcHJvcGVydHkge251bWJlcn0gW3ByZWxvYWQ9MF0gUHJlbG9hZC4gTG9hZCBsb3ctcmVzb2x1dGlvbiB0aWxlcyB1cCB0byBgcHJlbG9hZGAgbGV2ZWxzLiBgMGBcbiAqIG1lYW5zIG5vIHByZWxvYWRpbmcuXG4gKiBAcHJvcGVydHkge2Jvb2xlYW59IFt1c2VJbnRlcmltVGlsZXNPbkVycm9yPXRydWVdIFVzZSBpbnRlcmltIHRpbGVzIG9uIGVycm9yLlxuICovXG5cbi8qKlxuICogQGNsYXNzZGVzY1xuICogTGF5ZXIgZm9yIHZlY3RvciB0aWxlIGRhdGEgdGhhdCBpcyByZW5kZXJlZCBjbGllbnQtc2lkZS5cbiAqIE5vdGUgdGhhdCBhbnkgcHJvcGVydHkgc2V0IGluIHRoZSBvcHRpb25zIGlzIHNldCBhcyBhIHtAbGluayBtb2R1bGU6b2wvT2JqZWN0fkJhc2VPYmplY3R9XG4gKiBwcm9wZXJ0eSBvbiB0aGUgbGF5ZXIgb2JqZWN0OyBmb3IgZXhhbXBsZSwgc2V0dGluZyBgdGl0bGU6ICdNeSBUaXRsZSdgIGluIHRoZVxuICogb3B0aW9ucyBtZWFucyB0aGF0IGB0aXRsZWAgaXMgb2JzZXJ2YWJsZSwgYW5kIGhhcyBnZXQvc2V0IGFjY2Vzc29ycy5cbiAqXG4gKiBAcGFyYW0ge09wdGlvbnM9fSBvcHRfb3B0aW9ucyBPcHRpb25zLlxuICogQGV4dGVuZHMge0Jhc2VWZWN0b3JMYXllcjxpbXBvcnQoXCIuLi9zb3VyY2UvVmVjdG9yVGlsZS5qc1wiKS5kZWZhdWx0Pn1cbiAqIEBhcGlcbiAqL1xuXG52YXIgVmVjdG9yVGlsZUxheWVyID1cbi8qKiBAY2xhc3MgKi9cbmZ1bmN0aW9uIChfc3VwZXIpIHtcbiAgX19leHRlbmRzKFZlY3RvclRpbGVMYXllciwgX3N1cGVyKTtcbiAgLyoqXG4gICAqIEBwYXJhbSB7T3B0aW9ucz19IG9wdF9vcHRpb25zIE9wdGlvbnMuXG4gICAqL1xuXG5cbiAgZnVuY3Rpb24gVmVjdG9yVGlsZUxheWVyKG9wdF9vcHRpb25zKSB7XG4gICAgdmFyIF90aGlzID0gdGhpcztcblxuICAgIHZhciBvcHRpb25zID0gb3B0X29wdGlvbnMgPyBvcHRfb3B0aW9ucyA6IHt9O1xuICAgIHZhciBiYXNlT3B0aW9ucyA9XG4gICAgLyoqIEB0eXBlIHtPYmplY3R9ICovXG4gICAgYXNzaWduKHt9LCBvcHRpb25zKTtcbiAgICBkZWxldGUgYmFzZU9wdGlvbnMucHJlbG9hZDtcbiAgICBkZWxldGUgYmFzZU9wdGlvbnMudXNlSW50ZXJpbVRpbGVzT25FcnJvcjtcbiAgICBfdGhpcyA9IF9zdXBlci5jYWxsKHRoaXMsXG4gICAgLyoqIEB0eXBlIHtpbXBvcnQoXCIuL0Jhc2VWZWN0b3IuanNcIikuT3B0aW9uc30gKi9cbiAgICBiYXNlT3B0aW9ucykgfHwgdGhpcztcbiAgICB2YXIgcmVuZGVyTW9kZSA9IG9wdGlvbnMucmVuZGVyTW9kZSB8fCBWZWN0b3JUaWxlUmVuZGVyVHlwZS5IWUJSSUQ7XG4gICAgYXNzZXJ0KHJlbmRlck1vZGUgPT0gdW5kZWZpbmVkIHx8IHJlbmRlck1vZGUgPT0gVmVjdG9yVGlsZVJlbmRlclR5cGUuSU1BR0UgfHwgcmVuZGVyTW9kZSA9PSBWZWN0b3JUaWxlUmVuZGVyVHlwZS5IWUJSSUQgfHwgcmVuZGVyTW9kZSA9PSBWZWN0b3JUaWxlUmVuZGVyVHlwZS5WRUNUT1IsIDI4KTsgLy8gYHJlbmRlck1vZGVgIG11c3QgYmUgYCdpbWFnZSdgLCBgJ2h5YnJpZCdgIG9yIGAndmVjdG9yJ2AuXG5cbiAgICAvKipcbiAgICAgKiBAcHJpdmF0ZVxuICAgICAqIEB0eXBlIHtpbXBvcnQoXCIuL1ZlY3RvclRpbGVSZW5kZXJUeXBlLmpzXCIpLmRlZmF1bHR9XG4gICAgICovXG5cbiAgICBfdGhpcy5yZW5kZXJNb2RlXyA9IHJlbmRlck1vZGU7XG5cbiAgICBfdGhpcy5zZXRQcmVsb2FkKG9wdGlvbnMucHJlbG9hZCA/IG9wdGlvbnMucHJlbG9hZCA6IDApO1xuXG4gICAgX3RoaXMuc2V0VXNlSW50ZXJpbVRpbGVzT25FcnJvcihvcHRpb25zLnVzZUludGVyaW1UaWxlc09uRXJyb3IgIT09IHVuZGVmaW5lZCA/IG9wdGlvbnMudXNlSW50ZXJpbVRpbGVzT25FcnJvciA6IHRydWUpO1xuXG4gICAgcmV0dXJuIF90aGlzO1xuICB9XG4gIC8qKlxuICAgKiBDcmVhdGUgYSByZW5kZXJlciBmb3IgdGhpcyBsYXllci5cbiAgICogQHJldHVybiB7aW1wb3J0KFwiLi4vcmVuZGVyZXIvTGF5ZXIuanNcIikuZGVmYXVsdH0gQSBsYXllciByZW5kZXJlci5cbiAgICogQHByb3RlY3RlZFxuICAgKi9cblxuXG4gIFZlY3RvclRpbGVMYXllci5wcm90b3R5cGUuY3JlYXRlUmVuZGVyZXIgPSBmdW5jdGlvbiAoKSB7XG4gICAgcmV0dXJuIG5ldyBDYW52YXNWZWN0b3JUaWxlTGF5ZXJSZW5kZXJlcih0aGlzKTtcbiAgfTtcbiAgLyoqXG4gICAqIEdldCB0aGUgdG9wbW9zdCBmZWF0dXJlIHRoYXQgaW50ZXJzZWN0cyB0aGUgZ2l2ZW4gcGl4ZWwgb24gdGhlIHZpZXdwb3J0LiBSZXR1cm5zIGEgcHJvbWlzZVxuICAgKiB0aGF0IHJlc29sdmVzIHdpdGggYW4gYXJyYXkgb2YgZmVhdHVyZXMuIFRoZSBhcnJheSB3aWxsIGVpdGhlciBjb250YWluIHRoZSB0b3Btb3N0IGZlYXR1cmVcbiAgICogd2hlbiBhIGhpdCB3YXMgZGV0ZWN0ZWQsIG9yIGl0IHdpbGwgYmUgZW1wdHkuXG4gICAqXG4gICAqIFRoZSBoaXQgZGV0ZWN0aW9uIGFsZ29yaXRobSB1c2VkIGZvciB0aGlzIG1ldGhvZCBpcyBvcHRpbWl6ZWQgZm9yIHBlcmZvcm1hbmNlLCBidXQgaXMgbGVzc1xuICAgKiBhY2N1cmF0ZSB0aGFuIHRoZSBvbmUgdXNlZCBpbiB7QGxpbmsgaW1wb3J0KFwiLi4vUGx1Z2dhYmxlTWFwLmpzXCIpLmRlZmF1bHQjZ2V0RmVhdHVyZXNBdFBpeGVsfTogVGV4dFxuICAgKiBpcyBub3QgY29uc2lkZXJlZCwgYW5kIGljb25zIGFyZSBvbmx5IHJlcHJlc2VudGVkIGJ5IHRoZWlyIGJvdW5kaW5nIGJveCBpbnN0ZWFkIG9mIHRoZSBleGFjdFxuICAgKiBpbWFnZS5cbiAgICpcbiAgICogQHBhcmFtIHtpbXBvcnQoXCIuLi9waXhlbC5qc1wiKS5QaXhlbH0gcGl4ZWwgUGl4ZWwuXG4gICAqIEByZXR1cm4ge1Byb21pc2U8QXJyYXk8aW1wb3J0KFwiLi4vRmVhdHVyZVwiKS5kZWZhdWx0Pj59IFByb21pc2UgdGhhdCByZXNvbHZlcyB3aXRoIGFuIGFycmF5IG9mIGZlYXR1cmVzLlxuICAgKiBAYXBpXG4gICAqL1xuXG5cbiAgVmVjdG9yVGlsZUxheWVyLnByb3RvdHlwZS5nZXRGZWF0dXJlcyA9IGZ1bmN0aW9uIChwaXhlbCkge1xuICAgIHJldHVybiBfc3VwZXIucHJvdG90eXBlLmdldEZlYXR1cmVzLmNhbGwodGhpcywgcGl4ZWwpO1xuICB9O1xuICAvKipcbiAgICogQHJldHVybiB7aW1wb3J0KFwiLi9WZWN0b3JUaWxlUmVuZGVyVHlwZS5qc1wiKS5kZWZhdWx0fSBUaGUgcmVuZGVyIG1vZGUuXG4gICAqL1xuXG5cbiAgVmVjdG9yVGlsZUxheWVyLnByb3RvdHlwZS5nZXRSZW5kZXJNb2RlID0gZnVuY3Rpb24gKCkge1xuICAgIHJldHVybiB0aGlzLnJlbmRlck1vZGVfO1xuICB9O1xuICAvKipcbiAgICogUmV0dXJuIHRoZSBsZXZlbCBhcyBudW1iZXIgdG8gd2hpY2ggd2Ugd2lsbCBwcmVsb2FkIHRpbGVzIHVwIHRvLlxuICAgKiBAcmV0dXJuIHtudW1iZXJ9IFRoZSBsZXZlbCB0byBwcmVsb2FkIHRpbGVzIHVwIHRvLlxuICAgKiBAb2JzZXJ2YWJsZVxuICAgKiBAYXBpXG4gICAqL1xuXG5cbiAgVmVjdG9yVGlsZUxheWVyLnByb3RvdHlwZS5nZXRQcmVsb2FkID0gZnVuY3Rpb24gKCkge1xuICAgIHJldHVybiAoXG4gICAgICAvKiogQHR5cGUge251bWJlcn0gKi9cbiAgICAgIHRoaXMuZ2V0KFRpbGVQcm9wZXJ0eS5QUkVMT0FEKVxuICAgICk7XG4gIH07XG4gIC8qKlxuICAgKiBXaGV0aGVyIHdlIHVzZSBpbnRlcmltIHRpbGVzIG9uIGVycm9yLlxuICAgKiBAcmV0dXJuIHtib29sZWFufSBVc2UgaW50ZXJpbSB0aWxlcyBvbiBlcnJvci5cbiAgICogQG9ic2VydmFibGVcbiAgICogQGFwaVxuICAgKi9cblxuXG4gIFZlY3RvclRpbGVMYXllci5wcm90b3R5cGUuZ2V0VXNlSW50ZXJpbVRpbGVzT25FcnJvciA9IGZ1bmN0aW9uICgpIHtcbiAgICByZXR1cm4gKFxuICAgICAgLyoqIEB0eXBlIHtib29sZWFufSAqL1xuICAgICAgdGhpcy5nZXQoVGlsZVByb3BlcnR5LlVTRV9JTlRFUklNX1RJTEVTX09OX0VSUk9SKVxuICAgICk7XG4gIH07XG4gIC8qKlxuICAgKiBTZXQgdGhlIGxldmVsIGFzIG51bWJlciB0byB3aGljaCB3ZSB3aWxsIHByZWxvYWQgdGlsZXMgdXAgdG8uXG4gICAqIEBwYXJhbSB7bnVtYmVyfSBwcmVsb2FkIFRoZSBsZXZlbCB0byBwcmVsb2FkIHRpbGVzIHVwIHRvLlxuICAgKiBAb2JzZXJ2YWJsZVxuICAgKiBAYXBpXG4gICAqL1xuXG5cbiAgVmVjdG9yVGlsZUxheWVyLnByb3RvdHlwZS5zZXRQcmVsb2FkID0gZnVuY3Rpb24gKHByZWxvYWQpIHtcbiAgICB0aGlzLnNldChUaWxlUHJvcGVydHkuUFJFTE9BRCwgcHJlbG9hZCk7XG4gIH07XG4gIC8qKlxuICAgKiBTZXQgd2hldGhlciB3ZSB1c2UgaW50ZXJpbSB0aWxlcyBvbiBlcnJvci5cbiAgICogQHBhcmFtIHtib29sZWFufSB1c2VJbnRlcmltVGlsZXNPbkVycm9yIFVzZSBpbnRlcmltIHRpbGVzIG9uIGVycm9yLlxuICAgKiBAb2JzZXJ2YWJsZVxuICAgKiBAYXBpXG4gICAqL1xuXG5cbiAgVmVjdG9yVGlsZUxheWVyLnByb3RvdHlwZS5zZXRVc2VJbnRlcmltVGlsZXNPbkVycm9yID0gZnVuY3Rpb24gKHVzZUludGVyaW1UaWxlc09uRXJyb3IpIHtcbiAgICB0aGlzLnNldChUaWxlUHJvcGVydHkuVVNFX0lOVEVSSU1fVElMRVNfT05fRVJST1IsIHVzZUludGVyaW1UaWxlc09uRXJyb3IpO1xuICB9O1xuXG4gIHJldHVybiBWZWN0b3JUaWxlTGF5ZXI7XG59KEJhc2VWZWN0b3JMYXllcik7XG5cbmV4cG9ydCBkZWZhdWx0IFZlY3RvclRpbGVMYXllcjsiLCIvKipcbiAqIEBtb2R1bGUgb2wvZm9ybWF0L0ZlYXR1cmVcbiAqL1xuaW1wb3J0IFVuaXRzIGZyb20gJy4uL3Byb2ovVW5pdHMuanMnO1xuaW1wb3J0IHsgYWJzdHJhY3QgfSBmcm9tICcuLi91dGlsLmpzJztcbmltcG9ydCB7IGFzc2lnbiB9IGZyb20gJy4uL29iai5qcyc7XG5pbXBvcnQgeyBlcXVpdmFsZW50IGFzIGVxdWl2YWxlbnRQcm9qZWN0aW9uLCBnZXQgYXMgZ2V0UHJvamVjdGlvbiwgdHJhbnNmb3JtRXh0ZW50IH0gZnJvbSAnLi4vcHJvai5qcyc7XG4vKipcbiAqIEB0eXBlZGVmIHtPYmplY3R9IFJlYWRPcHRpb25zXG4gKiBAcHJvcGVydHkge2ltcG9ydChcIi4uL3Byb2ouanNcIikuUHJvamVjdGlvbkxpa2V9IFtkYXRhUHJvamVjdGlvbl0gUHJvamVjdGlvbiBvZiB0aGUgZGF0YSB3ZSBhcmUgcmVhZGluZy5cbiAqIElmIG5vdCBwcm92aWRlZCwgdGhlIHByb2plY3Rpb24gd2lsbCBiZSBkZXJpdmVkIGZyb20gdGhlIGRhdGEgKHdoZXJlIHBvc3NpYmxlKSBvclxuICogdGhlIGBkYXRhUHJvamVjdGlvbmAgb2YgdGhlIGZvcm1hdCBpcyBhc3NpZ25lZCAod2hlcmUgc2V0KS4gSWYgdGhlIHByb2plY3Rpb25cbiAqIGNhbiBub3QgYmUgZGVyaXZlZCBmcm9tIHRoZSBkYXRhIGFuZCBpZiBubyBgZGF0YVByb2plY3Rpb25gIGlzIHNldCBmb3IgYSBmb3JtYXQsXG4gKiB0aGUgZmVhdHVyZXMgd2lsbCBub3QgYmUgcmVwcm9qZWN0ZWQuXG4gKiBAcHJvcGVydHkge2ltcG9ydChcIi4uL2V4dGVudC5qc1wiKS5FeHRlbnR9IFtleHRlbnRdIFRpbGUgZXh0ZW50IGluIG1hcCB1bml0cyBvZiB0aGUgdGlsZSBiZWluZyByZWFkLlxuICogVGhpcyBpcyBvbmx5IHJlcXVpcmVkIHdoZW4gcmVhZGluZyBkYXRhIHdpdGggdGlsZSBwaXhlbHMgYXMgZ2VvbWV0cnkgdW5pdHMuIFdoZW4gY29uZmlndXJlZCxcbiAqIGEgYGRhdGFQcm9qZWN0aW9uYCB3aXRoIGBUSUxFX1BJWEVMU2AgYXMgYHVuaXRzYCBhbmQgdGhlIHRpbGUncyBwaXhlbCBleHRlbnQgYXMgYGV4dGVudGAgbmVlZHMgdG8gYmVcbiAqIHByb3ZpZGVkLlxuICogQHByb3BlcnR5IHtpbXBvcnQoXCIuLi9wcm9qLmpzXCIpLlByb2plY3Rpb25MaWtlfSBbZmVhdHVyZVByb2plY3Rpb25dIFByb2plY3Rpb24gb2YgdGhlIGZlYXR1cmUgZ2VvbWV0cmllc1xuICogY3JlYXRlZCBieSB0aGUgZm9ybWF0IHJlYWRlci4gSWYgbm90IHByb3ZpZGVkLCBmZWF0dXJlcyB3aWxsIGJlIHJldHVybmVkIGluIHRoZVxuICogYGRhdGFQcm9qZWN0aW9uYC5cbiAqL1xuXG4vKipcbiAqIEB0eXBlZGVmIHtPYmplY3R9IFdyaXRlT3B0aW9uc1xuICogQHByb3BlcnR5IHtpbXBvcnQoXCIuLi9wcm9qLmpzXCIpLlByb2plY3Rpb25MaWtlfSBbZGF0YVByb2plY3Rpb25dIFByb2plY3Rpb24gb2YgdGhlIGRhdGEgd2UgYXJlIHdyaXRpbmcuXG4gKiBJZiBub3QgcHJvdmlkZWQsIHRoZSBgZGF0YVByb2plY3Rpb25gIG9mIHRoZSBmb3JtYXQgaXMgYXNzaWduZWQgKHdoZXJlIHNldCkuXG4gKiBJZiBubyBgZGF0YVByb2plY3Rpb25gIGlzIHNldCBmb3IgYSBmb3JtYXQsIHRoZSBmZWF0dXJlcyB3aWxsIGJlIHJldHVybmVkXG4gKiBpbiB0aGUgYGZlYXR1cmVQcm9qZWN0aW9uYC5cbiAqIEBwcm9wZXJ0eSB7aW1wb3J0KFwiLi4vcHJvai5qc1wiKS5Qcm9qZWN0aW9uTGlrZX0gW2ZlYXR1cmVQcm9qZWN0aW9uXSBQcm9qZWN0aW9uIG9mIHRoZSBmZWF0dXJlIGdlb21ldHJpZXNcbiAqIHRoYXQgd2lsbCBiZSBzZXJpYWxpemVkIGJ5IHRoZSBmb3JtYXQgd3JpdGVyLiBJZiBub3QgcHJvdmlkZWQsIGdlb21ldHJpZXMgYXJlIGFzc3VtZWRcbiAqIHRvIGJlIGluIHRoZSBgZGF0YVByb2plY3Rpb25gIGlmIHRoYXQgaXMgc2V0OyBpbiBvdGhlciB3b3JkcywgdGhleSBhcmUgbm90IHRyYW5zZm9ybWVkLlxuICogQHByb3BlcnR5IHtib29sZWFufSBbcmlnaHRIYW5kZWRdIFdoZW4gd3JpdGluZyBnZW9tZXRyaWVzLCBmb2xsb3cgdGhlIHJpZ2h0LWhhbmRcbiAqIHJ1bGUgZm9yIGxpbmVhciByaW5nIG9yaWVudGF0aW9uLiAgVGhpcyBtZWFucyB0aGF0IHBvbHlnb25zIHdpbGwgaGF2ZSBjb3VudGVyLWNsb2Nrd2lzZVxuICogZXh0ZXJpb3IgcmluZ3MgYW5kIGNsb2Nrd2lzZSBpbnRlcmlvciByaW5ncy4gIEJ5IGRlZmF1bHQsIGNvb3JkaW5hdGVzIGFyZSBzZXJpYWxpemVkXG4gKiBhcyB0aGV5IGFyZSBwcm92aWRlZCBhdCBjb25zdHJ1Y3Rpb24uICBJZiBgdHJ1ZWAsIHRoZSByaWdodC1oYW5kIHJ1bGUgd2lsbFxuICogYmUgYXBwbGllZC4gIElmIGBmYWxzZWAsIHRoZSBsZWZ0LWhhbmQgcnVsZSB3aWxsIGJlIGFwcGxpZWQgKGNsb2Nrd2lzZSBmb3JcbiAqIGV4dGVyaW9yIGFuZCBjb3VudGVyLWNsb2Nrd2lzZSBmb3IgaW50ZXJpb3IgcmluZ3MpLiAgTm90ZSB0aGF0IG5vdCBhbGxcbiAqIGZvcm1hdHMgc3VwcG9ydCB0aGlzLiAgVGhlIEdlb0pTT04gZm9ybWF0IGRvZXMgdXNlIHRoaXMgcHJvcGVydHkgd2hlbiB3cml0aW5nXG4gKiBnZW9tZXRyaWVzLlxuICogQHByb3BlcnR5IHtudW1iZXJ9IFtkZWNpbWFsc10gTWF4aW11bSBudW1iZXIgb2YgZGVjaW1hbCBwbGFjZXMgZm9yIGNvb3JkaW5hdGVzLlxuICogQ29vcmRpbmF0ZXMgYXJlIHN0b3JlZCBpbnRlcm5hbGx5IGFzIGZsb2F0cywgYnV0IGZsb2F0aW5nLXBvaW50IGFyaXRobWV0aWMgY2FuIGNyZWF0ZVxuICogY29vcmRpbmF0ZXMgd2l0aCBhIGxhcmdlIG51bWJlciBvZiBkZWNpbWFsIHBsYWNlcywgbm90IGdlbmVyYWxseSB3YW50ZWQgb24gb3V0cHV0LlxuICogU2V0IGEgbnVtYmVyIGhlcmUgdG8gcm91bmQgY29vcmRpbmF0ZXMuIENhbiBhbHNvIGJlIHVzZWQgdG8gZW5zdXJlIHRoYXRcbiAqIGNvb3JkaW5hdGVzIHJlYWQgaW4gY2FuIGJlIHdyaXR0ZW4gYmFjayBvdXQgd2l0aCB0aGUgc2FtZSBudW1iZXIgb2YgZGVjaW1hbHMuXG4gKiBEZWZhdWx0IGlzIG5vIHJvdW5kaW5nLlxuICovXG5cbi8qKlxuICogQGNsYXNzZGVzY1xuICogQWJzdHJhY3QgYmFzZSBjbGFzczsgbm9ybWFsbHkgb25seSB1c2VkIGZvciBjcmVhdGluZyBzdWJjbGFzc2VzIGFuZCBub3RcbiAqIGluc3RhbnRpYXRlZCBpbiBhcHBzLlxuICogQmFzZSBjbGFzcyBmb3IgZmVhdHVyZSBmb3JtYXRzLlxuICoge0BsaW5rIG1vZHVsZTpvbC9mb3JtYXQvRmVhdHVyZX5GZWF0dXJlRm9ybWF0fSBzdWJjbGFzc2VzIHByb3ZpZGUgdGhlIGFiaWxpdHkgdG8gZGVjb2RlIGFuZCBlbmNvZGVcbiAqIHtAbGluayBtb2R1bGU6b2wvRmVhdHVyZX5GZWF0dXJlfSBvYmplY3RzIGZyb20gYSB2YXJpZXR5IG9mIGNvbW1vbmx5IHVzZWQgZ2Vvc3BhdGlhbFxuICogZmlsZSBmb3JtYXRzLiAgU2VlIHRoZSBkb2N1bWVudGF0aW9uIGZvciBlYWNoIGZvcm1hdCBmb3IgbW9yZSBkZXRhaWxzLlxuICpcbiAqIEBhYnN0cmFjdFxuICogQGFwaVxuICovXG5cbnZhciBGZWF0dXJlRm9ybWF0ID1cbi8qKiBAY2xhc3MgKi9cbmZ1bmN0aW9uICgpIHtcbiAgZnVuY3Rpb24gRmVhdHVyZUZvcm1hdCgpIHtcbiAgICAvKipcbiAgICAgKiBAcHJvdGVjdGVkXG4gICAgICogQHR5cGUge2ltcG9ydChcIi4uL3Byb2ovUHJvamVjdGlvbi5qc1wiKS5kZWZhdWx0fVxuICAgICAqL1xuICAgIHRoaXMuZGF0YVByb2plY3Rpb24gPSBudWxsO1xuICAgIC8qKlxuICAgICAqIEBwcm90ZWN0ZWRcbiAgICAgKiBAdHlwZSB7aW1wb3J0KFwiLi4vcHJvai9Qcm9qZWN0aW9uLmpzXCIpLmRlZmF1bHR9XG4gICAgICovXG5cbiAgICB0aGlzLmRlZmF1bHRGZWF0dXJlUHJvamVjdGlvbiA9IG51bGw7XG4gIH1cbiAgLyoqXG4gICAqIEFkZHMgdGhlIGRhdGEgcHJvamVjdGlvbiB0byB0aGUgcmVhZCBvcHRpb25zLlxuICAgKiBAcGFyYW0ge0RvY3VtZW50fEVsZW1lbnR8T2JqZWN0fHN0cmluZ30gc291cmNlIFNvdXJjZS5cbiAgICogQHBhcmFtIHtSZWFkT3B0aW9ucz19IG9wdF9vcHRpb25zIE9wdGlvbnMuXG4gICAqIEByZXR1cm4ge1JlYWRPcHRpb25zfHVuZGVmaW5lZH0gT3B0aW9ucy5cbiAgICogQHByb3RlY3RlZFxuICAgKi9cblxuXG4gIEZlYXR1cmVGb3JtYXQucHJvdG90eXBlLmdldFJlYWRPcHRpb25zID0gZnVuY3Rpb24gKHNvdXJjZSwgb3B0X29wdGlvbnMpIHtcbiAgICB2YXIgb3B0aW9ucztcblxuICAgIGlmIChvcHRfb3B0aW9ucykge1xuICAgICAgdmFyIGRhdGFQcm9qZWN0aW9uID0gb3B0X29wdGlvbnMuZGF0YVByb2plY3Rpb24gPyBnZXRQcm9qZWN0aW9uKG9wdF9vcHRpb25zLmRhdGFQcm9qZWN0aW9uKSA6IHRoaXMucmVhZFByb2plY3Rpb24oc291cmNlKTtcblxuICAgICAgaWYgKG9wdF9vcHRpb25zLmV4dGVudCAmJiBkYXRhUHJvamVjdGlvbiAmJiBkYXRhUHJvamVjdGlvbi5nZXRVbml0cygpID09PSBVbml0cy5USUxFX1BJWEVMUykge1xuICAgICAgICBkYXRhUHJvamVjdGlvbiA9IGdldFByb2plY3Rpb24oZGF0YVByb2plY3Rpb24pO1xuICAgICAgICBkYXRhUHJvamVjdGlvbi5zZXRXb3JsZEV4dGVudChvcHRfb3B0aW9ucy5leHRlbnQpO1xuICAgICAgfVxuXG4gICAgICBvcHRpb25zID0ge1xuICAgICAgICBkYXRhUHJvamVjdGlvbjogZGF0YVByb2plY3Rpb24sXG4gICAgICAgIGZlYXR1cmVQcm9qZWN0aW9uOiBvcHRfb3B0aW9ucy5mZWF0dXJlUHJvamVjdGlvblxuICAgICAgfTtcbiAgICB9XG5cbiAgICByZXR1cm4gdGhpcy5hZGFwdE9wdGlvbnMob3B0aW9ucyk7XG4gIH07XG4gIC8qKlxuICAgKiBTZXRzIHRoZSBgZGF0YVByb2plY3Rpb25gIG9uIHRoZSBvcHRpb25zLCBpZiBubyBgZGF0YVByb2plY3Rpb25gXG4gICAqIGlzIHNldC5cbiAgICogQHBhcmFtIHtXcml0ZU9wdGlvbnN8UmVhZE9wdGlvbnN8dW5kZWZpbmVkfSBvcHRpb25zXG4gICAqICAgICBPcHRpb25zLlxuICAgKiBAcHJvdGVjdGVkXG4gICAqIEByZXR1cm4ge1dyaXRlT3B0aW9uc3xSZWFkT3B0aW9uc3x1bmRlZmluZWR9XG4gICAqICAgICBVcGRhdGVkIG9wdGlvbnMuXG4gICAqL1xuXG5cbiAgRmVhdHVyZUZvcm1hdC5wcm90b3R5cGUuYWRhcHRPcHRpb25zID0gZnVuY3Rpb24gKG9wdGlvbnMpIHtcbiAgICByZXR1cm4gYXNzaWduKHtcbiAgICAgIGRhdGFQcm9qZWN0aW9uOiB0aGlzLmRhdGFQcm9qZWN0aW9uLFxuICAgICAgZmVhdHVyZVByb2plY3Rpb246IHRoaXMuZGVmYXVsdEZlYXR1cmVQcm9qZWN0aW9uXG4gICAgfSwgb3B0aW9ucyk7XG4gIH07XG4gIC8qKlxuICAgKiBAYWJzdHJhY3RcbiAgICogQHJldHVybiB7aW1wb3J0KFwiLi9Gb3JtYXRUeXBlLmpzXCIpLmRlZmF1bHR9IEZvcm1hdC5cbiAgICovXG5cblxuICBGZWF0dXJlRm9ybWF0LnByb3RvdHlwZS5nZXRUeXBlID0gZnVuY3Rpb24gKCkge1xuICAgIHJldHVybiBhYnN0cmFjdCgpO1xuICB9O1xuICAvKipcbiAgICogUmVhZCBhIHNpbmdsZSBmZWF0dXJlIGZyb20gYSBzb3VyY2UuXG4gICAqXG4gICAqIEBhYnN0cmFjdFxuICAgKiBAcGFyYW0ge0RvY3VtZW50fEVsZW1lbnR8T2JqZWN0fHN0cmluZ30gc291cmNlIFNvdXJjZS5cbiAgICogQHBhcmFtIHtSZWFkT3B0aW9ucz19IG9wdF9vcHRpb25zIFJlYWQgb3B0aW9ucy5cbiAgICogQHJldHVybiB7aW1wb3J0KFwiLi4vRmVhdHVyZS5qc1wiKS5GZWF0dXJlTGlrZX0gRmVhdHVyZS5cbiAgICovXG5cblxuICBGZWF0dXJlRm9ybWF0LnByb3RvdHlwZS5yZWFkRmVhdHVyZSA9IGZ1bmN0aW9uIChzb3VyY2UsIG9wdF9vcHRpb25zKSB7XG4gICAgcmV0dXJuIGFic3RyYWN0KCk7XG4gIH07XG4gIC8qKlxuICAgKiBSZWFkIGFsbCBmZWF0dXJlcyBmcm9tIGEgc291cmNlLlxuICAgKlxuICAgKiBAYWJzdHJhY3RcbiAgICogQHBhcmFtIHtEb2N1bWVudHxFbGVtZW50fEFycmF5QnVmZmVyfE9iamVjdHxzdHJpbmd9IHNvdXJjZSBTb3VyY2UuXG4gICAqIEBwYXJhbSB7UmVhZE9wdGlvbnM9fSBvcHRfb3B0aW9ucyBSZWFkIG9wdGlvbnMuXG4gICAqIEByZXR1cm4ge0FycmF5PGltcG9ydChcIi4uL0ZlYXR1cmUuanNcIikuRmVhdHVyZUxpa2U+fSBGZWF0dXJlcy5cbiAgICovXG5cblxuICBGZWF0dXJlRm9ybWF0LnByb3RvdHlwZS5yZWFkRmVhdHVyZXMgPSBmdW5jdGlvbiAoc291cmNlLCBvcHRfb3B0aW9ucykge1xuICAgIHJldHVybiBhYnN0cmFjdCgpO1xuICB9O1xuICAvKipcbiAgICogUmVhZCBhIHNpbmdsZSBnZW9tZXRyeSBmcm9tIGEgc291cmNlLlxuICAgKlxuICAgKiBAYWJzdHJhY3RcbiAgICogQHBhcmFtIHtEb2N1bWVudHxFbGVtZW50fE9iamVjdHxzdHJpbmd9IHNvdXJjZSBTb3VyY2UuXG4gICAqIEBwYXJhbSB7UmVhZE9wdGlvbnM9fSBvcHRfb3B0aW9ucyBSZWFkIG9wdGlvbnMuXG4gICAqIEByZXR1cm4ge2ltcG9ydChcIi4uL2dlb20vR2VvbWV0cnkuanNcIikuZGVmYXVsdH0gR2VvbWV0cnkuXG4gICAqL1xuXG5cbiAgRmVhdHVyZUZvcm1hdC5wcm90b3R5cGUucmVhZEdlb21ldHJ5ID0gZnVuY3Rpb24gKHNvdXJjZSwgb3B0X29wdGlvbnMpIHtcbiAgICByZXR1cm4gYWJzdHJhY3QoKTtcbiAgfTtcbiAgLyoqXG4gICAqIFJlYWQgdGhlIHByb2plY3Rpb24gZnJvbSBhIHNvdXJjZS5cbiAgICpcbiAgICogQGFic3RyYWN0XG4gICAqIEBwYXJhbSB7RG9jdW1lbnR8RWxlbWVudHxPYmplY3R8c3RyaW5nfSBzb3VyY2UgU291cmNlLlxuICAgKiBAcmV0dXJuIHtpbXBvcnQoXCIuLi9wcm9qL1Byb2plY3Rpb24uanNcIikuZGVmYXVsdH0gUHJvamVjdGlvbi5cbiAgICovXG5cblxuICBGZWF0dXJlRm9ybWF0LnByb3RvdHlwZS5yZWFkUHJvamVjdGlvbiA9IGZ1bmN0aW9uIChzb3VyY2UpIHtcbiAgICByZXR1cm4gYWJzdHJhY3QoKTtcbiAgfTtcbiAgLyoqXG4gICAqIEVuY29kZSBhIGZlYXR1cmUgaW4gdGhpcyBmb3JtYXQuXG4gICAqXG4gICAqIEBhYnN0cmFjdFxuICAgKiBAcGFyYW0ge2ltcG9ydChcIi4uL0ZlYXR1cmUuanNcIikuZGVmYXVsdH0gZmVhdHVyZSBGZWF0dXJlLlxuICAgKiBAcGFyYW0ge1dyaXRlT3B0aW9ucz19IG9wdF9vcHRpb25zIFdyaXRlIG9wdGlvbnMuXG4gICAqIEByZXR1cm4ge3N0cmluZ30gUmVzdWx0LlxuICAgKi9cblxuXG4gIEZlYXR1cmVGb3JtYXQucHJvdG90eXBlLndyaXRlRmVhdHVyZSA9IGZ1bmN0aW9uIChmZWF0dXJlLCBvcHRfb3B0aW9ucykge1xuICAgIHJldHVybiBhYnN0cmFjdCgpO1xuICB9O1xuICAvKipcbiAgICogRW5jb2RlIGFuIGFycmF5IG9mIGZlYXR1cmVzIGluIHRoaXMgZm9ybWF0LlxuICAgKlxuICAgKiBAYWJzdHJhY3RcbiAgICogQHBhcmFtIHtBcnJheTxpbXBvcnQoXCIuLi9GZWF0dXJlLmpzXCIpLmRlZmF1bHQ+fSBmZWF0dXJlcyBGZWF0dXJlcy5cbiAgICogQHBhcmFtIHtXcml0ZU9wdGlvbnM9fSBvcHRfb3B0aW9ucyBXcml0ZSBvcHRpb25zLlxuICAgKiBAcmV0dXJuIHtzdHJpbmd9IFJlc3VsdC5cbiAgICovXG5cblxuICBGZWF0dXJlRm9ybWF0LnByb3RvdHlwZS53cml0ZUZlYXR1cmVzID0gZnVuY3Rpb24gKGZlYXR1cmVzLCBvcHRfb3B0aW9ucykge1xuICAgIHJldHVybiBhYnN0cmFjdCgpO1xuICB9O1xuICAvKipcbiAgICogV3JpdGUgYSBzaW5nbGUgZ2VvbWV0cnkgaW4gdGhpcyBmb3JtYXQuXG4gICAqXG4gICAqIEBhYnN0cmFjdFxuICAgKiBAcGFyYW0ge2ltcG9ydChcIi4uL2dlb20vR2VvbWV0cnkuanNcIikuZGVmYXVsdH0gZ2VvbWV0cnkgR2VvbWV0cnkuXG4gICAqIEBwYXJhbSB7V3JpdGVPcHRpb25zPX0gb3B0X29wdGlvbnMgV3JpdGUgb3B0aW9ucy5cbiAgICogQHJldHVybiB7c3RyaW5nfSBSZXN1bHQuXG4gICAqL1xuXG5cbiAgRmVhdHVyZUZvcm1hdC5wcm90b3R5cGUud3JpdGVHZW9tZXRyeSA9IGZ1bmN0aW9uIChnZW9tZXRyeSwgb3B0X29wdGlvbnMpIHtcbiAgICByZXR1cm4gYWJzdHJhY3QoKTtcbiAgfTtcblxuICByZXR1cm4gRmVhdHVyZUZvcm1hdDtcbn0oKTtcblxuZXhwb3J0IGRlZmF1bHQgRmVhdHVyZUZvcm1hdDtcbi8qKlxuICogQHBhcmFtIHtpbXBvcnQoXCIuLi9nZW9tL0dlb21ldHJ5LmpzXCIpLmRlZmF1bHR9IGdlb21ldHJ5IEdlb21ldHJ5LlxuICogQHBhcmFtIHtib29sZWFufSB3cml0ZSBTZXQgdG8gdHJ1ZSBmb3Igd3JpdGluZywgZmFsc2UgZm9yIHJlYWRpbmcuXG4gKiBAcGFyYW0geyhXcml0ZU9wdGlvbnN8UmVhZE9wdGlvbnMpPX0gb3B0X29wdGlvbnMgT3B0aW9ucy5cbiAqIEByZXR1cm4ge2ltcG9ydChcIi4uL2dlb20vR2VvbWV0cnkuanNcIikuZGVmYXVsdH0gVHJhbnNmb3JtZWQgZ2VvbWV0cnkuXG4gKi9cblxuZXhwb3J0IGZ1bmN0aW9uIHRyYW5zZm9ybUdlb21ldHJ5V2l0aE9wdGlvbnMoZ2VvbWV0cnksIHdyaXRlLCBvcHRfb3B0aW9ucykge1xuICB2YXIgZmVhdHVyZVByb2plY3Rpb24gPSBvcHRfb3B0aW9ucyA/IGdldFByb2plY3Rpb24ob3B0X29wdGlvbnMuZmVhdHVyZVByb2plY3Rpb24pIDogbnVsbDtcbiAgdmFyIGRhdGFQcm9qZWN0aW9uID0gb3B0X29wdGlvbnMgPyBnZXRQcm9qZWN0aW9uKG9wdF9vcHRpb25zLmRhdGFQcm9qZWN0aW9uKSA6IG51bGw7XG4gIHZhciB0cmFuc2Zvcm1lZDtcblxuICBpZiAoZmVhdHVyZVByb2plY3Rpb24gJiYgZGF0YVByb2plY3Rpb24gJiYgIWVxdWl2YWxlbnRQcm9qZWN0aW9uKGZlYXR1cmVQcm9qZWN0aW9uLCBkYXRhUHJvamVjdGlvbikpIHtcbiAgICB0cmFuc2Zvcm1lZCA9ICh3cml0ZSA/IGdlb21ldHJ5LmNsb25lKCkgOiBnZW9tZXRyeSkudHJhbnNmb3JtKHdyaXRlID8gZmVhdHVyZVByb2plY3Rpb24gOiBkYXRhUHJvamVjdGlvbiwgd3JpdGUgPyBkYXRhUHJvamVjdGlvbiA6IGZlYXR1cmVQcm9qZWN0aW9uKTtcbiAgfSBlbHNlIHtcbiAgICB0cmFuc2Zvcm1lZCA9IGdlb21ldHJ5O1xuICB9XG5cbiAgaWYgKHdyaXRlICYmIG9wdF9vcHRpb25zICYmXG4gIC8qKiBAdHlwZSB7V3JpdGVPcHRpb25zfSAqL1xuICBvcHRfb3B0aW9ucy5kZWNpbWFscyAhPT0gdW5kZWZpbmVkKSB7XG4gICAgdmFyIHBvd2VyXzEgPSBNYXRoLnBvdygxMCxcbiAgICAvKiogQHR5cGUge1dyaXRlT3B0aW9uc30gKi9cbiAgICBvcHRfb3B0aW9ucy5kZWNpbWFscyk7IC8vIGlmIGRlY2ltYWxzIG9wdGlvbiBvbiB3cml0ZSwgcm91bmQgZWFjaCBjb29yZGluYXRlIGFwcHJvcHJpYXRlbHlcblxuICAgIC8qKlxuICAgICAqIEBwYXJhbSB7QXJyYXk8bnVtYmVyPn0gY29vcmRpbmF0ZXMgQ29vcmRpbmF0ZXMuXG4gICAgICogQHJldHVybiB7QXJyYXk8bnVtYmVyPn0gVHJhbnNmb3JtZWQgY29vcmRpbmF0ZXMuXG4gICAgICovXG5cbiAgICB2YXIgdHJhbnNmb3JtID0gZnVuY3Rpb24gdHJhbnNmb3JtKGNvb3JkaW5hdGVzKSB7XG4gICAgICBmb3IgKHZhciBpID0gMCwgaWkgPSBjb29yZGluYXRlcy5sZW5ndGg7IGkgPCBpaTsgKytpKSB7XG4gICAgICAgIGNvb3JkaW5hdGVzW2ldID0gTWF0aC5yb3VuZChjb29yZGluYXRlc1tpXSAqIHBvd2VyXzEpIC8gcG93ZXJfMTtcbiAgICAgIH1cblxuICAgICAgcmV0dXJuIGNvb3JkaW5hdGVzO1xuICAgIH07XG5cbiAgICBpZiAodHJhbnNmb3JtZWQgPT09IGdlb21ldHJ5KSB7XG4gICAgICB0cmFuc2Zvcm1lZCA9IGdlb21ldHJ5LmNsb25lKCk7XG4gICAgfVxuXG4gICAgdHJhbnNmb3JtZWQuYXBwbHlUcmFuc2Zvcm0odHJhbnNmb3JtKTtcbiAgfVxuXG4gIHJldHVybiB0cmFuc2Zvcm1lZDtcbn1cbi8qKlxuICogQHBhcmFtIHtpbXBvcnQoXCIuLi9leHRlbnQuanNcIikuRXh0ZW50fSBleHRlbnQgRXh0ZW50LlxuICogQHBhcmFtIHtSZWFkT3B0aW9ucz19IG9wdF9vcHRpb25zIFJlYWQgb3B0aW9ucy5cbiAqIEByZXR1cm4ge2ltcG9ydChcIi4uL2V4dGVudC5qc1wiKS5FeHRlbnR9IFRyYW5zZm9ybWVkIGV4dGVudC5cbiAqL1xuXG5leHBvcnQgZnVuY3Rpb24gdHJhbnNmb3JtRXh0ZW50V2l0aE9wdGlvbnMoZXh0ZW50LCBvcHRfb3B0aW9ucykge1xuICB2YXIgZmVhdHVyZVByb2plY3Rpb24gPSBvcHRfb3B0aW9ucyA/IGdldFByb2plY3Rpb24ob3B0X29wdGlvbnMuZmVhdHVyZVByb2plY3Rpb24pIDogbnVsbDtcbiAgdmFyIGRhdGFQcm9qZWN0aW9uID0gb3B0X29wdGlvbnMgPyBnZXRQcm9qZWN0aW9uKG9wdF9vcHRpb25zLmRhdGFQcm9qZWN0aW9uKSA6IG51bGw7XG5cbiAgaWYgKGZlYXR1cmVQcm9qZWN0aW9uICYmIGRhdGFQcm9qZWN0aW9uICYmICFlcXVpdmFsZW50UHJvamVjdGlvbihmZWF0dXJlUHJvamVjdGlvbiwgZGF0YVByb2plY3Rpb24pKSB7XG4gICAgcmV0dXJuIHRyYW5zZm9ybUV4dGVudChleHRlbnQsIGRhdGFQcm9qZWN0aW9uLCBmZWF0dXJlUHJvamVjdGlvbik7XG4gIH0gZWxzZSB7XG4gICAgcmV0dXJuIGV4dGVudDtcbiAgfVxufSIsIi8qKlxuICogQG1vZHVsZSBvbC9nZW9tL2ZsYXQvaW50ZXJwb2xhdGVcbiAqL1xuaW1wb3J0IHsgYmluYXJ5U2VhcmNoIH0gZnJvbSAnLi4vLi4vYXJyYXkuanMnO1xuaW1wb3J0IHsgbGVycCB9IGZyb20gJy4uLy4uL21hdGguanMnO1xuLyoqXG4gKiBAcGFyYW0ge0FycmF5PG51bWJlcj59IGZsYXRDb29yZGluYXRlcyBGbGF0IGNvb3JkaW5hdGVzLlxuICogQHBhcmFtIHtudW1iZXJ9IG9mZnNldCBPZmZzZXQuXG4gKiBAcGFyYW0ge251bWJlcn0gZW5kIEVuZC5cbiAqIEBwYXJhbSB7bnVtYmVyfSBzdHJpZGUgU3RyaWRlLlxuICogQHBhcmFtIHtudW1iZXJ9IGZyYWN0aW9uIEZyYWN0aW9uLlxuICogQHBhcmFtIHtBcnJheTxudW1iZXI+PX0gb3B0X2Rlc3QgRGVzdGluYXRpb24uXG4gKiBAcGFyYW0ge251bWJlcj19IG9wdF9kaW1lbnNpb24gRGVzdGluYXRpb24gZGltZW5zaW9uIChkZWZhdWx0IGlzIGAyYClcbiAqIEByZXR1cm4ge0FycmF5PG51bWJlcj59IERlc3RpbmF0aW9uLlxuICovXG5cbmV4cG9ydCBmdW5jdGlvbiBpbnRlcnBvbGF0ZVBvaW50KGZsYXRDb29yZGluYXRlcywgb2Zmc2V0LCBlbmQsIHN0cmlkZSwgZnJhY3Rpb24sIG9wdF9kZXN0LCBvcHRfZGltZW5zaW9uKSB7XG4gIHZhciBvLCB0O1xuICB2YXIgbiA9IChlbmQgLSBvZmZzZXQpIC8gc3RyaWRlO1xuXG4gIGlmIChuID09PSAxKSB7XG4gICAgbyA9IG9mZnNldDtcbiAgfSBlbHNlIGlmIChuID09PSAyKSB7XG4gICAgbyA9IG9mZnNldDtcbiAgICB0ID0gZnJhY3Rpb247XG4gIH0gZWxzZSBpZiAobiAhPT0gMCkge1xuICAgIHZhciB4MSA9IGZsYXRDb29yZGluYXRlc1tvZmZzZXRdO1xuICAgIHZhciB5MSA9IGZsYXRDb29yZGluYXRlc1tvZmZzZXQgKyAxXTtcbiAgICB2YXIgbGVuZ3RoXzEgPSAwO1xuICAgIHZhciBjdW11bGF0aXZlTGVuZ3RocyA9IFswXTtcblxuICAgIGZvciAodmFyIGkgPSBvZmZzZXQgKyBzdHJpZGU7IGkgPCBlbmQ7IGkgKz0gc3RyaWRlKSB7XG4gICAgICB2YXIgeDIgPSBmbGF0Q29vcmRpbmF0ZXNbaV07XG4gICAgICB2YXIgeTIgPSBmbGF0Q29vcmRpbmF0ZXNbaSArIDFdO1xuICAgICAgbGVuZ3RoXzEgKz0gTWF0aC5zcXJ0KCh4MiAtIHgxKSAqICh4MiAtIHgxKSArICh5MiAtIHkxKSAqICh5MiAtIHkxKSk7XG4gICAgICBjdW11bGF0aXZlTGVuZ3Rocy5wdXNoKGxlbmd0aF8xKTtcbiAgICAgIHgxID0geDI7XG4gICAgICB5MSA9IHkyO1xuICAgIH1cblxuICAgIHZhciB0YXJnZXQgPSBmcmFjdGlvbiAqIGxlbmd0aF8xO1xuICAgIHZhciBpbmRleCA9IGJpbmFyeVNlYXJjaChjdW11bGF0aXZlTGVuZ3RocywgdGFyZ2V0KTtcblxuICAgIGlmIChpbmRleCA8IDApIHtcbiAgICAgIHQgPSAodGFyZ2V0IC0gY3VtdWxhdGl2ZUxlbmd0aHNbLWluZGV4IC0gMl0pIC8gKGN1bXVsYXRpdmVMZW5ndGhzWy1pbmRleCAtIDFdIC0gY3VtdWxhdGl2ZUxlbmd0aHNbLWluZGV4IC0gMl0pO1xuICAgICAgbyA9IG9mZnNldCArICgtaW5kZXggLSAyKSAqIHN0cmlkZTtcbiAgICB9IGVsc2Uge1xuICAgICAgbyA9IG9mZnNldCArIGluZGV4ICogc3RyaWRlO1xuICAgIH1cbiAgfVxuXG4gIHZhciBkaW1lbnNpb24gPSBvcHRfZGltZW5zaW9uID4gMSA/IG9wdF9kaW1lbnNpb24gOiAyO1xuICB2YXIgZGVzdCA9IG9wdF9kZXN0ID8gb3B0X2Rlc3QgOiBuZXcgQXJyYXkoZGltZW5zaW9uKTtcblxuICBmb3IgKHZhciBpID0gMDsgaSA8IGRpbWVuc2lvbjsgKytpKSB7XG4gICAgZGVzdFtpXSA9IG8gPT09IHVuZGVmaW5lZCA/IE5hTiA6IHQgPT09IHVuZGVmaW5lZCA/IGZsYXRDb29yZGluYXRlc1tvICsgaV0gOiBsZXJwKGZsYXRDb29yZGluYXRlc1tvICsgaV0sIGZsYXRDb29yZGluYXRlc1tvICsgc3RyaWRlICsgaV0sIHQpO1xuICB9XG5cbiAgcmV0dXJuIGRlc3Q7XG59XG4vKipcbiAqIEBwYXJhbSB7QXJyYXk8bnVtYmVyPn0gZmxhdENvb3JkaW5hdGVzIEZsYXQgY29vcmRpbmF0ZXMuXG4gKiBAcGFyYW0ge251bWJlcn0gb2Zmc2V0IE9mZnNldC5cbiAqIEBwYXJhbSB7bnVtYmVyfSBlbmQgRW5kLlxuICogQHBhcmFtIHtudW1iZXJ9IHN0cmlkZSBTdHJpZGUuXG4gKiBAcGFyYW0ge251bWJlcn0gbSBNLlxuICogQHBhcmFtIHtib29sZWFufSBleHRyYXBvbGF0ZSBFeHRyYXBvbGF0ZS5cbiAqIEByZXR1cm4ge2ltcG9ydChcIi4uLy4uL2Nvb3JkaW5hdGUuanNcIikuQ29vcmRpbmF0ZX0gQ29vcmRpbmF0ZS5cbiAqL1xuXG5leHBvcnQgZnVuY3Rpb24gbGluZVN0cmluZ0Nvb3JkaW5hdGVBdE0oZmxhdENvb3JkaW5hdGVzLCBvZmZzZXQsIGVuZCwgc3RyaWRlLCBtLCBleHRyYXBvbGF0ZSkge1xuICBpZiAoZW5kID09IG9mZnNldCkge1xuICAgIHJldHVybiBudWxsO1xuICB9XG5cbiAgdmFyIGNvb3JkaW5hdGU7XG5cbiAgaWYgKG0gPCBmbGF0Q29vcmRpbmF0ZXNbb2Zmc2V0ICsgc3RyaWRlIC0gMV0pIHtcbiAgICBpZiAoZXh0cmFwb2xhdGUpIHtcbiAgICAgIGNvb3JkaW5hdGUgPSBmbGF0Q29vcmRpbmF0ZXMuc2xpY2Uob2Zmc2V0LCBvZmZzZXQgKyBzdHJpZGUpO1xuICAgICAgY29vcmRpbmF0ZVtzdHJpZGUgLSAxXSA9IG07XG4gICAgICByZXR1cm4gY29vcmRpbmF0ZTtcbiAgICB9IGVsc2Uge1xuICAgICAgcmV0dXJuIG51bGw7XG4gICAgfVxuICB9IGVsc2UgaWYgKGZsYXRDb29yZGluYXRlc1tlbmQgLSAxXSA8IG0pIHtcbiAgICBpZiAoZXh0cmFwb2xhdGUpIHtcbiAgICAgIGNvb3JkaW5hdGUgPSBmbGF0Q29vcmRpbmF0ZXMuc2xpY2UoZW5kIC0gc3RyaWRlLCBlbmQpO1xuICAgICAgY29vcmRpbmF0ZVtzdHJpZGUgLSAxXSA9IG07XG4gICAgICByZXR1cm4gY29vcmRpbmF0ZTtcbiAgICB9IGVsc2Uge1xuICAgICAgcmV0dXJuIG51bGw7XG4gICAgfVxuICB9IC8vIEZJWE1FIHVzZSBPKDEpIHNlYXJjaFxuXG5cbiAgaWYgKG0gPT0gZmxhdENvb3JkaW5hdGVzW29mZnNldCArIHN0cmlkZSAtIDFdKSB7XG4gICAgcmV0dXJuIGZsYXRDb29yZGluYXRlcy5zbGljZShvZmZzZXQsIG9mZnNldCArIHN0cmlkZSk7XG4gIH1cblxuICB2YXIgbG8gPSBvZmZzZXQgLyBzdHJpZGU7XG4gIHZhciBoaSA9IGVuZCAvIHN0cmlkZTtcblxuICB3aGlsZSAobG8gPCBoaSkge1xuICAgIHZhciBtaWQgPSBsbyArIGhpID4+IDE7XG5cbiAgICBpZiAobSA8IGZsYXRDb29yZGluYXRlc1sobWlkICsgMSkgKiBzdHJpZGUgLSAxXSkge1xuICAgICAgaGkgPSBtaWQ7XG4gICAgfSBlbHNlIHtcbiAgICAgIGxvID0gbWlkICsgMTtcbiAgICB9XG4gIH1cblxuICB2YXIgbTAgPSBmbGF0Q29vcmRpbmF0ZXNbbG8gKiBzdHJpZGUgLSAxXTtcblxuICBpZiAobSA9PSBtMCkge1xuICAgIHJldHVybiBmbGF0Q29vcmRpbmF0ZXMuc2xpY2UoKGxvIC0gMSkgKiBzdHJpZGUsIChsbyAtIDEpICogc3RyaWRlICsgc3RyaWRlKTtcbiAgfVxuXG4gIHZhciBtMSA9IGZsYXRDb29yZGluYXRlc1sobG8gKyAxKSAqIHN0cmlkZSAtIDFdO1xuICB2YXIgdCA9IChtIC0gbTApIC8gKG0xIC0gbTApO1xuICBjb29yZGluYXRlID0gW107XG5cbiAgZm9yICh2YXIgaSA9IDA7IGkgPCBzdHJpZGUgLSAxOyArK2kpIHtcbiAgICBjb29yZGluYXRlLnB1c2gobGVycChmbGF0Q29vcmRpbmF0ZXNbKGxvIC0gMSkgKiBzdHJpZGUgKyBpXSwgZmxhdENvb3JkaW5hdGVzW2xvICogc3RyaWRlICsgaV0sIHQpKTtcbiAgfVxuXG4gIGNvb3JkaW5hdGUucHVzaChtKTtcbiAgcmV0dXJuIGNvb3JkaW5hdGU7XG59XG4vKipcbiAqIEBwYXJhbSB7QXJyYXk8bnVtYmVyPn0gZmxhdENvb3JkaW5hdGVzIEZsYXQgY29vcmRpbmF0ZXMuXG4gKiBAcGFyYW0ge251bWJlcn0gb2Zmc2V0IE9mZnNldC5cbiAqIEBwYXJhbSB7QXJyYXk8bnVtYmVyPn0gZW5kcyBFbmRzLlxuICogQHBhcmFtIHtudW1iZXJ9IHN0cmlkZSBTdHJpZGUuXG4gKiBAcGFyYW0ge251bWJlcn0gbSBNLlxuICogQHBhcmFtIHtib29sZWFufSBleHRyYXBvbGF0ZSBFeHRyYXBvbGF0ZS5cbiAqIEBwYXJhbSB7Ym9vbGVhbn0gaW50ZXJwb2xhdGUgSW50ZXJwb2xhdGUuXG4gKiBAcmV0dXJuIHtpbXBvcnQoXCIuLi8uLi9jb29yZGluYXRlLmpzXCIpLkNvb3JkaW5hdGV9IENvb3JkaW5hdGUuXG4gKi9cblxuZXhwb3J0IGZ1bmN0aW9uIGxpbmVTdHJpbmdzQ29vcmRpbmF0ZUF0TShmbGF0Q29vcmRpbmF0ZXMsIG9mZnNldCwgZW5kcywgc3RyaWRlLCBtLCBleHRyYXBvbGF0ZSwgaW50ZXJwb2xhdGUpIHtcbiAgaWYgKGludGVycG9sYXRlKSB7XG4gICAgcmV0dXJuIGxpbmVTdHJpbmdDb29yZGluYXRlQXRNKGZsYXRDb29yZGluYXRlcywgb2Zmc2V0LCBlbmRzW2VuZHMubGVuZ3RoIC0gMV0sIHN0cmlkZSwgbSwgZXh0cmFwb2xhdGUpO1xuICB9XG5cbiAgdmFyIGNvb3JkaW5hdGU7XG5cbiAgaWYgKG0gPCBmbGF0Q29vcmRpbmF0ZXNbc3RyaWRlIC0gMV0pIHtcbiAgICBpZiAoZXh0cmFwb2xhdGUpIHtcbiAgICAgIGNvb3JkaW5hdGUgPSBmbGF0Q29vcmRpbmF0ZXMuc2xpY2UoMCwgc3RyaWRlKTtcbiAgICAgIGNvb3JkaW5hdGVbc3RyaWRlIC0gMV0gPSBtO1xuICAgICAgcmV0dXJuIGNvb3JkaW5hdGU7XG4gICAgfSBlbHNlIHtcbiAgICAgIHJldHVybiBudWxsO1xuICAgIH1cbiAgfVxuXG4gIGlmIChmbGF0Q29vcmRpbmF0ZXNbZmxhdENvb3JkaW5hdGVzLmxlbmd0aCAtIDFdIDwgbSkge1xuICAgIGlmIChleHRyYXBvbGF0ZSkge1xuICAgICAgY29vcmRpbmF0ZSA9IGZsYXRDb29yZGluYXRlcy5zbGljZShmbGF0Q29vcmRpbmF0ZXMubGVuZ3RoIC0gc3RyaWRlKTtcbiAgICAgIGNvb3JkaW5hdGVbc3RyaWRlIC0gMV0gPSBtO1xuICAgICAgcmV0dXJuIGNvb3JkaW5hdGU7XG4gICAgfSBlbHNlIHtcbiAgICAgIHJldHVybiBudWxsO1xuICAgIH1cbiAgfVxuXG4gIGZvciAodmFyIGkgPSAwLCBpaSA9IGVuZHMubGVuZ3RoOyBpIDwgaWk7ICsraSkge1xuICAgIHZhciBlbmQgPSBlbmRzW2ldO1xuXG4gICAgaWYgKG9mZnNldCA9PSBlbmQpIHtcbiAgICAgIGNvbnRpbnVlO1xuICAgIH1cblxuICAgIGlmIChtIDwgZmxhdENvb3JkaW5hdGVzW29mZnNldCArIHN0cmlkZSAtIDFdKSB7XG4gICAgICByZXR1cm4gbnVsbDtcbiAgICB9IGVsc2UgaWYgKG0gPD0gZmxhdENvb3JkaW5hdGVzW2VuZCAtIDFdKSB7XG4gICAgICByZXR1cm4gbGluZVN0cmluZ0Nvb3JkaW5hdGVBdE0oZmxhdENvb3JkaW5hdGVzLCBvZmZzZXQsIGVuZCwgc3RyaWRlLCBtLCBmYWxzZSk7XG4gICAgfVxuXG4gICAgb2Zmc2V0ID0gZW5kO1xuICB9XG5cbiAgcmV0dXJuIG51bGw7XG59IiwidmFyIF9fZXh0ZW5kcyA9IHRoaXMgJiYgdGhpcy5fX2V4dGVuZHMgfHwgZnVuY3Rpb24gKCkge1xuICB2YXIgX2V4dGVuZFN0YXRpY3MgPSBmdW5jdGlvbiBleHRlbmRTdGF0aWNzKGQsIGIpIHtcbiAgICBfZXh0ZW5kU3RhdGljcyA9IE9iamVjdC5zZXRQcm90b3R5cGVPZiB8fCB7XG4gICAgICBfX3Byb3RvX186IFtdXG4gICAgfSBpbnN0YW5jZW9mIEFycmF5ICYmIGZ1bmN0aW9uIChkLCBiKSB7XG4gICAgICBkLl9fcHJvdG9fXyA9IGI7XG4gICAgfSB8fCBmdW5jdGlvbiAoZCwgYikge1xuICAgICAgZm9yICh2YXIgcCBpbiBiKSB7XG4gICAgICAgIGlmIChPYmplY3QucHJvdG90eXBlLmhhc093blByb3BlcnR5LmNhbGwoYiwgcCkpIGRbcF0gPSBiW3BdO1xuICAgICAgfVxuICAgIH07XG5cbiAgICByZXR1cm4gX2V4dGVuZFN0YXRpY3MoZCwgYik7XG4gIH07XG5cbiAgcmV0dXJuIGZ1bmN0aW9uIChkLCBiKSB7XG4gICAgX2V4dGVuZFN0YXRpY3MoZCwgYik7XG5cbiAgICBmdW5jdGlvbiBfXygpIHtcbiAgICAgIHRoaXMuY29uc3RydWN0b3IgPSBkO1xuICAgIH1cblxuICAgIGQucHJvdG90eXBlID0gYiA9PT0gbnVsbCA/IE9iamVjdC5jcmVhdGUoYikgOiAoX18ucHJvdG90eXBlID0gYi5wcm90b3R5cGUsIG5ldyBfXygpKTtcbiAgfTtcbn0oKTtcbi8qKlxuICogQG1vZHVsZSBvbC9nZW9tL0xpbmVTdHJpbmdcbiAqL1xuXG5cbmltcG9ydCBHZW9tZXRyeUxheW91dCBmcm9tICcuL0dlb21ldHJ5TGF5b3V0LmpzJztcbmltcG9ydCBHZW9tZXRyeVR5cGUgZnJvbSAnLi9HZW9tZXRyeVR5cGUuanMnO1xuaW1wb3J0IFNpbXBsZUdlb21ldHJ5IGZyb20gJy4vU2ltcGxlR2VvbWV0cnkuanMnO1xuaW1wb3J0IHsgYXNzaWduQ2xvc2VzdFBvaW50LCBtYXhTcXVhcmVkRGVsdGEgfSBmcm9tICcuL2ZsYXQvY2xvc2VzdC5qcyc7XG5pbXBvcnQgeyBjbG9zZXN0U3F1YXJlZERpc3RhbmNlWFkgfSBmcm9tICcuLi9leHRlbnQuanMnO1xuaW1wb3J0IHsgZGVmbGF0ZUNvb3JkaW5hdGVzIH0gZnJvbSAnLi9mbGF0L2RlZmxhdGUuanMnO1xuaW1wb3J0IHsgZG91Z2xhc1BldWNrZXIgfSBmcm9tICcuL2ZsYXQvc2ltcGxpZnkuanMnO1xuaW1wb3J0IHsgZXh0ZW5kIH0gZnJvbSAnLi4vYXJyYXkuanMnO1xuaW1wb3J0IHsgZm9yRWFjaCBhcyBmb3JFYWNoU2VnbWVudCB9IGZyb20gJy4vZmxhdC9zZWdtZW50cy5qcyc7XG5pbXBvcnQgeyBpbmZsYXRlQ29vcmRpbmF0ZXMgfSBmcm9tICcuL2ZsYXQvaW5mbGF0ZS5qcyc7XG5pbXBvcnQgeyBpbnRlcnBvbGF0ZVBvaW50LCBsaW5lU3RyaW5nQ29vcmRpbmF0ZUF0TSB9IGZyb20gJy4vZmxhdC9pbnRlcnBvbGF0ZS5qcyc7XG5pbXBvcnQgeyBpbnRlcnNlY3RzTGluZVN0cmluZyB9IGZyb20gJy4vZmxhdC9pbnRlcnNlY3RzZXh0ZW50LmpzJztcbmltcG9ydCB7IGxpbmVTdHJpbmdMZW5ndGggfSBmcm9tICcuL2ZsYXQvbGVuZ3RoLmpzJztcbi8qKlxuICogQGNsYXNzZGVzY1xuICogTGluZXN0cmluZyBnZW9tZXRyeS5cbiAqXG4gKiBAYXBpXG4gKi9cblxudmFyIExpbmVTdHJpbmcgPVxuLyoqIEBjbGFzcyAqL1xuZnVuY3Rpb24gKF9zdXBlcikge1xuICBfX2V4dGVuZHMoTGluZVN0cmluZywgX3N1cGVyKTtcbiAgLyoqXG4gICAqIEBwYXJhbSB7QXJyYXk8aW1wb3J0KFwiLi4vY29vcmRpbmF0ZS5qc1wiKS5Db29yZGluYXRlPnxBcnJheTxudW1iZXI+fSBjb29yZGluYXRlcyBDb29yZGluYXRlcy5cbiAgICogICAgIEZvciBpbnRlcm5hbCB1c2UsIGZsYXQgY29vcmRpbmF0ZXMgaW4gY29tYmluYXRpb24gd2l0aCBgb3B0X2xheW91dGAgYXJlIGFsc28gYWNjZXB0ZWQuXG4gICAqIEBwYXJhbSB7aW1wb3J0KFwiLi9HZW9tZXRyeUxheW91dC5qc1wiKS5kZWZhdWx0PX0gb3B0X2xheW91dCBMYXlvdXQuXG4gICAqL1xuXG5cbiAgZnVuY3Rpb24gTGluZVN0cmluZyhjb29yZGluYXRlcywgb3B0X2xheW91dCkge1xuICAgIHZhciBfdGhpcyA9IF9zdXBlci5jYWxsKHRoaXMpIHx8IHRoaXM7XG4gICAgLyoqXG4gICAgICogQHByaXZhdGVcbiAgICAgKiBAdHlwZSB7aW1wb3J0KFwiLi4vY29vcmRpbmF0ZS5qc1wiKS5Db29yZGluYXRlfVxuICAgICAqL1xuXG5cbiAgICBfdGhpcy5mbGF0TWlkcG9pbnRfID0gbnVsbDtcbiAgICAvKipcbiAgICAgKiBAcHJpdmF0ZVxuICAgICAqIEB0eXBlIHtudW1iZXJ9XG4gICAgICovXG5cbiAgICBfdGhpcy5mbGF0TWlkcG9pbnRSZXZpc2lvbl8gPSAtMTtcbiAgICAvKipcbiAgICAgKiBAcHJpdmF0ZVxuICAgICAqIEB0eXBlIHtudW1iZXJ9XG4gICAgICovXG5cbiAgICBfdGhpcy5tYXhEZWx0YV8gPSAtMTtcbiAgICAvKipcbiAgICAgKiBAcHJpdmF0ZVxuICAgICAqIEB0eXBlIHtudW1iZXJ9XG4gICAgICovXG5cbiAgICBfdGhpcy5tYXhEZWx0YVJldmlzaW9uXyA9IC0xO1xuXG4gICAgaWYgKG9wdF9sYXlvdXQgIT09IHVuZGVmaW5lZCAmJiAhQXJyYXkuaXNBcnJheShjb29yZGluYXRlc1swXSkpIHtcbiAgICAgIF90aGlzLnNldEZsYXRDb29yZGluYXRlcyhvcHRfbGF5b3V0LFxuICAgICAgLyoqIEB0eXBlIHtBcnJheTxudW1iZXI+fSAqL1xuICAgICAgY29vcmRpbmF0ZXMpO1xuICAgIH0gZWxzZSB7XG4gICAgICBfdGhpcy5zZXRDb29yZGluYXRlcyhcbiAgICAgIC8qKiBAdHlwZSB7QXJyYXk8aW1wb3J0KFwiLi4vY29vcmRpbmF0ZS5qc1wiKS5Db29yZGluYXRlPn0gKi9cbiAgICAgIGNvb3JkaW5hdGVzLCBvcHRfbGF5b3V0KTtcbiAgICB9XG5cbiAgICByZXR1cm4gX3RoaXM7XG4gIH1cbiAgLyoqXG4gICAqIEFwcGVuZCB0aGUgcGFzc2VkIGNvb3JkaW5hdGUgdG8gdGhlIGNvb3JkaW5hdGVzIG9mIHRoZSBsaW5lc3RyaW5nLlxuICAgKiBAcGFyYW0ge2ltcG9ydChcIi4uL2Nvb3JkaW5hdGUuanNcIikuQ29vcmRpbmF0ZX0gY29vcmRpbmF0ZSBDb29yZGluYXRlLlxuICAgKiBAYXBpXG4gICAqL1xuXG5cbiAgTGluZVN0cmluZy5wcm90b3R5cGUuYXBwZW5kQ29vcmRpbmF0ZSA9IGZ1bmN0aW9uIChjb29yZGluYXRlKSB7XG4gICAgaWYgKCF0aGlzLmZsYXRDb29yZGluYXRlcykge1xuICAgICAgdGhpcy5mbGF0Q29vcmRpbmF0ZXMgPSBjb29yZGluYXRlLnNsaWNlKCk7XG4gICAgfSBlbHNlIHtcbiAgICAgIGV4dGVuZCh0aGlzLmZsYXRDb29yZGluYXRlcywgY29vcmRpbmF0ZSk7XG4gICAgfVxuXG4gICAgdGhpcy5jaGFuZ2VkKCk7XG4gIH07XG4gIC8qKlxuICAgKiBNYWtlIGEgY29tcGxldGUgY29weSBvZiB0aGUgZ2VvbWV0cnkuXG4gICAqIEByZXR1cm4geyFMaW5lU3RyaW5nfSBDbG9uZS5cbiAgICogQGFwaVxuICAgKi9cblxuXG4gIExpbmVTdHJpbmcucHJvdG90eXBlLmNsb25lID0gZnVuY3Rpb24gKCkge1xuICAgIHZhciBsaW5lU3RyaW5nID0gbmV3IExpbmVTdHJpbmcodGhpcy5mbGF0Q29vcmRpbmF0ZXMuc2xpY2UoKSwgdGhpcy5sYXlvdXQpO1xuICAgIGxpbmVTdHJpbmcuYXBwbHlQcm9wZXJ0aWVzKHRoaXMpO1xuICAgIHJldHVybiBsaW5lU3RyaW5nO1xuICB9O1xuICAvKipcbiAgICogQHBhcmFtIHtudW1iZXJ9IHggWC5cbiAgICogQHBhcmFtIHtudW1iZXJ9IHkgWS5cbiAgICogQHBhcmFtIHtpbXBvcnQoXCIuLi9jb29yZGluYXRlLmpzXCIpLkNvb3JkaW5hdGV9IGNsb3Nlc3RQb2ludCBDbG9zZXN0IHBvaW50LlxuICAgKiBAcGFyYW0ge251bWJlcn0gbWluU3F1YXJlZERpc3RhbmNlIE1pbmltdW0gc3F1YXJlZCBkaXN0YW5jZS5cbiAgICogQHJldHVybiB7bnVtYmVyfSBNaW5pbXVtIHNxdWFyZWQgZGlzdGFuY2UuXG4gICAqL1xuXG5cbiAgTGluZVN0cmluZy5wcm90b3R5cGUuY2xvc2VzdFBvaW50WFkgPSBmdW5jdGlvbiAoeCwgeSwgY2xvc2VzdFBvaW50LCBtaW5TcXVhcmVkRGlzdGFuY2UpIHtcbiAgICBpZiAobWluU3F1YXJlZERpc3RhbmNlIDwgY2xvc2VzdFNxdWFyZWREaXN0YW5jZVhZKHRoaXMuZ2V0RXh0ZW50KCksIHgsIHkpKSB7XG4gICAgICByZXR1cm4gbWluU3F1YXJlZERpc3RhbmNlO1xuICAgIH1cblxuICAgIGlmICh0aGlzLm1heERlbHRhUmV2aXNpb25fICE9IHRoaXMuZ2V0UmV2aXNpb24oKSkge1xuICAgICAgdGhpcy5tYXhEZWx0YV8gPSBNYXRoLnNxcnQobWF4U3F1YXJlZERlbHRhKHRoaXMuZmxhdENvb3JkaW5hdGVzLCAwLCB0aGlzLmZsYXRDb29yZGluYXRlcy5sZW5ndGgsIHRoaXMuc3RyaWRlLCAwKSk7XG4gICAgICB0aGlzLm1heERlbHRhUmV2aXNpb25fID0gdGhpcy5nZXRSZXZpc2lvbigpO1xuICAgIH1cblxuICAgIHJldHVybiBhc3NpZ25DbG9zZXN0UG9pbnQodGhpcy5mbGF0Q29vcmRpbmF0ZXMsIDAsIHRoaXMuZmxhdENvb3JkaW5hdGVzLmxlbmd0aCwgdGhpcy5zdHJpZGUsIHRoaXMubWF4RGVsdGFfLCBmYWxzZSwgeCwgeSwgY2xvc2VzdFBvaW50LCBtaW5TcXVhcmVkRGlzdGFuY2UpO1xuICB9O1xuICAvKipcbiAgICogSXRlcmF0ZSBvdmVyIGVhY2ggc2VnbWVudCwgY2FsbGluZyB0aGUgcHJvdmlkZWQgY2FsbGJhY2suXG4gICAqIElmIHRoZSBjYWxsYmFjayByZXR1cm5zIGEgdHJ1dGh5IHZhbHVlIHRoZSBmdW5jdGlvbiByZXR1cm5zIHRoYXRcbiAgICogdmFsdWUgaW1tZWRpYXRlbHkuIE90aGVyd2lzZSB0aGUgZnVuY3Rpb24gcmV0dXJucyBgZmFsc2VgLlxuICAgKlxuICAgKiBAcGFyYW0ge2Z1bmN0aW9uKHRoaXM6IFMsIGltcG9ydChcIi4uL2Nvb3JkaW5hdGUuanNcIikuQ29vcmRpbmF0ZSwgaW1wb3J0KFwiLi4vY29vcmRpbmF0ZS5qc1wiKS5Db29yZGluYXRlKTogVH0gY2FsbGJhY2sgRnVuY3Rpb25cbiAgICogICAgIGNhbGxlZCBmb3IgZWFjaCBzZWdtZW50LiBUaGUgZnVuY3Rpb24gd2lsbCByZWNlaXZlIHR3byBhcmd1bWVudHMsIHRoZSBzdGFydCBhbmQgZW5kIGNvb3JkaW5hdGVzIG9mIHRoZSBzZWdtZW50LlxuICAgKiBAcmV0dXJuIHtUfGJvb2xlYW59IFZhbHVlLlxuICAgKiBAdGVtcGxhdGUgVCxTXG4gICAqIEBhcGlcbiAgICovXG5cblxuICBMaW5lU3RyaW5nLnByb3RvdHlwZS5mb3JFYWNoU2VnbWVudCA9IGZ1bmN0aW9uIChjYWxsYmFjaykge1xuICAgIHJldHVybiBmb3JFYWNoU2VnbWVudCh0aGlzLmZsYXRDb29yZGluYXRlcywgMCwgdGhpcy5mbGF0Q29vcmRpbmF0ZXMubGVuZ3RoLCB0aGlzLnN0cmlkZSwgY2FsbGJhY2spO1xuICB9O1xuICAvKipcbiAgICogUmV0dXJucyB0aGUgY29vcmRpbmF0ZSBhdCBgbWAgdXNpbmcgbGluZWFyIGludGVycG9sYXRpb24sIG9yIGBudWxsYCBpZiBub1xuICAgKiBzdWNoIGNvb3JkaW5hdGUgZXhpc3RzLlxuICAgKlxuICAgKiBgb3B0X2V4dHJhcG9sYXRlYCBjb250cm9scyBleHRyYXBvbGF0aW9uIGJleW9uZCB0aGUgcmFuZ2Ugb2YgTXMgaW4gdGhlXG4gICAqIE11bHRpTGluZVN0cmluZy4gSWYgYG9wdF9leHRyYXBvbGF0ZWAgaXMgYHRydWVgIHRoZW4gTXMgbGVzcyB0aGFuIHRoZSBmaXJzdFxuICAgKiBNIHdpbGwgcmV0dXJuIHRoZSBmaXJzdCBjb29yZGluYXRlIGFuZCBNcyBncmVhdGVyIHRoYW4gdGhlIGxhc3QgTSB3aWxsXG4gICAqIHJldHVybiB0aGUgbGFzdCBjb29yZGluYXRlLlxuICAgKlxuICAgKiBAcGFyYW0ge251bWJlcn0gbSBNLlxuICAgKiBAcGFyYW0ge2Jvb2xlYW49fSBvcHRfZXh0cmFwb2xhdGUgRXh0cmFwb2xhdGUuIERlZmF1bHQgaXMgYGZhbHNlYC5cbiAgICogQHJldHVybiB7aW1wb3J0KFwiLi4vY29vcmRpbmF0ZS5qc1wiKS5Db29yZGluYXRlfSBDb29yZGluYXRlLlxuICAgKiBAYXBpXG4gICAqL1xuXG5cbiAgTGluZVN0cmluZy5wcm90b3R5cGUuZ2V0Q29vcmRpbmF0ZUF0TSA9IGZ1bmN0aW9uIChtLCBvcHRfZXh0cmFwb2xhdGUpIHtcbiAgICBpZiAodGhpcy5sYXlvdXQgIT0gR2VvbWV0cnlMYXlvdXQuWFlNICYmIHRoaXMubGF5b3V0ICE9IEdlb21ldHJ5TGF5b3V0LlhZWk0pIHtcbiAgICAgIHJldHVybiBudWxsO1xuICAgIH1cblxuICAgIHZhciBleHRyYXBvbGF0ZSA9IG9wdF9leHRyYXBvbGF0ZSAhPT0gdW5kZWZpbmVkID8gb3B0X2V4dHJhcG9sYXRlIDogZmFsc2U7XG4gICAgcmV0dXJuIGxpbmVTdHJpbmdDb29yZGluYXRlQXRNKHRoaXMuZmxhdENvb3JkaW5hdGVzLCAwLCB0aGlzLmZsYXRDb29yZGluYXRlcy5sZW5ndGgsIHRoaXMuc3RyaWRlLCBtLCBleHRyYXBvbGF0ZSk7XG4gIH07XG4gIC8qKlxuICAgKiBSZXR1cm4gdGhlIGNvb3JkaW5hdGVzIG9mIHRoZSBsaW5lc3RyaW5nLlxuICAgKiBAcmV0dXJuIHtBcnJheTxpbXBvcnQoXCIuLi9jb29yZGluYXRlLmpzXCIpLkNvb3JkaW5hdGU+fSBDb29yZGluYXRlcy5cbiAgICogQGFwaVxuICAgKi9cblxuXG4gIExpbmVTdHJpbmcucHJvdG90eXBlLmdldENvb3JkaW5hdGVzID0gZnVuY3Rpb24gKCkge1xuICAgIHJldHVybiBpbmZsYXRlQ29vcmRpbmF0ZXModGhpcy5mbGF0Q29vcmRpbmF0ZXMsIDAsIHRoaXMuZmxhdENvb3JkaW5hdGVzLmxlbmd0aCwgdGhpcy5zdHJpZGUpO1xuICB9O1xuICAvKipcbiAgICogUmV0dXJuIHRoZSBjb29yZGluYXRlIGF0IHRoZSBwcm92aWRlZCBmcmFjdGlvbiBhbG9uZyB0aGUgbGluZXN0cmluZy5cbiAgICogVGhlIGBmcmFjdGlvbmAgaXMgYSBudW1iZXIgYmV0d2VlbiAwIGFuZCAxLCB3aGVyZSAwIGlzIHRoZSBzdGFydCBvZiB0aGVcbiAgICogbGluZXN0cmluZyBhbmQgMSBpcyB0aGUgZW5kLlxuICAgKiBAcGFyYW0ge251bWJlcn0gZnJhY3Rpb24gRnJhY3Rpb24uXG4gICAqIEBwYXJhbSB7aW1wb3J0KFwiLi4vY29vcmRpbmF0ZS5qc1wiKS5Db29yZGluYXRlPX0gb3B0X2Rlc3QgT3B0aW9uYWwgY29vcmRpbmF0ZSB3aG9zZSB2YWx1ZXMgd2lsbFxuICAgKiAgICAgYmUgbW9kaWZpZWQuIElmIG5vdCBwcm92aWRlZCwgYSBuZXcgY29vcmRpbmF0ZSB3aWxsIGJlIHJldHVybmVkLlxuICAgKiBAcmV0dXJuIHtpbXBvcnQoXCIuLi9jb29yZGluYXRlLmpzXCIpLkNvb3JkaW5hdGV9IENvb3JkaW5hdGUgb2YgdGhlIGludGVycG9sYXRlZCBwb2ludC5cbiAgICogQGFwaVxuICAgKi9cblxuXG4gIExpbmVTdHJpbmcucHJvdG90eXBlLmdldENvb3JkaW5hdGVBdCA9IGZ1bmN0aW9uIChmcmFjdGlvbiwgb3B0X2Rlc3QpIHtcbiAgICByZXR1cm4gaW50ZXJwb2xhdGVQb2ludCh0aGlzLmZsYXRDb29yZGluYXRlcywgMCwgdGhpcy5mbGF0Q29vcmRpbmF0ZXMubGVuZ3RoLCB0aGlzLnN0cmlkZSwgZnJhY3Rpb24sIG9wdF9kZXN0LCB0aGlzLnN0cmlkZSk7XG4gIH07XG4gIC8qKlxuICAgKiBSZXR1cm4gdGhlIGxlbmd0aCBvZiB0aGUgbGluZXN0cmluZyBvbiBwcm9qZWN0ZWQgcGxhbmUuXG4gICAqIEByZXR1cm4ge251bWJlcn0gTGVuZ3RoIChvbiBwcm9qZWN0ZWQgcGxhbmUpLlxuICAgKiBAYXBpXG4gICAqL1xuXG5cbiAgTGluZVN0cmluZy5wcm90b3R5cGUuZ2V0TGVuZ3RoID0gZnVuY3Rpb24gKCkge1xuICAgIHJldHVybiBsaW5lU3RyaW5nTGVuZ3RoKHRoaXMuZmxhdENvb3JkaW5hdGVzLCAwLCB0aGlzLmZsYXRDb29yZGluYXRlcy5sZW5ndGgsIHRoaXMuc3RyaWRlKTtcbiAgfTtcbiAgLyoqXG4gICAqIEByZXR1cm4ge0FycmF5PG51bWJlcj59IEZsYXQgbWlkcG9pbnQuXG4gICAqL1xuXG5cbiAgTGluZVN0cmluZy5wcm90b3R5cGUuZ2V0RmxhdE1pZHBvaW50ID0gZnVuY3Rpb24gKCkge1xuICAgIGlmICh0aGlzLmZsYXRNaWRwb2ludFJldmlzaW9uXyAhPSB0aGlzLmdldFJldmlzaW9uKCkpIHtcbiAgICAgIHRoaXMuZmxhdE1pZHBvaW50XyA9IHRoaXMuZ2V0Q29vcmRpbmF0ZUF0KDAuNSwgdGhpcy5mbGF0TWlkcG9pbnRfKTtcbiAgICAgIHRoaXMuZmxhdE1pZHBvaW50UmV2aXNpb25fID0gdGhpcy5nZXRSZXZpc2lvbigpO1xuICAgIH1cblxuICAgIHJldHVybiB0aGlzLmZsYXRNaWRwb2ludF87XG4gIH07XG4gIC8qKlxuICAgKiBAcGFyYW0ge251bWJlcn0gc3F1YXJlZFRvbGVyYW5jZSBTcXVhcmVkIHRvbGVyYW5jZS5cbiAgICogQHJldHVybiB7TGluZVN0cmluZ30gU2ltcGxpZmllZCBMaW5lU3RyaW5nLlxuICAgKiBAcHJvdGVjdGVkXG4gICAqL1xuXG5cbiAgTGluZVN0cmluZy5wcm90b3R5cGUuZ2V0U2ltcGxpZmllZEdlb21ldHJ5SW50ZXJuYWwgPSBmdW5jdGlvbiAoc3F1YXJlZFRvbGVyYW5jZSkge1xuICAgIHZhciBzaW1wbGlmaWVkRmxhdENvb3JkaW5hdGVzID0gW107XG4gICAgc2ltcGxpZmllZEZsYXRDb29yZGluYXRlcy5sZW5ndGggPSBkb3VnbGFzUGV1Y2tlcih0aGlzLmZsYXRDb29yZGluYXRlcywgMCwgdGhpcy5mbGF0Q29vcmRpbmF0ZXMubGVuZ3RoLCB0aGlzLnN0cmlkZSwgc3F1YXJlZFRvbGVyYW5jZSwgc2ltcGxpZmllZEZsYXRDb29yZGluYXRlcywgMCk7XG4gICAgcmV0dXJuIG5ldyBMaW5lU3RyaW5nKHNpbXBsaWZpZWRGbGF0Q29vcmRpbmF0ZXMsIEdlb21ldHJ5TGF5b3V0LlhZKTtcbiAgfTtcbiAgLyoqXG4gICAqIEdldCB0aGUgdHlwZSBvZiB0aGlzIGdlb21ldHJ5LlxuICAgKiBAcmV0dXJuIHtpbXBvcnQoXCIuL0dlb21ldHJ5VHlwZS5qc1wiKS5kZWZhdWx0fSBHZW9tZXRyeSB0eXBlLlxuICAgKiBAYXBpXG4gICAqL1xuXG5cbiAgTGluZVN0cmluZy5wcm90b3R5cGUuZ2V0VHlwZSA9IGZ1bmN0aW9uICgpIHtcbiAgICByZXR1cm4gR2VvbWV0cnlUeXBlLkxJTkVfU1RSSU5HO1xuICB9O1xuICAvKipcbiAgICogVGVzdCBpZiB0aGUgZ2VvbWV0cnkgYW5kIHRoZSBwYXNzZWQgZXh0ZW50IGludGVyc2VjdC5cbiAgICogQHBhcmFtIHtpbXBvcnQoXCIuLi9leHRlbnQuanNcIikuRXh0ZW50fSBleHRlbnQgRXh0ZW50LlxuICAgKiBAcmV0dXJuIHtib29sZWFufSBgdHJ1ZWAgaWYgdGhlIGdlb21ldHJ5IGFuZCB0aGUgZXh0ZW50IGludGVyc2VjdC5cbiAgICogQGFwaVxuICAgKi9cblxuXG4gIExpbmVTdHJpbmcucHJvdG90eXBlLmludGVyc2VjdHNFeHRlbnQgPSBmdW5jdGlvbiAoZXh0ZW50KSB7XG4gICAgcmV0dXJuIGludGVyc2VjdHNMaW5lU3RyaW5nKHRoaXMuZmxhdENvb3JkaW5hdGVzLCAwLCB0aGlzLmZsYXRDb29yZGluYXRlcy5sZW5ndGgsIHRoaXMuc3RyaWRlLCBleHRlbnQpO1xuICB9O1xuICAvKipcbiAgICogU2V0IHRoZSBjb29yZGluYXRlcyBvZiB0aGUgbGluZXN0cmluZy5cbiAgICogQHBhcmFtIHshQXJyYXk8aW1wb3J0KFwiLi4vY29vcmRpbmF0ZS5qc1wiKS5Db29yZGluYXRlPn0gY29vcmRpbmF0ZXMgQ29vcmRpbmF0ZXMuXG4gICAqIEBwYXJhbSB7aW1wb3J0KFwiLi9HZW9tZXRyeUxheW91dC5qc1wiKS5kZWZhdWx0PX0gb3B0X2xheW91dCBMYXlvdXQuXG4gICAqIEBhcGlcbiAgICovXG5cblxuICBMaW5lU3RyaW5nLnByb3RvdHlwZS5zZXRDb29yZGluYXRlcyA9IGZ1bmN0aW9uIChjb29yZGluYXRlcywgb3B0X2xheW91dCkge1xuICAgIHRoaXMuc2V0TGF5b3V0KG9wdF9sYXlvdXQsIGNvb3JkaW5hdGVzLCAxKTtcblxuICAgIGlmICghdGhpcy5mbGF0Q29vcmRpbmF0ZXMpIHtcbiAgICAgIHRoaXMuZmxhdENvb3JkaW5hdGVzID0gW107XG4gICAgfVxuXG4gICAgdGhpcy5mbGF0Q29vcmRpbmF0ZXMubGVuZ3RoID0gZGVmbGF0ZUNvb3JkaW5hdGVzKHRoaXMuZmxhdENvb3JkaW5hdGVzLCAwLCBjb29yZGluYXRlcywgdGhpcy5zdHJpZGUpO1xuICAgIHRoaXMuY2hhbmdlZCgpO1xuICB9O1xuXG4gIHJldHVybiBMaW5lU3RyaW5nO1xufShTaW1wbGVHZW9tZXRyeSk7XG5cbmV4cG9ydCBkZWZhdWx0IExpbmVTdHJpbmc7IiwidmFyIF9fZXh0ZW5kcyA9IHRoaXMgJiYgdGhpcy5fX2V4dGVuZHMgfHwgZnVuY3Rpb24gKCkge1xuICB2YXIgX2V4dGVuZFN0YXRpY3MgPSBmdW5jdGlvbiBleHRlbmRTdGF0aWNzKGQsIGIpIHtcbiAgICBfZXh0ZW5kU3RhdGljcyA9IE9iamVjdC5zZXRQcm90b3R5cGVPZiB8fCB7XG4gICAgICBfX3Byb3RvX186IFtdXG4gICAgfSBpbnN0YW5jZW9mIEFycmF5ICYmIGZ1bmN0aW9uIChkLCBiKSB7XG4gICAgICBkLl9fcHJvdG9fXyA9IGI7XG4gICAgfSB8fCBmdW5jdGlvbiAoZCwgYikge1xuICAgICAgZm9yICh2YXIgcCBpbiBiKSB7XG4gICAgICAgIGlmIChPYmplY3QucHJvdG90eXBlLmhhc093blByb3BlcnR5LmNhbGwoYiwgcCkpIGRbcF0gPSBiW3BdO1xuICAgICAgfVxuICAgIH07XG5cbiAgICByZXR1cm4gX2V4dGVuZFN0YXRpY3MoZCwgYik7XG4gIH07XG5cbiAgcmV0dXJuIGZ1bmN0aW9uIChkLCBiKSB7XG4gICAgX2V4dGVuZFN0YXRpY3MoZCwgYik7XG5cbiAgICBmdW5jdGlvbiBfXygpIHtcbiAgICAgIHRoaXMuY29uc3RydWN0b3IgPSBkO1xuICAgIH1cblxuICAgIGQucHJvdG90eXBlID0gYiA9PT0gbnVsbCA/IE9iamVjdC5jcmVhdGUoYikgOiAoX18ucHJvdG90eXBlID0gYi5wcm90b3R5cGUsIG5ldyBfXygpKTtcbiAgfTtcbn0oKTtcbi8qKlxuICogQG1vZHVsZSBvbC9nZW9tL011bHRpTGluZVN0cmluZ1xuICovXG5cblxuaW1wb3J0IEdlb21ldHJ5TGF5b3V0IGZyb20gJy4vR2VvbWV0cnlMYXlvdXQuanMnO1xuaW1wb3J0IEdlb21ldHJ5VHlwZSBmcm9tICcuL0dlb21ldHJ5VHlwZS5qcyc7XG5pbXBvcnQgTGluZVN0cmluZyBmcm9tICcuL0xpbmVTdHJpbmcuanMnO1xuaW1wb3J0IFNpbXBsZUdlb21ldHJ5IGZyb20gJy4vU2ltcGxlR2VvbWV0cnkuanMnO1xuaW1wb3J0IHsgYXJyYXlNYXhTcXVhcmVkRGVsdGEsIGFzc2lnbkNsb3Nlc3RBcnJheVBvaW50IH0gZnJvbSAnLi9mbGF0L2Nsb3Nlc3QuanMnO1xuaW1wb3J0IHsgY2xvc2VzdFNxdWFyZWREaXN0YW5jZVhZIH0gZnJvbSAnLi4vZXh0ZW50LmpzJztcbmltcG9ydCB7IGRlZmxhdGVDb29yZGluYXRlc0FycmF5IH0gZnJvbSAnLi9mbGF0L2RlZmxhdGUuanMnO1xuaW1wb3J0IHsgZG91Z2xhc1BldWNrZXJBcnJheSB9IGZyb20gJy4vZmxhdC9zaW1wbGlmeS5qcyc7XG5pbXBvcnQgeyBleHRlbmQgfSBmcm9tICcuLi9hcnJheS5qcyc7XG5pbXBvcnQgeyBpbmZsYXRlQ29vcmRpbmF0ZXNBcnJheSB9IGZyb20gJy4vZmxhdC9pbmZsYXRlLmpzJztcbmltcG9ydCB7IGludGVycG9sYXRlUG9pbnQsIGxpbmVTdHJpbmdzQ29vcmRpbmF0ZUF0TSB9IGZyb20gJy4vZmxhdC9pbnRlcnBvbGF0ZS5qcyc7XG5pbXBvcnQgeyBpbnRlcnNlY3RzTGluZVN0cmluZ0FycmF5IH0gZnJvbSAnLi9mbGF0L2ludGVyc2VjdHNleHRlbnQuanMnO1xuLyoqXG4gKiBAY2xhc3NkZXNjXG4gKiBNdWx0aS1saW5lc3RyaW5nIGdlb21ldHJ5LlxuICpcbiAqIEBhcGlcbiAqL1xuXG52YXIgTXVsdGlMaW5lU3RyaW5nID1cbi8qKiBAY2xhc3MgKi9cbmZ1bmN0aW9uIChfc3VwZXIpIHtcbiAgX19leHRlbmRzKE11bHRpTGluZVN0cmluZywgX3N1cGVyKTtcbiAgLyoqXG4gICAqIEBwYXJhbSB7QXJyYXk8QXJyYXk8aW1wb3J0KFwiLi4vY29vcmRpbmF0ZS5qc1wiKS5Db29yZGluYXRlPnxMaW5lU3RyaW5nPnxBcnJheTxudW1iZXI+fSBjb29yZGluYXRlc1xuICAgKiAgICAgQ29vcmRpbmF0ZXMgb3IgTGluZVN0cmluZyBnZW9tZXRyaWVzLiAoRm9yIGludGVybmFsIHVzZSwgZmxhdCBjb29yZGluYXRlcyBpblxuICAgKiAgICAgY29tYmluYXRpb24gd2l0aCBgb3B0X2xheW91dGAgYW5kIGBvcHRfZW5kc2AgYXJlIGFsc28gYWNjZXB0ZWQuKVxuICAgKiBAcGFyYW0ge2ltcG9ydChcIi4vR2VvbWV0cnlMYXlvdXQuanNcIikuZGVmYXVsdD19IG9wdF9sYXlvdXQgTGF5b3V0LlxuICAgKiBAcGFyYW0ge0FycmF5PG51bWJlcj49fSBvcHRfZW5kcyBGbGF0IGNvb3JkaW5hdGUgZW5kcyBmb3IgaW50ZXJuYWwgdXNlLlxuICAgKi9cblxuXG4gIGZ1bmN0aW9uIE11bHRpTGluZVN0cmluZyhjb29yZGluYXRlcywgb3B0X2xheW91dCwgb3B0X2VuZHMpIHtcbiAgICB2YXIgX3RoaXMgPSBfc3VwZXIuY2FsbCh0aGlzKSB8fCB0aGlzO1xuICAgIC8qKlxuICAgICAqIEB0eXBlIHtBcnJheTxudW1iZXI+fVxuICAgICAqIEBwcml2YXRlXG4gICAgICovXG5cblxuICAgIF90aGlzLmVuZHNfID0gW107XG4gICAgLyoqXG4gICAgICogQHByaXZhdGVcbiAgICAgKiBAdHlwZSB7bnVtYmVyfVxuICAgICAqL1xuXG4gICAgX3RoaXMubWF4RGVsdGFfID0gLTE7XG4gICAgLyoqXG4gICAgICogQHByaXZhdGVcbiAgICAgKiBAdHlwZSB7bnVtYmVyfVxuICAgICAqL1xuXG4gICAgX3RoaXMubWF4RGVsdGFSZXZpc2lvbl8gPSAtMTtcblxuICAgIGlmIChBcnJheS5pc0FycmF5KGNvb3JkaW5hdGVzWzBdKSkge1xuICAgICAgX3RoaXMuc2V0Q29vcmRpbmF0ZXMoXG4gICAgICAvKiogQHR5cGUge0FycmF5PEFycmF5PGltcG9ydChcIi4uL2Nvb3JkaW5hdGUuanNcIikuQ29vcmRpbmF0ZT4+fSAqL1xuICAgICAgY29vcmRpbmF0ZXMsIG9wdF9sYXlvdXQpO1xuICAgIH0gZWxzZSBpZiAob3B0X2xheW91dCAhPT0gdW5kZWZpbmVkICYmIG9wdF9lbmRzKSB7XG4gICAgICBfdGhpcy5zZXRGbGF0Q29vcmRpbmF0ZXMob3B0X2xheW91dCxcbiAgICAgIC8qKiBAdHlwZSB7QXJyYXk8bnVtYmVyPn0gKi9cbiAgICAgIGNvb3JkaW5hdGVzKTtcblxuICAgICAgX3RoaXMuZW5kc18gPSBvcHRfZW5kcztcbiAgICB9IGVsc2Uge1xuICAgICAgdmFyIGxheW91dCA9IF90aGlzLmdldExheW91dCgpO1xuXG4gICAgICB2YXIgbGluZVN0cmluZ3MgPVxuICAgICAgLyoqIEB0eXBlIHtBcnJheTxMaW5lU3RyaW5nPn0gKi9cbiAgICAgIGNvb3JkaW5hdGVzO1xuICAgICAgdmFyIGZsYXRDb29yZGluYXRlcyA9IFtdO1xuICAgICAgdmFyIGVuZHMgPSBbXTtcblxuICAgICAgZm9yICh2YXIgaSA9IDAsIGlpID0gbGluZVN0cmluZ3MubGVuZ3RoOyBpIDwgaWk7ICsraSkge1xuICAgICAgICB2YXIgbGluZVN0cmluZyA9IGxpbmVTdHJpbmdzW2ldO1xuXG4gICAgICAgIGlmIChpID09PSAwKSB7XG4gICAgICAgICAgbGF5b3V0ID0gbGluZVN0cmluZy5nZXRMYXlvdXQoKTtcbiAgICAgICAgfVxuXG4gICAgICAgIGV4dGVuZChmbGF0Q29vcmRpbmF0ZXMsIGxpbmVTdHJpbmcuZ2V0RmxhdENvb3JkaW5hdGVzKCkpO1xuICAgICAgICBlbmRzLnB1c2goZmxhdENvb3JkaW5hdGVzLmxlbmd0aCk7XG4gICAgICB9XG5cbiAgICAgIF90aGlzLnNldEZsYXRDb29yZGluYXRlcyhsYXlvdXQsIGZsYXRDb29yZGluYXRlcyk7XG5cbiAgICAgIF90aGlzLmVuZHNfID0gZW5kcztcbiAgICB9XG5cbiAgICByZXR1cm4gX3RoaXM7XG4gIH1cbiAgLyoqXG4gICAqIEFwcGVuZCB0aGUgcGFzc2VkIGxpbmVzdHJpbmcgdG8gdGhlIG11bHRpbGluZXN0cmluZy5cbiAgICogQHBhcmFtIHtMaW5lU3RyaW5nfSBsaW5lU3RyaW5nIExpbmVTdHJpbmcuXG4gICAqIEBhcGlcbiAgICovXG5cblxuICBNdWx0aUxpbmVTdHJpbmcucHJvdG90eXBlLmFwcGVuZExpbmVTdHJpbmcgPSBmdW5jdGlvbiAobGluZVN0cmluZykge1xuICAgIGlmICghdGhpcy5mbGF0Q29vcmRpbmF0ZXMpIHtcbiAgICAgIHRoaXMuZmxhdENvb3JkaW5hdGVzID0gbGluZVN0cmluZy5nZXRGbGF0Q29vcmRpbmF0ZXMoKS5zbGljZSgpO1xuICAgIH0gZWxzZSB7XG4gICAgICBleHRlbmQodGhpcy5mbGF0Q29vcmRpbmF0ZXMsIGxpbmVTdHJpbmcuZ2V0RmxhdENvb3JkaW5hdGVzKCkuc2xpY2UoKSk7XG4gICAgfVxuXG4gICAgdGhpcy5lbmRzXy5wdXNoKHRoaXMuZmxhdENvb3JkaW5hdGVzLmxlbmd0aCk7XG4gICAgdGhpcy5jaGFuZ2VkKCk7XG4gIH07XG4gIC8qKlxuICAgKiBNYWtlIGEgY29tcGxldGUgY29weSBvZiB0aGUgZ2VvbWV0cnkuXG4gICAqIEByZXR1cm4geyFNdWx0aUxpbmVTdHJpbmd9IENsb25lLlxuICAgKiBAYXBpXG4gICAqL1xuXG5cbiAgTXVsdGlMaW5lU3RyaW5nLnByb3RvdHlwZS5jbG9uZSA9IGZ1bmN0aW9uICgpIHtcbiAgICB2YXIgbXVsdGlMaW5lU3RyaW5nID0gbmV3IE11bHRpTGluZVN0cmluZyh0aGlzLmZsYXRDb29yZGluYXRlcy5zbGljZSgpLCB0aGlzLmxheW91dCwgdGhpcy5lbmRzXy5zbGljZSgpKTtcbiAgICBtdWx0aUxpbmVTdHJpbmcuYXBwbHlQcm9wZXJ0aWVzKHRoaXMpO1xuICAgIHJldHVybiBtdWx0aUxpbmVTdHJpbmc7XG4gIH07XG4gIC8qKlxuICAgKiBAcGFyYW0ge251bWJlcn0geCBYLlxuICAgKiBAcGFyYW0ge251bWJlcn0geSBZLlxuICAgKiBAcGFyYW0ge2ltcG9ydChcIi4uL2Nvb3JkaW5hdGUuanNcIikuQ29vcmRpbmF0ZX0gY2xvc2VzdFBvaW50IENsb3Nlc3QgcG9pbnQuXG4gICAqIEBwYXJhbSB7bnVtYmVyfSBtaW5TcXVhcmVkRGlzdGFuY2UgTWluaW11bSBzcXVhcmVkIGRpc3RhbmNlLlxuICAgKiBAcmV0dXJuIHtudW1iZXJ9IE1pbmltdW0gc3F1YXJlZCBkaXN0YW5jZS5cbiAgICovXG5cblxuICBNdWx0aUxpbmVTdHJpbmcucHJvdG90eXBlLmNsb3Nlc3RQb2ludFhZID0gZnVuY3Rpb24gKHgsIHksIGNsb3Nlc3RQb2ludCwgbWluU3F1YXJlZERpc3RhbmNlKSB7XG4gICAgaWYgKG1pblNxdWFyZWREaXN0YW5jZSA8IGNsb3Nlc3RTcXVhcmVkRGlzdGFuY2VYWSh0aGlzLmdldEV4dGVudCgpLCB4LCB5KSkge1xuICAgICAgcmV0dXJuIG1pblNxdWFyZWREaXN0YW5jZTtcbiAgICB9XG5cbiAgICBpZiAodGhpcy5tYXhEZWx0YVJldmlzaW9uXyAhPSB0aGlzLmdldFJldmlzaW9uKCkpIHtcbiAgICAgIHRoaXMubWF4RGVsdGFfID0gTWF0aC5zcXJ0KGFycmF5TWF4U3F1YXJlZERlbHRhKHRoaXMuZmxhdENvb3JkaW5hdGVzLCAwLCB0aGlzLmVuZHNfLCB0aGlzLnN0cmlkZSwgMCkpO1xuICAgICAgdGhpcy5tYXhEZWx0YVJldmlzaW9uXyA9IHRoaXMuZ2V0UmV2aXNpb24oKTtcbiAgICB9XG5cbiAgICByZXR1cm4gYXNzaWduQ2xvc2VzdEFycmF5UG9pbnQodGhpcy5mbGF0Q29vcmRpbmF0ZXMsIDAsIHRoaXMuZW5kc18sIHRoaXMuc3RyaWRlLCB0aGlzLm1heERlbHRhXywgZmFsc2UsIHgsIHksIGNsb3Nlc3RQb2ludCwgbWluU3F1YXJlZERpc3RhbmNlKTtcbiAgfTtcbiAgLyoqXG4gICAqIFJldHVybnMgdGhlIGNvb3JkaW5hdGUgYXQgYG1gIHVzaW5nIGxpbmVhciBpbnRlcnBvbGF0aW9uLCBvciBgbnVsbGAgaWYgbm9cbiAgICogc3VjaCBjb29yZGluYXRlIGV4aXN0cy5cbiAgICpcbiAgICogYG9wdF9leHRyYXBvbGF0ZWAgY29udHJvbHMgZXh0cmFwb2xhdGlvbiBiZXlvbmQgdGhlIHJhbmdlIG9mIE1zIGluIHRoZVxuICAgKiBNdWx0aUxpbmVTdHJpbmcuIElmIGBvcHRfZXh0cmFwb2xhdGVgIGlzIGB0cnVlYCB0aGVuIE1zIGxlc3MgdGhhbiB0aGUgZmlyc3RcbiAgICogTSB3aWxsIHJldHVybiB0aGUgZmlyc3QgY29vcmRpbmF0ZSBhbmQgTXMgZ3JlYXRlciB0aGFuIHRoZSBsYXN0IE0gd2lsbFxuICAgKiByZXR1cm4gdGhlIGxhc3QgY29vcmRpbmF0ZS5cbiAgICpcbiAgICogYG9wdF9pbnRlcnBvbGF0ZWAgY29udHJvbHMgaW50ZXJwb2xhdGlvbiBiZXR3ZWVuIGNvbnNlY3V0aXZlIExpbmVTdHJpbmdzXG4gICAqIHdpdGhpbiB0aGUgTXVsdGlMaW5lU3RyaW5nLiBJZiBgb3B0X2ludGVycG9sYXRlYCBpcyBgdHJ1ZWAgdGhlIGNvb3JkaW5hdGVzXG4gICAqIHdpbGwgYmUgbGluZWFybHkgaW50ZXJwb2xhdGVkIGJldHdlZW4gdGhlIGxhc3QgY29vcmRpbmF0ZSBvZiBvbmUgTGluZVN0cmluZ1xuICAgKiBhbmQgdGhlIGZpcnN0IGNvb3JkaW5hdGUgb2YgdGhlIG5leHQgTGluZVN0cmluZy4gIElmIGBvcHRfaW50ZXJwb2xhdGVgIGlzXG4gICAqIGBmYWxzZWAgdGhlbiB0aGUgZnVuY3Rpb24gd2lsbCByZXR1cm4gYG51bGxgIGZvciBNcyBmYWxsaW5nIGJldHdlZW5cbiAgICogTGluZVN0cmluZ3MuXG4gICAqXG4gICAqIEBwYXJhbSB7bnVtYmVyfSBtIE0uXG4gICAqIEBwYXJhbSB7Ym9vbGVhbj19IG9wdF9leHRyYXBvbGF0ZSBFeHRyYXBvbGF0ZS4gRGVmYXVsdCBpcyBgZmFsc2VgLlxuICAgKiBAcGFyYW0ge2Jvb2xlYW49fSBvcHRfaW50ZXJwb2xhdGUgSW50ZXJwb2xhdGUuIERlZmF1bHQgaXMgYGZhbHNlYC5cbiAgICogQHJldHVybiB7aW1wb3J0KFwiLi4vY29vcmRpbmF0ZS5qc1wiKS5Db29yZGluYXRlfSBDb29yZGluYXRlLlxuICAgKiBAYXBpXG4gICAqL1xuXG5cbiAgTXVsdGlMaW5lU3RyaW5nLnByb3RvdHlwZS5nZXRDb29yZGluYXRlQXRNID0gZnVuY3Rpb24gKG0sIG9wdF9leHRyYXBvbGF0ZSwgb3B0X2ludGVycG9sYXRlKSB7XG4gICAgaWYgKHRoaXMubGF5b3V0ICE9IEdlb21ldHJ5TGF5b3V0LlhZTSAmJiB0aGlzLmxheW91dCAhPSBHZW9tZXRyeUxheW91dC5YWVpNIHx8IHRoaXMuZmxhdENvb3JkaW5hdGVzLmxlbmd0aCA9PT0gMCkge1xuICAgICAgcmV0dXJuIG51bGw7XG4gICAgfVxuXG4gICAgdmFyIGV4dHJhcG9sYXRlID0gb3B0X2V4dHJhcG9sYXRlICE9PSB1bmRlZmluZWQgPyBvcHRfZXh0cmFwb2xhdGUgOiBmYWxzZTtcbiAgICB2YXIgaW50ZXJwb2xhdGUgPSBvcHRfaW50ZXJwb2xhdGUgIT09IHVuZGVmaW5lZCA/IG9wdF9pbnRlcnBvbGF0ZSA6IGZhbHNlO1xuICAgIHJldHVybiBsaW5lU3RyaW5nc0Nvb3JkaW5hdGVBdE0odGhpcy5mbGF0Q29vcmRpbmF0ZXMsIDAsIHRoaXMuZW5kc18sIHRoaXMuc3RyaWRlLCBtLCBleHRyYXBvbGF0ZSwgaW50ZXJwb2xhdGUpO1xuICB9O1xuICAvKipcbiAgICogUmV0dXJuIHRoZSBjb29yZGluYXRlcyBvZiB0aGUgbXVsdGlsaW5lc3RyaW5nLlxuICAgKiBAcmV0dXJuIHtBcnJheTxBcnJheTxpbXBvcnQoXCIuLi9jb29yZGluYXRlLmpzXCIpLkNvb3JkaW5hdGU+Pn0gQ29vcmRpbmF0ZXMuXG4gICAqIEBhcGlcbiAgICovXG5cblxuICBNdWx0aUxpbmVTdHJpbmcucHJvdG90eXBlLmdldENvb3JkaW5hdGVzID0gZnVuY3Rpb24gKCkge1xuICAgIHJldHVybiBpbmZsYXRlQ29vcmRpbmF0ZXNBcnJheSh0aGlzLmZsYXRDb29yZGluYXRlcywgMCwgdGhpcy5lbmRzXywgdGhpcy5zdHJpZGUpO1xuICB9O1xuICAvKipcbiAgICogQHJldHVybiB7QXJyYXk8bnVtYmVyPn0gRW5kcy5cbiAgICovXG5cblxuICBNdWx0aUxpbmVTdHJpbmcucHJvdG90eXBlLmdldEVuZHMgPSBmdW5jdGlvbiAoKSB7XG4gICAgcmV0dXJuIHRoaXMuZW5kc187XG4gIH07XG4gIC8qKlxuICAgKiBSZXR1cm4gdGhlIGxpbmVzdHJpbmcgYXQgdGhlIHNwZWNpZmllZCBpbmRleC5cbiAgICogQHBhcmFtIHtudW1iZXJ9IGluZGV4IEluZGV4LlxuICAgKiBAcmV0dXJuIHtMaW5lU3RyaW5nfSBMaW5lU3RyaW5nLlxuICAgKiBAYXBpXG4gICAqL1xuXG5cbiAgTXVsdGlMaW5lU3RyaW5nLnByb3RvdHlwZS5nZXRMaW5lU3RyaW5nID0gZnVuY3Rpb24gKGluZGV4KSB7XG4gICAgaWYgKGluZGV4IDwgMCB8fCB0aGlzLmVuZHNfLmxlbmd0aCA8PSBpbmRleCkge1xuICAgICAgcmV0dXJuIG51bGw7XG4gICAgfVxuXG4gICAgcmV0dXJuIG5ldyBMaW5lU3RyaW5nKHRoaXMuZmxhdENvb3JkaW5hdGVzLnNsaWNlKGluZGV4ID09PSAwID8gMCA6IHRoaXMuZW5kc19baW5kZXggLSAxXSwgdGhpcy5lbmRzX1tpbmRleF0pLCB0aGlzLmxheW91dCk7XG4gIH07XG4gIC8qKlxuICAgKiBSZXR1cm4gdGhlIGxpbmVzdHJpbmdzIG9mIHRoaXMgbXVsdGlsaW5lc3RyaW5nLlxuICAgKiBAcmV0dXJuIHtBcnJheTxMaW5lU3RyaW5nPn0gTGluZVN0cmluZ3MuXG4gICAqIEBhcGlcbiAgICovXG5cblxuICBNdWx0aUxpbmVTdHJpbmcucHJvdG90eXBlLmdldExpbmVTdHJpbmdzID0gZnVuY3Rpb24gKCkge1xuICAgIHZhciBmbGF0Q29vcmRpbmF0ZXMgPSB0aGlzLmZsYXRDb29yZGluYXRlcztcbiAgICB2YXIgZW5kcyA9IHRoaXMuZW5kc187XG4gICAgdmFyIGxheW91dCA9IHRoaXMubGF5b3V0O1xuICAgIC8qKiBAdHlwZSB7QXJyYXk8TGluZVN0cmluZz59ICovXG5cbiAgICB2YXIgbGluZVN0cmluZ3MgPSBbXTtcbiAgICB2YXIgb2Zmc2V0ID0gMDtcblxuICAgIGZvciAodmFyIGkgPSAwLCBpaSA9IGVuZHMubGVuZ3RoOyBpIDwgaWk7ICsraSkge1xuICAgICAgdmFyIGVuZCA9IGVuZHNbaV07XG4gICAgICB2YXIgbGluZVN0cmluZyA9IG5ldyBMaW5lU3RyaW5nKGZsYXRDb29yZGluYXRlcy5zbGljZShvZmZzZXQsIGVuZCksIGxheW91dCk7XG4gICAgICBsaW5lU3RyaW5ncy5wdXNoKGxpbmVTdHJpbmcpO1xuICAgICAgb2Zmc2V0ID0gZW5kO1xuICAgIH1cblxuICAgIHJldHVybiBsaW5lU3RyaW5ncztcbiAgfTtcbiAgLyoqXG4gICAqIEByZXR1cm4ge0FycmF5PG51bWJlcj59IEZsYXQgbWlkcG9pbnRzLlxuICAgKi9cblxuXG4gIE11bHRpTGluZVN0cmluZy5wcm90b3R5cGUuZ2V0RmxhdE1pZHBvaW50cyA9IGZ1bmN0aW9uICgpIHtcbiAgICB2YXIgbWlkcG9pbnRzID0gW107XG4gICAgdmFyIGZsYXRDb29yZGluYXRlcyA9IHRoaXMuZmxhdENvb3JkaW5hdGVzO1xuICAgIHZhciBvZmZzZXQgPSAwO1xuICAgIHZhciBlbmRzID0gdGhpcy5lbmRzXztcbiAgICB2YXIgc3RyaWRlID0gdGhpcy5zdHJpZGU7XG5cbiAgICBmb3IgKHZhciBpID0gMCwgaWkgPSBlbmRzLmxlbmd0aDsgaSA8IGlpOyArK2kpIHtcbiAgICAgIHZhciBlbmQgPSBlbmRzW2ldO1xuICAgICAgdmFyIG1pZHBvaW50ID0gaW50ZXJwb2xhdGVQb2ludChmbGF0Q29vcmRpbmF0ZXMsIG9mZnNldCwgZW5kLCBzdHJpZGUsIDAuNSk7XG4gICAgICBleHRlbmQobWlkcG9pbnRzLCBtaWRwb2ludCk7XG4gICAgICBvZmZzZXQgPSBlbmQ7XG4gICAgfVxuXG4gICAgcmV0dXJuIG1pZHBvaW50cztcbiAgfTtcbiAgLyoqXG4gICAqIEBwYXJhbSB7bnVtYmVyfSBzcXVhcmVkVG9sZXJhbmNlIFNxdWFyZWQgdG9sZXJhbmNlLlxuICAgKiBAcmV0dXJuIHtNdWx0aUxpbmVTdHJpbmd9IFNpbXBsaWZpZWQgTXVsdGlMaW5lU3RyaW5nLlxuICAgKiBAcHJvdGVjdGVkXG4gICAqL1xuXG5cbiAgTXVsdGlMaW5lU3RyaW5nLnByb3RvdHlwZS5nZXRTaW1wbGlmaWVkR2VvbWV0cnlJbnRlcm5hbCA9IGZ1bmN0aW9uIChzcXVhcmVkVG9sZXJhbmNlKSB7XG4gICAgdmFyIHNpbXBsaWZpZWRGbGF0Q29vcmRpbmF0ZXMgPSBbXTtcbiAgICB2YXIgc2ltcGxpZmllZEVuZHMgPSBbXTtcbiAgICBzaW1wbGlmaWVkRmxhdENvb3JkaW5hdGVzLmxlbmd0aCA9IGRvdWdsYXNQZXVja2VyQXJyYXkodGhpcy5mbGF0Q29vcmRpbmF0ZXMsIDAsIHRoaXMuZW5kc18sIHRoaXMuc3RyaWRlLCBzcXVhcmVkVG9sZXJhbmNlLCBzaW1wbGlmaWVkRmxhdENvb3JkaW5hdGVzLCAwLCBzaW1wbGlmaWVkRW5kcyk7XG4gICAgcmV0dXJuIG5ldyBNdWx0aUxpbmVTdHJpbmcoc2ltcGxpZmllZEZsYXRDb29yZGluYXRlcywgR2VvbWV0cnlMYXlvdXQuWFksIHNpbXBsaWZpZWRFbmRzKTtcbiAgfTtcbiAgLyoqXG4gICAqIEdldCB0aGUgdHlwZSBvZiB0aGlzIGdlb21ldHJ5LlxuICAgKiBAcmV0dXJuIHtpbXBvcnQoXCIuL0dlb21ldHJ5VHlwZS5qc1wiKS5kZWZhdWx0fSBHZW9tZXRyeSB0eXBlLlxuICAgKiBAYXBpXG4gICAqL1xuXG5cbiAgTXVsdGlMaW5lU3RyaW5nLnByb3RvdHlwZS5nZXRUeXBlID0gZnVuY3Rpb24gKCkge1xuICAgIHJldHVybiBHZW9tZXRyeVR5cGUuTVVMVElfTElORV9TVFJJTkc7XG4gIH07XG4gIC8qKlxuICAgKiBUZXN0IGlmIHRoZSBnZW9tZXRyeSBhbmQgdGhlIHBhc3NlZCBleHRlbnQgaW50ZXJzZWN0LlxuICAgKiBAcGFyYW0ge2ltcG9ydChcIi4uL2V4dGVudC5qc1wiKS5FeHRlbnR9IGV4dGVudCBFeHRlbnQuXG4gICAqIEByZXR1cm4ge2Jvb2xlYW59IGB0cnVlYCBpZiB0aGUgZ2VvbWV0cnkgYW5kIHRoZSBleHRlbnQgaW50ZXJzZWN0LlxuICAgKiBAYXBpXG4gICAqL1xuXG5cbiAgTXVsdGlMaW5lU3RyaW5nLnByb3RvdHlwZS5pbnRlcnNlY3RzRXh0ZW50ID0gZnVuY3Rpb24gKGV4dGVudCkge1xuICAgIHJldHVybiBpbnRlcnNlY3RzTGluZVN0cmluZ0FycmF5KHRoaXMuZmxhdENvb3JkaW5hdGVzLCAwLCB0aGlzLmVuZHNfLCB0aGlzLnN0cmlkZSwgZXh0ZW50KTtcbiAgfTtcbiAgLyoqXG4gICAqIFNldCB0aGUgY29vcmRpbmF0ZXMgb2YgdGhlIG11bHRpbGluZXN0cmluZy5cbiAgICogQHBhcmFtIHshQXJyYXk8QXJyYXk8aW1wb3J0KFwiLi4vY29vcmRpbmF0ZS5qc1wiKS5Db29yZGluYXRlPj59IGNvb3JkaW5hdGVzIENvb3JkaW5hdGVzLlxuICAgKiBAcGFyYW0ge0dlb21ldHJ5TGF5b3V0PX0gb3B0X2xheW91dCBMYXlvdXQuXG4gICAqIEBhcGlcbiAgICovXG5cblxuICBNdWx0aUxpbmVTdHJpbmcucHJvdG90eXBlLnNldENvb3JkaW5hdGVzID0gZnVuY3Rpb24gKGNvb3JkaW5hdGVzLCBvcHRfbGF5b3V0KSB7XG4gICAgdGhpcy5zZXRMYXlvdXQob3B0X2xheW91dCwgY29vcmRpbmF0ZXMsIDIpO1xuXG4gICAgaWYgKCF0aGlzLmZsYXRDb29yZGluYXRlcykge1xuICAgICAgdGhpcy5mbGF0Q29vcmRpbmF0ZXMgPSBbXTtcbiAgICB9XG5cbiAgICB2YXIgZW5kcyA9IGRlZmxhdGVDb29yZGluYXRlc0FycmF5KHRoaXMuZmxhdENvb3JkaW5hdGVzLCAwLCBjb29yZGluYXRlcywgdGhpcy5zdHJpZGUsIHRoaXMuZW5kc18pO1xuICAgIHRoaXMuZmxhdENvb3JkaW5hdGVzLmxlbmd0aCA9IGVuZHMubGVuZ3RoID09PSAwID8gMCA6IGVuZHNbZW5kcy5sZW5ndGggLSAxXTtcbiAgICB0aGlzLmNoYW5nZWQoKTtcbiAgfTtcblxuICByZXR1cm4gTXVsdGlMaW5lU3RyaW5nO1xufShTaW1wbGVHZW9tZXRyeSk7XG5cbmV4cG9ydCBkZWZhdWx0IE11bHRpTGluZVN0cmluZzsiLCJ2YXIgX19leHRlbmRzID0gdGhpcyAmJiB0aGlzLl9fZXh0ZW5kcyB8fCBmdW5jdGlvbiAoKSB7XG4gIHZhciBfZXh0ZW5kU3RhdGljcyA9IGZ1bmN0aW9uIGV4dGVuZFN0YXRpY3MoZCwgYikge1xuICAgIF9leHRlbmRTdGF0aWNzID0gT2JqZWN0LnNldFByb3RvdHlwZU9mIHx8IHtcbiAgICAgIF9fcHJvdG9fXzogW11cbiAgICB9IGluc3RhbmNlb2YgQXJyYXkgJiYgZnVuY3Rpb24gKGQsIGIpIHtcbiAgICAgIGQuX19wcm90b19fID0gYjtcbiAgICB9IHx8IGZ1bmN0aW9uIChkLCBiKSB7XG4gICAgICBmb3IgKHZhciBwIGluIGIpIHtcbiAgICAgICAgaWYgKE9iamVjdC5wcm90b3R5cGUuaGFzT3duUHJvcGVydHkuY2FsbChiLCBwKSkgZFtwXSA9IGJbcF07XG4gICAgICB9XG4gICAgfTtcblxuICAgIHJldHVybiBfZXh0ZW5kU3RhdGljcyhkLCBiKTtcbiAgfTtcblxuICByZXR1cm4gZnVuY3Rpb24gKGQsIGIpIHtcbiAgICBfZXh0ZW5kU3RhdGljcyhkLCBiKTtcblxuICAgIGZ1bmN0aW9uIF9fKCkge1xuICAgICAgdGhpcy5jb25zdHJ1Y3RvciA9IGQ7XG4gICAgfVxuXG4gICAgZC5wcm90b3R5cGUgPSBiID09PSBudWxsID8gT2JqZWN0LmNyZWF0ZShiKSA6IChfXy5wcm90b3R5cGUgPSBiLnByb3RvdHlwZSwgbmV3IF9fKCkpO1xuICB9O1xufSgpO1xuLyoqXG4gKiBAbW9kdWxlIG9sL2dlb20vTXVsdGlQb2ludFxuICovXG5cblxuaW1wb3J0IEdlb21ldHJ5VHlwZSBmcm9tICcuL0dlb21ldHJ5VHlwZS5qcyc7XG5pbXBvcnQgUG9pbnQgZnJvbSAnLi9Qb2ludC5qcyc7XG5pbXBvcnQgU2ltcGxlR2VvbWV0cnkgZnJvbSAnLi9TaW1wbGVHZW9tZXRyeS5qcyc7XG5pbXBvcnQgeyBjbG9zZXN0U3F1YXJlZERpc3RhbmNlWFksIGNvbnRhaW5zWFkgfSBmcm9tICcuLi9leHRlbnQuanMnO1xuaW1wb3J0IHsgZGVmbGF0ZUNvb3JkaW5hdGVzIH0gZnJvbSAnLi9mbGF0L2RlZmxhdGUuanMnO1xuaW1wb3J0IHsgZXh0ZW5kIH0gZnJvbSAnLi4vYXJyYXkuanMnO1xuaW1wb3J0IHsgaW5mbGF0ZUNvb3JkaW5hdGVzIH0gZnJvbSAnLi9mbGF0L2luZmxhdGUuanMnO1xuaW1wb3J0IHsgc3F1YXJlZERpc3RhbmNlIGFzIHNxdWFyZWREeCB9IGZyb20gJy4uL21hdGguanMnO1xuLyoqXG4gKiBAY2xhc3NkZXNjXG4gKiBNdWx0aS1wb2ludCBnZW9tZXRyeS5cbiAqXG4gKiBAYXBpXG4gKi9cblxudmFyIE11bHRpUG9pbnQgPVxuLyoqIEBjbGFzcyAqL1xuZnVuY3Rpb24gKF9zdXBlcikge1xuICBfX2V4dGVuZHMoTXVsdGlQb2ludCwgX3N1cGVyKTtcbiAgLyoqXG4gICAqIEBwYXJhbSB7QXJyYXk8aW1wb3J0KFwiLi4vY29vcmRpbmF0ZS5qc1wiKS5Db29yZGluYXRlPnxBcnJheTxudW1iZXI+fSBjb29yZGluYXRlcyBDb29yZGluYXRlcy5cbiAgICogICAgIEZvciBpbnRlcm5hbCB1c2UsIGZsYXQgY29vcmRpbmF0ZXMgaW4gY29tYmluYXRpb24gd2l0aCBgb3B0X2xheW91dGAgYXJlIGFsc28gYWNjZXB0ZWQuXG4gICAqIEBwYXJhbSB7aW1wb3J0KFwiLi9HZW9tZXRyeUxheW91dC5qc1wiKS5kZWZhdWx0PX0gb3B0X2xheW91dCBMYXlvdXQuXG4gICAqL1xuXG5cbiAgZnVuY3Rpb24gTXVsdGlQb2ludChjb29yZGluYXRlcywgb3B0X2xheW91dCkge1xuICAgIHZhciBfdGhpcyA9IF9zdXBlci5jYWxsKHRoaXMpIHx8IHRoaXM7XG5cbiAgICBpZiAob3B0X2xheW91dCAmJiAhQXJyYXkuaXNBcnJheShjb29yZGluYXRlc1swXSkpIHtcbiAgICAgIF90aGlzLnNldEZsYXRDb29yZGluYXRlcyhvcHRfbGF5b3V0LFxuICAgICAgLyoqIEB0eXBlIHtBcnJheTxudW1iZXI+fSAqL1xuICAgICAgY29vcmRpbmF0ZXMpO1xuICAgIH0gZWxzZSB7XG4gICAgICBfdGhpcy5zZXRDb29yZGluYXRlcyhcbiAgICAgIC8qKiBAdHlwZSB7QXJyYXk8aW1wb3J0KFwiLi4vY29vcmRpbmF0ZS5qc1wiKS5Db29yZGluYXRlPn0gKi9cbiAgICAgIGNvb3JkaW5hdGVzLCBvcHRfbGF5b3V0KTtcbiAgICB9XG5cbiAgICByZXR1cm4gX3RoaXM7XG4gIH1cbiAgLyoqXG4gICAqIEFwcGVuZCB0aGUgcGFzc2VkIHBvaW50IHRvIHRoaXMgbXVsdGlwb2ludC5cbiAgICogQHBhcmFtIHtQb2ludH0gcG9pbnQgUG9pbnQuXG4gICAqIEBhcGlcbiAgICovXG5cblxuICBNdWx0aVBvaW50LnByb3RvdHlwZS5hcHBlbmRQb2ludCA9IGZ1bmN0aW9uIChwb2ludCkge1xuICAgIGlmICghdGhpcy5mbGF0Q29vcmRpbmF0ZXMpIHtcbiAgICAgIHRoaXMuZmxhdENvb3JkaW5hdGVzID0gcG9pbnQuZ2V0RmxhdENvb3JkaW5hdGVzKCkuc2xpY2UoKTtcbiAgICB9IGVsc2Uge1xuICAgICAgZXh0ZW5kKHRoaXMuZmxhdENvb3JkaW5hdGVzLCBwb2ludC5nZXRGbGF0Q29vcmRpbmF0ZXMoKSk7XG4gICAgfVxuXG4gICAgdGhpcy5jaGFuZ2VkKCk7XG4gIH07XG4gIC8qKlxuICAgKiBNYWtlIGEgY29tcGxldGUgY29weSBvZiB0aGUgZ2VvbWV0cnkuXG4gICAqIEByZXR1cm4geyFNdWx0aVBvaW50fSBDbG9uZS5cbiAgICogQGFwaVxuICAgKi9cblxuXG4gIE11bHRpUG9pbnQucHJvdG90eXBlLmNsb25lID0gZnVuY3Rpb24gKCkge1xuICAgIHZhciBtdWx0aVBvaW50ID0gbmV3IE11bHRpUG9pbnQodGhpcy5mbGF0Q29vcmRpbmF0ZXMuc2xpY2UoKSwgdGhpcy5sYXlvdXQpO1xuICAgIG11bHRpUG9pbnQuYXBwbHlQcm9wZXJ0aWVzKHRoaXMpO1xuICAgIHJldHVybiBtdWx0aVBvaW50O1xuICB9O1xuICAvKipcbiAgICogQHBhcmFtIHtudW1iZXJ9IHggWC5cbiAgICogQHBhcmFtIHtudW1iZXJ9IHkgWS5cbiAgICogQHBhcmFtIHtpbXBvcnQoXCIuLi9jb29yZGluYXRlLmpzXCIpLkNvb3JkaW5hdGV9IGNsb3Nlc3RQb2ludCBDbG9zZXN0IHBvaW50LlxuICAgKiBAcGFyYW0ge251bWJlcn0gbWluU3F1YXJlZERpc3RhbmNlIE1pbmltdW0gc3F1YXJlZCBkaXN0YW5jZS5cbiAgICogQHJldHVybiB7bnVtYmVyfSBNaW5pbXVtIHNxdWFyZWQgZGlzdGFuY2UuXG4gICAqL1xuXG5cbiAgTXVsdGlQb2ludC5wcm90b3R5cGUuY2xvc2VzdFBvaW50WFkgPSBmdW5jdGlvbiAoeCwgeSwgY2xvc2VzdFBvaW50LCBtaW5TcXVhcmVkRGlzdGFuY2UpIHtcbiAgICBpZiAobWluU3F1YXJlZERpc3RhbmNlIDwgY2xvc2VzdFNxdWFyZWREaXN0YW5jZVhZKHRoaXMuZ2V0RXh0ZW50KCksIHgsIHkpKSB7XG4gICAgICByZXR1cm4gbWluU3F1YXJlZERpc3RhbmNlO1xuICAgIH1cblxuICAgIHZhciBmbGF0Q29vcmRpbmF0ZXMgPSB0aGlzLmZsYXRDb29yZGluYXRlcztcbiAgICB2YXIgc3RyaWRlID0gdGhpcy5zdHJpZGU7XG5cbiAgICBmb3IgKHZhciBpID0gMCwgaWkgPSBmbGF0Q29vcmRpbmF0ZXMubGVuZ3RoOyBpIDwgaWk7IGkgKz0gc3RyaWRlKSB7XG4gICAgICB2YXIgc3F1YXJlZERpc3RhbmNlID0gc3F1YXJlZER4KHgsIHksIGZsYXRDb29yZGluYXRlc1tpXSwgZmxhdENvb3JkaW5hdGVzW2kgKyAxXSk7XG5cbiAgICAgIGlmIChzcXVhcmVkRGlzdGFuY2UgPCBtaW5TcXVhcmVkRGlzdGFuY2UpIHtcbiAgICAgICAgbWluU3F1YXJlZERpc3RhbmNlID0gc3F1YXJlZERpc3RhbmNlO1xuXG4gICAgICAgIGZvciAodmFyIGogPSAwOyBqIDwgc3RyaWRlOyArK2opIHtcbiAgICAgICAgICBjbG9zZXN0UG9pbnRbal0gPSBmbGF0Q29vcmRpbmF0ZXNbaSArIGpdO1xuICAgICAgICB9XG5cbiAgICAgICAgY2xvc2VzdFBvaW50Lmxlbmd0aCA9IHN0cmlkZTtcbiAgICAgIH1cbiAgICB9XG5cbiAgICByZXR1cm4gbWluU3F1YXJlZERpc3RhbmNlO1xuICB9O1xuICAvKipcbiAgICogUmV0dXJuIHRoZSBjb29yZGluYXRlcyBvZiB0aGUgbXVsdGlwb2ludC5cbiAgICogQHJldHVybiB7QXJyYXk8aW1wb3J0KFwiLi4vY29vcmRpbmF0ZS5qc1wiKS5Db29yZGluYXRlPn0gQ29vcmRpbmF0ZXMuXG4gICAqIEBhcGlcbiAgICovXG5cblxuICBNdWx0aVBvaW50LnByb3RvdHlwZS5nZXRDb29yZGluYXRlcyA9IGZ1bmN0aW9uICgpIHtcbiAgICByZXR1cm4gaW5mbGF0ZUNvb3JkaW5hdGVzKHRoaXMuZmxhdENvb3JkaW5hdGVzLCAwLCB0aGlzLmZsYXRDb29yZGluYXRlcy5sZW5ndGgsIHRoaXMuc3RyaWRlKTtcbiAgfTtcbiAgLyoqXG4gICAqIFJldHVybiB0aGUgcG9pbnQgYXQgdGhlIHNwZWNpZmllZCBpbmRleC5cbiAgICogQHBhcmFtIHtudW1iZXJ9IGluZGV4IEluZGV4LlxuICAgKiBAcmV0dXJuIHtQb2ludH0gUG9pbnQuXG4gICAqIEBhcGlcbiAgICovXG5cblxuICBNdWx0aVBvaW50LnByb3RvdHlwZS5nZXRQb2ludCA9IGZ1bmN0aW9uIChpbmRleCkge1xuICAgIHZhciBuID0gIXRoaXMuZmxhdENvb3JkaW5hdGVzID8gMCA6IHRoaXMuZmxhdENvb3JkaW5hdGVzLmxlbmd0aCAvIHRoaXMuc3RyaWRlO1xuXG4gICAgaWYgKGluZGV4IDwgMCB8fCBuIDw9IGluZGV4KSB7XG4gICAgICByZXR1cm4gbnVsbDtcbiAgICB9XG5cbiAgICByZXR1cm4gbmV3IFBvaW50KHRoaXMuZmxhdENvb3JkaW5hdGVzLnNsaWNlKGluZGV4ICogdGhpcy5zdHJpZGUsIChpbmRleCArIDEpICogdGhpcy5zdHJpZGUpLCB0aGlzLmxheW91dCk7XG4gIH07XG4gIC8qKlxuICAgKiBSZXR1cm4gdGhlIHBvaW50cyBvZiB0aGlzIG11bHRpcG9pbnQuXG4gICAqIEByZXR1cm4ge0FycmF5PFBvaW50Pn0gUG9pbnRzLlxuICAgKiBAYXBpXG4gICAqL1xuXG5cbiAgTXVsdGlQb2ludC5wcm90b3R5cGUuZ2V0UG9pbnRzID0gZnVuY3Rpb24gKCkge1xuICAgIHZhciBmbGF0Q29vcmRpbmF0ZXMgPSB0aGlzLmZsYXRDb29yZGluYXRlcztcbiAgICB2YXIgbGF5b3V0ID0gdGhpcy5sYXlvdXQ7XG4gICAgdmFyIHN0cmlkZSA9IHRoaXMuc3RyaWRlO1xuICAgIC8qKiBAdHlwZSB7QXJyYXk8UG9pbnQ+fSAqL1xuXG4gICAgdmFyIHBvaW50cyA9IFtdO1xuXG4gICAgZm9yICh2YXIgaSA9IDAsIGlpID0gZmxhdENvb3JkaW5hdGVzLmxlbmd0aDsgaSA8IGlpOyBpICs9IHN0cmlkZSkge1xuICAgICAgdmFyIHBvaW50ID0gbmV3IFBvaW50KGZsYXRDb29yZGluYXRlcy5zbGljZShpLCBpICsgc3RyaWRlKSwgbGF5b3V0KTtcbiAgICAgIHBvaW50cy5wdXNoKHBvaW50KTtcbiAgICB9XG5cbiAgICByZXR1cm4gcG9pbnRzO1xuICB9O1xuICAvKipcbiAgICogR2V0IHRoZSB0eXBlIG9mIHRoaXMgZ2VvbWV0cnkuXG4gICAqIEByZXR1cm4ge2ltcG9ydChcIi4vR2VvbWV0cnlUeXBlLmpzXCIpLmRlZmF1bHR9IEdlb21ldHJ5IHR5cGUuXG4gICAqIEBhcGlcbiAgICovXG5cblxuICBNdWx0aVBvaW50LnByb3RvdHlwZS5nZXRUeXBlID0gZnVuY3Rpb24gKCkge1xuICAgIHJldHVybiBHZW9tZXRyeVR5cGUuTVVMVElfUE9JTlQ7XG4gIH07XG4gIC8qKlxuICAgKiBUZXN0IGlmIHRoZSBnZW9tZXRyeSBhbmQgdGhlIHBhc3NlZCBleHRlbnQgaW50ZXJzZWN0LlxuICAgKiBAcGFyYW0ge2ltcG9ydChcIi4uL2V4dGVudC5qc1wiKS5FeHRlbnR9IGV4dGVudCBFeHRlbnQuXG4gICAqIEByZXR1cm4ge2Jvb2xlYW59IGB0cnVlYCBpZiB0aGUgZ2VvbWV0cnkgYW5kIHRoZSBleHRlbnQgaW50ZXJzZWN0LlxuICAgKiBAYXBpXG4gICAqL1xuXG5cbiAgTXVsdGlQb2ludC5wcm90b3R5cGUuaW50ZXJzZWN0c0V4dGVudCA9IGZ1bmN0aW9uIChleHRlbnQpIHtcbiAgICB2YXIgZmxhdENvb3JkaW5hdGVzID0gdGhpcy5mbGF0Q29vcmRpbmF0ZXM7XG4gICAgdmFyIHN0cmlkZSA9IHRoaXMuc3RyaWRlO1xuXG4gICAgZm9yICh2YXIgaSA9IDAsIGlpID0gZmxhdENvb3JkaW5hdGVzLmxlbmd0aDsgaSA8IGlpOyBpICs9IHN0cmlkZSkge1xuICAgICAgdmFyIHggPSBmbGF0Q29vcmRpbmF0ZXNbaV07XG4gICAgICB2YXIgeSA9IGZsYXRDb29yZGluYXRlc1tpICsgMV07XG5cbiAgICAgIGlmIChjb250YWluc1hZKGV4dGVudCwgeCwgeSkpIHtcbiAgICAgICAgcmV0dXJuIHRydWU7XG4gICAgICB9XG4gICAgfVxuXG4gICAgcmV0dXJuIGZhbHNlO1xuICB9O1xuICAvKipcbiAgICogU2V0IHRoZSBjb29yZGluYXRlcyBvZiB0aGUgbXVsdGlwb2ludC5cbiAgICogQHBhcmFtIHshQXJyYXk8aW1wb3J0KFwiLi4vY29vcmRpbmF0ZS5qc1wiKS5Db29yZGluYXRlPn0gY29vcmRpbmF0ZXMgQ29vcmRpbmF0ZXMuXG4gICAqIEBwYXJhbSB7aW1wb3J0KFwiLi9HZW9tZXRyeUxheW91dC5qc1wiKS5kZWZhdWx0PX0gb3B0X2xheW91dCBMYXlvdXQuXG4gICAqIEBhcGlcbiAgICovXG5cblxuICBNdWx0aVBvaW50LnByb3RvdHlwZS5zZXRDb29yZGluYXRlcyA9IGZ1bmN0aW9uIChjb29yZGluYXRlcywgb3B0X2xheW91dCkge1xuICAgIHRoaXMuc2V0TGF5b3V0KG9wdF9sYXlvdXQsIGNvb3JkaW5hdGVzLCAxKTtcblxuICAgIGlmICghdGhpcy5mbGF0Q29vcmRpbmF0ZXMpIHtcbiAgICAgIHRoaXMuZmxhdENvb3JkaW5hdGVzID0gW107XG4gICAgfVxuXG4gICAgdGhpcy5mbGF0Q29vcmRpbmF0ZXMubGVuZ3RoID0gZGVmbGF0ZUNvb3JkaW5hdGVzKHRoaXMuZmxhdENvb3JkaW5hdGVzLCAwLCBjb29yZGluYXRlcywgdGhpcy5zdHJpZGUpO1xuICAgIHRoaXMuY2hhbmdlZCgpO1xuICB9O1xuXG4gIHJldHVybiBNdWx0aVBvaW50O1xufShTaW1wbGVHZW9tZXRyeSk7XG5cbmV4cG9ydCBkZWZhdWx0IE11bHRpUG9pbnQ7IiwiLyoqXG4gKiBAbW9kdWxlIG9sL2dlb20vZmxhdC9jZW50ZXJcbiAqL1xuaW1wb3J0IHsgY3JlYXRlRW1wdHksIGNyZWF0ZU9yVXBkYXRlRnJvbUZsYXRDb29yZGluYXRlcyB9IGZyb20gJy4uLy4uL2V4dGVudC5qcyc7XG4vKipcbiAqIEBwYXJhbSB7QXJyYXk8bnVtYmVyPn0gZmxhdENvb3JkaW5hdGVzIEZsYXQgY29vcmRpbmF0ZXMuXG4gKiBAcGFyYW0ge251bWJlcn0gb2Zmc2V0IE9mZnNldC5cbiAqIEBwYXJhbSB7QXJyYXk8QXJyYXk8bnVtYmVyPj59IGVuZHNzIEVuZHNzLlxuICogQHBhcmFtIHtudW1iZXJ9IHN0cmlkZSBTdHJpZGUuXG4gKiBAcmV0dXJuIHtBcnJheTxudW1iZXI+fSBGbGF0IGNlbnRlcnMuXG4gKi9cblxuZXhwb3J0IGZ1bmN0aW9uIGxpbmVhclJpbmdzcyhmbGF0Q29vcmRpbmF0ZXMsIG9mZnNldCwgZW5kc3MsIHN0cmlkZSkge1xuICB2YXIgZmxhdENlbnRlcnMgPSBbXTtcbiAgdmFyIGV4dGVudCA9IGNyZWF0ZUVtcHR5KCk7XG5cbiAgZm9yICh2YXIgaSA9IDAsIGlpID0gZW5kc3MubGVuZ3RoOyBpIDwgaWk7ICsraSkge1xuICAgIHZhciBlbmRzID0gZW5kc3NbaV07XG4gICAgZXh0ZW50ID0gY3JlYXRlT3JVcGRhdGVGcm9tRmxhdENvb3JkaW5hdGVzKGZsYXRDb29yZGluYXRlcywgb2Zmc2V0LCBlbmRzWzBdLCBzdHJpZGUpO1xuICAgIGZsYXRDZW50ZXJzLnB1c2goKGV4dGVudFswXSArIGV4dGVudFsyXSkgLyAyLCAoZXh0ZW50WzFdICsgZXh0ZW50WzNdKSAvIDIpO1xuICAgIG9mZnNldCA9IGVuZHNbZW5kcy5sZW5ndGggLSAxXTtcbiAgfVxuXG4gIHJldHVybiBmbGF0Q2VudGVycztcbn0iLCJ2YXIgX19leHRlbmRzID0gdGhpcyAmJiB0aGlzLl9fZXh0ZW5kcyB8fCBmdW5jdGlvbiAoKSB7XG4gIHZhciBfZXh0ZW5kU3RhdGljcyA9IGZ1bmN0aW9uIGV4dGVuZFN0YXRpY3MoZCwgYikge1xuICAgIF9leHRlbmRTdGF0aWNzID0gT2JqZWN0LnNldFByb3RvdHlwZU9mIHx8IHtcbiAgICAgIF9fcHJvdG9fXzogW11cbiAgICB9IGluc3RhbmNlb2YgQXJyYXkgJiYgZnVuY3Rpb24gKGQsIGIpIHtcbiAgICAgIGQuX19wcm90b19fID0gYjtcbiAgICB9IHx8IGZ1bmN0aW9uIChkLCBiKSB7XG4gICAgICBmb3IgKHZhciBwIGluIGIpIHtcbiAgICAgICAgaWYgKE9iamVjdC5wcm90b3R5cGUuaGFzT3duUHJvcGVydHkuY2FsbChiLCBwKSkgZFtwXSA9IGJbcF07XG4gICAgICB9XG4gICAgfTtcblxuICAgIHJldHVybiBfZXh0ZW5kU3RhdGljcyhkLCBiKTtcbiAgfTtcblxuICByZXR1cm4gZnVuY3Rpb24gKGQsIGIpIHtcbiAgICBfZXh0ZW5kU3RhdGljcyhkLCBiKTtcblxuICAgIGZ1bmN0aW9uIF9fKCkge1xuICAgICAgdGhpcy5jb25zdHJ1Y3RvciA9IGQ7XG4gICAgfVxuXG4gICAgZC5wcm90b3R5cGUgPSBiID09PSBudWxsID8gT2JqZWN0LmNyZWF0ZShiKSA6IChfXy5wcm90b3R5cGUgPSBiLnByb3RvdHlwZSwgbmV3IF9fKCkpO1xuICB9O1xufSgpO1xuLyoqXG4gKiBAbW9kdWxlIG9sL2dlb20vTXVsdGlQb2x5Z29uXG4gKi9cblxuXG5pbXBvcnQgR2VvbWV0cnlMYXlvdXQgZnJvbSAnLi9HZW9tZXRyeUxheW91dC5qcyc7XG5pbXBvcnQgR2VvbWV0cnlUeXBlIGZyb20gJy4vR2VvbWV0cnlUeXBlLmpzJztcbmltcG9ydCBNdWx0aVBvaW50IGZyb20gJy4vTXVsdGlQb2ludC5qcyc7XG5pbXBvcnQgUG9seWdvbiBmcm9tICcuL1BvbHlnb24uanMnO1xuaW1wb3J0IFNpbXBsZUdlb21ldHJ5IGZyb20gJy4vU2ltcGxlR2VvbWV0cnkuanMnO1xuaW1wb3J0IHsgYXNzaWduQ2xvc2VzdE11bHRpQXJyYXlQb2ludCwgbXVsdGlBcnJheU1heFNxdWFyZWREZWx0YSB9IGZyb20gJy4vZmxhdC9jbG9zZXN0LmpzJztcbmltcG9ydCB7IGNsb3Nlc3RTcXVhcmVkRGlzdGFuY2VYWSB9IGZyb20gJy4uL2V4dGVudC5qcyc7XG5pbXBvcnQgeyBkZWZsYXRlTXVsdGlDb29yZGluYXRlc0FycmF5IH0gZnJvbSAnLi9mbGF0L2RlZmxhdGUuanMnO1xuaW1wb3J0IHsgZXh0ZW5kIH0gZnJvbSAnLi4vYXJyYXkuanMnO1xuaW1wb3J0IHsgZ2V0SW50ZXJpb3JQb2ludHNPZk11bHRpQXJyYXkgfSBmcm9tICcuL2ZsYXQvaW50ZXJpb3Jwb2ludC5qcyc7XG5pbXBvcnQgeyBpbmZsYXRlTXVsdGlDb29yZGluYXRlc0FycmF5IH0gZnJvbSAnLi9mbGF0L2luZmxhdGUuanMnO1xuaW1wb3J0IHsgaW50ZXJzZWN0c0xpbmVhclJpbmdNdWx0aUFycmF5IH0gZnJvbSAnLi9mbGF0L2ludGVyc2VjdHNleHRlbnQuanMnO1xuaW1wb3J0IHsgbGluZWFyUmluZ3NzQXJlT3JpZW50ZWQsIG9yaWVudExpbmVhclJpbmdzQXJyYXkgfSBmcm9tICcuL2ZsYXQvb3JpZW50LmpzJztcbmltcG9ydCB7IGxpbmVhclJpbmdzcyBhcyBsaW5lYXJSaW5nc3NBcmVhIH0gZnJvbSAnLi9mbGF0L2FyZWEuanMnO1xuaW1wb3J0IHsgbGluZWFyUmluZ3NzIGFzIGxpbmVhclJpbmdzc0NlbnRlciB9IGZyb20gJy4vZmxhdC9jZW50ZXIuanMnO1xuaW1wb3J0IHsgbGluZWFyUmluZ3NzQ29udGFpbnNYWSB9IGZyb20gJy4vZmxhdC9jb250YWlucy5qcyc7XG5pbXBvcnQgeyBxdWFudGl6ZU11bHRpQXJyYXkgfSBmcm9tICcuL2ZsYXQvc2ltcGxpZnkuanMnO1xuLyoqXG4gKiBAY2xhc3NkZXNjXG4gKiBNdWx0aS1wb2x5Z29uIGdlb21ldHJ5LlxuICpcbiAqIEBhcGlcbiAqL1xuXG52YXIgTXVsdGlQb2x5Z29uID1cbi8qKiBAY2xhc3MgKi9cbmZ1bmN0aW9uIChfc3VwZXIpIHtcbiAgX19leHRlbmRzKE11bHRpUG9seWdvbiwgX3N1cGVyKTtcbiAgLyoqXG4gICAqIEBwYXJhbSB7QXJyYXk8QXJyYXk8QXJyYXk8aW1wb3J0KFwiLi4vY29vcmRpbmF0ZS5qc1wiKS5Db29yZGluYXRlPj58UG9seWdvbj58QXJyYXk8bnVtYmVyPn0gY29vcmRpbmF0ZXMgQ29vcmRpbmF0ZXMuXG4gICAqICAgICBGb3IgaW50ZXJuYWwgdXNlLCBmbGF0IGNvb3JkaW5hdGVzIGluIGNvbWJpbmF0aW9uIHdpdGggYG9wdF9sYXlvdXRgIGFuZCBgb3B0X2VuZHNzYCBhcmUgYWxzbyBhY2NlcHRlZC5cbiAgICogQHBhcmFtIHtpbXBvcnQoXCIuL0dlb21ldHJ5TGF5b3V0LmpzXCIpLmRlZmF1bHQ9fSBvcHRfbGF5b3V0IExheW91dC5cbiAgICogQHBhcmFtIHtBcnJheTxBcnJheTxudW1iZXI+Pj19IG9wdF9lbmRzcyBBcnJheSBvZiBlbmRzIGZvciBpbnRlcm5hbCB1c2Ugd2l0aCBmbGF0IGNvb3JkaW5hdGVzLlxuICAgKi9cblxuXG4gIGZ1bmN0aW9uIE11bHRpUG9seWdvbihjb29yZGluYXRlcywgb3B0X2xheW91dCwgb3B0X2VuZHNzKSB7XG4gICAgdmFyIF90aGlzID0gX3N1cGVyLmNhbGwodGhpcykgfHwgdGhpcztcbiAgICAvKipcbiAgICAgKiBAdHlwZSB7QXJyYXk8QXJyYXk8bnVtYmVyPj59XG4gICAgICogQHByaXZhdGVcbiAgICAgKi9cblxuXG4gICAgX3RoaXMuZW5kc3NfID0gW107XG4gICAgLyoqXG4gICAgICogQHByaXZhdGVcbiAgICAgKiBAdHlwZSB7bnVtYmVyfVxuICAgICAqL1xuXG4gICAgX3RoaXMuZmxhdEludGVyaW9yUG9pbnRzUmV2aXNpb25fID0gLTE7XG4gICAgLyoqXG4gICAgICogQHByaXZhdGVcbiAgICAgKiBAdHlwZSB7QXJyYXk8bnVtYmVyPn1cbiAgICAgKi9cblxuICAgIF90aGlzLmZsYXRJbnRlcmlvclBvaW50c18gPSBudWxsO1xuICAgIC8qKlxuICAgICAqIEBwcml2YXRlXG4gICAgICogQHR5cGUge251bWJlcn1cbiAgICAgKi9cblxuICAgIF90aGlzLm1heERlbHRhXyA9IC0xO1xuICAgIC8qKlxuICAgICAqIEBwcml2YXRlXG4gICAgICogQHR5cGUge251bWJlcn1cbiAgICAgKi9cblxuICAgIF90aGlzLm1heERlbHRhUmV2aXNpb25fID0gLTE7XG4gICAgLyoqXG4gICAgICogQHByaXZhdGVcbiAgICAgKiBAdHlwZSB7bnVtYmVyfVxuICAgICAqL1xuXG4gICAgX3RoaXMub3JpZW50ZWRSZXZpc2lvbl8gPSAtMTtcbiAgICAvKipcbiAgICAgKiBAcHJpdmF0ZVxuICAgICAqIEB0eXBlIHtBcnJheTxudW1iZXI+fVxuICAgICAqL1xuXG4gICAgX3RoaXMub3JpZW50ZWRGbGF0Q29vcmRpbmF0ZXNfID0gbnVsbDtcblxuICAgIGlmICghb3B0X2VuZHNzICYmICFBcnJheS5pc0FycmF5KGNvb3JkaW5hdGVzWzBdKSkge1xuICAgICAgdmFyIGxheW91dCA9IF90aGlzLmdldExheW91dCgpO1xuXG4gICAgICB2YXIgcG9seWdvbnMgPVxuICAgICAgLyoqIEB0eXBlIHtBcnJheTxQb2x5Z29uPn0gKi9cbiAgICAgIGNvb3JkaW5hdGVzO1xuICAgICAgdmFyIGZsYXRDb29yZGluYXRlcyA9IFtdO1xuICAgICAgdmFyIGVuZHNzID0gW107XG5cbiAgICAgIGZvciAodmFyIGkgPSAwLCBpaSA9IHBvbHlnb25zLmxlbmd0aDsgaSA8IGlpOyArK2kpIHtcbiAgICAgICAgdmFyIHBvbHlnb24gPSBwb2x5Z29uc1tpXTtcblxuICAgICAgICBpZiAoaSA9PT0gMCkge1xuICAgICAgICAgIGxheW91dCA9IHBvbHlnb24uZ2V0TGF5b3V0KCk7XG4gICAgICAgIH1cblxuICAgICAgICB2YXIgb2Zmc2V0ID0gZmxhdENvb3JkaW5hdGVzLmxlbmd0aDtcbiAgICAgICAgdmFyIGVuZHMgPSBwb2x5Z29uLmdldEVuZHMoKTtcblxuICAgICAgICBmb3IgKHZhciBqID0gMCwgamogPSBlbmRzLmxlbmd0aDsgaiA8IGpqOyArK2opIHtcbiAgICAgICAgICBlbmRzW2pdICs9IG9mZnNldDtcbiAgICAgICAgfVxuXG4gICAgICAgIGV4dGVuZChmbGF0Q29vcmRpbmF0ZXMsIHBvbHlnb24uZ2V0RmxhdENvb3JkaW5hdGVzKCkpO1xuICAgICAgICBlbmRzcy5wdXNoKGVuZHMpO1xuICAgICAgfVxuXG4gICAgICBvcHRfbGF5b3V0ID0gbGF5b3V0O1xuICAgICAgY29vcmRpbmF0ZXMgPSBmbGF0Q29vcmRpbmF0ZXM7XG4gICAgICBvcHRfZW5kc3MgPSBlbmRzcztcbiAgICB9XG5cbiAgICBpZiAob3B0X2xheW91dCAhPT0gdW5kZWZpbmVkICYmIG9wdF9lbmRzcykge1xuICAgICAgX3RoaXMuc2V0RmxhdENvb3JkaW5hdGVzKG9wdF9sYXlvdXQsXG4gICAgICAvKiogQHR5cGUge0FycmF5PG51bWJlcj59ICovXG4gICAgICBjb29yZGluYXRlcyk7XG5cbiAgICAgIF90aGlzLmVuZHNzXyA9IG9wdF9lbmRzcztcbiAgICB9IGVsc2Uge1xuICAgICAgX3RoaXMuc2V0Q29vcmRpbmF0ZXMoXG4gICAgICAvKiogQHR5cGUge0FycmF5PEFycmF5PEFycmF5PGltcG9ydChcIi4uL2Nvb3JkaW5hdGUuanNcIikuQ29vcmRpbmF0ZT4+Pn0gKi9cbiAgICAgIGNvb3JkaW5hdGVzLCBvcHRfbGF5b3V0KTtcbiAgICB9XG5cbiAgICByZXR1cm4gX3RoaXM7XG4gIH1cbiAgLyoqXG4gICAqIEFwcGVuZCB0aGUgcGFzc2VkIHBvbHlnb24gdG8gdGhpcyBtdWx0aXBvbHlnb24uXG4gICAqIEBwYXJhbSB7UG9seWdvbn0gcG9seWdvbiBQb2x5Z29uLlxuICAgKiBAYXBpXG4gICAqL1xuXG5cbiAgTXVsdGlQb2x5Z29uLnByb3RvdHlwZS5hcHBlbmRQb2x5Z29uID0gZnVuY3Rpb24gKHBvbHlnb24pIHtcbiAgICAvKiogQHR5cGUge0FycmF5PG51bWJlcj59ICovXG4gICAgdmFyIGVuZHM7XG5cbiAgICBpZiAoIXRoaXMuZmxhdENvb3JkaW5hdGVzKSB7XG4gICAgICB0aGlzLmZsYXRDb29yZGluYXRlcyA9IHBvbHlnb24uZ2V0RmxhdENvb3JkaW5hdGVzKCkuc2xpY2UoKTtcbiAgICAgIGVuZHMgPSBwb2x5Z29uLmdldEVuZHMoKS5zbGljZSgpO1xuICAgICAgdGhpcy5lbmRzc18ucHVzaCgpO1xuICAgIH0gZWxzZSB7XG4gICAgICB2YXIgb2Zmc2V0ID0gdGhpcy5mbGF0Q29vcmRpbmF0ZXMubGVuZ3RoO1xuICAgICAgZXh0ZW5kKHRoaXMuZmxhdENvb3JkaW5hdGVzLCBwb2x5Z29uLmdldEZsYXRDb29yZGluYXRlcygpKTtcbiAgICAgIGVuZHMgPSBwb2x5Z29uLmdldEVuZHMoKS5zbGljZSgpO1xuXG4gICAgICBmb3IgKHZhciBpID0gMCwgaWkgPSBlbmRzLmxlbmd0aDsgaSA8IGlpOyArK2kpIHtcbiAgICAgICAgZW5kc1tpXSArPSBvZmZzZXQ7XG4gICAgICB9XG4gICAgfVxuXG4gICAgdGhpcy5lbmRzc18ucHVzaChlbmRzKTtcbiAgICB0aGlzLmNoYW5nZWQoKTtcbiAgfTtcbiAgLyoqXG4gICAqIE1ha2UgYSBjb21wbGV0ZSBjb3B5IG9mIHRoZSBnZW9tZXRyeS5cbiAgICogQHJldHVybiB7IU11bHRpUG9seWdvbn0gQ2xvbmUuXG4gICAqIEBhcGlcbiAgICovXG5cblxuICBNdWx0aVBvbHlnb24ucHJvdG90eXBlLmNsb25lID0gZnVuY3Rpb24gKCkge1xuICAgIHZhciBsZW4gPSB0aGlzLmVuZHNzXy5sZW5ndGg7XG4gICAgdmFyIG5ld0VuZHNzID0gbmV3IEFycmF5KGxlbik7XG5cbiAgICBmb3IgKHZhciBpID0gMDsgaSA8IGxlbjsgKytpKSB7XG4gICAgICBuZXdFbmRzc1tpXSA9IHRoaXMuZW5kc3NfW2ldLnNsaWNlKCk7XG4gICAgfVxuXG4gICAgdmFyIG11bHRpUG9seWdvbiA9IG5ldyBNdWx0aVBvbHlnb24odGhpcy5mbGF0Q29vcmRpbmF0ZXMuc2xpY2UoKSwgdGhpcy5sYXlvdXQsIG5ld0VuZHNzKTtcbiAgICBtdWx0aVBvbHlnb24uYXBwbHlQcm9wZXJ0aWVzKHRoaXMpO1xuICAgIHJldHVybiBtdWx0aVBvbHlnb247XG4gIH07XG4gIC8qKlxuICAgKiBAcGFyYW0ge251bWJlcn0geCBYLlxuICAgKiBAcGFyYW0ge251bWJlcn0geSBZLlxuICAgKiBAcGFyYW0ge2ltcG9ydChcIi4uL2Nvb3JkaW5hdGUuanNcIikuQ29vcmRpbmF0ZX0gY2xvc2VzdFBvaW50IENsb3Nlc3QgcG9pbnQuXG4gICAqIEBwYXJhbSB7bnVtYmVyfSBtaW5TcXVhcmVkRGlzdGFuY2UgTWluaW11bSBzcXVhcmVkIGRpc3RhbmNlLlxuICAgKiBAcmV0dXJuIHtudW1iZXJ9IE1pbmltdW0gc3F1YXJlZCBkaXN0YW5jZS5cbiAgICovXG5cblxuICBNdWx0aVBvbHlnb24ucHJvdG90eXBlLmNsb3Nlc3RQb2ludFhZID0gZnVuY3Rpb24gKHgsIHksIGNsb3Nlc3RQb2ludCwgbWluU3F1YXJlZERpc3RhbmNlKSB7XG4gICAgaWYgKG1pblNxdWFyZWREaXN0YW5jZSA8IGNsb3Nlc3RTcXVhcmVkRGlzdGFuY2VYWSh0aGlzLmdldEV4dGVudCgpLCB4LCB5KSkge1xuICAgICAgcmV0dXJuIG1pblNxdWFyZWREaXN0YW5jZTtcbiAgICB9XG5cbiAgICBpZiAodGhpcy5tYXhEZWx0YVJldmlzaW9uXyAhPSB0aGlzLmdldFJldmlzaW9uKCkpIHtcbiAgICAgIHRoaXMubWF4RGVsdGFfID0gTWF0aC5zcXJ0KG11bHRpQXJyYXlNYXhTcXVhcmVkRGVsdGEodGhpcy5mbGF0Q29vcmRpbmF0ZXMsIDAsIHRoaXMuZW5kc3NfLCB0aGlzLnN0cmlkZSwgMCkpO1xuICAgICAgdGhpcy5tYXhEZWx0YVJldmlzaW9uXyA9IHRoaXMuZ2V0UmV2aXNpb24oKTtcbiAgICB9XG5cbiAgICByZXR1cm4gYXNzaWduQ2xvc2VzdE11bHRpQXJyYXlQb2ludCh0aGlzLmdldE9yaWVudGVkRmxhdENvb3JkaW5hdGVzKCksIDAsIHRoaXMuZW5kc3NfLCB0aGlzLnN0cmlkZSwgdGhpcy5tYXhEZWx0YV8sIHRydWUsIHgsIHksIGNsb3Nlc3RQb2ludCwgbWluU3F1YXJlZERpc3RhbmNlKTtcbiAgfTtcbiAgLyoqXG4gICAqIEBwYXJhbSB7bnVtYmVyfSB4IFguXG4gICAqIEBwYXJhbSB7bnVtYmVyfSB5IFkuXG4gICAqIEByZXR1cm4ge2Jvb2xlYW59IENvbnRhaW5zICh4LCB5KS5cbiAgICovXG5cblxuICBNdWx0aVBvbHlnb24ucHJvdG90eXBlLmNvbnRhaW5zWFkgPSBmdW5jdGlvbiAoeCwgeSkge1xuICAgIHJldHVybiBsaW5lYXJSaW5nc3NDb250YWluc1hZKHRoaXMuZ2V0T3JpZW50ZWRGbGF0Q29vcmRpbmF0ZXMoKSwgMCwgdGhpcy5lbmRzc18sIHRoaXMuc3RyaWRlLCB4LCB5KTtcbiAgfTtcbiAgLyoqXG4gICAqIFJldHVybiB0aGUgYXJlYSBvZiB0aGUgbXVsdGlwb2x5Z29uIG9uIHByb2plY3RlZCBwbGFuZS5cbiAgICogQHJldHVybiB7bnVtYmVyfSBBcmVhIChvbiBwcm9qZWN0ZWQgcGxhbmUpLlxuICAgKiBAYXBpXG4gICAqL1xuXG5cbiAgTXVsdGlQb2x5Z29uLnByb3RvdHlwZS5nZXRBcmVhID0gZnVuY3Rpb24gKCkge1xuICAgIHJldHVybiBsaW5lYXJSaW5nc3NBcmVhKHRoaXMuZ2V0T3JpZW50ZWRGbGF0Q29vcmRpbmF0ZXMoKSwgMCwgdGhpcy5lbmRzc18sIHRoaXMuc3RyaWRlKTtcbiAgfTtcbiAgLyoqXG4gICAqIEdldCB0aGUgY29vcmRpbmF0ZSBhcnJheSBmb3IgdGhpcyBnZW9tZXRyeS4gIFRoaXMgYXJyYXkgaGFzIHRoZSBzdHJ1Y3R1cmVcbiAgICogb2YgYSBHZW9KU09OIGNvb3JkaW5hdGUgYXJyYXkgZm9yIG11bHRpLXBvbHlnb25zLlxuICAgKlxuICAgKiBAcGFyYW0ge2Jvb2xlYW49fSBvcHRfcmlnaHQgT3JpZW50IGNvb3JkaW5hdGVzIGFjY29yZGluZyB0byB0aGUgcmlnaHQtaGFuZFxuICAgKiAgICAgcnVsZSAoY291bnRlci1jbG9ja3dpc2UgZm9yIGV4dGVyaW9yIGFuZCBjbG9ja3dpc2UgZm9yIGludGVyaW9yIHJpbmdzKS5cbiAgICogICAgIElmIGBmYWxzZWAsIGNvb3JkaW5hdGVzIHdpbGwgYmUgb3JpZW50ZWQgYWNjb3JkaW5nIHRvIHRoZSBsZWZ0LWhhbmQgcnVsZVxuICAgKiAgICAgKGNsb2Nrd2lzZSBmb3IgZXh0ZXJpb3IgYW5kIGNvdW50ZXItY2xvY2t3aXNlIGZvciBpbnRlcmlvciByaW5ncykuXG4gICAqICAgICBCeSBkZWZhdWx0LCBjb29yZGluYXRlIG9yaWVudGF0aW9uIHdpbGwgZGVwZW5kIG9uIGhvdyB0aGUgZ2VvbWV0cnkgd2FzXG4gICAqICAgICBjb25zdHJ1Y3RlZC5cbiAgICogQHJldHVybiB7QXJyYXk8QXJyYXk8QXJyYXk8aW1wb3J0KFwiLi4vY29vcmRpbmF0ZS5qc1wiKS5Db29yZGluYXRlPj4+fSBDb29yZGluYXRlcy5cbiAgICogQGFwaVxuICAgKi9cblxuXG4gIE11bHRpUG9seWdvbi5wcm90b3R5cGUuZ2V0Q29vcmRpbmF0ZXMgPSBmdW5jdGlvbiAob3B0X3JpZ2h0KSB7XG4gICAgdmFyIGZsYXRDb29yZGluYXRlcztcblxuICAgIGlmIChvcHRfcmlnaHQgIT09IHVuZGVmaW5lZCkge1xuICAgICAgZmxhdENvb3JkaW5hdGVzID0gdGhpcy5nZXRPcmllbnRlZEZsYXRDb29yZGluYXRlcygpLnNsaWNlKCk7XG4gICAgICBvcmllbnRMaW5lYXJSaW5nc0FycmF5KGZsYXRDb29yZGluYXRlcywgMCwgdGhpcy5lbmRzc18sIHRoaXMuc3RyaWRlLCBvcHRfcmlnaHQpO1xuICAgIH0gZWxzZSB7XG4gICAgICBmbGF0Q29vcmRpbmF0ZXMgPSB0aGlzLmZsYXRDb29yZGluYXRlcztcbiAgICB9XG5cbiAgICByZXR1cm4gaW5mbGF0ZU11bHRpQ29vcmRpbmF0ZXNBcnJheShmbGF0Q29vcmRpbmF0ZXMsIDAsIHRoaXMuZW5kc3NfLCB0aGlzLnN0cmlkZSk7XG4gIH07XG4gIC8qKlxuICAgKiBAcmV0dXJuIHtBcnJheTxBcnJheTxudW1iZXI+Pn0gRW5kc3MuXG4gICAqL1xuXG5cbiAgTXVsdGlQb2x5Z29uLnByb3RvdHlwZS5nZXRFbmRzcyA9IGZ1bmN0aW9uICgpIHtcbiAgICByZXR1cm4gdGhpcy5lbmRzc187XG4gIH07XG4gIC8qKlxuICAgKiBAcmV0dXJuIHtBcnJheTxudW1iZXI+fSBGbGF0IGludGVyaW9yIHBvaW50cy5cbiAgICovXG5cblxuICBNdWx0aVBvbHlnb24ucHJvdG90eXBlLmdldEZsYXRJbnRlcmlvclBvaW50cyA9IGZ1bmN0aW9uICgpIHtcbiAgICBpZiAodGhpcy5mbGF0SW50ZXJpb3JQb2ludHNSZXZpc2lvbl8gIT0gdGhpcy5nZXRSZXZpc2lvbigpKSB7XG4gICAgICB2YXIgZmxhdENlbnRlcnMgPSBsaW5lYXJSaW5nc3NDZW50ZXIodGhpcy5mbGF0Q29vcmRpbmF0ZXMsIDAsIHRoaXMuZW5kc3NfLCB0aGlzLnN0cmlkZSk7XG4gICAgICB0aGlzLmZsYXRJbnRlcmlvclBvaW50c18gPSBnZXRJbnRlcmlvclBvaW50c09mTXVsdGlBcnJheSh0aGlzLmdldE9yaWVudGVkRmxhdENvb3JkaW5hdGVzKCksIDAsIHRoaXMuZW5kc3NfLCB0aGlzLnN0cmlkZSwgZmxhdENlbnRlcnMpO1xuICAgICAgdGhpcy5mbGF0SW50ZXJpb3JQb2ludHNSZXZpc2lvbl8gPSB0aGlzLmdldFJldmlzaW9uKCk7XG4gICAgfVxuXG4gICAgcmV0dXJuIHRoaXMuZmxhdEludGVyaW9yUG9pbnRzXztcbiAgfTtcbiAgLyoqXG4gICAqIFJldHVybiB0aGUgaW50ZXJpb3IgcG9pbnRzIGFzIHtAbGluayBtb2R1bGU6b2wvZ2VvbS9NdWx0aVBvaW50IG11bHRpcG9pbnR9LlxuICAgKiBAcmV0dXJuIHtNdWx0aVBvaW50fSBJbnRlcmlvciBwb2ludHMgYXMgWFlNIGNvb3JkaW5hdGVzLCB3aGVyZSBNIGlzXG4gICAqIHRoZSBsZW5ndGggb2YgdGhlIGhvcml6b250YWwgaW50ZXJzZWN0aW9uIHRoYXQgdGhlIHBvaW50IGJlbG9uZ3MgdG8uXG4gICAqIEBhcGlcbiAgICovXG5cblxuICBNdWx0aVBvbHlnb24ucHJvdG90eXBlLmdldEludGVyaW9yUG9pbnRzID0gZnVuY3Rpb24gKCkge1xuICAgIHJldHVybiBuZXcgTXVsdGlQb2ludCh0aGlzLmdldEZsYXRJbnRlcmlvclBvaW50cygpLnNsaWNlKCksIEdlb21ldHJ5TGF5b3V0LlhZTSk7XG4gIH07XG4gIC8qKlxuICAgKiBAcmV0dXJuIHtBcnJheTxudW1iZXI+fSBPcmllbnRlZCBmbGF0IGNvb3JkaW5hdGVzLlxuICAgKi9cblxuXG4gIE11bHRpUG9seWdvbi5wcm90b3R5cGUuZ2V0T3JpZW50ZWRGbGF0Q29vcmRpbmF0ZXMgPSBmdW5jdGlvbiAoKSB7XG4gICAgaWYgKHRoaXMub3JpZW50ZWRSZXZpc2lvbl8gIT0gdGhpcy5nZXRSZXZpc2lvbigpKSB7XG4gICAgICB2YXIgZmxhdENvb3JkaW5hdGVzID0gdGhpcy5mbGF0Q29vcmRpbmF0ZXM7XG5cbiAgICAgIGlmIChsaW5lYXJSaW5nc3NBcmVPcmllbnRlZChmbGF0Q29vcmRpbmF0ZXMsIDAsIHRoaXMuZW5kc3NfLCB0aGlzLnN0cmlkZSkpIHtcbiAgICAgICAgdGhpcy5vcmllbnRlZEZsYXRDb29yZGluYXRlc18gPSBmbGF0Q29vcmRpbmF0ZXM7XG4gICAgICB9IGVsc2Uge1xuICAgICAgICB0aGlzLm9yaWVudGVkRmxhdENvb3JkaW5hdGVzXyA9IGZsYXRDb29yZGluYXRlcy5zbGljZSgpO1xuICAgICAgICB0aGlzLm9yaWVudGVkRmxhdENvb3JkaW5hdGVzXy5sZW5ndGggPSBvcmllbnRMaW5lYXJSaW5nc0FycmF5KHRoaXMub3JpZW50ZWRGbGF0Q29vcmRpbmF0ZXNfLCAwLCB0aGlzLmVuZHNzXywgdGhpcy5zdHJpZGUpO1xuICAgICAgfVxuXG4gICAgICB0aGlzLm9yaWVudGVkUmV2aXNpb25fID0gdGhpcy5nZXRSZXZpc2lvbigpO1xuICAgIH1cblxuICAgIHJldHVybiB0aGlzLm9yaWVudGVkRmxhdENvb3JkaW5hdGVzXztcbiAgfTtcbiAgLyoqXG4gICAqIEBwYXJhbSB7bnVtYmVyfSBzcXVhcmVkVG9sZXJhbmNlIFNxdWFyZWQgdG9sZXJhbmNlLlxuICAgKiBAcmV0dXJuIHtNdWx0aVBvbHlnb259IFNpbXBsaWZpZWQgTXVsdGlQb2x5Z29uLlxuICAgKiBAcHJvdGVjdGVkXG4gICAqL1xuXG5cbiAgTXVsdGlQb2x5Z29uLnByb3RvdHlwZS5nZXRTaW1wbGlmaWVkR2VvbWV0cnlJbnRlcm5hbCA9IGZ1bmN0aW9uIChzcXVhcmVkVG9sZXJhbmNlKSB7XG4gICAgdmFyIHNpbXBsaWZpZWRGbGF0Q29vcmRpbmF0ZXMgPSBbXTtcbiAgICB2YXIgc2ltcGxpZmllZEVuZHNzID0gW107XG4gICAgc2ltcGxpZmllZEZsYXRDb29yZGluYXRlcy5sZW5ndGggPSBxdWFudGl6ZU11bHRpQXJyYXkodGhpcy5mbGF0Q29vcmRpbmF0ZXMsIDAsIHRoaXMuZW5kc3NfLCB0aGlzLnN0cmlkZSwgTWF0aC5zcXJ0KHNxdWFyZWRUb2xlcmFuY2UpLCBzaW1wbGlmaWVkRmxhdENvb3JkaW5hdGVzLCAwLCBzaW1wbGlmaWVkRW5kc3MpO1xuICAgIHJldHVybiBuZXcgTXVsdGlQb2x5Z29uKHNpbXBsaWZpZWRGbGF0Q29vcmRpbmF0ZXMsIEdlb21ldHJ5TGF5b3V0LlhZLCBzaW1wbGlmaWVkRW5kc3MpO1xuICB9O1xuICAvKipcbiAgICogUmV0dXJuIHRoZSBwb2x5Z29uIGF0IHRoZSBzcGVjaWZpZWQgaW5kZXguXG4gICAqIEBwYXJhbSB7bnVtYmVyfSBpbmRleCBJbmRleC5cbiAgICogQHJldHVybiB7UG9seWdvbn0gUG9seWdvbi5cbiAgICogQGFwaVxuICAgKi9cblxuXG4gIE11bHRpUG9seWdvbi5wcm90b3R5cGUuZ2V0UG9seWdvbiA9IGZ1bmN0aW9uIChpbmRleCkge1xuICAgIGlmIChpbmRleCA8IDAgfHwgdGhpcy5lbmRzc18ubGVuZ3RoIDw9IGluZGV4KSB7XG4gICAgICByZXR1cm4gbnVsbDtcbiAgICB9XG5cbiAgICB2YXIgb2Zmc2V0O1xuXG4gICAgaWYgKGluZGV4ID09PSAwKSB7XG4gICAgICBvZmZzZXQgPSAwO1xuICAgIH0gZWxzZSB7XG4gICAgICB2YXIgcHJldkVuZHMgPSB0aGlzLmVuZHNzX1tpbmRleCAtIDFdO1xuICAgICAgb2Zmc2V0ID0gcHJldkVuZHNbcHJldkVuZHMubGVuZ3RoIC0gMV07XG4gICAgfVxuXG4gICAgdmFyIGVuZHMgPSB0aGlzLmVuZHNzX1tpbmRleF0uc2xpY2UoKTtcbiAgICB2YXIgZW5kID0gZW5kc1tlbmRzLmxlbmd0aCAtIDFdO1xuXG4gICAgaWYgKG9mZnNldCAhPT0gMCkge1xuICAgICAgZm9yICh2YXIgaSA9IDAsIGlpID0gZW5kcy5sZW5ndGg7IGkgPCBpaTsgKytpKSB7XG4gICAgICAgIGVuZHNbaV0gLT0gb2Zmc2V0O1xuICAgICAgfVxuICAgIH1cblxuICAgIHJldHVybiBuZXcgUG9seWdvbih0aGlzLmZsYXRDb29yZGluYXRlcy5zbGljZShvZmZzZXQsIGVuZCksIHRoaXMubGF5b3V0LCBlbmRzKTtcbiAgfTtcbiAgLyoqXG4gICAqIFJldHVybiB0aGUgcG9seWdvbnMgb2YgdGhpcyBtdWx0aXBvbHlnb24uXG4gICAqIEByZXR1cm4ge0FycmF5PFBvbHlnb24+fSBQb2x5Z29ucy5cbiAgICogQGFwaVxuICAgKi9cblxuXG4gIE11bHRpUG9seWdvbi5wcm90b3R5cGUuZ2V0UG9seWdvbnMgPSBmdW5jdGlvbiAoKSB7XG4gICAgdmFyIGxheW91dCA9IHRoaXMubGF5b3V0O1xuICAgIHZhciBmbGF0Q29vcmRpbmF0ZXMgPSB0aGlzLmZsYXRDb29yZGluYXRlcztcbiAgICB2YXIgZW5kc3MgPSB0aGlzLmVuZHNzXztcbiAgICB2YXIgcG9seWdvbnMgPSBbXTtcbiAgICB2YXIgb2Zmc2V0ID0gMDtcblxuICAgIGZvciAodmFyIGkgPSAwLCBpaSA9IGVuZHNzLmxlbmd0aDsgaSA8IGlpOyArK2kpIHtcbiAgICAgIHZhciBlbmRzID0gZW5kc3NbaV0uc2xpY2UoKTtcbiAgICAgIHZhciBlbmQgPSBlbmRzW2VuZHMubGVuZ3RoIC0gMV07XG5cbiAgICAgIGlmIChvZmZzZXQgIT09IDApIHtcbiAgICAgICAgZm9yICh2YXIgaiA9IDAsIGpqID0gZW5kcy5sZW5ndGg7IGogPCBqajsgKytqKSB7XG4gICAgICAgICAgZW5kc1tqXSAtPSBvZmZzZXQ7XG4gICAgICAgIH1cbiAgICAgIH1cblxuICAgICAgdmFyIHBvbHlnb24gPSBuZXcgUG9seWdvbihmbGF0Q29vcmRpbmF0ZXMuc2xpY2Uob2Zmc2V0LCBlbmQpLCBsYXlvdXQsIGVuZHMpO1xuICAgICAgcG9seWdvbnMucHVzaChwb2x5Z29uKTtcbiAgICAgIG9mZnNldCA9IGVuZDtcbiAgICB9XG5cbiAgICByZXR1cm4gcG9seWdvbnM7XG4gIH07XG4gIC8qKlxuICAgKiBHZXQgdGhlIHR5cGUgb2YgdGhpcyBnZW9tZXRyeS5cbiAgICogQHJldHVybiB7aW1wb3J0KFwiLi9HZW9tZXRyeVR5cGUuanNcIikuZGVmYXVsdH0gR2VvbWV0cnkgdHlwZS5cbiAgICogQGFwaVxuICAgKi9cblxuXG4gIE11bHRpUG9seWdvbi5wcm90b3R5cGUuZ2V0VHlwZSA9IGZ1bmN0aW9uICgpIHtcbiAgICByZXR1cm4gR2VvbWV0cnlUeXBlLk1VTFRJX1BPTFlHT047XG4gIH07XG4gIC8qKlxuICAgKiBUZXN0IGlmIHRoZSBnZW9tZXRyeSBhbmQgdGhlIHBhc3NlZCBleHRlbnQgaW50ZXJzZWN0LlxuICAgKiBAcGFyYW0ge2ltcG9ydChcIi4uL2V4dGVudC5qc1wiKS5FeHRlbnR9IGV4dGVudCBFeHRlbnQuXG4gICAqIEByZXR1cm4ge2Jvb2xlYW59IGB0cnVlYCBpZiB0aGUgZ2VvbWV0cnkgYW5kIHRoZSBleHRlbnQgaW50ZXJzZWN0LlxuICAgKiBAYXBpXG4gICAqL1xuXG5cbiAgTXVsdGlQb2x5Z29uLnByb3RvdHlwZS5pbnRlcnNlY3RzRXh0ZW50ID0gZnVuY3Rpb24gKGV4dGVudCkge1xuICAgIHJldHVybiBpbnRlcnNlY3RzTGluZWFyUmluZ011bHRpQXJyYXkodGhpcy5nZXRPcmllbnRlZEZsYXRDb29yZGluYXRlcygpLCAwLCB0aGlzLmVuZHNzXywgdGhpcy5zdHJpZGUsIGV4dGVudCk7XG4gIH07XG4gIC8qKlxuICAgKiBTZXQgdGhlIGNvb3JkaW5hdGVzIG9mIHRoZSBtdWx0aXBvbHlnb24uXG4gICAqIEBwYXJhbSB7IUFycmF5PEFycmF5PEFycmF5PGltcG9ydChcIi4uL2Nvb3JkaW5hdGUuanNcIikuQ29vcmRpbmF0ZT4+Pn0gY29vcmRpbmF0ZXMgQ29vcmRpbmF0ZXMuXG4gICAqIEBwYXJhbSB7aW1wb3J0KFwiLi9HZW9tZXRyeUxheW91dC5qc1wiKS5kZWZhdWx0PX0gb3B0X2xheW91dCBMYXlvdXQuXG4gICAqIEBhcGlcbiAgICovXG5cblxuICBNdWx0aVBvbHlnb24ucHJvdG90eXBlLnNldENvb3JkaW5hdGVzID0gZnVuY3Rpb24gKGNvb3JkaW5hdGVzLCBvcHRfbGF5b3V0KSB7XG4gICAgdGhpcy5zZXRMYXlvdXQob3B0X2xheW91dCwgY29vcmRpbmF0ZXMsIDMpO1xuXG4gICAgaWYgKCF0aGlzLmZsYXRDb29yZGluYXRlcykge1xuICAgICAgdGhpcy5mbGF0Q29vcmRpbmF0ZXMgPSBbXTtcbiAgICB9XG5cbiAgICB2YXIgZW5kc3MgPSBkZWZsYXRlTXVsdGlDb29yZGluYXRlc0FycmF5KHRoaXMuZmxhdENvb3JkaW5hdGVzLCAwLCBjb29yZGluYXRlcywgdGhpcy5zdHJpZGUsIHRoaXMuZW5kc3NfKTtcblxuICAgIGlmIChlbmRzcy5sZW5ndGggPT09IDApIHtcbiAgICAgIHRoaXMuZmxhdENvb3JkaW5hdGVzLmxlbmd0aCA9IDA7XG4gICAgfSBlbHNlIHtcbiAgICAgIHZhciBsYXN0RW5kcyA9IGVuZHNzW2VuZHNzLmxlbmd0aCAtIDFdO1xuICAgICAgdGhpcy5mbGF0Q29vcmRpbmF0ZXMubGVuZ3RoID0gbGFzdEVuZHMubGVuZ3RoID09PSAwID8gMCA6IGxhc3RFbmRzW2xhc3RFbmRzLmxlbmd0aCAtIDFdO1xuICAgIH1cblxuICAgIHRoaXMuY2hhbmdlZCgpO1xuICB9O1xuXG4gIHJldHVybiBNdWx0aVBvbHlnb247XG59KFNpbXBsZUdlb21ldHJ5KTtcblxuZXhwb3J0IGRlZmF1bHQgTXVsdGlQb2x5Z29uOyIsIi8qKlxuICogQG1vZHVsZSBvbC9yZW5kZXIvRmVhdHVyZVxuICovXG5pbXBvcnQgR2VvbWV0cnlUeXBlIGZyb20gJy4uL2dlb20vR2VvbWV0cnlUeXBlLmpzJztcbmltcG9ydCB7IGNvbXBvc2UgYXMgY29tcG9zZVRyYW5zZm9ybSwgY3JlYXRlIGFzIGNyZWF0ZVRyYW5zZm9ybSB9IGZyb20gJy4uL3RyYW5zZm9ybS5qcyc7XG5pbXBvcnQgeyBjcmVhdGVPclVwZGF0ZUZyb21Db29yZGluYXRlLCBjcmVhdGVPclVwZGF0ZUZyb21GbGF0Q29vcmRpbmF0ZXMsIGdldENlbnRlciwgZ2V0SGVpZ2h0IH0gZnJvbSAnLi4vZXh0ZW50LmpzJztcbmltcG9ydCB7IGV4dGVuZCB9IGZyb20gJy4uL2FycmF5LmpzJztcbmltcG9ydCB7IGdldEludGVyaW9yUG9pbnRPZkFycmF5LCBnZXRJbnRlcmlvclBvaW50c09mTXVsdGlBcnJheSB9IGZyb20gJy4uL2dlb20vZmxhdC9pbnRlcmlvcnBvaW50LmpzJztcbmltcG9ydCB7IGdldCBhcyBnZXRQcm9qZWN0aW9uIH0gZnJvbSAnLi4vcHJvai5qcyc7XG5pbXBvcnQgeyBpbnRlcnBvbGF0ZVBvaW50IH0gZnJvbSAnLi4vZ2VvbS9mbGF0L2ludGVycG9sYXRlLmpzJztcbmltcG9ydCB7IGxpbmVhclJpbmdzcyBhcyBsaW5lYXJSaW5nc3NDZW50ZXIgfSBmcm9tICcuLi9nZW9tL2ZsYXQvY2VudGVyLmpzJztcbmltcG9ydCB7IHRyYW5zZm9ybTJEIH0gZnJvbSAnLi4vZ2VvbS9mbGF0L3RyYW5zZm9ybS5qcyc7XG4vKipcbiAqIEB0eXBlIHtpbXBvcnQoXCIuLi90cmFuc2Zvcm0uanNcIikuVHJhbnNmb3JtfVxuICovXG5cbnZhciB0bXBUcmFuc2Zvcm0gPSBjcmVhdGVUcmFuc2Zvcm0oKTtcbi8qKlxuICogTGlnaHR3ZWlnaHQsIHJlYWQtb25seSwge0BsaW5rIG1vZHVsZTpvbC9GZWF0dXJlfkZlYXR1cmV9IGFuZCB7QGxpbmsgbW9kdWxlOm9sL2dlb20vR2VvbWV0cnl+R2VvbWV0cnl9IGxpa2VcbiAqIHN0cnVjdHVyZSwgb3B0aW1pemVkIGZvciB2ZWN0b3IgdGlsZSByZW5kZXJpbmcgYW5kIHN0eWxpbmcuIEdlb21ldHJ5IGFjY2Vzc1xuICogdGhyb3VnaCB0aGUgQVBJIGlzIGxpbWl0ZWQgdG8gZ2V0dGluZyB0aGUgdHlwZSBhbmQgZXh0ZW50IG9mIHRoZSBnZW9tZXRyeS5cbiAqL1xuXG52YXIgUmVuZGVyRmVhdHVyZSA9XG4vKiogQGNsYXNzICovXG5mdW5jdGlvbiAoKSB7XG4gIC8qKlxuICAgKiBAcGFyYW0ge2ltcG9ydChcIi4uL2dlb20vR2VvbWV0cnlUeXBlLmpzXCIpLmRlZmF1bHR9IHR5cGUgR2VvbWV0cnkgdHlwZS5cbiAgICogQHBhcmFtIHtBcnJheTxudW1iZXI+fSBmbGF0Q29vcmRpbmF0ZXMgRmxhdCBjb29yZGluYXRlcy4gVGhlc2UgYWx3YXlzIG5lZWRcbiAgICogICAgIHRvIGJlIHJpZ2h0LWhhbmRlZCBmb3IgcG9seWdvbnMuXG4gICAqIEBwYXJhbSB7QXJyYXk8bnVtYmVyPnxBcnJheTxBcnJheTxudW1iZXI+Pn0gZW5kcyBFbmRzIG9yIEVuZHNzLlxuICAgKiBAcGFyYW0ge09iamVjdDxzdHJpbmcsICo+fSBwcm9wZXJ0aWVzIFByb3BlcnRpZXMuXG4gICAqIEBwYXJhbSB7bnVtYmVyfHN0cmluZ3x1bmRlZmluZWR9IGlkIEZlYXR1cmUgaWQuXG4gICAqL1xuICBmdW5jdGlvbiBSZW5kZXJGZWF0dXJlKHR5cGUsIGZsYXRDb29yZGluYXRlcywgZW5kcywgcHJvcGVydGllcywgaWQpIHtcbiAgICAvKipcbiAgICAgKiBAcHJpdmF0ZVxuICAgICAqIEB0eXBlIHtpbXBvcnQoXCIuLi9leHRlbnQuanNcIikuRXh0ZW50fHVuZGVmaW5lZH1cbiAgICAgKi9cbiAgICB0aGlzLmV4dGVudF87XG4gICAgLyoqXG4gICAgICogQHByaXZhdGVcbiAgICAgKiBAdHlwZSB7bnVtYmVyfHN0cmluZ3x1bmRlZmluZWR9XG4gICAgICovXG5cbiAgICB0aGlzLmlkXyA9IGlkO1xuICAgIC8qKlxuICAgICAqIEBwcml2YXRlXG4gICAgICogQHR5cGUge2ltcG9ydChcIi4uL2dlb20vR2VvbWV0cnlUeXBlLmpzXCIpLmRlZmF1bHR9XG4gICAgICovXG5cbiAgICB0aGlzLnR5cGVfID0gdHlwZTtcbiAgICAvKipcbiAgICAgKiBAcHJpdmF0ZVxuICAgICAqIEB0eXBlIHtBcnJheTxudW1iZXI+fVxuICAgICAqL1xuXG4gICAgdGhpcy5mbGF0Q29vcmRpbmF0ZXNfID0gZmxhdENvb3JkaW5hdGVzO1xuICAgIC8qKlxuICAgICAqIEBwcml2YXRlXG4gICAgICogQHR5cGUge0FycmF5PG51bWJlcj59XG4gICAgICovXG5cbiAgICB0aGlzLmZsYXRJbnRlcmlvclBvaW50c18gPSBudWxsO1xuICAgIC8qKlxuICAgICAqIEBwcml2YXRlXG4gICAgICogQHR5cGUge0FycmF5PG51bWJlcj59XG4gICAgICovXG5cbiAgICB0aGlzLmZsYXRNaWRwb2ludHNfID0gbnVsbDtcbiAgICAvKipcbiAgICAgKiBAcHJpdmF0ZVxuICAgICAqIEB0eXBlIHtBcnJheTxudW1iZXI+fEFycmF5PEFycmF5PG51bWJlcj4+fVxuICAgICAqL1xuXG4gICAgdGhpcy5lbmRzXyA9IGVuZHM7XG4gICAgLyoqXG4gICAgICogQHByaXZhdGVcbiAgICAgKiBAdHlwZSB7T2JqZWN0PHN0cmluZywgKj59XG4gICAgICovXG5cbiAgICB0aGlzLnByb3BlcnRpZXNfID0gcHJvcGVydGllcztcbiAgfVxuICAvKipcbiAgICogR2V0IGEgZmVhdHVyZSBwcm9wZXJ0eSBieSBpdHMga2V5LlxuICAgKiBAcGFyYW0ge3N0cmluZ30ga2V5IEtleVxuICAgKiBAcmV0dXJuIHsqfSBWYWx1ZSBmb3IgdGhlIHJlcXVlc3RlZCBrZXkuXG4gICAqIEBhcGlcbiAgICovXG5cblxuICBSZW5kZXJGZWF0dXJlLnByb3RvdHlwZS5nZXQgPSBmdW5jdGlvbiAoa2V5KSB7XG4gICAgcmV0dXJuIHRoaXMucHJvcGVydGllc19ba2V5XTtcbiAgfTtcbiAgLyoqXG4gICAqIEdldCB0aGUgZXh0ZW50IG9mIHRoaXMgZmVhdHVyZSdzIGdlb21ldHJ5LlxuICAgKiBAcmV0dXJuIHtpbXBvcnQoXCIuLi9leHRlbnQuanNcIikuRXh0ZW50fSBFeHRlbnQuXG4gICAqIEBhcGlcbiAgICovXG5cblxuICBSZW5kZXJGZWF0dXJlLnByb3RvdHlwZS5nZXRFeHRlbnQgPSBmdW5jdGlvbiAoKSB7XG4gICAgaWYgKCF0aGlzLmV4dGVudF8pIHtcbiAgICAgIHRoaXMuZXh0ZW50XyA9IHRoaXMudHlwZV8gPT09IEdlb21ldHJ5VHlwZS5QT0lOVCA/IGNyZWF0ZU9yVXBkYXRlRnJvbUNvb3JkaW5hdGUodGhpcy5mbGF0Q29vcmRpbmF0ZXNfKSA6IGNyZWF0ZU9yVXBkYXRlRnJvbUZsYXRDb29yZGluYXRlcyh0aGlzLmZsYXRDb29yZGluYXRlc18sIDAsIHRoaXMuZmxhdENvb3JkaW5hdGVzXy5sZW5ndGgsIDIpO1xuICAgIH1cblxuICAgIHJldHVybiB0aGlzLmV4dGVudF87XG4gIH07XG4gIC8qKlxuICAgKiBAcmV0dXJuIHtBcnJheTxudW1iZXI+fSBGbGF0IGludGVyaW9yIHBvaW50cy5cbiAgICovXG5cblxuICBSZW5kZXJGZWF0dXJlLnByb3RvdHlwZS5nZXRGbGF0SW50ZXJpb3JQb2ludCA9IGZ1bmN0aW9uICgpIHtcbiAgICBpZiAoIXRoaXMuZmxhdEludGVyaW9yUG9pbnRzXykge1xuICAgICAgdmFyIGZsYXRDZW50ZXIgPSBnZXRDZW50ZXIodGhpcy5nZXRFeHRlbnQoKSk7XG4gICAgICB0aGlzLmZsYXRJbnRlcmlvclBvaW50c18gPSBnZXRJbnRlcmlvclBvaW50T2ZBcnJheSh0aGlzLmZsYXRDb29yZGluYXRlc18sIDAsXG4gICAgICAvKiogQHR5cGUge0FycmF5PG51bWJlcj59ICovXG4gICAgICB0aGlzLmVuZHNfLCAyLCBmbGF0Q2VudGVyLCAwKTtcbiAgICB9XG5cbiAgICByZXR1cm4gdGhpcy5mbGF0SW50ZXJpb3JQb2ludHNfO1xuICB9O1xuICAvKipcbiAgICogQHJldHVybiB7QXJyYXk8bnVtYmVyPn0gRmxhdCBpbnRlcmlvciBwb2ludHMuXG4gICAqL1xuXG5cbiAgUmVuZGVyRmVhdHVyZS5wcm90b3R5cGUuZ2V0RmxhdEludGVyaW9yUG9pbnRzID0gZnVuY3Rpb24gKCkge1xuICAgIGlmICghdGhpcy5mbGF0SW50ZXJpb3JQb2ludHNfKSB7XG4gICAgICB2YXIgZmxhdENlbnRlcnMgPSBsaW5lYXJSaW5nc3NDZW50ZXIodGhpcy5mbGF0Q29vcmRpbmF0ZXNfLCAwLFxuICAgICAgLyoqIEB0eXBlIHtBcnJheTxBcnJheTxudW1iZXI+Pn0gKi9cbiAgICAgIHRoaXMuZW5kc18sIDIpO1xuICAgICAgdGhpcy5mbGF0SW50ZXJpb3JQb2ludHNfID0gZ2V0SW50ZXJpb3JQb2ludHNPZk11bHRpQXJyYXkodGhpcy5mbGF0Q29vcmRpbmF0ZXNfLCAwLFxuICAgICAgLyoqIEB0eXBlIHtBcnJheTxBcnJheTxudW1iZXI+Pn0gKi9cbiAgICAgIHRoaXMuZW5kc18sIDIsIGZsYXRDZW50ZXJzKTtcbiAgICB9XG5cbiAgICByZXR1cm4gdGhpcy5mbGF0SW50ZXJpb3JQb2ludHNfO1xuICB9O1xuICAvKipcbiAgICogQHJldHVybiB7QXJyYXk8bnVtYmVyPn0gRmxhdCBtaWRwb2ludC5cbiAgICovXG5cblxuICBSZW5kZXJGZWF0dXJlLnByb3RvdHlwZS5nZXRGbGF0TWlkcG9pbnQgPSBmdW5jdGlvbiAoKSB7XG4gICAgaWYgKCF0aGlzLmZsYXRNaWRwb2ludHNfKSB7XG4gICAgICB0aGlzLmZsYXRNaWRwb2ludHNfID0gaW50ZXJwb2xhdGVQb2ludCh0aGlzLmZsYXRDb29yZGluYXRlc18sIDAsIHRoaXMuZmxhdENvb3JkaW5hdGVzXy5sZW5ndGgsIDIsIDAuNSk7XG4gICAgfVxuXG4gICAgcmV0dXJuIHRoaXMuZmxhdE1pZHBvaW50c187XG4gIH07XG4gIC8qKlxuICAgKiBAcmV0dXJuIHtBcnJheTxudW1iZXI+fSBGbGF0IG1pZHBvaW50cy5cbiAgICovXG5cblxuICBSZW5kZXJGZWF0dXJlLnByb3RvdHlwZS5nZXRGbGF0TWlkcG9pbnRzID0gZnVuY3Rpb24gKCkge1xuICAgIGlmICghdGhpcy5mbGF0TWlkcG9pbnRzXykge1xuICAgICAgdGhpcy5mbGF0TWlkcG9pbnRzXyA9IFtdO1xuICAgICAgdmFyIGZsYXRDb29yZGluYXRlcyA9IHRoaXMuZmxhdENvb3JkaW5hdGVzXztcbiAgICAgIHZhciBvZmZzZXQgPSAwO1xuICAgICAgdmFyIGVuZHMgPVxuICAgICAgLyoqIEB0eXBlIHtBcnJheTxudW1iZXI+fSAqL1xuICAgICAgdGhpcy5lbmRzXztcblxuICAgICAgZm9yICh2YXIgaSA9IDAsIGlpID0gZW5kcy5sZW5ndGg7IGkgPCBpaTsgKytpKSB7XG4gICAgICAgIHZhciBlbmQgPSBlbmRzW2ldO1xuICAgICAgICB2YXIgbWlkcG9pbnQgPSBpbnRlcnBvbGF0ZVBvaW50KGZsYXRDb29yZGluYXRlcywgb2Zmc2V0LCBlbmQsIDIsIDAuNSk7XG4gICAgICAgIGV4dGVuZCh0aGlzLmZsYXRNaWRwb2ludHNfLCBtaWRwb2ludCk7XG4gICAgICAgIG9mZnNldCA9IGVuZDtcbiAgICAgIH1cbiAgICB9XG5cbiAgICByZXR1cm4gdGhpcy5mbGF0TWlkcG9pbnRzXztcbiAgfTtcbiAgLyoqXG4gICAqIEdldCB0aGUgZmVhdHVyZSBpZGVudGlmaWVyLiAgVGhpcyBpcyBhIHN0YWJsZSBpZGVudGlmaWVyIGZvciB0aGUgZmVhdHVyZSBhbmRcbiAgICogaXMgc2V0IHdoZW4gcmVhZGluZyBkYXRhIGZyb20gYSByZW1vdGUgc291cmNlLlxuICAgKiBAcmV0dXJuIHtudW1iZXJ8c3RyaW5nfHVuZGVmaW5lZH0gSWQuXG4gICAqIEBhcGlcbiAgICovXG5cblxuICBSZW5kZXJGZWF0dXJlLnByb3RvdHlwZS5nZXRJZCA9IGZ1bmN0aW9uICgpIHtcbiAgICByZXR1cm4gdGhpcy5pZF87XG4gIH07XG4gIC8qKlxuICAgKiBAcmV0dXJuIHtBcnJheTxudW1iZXI+fSBGbGF0IGNvb3JkaW5hdGVzLlxuICAgKi9cblxuXG4gIFJlbmRlckZlYXR1cmUucHJvdG90eXBlLmdldE9yaWVudGVkRmxhdENvb3JkaW5hdGVzID0gZnVuY3Rpb24gKCkge1xuICAgIHJldHVybiB0aGlzLmZsYXRDb29yZGluYXRlc187XG4gIH07XG4gIC8qKlxuICAgKiBGb3IgQVBJIGNvbXBhdGliaWxpdHkgd2l0aCB7QGxpbmsgbW9kdWxlOm9sL0ZlYXR1cmV+RmVhdHVyZX0sIHRoaXMgbWV0aG9kIGlzIHVzZWZ1bCB3aGVuXG4gICAqIGRldGVybWluaW5nIHRoZSBnZW9tZXRyeSB0eXBlIGluIHN0eWxlIGZ1bmN0aW9uIChzZWUge0BsaW5rICNnZXRUeXBlfSkuXG4gICAqIEByZXR1cm4ge1JlbmRlckZlYXR1cmV9IEZlYXR1cmUuXG4gICAqIEBhcGlcbiAgICovXG5cblxuICBSZW5kZXJGZWF0dXJlLnByb3RvdHlwZS5nZXRHZW9tZXRyeSA9IGZ1bmN0aW9uICgpIHtcbiAgICByZXR1cm4gdGhpcztcbiAgfTtcbiAgLyoqXG4gICAqIEBwYXJhbSB7bnVtYmVyfSBzcXVhcmVkVG9sZXJhbmNlIFNxdWFyZWQgdG9sZXJhbmNlLlxuICAgKiBAcmV0dXJuIHtSZW5kZXJGZWF0dXJlfSBTaW1wbGlmaWVkIGdlb21ldHJ5LlxuICAgKi9cblxuXG4gIFJlbmRlckZlYXR1cmUucHJvdG90eXBlLmdldFNpbXBsaWZpZWRHZW9tZXRyeSA9IGZ1bmN0aW9uIChzcXVhcmVkVG9sZXJhbmNlKSB7XG4gICAgcmV0dXJuIHRoaXM7XG4gIH07XG4gIC8qKlxuICAgKiBHZXQgYSB0cmFuc2Zvcm1lZCBhbmQgc2ltcGxpZmllZCB2ZXJzaW9uIG9mIHRoZSBnZW9tZXRyeS5cbiAgICogQGFic3RyYWN0XG4gICAqIEBwYXJhbSB7bnVtYmVyfSBzcXVhcmVkVG9sZXJhbmNlIFNxdWFyZWQgdG9sZXJhbmNlLlxuICAgKiBAcGFyYW0ge2ltcG9ydChcIi4uL3Byb2ouanNcIikuVHJhbnNmb3JtRnVuY3Rpb259IFtvcHRfdHJhbnNmb3JtXSBPcHRpb25hbCB0cmFuc2Zvcm0gZnVuY3Rpb24uXG4gICAqIEByZXR1cm4ge1JlbmRlckZlYXR1cmV9IFNpbXBsaWZpZWQgZ2VvbWV0cnkuXG4gICAqL1xuXG5cbiAgUmVuZGVyRmVhdHVyZS5wcm90b3R5cGUuc2ltcGxpZnlUcmFuc2Zvcm1lZCA9IGZ1bmN0aW9uIChzcXVhcmVkVG9sZXJhbmNlLCBvcHRfdHJhbnNmb3JtKSB7XG4gICAgcmV0dXJuIHRoaXM7XG4gIH07XG4gIC8qKlxuICAgKiBHZXQgdGhlIGZlYXR1cmUgcHJvcGVydGllcy5cbiAgICogQHJldHVybiB7T2JqZWN0PHN0cmluZywgKj59IEZlYXR1cmUgcHJvcGVydGllcy5cbiAgICogQGFwaVxuICAgKi9cblxuXG4gIFJlbmRlckZlYXR1cmUucHJvdG90eXBlLmdldFByb3BlcnRpZXMgPSBmdW5jdGlvbiAoKSB7XG4gICAgcmV0dXJuIHRoaXMucHJvcGVydGllc187XG4gIH07XG4gIC8qKlxuICAgKiBAcmV0dXJuIHtudW1iZXJ9IFN0cmlkZS5cbiAgICovXG5cblxuICBSZW5kZXJGZWF0dXJlLnByb3RvdHlwZS5nZXRTdHJpZGUgPSBmdW5jdGlvbiAoKSB7XG4gICAgcmV0dXJuIDI7XG4gIH07XG4gIC8qKlxuICAgKiBAcmV0dXJuIHt1bmRlZmluZWR9XG4gICAqL1xuXG5cbiAgUmVuZGVyRmVhdHVyZS5wcm90b3R5cGUuZ2V0U3R5bGVGdW5jdGlvbiA9IGZ1bmN0aW9uICgpIHtcbiAgICByZXR1cm4gdW5kZWZpbmVkO1xuICB9O1xuICAvKipcbiAgICogR2V0IHRoZSB0eXBlIG9mIHRoaXMgZmVhdHVyZSdzIGdlb21ldHJ5LlxuICAgKiBAcmV0dXJuIHtpbXBvcnQoXCIuLi9nZW9tL0dlb21ldHJ5VHlwZS5qc1wiKS5kZWZhdWx0fSBHZW9tZXRyeSB0eXBlLlxuICAgKiBAYXBpXG4gICAqL1xuXG5cbiAgUmVuZGVyRmVhdHVyZS5wcm90b3R5cGUuZ2V0VHlwZSA9IGZ1bmN0aW9uICgpIHtcbiAgICByZXR1cm4gdGhpcy50eXBlXztcbiAgfTtcbiAgLyoqXG4gICAqIFRyYW5zZm9ybSBnZW9tZXRyeSBjb29yZGluYXRlcyBmcm9tIHRpbGUgcGl4ZWwgc3BhY2UgdG8gcHJvamVjdGVkLlxuICAgKlxuICAgKiBAcGFyYW0ge2ltcG9ydChcIi4uL3Byb2ouanNcIikuUHJvamVjdGlvbkxpa2V9IHByb2plY3Rpb24gVGhlIGRhdGEgcHJvamVjdGlvblxuICAgKi9cblxuXG4gIFJlbmRlckZlYXR1cmUucHJvdG90eXBlLnRyYW5zZm9ybSA9IGZ1bmN0aW9uIChwcm9qZWN0aW9uKSB7XG4gICAgcHJvamVjdGlvbiA9IGdldFByb2plY3Rpb24ocHJvamVjdGlvbik7XG4gICAgdmFyIHBpeGVsRXh0ZW50ID0gcHJvamVjdGlvbi5nZXRFeHRlbnQoKTtcbiAgICB2YXIgcHJvamVjdGVkRXh0ZW50ID0gcHJvamVjdGlvbi5nZXRXb3JsZEV4dGVudCgpO1xuXG4gICAgaWYgKHBpeGVsRXh0ZW50ICYmIHByb2plY3RlZEV4dGVudCkge1xuICAgICAgdmFyIHNjYWxlID0gZ2V0SGVpZ2h0KHByb2plY3RlZEV4dGVudCkgLyBnZXRIZWlnaHQocGl4ZWxFeHRlbnQpO1xuICAgICAgY29tcG9zZVRyYW5zZm9ybSh0bXBUcmFuc2Zvcm0sIHByb2plY3RlZEV4dGVudFswXSwgcHJvamVjdGVkRXh0ZW50WzNdLCBzY2FsZSwgLXNjYWxlLCAwLCAwLCAwKTtcbiAgICAgIHRyYW5zZm9ybTJEKHRoaXMuZmxhdENvb3JkaW5hdGVzXywgMCwgdGhpcy5mbGF0Q29vcmRpbmF0ZXNfLmxlbmd0aCwgMiwgdG1wVHJhbnNmb3JtLCB0aGlzLmZsYXRDb29yZGluYXRlc18pO1xuICAgIH1cbiAgfTtcbiAgLyoqXG4gICAqIEByZXR1cm4ge0FycmF5PG51bWJlcj58QXJyYXk8QXJyYXk8bnVtYmVyPj59IEVuZHMgb3IgZW5kc3MuXG4gICAqL1xuXG5cbiAgUmVuZGVyRmVhdHVyZS5wcm90b3R5cGUuZ2V0RW5kcyA9IGZ1bmN0aW9uICgpIHtcbiAgICByZXR1cm4gdGhpcy5lbmRzXztcbiAgfTtcblxuICByZXR1cm4gUmVuZGVyRmVhdHVyZTtcbn0oKTtcblxuUmVuZGVyRmVhdHVyZS5wcm90b3R5cGUuZ2V0RW5kc3MgPSBSZW5kZXJGZWF0dXJlLnByb3RvdHlwZS5nZXRFbmRzO1xuLyoqXG4gKiBAcmV0dXJuIHtBcnJheTxudW1iZXI+fSBGbGF0IGNvb3JkaW5hdGVzLlxuICovXG5cblJlbmRlckZlYXR1cmUucHJvdG90eXBlLmdldEZsYXRDb29yZGluYXRlcyA9IFJlbmRlckZlYXR1cmUucHJvdG90eXBlLmdldE9yaWVudGVkRmxhdENvb3JkaW5hdGVzO1xuZXhwb3J0IGRlZmF1bHQgUmVuZGVyRmVhdHVyZTsiLCIvKipcbiAqIEBtb2R1bGUgb2wvZm9ybWF0L01WVFxuICovXG4vL0ZJWE1FIEltcGxlbWVudCBwcm9qZWN0aW9uIGhhbmRsaW5nXG52YXIgX19leHRlbmRzID0gdGhpcyAmJiB0aGlzLl9fZXh0ZW5kcyB8fCBmdW5jdGlvbiAoKSB7XG4gIHZhciBfZXh0ZW5kU3RhdGljcyA9IGZ1bmN0aW9uIGV4dGVuZFN0YXRpY3MoZCwgYikge1xuICAgIF9leHRlbmRTdGF0aWNzID0gT2JqZWN0LnNldFByb3RvdHlwZU9mIHx8IHtcbiAgICAgIF9fcHJvdG9fXzogW11cbiAgICB9IGluc3RhbmNlb2YgQXJyYXkgJiYgZnVuY3Rpb24gKGQsIGIpIHtcbiAgICAgIGQuX19wcm90b19fID0gYjtcbiAgICB9IHx8IGZ1bmN0aW9uIChkLCBiKSB7XG4gICAgICBmb3IgKHZhciBwIGluIGIpIHtcbiAgICAgICAgaWYgKE9iamVjdC5wcm90b3R5cGUuaGFzT3duUHJvcGVydHkuY2FsbChiLCBwKSkgZFtwXSA9IGJbcF07XG4gICAgICB9XG4gICAgfTtcblxuICAgIHJldHVybiBfZXh0ZW5kU3RhdGljcyhkLCBiKTtcbiAgfTtcblxuICByZXR1cm4gZnVuY3Rpb24gKGQsIGIpIHtcbiAgICBfZXh0ZW5kU3RhdGljcyhkLCBiKTtcblxuICAgIGZ1bmN0aW9uIF9fKCkge1xuICAgICAgdGhpcy5jb25zdHJ1Y3RvciA9IGQ7XG4gICAgfVxuXG4gICAgZC5wcm90b3R5cGUgPSBiID09PSBudWxsID8gT2JqZWN0LmNyZWF0ZShiKSA6IChfXy5wcm90b3R5cGUgPSBiLnByb3RvdHlwZSwgbmV3IF9fKCkpO1xuICB9O1xufSgpO1xuXG5pbXBvcnQgRmVhdHVyZUZvcm1hdCwgeyB0cmFuc2Zvcm1HZW9tZXRyeVdpdGhPcHRpb25zIH0gZnJvbSAnLi9GZWF0dXJlLmpzJztcbmltcG9ydCBGb3JtYXRUeXBlIGZyb20gJy4vRm9ybWF0VHlwZS5qcyc7XG5pbXBvcnQgR2VvbWV0cnlMYXlvdXQgZnJvbSAnLi4vZ2VvbS9HZW9tZXRyeUxheW91dC5qcyc7XG5pbXBvcnQgR2VvbWV0cnlUeXBlIGZyb20gJy4uL2dlb20vR2VvbWV0cnlUeXBlLmpzJztcbmltcG9ydCBMaW5lU3RyaW5nIGZyb20gJy4uL2dlb20vTGluZVN0cmluZy5qcyc7XG5pbXBvcnQgTXVsdGlMaW5lU3RyaW5nIGZyb20gJy4uL2dlb20vTXVsdGlMaW5lU3RyaW5nLmpzJztcbmltcG9ydCBNdWx0aVBvaW50IGZyb20gJy4uL2dlb20vTXVsdGlQb2ludC5qcyc7XG5pbXBvcnQgTXVsdGlQb2x5Z29uIGZyb20gJy4uL2dlb20vTXVsdGlQb2x5Z29uLmpzJztcbmltcG9ydCBQQkYgZnJvbSAncGJmJztcbmltcG9ydCBQb2ludCBmcm9tICcuLi9nZW9tL1BvaW50LmpzJztcbmltcG9ydCBQb2x5Z29uIGZyb20gJy4uL2dlb20vUG9seWdvbi5qcyc7XG5pbXBvcnQgUHJvamVjdGlvbiBmcm9tICcuLi9wcm9qL1Byb2plY3Rpb24uanMnO1xuaW1wb3J0IFJlbmRlckZlYXR1cmUgZnJvbSAnLi4vcmVuZGVyL0ZlYXR1cmUuanMnO1xuaW1wb3J0IFVuaXRzIGZyb20gJy4uL3Byb2ovVW5pdHMuanMnO1xuaW1wb3J0IHsgYXNzZXJ0IH0gZnJvbSAnLi4vYXNzZXJ0cy5qcyc7XG5pbXBvcnQgeyBnZXQgfSBmcm9tICcuLi9wcm9qLmpzJztcbmltcG9ydCB7IGxpbmVhclJpbmdJc0Nsb2Nrd2lzZSB9IGZyb20gJy4uL2dlb20vZmxhdC9vcmllbnQuanMnO1xuLyoqXG4gKiBAdHlwZWRlZiB7T2JqZWN0fSBPcHRpb25zXG4gKiBAcHJvcGVydHkge2ltcG9ydChcIi4uL0ZlYXR1cmUuanNcIikuRmVhdHVyZUNsYXNzfSBbZmVhdHVyZUNsYXNzXSBDbGFzcyBmb3IgZmVhdHVyZXMgcmV0dXJuZWQgYnlcbiAqIHtAbGluayBtb2R1bGU6b2wvZm9ybWF0L01WVCNyZWFkRmVhdHVyZXN9LiBTZXQgdG8ge0BsaW5rIG1vZHVsZTpvbC9GZWF0dXJlfkZlYXR1cmV9IHRvIGdldCBmdWxsIGVkaXRpbmcgYW5kIGdlb21ldHJ5XG4gKiBzdXBwb3J0IGF0IHRoZSBjb3N0IG9mIGRlY3JlYXNlZCByZW5kZXJpbmcgcGVyZm9ybWFuY2UuIFRoZSBkZWZhdWx0IGlzXG4gKiB7QGxpbmsgbW9kdWxlOm9sL3JlbmRlci9GZWF0dXJlflJlbmRlckZlYXR1cmV9LCB3aGljaCBpcyBvcHRpbWl6ZWQgZm9yIHJlbmRlcmluZyBhbmQgaGl0IGRldGVjdGlvbi5cbiAqIEBwcm9wZXJ0eSB7c3RyaW5nfSBbZ2VvbWV0cnlOYW1lPSdnZW9tZXRyeSddIEdlb21ldHJ5IG5hbWUgdG8gdXNlIHdoZW4gY3JlYXRpbmcgZmVhdHVyZXMuXG4gKiBAcHJvcGVydHkge3N0cmluZ30gW2xheWVyTmFtZT0nbGF5ZXInXSBOYW1lIG9mIHRoZSBmZWF0dXJlIGF0dHJpYnV0ZSB0aGF0IGhvbGRzIHRoZSBsYXllciBuYW1lLlxuICogQHByb3BlcnR5IHtBcnJheTxzdHJpbmc+fSBbbGF5ZXJzXSBMYXllcnMgdG8gcmVhZCBmZWF0dXJlcyBmcm9tLiBJZiBub3QgcHJvdmlkZWQsIGZlYXR1cmVzIHdpbGwgYmUgcmVhZCBmcm9tIGFsbFxuICogQHByb3BlcnR5IHtzdHJpbmd9IFtpZFByb3BlcnR5XSBPcHRpb25hbCBwcm9wZXJ0eSB0aGF0IHdpbGwgYmUgYXNzaWduZWQgYXMgdGhlIGZlYXR1cmUgaWQgYW5kIHJlbW92ZWQgZnJvbSB0aGUgcHJvcGVydGllcy5cbiAqIGxheWVycy5cbiAqL1xuXG4vKipcbiAqIEBjbGFzc2Rlc2NcbiAqIEZlYXR1cmUgZm9ybWF0IGZvciByZWFkaW5nIGRhdGEgaW4gdGhlIE1hcGJveCBNVlQgZm9ybWF0LlxuICpcbiAqIEBwYXJhbSB7T3B0aW9ucz19IG9wdF9vcHRpb25zIE9wdGlvbnMuXG4gKiBAYXBpXG4gKi9cblxudmFyIE1WVCA9XG4vKiogQGNsYXNzICovXG5mdW5jdGlvbiAoX3N1cGVyKSB7XG4gIF9fZXh0ZW5kcyhNVlQsIF9zdXBlcik7XG4gIC8qKlxuICAgKiBAcGFyYW0ge09wdGlvbnM9fSBvcHRfb3B0aW9ucyBPcHRpb25zLlxuICAgKi9cblxuXG4gIGZ1bmN0aW9uIE1WVChvcHRfb3B0aW9ucykge1xuICAgIHZhciBfdGhpcyA9IF9zdXBlci5jYWxsKHRoaXMpIHx8IHRoaXM7XG5cbiAgICB2YXIgb3B0aW9ucyA9IG9wdF9vcHRpb25zID8gb3B0X29wdGlvbnMgOiB7fTtcbiAgICAvKipcbiAgICAgKiBAdHlwZSB7UHJvamVjdGlvbn1cbiAgICAgKi9cblxuICAgIF90aGlzLmRhdGFQcm9qZWN0aW9uID0gbmV3IFByb2plY3Rpb24oe1xuICAgICAgY29kZTogJycsXG4gICAgICB1bml0czogVW5pdHMuVElMRV9QSVhFTFNcbiAgICB9KTtcbiAgICAvKipcbiAgICAgKiBAcHJpdmF0ZVxuICAgICAqIEB0eXBlIHtpbXBvcnQoXCIuLi9GZWF0dXJlLmpzXCIpLkZlYXR1cmVDbGFzc31cbiAgICAgKi9cblxuICAgIF90aGlzLmZlYXR1cmVDbGFzc18gPSBvcHRpb25zLmZlYXR1cmVDbGFzcyA/IG9wdGlvbnMuZmVhdHVyZUNsYXNzIDogUmVuZGVyRmVhdHVyZTtcbiAgICAvKipcbiAgICAgKiBAcHJpdmF0ZVxuICAgICAqIEB0eXBlIHtzdHJpbmd8dW5kZWZpbmVkfVxuICAgICAqL1xuXG4gICAgX3RoaXMuZ2VvbWV0cnlOYW1lXyA9IG9wdGlvbnMuZ2VvbWV0cnlOYW1lO1xuICAgIC8qKlxuICAgICAqIEBwcml2YXRlXG4gICAgICogQHR5cGUge3N0cmluZ31cbiAgICAgKi9cblxuICAgIF90aGlzLmxheWVyTmFtZV8gPSBvcHRpb25zLmxheWVyTmFtZSA/IG9wdGlvbnMubGF5ZXJOYW1lIDogJ2xheWVyJztcbiAgICAvKipcbiAgICAgKiBAcHJpdmF0ZVxuICAgICAqIEB0eXBlIHtBcnJheTxzdHJpbmc+fVxuICAgICAqL1xuXG4gICAgX3RoaXMubGF5ZXJzXyA9IG9wdGlvbnMubGF5ZXJzID8gb3B0aW9ucy5sYXllcnMgOiBudWxsO1xuICAgIC8qKlxuICAgICAqIEBwcml2YXRlXG4gICAgICogQHR5cGUge3N0cmluZ31cbiAgICAgKi9cblxuICAgIF90aGlzLmlkUHJvcGVydHlfID0gb3B0aW9ucy5pZFByb3BlcnR5O1xuICAgIHJldHVybiBfdGhpcztcbiAgfVxuICAvKipcbiAgICogUmVhZCB0aGUgcmF3IGdlb21ldHJ5IGZyb20gdGhlIHBiZiBvZmZzZXQgc3RvcmVkIGluIGEgcmF3IGZlYXR1cmUncyBnZW9tZXRyeVxuICAgKiBwcm9wZXJ0eS5cbiAgICogQHBhcmFtIHtQQkZ9IHBiZiBQQkYuXG4gICAqIEBwYXJhbSB7T2JqZWN0fSBmZWF0dXJlIFJhdyBmZWF0dXJlLlxuICAgKiBAcGFyYW0ge0FycmF5PG51bWJlcj59IGZsYXRDb29yZGluYXRlcyBBcnJheSB0byBzdG9yZSBmbGF0IGNvb3JkaW5hdGVzIGluLlxuICAgKiBAcGFyYW0ge0FycmF5PG51bWJlcj59IGVuZHMgQXJyYXkgdG8gc3RvcmUgZW5kcyBpbi5cbiAgICogQHByaXZhdGVcbiAgICovXG5cblxuICBNVlQucHJvdG90eXBlLnJlYWRSYXdHZW9tZXRyeV8gPSBmdW5jdGlvbiAocGJmLCBmZWF0dXJlLCBmbGF0Q29vcmRpbmF0ZXMsIGVuZHMpIHtcbiAgICBwYmYucG9zID0gZmVhdHVyZS5nZW9tZXRyeTtcbiAgICB2YXIgZW5kID0gcGJmLnJlYWRWYXJpbnQoKSArIHBiZi5wb3M7XG4gICAgdmFyIGNtZCA9IDE7XG4gICAgdmFyIGxlbmd0aCA9IDA7XG4gICAgdmFyIHggPSAwO1xuICAgIHZhciB5ID0gMDtcbiAgICB2YXIgY29vcmRzTGVuID0gMDtcbiAgICB2YXIgY3VycmVudEVuZCA9IDA7XG5cbiAgICB3aGlsZSAocGJmLnBvcyA8IGVuZCkge1xuICAgICAgaWYgKCFsZW5ndGgpIHtcbiAgICAgICAgdmFyIGNtZExlbiA9IHBiZi5yZWFkVmFyaW50KCk7XG4gICAgICAgIGNtZCA9IGNtZExlbiAmIDB4NztcbiAgICAgICAgbGVuZ3RoID0gY21kTGVuID4+IDM7XG4gICAgICB9XG5cbiAgICAgIGxlbmd0aC0tO1xuXG4gICAgICBpZiAoY21kID09PSAxIHx8IGNtZCA9PT0gMikge1xuICAgICAgICB4ICs9IHBiZi5yZWFkU1ZhcmludCgpO1xuICAgICAgICB5ICs9IHBiZi5yZWFkU1ZhcmludCgpO1xuXG4gICAgICAgIGlmIChjbWQgPT09IDEpIHtcbiAgICAgICAgICAvLyBtb3ZlVG9cbiAgICAgICAgICBpZiAoY29vcmRzTGVuID4gY3VycmVudEVuZCkge1xuICAgICAgICAgICAgZW5kcy5wdXNoKGNvb3Jkc0xlbik7XG4gICAgICAgICAgICBjdXJyZW50RW5kID0gY29vcmRzTGVuO1xuICAgICAgICAgIH1cbiAgICAgICAgfVxuXG4gICAgICAgIGZsYXRDb29yZGluYXRlcy5wdXNoKHgsIHkpO1xuICAgICAgICBjb29yZHNMZW4gKz0gMjtcbiAgICAgIH0gZWxzZSBpZiAoY21kID09PSA3KSB7XG4gICAgICAgIGlmIChjb29yZHNMZW4gPiBjdXJyZW50RW5kKSB7XG4gICAgICAgICAgLy8gY2xvc2UgcG9seWdvblxuICAgICAgICAgIGZsYXRDb29yZGluYXRlcy5wdXNoKGZsYXRDb29yZGluYXRlc1tjdXJyZW50RW5kXSwgZmxhdENvb3JkaW5hdGVzW2N1cnJlbnRFbmQgKyAxXSk7XG4gICAgICAgICAgY29vcmRzTGVuICs9IDI7XG4gICAgICAgIH1cbiAgICAgIH0gZWxzZSB7XG4gICAgICAgIGFzc2VydChmYWxzZSwgNTkpOyAvLyBJbnZhbGlkIGNvbW1hbmQgZm91bmQgaW4gdGhlIFBCRlxuICAgICAgfVxuICAgIH1cblxuICAgIGlmIChjb29yZHNMZW4gPiBjdXJyZW50RW5kKSB7XG4gICAgICBlbmRzLnB1c2goY29vcmRzTGVuKTtcbiAgICAgIGN1cnJlbnRFbmQgPSBjb29yZHNMZW47XG4gICAgfVxuICB9O1xuICAvKipcbiAgICogQHByaXZhdGVcbiAgICogQHBhcmFtIHtQQkZ9IHBiZiBQQkZcbiAgICogQHBhcmFtIHtPYmplY3R9IHJhd0ZlYXR1cmUgUmF3IE1hcGJveCBmZWF0dXJlLlxuICAgKiBAcGFyYW0ge2ltcG9ydChcIi4vRmVhdHVyZS5qc1wiKS5SZWFkT3B0aW9uc30gb3B0aW9ucyBSZWFkIG9wdGlvbnMuXG4gICAqIEByZXR1cm4ge2ltcG9ydChcIi4uL0ZlYXR1cmUuanNcIikuRmVhdHVyZUxpa2V9IEZlYXR1cmUuXG4gICAqL1xuXG5cbiAgTVZULnByb3RvdHlwZS5jcmVhdGVGZWF0dXJlXyA9IGZ1bmN0aW9uIChwYmYsIHJhd0ZlYXR1cmUsIG9wdGlvbnMpIHtcbiAgICB2YXIgdHlwZSA9IHJhd0ZlYXR1cmUudHlwZTtcblxuICAgIGlmICh0eXBlID09PSAwKSB7XG4gICAgICByZXR1cm4gbnVsbDtcbiAgICB9XG5cbiAgICB2YXIgZmVhdHVyZTtcbiAgICB2YXIgdmFsdWVzID0gcmF3RmVhdHVyZS5wcm9wZXJ0aWVzO1xuICAgIHZhciBpZDtcblxuICAgIGlmICghdGhpcy5pZFByb3BlcnR5Xykge1xuICAgICAgaWQgPSByYXdGZWF0dXJlLmlkO1xuICAgIH0gZWxzZSB7XG4gICAgICBpZCA9IHZhbHVlc1t0aGlzLmlkUHJvcGVydHlfXTtcbiAgICAgIGRlbGV0ZSB2YWx1ZXNbdGhpcy5pZFByb3BlcnR5X107XG4gICAgfVxuXG4gICAgdmFsdWVzW3RoaXMubGF5ZXJOYW1lX10gPSByYXdGZWF0dXJlLmxheWVyLm5hbWU7XG4gICAgdmFyIGZsYXRDb29yZGluYXRlcyA9IFtdO1xuICAgIHZhciBlbmRzID0gW107XG4gICAgdGhpcy5yZWFkUmF3R2VvbWV0cnlfKHBiZiwgcmF3RmVhdHVyZSwgZmxhdENvb3JkaW5hdGVzLCBlbmRzKTtcbiAgICB2YXIgZ2VvbWV0cnlUeXBlID0gZ2V0R2VvbWV0cnlUeXBlKHR5cGUsIGVuZHMubGVuZ3RoKTtcblxuICAgIGlmICh0aGlzLmZlYXR1cmVDbGFzc18gPT09IFJlbmRlckZlYXR1cmUpIHtcbiAgICAgIGZlYXR1cmUgPSBuZXcgdGhpcy5mZWF0dXJlQ2xhc3NfKGdlb21ldHJ5VHlwZSwgZmxhdENvb3JkaW5hdGVzLCBlbmRzLCB2YWx1ZXMsIGlkKTtcbiAgICAgIGZlYXR1cmUudHJhbnNmb3JtKG9wdGlvbnMuZGF0YVByb2plY3Rpb24pO1xuICAgIH0gZWxzZSB7XG4gICAgICB2YXIgZ2VvbSA9IHZvaWQgMDtcblxuICAgICAgaWYgKGdlb21ldHJ5VHlwZSA9PSBHZW9tZXRyeVR5cGUuUE9MWUdPTikge1xuICAgICAgICB2YXIgZW5kc3MgPSBbXTtcbiAgICAgICAgdmFyIG9mZnNldCA9IDA7XG4gICAgICAgIHZhciBwcmV2RW5kSW5kZXggPSAwO1xuXG4gICAgICAgIGZvciAodmFyIGkgPSAwLCBpaSA9IGVuZHMubGVuZ3RoOyBpIDwgaWk7ICsraSkge1xuICAgICAgICAgIHZhciBlbmQgPSBlbmRzW2ldOyAvLyBjbGFzc2lmaWVzIGFuIGFycmF5IG9mIHJpbmdzIGludG8gcG9seWdvbnMgd2l0aCBvdXRlciByaW5ncyBhbmQgaG9sZXNcblxuICAgICAgICAgIGlmICghbGluZWFyUmluZ0lzQ2xvY2t3aXNlKGZsYXRDb29yZGluYXRlcywgb2Zmc2V0LCBlbmQsIDIpKSB7XG4gICAgICAgICAgICBlbmRzcy5wdXNoKGVuZHMuc2xpY2UocHJldkVuZEluZGV4LCBpICsgMSkpO1xuICAgICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICBpZiAoZW5kc3MubGVuZ3RoID09PSAwKSB7XG4gICAgICAgICAgICAgIGNvbnRpbnVlO1xuICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICBlbmRzc1tlbmRzcy5sZW5ndGggLSAxXS5wdXNoKGVuZHNbcHJldkVuZEluZGV4XSk7XG4gICAgICAgICAgfVxuXG4gICAgICAgICAgcHJldkVuZEluZGV4ID0gaSArIDE7XG4gICAgICAgICAgb2Zmc2V0ID0gZW5kO1xuICAgICAgICB9XG5cbiAgICAgICAgaWYgKGVuZHNzLmxlbmd0aCA+IDEpIHtcbiAgICAgICAgICBnZW9tID0gbmV3IE11bHRpUG9seWdvbihmbGF0Q29vcmRpbmF0ZXMsIEdlb21ldHJ5TGF5b3V0LlhZLCBlbmRzcyk7XG4gICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgZ2VvbSA9IG5ldyBQb2x5Z29uKGZsYXRDb29yZGluYXRlcywgR2VvbWV0cnlMYXlvdXQuWFksIGVuZHMpO1xuICAgICAgICB9XG4gICAgICB9IGVsc2Uge1xuICAgICAgICBnZW9tID0gZ2VvbWV0cnlUeXBlID09PSBHZW9tZXRyeVR5cGUuUE9JTlQgPyBuZXcgUG9pbnQoZmxhdENvb3JkaW5hdGVzLCBHZW9tZXRyeUxheW91dC5YWSkgOiBnZW9tZXRyeVR5cGUgPT09IEdlb21ldHJ5VHlwZS5MSU5FX1NUUklORyA/IG5ldyBMaW5lU3RyaW5nKGZsYXRDb29yZGluYXRlcywgR2VvbWV0cnlMYXlvdXQuWFkpIDogZ2VvbWV0cnlUeXBlID09PSBHZW9tZXRyeVR5cGUuUE9MWUdPTiA/IG5ldyBQb2x5Z29uKGZsYXRDb29yZGluYXRlcywgR2VvbWV0cnlMYXlvdXQuWFksIGVuZHMpIDogZ2VvbWV0cnlUeXBlID09PSBHZW9tZXRyeVR5cGUuTVVMVElfUE9JTlQgPyBuZXcgTXVsdGlQb2ludChmbGF0Q29vcmRpbmF0ZXMsIEdlb21ldHJ5TGF5b3V0LlhZKSA6IGdlb21ldHJ5VHlwZSA9PT0gR2VvbWV0cnlUeXBlLk1VTFRJX0xJTkVfU1RSSU5HID8gbmV3IE11bHRpTGluZVN0cmluZyhmbGF0Q29vcmRpbmF0ZXMsIEdlb21ldHJ5TGF5b3V0LlhZLCBlbmRzKSA6IG51bGw7XG4gICAgICB9XG5cbiAgICAgIHZhciBjdG9yID1cbiAgICAgIC8qKiBAdHlwZSB7dHlwZW9mIGltcG9ydChcIi4uL0ZlYXR1cmUuanNcIikuZGVmYXVsdH0gKi9cbiAgICAgIHRoaXMuZmVhdHVyZUNsYXNzXztcbiAgICAgIGZlYXR1cmUgPSBuZXcgY3RvcigpO1xuXG4gICAgICBpZiAodGhpcy5nZW9tZXRyeU5hbWVfKSB7XG4gICAgICAgIGZlYXR1cmUuc2V0R2VvbWV0cnlOYW1lKHRoaXMuZ2VvbWV0cnlOYW1lXyk7XG4gICAgICB9XG5cbiAgICAgIHZhciBnZW9tZXRyeSA9IHRyYW5zZm9ybUdlb21ldHJ5V2l0aE9wdGlvbnMoZ2VvbSwgZmFsc2UsIG9wdGlvbnMpO1xuICAgICAgZmVhdHVyZS5zZXRHZW9tZXRyeShnZW9tZXRyeSk7XG4gICAgICBmZWF0dXJlLnNldElkKGlkKTtcbiAgICAgIGZlYXR1cmUuc2V0UHJvcGVydGllcyh2YWx1ZXMsIHRydWUpO1xuICAgIH1cblxuICAgIHJldHVybiBmZWF0dXJlO1xuICB9O1xuICAvKipcbiAgICogQHJldHVybiB7aW1wb3J0KFwiLi9Gb3JtYXRUeXBlLmpzXCIpLmRlZmF1bHR9IEZvcm1hdC5cbiAgICovXG5cblxuICBNVlQucHJvdG90eXBlLmdldFR5cGUgPSBmdW5jdGlvbiAoKSB7XG4gICAgcmV0dXJuIEZvcm1hdFR5cGUuQVJSQVlfQlVGRkVSO1xuICB9O1xuICAvKipcbiAgICogUmVhZCBhbGwgZmVhdHVyZXMuXG4gICAqXG4gICAqIEBwYXJhbSB7QXJyYXlCdWZmZXJ9IHNvdXJjZSBTb3VyY2UuXG4gICAqIEBwYXJhbSB7aW1wb3J0KFwiLi9GZWF0dXJlLmpzXCIpLlJlYWRPcHRpb25zPX0gb3B0X29wdGlvbnMgUmVhZCBvcHRpb25zLlxuICAgKiBAcmV0dXJuIHtBcnJheTxpbXBvcnQoXCIuLi9GZWF0dXJlLmpzXCIpLkZlYXR1cmVMaWtlPn0gRmVhdHVyZXMuXG4gICAqIEBhcGlcbiAgICovXG5cblxuICBNVlQucHJvdG90eXBlLnJlYWRGZWF0dXJlcyA9IGZ1bmN0aW9uIChzb3VyY2UsIG9wdF9vcHRpb25zKSB7XG4gICAgdmFyIGxheWVycyA9IHRoaXMubGF5ZXJzXztcbiAgICB2YXIgb3B0aW9ucyA9XG4gICAgLyoqIEB0eXBlIHtpbXBvcnQoXCIuL0ZlYXR1cmUuanNcIikuUmVhZE9wdGlvbnN9ICovXG4gICAgdGhpcy5hZGFwdE9wdGlvbnMob3B0X29wdGlvbnMpO1xuICAgIHZhciBkYXRhUHJvamVjdGlvbiA9IGdldChvcHRpb25zLmRhdGFQcm9qZWN0aW9uKTtcbiAgICBkYXRhUHJvamVjdGlvbi5zZXRXb3JsZEV4dGVudChvcHRpb25zLmV4dGVudCk7XG4gICAgb3B0aW9ucy5kYXRhUHJvamVjdGlvbiA9IGRhdGFQcm9qZWN0aW9uO1xuICAgIHZhciBwYmYgPSBuZXcgUEJGKFxuICAgIC8qKiBAdHlwZSB7QXJyYXlCdWZmZXJ9ICovXG4gICAgc291cmNlKTtcbiAgICB2YXIgcGJmTGF5ZXJzID0gcGJmLnJlYWRGaWVsZHMobGF5ZXJzUEJGUmVhZGVyLCB7fSk7XG4gICAgdmFyIGZlYXR1cmVzID0gW107XG5cbiAgICBmb3IgKHZhciBuYW1lXzEgaW4gcGJmTGF5ZXJzKSB7XG4gICAgICBpZiAobGF5ZXJzICYmIGxheWVycy5pbmRleE9mKG5hbWVfMSkgPT0gLTEpIHtcbiAgICAgICAgY29udGludWU7XG4gICAgICB9XG5cbiAgICAgIHZhciBwYmZMYXllciA9IHBiZkxheWVyc1tuYW1lXzFdO1xuICAgICAgdmFyIGV4dGVudCA9IHBiZkxheWVyID8gWzAsIDAsIHBiZkxheWVyLmV4dGVudCwgcGJmTGF5ZXIuZXh0ZW50XSA6IG51bGw7XG4gICAgICBkYXRhUHJvamVjdGlvbi5zZXRFeHRlbnQoZXh0ZW50KTtcblxuICAgICAgZm9yICh2YXIgaSA9IDAsIGlpID0gcGJmTGF5ZXIubGVuZ3RoOyBpIDwgaWk7ICsraSkge1xuICAgICAgICB2YXIgcmF3RmVhdHVyZSA9IHJlYWRSYXdGZWF0dXJlKHBiZiwgcGJmTGF5ZXIsIGkpO1xuICAgICAgICBmZWF0dXJlcy5wdXNoKHRoaXMuY3JlYXRlRmVhdHVyZV8ocGJmLCByYXdGZWF0dXJlLCBvcHRpb25zKSk7XG4gICAgICB9XG4gICAgfVxuXG4gICAgcmV0dXJuIGZlYXR1cmVzO1xuICB9O1xuICAvKipcbiAgICogUmVhZCB0aGUgcHJvamVjdGlvbiBmcm9tIHRoZSBzb3VyY2UuXG4gICAqXG4gICAqIEBwYXJhbSB7RG9jdW1lbnR8RWxlbWVudHxPYmplY3R8c3RyaW5nfSBzb3VyY2UgU291cmNlLlxuICAgKiBAcmV0dXJuIHtpbXBvcnQoXCIuLi9wcm9qL1Byb2plY3Rpb24uanNcIikuZGVmYXVsdH0gUHJvamVjdGlvbi5cbiAgICogQGFwaVxuICAgKi9cblxuXG4gIE1WVC5wcm90b3R5cGUucmVhZFByb2plY3Rpb24gPSBmdW5jdGlvbiAoc291cmNlKSB7XG4gICAgcmV0dXJuIHRoaXMuZGF0YVByb2plY3Rpb247XG4gIH07XG4gIC8qKlxuICAgKiBTZXRzIHRoZSBsYXllcnMgdGhhdCBmZWF0dXJlcyB3aWxsIGJlIHJlYWQgZnJvbS5cbiAgICogQHBhcmFtIHtBcnJheTxzdHJpbmc+fSBsYXllcnMgTGF5ZXJzLlxuICAgKiBAYXBpXG4gICAqL1xuXG5cbiAgTVZULnByb3RvdHlwZS5zZXRMYXllcnMgPSBmdW5jdGlvbiAobGF5ZXJzKSB7XG4gICAgdGhpcy5sYXllcnNfID0gbGF5ZXJzO1xuICB9O1xuXG4gIHJldHVybiBNVlQ7XG59KEZlYXR1cmVGb3JtYXQpO1xuLyoqXG4gKiBSZWFkZXIgY2FsbGJhY2sgZm9yIHBhcnNpbmcgbGF5ZXJzLlxuICogQHBhcmFtIHtudW1iZXJ9IHRhZyBUaGUgdGFnLlxuICogQHBhcmFtIHtPYmplY3R9IGxheWVycyBUaGUgbGF5ZXJzIG9iamVjdC5cbiAqIEBwYXJhbSB7UEJGfSBwYmYgVGhlIFBCRi5cbiAqL1xuXG5cbmZ1bmN0aW9uIGxheWVyc1BCRlJlYWRlcih0YWcsIGxheWVycywgcGJmKSB7XG4gIGlmICh0YWcgPT09IDMpIHtcbiAgICB2YXIgbGF5ZXIgPSB7XG4gICAgICBrZXlzOiBbXSxcbiAgICAgIHZhbHVlczogW10sXG4gICAgICBmZWF0dXJlczogW11cbiAgICB9O1xuICAgIHZhciBlbmQgPSBwYmYucmVhZFZhcmludCgpICsgcGJmLnBvcztcbiAgICBwYmYucmVhZEZpZWxkcyhsYXllclBCRlJlYWRlciwgbGF5ZXIsIGVuZCk7XG4gICAgbGF5ZXIubGVuZ3RoID0gbGF5ZXIuZmVhdHVyZXMubGVuZ3RoO1xuXG4gICAgaWYgKGxheWVyLmxlbmd0aCkge1xuICAgICAgbGF5ZXJzW2xheWVyLm5hbWVdID0gbGF5ZXI7XG4gICAgfVxuICB9XG59XG4vKipcbiAqIFJlYWRlciBjYWxsYmFjayBmb3IgcGFyc2luZyBsYXllci5cbiAqIEBwYXJhbSB7bnVtYmVyfSB0YWcgVGhlIHRhZy5cbiAqIEBwYXJhbSB7T2JqZWN0fSBsYXllciBUaGUgbGF5ZXIgb2JqZWN0LlxuICogQHBhcmFtIHtQQkZ9IHBiZiBUaGUgUEJGLlxuICovXG5cblxuZnVuY3Rpb24gbGF5ZXJQQkZSZWFkZXIodGFnLCBsYXllciwgcGJmKSB7XG4gIGlmICh0YWcgPT09IDE1KSB7XG4gICAgbGF5ZXIudmVyc2lvbiA9IHBiZi5yZWFkVmFyaW50KCk7XG4gIH0gZWxzZSBpZiAodGFnID09PSAxKSB7XG4gICAgbGF5ZXIubmFtZSA9IHBiZi5yZWFkU3RyaW5nKCk7XG4gIH0gZWxzZSBpZiAodGFnID09PSA1KSB7XG4gICAgbGF5ZXIuZXh0ZW50ID0gcGJmLnJlYWRWYXJpbnQoKTtcbiAgfSBlbHNlIGlmICh0YWcgPT09IDIpIHtcbiAgICBsYXllci5mZWF0dXJlcy5wdXNoKHBiZi5wb3MpO1xuICB9IGVsc2UgaWYgKHRhZyA9PT0gMykge1xuICAgIGxheWVyLmtleXMucHVzaChwYmYucmVhZFN0cmluZygpKTtcbiAgfSBlbHNlIGlmICh0YWcgPT09IDQpIHtcbiAgICB2YXIgdmFsdWUgPSBudWxsO1xuICAgIHZhciBlbmQgPSBwYmYucmVhZFZhcmludCgpICsgcGJmLnBvcztcblxuICAgIHdoaWxlIChwYmYucG9zIDwgZW5kKSB7XG4gICAgICB0YWcgPSBwYmYucmVhZFZhcmludCgpID4+IDM7XG4gICAgICB2YWx1ZSA9IHRhZyA9PT0gMSA/IHBiZi5yZWFkU3RyaW5nKCkgOiB0YWcgPT09IDIgPyBwYmYucmVhZEZsb2F0KCkgOiB0YWcgPT09IDMgPyBwYmYucmVhZERvdWJsZSgpIDogdGFnID09PSA0ID8gcGJmLnJlYWRWYXJpbnQ2NCgpIDogdGFnID09PSA1ID8gcGJmLnJlYWRWYXJpbnQoKSA6IHRhZyA9PT0gNiA/IHBiZi5yZWFkU1ZhcmludCgpIDogdGFnID09PSA3ID8gcGJmLnJlYWRCb29sZWFuKCkgOiBudWxsO1xuICAgIH1cblxuICAgIGxheWVyLnZhbHVlcy5wdXNoKHZhbHVlKTtcbiAgfVxufVxuLyoqXG4gKiBSZWFkZXIgY2FsbGJhY2sgZm9yIHBhcnNpbmcgZmVhdHVyZS5cbiAqIEBwYXJhbSB7bnVtYmVyfSB0YWcgVGhlIHRhZy5cbiAqIEBwYXJhbSB7T2JqZWN0fSBmZWF0dXJlIFRoZSBmZWF0dXJlIG9iamVjdC5cbiAqIEBwYXJhbSB7UEJGfSBwYmYgVGhlIFBCRi5cbiAqL1xuXG5cbmZ1bmN0aW9uIGZlYXR1cmVQQkZSZWFkZXIodGFnLCBmZWF0dXJlLCBwYmYpIHtcbiAgaWYgKHRhZyA9PSAxKSB7XG4gICAgZmVhdHVyZS5pZCA9IHBiZi5yZWFkVmFyaW50KCk7XG4gIH0gZWxzZSBpZiAodGFnID09IDIpIHtcbiAgICB2YXIgZW5kID0gcGJmLnJlYWRWYXJpbnQoKSArIHBiZi5wb3M7XG5cbiAgICB3aGlsZSAocGJmLnBvcyA8IGVuZCkge1xuICAgICAgdmFyIGtleSA9IGZlYXR1cmUubGF5ZXIua2V5c1twYmYucmVhZFZhcmludCgpXTtcbiAgICAgIHZhciB2YWx1ZSA9IGZlYXR1cmUubGF5ZXIudmFsdWVzW3BiZi5yZWFkVmFyaW50KCldO1xuICAgICAgZmVhdHVyZS5wcm9wZXJ0aWVzW2tleV0gPSB2YWx1ZTtcbiAgICB9XG4gIH0gZWxzZSBpZiAodGFnID09IDMpIHtcbiAgICBmZWF0dXJlLnR5cGUgPSBwYmYucmVhZFZhcmludCgpO1xuICB9IGVsc2UgaWYgKHRhZyA9PSA0KSB7XG4gICAgZmVhdHVyZS5nZW9tZXRyeSA9IHBiZi5wb3M7XG4gIH1cbn1cbi8qKlxuICogUmVhZCBhIHJhdyBmZWF0dXJlIGZyb20gdGhlIHBiZiBvZmZzZXQgc3RvcmVkIGF0IGluZGV4IGBpYCBpbiB0aGUgcmF3IGxheWVyLlxuICogQHBhcmFtIHtQQkZ9IHBiZiBQQkYuXG4gKiBAcGFyYW0ge09iamVjdH0gbGF5ZXIgUmF3IGxheWVyLlxuICogQHBhcmFtIHtudW1iZXJ9IGkgSW5kZXggb2YgdGhlIGZlYXR1cmUgaW4gdGhlIHJhdyBsYXllcidzIGBmZWF0dXJlc2AgYXJyYXkuXG4gKiBAcmV0dXJuIHtPYmplY3R9IFJhdyBmZWF0dXJlLlxuICovXG5cblxuZnVuY3Rpb24gcmVhZFJhd0ZlYXR1cmUocGJmLCBsYXllciwgaSkge1xuICBwYmYucG9zID0gbGF5ZXIuZmVhdHVyZXNbaV07XG4gIHZhciBlbmQgPSBwYmYucmVhZFZhcmludCgpICsgcGJmLnBvcztcbiAgdmFyIGZlYXR1cmUgPSB7XG4gICAgbGF5ZXI6IGxheWVyLFxuICAgIHR5cGU6IDAsXG4gICAgcHJvcGVydGllczoge31cbiAgfTtcbiAgcGJmLnJlYWRGaWVsZHMoZmVhdHVyZVBCRlJlYWRlciwgZmVhdHVyZSwgZW5kKTtcbiAgcmV0dXJuIGZlYXR1cmU7XG59XG4vKipcbiAqIEBwYXJhbSB7bnVtYmVyfSB0eXBlIFRoZSByYXcgZmVhdHVyZSdzIGdlb21ldHJ5IHR5cGVcbiAqIEBwYXJhbSB7bnVtYmVyfSBudW1FbmRzIE51bWJlciBvZiBlbmRzIG9mIHRoZSBmbGF0IGNvb3JkaW5hdGVzIG9mIHRoZVxuICogZ2VvbWV0cnkuXG4gKiBAcmV0dXJuIHtpbXBvcnQoXCIuLi9nZW9tL0dlb21ldHJ5VHlwZS5qc1wiKS5kZWZhdWx0fSBUaGUgZ2VvbWV0cnkgdHlwZS5cbiAqL1xuXG5cbmZ1bmN0aW9uIGdldEdlb21ldHJ5VHlwZSh0eXBlLCBudW1FbmRzKSB7XG4gIC8qKiBAdHlwZSB7aW1wb3J0KFwiLi4vZ2VvbS9HZW9tZXRyeVR5cGUuanNcIikuZGVmYXVsdH0gKi9cbiAgdmFyIGdlb21ldHJ5VHlwZTtcblxuICBpZiAodHlwZSA9PT0gMSkge1xuICAgIGdlb21ldHJ5VHlwZSA9IG51bUVuZHMgPT09IDEgPyBHZW9tZXRyeVR5cGUuUE9JTlQgOiBHZW9tZXRyeVR5cGUuTVVMVElfUE9JTlQ7XG4gIH0gZWxzZSBpZiAodHlwZSA9PT0gMikge1xuICAgIGdlb21ldHJ5VHlwZSA9IG51bUVuZHMgPT09IDEgPyBHZW9tZXRyeVR5cGUuTElORV9TVFJJTkcgOiBHZW9tZXRyeVR5cGUuTVVMVElfTElORV9TVFJJTkc7XG4gIH0gZWxzZSBpZiAodHlwZSA9PT0gMykge1xuICAgIGdlb21ldHJ5VHlwZSA9IEdlb21ldHJ5VHlwZS5QT0xZR09OOyAvLyBNdWx0aVBvbHlnb24gbm90IHJlbGV2YW50IGZvciByZW5kZXJpbmcgLSB3aW5kaW5nIG9yZGVyIGRldGVybWluZXNcbiAgICAvLyBvdXRlciByaW5ncyBvZiBwb2x5Z29ucy5cbiAgfVxuXG4gIHJldHVybiBnZW9tZXRyeVR5cGU7XG59XG5cbmV4cG9ydCBkZWZhdWx0IE1WVDsiLCIvKipcbiAqIEBtb2R1bGUgb2wvc3RydWN0cy9SQnVzaFxuICovXG5pbXBvcnQgUkJ1c2hfIGZyb20gJ3JidXNoJztcbmltcG9ydCB7IGNyZWF0ZU9yVXBkYXRlLCBlcXVhbHMgfSBmcm9tICcuLi9leHRlbnQuanMnO1xuaW1wb3J0IHsgZ2V0VWlkIH0gZnJvbSAnLi4vdXRpbC5qcyc7XG5pbXBvcnQgeyBpc0VtcHR5IH0gZnJvbSAnLi4vb2JqLmpzJztcbi8qKlxuICogQHR5cGVkZWYge09iamVjdH0gRW50cnlcbiAqIEBwcm9wZXJ0eSB7bnVtYmVyfSBtaW5YXG4gKiBAcHJvcGVydHkge251bWJlcn0gbWluWVxuICogQHByb3BlcnR5IHtudW1iZXJ9IG1heFhcbiAqIEBwcm9wZXJ0eSB7bnVtYmVyfSBtYXhZXG4gKiBAcHJvcGVydHkge09iamVjdH0gW3ZhbHVlXVxuICovXG5cbi8qKlxuICogQGNsYXNzZGVzY1xuICogV3JhcHBlciBhcm91bmQgdGhlIFJCdXNoIGJ5IFZsYWRpbWlyIEFnYWZvbmtpbi5cbiAqIFNlZSBodHRwczovL2dpdGh1Yi5jb20vbW91cm5lci9yYnVzaC5cbiAqXG4gKiBAdGVtcGxhdGUgVFxuICovXG5cbnZhciBSQnVzaCA9XG4vKiogQGNsYXNzICovXG5mdW5jdGlvbiAoKSB7XG4gIC8qKlxuICAgKiBAcGFyYW0ge251bWJlcj19IG9wdF9tYXhFbnRyaWVzIE1heCBlbnRyaWVzLlxuICAgKi9cbiAgZnVuY3Rpb24gUkJ1c2gob3B0X21heEVudHJpZXMpIHtcbiAgICAvKipcbiAgICAgKiBAcHJpdmF0ZVxuICAgICAqL1xuICAgIHRoaXMucmJ1c2hfID0gbmV3IFJCdXNoXyhvcHRfbWF4RW50cmllcyk7XG4gICAgLyoqXG4gICAgICogQSBtYXBwaW5nIGJldHdlZW4gdGhlIG9iamVjdHMgYWRkZWQgdG8gdGhpcyByYnVzaCB3cmFwcGVyXG4gICAgICogYW5kIHRoZSBvYmplY3RzIHRoYXQgYXJlIGFjdHVhbGx5IGFkZGVkIHRvIHRoZSBpbnRlcm5hbCByYnVzaC5cbiAgICAgKiBAcHJpdmF0ZVxuICAgICAqIEB0eXBlIHtPYmplY3Q8c3RyaW5nLCBFbnRyeT59XG4gICAgICovXG5cbiAgICB0aGlzLml0ZW1zXyA9IHt9O1xuICB9XG4gIC8qKlxuICAgKiBJbnNlcnQgYSB2YWx1ZSBpbnRvIHRoZSBSQnVzaC5cbiAgICogQHBhcmFtIHtpbXBvcnQoXCIuLi9leHRlbnQuanNcIikuRXh0ZW50fSBleHRlbnQgRXh0ZW50LlxuICAgKiBAcGFyYW0ge1R9IHZhbHVlIFZhbHVlLlxuICAgKi9cblxuXG4gIFJCdXNoLnByb3RvdHlwZS5pbnNlcnQgPSBmdW5jdGlvbiAoZXh0ZW50LCB2YWx1ZSkge1xuICAgIC8qKiBAdHlwZSB7RW50cnl9ICovXG4gICAgdmFyIGl0ZW0gPSB7XG4gICAgICBtaW5YOiBleHRlbnRbMF0sXG4gICAgICBtaW5ZOiBleHRlbnRbMV0sXG4gICAgICBtYXhYOiBleHRlbnRbMl0sXG4gICAgICBtYXhZOiBleHRlbnRbM10sXG4gICAgICB2YWx1ZTogdmFsdWVcbiAgICB9O1xuICAgIHRoaXMucmJ1c2hfLmluc2VydChpdGVtKTtcbiAgICB0aGlzLml0ZW1zX1tnZXRVaWQodmFsdWUpXSA9IGl0ZW07XG4gIH07XG4gIC8qKlxuICAgKiBCdWxrLWluc2VydCB2YWx1ZXMgaW50byB0aGUgUkJ1c2guXG4gICAqIEBwYXJhbSB7QXJyYXk8aW1wb3J0KFwiLi4vZXh0ZW50LmpzXCIpLkV4dGVudD59IGV4dGVudHMgRXh0ZW50cy5cbiAgICogQHBhcmFtIHtBcnJheTxUPn0gdmFsdWVzIFZhbHVlcy5cbiAgICovXG5cblxuICBSQnVzaC5wcm90b3R5cGUubG9hZCA9IGZ1bmN0aW9uIChleHRlbnRzLCB2YWx1ZXMpIHtcbiAgICB2YXIgaXRlbXMgPSBuZXcgQXJyYXkodmFsdWVzLmxlbmd0aCk7XG5cbiAgICBmb3IgKHZhciBpID0gMCwgbCA9IHZhbHVlcy5sZW5ndGg7IGkgPCBsOyBpKyspIHtcbiAgICAgIHZhciBleHRlbnQgPSBleHRlbnRzW2ldO1xuICAgICAgdmFyIHZhbHVlID0gdmFsdWVzW2ldO1xuICAgICAgLyoqIEB0eXBlIHtFbnRyeX0gKi9cblxuICAgICAgdmFyIGl0ZW0gPSB7XG4gICAgICAgIG1pblg6IGV4dGVudFswXSxcbiAgICAgICAgbWluWTogZXh0ZW50WzFdLFxuICAgICAgICBtYXhYOiBleHRlbnRbMl0sXG4gICAgICAgIG1heFk6IGV4dGVudFszXSxcbiAgICAgICAgdmFsdWU6IHZhbHVlXG4gICAgICB9O1xuICAgICAgaXRlbXNbaV0gPSBpdGVtO1xuICAgICAgdGhpcy5pdGVtc19bZ2V0VWlkKHZhbHVlKV0gPSBpdGVtO1xuICAgIH1cblxuICAgIHRoaXMucmJ1c2hfLmxvYWQoaXRlbXMpO1xuICB9O1xuICAvKipcbiAgICogUmVtb3ZlIGEgdmFsdWUgZnJvbSB0aGUgUkJ1c2guXG4gICAqIEBwYXJhbSB7VH0gdmFsdWUgVmFsdWUuXG4gICAqIEByZXR1cm4ge2Jvb2xlYW59IFJlbW92ZWQuXG4gICAqL1xuXG5cbiAgUkJ1c2gucHJvdG90eXBlLnJlbW92ZSA9IGZ1bmN0aW9uICh2YWx1ZSkge1xuICAgIHZhciB1aWQgPSBnZXRVaWQodmFsdWUpOyAvLyBnZXQgdGhlIG9iamVjdCBpbiB3aGljaCB0aGUgdmFsdWUgd2FzIHdyYXBwZWQgd2hlbiBhZGRpbmcgdG8gdGhlXG4gICAgLy8gaW50ZXJuYWwgcmJ1c2guIHRoZW4gdXNlIHRoYXQgb2JqZWN0IHRvIGRvIHRoZSByZW1vdmFsLlxuXG4gICAgdmFyIGl0ZW0gPSB0aGlzLml0ZW1zX1t1aWRdO1xuICAgIGRlbGV0ZSB0aGlzLml0ZW1zX1t1aWRdO1xuICAgIHJldHVybiB0aGlzLnJidXNoXy5yZW1vdmUoaXRlbSkgIT09IG51bGw7XG4gIH07XG4gIC8qKlxuICAgKiBVcGRhdGUgdGhlIGV4dGVudCBvZiBhIHZhbHVlIGluIHRoZSBSQnVzaC5cbiAgICogQHBhcmFtIHtpbXBvcnQoXCIuLi9leHRlbnQuanNcIikuRXh0ZW50fSBleHRlbnQgRXh0ZW50LlxuICAgKiBAcGFyYW0ge1R9IHZhbHVlIFZhbHVlLlxuICAgKi9cblxuXG4gIFJCdXNoLnByb3RvdHlwZS51cGRhdGUgPSBmdW5jdGlvbiAoZXh0ZW50LCB2YWx1ZSkge1xuICAgIHZhciBpdGVtID0gdGhpcy5pdGVtc19bZ2V0VWlkKHZhbHVlKV07XG4gICAgdmFyIGJib3ggPSBbaXRlbS5taW5YLCBpdGVtLm1pblksIGl0ZW0ubWF4WCwgaXRlbS5tYXhZXTtcblxuICAgIGlmICghZXF1YWxzKGJib3gsIGV4dGVudCkpIHtcbiAgICAgIHRoaXMucmVtb3ZlKHZhbHVlKTtcbiAgICAgIHRoaXMuaW5zZXJ0KGV4dGVudCwgdmFsdWUpO1xuICAgIH1cbiAgfTtcbiAgLyoqXG4gICAqIFJldHVybiBhbGwgdmFsdWVzIGluIHRoZSBSQnVzaC5cbiAgICogQHJldHVybiB7QXJyYXk8VD59IEFsbC5cbiAgICovXG5cblxuICBSQnVzaC5wcm90b3R5cGUuZ2V0QWxsID0gZnVuY3Rpb24gKCkge1xuICAgIHZhciBpdGVtcyA9IHRoaXMucmJ1c2hfLmFsbCgpO1xuICAgIHJldHVybiBpdGVtcy5tYXAoZnVuY3Rpb24gKGl0ZW0pIHtcbiAgICAgIHJldHVybiBpdGVtLnZhbHVlO1xuICAgIH0pO1xuICB9O1xuICAvKipcbiAgICogUmV0dXJuIGFsbCB2YWx1ZXMgaW4gdGhlIGdpdmVuIGV4dGVudC5cbiAgICogQHBhcmFtIHtpbXBvcnQoXCIuLi9leHRlbnQuanNcIikuRXh0ZW50fSBleHRlbnQgRXh0ZW50LlxuICAgKiBAcmV0dXJuIHtBcnJheTxUPn0gQWxsIGluIGV4dGVudC5cbiAgICovXG5cblxuICBSQnVzaC5wcm90b3R5cGUuZ2V0SW5FeHRlbnQgPSBmdW5jdGlvbiAoZXh0ZW50KSB7XG4gICAgLyoqIEB0eXBlIHtFbnRyeX0gKi9cbiAgICB2YXIgYmJveCA9IHtcbiAgICAgIG1pblg6IGV4dGVudFswXSxcbiAgICAgIG1pblk6IGV4dGVudFsxXSxcbiAgICAgIG1heFg6IGV4dGVudFsyXSxcbiAgICAgIG1heFk6IGV4dGVudFszXVxuICAgIH07XG4gICAgdmFyIGl0ZW1zID0gdGhpcy5yYnVzaF8uc2VhcmNoKGJib3gpO1xuICAgIHJldHVybiBpdGVtcy5tYXAoZnVuY3Rpb24gKGl0ZW0pIHtcbiAgICAgIHJldHVybiBpdGVtLnZhbHVlO1xuICAgIH0pO1xuICB9O1xuICAvKipcbiAgICogQ2FsbHMgYSBjYWxsYmFjayBmdW5jdGlvbiB3aXRoIGVhY2ggdmFsdWUgaW4gdGhlIHRyZWUuXG4gICAqIElmIHRoZSBjYWxsYmFjayByZXR1cm5zIGEgdHJ1dGh5IHZhbHVlLCB0aGlzIHZhbHVlIGlzIHJldHVybmVkIHdpdGhvdXRcbiAgICogY2hlY2tpbmcgdGhlIHJlc3Qgb2YgdGhlIHRyZWUuXG4gICAqIEBwYXJhbSB7ZnVuY3Rpb24oVCk6ICp9IGNhbGxiYWNrIENhbGxiYWNrLlxuICAgKiBAcmV0dXJuIHsqfSBDYWxsYmFjayByZXR1cm4gdmFsdWUuXG4gICAqL1xuXG5cbiAgUkJ1c2gucHJvdG90eXBlLmZvckVhY2ggPSBmdW5jdGlvbiAoY2FsbGJhY2spIHtcbiAgICByZXR1cm4gdGhpcy5mb3JFYWNoXyh0aGlzLmdldEFsbCgpLCBjYWxsYmFjayk7XG4gIH07XG4gIC8qKlxuICAgKiBDYWxscyBhIGNhbGxiYWNrIGZ1bmN0aW9uIHdpdGggZWFjaCB2YWx1ZSBpbiB0aGUgcHJvdmlkZWQgZXh0ZW50LlxuICAgKiBAcGFyYW0ge2ltcG9ydChcIi4uL2V4dGVudC5qc1wiKS5FeHRlbnR9IGV4dGVudCBFeHRlbnQuXG4gICAqIEBwYXJhbSB7ZnVuY3Rpb24oVCk6ICp9IGNhbGxiYWNrIENhbGxiYWNrLlxuICAgKiBAcmV0dXJuIHsqfSBDYWxsYmFjayByZXR1cm4gdmFsdWUuXG4gICAqL1xuXG5cbiAgUkJ1c2gucHJvdG90eXBlLmZvckVhY2hJbkV4dGVudCA9IGZ1bmN0aW9uIChleHRlbnQsIGNhbGxiYWNrKSB7XG4gICAgcmV0dXJuIHRoaXMuZm9yRWFjaF8odGhpcy5nZXRJbkV4dGVudChleHRlbnQpLCBjYWxsYmFjayk7XG4gIH07XG4gIC8qKlxuICAgKiBAcGFyYW0ge0FycmF5PFQ+fSB2YWx1ZXMgVmFsdWVzLlxuICAgKiBAcGFyYW0ge2Z1bmN0aW9uKFQpOiAqfSBjYWxsYmFjayBDYWxsYmFjay5cbiAgICogQHByaXZhdGVcbiAgICogQHJldHVybiB7Kn0gQ2FsbGJhY2sgcmV0dXJuIHZhbHVlLlxuICAgKi9cblxuXG4gIFJCdXNoLnByb3RvdHlwZS5mb3JFYWNoXyA9IGZ1bmN0aW9uICh2YWx1ZXMsIGNhbGxiYWNrKSB7XG4gICAgdmFyIHJlc3VsdDtcblxuICAgIGZvciAodmFyIGkgPSAwLCBsID0gdmFsdWVzLmxlbmd0aDsgaSA8IGw7IGkrKykge1xuICAgICAgcmVzdWx0ID0gY2FsbGJhY2sodmFsdWVzW2ldKTtcblxuICAgICAgaWYgKHJlc3VsdCkge1xuICAgICAgICByZXR1cm4gcmVzdWx0O1xuICAgICAgfVxuICAgIH1cblxuICAgIHJldHVybiByZXN1bHQ7XG4gIH07XG4gIC8qKlxuICAgKiBAcmV0dXJuIHtib29sZWFufSBJcyBlbXB0eS5cbiAgICovXG5cblxuICBSQnVzaC5wcm90b3R5cGUuaXNFbXB0eSA9IGZ1bmN0aW9uICgpIHtcbiAgICByZXR1cm4gaXNFbXB0eSh0aGlzLml0ZW1zXyk7XG4gIH07XG4gIC8qKlxuICAgKiBSZW1vdmUgYWxsIHZhbHVlcyBmcm9tIHRoZSBSQnVzaC5cbiAgICovXG5cblxuICBSQnVzaC5wcm90b3R5cGUuY2xlYXIgPSBmdW5jdGlvbiAoKSB7XG4gICAgdGhpcy5yYnVzaF8uY2xlYXIoKTtcbiAgICB0aGlzLml0ZW1zXyA9IHt9O1xuICB9O1xuICAvKipcbiAgICogQHBhcmFtIHtpbXBvcnQoXCIuLi9leHRlbnQuanNcIikuRXh0ZW50PX0gb3B0X2V4dGVudCBFeHRlbnQuXG4gICAqIEByZXR1cm4ge2ltcG9ydChcIi4uL2V4dGVudC5qc1wiKS5FeHRlbnR9IEV4dGVudC5cbiAgICovXG5cblxuICBSQnVzaC5wcm90b3R5cGUuZ2V0RXh0ZW50ID0gZnVuY3Rpb24gKG9wdF9leHRlbnQpIHtcbiAgICB2YXIgZGF0YSA9IHRoaXMucmJ1c2hfLnRvSlNPTigpO1xuICAgIHJldHVybiBjcmVhdGVPclVwZGF0ZShkYXRhLm1pblgsIGRhdGEubWluWSwgZGF0YS5tYXhYLCBkYXRhLm1heFksIG9wdF9leHRlbnQpO1xuICB9O1xuICAvKipcbiAgICogQHBhcmFtIHtSQnVzaH0gcmJ1c2ggUi1UcmVlLlxuICAgKi9cblxuXG4gIFJCdXNoLnByb3RvdHlwZS5jb25jYXQgPSBmdW5jdGlvbiAocmJ1c2gpIHtcbiAgICB0aGlzLnJidXNoXy5sb2FkKHJidXNoLnJidXNoXy5hbGwoKSk7XG5cbiAgICBmb3IgKHZhciBpIGluIHJidXNoLml0ZW1zXykge1xuICAgICAgdGhpcy5pdGVtc19baV0gPSByYnVzaC5pdGVtc19baV07XG4gICAgfVxuICB9O1xuXG4gIHJldHVybiBSQnVzaDtcbn0oKTtcblxuZXhwb3J0IGRlZmF1bHQgUkJ1c2g7IiwiLyoqXG4gKiBAbW9kdWxlIG9sL3NvdXJjZS9WZWN0b3JFdmVudFR5cGVcbiAqL1xuXG4vKipcbiAqIEBlbnVtIHtzdHJpbmd9XG4gKi9cbmV4cG9ydCBkZWZhdWx0IHtcbiAgLyoqXG4gICAqIFRyaWdnZXJlZCB3aGVuIGEgZmVhdHVyZSBpcyBhZGRlZCB0byB0aGUgc291cmNlLlxuICAgKiBAZXZlbnQgbW9kdWxlOm9sL3NvdXJjZS9WZWN0b3IuVmVjdG9yU291cmNlRXZlbnQjYWRkZmVhdHVyZVxuICAgKiBAYXBpXG4gICAqL1xuICBBRERGRUFUVVJFOiAnYWRkZmVhdHVyZScsXG5cbiAgLyoqXG4gICAqIFRyaWdnZXJlZCB3aGVuIGEgZmVhdHVyZSBpcyB1cGRhdGVkLlxuICAgKiBAZXZlbnQgbW9kdWxlOm9sL3NvdXJjZS9WZWN0b3IuVmVjdG9yU291cmNlRXZlbnQjY2hhbmdlZmVhdHVyZVxuICAgKiBAYXBpXG4gICAqL1xuICBDSEFOR0VGRUFUVVJFOiAnY2hhbmdlZmVhdHVyZScsXG5cbiAgLyoqXG4gICAqIFRyaWdnZXJlZCB3aGVuIHRoZSBjbGVhciBtZXRob2QgaXMgY2FsbGVkIG9uIHRoZSBzb3VyY2UuXG4gICAqIEBldmVudCBtb2R1bGU6b2wvc291cmNlL1ZlY3Rvci5WZWN0b3JTb3VyY2VFdmVudCNjbGVhclxuICAgKiBAYXBpXG4gICAqL1xuICBDTEVBUjogJ2NsZWFyJyxcblxuICAvKipcbiAgICogVHJpZ2dlcmVkIHdoZW4gYSBmZWF0dXJlIGlzIHJlbW92ZWQgZnJvbSB0aGUgc291cmNlLlxuICAgKiBTZWUge0BsaW5rIG1vZHVsZTpvbC9zb3VyY2UvVmVjdG9yI2NsZWFyIHNvdXJjZS5jbGVhcigpfSBmb3IgZXhjZXB0aW9ucy5cbiAgICogQGV2ZW50IG1vZHVsZTpvbC9zb3VyY2UvVmVjdG9yLlZlY3RvclNvdXJjZUV2ZW50I3JlbW92ZWZlYXR1cmVcbiAgICogQGFwaVxuICAgKi9cbiAgUkVNT1ZFRkVBVFVSRTogJ3JlbW92ZWZlYXR1cmUnLFxuXG4gIC8qKlxuICAgKiBUcmlnZ2VyZWQgd2hlbiBmZWF0dXJlcyBzdGFydHMgbG9hZGluZy5cbiAgICogQGV2ZW50IG1vZHVsZTpvbC9zb3VyY2UvVmVjdG9yLlZlY3RvclNvdXJjZUV2ZW50I2ZlYXR1cmVzbG9hZHN0YXJ0XG4gICAqIEBhcGlcbiAgICovXG4gIEZFQVRVUkVTTE9BRFNUQVJUOiAnZmVhdHVyZXNsb2Fkc3RhcnQnLFxuXG4gIC8qKlxuICAgKiBUcmlnZ2VyZWQgd2hlbiBmZWF0dXJlcyBmaW5pc2hlcyBsb2FkaW5nLlxuICAgKiBAZXZlbnQgbW9kdWxlOm9sL3NvdXJjZS9WZWN0b3IuVmVjdG9yU291cmNlRXZlbnQjZmVhdHVyZXNsb2FkZW5kXG4gICAqIEBhcGlcbiAgICovXG4gIEZFQVRVUkVTTE9BREVORDogJ2ZlYXR1cmVzbG9hZGVuZCcsXG5cbiAgLyoqXG4gICAqIFRyaWdnZXJlZCBpZiBmZWF0dXJlIGxvYWRpbmcgcmVzdWx0cyBpbiBhbiBlcnJvci5cbiAgICogQGV2ZW50IG1vZHVsZTpvbC9zb3VyY2UvVmVjdG9yLlZlY3RvclNvdXJjZUV2ZW50I2ZlYXR1cmVzbG9hZGVycm9yXG4gICAqIEBhcGlcbiAgICovXG4gIEZFQVRVUkVTTE9BREVSUk9SOiAnZmVhdHVyZXNsb2FkZXJyb3InXG59OyIsIi8qKlxuICogQG1vZHVsZSBvbC9sb2FkaW5nc3RyYXRlZ3lcbiAqL1xuXG4vKipcbiAqIFN0cmF0ZWd5IGZ1bmN0aW9uIGZvciBsb2FkaW5nIGFsbCBmZWF0dXJlcyB3aXRoIGEgc2luZ2xlIHJlcXVlc3QuXG4gKiBAcGFyYW0ge2ltcG9ydChcIi4vZXh0ZW50LmpzXCIpLkV4dGVudH0gZXh0ZW50IEV4dGVudC5cbiAqIEBwYXJhbSB7bnVtYmVyfSByZXNvbHV0aW9uIFJlc29sdXRpb24uXG4gKiBAcmV0dXJuIHtBcnJheTxpbXBvcnQoXCIuL2V4dGVudC5qc1wiKS5FeHRlbnQ+fSBFeHRlbnRzLlxuICogQGFwaVxuICovXG5leHBvcnQgZnVuY3Rpb24gYWxsKGV4dGVudCwgcmVzb2x1dGlvbikge1xuICByZXR1cm4gW1stSW5maW5pdHksIC1JbmZpbml0eSwgSW5maW5pdHksIEluZmluaXR5XV07XG59XG4vKipcbiAqIFN0cmF0ZWd5IGZ1bmN0aW9uIGZvciBsb2FkaW5nIGZlYXR1cmVzIGJhc2VkIG9uIHRoZSB2aWV3J3MgZXh0ZW50IGFuZFxuICogcmVzb2x1dGlvbi5cbiAqIEBwYXJhbSB7aW1wb3J0KFwiLi9leHRlbnQuanNcIikuRXh0ZW50fSBleHRlbnQgRXh0ZW50LlxuICogQHBhcmFtIHtudW1iZXJ9IHJlc29sdXRpb24gUmVzb2x1dGlvbi5cbiAqIEByZXR1cm4ge0FycmF5PGltcG9ydChcIi4vZXh0ZW50LmpzXCIpLkV4dGVudD59IEV4dGVudHMuXG4gKiBAYXBpXG4gKi9cblxuZXhwb3J0IGZ1bmN0aW9uIGJib3goZXh0ZW50LCByZXNvbHV0aW9uKSB7XG4gIHJldHVybiBbZXh0ZW50XTtcbn1cbi8qKlxuICogQ3JlYXRlcyBhIHN0cmF0ZWd5IGZ1bmN0aW9uIGZvciBsb2FkaW5nIGZlYXR1cmVzIGJhc2VkIG9uIGEgdGlsZSBncmlkLlxuICogQHBhcmFtIHtpbXBvcnQoXCIuL3RpbGVncmlkL1RpbGVHcmlkLmpzXCIpLmRlZmF1bHR9IHRpbGVHcmlkIFRpbGUgZ3JpZC5cbiAqIEByZXR1cm4ge2Z1bmN0aW9uKGltcG9ydChcIi4vZXh0ZW50LmpzXCIpLkV4dGVudCwgbnVtYmVyKTogQXJyYXk8aW1wb3J0KFwiLi9leHRlbnQuanNcIikuRXh0ZW50Pn0gTG9hZGluZyBzdHJhdGVneS5cbiAqIEBhcGlcbiAqL1xuXG5leHBvcnQgZnVuY3Rpb24gdGlsZSh0aWxlR3JpZCkge1xuICByZXR1cm4gKFxuICAgIC8qKlxuICAgICAqIEBwYXJhbSB7aW1wb3J0KFwiLi9leHRlbnQuanNcIikuRXh0ZW50fSBleHRlbnQgRXh0ZW50LlxuICAgICAqIEBwYXJhbSB7bnVtYmVyfSByZXNvbHV0aW9uIFJlc29sdXRpb24uXG4gICAgICogQHJldHVybiB7QXJyYXk8aW1wb3J0KFwiLi9leHRlbnQuanNcIikuRXh0ZW50Pn0gRXh0ZW50cy5cbiAgICAgKi9cbiAgICBmdW5jdGlvbiAoZXh0ZW50LCByZXNvbHV0aW9uKSB7XG4gICAgICB2YXIgeiA9IHRpbGVHcmlkLmdldFpGb3JSZXNvbHV0aW9uKHJlc29sdXRpb24pO1xuICAgICAgdmFyIHRpbGVSYW5nZSA9IHRpbGVHcmlkLmdldFRpbGVSYW5nZUZvckV4dGVudEFuZFooZXh0ZW50LCB6KTtcbiAgICAgIC8qKiBAdHlwZSB7QXJyYXk8aW1wb3J0KFwiLi9leHRlbnQuanNcIikuRXh0ZW50Pn0gKi9cblxuICAgICAgdmFyIGV4dGVudHMgPSBbXTtcbiAgICAgIC8qKiBAdHlwZSB7aW1wb3J0KFwiLi90aWxlY29vcmQuanNcIikuVGlsZUNvb3JkfSAqL1xuXG4gICAgICB2YXIgdGlsZUNvb3JkID0gW3osIDAsIDBdO1xuXG4gICAgICBmb3IgKHRpbGVDb29yZFsxXSA9IHRpbGVSYW5nZS5taW5YOyB0aWxlQ29vcmRbMV0gPD0gdGlsZVJhbmdlLm1heFg7ICsrdGlsZUNvb3JkWzFdKSB7XG4gICAgICAgIGZvciAodGlsZUNvb3JkWzJdID0gdGlsZVJhbmdlLm1pblk7IHRpbGVDb29yZFsyXSA8PSB0aWxlUmFuZ2UubWF4WTsgKyt0aWxlQ29vcmRbMl0pIHtcbiAgICAgICAgICBleHRlbnRzLnB1c2godGlsZUdyaWQuZ2V0VGlsZUNvb3JkRXh0ZW50KHRpbGVDb29yZCkpO1xuICAgICAgICB9XG4gICAgICB9XG5cbiAgICAgIHJldHVybiBleHRlbnRzO1xuICAgIH1cbiAgKTtcbn0iLCIvKipcbiAqIEBtb2R1bGUgb2wvc291cmNlL1ZlY3RvclxuICovXG52YXIgX19leHRlbmRzID0gdGhpcyAmJiB0aGlzLl9fZXh0ZW5kcyB8fCBmdW5jdGlvbiAoKSB7XG4gIHZhciBfZXh0ZW5kU3RhdGljcyA9IGZ1bmN0aW9uIGV4dGVuZFN0YXRpY3MoZCwgYikge1xuICAgIF9leHRlbmRTdGF0aWNzID0gT2JqZWN0LnNldFByb3RvdHlwZU9mIHx8IHtcbiAgICAgIF9fcHJvdG9fXzogW11cbiAgICB9IGluc3RhbmNlb2YgQXJyYXkgJiYgZnVuY3Rpb24gKGQsIGIpIHtcbiAgICAgIGQuX19wcm90b19fID0gYjtcbiAgICB9IHx8IGZ1bmN0aW9uIChkLCBiKSB7XG4gICAgICBmb3IgKHZhciBwIGluIGIpIHtcbiAgICAgICAgaWYgKE9iamVjdC5wcm90b3R5cGUuaGFzT3duUHJvcGVydHkuY2FsbChiLCBwKSkgZFtwXSA9IGJbcF07XG4gICAgICB9XG4gICAgfTtcblxuICAgIHJldHVybiBfZXh0ZW5kU3RhdGljcyhkLCBiKTtcbiAgfTtcblxuICByZXR1cm4gZnVuY3Rpb24gKGQsIGIpIHtcbiAgICBfZXh0ZW5kU3RhdGljcyhkLCBiKTtcblxuICAgIGZ1bmN0aW9uIF9fKCkge1xuICAgICAgdGhpcy5jb25zdHJ1Y3RvciA9IGQ7XG4gICAgfVxuXG4gICAgZC5wcm90b3R5cGUgPSBiID09PSBudWxsID8gT2JqZWN0LmNyZWF0ZShiKSA6IChfXy5wcm90b3R5cGUgPSBiLnByb3RvdHlwZSwgbmV3IF9fKCkpO1xuICB9O1xufSgpO1xuXG5pbXBvcnQgQ29sbGVjdGlvbiBmcm9tICcuLi9Db2xsZWN0aW9uLmpzJztcbmltcG9ydCBDb2xsZWN0aW9uRXZlbnRUeXBlIGZyb20gJy4uL0NvbGxlY3Rpb25FdmVudFR5cGUuanMnO1xuaW1wb3J0IEV2ZW50IGZyb20gJy4uL2V2ZW50cy9FdmVudC5qcyc7XG5pbXBvcnQgRXZlbnRUeXBlIGZyb20gJy4uL2V2ZW50cy9FdmVudFR5cGUuanMnO1xuaW1wb3J0IE9iamVjdEV2ZW50VHlwZSBmcm9tICcuLi9PYmplY3RFdmVudFR5cGUuanMnO1xuaW1wb3J0IFJCdXNoIGZyb20gJy4uL3N0cnVjdHMvUkJ1c2guanMnO1xuaW1wb3J0IFNvdXJjZSBmcm9tICcuL1NvdXJjZS5qcyc7XG5pbXBvcnQgU291cmNlU3RhdGUgZnJvbSAnLi9TdGF0ZS5qcyc7XG5pbXBvcnQgVmVjdG9yRXZlbnRUeXBlIGZyb20gJy4vVmVjdG9yRXZlbnRUeXBlLmpzJztcbmltcG9ydCB7IFRSVUUsIFZPSUQgfSBmcm9tICcuLi9mdW5jdGlvbnMuanMnO1xuaW1wb3J0IHsgYWxsIGFzIGFsbFN0cmF0ZWd5IH0gZnJvbSAnLi4vbG9hZGluZ3N0cmF0ZWd5LmpzJztcbmltcG9ydCB7IGFzc2VydCB9IGZyb20gJy4uL2Fzc2VydHMuanMnO1xuaW1wb3J0IHsgY29udGFpbnNFeHRlbnQsIGVxdWFscyB9IGZyb20gJy4uL2V4dGVudC5qcyc7XG5pbXBvcnQgeyBleHRlbmQgfSBmcm9tICcuLi9hcnJheS5qcyc7XG5pbXBvcnQgeyBnZXRVaWQgfSBmcm9tICcuLi91dGlsLmpzJztcbmltcG9ydCB7IGdldFZhbHVlcywgaXNFbXB0eSB9IGZyb20gJy4uL29iai5qcyc7XG5pbXBvcnQgeyBsaXN0ZW4sIHVubGlzdGVuQnlLZXkgfSBmcm9tICcuLi9ldmVudHMuanMnO1xuaW1wb3J0IHsgeGhyIH0gZnJvbSAnLi4vZmVhdHVyZWxvYWRlci5qcyc7XG4vKipcbiAqIEEgZnVuY3Rpb24gdGhhdCB0YWtlcyBhbiB7QGxpbmsgbW9kdWxlOm9sL2V4dGVudH5FeHRlbnR9IGFuZCBhIHJlc29sdXRpb24gYXMgYXJndW1lbnRzLCBhbmRcbiAqIHJldHVybnMgYW4gYXJyYXkgb2Yge0BsaW5rIG1vZHVsZTpvbC9leHRlbnR+RXh0ZW50fSB3aXRoIHRoZSBleHRlbnRzIHRvIGxvYWQuIFVzdWFsbHkgdGhpc1xuICogaXMgb25lIG9mIHRoZSBzdGFuZGFyZCB7QGxpbmsgbW9kdWxlOm9sL2xvYWRpbmdzdHJhdGVneX0gc3RyYXRlZ2llcy5cbiAqXG4gKiBAdHlwZWRlZiB7ZnVuY3Rpb24oaW1wb3J0KFwiLi4vZXh0ZW50LmpzXCIpLkV4dGVudCwgbnVtYmVyKTogQXJyYXk8aW1wb3J0KFwiLi4vZXh0ZW50LmpzXCIpLkV4dGVudD59IExvYWRpbmdTdHJhdGVneVxuICogQGFwaVxuICovXG5cbi8qKlxuICogQGNsYXNzZGVzY1xuICogRXZlbnRzIGVtaXR0ZWQgYnkge0BsaW5rIG1vZHVsZTpvbC9zb3VyY2UvVmVjdG9yfSBpbnN0YW5jZXMgYXJlIGluc3RhbmNlcyBvZiB0aGlzXG4gKiB0eXBlLlxuICogQHRlbXBsYXRlIHtpbXBvcnQoXCIuLi9nZW9tL0dlb21ldHJ5LmpzXCIpLmRlZmF1bHR9IEdlb21ldHJ5XG4gKi9cblxudmFyIFZlY3RvclNvdXJjZUV2ZW50ID1cbi8qKiBAY2xhc3MgKi9cbmZ1bmN0aW9uIChfc3VwZXIpIHtcbiAgX19leHRlbmRzKFZlY3RvclNvdXJjZUV2ZW50LCBfc3VwZXIpO1xuICAvKipcbiAgICogQHBhcmFtIHtzdHJpbmd9IHR5cGUgVHlwZS5cbiAgICogQHBhcmFtIHtpbXBvcnQoXCIuLi9GZWF0dXJlLmpzXCIpLmRlZmF1bHQ8R2VvbWV0cnk+PX0gb3B0X2ZlYXR1cmUgRmVhdHVyZS5cbiAgICogQHBhcmFtIHtBcnJheTxpbXBvcnQoXCIuLi9GZWF0dXJlLmpzXCIpLmRlZmF1bHQ8R2VvbWV0cnk+Pj19IG9wdF9mZWF0dXJlcyBGZWF0dXJlcy5cbiAgICovXG5cblxuICBmdW5jdGlvbiBWZWN0b3JTb3VyY2VFdmVudCh0eXBlLCBvcHRfZmVhdHVyZSwgb3B0X2ZlYXR1cmVzKSB7XG4gICAgdmFyIF90aGlzID0gX3N1cGVyLmNhbGwodGhpcywgdHlwZSkgfHwgdGhpcztcbiAgICAvKipcbiAgICAgKiBUaGUgYWRkZWQgb3IgcmVtb3ZlZCBmZWF0dXJlIGZvciB0aGUgYEFEREZFQVRVUkVgIGFuZCBgUkVNT1ZFRkVBVFVSRWAgZXZlbnRzLCBgdW5kZWZpbmVkYCBvdGhlcndpc2UuXG4gICAgICogQHR5cGUge2ltcG9ydChcIi4uL0ZlYXR1cmUuanNcIikuZGVmYXVsdDxHZW9tZXRyeT58dW5kZWZpbmVkfVxuICAgICAqIEBhcGlcbiAgICAgKi9cblxuXG4gICAgX3RoaXMuZmVhdHVyZSA9IG9wdF9mZWF0dXJlO1xuICAgIC8qKlxuICAgICAqIFRoZSBsb2FkZWQgZmVhdHVyZXMgZm9yIHRoZSBgRkVBVFVSRVNMT0FERURgIGV2ZW50LCBgdW5kZWZpbmVkYCBvdGhlcndpc2UuXG4gICAgICogQHR5cGUge0FycmF5PGltcG9ydChcIi4uL0ZlYXR1cmUuanNcIikuZGVmYXVsdDxHZW9tZXRyeT4+fHVuZGVmaW5lZH1cbiAgICAgKiBAYXBpXG4gICAgICovXG5cbiAgICBfdGhpcy5mZWF0dXJlcyA9IG9wdF9mZWF0dXJlcztcbiAgICByZXR1cm4gX3RoaXM7XG4gIH1cblxuICByZXR1cm4gVmVjdG9yU291cmNlRXZlbnQ7XG59KEV2ZW50KTtcblxuZXhwb3J0IHsgVmVjdG9yU291cmNlRXZlbnQgfTtcbi8qKlxuICogQHR5cGVkZWYge09iamVjdH0gT3B0aW9uc1xuICogQHByb3BlcnR5IHtpbXBvcnQoXCIuL1NvdXJjZS5qc1wiKS5BdHRyaWJ1dGlvbkxpa2V9IFthdHRyaWJ1dGlvbnNdIEF0dHJpYnV0aW9ucy5cbiAqIEBwcm9wZXJ0eSB7QXJyYXk8aW1wb3J0KFwiLi4vRmVhdHVyZS5qc1wiKS5kZWZhdWx0PnxDb2xsZWN0aW9uPGltcG9ydChcIi4uL0ZlYXR1cmUuanNcIikuZGVmYXVsdD59IFtmZWF0dXJlc11cbiAqIEZlYXR1cmVzLiBJZiBwcm92aWRlZCBhcyB7QGxpbmsgbW9kdWxlOm9sL0NvbGxlY3Rpb259LCB0aGUgZmVhdHVyZXMgaW4gdGhlIHNvdXJjZVxuICogYW5kIHRoZSBjb2xsZWN0aW9uIHdpbGwgc3RheSBpbiBzeW5jLlxuICogQHByb3BlcnR5IHtpbXBvcnQoXCIuLi9mb3JtYXQvRmVhdHVyZS5qc1wiKS5kZWZhdWx0fSBbZm9ybWF0XSBUaGUgZmVhdHVyZSBmb3JtYXQgdXNlZCBieSB0aGUgWEhSXG4gKiBmZWF0dXJlIGxvYWRlciB3aGVuIGB1cmxgIGlzIHNldC4gUmVxdWlyZWQgaWYgYHVybGAgaXMgc2V0LCBvdGhlcndpc2UgaWdub3JlZC5cbiAqIEBwcm9wZXJ0eSB7aW1wb3J0KFwiLi4vZmVhdHVyZWxvYWRlci5qc1wiKS5GZWF0dXJlTG9hZGVyfSBbbG9hZGVyXVxuICogVGhlIGxvYWRlciBmdW5jdGlvbiB1c2VkIHRvIGxvYWQgZmVhdHVyZXMsIGZyb20gYSByZW1vdGUgc291cmNlIGZvciBleGFtcGxlLlxuICogSWYgdGhpcyBpcyBub3Qgc2V0IGFuZCBgdXJsYCBpcyBzZXQsIHRoZSBzb3VyY2Ugd2lsbCBjcmVhdGUgYW5kIHVzZSBhbiBYSFJcbiAqIGZlYXR1cmUgbG9hZGVyLlxuICpcbiAqIEV4YW1wbGU6XG4gKlxuICogYGBganNcbiAqIGltcG9ydCB7VmVjdG9yfSBmcm9tICdvbC9zb3VyY2UnO1xuICogaW1wb3J0IHtHZW9KU09OfSBmcm9tICdvbC9mb3JtYXQnO1xuICogaW1wb3J0IHtiYm94fSBmcm9tICdvbC9sb2FkaW5nc3RyYXRlZ3knO1xuICpcbiAqIHZhciB2ZWN0b3JTb3VyY2UgPSBuZXcgVmVjdG9yKHtcbiAqICAgZm9ybWF0OiBuZXcgR2VvSlNPTigpLFxuICogICBsb2FkZXI6IGZ1bmN0aW9uKGV4dGVudCwgcmVzb2x1dGlvbiwgcHJvamVjdGlvbikge1xuICogICAgICB2YXIgcHJvaiA9IHByb2plY3Rpb24uZ2V0Q29kZSgpO1xuICogICAgICB2YXIgdXJsID0gJ2h0dHBzOi8vYWhvY2V2YXIuY29tL2dlb3NlcnZlci93ZnM/c2VydmljZT1XRlMmJyArXG4gKiAgICAgICAgICAndmVyc2lvbj0xLjEuMCZyZXF1ZXN0PUdldEZlYXR1cmUmdHlwZW5hbWU9b3NtOndhdGVyX2FyZWFzJicgK1xuICogICAgICAgICAgJ291dHB1dEZvcm1hdD1hcHBsaWNhdGlvbi9qc29uJnNyc25hbWU9JyArIHByb2ogKyAnJicgK1xuICogICAgICAgICAgJ2Jib3g9JyArIGV4dGVudC5qb2luKCcsJykgKyAnLCcgKyBwcm9qO1xuICogICAgICB2YXIgeGhyID0gbmV3IFhNTEh0dHBSZXF1ZXN0KCk7XG4gKiAgICAgIHhoci5vcGVuKCdHRVQnLCB1cmwpO1xuICogICAgICB2YXIgb25FcnJvciA9IGZ1bmN0aW9uKCkge1xuICogICAgICAgIHZlY3RvclNvdXJjZS5yZW1vdmVMb2FkZWRFeHRlbnQoZXh0ZW50KTtcbiAqICAgICAgfVxuICogICAgICB4aHIub25lcnJvciA9IG9uRXJyb3I7XG4gKiAgICAgIHhoci5vbmxvYWQgPSBmdW5jdGlvbigpIHtcbiAqICAgICAgICBpZiAoeGhyLnN0YXR1cyA9PSAyMDApIHtcbiAqICAgICAgICAgIHZlY3RvclNvdXJjZS5hZGRGZWF0dXJlcyhcbiAqICAgICAgICAgICAgICB2ZWN0b3JTb3VyY2UuZ2V0Rm9ybWF0KCkucmVhZEZlYXR1cmVzKHhoci5yZXNwb25zZVRleHQpKTtcbiAqICAgICAgICB9IGVsc2Uge1xuICogICAgICAgICAgb25FcnJvcigpO1xuICogICAgICAgIH1cbiAqICAgICAgfVxuICogICAgICB4aHIuc2VuZCgpO1xuICogICAgfSxcbiAqICAgIHN0cmF0ZWd5OiBiYm94XG4gKiAgfSk7XG4gKiBgYGBcbiAqIEBwcm9wZXJ0eSB7Ym9vbGVhbn0gW292ZXJsYXBzPXRydWVdIFRoaXMgc291cmNlIG1heSBoYXZlIG92ZXJsYXBwaW5nIGdlb21ldHJpZXMuXG4gKiBTZXR0aW5nIHRoaXMgdG8gYGZhbHNlYCAoZS5nLiBmb3Igc291cmNlcyB3aXRoIHBvbHlnb25zIHRoYXQgcmVwcmVzZW50IGFkbWluaXN0cmF0aXZlXG4gKiBib3VuZGFyaWVzIG9yIFRvcG9KU09OIHNvdXJjZXMpIGFsbG93cyB0aGUgcmVuZGVyZXIgdG8gb3B0aW1pc2UgZmlsbCBhbmRcbiAqIHN0cm9rZSBvcGVyYXRpb25zLlxuICogQHByb3BlcnR5IHtMb2FkaW5nU3RyYXRlZ3l9IFtzdHJhdGVneV0gVGhlIGxvYWRpbmcgc3RyYXRlZ3kgdG8gdXNlLlxuICogQnkgZGVmYXVsdCBhbiB7QGxpbmsgbW9kdWxlOm9sL2xvYWRpbmdzdHJhdGVneX5hbGx9XG4gKiBzdHJhdGVneSBpcyB1c2VkLCBhIG9uZS1vZmYgc3RyYXRlZ3kgd2hpY2ggbG9hZHMgYWxsIGZlYXR1cmVzIGF0IG9uY2UuXG4gKiBAcHJvcGVydHkge3N0cmluZ3xpbXBvcnQoXCIuLi9mZWF0dXJlbG9hZGVyLmpzXCIpLkZlYXR1cmVVcmxGdW5jdGlvbn0gW3VybF1cbiAqIFNldHRpbmcgdGhpcyBvcHRpb24gaW5zdHJ1Y3RzIHRoZSBzb3VyY2UgdG8gbG9hZCBmZWF0dXJlcyB1c2luZyBhbiBYSFIgbG9hZGVyXG4gKiAoc2VlIHtAbGluayBtb2R1bGU6b2wvZmVhdHVyZWxvYWRlcn54aHJ9KS4gVXNlIGEgYHN0cmluZ2AgYW5kIGFuXG4gKiB7QGxpbmsgbW9kdWxlOm9sL2xvYWRpbmdzdHJhdGVneX5hbGx9IGZvciBhIG9uZS1vZmYgZG93bmxvYWQgb2YgYWxsIGZlYXR1cmVzIGZyb21cbiAqIHRoZSBnaXZlbiBVUkwuIFVzZSBhIHtAbGluayBtb2R1bGU6b2wvZmVhdHVyZWxvYWRlcn5GZWF0dXJlVXJsRnVuY3Rpb259IHRvIGdlbmVyYXRlIHRoZSB1cmwgd2l0aFxuICogb3RoZXIgbG9hZGluZyBzdHJhdGVnaWVzLlxuICogUmVxdWlyZXMgYGZvcm1hdGAgdG8gYmUgc2V0IGFzIHdlbGwuXG4gKiBXaGVuIGRlZmF1bHQgWEhSIGZlYXR1cmUgbG9hZGVyIGlzIHByb3ZpZGVkLCB0aGUgZmVhdHVyZXMgd2lsbFxuICogYmUgdHJhbnNmb3JtZWQgZnJvbSB0aGUgZGF0YSBwcm9qZWN0aW9uIHRvIHRoZSB2aWV3IHByb2plY3Rpb25cbiAqIGR1cmluZyBwYXJzaW5nLiBJZiB5b3VyIHJlbW90ZSBkYXRhIHNvdXJjZSBkb2VzIG5vdCBhZHZlcnRpc2UgaXRzIHByb2plY3Rpb25cbiAqIHByb3Blcmx5LCB0aGlzIHRyYW5zZm9ybWF0aW9uIHdpbGwgYmUgaW5jb3JyZWN0LiBGb3Igc29tZSBmb3JtYXRzLCB0aGVcbiAqIGRlZmF1bHQgcHJvamVjdGlvbiAodXN1YWxseSBFUFNHOjQzMjYpIGNhbiBiZSBvdmVycmlkZGVuIGJ5IHNldHRpbmcgdGhlXG4gKiBkYXRhUHJvamVjdGlvbiBjb25zdHJ1Y3RvciBvcHRpb24gb24gdGhlIGZvcm1hdC5cbiAqIE5vdGUgdGhhdCBpZiBhIHNvdXJjZSBjb250YWlucyBub24tZmVhdHVyZSBkYXRhLCBzdWNoIGFzIGEgR2VvSlNPTiBnZW9tZXRyeVxuICogb3IgYSBLTUwgTmV0d29ya0xpbmssIHRoZXNlIHdpbGwgYmUgaWdub3JlZC4gVXNlIGEgY3VzdG9tIGxvYWRlciB0byBsb2FkIHRoZXNlLlxuICogQHByb3BlcnR5IHtib29sZWFufSBbdXNlU3BhdGlhbEluZGV4PXRydWVdXG4gKiBCeSBkZWZhdWx0LCBhbiBSVHJlZSBpcyB1c2VkIGFzIHNwYXRpYWwgaW5kZXguIFdoZW4gZmVhdHVyZXMgYXJlIHJlbW92ZWQgYW5kXG4gKiBhZGRlZCBmcmVxdWVudGx5LCBhbmQgdGhlIHRvdGFsIG51bWJlciBvZiBmZWF0dXJlcyBpcyBsb3csIHNldHRpbmcgdGhpcyB0b1xuICogYGZhbHNlYCBtYXkgaW1wcm92ZSBwZXJmb3JtYW5jZS5cbiAqXG4gKiBOb3RlIHRoYXRcbiAqIHtAbGluayBtb2R1bGU6b2wvc291cmNlL1ZlY3Rvcn5WZWN0b3JTb3VyY2UjZ2V0RmVhdHVyZXNJbkV4dGVudH0sXG4gKiB7QGxpbmsgbW9kdWxlOm9sL3NvdXJjZS9WZWN0b3J+VmVjdG9yU291cmNlI2dldENsb3Nlc3RGZWF0dXJlVG9Db29yZGluYXRlfSBhbmRcbiAqIHtAbGluayBtb2R1bGU6b2wvc291cmNlL1ZlY3Rvcn5WZWN0b3JTb3VyY2UjZ2V0RXh0ZW50fSBjYW5ub3QgYmUgdXNlZCB3aGVuIGB1c2VTcGF0aWFsSW5kZXhgIGlzXG4gKiBzZXQgdG8gYGZhbHNlYCwgYW5kIHtAbGluayBtb2R1bGU6b2wvc291cmNlL1ZlY3Rvcn5WZWN0b3JTb3VyY2UjZm9yRWFjaEZlYXR1cmVJbkV4dGVudH0gd2lsbCBsb29wXG4gKiB0aHJvdWdoIGFsbCBmZWF0dXJlcy5cbiAqXG4gKiBXaGVuIHNldCB0byBgZmFsc2VgLCB0aGUgZmVhdHVyZXMgd2lsbCBiZSBtYWludGFpbmVkIGluIGFuXG4gKiB7QGxpbmsgbW9kdWxlOm9sL0NvbGxlY3Rpb259LCB3aGljaCBjYW4gYmUgcmV0cmlldmVkIHRocm91Z2hcbiAqIHtAbGluayBtb2R1bGU6b2wvc291cmNlL1ZlY3Rvcn5WZWN0b3JTb3VyY2UjZ2V0RmVhdHVyZXNDb2xsZWN0aW9ufS5cbiAqIEBwcm9wZXJ0eSB7Ym9vbGVhbn0gW3dyYXBYPXRydWVdIFdyYXAgdGhlIHdvcmxkIGhvcml6b250YWxseS4gRm9yIHZlY3RvciBlZGl0aW5nIGFjcm9zcyB0aGVcbiAqIC0xODDCsCBhbmQgMTgwwrAgbWVyaWRpYW5zIHRvIHdvcmsgcHJvcGVybHksIHRoaXMgc2hvdWxkIGJlIHNldCB0byBgZmFsc2VgLiBUaGVcbiAqIHJlc3VsdGluZyBnZW9tZXRyeSBjb29yZGluYXRlcyB3aWxsIHRoZW4gZXhjZWVkIHRoZSB3b3JsZCBib3VuZHMuXG4gKi9cblxuLyoqXG4gKiBAY2xhc3NkZXNjXG4gKiBQcm92aWRlcyBhIHNvdXJjZSBvZiBmZWF0dXJlcyBmb3IgdmVjdG9yIGxheWVycy4gVmVjdG9yIGZlYXR1cmVzIHByb3ZpZGVkXG4gKiBieSB0aGlzIHNvdXJjZSBhcmUgc3VpdGFibGUgZm9yIGVkaXRpbmcuIFNlZSB7QGxpbmsgbW9kdWxlOm9sL3NvdXJjZS9WZWN0b3JUaWxlflZlY3RvclRpbGV9IGZvclxuICogdmVjdG9yIGRhdGEgdGhhdCBpcyBvcHRpbWl6ZWQgZm9yIHJlbmRlcmluZy5cbiAqXG4gKiBAZmlyZXMgVmVjdG9yU291cmNlRXZlbnRcbiAqIEBhcGlcbiAqIEB0ZW1wbGF0ZSB7aW1wb3J0KFwiLi4vZ2VvbS9HZW9tZXRyeS5qc1wiKS5kZWZhdWx0fSBHZW9tZXRyeVxuICovXG5cbnZhciBWZWN0b3JTb3VyY2UgPVxuLyoqIEBjbGFzcyAqL1xuZnVuY3Rpb24gKF9zdXBlcikge1xuICBfX2V4dGVuZHMoVmVjdG9yU291cmNlLCBfc3VwZXIpO1xuICAvKipcbiAgICogQHBhcmFtIHtPcHRpb25zPX0gb3B0X29wdGlvbnMgVmVjdG9yIHNvdXJjZSBvcHRpb25zLlxuICAgKi9cblxuXG4gIGZ1bmN0aW9uIFZlY3RvclNvdXJjZShvcHRfb3B0aW9ucykge1xuICAgIHZhciBfdGhpcyA9IHRoaXM7XG5cbiAgICB2YXIgb3B0aW9ucyA9IG9wdF9vcHRpb25zIHx8IHt9O1xuICAgIF90aGlzID0gX3N1cGVyLmNhbGwodGhpcywge1xuICAgICAgYXR0cmlidXRpb25zOiBvcHRpb25zLmF0dHJpYnV0aW9ucyxcbiAgICAgIHByb2plY3Rpb246IHVuZGVmaW5lZCxcbiAgICAgIHN0YXRlOiBTb3VyY2VTdGF0ZS5SRUFEWSxcbiAgICAgIHdyYXBYOiBvcHRpb25zLndyYXBYICE9PSB1bmRlZmluZWQgPyBvcHRpb25zLndyYXBYIDogdHJ1ZVxuICAgIH0pIHx8IHRoaXM7XG4gICAgLyoqXG4gICAgICogQHByaXZhdGVcbiAgICAgKiBAdHlwZSB7aW1wb3J0KFwiLi4vZmVhdHVyZWxvYWRlci5qc1wiKS5GZWF0dXJlTG9hZGVyfVxuICAgICAqL1xuXG4gICAgX3RoaXMubG9hZGVyXyA9IFZPSUQ7XG4gICAgLyoqXG4gICAgICogQHByaXZhdGVcbiAgICAgKiBAdHlwZSB7aW1wb3J0KFwiLi4vZm9ybWF0L0ZlYXR1cmUuanNcIikuZGVmYXVsdHx1bmRlZmluZWR9XG4gICAgICovXG5cbiAgICBfdGhpcy5mb3JtYXRfID0gb3B0aW9ucy5mb3JtYXQ7XG4gICAgLyoqXG4gICAgICogQHByaXZhdGVcbiAgICAgKiBAdHlwZSB7Ym9vbGVhbn1cbiAgICAgKi9cblxuICAgIF90aGlzLm92ZXJsYXBzXyA9IG9wdGlvbnMub3ZlcmxhcHMgPT09IHVuZGVmaW5lZCA/IHRydWUgOiBvcHRpb25zLm92ZXJsYXBzO1xuICAgIC8qKlxuICAgICAqIEBwcml2YXRlXG4gICAgICogQHR5cGUge3N0cmluZ3xpbXBvcnQoXCIuLi9mZWF0dXJlbG9hZGVyLmpzXCIpLkZlYXR1cmVVcmxGdW5jdGlvbnx1bmRlZmluZWR9XG4gICAgICovXG5cbiAgICBfdGhpcy51cmxfID0gb3B0aW9ucy51cmw7XG5cbiAgICBpZiAob3B0aW9ucy5sb2FkZXIgIT09IHVuZGVmaW5lZCkge1xuICAgICAgX3RoaXMubG9hZGVyXyA9IG9wdGlvbnMubG9hZGVyO1xuICAgIH0gZWxzZSBpZiAoX3RoaXMudXJsXyAhPT0gdW5kZWZpbmVkKSB7XG4gICAgICBhc3NlcnQoX3RoaXMuZm9ybWF0XywgNyk7IC8vIGBmb3JtYXRgIG11c3QgYmUgc2V0IHdoZW4gYHVybGAgaXMgc2V0XG4gICAgICAvLyBjcmVhdGUgYSBYSFIgZmVhdHVyZSBsb2FkZXIgZm9yIFwidXJsXCIgYW5kIFwiZm9ybWF0XCJcblxuICAgICAgX3RoaXMubG9hZGVyXyA9IHhocihfdGhpcy51cmxfLFxuICAgICAgLyoqIEB0eXBlIHtpbXBvcnQoXCIuLi9mb3JtYXQvRmVhdHVyZS5qc1wiKS5kZWZhdWx0fSAqL1xuICAgICAgX3RoaXMuZm9ybWF0Xyk7XG4gICAgfVxuICAgIC8qKlxuICAgICAqIEBwcml2YXRlXG4gICAgICogQHR5cGUge0xvYWRpbmdTdHJhdGVneX1cbiAgICAgKi9cblxuXG4gICAgX3RoaXMuc3RyYXRlZ3lfID0gb3B0aW9ucy5zdHJhdGVneSAhPT0gdW5kZWZpbmVkID8gb3B0aW9ucy5zdHJhdGVneSA6IGFsbFN0cmF0ZWd5O1xuICAgIHZhciB1c2VTcGF0aWFsSW5kZXggPSBvcHRpb25zLnVzZVNwYXRpYWxJbmRleCAhPT0gdW5kZWZpbmVkID8gb3B0aW9ucy51c2VTcGF0aWFsSW5kZXggOiB0cnVlO1xuICAgIC8qKlxuICAgICAqIEBwcml2YXRlXG4gICAgICogQHR5cGUge1JCdXNoPGltcG9ydChcIi4uL0ZlYXR1cmUuanNcIikuZGVmYXVsdDxHZW9tZXRyeT4+fVxuICAgICAqL1xuXG4gICAgX3RoaXMuZmVhdHVyZXNSdHJlZV8gPSB1c2VTcGF0aWFsSW5kZXggPyBuZXcgUkJ1c2goKSA6IG51bGw7XG4gICAgLyoqXG4gICAgICogQHByaXZhdGVcbiAgICAgKiBAdHlwZSB7UkJ1c2g8e2V4dGVudDogaW1wb3J0KFwiLi4vZXh0ZW50LmpzXCIpLkV4dGVudH0+fVxuICAgICAqL1xuXG4gICAgX3RoaXMubG9hZGVkRXh0ZW50c1J0cmVlXyA9IG5ldyBSQnVzaCgpO1xuICAgIC8qKlxuICAgICAqIEBwcml2YXRlXG4gICAgICogQHR5cGUgeyFPYmplY3Q8c3RyaW5nLCBpbXBvcnQoXCIuLi9GZWF0dXJlLmpzXCIpLmRlZmF1bHQ8R2VvbWV0cnk+Pn1cbiAgICAgKi9cblxuICAgIF90aGlzLm51bGxHZW9tZXRyeUZlYXR1cmVzXyA9IHt9O1xuICAgIC8qKlxuICAgICAqIEEgbG9va3VwIG9mIGZlYXR1cmVzIGJ5IGlkICh0aGUgcmV0dXJuIGZyb20gZmVhdHVyZS5nZXRJZCgpKS5cbiAgICAgKiBAcHJpdmF0ZVxuICAgICAqIEB0eXBlIHshT2JqZWN0PHN0cmluZywgaW1wb3J0KFwiLi4vRmVhdHVyZS5qc1wiKS5kZWZhdWx0PEdlb21ldHJ5Pj59XG4gICAgICovXG5cbiAgICBfdGhpcy5pZEluZGV4XyA9IHt9O1xuICAgIC8qKlxuICAgICAqIEEgbG9va3VwIG9mIGZlYXR1cmVzIGJ5IHVpZCAodXNpbmcgZ2V0VWlkKGZlYXR1cmUpKS5cbiAgICAgKiBAcHJpdmF0ZVxuICAgICAqIEB0eXBlIHshT2JqZWN0PHN0cmluZywgaW1wb3J0KFwiLi4vRmVhdHVyZS5qc1wiKS5kZWZhdWx0PEdlb21ldHJ5Pj59XG4gICAgICovXG5cbiAgICBfdGhpcy51aWRJbmRleF8gPSB7fTtcbiAgICAvKipcbiAgICAgKiBAcHJpdmF0ZVxuICAgICAqIEB0eXBlIHtPYmplY3Q8c3RyaW5nLCBBcnJheTxpbXBvcnQoXCIuLi9ldmVudHMuanNcIikuRXZlbnRzS2V5Pj59XG4gICAgICovXG5cbiAgICBfdGhpcy5mZWF0dXJlQ2hhbmdlS2V5c18gPSB7fTtcbiAgICAvKipcbiAgICAgKiBAcHJpdmF0ZVxuICAgICAqIEB0eXBlIHtDb2xsZWN0aW9uPGltcG9ydChcIi4uL0ZlYXR1cmUuanNcIikuZGVmYXVsdDxHZW9tZXRyeT4+fVxuICAgICAqL1xuXG4gICAgX3RoaXMuZmVhdHVyZXNDb2xsZWN0aW9uXyA9IG51bGw7XG4gICAgdmFyIGNvbGxlY3Rpb24sIGZlYXR1cmVzO1xuXG4gICAgaWYgKEFycmF5LmlzQXJyYXkob3B0aW9ucy5mZWF0dXJlcykpIHtcbiAgICAgIGZlYXR1cmVzID0gb3B0aW9ucy5mZWF0dXJlcztcbiAgICB9IGVsc2UgaWYgKG9wdGlvbnMuZmVhdHVyZXMpIHtcbiAgICAgIGNvbGxlY3Rpb24gPSBvcHRpb25zLmZlYXR1cmVzO1xuICAgICAgZmVhdHVyZXMgPSBjb2xsZWN0aW9uLmdldEFycmF5KCk7XG4gICAgfVxuXG4gICAgaWYgKCF1c2VTcGF0aWFsSW5kZXggJiYgY29sbGVjdGlvbiA9PT0gdW5kZWZpbmVkKSB7XG4gICAgICBjb2xsZWN0aW9uID0gbmV3IENvbGxlY3Rpb24oZmVhdHVyZXMpO1xuICAgIH1cblxuICAgIGlmIChmZWF0dXJlcyAhPT0gdW5kZWZpbmVkKSB7XG4gICAgICBfdGhpcy5hZGRGZWF0dXJlc0ludGVybmFsKGZlYXR1cmVzKTtcbiAgICB9XG5cbiAgICBpZiAoY29sbGVjdGlvbiAhPT0gdW5kZWZpbmVkKSB7XG4gICAgICBfdGhpcy5iaW5kRmVhdHVyZXNDb2xsZWN0aW9uXyhjb2xsZWN0aW9uKTtcbiAgICB9XG5cbiAgICByZXR1cm4gX3RoaXM7XG4gIH1cbiAgLyoqXG4gICAqIEFkZCBhIHNpbmdsZSBmZWF0dXJlIHRvIHRoZSBzb3VyY2UuICBJZiB5b3Ugd2FudCB0byBhZGQgYSBiYXRjaCBvZiBmZWF0dXJlc1xuICAgKiBhdCBvbmNlLCBjYWxsIHtAbGluayBtb2R1bGU6b2wvc291cmNlL1ZlY3Rvcn5WZWN0b3JTb3VyY2UjYWRkRmVhdHVyZXMgI2FkZEZlYXR1cmVzKCl9XG4gICAqIGluc3RlYWQuIEEgZmVhdHVyZSB3aWxsIG5vdCBiZSBhZGRlZCB0byB0aGUgc291cmNlIGlmIGZlYXR1cmUgd2l0aFxuICAgKiB0aGUgc2FtZSBpZCBpcyBhbHJlYWR5IHRoZXJlLiBUaGUgcmVhc29uIGZvciB0aGlzIGJlaGF2aW9yIGlzIHRvIGF2b2lkXG4gICAqIGZlYXR1cmUgZHVwbGljYXRpb24gd2hlbiB1c2luZyBiYm94IG9yIHRpbGUgbG9hZGluZyBzdHJhdGVnaWVzLlxuICAgKiBOb3RlOiB0aGlzIGFsc28gYXBwbGllcyBpZiBhbiB7QGxpbmsgbW9kdWxlOm9sL0NvbGxlY3Rpb259IGlzIHVzZWQgZm9yIGZlYXR1cmVzLFxuICAgKiBtZWFuaW5nIHRoYXQgaWYgYSBmZWF0dXJlIHdpdGggYSBkdXBsaWNhdGUgaWQgaXMgYWRkZWQgaW4gdGhlIGNvbGxlY3Rpb24sIGl0IHdpbGxcbiAgICogYmUgcmVtb3ZlZCBmcm9tIGl0IHJpZ2h0IGF3YXkuXG4gICAqIEBwYXJhbSB7aW1wb3J0KFwiLi4vRmVhdHVyZS5qc1wiKS5kZWZhdWx0PEdlb21ldHJ5Pn0gZmVhdHVyZSBGZWF0dXJlIHRvIGFkZC5cbiAgICogQGFwaVxuICAgKi9cblxuXG4gIFZlY3RvclNvdXJjZS5wcm90b3R5cGUuYWRkRmVhdHVyZSA9IGZ1bmN0aW9uIChmZWF0dXJlKSB7XG4gICAgdGhpcy5hZGRGZWF0dXJlSW50ZXJuYWwoZmVhdHVyZSk7XG4gICAgdGhpcy5jaGFuZ2VkKCk7XG4gIH07XG4gIC8qKlxuICAgKiBBZGQgYSBmZWF0dXJlIHdpdGhvdXQgZmlyaW5nIGEgYGNoYW5nZWAgZXZlbnQuXG4gICAqIEBwYXJhbSB7aW1wb3J0KFwiLi4vRmVhdHVyZS5qc1wiKS5kZWZhdWx0PEdlb21ldHJ5Pn0gZmVhdHVyZSBGZWF0dXJlLlxuICAgKiBAcHJvdGVjdGVkXG4gICAqL1xuXG5cbiAgVmVjdG9yU291cmNlLnByb3RvdHlwZS5hZGRGZWF0dXJlSW50ZXJuYWwgPSBmdW5jdGlvbiAoZmVhdHVyZSkge1xuICAgIHZhciBmZWF0dXJlS2V5ID0gZ2V0VWlkKGZlYXR1cmUpO1xuXG4gICAgaWYgKCF0aGlzLmFkZFRvSW5kZXhfKGZlYXR1cmVLZXksIGZlYXR1cmUpKSB7XG4gICAgICBpZiAodGhpcy5mZWF0dXJlc0NvbGxlY3Rpb25fKSB7XG4gICAgICAgIHRoaXMuZmVhdHVyZXNDb2xsZWN0aW9uXy5yZW1vdmUoZmVhdHVyZSk7XG4gICAgICB9XG5cbiAgICAgIHJldHVybjtcbiAgICB9XG5cbiAgICB0aGlzLnNldHVwQ2hhbmdlRXZlbnRzXyhmZWF0dXJlS2V5LCBmZWF0dXJlKTtcbiAgICB2YXIgZ2VvbWV0cnkgPSBmZWF0dXJlLmdldEdlb21ldHJ5KCk7XG5cbiAgICBpZiAoZ2VvbWV0cnkpIHtcbiAgICAgIHZhciBleHRlbnQgPSBnZW9tZXRyeS5nZXRFeHRlbnQoKTtcblxuICAgICAgaWYgKHRoaXMuZmVhdHVyZXNSdHJlZV8pIHtcbiAgICAgICAgdGhpcy5mZWF0dXJlc1J0cmVlXy5pbnNlcnQoZXh0ZW50LCBmZWF0dXJlKTtcbiAgICAgIH1cbiAgICB9IGVsc2Uge1xuICAgICAgdGhpcy5udWxsR2VvbWV0cnlGZWF0dXJlc19bZmVhdHVyZUtleV0gPSBmZWF0dXJlO1xuICAgIH1cblxuICAgIHRoaXMuZGlzcGF0Y2hFdmVudChuZXcgVmVjdG9yU291cmNlRXZlbnQoVmVjdG9yRXZlbnRUeXBlLkFEREZFQVRVUkUsIGZlYXR1cmUpKTtcbiAgfTtcbiAgLyoqXG4gICAqIEBwYXJhbSB7c3RyaW5nfSBmZWF0dXJlS2V5IFVuaXF1ZSBpZGVudGlmaWVyIGZvciB0aGUgZmVhdHVyZS5cbiAgICogQHBhcmFtIHtpbXBvcnQoXCIuLi9GZWF0dXJlLmpzXCIpLmRlZmF1bHQ8R2VvbWV0cnk+fSBmZWF0dXJlIFRoZSBmZWF0dXJlLlxuICAgKiBAcHJpdmF0ZVxuICAgKi9cblxuXG4gIFZlY3RvclNvdXJjZS5wcm90b3R5cGUuc2V0dXBDaGFuZ2VFdmVudHNfID0gZnVuY3Rpb24gKGZlYXR1cmVLZXksIGZlYXR1cmUpIHtcbiAgICB0aGlzLmZlYXR1cmVDaGFuZ2VLZXlzX1tmZWF0dXJlS2V5XSA9IFtsaXN0ZW4oZmVhdHVyZSwgRXZlbnRUeXBlLkNIQU5HRSwgdGhpcy5oYW5kbGVGZWF0dXJlQ2hhbmdlXywgdGhpcyksIGxpc3RlbihmZWF0dXJlLCBPYmplY3RFdmVudFR5cGUuUFJPUEVSVFlDSEFOR0UsIHRoaXMuaGFuZGxlRmVhdHVyZUNoYW5nZV8sIHRoaXMpXTtcbiAgfTtcbiAgLyoqXG4gICAqIEBwYXJhbSB7c3RyaW5nfSBmZWF0dXJlS2V5IFVuaXF1ZSBpZGVudGlmaWVyIGZvciB0aGUgZmVhdHVyZS5cbiAgICogQHBhcmFtIHtpbXBvcnQoXCIuLi9GZWF0dXJlLmpzXCIpLmRlZmF1bHQ8R2VvbWV0cnk+fSBmZWF0dXJlIFRoZSBmZWF0dXJlLlxuICAgKiBAcmV0dXJuIHtib29sZWFufSBUaGUgZmVhdHVyZSBpcyBcInZhbGlkXCIsIGluIHRoZSBzZW5zZSB0aGF0IGl0IGlzIGFsc28gYVxuICAgKiAgICAgY2FuZGlkYXRlIGZvciBpbnNlcnRpb24gaW50byB0aGUgUnRyZWUuXG4gICAqIEBwcml2YXRlXG4gICAqL1xuXG5cbiAgVmVjdG9yU291cmNlLnByb3RvdHlwZS5hZGRUb0luZGV4XyA9IGZ1bmN0aW9uIChmZWF0dXJlS2V5LCBmZWF0dXJlKSB7XG4gICAgdmFyIHZhbGlkID0gdHJ1ZTtcbiAgICB2YXIgaWQgPSBmZWF0dXJlLmdldElkKCk7XG5cbiAgICBpZiAoaWQgIT09IHVuZGVmaW5lZCkge1xuICAgICAgaWYgKCEoaWQudG9TdHJpbmcoKSBpbiB0aGlzLmlkSW5kZXhfKSkge1xuICAgICAgICB0aGlzLmlkSW5kZXhfW2lkLnRvU3RyaW5nKCldID0gZmVhdHVyZTtcbiAgICAgIH0gZWxzZSB7XG4gICAgICAgIHZhbGlkID0gZmFsc2U7XG4gICAgICB9XG4gICAgfVxuXG4gICAgaWYgKHZhbGlkKSB7XG4gICAgICBhc3NlcnQoIShmZWF0dXJlS2V5IGluIHRoaXMudWlkSW5kZXhfKSwgMzApOyAvLyBUaGUgcGFzc2VkIGBmZWF0dXJlYCB3YXMgYWxyZWFkeSBhZGRlZCB0byB0aGUgc291cmNlXG5cbiAgICAgIHRoaXMudWlkSW5kZXhfW2ZlYXR1cmVLZXldID0gZmVhdHVyZTtcbiAgICB9XG5cbiAgICByZXR1cm4gdmFsaWQ7XG4gIH07XG4gIC8qKlxuICAgKiBBZGQgYSBiYXRjaCBvZiBmZWF0dXJlcyB0byB0aGUgc291cmNlLlxuICAgKiBAcGFyYW0ge0FycmF5PGltcG9ydChcIi4uL0ZlYXR1cmUuanNcIikuZGVmYXVsdDxHZW9tZXRyeT4+fSBmZWF0dXJlcyBGZWF0dXJlcyB0byBhZGQuXG4gICAqIEBhcGlcbiAgICovXG5cblxuICBWZWN0b3JTb3VyY2UucHJvdG90eXBlLmFkZEZlYXR1cmVzID0gZnVuY3Rpb24gKGZlYXR1cmVzKSB7XG4gICAgdGhpcy5hZGRGZWF0dXJlc0ludGVybmFsKGZlYXR1cmVzKTtcbiAgICB0aGlzLmNoYW5nZWQoKTtcbiAgfTtcbiAgLyoqXG4gICAqIEFkZCBmZWF0dXJlcyB3aXRob3V0IGZpcmluZyBhIGBjaGFuZ2VgIGV2ZW50LlxuICAgKiBAcGFyYW0ge0FycmF5PGltcG9ydChcIi4uL0ZlYXR1cmUuanNcIikuZGVmYXVsdDxHZW9tZXRyeT4+fSBmZWF0dXJlcyBGZWF0dXJlcy5cbiAgICogQHByb3RlY3RlZFxuICAgKi9cblxuXG4gIFZlY3RvclNvdXJjZS5wcm90b3R5cGUuYWRkRmVhdHVyZXNJbnRlcm5hbCA9IGZ1bmN0aW9uIChmZWF0dXJlcykge1xuICAgIHZhciBleHRlbnRzID0gW107XG4gICAgdmFyIG5ld0ZlYXR1cmVzID0gW107XG4gICAgdmFyIGdlb21ldHJ5RmVhdHVyZXMgPSBbXTtcblxuICAgIGZvciAodmFyIGkgPSAwLCBsZW5ndGhfMSA9IGZlYXR1cmVzLmxlbmd0aDsgaSA8IGxlbmd0aF8xOyBpKyspIHtcbiAgICAgIHZhciBmZWF0dXJlID0gZmVhdHVyZXNbaV07XG4gICAgICB2YXIgZmVhdHVyZUtleSA9IGdldFVpZChmZWF0dXJlKTtcblxuICAgICAgaWYgKHRoaXMuYWRkVG9JbmRleF8oZmVhdHVyZUtleSwgZmVhdHVyZSkpIHtcbiAgICAgICAgbmV3RmVhdHVyZXMucHVzaChmZWF0dXJlKTtcbiAgICAgIH1cbiAgICB9XG5cbiAgICBmb3IgKHZhciBpID0gMCwgbGVuZ3RoXzIgPSBuZXdGZWF0dXJlcy5sZW5ndGg7IGkgPCBsZW5ndGhfMjsgaSsrKSB7XG4gICAgICB2YXIgZmVhdHVyZSA9IG5ld0ZlYXR1cmVzW2ldO1xuICAgICAgdmFyIGZlYXR1cmVLZXkgPSBnZXRVaWQoZmVhdHVyZSk7XG4gICAgICB0aGlzLnNldHVwQ2hhbmdlRXZlbnRzXyhmZWF0dXJlS2V5LCBmZWF0dXJlKTtcbiAgICAgIHZhciBnZW9tZXRyeSA9IGZlYXR1cmUuZ2V0R2VvbWV0cnkoKTtcblxuICAgICAgaWYgKGdlb21ldHJ5KSB7XG4gICAgICAgIHZhciBleHRlbnQgPSBnZW9tZXRyeS5nZXRFeHRlbnQoKTtcbiAgICAgICAgZXh0ZW50cy5wdXNoKGV4dGVudCk7XG4gICAgICAgIGdlb21ldHJ5RmVhdHVyZXMucHVzaChmZWF0dXJlKTtcbiAgICAgIH0gZWxzZSB7XG4gICAgICAgIHRoaXMubnVsbEdlb21ldHJ5RmVhdHVyZXNfW2ZlYXR1cmVLZXldID0gZmVhdHVyZTtcbiAgICAgIH1cbiAgICB9XG5cbiAgICBpZiAodGhpcy5mZWF0dXJlc1J0cmVlXykge1xuICAgICAgdGhpcy5mZWF0dXJlc1J0cmVlXy5sb2FkKGV4dGVudHMsIGdlb21ldHJ5RmVhdHVyZXMpO1xuICAgIH1cblxuICAgIGZvciAodmFyIGkgPSAwLCBsZW5ndGhfMyA9IG5ld0ZlYXR1cmVzLmxlbmd0aDsgaSA8IGxlbmd0aF8zOyBpKyspIHtcbiAgICAgIHRoaXMuZGlzcGF0Y2hFdmVudChuZXcgVmVjdG9yU291cmNlRXZlbnQoVmVjdG9yRXZlbnRUeXBlLkFEREZFQVRVUkUsIG5ld0ZlYXR1cmVzW2ldKSk7XG4gICAgfVxuICB9O1xuICAvKipcbiAgICogQHBhcmFtIHshQ29sbGVjdGlvbjxpbXBvcnQoXCIuLi9GZWF0dXJlLmpzXCIpLmRlZmF1bHQ8R2VvbWV0cnk+Pn0gY29sbGVjdGlvbiBDb2xsZWN0aW9uLlxuICAgKiBAcHJpdmF0ZVxuICAgKi9cblxuXG4gIFZlY3RvclNvdXJjZS5wcm90b3R5cGUuYmluZEZlYXR1cmVzQ29sbGVjdGlvbl8gPSBmdW5jdGlvbiAoY29sbGVjdGlvbikge1xuICAgIHZhciBtb2RpZnlpbmdDb2xsZWN0aW9uID0gZmFsc2U7XG4gICAgdGhpcy5hZGRFdmVudExpc3RlbmVyKFZlY3RvckV2ZW50VHlwZS5BRERGRUFUVVJFLFxuICAgIC8qKlxuICAgICAqIEBwYXJhbSB7VmVjdG9yU291cmNlRXZlbnQ8R2VvbWV0cnk+fSBldnQgVGhlIHZlY3RvciBzb3VyY2UgZXZlbnRcbiAgICAgKi9cbiAgICBmdW5jdGlvbiAoZXZ0KSB7XG4gICAgICBpZiAoIW1vZGlmeWluZ0NvbGxlY3Rpb24pIHtcbiAgICAgICAgbW9kaWZ5aW5nQ29sbGVjdGlvbiA9IHRydWU7XG4gICAgICAgIGNvbGxlY3Rpb24ucHVzaChldnQuZmVhdHVyZSk7XG4gICAgICAgIG1vZGlmeWluZ0NvbGxlY3Rpb24gPSBmYWxzZTtcbiAgICAgIH1cbiAgICB9KTtcbiAgICB0aGlzLmFkZEV2ZW50TGlzdGVuZXIoVmVjdG9yRXZlbnRUeXBlLlJFTU9WRUZFQVRVUkUsXG4gICAgLyoqXG4gICAgICogQHBhcmFtIHtWZWN0b3JTb3VyY2VFdmVudDxHZW9tZXRyeT59IGV2dCBUaGUgdmVjdG9yIHNvdXJjZSBldmVudFxuICAgICAqL1xuICAgIGZ1bmN0aW9uIChldnQpIHtcbiAgICAgIGlmICghbW9kaWZ5aW5nQ29sbGVjdGlvbikge1xuICAgICAgICBtb2RpZnlpbmdDb2xsZWN0aW9uID0gdHJ1ZTtcbiAgICAgICAgY29sbGVjdGlvbi5yZW1vdmUoZXZ0LmZlYXR1cmUpO1xuICAgICAgICBtb2RpZnlpbmdDb2xsZWN0aW9uID0gZmFsc2U7XG4gICAgICB9XG4gICAgfSk7XG4gICAgY29sbGVjdGlvbi5hZGRFdmVudExpc3RlbmVyKENvbGxlY3Rpb25FdmVudFR5cGUuQURELFxuICAgIC8qKlxuICAgICAqIEBwYXJhbSB7aW1wb3J0KFwiLi4vQ29sbGVjdGlvbi5qc1wiKS5Db2xsZWN0aW9uRXZlbnR9IGV2dCBUaGUgY29sbGVjdGlvbiBldmVudFxuICAgICAqL1xuICAgIGZ1bmN0aW9uIChldnQpIHtcbiAgICAgIGlmICghbW9kaWZ5aW5nQ29sbGVjdGlvbikge1xuICAgICAgICBtb2RpZnlpbmdDb2xsZWN0aW9uID0gdHJ1ZTtcbiAgICAgICAgdGhpcy5hZGRGZWF0dXJlKFxuICAgICAgICAvKiogQHR5cGUge2ltcG9ydChcIi4uL0ZlYXR1cmUuanNcIikuZGVmYXVsdDxHZW9tZXRyeT59ICovXG4gICAgICAgIGV2dC5lbGVtZW50KTtcbiAgICAgICAgbW9kaWZ5aW5nQ29sbGVjdGlvbiA9IGZhbHNlO1xuICAgICAgfVxuICAgIH0uYmluZCh0aGlzKSk7XG4gICAgY29sbGVjdGlvbi5hZGRFdmVudExpc3RlbmVyKENvbGxlY3Rpb25FdmVudFR5cGUuUkVNT1ZFLFxuICAgIC8qKlxuICAgICAqIEBwYXJhbSB7aW1wb3J0KFwiLi4vQ29sbGVjdGlvbi5qc1wiKS5Db2xsZWN0aW9uRXZlbnR9IGV2dCBUaGUgY29sbGVjdGlvbiBldmVudFxuICAgICAqL1xuICAgIGZ1bmN0aW9uIChldnQpIHtcbiAgICAgIGlmICghbW9kaWZ5aW5nQ29sbGVjdGlvbikge1xuICAgICAgICBtb2RpZnlpbmdDb2xsZWN0aW9uID0gdHJ1ZTtcbiAgICAgICAgdGhpcy5yZW1vdmVGZWF0dXJlKFxuICAgICAgICAvKiogQHR5cGUge2ltcG9ydChcIi4uL0ZlYXR1cmUuanNcIikuZGVmYXVsdDxHZW9tZXRyeT59ICovXG4gICAgICAgIGV2dC5lbGVtZW50KTtcbiAgICAgICAgbW9kaWZ5aW5nQ29sbGVjdGlvbiA9IGZhbHNlO1xuICAgICAgfVxuICAgIH0uYmluZCh0aGlzKSk7XG4gICAgdGhpcy5mZWF0dXJlc0NvbGxlY3Rpb25fID0gY29sbGVjdGlvbjtcbiAgfTtcbiAgLyoqXG4gICAqIFJlbW92ZSBhbGwgZmVhdHVyZXMgZnJvbSB0aGUgc291cmNlLlxuICAgKiBAcGFyYW0ge2Jvb2xlYW49fSBvcHRfZmFzdCBTa2lwIGRpc3BhdGNoaW5nIG9mIHtAbGluayBtb2R1bGU6b2wvc291cmNlL1ZlY3Rvci5WZWN0b3JTb3VyY2VFdmVudCNyZW1vdmVmZWF0dXJlfSBldmVudHMuXG4gICAqIEBhcGlcbiAgICovXG5cblxuICBWZWN0b3JTb3VyY2UucHJvdG90eXBlLmNsZWFyID0gZnVuY3Rpb24gKG9wdF9mYXN0KSB7XG4gICAgaWYgKG9wdF9mYXN0KSB7XG4gICAgICBmb3IgKHZhciBmZWF0dXJlSWQgaW4gdGhpcy5mZWF0dXJlQ2hhbmdlS2V5c18pIHtcbiAgICAgICAgdmFyIGtleXMgPSB0aGlzLmZlYXR1cmVDaGFuZ2VLZXlzX1tmZWF0dXJlSWRdO1xuICAgICAgICBrZXlzLmZvckVhY2godW5saXN0ZW5CeUtleSk7XG4gICAgICB9XG5cbiAgICAgIGlmICghdGhpcy5mZWF0dXJlc0NvbGxlY3Rpb25fKSB7XG4gICAgICAgIHRoaXMuZmVhdHVyZUNoYW5nZUtleXNfID0ge307XG4gICAgICAgIHRoaXMuaWRJbmRleF8gPSB7fTtcbiAgICAgICAgdGhpcy51aWRJbmRleF8gPSB7fTtcbiAgICAgIH1cbiAgICB9IGVsc2Uge1xuICAgICAgaWYgKHRoaXMuZmVhdHVyZXNSdHJlZV8pIHtcbiAgICAgICAgdGhpcy5mZWF0dXJlc1J0cmVlXy5mb3JFYWNoKHRoaXMucmVtb3ZlRmVhdHVyZUludGVybmFsLmJpbmQodGhpcykpO1xuXG4gICAgICAgIGZvciAodmFyIGlkIGluIHRoaXMubnVsbEdlb21ldHJ5RmVhdHVyZXNfKSB7XG4gICAgICAgICAgdGhpcy5yZW1vdmVGZWF0dXJlSW50ZXJuYWwodGhpcy5udWxsR2VvbWV0cnlGZWF0dXJlc19baWRdKTtcbiAgICAgICAgfVxuICAgICAgfVxuICAgIH1cblxuICAgIGlmICh0aGlzLmZlYXR1cmVzQ29sbGVjdGlvbl8pIHtcbiAgICAgIHRoaXMuZmVhdHVyZXNDb2xsZWN0aW9uXy5jbGVhcigpO1xuICAgIH1cblxuICAgIGlmICh0aGlzLmZlYXR1cmVzUnRyZWVfKSB7XG4gICAgICB0aGlzLmZlYXR1cmVzUnRyZWVfLmNsZWFyKCk7XG4gICAgfVxuXG4gICAgdGhpcy5udWxsR2VvbWV0cnlGZWF0dXJlc18gPSB7fTtcbiAgICB2YXIgY2xlYXJFdmVudCA9IG5ldyBWZWN0b3JTb3VyY2VFdmVudChWZWN0b3JFdmVudFR5cGUuQ0xFQVIpO1xuICAgIHRoaXMuZGlzcGF0Y2hFdmVudChjbGVhckV2ZW50KTtcbiAgICB0aGlzLmNoYW5nZWQoKTtcbiAgfTtcbiAgLyoqXG4gICAqIEl0ZXJhdGUgdGhyb3VnaCBhbGwgZmVhdHVyZXMgb24gdGhlIHNvdXJjZSwgY2FsbGluZyB0aGUgcHJvdmlkZWQgY2FsbGJhY2tcbiAgICogd2l0aCBlYWNoIG9uZS4gIElmIHRoZSBjYWxsYmFjayByZXR1cm5zIGFueSBcInRydXRoeVwiIHZhbHVlLCBpdGVyYXRpb24gd2lsbFxuICAgKiBzdG9wIGFuZCB0aGUgZnVuY3Rpb24gd2lsbCByZXR1cm4gdGhlIHNhbWUgdmFsdWUuXG4gICAqIE5vdGU6IHRoaXMgZnVuY3Rpb24gb25seSBpdGVyYXRlIHRocm91Z2ggdGhlIGZlYXR1cmUgdGhhdCBoYXZlIGEgZGVmaW5lZCBnZW9tZXRyeS5cbiAgICpcbiAgICogQHBhcmFtIHtmdW5jdGlvbihpbXBvcnQoXCIuLi9GZWF0dXJlLmpzXCIpLmRlZmF1bHQ8R2VvbWV0cnk+KTogVH0gY2FsbGJhY2sgQ2FsbGVkIHdpdGggZWFjaCBmZWF0dXJlXG4gICAqICAgICBvbiB0aGUgc291cmNlLiAgUmV0dXJuIGEgdHJ1dGh5IHZhbHVlIHRvIHN0b3AgaXRlcmF0aW9uLlxuICAgKiBAcmV0dXJuIHtUfHVuZGVmaW5lZH0gVGhlIHJldHVybiB2YWx1ZSBmcm9tIHRoZSBsYXN0IGNhbGwgdG8gdGhlIGNhbGxiYWNrLlxuICAgKiBAdGVtcGxhdGUgVFxuICAgKiBAYXBpXG4gICAqL1xuXG5cbiAgVmVjdG9yU291cmNlLnByb3RvdHlwZS5mb3JFYWNoRmVhdHVyZSA9IGZ1bmN0aW9uIChjYWxsYmFjaykge1xuICAgIGlmICh0aGlzLmZlYXR1cmVzUnRyZWVfKSB7XG4gICAgICByZXR1cm4gdGhpcy5mZWF0dXJlc1J0cmVlXy5mb3JFYWNoKGNhbGxiYWNrKTtcbiAgICB9IGVsc2UgaWYgKHRoaXMuZmVhdHVyZXNDb2xsZWN0aW9uXykge1xuICAgICAgdGhpcy5mZWF0dXJlc0NvbGxlY3Rpb25fLmZvckVhY2goY2FsbGJhY2spO1xuICAgIH1cbiAgfTtcbiAgLyoqXG4gICAqIEl0ZXJhdGUgdGhyb3VnaCBhbGwgZmVhdHVyZXMgd2hvc2UgZ2VvbWV0cmllcyBjb250YWluIHRoZSBwcm92aWRlZFxuICAgKiBjb29yZGluYXRlLCBjYWxsaW5nIHRoZSBjYWxsYmFjayB3aXRoIGVhY2ggZmVhdHVyZS4gIElmIHRoZSBjYWxsYmFjayByZXR1cm5zXG4gICAqIGEgXCJ0cnV0aHlcIiB2YWx1ZSwgaXRlcmF0aW9uIHdpbGwgc3RvcCBhbmQgdGhlIGZ1bmN0aW9uIHdpbGwgcmV0dXJuIHRoZSBzYW1lXG4gICAqIHZhbHVlLlxuICAgKlxuICAgKiBAcGFyYW0ge2ltcG9ydChcIi4uL2Nvb3JkaW5hdGUuanNcIikuQ29vcmRpbmF0ZX0gY29vcmRpbmF0ZSBDb29yZGluYXRlLlxuICAgKiBAcGFyYW0ge2Z1bmN0aW9uKGltcG9ydChcIi4uL0ZlYXR1cmUuanNcIikuZGVmYXVsdDxHZW9tZXRyeT4pOiBUfSBjYWxsYmFjayBDYWxsZWQgd2l0aCBlYWNoIGZlYXR1cmVcbiAgICogICAgIHdob3NlIGdvZW1ldHJ5IGNvbnRhaW5zIHRoZSBwcm92aWRlZCBjb29yZGluYXRlLlxuICAgKiBAcmV0dXJuIHtUfHVuZGVmaW5lZH0gVGhlIHJldHVybiB2YWx1ZSBmcm9tIHRoZSBsYXN0IGNhbGwgdG8gdGhlIGNhbGxiYWNrLlxuICAgKiBAdGVtcGxhdGUgVFxuICAgKi9cblxuXG4gIFZlY3RvclNvdXJjZS5wcm90b3R5cGUuZm9yRWFjaEZlYXR1cmVBdENvb3JkaW5hdGVEaXJlY3QgPSBmdW5jdGlvbiAoY29vcmRpbmF0ZSwgY2FsbGJhY2spIHtcbiAgICB2YXIgZXh0ZW50ID0gW2Nvb3JkaW5hdGVbMF0sIGNvb3JkaW5hdGVbMV0sIGNvb3JkaW5hdGVbMF0sIGNvb3JkaW5hdGVbMV1dO1xuICAgIHJldHVybiB0aGlzLmZvckVhY2hGZWF0dXJlSW5FeHRlbnQoZXh0ZW50LCBmdW5jdGlvbiAoZmVhdHVyZSkge1xuICAgICAgdmFyIGdlb21ldHJ5ID0gZmVhdHVyZS5nZXRHZW9tZXRyeSgpO1xuXG4gICAgICBpZiAoZ2VvbWV0cnkuaW50ZXJzZWN0c0Nvb3JkaW5hdGUoY29vcmRpbmF0ZSkpIHtcbiAgICAgICAgcmV0dXJuIGNhbGxiYWNrKGZlYXR1cmUpO1xuICAgICAgfSBlbHNlIHtcbiAgICAgICAgcmV0dXJuIHVuZGVmaW5lZDtcbiAgICAgIH1cbiAgICB9KTtcbiAgfTtcbiAgLyoqXG4gICAqIEl0ZXJhdGUgdGhyb3VnaCBhbGwgZmVhdHVyZXMgd2hvc2UgYm91bmRpbmcgYm94IGludGVyc2VjdHMgdGhlIHByb3ZpZGVkXG4gICAqIGV4dGVudCAobm90ZSB0aGF0IHRoZSBmZWF0dXJlJ3MgZ2VvbWV0cnkgbWF5IG5vdCBpbnRlcnNlY3QgdGhlIGV4dGVudCksXG4gICAqIGNhbGxpbmcgdGhlIGNhbGxiYWNrIHdpdGggZWFjaCBmZWF0dXJlLiAgSWYgdGhlIGNhbGxiYWNrIHJldHVybnMgYSBcInRydXRoeVwiXG4gICAqIHZhbHVlLCBpdGVyYXRpb24gd2lsbCBzdG9wIGFuZCB0aGUgZnVuY3Rpb24gd2lsbCByZXR1cm4gdGhlIHNhbWUgdmFsdWUuXG4gICAqXG4gICAqIElmIHlvdSBhcmUgaW50ZXJlc3RlZCBpbiBmZWF0dXJlcyB3aG9zZSBnZW9tZXRyeSBpbnRlcnNlY3RzIGFuIGV4dGVudCwgY2FsbFxuICAgKiB0aGUge0BsaW5rIG1vZHVsZTpvbC9zb3VyY2UvVmVjdG9yflZlY3RvclNvdXJjZSNmb3JFYWNoRmVhdHVyZUludGVyc2VjdGluZ0V4dGVudCAjZm9yRWFjaEZlYXR1cmVJbnRlcnNlY3RpbmdFeHRlbnQoKX0gbWV0aG9kIGluc3RlYWQuXG4gICAqXG4gICAqIFdoZW4gYHVzZVNwYXRpYWxJbmRleGAgaXMgc2V0IHRvIGZhbHNlLCB0aGlzIG1ldGhvZCB3aWxsIGxvb3AgdGhyb3VnaCBhbGxcbiAgICogZmVhdHVyZXMsIGVxdWl2YWxlbnQgdG8ge0BsaW5rIG1vZHVsZTpvbC9zb3VyY2UvVmVjdG9yflZlY3RvclNvdXJjZSNmb3JFYWNoRmVhdHVyZSAjZm9yRWFjaEZlYXR1cmUoKX0uXG4gICAqXG4gICAqIEBwYXJhbSB7aW1wb3J0KFwiLi4vZXh0ZW50LmpzXCIpLkV4dGVudH0gZXh0ZW50IEV4dGVudC5cbiAgICogQHBhcmFtIHtmdW5jdGlvbihpbXBvcnQoXCIuLi9GZWF0dXJlLmpzXCIpLmRlZmF1bHQ8R2VvbWV0cnk+KTogVH0gY2FsbGJhY2sgQ2FsbGVkIHdpdGggZWFjaCBmZWF0dXJlXG4gICAqICAgICB3aG9zZSBib3VuZGluZyBib3ggaW50ZXJzZWN0cyB0aGUgcHJvdmlkZWQgZXh0ZW50LlxuICAgKiBAcmV0dXJuIHtUfHVuZGVmaW5lZH0gVGhlIHJldHVybiB2YWx1ZSBmcm9tIHRoZSBsYXN0IGNhbGwgdG8gdGhlIGNhbGxiYWNrLlxuICAgKiBAdGVtcGxhdGUgVFxuICAgKiBAYXBpXG4gICAqL1xuXG5cbiAgVmVjdG9yU291cmNlLnByb3RvdHlwZS5mb3JFYWNoRmVhdHVyZUluRXh0ZW50ID0gZnVuY3Rpb24gKGV4dGVudCwgY2FsbGJhY2spIHtcbiAgICBpZiAodGhpcy5mZWF0dXJlc1J0cmVlXykge1xuICAgICAgcmV0dXJuIHRoaXMuZmVhdHVyZXNSdHJlZV8uZm9yRWFjaEluRXh0ZW50KGV4dGVudCwgY2FsbGJhY2spO1xuICAgIH0gZWxzZSBpZiAodGhpcy5mZWF0dXJlc0NvbGxlY3Rpb25fKSB7XG4gICAgICB0aGlzLmZlYXR1cmVzQ29sbGVjdGlvbl8uZm9yRWFjaChjYWxsYmFjayk7XG4gICAgfVxuICB9O1xuICAvKipcbiAgICogSXRlcmF0ZSB0aHJvdWdoIGFsbCBmZWF0dXJlcyB3aG9zZSBnZW9tZXRyeSBpbnRlcnNlY3RzIHRoZSBwcm92aWRlZCBleHRlbnQsXG4gICAqIGNhbGxpbmcgdGhlIGNhbGxiYWNrIHdpdGggZWFjaCBmZWF0dXJlLiAgSWYgdGhlIGNhbGxiYWNrIHJldHVybnMgYSBcInRydXRoeVwiXG4gICAqIHZhbHVlLCBpdGVyYXRpb24gd2lsbCBzdG9wIGFuZCB0aGUgZnVuY3Rpb24gd2lsbCByZXR1cm4gdGhlIHNhbWUgdmFsdWUuXG4gICAqXG4gICAqIElmIHlvdSBvbmx5IHdhbnQgdG8gdGVzdCBmb3IgYm91bmRpbmcgYm94IGludGVyc2VjdGlvbiwgY2FsbCB0aGVcbiAgICoge0BsaW5rIG1vZHVsZTpvbC9zb3VyY2UvVmVjdG9yflZlY3RvclNvdXJjZSNmb3JFYWNoRmVhdHVyZUluRXh0ZW50ICNmb3JFYWNoRmVhdHVyZUluRXh0ZW50KCl9IG1ldGhvZCBpbnN0ZWFkLlxuICAgKlxuICAgKiBAcGFyYW0ge2ltcG9ydChcIi4uL2V4dGVudC5qc1wiKS5FeHRlbnR9IGV4dGVudCBFeHRlbnQuXG4gICAqIEBwYXJhbSB7ZnVuY3Rpb24oaW1wb3J0KFwiLi4vRmVhdHVyZS5qc1wiKS5kZWZhdWx0PEdlb21ldHJ5Pik6IFR9IGNhbGxiYWNrIENhbGxlZCB3aXRoIGVhY2ggZmVhdHVyZVxuICAgKiAgICAgd2hvc2UgZ2VvbWV0cnkgaW50ZXJzZWN0cyB0aGUgcHJvdmlkZWQgZXh0ZW50LlxuICAgKiBAcmV0dXJuIHtUfHVuZGVmaW5lZH0gVGhlIHJldHVybiB2YWx1ZSBmcm9tIHRoZSBsYXN0IGNhbGwgdG8gdGhlIGNhbGxiYWNrLlxuICAgKiBAdGVtcGxhdGUgVFxuICAgKiBAYXBpXG4gICAqL1xuXG5cbiAgVmVjdG9yU291cmNlLnByb3RvdHlwZS5mb3JFYWNoRmVhdHVyZUludGVyc2VjdGluZ0V4dGVudCA9IGZ1bmN0aW9uIChleHRlbnQsIGNhbGxiYWNrKSB7XG4gICAgcmV0dXJuIHRoaXMuZm9yRWFjaEZlYXR1cmVJbkV4dGVudChleHRlbnQsXG4gICAgLyoqXG4gICAgICogQHBhcmFtIHtpbXBvcnQoXCIuLi9GZWF0dXJlLmpzXCIpLmRlZmF1bHQ8R2VvbWV0cnk+fSBmZWF0dXJlIEZlYXR1cmUuXG4gICAgICogQHJldHVybiB7VHx1bmRlZmluZWR9IFRoZSByZXR1cm4gdmFsdWUgZnJvbSB0aGUgbGFzdCBjYWxsIHRvIHRoZSBjYWxsYmFjay5cbiAgICAgKi9cbiAgICBmdW5jdGlvbiAoZmVhdHVyZSkge1xuICAgICAgdmFyIGdlb21ldHJ5ID0gZmVhdHVyZS5nZXRHZW9tZXRyeSgpO1xuXG4gICAgICBpZiAoZ2VvbWV0cnkuaW50ZXJzZWN0c0V4dGVudChleHRlbnQpKSB7XG4gICAgICAgIHZhciByZXN1bHQgPSBjYWxsYmFjayhmZWF0dXJlKTtcblxuICAgICAgICBpZiAocmVzdWx0KSB7XG4gICAgICAgICAgcmV0dXJuIHJlc3VsdDtcbiAgICAgICAgfVxuICAgICAgfVxuICAgIH0pO1xuICB9O1xuICAvKipcbiAgICogR2V0IHRoZSBmZWF0dXJlcyBjb2xsZWN0aW9uIGFzc29jaWF0ZWQgd2l0aCB0aGlzIHNvdXJjZS4gV2lsbCBiZSBgbnVsbGBcbiAgICogdW5sZXNzIHRoZSBzb3VyY2Ugd2FzIGNvbmZpZ3VyZWQgd2l0aCBgdXNlU3BhdGlhbEluZGV4YCBzZXQgdG8gYGZhbHNlYCwgb3JcbiAgICogd2l0aCBhbiB7QGxpbmsgbW9kdWxlOm9sL0NvbGxlY3Rpb259IGFzIGBmZWF0dXJlc2AuXG4gICAqIEByZXR1cm4ge0NvbGxlY3Rpb248aW1wb3J0KFwiLi4vRmVhdHVyZS5qc1wiKS5kZWZhdWx0PEdlb21ldHJ5Pj59IFRoZSBjb2xsZWN0aW9uIG9mIGZlYXR1cmVzLlxuICAgKiBAYXBpXG4gICAqL1xuXG5cbiAgVmVjdG9yU291cmNlLnByb3RvdHlwZS5nZXRGZWF0dXJlc0NvbGxlY3Rpb24gPSBmdW5jdGlvbiAoKSB7XG4gICAgcmV0dXJuIHRoaXMuZmVhdHVyZXNDb2xsZWN0aW9uXztcbiAgfTtcbiAgLyoqXG4gICAqIEdldCBhbGwgZmVhdHVyZXMgb24gdGhlIHNvdXJjZSBpbiByYW5kb20gb3JkZXIuXG4gICAqIEByZXR1cm4ge0FycmF5PGltcG9ydChcIi4uL0ZlYXR1cmUuanNcIikuZGVmYXVsdDxHZW9tZXRyeT4+fSBGZWF0dXJlcy5cbiAgICogQGFwaVxuICAgKi9cblxuXG4gIFZlY3RvclNvdXJjZS5wcm90b3R5cGUuZ2V0RmVhdHVyZXMgPSBmdW5jdGlvbiAoKSB7XG4gICAgdmFyIGZlYXR1cmVzO1xuXG4gICAgaWYgKHRoaXMuZmVhdHVyZXNDb2xsZWN0aW9uXykge1xuICAgICAgZmVhdHVyZXMgPSB0aGlzLmZlYXR1cmVzQ29sbGVjdGlvbl8uZ2V0QXJyYXkoKTtcbiAgICB9IGVsc2UgaWYgKHRoaXMuZmVhdHVyZXNSdHJlZV8pIHtcbiAgICAgIGZlYXR1cmVzID0gdGhpcy5mZWF0dXJlc1J0cmVlXy5nZXRBbGwoKTtcblxuICAgICAgaWYgKCFpc0VtcHR5KHRoaXMubnVsbEdlb21ldHJ5RmVhdHVyZXNfKSkge1xuICAgICAgICBleHRlbmQoZmVhdHVyZXMsIGdldFZhbHVlcyh0aGlzLm51bGxHZW9tZXRyeUZlYXR1cmVzXykpO1xuICAgICAgfVxuICAgIH1cblxuICAgIHJldHVybiAoXG4gICAgICAvKiogQHR5cGUge0FycmF5PGltcG9ydChcIi4uL0ZlYXR1cmUuanNcIikuZGVmYXVsdDxHZW9tZXRyeT4+fSAqL1xuICAgICAgZmVhdHVyZXNcbiAgICApO1xuICB9O1xuICAvKipcbiAgICogR2V0IGFsbCBmZWF0dXJlcyB3aG9zZSBnZW9tZXRyeSBpbnRlcnNlY3RzIHRoZSBwcm92aWRlZCBjb29yZGluYXRlLlxuICAgKiBAcGFyYW0ge2ltcG9ydChcIi4uL2Nvb3JkaW5hdGUuanNcIikuQ29vcmRpbmF0ZX0gY29vcmRpbmF0ZSBDb29yZGluYXRlLlxuICAgKiBAcmV0dXJuIHtBcnJheTxpbXBvcnQoXCIuLi9GZWF0dXJlLmpzXCIpLmRlZmF1bHQ8R2VvbWV0cnk+Pn0gRmVhdHVyZXMuXG4gICAqIEBhcGlcbiAgICovXG5cblxuICBWZWN0b3JTb3VyY2UucHJvdG90eXBlLmdldEZlYXR1cmVzQXRDb29yZGluYXRlID0gZnVuY3Rpb24gKGNvb3JkaW5hdGUpIHtcbiAgICB2YXIgZmVhdHVyZXMgPSBbXTtcbiAgICB0aGlzLmZvckVhY2hGZWF0dXJlQXRDb29yZGluYXRlRGlyZWN0KGNvb3JkaW5hdGUsIGZ1bmN0aW9uIChmZWF0dXJlKSB7XG4gICAgICBmZWF0dXJlcy5wdXNoKGZlYXR1cmUpO1xuICAgIH0pO1xuICAgIHJldHVybiBmZWF0dXJlcztcbiAgfTtcbiAgLyoqXG4gICAqIEdldCBhbGwgZmVhdHVyZXMgd2hvc2UgYm91bmRpbmcgYm94IGludGVyc2VjdHMgdGhlIHByb3ZpZGVkIGV4dGVudC4gIE5vdGUgdGhhdCB0aGlzIHJldHVybnMgYW4gYXJyYXkgb2ZcbiAgICogYWxsIGZlYXR1cmVzIGludGVyc2VjdGluZyB0aGUgZ2l2ZW4gZXh0ZW50IGluIHJhbmRvbSBvcmRlciAoc28gaXQgbWF5IGluY2x1ZGVcbiAgICogZmVhdHVyZXMgd2hvc2UgZ2VvbWV0cmllcyBkbyBub3QgaW50ZXJzZWN0IHRoZSBleHRlbnQpLlxuICAgKlxuICAgKiBXaGVuIGB1c2VTcGF0aWFsSW5kZXhgIGlzIHNldCB0byBmYWxzZSwgdGhpcyBtZXRob2Qgd2lsbCByZXR1cm4gYWxsXG4gICAqIGZlYXR1cmVzLlxuICAgKlxuICAgKiBAcGFyYW0ge2ltcG9ydChcIi4uL2V4dGVudC5qc1wiKS5FeHRlbnR9IGV4dGVudCBFeHRlbnQuXG4gICAqIEByZXR1cm4ge0FycmF5PGltcG9ydChcIi4uL0ZlYXR1cmUuanNcIikuZGVmYXVsdDxHZW9tZXRyeT4+fSBGZWF0dXJlcy5cbiAgICogQGFwaVxuICAgKi9cblxuXG4gIFZlY3RvclNvdXJjZS5wcm90b3R5cGUuZ2V0RmVhdHVyZXNJbkV4dGVudCA9IGZ1bmN0aW9uIChleHRlbnQpIHtcbiAgICBpZiAodGhpcy5mZWF0dXJlc1J0cmVlXykge1xuICAgICAgcmV0dXJuIHRoaXMuZmVhdHVyZXNSdHJlZV8uZ2V0SW5FeHRlbnQoZXh0ZW50KTtcbiAgICB9IGVsc2UgaWYgKHRoaXMuZmVhdHVyZXNDb2xsZWN0aW9uXykge1xuICAgICAgcmV0dXJuIHRoaXMuZmVhdHVyZXNDb2xsZWN0aW9uXy5nZXRBcnJheSgpO1xuICAgIH0gZWxzZSB7XG4gICAgICByZXR1cm4gW107XG4gICAgfVxuICB9O1xuICAvKipcbiAgICogR2V0IHRoZSBjbG9zZXN0IGZlYXR1cmUgdG8gdGhlIHByb3ZpZGVkIGNvb3JkaW5hdGUuXG4gICAqXG4gICAqIFRoaXMgbWV0aG9kIGlzIG5vdCBhdmFpbGFibGUgd2hlbiB0aGUgc291cmNlIGlzIGNvbmZpZ3VyZWQgd2l0aFxuICAgKiBgdXNlU3BhdGlhbEluZGV4YCBzZXQgdG8gYGZhbHNlYC5cbiAgICogQHBhcmFtIHtpbXBvcnQoXCIuLi9jb29yZGluYXRlLmpzXCIpLkNvb3JkaW5hdGV9IGNvb3JkaW5hdGUgQ29vcmRpbmF0ZS5cbiAgICogQHBhcmFtIHtmdW5jdGlvbihpbXBvcnQoXCIuLi9GZWF0dXJlLmpzXCIpLmRlZmF1bHQ8R2VvbWV0cnk+KTpib29sZWFuPX0gb3B0X2ZpbHRlciBGZWF0dXJlIGZpbHRlciBmdW5jdGlvbi5cbiAgICogICAgIFRoZSBmaWx0ZXIgZnVuY3Rpb24gd2lsbCByZWNlaXZlIG9uZSBhcmd1bWVudCwgdGhlIHtAbGluayBtb2R1bGU6b2wvRmVhdHVyZSBmZWF0dXJlfVxuICAgKiAgICAgYW5kIGl0IHNob3VsZCByZXR1cm4gYSBib29sZWFuIHZhbHVlLiBCeSBkZWZhdWx0LCBubyBmaWx0ZXJpbmcgaXMgbWFkZS5cbiAgICogQHJldHVybiB7aW1wb3J0KFwiLi4vRmVhdHVyZS5qc1wiKS5kZWZhdWx0PEdlb21ldHJ5Pn0gQ2xvc2VzdCBmZWF0dXJlLlxuICAgKiBAYXBpXG4gICAqL1xuXG5cbiAgVmVjdG9yU291cmNlLnByb3RvdHlwZS5nZXRDbG9zZXN0RmVhdHVyZVRvQ29vcmRpbmF0ZSA9IGZ1bmN0aW9uIChjb29yZGluYXRlLCBvcHRfZmlsdGVyKSB7XG4gICAgLy8gRmluZCB0aGUgY2xvc2VzdCBmZWF0dXJlIHVzaW5nIGJyYW5jaCBhbmQgYm91bmQuICBXZSBzdGFydCBzZWFyY2hpbmcgYW5cbiAgICAvLyBpbmZpbml0ZSBleHRlbnQsIGFuZCBmaW5kIHRoZSBkaXN0YW5jZSBmcm9tIHRoZSBmaXJzdCBmZWF0dXJlIGZvdW5kLiAgVGhpc1xuICAgIC8vIGJlY29tZXMgdGhlIGNsb3Nlc3QgZmVhdHVyZS4gIFdlIHRoZW4gY29tcHV0ZSBhIHNtYWxsZXIgZXh0ZW50IHdoaWNoIGFueVxuICAgIC8vIGNsb3NlciBmZWF0dXJlIG11c3QgaW50ZXJzZWN0LiAgV2UgY29udGludWUgc2VhcmNoaW5nIHdpdGggdGhpcyBzbWFsbGVyXG4gICAgLy8gZXh0ZW50LCB0cnlpbmcgdG8gZmluZCBhIGNsb3NlciBmZWF0dXJlLiAgRXZlcnkgdGltZSB3ZSBmaW5kIGEgY2xvc2VyXG4gICAgLy8gZmVhdHVyZSwgd2UgdXBkYXRlIHRoZSBleHRlbnQgYmVpbmcgc2VhcmNoZWQgc28gdGhhdCBhbnkgZXZlbiBjbG9zZXJcbiAgICAvLyBmZWF0dXJlIG11c3QgaW50ZXJzZWN0IGl0LiAgV2UgY29udGludWUgdW50aWwgd2UgcnVuIG91dCBvZiBmZWF0dXJlcy5cbiAgICB2YXIgeCA9IGNvb3JkaW5hdGVbMF07XG4gICAgdmFyIHkgPSBjb29yZGluYXRlWzFdO1xuICAgIHZhciBjbG9zZXN0RmVhdHVyZSA9IG51bGw7XG4gICAgdmFyIGNsb3Nlc3RQb2ludCA9IFtOYU4sIE5hTl07XG4gICAgdmFyIG1pblNxdWFyZWREaXN0YW5jZSA9IEluZmluaXR5O1xuICAgIHZhciBleHRlbnQgPSBbLUluZmluaXR5LCAtSW5maW5pdHksIEluZmluaXR5LCBJbmZpbml0eV07XG4gICAgdmFyIGZpbHRlciA9IG9wdF9maWx0ZXIgPyBvcHRfZmlsdGVyIDogVFJVRTtcbiAgICB0aGlzLmZlYXR1cmVzUnRyZWVfLmZvckVhY2hJbkV4dGVudChleHRlbnQsXG4gICAgLyoqXG4gICAgICogQHBhcmFtIHtpbXBvcnQoXCIuLi9GZWF0dXJlLmpzXCIpLmRlZmF1bHQ8R2VvbWV0cnk+fSBmZWF0dXJlIEZlYXR1cmUuXG4gICAgICovXG4gICAgZnVuY3Rpb24gKGZlYXR1cmUpIHtcbiAgICAgIGlmIChmaWx0ZXIoZmVhdHVyZSkpIHtcbiAgICAgICAgdmFyIGdlb21ldHJ5ID0gZmVhdHVyZS5nZXRHZW9tZXRyeSgpO1xuICAgICAgICB2YXIgcHJldmlvdXNNaW5TcXVhcmVkRGlzdGFuY2UgPSBtaW5TcXVhcmVkRGlzdGFuY2U7XG4gICAgICAgIG1pblNxdWFyZWREaXN0YW5jZSA9IGdlb21ldHJ5LmNsb3Nlc3RQb2ludFhZKHgsIHksIGNsb3Nlc3RQb2ludCwgbWluU3F1YXJlZERpc3RhbmNlKTtcblxuICAgICAgICBpZiAobWluU3F1YXJlZERpc3RhbmNlIDwgcHJldmlvdXNNaW5TcXVhcmVkRGlzdGFuY2UpIHtcbiAgICAgICAgICBjbG9zZXN0RmVhdHVyZSA9IGZlYXR1cmU7IC8vIFRoaXMgaXMgc25lYWt5LiAgUmVkdWNlIHRoZSBleHRlbnQgdGhhdCBpdCBpcyBjdXJyZW50bHkgYmVpbmdcbiAgICAgICAgICAvLyBzZWFyY2hlZCB3aGlsZSB0aGUgUi1UcmVlIHRyYXZlcnNhbCB1c2luZyB0aGlzIHNhbWUgZXh0ZW50IG9iamVjdFxuICAgICAgICAgIC8vIGlzIHN0aWxsIGluIHByb2dyZXNzLiAgVGhpcyBpcyBzYWZlIGJlY2F1c2UgdGhlIG5ldyBleHRlbnQgaXNcbiAgICAgICAgICAvLyBzdHJpY3RseSBjb250YWluZWQgYnkgdGhlIG9sZCBleHRlbnQuXG5cbiAgICAgICAgICB2YXIgbWluRGlzdGFuY2UgPSBNYXRoLnNxcnQobWluU3F1YXJlZERpc3RhbmNlKTtcbiAgICAgICAgICBleHRlbnRbMF0gPSB4IC0gbWluRGlzdGFuY2U7XG4gICAgICAgICAgZXh0ZW50WzFdID0geSAtIG1pbkRpc3RhbmNlO1xuICAgICAgICAgIGV4dGVudFsyXSA9IHggKyBtaW5EaXN0YW5jZTtcbiAgICAgICAgICBleHRlbnRbM10gPSB5ICsgbWluRGlzdGFuY2U7XG4gICAgICAgIH1cbiAgICAgIH1cbiAgICB9KTtcbiAgICByZXR1cm4gY2xvc2VzdEZlYXR1cmU7XG4gIH07XG4gIC8qKlxuICAgKiBHZXQgdGhlIGV4dGVudCBvZiB0aGUgZmVhdHVyZXMgY3VycmVudGx5IGluIHRoZSBzb3VyY2UuXG4gICAqXG4gICAqIFRoaXMgbWV0aG9kIGlzIG5vdCBhdmFpbGFibGUgd2hlbiB0aGUgc291cmNlIGlzIGNvbmZpZ3VyZWQgd2l0aFxuICAgKiBgdXNlU3BhdGlhbEluZGV4YCBzZXQgdG8gYGZhbHNlYC5cbiAgICogQHBhcmFtIHtpbXBvcnQoXCIuLi9leHRlbnQuanNcIikuRXh0ZW50PX0gb3B0X2V4dGVudCBEZXN0aW5hdGlvbiBleHRlbnQuIElmIHByb3ZpZGVkLCBubyBuZXcgZXh0ZW50XG4gICAqICAgICB3aWxsIGJlIGNyZWF0ZWQuIEluc3RlYWQsIHRoYXQgZXh0ZW50J3MgY29vcmRpbmF0ZXMgd2lsbCBiZSBvdmVyd3JpdHRlbi5cbiAgICogQHJldHVybiB7aW1wb3J0KFwiLi4vZXh0ZW50LmpzXCIpLkV4dGVudH0gRXh0ZW50LlxuICAgKiBAYXBpXG4gICAqL1xuXG5cbiAgVmVjdG9yU291cmNlLnByb3RvdHlwZS5nZXRFeHRlbnQgPSBmdW5jdGlvbiAob3B0X2V4dGVudCkge1xuICAgIHJldHVybiB0aGlzLmZlYXR1cmVzUnRyZWVfLmdldEV4dGVudChvcHRfZXh0ZW50KTtcbiAgfTtcbiAgLyoqXG4gICAqIEdldCBhIGZlYXR1cmUgYnkgaXRzIGlkZW50aWZpZXIgKHRoZSB2YWx1ZSByZXR1cm5lZCBieSBmZWF0dXJlLmdldElkKCkpLlxuICAgKiBOb3RlIHRoYXQgdGhlIGluZGV4IHRyZWF0cyBzdHJpbmcgYW5kIG51bWVyaWMgaWRlbnRpZmllcnMgYXMgdGhlIHNhbWUuICBTb1xuICAgKiBgc291cmNlLmdldEZlYXR1cmVCeUlkKDIpYCB3aWxsIHJldHVybiBhIGZlYXR1cmUgd2l0aCBpZCBgJzInYCBvciBgMmAuXG4gICAqXG4gICAqIEBwYXJhbSB7c3RyaW5nfG51bWJlcn0gaWQgRmVhdHVyZSBpZGVudGlmaWVyLlxuICAgKiBAcmV0dXJuIHtpbXBvcnQoXCIuLi9GZWF0dXJlLmpzXCIpLmRlZmF1bHQ8R2VvbWV0cnk+fSBUaGUgZmVhdHVyZSAob3IgYG51bGxgIGlmIG5vdCBmb3VuZCkuXG4gICAqIEBhcGlcbiAgICovXG5cblxuICBWZWN0b3JTb3VyY2UucHJvdG90eXBlLmdldEZlYXR1cmVCeUlkID0gZnVuY3Rpb24gKGlkKSB7XG4gICAgdmFyIGZlYXR1cmUgPSB0aGlzLmlkSW5kZXhfW2lkLnRvU3RyaW5nKCldO1xuICAgIHJldHVybiBmZWF0dXJlICE9PSB1bmRlZmluZWQgPyBmZWF0dXJlIDogbnVsbDtcbiAgfTtcbiAgLyoqXG4gICAqIEdldCBhIGZlYXR1cmUgYnkgaXRzIGludGVybmFsIHVuaXF1ZSBpZGVudGlmaWVyICh1c2luZyBgZ2V0VWlkYCkuXG4gICAqXG4gICAqIEBwYXJhbSB7c3RyaW5nfSB1aWQgRmVhdHVyZSBpZGVudGlmaWVyLlxuICAgKiBAcmV0dXJuIHtpbXBvcnQoXCIuLi9GZWF0dXJlLmpzXCIpLmRlZmF1bHQ8R2VvbWV0cnk+fSBUaGUgZmVhdHVyZSAob3IgYG51bGxgIGlmIG5vdCBmb3VuZCkuXG4gICAqL1xuXG5cbiAgVmVjdG9yU291cmNlLnByb3RvdHlwZS5nZXRGZWF0dXJlQnlVaWQgPSBmdW5jdGlvbiAodWlkKSB7XG4gICAgdmFyIGZlYXR1cmUgPSB0aGlzLnVpZEluZGV4X1t1aWRdO1xuICAgIHJldHVybiBmZWF0dXJlICE9PSB1bmRlZmluZWQgPyBmZWF0dXJlIDogbnVsbDtcbiAgfTtcbiAgLyoqXG4gICAqIEdldCB0aGUgZm9ybWF0IGFzc29jaWF0ZWQgd2l0aCB0aGlzIHNvdXJjZS5cbiAgICpcbiAgICogQHJldHVybiB7aW1wb3J0KFwiLi4vZm9ybWF0L0ZlYXR1cmUuanNcIikuZGVmYXVsdHx1bmRlZmluZWR9IFRoZSBmZWF0dXJlIGZvcm1hdC5cbiAgICogQGFwaVxuICAgKi9cblxuXG4gIFZlY3RvclNvdXJjZS5wcm90b3R5cGUuZ2V0Rm9ybWF0ID0gZnVuY3Rpb24gKCkge1xuICAgIHJldHVybiB0aGlzLmZvcm1hdF87XG4gIH07XG4gIC8qKlxuICAgKiBAcmV0dXJuIHtib29sZWFufSBUaGUgc291cmNlIGNhbiBoYXZlIG92ZXJsYXBwaW5nIGdlb21ldHJpZXMuXG4gICAqL1xuXG5cbiAgVmVjdG9yU291cmNlLnByb3RvdHlwZS5nZXRPdmVybGFwcyA9IGZ1bmN0aW9uICgpIHtcbiAgICByZXR1cm4gdGhpcy5vdmVybGFwc187XG4gIH07XG4gIC8qKlxuICAgKiBHZXQgdGhlIHVybCBhc3NvY2lhdGVkIHdpdGggdGhpcyBzb3VyY2UuXG4gICAqXG4gICAqIEByZXR1cm4ge3N0cmluZ3xpbXBvcnQoXCIuLi9mZWF0dXJlbG9hZGVyLmpzXCIpLkZlYXR1cmVVcmxGdW5jdGlvbnx1bmRlZmluZWR9IFRoZSB1cmwuXG4gICAqIEBhcGlcbiAgICovXG5cblxuICBWZWN0b3JTb3VyY2UucHJvdG90eXBlLmdldFVybCA9IGZ1bmN0aW9uICgpIHtcbiAgICByZXR1cm4gdGhpcy51cmxfO1xuICB9O1xuICAvKipcbiAgICogQHBhcmFtIHtFdmVudH0gZXZlbnQgRXZlbnQuXG4gICAqIEBwcml2YXRlXG4gICAqL1xuXG5cbiAgVmVjdG9yU291cmNlLnByb3RvdHlwZS5oYW5kbGVGZWF0dXJlQ2hhbmdlXyA9IGZ1bmN0aW9uIChldmVudCkge1xuICAgIHZhciBmZWF0dXJlID1cbiAgICAvKiogQHR5cGUge2ltcG9ydChcIi4uL0ZlYXR1cmUuanNcIikuZGVmYXVsdDxHZW9tZXRyeT59ICovXG4gICAgZXZlbnQudGFyZ2V0O1xuICAgIHZhciBmZWF0dXJlS2V5ID0gZ2V0VWlkKGZlYXR1cmUpO1xuICAgIHZhciBnZW9tZXRyeSA9IGZlYXR1cmUuZ2V0R2VvbWV0cnkoKTtcblxuICAgIGlmICghZ2VvbWV0cnkpIHtcbiAgICAgIGlmICghKGZlYXR1cmVLZXkgaW4gdGhpcy5udWxsR2VvbWV0cnlGZWF0dXJlc18pKSB7XG4gICAgICAgIGlmICh0aGlzLmZlYXR1cmVzUnRyZWVfKSB7XG4gICAgICAgICAgdGhpcy5mZWF0dXJlc1J0cmVlXy5yZW1vdmUoZmVhdHVyZSk7XG4gICAgICAgIH1cblxuICAgICAgICB0aGlzLm51bGxHZW9tZXRyeUZlYXR1cmVzX1tmZWF0dXJlS2V5XSA9IGZlYXR1cmU7XG4gICAgICB9XG4gICAgfSBlbHNlIHtcbiAgICAgIHZhciBleHRlbnQgPSBnZW9tZXRyeS5nZXRFeHRlbnQoKTtcblxuICAgICAgaWYgKGZlYXR1cmVLZXkgaW4gdGhpcy5udWxsR2VvbWV0cnlGZWF0dXJlc18pIHtcbiAgICAgICAgZGVsZXRlIHRoaXMubnVsbEdlb21ldHJ5RmVhdHVyZXNfW2ZlYXR1cmVLZXldO1xuXG4gICAgICAgIGlmICh0aGlzLmZlYXR1cmVzUnRyZWVfKSB7XG4gICAgICAgICAgdGhpcy5mZWF0dXJlc1J0cmVlXy5pbnNlcnQoZXh0ZW50LCBmZWF0dXJlKTtcbiAgICAgICAgfVxuICAgICAgfSBlbHNlIHtcbiAgICAgICAgaWYgKHRoaXMuZmVhdHVyZXNSdHJlZV8pIHtcbiAgICAgICAgICB0aGlzLmZlYXR1cmVzUnRyZWVfLnVwZGF0ZShleHRlbnQsIGZlYXR1cmUpO1xuICAgICAgICB9XG4gICAgICB9XG4gICAgfVxuXG4gICAgdmFyIGlkID0gZmVhdHVyZS5nZXRJZCgpO1xuXG4gICAgaWYgKGlkICE9PSB1bmRlZmluZWQpIHtcbiAgICAgIHZhciBzaWQgPSBpZC50b1N0cmluZygpO1xuXG4gICAgICBpZiAodGhpcy5pZEluZGV4X1tzaWRdICE9PSBmZWF0dXJlKSB7XG4gICAgICAgIHRoaXMucmVtb3ZlRnJvbUlkSW5kZXhfKGZlYXR1cmUpO1xuICAgICAgICB0aGlzLmlkSW5kZXhfW3NpZF0gPSBmZWF0dXJlO1xuICAgICAgfVxuICAgIH0gZWxzZSB7XG4gICAgICB0aGlzLnJlbW92ZUZyb21JZEluZGV4XyhmZWF0dXJlKTtcbiAgICAgIHRoaXMudWlkSW5kZXhfW2ZlYXR1cmVLZXldID0gZmVhdHVyZTtcbiAgICB9XG5cbiAgICB0aGlzLmNoYW5nZWQoKTtcbiAgICB0aGlzLmRpc3BhdGNoRXZlbnQobmV3IFZlY3RvclNvdXJjZUV2ZW50KFZlY3RvckV2ZW50VHlwZS5DSEFOR0VGRUFUVVJFLCBmZWF0dXJlKSk7XG4gIH07XG4gIC8qKlxuICAgKiBSZXR1cm5zIHRydWUgaWYgdGhlIGZlYXR1cmUgaXMgY29udGFpbmVkIHdpdGhpbiB0aGUgc291cmNlLlxuICAgKiBAcGFyYW0ge2ltcG9ydChcIi4uL0ZlYXR1cmUuanNcIikuZGVmYXVsdDxHZW9tZXRyeT59IGZlYXR1cmUgRmVhdHVyZS5cbiAgICogQHJldHVybiB7Ym9vbGVhbn0gSGFzIGZlYXR1cmUuXG4gICAqIEBhcGlcbiAgICovXG5cblxuICBWZWN0b3JTb3VyY2UucHJvdG90eXBlLmhhc0ZlYXR1cmUgPSBmdW5jdGlvbiAoZmVhdHVyZSkge1xuICAgIHZhciBpZCA9IGZlYXR1cmUuZ2V0SWQoKTtcblxuICAgIGlmIChpZCAhPT0gdW5kZWZpbmVkKSB7XG4gICAgICByZXR1cm4gaWQgaW4gdGhpcy5pZEluZGV4XztcbiAgICB9IGVsc2Uge1xuICAgICAgcmV0dXJuIGdldFVpZChmZWF0dXJlKSBpbiB0aGlzLnVpZEluZGV4XztcbiAgICB9XG4gIH07XG4gIC8qKlxuICAgKiBAcmV0dXJuIHtib29sZWFufSBJcyBlbXB0eS5cbiAgICovXG5cblxuICBWZWN0b3JTb3VyY2UucHJvdG90eXBlLmlzRW1wdHkgPSBmdW5jdGlvbiAoKSB7XG4gICAgcmV0dXJuIHRoaXMuZmVhdHVyZXNSdHJlZV8uaXNFbXB0eSgpICYmIGlzRW1wdHkodGhpcy5udWxsR2VvbWV0cnlGZWF0dXJlc18pO1xuICB9O1xuICAvKipcbiAgICogQHBhcmFtIHtpbXBvcnQoXCIuLi9leHRlbnQuanNcIikuRXh0ZW50fSBleHRlbnQgRXh0ZW50LlxuICAgKiBAcGFyYW0ge251bWJlcn0gcmVzb2x1dGlvbiBSZXNvbHV0aW9uLlxuICAgKiBAcGFyYW0ge2ltcG9ydChcIi4uL3Byb2ovUHJvamVjdGlvbi5qc1wiKS5kZWZhdWx0fSBwcm9qZWN0aW9uIFByb2plY3Rpb24uXG4gICAqL1xuXG5cbiAgVmVjdG9yU291cmNlLnByb3RvdHlwZS5sb2FkRmVhdHVyZXMgPSBmdW5jdGlvbiAoZXh0ZW50LCByZXNvbHV0aW9uLCBwcm9qZWN0aW9uKSB7XG4gICAgdmFyIGxvYWRlZEV4dGVudHNSdHJlZSA9IHRoaXMubG9hZGVkRXh0ZW50c1J0cmVlXztcbiAgICB2YXIgZXh0ZW50c1RvTG9hZCA9IHRoaXMuc3RyYXRlZ3lfKGV4dGVudCwgcmVzb2x1dGlvbik7XG4gICAgdGhpcy5sb2FkaW5nID0gZmFsc2U7XG5cbiAgICB2YXIgX2xvb3BfMSA9IGZ1bmN0aW9uIF9sb29wXzEoaSwgaWkpIHtcbiAgICAgIHZhciBleHRlbnRUb0xvYWQgPSBleHRlbnRzVG9Mb2FkW2ldO1xuICAgICAgdmFyIGFscmVhZHlMb2FkZWQgPSBsb2FkZWRFeHRlbnRzUnRyZWUuZm9yRWFjaEluRXh0ZW50KGV4dGVudFRvTG9hZCxcbiAgICAgIC8qKlxuICAgICAgICogQHBhcmFtIHt7ZXh0ZW50OiBpbXBvcnQoXCIuLi9leHRlbnQuanNcIikuRXh0ZW50fX0gb2JqZWN0IE9iamVjdC5cbiAgICAgICAqIEByZXR1cm4ge2Jvb2xlYW59IENvbnRhaW5zLlxuICAgICAgICovXG4gICAgICBmdW5jdGlvbiAob2JqZWN0KSB7XG4gICAgICAgIHJldHVybiBjb250YWluc0V4dGVudChvYmplY3QuZXh0ZW50LCBleHRlbnRUb0xvYWQpO1xuICAgICAgfSk7XG5cbiAgICAgIGlmICghYWxyZWFkeUxvYWRlZCkge1xuICAgICAgICB0aGlzXzEuZGlzcGF0Y2hFdmVudChuZXcgVmVjdG9yU291cmNlRXZlbnQoVmVjdG9yRXZlbnRUeXBlLkZFQVRVUkVTTE9BRFNUQVJUKSk7XG4gICAgICAgIHRoaXNfMS5sb2FkZXJfLmNhbGwodGhpc18xLCBleHRlbnRUb0xvYWQsIHJlc29sdXRpb24sIHByb2plY3Rpb24sIGZ1bmN0aW9uIChmZWF0dXJlcykge1xuICAgICAgICAgIHRoaXMuZGlzcGF0Y2hFdmVudChuZXcgVmVjdG9yU291cmNlRXZlbnQoVmVjdG9yRXZlbnRUeXBlLkZFQVRVUkVTTE9BREVORCwgdW5kZWZpbmVkLCBmZWF0dXJlcykpO1xuICAgICAgICB9LmJpbmQodGhpc18xKSwgZnVuY3Rpb24gKCkge1xuICAgICAgICAgIHRoaXMuZGlzcGF0Y2hFdmVudChuZXcgVmVjdG9yU291cmNlRXZlbnQoVmVjdG9yRXZlbnRUeXBlLkZFQVRVUkVTTE9BREVSUk9SKSk7XG4gICAgICAgIH0uYmluZCh0aGlzXzEpKTtcbiAgICAgICAgbG9hZGVkRXh0ZW50c1J0cmVlLmluc2VydChleHRlbnRUb0xvYWQsIHtcbiAgICAgICAgICBleHRlbnQ6IGV4dGVudFRvTG9hZC5zbGljZSgpXG4gICAgICAgIH0pO1xuICAgICAgICB0aGlzXzEubG9hZGluZyA9IHRoaXNfMS5sb2FkZXJfICE9PSBWT0lEO1xuICAgICAgfVxuICAgIH07XG5cbiAgICB2YXIgdGhpc18xID0gdGhpcztcblxuICAgIGZvciAodmFyIGkgPSAwLCBpaSA9IGV4dGVudHNUb0xvYWQubGVuZ3RoOyBpIDwgaWk7ICsraSkge1xuICAgICAgX2xvb3BfMShpLCBpaSk7XG4gICAgfVxuICB9O1xuXG4gIFZlY3RvclNvdXJjZS5wcm90b3R5cGUucmVmcmVzaCA9IGZ1bmN0aW9uICgpIHtcbiAgICB0aGlzLmNsZWFyKHRydWUpO1xuICAgIHRoaXMubG9hZGVkRXh0ZW50c1J0cmVlXy5jbGVhcigpO1xuXG4gICAgX3N1cGVyLnByb3RvdHlwZS5yZWZyZXNoLmNhbGwodGhpcyk7XG4gIH07XG4gIC8qKlxuICAgKiBSZW1vdmUgYW4gZXh0ZW50IGZyb20gdGhlIGxpc3Qgb2YgbG9hZGVkIGV4dGVudHMuXG4gICAqIEBwYXJhbSB7aW1wb3J0KFwiLi4vZXh0ZW50LmpzXCIpLkV4dGVudH0gZXh0ZW50IEV4dGVudC5cbiAgICogQGFwaVxuICAgKi9cblxuXG4gIFZlY3RvclNvdXJjZS5wcm90b3R5cGUucmVtb3ZlTG9hZGVkRXh0ZW50ID0gZnVuY3Rpb24gKGV4dGVudCkge1xuICAgIHZhciBsb2FkZWRFeHRlbnRzUnRyZWUgPSB0aGlzLmxvYWRlZEV4dGVudHNSdHJlZV87XG4gICAgdmFyIG9iajtcbiAgICBsb2FkZWRFeHRlbnRzUnRyZWUuZm9yRWFjaEluRXh0ZW50KGV4dGVudCwgZnVuY3Rpb24gKG9iamVjdCkge1xuICAgICAgaWYgKGVxdWFscyhvYmplY3QuZXh0ZW50LCBleHRlbnQpKSB7XG4gICAgICAgIG9iaiA9IG9iamVjdDtcbiAgICAgICAgcmV0dXJuIHRydWU7XG4gICAgICB9XG4gICAgfSk7XG5cbiAgICBpZiAob2JqKSB7XG4gICAgICBsb2FkZWRFeHRlbnRzUnRyZWUucmVtb3ZlKG9iaik7XG4gICAgfVxuICB9O1xuICAvKipcbiAgICogUmVtb3ZlIGEgc2luZ2xlIGZlYXR1cmUgZnJvbSB0aGUgc291cmNlLiAgSWYgeW91IHdhbnQgdG8gcmVtb3ZlIGFsbCBmZWF0dXJlc1xuICAgKiBhdCBvbmNlLCB1c2UgdGhlIHtAbGluayBtb2R1bGU6b2wvc291cmNlL1ZlY3Rvcn5WZWN0b3JTb3VyY2UjY2xlYXIgI2NsZWFyKCl9IG1ldGhvZFxuICAgKiBpbnN0ZWFkLlxuICAgKiBAcGFyYW0ge2ltcG9ydChcIi4uL0ZlYXR1cmUuanNcIikuZGVmYXVsdDxHZW9tZXRyeT59IGZlYXR1cmUgRmVhdHVyZSB0byByZW1vdmUuXG4gICAqIEBhcGlcbiAgICovXG5cblxuICBWZWN0b3JTb3VyY2UucHJvdG90eXBlLnJlbW92ZUZlYXR1cmUgPSBmdW5jdGlvbiAoZmVhdHVyZSkge1xuICAgIHZhciBmZWF0dXJlS2V5ID0gZ2V0VWlkKGZlYXR1cmUpO1xuXG4gICAgaWYgKGZlYXR1cmVLZXkgaW4gdGhpcy5udWxsR2VvbWV0cnlGZWF0dXJlc18pIHtcbiAgICAgIGRlbGV0ZSB0aGlzLm51bGxHZW9tZXRyeUZlYXR1cmVzX1tmZWF0dXJlS2V5XTtcbiAgICB9IGVsc2Uge1xuICAgICAgaWYgKHRoaXMuZmVhdHVyZXNSdHJlZV8pIHtcbiAgICAgICAgdGhpcy5mZWF0dXJlc1J0cmVlXy5yZW1vdmUoZmVhdHVyZSk7XG4gICAgICB9XG4gICAgfVxuXG4gICAgdGhpcy5yZW1vdmVGZWF0dXJlSW50ZXJuYWwoZmVhdHVyZSk7XG4gICAgdGhpcy5jaGFuZ2VkKCk7XG4gIH07XG4gIC8qKlxuICAgKiBSZW1vdmUgZmVhdHVyZSB3aXRob3V0IGZpcmluZyBhIGBjaGFuZ2VgIGV2ZW50LlxuICAgKiBAcGFyYW0ge2ltcG9ydChcIi4uL0ZlYXR1cmUuanNcIikuZGVmYXVsdDxHZW9tZXRyeT59IGZlYXR1cmUgRmVhdHVyZS5cbiAgICogQHByb3RlY3RlZFxuICAgKi9cblxuXG4gIFZlY3RvclNvdXJjZS5wcm90b3R5cGUucmVtb3ZlRmVhdHVyZUludGVybmFsID0gZnVuY3Rpb24gKGZlYXR1cmUpIHtcbiAgICB2YXIgZmVhdHVyZUtleSA9IGdldFVpZChmZWF0dXJlKTtcbiAgICB0aGlzLmZlYXR1cmVDaGFuZ2VLZXlzX1tmZWF0dXJlS2V5XS5mb3JFYWNoKHVubGlzdGVuQnlLZXkpO1xuICAgIGRlbGV0ZSB0aGlzLmZlYXR1cmVDaGFuZ2VLZXlzX1tmZWF0dXJlS2V5XTtcbiAgICB2YXIgaWQgPSBmZWF0dXJlLmdldElkKCk7XG5cbiAgICBpZiAoaWQgIT09IHVuZGVmaW5lZCkge1xuICAgICAgZGVsZXRlIHRoaXMuaWRJbmRleF9baWQudG9TdHJpbmcoKV07XG4gICAgfVxuXG4gICAgZGVsZXRlIHRoaXMudWlkSW5kZXhfW2ZlYXR1cmVLZXldO1xuICAgIHRoaXMuZGlzcGF0Y2hFdmVudChuZXcgVmVjdG9yU291cmNlRXZlbnQoVmVjdG9yRXZlbnRUeXBlLlJFTU9WRUZFQVRVUkUsIGZlYXR1cmUpKTtcbiAgfTtcbiAgLyoqXG4gICAqIFJlbW92ZSBhIGZlYXR1cmUgZnJvbSB0aGUgaWQgaW5kZXguICBDYWxsZWQgaW50ZXJuYWxseSB3aGVuIHRoZSBmZWF0dXJlIGlkXG4gICAqIG1heSBoYXZlIGNoYW5nZWQuXG4gICAqIEBwYXJhbSB7aW1wb3J0KFwiLi4vRmVhdHVyZS5qc1wiKS5kZWZhdWx0PEdlb21ldHJ5Pn0gZmVhdHVyZSBUaGUgZmVhdHVyZS5cbiAgICogQHJldHVybiB7Ym9vbGVhbn0gUmVtb3ZlZCB0aGUgZmVhdHVyZSBmcm9tIHRoZSBpbmRleC5cbiAgICogQHByaXZhdGVcbiAgICovXG5cblxuICBWZWN0b3JTb3VyY2UucHJvdG90eXBlLnJlbW92ZUZyb21JZEluZGV4XyA9IGZ1bmN0aW9uIChmZWF0dXJlKSB7XG4gICAgdmFyIHJlbW92ZWQgPSBmYWxzZTtcblxuICAgIGZvciAodmFyIGlkIGluIHRoaXMuaWRJbmRleF8pIHtcbiAgICAgIGlmICh0aGlzLmlkSW5kZXhfW2lkXSA9PT0gZmVhdHVyZSkge1xuICAgICAgICBkZWxldGUgdGhpcy5pZEluZGV4X1tpZF07XG4gICAgICAgIHJlbW92ZWQgPSB0cnVlO1xuICAgICAgICBicmVhaztcbiAgICAgIH1cbiAgICB9XG5cbiAgICByZXR1cm4gcmVtb3ZlZDtcbiAgfTtcbiAgLyoqXG4gICAqIFNldCB0aGUgbmV3IGxvYWRlciBvZiB0aGUgc291cmNlLiBUaGUgbmV4dCByZW5kZXIgY3ljbGUgd2lsbCB1c2UgdGhlXG4gICAqIG5ldyBsb2FkZXIuXG4gICAqIEBwYXJhbSB7aW1wb3J0KFwiLi4vZmVhdHVyZWxvYWRlci5qc1wiKS5GZWF0dXJlTG9hZGVyfSBsb2FkZXIgVGhlIGxvYWRlciB0byBzZXQuXG4gICAqIEBhcGlcbiAgICovXG5cblxuICBWZWN0b3JTb3VyY2UucHJvdG90eXBlLnNldExvYWRlciA9IGZ1bmN0aW9uIChsb2FkZXIpIHtcbiAgICB0aGlzLmxvYWRlcl8gPSBsb2FkZXI7XG4gIH07XG4gIC8qKlxuICAgKiBQb2ludHMgdGhlIHNvdXJjZSB0byBhIG5ldyB1cmwuIFRoZSBuZXh0IHJlbmRlciBjeWNsZSB3aWxsIHVzZSB0aGUgbmV3IHVybC5cbiAgICogQHBhcmFtIHtzdHJpbmd8aW1wb3J0KFwiLi4vZmVhdHVyZWxvYWRlci5qc1wiKS5GZWF0dXJlVXJsRnVuY3Rpb259IHVybCBVcmwuXG4gICAqIEBhcGlcbiAgICovXG5cblxuICBWZWN0b3JTb3VyY2UucHJvdG90eXBlLnNldFVybCA9IGZ1bmN0aW9uICh1cmwpIHtcbiAgICBhc3NlcnQodGhpcy5mb3JtYXRfLCA3KTsgLy8gYGZvcm1hdGAgbXVzdCBiZSBzZXQgd2hlbiBgdXJsYCBpcyBzZXRcblxuICAgIHRoaXMuc2V0TG9hZGVyKHhocih1cmwsIHRoaXMuZm9ybWF0XykpO1xuICB9O1xuXG4gIHJldHVybiBWZWN0b3JTb3VyY2U7XG59KFNvdXJjZSk7XG5cbmV4cG9ydCBkZWZhdWx0IFZlY3RvclNvdXJjZTsiLCJ2YXIgX19leHRlbmRzID0gdGhpcyAmJiB0aGlzLl9fZXh0ZW5kcyB8fCBmdW5jdGlvbiAoKSB7XG4gIHZhciBfZXh0ZW5kU3RhdGljcyA9IGZ1bmN0aW9uIGV4dGVuZFN0YXRpY3MoZCwgYikge1xuICAgIF9leHRlbmRTdGF0aWNzID0gT2JqZWN0LnNldFByb3RvdHlwZU9mIHx8IHtcbiAgICAgIF9fcHJvdG9fXzogW11cbiAgICB9IGluc3RhbmNlb2YgQXJyYXkgJiYgZnVuY3Rpb24gKGQsIGIpIHtcbiAgICAgIGQuX19wcm90b19fID0gYjtcbiAgICB9IHx8IGZ1bmN0aW9uIChkLCBiKSB7XG4gICAgICBmb3IgKHZhciBwIGluIGIpIHtcbiAgICAgICAgaWYgKE9iamVjdC5wcm90b3R5cGUuaGFzT3duUHJvcGVydHkuY2FsbChiLCBwKSkgZFtwXSA9IGJbcF07XG4gICAgICB9XG4gICAgfTtcblxuICAgIHJldHVybiBfZXh0ZW5kU3RhdGljcyhkLCBiKTtcbiAgfTtcblxuICByZXR1cm4gZnVuY3Rpb24gKGQsIGIpIHtcbiAgICBfZXh0ZW5kU3RhdGljcyhkLCBiKTtcblxuICAgIGZ1bmN0aW9uIF9fKCkge1xuICAgICAgdGhpcy5jb25zdHJ1Y3RvciA9IGQ7XG4gICAgfVxuXG4gICAgZC5wcm90b3R5cGUgPSBiID09PSBudWxsID8gT2JqZWN0LmNyZWF0ZShiKSA6IChfXy5wcm90b3R5cGUgPSBiLnByb3RvdHlwZSwgbmV3IF9fKCkpO1xuICB9O1xufSgpO1xuLyoqXG4gKiBAbW9kdWxlIG9sL0ltYWdlVGlsZVxuICovXG5cblxuaW1wb3J0IFRpbGUgZnJvbSAnLi9UaWxlLmpzJztcbmltcG9ydCBUaWxlU3RhdGUgZnJvbSAnLi9UaWxlU3RhdGUuanMnO1xuaW1wb3J0IHsgY3JlYXRlQ2FudmFzQ29udGV4dDJEIH0gZnJvbSAnLi9kb20uanMnO1xuaW1wb3J0IHsgbGlzdGVuSW1hZ2UgfSBmcm9tICcuL0ltYWdlLmpzJztcblxudmFyIEltYWdlVGlsZSA9XG4vKiogQGNsYXNzICovXG5mdW5jdGlvbiAoX3N1cGVyKSB7XG4gIF9fZXh0ZW5kcyhJbWFnZVRpbGUsIF9zdXBlcik7XG4gIC8qKlxuICAgKiBAcGFyYW0ge2ltcG9ydChcIi4vdGlsZWNvb3JkLmpzXCIpLlRpbGVDb29yZH0gdGlsZUNvb3JkIFRpbGUgY29vcmRpbmF0ZS5cbiAgICogQHBhcmFtIHtpbXBvcnQoXCIuL1RpbGVTdGF0ZS5qc1wiKS5kZWZhdWx0fSBzdGF0ZSBTdGF0ZS5cbiAgICogQHBhcmFtIHtzdHJpbmd9IHNyYyBJbWFnZSBzb3VyY2UgVVJJLlxuICAgKiBAcGFyYW0gez9zdHJpbmd9IGNyb3NzT3JpZ2luIENyb3NzIG9yaWdpbi5cbiAgICogQHBhcmFtIHtpbXBvcnQoXCIuL1RpbGUuanNcIikuTG9hZEZ1bmN0aW9ufSB0aWxlTG9hZEZ1bmN0aW9uIFRpbGUgbG9hZCBmdW5jdGlvbi5cbiAgICogQHBhcmFtIHtpbXBvcnQoXCIuL1RpbGUuanNcIikuT3B0aW9ucz19IG9wdF9vcHRpb25zIFRpbGUgb3B0aW9ucy5cbiAgICovXG5cblxuICBmdW5jdGlvbiBJbWFnZVRpbGUodGlsZUNvb3JkLCBzdGF0ZSwgc3JjLCBjcm9zc09yaWdpbiwgdGlsZUxvYWRGdW5jdGlvbiwgb3B0X29wdGlvbnMpIHtcbiAgICB2YXIgX3RoaXMgPSBfc3VwZXIuY2FsbCh0aGlzLCB0aWxlQ29vcmQsIHN0YXRlLCBvcHRfb3B0aW9ucykgfHwgdGhpcztcbiAgICAvKipcbiAgICAgKiBAcHJpdmF0ZVxuICAgICAqIEB0eXBlIHs/c3RyaW5nfVxuICAgICAqL1xuXG5cbiAgICBfdGhpcy5jcm9zc09yaWdpbl8gPSBjcm9zc09yaWdpbjtcbiAgICAvKipcbiAgICAgKiBJbWFnZSBVUklcbiAgICAgKlxuICAgICAqIEBwcml2YXRlXG4gICAgICogQHR5cGUge3N0cmluZ31cbiAgICAgKi9cblxuICAgIF90aGlzLnNyY18gPSBzcmM7XG4gICAgX3RoaXMua2V5ID0gc3JjO1xuICAgIC8qKlxuICAgICAqIEBwcml2YXRlXG4gICAgICogQHR5cGUge0hUTUxJbWFnZUVsZW1lbnR8SFRNTENhbnZhc0VsZW1lbnR9XG4gICAgICovXG5cbiAgICBfdGhpcy5pbWFnZV8gPSBuZXcgSW1hZ2UoKTtcblxuICAgIGlmIChjcm9zc09yaWdpbiAhPT0gbnVsbCkge1xuICAgICAgX3RoaXMuaW1hZ2VfLmNyb3NzT3JpZ2luID0gY3Jvc3NPcmlnaW47XG4gICAgfVxuICAgIC8qKlxuICAgICAqIEBwcml2YXRlXG4gICAgICogQHR5cGUgez9mdW5jdGlvbigpOnZvaWR9XG4gICAgICovXG5cblxuICAgIF90aGlzLnVubGlzdGVuXyA9IG51bGw7XG4gICAgLyoqXG4gICAgICogQHByaXZhdGVcbiAgICAgKiBAdHlwZSB7aW1wb3J0KFwiLi9UaWxlLmpzXCIpLkxvYWRGdW5jdGlvbn1cbiAgICAgKi9cblxuICAgIF90aGlzLnRpbGVMb2FkRnVuY3Rpb25fID0gdGlsZUxvYWRGdW5jdGlvbjtcbiAgICByZXR1cm4gX3RoaXM7XG4gIH1cbiAgLyoqXG4gICAqIEdldCB0aGUgSFRNTCBpbWFnZSBlbGVtZW50IGZvciB0aGlzIHRpbGUgKG1heSBiZSBhIENhbnZhcywgSW1hZ2UsIG9yIFZpZGVvKS5cbiAgICogQHJldHVybiB7SFRNTENhbnZhc0VsZW1lbnR8SFRNTEltYWdlRWxlbWVudHxIVE1MVmlkZW9FbGVtZW50fSBJbWFnZS5cbiAgICogQGFwaVxuICAgKi9cblxuXG4gIEltYWdlVGlsZS5wcm90b3R5cGUuZ2V0SW1hZ2UgPSBmdW5jdGlvbiAoKSB7XG4gICAgcmV0dXJuIHRoaXMuaW1hZ2VfO1xuICB9O1xuICAvKipcbiAgICogVHJhY2tzIGxvYWRpbmcgb3IgcmVhZCBlcnJvcnMuXG4gICAqXG4gICAqIEBwcml2YXRlXG4gICAqL1xuXG5cbiAgSW1hZ2VUaWxlLnByb3RvdHlwZS5oYW5kbGVJbWFnZUVycm9yXyA9IGZ1bmN0aW9uICgpIHtcbiAgICB0aGlzLnN0YXRlID0gVGlsZVN0YXRlLkVSUk9SO1xuICAgIHRoaXMudW5saXN0ZW5JbWFnZV8oKTtcbiAgICB0aGlzLmltYWdlXyA9IGdldEJsYW5rSW1hZ2UoKTtcbiAgICB0aGlzLmNoYW5nZWQoKTtcbiAgfTtcbiAgLyoqXG4gICAqIFRyYWNrcyBzdWNjZXNzZnVsIGltYWdlIGxvYWQuXG4gICAqXG4gICAqIEBwcml2YXRlXG4gICAqL1xuXG5cbiAgSW1hZ2VUaWxlLnByb3RvdHlwZS5oYW5kbGVJbWFnZUxvYWRfID0gZnVuY3Rpb24gKCkge1xuICAgIHZhciBpbWFnZSA9XG4gICAgLyoqIEB0eXBlIHtIVE1MSW1hZ2VFbGVtZW50fSAqL1xuICAgIHRoaXMuaW1hZ2VfO1xuXG4gICAgaWYgKGltYWdlLm5hdHVyYWxXaWR0aCAmJiBpbWFnZS5uYXR1cmFsSGVpZ2h0KSB7XG4gICAgICB0aGlzLnN0YXRlID0gVGlsZVN0YXRlLkxPQURFRDtcbiAgICB9IGVsc2Uge1xuICAgICAgdGhpcy5zdGF0ZSA9IFRpbGVTdGF0ZS5FTVBUWTtcbiAgICB9XG5cbiAgICB0aGlzLnVubGlzdGVuSW1hZ2VfKCk7XG4gICAgdGhpcy5jaGFuZ2VkKCk7XG4gIH07XG4gIC8qKlxuICAgKiBMb2FkIG5vdCB5ZXQgbG9hZGVkIFVSSS5cbiAgICogQGFwaVxuICAgKi9cblxuXG4gIEltYWdlVGlsZS5wcm90b3R5cGUubG9hZCA9IGZ1bmN0aW9uICgpIHtcbiAgICBpZiAodGhpcy5zdGF0ZSA9PSBUaWxlU3RhdGUuRVJST1IpIHtcbiAgICAgIHRoaXMuc3RhdGUgPSBUaWxlU3RhdGUuSURMRTtcbiAgICAgIHRoaXMuaW1hZ2VfID0gbmV3IEltYWdlKCk7XG5cbiAgICAgIGlmICh0aGlzLmNyb3NzT3JpZ2luXyAhPT0gbnVsbCkge1xuICAgICAgICB0aGlzLmltYWdlXy5jcm9zc09yaWdpbiA9IHRoaXMuY3Jvc3NPcmlnaW5fO1xuICAgICAgfVxuICAgIH1cblxuICAgIGlmICh0aGlzLnN0YXRlID09IFRpbGVTdGF0ZS5JRExFKSB7XG4gICAgICB0aGlzLnN0YXRlID0gVGlsZVN0YXRlLkxPQURJTkc7XG4gICAgICB0aGlzLmNoYW5nZWQoKTtcbiAgICAgIHRoaXMudGlsZUxvYWRGdW5jdGlvbl8odGhpcywgdGhpcy5zcmNfKTtcbiAgICAgIHRoaXMudW5saXN0ZW5fID0gbGlzdGVuSW1hZ2UodGhpcy5pbWFnZV8sIHRoaXMuaGFuZGxlSW1hZ2VMb2FkXy5iaW5kKHRoaXMpLCB0aGlzLmhhbmRsZUltYWdlRXJyb3JfLmJpbmQodGhpcykpO1xuICAgIH1cbiAgfTtcbiAgLyoqXG4gICAqIERpc2NhcmRzIGV2ZW50IGhhbmRsZXJzIHdoaWNoIGxpc3RlbiBmb3IgbG9hZCBjb21wbGV0aW9uIG9yIGVycm9ycy5cbiAgICpcbiAgICogQHByaXZhdGVcbiAgICovXG5cblxuICBJbWFnZVRpbGUucHJvdG90eXBlLnVubGlzdGVuSW1hZ2VfID0gZnVuY3Rpb24gKCkge1xuICAgIGlmICh0aGlzLnVubGlzdGVuXykge1xuICAgICAgdGhpcy51bmxpc3Rlbl8oKTtcbiAgICAgIHRoaXMudW5saXN0ZW5fID0gbnVsbDtcbiAgICB9XG4gIH07XG5cbiAgcmV0dXJuIEltYWdlVGlsZTtcbn0oVGlsZSk7XG4vKipcbiAqIEdldCBhIDEtcGl4ZWwgYmxhbmsgaW1hZ2UuXG4gKiBAcmV0dXJuIHtIVE1MQ2FudmFzRWxlbWVudH0gQmxhbmsgaW1hZ2UuXG4gKi9cblxuXG5mdW5jdGlvbiBnZXRCbGFua0ltYWdlKCkge1xuICB2YXIgY3R4ID0gY3JlYXRlQ2FudmFzQ29udGV4dDJEKDEsIDEpO1xuICBjdHguZmlsbFN0eWxlID0gJ3JnYmEoMCwwLDAsMCknO1xuICBjdHguZmlsbFJlY3QoMCwgMCwgMSwgMSk7XG4gIHJldHVybiBjdHguY2FudmFzO1xufVxuXG5leHBvcnQgZGVmYXVsdCBJbWFnZVRpbGU7IiwiLyoqXG4gKiBAbW9kdWxlIG9sL3JlcHJvai9jb21tb25cbiAqL1xuXG4vKipcbiAqIERlZmF1bHQgbWF4aW11bSBhbGxvd2VkIHRocmVzaG9sZCAgKGluIHBpeGVscykgZm9yIHJlcHJvamVjdGlvblxuICogdHJpYW5ndWxhdGlvbi5cbiAqIEB0eXBlIHtudW1iZXJ9XG4gKi9cbmV4cG9ydCB2YXIgRVJST1JfVEhSRVNIT0xEID0gMC41O1xuLyoqXG4gKiBFbmFibGUgYXV0b21hdGljIHJlcHJvamVjdGlvbiBvZiByYXN0ZXIgc291cmNlcy4gRGVmYXVsdCBpcyBgdHJ1ZWAuXG4gKiBUT0RPOiBkZWNpZGUgaWYgd2Ugd2FudCB0byBleHBvc2UgdGhpcyBhcyBhIGJ1aWxkIGZsYWcgb3IgcmVtb3ZlIGl0XG4gKiBAdHlwZSB7Ym9vbGVhbn1cbiAqL1xuXG5leHBvcnQgdmFyIEVOQUJMRV9SQVNURVJfUkVQUk9KRUNUSU9OID0gdHJ1ZTsiLCIvKipcbiAqIEBtb2R1bGUgb2wvcmVwcm9qL1RyaWFuZ3VsYXRpb25cbiAqL1xuaW1wb3J0IHsgYm91bmRpbmdFeHRlbnQsIGNyZWF0ZUVtcHR5LCBleHRlbmRDb29yZGluYXRlLCBnZXRBcmVhLCBnZXRCb3R0b21MZWZ0LCBnZXRCb3R0b21SaWdodCwgZ2V0VG9wTGVmdCwgZ2V0VG9wUmlnaHQsIGdldFdpZHRoLCBpbnRlcnNlY3RzIH0gZnJvbSAnLi4vZXh0ZW50LmpzJztcbmltcG9ydCB7IGdldFRyYW5zZm9ybSB9IGZyb20gJy4uL3Byb2ouanMnO1xuaW1wb3J0IHsgbG9nMiwgbW9kdWxvIH0gZnJvbSAnLi4vbWF0aC5qcyc7XG4vKipcbiAqIFNpbmdsZSB0cmlhbmdsZTsgY29uc2lzdHMgb2YgMyBzb3VyY2UgcG9pbnRzIGFuZCAzIHRhcmdldCBwb2ludHMuXG4gKiBAdHlwZWRlZiB7T2JqZWN0fSBUcmlhbmdsZVxuICogQHByb3BlcnR5IHtBcnJheTxpbXBvcnQoXCIuLi9jb29yZGluYXRlLmpzXCIpLkNvb3JkaW5hdGU+fSBzb3VyY2VcbiAqIEBwcm9wZXJ0eSB7QXJyYXk8aW1wb3J0KFwiLi4vY29vcmRpbmF0ZS5qc1wiKS5Db29yZGluYXRlPn0gdGFyZ2V0XG4gKi9cblxuLyoqXG4gKiBNYXhpbXVtIG51bWJlciBvZiBzdWJkaXZpc2lvbiBzdGVwcyBkdXJpbmcgcmFzdGVyIHJlcHJvamVjdGlvbiB0cmlhbmd1bGF0aW9uLlxuICogUHJldmVudHMgaGlnaCBtZW1vcnkgdXNhZ2UgYW5kIGxhcmdlIG51bWJlciBvZiBwcm9qNCBjYWxscyAoZm9yIGNlcnRhaW5cbiAqIHRyYW5zZm9ybWF0aW9ucyBhbmQgYXJlYXMpLiBBdCBtb3N0IGAyKigyXnRoaXMpYCB0cmlhbmdsZXMgYXJlIGNyZWF0ZWQgZm9yXG4gKiBlYWNoIHRyaWFuZ3VsYXRlZCBleHRlbnQgKHRpbGUvaW1hZ2UpLlxuICogQHR5cGUge251bWJlcn1cbiAqL1xuXG52YXIgTUFYX1NVQkRJVklTSU9OID0gMTA7XG4vKipcbiAqIE1heGltdW0gYWxsb3dlZCBzaXplIG9mIHRyaWFuZ2xlIHJlbGF0aXZlIHRvIHdvcmxkIHdpZHRoLiBXaGVuIHRyYW5zZm9ybWluZ1xuICogY29ybmVycyBvZiB3b3JsZCBleHRlbnQgYmV0d2VlbiBjZXJ0YWluIHByb2plY3Rpb25zLCB0aGUgcmVzdWx0aW5nXG4gKiB0cmlhbmd1bGF0aW9uIHNlZW1zIHRvIGhhdmUgemVybyBlcnJvciBhbmQgbm8gc3ViZGl2aXNpb24gaXMgcGVyZm9ybWVkLiBJZlxuICogdGhlIHRyaWFuZ2xlIHdpZHRoIGlzIG1vcmUgdGhhbiB0aGlzIChyZWxhdGl2ZSB0byB3b3JsZCB3aWR0aDsgMC0xKSxcbiAqIHN1YmRpdmlzb24gaXMgZm9yY2VkICh1cCB0byBgTUFYX1NVQkRJVklTSU9OYCkuIERlZmF1bHQgaXMgYDAuMjVgLlxuICogQHR5cGUge251bWJlcn1cbiAqL1xuXG52YXIgTUFYX1RSSUFOR0xFX1dJRFRIID0gMC4yNTtcbi8qKlxuICogQGNsYXNzZGVzY1xuICogQ2xhc3MgY29udGFpbmluZyB0cmlhbmd1bGF0aW9uIG9mIHRoZSBnaXZlbiB0YXJnZXQgZXh0ZW50LlxuICogVXNlZCBmb3IgZGV0ZXJtaW5pbmcgc291cmNlIGRhdGEgYW5kIHRoZSByZXByb2plY3Rpb24gaXRzZWxmLlxuICovXG5cbnZhciBUcmlhbmd1bGF0aW9uID1cbi8qKiBAY2xhc3MgKi9cbmZ1bmN0aW9uICgpIHtcbiAgLyoqXG4gICAqIEBwYXJhbSB7aW1wb3J0KFwiLi4vcHJvai9Qcm9qZWN0aW9uLmpzXCIpLmRlZmF1bHR9IHNvdXJjZVByb2ogU291cmNlIHByb2plY3Rpb24uXG4gICAqIEBwYXJhbSB7aW1wb3J0KFwiLi4vcHJvai9Qcm9qZWN0aW9uLmpzXCIpLmRlZmF1bHR9IHRhcmdldFByb2ogVGFyZ2V0IHByb2plY3Rpb24uXG4gICAqIEBwYXJhbSB7aW1wb3J0KFwiLi4vZXh0ZW50LmpzXCIpLkV4dGVudH0gdGFyZ2V0RXh0ZW50IFRhcmdldCBleHRlbnQgdG8gdHJpYW5ndWxhdGUuXG4gICAqIEBwYXJhbSB7aW1wb3J0KFwiLi4vZXh0ZW50LmpzXCIpLkV4dGVudH0gbWF4U291cmNlRXh0ZW50IE1heGltYWwgc291cmNlIGV4dGVudCB0aGF0IGNhbiBiZSB1c2VkLlxuICAgKiBAcGFyYW0ge251bWJlcn0gZXJyb3JUaHJlc2hvbGQgQWNjZXB0YWJsZSBlcnJvciAoaW4gc291cmNlIHVuaXRzKS5cbiAgICogQHBhcmFtIHs/bnVtYmVyfSBvcHRfZGVzdGluYXRpb25SZXNvbHV0aW9uIFRoZSAob3B0aW9uYWwpIHJlc29sdXRpb24gb2YgdGhlIGRlc3RpbmF0aW9uLlxuICAgKi9cbiAgZnVuY3Rpb24gVHJpYW5ndWxhdGlvbihzb3VyY2VQcm9qLCB0YXJnZXRQcm9qLCB0YXJnZXRFeHRlbnQsIG1heFNvdXJjZUV4dGVudCwgZXJyb3JUaHJlc2hvbGQsIG9wdF9kZXN0aW5hdGlvblJlc29sdXRpb24pIHtcbiAgICAvKipcbiAgICAgKiBAdHlwZSB7aW1wb3J0KFwiLi4vcHJvai9Qcm9qZWN0aW9uLmpzXCIpLmRlZmF1bHR9XG4gICAgICogQHByaXZhdGVcbiAgICAgKi9cbiAgICB0aGlzLnNvdXJjZVByb2pfID0gc291cmNlUHJvajtcbiAgICAvKipcbiAgICAgKiBAdHlwZSB7aW1wb3J0KFwiLi4vcHJvai9Qcm9qZWN0aW9uLmpzXCIpLmRlZmF1bHR9XG4gICAgICogQHByaXZhdGVcbiAgICAgKi9cblxuICAgIHRoaXMudGFyZ2V0UHJval8gPSB0YXJnZXRQcm9qO1xuICAgIC8qKiBAdHlwZSB7IU9iamVjdDxzdHJpbmcsIGltcG9ydChcIi4uL2Nvb3JkaW5hdGUuanNcIikuQ29vcmRpbmF0ZT59ICovXG5cbiAgICB2YXIgdHJhbnNmb3JtSW52Q2FjaGUgPSB7fTtcbiAgICB2YXIgdHJhbnNmb3JtSW52ID0gZ2V0VHJhbnNmb3JtKHRoaXMudGFyZ2V0UHJval8sIHRoaXMuc291cmNlUHJval8pO1xuICAgIC8qKlxuICAgICAqIEBwYXJhbSB7aW1wb3J0KFwiLi4vY29vcmRpbmF0ZS5qc1wiKS5Db29yZGluYXRlfSBjIEEgY29vcmRpbmF0ZS5cbiAgICAgKiBAcmV0dXJuIHtpbXBvcnQoXCIuLi9jb29yZGluYXRlLmpzXCIpLkNvb3JkaW5hdGV9IFRyYW5zZm9ybWVkIGNvb3JkaW5hdGUuXG4gICAgICogQHByaXZhdGVcbiAgICAgKi9cblxuICAgIHRoaXMudHJhbnNmb3JtSW52XyA9IGZ1bmN0aW9uIChjKSB7XG4gICAgICB2YXIga2V5ID0gY1swXSArICcvJyArIGNbMV07XG5cbiAgICAgIGlmICghdHJhbnNmb3JtSW52Q2FjaGVba2V5XSkge1xuICAgICAgICB0cmFuc2Zvcm1JbnZDYWNoZVtrZXldID0gdHJhbnNmb3JtSW52KGMpO1xuICAgICAgfVxuXG4gICAgICByZXR1cm4gdHJhbnNmb3JtSW52Q2FjaGVba2V5XTtcbiAgICB9O1xuICAgIC8qKlxuICAgICAqIEB0eXBlIHtpbXBvcnQoXCIuLi9leHRlbnQuanNcIikuRXh0ZW50fVxuICAgICAqIEBwcml2YXRlXG4gICAgICovXG5cblxuICAgIHRoaXMubWF4U291cmNlRXh0ZW50XyA9IG1heFNvdXJjZUV4dGVudDtcbiAgICAvKipcbiAgICAgKiBAdHlwZSB7bnVtYmVyfVxuICAgICAqIEBwcml2YXRlXG4gICAgICovXG5cbiAgICB0aGlzLmVycm9yVGhyZXNob2xkU3F1YXJlZF8gPSBlcnJvclRocmVzaG9sZCAqIGVycm9yVGhyZXNob2xkO1xuICAgIC8qKlxuICAgICAqIEB0eXBlIHtBcnJheTxUcmlhbmdsZT59XG4gICAgICogQHByaXZhdGVcbiAgICAgKi9cblxuICAgIHRoaXMudHJpYW5nbGVzXyA9IFtdO1xuICAgIC8qKlxuICAgICAqIEluZGljYXRlcyB0aGF0IHRoZSB0cmlhbmd1bGF0aW9uIGNyb3NzZXMgZWRnZSBvZiB0aGUgc291cmNlIHByb2plY3Rpb24uXG4gICAgICogQHR5cGUge2Jvb2xlYW59XG4gICAgICogQHByaXZhdGVcbiAgICAgKi9cblxuICAgIHRoaXMud3JhcHNYSW5Tb3VyY2VfID0gZmFsc2U7XG4gICAgLyoqXG4gICAgICogQHR5cGUge2Jvb2xlYW59XG4gICAgICogQHByaXZhdGVcbiAgICAgKi9cblxuICAgIHRoaXMuY2FuV3JhcFhJblNvdXJjZV8gPSB0aGlzLnNvdXJjZVByb2pfLmNhbldyYXBYKCkgJiYgISFtYXhTb3VyY2VFeHRlbnQgJiYgISF0aGlzLnNvdXJjZVByb2pfLmdldEV4dGVudCgpICYmIGdldFdpZHRoKG1heFNvdXJjZUV4dGVudCkgPT0gZ2V0V2lkdGgodGhpcy5zb3VyY2VQcm9qXy5nZXRFeHRlbnQoKSk7XG4gICAgLyoqXG4gICAgICogQHR5cGUgez9udW1iZXJ9XG4gICAgICogQHByaXZhdGVcbiAgICAgKi9cblxuICAgIHRoaXMuc291cmNlV29ybGRXaWR0aF8gPSB0aGlzLnNvdXJjZVByb2pfLmdldEV4dGVudCgpID8gZ2V0V2lkdGgodGhpcy5zb3VyY2VQcm9qXy5nZXRFeHRlbnQoKSkgOiBudWxsO1xuICAgIC8qKlxuICAgICAqIEB0eXBlIHs/bnVtYmVyfVxuICAgICAqIEBwcml2YXRlXG4gICAgICovXG5cbiAgICB0aGlzLnRhcmdldFdvcmxkV2lkdGhfID0gdGhpcy50YXJnZXRQcm9qXy5nZXRFeHRlbnQoKSA/IGdldFdpZHRoKHRoaXMudGFyZ2V0UHJval8uZ2V0RXh0ZW50KCkpIDogbnVsbDtcbiAgICB2YXIgZGVzdGluYXRpb25Ub3BMZWZ0ID0gZ2V0VG9wTGVmdCh0YXJnZXRFeHRlbnQpO1xuICAgIHZhciBkZXN0aW5hdGlvblRvcFJpZ2h0ID0gZ2V0VG9wUmlnaHQodGFyZ2V0RXh0ZW50KTtcbiAgICB2YXIgZGVzdGluYXRpb25Cb3R0b21SaWdodCA9IGdldEJvdHRvbVJpZ2h0KHRhcmdldEV4dGVudCk7XG4gICAgdmFyIGRlc3RpbmF0aW9uQm90dG9tTGVmdCA9IGdldEJvdHRvbUxlZnQodGFyZ2V0RXh0ZW50KTtcbiAgICB2YXIgc291cmNlVG9wTGVmdCA9IHRoaXMudHJhbnNmb3JtSW52XyhkZXN0aW5hdGlvblRvcExlZnQpO1xuICAgIHZhciBzb3VyY2VUb3BSaWdodCA9IHRoaXMudHJhbnNmb3JtSW52XyhkZXN0aW5hdGlvblRvcFJpZ2h0KTtcbiAgICB2YXIgc291cmNlQm90dG9tUmlnaHQgPSB0aGlzLnRyYW5zZm9ybUludl8oZGVzdGluYXRpb25Cb3R0b21SaWdodCk7XG4gICAgdmFyIHNvdXJjZUJvdHRvbUxlZnQgPSB0aGlzLnRyYW5zZm9ybUludl8oZGVzdGluYXRpb25Cb3R0b21MZWZ0KTtcbiAgICAvKlxuICAgICAqIFRoZSBtYXhTdWJkaXZpc2lvbiBjb250cm9scyBob3cgbWFueSBzcGxpdHRpbmdzIG9mIHRoZSB0YXJnZXQgYXJlYSBjYW5cbiAgICAgKiBiZSBkb25lLiBUaGUgaWRlYSBoZXJlIGlzIHRvIGRvIGEgbGluZWFyIG1hcHBpbmcgb2YgdGhlIHRhcmdldCBhcmVhc1xuICAgICAqIGJ1dCB0aGUgYWN0dWFsIG92ZXJhbCByZXByb2plY3Rpb24gKGNhbiBiZSkgZXh0cmVtZWx5IG5vbi1saW5lYXIuIFRoZVxuICAgICAqIGRlZmF1bHQgdmFsdWUgb2YgTUFYX1NVQkRJVklTSU9OIHdhcyBjaG9zZW4gYmFzZWQgb24gbWFwcGluZyBhIDI1NngyNTZcbiAgICAgKiB0aWxlIHNpemUuIEhvd2V2ZXIgdGhpcyBmdW5jdGlvbiBpcyBhbHNvIGNhbGxlZCB0byByZW1hcCBjYW52YXMgcmVuZGVyZWRcbiAgICAgKiBsYXllcnMgd2hpY2ggY2FuIGJlIG11Y2ggbGFyZ2VyLiBUaGlzIGNhbGN1bGF0aW9uIGluY3JlYXNlcyB0aGUgbWF4U3ViZGl2aXNpb25cbiAgICAgKiB2YWx1ZSBieSB0aGUgcmlnaHQgZmFjdG9yIHNvIHRoYXQgZWFjaCAyNTZ4MjU2IHBpeGVsIGFyZWEgaGFzXG4gICAgICogTUFYX1NVQkRJVklTSU9OIGRpdmlzaW9ucy5cbiAgICAgKi9cblxuICAgIHZhciBtYXhTdWJkaXZpc2lvbiA9IE1BWF9TVUJESVZJU0lPTiArIChvcHRfZGVzdGluYXRpb25SZXNvbHV0aW9uID8gTWF0aC5tYXgoMCwgTWF0aC5jZWlsKGxvZzIoZ2V0QXJlYSh0YXJnZXRFeHRlbnQpIC8gKG9wdF9kZXN0aW5hdGlvblJlc29sdXRpb24gKiBvcHRfZGVzdGluYXRpb25SZXNvbHV0aW9uICogMjU2ICogMjU2KSkpKSA6IDApO1xuICAgIHRoaXMuYWRkUXVhZF8oZGVzdGluYXRpb25Ub3BMZWZ0LCBkZXN0aW5hdGlvblRvcFJpZ2h0LCBkZXN0aW5hdGlvbkJvdHRvbVJpZ2h0LCBkZXN0aW5hdGlvbkJvdHRvbUxlZnQsIHNvdXJjZVRvcExlZnQsIHNvdXJjZVRvcFJpZ2h0LCBzb3VyY2VCb3R0b21SaWdodCwgc291cmNlQm90dG9tTGVmdCwgbWF4U3ViZGl2aXNpb24pO1xuXG4gICAgaWYgKHRoaXMud3JhcHNYSW5Tb3VyY2VfKSB7XG4gICAgICB2YXIgbGVmdEJvdW5kXzEgPSBJbmZpbml0eTtcbiAgICAgIHRoaXMudHJpYW5nbGVzXy5mb3JFYWNoKGZ1bmN0aW9uICh0cmlhbmdsZSwgaSwgYXJyKSB7XG4gICAgICAgIGxlZnRCb3VuZF8xID0gTWF0aC5taW4obGVmdEJvdW5kXzEsIHRyaWFuZ2xlLnNvdXJjZVswXVswXSwgdHJpYW5nbGUuc291cmNlWzFdWzBdLCB0cmlhbmdsZS5zb3VyY2VbMl1bMF0pO1xuICAgICAgfSk7IC8vIFNoaWZ0IHRyaWFuZ2xlcyB0byBiZSBhcyBjbG9zZSB0byBgbGVmdEJvdW5kYCBhcyBwb3NzaWJsZVxuICAgICAgLy8gKGlmIHRoZSBkaXN0YW5jZSBpcyBtb3JlIHRoYW4gYHdvcmxkV2lkdGggLyAyYCBpdCBjYW4gYmUgY2xvc2VyLlxuXG4gICAgICB0aGlzLnRyaWFuZ2xlc18uZm9yRWFjaChmdW5jdGlvbiAodHJpYW5nbGUpIHtcbiAgICAgICAgaWYgKE1hdGgubWF4KHRyaWFuZ2xlLnNvdXJjZVswXVswXSwgdHJpYW5nbGUuc291cmNlWzFdWzBdLCB0cmlhbmdsZS5zb3VyY2VbMl1bMF0pIC0gbGVmdEJvdW5kXzEgPiB0aGlzLnNvdXJjZVdvcmxkV2lkdGhfIC8gMikge1xuICAgICAgICAgIHZhciBuZXdUcmlhbmdsZSA9IFtbdHJpYW5nbGUuc291cmNlWzBdWzBdLCB0cmlhbmdsZS5zb3VyY2VbMF1bMV1dLCBbdHJpYW5nbGUuc291cmNlWzFdWzBdLCB0cmlhbmdsZS5zb3VyY2VbMV1bMV1dLCBbdHJpYW5nbGUuc291cmNlWzJdWzBdLCB0cmlhbmdsZS5zb3VyY2VbMl1bMV1dXTtcblxuICAgICAgICAgIGlmIChuZXdUcmlhbmdsZVswXVswXSAtIGxlZnRCb3VuZF8xID4gdGhpcy5zb3VyY2VXb3JsZFdpZHRoXyAvIDIpIHtcbiAgICAgICAgICAgIG5ld1RyaWFuZ2xlWzBdWzBdIC09IHRoaXMuc291cmNlV29ybGRXaWR0aF87XG4gICAgICAgICAgfVxuXG4gICAgICAgICAgaWYgKG5ld1RyaWFuZ2xlWzFdWzBdIC0gbGVmdEJvdW5kXzEgPiB0aGlzLnNvdXJjZVdvcmxkV2lkdGhfIC8gMikge1xuICAgICAgICAgICAgbmV3VHJpYW5nbGVbMV1bMF0gLT0gdGhpcy5zb3VyY2VXb3JsZFdpZHRoXztcbiAgICAgICAgICB9XG5cbiAgICAgICAgICBpZiAobmV3VHJpYW5nbGVbMl1bMF0gLSBsZWZ0Qm91bmRfMSA+IHRoaXMuc291cmNlV29ybGRXaWR0aF8gLyAyKSB7XG4gICAgICAgICAgICBuZXdUcmlhbmdsZVsyXVswXSAtPSB0aGlzLnNvdXJjZVdvcmxkV2lkdGhfO1xuICAgICAgICAgIH0gLy8gUmFyZWx5IChpZiB0aGUgZXh0ZW50IGNvbnRhaW5zIGJvdGggdGhlIGRhdGVsaW5lIGFuZCBwcmltZSBtZXJpZGlhbilcbiAgICAgICAgICAvLyB0aGUgc2hpZnQgY2FuIGluIHR1cm4gYnJlYWsgc29tZSB0cmlhbmdsZXMuXG4gICAgICAgICAgLy8gRGV0ZWN0IHRoaXMgaGVyZSBhbmQgZG9uJ3Qgc2hpZnQgaW4gc3VjaCBjYXNlcy5cblxuXG4gICAgICAgICAgdmFyIG1pblggPSBNYXRoLm1pbihuZXdUcmlhbmdsZVswXVswXSwgbmV3VHJpYW5nbGVbMV1bMF0sIG5ld1RyaWFuZ2xlWzJdWzBdKTtcbiAgICAgICAgICB2YXIgbWF4WCA9IE1hdGgubWF4KG5ld1RyaWFuZ2xlWzBdWzBdLCBuZXdUcmlhbmdsZVsxXVswXSwgbmV3VHJpYW5nbGVbMl1bMF0pO1xuXG4gICAgICAgICAgaWYgKG1heFggLSBtaW5YIDwgdGhpcy5zb3VyY2VXb3JsZFdpZHRoXyAvIDIpIHtcbiAgICAgICAgICAgIHRyaWFuZ2xlLnNvdXJjZSA9IG5ld1RyaWFuZ2xlO1xuICAgICAgICAgIH1cbiAgICAgICAgfVxuICAgICAgfS5iaW5kKHRoaXMpKTtcbiAgICB9XG5cbiAgICB0cmFuc2Zvcm1JbnZDYWNoZSA9IHt9O1xuICB9XG4gIC8qKlxuICAgKiBBZGRzIHRyaWFuZ2xlIHRvIHRoZSB0cmlhbmd1bGF0aW9uLlxuICAgKiBAcGFyYW0ge2ltcG9ydChcIi4uL2Nvb3JkaW5hdGUuanNcIikuQ29vcmRpbmF0ZX0gYSBUaGUgdGFyZ2V0IGEgY29vcmRpbmF0ZS5cbiAgICogQHBhcmFtIHtpbXBvcnQoXCIuLi9jb29yZGluYXRlLmpzXCIpLkNvb3JkaW5hdGV9IGIgVGhlIHRhcmdldCBiIGNvb3JkaW5hdGUuXG4gICAqIEBwYXJhbSB7aW1wb3J0KFwiLi4vY29vcmRpbmF0ZS5qc1wiKS5Db29yZGluYXRlfSBjIFRoZSB0YXJnZXQgYyBjb29yZGluYXRlLlxuICAgKiBAcGFyYW0ge2ltcG9ydChcIi4uL2Nvb3JkaW5hdGUuanNcIikuQ29vcmRpbmF0ZX0gYVNyYyBUaGUgc291cmNlIGEgY29vcmRpbmF0ZS5cbiAgICogQHBhcmFtIHtpbXBvcnQoXCIuLi9jb29yZGluYXRlLmpzXCIpLkNvb3JkaW5hdGV9IGJTcmMgVGhlIHNvdXJjZSBiIGNvb3JkaW5hdGUuXG4gICAqIEBwYXJhbSB7aW1wb3J0KFwiLi4vY29vcmRpbmF0ZS5qc1wiKS5Db29yZGluYXRlfSBjU3JjIFRoZSBzb3VyY2UgYyBjb29yZGluYXRlLlxuICAgKiBAcHJpdmF0ZVxuICAgKi9cblxuXG4gIFRyaWFuZ3VsYXRpb24ucHJvdG90eXBlLmFkZFRyaWFuZ2xlXyA9IGZ1bmN0aW9uIChhLCBiLCBjLCBhU3JjLCBiU3JjLCBjU3JjKSB7XG4gICAgdGhpcy50cmlhbmdsZXNfLnB1c2goe1xuICAgICAgc291cmNlOiBbYVNyYywgYlNyYywgY1NyY10sXG4gICAgICB0YXJnZXQ6IFthLCBiLCBjXVxuICAgIH0pO1xuICB9O1xuICAvKipcbiAgICogQWRkcyBxdWFkIChwb2ludHMgaW4gY2xvY2std2lzZSBvcmRlcikgdG8gdGhlIHRyaWFuZ3VsYXRpb25cbiAgICogKGFuZCByZXByb2plY3RzIHRoZSB2ZXJ0aWNlcykgaWYgdmFsaWQuXG4gICAqIFBlcmZvcm1zIHF1YWQgc3ViZGl2aXNpb24gaWYgbmVlZGVkIHRvIGluY3JlYXNlIHByZWNpc2lvbi5cbiAgICpcbiAgICogQHBhcmFtIHtpbXBvcnQoXCIuLi9jb29yZGluYXRlLmpzXCIpLkNvb3JkaW5hdGV9IGEgVGhlIHRhcmdldCBhIGNvb3JkaW5hdGUuXG4gICAqIEBwYXJhbSB7aW1wb3J0KFwiLi4vY29vcmRpbmF0ZS5qc1wiKS5Db29yZGluYXRlfSBiIFRoZSB0YXJnZXQgYiBjb29yZGluYXRlLlxuICAgKiBAcGFyYW0ge2ltcG9ydChcIi4uL2Nvb3JkaW5hdGUuanNcIikuQ29vcmRpbmF0ZX0gYyBUaGUgdGFyZ2V0IGMgY29vcmRpbmF0ZS5cbiAgICogQHBhcmFtIHtpbXBvcnQoXCIuLi9jb29yZGluYXRlLmpzXCIpLkNvb3JkaW5hdGV9IGQgVGhlIHRhcmdldCBkIGNvb3JkaW5hdGUuXG4gICAqIEBwYXJhbSB7aW1wb3J0KFwiLi4vY29vcmRpbmF0ZS5qc1wiKS5Db29yZGluYXRlfSBhU3JjIFRoZSBzb3VyY2UgYSBjb29yZGluYXRlLlxuICAgKiBAcGFyYW0ge2ltcG9ydChcIi4uL2Nvb3JkaW5hdGUuanNcIikuQ29vcmRpbmF0ZX0gYlNyYyBUaGUgc291cmNlIGIgY29vcmRpbmF0ZS5cbiAgICogQHBhcmFtIHtpbXBvcnQoXCIuLi9jb29yZGluYXRlLmpzXCIpLkNvb3JkaW5hdGV9IGNTcmMgVGhlIHNvdXJjZSBjIGNvb3JkaW5hdGUuXG4gICAqIEBwYXJhbSB7aW1wb3J0KFwiLi4vY29vcmRpbmF0ZS5qc1wiKS5Db29yZGluYXRlfSBkU3JjIFRoZSBzb3VyY2UgZCBjb29yZGluYXRlLlxuICAgKiBAcGFyYW0ge251bWJlcn0gbWF4U3ViZGl2aXNpb24gTWF4aW1hbCBhbGxvd2VkIHN1YmRpdmlzaW9uIG9mIHRoZSBxdWFkLlxuICAgKiBAcHJpdmF0ZVxuICAgKi9cblxuXG4gIFRyaWFuZ3VsYXRpb24ucHJvdG90eXBlLmFkZFF1YWRfID0gZnVuY3Rpb24gKGEsIGIsIGMsIGQsIGFTcmMsIGJTcmMsIGNTcmMsIGRTcmMsIG1heFN1YmRpdmlzaW9uKSB7XG4gICAgdmFyIHNvdXJjZVF1YWRFeHRlbnQgPSBib3VuZGluZ0V4dGVudChbYVNyYywgYlNyYywgY1NyYywgZFNyY10pO1xuICAgIHZhciBzb3VyY2VDb3ZlcmFnZVggPSB0aGlzLnNvdXJjZVdvcmxkV2lkdGhfID8gZ2V0V2lkdGgoc291cmNlUXVhZEV4dGVudCkgLyB0aGlzLnNvdXJjZVdvcmxkV2lkdGhfIDogbnVsbDtcbiAgICB2YXIgc291cmNlV29ybGRXaWR0aCA9XG4gICAgLyoqIEB0eXBlIHtudW1iZXJ9ICovXG4gICAgdGhpcy5zb3VyY2VXb3JsZFdpZHRoXzsgLy8gd2hlbiB0aGUgcXVhZCBpcyB3cmFwcGVkIGluIHRoZSBzb3VyY2UgcHJvamVjdGlvblxuICAgIC8vIGl0IGNvdmVycyBtb3N0IG9mIHRoZSBwcm9qZWN0aW9uIGV4dGVudCwgYnV0IG5vdCBmdWxseVxuXG4gICAgdmFyIHdyYXBzWCA9IHRoaXMuc291cmNlUHJval8uY2FuV3JhcFgoKSAmJiBzb3VyY2VDb3ZlcmFnZVggPiAwLjUgJiYgc291cmNlQ292ZXJhZ2VYIDwgMTtcbiAgICB2YXIgbmVlZHNTdWJkaXZpc2lvbiA9IGZhbHNlO1xuXG4gICAgaWYgKG1heFN1YmRpdmlzaW9uID4gMCkge1xuICAgICAgaWYgKHRoaXMudGFyZ2V0UHJval8uaXNHbG9iYWwoKSAmJiB0aGlzLnRhcmdldFdvcmxkV2lkdGhfKSB7XG4gICAgICAgIHZhciB0YXJnZXRRdWFkRXh0ZW50ID0gYm91bmRpbmdFeHRlbnQoW2EsIGIsIGMsIGRdKTtcbiAgICAgICAgdmFyIHRhcmdldENvdmVyYWdlWCA9IGdldFdpZHRoKHRhcmdldFF1YWRFeHRlbnQpIC8gdGhpcy50YXJnZXRXb3JsZFdpZHRoXztcbiAgICAgICAgbmVlZHNTdWJkaXZpc2lvbiA9IHRhcmdldENvdmVyYWdlWCA+IE1BWF9UUklBTkdMRV9XSURUSCB8fCBuZWVkc1N1YmRpdmlzaW9uO1xuICAgICAgfVxuXG4gICAgICBpZiAoIXdyYXBzWCAmJiB0aGlzLnNvdXJjZVByb2pfLmlzR2xvYmFsKCkgJiYgc291cmNlQ292ZXJhZ2VYKSB7XG4gICAgICAgIG5lZWRzU3ViZGl2aXNpb24gPSBzb3VyY2VDb3ZlcmFnZVggPiBNQVhfVFJJQU5HTEVfV0lEVEggfHwgbmVlZHNTdWJkaXZpc2lvbjtcbiAgICAgIH1cbiAgICB9XG5cbiAgICBpZiAoIW5lZWRzU3ViZGl2aXNpb24gJiYgdGhpcy5tYXhTb3VyY2VFeHRlbnRfKSB7XG4gICAgICBpZiAoaXNGaW5pdGUoc291cmNlUXVhZEV4dGVudFswXSkgJiYgaXNGaW5pdGUoc291cmNlUXVhZEV4dGVudFsxXSkgJiYgaXNGaW5pdGUoc291cmNlUXVhZEV4dGVudFsyXSkgJiYgaXNGaW5pdGUoc291cmNlUXVhZEV4dGVudFszXSkpIHtcbiAgICAgICAgaWYgKCFpbnRlcnNlY3RzKHNvdXJjZVF1YWRFeHRlbnQsIHRoaXMubWF4U291cmNlRXh0ZW50XykpIHtcbiAgICAgICAgICAvLyB3aG9sZSBxdWFkIG91dHNpZGUgc291cmNlIHByb2plY3Rpb24gZXh0ZW50IC0+IGlnbm9yZVxuICAgICAgICAgIHJldHVybjtcbiAgICAgICAgfVxuICAgICAgfVxuICAgIH1cblxuICAgIHZhciBpc05vdEZpbml0ZSA9IDA7XG5cbiAgICBpZiAoIW5lZWRzU3ViZGl2aXNpb24pIHtcbiAgICAgIGlmICghaXNGaW5pdGUoYVNyY1swXSkgfHwgIWlzRmluaXRlKGFTcmNbMV0pIHx8ICFpc0Zpbml0ZShiU3JjWzBdKSB8fCAhaXNGaW5pdGUoYlNyY1sxXSkgfHwgIWlzRmluaXRlKGNTcmNbMF0pIHx8ICFpc0Zpbml0ZShjU3JjWzFdKSB8fCAhaXNGaW5pdGUoZFNyY1swXSkgfHwgIWlzRmluaXRlKGRTcmNbMV0pKSB7XG4gICAgICAgIGlmIChtYXhTdWJkaXZpc2lvbiA+IDApIHtcbiAgICAgICAgICBuZWVkc1N1YmRpdmlzaW9uID0gdHJ1ZTtcbiAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAvLyBJdCBtaWdodCBiZSB0aGUgY2FzZSB0aGF0IG9ubHkgMSBvZiB0aGUgcG9pbnRzIGlzIGluZmluaXRlLiBJbiB0aGlzIGNhc2VcbiAgICAgICAgICAvLyB3ZSBjYW4gZHJhdyBhIHNpbmdsZSB0cmlhbmdsZSB3aXRoIHRoZSBvdGhlciB0aHJlZSBwb2ludHNcbiAgICAgICAgICBpc05vdEZpbml0ZSA9ICghaXNGaW5pdGUoYVNyY1swXSkgfHwgIWlzRmluaXRlKGFTcmNbMV0pID8gOCA6IDApICsgKCFpc0Zpbml0ZShiU3JjWzBdKSB8fCAhaXNGaW5pdGUoYlNyY1sxXSkgPyA0IDogMCkgKyAoIWlzRmluaXRlKGNTcmNbMF0pIHx8ICFpc0Zpbml0ZShjU3JjWzFdKSA/IDIgOiAwKSArICghaXNGaW5pdGUoZFNyY1swXSkgfHwgIWlzRmluaXRlKGRTcmNbMV0pID8gMSA6IDApO1xuXG4gICAgICAgICAgaWYgKGlzTm90RmluaXRlICE9IDEgJiYgaXNOb3RGaW5pdGUgIT0gMiAmJiBpc05vdEZpbml0ZSAhPSA0ICYmIGlzTm90RmluaXRlICE9IDgpIHtcbiAgICAgICAgICAgIHJldHVybjtcbiAgICAgICAgICB9XG4gICAgICAgIH1cbiAgICAgIH1cbiAgICB9XG5cbiAgICBpZiAobWF4U3ViZGl2aXNpb24gPiAwKSB7XG4gICAgICBpZiAoIW5lZWRzU3ViZGl2aXNpb24pIHtcbiAgICAgICAgdmFyIGNlbnRlciA9IFsoYVswXSArIGNbMF0pIC8gMiwgKGFbMV0gKyBjWzFdKSAvIDJdO1xuICAgICAgICB2YXIgY2VudGVyU3JjID0gdGhpcy50cmFuc2Zvcm1JbnZfKGNlbnRlcik7XG4gICAgICAgIHZhciBkeCA9IHZvaWQgMDtcblxuICAgICAgICBpZiAod3JhcHNYKSB7XG4gICAgICAgICAgdmFyIGNlbnRlclNyY0VzdGltWCA9IChtb2R1bG8oYVNyY1swXSwgc291cmNlV29ybGRXaWR0aCkgKyBtb2R1bG8oY1NyY1swXSwgc291cmNlV29ybGRXaWR0aCkpIC8gMjtcbiAgICAgICAgICBkeCA9IGNlbnRlclNyY0VzdGltWCAtIG1vZHVsbyhjZW50ZXJTcmNbMF0sIHNvdXJjZVdvcmxkV2lkdGgpO1xuICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgIGR4ID0gKGFTcmNbMF0gKyBjU3JjWzBdKSAvIDIgLSBjZW50ZXJTcmNbMF07XG4gICAgICAgIH1cblxuICAgICAgICB2YXIgZHkgPSAoYVNyY1sxXSArIGNTcmNbMV0pIC8gMiAtIGNlbnRlclNyY1sxXTtcbiAgICAgICAgdmFyIGNlbnRlclNyY0Vycm9yU3F1YXJlZCA9IGR4ICogZHggKyBkeSAqIGR5O1xuICAgICAgICBuZWVkc1N1YmRpdmlzaW9uID0gY2VudGVyU3JjRXJyb3JTcXVhcmVkID4gdGhpcy5lcnJvclRocmVzaG9sZFNxdWFyZWRfO1xuICAgICAgfVxuXG4gICAgICBpZiAobmVlZHNTdWJkaXZpc2lvbikge1xuICAgICAgICBpZiAoTWF0aC5hYnMoYVswXSAtIGNbMF0pIDw9IE1hdGguYWJzKGFbMV0gLSBjWzFdKSkge1xuICAgICAgICAgIC8vIHNwbGl0IGhvcml6b250YWxseSAodG9wICYgYm90dG9tKVxuICAgICAgICAgIHZhciBiYyA9IFsoYlswXSArIGNbMF0pIC8gMiwgKGJbMV0gKyBjWzFdKSAvIDJdO1xuICAgICAgICAgIHZhciBiY1NyYyA9IHRoaXMudHJhbnNmb3JtSW52XyhiYyk7XG4gICAgICAgICAgdmFyIGRhID0gWyhkWzBdICsgYVswXSkgLyAyLCAoZFsxXSArIGFbMV0pIC8gMl07XG4gICAgICAgICAgdmFyIGRhU3JjID0gdGhpcy50cmFuc2Zvcm1JbnZfKGRhKTtcbiAgICAgICAgICB0aGlzLmFkZFF1YWRfKGEsIGIsIGJjLCBkYSwgYVNyYywgYlNyYywgYmNTcmMsIGRhU3JjLCBtYXhTdWJkaXZpc2lvbiAtIDEpO1xuICAgICAgICAgIHRoaXMuYWRkUXVhZF8oZGEsIGJjLCBjLCBkLCBkYVNyYywgYmNTcmMsIGNTcmMsIGRTcmMsIG1heFN1YmRpdmlzaW9uIC0gMSk7XG4gICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgLy8gc3BsaXQgdmVydGljYWxseSAobGVmdCAmIHJpZ2h0KVxuICAgICAgICAgIHZhciBhYiA9IFsoYVswXSArIGJbMF0pIC8gMiwgKGFbMV0gKyBiWzFdKSAvIDJdO1xuICAgICAgICAgIHZhciBhYlNyYyA9IHRoaXMudHJhbnNmb3JtSW52XyhhYik7XG4gICAgICAgICAgdmFyIGNkID0gWyhjWzBdICsgZFswXSkgLyAyLCAoY1sxXSArIGRbMV0pIC8gMl07XG4gICAgICAgICAgdmFyIGNkU3JjID0gdGhpcy50cmFuc2Zvcm1JbnZfKGNkKTtcbiAgICAgICAgICB0aGlzLmFkZFF1YWRfKGEsIGFiLCBjZCwgZCwgYVNyYywgYWJTcmMsIGNkU3JjLCBkU3JjLCBtYXhTdWJkaXZpc2lvbiAtIDEpO1xuICAgICAgICAgIHRoaXMuYWRkUXVhZF8oYWIsIGIsIGMsIGNkLCBhYlNyYywgYlNyYywgY1NyYywgY2RTcmMsIG1heFN1YmRpdmlzaW9uIC0gMSk7XG4gICAgICAgIH1cblxuICAgICAgICByZXR1cm47XG4gICAgICB9XG4gICAgfVxuXG4gICAgaWYgKHdyYXBzWCkge1xuICAgICAgaWYgKCF0aGlzLmNhbldyYXBYSW5Tb3VyY2VfKSB7XG4gICAgICAgIHJldHVybjtcbiAgICAgIH1cblxuICAgICAgdGhpcy53cmFwc1hJblNvdXJjZV8gPSB0cnVlO1xuICAgIH0gLy8gRXhhY3RseSB6ZXJvIG9yIG9uZSBvZiAqU3JjIGlzIG5vdCBmaW5pdGVcbiAgICAvLyBUaGUgdHJpYW5nbGVzIG11c3QgaGF2ZSB0aGUgZGlhZ29uYWwgbGluZSBhcyB0aGUgZmlyc3Qgc2lkZVxuICAgIC8vIFRoaXMgaXMgdG8gYWxsb3cgZWFzeSBjb2RlIGluIHJlcHJvai5zIHRvIG1ha2UgaXQgc3RyYWlnaHQgZm9yIGJyb2tlblxuICAgIC8vIGJyb3dzZXJzIHRoYXQgY2FuJ3QgaGFuZGxlIGRpYWdvbmFsIGNsaXBwaW5nXG5cblxuICAgIGlmICgoaXNOb3RGaW5pdGUgJiAweGIpID09IDApIHtcbiAgICAgIHRoaXMuYWRkVHJpYW5nbGVfKGEsIGMsIGQsIGFTcmMsIGNTcmMsIGRTcmMpO1xuICAgIH1cblxuICAgIGlmICgoaXNOb3RGaW5pdGUgJiAweGUpID09IDApIHtcbiAgICAgIHRoaXMuYWRkVHJpYW5nbGVfKGEsIGMsIGIsIGFTcmMsIGNTcmMsIGJTcmMpO1xuICAgIH1cblxuICAgIGlmIChpc05vdEZpbml0ZSkge1xuICAgICAgLy8gVHJ5IHRoZSBvdGhlciB0d28gdHJpYW5nbGVzXG4gICAgICBpZiAoKGlzTm90RmluaXRlICYgMHhkKSA9PSAwKSB7XG4gICAgICAgIHRoaXMuYWRkVHJpYW5nbGVfKGIsIGQsIGEsIGJTcmMsIGRTcmMsIGFTcmMpO1xuICAgICAgfVxuXG4gICAgICBpZiAoKGlzTm90RmluaXRlICYgMHg3KSA9PSAwKSB7XG4gICAgICAgIHRoaXMuYWRkVHJpYW5nbGVfKGIsIGQsIGMsIGJTcmMsIGRTcmMsIGNTcmMpO1xuICAgICAgfVxuICAgIH1cbiAgfTtcbiAgLyoqXG4gICAqIENhbGN1bGF0ZXMgZXh0ZW50IG9mIHRoZSAnc291cmNlJyBjb29yZGluYXRlcyBmcm9tIGFsbCB0aGUgdHJpYW5nbGVzLlxuICAgKlxuICAgKiBAcmV0dXJuIHtpbXBvcnQoXCIuLi9leHRlbnQuanNcIikuRXh0ZW50fSBDYWxjdWxhdGVkIGV4dGVudC5cbiAgICovXG5cblxuICBUcmlhbmd1bGF0aW9uLnByb3RvdHlwZS5jYWxjdWxhdGVTb3VyY2VFeHRlbnQgPSBmdW5jdGlvbiAoKSB7XG4gICAgdmFyIGV4dGVudCA9IGNyZWF0ZUVtcHR5KCk7XG4gICAgdGhpcy50cmlhbmdsZXNfLmZvckVhY2goZnVuY3Rpb24gKHRyaWFuZ2xlLCBpLCBhcnIpIHtcbiAgICAgIHZhciBzcmMgPSB0cmlhbmdsZS5zb3VyY2U7XG4gICAgICBleHRlbmRDb29yZGluYXRlKGV4dGVudCwgc3JjWzBdKTtcbiAgICAgIGV4dGVuZENvb3JkaW5hdGUoZXh0ZW50LCBzcmNbMV0pO1xuICAgICAgZXh0ZW5kQ29vcmRpbmF0ZShleHRlbnQsIHNyY1syXSk7XG4gICAgfSk7XG4gICAgcmV0dXJuIGV4dGVudDtcbiAgfTtcbiAgLyoqXG4gICAqIEByZXR1cm4ge0FycmF5PFRyaWFuZ2xlPn0gQXJyYXkgb2YgdGhlIGNhbGN1bGF0ZWQgdHJpYW5nbGVzLlxuICAgKi9cblxuXG4gIFRyaWFuZ3VsYXRpb24ucHJvdG90eXBlLmdldFRyaWFuZ2xlcyA9IGZ1bmN0aW9uICgpIHtcbiAgICByZXR1cm4gdGhpcy50cmlhbmdsZXNfO1xuICB9O1xuXG4gIHJldHVybiBUcmlhbmd1bGF0aW9uO1xufSgpO1xuXG5leHBvcnQgZGVmYXVsdCBUcmlhbmd1bGF0aW9uOyIsIi8qKlxuICogQG1vZHVsZSBvbC9zb3VyY2UvY29tbW9uXG4gKi9cblxuLyoqXG4gKiBEZWZhdWx0IFdNUyB2ZXJzaW9uLlxuICogQHR5cGUge3N0cmluZ31cbiAqL1xuZXhwb3J0IHZhciBERUZBVUxUX1dNU19WRVJTSU9OID0gJzEuMy4wJztcbi8qKlxuICogQ29udGV4dCBvcHRpb25zIHRvIGRpc2FibGUgaW1hZ2Ugc21vb3RoaW5nLlxuICogQHR5cGUge09iamVjdH1cbiAqL1xuXG5leHBvcnQgdmFyIElNQUdFX1NNT09USElOR19ESVNBQkxFRCA9IHtcbiAgaW1hZ2VTbW9vdGhpbmdFbmFibGVkOiBmYWxzZSxcbiAgbXNJbWFnZVNtb290aGluZ0VuYWJsZWQ6IGZhbHNlXG59OyIsIi8qKlxuICogQG1vZHVsZSBvbC9yZXByb2pcbiAqL1xuaW1wb3J0IHsgSU1BR0VfU01PT1RISU5HX0RJU0FCTEVEIH0gZnJvbSAnLi9zb3VyY2UvY29tbW9uLmpzJztcbmltcG9ydCB7IGFzc2lnbiB9IGZyb20gJy4vb2JqLmpzJztcbmltcG9ydCB7IGNvbnRhaW5zQ29vcmRpbmF0ZSwgY3JlYXRlRW1wdHksIGV4dGVuZCwgZm9yRWFjaENvcm5lciwgZ2V0Q2VudGVyLCBnZXRIZWlnaHQsIGdldFRvcExlZnQsIGdldFdpZHRoIH0gZnJvbSAnLi9leHRlbnQuanMnO1xuaW1wb3J0IHsgY3JlYXRlQ2FudmFzQ29udGV4dDJEIH0gZnJvbSAnLi9kb20uanMnO1xuaW1wb3J0IHsgZ2V0UG9pbnRSZXNvbHV0aW9uLCB0cmFuc2Zvcm0gfSBmcm9tICcuL3Byb2ouanMnO1xuaW1wb3J0IHsgc29sdmVMaW5lYXJTeXN0ZW0gfSBmcm9tICcuL21hdGguanMnO1xudmFyIGJyb2tlbkRpYWdvbmFsUmVuZGVyaW5nXztcbi8qKlxuICogVGhpcyBkcmF3cyBhIHNtYWxsIHRyaWFuZ2xlIGludG8gYSBjYW52YXMgYnkgc2V0dGluZyB0aGUgdHJpYW5nbGUgYXMgdGhlIGNsaXAgcmVnaW9uXG4gKiBhbmQgdGhlbiBkcmF3aW5nIGEgKHRvbyBsYXJnZSkgcmVjdGFuZ2xlXG4gKlxuICogQHBhcmFtIHtDYW52YXNSZW5kZXJpbmdDb250ZXh0MkR9IGN0eCBUaGUgY29udGV4dCBpbiB3aGljaCB0byBkcmF3IHRoZSB0cmlhbmdsZVxuICogQHBhcmFtIHtudW1iZXJ9IHUxIFRoZSB4LWNvb3JkaW5hdGUgb2YgdGhlIHNlY29uZCBwb2ludC4gVGhlIGZpcnN0IHBvaW50IGlzIDAsMC5cbiAqIEBwYXJhbSB7bnVtYmVyfSB2MSBUaGUgeS1jb29yZGluYXRlIG9mIHRoZSBzZWNvbmQgcG9pbnQuXG4gKiBAcGFyYW0ge251bWJlcn0gdTIgVGhlIHgtY29vcmRpbmF0ZSBvZiB0aGUgdGhpcmQgcG9pbnQuXG4gKiBAcGFyYW0ge251bWJlcn0gdjIgVGhlIHktY29vcmRpbmF0ZSBvZiB0aGUgdGhpcmQgcG9pbnQuXG4gKi9cblxuZnVuY3Rpb24gZHJhd1Rlc3RUcmlhbmdsZShjdHgsIHUxLCB2MSwgdTIsIHYyKSB7XG4gIGN0eC5iZWdpblBhdGgoKTtcbiAgY3R4Lm1vdmVUbygwLCAwKTtcbiAgY3R4LmxpbmVUbyh1MSwgdjEpO1xuICBjdHgubGluZVRvKHUyLCB2Mik7XG4gIGN0eC5jbG9zZVBhdGgoKTtcbiAgY3R4LnNhdmUoKTtcbiAgY3R4LmNsaXAoKTtcbiAgY3R4LmZpbGxSZWN0KDAsIDAsIE1hdGgubWF4KHUxLCB1MikgKyAxLCBNYXRoLm1heCh2MSwgdjIpKTtcbiAgY3R4LnJlc3RvcmUoKTtcbn1cbi8qKlxuICogR2l2ZW4gdGhlIGRhdGEgZnJvbSBnZXRJbWFnZURhdGEsIHNlZSBpZiB0aGUgcmlnaHQgdmFsdWVzIGFwcGVhciBhdCB0aGUgcHJvdmlkZWQgb2Zmc2V0LlxuICogUmV0dXJucyB0cnVlIGlmIGVpdGhlciB0aGUgY29sb3Igb3IgdHJhbnNwYXJlbmN5IGlzIG9mZlxuICpcbiAqIEBwYXJhbSB7VWludDhDbGFtcGVkQXJyYXl9IGRhdGEgVGhlIGRhdGEgcmV0dXJuZWQgZnJvbSBnZXRJbWFnZURhdGFcbiAqIEBwYXJhbSB7bnVtYmVyfSBvZmZzZXQgVGhlIHBpeGVsIG9mZnNldCBmcm9tIHRoZSBzdGFydCBvZiBkYXRhLlxuICogQHJldHVybiB7Ym9vbGVhbn0gdHJ1ZSBpZiB0aGUgZGlhZ29uYWwgcmVuZGVyaW5nIGlzIGJyb2tlblxuICovXG5cblxuZnVuY3Rpb24gdmVyaWZ5QnJva2VuRGlhZ29uYWxSZW5kZXJpbmcoZGF0YSwgb2Zmc2V0KSB7XG4gIC8vIHRoZSB2YWx1ZXMgb3VnaHQgdG8gYmUgY2xvc2UgdG8gdGhlIHJnYmEoMjEwLCAwLCAwLCAwLjc1KVxuICByZXR1cm4gTWF0aC5hYnMoZGF0YVtvZmZzZXQgKiA0XSAtIDIxMCkgPiAyIHx8IE1hdGguYWJzKGRhdGFbb2Zmc2V0ICogNCArIDNdIC0gMC43NSAqIDI1NSkgPiAyO1xufVxuLyoqXG4gKiBEZXRlcm1pbmVzIGlmIHRoZSBjdXJyZW50IGJyb3dzZXIgY29uZmlndXJhdGlvbiBjYW4gcmVuZGVyIHRyaWFuZ3VsYXIgY2xpcCByZWdpb25zIGNvcnJlY3RseS5cbiAqIFRoaXMgdmFsdWUgaXMgY2FjaGVkIHNvIHRoZSBmdW5jdGlvbiBpcyBvbmx5IGV4cGVuc2l2ZSB0aGUgZmlyc3QgdGltZSBjYWxsZWQuXG4gKiBGaXJlZm94IG9uIFdpbmRvd3MgKGFzIG9mIG5vdykgZG9lcyBub3QgaWYgSFdBIGlzIGVuYWJsZWQuIFNlZSBodHRwczovL2J1Z3ppbGxhLm1vemlsbGEub3JnL3Nob3dfYnVnLmNnaT9pZD0xNjA2OTc2XG4gKiBJRSBhbHNvIGRvZXNuJ3QuIENocm9tZSB3b3JrcywgYW5kIGV2ZXJ5dGhpbmcgc2VlbXMgdG8gd29yayBvbiBPU1ggYW5kIEFuZHJvaWQuIFRoaXMgZnVuY3Rpb24gY2FjaGVzIHRoZVxuICogcmVzdWx0LiBJIHN1cHBvc2UgdGhhdCBpdCBpcyBjb25jZWl2YWJseSBwb3NzaWJsZSB0aGF0IGEgYnJvd3NlciBtaWdodCBmbGlwIG1vZGVzIHdoaWxlIHRoZSBhcHAgaXNcbiAqIHJ1bm5pbmcsIGJ1dCBsZXRzIGhvcGUgbm90LlxuICpcbiAqIEByZXR1cm4ge2Jvb2xlYW59IHRydWUgaWYgdGhlIERpYWdvbmFsIFJlbmRlcmluZyBpcyBicm9rZW4uXG4gKi9cblxuXG5mdW5jdGlvbiBpc0Jyb2tlbkRpYWdvbmFsUmVuZGVyaW5nKCkge1xuICBpZiAoYnJva2VuRGlhZ29uYWxSZW5kZXJpbmdfID09PSB1bmRlZmluZWQpIHtcbiAgICB2YXIgY3R4ID0gZG9jdW1lbnQuY3JlYXRlRWxlbWVudCgnY2FudmFzJykuZ2V0Q29udGV4dCgnMmQnKTtcbiAgICBjdHguZ2xvYmFsQ29tcG9zaXRlT3BlcmF0aW9uID0gJ2xpZ2h0ZXInO1xuICAgIGN0eC5maWxsU3R5bGUgPSAncmdiYSgyMTAsIDAsIDAsIDAuNzUpJztcbiAgICBkcmF3VGVzdFRyaWFuZ2xlKGN0eCwgNCwgNSwgNCwgMCk7XG4gICAgZHJhd1Rlc3RUcmlhbmdsZShjdHgsIDQsIDUsIDAsIDUpO1xuICAgIHZhciBkYXRhID0gY3R4LmdldEltYWdlRGF0YSgwLCAwLCAzLCAzKS5kYXRhO1xuICAgIGJyb2tlbkRpYWdvbmFsUmVuZGVyaW5nXyA9IHZlcmlmeUJyb2tlbkRpYWdvbmFsUmVuZGVyaW5nKGRhdGEsIDApIHx8IHZlcmlmeUJyb2tlbkRpYWdvbmFsUmVuZGVyaW5nKGRhdGEsIDQpIHx8IHZlcmlmeUJyb2tlbkRpYWdvbmFsUmVuZGVyaW5nKGRhdGEsIDgpO1xuICB9XG5cbiAgcmV0dXJuIGJyb2tlbkRpYWdvbmFsUmVuZGVyaW5nXztcbn1cbi8qKlxuICogQ2FsY3VsYXRlcyBpZGVhbCByZXNvbHV0aW9uIHRvIHVzZSBmcm9tIHRoZSBzb3VyY2UgaW4gb3JkZXIgdG8gYWNoaWV2ZVxuICogcGl4ZWwgbWFwcGluZyBhcyBjbG9zZSBhcyBwb3NzaWJsZSB0byAxOjEgZHVyaW5nIHJlcHJvamVjdGlvbi5cbiAqIFRoZSByZXNvbHV0aW9uIGlzIGNhbGN1bGF0ZWQgcmVnYXJkbGVzcyBvZiB3aGF0IHJlc29sdXRpb25zXG4gKiBhcmUgYWN0dWFsbHkgYXZhaWxhYmxlIGluIHRoZSBkYXRhc2V0IChUaWxlR3JpZCwgSW1hZ2UsIC4uLikuXG4gKlxuICogQHBhcmFtIHtpbXBvcnQoXCIuL3Byb2ovUHJvamVjdGlvbi5qc1wiKS5kZWZhdWx0fSBzb3VyY2VQcm9qIFNvdXJjZSBwcm9qZWN0aW9uLlxuICogQHBhcmFtIHtpbXBvcnQoXCIuL3Byb2ovUHJvamVjdGlvbi5qc1wiKS5kZWZhdWx0fSB0YXJnZXRQcm9qIFRhcmdldCBwcm9qZWN0aW9uLlxuICogQHBhcmFtIHtpbXBvcnQoXCIuL2Nvb3JkaW5hdGUuanNcIikuQ29vcmRpbmF0ZX0gdGFyZ2V0Q2VudGVyIFRhcmdldCBjZW50ZXIuXG4gKiBAcGFyYW0ge251bWJlcn0gdGFyZ2V0UmVzb2x1dGlvbiBUYXJnZXQgcmVzb2x1dGlvbi5cbiAqIEByZXR1cm4ge251bWJlcn0gVGhlIGJlc3QgcmVzb2x1dGlvbiB0byB1c2UuIENhbiBiZSArLUluZmluaXR5LCBOYU4gb3IgMC5cbiAqL1xuXG5cbmV4cG9ydCBmdW5jdGlvbiBjYWxjdWxhdGVTb3VyY2VSZXNvbHV0aW9uKHNvdXJjZVByb2osIHRhcmdldFByb2osIHRhcmdldENlbnRlciwgdGFyZ2V0UmVzb2x1dGlvbikge1xuICB2YXIgc291cmNlQ2VudGVyID0gdHJhbnNmb3JtKHRhcmdldENlbnRlciwgdGFyZ2V0UHJvaiwgc291cmNlUHJvaik7IC8vIGNhbGN1bGF0ZSB0aGUgaWRlYWwgcmVzb2x1dGlvbiBvZiB0aGUgc291cmNlIGRhdGFcblxuICB2YXIgc291cmNlUmVzb2x1dGlvbiA9IGdldFBvaW50UmVzb2x1dGlvbih0YXJnZXRQcm9qLCB0YXJnZXRSZXNvbHV0aW9uLCB0YXJnZXRDZW50ZXIpO1xuICB2YXIgdGFyZ2V0TWV0ZXJzUGVyVW5pdCA9IHRhcmdldFByb2ouZ2V0TWV0ZXJzUGVyVW5pdCgpO1xuXG4gIGlmICh0YXJnZXRNZXRlcnNQZXJVbml0ICE9PSB1bmRlZmluZWQpIHtcbiAgICBzb3VyY2VSZXNvbHV0aW9uICo9IHRhcmdldE1ldGVyc1BlclVuaXQ7XG4gIH1cblxuICB2YXIgc291cmNlTWV0ZXJzUGVyVW5pdCA9IHNvdXJjZVByb2ouZ2V0TWV0ZXJzUGVyVW5pdCgpO1xuXG4gIGlmIChzb3VyY2VNZXRlcnNQZXJVbml0ICE9PSB1bmRlZmluZWQpIHtcbiAgICBzb3VyY2VSZXNvbHV0aW9uIC89IHNvdXJjZU1ldGVyc1BlclVuaXQ7XG4gIH0gLy8gQmFzZWQgb24gdGhlIHByb2plY3Rpb24gcHJvcGVydGllcywgdGhlIHBvaW50IHJlc29sdXRpb24gYXQgdGhlIHNwZWNpZmllZFxuICAvLyBjb29yZGluYXRlcyBtYXkgYmUgc2xpZ2h0bHkgZGlmZmVyZW50LiBXZSBuZWVkIHRvIHJldmVyc2UtY29tcGVuc2F0ZSB0aGlzXG4gIC8vIGluIG9yZGVyIHRvIGFjaGlldmUgb3B0aW1hbCByZXN1bHRzLlxuXG5cbiAgdmFyIHNvdXJjZUV4dGVudCA9IHNvdXJjZVByb2ouZ2V0RXh0ZW50KCk7XG5cbiAgaWYgKCFzb3VyY2VFeHRlbnQgfHwgY29udGFpbnNDb29yZGluYXRlKHNvdXJjZUV4dGVudCwgc291cmNlQ2VudGVyKSkge1xuICAgIHZhciBjb21wZW5zYXRpb25GYWN0b3IgPSBnZXRQb2ludFJlc29sdXRpb24oc291cmNlUHJvaiwgc291cmNlUmVzb2x1dGlvbiwgc291cmNlQ2VudGVyKSAvIHNvdXJjZVJlc29sdXRpb247XG5cbiAgICBpZiAoaXNGaW5pdGUoY29tcGVuc2F0aW9uRmFjdG9yKSAmJiBjb21wZW5zYXRpb25GYWN0b3IgPiAwKSB7XG4gICAgICBzb3VyY2VSZXNvbHV0aW9uIC89IGNvbXBlbnNhdGlvbkZhY3RvcjtcbiAgICB9XG4gIH1cblxuICByZXR1cm4gc291cmNlUmVzb2x1dGlvbjtcbn1cbi8qKlxuICogQ2FsY3VsYXRlcyBpZGVhbCByZXNvbHV0aW9uIHRvIHVzZSBmcm9tIHRoZSBzb3VyY2UgaW4gb3JkZXIgdG8gYWNoaWV2ZVxuICogcGl4ZWwgbWFwcGluZyBhcyBjbG9zZSBhcyBwb3NzaWJsZSB0byAxOjEgZHVyaW5nIHJlcHJvamVjdGlvbi5cbiAqIFRoZSByZXNvbHV0aW9uIGlzIGNhbGN1bGF0ZWQgcmVnYXJkbGVzcyBvZiB3aGF0IHJlc29sdXRpb25zXG4gKiBhcmUgYWN0dWFsbHkgYXZhaWxhYmxlIGluIHRoZSBkYXRhc2V0IChUaWxlR3JpZCwgSW1hZ2UsIC4uLikuXG4gKlxuICogQHBhcmFtIHtpbXBvcnQoXCIuL3Byb2ovUHJvamVjdGlvbi5qc1wiKS5kZWZhdWx0fSBzb3VyY2VQcm9qIFNvdXJjZSBwcm9qZWN0aW9uLlxuICogQHBhcmFtIHtpbXBvcnQoXCIuL3Byb2ovUHJvamVjdGlvbi5qc1wiKS5kZWZhdWx0fSB0YXJnZXRQcm9qIFRhcmdldCBwcm9qZWN0aW9uLlxuICogQHBhcmFtIHtpbXBvcnQoXCIuL2V4dGVudC5qc1wiKS5FeHRlbnR9IHRhcmdldEV4dGVudCBUYXJnZXQgZXh0ZW50XG4gKiBAcGFyYW0ge251bWJlcn0gdGFyZ2V0UmVzb2x1dGlvbiBUYXJnZXQgcmVzb2x1dGlvbi5cbiAqIEByZXR1cm4ge251bWJlcn0gVGhlIGJlc3QgcmVzb2x1dGlvbiB0byB1c2UuIENhbiBiZSArLUluZmluaXR5LCBOYU4gb3IgMC5cbiAqL1xuXG5leHBvcnQgZnVuY3Rpb24gY2FsY3VsYXRlU291cmNlRXh0ZW50UmVzb2x1dGlvbihzb3VyY2VQcm9qLCB0YXJnZXRQcm9qLCB0YXJnZXRFeHRlbnQsIHRhcmdldFJlc29sdXRpb24pIHtcbiAgdmFyIHRhcmdldENlbnRlciA9IGdldENlbnRlcih0YXJnZXRFeHRlbnQpO1xuICB2YXIgc291cmNlUmVzb2x1dGlvbiA9IGNhbGN1bGF0ZVNvdXJjZVJlc29sdXRpb24oc291cmNlUHJvaiwgdGFyZ2V0UHJvaiwgdGFyZ2V0Q2VudGVyLCB0YXJnZXRSZXNvbHV0aW9uKTtcblxuICBpZiAoIWlzRmluaXRlKHNvdXJjZVJlc29sdXRpb24pIHx8IHNvdXJjZVJlc29sdXRpb24gPD0gMCkge1xuICAgIGZvckVhY2hDb3JuZXIodGFyZ2V0RXh0ZW50LCBmdW5jdGlvbiAoY29ybmVyKSB7XG4gICAgICBzb3VyY2VSZXNvbHV0aW9uID0gY2FsY3VsYXRlU291cmNlUmVzb2x1dGlvbihzb3VyY2VQcm9qLCB0YXJnZXRQcm9qLCBjb3JuZXIsIHRhcmdldFJlc29sdXRpb24pO1xuICAgICAgcmV0dXJuIGlzRmluaXRlKHNvdXJjZVJlc29sdXRpb24pICYmIHNvdXJjZVJlc29sdXRpb24gPiAwO1xuICAgIH0pO1xuICB9XG5cbiAgcmV0dXJuIHNvdXJjZVJlc29sdXRpb247XG59XG4vKipcbiAqIFJlbmRlcnMgdGhlIHNvdXJjZSBkYXRhIGludG8gbmV3IGNhbnZhcyBiYXNlZCBvbiB0aGUgdHJpYW5ndWxhdGlvbi5cbiAqXG4gKiBAcGFyYW0ge251bWJlcn0gd2lkdGggV2lkdGggb2YgdGhlIGNhbnZhcy5cbiAqIEBwYXJhbSB7bnVtYmVyfSBoZWlnaHQgSGVpZ2h0IG9mIHRoZSBjYW52YXMuXG4gKiBAcGFyYW0ge251bWJlcn0gcGl4ZWxSYXRpbyBQaXhlbCByYXRpby5cbiAqIEBwYXJhbSB7bnVtYmVyfSBzb3VyY2VSZXNvbHV0aW9uIFNvdXJjZSByZXNvbHV0aW9uLlxuICogQHBhcmFtIHtpbXBvcnQoXCIuL2V4dGVudC5qc1wiKS5FeHRlbnR9IHNvdXJjZUV4dGVudCBFeHRlbnQgb2YgdGhlIGRhdGEgc291cmNlLlxuICogQHBhcmFtIHtudW1iZXJ9IHRhcmdldFJlc29sdXRpb24gVGFyZ2V0IHJlc29sdXRpb24uXG4gKiBAcGFyYW0ge2ltcG9ydChcIi4vZXh0ZW50LmpzXCIpLkV4dGVudH0gdGFyZ2V0RXh0ZW50IFRhcmdldCBleHRlbnQuXG4gKiBAcGFyYW0ge2ltcG9ydChcIi4vcmVwcm9qL1RyaWFuZ3VsYXRpb24uanNcIikuZGVmYXVsdH0gdHJpYW5ndWxhdGlvblxuICogQ2FsY3VsYXRlZCB0cmlhbmd1bGF0aW9uLlxuICogQHBhcmFtIHtBcnJheTx7ZXh0ZW50OiBpbXBvcnQoXCIuL2V4dGVudC5qc1wiKS5FeHRlbnQsXG4gKiAgICAgICAgICAgICAgICAgaW1hZ2U6IChIVE1MQ2FudmFzRWxlbWVudHxIVE1MSW1hZ2VFbGVtZW50fEhUTUxWaWRlb0VsZW1lbnQpfT59IHNvdXJjZXNcbiAqIEFycmF5IG9mIHNvdXJjZXMuXG4gKiBAcGFyYW0ge251bWJlcn0gZ3V0dGVyIEd1dHRlciBvZiB0aGUgc291cmNlcy5cbiAqIEBwYXJhbSB7Ym9vbGVhbj19IG9wdF9yZW5kZXJFZGdlcyBSZW5kZXIgcmVwcm9qZWN0aW9uIGVkZ2VzLlxuICogQHBhcmFtIHtvYmplY3Q9fSBvcHRfY29udGV4dE9wdGlvbnMgUHJvcGVydGllcyB0byBzZXQgb24gdGhlIGNhbnZhcyBjb250ZXh0LlxuICogQHJldHVybiB7SFRNTENhbnZhc0VsZW1lbnR9IENhbnZhcyB3aXRoIHJlcHJvamVjdGVkIGRhdGEuXG4gKi9cblxuZXhwb3J0IGZ1bmN0aW9uIHJlbmRlcih3aWR0aCwgaGVpZ2h0LCBwaXhlbFJhdGlvLCBzb3VyY2VSZXNvbHV0aW9uLCBzb3VyY2VFeHRlbnQsIHRhcmdldFJlc29sdXRpb24sIHRhcmdldEV4dGVudCwgdHJpYW5ndWxhdGlvbiwgc291cmNlcywgZ3V0dGVyLCBvcHRfcmVuZGVyRWRnZXMsIG9wdF9jb250ZXh0T3B0aW9ucykge1xuICB2YXIgY29udGV4dCA9IGNyZWF0ZUNhbnZhc0NvbnRleHQyRChNYXRoLnJvdW5kKHBpeGVsUmF0aW8gKiB3aWR0aCksIE1hdGgucm91bmQocGl4ZWxSYXRpbyAqIGhlaWdodCkpO1xuICBhc3NpZ24oY29udGV4dCwgb3B0X2NvbnRleHRPcHRpb25zKTtcblxuICBpZiAoc291cmNlcy5sZW5ndGggPT09IDApIHtcbiAgICByZXR1cm4gY29udGV4dC5jYW52YXM7XG4gIH1cblxuICBjb250ZXh0LnNjYWxlKHBpeGVsUmF0aW8sIHBpeGVsUmF0aW8pO1xuXG4gIGZ1bmN0aW9uIHBpeGVsUm91bmQodmFsdWUpIHtcbiAgICByZXR1cm4gTWF0aC5yb3VuZCh2YWx1ZSAqIHBpeGVsUmF0aW8pIC8gcGl4ZWxSYXRpbztcbiAgfVxuXG4gIGNvbnRleHQuZ2xvYmFsQ29tcG9zaXRlT3BlcmF0aW9uID0gJ2xpZ2h0ZXInO1xuICB2YXIgc291cmNlRGF0YUV4dGVudCA9IGNyZWF0ZUVtcHR5KCk7XG4gIHNvdXJjZXMuZm9yRWFjaChmdW5jdGlvbiAoc3JjLCBpLCBhcnIpIHtcbiAgICBleHRlbmQoc291cmNlRGF0YUV4dGVudCwgc3JjLmV4dGVudCk7XG4gIH0pO1xuICB2YXIgY2FudmFzV2lkdGhJblVuaXRzID0gZ2V0V2lkdGgoc291cmNlRGF0YUV4dGVudCk7XG4gIHZhciBjYW52YXNIZWlnaHRJblVuaXRzID0gZ2V0SGVpZ2h0KHNvdXJjZURhdGFFeHRlbnQpO1xuICB2YXIgc3RpdGNoQ29udGV4dCA9IGNyZWF0ZUNhbnZhc0NvbnRleHQyRChNYXRoLnJvdW5kKHBpeGVsUmF0aW8gKiBjYW52YXNXaWR0aEluVW5pdHMgLyBzb3VyY2VSZXNvbHV0aW9uKSwgTWF0aC5yb3VuZChwaXhlbFJhdGlvICogY2FudmFzSGVpZ2h0SW5Vbml0cyAvIHNvdXJjZVJlc29sdXRpb24pKTtcbiAgYXNzaWduKHN0aXRjaENvbnRleHQsIG9wdF9jb250ZXh0T3B0aW9ucyk7XG4gIHZhciBzdGl0Y2hTY2FsZSA9IHBpeGVsUmF0aW8gLyBzb3VyY2VSZXNvbHV0aW9uO1xuICBzb3VyY2VzLmZvckVhY2goZnVuY3Rpb24gKHNyYywgaSwgYXJyKSB7XG4gICAgdmFyIHhQb3MgPSBzcmMuZXh0ZW50WzBdIC0gc291cmNlRGF0YUV4dGVudFswXTtcbiAgICB2YXIgeVBvcyA9IC0oc3JjLmV4dGVudFszXSAtIHNvdXJjZURhdGFFeHRlbnRbM10pO1xuICAgIHZhciBzcmNXaWR0aCA9IGdldFdpZHRoKHNyYy5leHRlbnQpO1xuICAgIHZhciBzcmNIZWlnaHQgPSBnZXRIZWlnaHQoc3JjLmV4dGVudCk7IC8vIFRoaXMgdGVzdCBzaG91bGQgbmV2ZXIgZmFpbCAtLSBidXQgaXQgZG9lcy4gTmVlZCB0byBmaW5kIGEgZml4IHRoZSB1cHN0cmVhbSBjb25kaXRpb25cblxuICAgIGlmIChzcmMuaW1hZ2Uud2lkdGggPiAwICYmIHNyYy5pbWFnZS5oZWlnaHQgPiAwKSB7XG4gICAgICBzdGl0Y2hDb250ZXh0LmRyYXdJbWFnZShzcmMuaW1hZ2UsIGd1dHRlciwgZ3V0dGVyLCBzcmMuaW1hZ2Uud2lkdGggLSAyICogZ3V0dGVyLCBzcmMuaW1hZ2UuaGVpZ2h0IC0gMiAqIGd1dHRlciwgeFBvcyAqIHN0aXRjaFNjYWxlLCB5UG9zICogc3RpdGNoU2NhbGUsIHNyY1dpZHRoICogc3RpdGNoU2NhbGUsIHNyY0hlaWdodCAqIHN0aXRjaFNjYWxlKTtcbiAgICB9XG4gIH0pO1xuICB2YXIgdGFyZ2V0VG9wTGVmdCA9IGdldFRvcExlZnQodGFyZ2V0RXh0ZW50KTtcbiAgdHJpYW5ndWxhdGlvbi5nZXRUcmlhbmdsZXMoKS5mb3JFYWNoKGZ1bmN0aW9uICh0cmlhbmdsZSwgaSwgYXJyKSB7XG4gICAgLyogQ2FsY3VsYXRlIGFmZmluZSB0cmFuc2Zvcm0gKHNyYyAtPiBkc3QpXG4gICAgICogUmVzdWx0aW5nIG1hdHJpeCBjYW4gYmUgdXNlZCB0byB0cmFuc2Zvcm0gY29vcmRpbmF0ZVxuICAgICAqIGZyb20gYHNvdXJjZVByb2plY3Rpb25gIHRvIGRlc3RpbmF0aW9uIHBpeGVscy5cbiAgICAgKlxuICAgICAqIFRvIG9wdGltaXplIG51bWJlciBvZiBjb250ZXh0IGNhbGxzIGFuZCBpbmNyZWFzZSBudW1lcmljYWwgc3RhYmlsaXR5LFxuICAgICAqIHdlIGFsc28gZG8gdGhlIGZvbGxvd2luZyBvcGVyYXRpb25zOlxuICAgICAqIHRyYW5zKC10b3BMZWZ0RXh0ZW50Q29ybmVyKSwgc2NhbGUoMSAvIHRhcmdldFJlc29sdXRpb24pLCBzY2FsZSgxLCAtMSlcbiAgICAgKiBoZXJlIGJlZm9yZSBzb2x2aW5nIHRoZSBsaW5lYXIgc3lzdGVtIHNvIFt1aSwgdmldIGFyZSBwaXhlbCBjb29yZGluYXRlcy5cbiAgICAgKlxuICAgICAqIFNyYyBwb2ludHM6IHhpLCB5aVxuICAgICAqIERzdCBwb2ludHM6IHVpLCB2aVxuICAgICAqIEFmZmluZSBjb2VmZmljaWVudHM6IGFpalxuICAgICAqXG4gICAgICogfCB4MCB5MCAxICAwICAwIDAgfCAgIHxhMDB8ICAgfHUwfFxuICAgICAqIHwgeDEgeTEgMSAgMCAgMCAwIHwgICB8YTAxfCAgIHx1MXxcbiAgICAgKiB8IHgyIHkyIDEgIDAgIDAgMCB8IHggfGEwMnwgPSB8dTJ8XG4gICAgICogfCAgMCAgMCAwIHgwIHkwIDEgfCAgIHxhMTB8ICAgfHYwfFxuICAgICAqIHwgIDAgIDAgMCB4MSB5MSAxIHwgICB8YTExfCAgIHx2MXxcbiAgICAgKiB8ICAwICAwIDAgeDIgeTIgMSB8ICAgfGExMnwgICB8djJ8XG4gICAgICovXG4gICAgdmFyIHNvdXJjZSA9IHRyaWFuZ2xlLnNvdXJjZTtcbiAgICB2YXIgdGFyZ2V0ID0gdHJpYW5nbGUudGFyZ2V0O1xuICAgIHZhciB4MCA9IHNvdXJjZVswXVswXSxcbiAgICAgICAgeTAgPSBzb3VyY2VbMF1bMV07XG4gICAgdmFyIHgxID0gc291cmNlWzFdWzBdLFxuICAgICAgICB5MSA9IHNvdXJjZVsxXVsxXTtcbiAgICB2YXIgeDIgPSBzb3VyY2VbMl1bMF0sXG4gICAgICAgIHkyID0gc291cmNlWzJdWzFdOyAvLyBNYWtlIHN1cmUgdGhhdCBldmVyeXRoaW5nIGlzIG9uIHBpeGVsIGJvdW5kYXJpZXNcblxuICAgIHZhciB1MCA9IHBpeGVsUm91bmQoKHRhcmdldFswXVswXSAtIHRhcmdldFRvcExlZnRbMF0pIC8gdGFyZ2V0UmVzb2x1dGlvbik7XG4gICAgdmFyIHYwID0gcGl4ZWxSb3VuZCgtKHRhcmdldFswXVsxXSAtIHRhcmdldFRvcExlZnRbMV0pIC8gdGFyZ2V0UmVzb2x1dGlvbik7XG4gICAgdmFyIHUxID0gcGl4ZWxSb3VuZCgodGFyZ2V0WzFdWzBdIC0gdGFyZ2V0VG9wTGVmdFswXSkgLyB0YXJnZXRSZXNvbHV0aW9uKTtcbiAgICB2YXIgdjEgPSBwaXhlbFJvdW5kKC0odGFyZ2V0WzFdWzFdIC0gdGFyZ2V0VG9wTGVmdFsxXSkgLyB0YXJnZXRSZXNvbHV0aW9uKTtcbiAgICB2YXIgdTIgPSBwaXhlbFJvdW5kKCh0YXJnZXRbMl1bMF0gLSB0YXJnZXRUb3BMZWZ0WzBdKSAvIHRhcmdldFJlc29sdXRpb24pO1xuICAgIHZhciB2MiA9IHBpeGVsUm91bmQoLSh0YXJnZXRbMl1bMV0gLSB0YXJnZXRUb3BMZWZ0WzFdKSAvIHRhcmdldFJlc29sdXRpb24pOyAvLyBTaGlmdCBhbGwgdGhlIHNvdXJjZSBwb2ludHMgdG8gaW1wcm92ZSBudW1lcmljYWwgc3RhYmlsaXR5XG4gICAgLy8gb2YgYWxsIHRoZSBzdWJzZXF1ZW50IGNhbGN1bGF0aW9ucy4gVGhlIFt4MCwgeTBdIGlzIHVzZWQgaGVyZS5cbiAgICAvLyBUaGlzIGlzIGFsc28gdXNlZCB0byBzaW1wbGlmeSB0aGUgbGluZWFyIHN5c3RlbS5cblxuICAgIHZhciBzb3VyY2VOdW1lcmljYWxTaGlmdFggPSB4MDtcbiAgICB2YXIgc291cmNlTnVtZXJpY2FsU2hpZnRZID0geTA7XG4gICAgeDAgPSAwO1xuICAgIHkwID0gMDtcbiAgICB4MSAtPSBzb3VyY2VOdW1lcmljYWxTaGlmdFg7XG4gICAgeTEgLT0gc291cmNlTnVtZXJpY2FsU2hpZnRZO1xuICAgIHgyIC09IHNvdXJjZU51bWVyaWNhbFNoaWZ0WDtcbiAgICB5MiAtPSBzb3VyY2VOdW1lcmljYWxTaGlmdFk7XG4gICAgdmFyIGF1Z21lbnRlZE1hdHJpeCA9IFtbeDEsIHkxLCAwLCAwLCB1MSAtIHUwXSwgW3gyLCB5MiwgMCwgMCwgdTIgLSB1MF0sIFswLCAwLCB4MSwgeTEsIHYxIC0gdjBdLCBbMCwgMCwgeDIsIHkyLCB2MiAtIHYwXV07XG4gICAgdmFyIGFmZmluZUNvZWZzID0gc29sdmVMaW5lYXJTeXN0ZW0oYXVnbWVudGVkTWF0cml4KTtcblxuICAgIGlmICghYWZmaW5lQ29lZnMpIHtcbiAgICAgIHJldHVybjtcbiAgICB9XG5cbiAgICBjb250ZXh0LnNhdmUoKTtcbiAgICBjb250ZXh0LmJlZ2luUGF0aCgpO1xuXG4gICAgaWYgKGlzQnJva2VuRGlhZ29uYWxSZW5kZXJpbmcoKSB8fCBvcHRfY29udGV4dE9wdGlvbnMgPT09IElNQUdFX1NNT09USElOR19ESVNBQkxFRCkge1xuICAgICAgLy8gTWFrZSBzdXJlIHRoYXQgYWxsIGxpbmVzIGFyZSBob3Jpem9udGFsIG9yIHZlcnRpY2FsXG4gICAgICBjb250ZXh0Lm1vdmVUbyh1MSwgdjEpOyAvLyBUaGlzIGlzIHRoZSBkaWFnb25hbCBsaW5lLiBEbyBpdCBpbiA0IHN0ZXBzXG5cbiAgICAgIHZhciBzdGVwcyA9IDQ7XG4gICAgICB2YXIgdWQgPSB1MCAtIHUxO1xuICAgICAgdmFyIHZkID0gdjAgLSB2MTtcblxuICAgICAgZm9yICh2YXIgc3RlcCA9IDA7IHN0ZXAgPCBzdGVwczsgc3RlcCsrKSB7XG4gICAgICAgIC8vIEdvIGhvcml6b250YWxseVxuICAgICAgICBjb250ZXh0LmxpbmVUbyh1MSArIHBpeGVsUm91bmQoKHN0ZXAgKyAxKSAqIHVkIC8gc3RlcHMpLCB2MSArIHBpeGVsUm91bmQoc3RlcCAqIHZkIC8gKHN0ZXBzIC0gMSkpKTsgLy8gR28gdmVydGljYWxseVxuXG4gICAgICAgIGlmIChzdGVwICE9IHN0ZXBzIC0gMSkge1xuICAgICAgICAgIGNvbnRleHQubGluZVRvKHUxICsgcGl4ZWxSb3VuZCgoc3RlcCArIDEpICogdWQgLyBzdGVwcyksIHYxICsgcGl4ZWxSb3VuZCgoc3RlcCArIDEpICogdmQgLyAoc3RlcHMgLSAxKSkpO1xuICAgICAgICB9XG4gICAgICB9IC8vIFdlIGFyZSBhbG1vc3QgYXQgdTByLCB2MHJcblxuXG4gICAgICBjb250ZXh0LmxpbmVUbyh1MiwgdjIpO1xuICAgIH0gZWxzZSB7XG4gICAgICBjb250ZXh0Lm1vdmVUbyh1MSwgdjEpO1xuICAgICAgY29udGV4dC5saW5lVG8odTAsIHYwKTtcbiAgICAgIGNvbnRleHQubGluZVRvKHUyLCB2Mik7XG4gICAgfVxuXG4gICAgY29udGV4dC5jbGlwKCk7XG4gICAgY29udGV4dC50cmFuc2Zvcm0oYWZmaW5lQ29lZnNbMF0sIGFmZmluZUNvZWZzWzJdLCBhZmZpbmVDb2Vmc1sxXSwgYWZmaW5lQ29lZnNbM10sIHUwLCB2MCk7XG4gICAgY29udGV4dC50cmFuc2xhdGUoc291cmNlRGF0YUV4dGVudFswXSAtIHNvdXJjZU51bWVyaWNhbFNoaWZ0WCwgc291cmNlRGF0YUV4dGVudFszXSAtIHNvdXJjZU51bWVyaWNhbFNoaWZ0WSk7XG4gICAgY29udGV4dC5zY2FsZShzb3VyY2VSZXNvbHV0aW9uIC8gcGl4ZWxSYXRpbywgLXNvdXJjZVJlc29sdXRpb24gLyBwaXhlbFJhdGlvKTtcbiAgICBjb250ZXh0LmRyYXdJbWFnZShzdGl0Y2hDb250ZXh0LmNhbnZhcywgMCwgMCk7XG4gICAgY29udGV4dC5yZXN0b3JlKCk7XG4gIH0pO1xuXG4gIGlmIChvcHRfcmVuZGVyRWRnZXMpIHtcbiAgICBjb250ZXh0LnNhdmUoKTtcbiAgICBjb250ZXh0Lmdsb2JhbENvbXBvc2l0ZU9wZXJhdGlvbiA9ICdzb3VyY2Utb3Zlcic7XG4gICAgY29udGV4dC5zdHJva2VTdHlsZSA9ICdibGFjayc7XG4gICAgY29udGV4dC5saW5lV2lkdGggPSAxO1xuICAgIHRyaWFuZ3VsYXRpb24uZ2V0VHJpYW5nbGVzKCkuZm9yRWFjaChmdW5jdGlvbiAodHJpYW5nbGUsIGksIGFycikge1xuICAgICAgdmFyIHRhcmdldCA9IHRyaWFuZ2xlLnRhcmdldDtcbiAgICAgIHZhciB1MCA9ICh0YXJnZXRbMF1bMF0gLSB0YXJnZXRUb3BMZWZ0WzBdKSAvIHRhcmdldFJlc29sdXRpb247XG4gICAgICB2YXIgdjAgPSAtKHRhcmdldFswXVsxXSAtIHRhcmdldFRvcExlZnRbMV0pIC8gdGFyZ2V0UmVzb2x1dGlvbjtcbiAgICAgIHZhciB1MSA9ICh0YXJnZXRbMV1bMF0gLSB0YXJnZXRUb3BMZWZ0WzBdKSAvIHRhcmdldFJlc29sdXRpb247XG4gICAgICB2YXIgdjEgPSAtKHRhcmdldFsxXVsxXSAtIHRhcmdldFRvcExlZnRbMV0pIC8gdGFyZ2V0UmVzb2x1dGlvbjtcbiAgICAgIHZhciB1MiA9ICh0YXJnZXRbMl1bMF0gLSB0YXJnZXRUb3BMZWZ0WzBdKSAvIHRhcmdldFJlc29sdXRpb247XG4gICAgICB2YXIgdjIgPSAtKHRhcmdldFsyXVsxXSAtIHRhcmdldFRvcExlZnRbMV0pIC8gdGFyZ2V0UmVzb2x1dGlvbjtcbiAgICAgIGNvbnRleHQuYmVnaW5QYXRoKCk7XG4gICAgICBjb250ZXh0Lm1vdmVUbyh1MSwgdjEpO1xuICAgICAgY29udGV4dC5saW5lVG8odTAsIHYwKTtcbiAgICAgIGNvbnRleHQubGluZVRvKHUyLCB2Mik7XG4gICAgICBjb250ZXh0LmNsb3NlUGF0aCgpO1xuICAgICAgY29udGV4dC5zdHJva2UoKTtcbiAgICB9KTtcbiAgICBjb250ZXh0LnJlc3RvcmUoKTtcbiAgfVxuXG4gIHJldHVybiBjb250ZXh0LmNhbnZhcztcbn0iLCJ2YXIgX19leHRlbmRzID0gdGhpcyAmJiB0aGlzLl9fZXh0ZW5kcyB8fCBmdW5jdGlvbiAoKSB7XG4gIHZhciBfZXh0ZW5kU3RhdGljcyA9IGZ1bmN0aW9uIGV4dGVuZFN0YXRpY3MoZCwgYikge1xuICAgIF9leHRlbmRTdGF0aWNzID0gT2JqZWN0LnNldFByb3RvdHlwZU9mIHx8IHtcbiAgICAgIF9fcHJvdG9fXzogW11cbiAgICB9IGluc3RhbmNlb2YgQXJyYXkgJiYgZnVuY3Rpb24gKGQsIGIpIHtcbiAgICAgIGQuX19wcm90b19fID0gYjtcbiAgICB9IHx8IGZ1bmN0aW9uIChkLCBiKSB7XG4gICAgICBmb3IgKHZhciBwIGluIGIpIHtcbiAgICAgICAgaWYgKE9iamVjdC5wcm90b3R5cGUuaGFzT3duUHJvcGVydHkuY2FsbChiLCBwKSkgZFtwXSA9IGJbcF07XG4gICAgICB9XG4gICAgfTtcblxuICAgIHJldHVybiBfZXh0ZW5kU3RhdGljcyhkLCBiKTtcbiAgfTtcblxuICByZXR1cm4gZnVuY3Rpb24gKGQsIGIpIHtcbiAgICBfZXh0ZW5kU3RhdGljcyhkLCBiKTtcblxuICAgIGZ1bmN0aW9uIF9fKCkge1xuICAgICAgdGhpcy5jb25zdHJ1Y3RvciA9IGQ7XG4gICAgfVxuXG4gICAgZC5wcm90b3R5cGUgPSBiID09PSBudWxsID8gT2JqZWN0LmNyZWF0ZShiKSA6IChfXy5wcm90b3R5cGUgPSBiLnByb3RvdHlwZSwgbmV3IF9fKCkpO1xuICB9O1xufSgpO1xuLyoqXG4gKiBAbW9kdWxlIG9sL3JlcHJvai9UaWxlXG4gKi9cblxuXG5pbXBvcnQgeyBFUlJPUl9USFJFU0hPTEQgfSBmcm9tICcuL2NvbW1vbi5qcyc7XG5pbXBvcnQgRXZlbnRUeXBlIGZyb20gJy4uL2V2ZW50cy9FdmVudFR5cGUuanMnO1xuaW1wb3J0IFRpbGUgZnJvbSAnLi4vVGlsZS5qcyc7XG5pbXBvcnQgVGlsZVN0YXRlIGZyb20gJy4uL1RpbGVTdGF0ZS5qcyc7XG5pbXBvcnQgVHJpYW5ndWxhdGlvbiBmcm9tICcuL1RyaWFuZ3VsYXRpb24uanMnO1xuaW1wb3J0IHsgY2FsY3VsYXRlU291cmNlRXh0ZW50UmVzb2x1dGlvbiwgcmVuZGVyIGFzIHJlbmRlclJlcHJvamVjdGVkIH0gZnJvbSAnLi4vcmVwcm9qLmpzJztcbmltcG9ydCB7IGNsYW1wIH0gZnJvbSAnLi4vbWF0aC5qcyc7XG5pbXBvcnQgeyBnZXRBcmVhLCBnZXRJbnRlcnNlY3Rpb24gfSBmcm9tICcuLi9leHRlbnQuanMnO1xuaW1wb3J0IHsgbGlzdGVuLCB1bmxpc3RlbkJ5S2V5IH0gZnJvbSAnLi4vZXZlbnRzLmpzJztcbi8qKlxuICogQHR5cGVkZWYge2Z1bmN0aW9uKG51bWJlciwgbnVtYmVyLCBudW1iZXIsIG51bWJlcikgOiBpbXBvcnQoXCIuLi9UaWxlLmpzXCIpLmRlZmF1bHR9IEZ1bmN0aW9uVHlwZVxuICovXG5cbi8qKlxuICogQGNsYXNzZGVzY1xuICogQ2xhc3MgZW5jYXBzdWxhdGluZyBzaW5nbGUgcmVwcm9qZWN0ZWQgdGlsZS5cbiAqIFNlZSB7QGxpbmsgbW9kdWxlOm9sL3NvdXJjZS9UaWxlSW1hZ2V+VGlsZUltYWdlfS5cbiAqXG4gKi9cblxudmFyIFJlcHJvalRpbGUgPVxuLyoqIEBjbGFzcyAqL1xuZnVuY3Rpb24gKF9zdXBlcikge1xuICBfX2V4dGVuZHMoUmVwcm9qVGlsZSwgX3N1cGVyKTtcbiAgLyoqXG4gICAqIEBwYXJhbSB7aW1wb3J0KFwiLi4vcHJvai9Qcm9qZWN0aW9uLmpzXCIpLmRlZmF1bHR9IHNvdXJjZVByb2ogU291cmNlIHByb2plY3Rpb24uXG4gICAqIEBwYXJhbSB7aW1wb3J0KFwiLi4vdGlsZWdyaWQvVGlsZUdyaWQuanNcIikuZGVmYXVsdH0gc291cmNlVGlsZUdyaWQgU291cmNlIHRpbGUgZ3JpZC5cbiAgICogQHBhcmFtIHtpbXBvcnQoXCIuLi9wcm9qL1Byb2plY3Rpb24uanNcIikuZGVmYXVsdH0gdGFyZ2V0UHJvaiBUYXJnZXQgcHJvamVjdGlvbi5cbiAgICogQHBhcmFtIHtpbXBvcnQoXCIuLi90aWxlZ3JpZC9UaWxlR3JpZC5qc1wiKS5kZWZhdWx0fSB0YXJnZXRUaWxlR3JpZCBUYXJnZXQgdGlsZSBncmlkLlxuICAgKiBAcGFyYW0ge2ltcG9ydChcIi4uL3RpbGVjb29yZC5qc1wiKS5UaWxlQ29vcmR9IHRpbGVDb29yZCBDb29yZGluYXRlIG9mIHRoZSB0aWxlLlxuICAgKiBAcGFyYW0ge2ltcG9ydChcIi4uL3RpbGVjb29yZC5qc1wiKS5UaWxlQ29vcmR9IHdyYXBwZWRUaWxlQ29vcmQgQ29vcmRpbmF0ZSBvZiB0aGUgdGlsZSB3cmFwcGVkIGluIFguXG4gICAqIEBwYXJhbSB7bnVtYmVyfSBwaXhlbFJhdGlvIFBpeGVsIHJhdGlvLlxuICAgKiBAcGFyYW0ge251bWJlcn0gZ3V0dGVyIEd1dHRlciBvZiB0aGUgc291cmNlIHRpbGVzLlxuICAgKiBAcGFyYW0ge0Z1bmN0aW9uVHlwZX0gZ2V0VGlsZUZ1bmN0aW9uXG4gICAqICAgICBGdW5jdGlvbiByZXR1cm5pbmcgc291cmNlIHRpbGVzICh6LCB4LCB5LCBwaXhlbFJhdGlvKS5cbiAgICogQHBhcmFtIHtudW1iZXI9fSBvcHRfZXJyb3JUaHJlc2hvbGQgQWNjZXB0YWJsZSByZXByb2plY3Rpb24gZXJyb3IgKGluIHB4KS5cbiAgICogQHBhcmFtIHtib29sZWFuPX0gb3B0X3JlbmRlckVkZ2VzIFJlbmRlciByZXByb2plY3Rpb24gZWRnZXMuXG4gICAqIEBwYXJhbSB7b2JqZWN0PX0gb3B0X2NvbnRleHRPcHRpb25zIFByb3BlcnRpZXMgdG8gc2V0IG9uIHRoZSBjYW52YXMgY29udGV4dC5cbiAgICovXG5cblxuICBmdW5jdGlvbiBSZXByb2pUaWxlKHNvdXJjZVByb2osIHNvdXJjZVRpbGVHcmlkLCB0YXJnZXRQcm9qLCB0YXJnZXRUaWxlR3JpZCwgdGlsZUNvb3JkLCB3cmFwcGVkVGlsZUNvb3JkLCBwaXhlbFJhdGlvLCBndXR0ZXIsIGdldFRpbGVGdW5jdGlvbiwgb3B0X2Vycm9yVGhyZXNob2xkLCBvcHRfcmVuZGVyRWRnZXMsIG9wdF9jb250ZXh0T3B0aW9ucykge1xuICAgIHZhciBfdGhpcyA9IF9zdXBlci5jYWxsKHRoaXMsIHRpbGVDb29yZCwgVGlsZVN0YXRlLklETEUpIHx8IHRoaXM7XG4gICAgLyoqXG4gICAgICogQHByaXZhdGVcbiAgICAgKiBAdHlwZSB7Ym9vbGVhbn1cbiAgICAgKi9cblxuXG4gICAgX3RoaXMucmVuZGVyRWRnZXNfID0gb3B0X3JlbmRlckVkZ2VzICE9PSB1bmRlZmluZWQgPyBvcHRfcmVuZGVyRWRnZXMgOiBmYWxzZTtcbiAgICAvKipcbiAgICAgKiBAcHJpdmF0ZVxuICAgICAqIEB0eXBlIHtvYmplY3R9XG4gICAgICovXG5cbiAgICBfdGhpcy5jb250ZXh0T3B0aW9uc18gPSBvcHRfY29udGV4dE9wdGlvbnM7XG4gICAgLyoqXG4gICAgICogQHByaXZhdGVcbiAgICAgKiBAdHlwZSB7bnVtYmVyfVxuICAgICAqL1xuXG4gICAgX3RoaXMucGl4ZWxSYXRpb18gPSBwaXhlbFJhdGlvO1xuICAgIC8qKlxuICAgICAqIEBwcml2YXRlXG4gICAgICogQHR5cGUge251bWJlcn1cbiAgICAgKi9cblxuICAgIF90aGlzLmd1dHRlcl8gPSBndXR0ZXI7XG4gICAgLyoqXG4gICAgICogQHByaXZhdGVcbiAgICAgKiBAdHlwZSB7SFRNTENhbnZhc0VsZW1lbnR9XG4gICAgICovXG5cbiAgICBfdGhpcy5jYW52YXNfID0gbnVsbDtcbiAgICAvKipcbiAgICAgKiBAcHJpdmF0ZVxuICAgICAqIEB0eXBlIHtpbXBvcnQoXCIuLi90aWxlZ3JpZC9UaWxlR3JpZC5qc1wiKS5kZWZhdWx0fVxuICAgICAqL1xuXG4gICAgX3RoaXMuc291cmNlVGlsZUdyaWRfID0gc291cmNlVGlsZUdyaWQ7XG4gICAgLyoqXG4gICAgICogQHByaXZhdGVcbiAgICAgKiBAdHlwZSB7aW1wb3J0KFwiLi4vdGlsZWdyaWQvVGlsZUdyaWQuanNcIikuZGVmYXVsdH1cbiAgICAgKi9cblxuICAgIF90aGlzLnRhcmdldFRpbGVHcmlkXyA9IHRhcmdldFRpbGVHcmlkO1xuICAgIC8qKlxuICAgICAqIEBwcml2YXRlXG4gICAgICogQHR5cGUge2ltcG9ydChcIi4uL3RpbGVjb29yZC5qc1wiKS5UaWxlQ29vcmR9XG4gICAgICovXG5cbiAgICBfdGhpcy53cmFwcGVkVGlsZUNvb3JkXyA9IHdyYXBwZWRUaWxlQ29vcmQgPyB3cmFwcGVkVGlsZUNvb3JkIDogdGlsZUNvb3JkO1xuICAgIC8qKlxuICAgICAqIEBwcml2YXRlXG4gICAgICogQHR5cGUgeyFBcnJheTxpbXBvcnQoXCIuLi9UaWxlLmpzXCIpLmRlZmF1bHQ+fVxuICAgICAqL1xuXG4gICAgX3RoaXMuc291cmNlVGlsZXNfID0gW107XG4gICAgLyoqXG4gICAgICogQHByaXZhdGVcbiAgICAgKiBAdHlwZSB7P0FycmF5PGltcG9ydChcIi4uL2V2ZW50cy5qc1wiKS5FdmVudHNLZXk+fVxuICAgICAqL1xuXG4gICAgX3RoaXMuc291cmNlc0xpc3RlbmVyS2V5c18gPSBudWxsO1xuICAgIC8qKlxuICAgICAqIEBwcml2YXRlXG4gICAgICogQHR5cGUge251bWJlcn1cbiAgICAgKi9cblxuICAgIF90aGlzLnNvdXJjZVpfID0gMDtcbiAgICB2YXIgdGFyZ2V0RXh0ZW50ID0gdGFyZ2V0VGlsZUdyaWQuZ2V0VGlsZUNvb3JkRXh0ZW50KF90aGlzLndyYXBwZWRUaWxlQ29vcmRfKTtcblxuICAgIHZhciBtYXhUYXJnZXRFeHRlbnQgPSBfdGhpcy50YXJnZXRUaWxlR3JpZF8uZ2V0RXh0ZW50KCk7XG5cbiAgICB2YXIgbWF4U291cmNlRXh0ZW50ID0gX3RoaXMuc291cmNlVGlsZUdyaWRfLmdldEV4dGVudCgpO1xuXG4gICAgdmFyIGxpbWl0ZWRUYXJnZXRFeHRlbnQgPSBtYXhUYXJnZXRFeHRlbnQgPyBnZXRJbnRlcnNlY3Rpb24odGFyZ2V0RXh0ZW50LCBtYXhUYXJnZXRFeHRlbnQpIDogdGFyZ2V0RXh0ZW50O1xuXG4gICAgaWYgKGdldEFyZWEobGltaXRlZFRhcmdldEV4dGVudCkgPT09IDApIHtcbiAgICAgIC8vIFRpbGUgaXMgY29tcGxldGVseSBvdXRzaWRlIHJhbmdlIC0+IEVNUFRZXG4gICAgICAvLyBUT0RPOiBpcyBpdCBhY3R1YWxseSBjb3JyZWN0IHRoYXQgdGhlIHNvdXJjZSBldmVuIGNyZWF0ZXMgdGhlIHRpbGUgP1xuICAgICAgX3RoaXMuc3RhdGUgPSBUaWxlU3RhdGUuRU1QVFk7XG4gICAgICByZXR1cm4gX3RoaXM7XG4gICAgfVxuXG4gICAgdmFyIHNvdXJjZVByb2pFeHRlbnQgPSBzb3VyY2VQcm9qLmdldEV4dGVudCgpO1xuXG4gICAgaWYgKHNvdXJjZVByb2pFeHRlbnQpIHtcbiAgICAgIGlmICghbWF4U291cmNlRXh0ZW50KSB7XG4gICAgICAgIG1heFNvdXJjZUV4dGVudCA9IHNvdXJjZVByb2pFeHRlbnQ7XG4gICAgICB9IGVsc2Uge1xuICAgICAgICBtYXhTb3VyY2VFeHRlbnQgPSBnZXRJbnRlcnNlY3Rpb24obWF4U291cmNlRXh0ZW50LCBzb3VyY2VQcm9qRXh0ZW50KTtcbiAgICAgIH1cbiAgICB9XG5cbiAgICB2YXIgdGFyZ2V0UmVzb2x1dGlvbiA9IHRhcmdldFRpbGVHcmlkLmdldFJlc29sdXRpb24oX3RoaXMud3JhcHBlZFRpbGVDb29yZF9bMF0pO1xuICAgIHZhciBzb3VyY2VSZXNvbHV0aW9uID0gY2FsY3VsYXRlU291cmNlRXh0ZW50UmVzb2x1dGlvbihzb3VyY2VQcm9qLCB0YXJnZXRQcm9qLCBsaW1pdGVkVGFyZ2V0RXh0ZW50LCB0YXJnZXRSZXNvbHV0aW9uKTtcblxuICAgIGlmICghaXNGaW5pdGUoc291cmNlUmVzb2x1dGlvbikgfHwgc291cmNlUmVzb2x1dGlvbiA8PSAwKSB7XG4gICAgICAvLyBpbnZhbGlkIHNvdXJjZVJlc29sdXRpb24gLT4gRU1QVFlcbiAgICAgIC8vIHByb2JhYmx5IGVkZ2VzIG9mIHRoZSBwcm9qZWN0aW9ucyB3aGVuIG5vIGV4dGVudCBpcyBkZWZpbmVkXG4gICAgICBfdGhpcy5zdGF0ZSA9IFRpbGVTdGF0ZS5FTVBUWTtcbiAgICAgIHJldHVybiBfdGhpcztcbiAgICB9XG5cbiAgICB2YXIgZXJyb3JUaHJlc2hvbGRJblBpeGVscyA9IG9wdF9lcnJvclRocmVzaG9sZCAhPT0gdW5kZWZpbmVkID8gb3B0X2Vycm9yVGhyZXNob2xkIDogRVJST1JfVEhSRVNIT0xEO1xuICAgIC8qKlxuICAgICAqIEBwcml2YXRlXG4gICAgICogQHR5cGUgeyFpbXBvcnQoXCIuL1RyaWFuZ3VsYXRpb24uanNcIikuZGVmYXVsdH1cbiAgICAgKi9cblxuICAgIF90aGlzLnRyaWFuZ3VsYXRpb25fID0gbmV3IFRyaWFuZ3VsYXRpb24oc291cmNlUHJvaiwgdGFyZ2V0UHJvaiwgbGltaXRlZFRhcmdldEV4dGVudCwgbWF4U291cmNlRXh0ZW50LCBzb3VyY2VSZXNvbHV0aW9uICogZXJyb3JUaHJlc2hvbGRJblBpeGVscywgdGFyZ2V0UmVzb2x1dGlvbik7XG5cbiAgICBpZiAoX3RoaXMudHJpYW5ndWxhdGlvbl8uZ2V0VHJpYW5nbGVzKCkubGVuZ3RoID09PSAwKSB7XG4gICAgICAvLyBubyB2YWxpZCB0cmlhbmdsZXMgLT4gRU1QVFlcbiAgICAgIF90aGlzLnN0YXRlID0gVGlsZVN0YXRlLkVNUFRZO1xuICAgICAgcmV0dXJuIF90aGlzO1xuICAgIH1cblxuICAgIF90aGlzLnNvdXJjZVpfID0gc291cmNlVGlsZUdyaWQuZ2V0WkZvclJlc29sdXRpb24oc291cmNlUmVzb2x1dGlvbik7XG5cbiAgICB2YXIgc291cmNlRXh0ZW50ID0gX3RoaXMudHJpYW5ndWxhdGlvbl8uY2FsY3VsYXRlU291cmNlRXh0ZW50KCk7XG5cbiAgICBpZiAobWF4U291cmNlRXh0ZW50KSB7XG4gICAgICBpZiAoc291cmNlUHJvai5jYW5XcmFwWCgpKSB7XG4gICAgICAgIHNvdXJjZUV4dGVudFsxXSA9IGNsYW1wKHNvdXJjZUV4dGVudFsxXSwgbWF4U291cmNlRXh0ZW50WzFdLCBtYXhTb3VyY2VFeHRlbnRbM10pO1xuICAgICAgICBzb3VyY2VFeHRlbnRbM10gPSBjbGFtcChzb3VyY2VFeHRlbnRbM10sIG1heFNvdXJjZUV4dGVudFsxXSwgbWF4U291cmNlRXh0ZW50WzNdKTtcbiAgICAgIH0gZWxzZSB7XG4gICAgICAgIHNvdXJjZUV4dGVudCA9IGdldEludGVyc2VjdGlvbihzb3VyY2VFeHRlbnQsIG1heFNvdXJjZUV4dGVudCk7XG4gICAgICB9XG4gICAgfVxuXG4gICAgaWYgKCFnZXRBcmVhKHNvdXJjZUV4dGVudCkpIHtcbiAgICAgIF90aGlzLnN0YXRlID0gVGlsZVN0YXRlLkVNUFRZO1xuICAgIH0gZWxzZSB7XG4gICAgICB2YXIgc291cmNlUmFuZ2UgPSBzb3VyY2VUaWxlR3JpZC5nZXRUaWxlUmFuZ2VGb3JFeHRlbnRBbmRaKHNvdXJjZUV4dGVudCwgX3RoaXMuc291cmNlWl8pO1xuXG4gICAgICBmb3IgKHZhciBzcmNYID0gc291cmNlUmFuZ2UubWluWDsgc3JjWCA8PSBzb3VyY2VSYW5nZS5tYXhYOyBzcmNYKyspIHtcbiAgICAgICAgZm9yICh2YXIgc3JjWSA9IHNvdXJjZVJhbmdlLm1pblk7IHNyY1kgPD0gc291cmNlUmFuZ2UubWF4WTsgc3JjWSsrKSB7XG4gICAgICAgICAgdmFyIHRpbGUgPSBnZXRUaWxlRnVuY3Rpb24oX3RoaXMuc291cmNlWl8sIHNyY1gsIHNyY1ksIHBpeGVsUmF0aW8pO1xuXG4gICAgICAgICAgaWYgKHRpbGUpIHtcbiAgICAgICAgICAgIF90aGlzLnNvdXJjZVRpbGVzXy5wdXNoKHRpbGUpO1xuICAgICAgICAgIH1cbiAgICAgICAgfVxuICAgICAgfVxuXG4gICAgICBpZiAoX3RoaXMuc291cmNlVGlsZXNfLmxlbmd0aCA9PT0gMCkge1xuICAgICAgICBfdGhpcy5zdGF0ZSA9IFRpbGVTdGF0ZS5FTVBUWTtcbiAgICAgIH1cbiAgICB9XG5cbiAgICByZXR1cm4gX3RoaXM7XG4gIH1cbiAgLyoqXG4gICAqIEdldCB0aGUgSFRNTCBDYW52YXMgZWxlbWVudCBmb3IgdGhpcyB0aWxlLlxuICAgKiBAcmV0dXJuIHtIVE1MQ2FudmFzRWxlbWVudH0gQ2FudmFzLlxuICAgKi9cblxuXG4gIFJlcHJvalRpbGUucHJvdG90eXBlLmdldEltYWdlID0gZnVuY3Rpb24gKCkge1xuICAgIHJldHVybiB0aGlzLmNhbnZhc187XG4gIH07XG4gIC8qKlxuICAgKiBAcHJpdmF0ZVxuICAgKi9cblxuXG4gIFJlcHJvalRpbGUucHJvdG90eXBlLnJlcHJvamVjdF8gPSBmdW5jdGlvbiAoKSB7XG4gICAgdmFyIHNvdXJjZXMgPSBbXTtcbiAgICB0aGlzLnNvdXJjZVRpbGVzXy5mb3JFYWNoKGZ1bmN0aW9uICh0aWxlLCBpLCBhcnIpIHtcbiAgICAgIGlmICh0aWxlICYmIHRpbGUuZ2V0U3RhdGUoKSA9PSBUaWxlU3RhdGUuTE9BREVEKSB7XG4gICAgICAgIHNvdXJjZXMucHVzaCh7XG4gICAgICAgICAgZXh0ZW50OiB0aGlzLnNvdXJjZVRpbGVHcmlkXy5nZXRUaWxlQ29vcmRFeHRlbnQodGlsZS50aWxlQ29vcmQpLFxuICAgICAgICAgIGltYWdlOiB0aWxlLmdldEltYWdlKClcbiAgICAgICAgfSk7XG4gICAgICB9XG4gICAgfS5iaW5kKHRoaXMpKTtcbiAgICB0aGlzLnNvdXJjZVRpbGVzXy5sZW5ndGggPSAwO1xuXG4gICAgaWYgKHNvdXJjZXMubGVuZ3RoID09PSAwKSB7XG4gICAgICB0aGlzLnN0YXRlID0gVGlsZVN0YXRlLkVSUk9SO1xuICAgIH0gZWxzZSB7XG4gICAgICB2YXIgeiA9IHRoaXMud3JhcHBlZFRpbGVDb29yZF9bMF07XG4gICAgICB2YXIgc2l6ZSA9IHRoaXMudGFyZ2V0VGlsZUdyaWRfLmdldFRpbGVTaXplKHopO1xuICAgICAgdmFyIHdpZHRoID0gdHlwZW9mIHNpemUgPT09ICdudW1iZXInID8gc2l6ZSA6IHNpemVbMF07XG4gICAgICB2YXIgaGVpZ2h0ID0gdHlwZW9mIHNpemUgPT09ICdudW1iZXInID8gc2l6ZSA6IHNpemVbMV07XG4gICAgICB2YXIgdGFyZ2V0UmVzb2x1dGlvbiA9IHRoaXMudGFyZ2V0VGlsZUdyaWRfLmdldFJlc29sdXRpb24oeik7XG4gICAgICB2YXIgc291cmNlUmVzb2x1dGlvbiA9IHRoaXMuc291cmNlVGlsZUdyaWRfLmdldFJlc29sdXRpb24odGhpcy5zb3VyY2VaXyk7XG4gICAgICB2YXIgdGFyZ2V0RXh0ZW50ID0gdGhpcy50YXJnZXRUaWxlR3JpZF8uZ2V0VGlsZUNvb3JkRXh0ZW50KHRoaXMud3JhcHBlZFRpbGVDb29yZF8pO1xuICAgICAgdGhpcy5jYW52YXNfID0gcmVuZGVyUmVwcm9qZWN0ZWQod2lkdGgsIGhlaWdodCwgdGhpcy5waXhlbFJhdGlvXywgc291cmNlUmVzb2x1dGlvbiwgdGhpcy5zb3VyY2VUaWxlR3JpZF8uZ2V0RXh0ZW50KCksIHRhcmdldFJlc29sdXRpb24sIHRhcmdldEV4dGVudCwgdGhpcy50cmlhbmd1bGF0aW9uXywgc291cmNlcywgdGhpcy5ndXR0ZXJfLCB0aGlzLnJlbmRlckVkZ2VzXywgdGhpcy5jb250ZXh0T3B0aW9uc18pO1xuICAgICAgdGhpcy5zdGF0ZSA9IFRpbGVTdGF0ZS5MT0FERUQ7XG4gICAgfVxuXG4gICAgdGhpcy5jaGFuZ2VkKCk7XG4gIH07XG4gIC8qKlxuICAgKiBMb2FkIG5vdCB5ZXQgbG9hZGVkIFVSSS5cbiAgICovXG5cblxuICBSZXByb2pUaWxlLnByb3RvdHlwZS5sb2FkID0gZnVuY3Rpb24gKCkge1xuICAgIGlmICh0aGlzLnN0YXRlID09IFRpbGVTdGF0ZS5JRExFKSB7XG4gICAgICB0aGlzLnN0YXRlID0gVGlsZVN0YXRlLkxPQURJTkc7XG4gICAgICB0aGlzLmNoYW5nZWQoKTtcbiAgICAgIHZhciBsZWZ0VG9Mb2FkXzEgPSAwO1xuICAgICAgdGhpcy5zb3VyY2VzTGlzdGVuZXJLZXlzXyA9IFtdO1xuICAgICAgdGhpcy5zb3VyY2VUaWxlc18uZm9yRWFjaChmdW5jdGlvbiAodGlsZSwgaSwgYXJyKSB7XG4gICAgICAgIHZhciBzdGF0ZSA9IHRpbGUuZ2V0U3RhdGUoKTtcblxuICAgICAgICBpZiAoc3RhdGUgPT0gVGlsZVN0YXRlLklETEUgfHwgc3RhdGUgPT0gVGlsZVN0YXRlLkxPQURJTkcpIHtcbiAgICAgICAgICBsZWZ0VG9Mb2FkXzErKztcbiAgICAgICAgICB2YXIgc291cmNlTGlzdGVuS2V5XzEgPSBsaXN0ZW4odGlsZSwgRXZlbnRUeXBlLkNIQU5HRSwgZnVuY3Rpb24gKGUpIHtcbiAgICAgICAgICAgIHZhciBzdGF0ZSA9IHRpbGUuZ2V0U3RhdGUoKTtcblxuICAgICAgICAgICAgaWYgKHN0YXRlID09IFRpbGVTdGF0ZS5MT0FERUQgfHwgc3RhdGUgPT0gVGlsZVN0YXRlLkVSUk9SIHx8IHN0YXRlID09IFRpbGVTdGF0ZS5FTVBUWSkge1xuICAgICAgICAgICAgICB1bmxpc3RlbkJ5S2V5KHNvdXJjZUxpc3RlbktleV8xKTtcbiAgICAgICAgICAgICAgbGVmdFRvTG9hZF8xLS07XG5cbiAgICAgICAgICAgICAgaWYgKGxlZnRUb0xvYWRfMSA9PT0gMCkge1xuICAgICAgICAgICAgICAgIHRoaXMudW5saXN0ZW5Tb3VyY2VzXygpO1xuICAgICAgICAgICAgICAgIHRoaXMucmVwcm9qZWN0XygpO1xuICAgICAgICAgICAgICB9XG4gICAgICAgICAgICB9XG4gICAgICAgICAgfSwgdGhpcyk7XG4gICAgICAgICAgdGhpcy5zb3VyY2VzTGlzdGVuZXJLZXlzXy5wdXNoKHNvdXJjZUxpc3RlbktleV8xKTtcbiAgICAgICAgfVxuICAgICAgfS5iaW5kKHRoaXMpKTtcbiAgICAgIHRoaXMuc291cmNlVGlsZXNfLmZvckVhY2goZnVuY3Rpb24gKHRpbGUsIGksIGFycikge1xuICAgICAgICB2YXIgc3RhdGUgPSB0aWxlLmdldFN0YXRlKCk7XG5cbiAgICAgICAgaWYgKHN0YXRlID09IFRpbGVTdGF0ZS5JRExFKSB7XG4gICAgICAgICAgdGlsZS5sb2FkKCk7XG4gICAgICAgIH1cbiAgICAgIH0pO1xuXG4gICAgICBpZiAobGVmdFRvTG9hZF8xID09PSAwKSB7XG4gICAgICAgIHNldFRpbWVvdXQodGhpcy5yZXByb2plY3RfLmJpbmQodGhpcyksIDApO1xuICAgICAgfVxuICAgIH1cbiAgfTtcbiAgLyoqXG4gICAqIEBwcml2YXRlXG4gICAqL1xuXG5cbiAgUmVwcm9qVGlsZS5wcm90b3R5cGUudW5saXN0ZW5Tb3VyY2VzXyA9IGZ1bmN0aW9uICgpIHtcbiAgICB0aGlzLnNvdXJjZXNMaXN0ZW5lcktleXNfLmZvckVhY2godW5saXN0ZW5CeUtleSk7XG4gICAgdGhpcy5zb3VyY2VzTGlzdGVuZXJLZXlzXyA9IG51bGw7XG4gIH07XG5cbiAgcmV0dXJuIFJlcHJvalRpbGU7XG59KFRpbGUpO1xuXG5leHBvcnQgZGVmYXVsdCBSZXByb2pUaWxlOyIsInZhciBfX2V4dGVuZHMgPSB0aGlzICYmIHRoaXMuX19leHRlbmRzIHx8IGZ1bmN0aW9uICgpIHtcbiAgdmFyIF9leHRlbmRTdGF0aWNzID0gZnVuY3Rpb24gZXh0ZW5kU3RhdGljcyhkLCBiKSB7XG4gICAgX2V4dGVuZFN0YXRpY3MgPSBPYmplY3Quc2V0UHJvdG90eXBlT2YgfHwge1xuICAgICAgX19wcm90b19fOiBbXVxuICAgIH0gaW5zdGFuY2VvZiBBcnJheSAmJiBmdW5jdGlvbiAoZCwgYikge1xuICAgICAgZC5fX3Byb3RvX18gPSBiO1xuICAgIH0gfHwgZnVuY3Rpb24gKGQsIGIpIHtcbiAgICAgIGZvciAodmFyIHAgaW4gYikge1xuICAgICAgICBpZiAoT2JqZWN0LnByb3RvdHlwZS5oYXNPd25Qcm9wZXJ0eS5jYWxsKGIsIHApKSBkW3BdID0gYltwXTtcbiAgICAgIH1cbiAgICB9O1xuXG4gICAgcmV0dXJuIF9leHRlbmRTdGF0aWNzKGQsIGIpO1xuICB9O1xuXG4gIHJldHVybiBmdW5jdGlvbiAoZCwgYikge1xuICAgIF9leHRlbmRTdGF0aWNzKGQsIGIpO1xuXG4gICAgZnVuY3Rpb24gX18oKSB7XG4gICAgICB0aGlzLmNvbnN0cnVjdG9yID0gZDtcbiAgICB9XG5cbiAgICBkLnByb3RvdHlwZSA9IGIgPT09IG51bGwgPyBPYmplY3QuY3JlYXRlKGIpIDogKF9fLnByb3RvdHlwZSA9IGIucHJvdG90eXBlLCBuZXcgX18oKSk7XG4gIH07XG59KCk7XG4vKipcbiAqIEBtb2R1bGUgb2wvc291cmNlL1RpbGVJbWFnZVxuICovXG5cblxuaW1wb3J0IEV2ZW50VHlwZSBmcm9tICcuLi9ldmVudHMvRXZlbnRUeXBlLmpzJztcbmltcG9ydCBJbWFnZVRpbGUgZnJvbSAnLi4vSW1hZ2VUaWxlLmpzJztcbmltcG9ydCBSZXByb2pUaWxlIGZyb20gJy4uL3JlcHJvai9UaWxlLmpzJztcbmltcG9ydCBUaWxlQ2FjaGUgZnJvbSAnLi4vVGlsZUNhY2hlLmpzJztcbmltcG9ydCBUaWxlU3RhdGUgZnJvbSAnLi4vVGlsZVN0YXRlLmpzJztcbmltcG9ydCBVcmxUaWxlIGZyb20gJy4vVXJsVGlsZS5qcyc7XG5pbXBvcnQgeyBFTkFCTEVfUkFTVEVSX1JFUFJPSkVDVElPTiB9IGZyb20gJy4uL3JlcHJvai9jb21tb24uanMnO1xuaW1wb3J0IHsgSU1BR0VfU01PT1RISU5HX0RJU0FCTEVEIH0gZnJvbSAnLi9jb21tb24uanMnO1xuaW1wb3J0IHsgZXF1aXZhbGVudCwgZ2V0IGFzIGdldFByb2plY3Rpb24gfSBmcm9tICcuLi9wcm9qLmpzJztcbmltcG9ydCB7IGdldEtleSwgZ2V0S2V5WlhZIH0gZnJvbSAnLi4vdGlsZWNvb3JkLmpzJztcbmltcG9ydCB7IGdldEZvclByb2plY3Rpb24gYXMgZ2V0VGlsZUdyaWRGb3JQcm9qZWN0aW9uIH0gZnJvbSAnLi4vdGlsZWdyaWQuanMnO1xuaW1wb3J0IHsgZ2V0VWlkIH0gZnJvbSAnLi4vdXRpbC5qcyc7XG4vKipcbiAqIEB0eXBlZGVmIHtPYmplY3R9IE9wdGlvbnNcbiAqIEBwcm9wZXJ0eSB7aW1wb3J0KFwiLi9Tb3VyY2UuanNcIikuQXR0cmlidXRpb25MaWtlfSBbYXR0cmlidXRpb25zXSBBdHRyaWJ1dGlvbnMuXG4gKiBAcHJvcGVydHkge2Jvb2xlYW59IFthdHRyaWJ1dGlvbnNDb2xsYXBzaWJsZT10cnVlXSBBdHRyaWJ1dGlvbnMgYXJlIGNvbGxhcHNpYmxlLlxuICogQHByb3BlcnR5IHtudW1iZXJ9IFtjYWNoZVNpemVdIEluaXRpYWwgdGlsZSBjYWNoZSBzaXplLiBXaWxsIGF1dG8tZ3JvdyB0byBob2xkIGF0IGxlYXN0IHRoZSBudW1iZXIgb2YgdGlsZXMgaW4gdGhlIHZpZXdwb3J0LlxuICogQHByb3BlcnR5IHtudWxsfHN0cmluZ30gW2Nyb3NzT3JpZ2luXSBUaGUgYGNyb3NzT3JpZ2luYCBhdHRyaWJ1dGUgZm9yIGxvYWRlZCBpbWFnZXMuICBOb3RlIHRoYXRcbiAqIHlvdSBtdXN0IHByb3ZpZGUgYSBgY3Jvc3NPcmlnaW5gIHZhbHVlIGlmIHlvdSB3YW50IHRvIGFjY2VzcyBwaXhlbCBkYXRhIHdpdGggdGhlIENhbnZhcyByZW5kZXJlci5cbiAqIFNlZSBodHRwczovL2RldmVsb3Blci5tb3ppbGxhLm9yZy9lbi1VUy9kb2NzL1dlYi9IVE1ML0NPUlNfZW5hYmxlZF9pbWFnZSBmb3IgbW9yZSBkZXRhaWwuXG4gKiBAcHJvcGVydHkge2Jvb2xlYW59IFtpbWFnZVNtb290aGluZz10cnVlXSBFbmFibGUgaW1hZ2Ugc21vb3RoaW5nLlxuICogQHByb3BlcnR5IHtib29sZWFufSBbb3BhcXVlPWZhbHNlXSBXaGV0aGVyIHRoZSBsYXllciBpcyBvcGFxdWUuXG4gKiBAcHJvcGVydHkge2ltcG9ydChcIi4uL3Byb2ouanNcIikuUHJvamVjdGlvbkxpa2V9IFtwcm9qZWN0aW9uXSBQcm9qZWN0aW9uLiBEZWZhdWx0IGlzIHRoZSB2aWV3IHByb2plY3Rpb24uXG4gKiBAcHJvcGVydHkge251bWJlcn0gW3JlcHJvamVjdGlvbkVycm9yVGhyZXNob2xkPTAuNV0gTWF4aW11bSBhbGxvd2VkIHJlcHJvamVjdGlvbiBlcnJvciAoaW4gcGl4ZWxzKS5cbiAqIEhpZ2hlciB2YWx1ZXMgY2FuIGluY3JlYXNlIHJlcHJvamVjdGlvbiBwZXJmb3JtYW5jZSwgYnV0IGRlY3JlYXNlIHByZWNpc2lvbi5cbiAqIEBwcm9wZXJ0eSB7aW1wb3J0KFwiLi9TdGF0ZS5qc1wiKS5kZWZhdWx0fSBbc3RhdGVdIFNvdXJjZSBzdGF0ZS5cbiAqIEBwcm9wZXJ0eSB7dHlwZW9mIGltcG9ydChcIi4uL0ltYWdlVGlsZS5qc1wiKS5kZWZhdWx0fSBbdGlsZUNsYXNzXSBDbGFzcyB1c2VkIHRvIGluc3RhbnRpYXRlIGltYWdlIHRpbGVzLlxuICogRGVmYXVsdCBpcyB7QGxpbmsgbW9kdWxlOm9sL0ltYWdlVGlsZX5JbWFnZVRpbGV9LlxuICogQHByb3BlcnR5IHtpbXBvcnQoXCIuLi90aWxlZ3JpZC9UaWxlR3JpZC5qc1wiKS5kZWZhdWx0fSBbdGlsZUdyaWRdIFRpbGUgZ3JpZC5cbiAqIEBwcm9wZXJ0eSB7aW1wb3J0KFwiLi4vVGlsZS5qc1wiKS5Mb2FkRnVuY3Rpb259IFt0aWxlTG9hZEZ1bmN0aW9uXSBPcHRpb25hbCBmdW5jdGlvbiB0byBsb2FkIGEgdGlsZSBnaXZlbiBhIFVSTC4gVGhlIGRlZmF1bHQgaXNcbiAqIGBgYGpzXG4gKiBmdW5jdGlvbihpbWFnZVRpbGUsIHNyYykge1xuICogICBpbWFnZVRpbGUuZ2V0SW1hZ2UoKS5zcmMgPSBzcmM7XG4gKiB9O1xuICogYGBgXG4gKiBAcHJvcGVydHkge251bWJlcn0gW3RpbGVQaXhlbFJhdGlvPTFdIFRoZSBwaXhlbCByYXRpbyB1c2VkIGJ5IHRoZSB0aWxlIHNlcnZpY2UuIEZvciBleGFtcGxlLCBpZiB0aGUgdGlsZVxuICogc2VydmljZSBhZHZlcnRpemVzIDI1NnB4IGJ5IDI1NnB4IHRpbGVzIGJ1dCBhY3R1YWxseSBzZW5kcyA1MTJweFxuICogYnkgNTEycHggaW1hZ2VzIChmb3IgcmV0aW5hL2hpZHBpIGRldmljZXMpIHRoZW4gYHRpbGVQaXhlbFJhdGlvYFxuICogc2hvdWxkIGJlIHNldCB0byBgMmAuXG4gKiBAcHJvcGVydHkge2ltcG9ydChcIi4uL1RpbGUuanNcIikuVXJsRnVuY3Rpb259IFt0aWxlVXJsRnVuY3Rpb25dIE9wdGlvbmFsIGZ1bmN0aW9uIHRvIGdldCB0aWxlIFVSTCBnaXZlbiBhIHRpbGUgY29vcmRpbmF0ZSBhbmQgdGhlIHByb2plY3Rpb24uXG4gKiBAcHJvcGVydHkge3N0cmluZ30gW3VybF0gVVJMIHRlbXBsYXRlLiBNdXN0IGluY2x1ZGUgYHt4fWAsIGB7eX1gIG9yIGB7LXl9YCwgYW5kIGB7en1gIHBsYWNlaG9sZGVycy5cbiAqIEEgYHs/LT99YCB0ZW1wbGF0ZSBwYXR0ZXJuLCBmb3IgZXhhbXBsZSBgc3ViZG9tYWlue2EtZn0uZG9tYWluLmNvbWAsIG1heSBiZVxuICogdXNlZCBpbnN0ZWFkIG9mIGRlZmluaW5nIGVhY2ggb25lIHNlcGFyYXRlbHkgaW4gdGhlIGB1cmxzYCBvcHRpb24uXG4gKiBAcHJvcGVydHkge0FycmF5PHN0cmluZz59IFt1cmxzXSBBbiBhcnJheSBvZiBVUkwgdGVtcGxhdGVzLlxuICogQHByb3BlcnR5IHtib29sZWFufSBbd3JhcFhdIFdoZXRoZXIgdG8gd3JhcCB0aGUgd29ybGQgaG9yaXpvbnRhbGx5LiBUaGUgZGVmYXVsdCwgaXMgdG9cbiAqIHJlcXVlc3Qgb3V0LW9mLWJvdW5kcyB0aWxlcyBmcm9tIHRoZSBzZXJ2ZXIuIFdoZW4gc2V0IHRvIGBmYWxzZWAsIG9ubHkgb25lXG4gKiB3b3JsZCB3aWxsIGJlIHJlbmRlcmVkLiBXaGVuIHNldCB0byBgdHJ1ZWAsIHRpbGVzIHdpbGwgYmUgcmVxdWVzdGVkIGZvciBvbmVcbiAqIHdvcmxkIG9ubHksIGJ1dCB0aGV5IHdpbGwgYmUgd3JhcHBlZCBob3Jpem9udGFsbHkgdG8gcmVuZGVyIG11bHRpcGxlIHdvcmxkcy5cbiAqIEBwcm9wZXJ0eSB7bnVtYmVyfSBbdHJhbnNpdGlvbl0gRHVyYXRpb24gb2YgdGhlIG9wYWNpdHkgdHJhbnNpdGlvbiBmb3IgcmVuZGVyaW5nLlxuICogVG8gZGlzYWJsZSB0aGUgb3BhY2l0eSB0cmFuc2l0aW9uLCBwYXNzIGB0cmFuc2l0aW9uOiAwYC5cbiAqIEBwcm9wZXJ0eSB7c3RyaW5nfSBba2V5XSBPcHRpb25hbCB0aWxlIGtleSBmb3IgcHJvcGVyIGNhY2hlIGZldGNoaW5nXG4gKiBAcHJvcGVydHkge251bWJlcn0gW3pEaXJlY3Rpb249MF0gSW5kaWNhdGUgd2hpY2ggcmVzb2x1dGlvbiBzaG91bGQgYmUgdXNlZFxuICogYnkgYSByZW5kZXJlciBpZiB0aGUgdmlldyByZXNvbHV0aW9uIGRvZXMgbm90IG1hdGNoIGFueSByZXNvbHV0aW9uIG9mIHRoZSB0aWxlIHNvdXJjZS5cbiAqIElmIDAsIHRoZSBuZWFyZXN0IHJlc29sdXRpb24gd2lsbCBiZSB1c2VkLiBJZiAxLCB0aGUgbmVhcmVzdCBsb3dlciByZXNvbHV0aW9uXG4gKiB3aWxsIGJlIHVzZWQuIElmIC0xLCB0aGUgbmVhcmVzdCBoaWdoZXIgcmVzb2x1dGlvbiB3aWxsIGJlIHVzZWQuXG4gKi9cblxuLyoqXG4gKiBAY2xhc3NkZXNjXG4gKiBCYXNlIGNsYXNzIGZvciBzb3VyY2VzIHByb3ZpZGluZyBpbWFnZXMgZGl2aWRlZCBpbnRvIGEgdGlsZSBncmlkLlxuICpcbiAqIEBmaXJlcyBpbXBvcnQoXCIuL1RpbGUuanNcIikuVGlsZVNvdXJjZUV2ZW50XG4gKiBAYXBpXG4gKi9cblxudmFyIFRpbGVJbWFnZSA9XG4vKiogQGNsYXNzICovXG5mdW5jdGlvbiAoX3N1cGVyKSB7XG4gIF9fZXh0ZW5kcyhUaWxlSW1hZ2UsIF9zdXBlcik7XG4gIC8qKlxuICAgKiBAcGFyYW0geyFPcHRpb25zfSBvcHRpb25zIEltYWdlIHRpbGUgb3B0aW9ucy5cbiAgICovXG5cblxuICBmdW5jdGlvbiBUaWxlSW1hZ2Uob3B0aW9ucykge1xuICAgIHZhciBfdGhpcyA9IF9zdXBlci5jYWxsKHRoaXMsIHtcbiAgICAgIGF0dHJpYnV0aW9uczogb3B0aW9ucy5hdHRyaWJ1dGlvbnMsXG4gICAgICBjYWNoZVNpemU6IG9wdGlvbnMuY2FjaGVTaXplLFxuICAgICAgb3BhcXVlOiBvcHRpb25zLm9wYXF1ZSxcbiAgICAgIHByb2plY3Rpb246IG9wdGlvbnMucHJvamVjdGlvbixcbiAgICAgIHN0YXRlOiBvcHRpb25zLnN0YXRlLFxuICAgICAgdGlsZUdyaWQ6IG9wdGlvbnMudGlsZUdyaWQsXG4gICAgICB0aWxlTG9hZEZ1bmN0aW9uOiBvcHRpb25zLnRpbGVMb2FkRnVuY3Rpb24gPyBvcHRpb25zLnRpbGVMb2FkRnVuY3Rpb24gOiBkZWZhdWx0VGlsZUxvYWRGdW5jdGlvbixcbiAgICAgIHRpbGVQaXhlbFJhdGlvOiBvcHRpb25zLnRpbGVQaXhlbFJhdGlvLFxuICAgICAgdGlsZVVybEZ1bmN0aW9uOiBvcHRpb25zLnRpbGVVcmxGdW5jdGlvbixcbiAgICAgIHVybDogb3B0aW9ucy51cmwsXG4gICAgICB1cmxzOiBvcHRpb25zLnVybHMsXG4gICAgICB3cmFwWDogb3B0aW9ucy53cmFwWCxcbiAgICAgIHRyYW5zaXRpb246IG9wdGlvbnMudHJhbnNpdGlvbixcbiAgICAgIGtleTogb3B0aW9ucy5rZXksXG4gICAgICBhdHRyaWJ1dGlvbnNDb2xsYXBzaWJsZTogb3B0aW9ucy5hdHRyaWJ1dGlvbnNDb2xsYXBzaWJsZSxcbiAgICAgIHpEaXJlY3Rpb246IG9wdGlvbnMuekRpcmVjdGlvblxuICAgIH0pIHx8IHRoaXM7XG4gICAgLyoqXG4gICAgICogQHByb3RlY3RlZFxuICAgICAqIEB0eXBlIHs/c3RyaW5nfVxuICAgICAqL1xuXG5cbiAgICBfdGhpcy5jcm9zc09yaWdpbiA9IG9wdGlvbnMuY3Jvc3NPcmlnaW4gIT09IHVuZGVmaW5lZCA/IG9wdGlvbnMuY3Jvc3NPcmlnaW4gOiBudWxsO1xuICAgIC8qKlxuICAgICAqIEBwcm90ZWN0ZWRcbiAgICAgKiBAdHlwZSB7dHlwZW9mIEltYWdlVGlsZX1cbiAgICAgKi9cblxuICAgIF90aGlzLnRpbGVDbGFzcyA9IG9wdGlvbnMudGlsZUNsYXNzICE9PSB1bmRlZmluZWQgPyBvcHRpb25zLnRpbGVDbGFzcyA6IEltYWdlVGlsZTtcbiAgICAvKipcbiAgICAgKiBAcHJvdGVjdGVkXG4gICAgICogQHR5cGUgeyFPYmplY3Q8c3RyaW5nLCBUaWxlQ2FjaGU+fVxuICAgICAqL1xuXG4gICAgX3RoaXMudGlsZUNhY2hlRm9yUHJvamVjdGlvbiA9IHt9O1xuICAgIC8qKlxuICAgICAqIEBwcm90ZWN0ZWRcbiAgICAgKiBAdHlwZSB7IU9iamVjdDxzdHJpbmcsIGltcG9ydChcIi4uL3RpbGVncmlkL1RpbGVHcmlkLmpzXCIpLmRlZmF1bHQ+fVxuICAgICAqL1xuXG4gICAgX3RoaXMudGlsZUdyaWRGb3JQcm9qZWN0aW9uID0ge307XG4gICAgLyoqXG4gICAgICogQHByaXZhdGVcbiAgICAgKiBAdHlwZSB7bnVtYmVyfHVuZGVmaW5lZH1cbiAgICAgKi9cblxuICAgIF90aGlzLnJlcHJvamVjdGlvbkVycm9yVGhyZXNob2xkXyA9IG9wdGlvbnMucmVwcm9qZWN0aW9uRXJyb3JUaHJlc2hvbGQ7XG4gICAgLyoqXG4gICAgICogQHByaXZhdGVcbiAgICAgKiBAdHlwZSB7b2JqZWN0fHVuZGVmaW5lZH1cbiAgICAgKi9cblxuICAgIF90aGlzLmNvbnRleHRPcHRpb25zXyA9IG9wdGlvbnMuaW1hZ2VTbW9vdGhpbmcgPT09IGZhbHNlID8gSU1BR0VfU01PT1RISU5HX0RJU0FCTEVEIDogdW5kZWZpbmVkO1xuICAgIC8qKlxuICAgICAqIEBwcml2YXRlXG4gICAgICogQHR5cGUge2Jvb2xlYW59XG4gICAgICovXG5cbiAgICBfdGhpcy5yZW5kZXJSZXByb2plY3Rpb25FZGdlc18gPSBmYWxzZTtcbiAgICByZXR1cm4gX3RoaXM7XG4gIH1cbiAgLyoqXG4gICAqIEByZXR1cm4ge2Jvb2xlYW59IENhbiBleHBpcmUgY2FjaGUuXG4gICAqL1xuXG5cbiAgVGlsZUltYWdlLnByb3RvdHlwZS5jYW5FeHBpcmVDYWNoZSA9IGZ1bmN0aW9uICgpIHtcbiAgICBpZiAoIUVOQUJMRV9SQVNURVJfUkVQUk9KRUNUSU9OKSB7XG4gICAgICByZXR1cm4gX3N1cGVyLnByb3RvdHlwZS5jYW5FeHBpcmVDYWNoZS5jYWxsKHRoaXMpO1xuICAgIH1cblxuICAgIGlmICh0aGlzLnRpbGVDYWNoZS5jYW5FeHBpcmVDYWNoZSgpKSB7XG4gICAgICByZXR1cm4gdHJ1ZTtcbiAgICB9IGVsc2Uge1xuICAgICAgZm9yICh2YXIga2V5IGluIHRoaXMudGlsZUNhY2hlRm9yUHJvamVjdGlvbikge1xuICAgICAgICBpZiAodGhpcy50aWxlQ2FjaGVGb3JQcm9qZWN0aW9uW2tleV0uY2FuRXhwaXJlQ2FjaGUoKSkge1xuICAgICAgICAgIHJldHVybiB0cnVlO1xuICAgICAgICB9XG4gICAgICB9XG4gICAgfVxuXG4gICAgcmV0dXJuIGZhbHNlO1xuICB9O1xuICAvKipcbiAgICogQHBhcmFtIHtpbXBvcnQoXCIuLi9wcm9qL1Byb2plY3Rpb24uanNcIikuZGVmYXVsdH0gcHJvamVjdGlvbiBQcm9qZWN0aW9uLlxuICAgKiBAcGFyYW0geyFPYmplY3Q8c3RyaW5nLCBib29sZWFuPn0gdXNlZFRpbGVzIFVzZWQgdGlsZXMuXG4gICAqL1xuXG5cbiAgVGlsZUltYWdlLnByb3RvdHlwZS5leHBpcmVDYWNoZSA9IGZ1bmN0aW9uIChwcm9qZWN0aW9uLCB1c2VkVGlsZXMpIHtcbiAgICBpZiAoIUVOQUJMRV9SQVNURVJfUkVQUk9KRUNUSU9OKSB7XG4gICAgICBfc3VwZXIucHJvdG90eXBlLmV4cGlyZUNhY2hlLmNhbGwodGhpcywgcHJvamVjdGlvbiwgdXNlZFRpbGVzKTtcblxuICAgICAgcmV0dXJuO1xuICAgIH1cblxuICAgIHZhciB1c2VkVGlsZUNhY2hlID0gdGhpcy5nZXRUaWxlQ2FjaGVGb3JQcm9qZWN0aW9uKHByb2plY3Rpb24pO1xuICAgIHRoaXMudGlsZUNhY2hlLmV4cGlyZUNhY2hlKHRoaXMudGlsZUNhY2hlID09IHVzZWRUaWxlQ2FjaGUgPyB1c2VkVGlsZXMgOiB7fSk7XG5cbiAgICBmb3IgKHZhciBpZCBpbiB0aGlzLnRpbGVDYWNoZUZvclByb2plY3Rpb24pIHtcbiAgICAgIHZhciB0aWxlQ2FjaGUgPSB0aGlzLnRpbGVDYWNoZUZvclByb2plY3Rpb25baWRdO1xuICAgICAgdGlsZUNhY2hlLmV4cGlyZUNhY2hlKHRpbGVDYWNoZSA9PSB1c2VkVGlsZUNhY2hlID8gdXNlZFRpbGVzIDoge30pO1xuICAgIH1cbiAgfTtcbiAgLyoqXG4gICAqIEByZXR1cm4ge09iamVjdHx1bmRlZmluZWR9IENvbnRleHQgb3B0aW9ucy5cbiAgICovXG5cblxuICBUaWxlSW1hZ2UucHJvdG90eXBlLmdldENvbnRleHRPcHRpb25zID0gZnVuY3Rpb24gKCkge1xuICAgIHJldHVybiB0aGlzLmNvbnRleHRPcHRpb25zXztcbiAgfTtcbiAgLyoqXG4gICAqIEBwYXJhbSB7aW1wb3J0KFwiLi4vcHJvai9Qcm9qZWN0aW9uLmpzXCIpLmRlZmF1bHR9IHByb2plY3Rpb24gUHJvamVjdGlvbi5cbiAgICogQHJldHVybiB7bnVtYmVyfSBHdXR0ZXIuXG4gICAqL1xuXG5cbiAgVGlsZUltYWdlLnByb3RvdHlwZS5nZXRHdXR0ZXJGb3JQcm9qZWN0aW9uID0gZnVuY3Rpb24gKHByb2plY3Rpb24pIHtcbiAgICBpZiAoRU5BQkxFX1JBU1RFUl9SRVBST0pFQ1RJT04gJiYgdGhpcy5nZXRQcm9qZWN0aW9uKCkgJiYgcHJvamVjdGlvbiAmJiAhZXF1aXZhbGVudCh0aGlzLmdldFByb2plY3Rpb24oKSwgcHJvamVjdGlvbikpIHtcbiAgICAgIHJldHVybiAwO1xuICAgIH0gZWxzZSB7XG4gICAgICByZXR1cm4gdGhpcy5nZXRHdXR0ZXIoKTtcbiAgICB9XG4gIH07XG4gIC8qKlxuICAgKiBAcmV0dXJuIHtudW1iZXJ9IEd1dHRlci5cbiAgICovXG5cblxuICBUaWxlSW1hZ2UucHJvdG90eXBlLmdldEd1dHRlciA9IGZ1bmN0aW9uICgpIHtcbiAgICByZXR1cm4gMDtcbiAgfTtcbiAgLyoqXG4gICAqIFJldHVybiB0aGUga2V5IHRvIGJlIHVzZWQgZm9yIGFsbCB0aWxlcyBpbiB0aGUgc291cmNlLlxuICAgKiBAcmV0dXJuIHtzdHJpbmd9IFRoZSBrZXkgZm9yIGFsbCB0aWxlcy5cbiAgICogQHByb3RlY3RlZFxuICAgKi9cblxuXG4gIFRpbGVJbWFnZS5wcm90b3R5cGUuZ2V0S2V5ID0gZnVuY3Rpb24gKCkge1xuICAgIHJldHVybiBfc3VwZXIucHJvdG90eXBlLmdldEtleS5jYWxsKHRoaXMpICsgKHRoaXMuY29udGV4dE9wdGlvbnNfID8gJ1xcbicgKyBKU09OLnN0cmluZ2lmeSh0aGlzLmNvbnRleHRPcHRpb25zXykgOiAnJyk7XG4gIH07XG4gIC8qKlxuICAgKiBAcGFyYW0ge2ltcG9ydChcIi4uL3Byb2ovUHJvamVjdGlvbi5qc1wiKS5kZWZhdWx0fSBwcm9qZWN0aW9uIFByb2plY3Rpb24uXG4gICAqIEByZXR1cm4ge2Jvb2xlYW59IE9wYXF1ZS5cbiAgICovXG5cblxuICBUaWxlSW1hZ2UucHJvdG90eXBlLmdldE9wYXF1ZSA9IGZ1bmN0aW9uIChwcm9qZWN0aW9uKSB7XG4gICAgaWYgKEVOQUJMRV9SQVNURVJfUkVQUk9KRUNUSU9OICYmIHRoaXMuZ2V0UHJvamVjdGlvbigpICYmIHByb2plY3Rpb24gJiYgIWVxdWl2YWxlbnQodGhpcy5nZXRQcm9qZWN0aW9uKCksIHByb2plY3Rpb24pKSB7XG4gICAgICByZXR1cm4gZmFsc2U7XG4gICAgfSBlbHNlIHtcbiAgICAgIHJldHVybiBfc3VwZXIucHJvdG90eXBlLmdldE9wYXF1ZS5jYWxsKHRoaXMsIHByb2plY3Rpb24pO1xuICAgIH1cbiAgfTtcbiAgLyoqXG4gICAqIEBwYXJhbSB7aW1wb3J0KFwiLi4vcHJvai9Qcm9qZWN0aW9uLmpzXCIpLmRlZmF1bHR9IHByb2plY3Rpb24gUHJvamVjdGlvbi5cbiAgICogQHJldHVybiB7IWltcG9ydChcIi4uL3RpbGVncmlkL1RpbGVHcmlkLmpzXCIpLmRlZmF1bHR9IFRpbGUgZ3JpZC5cbiAgICovXG5cblxuICBUaWxlSW1hZ2UucHJvdG90eXBlLmdldFRpbGVHcmlkRm9yUHJvamVjdGlvbiA9IGZ1bmN0aW9uIChwcm9qZWN0aW9uKSB7XG4gICAgaWYgKCFFTkFCTEVfUkFTVEVSX1JFUFJPSkVDVElPTikge1xuICAgICAgcmV0dXJuIF9zdXBlci5wcm90b3R5cGUuZ2V0VGlsZUdyaWRGb3JQcm9qZWN0aW9uLmNhbGwodGhpcywgcHJvamVjdGlvbik7XG4gICAgfVxuXG4gICAgdmFyIHRoaXNQcm9qID0gdGhpcy5nZXRQcm9qZWN0aW9uKCk7XG5cbiAgICBpZiAodGhpcy50aWxlR3JpZCAmJiAoIXRoaXNQcm9qIHx8IGVxdWl2YWxlbnQodGhpc1Byb2osIHByb2plY3Rpb24pKSkge1xuICAgICAgcmV0dXJuIHRoaXMudGlsZUdyaWQ7XG4gICAgfSBlbHNlIHtcbiAgICAgIHZhciBwcm9qS2V5ID0gZ2V0VWlkKHByb2plY3Rpb24pO1xuXG4gICAgICBpZiAoIShwcm9qS2V5IGluIHRoaXMudGlsZUdyaWRGb3JQcm9qZWN0aW9uKSkge1xuICAgICAgICB0aGlzLnRpbGVHcmlkRm9yUHJvamVjdGlvbltwcm9qS2V5XSA9IGdldFRpbGVHcmlkRm9yUHJvamVjdGlvbihwcm9qZWN0aW9uKTtcbiAgICAgIH1cblxuICAgICAgcmV0dXJuIHRoaXMudGlsZUdyaWRGb3JQcm9qZWN0aW9uW3Byb2pLZXldO1xuICAgIH1cbiAgfTtcbiAgLyoqXG4gICAqIEBwYXJhbSB7aW1wb3J0KFwiLi4vcHJvai9Qcm9qZWN0aW9uLmpzXCIpLmRlZmF1bHR9IHByb2plY3Rpb24gUHJvamVjdGlvbi5cbiAgICogQHJldHVybiB7aW1wb3J0KFwiLi4vVGlsZUNhY2hlLmpzXCIpLmRlZmF1bHR9IFRpbGUgY2FjaGUuXG4gICAqL1xuXG5cbiAgVGlsZUltYWdlLnByb3RvdHlwZS5nZXRUaWxlQ2FjaGVGb3JQcm9qZWN0aW9uID0gZnVuY3Rpb24gKHByb2plY3Rpb24pIHtcbiAgICBpZiAoIUVOQUJMRV9SQVNURVJfUkVQUk9KRUNUSU9OKSB7XG4gICAgICByZXR1cm4gX3N1cGVyLnByb3RvdHlwZS5nZXRUaWxlQ2FjaGVGb3JQcm9qZWN0aW9uLmNhbGwodGhpcywgcHJvamVjdGlvbik7XG4gICAgfVxuXG4gICAgdmFyIHRoaXNQcm9qID0gdGhpcy5nZXRQcm9qZWN0aW9uKCk7XG5cbiAgICBpZiAoIXRoaXNQcm9qIHx8IGVxdWl2YWxlbnQodGhpc1Byb2osIHByb2plY3Rpb24pKSB7XG4gICAgICByZXR1cm4gdGhpcy50aWxlQ2FjaGU7XG4gICAgfSBlbHNlIHtcbiAgICAgIHZhciBwcm9qS2V5ID0gZ2V0VWlkKHByb2plY3Rpb24pO1xuXG4gICAgICBpZiAoIShwcm9qS2V5IGluIHRoaXMudGlsZUNhY2hlRm9yUHJvamVjdGlvbikpIHtcbiAgICAgICAgdGhpcy50aWxlQ2FjaGVGb3JQcm9qZWN0aW9uW3Byb2pLZXldID0gbmV3IFRpbGVDYWNoZSh0aGlzLnRpbGVDYWNoZS5oaWdoV2F0ZXJNYXJrKTtcbiAgICAgIH1cblxuICAgICAgcmV0dXJuIHRoaXMudGlsZUNhY2hlRm9yUHJvamVjdGlvbltwcm9qS2V5XTtcbiAgICB9XG4gIH07XG4gIC8qKlxuICAgKiBAcGFyYW0ge251bWJlcn0geiBUaWxlIGNvb3JkaW5hdGUgei5cbiAgICogQHBhcmFtIHtudW1iZXJ9IHggVGlsZSBjb29yZGluYXRlIHguXG4gICAqIEBwYXJhbSB7bnVtYmVyfSB5IFRpbGUgY29vcmRpbmF0ZSB5LlxuICAgKiBAcGFyYW0ge251bWJlcn0gcGl4ZWxSYXRpbyBQaXhlbCByYXRpby5cbiAgICogQHBhcmFtIHtpbXBvcnQoXCIuLi9wcm9qL1Byb2plY3Rpb24uanNcIikuZGVmYXVsdH0gcHJvamVjdGlvbiBQcm9qZWN0aW9uLlxuICAgKiBAcGFyYW0ge3N0cmluZ30ga2V5IFRoZSBrZXkgc2V0IG9uIHRoZSB0aWxlLlxuICAgKiBAcmV0dXJuIHshaW1wb3J0KFwiLi4vVGlsZS5qc1wiKS5kZWZhdWx0fSBUaWxlLlxuICAgKiBAcHJpdmF0ZVxuICAgKi9cblxuXG4gIFRpbGVJbWFnZS5wcm90b3R5cGUuY3JlYXRlVGlsZV8gPSBmdW5jdGlvbiAoeiwgeCwgeSwgcGl4ZWxSYXRpbywgcHJvamVjdGlvbiwga2V5KSB7XG4gICAgdmFyIHRpbGVDb29yZCA9IFt6LCB4LCB5XTtcbiAgICB2YXIgdXJsVGlsZUNvb3JkID0gdGhpcy5nZXRUaWxlQ29vcmRGb3JUaWxlVXJsRnVuY3Rpb24odGlsZUNvb3JkLCBwcm9qZWN0aW9uKTtcbiAgICB2YXIgdGlsZVVybCA9IHVybFRpbGVDb29yZCA/IHRoaXMudGlsZVVybEZ1bmN0aW9uKHVybFRpbGVDb29yZCwgcGl4ZWxSYXRpbywgcHJvamVjdGlvbikgOiB1bmRlZmluZWQ7XG4gICAgdmFyIHRpbGUgPSBuZXcgdGhpcy50aWxlQ2xhc3ModGlsZUNvb3JkLCB0aWxlVXJsICE9PSB1bmRlZmluZWQgPyBUaWxlU3RhdGUuSURMRSA6IFRpbGVTdGF0ZS5FTVBUWSwgdGlsZVVybCAhPT0gdW5kZWZpbmVkID8gdGlsZVVybCA6ICcnLCB0aGlzLmNyb3NzT3JpZ2luLCB0aGlzLnRpbGVMb2FkRnVuY3Rpb24sIHRoaXMudGlsZU9wdGlvbnMpO1xuICAgIHRpbGUua2V5ID0ga2V5O1xuICAgIHRpbGUuYWRkRXZlbnRMaXN0ZW5lcihFdmVudFR5cGUuQ0hBTkdFLCB0aGlzLmhhbmRsZVRpbGVDaGFuZ2UuYmluZCh0aGlzKSk7XG4gICAgcmV0dXJuIHRpbGU7XG4gIH07XG4gIC8qKlxuICAgKiBAcGFyYW0ge251bWJlcn0geiBUaWxlIGNvb3JkaW5hdGUgei5cbiAgICogQHBhcmFtIHtudW1iZXJ9IHggVGlsZSBjb29yZGluYXRlIHguXG4gICAqIEBwYXJhbSB7bnVtYmVyfSB5IFRpbGUgY29vcmRpbmF0ZSB5LlxuICAgKiBAcGFyYW0ge251bWJlcn0gcGl4ZWxSYXRpbyBQaXhlbCByYXRpby5cbiAgICogQHBhcmFtIHtpbXBvcnQoXCIuLi9wcm9qL1Byb2plY3Rpb24uanNcIikuZGVmYXVsdH0gcHJvamVjdGlvbiBQcm9qZWN0aW9uLlxuICAgKiBAcmV0dXJuIHshaW1wb3J0KFwiLi4vVGlsZS5qc1wiKS5kZWZhdWx0fSBUaWxlLlxuICAgKi9cblxuXG4gIFRpbGVJbWFnZS5wcm90b3R5cGUuZ2V0VGlsZSA9IGZ1bmN0aW9uICh6LCB4LCB5LCBwaXhlbFJhdGlvLCBwcm9qZWN0aW9uKSB7XG4gICAgdmFyIHNvdXJjZVByb2plY3Rpb24gPSB0aGlzLmdldFByb2plY3Rpb24oKTtcblxuICAgIGlmICghRU5BQkxFX1JBU1RFUl9SRVBST0pFQ1RJT04gfHwgIXNvdXJjZVByb2plY3Rpb24gfHwgIXByb2plY3Rpb24gfHwgZXF1aXZhbGVudChzb3VyY2VQcm9qZWN0aW9uLCBwcm9qZWN0aW9uKSkge1xuICAgICAgcmV0dXJuIHRoaXMuZ2V0VGlsZUludGVybmFsKHosIHgsIHksIHBpeGVsUmF0aW8sIHNvdXJjZVByb2plY3Rpb24gfHwgcHJvamVjdGlvbik7XG4gICAgfSBlbHNlIHtcbiAgICAgIHZhciBjYWNoZSA9IHRoaXMuZ2V0VGlsZUNhY2hlRm9yUHJvamVjdGlvbihwcm9qZWN0aW9uKTtcbiAgICAgIHZhciB0aWxlQ29vcmQgPSBbeiwgeCwgeV07XG4gICAgICB2YXIgdGlsZSA9IHZvaWQgMDtcbiAgICAgIHZhciB0aWxlQ29vcmRLZXkgPSBnZXRLZXkodGlsZUNvb3JkKTtcblxuICAgICAgaWYgKGNhY2hlLmNvbnRhaW5zS2V5KHRpbGVDb29yZEtleSkpIHtcbiAgICAgICAgdGlsZSA9IGNhY2hlLmdldCh0aWxlQ29vcmRLZXkpO1xuICAgICAgfVxuXG4gICAgICB2YXIga2V5ID0gdGhpcy5nZXRLZXkoKTtcblxuICAgICAgaWYgKHRpbGUgJiYgdGlsZS5rZXkgPT0ga2V5KSB7XG4gICAgICAgIHJldHVybiB0aWxlO1xuICAgICAgfSBlbHNlIHtcbiAgICAgICAgdmFyIHNvdXJjZVRpbGVHcmlkID0gdGhpcy5nZXRUaWxlR3JpZEZvclByb2plY3Rpb24oc291cmNlUHJvamVjdGlvbik7XG4gICAgICAgIHZhciB0YXJnZXRUaWxlR3JpZCA9IHRoaXMuZ2V0VGlsZUdyaWRGb3JQcm9qZWN0aW9uKHByb2plY3Rpb24pO1xuICAgICAgICB2YXIgd3JhcHBlZFRpbGVDb29yZCA9IHRoaXMuZ2V0VGlsZUNvb3JkRm9yVGlsZVVybEZ1bmN0aW9uKHRpbGVDb29yZCwgcHJvamVjdGlvbik7XG4gICAgICAgIHZhciBuZXdUaWxlID0gbmV3IFJlcHJvalRpbGUoc291cmNlUHJvamVjdGlvbiwgc291cmNlVGlsZUdyaWQsIHByb2plY3Rpb24sIHRhcmdldFRpbGVHcmlkLCB0aWxlQ29vcmQsIHdyYXBwZWRUaWxlQ29vcmQsIHRoaXMuZ2V0VGlsZVBpeGVsUmF0aW8ocGl4ZWxSYXRpbyksIHRoaXMuZ2V0R3V0dGVyKCksIGZ1bmN0aW9uICh6LCB4LCB5LCBwaXhlbFJhdGlvKSB7XG4gICAgICAgICAgcmV0dXJuIHRoaXMuZ2V0VGlsZUludGVybmFsKHosIHgsIHksIHBpeGVsUmF0aW8sIHNvdXJjZVByb2plY3Rpb24pO1xuICAgICAgICB9LmJpbmQodGhpcyksIHRoaXMucmVwcm9qZWN0aW9uRXJyb3JUaHJlc2hvbGRfLCB0aGlzLnJlbmRlclJlcHJvamVjdGlvbkVkZ2VzXywgdGhpcy5jb250ZXh0T3B0aW9uc18pO1xuICAgICAgICBuZXdUaWxlLmtleSA9IGtleTtcblxuICAgICAgICBpZiAodGlsZSkge1xuICAgICAgICAgIG5ld1RpbGUuaW50ZXJpbVRpbGUgPSB0aWxlO1xuICAgICAgICAgIG5ld1RpbGUucmVmcmVzaEludGVyaW1DaGFpbigpO1xuICAgICAgICAgIGNhY2hlLnJlcGxhY2UodGlsZUNvb3JkS2V5LCBuZXdUaWxlKTtcbiAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICBjYWNoZS5zZXQodGlsZUNvb3JkS2V5LCBuZXdUaWxlKTtcbiAgICAgICAgfVxuXG4gICAgICAgIHJldHVybiBuZXdUaWxlO1xuICAgICAgfVxuICAgIH1cbiAgfTtcbiAgLyoqXG4gICAqIEBwYXJhbSB7bnVtYmVyfSB6IFRpbGUgY29vcmRpbmF0ZSB6LlxuICAgKiBAcGFyYW0ge251bWJlcn0geCBUaWxlIGNvb3JkaW5hdGUgeC5cbiAgICogQHBhcmFtIHtudW1iZXJ9IHkgVGlsZSBjb29yZGluYXRlIHkuXG4gICAqIEBwYXJhbSB7bnVtYmVyfSBwaXhlbFJhdGlvIFBpeGVsIHJhdGlvLlxuICAgKiBAcGFyYW0geyFpbXBvcnQoXCIuLi9wcm9qL1Byb2plY3Rpb24uanNcIikuZGVmYXVsdH0gcHJvamVjdGlvbiBQcm9qZWN0aW9uLlxuICAgKiBAcmV0dXJuIHshaW1wb3J0KFwiLi4vVGlsZS5qc1wiKS5kZWZhdWx0fSBUaWxlLlxuICAgKiBAcHJvdGVjdGVkXG4gICAqL1xuXG5cbiAgVGlsZUltYWdlLnByb3RvdHlwZS5nZXRUaWxlSW50ZXJuYWwgPSBmdW5jdGlvbiAoeiwgeCwgeSwgcGl4ZWxSYXRpbywgcHJvamVjdGlvbikge1xuICAgIHZhciB0aWxlID0gbnVsbDtcbiAgICB2YXIgdGlsZUNvb3JkS2V5ID0gZ2V0S2V5WlhZKHosIHgsIHkpO1xuICAgIHZhciBrZXkgPSB0aGlzLmdldEtleSgpO1xuXG4gICAgaWYgKCF0aGlzLnRpbGVDYWNoZS5jb250YWluc0tleSh0aWxlQ29vcmRLZXkpKSB7XG4gICAgICB0aWxlID0gdGhpcy5jcmVhdGVUaWxlXyh6LCB4LCB5LCBwaXhlbFJhdGlvLCBwcm9qZWN0aW9uLCBrZXkpO1xuICAgICAgdGhpcy50aWxlQ2FjaGUuc2V0KHRpbGVDb29yZEtleSwgdGlsZSk7XG4gICAgfSBlbHNlIHtcbiAgICAgIHRpbGUgPSB0aGlzLnRpbGVDYWNoZS5nZXQodGlsZUNvb3JkS2V5KTtcblxuICAgICAgaWYgKHRpbGUua2V5ICE9IGtleSkge1xuICAgICAgICAvLyBUaGUgc291cmNlJ3MgcGFyYW1zIGNoYW5nZWQuIElmIHRoZSB0aWxlIGhhcyBhbiBpbnRlcmltIHRpbGUgYW5kIGlmIHdlXG4gICAgICAgIC8vIGNhbiB1c2UgaXQgdGhlbiB3ZSB1c2UgaXQuIE90aGVyd2lzZSB3ZSBjcmVhdGUgYSBuZXcgdGlsZS4gIEluIGJvdGhcbiAgICAgICAgLy8gY2FzZXMgd2UgYXR0ZW1wdCB0byBhc3NpZ24gYW4gaW50ZXJpbSB0aWxlIHRvIHRoZSBuZXcgdGlsZS5cbiAgICAgICAgdmFyIGludGVyaW1UaWxlID0gdGlsZTtcbiAgICAgICAgdGlsZSA9IHRoaXMuY3JlYXRlVGlsZV8oeiwgeCwgeSwgcGl4ZWxSYXRpbywgcHJvamVjdGlvbiwga2V5KTsgLy9tYWtlIHRoZSBuZXcgdGlsZSB0aGUgaGVhZCBvZiB0aGUgbGlzdCxcblxuICAgICAgICBpZiAoaW50ZXJpbVRpbGUuZ2V0U3RhdGUoKSA9PSBUaWxlU3RhdGUuSURMRSkge1xuICAgICAgICAgIC8vdGhlIG9sZCB0aWxlIGhhc24ndCBiZWd1biBsb2FkaW5nIHlldCwgYW5kIGlzIG5vdyBvdXRkYXRlZCwgc28gd2UgY2FuIHNpbXBseSBkaXNjYXJkIGl0XG4gICAgICAgICAgdGlsZS5pbnRlcmltVGlsZSA9IGludGVyaW1UaWxlLmludGVyaW1UaWxlO1xuICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgIHRpbGUuaW50ZXJpbVRpbGUgPSBpbnRlcmltVGlsZTtcbiAgICAgICAgfVxuXG4gICAgICAgIHRpbGUucmVmcmVzaEludGVyaW1DaGFpbigpO1xuICAgICAgICB0aGlzLnRpbGVDYWNoZS5yZXBsYWNlKHRpbGVDb29yZEtleSwgdGlsZSk7XG4gICAgICB9XG4gICAgfVxuXG4gICAgcmV0dXJuIHRpbGU7XG4gIH07XG4gIC8qKlxuICAgKiBTZXRzIHdoZXRoZXIgdG8gcmVuZGVyIHJlcHJvamVjdGlvbiBlZGdlcyBvciBub3QgKHVzdWFsbHkgZm9yIGRlYnVnZ2luZykuXG4gICAqIEBwYXJhbSB7Ym9vbGVhbn0gcmVuZGVyIFJlbmRlciB0aGUgZWRnZXMuXG4gICAqIEBhcGlcbiAgICovXG5cblxuICBUaWxlSW1hZ2UucHJvdG90eXBlLnNldFJlbmRlclJlcHJvamVjdGlvbkVkZ2VzID0gZnVuY3Rpb24gKHJlbmRlcikge1xuICAgIGlmICghRU5BQkxFX1JBU1RFUl9SRVBST0pFQ1RJT04gfHwgdGhpcy5yZW5kZXJSZXByb2plY3Rpb25FZGdlc18gPT0gcmVuZGVyKSB7XG4gICAgICByZXR1cm47XG4gICAgfVxuXG4gICAgdGhpcy5yZW5kZXJSZXByb2plY3Rpb25FZGdlc18gPSByZW5kZXI7XG5cbiAgICBmb3IgKHZhciBpZCBpbiB0aGlzLnRpbGVDYWNoZUZvclByb2plY3Rpb24pIHtcbiAgICAgIHRoaXMudGlsZUNhY2hlRm9yUHJvamVjdGlvbltpZF0uY2xlYXIoKTtcbiAgICB9XG5cbiAgICB0aGlzLmNoYW5nZWQoKTtcbiAgfTtcbiAgLyoqXG4gICAqIFNldHMgdGhlIHRpbGUgZ3JpZCB0byB1c2Ugd2hlbiByZXByb2plY3RpbmcgdGhlIHRpbGVzIHRvIHRoZSBnaXZlblxuICAgKiBwcm9qZWN0aW9uIGluc3RlYWQgb2YgdGhlIGRlZmF1bHQgdGlsZSBncmlkIGZvciB0aGUgcHJvamVjdGlvbi5cbiAgICpcbiAgICogVGhpcyBjYW4gYmUgdXNlZnVsIHdoZW4gdGhlIGRlZmF1bHQgdGlsZSBncmlkIGNhbm5vdCBiZSBjcmVhdGVkXG4gICAqIChlLmcuIHByb2plY3Rpb24gaGFzIG5vIGV4dGVudCBkZWZpbmVkKSBvclxuICAgKiBmb3Igb3B0aW1pemF0aW9uIHJlYXNvbnMgKGN1c3RvbSB0aWxlIHNpemUsIHJlc29sdXRpb25zLCAuLi4pLlxuICAgKlxuICAgKiBAcGFyYW0ge2ltcG9ydChcIi4uL3Byb2ouanNcIikuUHJvamVjdGlvbkxpa2V9IHByb2plY3Rpb24gUHJvamVjdGlvbi5cbiAgICogQHBhcmFtIHtpbXBvcnQoXCIuLi90aWxlZ3JpZC9UaWxlR3JpZC5qc1wiKS5kZWZhdWx0fSB0aWxlZ3JpZCBUaWxlIGdyaWQgdG8gdXNlIGZvciB0aGUgcHJvamVjdGlvbi5cbiAgICogQGFwaVxuICAgKi9cblxuXG4gIFRpbGVJbWFnZS5wcm90b3R5cGUuc2V0VGlsZUdyaWRGb3JQcm9qZWN0aW9uID0gZnVuY3Rpb24gKHByb2plY3Rpb24sIHRpbGVncmlkKSB7XG4gICAgaWYgKEVOQUJMRV9SQVNURVJfUkVQUk9KRUNUSU9OKSB7XG4gICAgICB2YXIgcHJvaiA9IGdldFByb2plY3Rpb24ocHJvamVjdGlvbik7XG5cbiAgICAgIGlmIChwcm9qKSB7XG4gICAgICAgIHZhciBwcm9qS2V5ID0gZ2V0VWlkKHByb2opO1xuXG4gICAgICAgIGlmICghKHByb2pLZXkgaW4gdGhpcy50aWxlR3JpZEZvclByb2plY3Rpb24pKSB7XG4gICAgICAgICAgdGhpcy50aWxlR3JpZEZvclByb2plY3Rpb25bcHJvaktleV0gPSB0aWxlZ3JpZDtcbiAgICAgICAgfVxuICAgICAgfVxuICAgIH1cbiAgfTtcblxuICByZXR1cm4gVGlsZUltYWdlO1xufShVcmxUaWxlKTtcbi8qKlxuICogQHBhcmFtIHtJbWFnZVRpbGV9IGltYWdlVGlsZSBJbWFnZSB0aWxlLlxuICogQHBhcmFtIHtzdHJpbmd9IHNyYyBTb3VyY2UuXG4gKi9cblxuXG5mdW5jdGlvbiBkZWZhdWx0VGlsZUxvYWRGdW5jdGlvbihpbWFnZVRpbGUsIHNyYykge1xuICAvKiogQHR5cGUge0hUTUxJbWFnZUVsZW1lbnR8SFRNTFZpZGVvRWxlbWVudH0gKi9cbiAgaW1hZ2VUaWxlLmdldEltYWdlKCkuc3JjID0gc3JjO1xufVxuXG5leHBvcnQgZGVmYXVsdCBUaWxlSW1hZ2U7IiwiLyoqXG4gKiBAbW9kdWxlIG9sL3NvdXJjZS9YWVpcbiAqL1xudmFyIF9fZXh0ZW5kcyA9IHRoaXMgJiYgdGhpcy5fX2V4dGVuZHMgfHwgZnVuY3Rpb24gKCkge1xuICB2YXIgX2V4dGVuZFN0YXRpY3MgPSBmdW5jdGlvbiBleHRlbmRTdGF0aWNzKGQsIGIpIHtcbiAgICBfZXh0ZW5kU3RhdGljcyA9IE9iamVjdC5zZXRQcm90b3R5cGVPZiB8fCB7XG4gICAgICBfX3Byb3RvX186IFtdXG4gICAgfSBpbnN0YW5jZW9mIEFycmF5ICYmIGZ1bmN0aW9uIChkLCBiKSB7XG4gICAgICBkLl9fcHJvdG9fXyA9IGI7XG4gICAgfSB8fCBmdW5jdGlvbiAoZCwgYikge1xuICAgICAgZm9yICh2YXIgcCBpbiBiKSB7XG4gICAgICAgIGlmIChPYmplY3QucHJvdG90eXBlLmhhc093blByb3BlcnR5LmNhbGwoYiwgcCkpIGRbcF0gPSBiW3BdO1xuICAgICAgfVxuICAgIH07XG5cbiAgICByZXR1cm4gX2V4dGVuZFN0YXRpY3MoZCwgYik7XG4gIH07XG5cbiAgcmV0dXJuIGZ1bmN0aW9uIChkLCBiKSB7XG4gICAgX2V4dGVuZFN0YXRpY3MoZCwgYik7XG5cbiAgICBmdW5jdGlvbiBfXygpIHtcbiAgICAgIHRoaXMuY29uc3RydWN0b3IgPSBkO1xuICAgIH1cblxuICAgIGQucHJvdG90eXBlID0gYiA9PT0gbnVsbCA/IE9iamVjdC5jcmVhdGUoYikgOiAoX18ucHJvdG90eXBlID0gYi5wcm90b3R5cGUsIG5ldyBfXygpKTtcbiAgfTtcbn0oKTtcblxuaW1wb3J0IFRpbGVJbWFnZSBmcm9tICcuL1RpbGVJbWFnZS5qcyc7XG5pbXBvcnQgeyBjcmVhdGVYWVosIGV4dGVudEZyb21Qcm9qZWN0aW9uIH0gZnJvbSAnLi4vdGlsZWdyaWQuanMnO1xuLyoqXG4gKiBAdHlwZWRlZiB7T2JqZWN0fSBPcHRpb25zXG4gKiBAcHJvcGVydHkge2ltcG9ydChcIi4vU291cmNlLmpzXCIpLkF0dHJpYnV0aW9uTGlrZX0gW2F0dHJpYnV0aW9uc10gQXR0cmlidXRpb25zLlxuICogQHByb3BlcnR5IHtib29sZWFufSBbYXR0cmlidXRpb25zQ29sbGFwc2libGU9dHJ1ZV0gQXR0cmlidXRpb25zIGFyZSBjb2xsYXBzaWJsZS5cbiAqIEBwcm9wZXJ0eSB7bnVtYmVyfSBbY2FjaGVTaXplXSBJbml0aWFsIHRpbGUgY2FjaGUgc2l6ZS4gV2lsbCBhdXRvLWdyb3cgdG8gaG9sZCBhdCBsZWFzdCB0aGUgbnVtYmVyIG9mIHRpbGVzIGluIHRoZSB2aWV3cG9ydC5cbiAqIEBwcm9wZXJ0eSB7bnVsbHxzdHJpbmd9IFtjcm9zc09yaWdpbl0gVGhlIGBjcm9zc09yaWdpbmAgYXR0cmlidXRlIGZvciBsb2FkZWQgaW1hZ2VzLiAgTm90ZSB0aGF0XG4gKiB5b3UgbXVzdCBwcm92aWRlIGEgYGNyb3NzT3JpZ2luYCB2YWx1ZSBpZiB5b3Ugd2FudCB0byBhY2Nlc3MgcGl4ZWwgZGF0YSB3aXRoIHRoZSBDYW52YXMgcmVuZGVyZXIuXG4gKiBTZWUgaHR0cHM6Ly9kZXZlbG9wZXIubW96aWxsYS5vcmcvZW4tVVMvZG9jcy9XZWIvSFRNTC9DT1JTX2VuYWJsZWRfaW1hZ2UgZm9yIG1vcmUgZGV0YWlsLlxuICogQHByb3BlcnR5IHtib29sZWFufSBbaW1hZ2VTbW9vdGhpbmc9dHJ1ZV0gRW5hYmxlIGltYWdlIHNtb290aGluZy5cbiAqIEBwcm9wZXJ0eSB7Ym9vbGVhbn0gW29wYXF1ZT1mYWxzZV0gV2hldGhlciB0aGUgbGF5ZXIgaXMgb3BhcXVlLlxuICogQHByb3BlcnR5IHtpbXBvcnQoXCIuLi9wcm9qLmpzXCIpLlByb2plY3Rpb25MaWtlfSBbcHJvamVjdGlvbj0nRVBTRzozODU3J10gUHJvamVjdGlvbi5cbiAqIEBwcm9wZXJ0eSB7bnVtYmVyfSBbcmVwcm9qZWN0aW9uRXJyb3JUaHJlc2hvbGQ9MC41XSBNYXhpbXVtIGFsbG93ZWQgcmVwcm9qZWN0aW9uIGVycm9yIChpbiBwaXhlbHMpLlxuICogSGlnaGVyIHZhbHVlcyBjYW4gaW5jcmVhc2UgcmVwcm9qZWN0aW9uIHBlcmZvcm1hbmNlLCBidXQgZGVjcmVhc2UgcHJlY2lzaW9uLlxuICogQHByb3BlcnR5IHtudW1iZXJ9IFttYXhab29tPTQyXSBPcHRpb25hbCBtYXggem9vbSBsZXZlbC4gTm90IHVzZWQgaWYgYHRpbGVHcmlkYCBpcyBwcm92aWRlZC5cbiAqIEBwcm9wZXJ0eSB7bnVtYmVyfSBbbWluWm9vbT0wXSBPcHRpb25hbCBtaW4gem9vbSBsZXZlbC4gTm90IHVzZWQgaWYgYHRpbGVHcmlkYCBpcyBwcm92aWRlZC5cbiAqIEBwcm9wZXJ0eSB7bnVtYmVyfSBbbWF4UmVzb2x1dGlvbl0gT3B0aW9uYWwgdGlsZSBncmlkIHJlc29sdXRpb24gYXQgbGV2ZWwgemVyby4gTm90IHVzZWQgaWYgYHRpbGVHcmlkYCBpcyBwcm92aWRlZC5cbiAqIEBwcm9wZXJ0eSB7aW1wb3J0KFwiLi4vdGlsZWdyaWQvVGlsZUdyaWQuanNcIikuZGVmYXVsdH0gW3RpbGVHcmlkXSBUaWxlIGdyaWQuXG4gKiBAcHJvcGVydHkge2ltcG9ydChcIi4uL1RpbGUuanNcIikuTG9hZEZ1bmN0aW9ufSBbdGlsZUxvYWRGdW5jdGlvbl0gT3B0aW9uYWwgZnVuY3Rpb24gdG8gbG9hZCBhIHRpbGUgZ2l2ZW4gYSBVUkwuIFRoZSBkZWZhdWx0IGlzXG4gKiBgYGBqc1xuICogZnVuY3Rpb24oaW1hZ2VUaWxlLCBzcmMpIHtcbiAqICAgaW1hZ2VUaWxlLmdldEltYWdlKCkuc3JjID0gc3JjO1xuICogfTtcbiAqIGBgYFxuICogQHByb3BlcnR5IHtudW1iZXJ9IFt0aWxlUGl4ZWxSYXRpbz0xXSBUaGUgcGl4ZWwgcmF0aW8gdXNlZCBieSB0aGUgdGlsZSBzZXJ2aWNlLlxuICogRm9yIGV4YW1wbGUsIGlmIHRoZSB0aWxlIHNlcnZpY2UgYWR2ZXJ0aXplcyAyNTZweCBieSAyNTZweCB0aWxlcyBidXQgYWN0dWFsbHkgc2VuZHMgNTEycHhcbiAqIGJ5IDUxMnB4IGltYWdlcyAoZm9yIHJldGluYS9oaWRwaSBkZXZpY2VzKSB0aGVuIGB0aWxlUGl4ZWxSYXRpb2BcbiAqIHNob3VsZCBiZSBzZXQgdG8gYDJgLlxuICogQHByb3BlcnR5IHtudW1iZXJ8aW1wb3J0KFwiLi4vc2l6ZS5qc1wiKS5TaXplfSBbdGlsZVNpemU9WzI1NiwgMjU2XV0gVGhlIHRpbGUgc2l6ZSB1c2VkIGJ5IHRoZSB0aWxlIHNlcnZpY2UuXG4gKiBOb3QgdXNlZCBpZiBgdGlsZUdyaWRgIGlzIHByb3ZpZGVkLlxuICogQHByb3BlcnR5IHtpbXBvcnQoXCIuLi9UaWxlLmpzXCIpLlVybEZ1bmN0aW9ufSBbdGlsZVVybEZ1bmN0aW9uXSBPcHRpb25hbCBmdW5jdGlvbiB0byBnZXRcbiAqIHRpbGUgVVJMIGdpdmVuIGEgdGlsZSBjb29yZGluYXRlIGFuZCB0aGUgcHJvamVjdGlvbi5cbiAqIFJlcXVpcmVkIGlmIGB1cmxgIG9yIGB1cmxzYCBhcmUgbm90IHByb3ZpZGVkLlxuICogQHByb3BlcnR5IHtzdHJpbmd9IFt1cmxdIFVSTCB0ZW1wbGF0ZS4gTXVzdCBpbmNsdWRlIGB7eH1gLCBge3l9YCBvciBgey15fWAsXG4gKiBhbmQgYHt6fWAgcGxhY2Vob2xkZXJzLiBBIGB7Py0/fWAgdGVtcGxhdGUgcGF0dGVybiwgZm9yIGV4YW1wbGUgYHN1YmRvbWFpbnthLWZ9LmRvbWFpbi5jb21gLFxuICogbWF5IGJlIHVzZWQgaW5zdGVhZCBvZiBkZWZpbmluZyBlYWNoIG9uZSBzZXBhcmF0ZWx5IGluIHRoZSBgdXJsc2Agb3B0aW9uLlxuICogQHByb3BlcnR5IHtBcnJheTxzdHJpbmc+fSBbdXJsc10gQW4gYXJyYXkgb2YgVVJMIHRlbXBsYXRlcy5cbiAqIEBwcm9wZXJ0eSB7Ym9vbGVhbn0gW3dyYXBYPXRydWVdIFdoZXRoZXIgdG8gd3JhcCB0aGUgd29ybGQgaG9yaXpvbnRhbGx5LlxuICogQHByb3BlcnR5IHtudW1iZXJ9IFt0cmFuc2l0aW9uPTI1MF0gRHVyYXRpb24gb2YgdGhlIG9wYWNpdHkgdHJhbnNpdGlvbiBmb3IgcmVuZGVyaW5nLlxuICogVG8gZGlzYWJsZSB0aGUgb3BhY2l0eSB0cmFuc2l0aW9uLCBwYXNzIGB0cmFuc2l0aW9uOiAwYC5cbiAqIEBwcm9wZXJ0eSB7bnVtYmVyfSBbekRpcmVjdGlvbj0wXSBJbmRpY2F0ZSB3aGljaCByZXNvbHV0aW9uIHNob3VsZCBiZSB1c2VkXG4gKiBieSBhIHJlbmRlcmVyIGlmIHRoZSB2aWV3IHJlc29sdXRpb24gZG9lcyBub3QgbWF0Y2ggYW55IHJlc29sdXRpb24gb2YgdGhlIHRpbGUgc291cmNlLlxuICogSWYgMCwgdGhlIG5lYXJlc3QgcmVzb2x1dGlvbiB3aWxsIGJlIHVzZWQuIElmIDEsIHRoZSBuZWFyZXN0IGxvd2VyIHJlc29sdXRpb25cbiAqIHdpbGwgYmUgdXNlZC4gSWYgLTEsIHRoZSBuZWFyZXN0IGhpZ2hlciByZXNvbHV0aW9uIHdpbGwgYmUgdXNlZC5cbiAqL1xuXG4vKipcbiAqIEBjbGFzc2Rlc2NcbiAqIExheWVyIHNvdXJjZSBmb3IgdGlsZSBkYXRhIHdpdGggVVJMcyBpbiBhIHNldCBYWVogZm9ybWF0IHRoYXQgYXJlXG4gKiBkZWZpbmVkIGluIGEgVVJMIHRlbXBsYXRlLiBCeSBkZWZhdWx0LCB0aGlzIGZvbGxvd3MgdGhlIHdpZGVseS11c2VkXG4gKiBHb29nbGUgZ3JpZCB3aGVyZSBgeGAgMCBhbmQgYHlgIDAgYXJlIGluIHRoZSB0b3AgbGVmdC4gR3JpZHMgbGlrZVxuICogVE1TIHdoZXJlIGB4YCAwIGFuZCBgeWAgMCBhcmUgaW4gdGhlIGJvdHRvbSBsZWZ0IGNhbiBiZSB1c2VkIGJ5XG4gKiB1c2luZyB0aGUgYHsteX1gIHBsYWNlaG9sZGVyIGluIHRoZSBVUkwgdGVtcGxhdGUsIHNvIGxvbmcgYXMgdGhlXG4gKiBzb3VyY2UgZG9lcyBub3QgaGF2ZSBhIGN1c3RvbSB0aWxlIGdyaWQuIEluIHRoaXMgY2FzZVxuICogYSBgdGlsZVVybEZ1bmN0aW9uYCBjYW4gYmUgdXNlZCwgc3VjaCBhczpcbiAqIGBgYGpzXG4gKiAgdGlsZVVybEZ1bmN0aW9uOiBmdW5jdGlvbihjb29yZGluYXRlKSB7XG4gKiAgICByZXR1cm4gJ2h0dHA6Ly9tYXBzZXJ2ZXIuY29tLycgKyBjb29yZGluYXRlWzBdICsgJy8nICtcbiAqICAgICAgY29vcmRpbmF0ZVsxXSArICcvJyArICgtY29vcmRpbmF0ZVsyXSAtIDEpICsgJy5wbmcnO1xuICogIH1cbiAqIGBgYFxuICogQGFwaVxuICovXG5cbnZhciBYWVogPVxuLyoqIEBjbGFzcyAqL1xuZnVuY3Rpb24gKF9zdXBlcikge1xuICBfX2V4dGVuZHMoWFlaLCBfc3VwZXIpO1xuICAvKipcbiAgICogQHBhcmFtIHtPcHRpb25zPX0gb3B0X29wdGlvbnMgWFlaIG9wdGlvbnMuXG4gICAqL1xuXG5cbiAgZnVuY3Rpb24gWFlaKG9wdF9vcHRpb25zKSB7XG4gICAgdmFyIF90aGlzID0gdGhpcztcblxuICAgIHZhciBvcHRpb25zID0gb3B0X29wdGlvbnMgfHwge307XG4gICAgdmFyIHByb2plY3Rpb24gPSBvcHRpb25zLnByb2plY3Rpb24gIT09IHVuZGVmaW5lZCA/IG9wdGlvbnMucHJvamVjdGlvbiA6ICdFUFNHOjM4NTcnO1xuICAgIHZhciB0aWxlR3JpZCA9IG9wdGlvbnMudGlsZUdyaWQgIT09IHVuZGVmaW5lZCA/IG9wdGlvbnMudGlsZUdyaWQgOiBjcmVhdGVYWVooe1xuICAgICAgZXh0ZW50OiBleHRlbnRGcm9tUHJvamVjdGlvbihwcm9qZWN0aW9uKSxcbiAgICAgIG1heFJlc29sdXRpb246IG9wdGlvbnMubWF4UmVzb2x1dGlvbixcbiAgICAgIG1heFpvb206IG9wdGlvbnMubWF4Wm9vbSxcbiAgICAgIG1pblpvb206IG9wdGlvbnMubWluWm9vbSxcbiAgICAgIHRpbGVTaXplOiBvcHRpb25zLnRpbGVTaXplXG4gICAgfSk7XG4gICAgX3RoaXMgPSBfc3VwZXIuY2FsbCh0aGlzLCB7XG4gICAgICBhdHRyaWJ1dGlvbnM6IG9wdGlvbnMuYXR0cmlidXRpb25zLFxuICAgICAgY2FjaGVTaXplOiBvcHRpb25zLmNhY2hlU2l6ZSxcbiAgICAgIGNyb3NzT3JpZ2luOiBvcHRpb25zLmNyb3NzT3JpZ2luLFxuICAgICAgaW1hZ2VTbW9vdGhpbmc6IG9wdGlvbnMuaW1hZ2VTbW9vdGhpbmcsXG4gICAgICBvcGFxdWU6IG9wdGlvbnMub3BhcXVlLFxuICAgICAgcHJvamVjdGlvbjogcHJvamVjdGlvbixcbiAgICAgIHJlcHJvamVjdGlvbkVycm9yVGhyZXNob2xkOiBvcHRpb25zLnJlcHJvamVjdGlvbkVycm9yVGhyZXNob2xkLFxuICAgICAgdGlsZUdyaWQ6IHRpbGVHcmlkLFxuICAgICAgdGlsZUxvYWRGdW5jdGlvbjogb3B0aW9ucy50aWxlTG9hZEZ1bmN0aW9uLFxuICAgICAgdGlsZVBpeGVsUmF0aW86IG9wdGlvbnMudGlsZVBpeGVsUmF0aW8sXG4gICAgICB0aWxlVXJsRnVuY3Rpb246IG9wdGlvbnMudGlsZVVybEZ1bmN0aW9uLFxuICAgICAgdXJsOiBvcHRpb25zLnVybCxcbiAgICAgIHVybHM6IG9wdGlvbnMudXJscyxcbiAgICAgIHdyYXBYOiBvcHRpb25zLndyYXBYICE9PSB1bmRlZmluZWQgPyBvcHRpb25zLndyYXBYIDogdHJ1ZSxcbiAgICAgIHRyYW5zaXRpb246IG9wdGlvbnMudHJhbnNpdGlvbixcbiAgICAgIGF0dHJpYnV0aW9uc0NvbGxhcHNpYmxlOiBvcHRpb25zLmF0dHJpYnV0aW9uc0NvbGxhcHNpYmxlLFxuICAgICAgekRpcmVjdGlvbjogb3B0aW9ucy56RGlyZWN0aW9uXG4gICAgfSkgfHwgdGhpcztcbiAgICByZXR1cm4gX3RoaXM7XG4gIH1cblxuICByZXR1cm4gWFlaO1xufShUaWxlSW1hZ2UpO1xuXG5leHBvcnQgZGVmYXVsdCBYWVo7IiwiLy8gZXh0cmFjdGVkIGJ5IG1pbmktY3NzLWV4dHJhY3QtcGx1Z2luXG5leHBvcnQgdmFyIG1hcENvbnRhaW5lciA9IFwibWFwLW1vZHVsZS0tbWFwQ29udGFpbmVyLS0zekJpdVwiOyIsImltcG9ydCBSZWFjdCwge3VzZVN0YXRlLCB1c2VFZmZlY3QsIHVzZVJlZn0gZnJvbSAncmVhY3QnO1xuaW1wb3J0IE1hcCBmcm9tICdvbC9NYXAnO1xuaW1wb3J0IFZpZXcgZnJvbSAnb2wvVmlldyc7XG5pbXBvcnQgRmVhdHVyZSBmcm9tICdvbC9GZWF0dXJlJztcbmltcG9ydCBHZW9tZXRyeSBmcm9tICdvbC9nZW9tL0dlb21ldHJ5JztcbmltcG9ydCBUaWxlTGF5ZXIgZnJvbSAnb2wvbGF5ZXIvVGlsZSc7XG5pbXBvcnQgVmVjdG9yTGF5ZXIgZnJvbSAnb2wvbGF5ZXIvVmVjdG9yJztcbmltcG9ydCBWZWN0b3JUaWxlU291cmNlIGZyb20gJ29sL3NvdXJjZS9WZWN0b3JUaWxlJztcbmltcG9ydCBWZWN0b3JUaWxlTGF5ZXIgZnJvbSAnb2wvbGF5ZXIvVmVjdG9yVGlsZSc7XG5pbXBvcnQgTVZUIGZyb20gJ29sL2Zvcm1hdC9NVlQnO1xuaW1wb3J0IFZlY3RvclNvdXJjZSBmcm9tICdvbC9zb3VyY2UvVmVjdG9yJztcbmltcG9ydCBYWVogZnJvbSAnb2wvc291cmNlL1hZWic7XG5pbXBvcnQge2Zyb21Mb25MYXR9IGZyb20gJ29sL3Byb2onO1xuaW1wb3J0ICogYXMgc3R5bGVzIGZyb20gJy4vbWFwLm1vZHVsZS5zY3NzJztcblxuXG5pbnRlcmZhY2UgSU1hcFdyYXBwZXJQcm9wcyB7XG4gIGZlYXR1cmVzOiBGZWF0dXJlPEdlb21ldHJ5PltdLFxufTtcblxuLy8gVGhlIGJlbG93IGFkYXB0ZWQgZnJvbVxuLy8gaHR0cHM6Ly90YXlsb3IuY2FsbHNlbi5tZS91c2luZy1vcGVubGF5ZXJzLXdpdGgtcmVhY3QtZnVuY3Rpb25hbC1jb21wb25lbnRzL1xuY29uc3QgTWFwV3JhcHBlciA9ICh7ZmVhdHVyZXN9OiBJTWFwV3JhcHBlclByb3BzKSA9PiB7XG4gIGNvbnN0IFttYXAsIHNldE1hcF0gPSB1c2VTdGF0ZTxNYXA+KCk7XG4gIGNvbnN0IFtmZWF0dXJlc0xheWVyLCBzZXRGZWF0dXJlc0xheWVyXSA9IHVzZVN0YXRlPFZlY3RvckxheWVyPigpO1xuXG4gIGNvbnN0IG1hcEVsZW1lbnQgPSB1c2VSZWYoKSBhc1xuICAgICAgICBSZWFjdC5NdXRhYmxlUmVmT2JqZWN0PEhUTUxJbnB1dEVsZW1lbnQ+O1xuXG4gIHVzZUVmZmVjdCggKCkgPT4ge1xuICAgIGNvbnN0IGluaXRhbEZlYXR1cmVzTGF5ZXIgPSBuZXcgVmVjdG9yVGlsZUxheWVyKHtcbiAgICAgIHNvdXJjZTogbmV3IFZlY3RvclRpbGVTb3VyY2Uoe1xuICAgICAgICBmb3JtYXQ6IG5ldyBNVlQoKSxcbiAgICAgICAgdXJsOiAnaHR0cHM6Ly9naXMuZGF0YS5jZW5zdXMuZ292L2FyY2dpcy9yZXN0L3NlcnZpY2VzL0hvc3RlZC9WVF8yMDE5XzE1MF8wMF9QWV9EMS9WZWN0b3JUaWxlU2VydmVyL3RpbGUve3p9L3t5fS97eH0ubXZ0JyxcbiAgICAgIH0pLFxuICAgIH0pO1xuXG4gICAgY29uc3QgaW5pdGlhbE1hcCA9IG5ldyBNYXAoe1xuICAgICAgdGFyZ2V0OiBtYXBFbGVtZW50LmN1cnJlbnQsXG4gICAgICBsYXllcnM6IFtcblxuICAgICAgICBuZXcgVGlsZUxheWVyKHtcbiAgICAgICAgICBzb3VyY2U6IG5ldyBYWVooe1xuICAgICAgICAgICAgdXJsOiAnaHR0cHM6Ly97MS00fS5iYXNlbWFwcy5jYXJ0b2Nkbi5jb20vbGlnaHRfYWxsL3t6fS97eH0ve3l9QDJ4LnBuZycsXG4gICAgICAgICAgfSksXG4gICAgICAgIH0pLFxuICAgICAgICBpbml0YWxGZWF0dXJlc0xheWVyLFxuICAgICAgXSxcbiAgICAgIHZpZXc6IG5ldyBWaWV3KHtcbiAgICAgICAgcHJvamVjdGlvbjogJ0VQU0c6Mzg1NycsXG4gICAgICAgIGNlbnRlcjogZnJvbUxvbkxhdChbLTk1LjcxMjksIDM3LjA5MDJdKSwgLy8gWzM3LjA5MDIsIDk1LjcxMjldLFxuICAgICAgICB6b29tOiAzLFxuICAgICAgfSksXG4gICAgICBjb250cm9sczogW10sXG4gICAgfSk7XG5cbiAgICBzZXRNYXAoaW5pdGlhbE1hcCk7XG4gICAgc2V0RmVhdHVyZXNMYXllcihpbml0YWxGZWF0dXJlc0xheWVyKTtcbiAgfSwgW10pO1xuXG5cbiAgLy8gdXBkYXRlIG1hcCBpZiBmZWF0dXJlcyBwcm9wIGNoYW5nZXNcbiAgdXNlRWZmZWN0KCAoKSA9PiB7XG4gICAgaWYgKGZlYXR1cmVzLmxlbmd0aCkgeyAvLyBtYXkgYmUgZW1wdHkgb24gZmlyc3QgcmVuZGVyXG4gICAgICAvLyBzZXQgZmVhdHVyZXMgdG8gbWFwXG4gICAgICBmZWF0dXJlc0xheWVyPy5zZXRTb3VyY2UoXG4gICAgICAgICAgbmV3IFZlY3RvclNvdXJjZSh7XG4gICAgICAgICAgICBmZWF0dXJlczogZmVhdHVyZXMsXG4gICAgICAgICAgfSksXG4gICAgICApO1xuICAgICAgY29uc3QgZXh0ZW50ID0gZmVhdHVyZXNMYXllcj8uZ2V0U291cmNlKCkuZ2V0RXh0ZW50KCk7XG4gICAgICBpZiAoZXh0ZW50ICE9IG51bGwpIHtcbiAgICAgICAgLy8gZml0IG1hcCB0byBmZWF0dXJlIGV4dGVudCAod2l0aCAxMDBweCBvZiBwYWRkaW5nKVxuICAgICAgICBtYXA/LmdldFZpZXcoKS5maXQoZXh0ZW50LCB7XG4gICAgICAgICAgcGFkZGluZzogWzEwMCwgMTAwLCAxMDAsIDEwMF0sXG4gICAgICAgIH0pO1xuICAgICAgfVxuICAgIH1cbiAgfSwgW2ZlYXR1cmVzXSk7XG5cbiAgcmV0dXJuIChcbiAgICA8ZGl2IHJlZj17bWFwRWxlbWVudH0gY2xhc3NOYW1lPXtzdHlsZXMubWFwQ29udGFpbmVyfT48L2Rpdj5cbiAgKTtcbn07XG5cbmV4cG9ydCBkZWZhdWx0IE1hcFdyYXBwZXI7XG4iLCIvLyBleHRyYWN0ZWQgYnkgbWluaS1jc3MtZXh0cmFjdC1wbHVnaW5cbmV4cG9ydCB2YXIgbWFwQ29udHJvbENvbnRhaW5lciA9IFwibWFwQ29udHJvbHMtbW9kdWxlLS1tYXBDb250cm9sQ29udGFpbmVyLS0yd0V3elwiOyIsImltcG9ydCBSZWFjdCBmcm9tICdyZWFjdCc7XG5pbXBvcnQge0J1dHRvbiwgQnV0dG9uR3JvdXB9IGZyb20gJ0B0cnVzc3dvcmtzL3JlYWN0LXVzd2RzJztcbmltcG9ydCBGZWF0dXJlIGZyb20gJ29sL0ZlYXR1cmUnO1xuaW1wb3J0IEdlb21ldHJ5IGZyb20gJ29sL2dlb20vR2VvbWV0cnknO1xuaW1wb3J0ICogYXMgc3R5bGVzIGZyb20gJy4vbWFwQ29udHJvbHMubW9kdWxlLnNjc3MnO1xuXG5pbnRlcmZhY2UgSU1hcENvbnRyb2xzUHJvcHMge1xuICBzZXRGZWF0dXJlczogKGFyZzA6IEZlYXR1cmU8R2VvbWV0cnk+W10pID0+IHZvaWQ7XG59XG5cbmNvbnN0IE1hcENvbnRyb2xzID0gKHtzZXRGZWF0dXJlc306IElNYXBDb250cm9sc1Byb3BzKSA9PiB7XG4gIHJldHVybiAoXG4gICAgPD5cbiAgICAgIDxkaXYgY2xhc3NOYW1lPXtzdHlsZXMubWFwQ29udHJvbENvbnRhaW5lcn0+XG4gICAgICAgIDxoMj5FeHBsb3JlIHRoZSBUb29sPC9oMj5cbiAgICAgICAgPEJ1dHRvbkdyb3VwIHR5cGU9XCJzZWdtZW50ZWRcIj5cbiAgICAgICAgICA8QnV0dG9uIHR5cGU9XCJidXR0b25cIj5Db21iaW5lZDwvQnV0dG9uPlxuICAgICAgICAgIDxCdXR0b24gdHlwZT1cImJ1dHRvblwiIG91dGxpbmU9e3RydWV9PlBvdmVydHk8L0J1dHRvbj5cbiAgICAgICAgICA8QnV0dG9uIHR5cGU9XCJidXR0b25cIiBvdXRsaW5lPXt0cnVlfT5MaW5ndWlzdGljIElzb2xhdGlvbjwvQnV0dG9uPlxuICAgICAgICA8L0J1dHRvbkdyb3VwPlxuICAgICAgPC9kaXY+XG4gICAgPC8+XG4gICk7XG59O1xuXG5leHBvcnQgZGVmYXVsdCBNYXBDb250cm9scztcbiIsIi8vIGV4dHJhY3RlZCBieSBtaW5pLWNzcy1leHRyYWN0LXBsdWdpblxuZXhwb3J0IHZhciBob3dZb3VDYW5IZWxwQ29udGFpbmVyID0gXCJIb3dZb3VDYW5IZWxwLW1vZHVsZS0taG93WW91Q2FuSGVscENvbnRhaW5lci0tMmtxQmFcIjsiLCJpbXBvcnQgUmVhY3QgZnJvbSAncmVhY3QnO1xuaW1wb3J0ICogYXMgc3R5bGVzIGZyb20gJy4vSG93WW91Q2FuSGVscC5tb2R1bGUuc2Nzcyc7XG5cbmNvbnN0IEhvd1lvdUNhbkhlbHAgPSAoKSA9PiB7XG4gIHJldHVybiAoXG4gICAgPGRpdiBjbGFzc05hbWU9e3N0eWxlcy5ob3dZb3VDYW5IZWxwQ29udGFpbmVyfT5cbiAgICAgIDxoMj5Ib3cgWW91IENhbiBIZWxwIEltcHJvdmUgdGhlIFRvb2w8L2gyPlxuICAgICAgPHVsPlxuICAgICAgICA8bGk+SWYgeW91IGhhdmUgaW5mb3JtYXRpb24gdGhhdCBjb3VsZCBoZWxwLCB3ZeKAmWQgbG92ZSB0byBoZWFyIGZyb20geW91LjwvbGk+XG4gICAgICAgIDxsaT5WaWV3IG91ciBmdWxsIHNldCBvZiBkYXRhIHNvdXJjZXMgYW5kIG1ldGhvZG9sb2d5XG4gICAgICAgICAgICB3aGVyZSB5b3UgY2FuIGFkZCBvciBkb3dubG9hZCBzb3VyY2VzIGFuZCBjaGVjayBzdGF0dXNlcyBvbiBvdXIgZGF0YSByb2FkbWFwLjwvbGk+XG4gICAgICAgIDxsaT5DaGVjayBvdXQgb3VyIHRpbWVsaW5lIGFuZCBzZW5kIGZlZWRiYWNrIG9yIGF0dGVuZCByZWxldmFudCBldmVudHMuPC9saT5cbiAgICAgICAgPGxpPkNvbnRhY3QgdXMgYW5kIHNoYXJlIHRoZSBzdG9yaWVzIG9mIHlvdXIgY29tbXVuaXR5LjwvbGk+XG4gICAgICA8L3VsPlxuICAgIDwvZGl2PlxuICApO1xufTtcblxuZXhwb3J0IGRlZmF1bHQgSG93WW91Q2FuSGVscDtcbiIsIi8vIGV4dHJhY3RlZCBieSBtaW5pLWNzcy1leHRyYWN0LXBsdWdpblxuZXhwb3J0IHZhciBkaXNjbGFpbWVyID0gXCJjZWpzdC1tb2R1bGUtLWRpc2NsYWltZXItLTNMQzF5XCI7IiwiaW1wb3J0IFJlYWN0LCB7dXNlU3RhdGV9IGZyb20gJ3JlYWN0JztcbmltcG9ydCBMYXlvdXQgZnJvbSAnLi4vY29tcG9uZW50cy9sYXlvdXQnO1xuaW1wb3J0IE1hcFdyYXBwZXIgZnJvbSAnLi4vY29tcG9uZW50cy9tYXAnO1xuaW1wb3J0IE1hcENvbnRyb2xzIGZyb20gJy4uL2NvbXBvbmVudHMvbWFwQ29udHJvbHMnO1xuaW1wb3J0IEhvd1lvdUNhbkhlbHAgZnJvbSAnLi4vY29tcG9uZW50cy9Ib3dZb3VDYW5IZWxwJztcbmltcG9ydCBGZWF0dXJlIGZyb20gJ29sL0ZlYXR1cmUnO1xuaW1wb3J0IEdlb21ldHJ5IGZyb20gJ29sL2dlb20vR2VvbWV0cnknO1xuaW1wb3J0IHtBbGVydH0gZnJvbSAnQHRydXNzd29ya3MvcmVhY3QtdXN3ZHMnO1xuaW1wb3J0ICogYXMgc3R5bGVzIGZyb20gJy4vY2Vqc3QubW9kdWxlLnNjc3MnO1xuXG5cbmludGVyZmFjZSBJTWFwUGFnZVByb3BzIHtcbiAgbG9jYXRpb246IExvY2F0aW9uO1xufTtcblxuY29uc3QgQ0VKU1RQYWdlID0gKHtsb2NhdGlvbn06IElNYXBQYWdlUHJvcHMpID0+IHtcbiAgY29uc3QgW2ZlYXR1cmVzLCBzZXRGZWF0dXJlc10gPSB1c2VTdGF0ZTxGZWF0dXJlPEdlb21ldHJ5PltdPihbXSk7XG4gIHJldHVybiAoXG4gICAgPExheW91dCBsb2NhdGlvbj17bG9jYXRpb259PlxuICAgICAgPG1haW4gaWQ9XCJtYWluLWNvbnRlbnRcIiByb2xlPVwibWFpblwiPlxuICAgICAgICA8cCBjbGFzc05hbWU9e3N0eWxlcy5kaXNjbGFpbWVyfT5cbiAgICAgICAgICBUaGUgQ2xpbWF0ZSBhbmQgRWNvbm9taWMgSnVzdGljZSBTY3JlZW5pbmcgVG9vbCBoZWxwc1xuICAgICAgICAgIGlkZW50aWZ5IGFuZCBwcmlvcml0aXplIGNvbW11bml0aWVzIGFjcm9zcyB0aGUgVW5pdGVkXG4gICAgICAgICAgU3RhdGVzIGFuZCBVUyB0ZXJyaXRvcmllcyB0aGF0IGhhdmUgYmVlbiBoaXN0b3JpY2FsbHlcbiAgICAgICAgICBvdmVyYnVyZGVuZWQgYW5kIHVuZGVyc2VydmVkIHNvIHRoYXQgdGhleSBtYXkgcmVjZWl2ZVxuICAgICAgICAgIDQwJSBvZiB0aGUgYmVuZWZpdHMgZnJvbSBpbnZlc3RtZW50cyBpbiBzaXgga2V5IGFyZWFzIGFzXG4gICAgICAgICAgb3V0bGluZWQgaW4gdGhlIDxhXG4gICAgICAgICAgICBocmVmPXsnaHR0cHM6Ly93d3cud2hpdGVob3VzZS5nb3YvYnJpZWZpbmctcm9vbS8nICtcbiAgICAgICAgICAgICAgICAgICAgJ3ByZXNpZGVudGlhbC1hY3Rpb25zLzIwMjEvMDEvMjcvJyArXG4gICAgICAgICAgICAgICAgICAgICdleGVjdXRpdmUtb3JkZXItb24tdGFja2xpbmctdGhlLWNsaW1hdGUtJyArXG4gICAgICAgICAgICAgICAgICAgICdjcmlzaXMtYXQtaG9tZS1hbmQtYWJyb2FkLyd9XG4gICAgICAgICAgICB0YXJnZXQ9eydfYmxhbmsnfVxuICAgICAgICAgICAgcmVsPXsnbm9yZWZlcnJlcid9PlxuICAgICAgICAgICAgICAgICAgICBFeGVjdXRpdmUgT3JkZXIgb24gVGFja2xpbmcgdGhlIENsaW1hdGUgQ3Jpc2lzIGF0IEhvbWUgYW5kXG4gICAgICAgICAgICAgICAgICAgIEFicm9hZDwvYT4uXG4gICAgICAgICAgRXhwbG9yZSB0aGUgbWFwIGJlbG93IG9yIGxlYXJuXG4gICAgICAgICAgbW9yZSBhYm91dCB0aGUgbWV0aG9kb2xvZ3kgYW5kIGRhdGEgaW5kaWNhdG9ycyB1c2VkIHRvXG4gICAgICAgICAgcHJpb3JpdGl6ZSBKdXN0aWNlNDAgY29tbXVuaXRpZXMuXG4gICAgICAgIDwvcD5cbiAgICAgICAgPEFsZXJ0XG4gICAgICAgICAgdHlwZT1cIndhcm5pbmdcIlxuICAgICAgICAgIGhlYWRpbmc9XCJMaW1pdGVkIERhdGEgU291cmNlc1wiPlxuICAgICAgICAgIDxwPlxuICAgICAgICAgICAgSW4gdGhpcyB0b29sLCB3ZSBhcmUgdXNpbmcgZGF0YSBzb3VyY2VzIHRoYXQgb3VyXG4gICAgICAgICAgICBjb21iaW5lZCBieSBvdXIgY3VtbXVsYXRpdmUgaW1wYWN0IG1ldGhvZG9sb2d5LlxuICAgICAgICAgICAgT3VyIHNvdXJjZXMgd2VyZSBzZWxlY3RlZCBiZWNhdXNlIHNpdCBhbWV0LFxuICAgICAgICAgICAgY29uc2VjdGV0dXIgYWRpcGlzY2luZy4gU2VlIGFsbCB0aGUgc291cmNlcyB3ZVxuICAgICAgICAgICAgYXJlIGludmVzdGlnYXRpbmcgb24gb3VyIGRhdGEgcm9hZG1hcC5cbiAgICAgICAgICA8L3A+XG4gICAgICAgIDwvQWxlcnQ+XG4gICAgICAgIDxNYXBDb250cm9scyBzZXRGZWF0dXJlcz17c2V0RmVhdHVyZXN9Lz5cbiAgICAgICAgPE1hcFdyYXBwZXIgZmVhdHVyZXM9e2ZlYXR1cmVzfSAvPlxuICAgICAgICA8SG93WW91Q2FuSGVscCAvPlxuICAgICAgPC9tYWluPlxuICAgIDwvTGF5b3V0PlxuICApO1xufTtcblxuZXhwb3J0IGRlZmF1bHQgQ0VKU1RQYWdlO1xuIl0sInNvdXJjZVJvb3QiOiIifQ==\n//# sourceURL=webpack-internal:///9682\n')}}]); |