UNPKG

webglimpse

Version:

Webglimpse is a data visualization library for the web.

191 lines 26.3 kB
/* * Copyright (c) 2014, Metron, Inc. * All rights reserved. * * Redistribution and use in source and binary forms, with or without modification, * are permitted provided that the following conditions are met: * * 1. Redistributions of source code must retain the above copyright notice, this * list of conditions and the following disclaimer. * * 2. Redistributions in binary form must reproduce the above copyright notice, * this list of conditions and the following disclaimer in the documentation * and/or other materials provided with the distribution. * * 3. Neither the name of the copyright holder nor the names of its contributors * may be used to endorse or promote products derived from this software without * specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ import { BinaryTree } from './binary_tree'; import { getObjectId } from './util'; // A sorted map which allows multiple string values per key (K) export class SortedMultimap { constructor(comparator, idFn = getObjectId) { this._tree = new BinaryTree(this.createContainerComparator(comparator)); this._idFn = idFn; } createContainerComparator(comparator) { return { compare: function (container1, container2) { return comparator.compare(container1.key, container2.key); } }; } // Inserts the value into the tree. Nothing is inserted if the value already exists insert(key, value) { const wrappedKey = new Container(key); let values = this._tree.getValue(wrappedKey); if (values === null) { values = wrappedKey; this._tree.insert(values); } values.add(value, this._idFn); } remove(key, value) { const wrappedKey = new Container(key); const values = this._tree.getValue(wrappedKey); if (values === null) { return; } values.remove(value, this._idFn); if (values.size === 0) { this._tree.remove(values); } } contains(key, value) { const wrappedKey = new Container(key); const values = this._tree.getValue(wrappedKey); if (values === null) { return false; } else { return values.contains(value, this._idFn); } } // Returns the lowest element greater than or equal to the given value, or null if no such element exists ceiling(key) { return this.unwrap(this._tree.ceiling(this.wrap(key))); } // Returns the greatest element less than or equal to the given value, or null if no such element exists floor(key) { return this.unwrap(this._tree.floor(this.wrap(key))); } // Returns the greatest element strictly less than the given value, or null if no such element exists lower(key) { return this.unwrap(this._tree.lower(this.wrap(key))); } // Returns the lowest element strictly greater than the given value, or null if no such element exists higher(key) { return this.unwrap(this._tree.higher(this.wrap(key))); } // Returns all elements greater than (or equal to, if inclusive is true) the provided value (sorted from low to high) headSet(key, inclusive = true) { return this.unwrapArray(this._tree.headSet(this.wrap(key), inclusive)); } // Returns all elements less than ( or equal to, if inclusive is true) the provided value (sorted from low to high) tailSet(key, inclusive = false) { return this.unwrapArray(this._tree.tailSet(this.wrap(key), inclusive)); } // Returns all elements between the provided values (sorted from low to high) subSet(low, high, lowInclusive = true, highInclusive = false) { const wrappedLow = new Container(low); const wrappedHigh = new Container(high); const values = this._tree.subSet(wrappedLow, wrappedHigh, lowInclusive, highInclusive); return this.unwrapArray(values); } // Returns all keys in the tree (sorted from low to high) toArray() { return this.unwrapArray(this._tree.toArray()); } iterator() { const iter = this._tree.iterator(); let currentArray = null; let currentIndex = 0; return { next: function () { let value; if (currentArray == null || currentIndex >= currentArray.length) { currentArray = iter.next().toArray(); currentIndex = 0; value = currentArray[currentIndex]; } else { value = currentArray[currentIndex]; } currentIndex += 1; return value; }, hasNext: function () { return iter.hasNext() || (currentArray != null && currentIndex < currentArray.length); } }; } wrap(key) { return new Container(key); } unwrap(values) { if (values === null) { return []; } else { return values.toArray(); } } unwrapArray(values) { const unwrappedValues = new Array(); values.forEach(function (value) { value.toArray().forEach(function (val) { unwrappedValues.push(val); }); }); return unwrappedValues; } } export class SortedStringMultimap extends SortedMultimap { constructor(comparator) { super(comparator, (value) => value); } } // a container which stores a set of values (V) associated with a sorted key (K) // OrderedSet or even BinaryTree could be used here instead // more sophisticated set implementation: http://stackoverflow.com/questions/7958292/mimicking-sets-in-javascript class Container { constructor(key) { this._key = key; this._values = {}; } get size() { return this.toArray().length; } get key() { return this._key; } get values() { return this._values; } toArray() { return Object.keys(this._values).map(key => this._values[key]); } contains(value, idFn) { // safer than 'value in this._values' because of potential conflict with built in properties/methods return Object.prototype.hasOwnProperty.call(this._values, idFn(value)); } add(value, idFn) { this._values[idFn(value)] = value; } remove(value, idFn) { delete this._values[idFn(value)]; } } //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoic29ydGVkX211bHRpbWFwLmpzIiwic291cmNlUm9vdCI6IiIsInNvdXJjZXMiOlsiLi4vLi4vLi4vLi4vc3JjL3dlYmdsaW1wc2UvdXRpbC9zb3J0ZWRfbXVsdGltYXAudHMiXSwibmFtZXMiOltdLCJtYXBwaW5ncyI6IkFBQUE7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7R0E0Qkc7QUFDSCxPQUFPLEVBQUUsVUFBVSxFQUF3QixNQUFNLGVBQWUsQ0FBQztBQUNqRSxPQUFPLEVBQXlCLFdBQVcsRUFBRSxNQUFNLFFBQVEsQ0FBQztBQUU1RCwrREFBK0Q7QUFDL0QsTUFBTSxPQUFPLGNBQWM7SUFLdkIsWUFBWSxVQUF5QixFQUFFLE9BQXNCLFdBQVc7UUFDcEUsSUFBSSxDQUFDLEtBQUssR0FBRyxJQUFJLFVBQVUsQ0FBa0IsSUFBSSxDQUFDLHlCQUF5QixDQUFJLFVBQVUsQ0FBQyxDQUFDLENBQUM7UUFDNUYsSUFBSSxDQUFDLEtBQUssR0FBRyxJQUFJLENBQUM7SUFDdEIsQ0FBQztJQUVPLHlCQUF5QixDQUFJLFVBQXlCO1FBQzFELE9BQU87WUFDSCxPQUFPLEVBQUUsVUFBVSxVQUEyQixFQUFFLFVBQTJCO2dCQUN2RSxPQUFPLFVBQVUsQ0FBQyxPQUFPLENBQUMsVUFBVSxDQUFDLEdBQUcsRUFBRSxVQUFVLENBQUMsR0FBRyxDQUFDLENBQUM7WUFDOUQsQ0FBQztTQUNKLENBQUM7SUFDTixDQUFDO0lBRUQsbUZBQW1GO0lBQ25GLE1BQU0sQ0FBQyxHQUFNLEVBQUUsS0FBUTtRQUNuQixNQUFNLFVBQVUsR0FBRyxJQUFJLFNBQVMsQ0FBTyxHQUFHLENBQUMsQ0FBQztRQUM1QyxJQUFJLE1BQU0sR0FBb0IsSUFBSSxDQUFDLEtBQUssQ0FBQyxRQUFRLENBQUMsVUFBVSxDQUFDLENBQUM7UUFFOUQsSUFBSSxNQUFNLEtBQUssSUFBSSxFQUFFO1lBQ2pCLE1BQU0sR0FBRyxVQUFVLENBQUM7WUFDcEIsSUFBSSxDQUFDLEtBQUssQ0FBQyxNQUFNLENBQUMsTUFB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T0FBTyxJQUFJLENBQUMsSUFBSSxDQUFDO0lBQ3JCLENBQUM7SUFFRCxJQUFJLE1BQU07UUFDTixPQUFPLElBQUksQ0FBQyxPQUFPLENBQUM7SUFDeEIsQ0FBQztJQUVELE9BQU87UUFDSCxPQUFPLE1BQU0sQ0FBQyxJQUFJLENBQUMsSUFBSSxDQUFDLE9BQU8sQ0FBQyxDQUFDLEdBQUcsQ0FBQyxHQUFHLENBQUMsRUFBRSxDQUFDLElBQUksQ0FBQyxPQUFPLENBQUMsR0FBRyxDQUFDLENBQUMsQ0FBQztJQUNuRSxDQUFDO0lBRUQsUUFBUSxDQUFDLEtBQVEsRUFBRSxJQUFtQjtRQUNsQyxvR0FBb0c7UUFDcEcsT0FBTyxNQUFNLENBQUMsU0FBUyxDQUFDLGNBQWMsQ0FBQyxJQUFJLENBQUMsSUFBSSxDQUFDLE9BQU8sRUFBRSxJQUFJLENBQUMsS0FBSyxDQUFDLENBQUMsQ0FBQztJQUMzRSxDQUFDO0lBRUQsR0FBRyxDQUFDLEtBQVEsRUFBRSxJQUFtQjtRQUM3QixJQUFJLENBQUMsT0FBTyxDQUFDLElBQUksQ0FBQyxLQUFLLENBQUMsQ0FBQyxHQUFHLEtBQUssQ0FBQztJQUN0QyxDQUFDO0lBRUQsTUFBTSxDQUFDLEtBQVEsRUFBRSxJQUFtQjtRQUNoQyxPQUFPLElBQUksQ0FBQyxPQUFPLENBQUMsSUFBSSxDQUFDLEtBQUssQ0FBQyxDQUFDLENBQUM7SUFDckMsQ0FBQztDQUNKIiwic291cmNlc0NvbnRlbnQiOlsiLypcclxuICogQ29weXJpZ2h0IChjKSAyMDE0LCBNZXRyb24sIEluYy5cclxuICogQWxsIHJpZ2h0cyByZXNlcnZlZC5cclxuICpcclxuICogUmVkaXN0cmlidXRpb24gYW5kIHVzZSBpbiBzb3VyY2UgYW5kIGJpbmFyeSBmb3Jtcywgd2l0aCBvciB3aXRob3V0IG1vZGlmaWNhdGlvbixcclxuICogYXJlIHBlcm1pdHRlZCBwcm92aWRlZCB0aGF0IHRoZSBmb2xsb3dpbmcgY29uZGl0aW9ucyBhcmUgbWV0OlxyXG4gKlxyXG4gKiAxLiBSZWRpc3RyaWJ1dGlvbnMgb2Ygc291cmNlIGNvZGUgbXVzdCByZXRhaW4gdGhlIGFib3ZlIGNvcHlyaWdodCBub3RpY2UsIHRoaXNcclxuICogICAgbGlzdCBvZiBjb25kaXRpb25zIGFuZCB0aGUgZm9sbG93aW5nIGRpc2NsYWltZXIuXHJcbiAqXHJcbiAqIDIuIFJlZGlzdHJpYnV0aW9ucyBpbiBiaW5hcnkgZm9ybSBtdXN0IHJlcHJvZHVjZSB0aGUgYWJvdmUgY29weXJpZ2h0IG5vdGljZSxcclxuICogICAgdGhpcyBsaXN0IG9mIGNvbmRpdGlvbnMgYW5kIHRoZSBmb2xsb3dpbmcgZGlzY2xhaW1lciBpbiB0aGUgZG9jdW1lbnRhdGlvblxyXG4gKiAgICBhbmQvb3Igb3RoZXIgbWF0ZXJpYWxzIHByb3ZpZGVkIHdpdGggdGhlIGRpc3RyaWJ1dGlvbi5cclxuICpcclxuICogMy4gTmVpdGhlciB0aGUgbmFtZSBvZiB0aGUgY29weXJpZ2h0IGhvbGRlciBub3IgdGhlIG5hbWVzIG9mIGl0cyBjb250cmlidXRvcnNcclxuICogICAgbWF5IGJlIHVzZWQgdG8gZW5kb3JzZSBvciBwcm9tb3RlIHByb2R1Y3RzIGRlcml2ZWQgZnJvbSB0aGlzIHNvZnR3YXJlIHdpdGhvdXRcclxuICogICAgc3BlY2lmaWMgcHJpb3Igd3JpdHRlbiBwZXJtaXNzaW9uLlxyXG4gKlxyXG4gKiBUSElTIFNPRlRXQVJFIElTIFBST1ZJREVEIEJZIFRIRSBDT1BZUklHSFQgSE9MREVSUyBBTkQgQ09OVFJJQlVUT1JTIFwiQVMgSVNcIiBBTkRcclxuICogQU5ZIEVYUFJFU1MgT1IgSU1QTElFRCBXQVJSQU5USUVTLCBJTkNMVURJTkcsIEJVVCBOT1QgTElNSVRFRCBUTywgVEhFIElNUExJRURcclxuICogV0FSUkFOVElFUyBPRiBNRVJDSEFOVEFCSUxJVFkgQU5EIEZJVE5FU1MgRk9SIEEgUEFSVElDVUxBUiBQVVJQT1NFIEFSRVxyXG4gKiBESVNDTEFJTUVELiBJTiBOTyBFVkVOVCBTSEFMTCBUSEUgQ09QWVJJR0hUIEhPTERFUiBPUiBDT05UUklCVVRPUlMgQkUgTElBQkxFIEZPUlxyXG4gKiBBTlkgRElSRUNULCBJTkRJUkVDVCwgSU5DSURFTlRBTCwgU1BFQ0lBTCwgRVhFTVBMQVJZLCBPUiBDT05TRVFVRU5USUFMIERBTUFHRVNcclxuICogKElOQ0xVRElORywgQlVUIE5PVCBMSU1JVEVEIFRPLCBQUk9DVVJFTUVOVCBPRiBTVUJTVElUVVRFIEdPT0RTIE9SIFNFUlZJQ0VTO1xyXG4gKiBMT1NTIE9GIFVTRSwgREFUQSwgT1IgUFJPRklUUzsgT1IgQlVTSU5FU1MgSU5URVJSVVBUSU9OKSBIT1dFVkVSIENBVVNFRCBBTkQgT05cclxuICogQU5ZIFRIRU9SWSBPRiBMSUFCSUxJVFksIFdIRVRIRVIgSU4gQ09OVFJBQ1QsIFNUUklDVCBMSUFCSUxJVFksIE9SIFRPUlRcclxuICogKElOQ0xVRElORyBORUdMSUdFTkNFIE9SIE9USEVSV0lTRSkgQVJJU0lORyBJTiBBTlkgV0FZIE9VVCBPRiBUSEUgVVNFIE9GIFRISVNcclxuICogU09GVFdBUkUsIEVWRU4gSUYgQURWSVNFRCBPRiBUSEUgUE9TU0lCSUxJVFkgT0YgU1VDSCBEQU1BR0UuXHJcbiAqL1xyXG5pbXBvcnQgeyBCaW5hcnlUcmVlLCBDb21wYXJhdG9yLCBJdGVyYXRvciB9IGZyb20gJy4vYmluYXJ5X3RyZWUnO1xyXG5pbXBvcnQgeyBJZEZ1bmN0aW9uLCBTdHJpbmdNYXAsIGdldE9iamVjdElkIH0gZnJvbSAnLi91dGlsJztcclxuXHJcbi8vIEEgc29ydGVkIG1hcCB3aGljaCBhbGxvd3MgbXVsdGlwbGUgc3RyaW5nIHZhbHVlcyBwZXIga2V5IChLKVxyXG5leHBvcnQgY2xhc3MgU29ydGVkTXVsdGltYXA8SywgVj4ge1xyXG5cclxuICAgIHByaXZhdGUgX3RyZWU6IEJpbmFyeVRyZWU8Q29udGFpbmVyPEssIFY+PjtcclxuICAgIHByaXZhdGUgX2lkRm46IElkRnVuY3Rpb248Vj47XHJcblxyXG4gICAgY29uc3RydWN0b3IoY29tcGFyYXRvcjogQ29tcGFyYXRvcjxLPiwgaWRGbjogSWRGdW5jdGlvbjxWPiA9IGdldE9iamVjdElkKSB7XHJcbiAgICAgICAgdGhpcy5fdHJlZSA9IG5ldyBCaW5hcnlUcmVlPENvbnRhaW5lcjxLLCBWPj4odGhpcy5jcmVhdGVDb250YWluZXJDb21wYXJhdG9yPFY+KGNvbXBhcmF0b3IpKTtcclxuICAgICAgICB0aGlzLl9pZEZuID0gaWRGbjtcclxuICAgIH1cclxuXHJcbiAgICBwcml2YXRlIGNyZWF0ZUNvbnRhaW5lckNvbXBhcmF0b3I8VT4oY29tcGFyYXRvcjogQ29tcGFyYXRvcjxLPik6IENvbXBhcmF0b3I8Q29udGFpbmVyPEssIFU+PiB7XHJcbiAgICAgICAgcmV0dXJuIHtcclxuICAgICAgICAgICAgY29tcGFyZTogZnVuY3Rpb24gKGNvbnRhaW5lcjE6IENvbnRhaW5lcjxLLCBVPiwgY29udGFpbmVyMjogQ29udGFpbmVyPEssIFU+KTogbnVtYmVyIHtcclxuICAgICAgICAgICAgICAgIHJldHVybiBjb21wYXJhdG9yLmNvbXBhcmUoY29udGFpbmVyMS5rZXksIGNvbnRhaW5lcjIua2V5KTtcclxuICAgICAgICAgICAgfVxyXG4gICAgICAgIH07XHJcbiAgICB9XHJcblxyXG4gICAgLy8gSW5zZXJ0cyB0aGUgdmFsdWUgaW50byB0aGUgdHJlZS4gTm90aGluZyBpcyBpbnNlcnRlZCBpZiB0aGUgdmFsdWUgYWxyZWFkeSBleGlzdHNcclxuICAgIGluc2VydChrZXk6IEssIHZhbHVlOiBWKSB7XHJcbiAgICAgICAgY29uc3Qgd3JhcHBlZEtleSA9IG5ldyBDb250YWluZXI8SywgVj4oa2V5KTtcclxuICAgICAgICBsZXQgdmFsdWVzOiBDb250YWluZXI8SywgVj4gPSB0aGlzLl90cmVlLmdldFZhbHVlKHdyYXBwZWRLZXkpO1xyXG5cclxuICAgICAgICBpZiAodmFsdWVzID09PSBudWxsKSB7XHJcbiAgICAgICAgICAgIHZhbHVlcyA9IHdyYXBwZWRLZXk7XHJcbiAgICAgICAgICAgIHRoaXMuX3RyZWUuaW5zZXJ0KHZhbHVlcyk7XHJcbiAgICAgICAgfVxyXG5cclxuICAgICAgICB2YWx1ZXMuYWRkKHZhbHVlLCB0aGlzLl9pZEZuKTtcclxuICAgIH1cclxuXHJcbiAgICByZW1vdmUoa2V5OiBLLCB2YWx1ZTogVikge1xyXG4gICAgICAgIGNvbnN0IHdyYXBwZWRLZXkgPSBuZXcgQ29udGFpbmVyPEssIFY+KGtleSk7XHJcbiAgICAgICAgY29uc3QgdmFsdWVzOiBDb250YWluZXI8SywgVj4gPSB0aGlzLl90cmVlLmdldFZhbHVlKHdyYXBwZWRLZXkpO1xyXG5cclxuICAgICAgICBpZiAodmFsdWVzID09PSBudWxsKSB7XHJcbiAgICAgICAgICAgIHJldHVybjtcclxuICAgICAgICB9XHJcblxyXG4gICAgICAgIHZhbHVlcy5yZW1vdmUodmFsdWUsIHRoaXMuX2lkRm4pO1xyXG5cclxuICAgICAgICBpZiAodmFsdWVzLnNpemUgPT09IDApIHtcclxuICAgICAgICAgICAgdGhpcy5fdHJlZS5yZW1vdmUodmFsdWVzKTtcclxuICAgICAgICB9XHJcbiAgICB9XHJcblxyXG4gICAgY29udGFpbnMoa2V5OiBLLCB2YWx1ZTogVikge1xyXG4gICAgICAgIGNvbnN0IHdyYXBwZWRLZXkgPSBuZXcgQ29udGFpbmVyPEssIFY+KGtleSk7XHJcbiAgICAgICAgY29uc3QgdmFsdWVzOiBDb250YWluZXI8SywgVj4gPSB0aGlzLl90cmVlLmdldFZhbHVlKHdyYXBwZWRLZXkpO1xyXG5cclxuICAgICAgICBpZiAodmFsdWVzID09PSBudWxsKSB7XHJcbiAgICAgICAgICAgIHJldHVybiBmYWxzZTtcclxuICAgICAgICB9XHJcbiAgICAgICAgZWxzZSB7XHJcbiAgICAgICAgICAgIHJldHVybiB2YWx1ZXMuY29udGFpbnModmFsdWUsIHRoaXMuX2lkRm4pO1xyXG4gICAgICAgIH1cclxuICAgIH1cclxuXHJcbiAgICAvLyBSZXR1cm5zIHRoZSBsb3dlc3QgZWxlbWVudCBncmVhdGVyIHRoYW4gb3IgZXF1YWwgdG8gdGhlIGdpdmVuIHZhbHVlLCBvciBudWxsIGlmIG5vIHN1Y2ggZWxlbWVudCBleGlzdHNcclxuICAgIGNlaWxpbmcoa2V5OiBLKTogVltdIHtcclxuICAgICAgICByZXR1cm4gdGhpcy51bndyYXAodGhpcy5fdHJlZS5jZWlsaW5nKHRoaXMud3JhcChrZXkpKSk7XHJcbiAgICB9XHJcblxyXG4gICAgLy8gUmV0dXJucyB0aGUgZ3JlYXRlc3QgZWxlbWVudCBsZXNzIHRoYW4gb3IgZXF1YWwgdG8gdGhlIGdpdmVuIHZhbHVlLCBvciBudWxsIGlmIG5vIHN1Y2ggZWxlbWVudCBleGlzdHNcclxuICAgIGZsb29yKGtleTogSyk6IFZbXSB7XHJcbiAgICAgICAgcmV0dXJuIHRoaXMudW53cmFwKHRoaXMuX3RyZWUuZmxvb3IodGhpcy53cmFwKGtleSkpKTtcclxuICAgIH1cclxuXHJcbiAgICAvLyBSZXR1cm5zIHRoZSBncmVhdGVzdCBlbGVtZW50IHN0cmljdGx5IGxlc3MgdGhhbiB0aGUgZ2l2ZW4gdmFsdWUsIG9yIG51bGwgaWYgbm8gc3VjaCBlbGVtZW50IGV4aXN0c1xyXG4gICAgbG93ZXIoa2V5OiBLKTogVltdIHtcclxuICAgICAgICByZXR1cm4gdGhpcy51bndyYXAodGhpcy5fdHJlZS5sb3dlcih0aGlzLndyYXAoa2V5KSkpO1xyXG4gICAgfVxyXG5cclxuICAgIC8vIFJldHVybnMgdGhlIGxvd2VzdCBlbGVtZW50IHN0cmljdGx5IGdyZWF0ZXIgdGhhbiB0aGUgZ2l2ZW4gdmFsdWUsIG9yIG51bGwgaWYgbm8gc3VjaCBlbGVtZW50IGV4aXN0c1xyXG4gICAgaGlnaGVyKGtleTogSyk6IFZbXSB7XHJcbiAgICAgICAgcmV0dXJuIHRoaXMudW53cmFwKHRoaXMuX3RyZWUuaGlnaGVyKHRoaXMud3JhcChrZXkpKSk7XHJcbiAgICB9XHJcblxyXG4gICAgLy8gUmV0dXJucyBhbGwgZWxlbWVudHMgZ3JlYXRlciB0aGFuIChvciBlcXVhbCB0bywgaWYgaW5jbHVzaXZlIGlzIHRydWUpIHRoZSBwcm92aWRlZCB2YWx1ZSAoc29ydGVkIGZyb20gbG93IHRvIGhpZ2gpXHJcbiAgICBoZWFkU2V0KGtleTogSywgaW5jbHVzaXZlOiBib29sZWFuID0gdHJ1ZSk6IFZbXSB7XHJcbiAgICAgICAgcmV0dXJuIHRoaXMudW53cmFwQXJyYXkodGhpcy5fdHJlZS5oZWFkU2V0KHRoaXMud3JhcChrZXkpLCBpbmNsdXNpdmUpKTtcclxuICAgIH1cclxuXHJcbiAgICAvLyBSZXR1cm5zIGFsbCBlbGVtZW50cyBsZXNzIHRoYW4gKCBvciBlcXVhbCB0bywgaWYgaW5jbHVzaXZlIGlzIHRydWUpIHRoZSBwcm92aWRlZCB2YWx1ZSAoc29ydGVkIGZyb20gbG93IHRvIGhpZ2gpXHJcbiAgICB0YWlsU2V0KGtleTogSywgaW5jbHVzaXZlOiBib29sZWFuID0gZmFsc2UpOiBWW10ge1xyXG4gICAgICAgIHJldHVybiB0aGlzLnVud3JhcEFycmF5KHRoaXMuX3RyZWUudGFpbFNldCh0aGlzLndyYXAoa2V5KSwgaW5jbHVzaXZlKSk7XHJcbiAgICB9XHJcblxyXG4gICAgLy8gUmV0dXJucyBhbGwgZWxlbWVudHMgYmV0d2VlbiB0aGUgcHJvdmlkZWQgdmFsdWVzIChzb3J0ZWQgZnJvbSBsb3cgdG8gaGlnaClcclxuICAgIHN1YlNldChsb3c6IEssIGhpZ2g6IEssIGxvd0luY2x1c2l2ZTogYm9vbGVhbiA9IHRydWUsIGhpZ2hJbmNsdXNpdmU6IGJvb2xlYW4gPSBmYWxzZSk6IFZbXSB7XHJcbiAgICAgICAgY29uc3Qgd3JhcHBlZExvdyA9IG5ldyBDb250YWluZXI8SywgVj4obG93KTtcclxuICAgICAgICBjb25zdCB3cmFwcGVkSGlnaCA9IG5ldyBDb250YWluZXI8SywgVj4oaGlnaCk7XHJcbiAgICAgICAgY29uc3QgdmFsdWVzOiBDb250YWluZXI8SywgVj5bXSA9IHRoaXMuX3RyZWUuc3ViU2V0KHdyYXBwZWRMb3csIHdyYXBwZWRIaWdoLCBsb3dJbmNsdXNpdmUsIGhpZ2hJbmNsdXNpdmUpO1xyXG4gICAgICAgIHJldHVybiB0aGlzLnVud3JhcEFycmF5KHZhbHVlcyk7XHJcbiAgICB9XHJcblxyXG4gICAgLy8gUmV0dXJucyBhbGwga2V5cyBpbiB0aGUgdHJlZSAoc29ydGVkIGZyb20gbG93IHRvIGhpZ2gpXHJcbiAgICB0b0FycmF5KCk6IFZbXSB7XHJcbiAgICAgICAgcmV0dXJuIHRoaXMudW53cmFwQXJyYXkodGhpcy5fdHJlZS50b0FycmF5KCkpO1xyXG4gICAgfVxyXG5cclxuICAgIGl0ZXJhdG9yKCk6IEl0ZXJhdG9yPFY+IHtcclxuXHJcbiAgICAgICAgY29uc3QgaXRlcjogSXRlcmF0b3I8Q29udGFpbmVyPEssIFY+PiA9IHRoaXMuX3RyZWUuaXRlcmF0b3IoKTtcclxuICAgICAgICBsZXQgY3VycmVudEFycmF5OiBWW10gPSBudWxsO1xyXG4gICAgICAgIGxldCBjdXJyZW50SW5kZXggPSAwO1xyXG5cclxuICAgICAgICByZXR1cm4ge1xyXG4gICAgICAgICAgICBuZXh0OiBmdW5jdGlvbiAoKTogViB7XHJcblxyXG4gICAgICAgICAgICAgICAgbGV0IHZhbHVlOiBWO1xyXG5cclxuICAgICAgICAgICAgICAgIGlmIChjdXJyZW50QXJyYXkgPT0gbnVsbCB8fCBjdXJyZW50SW5kZXggPj0gY3VycmVudEFycmF5Lmxlbmd0aCkge1xyXG4gICAgICAgICAgICAgICAgICAgIGN1cnJlbnRBcnJheSA9IGl0ZXIubmV4dCgpLnRvQXJyYXkoKTtcclxuICAgICAgICAgICAgICAgICAgICBjdXJyZW50SW5kZXggPSAwO1xyXG4gICAgICAgICAgICAgICAgICAgIHZhbHVlID0gY3VycmVudEFycmF5W2N1cnJlbnRJbmRleF07XHJcbiAgICAgICAgICAgICAgICB9XHJcbiAgICAgICAgICAgICAgICBlbHNlIHtcclxuICAgICAgICAgICAgICAgICAgICB2YWx1ZSA9IGN1cnJlbnRBcnJheVtjdXJyZW50SW5kZXhdO1xyXG4gICAgICAgICAgICAgICAgfVxyXG5cclxuICAgICAgICAgICAgICAgIGN1cnJlbnRJbmRleCArPSAxO1xyXG5cclxuICAgICAgICAgICAgICAgIHJldHVybiB2YWx1ZTtcclxuICAgICAgICAgICAgfSxcclxuICAgICAgICAgICAgaGFzTmV4dDogZnVuY3Rpb24gKCk6IGJvb2xlYW4ge1xyXG4gICAgICAgICAgICAgICAgcmV0dXJuIGl0ZXIuaGFzTmV4dCgpIHx8IChjdXJyZW50QXJyYXkgIT0gbnVsbCAmJiBjdXJyZW50SW5kZXggPCBjdXJyZW50QXJyYXkubGVuZ3RoKTtcclxuICAgICAgICAgICAgfVxyXG4gICAgICAgIH07XHJcbiAgICB9XHJcblxyXG4gICAgcHJpdmF0ZSB3cmFwKGtleTogSyk6IENvbnRhaW5lcjxLLCBWPiB7XHJcbiAgICAgICAgcmV0dXJuIG5ldyBDb250YWluZXI8SywgVj4oa2V5KTtcclxuICAgIH1cclxuXHJcbiAgICBwcml2YXRlIHVud3JhcCh2YWx1ZXM6IENvbnRhaW5lcjxLLCBWPik6IFZbXSB7XHJcbiAgICAgICAgaWYgKHZhbHVlcyA9PT0gbnVsbCkge1xyXG4gICAgICAgICAgICByZXR1cm4gW107XHJcbiAgICAgICAgfVxyXG4gICAgICAgIGVsc2Uge1xyXG4gICAgICAgICAgICByZXR1cm4gdmFsdWVzLnRvQXJyYXkoKTtcclxuICAgICAgICB9XHJcbiAgICB9XHJcblxyXG4gICAgcHJpdmF0ZSB1bndyYXBBcnJheSh2YWx1ZXM6IENvbnRhaW5lcjxLLCBWPltdKTogVltdIHtcclxuICAgICAgICBjb25zdCB1bndyYXBwZWRWYWx1ZXM6IFZbXSA9IG5ldyBBcnJheTxWPigpO1xyXG4gICAgICAgIHZhbHVlcy5mb3JFYWNoKGZ1bmN0aW9uICh2YWx1ZTogQ29udGFpbmVyPEssIFY+KSB7XHJcbiAgICAgICAgICAgIHZhbHVlLnRvQXJyYXkoKS5mb3JFYWNoKGZ1bmN0aW9uICh2YWw6IFYpIHtcclxuICAgICAgICAgICAgICAgIHVud3JhcHBlZFZhbHVlcy5wdXNoKHZhbCk7XHJcbiAgICAgICAgICAgIH0pO1xyXG4gICAgICAgIH0pO1xyXG5cclxuICAgICAgICByZXR1cm4gdW53cmFwcGVkVmFsdWVzO1xyXG4gICAgfVxyXG59XHJcblxyXG5leHBvcnQgY2xhc3MgU29ydGVkU3RyaW5nTXVsdGltYXA8Sz4gZXh0ZW5kcyBTb3J0ZWRNdWx0aW1hcDxLLCBzdHJpbmc+IHtcclxuICAgIGNvbnN0cnVjdG9yKGNvbXBhcmF0b3I6IENvbXBhcmF0b3I8Sz4pIHtcclxuICAgICAgICBzdXBlcihjb21wYXJhdG9yLCAodmFsdWUpID0+IHZhbHVlKTtcclxuICAgIH1cclxufVxyXG5cclxuLy8gYSBjb250YWluZXIgd2hpY2ggc3RvcmVzIGEgc2V0IG9mIHZhbHVlcyAoVikgYXNzb2NpYXRlZCB3aXRoIGEgc29ydGVkIGtleSAoSylcclxuLy8gT3JkZXJlZFNldCBvciBldmVuIEJpbmFyeVRyZWUgY291bGQgYmUgdXNlZCBoZXJlIGluc3RlYWRcclxuLy8gbW9yZSBzb3BoaXN0aWNhdGVkIHNldCBpbXBsZW1lbnRhdGlvbjogaHR0cDovL3N0YWNrb3ZlcmZsb3cuY29tL3F1ZXN0aW9ucy83OTU4MjkyL21pbWlja2luZy1zZXRzLWluLWphdmFzY3JpcHRcclxuY2xhc3MgQ29udGFpbmVyPEssIFY+IHtcclxuXHJcbiAgICBwcml2YXRlIF9rZXk6IEs7XHJcbiAgICBwcml2YXRlIF92YWx1ZXM6IFN0cmluZ01hcDxWPjtcclxuXHJcbiAgICBjb25zdHJ1Y3RvcihrZXk6IEspIHtcclxuICAgICAgICB0aGlzLl9rZXkgPSBrZXk7XHJcbiAgICAgICAgdGhpcy5fdmFsdWVzID0ge307XHJcbiAgICB9XHJcblxyXG4gICAgZ2V0IHNpemUoKTogbnVtYmVyIHtcclxuICAgICAgICByZXR1cm4gdGhpcy50b0FycmF5KCkubGVuZ3RoO1xyXG4gICAgfVxyXG5cclxuICAgIGdldCBrZXkoKTogSyB7XHJcbiAgICAgICAgcmV0dXJuIHRoaXMuX2tleTtcclxuICAgIH1cclxuXHJcbiAgICBnZXQgdmFsdWVzKCk6IFN0cmluZ01hcDxWPiB7XHJcbiAgICAgICAgcmV0dXJuIHRoaXMuX3ZhbHVlcztcclxuICAgIH1cclxuXHJcbiAgICB0b0FycmF5KCk6IFZbXSB7XHJcbiAgICAgICAgcmV0dXJuIE9iamVjdC5rZXlzKHRoaXMuX3ZhbHVlcykubWFwKGtleSA9PiB0aGlzLl92YWx1ZXNba2V5XSk7XHJcbiAgICB9XHJcblxyXG4gICAgY29udGFpbnModmFsdWU6IFYsIGlkRm46IElkRnVuY3Rpb248Vj4pOiBib29sZWFuIHtcclxuICAgICAgICAvLyBzYWZlciB0aGFuICd2YWx1ZSBpbiB0aGlzLl92YWx1ZXMnIGJlY2F1c2Ugb2YgcG90ZW50aWFsIGNvbmZsaWN0IHdpdGggYnVpbHQgaW4gcHJvcGVydGllcy9tZXRob2RzXHJcbiAgICAgICAgcmV0dXJuIE9iamVjdC5wcm90b3R5cGUuaGFzT3duUHJvcGVydHkuY2FsbCh0aGlzLl92YWx1ZXMsIGlkRm4odmFsdWUpKTtcclxuICAgIH1cclxuXHJcbiAgICBhZGQodmFsdWU6IFYsIGlkRm46IElkRnVuY3Rpb248Vj4pIHtcclxuICAgICAgICB0aGlzLl92YWx1ZXNbaWRGbih2YWx1ZSldID0gdmFsdWU7XHJcbiAgICB9XHJcblxyXG4gICAgcmVtb3ZlKHZhbHVlOiBWLCBpZEZuOiBJZEZ1bmN0aW9uPFY+KSB7XHJcbiAgICAgICAgZGVsZXRlIHRoaXMuX3ZhbHVlc1tpZEZuKHZhbHVlKV07XHJcbiAgICB9XHJcbn1cclxuXHJcbiJdfQ==