UNPKG

@react-three/cannon

Version:
514 lines (432 loc) 799 kB
import { useFrame, useThree } from '@react-three/fiber'; import { MeshBasicMaterial, SphereGeometry, BoxGeometry, PlaneGeometry, Mesh, CylinderGeometry, BufferGeometry, Float32BufferAttribute, Quaternion as Quaternion$2, Vector3, Matrix4, Scene, InstancedMesh, Object3D, Euler, MathUtils, DynamicDrawUsage } from 'three'; import { createContext, useContext, useState, useRef, useMemo, useEffect, useLayoutEffect, useCallback } from 'react'; import { jsxs, jsx } from 'react/jsx-runtime'; var events = {exports: {}}; var R = typeof Reflect === 'object' ? Reflect : null; var ReflectApply = R && typeof R.apply === 'function' ? R.apply : function ReflectApply(target, receiver, args) { return Function.prototype.apply.call(target, receiver, args); }; var ReflectOwnKeys; if (R && typeof R.ownKeys === 'function') { ReflectOwnKeys = R.ownKeys; } else if (Object.getOwnPropertySymbols) { ReflectOwnKeys = function ReflectOwnKeys(target) { return Object.getOwnPropertyNames(target) .concat(Object.getOwnPropertySymbols(target)); }; } else { ReflectOwnKeys = function ReflectOwnKeys(target) { return Object.getOwnPropertyNames(target); }; } function ProcessEmitWarning(warning) { if (console && console.warn) console.warn(warning); } var NumberIsNaN = Number.isNaN || function NumberIsNaN(value) { return value !== value; }; function EventEmitter() { EventEmitter.init.call(this); } events.exports = EventEmitter; events.exports.once = once; // Backwards-compat with node 0.10.x EventEmitter.EventEmitter = EventEmitter; EventEmitter.prototype._events = undefined; EventEmitter.prototype._eventsCount = 0; EventEmitter.prototype._maxListeners = undefined; // By default EventEmitters will print a warning if more than 10 listeners are // added to it. This is a useful default which helps finding memory leaks. var defaultMaxListeners = 10; function checkListener(listener) { if (typeof listener !== 'function') { throw new TypeError('The "listener" argument must be of type Function. Received type ' + typeof listener); } } Object.defineProperty(EventEmitter, 'defaultMaxListeners', { enumerable: true, get: function() { return defaultMaxListeners; }, set: function(arg) { if (typeof arg !== 'number' || arg < 0 || NumberIsNaN(arg)) { throw new RangeError('The value of "defaultMaxListeners" is out of range. It must be a non-negative number. Received ' + arg + '.'); } defaultMaxListeners = arg; } }); EventEmitter.init = function() { if (this._events === undefined || this._events === Object.getPrototypeOf(this)._events) { this._events = Object.create(null); this._eventsCount = 0; } this._maxListeners = this._maxListeners || undefined; }; // Obviously not all Emitters should be limited to 10. This function allows // that to be increased. Set to zero for unlimited. EventEmitter.prototype.setMaxListeners = function setMaxListeners(n) { if (typeof n !== 'number' || n < 0 || NumberIsNaN(n)) { throw new RangeError('The value of "n" is out of range. It must be a non-negative number. Received ' + n + '.'); } this._maxListeners = n; return this; }; function _getMaxListeners(that) { if (that._maxListeners === undefined) return EventEmitter.defaultMaxListeners; return that._maxListeners; } EventEmitter.prototype.getMaxListeners = function getMaxListeners() { return _getMaxListeners(this); }; EventEmitter.prototype.emit = function emit(type) { var args = []; for (var i = 1; i < arguments.length; i++) args.push(arguments[i]); var doError = (type === 'error'); var events = this._events; if (events !== undefined) doError = (doError && events.error === undefined); else if (!doError) return false; // If there is no 'error' event listener then throw. if (doError) { var er; if (args.length > 0) er = args[0]; if (er instanceof Error) { // Note: The comments on the `throw` lines are intentional, they show // up in Node's output if this results in an unhandled exception. throw er; // Unhandled 'error' event } // At least give some kind of context to the user var err = new Error('Unhandled error.' + (er ? ' (' + er.message + ')' : '')); err.context = er; throw err; // Unhandled 'error' event } var handler = events[type]; if (handler === undefined) return false; if (typeof handler === 'function') { ReflectApply(handler, this, args); } else { var len = handler.length; var listeners = arrayClone(handler, len); for (var i = 0; i < len; ++i) ReflectApply(listeners[i], this, args); } return true; }; function _addListener(target, type, listener, prepend) { var m; var events; var existing; checkListener(listener); events = target._events; if (events === undefined) { events = target._events = Object.create(null); target._eventsCount = 0; } else { // To avoid recursion in the case that type === "newListener"! Before // adding it to the listeners, first emit "newListener". if (events.newListener !== undefined) { target.emit('newListener', type, listener.listener ? listener.listener : listener); // Re-assign `events` because a newListener handler could have caused the // this._events to be assigned to a new object events = target._events; } existing = events[type]; } if (existing === undefined) { // Optimize the case of one listener. Don't need the extra array object. existing = events[type] = listener; ++target._eventsCount; } else { if (typeof existing === 'function') { // Adding the second element, need to change to array. existing = events[type] = prepend ? [listener, existing] : [existing, listener]; // If we've already got an array, just append. } else if (prepend) { existing.unshift(listener); } else { existing.push(listener); } // Check for listener leak m = _getMaxListeners(target); if (m > 0 && existing.length > m && !existing.warned) { existing.warned = true; // No error code for this since it is a Warning // eslint-disable-next-line no-restricted-syntax var w = new Error('Possible EventEmitter memory leak detected. ' + existing.length + ' ' + String(type) + ' listeners ' + 'added. Use emitter.setMaxListeners() to ' + 'increase limit'); w.name = 'MaxListenersExceededWarning'; w.emitter = target; w.type = type; w.count = existing.length; ProcessEmitWarning(w); } } return target; } EventEmitter.prototype.addListener = function addListener(type, listener) { return _addListener(this, type, listener, false); }; EventEmitter.prototype.on = EventEmitter.prototype.addListener; EventEmitter.prototype.prependListener = function prependListener(type, listener) { return _addListener(this, type, listener, true); }; function onceWrapper() { if (!this.fired) { this.target.removeListener(this.type, this.wrapFn); this.fired = true; if (arguments.length === 0) return this.listener.call(this.target); return this.listener.apply(this.target, arguments); } } function _onceWrap(target, type, listener) { var state = { fired: false, wrapFn: undefined, target: target, type: type, listener: listener }; var wrapped = onceWrapper.bind(state); wrapped.listener = listener; state.wrapFn = wrapped; return wrapped; } EventEmitter.prototype.once = function once(type, listener) { checkListener(listener); this.on(type, _onceWrap(this, type, listener)); return this; }; EventEmitter.prototype.prependOnceListener = function prependOnceListener(type, listener) { checkListener(listener); this.prependListener(type, _onceWrap(this, type, listener)); return this; }; // Emits a 'removeListener' event if and only if the listener was removed. EventEmitter.prototype.removeListener = function removeListener(type, listener) { var list, events, position, i, originalListener; checkListener(listener); events = this._events; if (events === undefined) return this; list = events[type]; if (list === undefined) return this; if (list === listener || list.listener === listener) { if (--this._eventsCount === 0) this._events = Object.create(null); else { delete events[type]; if (events.removeListener) this.emit('removeListener', type, list.listener || listener); } } else if (typeof list !== 'function') { position = -1; for (i = list.length - 1; i >= 0; i--) { if (list[i] === listener || list[i].listener === listener) { originalListener = list[i].listener; position = i; break; } } if (position < 0) return this; if (position === 0) list.shift(); else { spliceOne(list, position); } if (list.length === 1) events[type] = list[0]; if (events.removeListener !== undefined) this.emit('removeListener', type, originalListener || listener); } return this; }; EventEmitter.prototype.off = EventEmitter.prototype.removeListener; EventEmitter.prototype.removeAllListeners = function removeAllListeners(type) { var listeners, events, i; events = this._events; if (events === undefined) return this; // not listening for removeListener, no need to emit if (events.removeListener === undefined) { if (arguments.length === 0) { this._events = Object.create(null); this._eventsCount = 0; } else if (events[type] !== undefined) { if (--this._eventsCount === 0) this._events = Object.create(null); else delete events[type]; } return this; } // emit removeListener for all listeners on all events if (arguments.length === 0) { var keys = Object.keys(events); var key; for (i = 0; i < keys.length; ++i) { key = keys[i]; if (key === 'removeListener') continue; this.removeAllListeners(key); } this.removeAllListeners('removeListener'); this._events = Object.create(null); this._eventsCount = 0; return this; } listeners = events[type]; if (typeof listeners === 'function') { this.removeListener(type, listeners); } else if (listeners !== undefined) { // LIFO order for (i = listeners.length - 1; i >= 0; i--) { this.removeListener(type, listeners[i]); } } return this; }; function _listeners(target, type, unwrap) { var events = target._events; if (events === undefined) return []; var evlistener = events[type]; if (evlistener === undefined) return []; if (typeof evlistener === 'function') return unwrap ? [evlistener.listener || evlistener] : [evlistener]; return unwrap ? unwrapListeners(evlistener) : arrayClone(evlistener, evlistener.length); } EventEmitter.prototype.listeners = function listeners(type) { return _listeners(this, type, true); }; EventEmitter.prototype.rawListeners = function rawListeners(type) { return _listeners(this, type, false); }; EventEmitter.listenerCount = function(emitter, type) { if (typeof emitter.listenerCount === 'function') { return emitter.listenerCount(type); } else { return listenerCount.call(emitter, type); } }; EventEmitter.prototype.listenerCount = listenerCount; function listenerCount(type) { var events = this._events; if (events !== undefined) { var evlistener = events[type]; if (typeof evlistener === 'function') { return 1; } else if (evlistener !== undefined) { return evlistener.length; } } return 0; } EventEmitter.prototype.eventNames = function eventNames() { return this._eventsCount > 0 ? ReflectOwnKeys(this._events) : []; }; function arrayClone(arr, n) { var copy = new Array(n); for (var i = 0; i < n; ++i) copy[i] = arr[i]; return copy; } function spliceOne(list, index) { for (; index + 1 < list.length; index++) list[index] = list[index + 1]; list.pop(); } function unwrapListeners(arr) { var ret = new Array(arr.length); for (var i = 0; i < ret.length; ++i) { ret[i] = arr[i].listener || arr[i]; } return ret; } function once(emitter, name) { return new Promise(function (resolve, reject) { function errorListener(err) { emitter.removeListener(name, resolver); reject(err); } function resolver() { if (typeof emitter.removeListener === 'function') { emitter.removeListener('error', errorListener); } resolve([].slice.call(arguments)); } eventTargetAgnosticAddListener(emitter, name, resolver, { once: true }); if (name !== 'error') { addErrorHandlerIfEventEmitter(emitter, errorListener, { once: true }); } }); } function addErrorHandlerIfEventEmitter(emitter, handler, flags) { if (typeof emitter.on === 'function') { eventTargetAgnosticAddListener(emitter, 'error', handler, flags); } } function eventTargetAgnosticAddListener(emitter, name, listener, flags) { if (typeof emitter.on === 'function') { if (flags.once) { emitter.once(name, listener); } else { emitter.on(name, listener); } } else if (typeof emitter.addEventListener === 'function') { // EventTarget does not have `error` event semantics like Node // EventEmitters, we do not listen for `error` events here. emitter.addEventListener(name, function wrapListener(arg) { // IE does not have builtin `{ once: true }` support so we // have to do it manually. if (flags.once) { emitter.removeEventListener(name, wrapListener); } listener(arg); }); } else { throw new TypeError('The "emitter" argument must be of type EventEmitter. Received type ' + typeof emitter); } } var EventEmitter$1 = events.exports; function decodeBase64(base64, enableUnicode) { var binaryString = atob(base64); if (enableUnicode) { var binaryView = new Uint8Array(binaryString.length); for (var i = 0, n = binaryString.length; i < n; ++i) { binaryView[i] = binaryString.charCodeAt(i); } return String.fromCharCode.apply(null, new Uint16Array(binaryView.buffer)); } return binaryString; } function createURL(base64, sourcemapArg, enableUnicodeArg) { var sourcemap = sourcemapArg === undefined ? null : sourcemapArg; var enableUnicode = enableUnicodeArg === undefined ? false : enableUnicodeArg; var source = decodeBase64(base64, enableUnicode); var start = source.indexOf('\n', 10) + 1; var body = source.substring(start) + (sourcemap ? '\/\/# sourceMappingURL=' + sourcemap : ''); var blob = new Blob([body], { type: 'application/javascript' }); return URL.createObjectURL(blob); } function createBase64WorkerFactory(base64, sourcemapArg, enableUnicodeArg) { var url; return function WorkerFactory(options) { url = url || createURL(base64, sourcemapArg, enableUnicodeArg); return new Worker(url, options); }; } var WorkerFactory = createBase64WorkerFactory('Lyogcm9sbHVwLXBsdWdpbi13ZWItd29ya2VyLWxvYWRlciAqLwooZnVuY3Rpb24gKCkgewogICd1c2Ugc3RyaWN0JzsKCiAgLyoqCiAgICogUmVjb3JkcyB3aGF0IG9iamVjdHMgYXJlIGNvbGxpZGluZyB3aXRoIGVhY2ggb3RoZXIKICAgKi8KCiAgLyoqCiAgICogQSAzeDMgbWF0cml4LgogICAqIEF1dGhvcmVkIGJ5IHtAbGluayBodHRwOi8vZ2l0aHViLmNvbS9zY2h0ZXBwZS8gc2NodGVwcGV9CiAgICovCiAgY2xhc3MgTWF0MyB7CiAgICAvKioKICAgICAqIEEgdmVjdG9yIG9mIGxlbmd0aCA5LCBjb250YWluaW5nIGFsbCBtYXRyaXggZWxlbWVudHMuCiAgICAgKi8KCiAgICAvKioKICAgICAqIEBwYXJhbSBlbGVtZW50cyBBIHZlY3RvciBvZiBsZW5ndGggOSwgY29udGFpbmluZyBhbGwgbWF0cml4IGVsZW1lbnRzLgogICAgICovCiAgICBjb25zdHJ1Y3RvcihlbGVtZW50cykgewogICAgICBpZiAoZWxlbWVudHMgPT09IHZvaWQgMCkgewogICAgICAgIGVsZW1lbnRzID0gWzAsIDAsIDAsIDAsIDAsIDAsIDAsIDAsIDBdOwogICAgICB9CgogICAgICB0aGlzLmVsZW1lbnRzID0gZWxlbWVudHM7CiAgICB9CiAgICAvKioKICAgICAqIFNldHMgdGhlIG1hdHJpeCB0byBpZGVudGl0eQogICAgICogQHRvZG8gU2hvdWxkIHBlcmhhcHMgYmUgcmVuYW1lZCB0byBgc2V0SWRlbnRpdHkoKWAgdG8gYmUgbW9yZSBjbGVhci4KICAgICAqIEB0b2RvIENyZWF0ZSBhbm90aGVyIGZ1bmN0aW9uIHRoYXQgaW1tZWRpYXRlbHkgY3JlYXRlcyBhbiBpZGVudGl0eSBtYXRyaXggZWcuIGBleWUoKWAKICAgICAqLwoKCiAgICBpZGVudGl0eSgpIHsKICAgICAgY29uc3QgZSA9IHRoaXMuZWxlbWVudHM7CiAgICAgIGVbMF0gPSAxOwogICAgICBlWzFdID0gMDsKICAgICAgZVsyXSA9IDA7CiAgICAgIGVbM10gPSAwOwogICAgICBlWzRdID0gMTsKICAgICAgZVs1XSA9IDA7CiAgICAgIGVbNl0gPSAwOwogICAgICBlWzddID0gMDsKICAgICAgZVs4XSA9IDE7CiAgICB9CiAgICAvKioKICAgICAqIFNldCBhbGwgZWxlbWVudHMgdG8gemVybwogICAgICovCgoKICAgIHNldFplcm8oKSB7CiAgICAgIGNvbnN0IGUgPSB0aGlzLmVsZW1lbnRzOwogICAgICBlWzBdID0gMDsKICAgICAgZVsxXSA9IDA7CiAgICAgIGVbMl0gPSAwOwogICAgICBlWzNdID0gMDsKICAgICAgZVs0XSA9IDA7CiAgICAgIGVbNV0gPSAwOwogICAgICBlWzZdID0gMDsKICAgICAgZVs3XSA9IDA7CiAgICAgIGVbOF0gPSAwOwogICAgfQogICAgLyoqCiAgICAgKiBTZXRzIHRoZSBtYXRyaXggZGlhZ29uYWwgZWxlbWVudHMgZnJvbSBhIFZlYzMKICAgICAqLwoKCiAgICBzZXRUcmFjZSh2ZWN0b3IpIHsKICAgICAgY29uc3QgZSA9IHRoaXMuZWxlbWVudHM7CiAgICAgIGVbMF0gPSB2ZWN0b3IueDsKICAgICAgZVs0XSA9IHZlY3Rvci55OwogICAgICBlWzhdID0gdmVjdG9yLno7CiAgICB9CiAgICAvKioKICAgICAqIEdldHMgdGhlIG1hdHJpeCBkaWFnb25hbCBlbGVtZW50cwogICAgICovCgoKICAgIGdldFRyYWNlKHRhcmdldCkgewogICAgICBpZiAodGFyZ2V0ID09PSB2b2lkIDApIHsKICAgICAgICB0YXJnZXQgPSBuZXcgVmVjMygpOwogICAgICB9CgogICAgICBjb25zdCBlID0gdGhpcy5lbGVtZW50czsKICAgICAgdGFyZ2V0LnggPSBlWzBdOwogICAgICB0YXJnZXQueSA9IGVbNF07CiAgICAgIHRhcmdldC56ID0gZVs4XTsKICAgICAgcmV0dXJuIHRhcmdldDsKICAgIH0KICAgIC8qKgogICAgICogTWF0cml4LVZlY3RvciBtdWx0aXBsaWNhdGlvbgogICAgICogQHBhcmFtIHYgVGhlIHZlY3RvciB0byBtdWx0aXBseSB3aXRoCiAgICAgKiBAcGFyYW0gdGFyZ2V0IE9wdGlvbmFsLCB0YXJnZXQgdG8gc2F2ZSB0aGUgcmVzdWx0IGluLgogICAgICovCgoKICAgIHZtdWx0KHYsIHRhcmdldCkgewogICAgICBpZiAodGFyZ2V0ID09PSB2b2lkIDApIHsKICAgICAgICB0YXJnZXQgPSBuZXcgVmVjMygpOwogICAgICB9CgogICAgICBjb25zdCBlID0gdGhpcy5lbGVtZW50czsKICAgICAgY29uc3QgeCA9IHYueDsKICAgICAgY29uc3QgeSA9IHYueTsKICAgICAgY29uc3QgeiA9IHYuejsKICAgICAgdGFyZ2V0LnggPSBlWzBdICogeCArIGVbMV0gKiB5ICsgZVsyXSAqIHo7CiAgICAgIHRhcmdldC55ID0gZVszXSAqIHggKyBlWzRdICogeSArIGVbNV0gKiB6OwogICAgICB0YXJnZXQueiA9IGVbNl0gKiB4ICsgZVs3XSAqIHkgKyBlWzhdICogejsKICAgICAgcmV0dXJuIHRhcmdldDsKICAgIH0KICAgIC8qKgogICAgICogTWF0cml4LXNjYWxhciBtdWx0aXBsaWNhdGlvbgogICAgICovCgoKICAgIHNtdWx0KHMpIHsKICAgICAgZm9yIChsZXQgaSA9IDA7IGkgPCB0aGlzLmVsZW1lbnRzLmxlbmd0aDsgaSsrKSB7CiAgICAgICAgdGhpcy5lbGVtZW50c1tpXSAqPSBzOwogICAgICB9CiAgICB9CiAgICAvKioKICAgICAqIE1hdHJpeCBtdWx0aXBsaWNhdGlvbgogICAgICogQHBhcmFtIG1hdHJpeCBNYXRyaXggdG8gbXVsdGlwbHkgd2l0aCBmcm9tIGxlZnQgc2lkZS4KICAgICAqLwoKCiAgICBtbXVsdChtYXRyaXgsIHRhcmdldCkgewogICAgICBpZiAodGFyZ2V0ID09PSB2b2lkIDApIHsKICAgICAgICB0YXJnZXQgPSBuZXcgTWF0MygpOwogICAgICB9CgogICAgICBjb25zdCBBID0gdGhpcy5lbGVtZW50czsKICAgICAgY29uc3QgQiA9IG1hdHJpeC5lbGVtZW50czsKICAgICAgY29uc3QgVCA9IHRhcmdldC5lbGVtZW50czsKICAgICAgY29uc3QgYTExID0gQVswXSwKICAgICAgICAgICAgYTEyID0gQVsxXSwKICAgICAgICAgICAgYTEzID0gQVsyXSwKICAgICAgICAgICAgYTIxID0gQVszXSwKICAgICAgICAgICAgYTIyID0gQVs0XSwKICAgICAgICAgICAgYTIzID0gQVs1XSwKICAgICAgICAgICAgYTMxID0gQVs2XSwKICAgICAgICAgICAgYTMyID0gQVs3XSwKICAgICAgICAgICAgYTMzID0gQVs4XTsKICAgICAgY29uc3QgYjExID0gQlswXSwKICAgICAgICAgICAgYjEyID0gQlsxXSwKICAgICAgICAgICAgYjEzID0gQlsyXSwKICAgICAgICAgICAgYjIxID0gQlszXSwKICAgICAgICAgICAgYjIyID0gQls0XSwKICAgICAgICAgICAgYjIzID0gQls1XSwKICAgICAgICAgICAgYjMxID0gQls2XSwKICAgICAgICAgICAgYjMyID0gQls3XSwKICAgICAgICAgICAgYjMzID0gQls4XTsKICAgICAgVFswXSA9IGExMSAqIGIxMSArIGExMiAqIGIyMSArIGExMyAqIGIzMTsKICAgICAgVFsxXSA9IGExMSAqIGIxMiArIGExMiAqIGIyMiArIGExMyAqIGIzMjsKICAgICAgVFsyXSA9IGExMSAqIGIxMyArIGExMiAqIGIyMyArIGExMyAqIGIzMzsKICAgICAgVFszXSA9IGEyMSAqIGIxMSArIGEyMiAqIGIyMSArIGEyMyAqIGIzMTsKICAgICAgVFs0XSA9IGEyMSAqIGIxMiArIGEyMiAqIGIyMiArIGEyMyAqIGIzMjsKICAgICAgVFs1XSA9IGEyMSAqIGIxMyArIGEyMiAqIGIyMyArIGEyMyAqIGIzMzsKICAgICAgVFs2XSA9IGEzMSAqIGIxMSArIGEzMiAqIGIyMSArIGEzMyAqIGIzMTsKICAgICAgVFs3XSA9IGEzMSAqIGIxMiArIGEzMiAqIGIyMiArIGEzMyAqIGIzMjsKICAgICAgVFs4XSA9IGEzMSAqIGIxMyArIGEzMiAqIGIyMyArIGEzMyAqIGIzMzsKICAgICAgcmV0dXJuIHRhcmdldDsKICAgIH0KICAgIC8qKgogICAgICogU2NhbGUgZWFjaCBjb2x1bW4gb2YgdGhlIG1hdHJpeAogICAgICovCgoKICAgIHNjYWxlKHZlY3RvciwgdGFyZ2V0KSB7CiAgICAgIGlmICh0YXJnZXQgPT09IHZvaWQgMCkgewogICAgICAgIHRhcmdldCA9IG5ldyBNYXQzKCk7CiAgICAgIH0KCiAgICAgIGNvbnN0IGUgPSB0aGlzLmVsZW1lbnRzOwogICAgICBjb25zdCB0ID0gdGFyZ2V0LmVsZW1lbnRzOwoKICAgICAgZm9yIChsZXQgaSA9IDA7IGkgIT09IDM7IGkrKykgewogICAgICAgIHRbMyAqIGkgKyAwXSA9IHZlY3Rvci54ICogZVszICogaSArIDBdOwogICAgICAgIHRbMyAqIGkgKyAxXSA9IHZlY3Rvci55ICogZVszICogaSArIDFdOwogICAgICAgIHRbMyAqIGkgKyAyXSA9IHZlY3Rvci56ICogZVszICogaSArIDJdOwogICAgICB9CgogICAgICByZXR1cm4gdGFyZ2V0OwogICAgfQogICAgLyoqCiAgICAgKiBTb2x2ZSBBeD1iCiAgICAgKiBAcGFyYW0gYiBUaGUgcmlnaHQgaGFuZCBzaWRlCiAgICAgKiBAcGFyYW0gdGFyZ2V0IE9wdGlvbmFsLiBUYXJnZXQgdmVjdG9yIHRvIHNhdmUgaW4uCiAgICAgKiBAcmV0dXJuIFRoZSBzb2x1dGlvbiB4CiAgICAgKiBAdG9kbyBzaG91bGQgcmV1c2UgYXJyYXlzCiAgICAgKi8KCgogICAgc29sdmUoYiwgdGFyZ2V0KSB7CiAgICAgIGlmICh0YXJnZXQgPT09IHZvaWQgMCkgewogICAgICAgIHRhcmdldCA9IG5ldyBWZWMzKCk7CiAgICAgIH0KCiAgICAgIC8vIENvbnN0cnVjdCBlcXVhdGlvbnMKICAgICAgY29uc3QgbnIgPSAzOyAvLyBudW0gcm93cwoKICAgICAgY29uc3QgbmMgPSA0OyAvLyBudW0gY29scwoKICAgICAgY29uc3QgZXFucyA9IFtdOwogICAgICBsZXQgaTsKICAgICAgbGV0IGo7CgogICAgICBmb3IgKGkgPSAwOyBpIDwgbnIgKiBuYzsgaSsrKSB7CiAgICAgICAgZXFucy5wdXNoKDApOwogICAgICB9CgogICAgICBmb3IgKGkgPSAwOyBpIDwgMzsgaSsrKSB7CiAgICAgICAgZm9yIChqID0gMDsgaiA8IDM7IGorKykgewogICAgICAgICAgZXFuc1tpICsgbmMgKiBqXSA9IHRoaXMuZWxlbWVudHNbaSArIDMgKiBqXTsKICAgICAgICB9CiAgICAgIH0KCiAgICAgIGVxbnNbMyArIDQgKiAwXSA9IGIueDsKICAgICAgZXFuc1szICsgNCAqIDFdID0gYi55OwogICAgICBlcW5zWzMgKyA0ICogMl0gPSBiLno7IC8vIENvbXB1dGUgcmlnaHQgdXBwZXIgdHJpYW5ndWxhciB2ZXJzaW9uIG9mIHRoZSBtYXRyaXggLSBHYXVzcyBlbGltaW5hdGlvbgoKICAgICAgbGV0IG4gPSAzOwogICAgICBjb25zdCBrID0gbjsKICAgICAgbGV0IG5wOwogICAgICBjb25zdCBrcCA9IDQ7IC8vIG51bSByb3dzCgogICAgICBsZXQgcDsKCiAgICAgIGRvIHsKICAgICAgICBpID0gayAtIG47CgogICAgICAgIGlmIChlcW5zW2kgKyBuYyAqIGldID09PSAwKSB7CiAgICAgICAgICAvLyB0aGUgcGl2b3QgaXMgbnVsbCwgc3dhcCBsaW5lcwogICAgICAgICAgZm9yIChqID0gaSArIDE7IGogPCBrOyBqKyspIHsKICAgICAgICAgICAgaWYgKGVxbnNbaSArIG5jICogal0gIT09IDApIHsKICAgICAgICAgICAgICBucCA9IGtwOwoKICAgICAgICAgICAgICBkbyB7CiAgICAgICAgICAgICAgICAvLyBkbyBsaWduZSggaSApID0gbGlnbmUoIGkgKSArIGxpZ25lKCBrICkKICAgICAgICAgICAgICAgIHAgPSBrcCAtIG5wOwogICAgICAgICAgICAgICAgZXFuc1twICsgbmMgKiBpXSArPSBlcW5zW3AgKyBuYyAqIGpdOwogICAgICAgICAgICAgIH0gd2hpbGUgKC0tbnApOwoKICAgICAgICAgICAgICBicmVhazsKICAgICAgICAgICAgfQogICAgICAgICAgfQogICAgICAgIH0KCiAgICAgICAgaWYgKGVxbnNbaSArIG5jICogaV0gIT09IDApIHsKICAgICAgICAgIGZvciAoaiA9IGkgKyAxOyBqIDwgazsgaisrKSB7CiAgICAgICAgICAgIGNvbnN0IG11bHRpcGxpZXIgPSBlcW5zW2kgKyBuYyAqIGpdIC8gZXFuc1tpICsgbmMgKiBpXTsKICAgICAgICAgICAgbnAgPSBrcDsKCiAgICAgICAgICAgIGRvIHsKICAgICAgICAgICAgICAvLyBkbyBsaWduZSggayApID0gbGlnbmUoIGsgKSAtIG11bHRpcGxpZXIgKiBsaWduZSggaSApCiAgICAgICAgICAgICAgcCA9IGtwIC0gbnA7CiAgICAgICAgICAgICAgZXFuc1twICsgbmMgKiBqXSA9IHAgPD0gaSA/IDAgOiBlcW5zW3AgKyBuYyAqIGpdIC0gZXFuc1twICsgbmMgKiBpXSAqIG11bHRpcGxpZXI7CiAgICAgICAgICAgIH0gd2hpbGUgKC0tbnApOwogICAgICAgICAgfQogICAgICAgIH0KICAgICAgfSB3aGlsZSAoLS1uKTsgLy8gR2V0IHRoZSBzb2x1dGlvbgoKCiAgICAgIHRhcmdldC56ID0gZXFuc1syICogbmMgKyAzXSAvIGVxbnNbMiAqIG5jICsgMl07CiAgICAgIHRhcmdldC55ID0gKGVxbnNbMSAqIG5jICsgM10gLSBlcW5zWzEgKiBuYyArIDJdICogdGFyZ2V0LnopIC8gZXFuc1sxICogbmMgKyAxXTsKICAgICAgdGFyZ2V0LnggPSAoZXFuc1swICogbmMgKyAzXSAtIGVxbnNbMCAqIG5jICsgMl0gKiB0YXJnZXQueiAtIGVxbnNbMCAqIG5jICsgMV0gKiB0YXJnZXQueSkgLyBlcW5zWzAgKiBuYyArIDBdOwoKICAgICAgaWYgKGlzTmFOKHRhcmdldC54KSB8fCBpc05hTih0YXJnZXQueSkgfHwgaXNOYU4odGFyZ2V0LnopIHx8IHRhcmdldC54ID09PSBJbmZpbml0eSB8fCB0YXJnZXQueSA9PT0gSW5maW5pdHkgfHwgdGFyZ2V0LnogPT09IEluZmluaXR5KSB7CiAgICAgICAgdGhyb3cgYENvdWxkIG5vdCBzb2x2ZSBlcXVhdGlvbiEgR290IHg9WyR7dGFyZ2V0LnRvU3RyaW5nKCl9XSwgYj1bJHtiLnRvU3RyaW5nKCl9XSwgQT1bJHt0aGlzLnRvU3RyaW5nKCl9XWA7CiAgICAgIH0KCiAgICAgIHJldHVybiB0YXJnZXQ7CiAgICB9CiAgICAvKioKICAgICAqIEdldCBhbiBlbGVtZW50IGluIHRoZSBtYXRyaXggYnkgaW5kZXguIEluZGV4IHN0YXJ0cyBhdCAwLCBub3QgMSEhIQogICAgICogQHBhcmFtIHZhbHVlIElmIHByb3ZpZGVkLCB0aGUgbWF0cml4IGVsZW1lbnQgd2lsbCBiZSBzZXQgdG8gdGhpcyB2YWx1ZS4KICAgICAqLwoKCiAgICBlKHJvdywgY29sdW1uLCB2YWx1ZSkgewogICAgICBpZiAodmFsdWUgPT09IHVuZGVmaW5lZCkgewogICAgICAgIHJldHVybiB0aGlzLmVsZW1lbnRzW2NvbHVtbiArIDMgKiByb3ddOwogICAgICB9IGVsc2UgewogICAgICAgIC8vIFNldCB2YWx1ZQogICAgICAgIHRoaXMuZWxlbWVudHNbY29sdW1uICsgMyAqIHJvd10gPSB2YWx1ZTsKICAgICAgfQogICAgfQogICAgLyoqCiAgICAgKiBDb3B5IGFub3RoZXIgbWF0cml4IGludG8gdGhpcyBtYXRyaXggb2JqZWN0LgogICAgICovCgoKICAgIGNvcHkobWF0cml4KSB7CiAgICAgIGZvciAobGV0IGkgPSAwOyBpIDwgbWF0cml4LmVsZW1lbnRzLmxlbmd0aDsgaSsrKSB7CiAgICAgICAgdGhpcy5lbGVtZW50c1tpXSA9IG1hdHJpeC5lbGVtZW50c1tpXTsKICAgICAgfQoKICAgICAgcmV0dXJuIHRoaXM7CiAgICB9CiAgICAvKioKICAgICAqIFJldHVybnMgYSBzdHJpbmcgcmVwcmVzZW50YXRpb24gb2YgdGhlIG1hdHJpeC4KICAgICAqLwoKCiAgICB0b1N0cmluZygpIHsKICAgICAgbGV0IHIgPSAnJzsKICAgICAgY29uc3Qgc2VwID0gJywnOwoKICAgICAgZm9yIChsZXQgaSA9IDA7IGkgPCA5OyBpKyspIHsKICAgICAgICByICs9IHRoaXMuZWxlbWVudHNbaV0gKyBzZXA7CiAgICAgIH0KCiAgICAgIHJldHVybiByOwogICAgfQogICAgLyoqCiAgICAgKiByZXZlcnNlIHRoZSBtYXRyaXgKICAgICAqIEBwYXJhbSB0YXJnZXQgVGFyZ2V0IG1hdHJpeCB0byBzYXZlIGluLgogICAgICogQHJldHVybiBUaGUgc29sdXRpb24geAogICAgICovCgoKICAgIHJldmVyc2UodGFyZ2V0KSB7CiAgICAgIGlmICh0YXJnZXQgPT09IHZvaWQgMCkgewogICAgICAgIHRhcmdldCA9IG5ldyBNYXQzKCk7CiAgICAgIH0KCiAgICAgIC8vIENvbnN0cnVjdCBlcXVhdGlvbnMKICAgICAgY29uc3QgbnIgPSAzOyAvLyBudW0gcm93cwoKICAgICAgY29uc3QgbmMgPSA2OyAvLyBudW0gY29scwoKICAgICAgY29uc3QgZXFucyA9IHJldmVyc2VfZXFuczsKICAgICAgbGV0IGk7CiAgICAgIGxldCBqOwoKICAgICAgZm9yIChpID0gMDsgaSA8IDM7IGkrKykgewogICAgICAgIGZvciAoaiA9IDA7IGogPCAzOyBqKyspIHsKICAgICAgICAgIGVxbnNbaSArIG5jICogal0gPSB0aGlzLmVsZW1lbnRzW2kgKyAzICogal07CiAgICAgICAgfQogICAgICB9CgogICAgICBlcW5zWzMgKyA2ICogMF0gPSAxOwogICAgICBlcW5zWzMgKyA2ICogMV0gPSAwOwogICAgICBlcW5zWzMgKyA2ICogMl0gPSAwOwogICAgICBlcW5zWzQgKyA2ICogMF0gPSAwOwogICAgICBlcW5zWzQgKyA2ICogMV0gPSAxOwogICAgICBlcW5zWzQgKyA2ICogMl0gPSAwOwogICAgICBlcW5zWzUgKyA2ICogMF0gPSAwOwogICAgICBlcW5zWzUgKyA2ICogMV0gPSAwOwogICAgICBlcW5zWzUgKyA2ICogMl0gPSAxOyAvLyBDb21wdXRlIHJpZ2h0IHVwcGVyIHRyaWFuZ3VsYXIgdmVyc2lvbiBvZiB0aGUgbWF0cml4IC0gR2F1c3MgZWxpbWluYXRpb24KCiAgICAgIGxldCBuID0gMzsKICAgICAgY29uc3QgayA9IG47CiAgICAgIGxldCBucDsKICAgICAgY29uc3Qga3AgPSBuYzsgLy8gbnVtIHJvd3MKCiAgICAgIGxldCBwOwoKICAgICAgZG8gewogICAgICAgIGkgPSBrIC0gbjsKCiAgICAgICAgaWYgKGVxbnNbaSArIG5jICogaV0gPT09IDApIHsKICAgICAgICAgIC8vIHRoZSBwaXZvdCBpcyBudWxsLCBzd2FwIGxpbmVzCiAgICAgICAgICBmb3IgKGogPSBpICsgMTsgaiA8IGs7IGorKykgewogICAgICAgICAgICBpZiAoZXFuc1tpICsgbmMgKiBqXSAhPT0gMCkgewogICAgICAgICAgICAgIG5wID0ga3A7CgogICAgICAgICAgICAgIGRvIHsKICAgICAgICAgICAgICAgIC8vIGRvIGxpbmUoIGkgKSA9IGxpbmUoIGkgKSArIGxpbmUoIGsgKQogICAgICAgICAgICAgICAgcCA9IGtwIC0gbnA7CiAgICAgICAgICAgICAgICBlcW5zW3AgKyBuYyAqIGldICs9IGVxbnNbcCArIG5jICogal07CiAgICAgICAgICAgICAgfSB3aGlsZSAoLS1ucCk7CgogICAgICAgICAgICAgIGJyZWFrOwogICAgICAgICAgICB9CiAgICAgICAgICB9CiAgICAgICAgfQoKICAgICAgICBpZiAoZXFuc1tpICsgbmMgKiBpXSAhPT0gMCkgewogICAgICAgICAgZm9yIChqID0gaSArIDE7IGogPCBrOyBqKyspIHsKICAgICAgICAgICAgY29uc3QgbXVsdGlwbGllciA9IGVxbnNbaSArIG5jICogal0gLyBlcW5zW2kgKyBuYyAqIGldOwogICAgICAgICAgICBucCA9IGtwOwoKICAgICAgICAgICAgZG8gewogICAgICAgICAgICAgIC8vIGRvIGxpbmUoIGsgKSA9IGxpbmUoIGsgKSAtIG11bHRpcGxpZXIgKiBsaW5lKCBpICkKICAgICAgICAgICAgICBwID0ga3AgLSBucDsKICAgICAgICAgICAgICBlcW5zW3AgKyBuYyAqIGpdID0gcCA8PSBpID8gMCA6IGVxbnNbcCArIG5jICogal0gLSBlcW5zW3AgKyBuYyAqIGldICogbXVsdGlwbGllcjsKICAgICAgICAgICAgfSB3aGlsZSAoLS1ucCk7CiAgICAgICAgICB9CiAgICAgICAgfQogICAgICB9IHdoaWxlICgtLW4pOyAvLyBlbGltaW5hdGUgdGhlIHVwcGVyIGxlZnQgdHJpYW5nbGUgb2YgdGhlIG1hdHJpeAoKCiAgICAgIGkgPSAyOwoKICAgICAgZG8gewogICAgICAgIGogPSBpIC0gMTsKCiAgICAgICAgZG8gewogICAgICAgICAgY29uc3QgbXVsdGlwbGllciA9IGVxbnNbaSArIG5jICogal0gLyBlcW5zW2kgKyBuYyAqIGldOwogICAgICAgICAgbnAgPSBuYzsKCiAgICAgICAgICBkbyB7CiAgICAgICAgICAgIHAgPSBuYyAtIG5wOwogICAgICAgICAgICBlcW5zW3AgKyBuYyAqIGpdID0gZXFuc1twICsgbmMgKiBqXSAtIGVxbnNbcCArIG5jICogaV0gKiBtdWx0aXBsaWVyOwogICAgICAgICAgfSB3aGlsZSAoLS1ucCk7CiAgICAgICAgfSB3aGlsZSAoai0tKTsKICAgICAgfSB3aGlsZSAoLS1pKTsgLy8gb3BlcmF0aW9ucyBvbiB0aGUgZGlhZ29uYWwKCgogICAgICBpID0gMjsKCiAgICAgIGRvIHsKICAgICAgICBjb25zdCBtdWx0aXBsaWVyID0gMSAvIGVxbnNbaSArIG5jICogaV07CiAgICAgICAgbnAgPSBuYzsKCiAgICAgICAgZG8gewogICAgICAgICAgcCA9IG5jIC0gbnA7CiAgICAgICAgICBlcW5zW3AgKyBuYyAqIGldID0gZXFuc1twICsgbmMgKiBpXSAqIG11bHRpcGxpZXI7CiAgICAgICAgfSB3aGlsZSAoLS1ucCk7CiAgICAgIH0gd2hpbGUgKGktLSk7CgogICAgICBpID0gMjsKCiAgICAgIGRvIHsKICAgICAgICBqID0gMjsKCiAgICAgICAgZG8gewogICAgICAgICAgcCA9IGVxbnNbbnIgKyBqICsgbmMgKiBpXTsKCiAgICAgICAgICBpZiAoaXNOYU4ocCkgfHwgcCA9PT0gSW5maW5pdHkpIHsKICAgICAgICAgICAgdGhyb3cgYENvdWxkIG5vdCByZXZlcnNlISBBPVske3RoaXMudG9TdHJpbmcoKX1dYDsKICAgICAgICAgIH0KCiAgICAgICAgICB0YXJnZXQuZShpLCBqLCBwKTsKICAgICAgICB9IHdoaWxlIChqLS0pOwogICAgICB9IHdoaWxlIChpLS0pOwoKICAgICAgcmV0dXJuIHRhcmdldDsKICAgIH0KICAgIC8qKgogICAgICogU2V0IHRoZSBtYXRyaXggZnJvbSBhIHF1YXRlcmlvbgogICAgICovCgoKICAgIHNldFJvdGF0aW9uRnJvbVF1YXRlcm5pb24ocSkgewogICAgICBjb25zdCB4ID0gcS54OwogICAgICBjb25zdCB5ID0gcS55OwogICAgICBjb25zdCB6ID0gcS56OwogICAgICBjb25zdCB3ID0gcS53OwogICAgICBjb25zdCB4MiA9IHggKyB4OwogICAgICBjb25zdCB5MiA9IHkgKyB5OwogICAgICBjb25zdCB6MiA9IHogKyB6OwogICAgICBjb25zdCB4eCA9IHggKiB4MjsKICAgICAgY29uc3QgeHkgPSB4ICogeTI7CiAgICAgIGNvbnN0IHh6ID0geCAqIHoyOwogICAgICBjb25zdCB5eSA9IHkgKiB5MjsKICAgICAgY29uc3QgeXogPSB5ICogejI7CiAgICAgIGNvbnN0IHp6ID0geiAqIHoyOwogICAgICBjb25zdCB3eCA9IHcgKiB4MjsKICAgICAgY29uc3Qgd3kgPSB3ICogeTI7CiAgICAgIGNvbnN0IHd6ID0gdyAqIHoyOwogICAgICBjb25zdCBlID0gdGhpcy5lbGVtZW50czsKICAgICAgZVszICogMCArIDBdID0gMSAtICh5eSArIHp6KTsKICAgICAgZVszICogMCArIDFdID0geHkgLSB3ejsKICAgICAgZVszICogMCArIDJdID0geHogKyB3eTsKICAgICAgZVszICogMSArIDBdID0geHkgKyB3ejsKICAgICAgZVszICogMSArIDFdID0gMSAtICh4eCArIHp6KTsKICAgICAgZVszICogMSArIDJdID0geXogLSB3eDsKICAgICAgZVszICogMiArIDBdID0geHogLSB3eTsKICAgICAgZVszICogMiArIDFdID0geXogKyB3eDsKICAgICAgZVszICogMiArIDJdID0gMSAtICh4eCArIHl5KTsKICAgICAgcmV0dXJuIHRoaXM7CiAgICB9CiAgICAvKioKICAgICAqIFRyYW5zcG9zZSB0aGUgbWF0cml4CiAgICAgKiBAcGFyYW0gdGFyZ2V0IE9wdGlvbmFsLiBXaGVyZSB0byBzdG9yZSB0aGUgcmVzdWx0LgogICAgICogQHJldHVybiBUaGUgdGFyZ2V0IE1hdDMsIG9yIGEgbmV3IE1hdDMgaWYgdGFyZ2V0IHdhcyBvbWl0dGVkLgogICAgICovCgoKICAgIHRyYW5zcG9zZSh0YXJnZXQpIHsKICAgICAgaWYgKHRhcmdldCA9PT0gdm9pZCAwKSB7CiAgICAgICAgdGFyZ2V0ID0gbmV3IE1hdDMoKTsKICAgICAgfQoKICAgICAgY29uc3QgTSA9IHRoaXMuZWxlbWVudHM7CiAgICAgIGNvbnN0IFQgPSB0YXJnZXQuZWxlbWVudHM7CiAgICAgIGxldCB0bXA7IC8vU2V0IGRpYWdvbmFscwoKICAgICAgVFswXSA9IE1bMF07CiAgICAgIFRbNF0gPSBNWzRdOwogICAgICBUWzhdID0gTVs4XTsKICAgICAgdG1wID0gTVsxXTsKICAgICAgVFsxXSA9IE1bM107CiAgICAgIFRbM10gPSB0bXA7CiAgICAgIHRtcCA9IE1bMl07CiAgICAgIFRbMl0gPSBNWzZdOwogICAgICBUWzZdID0gdG1wOwogICAgICB0bXAgPSBNWzVdOwogICAgICBUWzVdID0gTVs3XTsKICAgICAgVFs3XSA9IHRtcDsKICAgICAgcmV0dXJuIHRhcmdldDsKICAgIH0KCiAgfQogIGNvbnN0IHJldmVyc2VfZXFucyA9IFswLCAwLCAwLCAwLCAwLCAwLCAwLCAwLCAwLCAwLCAwLCAwLCAwLCAwLCAwLCAwLCAwLCAwXTsKCiAgLyoqCiAgICogMy1kaW1lbnNpb25hbCB2ZWN0b3IKICAgKiBAZXhhbXBsZQogICAqICAgICBjb25zdCB2ID0gbmV3IFZlYzMoMSwgMiwgMykKICAgKiAgICAgY29uc29sZS5sb2coJ3g9JyArIHYueCkgLy8geD0xCiAgICovCgogIGNsYXNzIFZlYzMgewogICAgY29uc3RydWN0b3IoeCwgeSwgeikgewogICAgICBpZiAoeCA9PT0gdm9pZCAwKSB7CiAgICAgICAgeCA9IDAuMDsKICAgICAgfQoKICAgICAgaWYgKHkgPT09IHZvaWQgMCkgewogICAgICAgIHkgPSAwLjA7CiAgICAgIH0KCiAgICAgIGlmICh6ID09PSB2b2lkIDApIHsKICAgICAgICB6ID0gMC4wOwogICAgICB9CgogICAgICB0aGlzLnggPSB4OwogICAgICB0aGlzLnkgPSB5OwogICAgICB0aGlzLnogPSB6OwogICAgfQogICAgLyoqCiAgICAgKiBWZWN0b3IgY3Jvc3MgcHJvZHVjdAogICAgICogQHBhcmFtIHRhcmdldCBPcHRpb25hbCB0YXJnZXQgdG8gc2F2ZSBpbi4KICAgICAqLwoKCiAgICBjcm9zcyh2ZWN0b3IsIHRhcmdldCkgewogICAgICBpZiAodGFyZ2V0ID09PSB2b2lkIDApIHsKICAgICAgICB0YXJnZXQgPSBuZXcgVmVjMygpOwogICAgICB9CgogICAgICBjb25zdCB2eCA9IHZlY3Rvci54OwogICAgICBjb25zdCB2eSA9IHZlY3Rvci55OwogICAgICBjb25zdCB2eiA9IHZlY3Rvci56OwogICAgICBjb25zdCB4ID0gdGhpcy54OwogICAgICBjb25zdCB5ID0gdGhpcy55OwogICAgICBjb25zdCB6ID0gdGhpcy56OwogICAgICB0YXJnZXQueCA9IHkgKiB2eiAtIHogKiB2eTsKICAgICAgdGFyZ2V0LnkgPSB6ICogdnggLSB4ICogdno7CiAgICAgIHRhcmdldC56ID0geCAqIHZ5IC0geSAqIHZ4OwogICAgICByZXR1cm4gdGFyZ2V0OwogICAgfQogICAgLyoqCiAgICAgKiBTZXQgdGhlIHZlY3RvcnMnIDMgZWxlbWVudHMKICAgICAqLwoKCiAgICBzZXQoeCwgeSwgeikgewogICAgICB0aGlzLnggPSB4OwogICAgICB0aGlzLnkgPSB5OwogICAgICB0aGlzLnogPSB6OwogICAgICByZXR1cm4gdGhpczsKICAgIH0KICAgIC8qKgogICAgICogU2V0IGFsbCBjb21wb25lbnRzIG9mIHRoZSB2ZWN0b3IgdG8gemVyby4KICAgICAqLwoKCiAgICBzZXRaZXJvKCkgewogICAgICB0aGlzLnggPSB0aGlzLnkgPSB0aGlzLnogPSAwOwogICAgfQogICAgLyoqCiAgICAgKiBWZWN0b3IgYWRkaXRpb24KICAgICAqLwoKCiAgICB2YWRkKHZlY3RvciwgdGFyZ2V0KSB7CiAgICAgIGlmICh0YXJnZXQpIHsKICAgICAgICB0YXJnZXQueCA9IHZlY3Rvci54ICsgdGhpcy54OwogICAgICAgIHRhcmdldC55ID0gdmVjdG9yLnkgKyB0aGlzLnk7CiAgICAgICAgdGFyZ2V0LnogPSB2ZWN0b3IueiArIHRoaXMuejsKICAgICAgfSBlbHNlIHsKICAgICAgICByZXR1cm4gbmV3IFZlYzModGhpcy54ICsgdmVjdG9yLngsIHRoaXMueSArIHZlY3Rvci55LCB0aGlzLnogKyB2ZWN0b3Iueik7CiAgICAgIH0KICAgIH0KICAgIC8qKgogICAgICogVmVjdG9yIHN1YnRyYWN0aW9uCiAgICAgKiBAcGFyYW0gdGFyZ2V0IE9wdGlvbmFsIHRhcmdldCB0byBzYXZlIGluLgogICAgICovCgoKICAgIHZzdWIodmVjdG9yLCB0YXJnZXQpIHsKICAgICAgaWYgKHRhcmdldCkgewogICAgICAgIHRhcmdldC54ID0gdGhpcy54IC0gdmVjdG9yLng7CiAgICAgICAgdGFyZ2V0LnkgPSB0aGlzLnkgLSB2ZWN0b3IueTsKICAgICAgICB0YXJnZXQueiA9IHRoaXMueiAtIHZlY3Rvci56OwogICAgICB9IGVsc2UgewogICAgICAgIHJldHVybiBuZXcgVmVjMyh0aGlzLnggLSB2ZWN0b3IueCwgdGhpcy55IC0gdmVjdG9yLnksIHRoaXMueiAtIHZlY3Rvci56KTsKICAgICAgfQogICAgfQogICAgLyoqCiAgICAgKiBHZXQgdGhlIGNyb3NzIHByb2R1Y3QgbWF0cml4IGFfY3Jvc3MgZnJvbSBhIHZlY3Rvciwgc3VjaCB0aGF0IGEgeCBiID0gYV9jcm9zcyAqIGIgPSBjCiAgICAgKgogICAgICogU2VlIHtAbGluayBodHRwczovL3d3dzguY3MudW11LnNlL2t1cnNlci9UREJEMjQvVlQwNi9sZWN0dXJlcy9MZWN0dXJlNi5wZGYgVW1lw6UgVW5pdmVyc2l0eSBMZWN0dXJlfQogICAgICovCgoKICAgIGNyb3NzbWF0KCkgewogICAgICByZXR1cm4gbmV3IE1hdDMoWzAsIC10aGlzLnosIHRoaXMueSwgdGhpcy56LCAwLCAtdGhpcy54LCAtdGhpcy55LCB0aGlzLngsIDBdKTsKICAgIH0KICAgIC8qKgogICAgICogTm9ybWFsaXplIHRoZSB2ZWN0b3IuIE5vdGUgdGhhdCB0aGlzIGNoYW5nZXMgdGhlIHZhbHVlcyBpbiB0aGUgdmVjdG9yLgogICAgICAqIEByZXR1cm4gUmV0dXJucyB0aGUgbm9ybSBvZiB0aGUgdmVjdG9yCiAgICAgKi8KCgogICAgbm9ybWFsaXplKCkgewogICAgICBjb25zdCB4ID0gdGhpcy54OwogICAgICBjb25zdCB5ID0gdGhpcy55OwogICAgICBjb25zdCB6ID0gdGhpcy56OwogICAgICBjb25zdCBuID0gTWF0aC5zcXJ0KHggKiB4ICsgeSAqIHkgKyB6ICogeik7CgogICAgICBpZiAobiA+IDAuMCkgewogICAgICAgIGNvbnN0IGludk4gPSAxIC8gbjsKICAgICAgICB0aGlzLnggKj0gaW52TjsKICAgICAgICB0aGlzLnkgKj0gaW52TjsKICAgICAgICB0aGlzLnogKj0gaW52TjsKICAgICAgfSBlbHNlIHsKICAgICAgICAvLyBNYWtlIHNvbWV0aGluZyB1cAogICAgICAgIHRoaXMueCA9IDA7CiAgICAgICAgdGhpcy55ID0gMDsKICAgICAgICB0aGlzLnogPSAwOwogICAgICB9CgogICAgICByZXR1cm4gbjsKICAgIH0KICAgIC8qKgogICAgICogR2V0IHRoZSB2ZXJzaW9uIG9mIHRoaXMgdmVjdG9yIHRoYXQgaXMgb2YgbGVuZ3RoIDEuCiAgICAgKiBAcGFyYW0gdGFyZ2V0IE9wdGlvbmFsIHRhcmdldCB0byBzYXZlIGluCiAgICAgKiBAcmV0dXJuIFJldHVybnMgdGhlIHVuaXQgdmVjdG9yCiAgICAgKi8KCgogICAgdW5pdCh0YXJnZXQpIHsKICAgICAgaWYgKHRhcmdldCA9PT0gdm9pZCAwKSB7CiAgICAgICAgdGFyZ2V0ID0gbmV3IFZlYzMoKTsKICAgICAgfQoKICAgICAgY29uc3QgeCA9IHRoaXMueDsKICAgICAgY29uc3QgeSA9IHRoaXMueTsKICAgICAgY29uc3QgeiA9IHRoaXMuejsKICAgICAgbGV0IG5pbnYgPSBNYXRoLnNxcnQoeCAqIHggKyB5ICogeSArIHogKiB6KTsKCiAgICAgIGlmIChuaW52ID4gMC4wKSB7CiAgICAgICAgbmludiA9IDEuMCAvIG5pbnY7CiAgICAgICAgdGFyZ2V0LnggPSB4ICogbmludjsKICAgICAgICB0YXJnZXQueSA9IHkgKiBuaW52OwogICAgICAgIHRhcmdldC56ID0geiAqIG5pbnY7CiAgICAgIH0gZWxzZSB7CiAgICAgICAgdGFyZ2V0LnggPSAxOwogICAgICAgIHRhcmdldC55ID0gMDsKICAgICAgICB0YXJnZXQueiA9IDA7CiAgICAgIH0KCiAgICAgIHJldHVybiB0YXJnZXQ7CiAgICB9CiAgICAvKioKICAgICAqIEdldCB0aGUgbGVuZ3RoIG9mIHRoZSB2ZWN0b3IKICAgICAqLwoKCiAgICBsZW5ndGgoKSB7CiAgICAgIGNvbnN0IHggPSB0aGlzLng7CiAgICAgIGNvbnN0IHkgPSB0aGlzLnk7CiAgICAgIGNvbnN0IHogPSB0aGlzLno7CiAgICAgIHJldHVybiBNYXRoLnNxcnQoeCAqIHggKyB5ICogeSArIHogKiB6KTsKICAgIH0KICAgIC8qKgogICAgICogR2V0IHRoZSBzcXVhcmVkIGxlbmd0aCBvZiB0aGUgdmVjdG9yLgogICAgICovCgoKICAgIGxlbmd0aFNxdWFyZWQoKSB7CiAgICAgIHJldHVybiB0aGlzLmRvdCh0aGlzKTsKICAgIH0KICAgIC8qKgogICAgICogR2V0IGRpc3RhbmNlIGZyb20gdGhpcyBwb2ludCB0byBhbm90aGVyIHBvaW50CiAgICAgKi8KCgogICAgZGlzdGFuY2VUbyhwKSB7CiAgICAgIGNvbnN0IHggPSB0aGlzLng7CiAgICAgIGNvbnN0IHkgPSB0aGlzLnk7CiAgICAgIGNvbnN0IHogPSB0aGlzLno7CiAgICAgIGNvbnN0IHB4ID0gcC54OwogICAgICBjb25zdCBweSA9IHAueTsKICAgICAgY29uc3QgcHogPSBwLno7CiAgICAgIHJldHVybiBNYXRoLnNxcnQoKHB4IC0geCkgKiAocHggLSB4KSArIChweSAtIHkpICogKHB5IC0geSkgKyAocHogLSB6KSAqIChweiAtIHopKTsKICAgIH0KICAgIC8qKgogICAgICogR2V0IHNxdWFyZWQgZGlzdGFuY2UgZnJvbSB0aGlzIHBvaW50IHRvIGFub3RoZXIgcG9pbnQKICAgICAqLwoKCiAgICBkaXN0YW5jZVNxdWFyZWQocCkgewogICAgICBjb25zdCB4ID0gdGhpcy54OwogICAgICBjb25zdCB5ID0gdGhpcy55OwogICAgICBjb25zdCB6ID0gdGhpcy56OwogICAgICBjb25zdCBweCA9IHAueDsKICAgICAgY29uc3QgcHkgPSBwLnk7CiAgICAgIGNvbnN0IHB6ID0gcC56OwogICAgICByZXR1cm4gKHB4IC0geCkgKiAocHggLSB4KSArIChweSAtIHkpICogKHB5IC0geSkgKyAocHogLSB6KSAqIChweiAtIHopOwogICAgfQogICAgLyoqCiAgICAgKiBNdWx0aXBseSBhbGwgdGhlIGNvbXBvbmVudHMgb2YgdGhlIHZlY3RvciB3aXRoIGEgc2NhbGFyLgogICAgICogQHBhcmFtIHRhcmdldCBUaGUgdmVjdG9yIHRvIHNhdmUgdGhlIHJlc3VsdCBpbi4KICAgICAqLwoKCiAgICBzY2FsZShzY2FsYXIsIHRhcmdldCkgewogICAgICBpZiAodGFyZ2V0ID09PSB2b2lkIDApIHsKICAgICAgICB0YXJnZXQgPSBuZXcgVmVjMygpOwogICAgICB9CgogICAgICBjb25zdCB4ID0gdGhpcy54OwogICAgICBjb25zdCB5ID0gdGhpcy55OwogICAgICBjb25zdCB6ID0gdGhpcy56OwogICAgICB0YXJnZXQueCA9IHNjYWxhciAqIHg7CiAgICAgIHRhcmdldC55ID0gc2NhbGFyICogeTsKICAgICAgdGFyZ2V0LnogPSBzY2FsYXIgKiB6OwogICAgICByZXR1cm4gdGFyZ2V0OwogICAgfQogICAgLyoqCiAgICAgKiBNdWx0aXBseSB0aGUgdmVjdG9yIHdpdGggYW4gb3RoZXIgdmVjdG9yLCBjb21wb25lbnQtd2lzZS4KICAgICAqIEBwYXJhbSB0YXJnZXQgVGhlIHZlY3RvciB0byBzYXZlIHRoZSByZXN1bHQgaW4uCiAgICAgKi8KCgogICAgdm11bCh2ZWN0b3IsIHRhcmdldCkgewogICAgICBpZiAodGFyZ2V0ID09PSB2b2lkIDApIHsKICAgICAgICB0YXJnZXQgPSBuZXcgVmVjMygpOwogICAgICB9CgogICAgICB0YXJnZXQueCA9IHZlY3Rvci54ICogdGhpcy54OwogICAgICB0YXJnZXQueSA9IHZlY3Rvci55ICogdGhpcy55OwogICAgICB0YXJnZXQueiA9IHZlY3Rvci56ICogdGhpcy56OwogICAgICByZXR1cm4gdGFyZ2V0OwogICAgfQogICAgLyoqCiAgICAgKiBTY2FsZSBhIHZlY3RvciBhbmQgYWRkIGl0IHRvIHRoaXMgdmVjdG9yLiBTYXZlIHRoZSByZXN1bHQgaW4gInRhcmdldCIuICh0YXJnZXQgPSB0aGlzICsgdmVjdG9yICogc2NhbGFyKQogICAgICogQHBhcmFtIHRhcmdldCBUaGUgdmVjdG9yIHRvIHNhdmUgdGhlIHJlc3VsdCBpbi4KICAgICAqLwoKCiAgICBhZGRTY2FsZWRWZWN0b3Ioc2NhbGFyLCB2ZWN0b3IsIHRhcmdldCkgewogICAgICBpZiAodGFyZ2V0ID09PSB2b2lkIDApIHsKICAgICAgICB0YXJnZXQgPSBuZXcgVmVjMygpOwogICAgICB9CgogICAgICB0YXJnZXQueCA9IHRoaXMueCArIHNjYWxhciAqIHZlY3Rvci54OwogICAgICB0YXJnZXQueSA9IHRoaXMueSArIHNjYWxhciAqIHZlY3Rvci55OwogICAgICB0YXJnZXQueiA9IHRoaXMueiArIHNjYWxhciAqIHZlY3Rvci56OwogICAgICByZXR1cm4gdGFyZ2V0OwogICAgfQogICAgLyoqCiAgICAgKiBDYWxjdWxhdGUgZG90IHByb2R1Y3QKICAgICAqIEBwYXJhbSB2ZWN0b3IKICAgICAqLwoKCiAgICBkb3QodmVjdG9yKSB7CiAgICAgIHJldHVybiB0aGlzLnggKiB2ZWN0b3IueCArIHRoaXMueSAqIHZlY3Rvci55ICsgdGhpcy56ICogdmVjdG9yLno7CiAgICB9CgogICAgaXNaZXJvKCkgewogICAgICByZXR1cm4gdGhpcy54ID09PSAwICYmIHRoaXMueSA9PT0gMCAmJiB0aGlzLnogPT09IDA7CiAgICB9CiAgICAvKioKICAgICAqIE1ha2UgdGhlIHZlY3RvciBwb2ludCBpbiB0aGUgb3Bwb3NpdGUgZGlyZWN0aW9uLgogICAgICogQHBhcmFtIHRhcmdldCBPcHRpb25hbCB0YXJnZXQgdG8gc2F2ZSBpbgogICAgICovCgoKICAgIG5lZ2F0ZSh0YXJnZXQpIHsKICAgICAgaWYgKHRhcmdldCA9PT0gdm9pZCAwKSB7CiAgICAgICAgdGFyZ2V0ID0gbmV3IFZlYzMoKTsKICAgICAgfQoKICAgICAgdGFyZ2V0LnggPSAtdGhpcy54OwogICAgICB0YXJnZXQueSA9IC10aGlzLnk7CiAgICAgIHRhcmdldC56ID0gLXRoaXMuejsKICAgICAgcmV0dXJuIHRhcmdldDsKICAgIH0KICAgIC8qKgogICAgICogQ29tcHV0ZSB0d28gYXJ0aWZpY2lhbCB0YW5nZW50cyB0byB0aGUgdmVjdG9yCiAgICAgKiBAcGFyYW0gdDEgVmVjdG9yIG9iamVjdCB0byBzYXZlIHRoZSBmaXJzdCB0YW5nZW50IGluCiAgICAgKiBAcGFyYW0gdDIgVmVjdG9yIG9iamVjdCB0byBzYXZlIHRoZSBzZWNvbmQgdGFuZ2VudCBpbgogICAgICovCgoKICAgIHRhbmdlbnRzKHQxLCB0MikgewogICAgICBjb25zdCBub3JtID0gdGhpcy5sZW5ndGgoKTsKCiAgICAgIGlmIChub3JtID4gMC4wKSB7CiAgICAgICAgY29uc3QgbiA9IFZlYzNfdGFuZ2VudHNfbjsKICAgICAgICBjb25zdCBpbm9ybSA9IDEgLyBub3JtOwogICAgICAgIG4uc2V0KHRoaXMueCAqIGlub3JtLCB0aGlzLnkgKiBpbm9ybSwgdGhpcy56ICogaW5vcm0pOwogICAgICAgIGNvbnN0IHJhbmRWZWMgPSBWZWMzX3RhbmdlbnRzX3JhbmRWZWM7CgogICAgICAgIGlmIChNYXRoLmFicyhuLngpIDwgMC45KSB7CiAgICAgICAgICByYW5kVmVjLnNldCgxLCAwLCAwKTsKICAgICAgICAgIG4uY3Jvc3MocmFuZFZlYywgdDEpOwogICAgICAgIH0gZWxzZSB7CiAgICAgICAgICByYW5kVmVjLnNldCgwLCAxLCAwKTsKICAgICAgICAgIG4uY3Jvc3MocmFuZFZlYywgdDEpOwogICAgICAgIH0KCiAgICAgICAgbi5jcm9zcyh0MSwgdDIpOwogICAgICB9IGVsc2UgewogICAgICAgIC8vIFRoZSBub3JtYWwgbGVuZ3RoIGlzIHplcm8sIG1ha2Ugc29tZXRoaW5nIHVwCiAgICAgICAgdDEuc2V0KDEsIDAsIDApOwogICAgICAgIHQyLnNldCgwLCAxLCAwKTsKICAgICAgfQogICAgfQogICAgLyoqCiAgICAgKiBDb252ZXJ0cyB0byBhIG1vcmUgcmVhZGFibGUgZm9ybWF0CiAgICAgKi8KCgogICAgdG9TdHJpbmcoKSB7CiAgICAgIHJldHVybiBgJHt0aGlzLnh9LCR7dGhpcy55fSwke3RoaXMuen1gOwogICAgfQogICAgLyoqCiAgICAgKiBDb252ZXJ0cyB0byBhbiBhcnJheQogICAgICovCgoKICAgIHRvQXJyYXkoKSB7CiAgICAgIHJldHVybiBbdGhpcy54LCB0aGlzLnksIHRoaXMuel07CiAgICB9CiAgICAvKioKICAgICAqIENvcGllcyB2YWx1ZSBvZiBzb3VyY2UgdG8gdGhpcyB2ZWN0b3IuCiAgICAgKi8KCgogICAgY29weSh2ZWN0b3IpIHsKICAgICAgdGhpcy54ID0gdmVjdG9yLng7CiAgICAgIHRoaXMueSA9IHZlY3Rvci55OwogICAgICB0aGlzLnogPSB2ZWN0b3IuejsKICAgICAgcmV0dXJuIHRoaXM7CiAgICB9CiAgICAvKioKICAgICAqIERvIGEgbGluZWFyIGludGVycG9sYXRpb24gYmV0d2VlbiB0d28gdmVjdG9ycwogICAgICogQHBhcmFtIHQgQSBudW1iZXIgYmV0d2VlbiAwIGFuZCAxLiAwIHdpbGwgbWFrZSB0aGlzIGZ1bmN0aW9uIHJldHVybiB1LCBhbmQgMSB3aWxsIG1ha2UgaXQgcmV0dXJuIHYuIE51bWJlcnMgaW4gYmV0d2VlbiB3aWxsIGdlbmVyYXRlIGEgdmVjdG9yIGluIGJldHdlZW4gdGhlbS4KICAgICAqLwoKCiAgICBsZXJwKHZlY3RvciwgdCwgdGFyZ2V0KSB7CiAgICAgIGNvbnN0IHggPSB0aGlzLng7CiAgICAgIGNvbnN0IHkgPSB0aGlzLnk7CiAgICAgIGNvbnN0IHogPSB0aGlzLno7CiAgICAgIHRhcmdldC54ID0geCArICh2ZWN0b3IueCAtIHgpICogdDsKICAgICAgdGFyZ2V0LnkgPSB5ICsgKHZlY3Rvci55IC0geSkgKiB0OwogICAgICB0YXJnZXQueiA9IHogKyAodmVjdG9yLnogLSB6KSAqIHQ7CiAgICB9CiAgICAvKioKICAgICAqIENoZWNrIGlmIGEgdmVjdG9yIGVxdWFscyBpcyBhbG1vc3QgZXF1YWwgdG8gYW5vdGhlciBvbmUuCiAgICAgKi8KCgogICAgYWxtb3N0RXF1YWxzKHZlY3RvciwgcHJlY2lzaW9uKSB7CiAgICAgIGlmIChwcmVjaXNpb24gPT09IHZvaWQgMCkgewogICAgICAgIHByZWNpc2lvbiA9IDFlLTY7CiAgICAgIH0KCiAgICAgIGlmIChNYXRoLmFicyh0aGlzLnggLSB2ZWN0b3IueCkgPiBwcmVjaXNpb24gfHwgTWF0aC5hYnModGhpcy55IC0gdmVjdG9yLnkpID4gcHJlY2lzaW9uIHx8IE1hdGguYWJzKHRoaXMueiAtIHZlY3Rvci56KSA+IHByZWNpc2lvbikgewogICAgICAgIHJldHVybiBmYWxzZTsKICAgICAgfQoKICAgICAgcmV0dXJuIHRydWU7CiAgICB9CiAgICAvKioKICAgICAqIENoZWNrIGlmIGEgdmVjdG9yIGlzIGFsbW9zdCB6ZXJvCiAgICAgKi8KCgogICAgYWxtb3N0WmVybyhwcmVjaXNpb24pIHsKICAgICAgaWYgKHByZWNpc2lvbiA9PT0gdm9pZCAwKSB7CiAgICAgICAgcHJlY2lzaW9uID0gMWUtNjsKICAgICAgfQoKICAgICAgaWYgKE1hdGguYWJzKHRoaXMueCkgPiBwcmVjaXNpb24gfHwgTWF0aC5hYnModGhpcy55KSA+IHByZWNpc2lvbiB8fCBNYXRoLmFicyh0aGlzLnopID4gcHJlY2lzaW9uKSB7CiAgICAgICAgcmV0dXJuIGZhbHNlOwogICAgICB9CgogICAgICByZXR1cm4gdHJ1ZTsKICAgIH0KICAgIC8qKgogICAgICogQ2hlY2sgaWYgdGhlIHZlY3RvciBpcyBhbnRpLXBhcmFsbGVsIHRvIGFub3RoZXIgdmVjdG9yLgogICAgICogQHBhcmFtIHByZWNpc2lvbiBTZXQgdG8gemVybyBmb3IgZXhhY3QgY29tcGFyaXNvbnMKICAgICAqLwoKCiAgICBpc0FudGlwYXJhbGxlbFRvKHZlY3RvciwgcHJlY2lzaW9uKSB7CiAgICAgIHRoaXMubmVnYXRlKGFudGlwX25lZyk7CiAgICAgIHJldHVybiBhbnRpcF9uZWcuYWxtb3N0RXF1YWxzKHZlY3RvciwgcHJlY2lzaW9uKTsKICAgIH0KICAgIC8qKgogICAgICogQ2xvbmUgdGhlIHZlY3RvcgogICAgICovCgoKICAgIGNsb25lKCkgewogICAgICByZXR1cm4gbmV3IFZlYzModGhpcy54LCB0aGlzLnksIHRoaXMueik7CiAgICB9CgogIH0KICBWZWMzLlpFUk8gPSBuZXcgVmVjMygwLCAwLCAwKTsKICBWZWMzLlVOSVRfWCA9IG5ldyBWZWMzKDEsIDAsIDApOwogIFZlYzMuVU5JVF9ZID0gbmV3IFZlYzMoMCwgMSwgMCk7CiAgVmVjMy5VTklUX1ogPSBuZXcgVmVjMygwLCAwLCAxKTsKICBjb25zdCBWZWMzX3RhbmdlbnRzX24gPSBuZXcgVmVjMygpOwogIGNvbnN0IFZlYzNfdGFuZ2VudHNfcmFuZFZlYyA9IG5ldyBWZWMzKCk7CiAgY29uc3QgYW50aXBfbmVnID0gbmV3IFZlYzMoKTsKCiAgLyoqCiAgICogQXhpcyBhbGlnbmVkIGJvdW5kaW5nIGJveCBjbGFzcy4KICAgKi8KICBjbGFzcyBBQUJCIHsKICAgIC8qKgogICAgICogVGhlIGxvd2VyIGJvdW5kIG9mIHRoZSBib3VuZGluZyBib3gKICAgICAqLwoKICAgIC8qKgogICAgICogVGhlIHVwcGVyIGJvdW5kIG9mIHRoZSBib3VuZGluZyBib3gKICAgICAqLwogICAgY29uc3RydWN0b3Iob3B0aW9ucykgewogICAgICBpZiAob3B0aW9ucyA9PT0gdm9pZCAwKSB7CiAgICAgICAgb3B0aW9ucyA9IHt9OwogICAgICB9CgogICAgICB0aGlzLmxvd2VyQm91bmQgPSBuZXcgVmVjMygpOwogICAgICB0aGlzLnVwcGVyQm91bmQgPSBuZXcgVmVjMygpOwoKICAgICAgaWYgKG9wdGlvbnMubG93ZXJCb3VuZCkgewogICAgICAgIHRoaXMubG93ZXJCb3VuZC5jb3B5KG9wdGlvbnMubG93ZXJCb3VuZCk7CiAgICAgIH0KCiAgICAgIGlmIChvcHRpb25zLnVwcGVyQm91bmQpIHsKICAgICAgICB0aGlzLnVwcGVyQm91bmQuY29weShvcHRpb25zLnVwcGVyQm91bmQpOwogICAgICB9CiAgICB9CiAgICAvKioKICAgICAqIFNldCB0aGUgQUFCQiBib3VuZHMgZnJvbSBhIHNldCBvZiBwb2ludHMuCiAgICAgKiBAcGFyYW0gcG9pbnRzIEFuIGFycmF5IG9mIFZlYzMncy4KICAgICAqIEByZXR1cm4gVGhlIHNlbGYgb2JqZWN0CiAgICAgKi8KCgogICAgc2V0RnJvbVBvaW50cyhwb2ludHMsIHBvc2l0aW9uLCBxdWF0ZXJuaW9uLCBza2luU2l6ZSkgewogICAgICBjb25zdCBsID0gdGhpcy5sb3dlckJvdW5kOwogICAgICBjb25zdCB1ID0gdGhpcy51cHBlckJvdW5kOwogICAgICBjb25zdCBxID0gcXVhdGVybmlvbjsgLy8gU2V0IHRvIHRoZSBmaXJzdCBwb2ludAoKICAgICAgbC5jb3B5KHBvaW50c1swXSk7CgogICAgICBpZiAocSkgewogICAgICAgIHEudm11bHQobCwgbCk7CiAgICAgIH0KCiAgICAgIHUuY29weShsKTsKCiAgICAgIGZvciAobGV0IGkgPSAxOyBpIDwgcG9pbnRzLmxlbmd0aDsgaSsrKSB7CiAgICAgICAgbGV0IHAgPSBwb2ludHNbaV07CgogICAgICAgIGlmIChxKSB7CiAgICAgICAgICBxLnZtdWx0KHAsIHRtcCQxKTsKICAgICAgICAgIHAgPSB0bXAkMTsKICAgICAgICB9CgogICAgICAgIGlmIChwLnggPiB1LngpIHsKICAgICAgICAgIHUueCA9IHAueDsKICAgICAgICB9CgogICAgICAgIGlmIChwLnggPCBsLngpIHsKICAgICAgICAgIGwueCA9IHAueDsKICAgICAgICB9CgogICAgICAgIGlmIChwLnkgPiB1LnkpIHsKICAgICAgICAgIHUueSA9IHAueTsKICAgICAgICB9CgogICAgICAgIGlmIChwLnkgPCBsLnkpIHsKICAgICAgICAgIGwueSA9IHAueTsKICAgICAgICB9CgogICAgICAgIGlmIChwLnogPiB1LnopIHsKICAgICAgICAgIHUueiA9IHAuejsKICAgICAgICB9CgogICAgICAgIGlmIChwLnogPCBsLnopIHsKICAgICAgICAgIGwueiA9IHAuejsKICAgICAgICB9CiAgICAgIH0gLy8gQWRkIG9mZnNldAoKCiAgICAgIGlmIChwb3NpdGlvbikgewogICAgICAgIHBvc2l0aW9uLnZhZGQobCwgbCk7CiAgICAgICAgcG9zaXRpb24udmFkZCh1LCB1KTsKICAgICAgfQoKICAgICAgaWYgKHNraW5TaXplKSB7CiAgICAgICAgbC54IC09IHNraW5TaXplOwogICAgICAgIGwueSAtPSBza2luU2l6ZTsKICAgICAgICBsLnogLT0gc2tpblNpemU7CiAgICAgICAgdS54ICs9IHNraW5TaXplOwogICAgICAgIHUueSArPSBza2luU2l6ZTsKICAgICAgICB1LnogKz0gc2tpblNpemU7CiAgICAgIH0KCiAgICAgIHJldHVybiB0aGlzOwogICAgfQogICAgLyoqCiAgICAgKiBDb3B5IGJvdW5kcyBmcm9tIGFuIEFBQkIgdG8gdGhpcyBBQUJCCiAgICAgKiBAcGFyYW0gYWFiYiBTb3VyY2UgdG8gY29weSBmcm9tCiAgICAgKiBAcmV0dXJuIFRoZSB0aGlzIG9iamVjdCwgZm9yIGNoYWluYWJpbGl0eQogICAgICovCgoKICAgIGNvcHkoYWFiYikgewogICAgICB0aGlzLmxvd2VyQm91bmQuY29weShhYWJiLmxvd2VyQm91bmQpOwogICAgICB0aGlzLnVwcGVyQm91bmQuY29weShhYWJiLnVwcGVyQm91bmQpOwogICAgICByZXR1cm4gdGhpczsKICAgIH0KICAgIC8qKgogICAgICogQ2xvbmUgYW4gQUFCQgogICAgICovCgoKICAgIGNsb25lKCkgewogICAgICByZXR1cm4gbmV3IEFBQkIoKS5jb3B5KHRoaXMpOwogICAgfQogICAgLyoqCiAgICAgKiBFeHRlbmQgdGhpcyBBQUJCIHNvIHRoYXQgaXQgY292ZXJzIHRoZSBnaXZlbiBBQUJCIHRvby4KICAgICAqLwoKCiAgICBleHRlbmQoYWFiYikgewogICAgICB0aGlzLmxvd2VyQm91bmQueCA9IE1hdGgubWluKHRoaXMubG93ZXJCb3VuZC54LCBhYWJiLmxvd2VyQm91bmQueCk7CiAgICAgIHRoaXMudXBwZXJCb3VuZC54ID0gTWF0aC5tYXgodGhpcy51cHBlckJvdW5kLngsIGFhYmIudXBwZXJCb3VuZC54KTsKICAgICAgdGhpcy5sb3dlckJvdW5kLnkgPSBNYXRoLm1pbih0aGlzLmxvd2VyQm91bmQueSwgYWFiYi5sb3dlckJvdW5kLnkpOwogICAgICB0aGlzLnVwcGVyQm91bmQueSA9IE1hdGgubWF4KHRoaXMudXBwZXJCb3VuZC55LCBhYWJiLnVwcGVyQm91bmQueSk7CiAgICAgIHRoaXMubG93ZXJCb3VuZC56ID0gTWF0aC5taW4odGhpcy5sb3dlckJvdW5kLnosIGFhYmIubG93ZXJCb3VuZC56KTsKICAgICAgdGhpcy51cHBlckJvdW5kLnogPSBNYXRoLm1heCh0aGlzLnVwcGVyQm91bmQueiwgYWFiYi51cHBlckJvdW5kLnopOwogICAgfQogICAgLyoqCiAgICAgKiBSZXR1cm5zIHRydWUgaWYgdGhlIGdpdmVuIEFBQkIgb3ZlcmxhcHMgdGhpcyBBQUJCLgogICAgICovCgoKICAgIG92ZXJsYXBzKGFhYmIpIHsKICAgICAgY29uc3QgbDEgPSB0aGlzLmxvd2VyQm91bmQ7CiAgICAgIGNvbnN0IHUxID0gdGhpcy51cHBlckJvdW5kOwogICAgICBjb25zdCBsMiA9IGFhYmIubG93ZXJCb3VuZDsKICAgICAgY29uc3QgdTIgPSBhYWJiLnVwcGVyQm91bmQ7IC8vICAgICAgbDIgICAgICAgIHUyCiAgICAgIC8vICAgICAgfC0tLS0tLS0tLXwKICAgICAgLy8gfC0tLS0tLS0tfAogICAgICAvLyBsMSAgICAgICB1MQoKICAgICAgY29uc3Qgb3ZlcmxhcHNYID0gbDIueCA8PSB1MS54ICYmIHUxLnggPD0gdTIueCB8fCBsMS54IDw9IHUyLnggJiYgdTIueCA8PSB1MS54OwogICAgICBjb25zdCBvdmVybGFwc1kgPSBsMi55IDw9IHUxLnkgJiYgdTEueSA8PSB1Mi55IHx8IGwxLnkgPD0gdTIueSAmJiB1Mi55IDw9IHUxLnk7CiAgICAgIGNvbnN0IG92ZXJsYXBzWiA9IGwyLnogPD0gdTEueiAmJiB1MS56IDw9IHUyLnogfHwgbDEueiA8PSB1Mi56ICYmIHUyLnogPD0gdTEuejsKICAgICAgcmV0dXJuIG92ZXJsYXBzWCAmJiBvdmVybGFwc1kgJiYgb3ZlcmxhcHNaOwogICAgfSAvLyBNb3N0bHkgZm9yIGRlYnVnZ2luZwoKCiAgICB2b2x1bWUoKSB7CiAgICAgIGNvbnN0IGwgPSB0aGlzLmxvd2VyQm91bmQ7CiAgICAgIGNvbnN0IHUgPSB0aGlzLnVwcGVyQm91bmQ7CiAgICAgIHJldHVybiAodS54IC0gbC54KSAqICh1LnkgLSBsLnkpICogKHUueiAtIGwueik7CiAgICB9CiAgICAvKioKICAgICAqIFJldHVybnMgdHJ1ZSBpZiB0aGUgZ2l2ZW4gQUFCQiBpcyBmdWxseSBjb250YWluZWQgaW4gdGhpcyBBQUJCLgogICAgICovCgoKICAgIGNvbnRhaW5zKGFhYmIpIHsKICAgICAgY29uc3QgbDEgPSB0aGlzLmxvd2VyQm91bmQ7CiAgICAgIGNvbnN0IHUxID0gdGhpcy51cHBlckJvdW5kOwogICAgICBjb25zdCBsMiA9IGFhYmIubG93ZXJCb3VuZDsKICAgICAgY29uc3QgdTIgPSBhYWJiLnVwcGVyQm91bmQ7IC8vICAgICAgbDIgICAgICAgIHUyCiAgICAgIC8vICAgICAgfC0tLS0tLS0tLXwKICAgICAgLy8gfC0tLS0tLS0tLS0tLS0tLXwKICAgICAgLy8gbDEgICAgICAgICAgICAgIHUxCgogICAgICByZXR1cm4gbDEueCA8PSBsMi54ICYmIHUxLnggPj0gdTIueCAmJiBsMS55IDw9IGwyLnkgJiYgdTEueSA+PSB1Mi55ICYmIGwxLnogPD0gbDIueiAmJiB1MS56ID49IHUyLno7CiAgICB9CgogICAgZ2V0Q29ybmVycyhhLCBiLCBjLCBkLCBlLCBmLCBnLCBoKSB7CiAgICAgIGNvbnN0IGwgPSB0aGlzLmxvd2VyQm91bmQ7CiAgICAgIGNvbnN0IHUgPSB0aGlzLnVwcGVyQm91bmQ7CiAgICAgIGEuY29weShsKTsKICAgICAgYi5zZXQodS54LCBsLnksIGwueik7CiAgICAgIGMuc2V0KHUueCwgdS55LCBsLnopOwogICAgICBkLnNldChsLngsIHUueSwgdS56KTsKICAgICAgZS5zZXQodS54LCBsLnksIHUueik7CiAgICAgIGYuc2V0KGwueCwgdS55LCBsLnopOwogICAgICBnLnNldChsLngsIGwueSwgdS56KTsKICAgICAgaC5jb3B5KHUpOwogICAgfQogICAgLyoqCiAgICAgKiBHZXQgdGhlIHJlcHJlc2VudGF0aW9uIG9mIGFuIEFBQkIgaW4gYW5vdGhlciBmcmFtZS4KICAgICAqIEByZXR1cm4gVGhlICJ0YXJnZXQiIEFBQkIgb2JqZWN0LgogICAgICovCgoKICAgIHRvTG9jYWxGcmFtZShmcmFtZSwgdGFyZ2V0KSB7CiAgICAgIGNvbnN0IGNvcm5lcnMgPSB0cmFuc2Zvcm1JbnRvRnJhbWVfY29ybmVyczsKICAgICAgY29uc3QgYSA9IGNvcm5lcnNbMF07CiAgICAgIGNvbnN0IGIgPSBjb3JuZXJzWzFdOwogICAgICBjb25zdCBjID0gY29ybmVyc1syXTsKICAgICAgY29uc3QgZCA9IGNvcm5lcnNbM107CiAgICAgIGNvbnN0IGUgPSBjb3JuZXJzWzRdOwogICAgICBjb25zdCBmID0gY29ybmVyc1s1XTsKICAgICAgY29uc3QgZyA9IGNvcm5lcnNbNl07CiAgICAgIGNvbnN0IGggPSBjb3JuZXJzWzddOyAvLyBHZXQgY29ybmVycyBpbiBjdXJyZW50IGZyYW1lCgogICAgICB0aGlzLmdldENvcm5lcnMoYSwgYiwgYywgZCwgZSwgZiwgZywgaCk7IC8vIFRyYW5zZm9ybSB0aGVtIHRvIG5ldyBsb2NhbCBmcmFtZQoKICAgICAgZm9yIChsZXQgaSA9IDA7IGkgIT09IDg7IGkrKykgewogICAgICAgIGNvbnN0IGNvcm5lciA9IGNvcm5lcnNbaV07CiAgICAgICAgZnJhbWUucG9pbnRUb0xvY2FsKGNvcm5lciwgY29ybmVyKTsKICAgICAgfQoKICAgICAgcmV0dXJuIHRhcmdldC5zZXRGcm9tUG9pbnRzKGNvcm5lcnMpOwogICAgfQogICAgLyoqCiAgICAgKiBHZXQgdGhlIHJlcHJlc2VudGF0aW9uIG9mIGFuIEFBQkIgaW4gdGhlIGdsb2JhbCBmcmFtZS4KICAgICAqIEByZXR1cm4gVGhlICJ0YXJnZXQiIEFBQkIgb2JqZWN0LgogICAgICovCgoKICAgIHRvV29ybGRGcmFtZShmc