foop
Version:
interfaces that describe their intentions.
353 lines (347 loc) • 23.5 kB
JavaScript
/** @ignore 🚧 wip */
// const toFunction = require('../cast/toFunction')
// const forInUnguarded = require('../loop/each/forInUnguarded')
//
// function __ehs(args) {
// this.__eh = 1
// }
// function _ehs(args) {
// __ehs.call(this)
// this._eh = args
// }
//
// const Ehs = toFunction(_ehs)
// function ehs(args) {
// return new _ehs(args)
// }
//
// console.log(new Ehs(0))
//
// const copy = x => forInUnguarded(x, (value, key) => x[key] = value)
//
// // https://h3manth.com/new/blog/2014/thisarg-in-javascript/
// // const fpChain = (...chains) => {
// // function functionContext() {
// // this.store = new Map()
// // return this
// // }
// // function eh() {
// // functionContext.call(this, this)
// // console.log(this)
// // }
//
// // function inherit(Parent, Child) {
// // const ParentPrototype = Object.getPrototypeOf(Parent)
// // Object.setPrototypeOf(Child, ParentPrototype)
// // Chained.prototype = Object.create(ParentPrototype);
// // Chained.prototype.constructor = Chained
// // }
// function _classCallCheck(instance, Constructor) {
// if (!(instance instanceof Constructor)) {
// throw new TypeError('Cannot call a class as a function')
// }
// }
//
// function _possibleConstructorReturn(self, _super) {
// if (!self) {
// throw new ReferenceError(
// 'this hasn\'t been initialised - super() hasn\'t been called'
// )
// }
//
// const call = _super.call(self)
// return call && (typeof call === 'object' || typeof call === 'function')
// ? call
// : self
// }
//
// function _inherits(subClass, superClass) {
// if (typeof superClass !== 'function' && superClass !== null) {
// throw new TypeError(
// 'Super expression must either be null or a function, not ' +
// typeof superClass
// )
// }
// subClass.prototype = Object.create(superClass && superClass.prototype, {
// constructor: {
// value: subClass,
// enumerable: false,
// writable: true,
// configurable: true,
// },
// })
// if (superClass)
// Object.setPrototypeOf
// ? Object.setPrototypeOf(subClass, superClass)
// : subClass.__proto__ = superClass
//
// return function callForConstructor(self) {
// const call = superClass.call(self)
// return call && (typeof call === 'object' || typeof call === 'function')
// ? call
// : self
// }
// }
//
// function eh() {
// console.log('what')
// this.eh = true
// // @NOTE this is an example of constructor returning & not using `this`
// var _this = copy(this)
// _this._ = 0
// return _this
// }
//
// const _super = eh
// const call = _inherits(Chained, _super)
// function Chained() {
// // _classCallCheck(this, Chained)
// // var _this = _super.call(this) || this
// var _this = call(this, _super)
//
// // _super.call(this)
// _this.ca = true
// console.log('chained')
// return _this
// }
// var Chained = (function(_super) {
// const call = _inherits(Chained, _super)
// function Chained() {
// // _classCallCheck(this, Chained)
// // var _this = _super.call(this) || this
// var _this = call(this, _super)
//
// // _super.call(this)
// _this.ca = true
// console.log('chained')
// return _this
// }
//
// return Chained
// // return buble(Chained, _super)
// })
// Chained = Chained(eh)
// console.log(new Chained())
// console.log(protos(Chained), protos(new Chained()))
// console.log({Chained})
// console.log(new Chained())
// fpChain([])
// const curry = require('./curry')
//
// /**
// * Returns the first function passed as an argument to the second,
// * allowing you to adjust arguments, run code before and after, and
// * conditionally execute the original function.
// *
// * @memberOf fp
// * @since 5.0.0-beta.5
// *
// * @param {Function} fn function to wrap
// * @param {Function} wrap function that wraps `fn`
// *
// * @symb 🍬
// * @name wrap
// *
// * {@link http://underscorejs.org/#wrap underscore-wrap}
// * {@link https://github.com/jashkenas/underscore/blob/master/underscore.js#L909 underscore-src-wrap}
// * @see {@link underscore-wrap}
// * @see {@link underscore-src-wrap}
// *
// * @example
// *
// * var hello = function(name) { return "hello: " + name; };
// * hello = wrap(hello, function(func) {
// * return "before, " + func("moe") + ", after";
// * })
// *
// * hello()
// * //=> 'before, hello: moe, after'
// *
// */
// function wrap(fn, wrapper) {
// // this just passes `fn` into wrap...
// // maybe, instead, add `pre` & `post`
// // was `partial(wrapper, fn)`
// return curry(3, wrapper, fn)
// }
//
// const argumentor = require('../cast/argumentor')
// const isFunction = require('../is/function')
//
// // @TODO maybe returning `false` will disable the function?
// // or returning `noop` ?
// // or anything but `nill` ?
// function pre(target, subscriber) {
// return curry(target.length, function() {
// const args = argumentor.apply(null, arguments)
//
// // call subscriber
// const returned = subscriber.apply(this, args)
//
// if (returned === false) return null
// else if (isFunction(returned)) return returned
// else return target.apply(this, args)
// })
// }
// function post(target, subscriber) {
// const args = argumentor.apply(null, arguments)
// const returned = target.apply(this, args)
//
// // also original args??
// subscriber.apply(null, returned)
// }
//
// // http://ramdajs.com/docs/#memoizeWith
//
// // AND THEN, COULD JUST USE `NTH` ON RETURNED
//
// // HOW CAN THE SUBSCRIBERS GET THE RESULTS?
// // LIKE IF WE WANT TO SEE THE RETURNED VALUE?
// //
// // return result from last?
// // @example
// //
// // const pre = console.log
// // const post = console.error
// // const multiply = (n, factor) => n * factor
// // notifyEach(pre, multiply, post)
// function notifyEach(subscribers) {
// return function() {
// const args = arguments
// const results = []
// subscribers.forEach(subscriber => {
// results.push(subscriber.apply(null, arguments))
// })
// }
// }
//
// // USE ARRAY OF OBJECTS, TO AN OBJECT WITH INDEXES AS A PROPERTY
// function indexBy() {}
//
//
// // Return a random integer between min and max (inclusive).
// const random = function(min, max) {
// if (isNill(max)) {
// max = min
// min = 0
// }
// return min + Math.floor(Math.random() * (max - min + 1))
// }
//
// // @NOTE USES LODASH.ORDERBY
// function orderByKeys(obj, orderFirst) {
// const orderedObj = {}
// orderFirst = orderFirst.reverse()
// const keys = Object.keys(obj)
// _sortBy(keys, key => orderFirst.indexOf(key))
// .reverse()
// .forEach(key => {
// orderedObj[key] = obj[key]
// })
// return orderedObj
// }
//
//
// /**
// * @example
// *
// * remapBy(prop('id'), [{'id': 'eh'}])
// *
// * @example
// * in: [
// * {id: 'eh', val: 'canada'},
// * {id: 'moose', val: 'igloo'}
// * ]
// *
// * out: {
// * 'eh': {id: 'eh', val: 'canada'},
// * 'moose': {id: 'moose', val: 'igloo'}
// * }
// */
// // or INDEXBY
// function remapBy(transformer, vals) {
// const remapped = {}
//
// // @TODO: should reload if there is no remap by id vals...
// if (!isObj(vals)) return remapped
//
// var asObj = values(vals)
//
// // if (isArray(vals)) {
// // // if it does not have the prop, add it as the index
// // // if it has it, and it is an array, join it
// // vals = values.map((data, i) => {
// // if (!data[prop]) data[prop] = i
// // if (isArray(data[prop])) data[prop] = data[prop].join(',')
// // return data
// // })
// //
// // return arrToObj(values, {
// // keyFn: ({i}) => values[i][prop],
// // valFn: ({i, val}) => val,
// // })
// // }
//
// // remap to add item id as object property
// const props = keys(asObj)
// for (let i = 0, len = props.length; i < len; i++) {
// const key = props[i]
// const val = asObj[key]
//
// remapped[val.id] = val
// }
// // console.debug('remapById', {values, asObj})
//
// return remapped
// }
//
//
// function omit(obj, keys) {
// const target = {}
// for (let i in obj) {
// if (keys.indexOf(i) >= 0 || !hasOwnProperty(obj, i)) continue
// target[i] = obj[i]
// }
// return target
// }
//
//
// // http://werxltd.com/wp/2010/05/13/javascript-implementation-of-javas-string-hashcode-method/
// // module.exports = function fliphash(str) {
// // // || typeof str !== 'string'
// // // if (str === undefined || str === null) {
// // // console.log('you passed not real value to fliphash')
// // // return str
// // // }
// // if (isNill(str)) return 'nill'
// // let len = str.length
// // if (len === 0) return 0
// //
// // let hash = 0
// //
// // for (let i = 0; i < len; i++) {
// // const char = str.charCodeAt(i)
// // hash = ((hash << 5) - hash) + char
// // hash = hash & hash // Convert to 32bit integer
// // }
// // return hash
// // }
// //
// // const test = require('ava')
// // const fliphash = require('../')
// //
// // test('hashes a number', t => {
// // t.plan(1)
// // const txt = 'ehohehoh... wayoh wayoh wayoh-wayoh!'
// // t.true(typeof fliphash(txt) === 'number')
// // })
// //
// // test('hashes are the same', t => {
// // t.plan(1)
// // const txt = 'hullabaloo000&&&!!!eh'
// // t.is(fliphash(txt), fliphash(txt))
// // })
//
//
// module.exports = curry(2, wrap)
//# sourceMappingURL=data:application/json;charset=utf-8;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoid3JhcC5qcyIsInNvdXJjZXMiOlsid3JhcC5qcyJdLCJzb3VyY2VzQ29udGVudCI6WyIvKiogQGlnbm9yZSDwn5qnIHdpcCAqL1xuXG4vLyBjb25zdCB0b0Z1bmN0aW9uID0gcmVxdWlyZSgnLi4vY2FzdC90b0Z1bmN0aW9uJylcbi8vIGNvbnN0IGZvckluVW5ndWFyZGVkID0gcmVxdWlyZSgnLi4vbG9vcC9lYWNoL2ZvckluVW5ndWFyZGVkJylcbi8vXG4vLyBmdW5jdGlvbiBfX2VocyhhcmdzKSB7XG4vLyAgIHRoaXMuX19laCA9IDFcbi8vIH1cbi8vIGZ1bmN0aW9uIF9laHMoYXJncykge1xuLy8gICBfX2Vocy5jYWxsKHRoaXMpXG4vLyAgIHRoaXMuX2VoID0gYXJnc1xuLy8gfVxuLy9cbi8vIGNvbnN0IEVocyA9IHRvRnVuY3Rpb24oX2Vocylcbi8vIGZ1bmN0aW9uIGVocyhhcmdzKSB7XG4vLyAgIHJldHVybiBuZXcgX2VocyhhcmdzKVxuLy8gfVxuLy9cbi8vIGNvbnNvbGUubG9nKG5ldyBFaHMoMCkpXG4vL1xuLy8gY29uc3QgY29weSA9IHggPT4gZm9ySW5Vbmd1YXJkZWQoeCwgKHZhbHVlLCBrZXkpID0+IHhba2V5XSA9IHZhbHVlKVxuLy9cbi8vIC8vIGh0dHBzOi8vaDNtYW50aC5jb20vbmV3L2Jsb2cvMjAxNC90aGlzYXJnLWluLWphdmFzY3JpcHQvXG4vLyAvLyBjb25zdCBmcENoYWluID0gKC4uLmNoYWlucykgPT4ge1xuLy8gLy8gICBmdW5jdGlvbiBmdW5jdGlvbkNvbnRleHQoKSB7XG4vLyAvLyAgICAgdGhpcy5zdG9yZSA9IG5ldyBNYXAoKVxuLy8gLy8gICAgIHJldHVybiB0aGlzXG4vLyAvLyAgIH1cbi8vIC8vICAgZnVuY3Rpb24gZWgoKSB7XG4vLyAvLyAgICAgZnVuY3Rpb25Db250ZXh0LmNhbGwodGhpcywgdGhpcylcbi8vIC8vICAgICBjb25zb2xlLmxvZyh0aGlzKVxuLy8gLy8gICB9XG4vL1xuLy8gLy8gICBmdW5jdGlvbiBpbmhlcml0KFBhcmVudCwgQ2hpbGQpIHtcbi8vIC8vICAgICBjb25zdCBQYXJlbnRQcm90b3R5cGUgPSBPYmplY3QuZ2V0UHJvdG90eXBlT2YoUGFyZW50KVxuLy8gLy8gICAgIE9iamVjdC5zZXRQcm90b3R5cGVPZihDaGlsZCwgUGFyZW50UHJvdG90eXBlKVxuLy8gLy8gICAgIENoYWluZWQucHJvdG90eXBlID0gT2JqZWN0LmNyZWF0ZShQYXJlbnRQcm90b3R5cGUpO1xuLy8gLy8gICAgIENoYWluZWQucHJvdG90eXBlLmNvbnN0cnVjdG9yID0gQ2hhaW5lZFxuLy8gLy8gICB9XG4vLyBmdW5jdGlvbiBfY2xhc3NDYWxsQ2hlY2soaW5zdGFuY2UsIENvbnN0cnVjdG9yKSB7XG4vLyAgIGlmICghKGluc3RhbmNlIGluc3RhbmNlb2YgQ29uc3RydWN0b3IpKSB7XG4vLyAgICAgdGhyb3cgbmV3IFR5cGVFcnJvcignQ2Fubm90IGNhbGwgYSBjbGFzcyBhcyBhIGZ1bmN0aW9uJylcbi8vICAgfVxuLy8gfVxuLy9cbi8vIGZ1bmN0aW9uIF9wb3NzaWJsZUNvbnN0cnVjdG9yUmV0dXJuKHNlbGYsIF9zdXBlcikge1xuLy8gICBpZiAoIXNlbGYpIHtcbi8vICAgICB0aHJvdyBuZXcgUmVmZXJlbmNlRXJyb3IoXG4vLyAgICAgICAndGhpcyBoYXNuXFwndCBiZWVuIGluaXRpYWxpc2VkIC0gc3VwZXIoKSBoYXNuXFwndCBiZWVuIGNhbGxlZCdcbi8vICAgICApXG4vLyAgIH1cbi8vXG4vLyAgIGNvbnN0IGNhbGwgPSBfc3VwZXIuY2FsbChzZWxmKVxuLy8gICByZXR1cm4gY2FsbCAmJiAodHlwZW9mIGNhbGwgPT09ICdvYmplY3QnIHx8IHR5cGVvZiBjYWxsID09PSAnZnVuY3Rpb24nKVxuLy8gICAgID8gY2FsbFxuLy8gICAgIDogc2VsZlxuLy8gfVxuLy9cbi8vIGZ1bmN0aW9uIF9pbmhlcml0cyhzdWJDbGFzcywgc3VwZXJDbGFzcykge1xuLy8gICBpZiAodHlwZW9mIHN1cGVyQ2xhc3MgIT09ICdmdW5jdGlvbicgJiYgc3VwZXJDbGFzcyAhPT0gbnVsbCkge1xuLy8gICAgIHRocm93IG5ldyBUeXBlRXJyb3IoXG4vLyAgICAgICAnU3VwZXIgZXhwcmVzc2lvbiBtdXN0IGVpdGhlciBiZSBudWxsIG9yIGEgZnVuY3Rpb24sIG5vdCAnICtcbi8vICAgICAgICAgdHlwZW9mIHN1cGVyQ2xhc3Ncbi8vICAgICApXG4vLyAgIH1cbi8vICAgc3ViQ2xhc3MucHJvdG90eXBlID0gT2JqZWN0LmNyZWF0ZShzdXBlckNsYXNzICYmIHN1cGVyQ2xhc3MucHJvdG90eXBlLCB7XG4vLyAgICAgY29uc3RydWN0b3I6IHtcbi8vICAgICAgIHZhbHVlOiBzdWJDbGFzcyxcbi8vICAgICAgIGVudW1lcmFibGU6IGZhbHNlLFxuLy8gICAgICAgd3JpdGFibGU6IHRydWUsXG4vLyAgICAgICBjb25maWd1cmFibGU6IHRydWUsXG4vLyAgICAgfSxcbi8vICAgfSlcbi8vICAgaWYgKHN1cGVyQ2xhc3MpXG4vLyAgICAgT2JqZWN0LnNldFByb3RvdHlwZU9mXG4vLyAgICAgICA/IE9iamVjdC5zZXRQcm90b3R5cGVPZihzdWJDbGFzcywgc3VwZXJDbGFzcylcbi8vICAgICAgIDogc3ViQ2xhc3MuX19wcm90b19fID0gc3VwZXJDbGFzc1xuLy9cbi8vICAgcmV0dXJuIGZ1bmN0aW9uIGNhbGxGb3JDb25zdHJ1Y3RvcihzZWxmKSB7XG4vLyAgICAgY29uc3QgY2FsbCA9IHN1cGVyQ2xhc3MuY2FsbChzZWxmKVxuLy8gICAgIHJldHVybiBjYWxsICYmICh0eXBlb2YgY2FsbCA9PT0gJ29iamVjdCcgfHwgdHlwZW9mIGNhbGwgPT09ICdmdW5jdGlvbicpXG4vLyAgICAgICA/IGNhbGxcbi8vICAgICAgIDogc2VsZlxuLy8gICB9XG4vLyB9XG4vL1xuLy8gZnVuY3Rpb24gZWgoKSB7XG4vLyAgIGNvbnNvbGUubG9nKCd3aGF0Jylcbi8vICAgdGhpcy5laCA9IHRydWVcbi8vICAgLy8gQE5PVEUgdGhpcyBpcyBhbiBleGFtcGxlIG9mIGNvbnN0cnVjdG9yIHJldHVybmluZyAmIG5vdCB1c2luZyBgdGhpc2Bcbi8vICAgdmFyIF90aGlzID0gY29weSh0aGlzKVxuLy8gICBfdGhpcy5fID0gMFxuLy8gICByZXR1cm4gX3RoaXNcbi8vIH1cbi8vXG4vLyBjb25zdCBfc3VwZXIgPSBlaFxuLy8gY29uc3QgY2FsbCA9IF9pbmhlcml0cyhDaGFpbmVkLCBfc3VwZXIpXG4vLyBmdW5jdGlvbiBDaGFpbmVkKCkge1xuLy8gICAvLyBfY2xhc3NDYWxsQ2hlY2sodGhpcywgQ2hhaW5lZClcbi8vICAgLy8gdmFyIF90aGlzID0gX3N1cGVyLmNhbGwodGhpcykgfHwgdGhpc1xuLy8gICB2YXIgX3RoaXMgPSBjYWxsKHRoaXMsIF9zdXBlcilcbi8vXG4vLyAgIC8vIF9zdXBlci5jYWxsKHRoaXMpXG4vLyAgIF90aGlzLmNhID0gdHJ1ZVxuLy8gICBjb25zb2xlLmxvZygnY2hhaW5lZCcpXG4vLyAgIHJldHVybiBfdGhpc1xuLy8gfVxuXG4vLyB2YXIgQ2hhaW5lZCA9IChmdW5jdGlvbihfc3VwZXIpIHtcbi8vICAgY29uc3QgY2FsbCA9IF9pbmhlcml0cyhDaGFpbmVkLCBfc3VwZXIpXG4vLyAgIGZ1bmN0aW9uIENoYWluZWQoKSB7XG4vLyAgICAgLy8gX2NsYXNzQ2FsbENoZWNrKHRoaXMsIENoYWluZWQpXG4vLyAgICAgLy8gdmFyIF90aGlzID0gX3N1cGVyLmNhbGwodGhpcykgfHwgdGhpc1xuLy8gICAgIHZhciBfdGhpcyA9IGNhbGwodGhpcywgX3N1cGVyKVxuLy9cbi8vICAgICAvLyBfc3VwZXIuY2FsbCh0aGlzKVxuLy8gICAgIF90aGlzLmNhID0gdHJ1ZVxuLy8gICAgIGNvbnNvbGUubG9nKCdjaGFpbmVkJylcbi8vICAgICByZXR1cm4gX3RoaXNcbi8vICAgfVxuLy9cbi8vICAgcmV0dXJuIENoYWluZWRcbi8vICAgLy8gcmV0dXJuIGJ1YmxlKENoYWluZWQsIF9zdXBlcilcbi8vIH0pXG4vLyBDaGFpbmVkID0gQ2hhaW5lZChlaClcblxuLy8gY29uc29sZS5sb2cobmV3IENoYWluZWQoKSlcbi8vIGNvbnNvbGUubG9nKHByb3RvcyhDaGFpbmVkKSwgcHJvdG9zKG5ldyBDaGFpbmVkKCkpKVxuLy8gY29uc29sZS5sb2coe0NoYWluZWR9KVxuLy8gY29uc29sZS5sb2cobmV3IENoYWluZWQoKSlcblxuLy8gZnBDaGFpbihbXSlcblxuLy8gY29uc3QgY3VycnkgPSByZXF1aXJlKCcuL2N1cnJ5Jylcbi8vXG4vLyAvKipcbi8vICAqIFJldHVybnMgdGhlIGZpcnN0IGZ1bmN0aW9uIHBhc3NlZCBhcyBhbiBhcmd1bWVudCB0byB0aGUgc2Vjb25kLFxuLy8gICogYWxsb3dpbmcgeW91IHRvIGFkanVzdCBhcmd1bWVudHMsIHJ1biBjb2RlIGJlZm9yZSBhbmQgYWZ0ZXIsIGFuZFxuLy8gICogY29uZGl0aW9uYWxseSBleGVjdXRlIHRoZSBvcmlnaW5hbCBmdW5jdGlvbi5cbi8vICAqXG4vLyAgKiBAbWVtYmVyT2YgZnBcbi8vICAqIEBzaW5jZSA1LjAuMC1iZXRhLjVcbi8vICAqXG4vLyAgKiBAcGFyYW0ge0Z1bmN0aW9ufSBmbiBmdW5jdGlvbiB0byB3cmFwXG4vLyAgKiBAcGFyYW0ge0Z1bmN0aW9ufSB3cmFwIGZ1bmN0aW9uIHRoYXQgd3JhcHMgYGZuYFxuLy8gICpcbi8vICAqIEBzeW1iIPCfjaxcbi8vICAqIEBuYW1lIHdyYXBcbi8vICAqXG4vLyAgKiB7QGxpbmsgaHR0cDovL3VuZGVyc2NvcmVqcy5vcmcvI3dyYXAgdW5kZXJzY29yZS13cmFwfVxuLy8gICoge0BsaW5rIGh0dHBzOi8vZ2l0aHViLmNvbS9qYXNoa2VuYXMvdW5kZXJzY29yZS9ibG9iL21hc3Rlci91bmRlcnNjb3JlLmpzI0w5MDkgdW5kZXJzY29yZS1zcmMtd3JhcH1cbi8vICAqIEBzZWUge0BsaW5rIHVuZGVyc2NvcmUtd3JhcH1cbi8vICAqIEBzZWUge0BsaW5rIHVuZGVyc2NvcmUtc3JjLXdyYXB9XG4vLyAgKlxuLy8gICogQGV4YW1wbGVcbi8vICAqXG4vLyAgKiAgIHZhciBoZWxsbyA9IGZ1bmN0aW9uKG5hbWUpIHsgcmV0dXJuIFwiaGVsbG86IFwiICsgbmFtZTsgfTtcbi8vICAqICAgaGVsbG8gPSB3cmFwKGhlbGxvLCBmdW5jdGlvbihmdW5jKSB7XG4vLyAgKiAgICAgcmV0dXJuIFwiYmVmb3JlLCBcIiArIGZ1bmMoXCJtb2VcIikgKyBcIiwgYWZ0ZXJcIjtcbi8vICAqICAgfSlcbi8vICAqXG4vLyAgKiAgIGhlbGxvKClcbi8vICAqICAgLy89PiAnYmVmb3JlLCBoZWxsbzogbW9lLCBhZnRlcidcbi8vICAqXG4vLyAgKi9cbi8vIGZ1bmN0aW9uIHdyYXAoZm4sIHdyYXBwZXIpIHtcbi8vICAgLy8gdGhpcyBqdXN0IHBhc3NlcyBgZm5gIGludG8gd3JhcC4uLlxuLy8gICAvLyBtYXliZSwgaW5zdGVhZCwgYWRkIGBwcmVgICYgYHBvc3RgXG4vLyAgIC8vIHdhcyBgcGFydGlhbCh3cmFwcGVyLCBmbilgXG4vLyAgIHJldHVybiBjdXJyeSgzLCB3cmFwcGVyLCBmbilcbi8vIH1cbi8vXG4vLyBjb25zdCBhcmd1bWVudG9yID0gcmVxdWlyZSgnLi4vY2FzdC9hcmd1bWVudG9yJylcbi8vIGNvbnN0IGlzRnVuY3Rpb24gPSByZXF1aXJlKCcuLi9pcy9mdW5jdGlvbicpXG4vL1xuLy8gLy8gQFRPRE8gbWF5YmUgcmV0dXJuaW5nIGBmYWxzZWAgd2lsbCBkaXNhYmxlIHRoZSBmdW5jdGlvbj9cbi8vIC8vICAgICAgIG9yIHJldHVybmluZyBgbm9vcGAgP1xuLy8gLy8gICAgICAgb3IgYW55dGhpbmcgYnV0IGBuaWxsYCA/XG4vLyBmdW5jdGlvbiBwcmUodGFyZ2V0LCBzdWJzY3JpYmVyKSB7XG4vLyAgIHJldHVybiBjdXJyeSh0YXJnZXQubGVuZ3RoLCBmdW5jdGlvbigpIHtcbi8vICAgICBjb25zdCBhcmdzID0gYXJndW1lbnRvci5hcHBseShudWxsLCBhcmd1bWVudHMpXG4vL1xuLy8gICAgIC8vIGNhbGwgc3Vic2NyaWJlclxuLy8gICAgIGNvbnN0IHJldHVybmVkID0gc3Vic2NyaWJlci5hcHBseSh0aGlzLCBhcmdzKVxuLy9cbi8vICAgICBpZiAocmV0dXJuZWQgPT09IGZhbHNlKSByZXR1cm4gbnVsbFxuLy8gICAgIGVsc2UgaWYgKGlzRnVuY3Rpb24ocmV0dXJuZWQpKSByZXR1cm4gcmV0dXJuZWRcbi8vICAgICBlbHNlIHJldHVybiB0YXJnZXQuYXBwbHkodGhpcywgYXJncylcbi8vICAgfSlcbi8vIH1cbi8vIGZ1bmN0aW9uIHBvc3QodGFyZ2V0LCBzdWJzY3JpYmVyKSB7XG4vLyAgIGNvbnN0IGFyZ3MgPSBhcmd1bWVudG9yLmFwcGx5KG51bGwsIGFyZ3VtZW50cylcbi8vICAgY29uc3QgcmV0dXJuZWQgPSB0YXJnZXQuYXBwbHkodGhpcywgYXJncylcbi8vXG4vLyAgIC8vIGFsc28gb3JpZ2luYWwgYXJncz8/XG4vLyAgIHN1YnNjcmliZXIuYXBwbHkobnVsbCwgcmV0dXJuZWQpXG4vLyB9XG4vL1xuLy8gLy8gaHR0cDovL3JhbWRhanMuY29tL2RvY3MvI21lbW9pemVXaXRoXG4vL1xuLy8gLy8gQU5EIFRIRU4sIENPVUxEIEpVU1QgVVNFIGBOVEhgIE9OIFJFVFVSTkVEXG4vL1xuLy8gLy8gSE9XIENBTiBUSEUgU1VCU0NSSUJFUlMgR0VUIFRIRSBSRVNVTFRTP1xuLy8gLy8gTElLRSBJRiBXRSBXQU5UIFRPIFNFRSBUSEUgUkVUVVJORUQgVkFMVUU/XG4vLyAvL1xuLy8gLy8gcmV0dXJuIHJlc3VsdCBmcm9tIGxhc3Q/XG4vLyAvLyBAZXhhbXBsZVxuLy8gLy9cbi8vIC8vICBjb25zdCBwcmUgPSBjb25zb2xlLmxvZ1xuLy8gLy8gIGNvbnN0IHBvc3QgPSBjb25zb2xlLmVycm9yXG4vLyAvLyAgY29uc3QgbXVsdGlwbHkgPSAobiwgZmFjdG9yKSA9PiBuICogZmFjdG9yXG4vLyAvLyAgbm90aWZ5RWFjaChwcmUsIG11bHRpcGx5LCBwb3N0KVxuLy8gZnVuY3Rpb24gbm90aWZ5RWFjaChzdWJzY3JpYmVycykge1xuLy8gICByZXR1cm4gZnVuY3Rpb24oKSB7XG4vLyAgICAgY29uc3QgYXJncyA9IGFyZ3VtZW50c1xuLy8gICAgIGNvbnN0IHJlc3VsdHMgPSBbXVxuLy8gICAgIHN1YnNjcmliZXJzLmZvckVhY2goc3Vic2NyaWJlciA9PiB7XG4vLyAgICAgICByZXN1bHRzLnB1c2goc3Vic2NyaWJlci5hcHBseShudWxsLCBhcmd1bWVudHMpKVxuLy8gICAgIH0pXG4vLyAgIH1cbi8vIH1cbi8vXG4vLyAvLyBVU0UgQVJSQVkgT0YgT0JKRUNUUywgVE8gQU4gT0JKRUNUIFdJVEggSU5ERVhFUyBBUyBBIFBST1BFUlRZXG4vLyBmdW5jdGlvbiBpbmRleEJ5KCkge31cbi8vXG4vL1xuLy8gLy8gUmV0dXJuIGEgcmFuZG9tIGludGVnZXIgYmV0d2VlbiBtaW4gYW5kIG1heCAoaW5jbHVzaXZlKS5cbi8vIGNvbnN0IHJhbmRvbSA9IGZ1bmN0aW9uKG1pbiwgbWF4KSB7XG4vLyAgIGlmIChpc05pbGwobWF4KSkge1xuLy8gICAgIG1heCA9IG1pblxuLy8gICAgIG1pbiA9IDBcbi8vICAgfVxuLy8gICByZXR1cm4gbWluICsgTWF0aC5mbG9vcihNYXRoLnJhbmRvbSgpICogKG1heCAtIG1pbiArIDEpKVxuLy8gfVxuLy9cbi8vIC8vIEBOT1RFIFVTRVMgTE9EQVNILk9SREVSQllcbi8vIGZ1bmN0aW9uIG9yZGVyQnlLZXlzKG9iaiwgb3JkZXJGaXJzdCkge1xuLy8gICBjb25zdCBvcmRlcmVkT2JqID0ge31cbi8vICAgb3JkZXJGaXJzdCA9IG9yZGVyRmlyc3QucmV2ZXJzZSgpXG4vLyAgIGNvbnN0IGtleXMgPSBPYmplY3Qua2V5cyhvYmopXG4vLyAgIF9zb3J0Qnkoa2V5cywga2V5ID0+IG9yZGVyRmlyc3QuaW5kZXhPZihrZXkpKVxuLy8gICAgIC5yZXZlcnNlKClcbi8vICAgICAuZm9yRWFjaChrZXkgPT4ge1xuLy8gICAgICAgb3JkZXJlZE9ialtrZXldID0gb2JqW2tleV1cbi8vICAgICB9KVxuLy8gICByZXR1cm4gb3JkZXJlZE9ialxuLy8gfVxuLy9cbi8vXG4vLyAvKipcbi8vICAqIEBleGFtcGxlXG4vLyAgKlxuLy8gICogcmVtYXBCeShwcm9wKCdpZCcpLCBbeydpZCc6ICdlaCd9XSlcbi8vICAqXG4vLyAgKiBAZXhhbXBsZVxuLy8gICogaW46IFtcbi8vICAqICB7aWQ6ICdlaCcsIHZhbDogJ2NhbmFkYSd9LFxuLy8gICogIHtpZDogJ21vb3NlJywgdmFsOiAnaWdsb28nfVxuLy8gICogXVxuLy8gICpcbi8vICAqIG91dDoge1xuLy8gICogICdlaCc6IHtpZDogJ2VoJywgdmFsOiAnY2FuYWRhJ30sXG4vLyAgKiAgJ21vb3NlJzoge2lkOiAnbW9vc2UnLCB2YWw6ICdpZ2xvbyd9XG4vLyAgKiB9XG4vLyAgKi9cbi8vIC8vIG9yIElOREVYQllcbi8vIGZ1bmN0aW9uIHJlbWFwQnkodHJhbnNmb3JtZXIsIHZhbHMpIHtcbi8vICAgY29uc3QgcmVtYXBwZWQgPSB7fVxuLy9cbi8vICAgLy8gQFRPRE86IHNob3VsZCByZWxvYWQgaWYgdGhlcmUgaXMgbm8gcmVtYXAgYnkgaWQgdmFscy4uLlxuLy8gICBpZiAoIWlzT2JqKHZhbHMpKSByZXR1cm4gcmVtYXBwZWRcbi8vXG4vLyAgIHZhciBhc09iaiA9IHZhbHVlcyh2YWxzKVxuLy9cbi8vICAgLy8gaWYgKGlzQXJyYXkodmFscykpIHtcbi8vICAgLy8gICAvLyBpZiBpdCBkb2VzIG5vdCBoYXZlIHRoZSBwcm9wLCBhZGQgaXQgYXMgdGhlIGluZGV4XG4vLyAgIC8vICAgLy8gaWYgaXQgaGFzIGl0LCBhbmQgaXQgaXMgYW4gYXJyYXksIGpvaW4gaXRcbi8vICAgLy8gICB2YWxzID0gdmFsdWVzLm1hcCgoZGF0YSwgaSkgPT4ge1xuLy8gICAvLyAgICAgaWYgKCFkYXRhW3Byb3BdKSBkYXRhW3Byb3BdID0gaVxuLy8gICAvLyAgICAgaWYgKGlzQXJyYXkoZGF0YVtwcm9wXSkpIGRhdGFbcHJvcF0gPSBkYXRhW3Byb3BdLmpvaW4oJywnKVxuLy8gICAvLyAgICAgcmV0dXJuIGRhdGFcbi8vICAgLy8gICB9KVxuLy8gICAvL1xuLy8gICAvLyAgIHJldHVybiBhcnJUb09iaih2YWx1ZXMsIHtcbi8vICAgLy8gICAgIGtleUZuOiAoe2l9KSA9PiB2YWx1ZXNbaV1bcHJvcF0sXG4vLyAgIC8vICAgICB2YWxGbjogKHtpLCB2YWx9KSA9PiB2YWwsXG4vLyAgIC8vICAgfSlcbi8vICAgLy8gfVxuLy9cbi8vICAgLy8gcmVtYXAgdG8gYWRkIGl0ZW0gaWQgYXMgb2JqZWN0IHByb3BlcnR5XG4vLyAgIGNvbnN0IHByb3BzID0ga2V5cyhhc09iailcbi8vICAgZm9yIChsZXQgaSA9IDAsIGxlbiA9IHByb3BzLmxlbmd0aDsgaSA8IGxlbjsgaSsrKSB7XG4vLyAgICAgY29uc3Qga2V5ID0gcHJvcHNbaV1cbi8vICAgICBjb25zdCB2YWwgPSBhc09ialtrZXldXG4vL1xuLy8gICAgIHJlbWFwcGVkW3ZhbC5pZF0gPSB2YWxcbi8vICAgfVxuLy8gICAvLyBjb25zb2xlLmRlYnVnKCdyZW1hcEJ5SWQnLCB7dmFsdWVzLCBhc09ian0pXG4vL1xuLy8gICByZXR1cm4gcmVtYXBwZWRcbi8vIH1cbi8vXG4vL1xuLy8gZnVuY3Rpb24gb21pdChvYmosIGtleXMpIHtcbi8vICAgY29uc3QgdGFyZ2V0ID0ge31cbi8vICAgZm9yIChsZXQgaSBpbiBvYmopIHtcbi8vICAgICBpZiAoa2V5cy5pbmRleE9mKGkpID49IDAgfHwgIWhhc093blByb3BlcnR5KG9iaiwgaSkpIGNvbnRpbnVlXG4vLyAgICAgdGFyZ2V0W2ldID0gb2JqW2ldXG4vLyAgIH1cbi8vICAgcmV0dXJuIHRhcmdldFxuLy8gfVxuLy9cbi8vXG4vLyAvLyBodHRwOi8vd2VyeGx0ZC5jb20vd3AvMjAxMC8wNS8xMy9qYXZhc2NyaXB0LWltcGxlbWVudGF0aW9uLW9mLWphdmFzLXN0cmluZy1oYXNoY29kZS1tZXRob2QvXG4vLyAvLyBtb2R1bGUuZXhwb3J0cyA9IGZ1bmN0aW9uIGZsaXBoYXNoKHN0cikge1xuLy8gLy8gICAvLyAgfHwgdHlwZW9mIHN0ciAhPT0gJ3N0cmluZydcbi8vIC8vICAgLy8gaWYgKHN0ciA9PT0gdW5kZWZpbmVkIHx8IHN0ciA9PT0gbnVsbCkge1xuLy8gLy8gICAvLyAgIGNvbnNvbGUubG9nKCd5b3UgcGFzc2VkIG5vdCByZWFsIHZhbHVlIHRvIGZsaXBoYXNoJylcbi8vIC8vICAgLy8gICByZXR1cm4gc3RyXG4vLyAvLyAgIC8vIH1cbi8vIC8vICAgaWYgKGlzTmlsbChzdHIpKSByZXR1cm4gJ25pbGwnXG4vLyAvLyAgIGxldCBsZW4gPSBzdHIubGVuZ3RoXG4vLyAvLyAgIGlmIChsZW4gPT09IDApIHJldHVybiAwXG4vLyAvL1xuLy8gLy8gICBsZXQgaGFzaCA9IDBcbi8vIC8vXG4vLyAvLyAgIGZvciAobGV0IGkgPSAwOyBpIDwgbGVuOyBpKyspIHtcbi8vIC8vICAgICBjb25zdCBjaGFyID0gc3RyLmNoYXJDb2RlQXQoaSlcbi8vIC8vICAgICBoYXNoID0gKChoYXNoIDw8IDUpIC0gaGFzaCkgKyBjaGFyXG4vLyAvLyAgICAgaGFzaCA9IGhhc2ggJiBoYXNoIC8vIENvbnZlcnQgdG8gMzJiaXQgaW50ZWdlclxuLy8gLy8gICB9XG4vLyAvLyAgIHJldHVybiBoYXNoXG4vLyAvLyB9XG4vLyAvL1xuLy8gLy8gY29uc3QgdGVzdCA9IHJlcXVpcmUoJ2F2YScpXG4vLyAvLyBjb25zdCBmbGlwaGFzaCA9IHJlcXVpcmUoJy4uLycpXG4vLyAvL1xuLy8gLy8gdGVzdCgnaGFzaGVzIGEgbnVtYmVyJywgdCA9PiB7XG4vLyAvLyAgIHQucGxhbigxKVxuLy8gLy8gICBjb25zdCB0eHQgPSAnZWhvaGVob2guLi4gd2F5b2ggd2F5b2ggd2F5b2gtd2F5b2ghJ1xuLy8gLy8gICB0LnRydWUodHlwZW9mIGZsaXBoYXNoKHR4dCkgPT09ICdudW1iZXInKVxuLy8gLy8gfSlcbi8vIC8vXG4vLyAvLyB0ZXN0KCdoYXNoZXMgYXJlIHRoZSBzYW1lJywgdCA9PiB7XG4vLyAvLyAgIHQucGxhbigxKVxuLy8gLy8gICBjb25zdCB0eHQgPSAnaHVsbGFiYWxvbzAwMCYmJiEhIWVoJ1xuLy8gLy8gICB0LmlzKGZsaXBoYXNoKHR4dCksIGZsaXBoYXNoKHR4dCkpXG4vLyAvLyB9KVxuLy9cbi8vXG4vLyBtb2R1bGUuZXhwb3J0cyA9IGN1cnJ5KDIsIHdyYXApXG4iXSwibmFtZXMiOltdLCJtYXBwaW5ncyI6IkFBQUE7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7OzsifQ==