foop
Version:
interfaces that describe their intentions.
162 lines (140 loc) • 14.3 kB
JavaScript
// conditionals
/* eslint complexity: "OFF" */
// not iterating on empty root
/* eslint consistent-return: "OFF" */
// const traverse = require('../traverse')
// const get = require('../dot/get')
var isObjNotNull = require('../is/objNotNull')
var isNull = require('../is/null')
var isEmpty = require('../is/empty')
var ENV_DEBUG = require('../env/debug')
var eqValue = require('./eqValue')
/* prettier-ignore */
/**
* @name eq
* @alias equals
* @since 3.0.0
* @version 5.0.0
* @memberOf Traverse
*
* {@link https://github.com/andrewplummer/Sugar/blob/master/lib/common.js#L668 sugar-equal}
* {@link https://github.com/the-grid/finitedomain/blob/master/src/propagator.js#L160 eq-qfox}
* {@link https://github.com/jasmine/jasmine.github.io/blob/master/lib/jasmine-1.3.1/jasmine.js#L940 jasmine-equals}
* {@link https://github.com/mobxjs/mobx/blob/master/src/utils/utils.ts#L145 mobx-deepequal}
* {@link https://github.com/js-data/js-data/blob/v2/src/utils.js#L571 js-data-circular}
* {@link https://github.com/js-data/js-data/blob/v2/src/utils.js#L300 js-data-equals}
* {@link http://dorey.github.io/JavaScript-Equality-Table/ js-equality-table}
* {@link https://github.com/facebook/react/blob/master/src/__mocks__/deepDiffer.js react-deep-differ}
* {@link https://github.com/substack/js-traverse/blob/master/test/lib/deep_equal.js traverse-deep-equal}
* {@link https://github.com/jashkenas/underscore/blob/master/underscore.js#L1183 underscore-equal}
* {@link https://github.com/angular/angular.js/blob/master/src/Angular.js angular-is-equal}
* {@link https://lodash.com/docs/4.17.4#isEqual lodash-is-equal}
* {@link http://ramdajs.com/docs/#equals ramda-equals}
* {@link https://github.com/substack/node-deep-equal node-deep-equal}
* {@link https://github.com/facebook/immutable-js/blob/master/src/utils/deepEqual.js immutable-js-deep-equal}
* @see {@link mobx-deepequal}
* @see {@link js-equality-table}
* @see {@link immutable-js-deep-equal}
* @see {@link node-deep-equal}
* @see {@link ramda-equals}
* @see {@link lodash-is-equal}
* @see {@link angular-is-equal}
* @see {@link underscore-equal}
* @see {@link traverse-deep-equal}
* @see {@link react-deep-differ}
* @see {@link js-data-equals}
* @see {@link jasmine-equals}
* @see {@link eq-qfox}
* @see {@link sugar-equal}
*
* @param {Traverse} traverse traversejs (scoped, @FIXME @HACK)
* @param {*} a compare to b
* @param {*} b compare to a
* @param {boolean} [loose] compare loosely
* @return {boolean} isEqual: a === b
*
* @extends eqValue
*
* @example
*
* eq(1, 1) //=> true
* eq(1, '1') //=> false
* eq(1, '1', true) //=> true
* eq([1], [1]) //=> true
*
*/
module.exports = function (traverse) { return function eq(a, b, loose) {
/* istanbul ignore next: dev */
if (ENV_DEBUG) {
console.log('\n')
}
var equal = true
var node = b
var nodes = [node]
var instance = traverse(a)
var notEqual = function () {
equal = false
instance.stop()
}
/* istanbul ignore next: dev */
if (ENV_DEBUG) {
console.log('eq?')
}
instance.forEach(function(key, y, traverser) {
// @NOTE do base comparisons on values that are not actually iteratable
// aka, .isRoot
if (isNull(key)) {
// always-valid state opionion vs always-invalid
// so it only returns false when it is !== fosho
if (eqValue(node, y, loose) === false) { return notEqual() }
else { return }
}
/* istanbul ignore next: dev */
if (ENV_DEBUG) {
console.log('eq: iterating:')
}
// could use it as a fallback if undefined && y !== undefined
// const xyz = get(b, traverser.path.join('.'), b)
var x = node
// isNotLeafAndIsObj
if (isObjNotNull(node) && !isEmpty(node)) {
/* istanbul ignore next: dev */
if (ENV_DEBUG) {
console.log('is leaf, is not empty node, going deeper')
}
// so x is our current one,
// if node is not empty, use the key, push the value
// and when it is empty, and it is not a leaf but has nodes, pop back up
x = node[key]
nodes.push(x)
}
// ENV_DEBUG
// console.log({[key]: {x, xyz, y, nodes, path: traverser.path.join('.')}})
// for next loop!!!
if (!traverser.isLeaf && !isEmpty(nodes)) {
/* istanbul ignore next: dev */
if (ENV_DEBUG) {
console.log('is not leaf, has nodes stack, pop')
}
node = nodes.pop()
}
/* istanbul ignore next: dev */
if (ENV_DEBUG) {
console.log({key: key, y: y, x: x, a: a, b: b})
}
var eqv = eqValue(x, y, loose)
/* istanbul ignore next: dev */
if (ENV_DEBUG) {
console.log({eqv: eqv})
}
if (eqv === false) {
// equal
notEqual()
}
})
// cleanup
nodes = undefined
node = undefined
return equal
}; }
//# sourceMappingURL=data:application/json;charset=utf-8;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiX2VxLmpzIiwic291cmNlcyI6WyJfZXEuanMiXSwic291cmNlc0NvbnRlbnQiOlsiLy8gY29uZGl0aW9uYWxzXG4vKiBlc2xpbnQgY29tcGxleGl0eTogXCJPRkZcIiAqL1xuXG4vLyBub3QgaXRlcmF0aW5nIG9uIGVtcHR5IHJvb3Rcbi8qIGVzbGludCBjb25zaXN0ZW50LXJldHVybjogXCJPRkZcIiAqL1xuXG4vLyBjb25zdCB0cmF2ZXJzZSA9IHJlcXVpcmUoJy4uL3RyYXZlcnNlJylcbi8vIGNvbnN0IGdldCA9IHJlcXVpcmUoJy4uL2RvdC9nZXQnKVxuY29uc3QgaXNPYmpOb3ROdWxsID0gcmVxdWlyZSgnLi4vaXMvb2JqTm90TnVsbCcpXG5jb25zdCBpc051bGwgPSByZXF1aXJlKCcuLi9pcy9udWxsJylcbmNvbnN0IGlzRW1wdHkgPSByZXF1aXJlKCcuLi9pcy9lbXB0eScpXG5jb25zdCBFTlZfREVCVUcgPSByZXF1aXJlKCcuLi9lbnYvZGVidWcnKVxuY29uc3QgZXFWYWx1ZSA9IHJlcXVpcmUoJy4vZXFWYWx1ZScpXG5cbi8qIHByZXR0aWVyLWlnbm9yZSAqL1xuLyoqXG4gKiBAbmFtZSBlcVxuICogQGFsaWFzIGVxdWFsc1xuICogQHNpbmNlIDMuMC4wXG4gKiBAdmVyc2lvbiA1LjAuMFxuICogQG1lbWJlck9mIFRyYXZlcnNlXG4gKlxuICoge0BsaW5rIGh0dHBzOi8vZ2l0aHViLmNvbS9hbmRyZXdwbHVtbWVyL1N1Z2FyL2Jsb2IvbWFzdGVyL2xpYi9jb21tb24uanMjTDY2OCBzdWdhci1lcXVhbH1cbiAqIHtAbGluayBodHRwczovL2dpdGh1Yi5jb20vdGhlLWdyaWQvZmluaXRlZG9tYWluL2Jsb2IvbWFzdGVyL3NyYy9wcm9wYWdhdG9yLmpzI0wxNjAgZXEtcWZveH1cbiAqIHtAbGluayBodHRwczovL2dpdGh1Yi5jb20vamFzbWluZS9qYXNtaW5lLmdpdGh1Yi5pby9ibG9iL21hc3Rlci9saWIvamFzbWluZS0xLjMuMS9qYXNtaW5lLmpzI0w5NDAgamFzbWluZS1lcXVhbHN9XG4gKiB7QGxpbmsgaHR0cHM6Ly9naXRodWIuY29tL21vYnhqcy9tb2J4L2Jsb2IvbWFzdGVyL3NyYy91dGlscy91dGlscy50cyNMMTQ1IG1vYngtZGVlcGVxdWFsfVxuICoge0BsaW5rIGh0dHBzOi8vZ2l0aHViLmNvbS9qcy1kYXRhL2pzLWRhdGEvYmxvYi92Mi9zcmMvdXRpbHMuanMjTDU3MSBqcy1kYXRhLWNpcmN1bGFyfVxuICoge0BsaW5rIGh0dHBzOi8vZ2l0aHViLmNvbS9qcy1kYXRhL2pzLWRhdGEvYmxvYi92Mi9zcmMvdXRpbHMuanMjTDMwMCBqcy1kYXRhLWVxdWFsc31cbiAqIHtAbGluayBodHRwOi8vZG9yZXkuZ2l0aHViLmlvL0phdmFTY3JpcHQtRXF1YWxpdHktVGFibGUvIGpzLWVxdWFsaXR5LXRhYmxlfVxuICoge0BsaW5rIGh0dHBzOi8vZ2l0aHViLmNvbS9mYWNlYm9vay9yZWFjdC9ibG9iL21hc3Rlci9zcmMvX19tb2Nrc19fL2RlZXBEaWZmZXIuanMgcmVhY3QtZGVlcC1kaWZmZXJ9XG4gKiB7QGxpbmsgaHR0cHM6Ly9naXRodWIuY29tL3N1YnN0YWNrL2pzLXRyYXZlcnNlL2Jsb2IvbWFzdGVyL3Rlc3QvbGliL2RlZXBfZXF1YWwuanMgdHJhdmVyc2UtZGVlcC1lcXVhbH1cbiAqIHtAbGluayBodHRwczovL2dpdGh1Yi5jb20vamFzaGtlbmFzL3VuZGVyc2NvcmUvYmxvYi9tYXN0ZXIvdW5kZXJzY29yZS5qcyNMMTE4MyB1bmRlcnNjb3JlLWVxdWFsfVxuICoge0BsaW5rIGh0dHBzOi8vZ2l0aHViLmNvbS9hbmd1bGFyL2FuZ3VsYXIuanMvYmxvYi9tYXN0ZXIvc3JjL0FuZ3VsYXIuanMgYW5ndWxhci1pcy1lcXVhbH1cbiAqIHtAbGluayBodHRwczovL2xvZGFzaC5jb20vZG9jcy80LjE3LjQjaXNFcXVhbCBsb2Rhc2gtaXMtZXF1YWx9XG4gKiB7QGxpbmsgaHR0cDovL3JhbWRhanMuY29tL2RvY3MvI2VxdWFscyByYW1kYS1lcXVhbHN9XG4gKiB7QGxpbmsgaHR0cHM6Ly9naXRodWIuY29tL3N1YnN0YWNrL25vZGUtZGVlcC1lcXVhbCBub2RlLWRlZXAtZXF1YWx9XG4gKiB7QGxpbmsgaHR0cHM6Ly9naXRodWIuY29tL2ZhY2Vib29rL2ltbXV0YWJsZS1qcy9ibG9iL21hc3Rlci9zcmMvdXRpbHMvZGVlcEVxdWFsLmpzIGltbXV0YWJsZS1qcy1kZWVwLWVxdWFsfVxuICogQHNlZSB7QGxpbmsgbW9ieC1kZWVwZXF1YWx9XG4gKiBAc2VlIHtAbGluayBqcy1lcXVhbGl0eS10YWJsZX1cbiAqIEBzZWUge0BsaW5rIGltbXV0YWJsZS1qcy1kZWVwLWVxdWFsfVxuICogQHNlZSB7QGxpbmsgbm9kZS1kZWVwLWVxdWFsfVxuICogQHNlZSB7QGxpbmsgcmFtZGEtZXF1YWxzfVxuICogQHNlZSB7QGxpbmsgbG9kYXNoLWlzLWVxdWFsfVxuICogQHNlZSB7QGxpbmsgYW5ndWxhci1pcy1lcXVhbH1cbiAqIEBzZWUge0BsaW5rIHVuZGVyc2NvcmUtZXF1YWx9XG4gKiBAc2VlIHtAbGluayB0cmF2ZXJzZS1kZWVwLWVxdWFsfVxuICogQHNlZSB7QGxpbmsgcmVhY3QtZGVlcC1kaWZmZXJ9XG4gKiBAc2VlIHtAbGluayBqcy1kYXRhLWVxdWFsc31cbiAqIEBzZWUge0BsaW5rIGphc21pbmUtZXF1YWxzfVxuICogQHNlZSB7QGxpbmsgZXEtcWZveH1cbiAqIEBzZWUge0BsaW5rIHN1Z2FyLWVxdWFsfVxuICpcbiAqIEBwYXJhbSB7VHJhdmVyc2V9IHRyYXZlcnNlIHRyYXZlcnNlanMgKHNjb3BlZCwgQEZJWE1FIEBIQUNLKVxuICogQHBhcmFtICB7Kn0gYSBjb21wYXJlIHRvIGJcbiAqIEBwYXJhbSAgeyp9IGIgY29tcGFyZSB0byBhXG4gKiBAcGFyYW0gIHtib29sZWFufSBbbG9vc2VdIGNvbXBhcmUgbG9vc2VseVxuICogQHJldHVybiB7Ym9vbGVhbn0gaXNFcXVhbDogYSA9PT0gYlxuICpcbiAqIEBleHRlbmRzIGVxVmFsdWVcbiAqXG4gKiBAZXhhbXBsZVxuICpcbiAqICAgIGVxKDEsIDEpICAgICAgICAgICAgLy89PiB0cnVlXG4gKiAgICBlcSgxLCAnMScpICAgICAgICAgIC8vPT4gZmFsc2VcbiAqICAgIGVxKDEsICcxJywgdHJ1ZSkgICAgLy89PiB0cnVlXG4gKiAgICBlcShbMV0sIFsxXSkgICAgICAgIC8vPT4gdHJ1ZVxuICpcbiAqL1xubW9kdWxlLmV4cG9ydHMgPSB0cmF2ZXJzZSA9PiBmdW5jdGlvbiBlcShhLCBiLCBsb29zZSkge1xuICAvKiBpc3RhbmJ1bCBpZ25vcmUgbmV4dDogZGV2ICovXG4gIGlmIChFTlZfREVCVUcpIHtcbiAgICBjb25zb2xlLmxvZygnXFxuJylcbiAgfVxuXG4gIGxldCBlcXVhbCA9IHRydWVcbiAgbGV0IG5vZGUgPSBiXG4gIGxldCBub2RlcyA9IFtub2RlXVxuXG4gIGNvbnN0IGluc3RhbmNlID0gdHJhdmVyc2UoYSlcblxuICBjb25zdCBub3RFcXVhbCA9ICgpID0+IHtcbiAgICBlcXVhbCA9IGZhbHNlXG4gICAgaW5zdGFuY2Uuc3RvcCgpXG4gIH1cblxuICAvKiBpc3RhbmJ1bCBpZ25vcmUgbmV4dDogZGV2ICovXG4gIGlmIChFTlZfREVCVUcpIHtcbiAgICBjb25zb2xlLmxvZygnZXE/JylcbiAgfVxuXG4gIGluc3RhbmNlLmZvckVhY2goZnVuY3Rpb24oa2V5LCB5LCB0cmF2ZXJzZXIpIHtcbiAgICAvLyBATk9URSBkbyBiYXNlIGNvbXBhcmlzb25zIG9uIHZhbHVlcyB0aGF0IGFyZSBub3QgYWN0dWFsbHkgaXRlcmF0YWJsZVxuICAgIC8vIGFrYSwgLmlzUm9vdFxuICAgIGlmIChpc051bGwoa2V5KSkge1xuICAgICAgLy8gYWx3YXlzLXZhbGlkIHN0YXRlIG9waW9uaW9uIHZzIGFsd2F5cy1pbnZhbGlkXG4gICAgICAvLyBzbyBpdCBvbmx5IHJldHVybnMgZmFsc2Ugd2hlbiBpdCBpcyAhPT0gZm9zaG9cbiAgICAgIGlmIChlcVZhbHVlKG5vZGUsIHksIGxvb3NlKSA9PT0gZmFsc2UpIHJldHVybiBub3RFcXVhbCgpXG4gICAgICBlbHNlIHJldHVyblxuICAgIH1cblxuICAgIC8qIGlzdGFuYnVsIGlnbm9yZSBuZXh0OiBkZXYgKi9cbiAgICBpZiAoRU5WX0RFQlVHKSB7XG4gICAgICBjb25zb2xlLmxvZygnZXE6IGl0ZXJhdGluZzonKVxuICAgIH1cblxuICAgIC8vIGNvdWxkIHVzZSBpdCBhcyBhIGZhbGxiYWNrIGlmIHVuZGVmaW5lZCAmJiB5ICE9PSB1bmRlZmluZWRcbiAgICAvLyBjb25zdCB4eXogPSBnZXQoYiwgdHJhdmVyc2VyLnBhdGguam9pbignLicpLCBiKVxuXG4gICAgbGV0IHggPSBub2RlXG5cbiAgICAvLyBpc05vdExlYWZBbmRJc09ialxuICAgIGlmIChpc09iak5vdE51bGwobm9kZSkgJiYgIWlzRW1wdHkobm9kZSkpIHtcbiAgICAgIC8qIGlzdGFuYnVsIGlnbm9yZSBuZXh0OiBkZXYgKi9cbiAgICAgIGlmIChFTlZfREVCVUcpIHtcbiAgICAgICAgY29uc29sZS5sb2coJ2lzIGxlYWYsIGlzIG5vdCBlbXB0eSBub2RlLCBnb2luZyBkZWVwZXInKVxuICAgICAgfVxuXG4gICAgICAvLyBzbyB4IGlzIG91ciBjdXJyZW50IG9uZSxcbiAgICAgIC8vIGlmIG5vZGUgaXMgbm90IGVtcHR5LCB1c2UgdGhlIGtleSwgcHVzaCB0aGUgdmFsdWVcbiAgICAgIC8vIGFuZCB3aGVuIGl0IGlzIGVtcHR5LCBhbmQgaXQgaXMgbm90IGEgbGVhZiBidXQgaGFzIG5vZGVzLCBwb3AgYmFjayB1cFxuICAgICAgeCA9IG5vZGVba2V5XVxuICAgICAgbm9kZXMucHVzaCh4KVxuICAgIH1cblxuICAgIC8vIEVOVl9ERUJVR1xuICAgIC8vIGNvbnNvbGUubG9nKHtba2V5XToge3gsIHh5eiwgeSwgbm9kZXMsIHBhdGg6IHRyYXZlcnNlci5wYXRoLmpvaW4oJy4nKX19KVxuXG4gICAgLy8gZm9yIG5leHQgbG9vcCEhIVxuICAgIGlmICghdHJhdmVyc2VyLmlzTGVhZiAmJiAhaXNFbXB0eShub2RlcykpIHtcbiAgICAgIC8qIGlzdGFuYnVsIGlnbm9yZSBuZXh0OiBkZXYgKi9cbiAgICAgIGlmIChFTlZfREVCVUcpIHtcbiAgICAgICAgY29uc29sZS5sb2coJ2lzIG5vdCBsZWFmLCBoYXMgbm9kZXMgc3RhY2ssIHBvcCcpXG4gICAgICB9XG4gICAgICBub2RlID0gbm9kZXMucG9wKClcbiAgICB9XG5cbiAgICAvKiBpc3RhbmJ1bCBpZ25vcmUgbmV4dDogZGV2ICovXG4gICAgaWYgKEVOVl9ERUJVRykge1xuICAgICAgY29uc29sZS5sb2coe2tleSwgeSwgeCwgYSwgYn0pXG4gICAgfVxuXG4gICAgY29uc3QgZXF2ID0gZXFWYWx1ZSh4LCB5LCBsb29zZSlcblxuICAgIC8qIGlzdGFuYnVsIGlnbm9yZSBuZXh0OiBkZXYgKi9cbiAgICBpZiAoRU5WX0RFQlVHKSB7XG4gICAgICBjb25zb2xlLmxvZyh7ZXF2fSlcbiAgICB9XG5cbiAgICBpZiAoZXF2ID09PSBmYWxzZSkge1xuICAgICAgLy8gZXF1YWxcbiAgICAgIG5vdEVxdWFsKClcbiAgICB9XG4gIH0pXG5cbiAgLy8gY2xlYW51cFxuICBub2RlcyA9IHVuZGVmaW5lZFxuICBub2RlID0gdW5kZWZpbmVkXG5cbiAgcmV0dXJuIGVxdWFsXG59XG4iXSwibmFtZXMiOlsiY29uc3QiLCJsZXQiXSwibWFwcGluZ3MiOiJBQUFBOzs7Ozs7OztBQVFBQSxHQUFLLENBQUMsWUFBWSxHQUFHLE9BQU8sQ0FBQyxrQkFBa0IsQ0FBQztBQUNoREEsR0FBSyxDQUFDLE1BQU0sR0FBRyxPQUFPLENBQUMsWUFBWSxDQUFDO0FBQ3BDQSxHQUFLLENBQUMsT0FBTyxHQUFHLE9BQU8sQ0FBQyxhQUFhLENBQUM7QUFDdENBLEdBQUssQ0FBQyxTQUFTLEdBQUcsT0FBTyxDQUFDLGNBQWMsQ0FBQztBQUN6Q0EsR0FBSyxDQUFDLE9BQU8sR0FBRyxPQUFPLENBQUMsV0FBVyxDQUFDOzs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7OztBQXdEcEMsTUFBTSxDQUFDLE9BQU8sR0FBRyxVQUFBLFFBQVEsQ0FBQSxDQUFDLEFBQUcsU0FBQSxTQUFTLEVBQUUsQ0FBQyxDQUFDLEVBQUUsQ0FBQyxFQUFFLEtBQUssRUFBRTs7RUFFcEQsSUFBSSxTQUFTLEVBQUU7SUFDYixPQUFPLENBQUMsR0FBRyxDQUFDLElBQUksQ0FBQztHQUNsQjs7RUFFREMsR0FBRyxDQUFDLEtBQUssR0FBRyxJQUFJO0VBQ2hCQSxHQUFHLENBQUMsSUFBSSxHQUFHLENBQUM7RUFDWkEsR0FBRyxDQUFDLEtBQUssR0FBRyxDQUFDLElBQUksQ0FBQzs7RUFFbEJELEdBQUssQ0FBQyxRQUFRLEdBQUcsUUFBUSxDQUFDLENBQUMsQ0FBQzs7RUFFNUJBLEdBQUssQ0FBQyxRQUFRLEdBQUcsU0FBQSxHQUFHLEFBQUc7SUFDckIsS0FBSyxHQUFHLEtBQUs7SUFDYixRQUFRLENBQUMsSUFBSSxFQUFFO0dBQ2hCOzs7RUFHRCxJQUFJLFNBQVMsRUFBRTtJQUNiLE9BQU8sQ0FBQyxHQUFHLENBQUMsS0FBSyxDQUFDO0dBQ25COztFQUVELFFBQVEsQ0FBQyxPQUFPLENBQUMsU0FBUyxHQUFHLEVBQUUsQ0FBQyxFQUFFLFNBQVMsRUFBRTs7O0lBRzNDLElBQUksTUFBTSxDQUFDLEdBQUcsQ0FBQyxFQUFFOzs7TUFHZixJQUFJLE9BQU8sQ0FBQyxJQUFJLEVBQUUsQ0FBQyxFQUFFLEtBQUssQ0FBQyxLQUFLLEtBQUssRUFBRSxFQUFBLE9BQU8sUUFBUSxFQUFFLEVBQUE7V0FDbkQsRUFBQSxNQUFNLEVBQUE7S0FDWjs7O0lBR0QsSUFBSSxTQUFTLEVBQUU7TUFDYixPQUFPLENBQUMsR0FBRyxDQUFDLGdCQUFnQixDQUFDO0tBQzlCOzs7OztJQUtEQyxHQUFHLENBQUMsQ0FBQyxHQUFHLElBQUk7OztJQUdaLElBQUksWUFBWSxDQUFDLElBQUksQ0FBQyxJQUFJLENBQUMsT0FBTyxDQUFDLElBQUksQ0FBQyxFQUFFOztNQUV4QyxJQUFJLFNBQVMsRUFBRTtRQUNiLE9BQU8sQ0FBQyxHQUFHLENBQUMsMENBQTBDLENBQUM7T0FDeEQ7Ozs7O01BS0QsQ0FBQyxHQUFHLElBQUksQ0FBQyxHQUFHLENBQUM7TUFDYixLQUFLLENBQUMsSUFBSSxDQUFDLENBQUMsQ0FBQztLQUNkOzs7Ozs7SUFNRCxJQUFJLENBQUMsU0FBUyxDQUFDLE1BQU0sSUFBSSxDQUFDLE9BQU8sQ0FBQyxLQUFLLENBQUMsRUFBRTs7TUFFeEMsSUFBSSxTQUFTLEVBQUU7UUFDYixPQUFPLENBQUMsR0FBRyxDQUFDLG1DQUFtQyxDQUFDO09BQ2pEO01BQ0QsSUFBSSxHQUFHLEtBQUssQ0FBQyxHQUFHLEVBQUU7S0FDbkI7OztJQUdELElBQUksU0FBUyxFQUFFO01BQ2IsT0FBTyxDQUFDLEdBQUcsQ0FBQyxDQUFDLEtBQUEsR0FBRyxFQUFFLEdBQUEsQ0FBQyxFQUFFLEdBQUEsQ0FBQyxFQUFFLEdBQUEsQ0FBQyxFQUFFLEdBQUEsQ0FBQyxDQUFDLENBQUM7S0FDL0I7O0lBRURELEdBQUssQ0FBQyxHQUFHLEdBQUcsT0FBTyxDQUFDLENBQUMsRUFBRSxDQUFDLEVBQUUsS0FBSyxDQUFDOzs7SUFHaEMsSUFBSSxTQUFTLEVBQUU7TUFDYixPQUFPLENBQUMsR0FBRyxDQUFDLENBQUMsS0FBQSxHQUFHLENBQUMsQ0FBQztLQUNuQjs7SUFFRCxJQUFJLEdBQUcsS0FBSyxLQUFLLEVBQUU7O01BRWpCLFFBQVEsRUFBRTtLQUNYO0dBQ0YsQ0FBQzs7O0VBR0YsS0FBSyxHQUFHLFNBQVM7RUFDakIsSUFBSSxHQUFHLFNBQVM7O0VBRWhCLE9BQU8sS0FBSztDQUNiLEdBQUE7In0=