@circuitly/diff
Version:
A javascript text diff implementation.
278 lines (270 loc) • 37.2 kB
JavaScript
;
Object.defineProperty(exports, "__esModule", {
value: true
});
exports["default"] = Diff;
function Diff() {}
Diff.prototype = {
diff: function diff(oldString, newString) {
var _options$timeout, _options$timeout2, _options;
var options = arguments.length > 2 && arguments[2] !== undefined ? arguments[2] : {};
var callback = options.callback;
if (typeof options === 'function') {
callback = options;
options = {};
}
var self = this;
function done(value) {
value = self.postProcess(value, options);
if (callback) {
setTimeout(function () {
callback(value);
}, 0);
return undefined;
} else {
return value;
}
}
// Allow subclasses to massage the input prior to running
oldString = this.castInput(oldString, options);
newString = this.castInput(newString, options);
oldString = this.removeEmpty(this.tokenize(oldString, options));
newString = this.removeEmpty(this.tokenize(newString, options));
var newLen = newString.length,
oldLen = oldString.length;
var editLength = 1;
var maxEditLength = newLen + oldLen;
if (options.maxEditLength != null) {
maxEditLength = Math.min(maxEditLength, options.maxEditLength);
}
var maxExecutionTime = (_options$timeout = options.timeout) !== null && _options$timeout !== void 0 ? _options$timeout : Infinity;
var abortAfterTimestamp = Date.now() + maxExecutionTime;
var bestPath = [{
oldPos: -1,
lastComponent: undefined
}];
// Seed editLength = 0, i.e. the content starts with the same values
var newPos = this.extractCommon(bestPath[0], newString, oldString, 0, options);
if (bestPath[0].oldPos + 1 >= oldLen && newPos + 1 >= newLen) {
// Identity per the equality and tokenizer
return done(buildValues(self, bestPath[0].lastComponent, newString, oldString, self.useLongestToken));
}
// Once we hit the right edge of the edit graph on some diagonal k, we can
// definitely reach the end of the edit graph in no more than k edits, so
// there's no point in considering any moves to diagonal k+1 any more (from
// which we're guaranteed to need at least k+1 more edits).
// Similarly, once we've reached the bottom of the edit graph, there's no
// point considering moves to lower diagonals.
// We record this fact by setting minDiagonalToConsider and
// maxDiagonalToConsider to some finite value once we've hit the edge of
// the edit graph.
// This optimization is not faithful to the original algorithm presented in
// Myers's paper, which instead pointlessly extends D-paths off the end of
// the edit graph - see page 7 of Myers's paper which notes this point
// explicitly and illustrates it with a diagram. This has major performance
// implications for some common scenarios. For instance, to compute a diff
// where the new text simply appends d characters on the end of the
// original text of length n, the true Myers algorithm will take O(n+d^2)
// time while this optimization needs only O(n+d) time.
var minDiagonalToConsider = -Infinity,
maxDiagonalToConsider = Infinity;
// Main worker method. checks all permutations of a given edit length for acceptance.
function execEditLength() {
for (var diagonalPath = Math.max(minDiagonalToConsider, -editLength); diagonalPath <= Math.min(maxDiagonalToConsider, editLength); diagonalPath += 2) {
var basePath = void 0;
var removePath = bestPath[diagonalPath - 1],
addPath = bestPath[diagonalPath + 1];
if (removePath) {
// No one else is going to attempt to use this value, clear it
bestPath[diagonalPath - 1] = undefined;
}
var canAdd = false;
if (addPath) {
// what newPos will be after we do an insertion:
var addPathNewPos = addPath.oldPos - diagonalPath;
canAdd = addPath && 0 <= addPathNewPos && addPathNewPos < newLen;
}
var canRemove = removePath && removePath.oldPos + 1 < oldLen;
if (!canAdd && !canRemove) {
// If this path is a terminal then prune
bestPath[diagonalPath] = undefined;
continue;
}
// Select the diagonal that we want to branch from. We select the prior
// path whose position in the old string is the farthest from the origin
// and does not pass the bounds of the diff graph
if (!canRemove || canAdd && removePath.oldPos < addPath.oldPos) {
basePath = self.addToPath(addPath, true, false, 0, options);
} else {
basePath = self.addToPath(removePath, false, true, 1, options);
}
newPos = self.extractCommon(basePath, newString, oldString, diagonalPath, options);
if (options.returnPartialResults && Date.now() > abortAfterTimestamp) {
options.gotPartialResults = true;
return done(buildValues(self, basePath.lastComponent, newString, oldString, self.useLongestToken));
}
if (basePath.oldPos + 1 >= oldLen && newPos + 1 >= newLen) {
// If we have hit the end of both strings, then we are done
return done(buildValues(self, basePath.lastComponent, newString, oldString, self.useLongestToken)) || true;
} else {
bestPath[diagonalPath] = basePath;
if (basePath.oldPos + 1 >= oldLen) {
maxDiagonalToConsider = Math.min(maxDiagonalToConsider, diagonalPath - 1);
}
if (newPos + 1 >= newLen) {
minDiagonalToConsider = Math.max(minDiagonalToConsider, diagonalPath + 1);
}
}
}
editLength++;
}
// Performs the length of edit iteration. Is a bit fugly as this has to support the
// sync and async mode which is never fun. Loops over execEditLength until a value
// is produced, or until the edit length exceeds options.maxEditLength (if given),
// in which case it will return undefined.
var abortAfterTimestamp2 = options.returnPartialResults ? abortAfterTimestamp + ((_options$timeout2 = (_options = options) === null || _options === void 0 ? void 0 : _options.timeout) !== null && _options$timeout2 !== void 0 ? _options$timeout2 : 0.0) * 1.25 : abortAfterTimestamp;
if (callback) {
(function exec() {
setTimeout(function () {
if (editLength > maxEditLength || Date.now() > abortAfterTimestamp2) {
return callback();
}
if (!execEditLength()) {
exec();
}
}, 0);
})();
} else {
while (editLength <= maxEditLength && Date.now() <= abortAfterTimestamp2) {
var ret = execEditLength();
if (ret) {
return ret;
}
}
}
},
addToPath: function addToPath(path, added, removed, oldPosInc, options) {
var last = path.lastComponent;
if (last && !options.oneChangePerToken && last.added === added && last.removed === removed) {
return {
oldPos: path.oldPos + oldPosInc,
lastComponent: {
count: last.count + 1,
added: added,
removed: removed,
previousComponent: last.previousComponent
}
};
} else {
return {
oldPos: path.oldPos + oldPosInc,
lastComponent: {
count: 1,
added: added,
removed: removed,
previousComponent: last
}
};
}
},
extractCommon: function extractCommon(basePath, newString, oldString, diagonalPath, options) {
var newLen = newString.length,
oldLen = oldString.length,
oldPos = basePath.oldPos,
newPos = oldPos - diagonalPath,
commonCount = 0;
while (newPos + 1 < newLen && oldPos + 1 < oldLen && this.equals(oldString[oldPos + 1], newString[newPos + 1], options)) {
newPos++;
oldPos++;
commonCount++;
if (options.oneChangePerToken) {
basePath.lastComponent = {
count: 1,
previousComponent: basePath.lastComponent,
added: false,
removed: false
};
}
}
if (commonCount && !options.oneChangePerToken) {
basePath.lastComponent = {
count: commonCount,
previousComponent: basePath.lastComponent,
added: false,
removed: false
};
}
basePath.oldPos = oldPos;
return newPos;
},
equals: function equals(left, right, options) {
if (options.comparator) {
return options.comparator(left, right);
} else {
return left === right || options.ignoreCase && left.toLowerCase() === right.toLowerCase();
}
},
removeEmpty: function removeEmpty(array) {
var ret = [];
for (var i = 0; i < array.length; i++) {
if (array[i]) {
ret.push(array[i]);
}
}
return ret;
},
castInput: function castInput(value) {
return value;
},
tokenize: function tokenize(value) {
return Array.from(value);
},
join: function join(chars) {
return chars.join('');
},
postProcess: function postProcess(changeObjects) {
return changeObjects;
}
};
function buildValues(diff, lastComponent, newString, oldString, useLongestToken) {
// First we convert our linked list of components in reverse order to an
// array in the right order:
var components = [];
var nextComponent;
while (lastComponent) {
components.push(lastComponent);
nextComponent = lastComponent.previousComponent;
delete lastComponent.previousComponent;
lastComponent = nextComponent;
}
components.reverse();
var componentPos = 0,
componentLen = components.length,
newPos = 0,
oldPos = 0;
for (; componentPos < componentLen; componentPos++) {
var component = components[componentPos];
if (!component.removed) {
if (!component.added && useLongestToken) {
var value = newString.slice(newPos, newPos + component.count);
value = value.map(function (value, i) {
var oldValue = oldString[oldPos + i];
return oldValue.length > value.length ? oldValue : value;
});
component.value = diff.join(value);
} else {
component.value = diff.join(newString.slice(newPos, newPos + component.count));
}
newPos += component.count;
// Common case
if (!component.added) {
oldPos += component.count;
}
} else {
component.value = diff.join(oldString.slice(oldPos, oldPos + component.count));
oldPos += component.count;
}
}
return components;
}
//# sourceMappingURL=data:application/json;charset=utf-8;base64,eyJ2ZXJzaW9uIjozLCJuYW1lcyI6WyJEaWZmIiwicHJvdG90eXBlIiwiZGlmZiIsIm9sZFN0cmluZyIsIm5ld1N0cmluZyIsIl9vcHRpb25zJHRpbWVvdXQiLCJfb3B0aW9ucyR0aW1lb3V0MiIsIl9vcHRpb25zIiwib3B0aW9ucyIsImFyZ3VtZW50cyIsImxlbmd0aCIsInVuZGVmaW5lZCIsImNhbGxiYWNrIiwic2VsZiIsImRvbmUiLCJ2YWx1ZSIsInBvc3RQcm9jZXNzIiwic2V0VGltZW91dCIsImNhc3RJbnB1dCIsInJlbW92ZUVtcHR5IiwidG9rZW5pemUiLCJuZXdMZW4iLCJvbGRMZW4iLCJlZGl0TGVuZ3RoIiwibWF4RWRpdExlbmd0aCIsIk1hdGgiLCJtaW4iLCJtYXhFeGVjdXRpb25UaW1lIiwidGltZW91dCIsIkluZmluaXR5IiwiYWJvcnRBZnRlclRpbWVzdGFtcCIsIkRhdGUiLCJub3ciLCJiZXN0UGF0aCIsIm9sZFBvcyIsImxhc3RDb21wb25lbnQiLCJuZXdQb3MiLCJleHRyYWN0Q29tbW9uIiwiYnVpbGRWYWx1ZXMiLCJ1c2VMb25nZXN0VG9rZW4iLCJtaW5EaWFnb25hbFRvQ29uc2lkZXIiLCJtYXhEaWFnb25hbFRvQ29uc2lkZXIiLCJleGVjRWRpdExlbmd0aCIsImRpYWdvbmFsUGF0aCIsIm1heCIsImJhc2VQYXRoIiwicmVtb3ZlUGF0aCIsImFkZFBhdGgiLCJjYW5BZGQiLCJhZGRQYXRoTmV3UG9zIiwiY2FuUmVtb3ZlIiwiYWRkVG9QYXRoIiwicmV0dXJuUGFydGlhbFJlc3VsdHMiLCJnb3RQYXJ0aWFsUmVzdWx0cyIsImFib3J0QWZ0ZXJUaW1lc3RhbXAyIiwiZXhlYyIsInJldCIsInBhdGgiLCJhZGRlZCIsInJlbW92ZWQiLCJvbGRQb3NJbmMiLCJsYXN0Iiwib25lQ2hhbmdlUGVyVG9rZW4iLCJjb3VudCIsInByZXZpb3VzQ29tcG9uZW50IiwiY29tbW9uQ291bnQiLCJlcXVhbHMiLCJsZWZ0IiwicmlnaHQiLCJjb21wYXJhdG9yIiwiaWdub3JlQ2FzZSIsInRvTG93ZXJDYXNlIiwiYXJyYXkiLCJpIiwicHVzaCIsIkFycmF5IiwiZnJvbSIsImpvaW4iLCJjaGFycyIsImNoYW5nZU9iamVjdHMiLCJjb21wb25lbnRzIiwibmV4dENvbXBvbmVudCIsInJldmVyc2UiLCJjb21wb25lbnRQb3MiLCJjb21wb25lbnRMZW4iLCJjb21wb25lbnQiLCJzbGljZSIsIm1hcCIsIm9sZFZhbHVlIl0sInNvdXJjZXMiOlsiLi4vLi4vc3JjL2RpZmYvYmFzZS5qcyJdLCJzb3VyY2VzQ29udGVudCI6WyJleHBvcnQgZGVmYXVsdCBmdW5jdGlvbiBEaWZmKCkge31cblxuRGlmZi5wcm90b3R5cGUgPSB7XG4gIGRpZmYob2xkU3RyaW5nLCBuZXdTdHJpbmcsIG9wdGlvbnMgPSB7fSkge1xuICAgIGxldCBjYWxsYmFjayA9IG9wdGlvbnMuY2FsbGJhY2s7XG4gICAgaWYgKHR5cGVvZiBvcHRpb25zID09PSAnZnVuY3Rpb24nKSB7XG4gICAgICBjYWxsYmFjayA9IG9wdGlvbnM7XG4gICAgICBvcHRpb25zID0ge307XG4gICAgfVxuXG4gICAgbGV0IHNlbGYgPSB0aGlzO1xuXG4gICAgZnVuY3Rpb24gZG9uZSh2YWx1ZSkge1xuICAgICAgdmFsdWUgPSBzZWxmLnBvc3RQcm9jZXNzKHZhbHVlLCBvcHRpb25zKTtcbiAgICAgIGlmIChjYWxsYmFjaykge1xuICAgICAgICBzZXRUaW1lb3V0KGZ1bmN0aW9uKCkgeyBjYWxsYmFjayh2YWx1ZSk7IH0sIDApO1xuICAgICAgICByZXR1cm4gdW5kZWZpbmVkO1xuICAgICAgfSBlbHNlIHtcbiAgICAgICAgcmV0dXJuIHZhbHVlO1xuICAgICAgfVxuICAgIH1cblxuICAgIC8vIEFsbG93IHN1YmNsYXNzZXMgdG8gbWFzc2FnZSB0aGUgaW5wdXQgcHJpb3IgdG8gcnVubmluZ1xuICAgIG9sZFN0cmluZyA9IHRoaXMuY2FzdElucHV0KG9sZFN0cmluZywgb3B0aW9ucyk7XG4gICAgbmV3U3RyaW5nID0gdGhpcy5jYXN0SW5wdXQobmV3U3RyaW5nLCBvcHRpb25zKTtcblxuICAgIG9sZFN0cmluZyA9IHRoaXMucmVtb3ZlRW1wdHkodGhpcy50b2tlbml6ZShvbGRTdHJpbmcsIG9wdGlvbnMpKTtcbiAgICBuZXdTdHJpbmcgPSB0aGlzLnJlbW92ZUVtcHR5KHRoaXMudG9rZW5pemUobmV3U3RyaW5nLCBvcHRpb25zKSk7XG5cbiAgICBsZXQgbmV3TGVuID0gbmV3U3RyaW5nLmxlbmd0aCwgb2xkTGVuID0gb2xkU3RyaW5nLmxlbmd0aDtcbiAgICBsZXQgZWRpdExlbmd0aCA9IDE7XG4gICAgbGV0IG1heEVkaXRMZW5ndGggPSBuZXdMZW4gKyBvbGRMZW47XG4gICAgaWYob3B0aW9ucy5tYXhFZGl0TGVuZ3RoICE9IG51bGwpIHtcbiAgICAgIG1heEVkaXRMZW5ndGggPSBNYXRoLm1pbihtYXhFZGl0TGVuZ3RoLCBvcHRpb25zLm1heEVkaXRMZW5ndGgpO1xuICAgIH1cbiAgICBjb25zdCBtYXhFeGVjdXRpb25UaW1lID0gb3B0aW9ucy50aW1lb3V0ID8/IEluZmluaXR5O1xuICAgIGNvbnN0IGFib3J0QWZ0ZXJUaW1lc3RhbXAgPSBEYXRlLm5vdygpICsgbWF4RXhlY3V0aW9uVGltZTtcblxuICAgIGxldCBiZXN0UGF0aCA9IFt7IG9sZFBvczogLTEsIGxhc3RDb21wb25lbnQ6IHVuZGVmaW5lZCB9XTtcblxuICAgIC8vIFNlZWQgZWRpdExlbmd0aCA9IDAsIGkuZS4gdGhlIGNvbnRlbnQgc3RhcnRzIHdpdGggdGhlIHNhbWUgdmFsdWVzXG4gICAgbGV0IG5ld1BvcyA9IHRoaXMuZXh0cmFjdENvbW1vbihiZXN0UGF0aFswXSwgbmV3U3RyaW5nLCBvbGRTdHJpbmcsIDAsIG9wdGlvbnMpO1xuICAgIGlmIChiZXN0UGF0aFswXS5vbGRQb3MgKyAxID49IG9sZExlbiAmJiBuZXdQb3MgKyAxID49IG5ld0xlbikge1xuICAgICAgLy8gSWRlbnRpdHkgcGVyIHRoZSBlcXVhbGl0eSBhbmQgdG9rZW5pemVyXG4gICAgICByZXR1cm4gZG9uZShidWlsZFZhbHVlcyhzZWxmLCBiZXN0UGF0aFswXS5sYXN0Q29tcG9uZW50LCBuZXdTdHJpbmcsIG9sZFN0cmluZywgc2VsZi51c2VMb25nZXN0VG9rZW4pKTtcbiAgICB9XG5cbiAgICAvLyBPbmNlIHdlIGhpdCB0aGUgcmlnaHQgZWRnZSBvZiB0aGUgZWRpdCBncmFwaCBvbiBzb21lIGRpYWdvbmFsIGssIHdlIGNhblxuICAgIC8vIGRlZmluaXRlbHkgcmVhY2ggdGhlIGVuZCBvZiB0aGUgZWRpdCBncmFwaCBpbiBubyBtb3JlIHRoYW4gayBlZGl0cywgc29cbiAgICAvLyB0aGVyZSdzIG5vIHBvaW50IGluIGNvbnNpZGVyaW5nIGFueSBtb3ZlcyB0byBkaWFnb25hbCBrKzEgYW55IG1vcmUgKGZyb21cbiAgICAvLyB3aGljaCB3ZSdyZSBndWFyYW50ZWVkIHRvIG5lZWQgYXQgbGVhc3QgaysxIG1vcmUgZWRpdHMpLlxuICAgIC8vIFNpbWlsYXJseSwgb25jZSB3ZSd2ZSByZWFjaGVkIHRoZSBib3R0b20gb2YgdGhlIGVkaXQgZ3JhcGgsIHRoZXJlJ3Mgbm9cbiAgICAvLyBwb2ludCBjb25zaWRlcmluZyBtb3ZlcyB0byBsb3dlciBkaWFnb25hbHMuXG4gICAgLy8gV2UgcmVjb3JkIHRoaXMgZmFjdCBieSBzZXR0aW5nIG1pbkRpYWdvbmFsVG9Db25zaWRlciBhbmRcbiAgICAvLyBtYXhEaWFnb25hbFRvQ29uc2lkZXIgdG8gc29tZSBmaW5pdGUgdmFsdWUgb25jZSB3ZSd2ZSBoaXQgdGhlIGVkZ2Ugb2ZcbiAgICAvLyB0aGUgZWRpdCBncmFwaC5cbiAgICAvLyBUaGlzIG9wdGltaXphdGlvbiBpcyBub3QgZmFpdGhmdWwgdG8gdGhlIG9yaWdpbmFsIGFsZ29yaXRobSBwcmVzZW50ZWQgaW5cbiAgICAvLyBNeWVycydzIHBhcGVyLCB3aGljaCBpbnN0ZWFkIHBvaW50bGVzc2x5IGV4dGVuZHMgRC1wYXRocyBvZmYgdGhlIGVuZCBvZlxuICAgIC8vIHRoZSBlZGl0IGdyYXBoIC0gc2VlIHBhZ2UgNyBvZiBNeWVycydzIHBhcGVyIHdoaWNoIG5vdGVzIHRoaXMgcG9pbnRcbiAgICAvLyBleHBsaWNpdGx5IGFuZCBpbGx1c3RyYXRlcyBpdCB3aXRoIGEgZGlhZ3JhbS4gVGhpcyBoYXMgbWFqb3IgcGVyZm9ybWFuY2VcbiAgICAvLyBpbXBsaWNhdGlvbnMgZm9yIHNvbWUgY29tbW9uIHNjZW5hcmlvcy4gRm9yIGluc3RhbmNlLCB0byBjb21wdXRlIGEgZGlmZlxuICAgIC8vIHdoZXJlIHRoZSBuZXcgdGV4dCBzaW1wbHkgYXBwZW5kcyBkIGNoYXJhY3RlcnMgb24gdGhlIGVuZCBvZiB0aGVcbiAgICAvLyBvcmlnaW5hbCB0ZXh0IG9mIGxlbmd0aCBuLCB0aGUgdHJ1ZSBNeWVycyBhbGdvcml0aG0gd2lsbCB0YWtlIE8obitkXjIpXG4gICAgLy8gdGltZSB3aGlsZSB0aGlzIG9wdGltaXphdGlvbiBuZWVkcyBvbmx5IE8obitkKSB0aW1lLlxuICAgIGxldCBtaW5EaWFnb25hbFRvQ29uc2lkZXIgPSAtSW5maW5pdHksIG1heERpYWdvbmFsVG9Db25zaWRlciA9IEluZmluaXR5O1xuXG4gICAgLy8gTWFpbiB3b3JrZXIgbWV0aG9kLiBjaGVja3MgYWxsIHBlcm11dGF0aW9ucyBvZiBhIGdpdmVuIGVkaXQgbGVuZ3RoIGZvciBhY2NlcHRhbmNlLlxuICAgIGZ1bmN0aW9uIGV4ZWNFZGl0TGVuZ3RoKCkge1xuICAgICAgZm9yIChcbiAgICAgICAgbGV0IGRpYWdvbmFsUGF0aCA9IE1hdGgubWF4KG1pbkRpYWdvbmFsVG9Db25zaWRlciwgLWVkaXRMZW5ndGgpO1xuICAgICAgICBkaWFnb25hbFBhdGggPD0gTWF0aC5taW4obWF4RGlhZ29uYWxUb0NvbnNpZGVyLCBlZGl0TGVuZ3RoKTtcbiAgICAgICAgZGlhZ29uYWxQYXRoICs9IDJcbiAgICAgICkge1xuICAgICAgICBsZXQgYmFzZVBhdGg7XG4gICAgICAgIGxldCByZW1vdmVQYXRoID0gYmVzdFBhdGhbZGlhZ29uYWxQYXRoIC0gMV0sXG4gICAgICAgICAgICBhZGRQYXRoID0gYmVzdFBhdGhbZGlhZ29uYWxQYXRoICsgMV07XG4gICAgICAgIGlmIChyZW1vdmVQYXRoKSB7XG4gICAgICAgICAgLy8gTm8gb25lIGVsc2UgaXMgZ29pbmcgdG8gYXR0ZW1wdCB0byB1c2UgdGhpcyB2YWx1ZSwgY2xlYXIgaXRcbiAgICAgICAgICBiZXN0UGF0aFtkaWFnb25hbFBhdGggLSAxXSA9IHVuZGVmaW5lZDtcbiAgICAgICAgfVxuXG4gICAgICAgIGxldCBjYW5BZGQgPSBmYWxzZTtcbiAgICAgICAgaWYgKGFkZFBhdGgpIHtcbiAgICAgICAgICAvLyB3aGF0IG5ld1BvcyB3aWxsIGJlIGFmdGVyIHdlIGRvIGFuIGluc2VydGlvbjpcbiAgICAgICAgICBjb25zdCBhZGRQYXRoTmV3UG9zID0gYWRkUGF0aC5vbGRQb3MgLSBkaWFnb25hbFBhdGg7XG4gICAgICAgICAgY2FuQWRkID0gYWRkUGF0aCAmJiAwIDw9IGFkZFBhdGhOZXdQb3MgJiYgYWRkUGF0aE5ld1BvcyA8IG5ld0xlbjtcbiAgICAgICAgfVxuXG4gICAgICAgIGxldCBjYW5SZW1vdmUgPSByZW1vdmVQYXRoICYmIHJlbW92ZVBhdGgub2xkUG9zICsgMSA8IG9sZExlbjtcbiAgICAgICAgaWYgKCFjYW5BZGQgJiYgIWNhblJlbW92ZSkge1xuICAgICAgICAgIC8vIElmIHRoaXMgcGF0aCBpcyBhIHRlcm1pbmFsIHRoZW4gcHJ1bmVcbiAgICAgICAgICBiZXN0UGF0aFtkaWFnb25hbFBhdGhdID0gdW5kZWZpbmVkO1xuICAgICAgICAgIGNvbnRpbnVlO1xuICAgICAgICB9XG5cbiAgICAgICAgLy8gU2VsZWN0IHRoZSBkaWFnb25hbCB0aGF0IHdlIHdhbnQgdG8gYnJhbmNoIGZyb20uIFdlIHNlbGVjdCB0aGUgcHJpb3JcbiAgICAgICAgLy8gcGF0aCB3aG9zZSBwb3NpdGlvbiBpbiB0aGUgb2xkIHN0cmluZyBpcyB0aGUgZmFydGhlc3QgZnJvbSB0aGUgb3JpZ2luXG4gICAgICAgIC8vIGFuZCBkb2VzIG5vdCBwYXNzIHRoZSBib3VuZHMgb2YgdGhlIGRpZmYgZ3JhcGhcbiAgICAgICAgaWYgKCFjYW5SZW1vdmUgfHwgKGNhbkFkZCAmJiByZW1vdmVQYXRoLm9sZFBvcyA8IGFkZFBhdGgub2xkUG9zKSkge1xuICAgICAgICAgIGJhc2VQYXRoID0gc2VsZi5hZGRUb1BhdGgoYWRkUGF0aCwgdHJ1ZSwgZmFsc2UsIDAsIG9wdGlvbnMpO1xuICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgIGJhc2VQYXRoID0gc2VsZi5hZGRUb1BhdGgocmVtb3ZlUGF0aCwgZmFsc2UsIHRydWUsIDEsIG9wdGlvbnMpO1xuICAgICAgICB9XG5cbiAgICAgICAgbmV3UG9zID0gc2VsZi5leHRyYWN0Q29tbW9uKGJhc2VQYXRoLCBuZXdTdHJpbmcsIG9sZFN0cmluZywgZGlhZ29uYWxQYXRoLCBvcHRpb25zKTtcblxuICAgICAgICBpZiAob3B0aW9ucy5yZXR1cm5QYXJ0aWFsUmVzdWx0cyAmJiBEYXRlLm5vdygpID4gYWJvcnRBZnRlclRpbWVzdGFtcCkge1xuICAgICAgICAgIG9wdGlvbnMuZ290UGFydGlhbFJlc3VsdHMgPSB0cnVlO1xuICAgICAgICAgIHJldHVybiBkb25lKGJ1aWxkVmFsdWVzKHNlbGYsIGJhc2VQYXRoLmxhc3RDb21wb25lbnQsIG5ld1N0cmluZywgb2xkU3RyaW5nLCBzZWxmLnVzZUxvbmdlc3RUb2tlbikpO1xuICAgICAgICB9XG5cbiAgICAgICAgaWYgKGJhc2VQYXRoLm9sZFBvcyArIDEgPj0gb2xkTGVuICYmIG5ld1BvcyArIDEgPj0gbmV3TGVuKSB7XG4gICAgICAgICAgLy8gSWYgd2UgaGF2ZSBoaXQgdGhlIGVuZCBvZiBib3RoIHN0cmluZ3MsIHRoZW4gd2UgYXJlIGRvbmVcbiAgICAgICAgICByZXR1cm4gZG9uZShidWlsZFZhbHVlcyhzZWxmLCBiYXNlUGF0aC5sYXN0Q29tcG9uZW50LCBuZXdTdHJpbmcsIG9sZFN0cmluZywgc2VsZi51c2VMb25nZXN0VG9rZW4pKSB8fCB0cnVlO1xuICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgIGJlc3RQYXRoW2RpYWdvbmFsUGF0aF0gPSBiYXNlUGF0aDtcbiAgICAgICAgICBpZiAoYmFzZVBhdGgub2xkUG9zICsgMSA+PSBvbGRMZW4pIHtcbiAgICAgICAgICAgIG1heERpYWdvbmFsVG9Db25zaWRlciA9IE1hdGgubWluKG1heERpYWdvbmFsVG9Db25zaWRlciwgZGlhZ29uYWxQYXRoIC0gMSk7XG4gICAgICAgICAgfVxuICAgICAgICAgIGlmIChuZXdQb3MgKyAxID49IG5ld0xlbikge1xuICAgICAgICAgICAgbWluRGlhZ29uYWxUb0NvbnNpZGVyID0gTWF0aC5tYXgobWluRGlhZ29uYWxUb0NvbnNpZGVyLCBkaWFnb25hbFBhdGggKyAxKTtcbiAgICAgICAgICB9XG4gICAgICAgIH1cbiAgICAgIH1cblxuICAgICAgZWRpdExlbmd0aCsrO1xuICAgIH1cblxuICAgIC8vIFBlcmZvcm1zIHRoZSBsZW5ndGggb2YgZWRpdCBpdGVyYXRpb24uIElzIGEgYml0IGZ1Z2x5IGFzIHRoaXMgaGFzIHRvIHN1cHBvcnQgdGhlXG4gICAgLy8gc3luYyBhbmQgYXN5bmMgbW9kZSB3aGljaCBpcyBuZXZlciBmdW4uIExvb3BzIG92ZXIgZXhlY0VkaXRMZW5ndGggdW50aWwgYSB2YWx1ZVxuICAgIC8vIGlzIHByb2R1Y2VkLCBvciB1bnRpbCB0aGUgZWRpdCBsZW5ndGggZXhjZWVkcyBvcHRpb25zLm1heEVkaXRMZW5ndGggKGlmIGdpdmVuKSxcbiAgICAvLyBpbiB3aGljaCBjYXNlIGl0IHdpbGwgcmV0dXJuIHVuZGVmaW5lZC5cbiAgICBjb25zdCBhYm9ydEFmdGVyVGltZXN0YW1wMiA9IG9wdGlvbnMucmV0dXJuUGFydGlhbFJlc3VsdHMgPyBhYm9ydEFmdGVyVGltZXN0YW1wICsgKG9wdGlvbnM/LnRpbWVvdXQgPz8gMC4wKSAqIDEuMjUgOiBhYm9ydEFmdGVyVGltZXN0YW1wO1xuICAgIGlmIChjYWxsYmFjaykge1xuICAgICAgKGZ1bmN0aW9uIGV4ZWMoKSB7XG4gICAgICAgIHNldFRpbWVvdXQoZnVuY3Rpb24oKSB7XG4gICAgICAgICAgaWYgKGVkaXRMZW5ndGggPiBtYXhFZGl0TGVuZ3RoIHx8IERhdGUubm93KCkgPiBhYm9ydEFmdGVyVGltZXN0YW1wMikge1xuICAgICAgICAgICAgcmV0dXJuIGNhbGxiYWNrKCk7XG4gICAgICAgICAgfVxuXG4gICAgICAgICAgaWYgKCFleGVjRWRpdExlbmd0aCgpKSB7XG4gICAgICAgICAgICBleGVjKCk7XG4gICAgICAgICAgfVxuICAgICAgICB9LCAwKTtcbiAgICAgIH0oKSk7XG4gICAgfSBlbHNlIHtcbiAgICAgIHdoaWxlIChlZGl0TGVuZ3RoIDw9IG1heEVkaXRMZW5ndGggJiYgRGF0ZS5ub3coKSA8PSBhYm9ydEFmdGVyVGltZXN0YW1wMikge1xuICAgICAgICBsZXQgcmV0ID0gZXhlY0VkaXRMZW5ndGgoKTtcbiAgICAgICAgaWYgKHJldCkge1xuICAgICAgICAgIHJldHVybiByZXQ7XG4gICAgICAgIH1cbiAgICAgIH1cbiAgICB9XG4gIH0sXG5cbiAgYWRkVG9QYXRoKHBhdGgsIGFkZGVkLCByZW1vdmVkLCBvbGRQb3NJbmMsIG9wdGlvbnMpIHtcbiAgICBsZXQgbGFzdCA9IHBhdGgubGFzdENvbXBvbmVudDtcbiAgICBpZiAobGFzdCAmJiAhb3B0aW9ucy5vbmVDaGFuZ2VQZXJUb2tlbiAmJiBsYXN0LmFkZGVkID09PSBhZGRlZCAmJiBsYXN0LnJlbW92ZWQgPT09IHJlbW92ZWQpIHtcbiAgICAgIHJldHVybiB7XG4gICAgICAgIG9sZFBvczogcGF0aC5vbGRQb3MgKyBvbGRQb3NJbmMsXG4gICAgICAgIGxhc3RDb21wb25lbnQ6IHtjb3VudDogbGFzdC5jb3VudCArIDEsIGFkZGVkOiBhZGRlZCwgcmVtb3ZlZDogcmVtb3ZlZCwgcHJldmlvdXNDb21wb25lbnQ6IGxhc3QucHJldmlvdXNDb21wb25lbnQgfVxuICAgICAgfTtcbiAgICB9IGVsc2Uge1xuICAgICAgcmV0dXJuIHtcbiAgICAgICAgb2xkUG9zOiBwYXRoLm9sZFBvcyArIG9sZFBvc0luYyxcbiAgICAgICAgbGFzdENvbXBvbmVudDoge2NvdW50OiAxLCBhZGRlZDogYWRkZWQsIHJlbW92ZWQ6IHJlbW92ZWQsIHByZXZpb3VzQ29tcG9uZW50OiBsYXN0IH1cbiAgICAgIH07XG4gICAgfVxuICB9LFxuICBleHRyYWN0Q29tbW9uKGJhc2VQYXRoLCBuZXdTdHJpbmcsIG9sZFN0cmluZywgZGlhZ29uYWxQYXRoLCBvcHRpb25zKSB7XG4gICAgbGV0IG5ld0xlbiA9IG5ld1N0cmluZy5sZW5ndGgsXG4gICAgICAgIG9sZExlbiA9IG9sZFN0cmluZy5sZW5ndGgsXG4gICAgICAgIG9sZFBvcyA9IGJhc2VQYXRoLm9sZFBvcyxcbiAgICAgICAgbmV3UG9zID0gb2xkUG9zIC0gZGlhZ29uYWxQYXRoLFxuXG4gICAgICAgIGNvbW1vbkNvdW50ID0gMDtcbiAgICB3aGlsZSAobmV3UG9zICsgMSA8IG5ld0xlbiAmJiBvbGRQb3MgKyAxIDwgb2xkTGVuICYmIHRoaXMuZXF1YWxzKG9sZFN0cmluZ1tvbGRQb3MgKyAxXSwgbmV3U3RyaW5nW25ld1BvcyArIDFdLCBvcHRpb25zKSkge1xuICAgICAgbmV3UG9zKys7XG4gICAgICBvbGRQb3MrKztcbiAgICAgIGNvbW1vbkNvdW50Kys7XG4gICAgICBpZiAob3B0aW9ucy5vbmVDaGFuZ2VQZXJUb2tlbikge1xuICAgICAgICBiYXNlUGF0aC5sYXN0Q29tcG9uZW50ID0ge2NvdW50OiAxLCBwcmV2aW91c0NvbXBvbmVudDogYmFzZVBhdGgubGFzdENvbXBvbmVudCwgYWRkZWQ6IGZhbHNlLCByZW1vdmVkOiBmYWxzZX07XG4gICAgICB9XG4gICAgfVxuXG4gICAgaWYgKGNvbW1vbkNvdW50ICYmICFvcHRpb25zLm9uZUNoYW5nZVBlclRva2VuKSB7XG4gICAgICBiYXNlUGF0aC5sYXN0Q29tcG9uZW50ID0ge2NvdW50OiBjb21tb25Db3VudCwgcHJldmlvdXNDb21wb25lbnQ6IGJhc2VQYXRoLmxhc3RDb21wb25lbnQsIGFkZGVkOiBmYWxzZSwgcmVtb3ZlZDogZmFsc2V9O1xuICAgIH1cblxuICAgIGJhc2VQYXRoLm9sZFBvcyA9IG9sZFBvcztcbiAgICByZXR1cm4gbmV3UG9zO1xuICB9LFxuXG4gIGVxdWFscyhsZWZ0LCByaWdodCwgb3B0aW9ucykge1xuICAgIGlmIChvcHRpb25zLmNvbXBhcmF0b3IpIHtcbiAgICAgIHJldHVybiBvcHRpb25zLmNvbXBhcmF0b3IobGVmdCwgcmlnaHQpO1xuICAgIH0gZWxzZSB7XG4gICAgICByZXR1cm4gbGVmdCA9PT0gcmlnaHRcbiAgICAgICAgfHwgKG9wdGlvbnMuaWdub3JlQ2FzZSAmJiBsZWZ0LnRvTG93ZXJDYXNlKCkgPT09IHJpZ2h0LnRvTG93ZXJDYXNlKCkpO1xuICAgIH1cbiAgfSxcbiAgcmVtb3ZlRW1wdHkoYXJyYXkpIHtcbiAgICBsZXQgcmV0ID0gW107XG4gICAgZm9yIChsZXQgaSA9IDA7IGkgPCBhcnJheS5sZW5ndGg7IGkrKykge1xuICAgICAgaWYgKGFycmF5W2ldKSB7XG4gICAgICAgIHJldC5wdXNoKGFycmF5W2ldKTtcbiAgICAgIH1cbiAgICB9XG4gICAgcmV0dXJuIHJldDtcbiAgfSxcbiAgY2FzdElucHV0KHZhbHVlKSB7XG4gICAgcmV0dXJuIHZhbHVlO1xuICB9LFxuICB0b2tlbml6ZSh2YWx1ZSkge1xuICAgIHJldHVybiBBcnJheS5mcm9tKHZhbHVlKTtcbiAgfSxcbiAgam9pbihjaGFycykge1xuICAgIHJldHVybiBjaGFycy5qb2luKCcnKTtcbiAgfSxcbiAgcG9zdFByb2Nlc3MoY2hhbmdlT2JqZWN0cykge1xuICAgIHJldHVybiBjaGFuZ2VPYmplY3RzO1xuICB9XG59O1xuXG5mdW5jdGlvbiBidWlsZFZhbHVlcyhkaWZmLCBsYXN0Q29tcG9uZW50LCBuZXdTdHJpbmcsIG9sZFN0cmluZywgdXNlTG9uZ2VzdFRva2VuKSB7XG4gIC8vIEZpcnN0IHdlIGNvbnZlcnQgb3VyIGxpbmtlZCBsaXN0IG9mIGNvbXBvbmVudHMgaW4gcmV2ZXJzZSBvcmRlciB0byBhblxuICAvLyBhcnJheSBpbiB0aGUgcmlnaHQgb3JkZXI6XG4gIGNvbnN0IGNvbXBvbmVudHMgPSBbXTtcbiAgbGV0IG5leHRDb21wb25lbnQ7XG4gIHdoaWxlIChsYXN0Q29tcG9uZW50KSB7XG4gICAgY29tcG9uZW50cy5wdXNoKGxhc3RDb21wb25lbnQpO1xuICAgIG5leHRDb21wb25lbnQgPSBsYXN0Q29tcG9uZW50LnByZXZpb3VzQ29tcG9uZW50O1xuICAgIGRlbGV0ZSBsYXN0Q29tcG9uZW50LnByZXZpb3VzQ29tcG9uZW50O1xuICAgIGxhc3RDb21wb25lbnQgPSBuZXh0Q29tcG9uZW50O1xuICB9XG4gIGNvbXBvbmVudHMucmV2ZXJzZSgpO1xuXG4gIGxldCBjb21wb25lbnRQb3MgPSAwLFxuICAgICAgY29tcG9uZW50TGVuID0gY29tcG9uZW50cy5sZW5ndGgsXG4gICAgICBuZXdQb3MgPSAwLFxuICAgICAgb2xkUG9zID0gMDtcblxuICBmb3IgKDsgY29tcG9uZW50UG9zIDwgY29tcG9uZW50TGVuOyBjb21wb25lbnRQb3MrKykge1xuICAgIGxldCBjb21wb25lbnQgPSBjb21wb25lbnRzW2NvbXBvbmVudFBvc107XG4gICAgaWYgKCFjb21wb25lbnQucmVtb3ZlZCkge1xuICAgICAgaWYgKCFjb21wb25lbnQuYWRkZWQgJiYgdXNlTG9uZ2VzdFRva2VuKSB7XG4gICAgICAgIGxldCB2YWx1ZSA9IG5ld1N0cmluZy5zbGljZShuZXdQb3MsIG5ld1BvcyArIGNvbXBvbmVudC5jb3VudCk7XG4gICAgICAgIHZhbHVlID0gdmFsdWUubWFwKGZ1bmN0aW9uKHZhbHVlLCBpKSB7XG4gICAgICAgICAgbGV0IG9sZFZhbHVlID0gb2xkU3RyaW5nW29sZFBvcyArIGldO1xuICAgICAgICAgIHJldHVybiBvbGRWYWx1ZS5sZW5ndGggPiB2YWx1ZS5sZW5ndGggPyBvbGRWYWx1ZSA6IHZhbHVlO1xuICAgICAgICB9KTtcblxuICAgICAgICBjb21wb25lbnQudmFsdWUgPSBkaWZmLmpvaW4odmFsdWUpO1xuICAgICAgfSBlbHNlIHtcbiAgICAgICAgY29tcG9uZW50LnZhbHVlID0gZGlmZi5qb2luKG5ld1N0cmluZy5zbGljZShuZXdQb3MsIG5ld1BvcyArIGNvbXBvbmVudC5jb3VudCkpO1xuICAgICAgfVxuICAgICAgbmV3UG9zICs9IGNvbXBvbmVudC5jb3VudDtcblxuICAgICAgLy8gQ29tbW9uIGNhc2VcbiAgICAgIGlmICghY29tcG9uZW50LmFkZGVkKSB7XG4gICAgICAgIG9sZFBvcyArPSBjb21wb25lbnQuY291bnQ7XG4gICAgICB9XG4gICAgfSBlbHNlIHtcbiAgICAgIGNvbXBvbmVudC52YWx1ZSA9IGRpZmYuam9pbihvbGRTdHJpbmcuc2xpY2Uob2xkUG9zLCBvbGRQb3MgKyBjb21wb25lbnQuY291bnQpKTtcbiAgICAgIG9sZFBvcyArPSBjb21wb25lbnQuY291bnQ7XG4gICAgfVxuICB9XG5cbiAgcmV0dXJuIGNvbXBvbmVudHM7XG59XG4iXSwibWFwcGluZ3MiOiI7Ozs7OztBQUFlLFNBQVNBLElBQUlBLENBQUEsRUFBRyxDQUFDO0FBRWhDQSxJQUFJLENBQUNDLFNBQVMsR0FBRztFQUNmQyxJQUFJLFdBQUpBLElBQUlBLENBQUNDLFNBQVMsRUFBRUMsU0FBUyxFQUFnQjtJQUFBLElBQUFDLGdCQUFBLEVBQUFDLGlCQUFBLEVBQUFDLFFBQUE7SUFBQSxJQUFkQyxPQUFPLEdBQUFDLFNBQUEsQ0FBQUMsTUFBQSxRQUFBRCxTQUFBLFFBQUFFLFNBQUEsR0FBQUYsU0FBQSxNQUFHLENBQUMsQ0FBQztJQUNyQyxJQUFJRyxRQUFRLEdBQUdKLE9BQU8sQ0FBQ0ksUUFBUTtJQUMvQixJQUFJLE9BQU9KLE9BQU8sS0FBSyxVQUFVLEVBQUU7TUFDakNJLFFBQVEsR0FBR0osT0FBTztNQUNsQkEsT0FBTyxHQUFHLENBQUMsQ0FBQztJQUNkO0lBRUEsSUFBSUssSUFBSSxHQUFHLElBQUk7SUFFZixTQUFTQyxJQUFJQSxDQUFDQyxLQUFLLEVBQUU7TUFDbkJBLEtBQUssR0FBR0YsSUFBSSxDQUFDRyxXQUFXLENBQUNELEtBQUssRUFBRVAsT0FBTyxDQUFDO01BQ3hDLElBQUlJLFFBQVEsRUFBRTtRQUNaSyxVQUFVLENBQUMsWUFBVztVQUFFTCxRQUFRLENBQUNHLEtBQUssQ0FBQztRQUFFLENBQUMsRUFBRSxDQUFDLENBQUM7UUFDOUMsT0FBT0osU0FBUztNQUNsQixDQUFDLE1BQU07UUFDTCxPQUFPSSxLQUFLO01BQ2Q7SUFDRjs7SUFFQTtJQUNBWixTQUFTLEdBQUcsSUFBSSxDQUFDZSxTQUFTLENBQUNmLFNBQVMsRUFBRUssT0FBTyxDQUFDO0lBQzlDSixTQUFTLEdBQUcsSUFBSSxDQUFDYyxTQUFTLENBQUNkLFNBQVMsRUFBRUksT0FBTyxDQUFDO0lBRTlDTCxTQUFTLEdBQUcsSUFBSSxDQUFDZ0IsV0FBVyxDQUFDLElBQUksQ0FBQ0MsUUFBUSxDQUFDakIsU0FBUyxFQUFFSyxPQUFPLENBQUMsQ0FBQztJQUMvREosU0FBUyxHQUFHLElBQUksQ0FBQ2UsV0FBVyxDQUFDLElBQUksQ0FBQ0MsUUFBUSxDQUFDaEIsU0FBUyxFQUFFSSxPQUFPLENBQUMsQ0FBQztJQUUvRCxJQUFJYSxNQUFNLEdBQUdqQixTQUFTLENBQUNNLE1BQU07TUFBRVksTUFBTSxHQUFHbkIsU0FBUyxDQUFDTyxNQUFNO0lBQ3hELElBQUlhLFVBQVUsR0FBRyxDQUFDO0lBQ2xCLElBQUlDLGFBQWEsR0FBR0gsTUFBTSxHQUFHQyxNQUFNO0lBQ25DLElBQUdkLE9BQU8sQ0FBQ2dCLGFBQWEsSUFBSSxJQUFJLEVBQUU7TUFDaENBLGFBQWEsR0FBR0MsSUFBSSxDQUFDQyxHQUFHLENBQUNGLGFBQWEsRUFBRWhCLE9BQU8sQ0FBQ2dCLGFBQWEsQ0FBQztJQUNoRTtJQUNBLElBQU1HLGdCQUFnQixJQUFBdEIsZ0JBQUEsR0FBR0csT0FBTyxDQUFDb0IsT0FBTyxjQUFBdkIsZ0JBQUEsY0FBQUEsZ0JBQUEsR0FBSXdCLFFBQVE7SUFDcEQsSUFBTUMsbUJBQW1CLEdBQUdDLElBQUksQ0FBQ0MsR0FBRyxDQUFDLENBQUMsR0FBR0wsZ0JBQWdCO0lBRXpELElBQUlNLFFBQVEsR0FBRyxDQUFDO01BQUVDLE1BQU0sRUFBRSxDQUFDLENBQUM7TUFBRUMsYUFBYSxFQUFFeEI7SUFBVSxDQUFDLENBQUM7O0lBRXpEO0lBQ0EsSUFBSXlCLE1BQU0sR0FBRyxJQUFJLENBQUNDLGFBQWEsQ0FBQ0osUUFBUSxDQUFDLENBQUMsQ0FBQyxFQUFFN0IsU0FBUyxFQUFFRCxTQUFTLEVBQUUsQ0FBQyxFQUFFSyxPQUFPLENBQUM7SUFDOUUsSUFBSXlCLFFBQVEsQ0FBQyxDQUFDLENBQUMsQ0FBQ0MsTUFBTSxHQUFHLENBQUMsSUFBSVosTUFBTSxJQUFJYyxNQUFNLEdBQUcsQ0FBQyxJQUFJZixNQUFNLEVBQUU7TUFDNUQ7TUFDQSxPQUFPUCxJQUFJLENBQUN3QixXQUFXLENBQUN6QixJQUFJLEVBQUVvQixRQUFRLENBQUMsQ0FBQyxDQUFDLENBQUNFLGFBQWEsRUFBRS9CLFNBQVMsRUFBRUQsU0FBUyxFQUFFVSxJQUFJLENBQUMwQixlQUFlLENBQUMsQ0FBQztJQUN2Rzs7SUFFQTtJQUNBO0lBQ0E7SUFDQTtJQUNBO0lBQ0E7SUFDQTtJQUNBO0lBQ0E7SUFDQTtJQUNBO0lBQ0E7SUFDQTtJQUNBO0lBQ0E7SUFDQTtJQUNBO0lBQ0EsSUFBSUMscUJBQXFCLEdBQUcsQ0FBQ1gsUUFBUTtNQUFFWSxxQkFBcUIsR0FBR1osUUFBUTs7SUFFdkU7SUFDQSxTQUFTYSxjQUFjQSxDQUFBLEVBQUc7TUFDeEIsS0FDRSxJQUFJQyxZQUFZLEdBQUdsQixJQUFJLENBQUNtQixHQUFHLENBQUNKLHFCQUFxQixFQUFFLENBQUNqQixVQUFVLENBQUMsRUFDL0RvQixZQUFZLElBQUlsQixJQUFJLENBQUNDLEdBQUcsQ0FBQ2UscUJBQXFCLEVBQUVsQixVQUFVLENBQUMsRUFDM0RvQixZQUFZLElBQUksQ0FBQyxFQUNqQjtRQUNBLElBQUlFLFFBQVE7UUFDWixJQUFJQyxVQUFVLEdBQUdiLFFBQVEsQ0FBQ1UsWUFBWSxHQUFHLENBQUMsQ0FBQztVQUN2Q0ksT0FBTyxHQUFHZCxRQUFRLENBQUNVLFlBQVksR0FBRyxDQUFDLENBQUM7UUFDeEMsSUFBSUcsVUFBVSxFQUFFO1VBQ2Q7VUFDQWIsUUFBUSxDQUFDVSxZQUFZLEdBQUcsQ0FBQyxDQUFDLEdBQUdoQyxTQUFTO1FBQ3hDO1FBRUEsSUFBSXFDLE1BQU0sR0FBRyxLQUFLO1FBQ2xCLElBQUlELE9BQU8sRUFBRTtVQUNYO1VBQ0EsSUFBTUUsYUFBYSxHQUFHRixPQUFPLENBQUNiLE1BQU0sR0FBR1MsWUFBWTtVQUNuREssTUFBTSxHQUFHRCxPQUFPLElBQUksQ0FBQyxJQUFJRSxhQUFhLElBQUlBLGFBQWEsR0FBRzVCLE1BQU07UUFDbEU7UUFFQSxJQUFJNkIsU0FBUyxHQUFHSixVQUFVLElBQUlBLFVBQVUsQ0FBQ1osTUFBTSxHQUFHLENBQUMsR0FBR1osTUFBTTtRQUM1RCxJQUFJLENBQUMwQixNQUFNLElBQUksQ0FBQ0UsU0FBUyxFQUFFO1VBQ3pCO1VBQ0FqQixRQUFRLENBQUNVLFlBQVksQ0FBQyxHQUFHaEMsU0FBUztVQUNsQztRQUNGOztRQUVBO1FBQ0E7UUFDQTtRQUNBLElBQUksQ0FBQ3VDLFNBQVMsSUFBS0YsTUFBTSxJQUFJRixVQUFVLENBQUNaLE1BQU0sR0FBR2EsT0FBTyxDQUFDYixNQUFPLEVBQUU7VUFDaEVXLFFBQVEsR0FBR2hDLElBQUksQ0FBQ3NDLFNBQVMsQ0FBQ0osT0FBTyxFQUFFLElBQUksRUFBRSxLQUFLLEVBQUUsQ0FBQyxFQUFFdkMsT0FBTyxDQUFDO1FBQzdELENBQUMsTUFBTTtVQUNMcUMsUUFBUSxHQUFHaEMsSUFBSSxDQUFDc0MsU0FBUyxDQUFDTCxVQUFVLEVBQUUsS0FBSyxFQUFFLElBQUksRUFBRSxDQUFDLEVBQUV0QyxPQUFPLENBQUM7UUFDaEU7UUFFQTRCLE1BQU0sR0FBR3ZCLElBQUksQ0FBQ3dCLGFBQWEsQ0FBQ1EsUUFBUSxFQUFFekMsU0FBUyxFQUFFRCxTQUFTLEVBQUV3QyxZQUFZLEVBQUVuQyxPQUFPLENBQUM7UUFFbEYsSUFBSUEsT0FBTyxDQUFDNEMsb0JBQW9CLElBQUlyQixJQUFJLENBQUNDLEdBQUcsQ0FBQyxDQUFDLEdBQUdGLG1CQUFtQixFQUFFO1VBQ3BFdEIsT0FBTyxDQUFDNkMsaUJBQWlCLEdBQUcsSUFBSTtVQUNoQyxPQUFPdkMsSUFBSSxDQUFDd0IsV0FBVyxDQUFDekIsSUFBSSxFQUFFZ0MsUUFBUSxDQUFDVixhQUFhLEVBQUUvQixTQUFTLEVBQUVELFNBQVMsRUFBRVUsSUFBSSxDQUFDMEIsZUFBZSxDQUFDLENBQUM7UUFDcEc7UUFFQSxJQUFJTSxRQUFRLENBQUNYLE1BQU0sR0FBRyxDQUFDLElBQUlaLE1BQU0sSUFBSWMsTUFBTSxHQUFHLENBQUMsSUFBSWYsTUFBTSxFQUFFO1VBQ3pEO1VBQ0EsT0FBT1AsSUFBSSxDQUFDd0IsV0FBVyxDQUFDekIsSUFBSSxFQUFFZ0MsUUFBUSxDQUFDVixhQUFhLEVBQUUvQixTQUFTLEVBQUVELFNBQVMsRUFBRVUsSUFBSSxDQUFDMEIsZUFBZSxDQUFDLENBQUMsSUFBSSxJQUFJO1FBQzVHLENBQUMsTUFBTTtVQUNMTixRQUFRLENBQUNVLFlBQVksQ0FBQyxHQUFHRSxRQUFRO1VBQ2pDLElBQUlBLFFBQVEsQ0FBQ1gsTUFBTSxHQUFHLENBQUMsSUFBSVosTUFBTSxFQUFFO1lBQ2pDbUIscUJBQXFCLEdBQUdoQixJQUFJLENBQUNDLEdBQUcsQ0FBQ2UscUJBQXFCLEVBQUVFLFlBQVksR0FBRyxDQUFDLENBQUM7VUFDM0U7VUFDQSxJQUFJUCxNQUFNLEdBQUcsQ0FBQyxJQUFJZixNQUFNLEVBQUU7WUFDeEJtQixxQkFBcUIsR0FBR2YsSUFBSSxDQUFDbUIsR0FBRyxDQUFDSixxQkFBcUIsRUFBRUcsWUFBWSxHQUFHLENBQUMsQ0FBQztVQUMzRTtRQUNGO01BQ0Y7TUFFQXBCLFVBQVUsRUFBRTtJQUNkOztJQUVBO0lBQ0E7SUFDQTtJQUNBO0lBQ0EsSUFBTStCLG9CQUFvQixHQUFHOUMsT0FBTyxDQUFDNEMsb0JBQW9CLEdBQUd0QixtQkFBbUIsR0FBRyxFQUFBeEIsaUJBQUEsSUFBQUMsUUFBQSxHQUFDQyxPQUFPLGNBQUFELFFBQUEsdUJBQVBBLFFBQUEsQ0FBU3FCLE9BQU8sY0FBQXRCLGlCQUFBLGNBQUFBLGlCQUFBLEdBQUksR0FBRyxJQUFJLElBQUksR0FBR3dCLG1CQUFtQjtJQUN4SSxJQUFJbEIsUUFBUSxFQUFFO01BQ1gsVUFBUzJDLElBQUlBLENBQUEsRUFBRztRQUNmdEMsVUFBVSxDQUFDLFlBQVc7VUFDcEIsSUFBSU0sVUFBVSxHQUFHQyxhQUFhLElBQUlPLElBQUksQ0FBQ0MsR0FBRyxDQUFDLENBQUMsR0FBR3NCLG9CQUFvQixFQUFFO1lBQ25FLE9BQU8xQyxRQUFRLENBQUMsQ0FBQztVQUNuQjtVQUVBLElBQUksQ0FBQzhCLGNBQWMsQ0FBQyxDQUFDLEVBQUU7WUFDckJhLElBQUksQ0FBQyxDQUFDO1VBQ1I7UUFDRixDQUFDLEVBQUUsQ0FBQyxDQUFDO01BQ1AsQ0FBQyxFQUFDLENBQUM7SUFDTCxDQUFDLE1BQU07TUFDTCxPQUFPaEMsVUFBVSxJQUFJQyxhQUFhLElBQUlPLElBQUksQ0FBQ0MsR0FBRyxDQUFDLENBQUMsSUFBSXNCLG9CQUFvQixFQUFFO1FBQ3hFLElBQUlFLEdBQUcsR0FBR2QsY0FBYyxDQUFDLENBQUM7UUFDMUIsSUFBSWMsR0FBRyxFQUFFO1VBQ1AsT0FBT0EsR0FBRztRQUNaO01BQ0Y7SUFDRjtFQUNGLENBQUM7RUFFREwsU0FBUyxXQUFUQSxTQUFTQSxDQUFDTSxJQUFJLEVBQUVDLEtBQUssRUFBRUMsT0FBTyxFQUFFQyxTQUFTLEVBQUVwRCxPQUFPLEVBQUU7SUFDbEQsSUFBSXFELElBQUksR0FBR0osSUFBSSxDQUFDdEIsYUFBYTtJQUM3QixJQUFJMEIsSUFBSSxJQUFJLENBQUNyRCxPQUFPLENBQUNzRCxpQkFBaUIsSUFBSUQsSUFBSSxDQUFDSCxLQUFLLEtBQUtBLEtBQUssSUFBSUcsSUFBSSxDQUFDRixPQUFPLEtBQUtBLE9BQU8sRUFBRTtNQUMxRixPQUFPO1FBQ0x6QixNQUFNLEVBQUV1QixJQUFJLENBQUN2QixNQUFNLEdBQUcwQixTQUFTO1FBQy9CekIsYUFBYSxFQUFFO1VBQUM0QixLQUFLLEVBQUVGLElBQUksQ0FBQ0UsS0FBSyxHQUFHLENBQUM7VUFBRUwsS0FBSyxFQUFFQSxLQUFLO1VBQUVDLE9BQU8sRUFBRUEsT0FBTztVQUFFSyxpQkFBaUIsRUFBRUgsSUFBSSxDQUFDRztRQUFrQjtNQUNuSCxDQUFDO0lBQ0gsQ0FBQyxNQUFNO01BQ0wsT0FBTztRQUNMOUIsTUFBTSxFQUFFdUIsSUFBSSxDQUFDdkIsTUFBTSxHQUFHMEIsU0FBUztRQUMvQnpCLGFBQWEsRUFBRTtVQUFDNEIsS0FBSyxFQUFFLENBQUM7VUFBRUwsS0FBSyxFQUFFQSxLQUFLO1VBQUVDLE9BQU8sRUFBRUEsT0FBTztVQUFFSyxpQkFBaUIsRUFBRUg7UUFBSztNQUNwRixDQUFDO0lBQ0g7RUFDRixDQUFDO0VBQ0R4QixhQUFhLFdBQWJBLGFBQWFBLENBQUNRLFFBQVEsRUFBRXpDLFNBQVMsRUFBRUQsU0FBUyxFQUFFd0MsWUFBWSxFQUFFbkMsT0FBTyxFQUFFO0lBQ25FLElBQUlhLE1BQU0sR0FBR2pCLFNBQVMsQ0FBQ00sTUFBTTtNQUN6QlksTUFBTSxHQUFHbkIsU0FBUyxDQUFDTyxNQUFNO01BQ3pCd0IsTUFBTSxHQUFHVyxRQUFRLENBQUNYLE1BQU07TUFDeEJFLE1BQU0sR0FBR0YsTUFBTSxHQUFHUyxZQUFZO01BRTlCc0IsV0FBVyxHQUFHLENBQUM7SUFDbkIsT0FBTzdCLE1BQU0sR0FBRyxDQUFDLEdBQUdmLE1BQU0sSUFBSWEsTUFBTSxHQUFHLENBQUMsR0FBR1osTUFBTSxJQUFJLElBQUksQ0FBQzRDLE1BQU0sQ0FBQy9ELFNBQVMsQ0FBQytCLE1BQU0sR0FBRyxDQUFDLENBQUMsRUFBRTlCLFNBQVMsQ0FBQ2dDLE1BQU0sR0FBRyxDQUFDLENBQUMsRUFBRTVCLE9BQU8sQ0FBQyxFQUFFO01BQ3ZINEIsTUFBTSxFQUFFO01BQ1JGLE1BQU0sRUFBRTtNQUNSK0IsV0FBVyxFQUFFO01BQ2IsSUFBSXpELE9BQU8sQ0FBQ3NELGlCQUFpQixFQUFFO1FBQzdCakIsUUFBUSxDQUFDVixhQUFhLEdBQUc7VUFBQzRCLEtBQUssRUFBRSxDQUFDO1VBQUVDLGlCQUFpQixFQUFFbkIsUUFBUSxDQUFDVixhQUFhO1VBQUV1QixLQUFLLEVBQUUsS0FBSztVQUFFQyxPQUFPLEVBQUU7UUFBSyxDQUFDO01BQzlHO0lBQ0Y7SUFFQSxJQUFJTSxXQUFXLElBQUksQ0FBQ3pELE9BQU8sQ0FBQ3NELGlCQUFpQixFQUFFO01BQzdDakIsUUFBUSxDQUFDVixhQUFhLEdBQUc7UUFBQzRCLEtBQUssRUFBRUUsV0FBVztRQUFFRCxpQkFBaUIsRUFBRW5CLFFBQVEsQ0FBQ1YsYUFBYTtRQUFFdUIsS0FBSyxFQUFFLEtBQUs7UUFBRUMsT0FBTyxFQUFFO01BQUssQ0FBQztJQUN4SDtJQUVBZCxRQUFRLENBQUNYLE1BQU0sR0FBR0EsTUFBTTtJQUN4QixPQUFPRSxNQUFNO0VBQ2YsQ0FBQztFQUVEOEIsTUFBTSxXQUFOQSxNQUFNQSxDQUFDQyxJQUFJLEVBQUVDLEtBQUssRUFBRTVELE9BQU8sRUFBRTtJQUMzQixJQUFJQSxPQUFPLENBQUM2RCxVQUFVLEVBQUU7TUFDdEIsT0FBTzdELE9BQU8sQ0FBQzZELFVBQVUsQ0FBQ0YsSUFBSSxFQUFFQyxLQUFLLENBQUM7SUFDeEMsQ0FBQyxNQUFNO01BQ0wsT0FBT0QsSUFBSSxLQUFLQyxLQUFLLElBQ2Y1RCxPQUFPLENBQUM4RCxVQUFVLElBQUlILElBQUksQ0FBQ0ksV0FBVyxDQUFDLENBQUMsS0FBS0gsS0FBSyxDQUFDRyxXQUFXLENBQUMsQ0FBRTtJQUN6RTtFQUNGLENBQUM7RUFDRHBELFdBQVcsV0FBWEEsV0FBV0EsQ0FBQ3FELEtBQUssRUFBRTtJQUNqQixJQUFJaEIsR0FBRyxHQUFHLEVBQUU7SUFDWixLQUFLLElBQUlpQixDQUFDLEdBQUcsQ0FBQyxFQUFFQSxDQUFDLEdBQUdELEtBQUssQ0FBQzlELE1BQU0sRUFBRStELENBQUMsRUFBRSxFQUFFO01BQ3JDLElBQUlELEtBQUssQ0FBQ0MsQ0FBQyxDQUFDLEVBQUU7UUFDWmpCLEdBQUcsQ0FBQ2tCLElBQUksQ0FBQ0YsS0FBSyxDQUFDQyxDQUFDLENBQUMsQ0FBQztNQUNwQjtJQUNGO0lBQ0EsT0FBT2pCLEdBQUc7RUFDWixDQUFDO0VBQ0R0QyxTQUFTLFdBQVRBLFNBQVNBLENBQUNILEtBQUssRUFBRTtJQUNmLE9BQU9BLEtBQUs7RUFDZCxDQUFDO0VBQ0RLLFFBQVEsV0FBUkEsUUFBUUEsQ0FBQ0wsS0FBSyxFQUFFO0lBQ2QsT0FBTzRELEtBQUssQ0FBQ0MsSUFBSSxDQUFDN0QsS0FBSyxDQUFDO0VBQzFCLENBQUM7RUFDRDhELElBQUksV0FBSkEsSUFBSUEsQ0FBQ0MsS0FBSyxFQUFFO0lBQ1YsT0FBT0EsS0FBSyxDQUFDRCxJQUFJLENBQUMsRUFBRSxDQUFDO0VBQ3ZCLENBQUM7RUFDRDdELFdBQVcsV0FBWEEsV0FBV0EsQ0FBQytELGFBQWEsRUFBRTtJQUN6QixPQUFPQSxhQUFhO0VBQ3RCO0FBQ0YsQ0FBQztBQUVELFNBQVN6QyxXQUFXQSxDQUFDcEMsSUFBSSxFQUFFaUMsYUFBYSxFQUFFL0IsU0FBUyxFQUFFRCxTQUFTLEVBQUVvQyxlQUFlLEVBQUU7RUFDL0U7RUFDQTtFQUNBLElBQU15QyxVQUFVLEdBQUcsRUFBRTtFQUNyQixJQUFJQyxhQUFhO0VBQ2pCLE9BQU85QyxhQUFhLEVBQUU7SUFDcEI2QyxVQUFVLENBQUNOLElBQUksQ0FBQ3ZDLGFBQWEsQ0FBQztJQUM5QjhDLGFBQWEsR0FBRzlDLGFBQWEsQ0FBQzZCLGlCQUFpQjtJQUMvQyxPQUFPN0IsYUFBYSxDQUFDNkIsaUJBQWlCO0lBQ3RDN0IsYUFBYSxHQUFHOEMsYUFBYTtFQUMvQjtFQUNBRCxVQUFVLENBQUNFLE9BQU8sQ0FBQyxDQUFDO0VBRXBCLElBQUlDLFlBQVksR0FBRyxDQUFDO0lBQ2hCQyxZQUFZLEdBQUdKLFVBQVUsQ0FBQ3RFLE1BQU07SUFDaEMwQixNQUFNLEdBQUcsQ0FBQztJQUNWRixNQUFNLEdBQUcsQ0FBQztFQUVkLE9BQU9pRCxZQUFZLEdBQUdDLFlBQVksRUFBRUQsWUFBWSxFQUFFLEVBQUU7SUFDbEQsSUFBSUUsU0FBUyxHQUFHTCxVQUFVLENBQUNHLFlBQVksQ0FBQztJQUN4QyxJQUFJLENBQUNFLFNBQVMsQ0FBQzFCLE9BQU8sRUFBRTtNQUN0QixJQUFJLENBQUMwQixTQUFTLENBQUMzQixLQUFLLElBQUluQixlQUFlLEVBQUU7UUFDdkMsSUFBSXhCLEtBQUssR0FBR1gsU0FBUyxDQUFDa0YsS0FBSyxDQUFDbEQsTUFBTSxFQUFFQSxNQUFNLEdBQUdpRCxTQUFTLENBQUN0QixLQUFLLENBQUM7UUFDN0RoRCxLQUFLLEdBQUdBLEtBQUssQ0FBQ3dFLEdBQUcsQ0FBQyxVQUFTeEUsS0FBSyxFQUFFMEQsQ0FBQyxFQUFFO1VBQ25DLElBQUllLFFBQVEsR0FBR3JGLFNBQVMsQ0FBQytCLE1BQU0sR0FBR3VDLENBQUMsQ0FBQztVQUNwQyxPQUFPZSxRQUFRLENBQUM5RSxNQUFNLEdBQUdLLEtBQUssQ0FBQ0wsTUFBTSxHQUFHOEUsUUFBUSxHQUFHekUsS0FBSztRQUMxRCxDQUFDLENBQUM7UUFFRnNFLFNBQVMsQ0FBQ3RFLEtBQUssR0FBR2IsSUFBSSxDQUFDMkUsSUFBSSxDQUFDOUQsS0FBSyxDQUFDO01BQ3BDLENBQUMsTUFBTTtRQUNMc0UsU0FBUyxDQUFDdEUsS0FBSyxHQUFHYixJQUFJLENBQUMyRSxJQUFJLENBQUN6RSxTQUFTLENBQUNrRixLQUFLLENBQUNsRCxNQUFNLEVBQUVBLE1BQU0sR0FBR2lELFNBQVMsQ0FBQ3RCLEtBQUssQ0FBQyxDQUFDO01BQ2hGO01BQ0EzQixNQUFNLElBQUlpRCxTQUFTLENBQUN0QixLQUFLOztNQUV6QjtNQUNBLElBQUksQ0FBQ3NCLFNBQVMsQ0FBQzNCLEtBQUssRUFBRTtRQUNwQnhCLE1BQU0sSUFBSW1ELFNBQVMsQ0FBQ3RCLEtBQUs7TUFDM0I7SUFDRixDQUFDLE1BQU07TUFDTHNCLFNBQVMsQ0FBQ3RFLEtBQUssR0FBR2IsSUFBSSxDQUFDMkUsSUFBSSxDQUFDMUUsU0FBUyxDQUFDbUYsS0FBSyxDQUFDcEQsTUFBTSxFQUFFQSxNQUFNLEdBQUdtRCxTQUFTLENBQUN0QixLQUFLLENBQUMsQ0FBQztNQUM5RTdCLE1BQU0sSUFBSW1ELFNBQVMsQ0FBQ3RCLEtBQUs7SUFDM0I7RUFDRjtFQUVBLE9BQU9pQixVQUFVO0FBQ25CIiwiaWdub3JlTGlzdCI6W119