kepler.gl
Version:
kepler.gl is a webgl based application to visualize large scale location data in the browser
261 lines (211 loc) • 28.4 kB
JavaScript
;
var _interopRequireDefault = require("@babel/runtime/helpers/interopRequireDefault");
Object.defineProperty(exports, "__esModule", {
value: true
});
exports.setFilterGpuMode = setFilterGpuMode;
exports.assignGpuChannels = assignGpuChannels;
exports.assignGpuChannel = assignGpuChannel;
exports.resetFilterGpuMode = resetFilterGpuMode;
exports.getGpuFilterProps = getGpuFilterProps;
exports.getDatasetFieldIndexForFilter = getDatasetFieldIndexForFilter;
var _defineProperty2 = _interopRequireDefault(require("@babel/runtime/helpers/defineProperty"));
var _utils = require("./utils");
var _defaultSettings = require("../constants/default-settings");
var _dataUtils = require("./data-utils");
var _moment = _interopRequireDefault(require("moment"));
function ownKeys(object, enumerableOnly) { var keys = Object.keys(object); if (Object.getOwnPropertySymbols) { var symbols = Object.getOwnPropertySymbols(object); if (enumerableOnly) symbols = symbols.filter(function (sym) { return Object.getOwnPropertyDescriptor(object, sym).enumerable; }); keys.push.apply(keys, symbols); } return keys; }
function _objectSpread(target) { for (var i = 1; i < arguments.length; i++) { var source = arguments[i] != null ? arguments[i] : {}; if (i % 2) { ownKeys(Object(source), true).forEach(function (key) { (0, _defineProperty2["default"])(target, key, source[key]); }); } else if (Object.getOwnPropertyDescriptors) { Object.defineProperties(target, Object.getOwnPropertyDescriptors(source)); } else { ownKeys(Object(source)).forEach(function (key) { Object.defineProperty(target, key, Object.getOwnPropertyDescriptor(source, key)); }); } } return target; }
/**
* Set gpu mode based on current number of gpu filters exists
* @type {typeof import('./gpu-filter-utils').setFilterGpuMode}
*/
function setFilterGpuMode(filter, filters) {
// filter can be applied to multiple datasets, hence gpu filter mode should also be
// an array, however, to keep us sane, for now, we only check if there is available channel for every dataId,
// if all of them has, we set gpu mode to true
// TODO: refactor filter so we don't keep an array of everything
filter.dataId.forEach(function (dataId, datasetIdx) {
var gpuFilters = filters.filter(function (f) {
return f.dataId.includes(dataId) && f.gpu;
});
if (filter.gpu && gpuFilters.length === _defaultSettings.MAX_GPU_FILTERS) {
return (0, _utils.set)(['gpu'], false, filter);
}
});
return filter;
}
/**
* Scan though all filters and assign gpu chanel to gpu filter
* @type {typeof import('./gpu-filter-utils').assignGpuChannels}
*/
function assignGpuChannels(allFilters) {
return allFilters.reduce(function (accu, f, index) {
var filters = accu; // if gpu is true assign and validate gpu Channel
if (f.gpu) {
f = assignGpuChannel(f, accu);
filters = (0, _utils.set)([index], f, accu);
}
return filters;
}, allFilters);
}
/**
* Assign a new gpu filter a channel based on first availability
* @type {typeof import('./gpu-filter-utils').assignGpuChannel}
*/
function assignGpuChannel(filter, filters) {
// find first available channel
if (!filter.gpu) {
return filter;
}
var gpuChannel = filter.gpuChannel || [];
filter.dataId.forEach(function (dataId, datasetIdx) {
var findGpuChannel = function findGpuChannel(channel) {
return function (f) {
var dataIdx = (0, _utils.toArray)(f.dataId).indexOf(dataId);
return f.id !== filter.id && dataIdx > -1 && f.gpu && (0, _utils.toArray)(f.gpuChannel)[dataIdx] === channel;
};
};
if (Number.isFinite(gpuChannel[datasetIdx]) && !filters.find(findGpuChannel(gpuChannel[datasetIdx]))) {
// if value is already assigned and valid
return;
}
var i = 0;
while (i < _defaultSettings.MAX_GPU_FILTERS) {
if (!filters.find(findGpuChannel(i))) {
gpuChannel[datasetIdx] = i;
return;
}
i++;
}
}); // if cannot find channel for all dataid, set gpu back to false
// TODO: refactor filter to handle same filter different gpu mode
if (!gpuChannel.length || !gpuChannel.every(Number.isFinite)) {
return _objectSpread(_objectSpread({}, filter), {}, {
gpu: false
});
}
return _objectSpread(_objectSpread({}, filter), {}, {
gpuChannel: gpuChannel
});
}
/**
* Edit filter.gpu to ensure that only
* X number of gpu filers can coexist.
* @type {typeof import('./gpu-filter-utils').resetFilterGpuMode}
*/
function resetFilterGpuMode(filters) {
var gpuPerDataset = {};
return filters.map(function (f, i) {
if (f.gpu) {
var gpu = true;
(0, _utils.toArray)(f.dataId).forEach(function (dataId) {
var count = gpuPerDataset[dataId];
if (count === _defaultSettings.MAX_GPU_FILTERS) {
gpu = false;
} else {
gpuPerDataset[dataId] = count ? count + 1 : 1;
}
});
if (!gpu) {
return (0, _utils.set)(['gpu'], false, f);
}
}
return f;
});
}
/**
* Initial filter uniform
* @returns {Array<Array<Number>>}
*/
function getEmptyFilterRange() {
return new Array(_defaultSettings.MAX_GPU_FILTERS).fill(0).map(function (d) {
return [0, 0];
});
}
/**
* Returns index of the data element.
* @param {any} d Data element with row index info.
* @returns number
*/
var defaultGetIndex = function defaultGetIndex(d) {
return d.index;
};
/**
* Returns value at the specified row from the data container.
* @param {import('./table-utils/data-container-interface').DataContainerInterface} dc Data container.
* @param {any} d Data element with row index info.
* @param {number} fieldIndex Column index in the data container.
* @returns
*/
var defaultGetData = function defaultGetData(dc, d, fieldIndex) {
return dc.valueAt(d.index, fieldIndex);
};
/**
* @param {Array<Object>} channels
* @param {string} dataId
* @param {Array<Object>} fields
* @return {Function} getFilterValue
*/
var getFilterValueAccessor = function getFilterValueAccessor(channels, dataId, fields) {
return function (dc) {
return function () {
var getIndex = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : defaultGetIndex;
var getData = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : defaultGetData;
return function (d) {
return (// for empty channel, value is 0 and min max would be [0, 0]
channels.map(function (filter) {
if (!filter) {
return 0;
}
var fieldIndex = getDatasetFieldIndexForFilter(dataId, filter);
var field = fields[fieldIndex];
var value = filter.type === _defaultSettings.FILTER_TYPES.timeRange ? field.filterProps && Array.isArray(field.filterProps.mappedValue) ? field.filterProps.mappedValue[getIndex(d)] : _moment["default"].utc(getData(dc, d, fieldIndex)).valueOf() : getData(dc, d, fieldIndex);
return (0, _dataUtils.notNullorUndefined)(value) ? value - filter.domain[0] : Number.MIN_SAFE_INTEGER;
})
);
};
};
};
};
/**
* Get filter properties for gpu filtering
* @type {typeof import('./gpu-filter-utils').getGpuFilterProps}
*/
function getGpuFilterProps(filters, dataId, fields) {
var filterRange = getEmptyFilterRange();
var triggers = {}; // array of filter for each channel, undefined, if no filter is assigned to that channel
var channels = [];
var _loop = function _loop(i) {
var filter = filters.find(function (f) {
return f.gpu && f.dataId.includes(dataId) && f.gpuChannel && f.gpuChannel[f.dataId.indexOf(dataId)] === i;
}); // @ts-ignore
filterRange[i][0] = filter ? filter.value[0] - filter.domain[0] : 0; // @ts-ignore
filterRange[i][1] = filter ? filter.value[1] - filter.domain[0] : 0;
triggers["gpuFilter_".concat(i)] = filter ? filter.name[filter.dataId.indexOf(dataId)] : null;
channels.push(filter);
};
for (var i = 0; i < _defaultSettings.MAX_GPU_FILTERS; i++) {
_loop(i);
}
var filterValueAccessor = getFilterValueAccessor(channels, dataId, fields);
return {
filterRange: filterRange,
filterValueUpdateTriggers: triggers,
filterValueAccessor: filterValueAccessor
};
}
/**
* Return dataset field index from filter.fieldIdx
* The index matches the same dataset index for filter.dataId
* @type {typeof import('./gpu-filter-utils').getDatasetFieldIndexForFilter}
*/
function getDatasetFieldIndexForFilter(dataId, filter) {
var datasetIndex = (0, _utils.toArray)(filter.dataId).indexOf(dataId);
if (datasetIndex < 0) {
return -1;
}
var fieldIndex = filter.fieldIdx[datasetIndex];
return (0, _dataUtils.notNullorUndefined)(fieldIndex) ? fieldIndex : -1;
}
//# sourceMappingURL=data:application/json;charset=utf-8;base64,eyJ2ZXJzaW9uIjozLCJzb3VyY2VzIjpbIi4uLy4uL3NyYy91dGlscy9ncHUtZmlsdGVyLXV0aWxzLmpzIl0sIm5hbWVzIjpbInNldEZpbHRlckdwdU1vZGUiLCJmaWx0ZXIiLCJmaWx0ZXJzIiwiZGF0YUlkIiwiZm9yRWFjaCIsImRhdGFzZXRJZHgiLCJncHVGaWx0ZXJzIiwiZiIsImluY2x1ZGVzIiwiZ3B1IiwibGVuZ3RoIiwiTUFYX0dQVV9GSUxURVJTIiwiYXNzaWduR3B1Q2hhbm5lbHMiLCJhbGxGaWx0ZXJzIiwicmVkdWNlIiwiYWNjdSIsImluZGV4IiwiYXNzaWduR3B1Q2hhbm5lbCIsImdwdUNoYW5uZWwiLCJmaW5kR3B1Q2hhbm5lbCIsImNoYW5uZWwiLCJkYXRhSWR4IiwiaW5kZXhPZiIsImlkIiwiTnVtYmVyIiwiaXNGaW5pdGUiLCJmaW5kIiwiaSIsImV2ZXJ5IiwicmVzZXRGaWx0ZXJHcHVNb2RlIiwiZ3B1UGVyRGF0YXNldCIsIm1hcCIsImNvdW50IiwiZ2V0RW1wdHlGaWx0ZXJSYW5nZSIsIkFycmF5IiwiZmlsbCIsImQiLCJkZWZhdWx0R2V0SW5kZXgiLCJkZWZhdWx0R2V0RGF0YSIsImRjIiwiZmllbGRJbmRleCIsInZhbHVlQXQiLCJnZXRGaWx0ZXJWYWx1ZUFjY2Vzc29yIiwiY2hhbm5lbHMiLCJmaWVsZHMiLCJnZXRJbmRleCIsImdldERhdGEiLCJnZXREYXRhc2V0RmllbGRJbmRleEZvckZpbHRlciIsImZpZWxkIiwidmFsdWUiLCJ0eXBlIiwiRklMVEVSX1RZUEVTIiwidGltZVJhbmdlIiwiZmlsdGVyUHJvcHMiLCJpc0FycmF5IiwibWFwcGVkVmFsdWUiLCJtb21lbnQiLCJ1dGMiLCJ2YWx1ZU9mIiwiZG9tYWluIiwiTUlOX1NBRkVfSU5URUdFUiIsImdldEdwdUZpbHRlclByb3BzIiwiZmlsdGVyUmFuZ2UiLCJ0cmlnZ2VycyIsIm5hbWUiLCJwdXNoIiwiZmlsdGVyVmFsdWVBY2Nlc3NvciIsImZpbHRlclZhbHVlVXBkYXRlVHJpZ2dlcnMiLCJkYXRhc2V0SW5kZXgi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QUFPO0FBQ0xrQixJQUFBQSxXQUFXLEVBQVhBLFdBREs7QUFFTEssSUFBQUEseUJBQXlCLEVBQUVKLFFBRnRCO0FBR0xHLElBQUFBLG1CQUFtQixFQUFuQkE7QUFISyxHQUFQO0FBS0Q7QUFFRDtBQUNBO0FBQ0E7QUFDQTtBQUNBOzs7QUFDTyxTQUFTbkIsNkJBQVQsQ0FBdUM1QyxNQUF2QyxFQUErQ0YsTUFBL0MsRUFBdUQ7QUFDNUQsTUFBTW1FLFlBQVksR0FBRyxvQkFBUW5FLE1BQU0sQ0FBQ0UsTUFBZixFQUF1Qm1CLE9BQXZCLENBQStCbkIsTUFBL0IsQ0FBckI7O0FBQ0EsTUFBSWlFLFlBQVksR0FBRyxDQUFuQixFQUFzQjtBQUNwQixXQUFPLENBQUMsQ0FBUjtBQUNEOztBQUVELE1BQU01QixVQUFVLEdBQUd2QyxNQUFNLENBQUNvRSxRQUFQLENBQWdCRCxZQUFoQixDQUFuQjtBQUVBLFNBQU8sbUNBQW1CNUIsVUFBbkIsSUFBaUNBLFVBQWpDLEdBQThDLENBQUMsQ0FBdEQ7QUFDRCIsInNvdXJjZXNDb250ZW50IjpbIi8vIENvcHlyaWdodCAoYykgMjAyMSBVYmVyIFRlY2hub2xvZ2llcywgSW5jLlxuLy9cbi8vIFBlcm1pc3Npb24gaXMgaGVyZWJ5IGdyYW50ZWQsIGZyZWUgb2YgY2hhcmdlLCB0byBhbnkgcGVyc29uIG9idGFpbmluZyBhIGNvcHlcbi8vIG9mIHRoaXMgc29mdHdhcmUgYW5kIGFzc29jaWF0ZWQgZG9jdW1lbnRhdGlvbiBmaWxlcyAodGhlIFwiU29mdHdhcmVcIiksIHRvIGRlYWxcbi8vIGluIHRoZSBTb2Z0d2FyZSB3aXRob3V0IHJlc3RyaWN0aW9uLCBpbmNsdWRpbmcgd2l0aG91dCBsaW1pdGF0aW9uIHRoZSByaWdodHNcbi8vIHRvIHVzZSwgY29weSwgbW9kaWZ5LCBtZXJnZSwgcHVibGlzaCwgZGlzdHJpYnV0ZSwgc3VibGljZW5zZSwgYW5kL29yIHNlbGxcbi8vIGNvcGllcyBvZiB0aGUgU29mdHdhcmUsIGFuZCB0byBwZXJtaXQgcGVyc29ucyB0byB3aG9tIHRoZSBTb2Z0d2FyZSBpc1xuLy8gZnVybmlzaGVkIHRvIGRvIHNvLCBzdWJqZWN0IHRvIHRoZSBmb2xsb3dpbmcgY29uZGl0aW9uczpcbi8vXG4vLyBUaGUgYWJvdmUgY29weXJpZ2h0IG5vdGljZSBhbmQgdGhpcyBwZXJtaXNzaW9uIG5vdGljZSBzaGFsbCBiZSBpbmNsdWRlZCBpblxuLy8gYWxsIGNvcGllcyBvciBzdWJzdGFudGlhbCBwb3J0aW9ucyBvZiB0aGUgU29mdHdhcmUuXG4vL1xuLy8gVEhFIFNPRlRXQVJFIElTIFBST1ZJREVEIFwiQVMgSVNcIiwgV0lUSE9VVCBXQVJSQU5UWSBPRiBBTlkgS0lORCwgRVhQUkVTUyBPUlxuLy8gSU1QTElFRCwgSU5DTFVESU5HIEJVVCBOT1QgTElNSVRFRCBUTyBUSEUgV0FSUkFOVElFUyBPRiBNRVJDSEFOVEFCSUxJVFksXG4vLyBGSVRORVNTIEZPUiBBIFBBUlRJQ1VMQVIgUFVSUE9TRSBBTkQgTk9OSU5GUklOR0VNRU5ULiBJTiBOTyBFVkVOVCBTSEFMTCBUSEVcbi8vIEFVVEhPUlMgT1IgQ09QWVJJR0hUIEhPTERFUlMgQkUgTElBQkxFIEZPUiBBTlkgQ0xBSU0sIERBTUFHRVMgT1IgT1RIRVJcbi8vIExJQUJJTElUWSwgV0hFVEhFUiBJTiBBTiBBQ1RJT04gT0YgQ09OVFJBQ1QsIFRPUlQgT1IgT1RIRVJXSVNFLCBBUklTSU5HIEZST00sXG4vLyBPVVQgT0YgT1IgSU4gQ09OTkVDVElPTiBXSVRIIFRIRSBTT0ZUV0FSRSBPUiBUSEUgVVNFIE9SIE9USEVSIERFQUxJTkdTIElOXG4vLyBUSEUgU09GVFdBUkUuXG5cbmltcG9ydCB7c2V0LCB0b0FycmF5fSBmcm9tICcuL3V0aWxzJztcbmltcG9ydCB7TUFYX0dQVV9GSUxURVJTLCBGSUxURVJfVFlQRVN9IGZyb20gJ2NvbnN0YW50cy9kZWZhdWx0LXNldHRpbmdzJztcbmltcG9ydCB7bm90TnVsbG9yVW5kZWZpbmVkfSBmcm9tICcuL2RhdGEtdXRpbHMnO1xuaW1wb3J0IG1vbWVudCBmcm9tICdtb21lbnQnO1xuXG4vKipcbiAqIFNldCBncHUgbW9kZSBiYXNlZCBvbiBjdXJyZW50IG51bWJlciBvZiBncHUgZmlsdGVycyBleGlzdHNcbiAqIEB0eXBlIHt0eXBlb2YgaW1wb3J0KCcuL2dwdS1maWx0ZXItdXRpbHMnKS5zZXRGaWx0ZXJHcHVNb2RlfVxuICovXG5leHBvcnQgZnVuY3Rpb24gc2V0RmlsdGVyR3B1TW9kZShmaWx0ZXIsIGZpbHRlcnMpIHtcbiAgLy8gZmlsdGVyIGNhbiBiZSBhcHBsaWVkIHRvIG11bHRpcGxlIGRhdGFzZXRzLCBoZW5jZSBncHUgZmlsdGVyIG1vZGUgc2hvdWxkIGFsc28gYmVcbiAgLy8gYW4gYXJyYXksIGhvd2V2ZXIsIHRvIGtlZXAgdXMgc2FuZSwgZm9yIG5vdywgd2Ugb25seSBjaGVjayBpZiB0aGVyZSBpcyBhdmFpbGFibGUgY2hhbm5lbCBmb3IgZXZlcnkgZGF0YUlkLFxuICAvLyBpZiBhbGwgb2YgdGhlbSBoYXMsIHdlIHNldCBncHUgbW9kZSB0byB0cnVlXG4gIC8vIFRPRE86IHJlZmFjdG9yIGZpbHRlciBzbyB3ZSBkb24ndCBrZWVwIGFuIGFycmF5IG9mIGV2ZXJ5dGhpbmdcblxuICBmaWx0ZXIuZGF0YUlkLmZvckVhY2goKGRhdGFJZCwgZGF0YXNldElkeCkgPT4ge1xuICAgIGNvbnN0IGdwdUZpbHRlcnMgPSBmaWx0ZXJzLmZpbHRlcihmID0+IGYuZGF0YUlkLmluY2x1ZGVzKGRhdGFJZCkgJiYgZi5ncHUpO1xuXG4gICAgaWYgKGZpbHRlci5ncHUgJiYgZ3B1RmlsdGVycy5sZW5ndGggPT09IE1BWF9HUFVfRklMVEVSUykge1xuICAgICAgcmV0dXJuIHNldChbJ2dwdSddLCBmYWxzZSwgZmlsdGVyKTtcbiAgICB9XG4gIH0pO1xuXG4gIHJldHVybiBmaWx0ZXI7XG59XG5cbi8qKlxuICogU2NhbiB0aG91Z2ggYWxsIGZpbHRlcnMgYW5kIGFzc2lnbiBncHUgY2hhbmVsIHRvIGdwdSBmaWx0ZXJcbiAqIEB0eXBlIHt0eXBlb2YgaW1wb3J0KCcuL2dwdS1maWx0ZXItdXRpbHMnKS5hc3NpZ25HcHVDaGFubmVsc31cbiAqL1xuZXhwb3J0IGZ1bmN0aW9uIGFzc2lnbkdwdUNoYW5uZWxzKGFsbEZpbHRlcnMpIHtcbiAgcmV0dXJuIGFsbEZpbHRlcnMucmVkdWNlKChhY2N1LCBmLCBpbmRleCkgPT4ge1xuICAgIGxldCBmaWx0ZXJzID0gYWNjdTtcblxuICAgIC8vIGlmIGdwdSBpcyB0cnVlIGFzc2lnbiBhbmQgdmFsaWRhdGUgZ3B1IENoYW5uZWxcbiAgICBpZiAoZi5ncHUpIHtcbiAgICAgIGYgPSBhc3NpZ25HcHVDaGFubmVsKGYsIGFjY3UpO1xuICAgICAgZmlsdGVycyA9IHNldChbaW5kZXhdLCBmLCBhY2N1KTtcbiAgICB9XG5cbiAgICByZXR1cm4gZmlsdGVycztcbiAgfSwgYWxsRmlsdGVycyk7XG59XG4vKipcbiAqIEFzc2lnbiBhIG5ldyBncHUgZmlsdGVyIGEgY2hhbm5lbCBiYXNlZCBvbiBmaXJzdCBhdmFpbGFiaWxpdHlcbiAqIEB0eXBlIHt0eXBlb2YgaW1wb3J0KCcuL2dwdS1maWx0ZXItdXRpbHMnKS5hc3NpZ25HcHVDaGFubmVsfVxuICovXG5leHBvcnQgZnVuY3Rpb24gYXNzaWduR3B1Q2hhbm5lbChmaWx0ZXIsIGZpbHRlcnMpIHtcbiAgLy8gZmluZCBmaXJzdCBhdmFpbGFibGUgY2hhbm5lbFxuICBpZiAoIWZpbHRlci5ncHUpIHtcbiAgICByZXR1cm4gZmlsdGVyO1xuICB9XG5cbiAgY29uc3QgZ3B1Q2hhbm5lbCA9IGZpbHRlci5ncHVDaGFubmVsIHx8IFtdO1xuXG4gIGZpbHRlci5kYXRhSWQuZm9yRWFjaCgoZGF0YUlkLCBkYXRhc2V0SWR4KSA9PiB7XG4gICAgY29uc3QgZmluZEdwdUNoYW5uZWwgPSBjaGFubmVsID0+IGYgPT4ge1xuICAgICAgY29uc3QgZGF0YUlkeCA9IHRvQXJyYXkoZi5kYXRhSWQpLmluZGV4T2YoZGF0YUlkKTtcbiAgICAgIHJldHVybiAoXG4gICAgICAgIGYuaWQgIT09IGZpbHRlci5pZCAmJiBkYXRhSWR4ID4gLTEgJiYgZi5ncHUgJiYgdG9BcnJheShmLmdwdUNoYW5uZWwpW2RhdGFJZHhdID09PSBjaGFubmVsXG4gICAgICApO1xuICAgIH07XG5cbiAgICBpZiAoXG4gICAgICBOdW1iZXIuaXNGaW5pdGUoZ3B1Q2hhbm5lbFtkYXRhc2V0SWR4XSkgJiZcbiAgICAgICFmaWx0ZXJzLmZpbmQoZmluZEdwdUNoYW5uZWwoZ3B1Q2hhbm5lbFtkYXRhc2V0SWR4XSkpXG4gICAgKSB7XG4gICAgICAvLyBpZiB2YWx1ZSBpcyBhbHJlYWR5IGFzc2lnbmVkIGFuZCB2YWxpZFxuICAgICAgcmV0dXJuO1xuICAgIH1cblxuICAgIGxldCBpID0gMDtcblxuICAgIHdoaWxlIChpIDwgTUFYX0dQVV9GSUxURVJTKSB7XG4gICAgICBpZiAoIWZpbHRlcnMuZmluZChmaW5kR3B1Q2hhbm5lbChpKSkpIHtcbiAgICAgICAgZ3B1Q2hhbm5lbFtkYXRhc2V0SWR4XSA9IGk7XG4gICAgICAgIHJldHVybjtcbiAgICAgIH1cbiAgICAgIGkrKztcbiAgICB9XG4gIH0pO1xuXG4gIC8vIGlmIGNhbm5vdCBmaW5kIGNoYW5uZWwgZm9yIGFsbCBkYXRhaWQsIHNldCBncHUgYmFjayB0byBmYWxzZVxuICAvLyBUT0RPOiByZWZhY3RvciBmaWx0ZXIgdG8gaGFuZGxlIHNhbWUgZmlsdGVyIGRpZmZlcmVudCBncHUgbW9kZVxuICBpZiAoIWdwdUNoYW5uZWwubGVuZ3RoIHx8ICFncHVDaGFubmVsLmV2ZXJ5KE51bWJlci5pc0Zpbml0ZSkpIHtcbiAgICByZXR1cm4ge1xuICAgICAgLi4uZmlsdGVyLFxuICAgICAgZ3B1OiBmYWxzZVxuICAgIH07XG4gIH1cblxuICByZXR1cm4ge1xuICAgIC4uLmZpbHRlcixcbiAgICBncHVDaGFubmVsXG4gIH07XG59XG4vKipcbiAqIEVkaXQgZmlsdGVyLmdwdSB0byBlbnN1cmUgdGhhdCBvbmx5XG4gKiBYIG51bWJlciBvZiBncHUgZmlsZXJzIGNhbiBjb2V4aXN0LlxuICogQHR5cGUge3R5cGVvZiBpbXBvcnQoJy4vZ3B1LWZpbHRlci11dGlscycpLnJlc2V0RmlsdGVyR3B1TW9kZX1cbiAqL1xuZXhwb3J0IGZ1bmN0aW9uIHJlc2V0RmlsdGVyR3B1TW9kZShmaWx0ZXJzKSB7XG4gIGNvbnN0IGdwdVBlckRhdGFzZXQgPSB7fTtcblxuICByZXR1cm4gZmlsdGVycy5tYXAoKGYsIGkpID0+IHtcbiAgICBpZiAoZi5ncHUpIHtcbiAgICAgIGxldCBncHUgPSB0cnVlO1xuICAgICAgdG9BcnJheShmLmRhdGFJZCkuZm9yRWFjaChkYXRhSWQgPT4ge1xuICAgICAgICBjb25zdCBjb3VudCA9IGdwdVBlckRhdGFzZXRbZGF0YUlkXTtcblxuICAgICAgICBpZiAoY291bnQgPT09IE1BWF9HUFVfRklMVEVSUykge1xuICAgICAgICAgIGdwdSA9IGZhbHNlO1xuICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgIGdwdVBlckRhdGFzZXRbZGF0YUlkXSA9IGNvdW50ID8gY291bnQgKyAxIDogMTtcbiAgICAgICAgfVxuICAgICAgfSk7XG5cbiAgICAgIGlmICghZ3B1KSB7XG4gICAgICAgIHJldHVybiBzZXQoWydncHUnXSwgZmFsc2UsIGYpO1xuICAgICAgfVxuICAgIH1cblxuICAgIHJldHVybiBmO1xuICB9KTtcbn1cblxuLyoqXG4gKiBJbml0aWFsIGZpbHRlciB1bmlmb3JtXG4gKiBAcmV0dXJucyB7QXJyYXk8QXJyYXk8TnVtYmVyPj59XG4gKi9cbmZ1bmN0aW9uIGdldEVtcHR5RmlsdGVyUmFuZ2UoKSB7XG4gIHJldHVybiBuZXcgQXJyYXkoTUFYX0dQVV9GSUxURVJTKS5maWxsKDApLm1hcChkID0+IFswLCAwXSk7XG59XG5cbi8qKlxuICogUmV0dXJucyBpbmRleCBvZiB0aGUgZGF0YSBlbGVtZW50LlxuICogQHBhcmFtIHthbnl9IGQgRGF0YSBlbGVtZW50IHdpdGggcm93IGluZGV4IGluZm8uXG4gKiBAcmV0dXJucyBudW1iZXJcbiAqL1xuY29uc3QgZGVmYXVsdEdldEluZGV4ID0gZCA9PiBkLmluZGV4O1xuXG4vKipcbiAqIFJldHVybnMgdmFsdWUgYXQgdGhlIHNwZWNpZmllZCByb3cgZnJvbSB0aGUgZGF0YSBjb250YWluZXIuXG4gKiBAcGFyYW0ge2ltcG9ydCgnLi90YWJsZS11dGlscy9kYXRhLWNvbnRhaW5lci1pbnRlcmZhY2UnKS5EYXRhQ29udGFpbmVySW50ZXJmYWNlfSBkYyBEYXRhIGNvbnRhaW5lci5cbiAqIEBwYXJhbSB7YW55fSBkIERhdGEgZWxlbWVudCB3aXRoIHJvdyBpbmRleCBpbmZvLlxuICogQHBhcmFtIHtudW1iZXJ9IGZpZWxkSW5kZXggQ29sdW1uIGluZGV4IGluIHRoZSBkYXRhIGNvbnRhaW5lci5cbiAqIEByZXR1cm5zXG4gKi9cbmNvbnN0IGRlZmF1bHRHZXREYXRhID0gKGRjLCBkLCBmaWVsZEluZGV4KSA9PiB7XG4gIHJldHVybiBkYy52YWx1ZUF0KGQuaW5kZXgsIGZpZWxkSW5kZXgpO1xufTtcblxuLyoqXG4gKiBAcGFyYW0ge0FycmF5PE9iamVjdD59IGNoYW5uZWxzXG4gKiBAcGFyYW0ge3N0cmluZ30gZGF0YUlkXG4gKiBAcGFyYW0ge0FycmF5PE9iamVjdD59IGZpZWxkc1xuICogQHJldHVybiB7RnVuY3Rpb259IGdldEZpbHRlclZhbHVlXG4gKi9cbmNvbnN0IGdldEZpbHRlclZhbHVlQWNjZXNzb3IgPSAoY2hhbm5lbHMsIGRhdGFJZCwgZmllbGRzKSA9PiBkYyA9PiAoXG4gIGdldEluZGV4ID0gZGVmYXVsdEdldEluZGV4LFxuICBnZXREYXRhID0gZGVmYXVsdEdldERhdGFcbikgPT4gZCA9PlxuICAvLyBmb3IgZW1wdHkgY2hhbm5lbCwgdmFsdWUgaXMgMCBhbmQgbWluIG1heCB3b3VsZCBiZSBbMCwgMF1cbiAgY2hhbm5lbHMubWFwKGZpbHRlciA9PiB7XG4gICAgaWYgKCFmaWx0ZXIpIHtcbiAgICAgIHJldHVybiAwO1xuICAgIH1cbiAgICBjb25zdCBmaWVsZEluZGV4ID0gZ2V0RGF0YXNldEZpZWxkSW5kZXhGb3JGaWx0ZXIoZGF0YUlkLCBmaWx0ZXIpO1xuICAgIGNvbnN0IGZpZWxkID0gZmllbGRzW2ZpZWxkSW5kZXhdO1xuXG4gICAgY29uc3QgdmFsdWUgPVxuICAgICAgZmlsdGVyLnR5cGUgPT09IEZJTFRFUl9UWVBFUy50aW1lUmFuZ2VcbiAgICAgICAgPyBmaWVsZC5maWx0ZXJQcm9wcyAmJiBBcnJheS5pc0FycmF5KGZpZWxkLmZpbHRlclByb3BzLm1hcHBlZFZhbHVlKVxuICAgICAgICAgID8gZmllbGQuZmlsdGVyUHJvcHMubWFwcGVkVmFsdWVbZ2V0SW5kZXgoZCldXG4gICAgICAgICAgOiBtb21lbnQudXRjKGdldERhdGEoZGMsIGQsIGZpZWxkSW5kZXgpKS52YWx1ZU9mKClcbiAgICAgICAgOiBnZXREYXRhKGRjLCBkLCBmaWVsZEluZGV4KTtcblxuICAgIHJldHVybiBub3ROdWxsb3JVbmRlZmluZWQodmFsdWUpID8gdmFsdWUgLSBmaWx0ZXIuZG9tYWluWzBdIDogTnVtYmVyLk1JTl9TQUZFX0lOVEVHRVI7XG4gIH0pO1xuXG4vKipcbiAqIEdldCBmaWx0ZXIgcHJvcGVydGllcyBmb3IgZ3B1IGZpbHRlcmluZ1xuICogQHR5cGUge3R5cGVvZiBpbXBvcnQoJy4vZ3B1LWZpbHRlci11dGlscycpLmdldEdwdUZpbHRlclByb3BzfVxuICovXG5leHBvcnQgZnVuY3Rpb24gZ2V0R3B1RmlsdGVyUHJvcHMoZmlsdGVycywgZGF0YUlkLCBmaWVsZHMpIHtcbiAgY29uc3QgZmlsdGVyUmFuZ2UgPSBnZXRFbXB0eUZpbHRlclJhbmdlKCk7XG4gIGNvbnN0IHRyaWdnZXJzID0ge307XG5cbiAgLy8gYXJyYXkgb2YgZmlsdGVyIGZvciBlYWNoIGNoYW5uZWwsIHVuZGVmaW5lZCwgaWYgbm8gZmlsdGVyIGlzIGFzc2lnbmVkIHRvIHRoYXQgY2hhbm5lbFxuICBjb25zdCBjaGFubmVscyA9IFtdO1xuXG4gIGZvciAobGV0IGkgPSAwOyBpIDwgTUFYX0dQVV9GSUxURVJTOyBpKyspIHtcbiAgICBjb25zdCBmaWx0ZXIgPSBmaWx0ZXJzLmZpbmQoXG4gICAgICBmID0+XG4gICAgICAgIGYuZ3B1ICYmXG4gICAgICAgIGYuZGF0YUlkLmluY2x1ZGVzKGRhdGFJZCkgJiZcbiAgICAgICAgZi5ncHVDaGFubmVsICYmXG4gICAgICAgIGYuZ3B1Q2hhbm5lbFtmLmRhdGFJZC5pbmRleE9mKGRhdGFJZCldID09PSBpXG4gICAgKTtcblxuICAgIC8vIEB0cy1pZ25vcmVcbiAgICBmaWx0ZXJSYW5nZVtpXVswXSA9IGZpbHRlciA/IGZpbHRlci52YWx1ZVswXSAtIGZpbHRlci5kb21haW5bMF0gOiAwO1xuICAgIC8vIEB0cy1pZ25vcmVcbiAgICBmaWx0ZXJSYW5nZVtpXVsxXSA9IGZpbHRlciA/IGZpbHRlci52YWx1ZVsxXSAtIGZpbHRlci5kb21haW5bMF0gOiAwO1xuXG4gICAgdHJpZ2dlcnNbYGdwdUZpbHRlcl8ke2l9YF0gPSBmaWx0ZXIgPyBmaWx0ZXIubmFtZVtmaWx0ZXIuZGF0YUlkLmluZGV4T2YoZGF0YUlkKV0gOiBudWxsO1xuICAgIGNoYW5uZWxzLnB1c2goZmlsdGVyKTtcbiAgfVxuXG4gIGNvbnN0IGZpbHRlclZhbHVlQWNjZXNzb3IgPSBnZXRGaWx0ZXJWYWx1ZUFjY2Vzc29yKGNoYW5uZWxzLCBkYXRhSWQsIGZpZWxkcyk7XG5cbiAgcmV0dXJuIHtcbiAgICBmaWx0ZXJSYW5nZSxcbiAgICBmaWx0ZXJWYWx1ZVVwZGF0ZVRyaWdnZXJzOiB0cmlnZ2VycyxcbiAgICBmaWx0ZXJWYWx1ZUFjY2Vzc29yXG4gIH07XG59XG5cbi8qKlxuICogUmV0dXJuIGRhdGFzZXQgZmllbGQgaW5kZXggZnJvbSBmaWx0ZXIuZmllbGRJZHhcbiAqIFRoZSBpbmRleCBtYXRjaGVzIHRoZSBzYW1lIGRhdGFzZXQgaW5kZXggZm9yIGZpbHRlci5kYXRhSWRcbiAqIEB0eXBlIHt0eXBlb2YgaW1wb3J0KCcuL2dwdS1maWx0ZXItdXRpbHMnKS5nZXREYXRhc2V0RmllbGRJbmRleEZvckZpbHRlcn1cbiAqL1xuZXhwb3J0IGZ1bmN0aW9uIGdldERhdGFzZXRGaWVsZEluZGV4Rm9yRmlsdGVyKGRhdGFJZCwgZmlsdGVyKSB7XG4gIGNvbnN0IGRhdGFzZXRJbmRleCA9IHRvQXJyYXkoZmlsdGVyLmRhdGFJZCkuaW5kZXhPZihkYXRhSWQpO1xuICBpZiAoZGF0YXNldEluZGV4IDwgMCkge1xuICAgIHJldHVybiAtMTtcbiAgfVxuXG4gIGNvbnN0IGZpZWxkSW5kZXggPSBmaWx0ZXIuZmllbGRJZHhbZGF0YXNldEluZGV4XTtcblxuICByZXR1cm4gbm90TnVsbG9yVW5kZWZpbmVkKGZpZWxkSW5kZXgpID8gZmllbGRJbmRleCA6IC0xO1xufVxuIl19