foop
Version:
interfaces that describe their intentions.
288 lines (287 loc) • 24 kB
JavaScript
// // https://github.com/processing-js/processing-js/blob/master/src/Objects/ArrayList.js
//
// /**
// * An ArrayList stores a variable number of objects.
// *
// * @param {int} initialCapacity optional defines the initial capacity of the list, it's empty by default
// *
// * @returns {ArrayList} new ArrayList object
// */
// module.exports = function(options) {
// var virtHashCode = options.virtHashCode
// var virtEquals = options.virtEquals
//
// function Iterator(array) {
// var index = -1
// this.hasNext = function() {
// return (index + 1) < array.length
// }
//
// this.next = function() {
// return array[++index]
// }
//
// this.remove = function() {
// array.splice(index--, 1)
// }
// }
//
// function ArrayList(a) {
// var array = []
//
// if (a && a.toArray) {
// array = a.toArray()
// }
//
// /**
// * @memberof ArrayList
// * ArrayList.get() Returns the element at the specified position in this list.
// *
// * @param {int} i index of element to return
// *
// * @returns {Object} the element at the specified position in this list.
// */
// this.get = function(i) {
// return array[i]
// }
// /**
// * @memberof ArrayList
// * ArrayList.contains() Returns true if this list contains the specified element.
// *
// * @param {Object} item element whose presence in this List is to be tested.
// *
// * @returns {boolean} true if the specified element is present; false otherwise.
// */
// this.contains = function(item) {
// return this.indexOf(item) > -1
// }
// /**
// * @memberof ArrayList
// * ArrayList.indexOf() Returns the position this element takes in the list, or -1 if the element is not found.
// *
// * @param {Object} item element whose position in this List is to be tested.
// *
// * @returns {int} the list position that the first match for this element holds in the list, or -1 if it is not in the list.
// */
// this.indexOf = function(item) {
// for (var i = 0, len = array.length; i < len; ++i) {
// if (virtEquals(item, array[i])) {
// return i
// }
// }
// return -1
// }
// /**
// * @memberof ArrayList
// * ArrayList.lastIndexOf() Returns the index of the last occurrence of the specified element in this list,
// * or -1 if this list does not contain the element. More formally, returns the highest index i such that
// * (o==null ? get(i)==null : o.equals(get(i))), or -1 if there is no such index.
// *
// * @param {Object} item element to search for.
// *
// * @returns {int} the index of the last occurrence of the specified element in this list, or -1 if this list does not contain the element.
// */
// this.lastIndexOf = function(item) {
// for (var i = array.length - 1; i >= 0; --i) {
// if (virtEquals(item, array[i])) {
// return i
// }
// }
// return -1
// }
// /**
// * @memberof ArrayList
// * ArrayList.add() Adds the specified element to this list.
// *
// * @param {int} index optional index at which the specified element is to be inserted
// * @param {Object} object element to be added to the list
// */
// this.add = function() {
// if (arguments.length === 1) {
// array.push(arguments[0]) // for add(Object)
// }
// else if (arguments.length === 2) {
// var arg0 = arguments[0]
// if (typeof arg0 === 'number') {
// if (arg0 >= 0 && arg0 <= array.length) {
// array.splice(arg0, 0, arguments[1]) // for add(i, Object)
// }
// else {
// throw (arg0 + ' is not a valid index')
// }
// }
// else {
// throw (typeof arg0 + ' is not a number')
// }
// }
// else {
// throw new InvalidArguments('Please use the proper number of parameters.')
// }
// }
// /**
// * @memberof ArrayList
// * ArrayList.addAll(collection) appends all of the elements in the specified
// * Collection to the end of this list, in the order that they are returned by
// * the specified Collection's Iterator.
// *
// * When called as addAll(index, collection) the elements are inserted into
// * this list at the position indicated by index.
// *
// * @param {index} Optional; specifies the position the colletion should be inserted at
// * @param {collection} Any iterable object (ArrayList, HashMap.keySet(), etc.)
// * @throws out of bounds error for negative index, or index greater than list size.
// */
// this.addAll = function(arg1, arg2) {
// // addAll(int, Collection)
// var it
// if (typeof arg1 === 'number') {
// if (arg1 < 0 || arg1 > array.length) {
// throw ('Index out of bounds for addAll: ' + arg1 + ' greater or equal than ' + array.length)
// }
// it = new ObjectIterator(arg2)
// while (it.hasNext()) {
// array.splice(arg1++, 0, it.next())
// }
// }
// // addAll(Collection)
// else {
// it = new ObjectIterator(arg1)
// while (it.hasNext()) {
// array.push(it.next())
// }
// }
// }
// /**
// * @memberof ArrayList
// * ArrayList.set() Replaces the element at the specified position in this list with the specified element.
// *
// * @param {int} index index of element to replace
// * @param {Object} object element to be stored at the specified position
// */
// this.set = function() {
// if (arguments.length === 2) {
// var arg0 = arguments[0]
// if (typeof arg0 === 'number') {
// if (arg0 >= 0 && arg0 < array.length) {
// array.splice(arg0, 1, arguments[1])
// }
// else {
// throw (arg0 + ' is not a valid index.')
// }
// }
// else {
// throw (typeof arg0 + ' is not a number')
// }
// }
// else {
// throw ('Please use the proper number of parameters.')
// }
// }
//
// /**
// * @memberof ArrayList
// * ArrayList.size() Returns the number of elements in this list.
// *
// * @returns {int} the number of elements in this list
// */
// this.size = function() {
// return array.length
// }
//
// /**
// * @memberof ArrayList
// * ArrayList.clear() Removes all of the elements from this list.
// * The list will be empty after this call returns.
// */
// this.clear = function() {
// array.length = 0
// }
//
// /**
// * @memberof ArrayList
// * ArrayList.remove() Removes an element either based on index, if the argument is a number, or
// * by equality check, if the argument is an object.
// *
// * @param {int|Object} item either the index of the element to be removed, or the element itself.
// *
// * @returns {Object|boolean} If removal is by index, the element that was removed, or null if nothing was removed. If removal is by object, true if removal occurred, otherwise false.
// */
// this.remove = function(item) {
// if (typeof item === 'number') {
// return array.splice(item, 1)[0]
// }
// item = this.indexOf(item)
// if (item > -1) {
// array.splice(item, 1)
// return true
// }
// return false
// }
//
// /**
// * @memberof ArrayList
// * ArrayList.removeAll Removes from this List all of the elements from
// * the current ArrayList which are present in the passed in paramater ArrayList 'c'.
// * Shifts any succeeding elements to the left (reduces their index).
// *
// * @param {ArrayList} the ArrayList to compare to the current ArrayList
// *
// * @returns {boolean} true if the ArrayList had an element removed; false otherwise
// */
// this.removeAll = function(c) {
// var i, x, item,
// newList = new ArrayList()
// newList.addAll(this)
// this.clear()
// // For every item that exists in the original ArrayList and not in the c ArrayList
// // copy it into the empty 'this' ArrayList to create the new 'this' Array.
// for (i = 0, x = 0; i < newList.size(); i++) {
// item = newList.get(i)
// if (!c.contains(item)) {
// this.add(x++, item)
// }
// }
// if (this.size() < newList.size()) {
// return true
// }
// return false
// }
//
// /**
// * @memberof ArrayList
// * ArrayList.isEmpty() Tests if this list has no elements.
// *
// * @returns {boolean} true if this list has no elements; false otherwise
// */
// this.isEmpty = function() {
// return !array.length
// }
//
// /**
// * @memberof ArrayList
// * ArrayList.clone() Returns a shallow copy of this ArrayList instance. (The elements themselves are not copied.)
// *
// * @returns {ArrayList} a clone of this ArrayList instance
// */
// this.clone = function() {
// return new ArrayList(this)
// }
//
// /**
// * @memberof ArrayList
// * ArrayList.toArray() Returns an array containing all of the elements in this list in the correct order.
// *
// * @returns {Object[]} Returns an array containing all of the elements in this list in the correct order
// */
// this.toArray = function() {
// return array.slice(0)
// }
//
// this.iterator = function() {
// return new Iterator(array)
// }
// }
//
// return ArrayList
// }
//# sourceMappingURL=data:application/json;charset=utf-8;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiQXJyYXlMaXN0LmpzIiwic291cmNlcyI6WyJBcnJheUxpc3QuanMiXSwic291cmNlc0NvbnRlbnQiOlsiLy8gLy8gaHR0cHM6Ly9naXRodWIuY29tL3Byb2Nlc3NpbmctanMvcHJvY2Vzc2luZy1qcy9ibG9iL21hc3Rlci9zcmMvT2JqZWN0cy9BcnJheUxpc3QuanNcbi8vXG4vLyAvKipcbi8vICAqIEFuIEFycmF5TGlzdCBzdG9yZXMgYSB2YXJpYWJsZSBudW1iZXIgb2Ygb2JqZWN0cy5cbi8vICAqXG4vLyAgKiBAcGFyYW0ge2ludH0gaW5pdGlhbENhcGFjaXR5IG9wdGlvbmFsIGRlZmluZXMgdGhlIGluaXRpYWwgY2FwYWNpdHkgb2YgdGhlIGxpc3QsIGl0J3MgZW1wdHkgYnkgZGVmYXVsdFxuLy8gICpcbi8vICAqIEByZXR1cm5zIHtBcnJheUxpc3R9IG5ldyBBcnJheUxpc3Qgb2JqZWN0XG4vLyAgKi9cbi8vIG1vZHVsZS5leHBvcnRzID0gZnVuY3Rpb24ob3B0aW9ucykge1xuLy8gICB2YXIgdmlydEhhc2hDb2RlID0gb3B0aW9ucy52aXJ0SGFzaENvZGVcbi8vICAgdmFyIHZpcnRFcXVhbHMgPSBvcHRpb25zLnZpcnRFcXVhbHNcbi8vXG4vLyAgIGZ1bmN0aW9uIEl0ZXJhdG9yKGFycmF5KSB7XG4vLyAgICAgdmFyIGluZGV4ID0gLTFcbi8vICAgICB0aGlzLmhhc05leHQgPSBmdW5jdGlvbigpIHtcbi8vICAgICAgIHJldHVybiAoaW5kZXggKyAxKSA8IGFycmF5Lmxlbmd0aFxuLy8gICAgIH1cbi8vXG4vLyAgICAgdGhpcy5uZXh0ID0gZnVuY3Rpb24oKSB7XG4vLyAgICAgICByZXR1cm4gYXJyYXlbKytpbmRleF1cbi8vICAgICB9XG4vL1xuLy8gICAgIHRoaXMucmVtb3ZlID0gZnVuY3Rpb24oKSB7XG4vLyAgICAgICBhcnJheS5zcGxpY2UoaW5kZXgtLSwgMSlcbi8vICAgICB9XG4vLyAgIH1cbi8vXG4vLyAgIGZ1bmN0aW9uIEFycmF5TGlzdChhKSB7XG4vLyAgICAgdmFyIGFycmF5ID0gW11cbi8vXG4vLyAgICAgaWYgKGEgJiYgYS50b0FycmF5KSB7XG4vLyAgICAgICBhcnJheSA9IGEudG9BcnJheSgpXG4vLyAgICAgfVxuLy9cbi8vICAgICAvKipcbi8vICAgICAgKiBAbWVtYmVyb2YgQXJyYXlMaXN0XG4vLyAgICAgICogQXJyYXlMaXN0LmdldCgpIFJldHVybnMgdGhlIGVsZW1lbnQgYXQgdGhlIHNwZWNpZmllZCBwb3NpdGlvbiBpbiB0aGlzIGxpc3QuXG4vLyAgICAgICpcbi8vICAgICAgKiBAcGFyYW0ge2ludH0gaSBpbmRleCBvZiBlbGVtZW50IHRvIHJldHVyblxuLy8gICAgICAqXG4vLyAgICAgICogQHJldHVybnMge09iamVjdH0gdGhlIGVsZW1lbnQgYXQgdGhlIHNwZWNpZmllZCBwb3NpdGlvbiBpbiB0aGlzIGxpc3QuXG4vLyAgICAgICovXG4vLyAgICAgdGhpcy5nZXQgPSBmdW5jdGlvbihpKSB7XG4vLyAgICAgICByZXR1cm4gYXJyYXlbaV1cbi8vICAgICB9XG4vLyAgICAgLyoqXG4vLyAgICAgICogQG1lbWJlcm9mIEFycmF5TGlzdFxuLy8gICAgICAqIEFycmF5TGlzdC5jb250YWlucygpIFJldHVybnMgdHJ1ZSBpZiB0aGlzIGxpc3QgY29udGFpbnMgdGhlIHNwZWNpZmllZCBlbGVtZW50LlxuLy8gICAgICAqXG4vLyAgICAgICogQHBhcmFtIHtPYmplY3R9IGl0ZW0gZWxlbWVudCB3aG9zZSBwcmVzZW5jZSBpbiB0aGlzIExpc3QgaXMgdG8gYmUgdGVzdGVkLlxuLy8gICAgICAqXG4vLyAgICAgICogQHJldHVybnMge2Jvb2xlYW59IHRydWUgaWYgdGhlIHNwZWNpZmllZCBlbGVtZW50IGlzIHByZXNlbnQ7IGZhbHNlIG90aGVyd2lzZS5cbi8vICAgICAgKi9cbi8vICAgICB0aGlzLmNvbnRhaW5zID0gZnVuY3Rpb24oaXRlbSkge1xuLy8gICAgICAgcmV0dXJuIHRoaXMuaW5kZXhPZihpdGVtKSA+IC0xXG4vLyAgICAgfVxuLy8gICAgIC8qKlxuLy8gICAgICAqIEBtZW1iZXJvZiBBcnJheUxpc3Rcbi8vICAgICAgKiBBcnJheUxpc3QuaW5kZXhPZigpIFJldHVybnMgdGhlIHBvc2l0aW9uIHRoaXMgZWxlbWVudCB0YWtlcyBpbiB0aGUgbGlzdCwgb3IgLTEgaWYgdGhlIGVsZW1lbnQgaXMgbm90IGZvdW5kLlxuLy8gICAgICAqXG4vLyAgICAgICogQHBhcmFtIHtPYmplY3R9IGl0ZW0gZWxlbWVudCB3aG9zZSBwb3NpdGlvbiBpbiB0aGlzIExpc3QgaXMgdG8gYmUgdGVzdGVkLlxuLy8gICAgICAqXG4vLyAgICAgICogQHJldHVybnMge2ludH0gdGhlIGxpc3QgcG9zaXRpb24gdGhhdCB0aGUgZmlyc3QgbWF0Y2ggZm9yIHRoaXMgZWxlbWVudCBob2xkcyBpbiB0aGUgbGlzdCwgb3IgLTEgaWYgaXQgaXMgbm90IGluIHRoZSBsaXN0LlxuLy8gICAgICAqL1xuLy8gICAgIHRoaXMuaW5kZXhPZiA9IGZ1bmN0aW9uKGl0ZW0pIHtcbi8vICAgICAgIGZvciAodmFyIGkgPSAwLCBsZW4gPSBhcnJheS5sZW5ndGg7IGkgPCBsZW47ICsraSkge1xuLy8gICAgICAgICBpZiAodmlydEVxdWFscyhpdGVtLCBhcnJheVtpXSkpIHtcbi8vICAgICAgICAgICByZXR1cm4gaVxuLy8gICAgICAgICB9XG4vLyAgICAgICB9XG4vLyAgICAgICByZXR1cm4gLTFcbi8vICAgICB9XG4vLyAgICAgLyoqXG4vLyAgICAgICogQG1lbWJlcm9mIEFycmF5TGlzdFxuLy8gICAgICAqIEFycmF5TGlzdC5sYXN0SW5kZXhPZigpIFJldHVybnMgdGhlIGluZGV4IG9mIHRoZSBsYXN0IG9jY3VycmVuY2Ugb2YgdGhlIHNwZWNpZmllZCBlbGVtZW50IGluIHRoaXMgbGlzdCxcbi8vICAgICAgKiBvciAtMSBpZiB0aGlzIGxpc3QgZG9lcyBub3QgY29udGFpbiB0aGUgZWxlbWVudC4gTW9yZSBmb3JtYWxseSwgcmV0dXJucyB0aGUgaGlnaGVzdCBpbmRleCBpIHN1Y2ggdGhhdFxuLy8gICAgICAqIChvPT1udWxsID8gZ2V0KGkpPT1udWxsIDogby5lcXVhbHMoZ2V0KGkpKSksIG9yIC0xIGlmIHRoZXJlIGlzIG5vIHN1Y2ggaW5kZXguXG4vLyAgICAgICpcbi8vICAgICAgKiBAcGFyYW0ge09iamVjdH0gaXRlbSBlbGVtZW50IHRvIHNlYXJjaCBmb3IuXG4vLyAgICAgICpcbi8vICAgICAgKiBAcmV0dXJucyB7aW50fSB0aGUgaW5kZXggb2YgdGhlIGxhc3Qgb2NjdXJyZW5jZSBvZiB0aGUgc3BlY2lmaWVkIGVsZW1lbnQgaW4gdGhpcyBsaXN0LCBvciAtMSBpZiB0aGlzIGxpc3QgZG9lcyBub3QgY29udGFpbiB0aGUgZWxlbWVudC5cbi8vICAgICAgKi9cbi8vICAgICB0aGlzLmxhc3RJbmRleE9mID0gZnVuY3Rpb24oaXRlbSkge1xuLy8gICAgICAgZm9yICh2YXIgaSA9IGFycmF5Lmxlbmd0aCAtIDE7IGkgPj0gMDsgLS1pKSB7XG4vLyAgICAgICAgIGlmICh2aXJ0RXF1YWxzKGl0ZW0sIGFycmF5W2ldKSkge1xuLy8gICAgICAgICAgIHJldHVybiBpXG4vLyAgICAgICAgIH1cbi8vICAgICAgIH1cbi8vICAgICAgIHJldHVybiAtMVxuLy8gICAgIH1cbi8vICAgICAvKipcbi8vICAgICAgKiBAbWVtYmVyb2YgQXJyYXlMaXN0XG4vLyAgICAgICogQXJyYXlMaXN0LmFkZCgpIEFkZHMgdGhlIHNwZWNpZmllZCBlbGVtZW50IHRvIHRoaXMgbGlzdC5cbi8vICAgICAgKlxuLy8gICAgICAqIEBwYXJhbSB7aW50fSAgICBpbmRleCAgb3B0aW9uYWwgaW5kZXggYXQgd2hpY2ggdGhlIHNwZWNpZmllZCBlbGVtZW50IGlzIHRvIGJlIGluc2VydGVkXG4vLyAgICAgICogQHBhcmFtIHtPYmplY3R9IG9iamVjdCBlbGVtZW50IHRvIGJlIGFkZGVkIHRvIHRoZSBsaXN0XG4vLyAgICAgICovXG4vLyAgICAgdGhpcy5hZGQgPSBmdW5jdGlvbigpIHtcbi8vICAgICAgIGlmIChhcmd1bWVudHMubGVuZ3RoID09PSAxKSB7XG4vLyAgICAgICAgIGFycmF5LnB1c2goYXJndW1lbnRzWzBdKSAvLyBmb3IgYWRkKE9iamVjdClcbi8vICAgICAgIH1cbi8vICAgICAgIGVsc2UgaWYgKGFyZ3VtZW50cy5sZW5ndGggPT09IDIpIHtcbi8vICAgICAgICAgdmFyIGFyZzAgPSBhcmd1bWVudHNbMF1cbi8vICAgICAgICAgaWYgKHR5cGVvZiBhcmcwID09PSAnbnVtYmVyJykge1xuLy8gICAgICAgICAgIGlmIChhcmcwID49IDAgJiYgYXJnMCA8PSBhcnJheS5sZW5ndGgpIHtcbi8vICAgICAgICAgICAgIGFycmF5LnNwbGljZShhcmcwLCAwLCBhcmd1bWVudHNbMV0pIC8vIGZvciBhZGQoaSwgT2JqZWN0KVxuLy8gICAgICAgICAgIH1cbi8vICAgICAgICAgICBlbHNlIHtcbi8vICAgICAgICAgICAgIHRocm93IChhcmcwICsgJyBpcyBub3QgYSB2YWxpZCBpbmRleCcpXG4vLyAgICAgICAgICAgfVxuLy8gICAgICAgICB9XG4vLyAgICAgICAgIGVsc2Uge1xuLy8gICAgICAgICAgIHRocm93ICh0eXBlb2YgYXJnMCArICcgaXMgbm90IGEgbnVtYmVyJylcbi8vICAgICAgICAgfVxuLy8gICAgICAgfVxuLy8gICAgICAgZWxzZSB7XG4vLyAgICAgICAgIHRocm93IG5ldyBJbnZhbGlkQXJndW1lbnRzKCdQbGVhc2UgdXNlIHRoZSBwcm9wZXIgbnVtYmVyIG9mIHBhcmFtZXRlcnMuJylcbi8vICAgICAgIH1cbi8vICAgICB9XG4vLyAgICAgLyoqXG4vLyAgICAgICogQG1lbWJlcm9mIEFycmF5TGlzdFxuLy8gICAgICAqIEFycmF5TGlzdC5hZGRBbGwoY29sbGVjdGlvbikgYXBwZW5kcyBhbGwgb2YgdGhlIGVsZW1lbnRzIGluIHRoZSBzcGVjaWZpZWRcbi8vICAgICAgKiBDb2xsZWN0aW9uIHRvIHRoZSBlbmQgb2YgdGhpcyBsaXN0LCBpbiB0aGUgb3JkZXIgdGhhdCB0aGV5IGFyZSByZXR1cm5lZCBieVxuLy8gICAgICAqIHRoZSBzcGVjaWZpZWQgQ29sbGVjdGlvbidzIEl0ZXJhdG9yLlxuLy8gICAgICAqXG4vLyAgICAgICogV2hlbiBjYWxsZWQgYXMgYWRkQWxsKGluZGV4LCBjb2xsZWN0aW9uKSB0aGUgZWxlbWVudHMgYXJlIGluc2VydGVkIGludG9cbi8vICAgICAgKiB0aGlzIGxpc3QgYXQgdGhlIHBvc2l0aW9uIGluZGljYXRlZCBieSBpbmRleC5cbi8vICAgICAgKlxuLy8gICAgICAqIEBwYXJhbSB7aW5kZXh9IE9wdGlvbmFsOyBzcGVjaWZpZXMgdGhlIHBvc2l0aW9uIHRoZSBjb2xsZXRpb24gc2hvdWxkIGJlIGluc2VydGVkIGF0XG4vLyAgICAgICogQHBhcmFtIHtjb2xsZWN0aW9ufSBBbnkgaXRlcmFibGUgb2JqZWN0IChBcnJheUxpc3QsIEhhc2hNYXAua2V5U2V0KCksIGV0Yy4pXG4vLyAgICAgICogQHRocm93cyBvdXQgb2YgYm91bmRzIGVycm9yIGZvciBuZWdhdGl2ZSBpbmRleCwgb3IgaW5kZXggZ3JlYXRlciB0aGFuIGxpc3Qgc2l6ZS5cbi8vICAgICAgKi9cbi8vICAgICB0aGlzLmFkZEFsbCA9IGZ1bmN0aW9uKGFyZzEsIGFyZzIpIHtcbi8vICAgICAgIC8vIGFkZEFsbChpbnQsIENvbGxlY3Rpb24pXG4vLyAgICAgICB2YXIgaXRcbi8vICAgICAgIGlmICh0eXBlb2YgYXJnMSA9PT0gJ251bWJlcicpIHtcbi8vICAgICAgICAgaWYgKGFyZzEgPCAwIHx8IGFyZzEgPiBhcnJheS5sZW5ndGgpIHtcbi8vICAgICAgICAgICB0aHJvdyAoJ0luZGV4IG91dCBvZiBib3VuZHMgZm9yIGFkZEFsbDogJyArIGFyZzEgKyAnIGdyZWF0ZXIgb3IgZXF1YWwgdGhhbiAnICsgYXJyYXkubGVuZ3RoKVxuLy8gICAgICAgICB9XG4vLyAgICAgICAgIGl0ID0gbmV3IE9iamVjdEl0ZXJhdG9yKGFyZzIpXG4vLyAgICAgICAgIHdoaWxlIChpdC5oYXNOZXh0KCkpIHtcbi8vICAgICAgICAgICBhcnJheS5zcGxpY2UoYXJnMSsrLCAwLCBpdC5uZXh0KCkpXG4vLyAgICAgICAgIH1cbi8vICAgICAgIH1cbi8vICAgICAgIC8vIGFkZEFsbChDb2xsZWN0aW9uKVxuLy8gICAgICAgZWxzZSB7XG4vLyAgICAgICAgIGl0ID0gbmV3IE9iamVjdEl0ZXJhdG9yKGFyZzEpXG4vLyAgICAgICAgIHdoaWxlIChpdC5oYXNOZXh0KCkpIHtcbi8vICAgICAgICAgICBhcnJheS5wdXNoKGl0Lm5leHQoKSlcbi8vICAgICAgICAgfVxuLy8gICAgICAgfVxuLy8gICAgIH1cbi8vICAgICAvKipcbi8vICAgICAgKiBAbWVtYmVyb2YgQXJyYXlMaXN0XG4vLyAgICAgICogQXJyYXlMaXN0LnNldCgpIFJlcGxhY2VzIHRoZSBlbGVtZW50IGF0IHRoZSBzcGVjaWZpZWQgcG9zaXRpb24gaW4gdGhpcyBsaXN0IHdpdGggdGhlIHNwZWNpZmllZCBlbGVtZW50LlxuLy8gICAgICAqXG4vLyAgICAgICogQHBhcmFtIHtpbnR9ICAgIGluZGV4ICBpbmRleCBvZiBlbGVtZW50IHRvIHJlcGxhY2Vcbi8vICAgICAgKiBAcGFyYW0ge09iamVjdH0gb2JqZWN0IGVsZW1lbnQgdG8gYmUgc3RvcmVkIGF0IHRoZSBzcGVjaWZpZWQgcG9zaXRpb25cbi8vICAgICAgKi9cbi8vICAgICB0aGlzLnNldCA9IGZ1bmN0aW9uKCkge1xuLy8gICAgICAgaWYgKGFyZ3VtZW50cy5sZW5ndGggPT09IDIpIHtcbi8vICAgICAgICAgdmFyIGFyZzAgPSBhcmd1bWVudHNbMF1cbi8vICAgICAgICAgaWYgKHR5cGVvZiBhcmcwID09PSAnbnVtYmVyJykge1xuLy8gICAgICAgICAgIGlmIChhcmcwID49IDAgJiYgYXJnMCA8IGFycmF5Lmxlbmd0aCkge1xuLy8gICAgICAgICAgICAgYXJyYXkuc3BsaWNlKGFyZzAsIDEsIGFyZ3VtZW50c1sxXSlcbi8vICAgICAgICAgICB9XG4vLyAgICAgICAgICAgZWxzZSB7XG4vLyAgICAgICAgICAgICB0aHJvdyAoYXJnMCArICcgaXMgbm90IGEgdmFsaWQgaW5kZXguJylcbi8vICAgICAgICAgICB9XG4vLyAgICAgICAgIH1cbi8vICAgICAgICAgZWxzZSB7XG4vLyAgICAgICAgICAgdGhyb3cgKHR5cGVvZiBhcmcwICsgJyBpcyBub3QgYSBudW1iZXInKVxuLy8gICAgICAgICB9XG4vLyAgICAgICB9XG4vLyAgICAgICBlbHNlIHtcbi8vICAgICAgICAgdGhyb3cgKCdQbGVhc2UgdXNlIHRoZSBwcm9wZXIgbnVtYmVyIG9mIHBhcmFtZXRlcnMuJylcbi8vICAgICAgIH1cbi8vICAgICB9XG4vL1xuLy8gICAgIC8qKlxuLy8gICAgICAqIEBtZW1iZXJvZiBBcnJheUxpc3Rcbi8vICAgICAgKiBBcnJheUxpc3Quc2l6ZSgpIFJldHVybnMgdGhlIG51bWJlciBvZiBlbGVtZW50cyBpbiB0aGlzIGxpc3QuXG4vLyAgICAgICpcbi8vICAgICAgKiBAcmV0dXJucyB7aW50fSB0aGUgbnVtYmVyIG9mIGVsZW1lbnRzIGluIHRoaXMgbGlzdFxuLy8gICAgICAqL1xuLy8gICAgIHRoaXMuc2l6ZSA9IGZ1bmN0aW9uKCkge1xuLy8gICAgICAgcmV0dXJuIGFycmF5Lmxlbmd0aFxuLy8gICAgIH1cbi8vXG4vLyAgICAgLyoqXG4vLyAgICAgICogQG1lbWJlcm9mIEFycmF5TGlzdFxuLy8gICAgICAqIEFycmF5TGlzdC5jbGVhcigpIFJlbW92ZXMgYWxsIG9mIHRoZSBlbGVtZW50cyBmcm9tIHRoaXMgbGlzdC5cbi8vICAgICAgKiBUaGUgbGlzdCB3aWxsIGJlIGVtcHR5IGFmdGVyIHRoaXMgY2FsbCByZXR1cm5zLlxuLy8gICAgICAqL1xuLy8gICAgIHRoaXMuY2xlYXIgPSBmdW5jdGlvbigpIHtcbi8vICAgICAgIGFycmF5Lmxlbmd0aCA9IDBcbi8vICAgICB9XG4vL1xuLy8gICAgIC8qKlxuLy8gICAgICAqIEBtZW1iZXJvZiBBcnJheUxpc3Rcbi8vICAgICAgKiBBcnJheUxpc3QucmVtb3ZlKCkgUmVtb3ZlcyBhbiBlbGVtZW50IGVpdGhlciBiYXNlZCBvbiBpbmRleCwgaWYgdGhlIGFyZ3VtZW50IGlzIGEgbnVtYmVyLCBvclxuLy8gICAgICAqIGJ5IGVxdWFsaXR5IGNoZWNrLCBpZiB0aGUgYXJndW1lbnQgaXMgYW4gb2JqZWN0LlxuLy8gICAgICAqXG4vLyAgICAgICogQHBhcmFtIHtpbnR8T2JqZWN0fSBpdGVtIGVpdGhlciB0aGUgaW5kZXggb2YgdGhlIGVsZW1lbnQgdG8gYmUgcmVtb3ZlZCwgb3IgdGhlIGVsZW1lbnQgaXRzZWxmLlxuLy8gICAgICAqXG4vLyAgICAgICogQHJldHVybnMge09iamVjdHxib29sZWFufSBJZiByZW1vdmFsIGlzIGJ5IGluZGV4LCB0aGUgZWxlbWVudCB0aGF0IHdhcyByZW1vdmVkLCBvciBudWxsIGlmIG5vdGhpbmcgd2FzIHJlbW92ZWQuIElmIHJlbW92YWwgaXMgYnkgb2JqZWN0LCB0cnVlIGlmIHJlbW92YWwgb2NjdXJyZWQsIG90aGVyd2lzZSBmYWxzZS5cbi8vICAgICAgKi9cbi8vICAgICB0aGlzLnJlbW92ZSA9IGZ1bmN0aW9uKGl0ZW0pIHtcbi8vICAgICAgIGlmICh0eXBlb2YgaXRlbSA9PT0gJ251bWJlcicpIHtcbi8vICAgICAgICAgcmV0dXJuIGFycmF5LnNwbGljZShpdGVtLCAxKVswXVxuLy8gICAgICAgfVxuLy8gICAgICAgaXRlbSA9IHRoaXMuaW5kZXhPZihpdGVtKVxuLy8gICAgICAgaWYgKGl0ZW0gPiAtMSkge1xuLy8gICAgICAgICBhcnJheS5zcGxpY2UoaXRlbSwgMSlcbi8vICAgICAgICAgcmV0dXJuIHRydWVcbi8vICAgICAgIH1cbi8vICAgICAgIHJldHVybiBmYWxzZVxuLy8gICAgIH1cbi8vXG4vLyAgICAgLyoqXG4vLyAgICAgICogQG1lbWJlcm9mIEFycmF5TGlzdFxuLy8gICAgICAqIEFycmF5TGlzdC5yZW1vdmVBbGwgUmVtb3ZlcyBmcm9tIHRoaXMgTGlzdCBhbGwgb2YgdGhlIGVsZW1lbnRzIGZyb21cbi8vICAgICAgKiB0aGUgY3VycmVudCBBcnJheUxpc3Qgd2hpY2ggYXJlIHByZXNlbnQgaW4gdGhlIHBhc3NlZCBpbiBwYXJhbWF0ZXIgQXJyYXlMaXN0ICdjJy5cbi8vICAgICAgKiBTaGlmdHMgYW55IHN1Y2NlZWRpbmcgZWxlbWVudHMgdG8gdGhlIGxlZnQgKHJlZHVjZXMgdGhlaXIgaW5kZXgpLlxuLy8gICAgICAqXG4vLyAgICAgICogQHBhcmFtIHtBcnJheUxpc3R9IHRoZSBBcnJheUxpc3QgdG8gY29tcGFyZSB0byB0aGUgY3VycmVudCBBcnJheUxpc3Rcbi8vICAgICAgKlxuLy8gICAgICAqIEByZXR1cm5zIHtib29sZWFufSB0cnVlIGlmIHRoZSBBcnJheUxpc3QgaGFkIGFuIGVsZW1lbnQgcmVtb3ZlZDsgZmFsc2Ugb3RoZXJ3aXNlXG4vLyAgICAgICovXG4vLyAgICAgdGhpcy5yZW1vdmVBbGwgPSBmdW5jdGlvbihjKSB7XG4vLyAgICAgICB2YXIgaSwgeCwgaXRlbSxcbi8vICAgICAgICAgbmV3TGlzdCA9IG5ldyBBcnJheUxpc3QoKVxuLy8gICAgICAgbmV3TGlzdC5hZGRBbGwodGhpcylcbi8vICAgICAgIHRoaXMuY2xlYXIoKVxuLy8gICAgICAgLy8gRm9yIGV2ZXJ5IGl0ZW0gdGhhdCBleGlzdHMgaW4gdGhlIG9yaWdpbmFsIEFycmF5TGlzdCBhbmQgbm90IGluIHRoZSBjIEFycmF5TGlzdFxuLy8gICAgICAgLy8gY29weSBpdCBpbnRvIHRoZSBlbXB0eSAndGhpcycgQXJyYXlMaXN0IHRvIGNyZWF0ZSB0aGUgbmV3ICd0aGlzJyBBcnJheS5cbi8vICAgICAgIGZvciAoaSA9IDAsIHggPSAwOyBpIDwgbmV3TGlzdC5zaXplKCk7IGkrKykge1xuLy8gICAgICAgICBpdGVtID0gbmV3TGlzdC5nZXQoaSlcbi8vICAgICAgICAgaWYgKCFjLmNvbnRhaW5zKGl0ZW0pKSB7XG4vLyAgICAgICAgICAgdGhpcy5hZGQoeCsrLCBpdGVtKVxuLy8gICAgICAgICB9XG4vLyAgICAgICB9XG4vLyAgICAgICBpZiAodGhpcy5zaXplKCkgPCBuZXdMaXN0LnNpemUoKSkge1xuLy8gICAgICAgICByZXR1cm4gdHJ1ZVxuLy8gICAgICAgfVxuLy8gICAgICAgcmV0dXJuIGZhbHNlXG4vLyAgICAgfVxuLy9cbi8vICAgICAvKipcbi8vICAgICAgKiBAbWVtYmVyb2YgQXJyYXlMaXN0XG4vLyAgICAgICogQXJyYXlMaXN0LmlzRW1wdHkoKSBUZXN0cyBpZiB0aGlzIGxpc3QgaGFzIG5vIGVsZW1lbnRzLlxuLy8gICAgICAqXG4vLyAgICAgICogQHJldHVybnMge2Jvb2xlYW59IHRydWUgaWYgdGhpcyBsaXN0IGhhcyBubyBlbGVtZW50czsgZmFsc2Ugb3RoZXJ3aXNlXG4vLyAgICAgICovXG4vLyAgICAgdGhpcy5pc0VtcHR5ID0gZnVuY3Rpb24oKSB7XG4vLyAgICAgICByZXR1cm4gIWFycmF5Lmxlbmd0aFxuLy8gICAgIH1cbi8vXG4vLyAgICAgLyoqXG4vLyAgICAgICogQG1lbWJlcm9mIEFycmF5TGlzdFxuLy8gICAgICAqIEFycmF5TGlzdC5jbG9uZSgpIFJldHVybnMgYSBzaGFsbG93IGNvcHkgb2YgdGhpcyBBcnJheUxpc3QgaW5zdGFuY2UuIChUaGUgZWxlbWVudHMgdGhlbXNlbHZlcyBhcmUgbm90IGNvcGllZC4pXG4vLyAgICAgICpcbi8vICAgICAgKiBAcmV0dXJucyB7QXJyYXlMaXN0fSBhIGNsb25lIG9mIHRoaXMgQXJyYXlMaXN0IGluc3RhbmNlXG4vLyAgICAgICovXG4vLyAgICAgdGhpcy5jbG9uZSA9IGZ1bmN0aW9uKCkge1xuLy8gICAgICAgcmV0dXJuIG5ldyBBcnJheUxpc3QodGhpcylcbi8vICAgICB9XG4vL1xuLy8gICAgIC8qKlxuLy8gICAgICAqIEBtZW1iZXJvZiBBcnJheUxpc3Rcbi8vICAgICAgKiBBcnJheUxpc3QudG9BcnJheSgpIFJldHVybnMgYW4gYXJyYXkgY29udGFpbmluZyBhbGwgb2YgdGhlIGVsZW1lbnRzIGluIHRoaXMgbGlzdCBpbiB0aGUgY29ycmVjdCBvcmRlci5cbi8vICAgICAgKlxuLy8gICAgICAqIEByZXR1cm5zIHtPYmplY3RbXX0gUmV0dXJucyBhbiBhcnJheSBjb250YWluaW5nIGFsbCBvZiB0aGUgZWxlbWVudHMgaW4gdGhpcyBsaXN0IGluIHRoZSBjb3JyZWN0IG9yZGVyXG4vLyAgICAgICovXG4vLyAgICAgdGhpcy50b0FycmF5ID0gZnVuY3Rpb24oKSB7XG4vLyAgICAgICByZXR1cm4gYXJyYXkuc2xpY2UoMClcbi8vICAgICB9XG4vL1xuLy8gICAgIHRoaXMuaXRlcmF0b3IgPSBmdW5jdGlvbigpIHtcbi8vICAgICAgIHJldHVybiBuZXcgSXRlcmF0b3IoYXJyYXkpXG4vLyAgICAgfVxuLy8gICB9XG4vL1xuLy8gICByZXR1cm4gQXJyYXlMaXN0XG4vLyB9XG4iXSwibmFtZXMiOltdLCJtYXBwaW5ncyI6IkFBQUE7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7In0=