UNPKG

kepler.gl

Version:

kepler.gl is a webgl based application to visualize large scale location data in the browser

740 lines (628 loc) 72.8 kB
"use strict"; var _interopRequireDefault = require("@babel/runtime/helpers/interopRequireDefault"); Object.defineProperty(exports, "__esModule", { value: true }); exports.processCsvData = processCsvData; exports.parseRowsByFields = parseRowsByFields; exports.getSampleForTypeAnalyze = getSampleForTypeAnalyze; exports.parseCsvRowsByFieldType = parseCsvRowsByFieldType; exports.getFieldsFromData = getFieldsFromData; exports.renameDuplicateFields = renameDuplicateFields; exports.analyzerTypeToFieldType = analyzerTypeToFieldType; exports.processRowObject = processRowObject; exports.processGeojson = processGeojson; exports.formatCsv = formatCsv; exports.validateInputData = validateInputData; exports.processKeplerglJSON = processKeplerglJSON; exports.processKeplerglDataset = processKeplerglDataset; exports.Processors = exports.DATASET_HANDLERS = exports.PARSE_FIELD_VALUE_FROM_STRING = exports.ACCEPTED_ANALYZER_TYPES = void 0; var _typeof2 = _interopRequireDefault(require("@babel/runtime/helpers/typeof")); var _toArray2 = _interopRequireDefault(require("@babel/runtime/helpers/toArray")); var _defineProperty2 = _interopRequireDefault(require("@babel/runtime/helpers/defineProperty")); var _d3Dsv = require("d3-dsv"); var _d3Array = require("d3-array"); var _window = require("global/window"); var _assert = _interopRequireDefault(require("assert")); var _typeAnalyzer = require("type-analyzer"); var _geojsonNormalize = _interopRequireDefault(require("@mapbox/geojson-normalize")); var _defaultSettings = require("../constants/default-settings"); var _dataUtils = require("../utils/data-utils"); var _schemas = _interopRequireDefault(require("../schemas")); var _userGuides = require("../constants/user-guides"); var _utils = require("../utils/utils"); var _PARSE_FIELD_VALUE_FR, _DATASET_HANDLERS; 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; } var ACCEPTED_ANALYZER_TYPES = [_typeAnalyzer.DATA_TYPES.DATE, _typeAnalyzer.DATA_TYPES.TIME, _typeAnalyzer.DATA_TYPES.DATETIME, _typeAnalyzer.DATA_TYPES.NUMBER, _typeAnalyzer.DATA_TYPES.INT, _typeAnalyzer.DATA_TYPES.FLOAT, _typeAnalyzer.DATA_TYPES.BOOLEAN, _typeAnalyzer.DATA_TYPES.STRING, _typeAnalyzer.DATA_TYPES.GEOMETRY, _typeAnalyzer.DATA_TYPES.GEOMETRY_FROM_STRING, _typeAnalyzer.DATA_TYPES.PAIR_GEOMETRY_FROM_STRING, _typeAnalyzer.DATA_TYPES.ZIPCODE, _typeAnalyzer.DATA_TYPES.ARRAY, _typeAnalyzer.DATA_TYPES.OBJECT]; // if any of these value occurs in csv, parse it to null; exports.ACCEPTED_ANALYZER_TYPES = ACCEPTED_ANALYZER_TYPES; var CSV_NULLS = ['', 'null', 'NULL', 'Null', 'NaN', '/N']; var IGNORE_DATA_TYPES = Object.keys(_typeAnalyzer.DATA_TYPES).filter(function (type) { return !ACCEPTED_ANALYZER_TYPES.includes(type); }); var PARSE_FIELD_VALUE_FROM_STRING = (_PARSE_FIELD_VALUE_FR = {}, (0, _defineProperty2["default"])(_PARSE_FIELD_VALUE_FR, _defaultSettings.ALL_FIELD_TYPES["boolean"], { valid: function valid(d) { return typeof d === 'boolean'; }, parse: function parse(d) { return d === 'true' || d === 'True' || d === '1'; } }), (0, _defineProperty2["default"])(_PARSE_FIELD_VALUE_FR, _defaultSettings.ALL_FIELD_TYPES.integer, { valid: function valid(d) { return parseInt(d, 10) === d; }, parse: function parse(d) { return parseInt(d, 10); } }), (0, _defineProperty2["default"])(_PARSE_FIELD_VALUE_FR, _defaultSettings.ALL_FIELD_TYPES.timestamp, { valid: function valid(d, field) { return ['x', 'X'].includes(field.format) ? typeof d === 'number' : typeof d === 'string'; }, parse: function parse(d, field) { return ['x', 'X'].includes(field.format) ? Number(d) : d; } }), (0, _defineProperty2["default"])(_PARSE_FIELD_VALUE_FR, _defaultSettings.ALL_FIELD_TYPES.real, { valid: function valid(d) { return parseFloat(d) === d; }, parse: parseFloat }), _PARSE_FIELD_VALUE_FR); /** * Process csv data, output a data object with `{fields: [], rows: []}`. * The data object can be wrapped in a `dataset` and pass to [`addDataToMap`](../actions/actions.md#adddatatomap) * @param {string} rawData raw csv string * @returns {Object} data object `{fields: [], rows: []}` * @public * @example * import {processCsvData} from 'kepler.gl/processors'; * * const testData = `gps_data.utc_timestamp,gps_data.lat,gps_data.lng,gps_data.types,epoch,has_result,id,time,begintrip_ts_utc,begintrip_ts_local,date * 2016-09-17 00:09:55,29.9900937,31.2590542,driver_analytics,1472688000000,False,1,2016-09-23T00:00:00.000Z,2016-10-01 09:41:39+00:00,2016-10-01 09:41:39+00:00,2016-09-23 * 2016-09-17 00:10:56,29.9927699,31.2461142,driver_analytics,1472688000000,False,2,2016-09-23T00:00:00.000Z,2016-10-01 09:46:37+00:00,2016-10-01 16:46:37+00:00,2016-09-23 * 2016-09-17 00:11:56,29.9907261,31.2312742,driver_analytics,1472688000000,False,3,2016-09-23T00:00:00.000Z,,,2016-09-23 * 2016-09-17 00:12:58,29.9870074,31.2175827,driver_analytics,1472688000000,False,4,2016-09-23T00:00:00.000Z,,,2016-09-23` * * const dataset = { * info: {id: 'test_data', label: 'My Csv'}, * data: processCsvData(testData) * }; * * dispatch(addDataToMap({ * datasets: [dataset], * options: {centerMap: true, readOnly: true} * })); */ exports.PARSE_FIELD_VALUE_FROM_STRING = PARSE_FIELD_VALUE_FROM_STRING; function processCsvData(rawData) { // here we assume the csv file that people uploaded will have first row // as name of the column // TODO: add a alert at upload csv to remind define first row var result = (0, _d3Dsv.csvParseRows)(rawData); if (!Array.isArray(result) || result.length < 2) { // looks like an empty file, throw error to be catch throw new Error('Read File Failed: CSV is empty'); } var _result = (0, _toArray2["default"])(result), headerRow = _result[0], rows = _result.slice(1); cleanUpFalsyCsvValue(rows); // No need to run type detection on every data point // here we get a list of none null values to run analyze on var sample = getSampleForTypeAnalyze({ fields: headerRow, allData: rows }); var fields = getFieldsFromData(sample, headerRow); var parsedRows = parseRowsByFields(rows, fields); return { fields: fields, rows: parsedRows }; } /** * Parse rows of csv by analyzed field types. So that `'1'` -> `1`, `'True'` -> `true` * @param {Array<Array>} rows * @param {Array<Object} fields */ function parseRowsByFields(rows, fields) { // Edit rows in place var geojsonFieldIdx = fields.findIndex(function (f) { return f.name === '_geojson'; }); fields.forEach(parseCsvRowsByFieldType.bind(null, rows, geojsonFieldIdx)); return rows; } /** * Getting sample data for analyzing field type. * * @param {Array<string>} fields an array of field names * @param {Array<Array>} allData * @param {Array} sampleCount * @returns {Array} formatted fields */ function getSampleForTypeAnalyze(_ref) { var fields = _ref.fields, allData = _ref.allData, _ref$sampleCount = _ref.sampleCount, sampleCount = _ref$sampleCount === void 0 ? 50 : _ref$sampleCount; var total = Math.min(sampleCount, allData.length); // const fieldOrder = fields.map(f => f.name); var sample = (0, _d3Array.range)(0, total, 1).map(function (d) { return {}; }); // collect sample data for each field fields.forEach(function (field, fieldIdx) { // data counter var i = 0; // sample counter var j = 0; while (j < total) { if (i >= allData.length) { // if depleted data pool sample[j][field] = null; j++; } else if ((0, _dataUtils.notNullorUndefined)(allData[i][fieldIdx])) { sample[j][field] = allData[i][fieldIdx]; j++; i++; } else { i++; } } }); return sample; } /** * Convert falsy value in csv including `'', 'null', 'NULL', 'Null', 'NaN'` to `null`, * so that type-analyzer won't detect it as string * * @param {Array<Array>} rows */ function cleanUpFalsyCsvValue(rows) { for (var i = 0; i < rows.length; i++) { for (var j = 0; j < rows[i].length; j++) { // analyzer will set any fields to 'string' if there are empty values // which will be parsed as '' by d3.csv // here we parse empty data as null // TODO: create warning when deltect `CSV_NULLS` in the data if (!rows[i][j] || CSV_NULLS.includes(rows[i][j])) { rows[i][j] = null; } } } } /** * Process uploaded csv file to parse value by field type * * @param {Array<Array>} rows * @param {Number} geo field index * @param {Object} field * @param {Number} i * @returns {void} */ function parseCsvRowsByFieldType(rows, geoFieldIdx, field, i) { var parser = PARSE_FIELD_VALUE_FROM_STRING[field.type]; if (parser) { // check first not null value of it's already parsed var first = rows.find(function (r) { return (0, _dataUtils.notNullorUndefined)(r[i]); }); if (!first || parser.valid(first[i], field)) { return; } rows.forEach(function (row) { // parse string value based on field type if (row[i] !== null) { row[i] = parser.parse(row[i], field); if (geoFieldIdx > -1 && row[geoFieldIdx] && row[geoFieldIdx].properties) { row[geoFieldIdx].properties[field.name] = row[i]; } } }); } } /** * Analyze field types from data in `string` format, e.g. uploaded csv. * Assign `type`, `tableFieldIndex` and `format` (timestamp only) to each field * * @param {Array<Object>} data array of row object * @param {Array} fieldOrder array of field names as string * @returns {Array<Object>} formatted fields * @public * @example * * import {getFieldsFromData} from 'kepler.gl/processors'; * const data = [{ * time: '2016-09-17 00:09:55', * value: '4', * surge: '1.2', * isTrip: 'true', * zeroOnes: '0' * }, { * time: '2016-09-17 00:30:08', * value: '3', * surge: null, * isTrip: 'false', * zeroOnes: '1' * }, { * time: null, * value: '2', * surge: '1.3', * isTrip: null, * zeroOnes: '1' * }]; * * const fieldOrder = ['time', 'value', 'surge', 'isTrip', 'zeroOnes']; * const fields = getFieldsFromData(data, fieldOrder); * // fields = [ * // {name: 'time', format: 'YYYY-M-D H:m:s', tableFieldIndex: 1, type: 'timestamp'}, * // {name: 'value', format: '', tableFieldIndex: 4, type: 'integer'}, * // {name: 'surge', format: '', tableFieldIndex: 5, type: 'real'}, * // {name: 'isTrip', format: '', tableFieldIndex: 6, type: 'boolean'}, * // {name: 'zeroOnes', format: '', tableFieldIndex: 7, type: 'integer'}]; * */ function getFieldsFromData(data, fieldOrder) { // add a check for epoch timestamp var metadata = _typeAnalyzer.Analyzer.computeColMeta(data, [{ regex: /.*geojson|all_points/g, dataType: 'GEOMETRY' }], { ignoredDataTypes: IGNORE_DATA_TYPES }); var _renameDuplicateField = renameDuplicateFields(fieldOrder), fieldByIndex = _renameDuplicateField.fieldByIndex; var result = fieldOrder.reduce(function (orderedArray, field, index) { var name = fieldByIndex[index]; var fieldMeta = metadata.find(function (m) { return m.key === field; }); var _ref2 = fieldMeta || {}, type = _ref2.type, format = _ref2.format; orderedArray[index] = { name: name, format: format, tableFieldIndex: index + 1, type: analyzerTypeToFieldType(type), analyzerType: type }; return orderedArray; }, []); return result; } /** * pass in an array of field names, rename duplicated one * and return a map from old field index to new name * * @param {Array} fieldOrder * @returns {Object} new field name by index */ function renameDuplicateFields(fieldOrder) { return fieldOrder.reduce(function (accu, field, i) { var allNames = accu.allNames; var fieldName = field; // add a counter to duplicated names if (allNames.includes(field)) { var counter = 0; while (allNames.includes("".concat(field, "-").concat(counter))) { counter++; } fieldName = "".concat(field, "-").concat(counter); } accu.fieldByIndex[i] = fieldName; accu.allNames.push(fieldName); return accu; }, { allNames: [], fieldByIndex: {} }); } /** * Convert type-analyzer output to kepler.gl field types * * @param {string} aType * @returns {string} corresponding type in `ALL_FIELD_TYPES` */ /* eslint-disable complexity */ function analyzerTypeToFieldType(aType) { var DATE = _typeAnalyzer.DATA_TYPES.DATE, TIME = _typeAnalyzer.DATA_TYPES.TIME, DATETIME = _typeAnalyzer.DATA_TYPES.DATETIME, NUMBER = _typeAnalyzer.DATA_TYPES.NUMBER, INT = _typeAnalyzer.DATA_TYPES.INT, FLOAT = _typeAnalyzer.DATA_TYPES.FLOAT, BOOLEAN = _typeAnalyzer.DATA_TYPES.BOOLEAN, STRING = _typeAnalyzer.DATA_TYPES.STRING, GEOMETRY = _typeAnalyzer.DATA_TYPES.GEOMETRY, GEOMETRY_FROM_STRING = _typeAnalyzer.DATA_TYPES.GEOMETRY_FROM_STRING, PAIR_GEOMETRY_FROM_STRING = _typeAnalyzer.DATA_TYPES.PAIR_GEOMETRY_FROM_STRING, ZIPCODE = _typeAnalyzer.DATA_TYPES.ZIPCODE, ARRAY = _typeAnalyzer.DATA_TYPES.ARRAY, OBJECT = _typeAnalyzer.DATA_TYPES.OBJECT; // TODO: un recognized types // CURRENCY PERCENT NONE switch (aType) { case DATE: return _defaultSettings.ALL_FIELD_TYPES.date; case TIME: case DATETIME: return _defaultSettings.ALL_FIELD_TYPES.timestamp; case FLOAT: return _defaultSettings.ALL_FIELD_TYPES.real; case INT: return _defaultSettings.ALL_FIELD_TYPES.integer; case BOOLEAN: return _defaultSettings.ALL_FIELD_TYPES["boolean"]; case GEOMETRY: case GEOMETRY_FROM_STRING: case PAIR_GEOMETRY_FROM_STRING: case ARRAY: case OBJECT: // TODO: create a new data type for objects and arrays return _defaultSettings.ALL_FIELD_TYPES.geojson; case NUMBER: case STRING: case ZIPCODE: return _defaultSettings.ALL_FIELD_TYPES.string; default: _window.console.warn("Unsupported analyzer type: ".concat(aType)); return _defaultSettings.ALL_FIELD_TYPES.string; } } /* eslint-enable complexity */ /** * Process data where each row is an object, output can be passed to [`addDataToMap`](../actions/actions.md#adddatatomap) * @param {Array<Object>} rawData an array of row object, each object should have the same number of keys * @returns {Object} dataset containing `fields` and `rows` * @public * @example * import {addDataToMap} from 'kepler.gl/actions'; * import {processRowObject} from 'kepler.gl/processors'; * * const data = [ * {lat: 31.27, lng: 127.56, value: 3}, * {lat: 31.22, lng: 126.26, value: 1} * ]; * * dispatch(addDataToMap({ * datasets: { * info: {label: 'My Data', id: 'my_data'}, * data: processRowObject(data) * } * })); */ function processRowObject(rawData) { if (!Array.isArray(rawData) || !rawData.length) { return null; } var keys = Object.keys(rawData[0]); var rows = rawData.map(function (d) { return keys.map(function (key) { return d[key]; }); }); // pick samples var sampleData = (0, _dataUtils.getSampleData)(rawData, 500); var fields = getFieldsFromData(sampleData, keys); var parsedRows = parseRowsByFields(rows, fields); return { fields: fields, rows: parsedRows }; } /** * Process GeoJSON [`FeatureCollection`](http://wiki.geojson.org/GeoJSON_draft_version_6#FeatureCollection), * output a data object with `{fields: [], rows: []}`. * The data object can be wrapped in a `dataset` and pass to [`addDataToMap`](../actions/actions.md#adddatatomap) * * @param {Object} rawData raw geojson feature collection * @returns {Object} dataset containing `fields` and `rows` * @public * @example * import {addDataToMap} from 'kepler.gl/actions'; * import {processGeojson} from 'kepler.gl/processors'; * * const geojson = { * "type" : "FeatureCollection", * "features" : [{ * "type" : "Feature", * "properties" : { * "capacity" : "10", * "type" : "U-Rack" * }, * "geometry" : { * "type" : "Point", * "coordinates" : [ -71.073283, 42.417500 ] * } * }] * }; * * dispatch(addDataToMap({ * datasets: { * info: { * label: 'Sample Taxi Trips in New York City', * id: 'test_trip_data' * }, * data: processGeojson(geojson) * } * })); */ function processGeojson(rawData) { var normalizedGeojson = (0, _geojsonNormalize["default"])(rawData); if (!normalizedGeojson || !Array.isArray(normalizedGeojson.features)) { var error = new Error("Read File Failed: File is not a valid GeoJSON. Read more about [supported file format](".concat(_userGuides.GUIDES_FILE_FORMAT, ")")); throw error; // fail to normalize geojson } // getting all feature fields var allDataRows = []; for (var i = 0; i < normalizedGeojson.features.length; i++) { var f = normalizedGeojson.features[i]; if (f.geometry) { allDataRows.push(_objectSpread({ // add feature to _geojson field _geojson: f }, f.properties || {})); } } // get all the field var fields = allDataRows.reduce(function (prev, curr) { Object.keys(curr).forEach(function (key) { if (!prev.includes(key)) { prev.push(key); } }); return prev; }, []); // make sure each feature has exact same fields allDataRows.forEach(function (d) { fields.forEach(function (f) { if (!(f in d)) { d[f] = null; d._geojson.properties[f] = null; } }); }); return processRowObject(allDataRows); } /** * On export data to csv * @param {Array<Array>} data `dataset.allData` or filtered data `dataset.data` * @param {Array<Object>} fields `dataset.fields` * @returns {string} csv string */ function formatCsv(data, fields) { var columns = fields.map(function (f) { return f.name; }); var formattedData = [columns]; // parse geojson object as string data.forEach(function (row) { formattedData.push(row.map(function (d, i) { return (0, _dataUtils.parseFieldValue)(d, fields[i].type); })); }); return (0, _d3Dsv.csvFormatRows)(formattedData); } /** * Validate input data, adding missing field types, rename duplicate columns * @param {Object} data dataset.data * @param {Array<Object>} data.fields an array of fields * @param {Array<Object>} data.rows an array of data rows * @returns {{allData: Array, fields: Array}} */ function validateInputData(data) { if (!(0, _utils.isPlainObject)(data)) { (0, _assert["default"])('addDataToMap Error: dataset.data cannot be null'); return null; } else if (!Array.isArray(data.fields)) { (0, _assert["default"])('addDataToMap Error: expect dataset.data.fields to be an array'); return null; } else if (!Array.isArray(data.rows)) { (0, _assert["default"])('addDataToMap Error: expect dataset.data.rows to be an array'); return null; } var fields = data.fields, rows = data.rows; // check if all fields has name, format and type var allValid = fields.every(function (f, i) { if (!(0, _utils.isPlainObject)(f)) { (0, _assert["default"])("fields needs to be an array of object, but find ".concat((0, _typeof2["default"])(f))); fields[i] = {}; } if (!f.name) { (0, _assert["default"])("field.name is required but missing in ".concat(JSON.stringify(f))); // assign a name fields[i].name = "column_".concat(i); } if (!_defaultSettings.ALL_FIELD_TYPES[f.type]) { (0, _assert["default"])("unknown field type ".concat(f.type)); return false; } if (!fields.every(function (field) { return field.analyzerType; })) { (0, _assert["default"])('field missing analyzerType'); return false; } // check time format is correct based on first 10 not empty element if (f.type === _defaultSettings.ALL_FIELD_TYPES.timestamp) { var sample = findNonEmptyRowsAtField(rows, i, 10).map(function (r) { return { ts: r[i] }; }); var analyzedType = _typeAnalyzer.Analyzer.computeColMeta(sample)[0]; return analyzedType.category === 'TIME' && analyzedType.format === f.format; } return true; }); if (allValid) { return { rows: rows, fields: fields }; } // if any field has missing type, recalculate it for everyone // because we simply lost faith in humanity var sampleData = getSampleForTypeAnalyze({ fields: fields.map(function (f) { return f.name; }), allData: rows }); var fieldOrder = fields.map(function (f) { return f.name; }); var meta = getFieldsFromData(sampleData, fieldOrder); var updatedFields = fields.map(function (f, i) { return _objectSpread({}, f, { type: meta[i].type, format: meta[i].format, analyzerType: meta[i].analyzerType }); }); return { fields: updatedFields, rows: rows }; } function findNonEmptyRowsAtField(rows, fieldIdx, total) { var sample = []; var i = 0; while (sample.length < total && i < rows.length) { if ((0, _dataUtils.notNullorUndefined)(rows[i][fieldIdx])) { sample.push(rows[i]); } i++; } return sample; } /** * Process saved kepler.gl json to be pass to [`addDataToMap`](../actions/actions.md#adddatatomap). * The json object should contain `datasets` and `config`. * @param {Object} rawData * @param {Array} rawData.datasets * @param {Object} rawData.config * @returns {Object} datasets and config `{datasets: {}, config: {}}` * @public * @example * import {addDataToMap} from 'kepler.gl/actions'; * import {processKeplerglJSON} from 'kepler.gl/processors'; * * dispatch(addDataToMap(processKeplerglJSON(keplerGlJson))); */ function processKeplerglJSON(rawData) { return rawData ? _schemas["default"].load(rawData.datasets, rawData.config) : null; } /** * Parse a single or an array of datasets saved using kepler.gl schema * @param {Array | Array<Object>} rawData */ function processKeplerglDataset(rawData) { if (!rawData) { return null; } var results = _schemas["default"].parseSavedData((0, _utils.toArray)(rawData)); return Array.isArray(rawData) ? results : results[0]; } var DATASET_HANDLERS = (_DATASET_HANDLERS = {}, (0, _defineProperty2["default"])(_DATASET_HANDLERS, _defaultSettings.DATASET_FORMATS.row, processRowObject), (0, _defineProperty2["default"])(_DATASET_HANDLERS, _defaultSettings.DATASET_FORMATS.geojson, processGeojson), (0, _defineProperty2["default"])(_DATASET_HANDLERS, _defaultSettings.DATASET_FORMATS.csv, processCsvData), (0, _defineProperty2["default"])(_DATASET_HANDLERS, _defaultSettings.DATASET_FORMATS.keplergl, processKeplerglDataset), _DATASET_HANDLERS); exports.DATASET_HANDLERS = DATASET_HANDLERS; var Processors = { processGeojson: processGeojson, processCsvData: processCsvData, processRowObject: processRowObject, processKeplerglJSON: processKeplerglJSON, processKeplerglDataset: processKeplerglDataset, analyzerTypeToFieldType: analyzerTypeToFieldType, getFieldsFromData: getFieldsFromData, parseCsvRowsByFieldType: parseCsvRowsByFieldType, formatCsv: formatCsv }; exports.Processors = Processors; //# sourceMappingURL=data:application/json;charset=utf-8;base64,eyJ2ZXJzaW9uIjozLCJzb3VyY2VzIjpbIi4uLy4uL3NyYy9wcm9jZXNzb3JzL2RhdGEtcHJvY2Vzc29yLmpzIl0sIm5hbWVzIjpbIkFDQ0VQVEVEX0FOQUxZWkVSX1RZUEVTIiwiQW5hbHl6ZXJEQVRBX1RZUEVTIiwiREFURSIsIlRJTUUiLCJEQVRFVElNRSIsIk5VTUJFUiIsIklOVCIsIkZMT0FUIiwiQk9PTEVBTiIsIlNUUklORyIsIkdFT01FVFJZIiwiR0VPTUVUUllfRlJPTV9TVFJJTkciLCJQQUlSX0dFT01FVFJZX0ZST01fU1RSSU5HIiwiWklQQ09ERSIsIkFSUkFZIiwiT0JKRUNUIiwiQ1NWX05VTExTIiwiSUdOT1JFX0RBVEFfVFlQRVMiLCJPYmplY3QiLCJrZXlzIiwiZmlsdGVyIiwidHlwZSIsImluY2x1ZGVzIiwiUEFSU0VfRklFTERfVkFMVUVfRlJPTV9TVFJJTkciLCJBTExfRklFTERfVFlQRVMiLCJ2YWxpZCIsImQiLCJwYXJzZSIsImludGVnZXIiLCJwYXJzZUludCIsInRpbWVzdGFtcCIsImZpZWxkIiwiZm9ybWF0IiwiTnVtYmVyIiwicmVhbCIsInBhcnNlRmxvYXQiLCJwcm9jZXNzQ3N2RGF0YSIsInJhd0RhdGEiLCJyZXN1bHQiLCJBcnJheSIsImlzQXJyYXkiLCJsZW5ndGgiLCJFcnJvciIsImhlYWRlclJvdyIsInJvd3MiLCJjbGVhblVwRmFsc3lDc3ZWYWx1ZSIsInNhbXBsZSIsImdldFNhbXBsZUZvclR5cGVBbmFseXplIiwiZmllbGRzIiwiYWxsRGF0YSIsImdldEZpZWxkc0Zyb21EYXRhIiwicGFyc2VkUm93cyIsInBhcnNlUm93c0J5RmllbGRzIiwiZ2VvanNvbkZpZWxkSWR4IiwiZmluZEluZGV4IiwiZiIsIm5hbWUiLCJmb3JFYWNoIiwicGFyc2VDc3ZSb3dzQnlGaWVsZFR5cGUiLCJiaW5kIiwic2FtcGxlQ291bnQiLCJ0b3RhbCIsIk1hdGgiLCJtaW4iLCJtYXAiLCJmaWVsZElkeCIsImkiLCJqIiwiZ2VvRmllbGRJZHgiLCJwYXJzZXIiLCJmaXJzdCIsImZpbmQiLCJyIiwicm93IiwicHJvcGVydGllcyIsImRhdGEiLCJmaWVsZE9yZGVyIiwibWV0YWRhdGEiLCJBbmFseXplciIsImNvbXB1dGVDb2xNZXRhIiwicmVnZXgiLCJkYXRhVHlwZSIsImlnbm9yZWREYXRhVHlwZXMiLCJyZW5hbWVEdXBsaWNhdGVGaWVsZHMiLCJmaWVsZEJ5SW5kZXgiLCJyZWR1Y2UiLCJvcmRlcmVkQXJyYXkiLCJpbmRleCIsImZpZWxkTWV0YSIsIm0iLCJrZXkiLCJ0YWJsZUZpZWxkSW5kZXgiLCJhbmFseXplclR5cGVUb0ZpZWxkVHlwZSIsImFuYWx5emVyVHlwZSIsImFjY3UiLCJhbGxOYW1lcyIsImZpZWxkTmFtZSIsImNvdW50ZXIiLCJwdXNoIiwiYVR5cGUiLCJkYXRlIiwiZ2VvanNvbiIsInN0cmluZyIsImdsb2JhbENvbnNvbGUiLCJ3YXJuIiwicHJvY2Vzc1Jvd09iamVjdCIsInNhbXBsZURhdGEiLCJwcm9jZXNzR2VvanNvbiIsIm5vcm1hbGl6ZWRHZW9qc29uIiwiZmVhdHVyZXMiLCJlcnJvciIsIkdVSURFU19GSUxFX0ZPUk1BVCIsImFsbERhdGFSb3dzIiwiZ2VvbWV0cnkiLCJfZ2VvanNvbiIsInByZXYiLCJjdXJyIiwiZm9ybWF0Q3N2IiwiY29sdW1ucyIsImZvcm1hdHRlZERhdGEiLCJ2YWxpZGF0ZUlucHV0RGF0YSIsImFsbFZhbGlkIiwiZXZlcnkiLCJKU09OIiwic3RyaW5naWZ5IiwiZmluZE5vbkVtcHR5Um93c0F0RmllbGQiLCJ0cyIsImFuYWx5emVkVHlwZSIsImNhdGVnb3J5IiwibWV0YSIsInVwZGF0ZWRGaWVsZHMiLCJwcm9jZXNzS2VwbGVyZ2xKU09OIiwiS2VwbGVyR2xTY2hlbWEiLCJsb2FkIiwiZGF0YXNldHMiLCJjb25maWciLCJwcm9jZXNzS2VwbGVyZ2xEYXRhc2V0IiwicmVzdWx0cyIsInBhcnNlU2F2ZWREYXRhIiwiREFUQVNFVF9IQU5ETEVSUyIsIkRBVEFTRVRfRk9STUFUUyIsImNzdiIsImtlcGxlcmdsIiwiUHJvY2Vzc29ycyJdLCJtYXBwaW5ncyI6Ijs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7OztBQW9CQTs7QUFDQTs7QUFDQTs7QUFDQTs7QUFDQTs7QUFDQTs7QUFDQTs7QUFDQTs7QUFDQTs7QUFDQTs7QUFDQTs7Ozs7Ozs7QUFFTyxJQUFNQSx1QkFBdUIsR0FBRyxDQUNyQ0MseUJBQW1CQyxJQURrQixFQUVyQ0QseUJBQW1CRSxJQUZrQixFQUdyQ0YseUJBQW1CRyxRQUhrQixFQUlyQ0gseUJBQW1CSSxNQUprQixFQUtyQ0oseUJBQW1CSyxHQUxrQixFQU1yQ0wseUJBQW1CTSxLQU5rQixFQU9yQ04seUJBQW1CTyxPQVBrQixFQVFyQ1AseUJBQW1CUSxNQVJrQixFQVNyQ1IseUJBQW1CUyxRQVRrQixFQVVyQ1QseUJBQW1CVSxvQkFWa0IsRUFXckNWLHlCQUFtQlcseUJBWGtCLEVBWXJDWCx5QkFBbUJZLE9BWmtCLEVBYXJDWix5QkFBbUJhLEtBYmtCLEVBY3JDYix5QkFBbUJjLE1BZGtCLENBQWhDLEMsQ0FpQlA7OztBQUNBLElBQU1DLFNBQVMsR0FBRyxDQUFDLEVBQUQsRUFBSyxNQUFMLEVBQWEsTUFBYixFQUFxQixNQUFyQixFQUE2QixLQUE3QixFQUFvQyxJQUFwQyxDQUFsQjtBQUVBLElBQU1DLGlCQUFpQixHQUFHQyxNQUFNLENBQUNDLElBQVAsQ0FBWWxCLHdCQUFaLEVBQWdDbUIsTUFBaEMsQ0FDeEIsVUFBQUMsSUFBSTtBQUFBLFNBQUksQ0FBQ3JCLHVCQUF1QixDQUFDc0IsUUFBeEIsQ0FBaUNELElBQWpDLENBQUw7QUFBQSxDQURvQixDQUExQjtBQUlPLElBQU1FLDZCQUE2Qix3RkFDdkNDLDJDQUR1QyxFQUNiO0FBQ3pCQyxFQUFBQSxLQUFLLEVBQUUsZUFBQUMsQ0FBQztBQUFBLFdBQUksT0FBT0EsQ0FBUCxLQUFhLFNBQWpCO0FBQUEsR0FEaUI7QUFFekJDLEVBQUFBLEtBQUssRUFBRSxlQUFBRCxDQUFDO0FBQUEsV0FBSUEsQ0FBQyxLQUFLLE1BQU4sSUFBZ0JBLENBQUMsS0FBSyxNQUF0QixJQUFnQ0EsQ0FBQyxLQUFLLEdBQTFDO0FBQUE7QUFGaUIsQ0FEYSwyREFLdkNGLGlDQUFnQkksT0FMdUIsRUFLYjtBQUN6QkgsRUFBQUEsS0FBSyxFQUFFLGVBQUFDLENBQUM7QUFBQSxXQUFJRyxRQUFRLENBQUNILENBQUQsRUFBSSxFQUFKLENBQVIsS0FBb0JBLENBQXhCO0FBQUEsR0FEaUI7QUFFekJDLEVBQUFBLEtBQUssRUFBRSxlQUFBRCxDQUFDO0FBQUEsV0FBSUcsUUFBUSxDQUFDSCxDQUFELEVBQUksRUFBSixDQUFaO0FBQUE7QUFGaUIsQ0FMYSwyREFTdkNGLGlDQUFnQk0sU0FUdUIsRUFTWDtBQUMzQkwsRUFBQUEsS0FBSyxFQUFFLGVBQUNDLENBQUQsRUFBSUssS0FBSjtBQUFBLFdBQ0wsQ0FBQyxHQUFELEVBQU0sR0FBTixFQUFXVCxRQUFYLENBQW9CUyxLQUFLLENBQUNDLE1BQTFCLElBQW9DLE9BQU9OLENBQVAsS0FBYSxRQUFqRCxHQUE0RCxPQUFPQSxDQUFQLEtBQWEsUUFEcEU7QUFBQSxHQURvQjtBQUczQkMsRUFBQUEsS0FBSyxFQUFFLGVBQUNELENBQUQsRUFBSUssS0FBSjtBQUFBLFdBQWUsQ0FBQyxHQUFELEVBQU0sR0FBTixFQUFXVCxRQUFYLENBQW9CUyxLQUFLLENBQUNDLE1BQTFCLElBQW9DQyxNQUFNLENBQUNQLENBQUQsQ0FBMUMsR0FBZ0RBLENBQS9EO0FBQUE7QUFIb0IsQ0FUVywyREFjdkNGLGlDQUFnQlUsSUFkdUIsRUFjaEI7QUFDdEJULEVBQUFBLEtBQUssRUFBRSxlQUFBQyxDQUFDO0FBQUEsV0FBSVMsVUFBVSxDQUFDVCxDQUFELENBQVYsS0FBa0JBLENBQXRCO0FBQUEsR0FEYztBQUV0QkMsRUFBQUEsS0FBSyxFQUFFUTtBQUZlLENBZGdCLHlCQUFuQztBQW9CUDs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7OztBQXlCTyxTQUFTQyxjQUFULENBQXdCQyxPQUF4QixFQUFpQztBQUN0QztBQUNBO0FBQ0E7QUFDQSxNQUFNQyxNQUFNLEdBQUcseUJBQWFELE9BQWIsQ0FBZjs7QUFDQSxNQUFJLENBQUNFLEtBQUssQ0FBQ0MsT0FBTixDQUFjRixNQUFkLENBQUQsSUFBMEJBLE1BQU0sQ0FBQ0csTUFBUCxHQUFnQixDQUE5QyxFQUFpRDtBQUMvQztBQUNBLFVBQU0sSUFBSUMsS0FBSixDQUFVLGdDQUFWLENBQU47QUFDRDs7QUFScUMsMENBVVRKLE1BVlM7QUFBQSxNQVUvQkssU0FWK0I7QUFBQSxNQVVqQkMsSUFWaUI7O0FBWXRDQyxFQUFBQSxvQkFBb0IsQ0FBQ0QsSUFBRCxDQUFwQixDQVpzQyxDQWF0QztBQUNBOztBQUNBLE1BQU1FLE1BQU0sR0FBR0MsdUJBQXVCLENBQUM7QUFBQ0MsSUFBQUEsTUFBTSxFQUFFTCxTQUFUO0FBQW9CTSxJQUFBQSxPQUFPLEVBQUVMO0FBQTdCLEdBQUQsQ0FBdEM7QUFFQSxNQUFNSSxNQUFNLEdBQUdFLGlCQUFpQixDQUFDSixNQUFELEVBQVNILFNBQVQsQ0FBaEM7QUFFQSxNQUFNUSxVQUFVLEdBQUdDLGlCQUFpQixDQUFDUixJQUFELEVBQU9JLE1BQVAsQ0FBcEM7QUFFQSxTQUFPO0FBQUNBLElBQUFBLE1BQU0sRUFBTkEsTUFBRDtBQUFTSixJQUFBQSxJQUFJLEVBQUVPO0FBQWYsR0FBUDtBQUNEO0FBRUQ7Ozs7Ozs7QUFLTyxTQUFTQyxpQkFBVCxDQUEyQlIsSUFBM0IsRUFBaUNJLE1BQWpDLEVBQXlDO0FBQzlDO0FBQ0EsTUFBTUssZUFBZSxHQUFHTCxNQUFNLENBQUNNLFNBQVAsQ0FBaUIsVUFBQUMsQ0FBQztBQUFBLFdBQUlBLENBQUMsQ0FBQ0MsSUFBRixLQUFXLFVBQWY7QUFBQSxHQUFsQixDQUF4QjtBQUNBUixFQUFBQSxNQUFNLENBQUNTLE9BQVAsQ0FBZUMsdUJBQXVCLENBQUNDLElBQXhCLENBQTZCLElBQTdCLEVBQW1DZixJQUFuQyxFQUF5Q1MsZUFBekMsQ0FBZjtBQUVBLFNBQU9ULElBQVA7QUFDRDtBQUNEOzs7Ozs7Ozs7O0FBUU8sU0FBU0csdUJBQVQsT0FBc0U7QUFBQSxNQUFwQ0MsTUFBb0MsUUFBcENBLE1BQW9DO0FBQUEsTUFBNUJDLE9BQTRCLFFBQTVCQSxPQUE0QjtBQUFBLDhCQUFuQlcsV0FBbUI7QUFBQSxNQUFuQkEsV0FBbUIsaUNBQUwsRUFBSztBQUMzRSxNQUFNQyxLQUFLLEdBQUdDLElBQUksQ0FBQ0MsR0FBTCxDQUFTSCxXQUFULEVBQXNCWCxPQUFPLENBQUNSLE1BQTlCLENBQWQsQ0FEMkUsQ0FFM0U7O0FBQ0EsTUFBTUssTUFBTSxHQUFHLG9CQUFNLENBQU4sRUFBU2UsS0FBVCxFQUFnQixDQUFoQixFQUFtQkcsR0FBbkIsQ0FBdUIsVUFBQXRDLENBQUM7QUFBQSxXQUFLLEVBQUw7QUFBQSxHQUF4QixDQUFmLENBSDJFLENBSzNFOztBQUNBc0IsRUFBQUEsTUFBTSxDQUFDUyxPQUFQLENBQWUsVUFBQzFCLEtBQUQsRUFBUWtDLFFBQVIsRUFBcUI7QUFDbEM7QUFDQSxRQUFJQyxDQUFDLEdBQUcsQ0FBUixDQUZrQyxDQUdsQzs7QUFDQSxRQUFJQyxDQUFDLEdBQUcsQ0FBUjs7QUFFQSxXQUFPQSxDQUFDLEdBQUdOLEtBQVgsRUFBa0I7QUFDaEIsVUFBSUssQ0FBQyxJQUFJakIsT0FBTyxDQUFDUixNQUFqQixFQUF5QjtBQUN2QjtBQUNBSyxRQUFBQSxNQUFNLENBQUNxQixDQUFELENBQU4sQ0FBVXBDLEtBQVYsSUFBbUIsSUFBbkI7QUFDQW9DLFFBQUFBLENBQUM7QUFDRixPQUpELE1BSU8sSUFBSSxtQ0FBbUJsQixPQUFPLENBQUNpQixDQUFELENBQVAsQ0FBV0QsUUFBWCxDQUFuQixDQUFKLEVBQThDO0FBQ25EbkIsUUFBQUEsTUFBTSxDQUFDcUIsQ0FBRCxDQUFOLENBQVVwQyxLQUFWLElBQW1Ca0IsT0FBTyxDQUFDaUIsQ0FBRCxDQUFQLENBQVdELFFBQVgsQ0FBbkI7QUFDQUUsUUFBQUEsQ0FBQztBQUNERCxRQUFBQSxDQUFDO0FBQ0YsT0FKTSxNQUlBO0FBQ0xBLFFBQUFBLENBQUM7QUFDRjtBQUNGO0FBQ0YsR0FuQkQ7QUFxQkEsU0FBT3BCLE1BQVA7QUFDRDtBQUVEOzs7Ozs7OztBQU1BLFNBQVNELG9CQUFULENBQThCRCxJQUE5QixFQUFvQztBQUNsQyxPQUFLLElBQUlzQixDQUFDLEdBQUcsQ0FBYixFQUFnQkEsQ0FBQyxHQUFHdEIsSUFBSSxDQUFDSCxNQUF6QixFQUFpQ3lCLENBQUMsRUFBbEMsRUFBc0M7QUFDcEMsU0FBSyxJQUFJQyxDQUFDLEdBQUcsQ0FBYixFQUFnQkEsQ0FBQyxHQUFHdkIsSUFBSSxDQUFDc0IsQ0FBRCxDQUFKLENBQVF6QixNQUE1QixFQUFvQzBCLENBQUMsRUFBckMsRUFBeUM7QUFDdkM7QUFDQTtBQUNBO0FBQ0E7QUFDQSxVQUFJLENBQUN2QixJQUFJLENBQUNzQixDQUFELENBQUosQ0FBUUMsQ0FBUixDQUFELElBQWVuRCxTQUFTLENBQUNNLFFBQVYsQ0FBbUJzQixJQUFJLENBQUNzQixDQUFELENBQUosQ0FBUUMsQ0FBUixDQUFuQixDQUFuQixFQUFtRDtBQUNqRHZCLFFBQUFBLElBQUksQ0FBQ3NCLENBQUQsQ0FBSixDQUFRQyxDQUFSLElBQWEsSUFBYjtBQUNEO0FBQ0Y7QUFDRjtBQUNGO0FBRUQ7Ozs7Ozs7Ozs7O0FBU08sU0FBU1QsdUJBQVQsQ0FBaUNkLElBQWpDLEVBQXVDd0IsV0FBdkMsRUFBb0RyQyxLQUFwRCxFQUEyRG1DLENBQTNELEVBQThEO0FBQ25FLE1BQU1HLE1BQU0sR0FBRzlDLDZCQUE2QixDQUFDUSxLQUFLLENBQUNWLElBQVAsQ0FBNUM7O0FBQ0EsTUFBSWdELE1BQUosRUFBWTtBQUNWO0FBQ0EsUUFBTUMsS0FBSyxHQUFHMUIsSUFBSSxDQUFDMkIsSUFBTCxDQUFVLFVBQUFDLENBQUM7QUFBQSxhQUFJLG1DQUFtQkEsQ0FBQyxDQUFDTixDQUFELENBQXBCLENBQUo7QUFBQSxLQUFYLENBQWQ7O0FBQ0EsUUFBSSxDQUFDSSxLQUFELElBQVVELE1BQU0sQ0FBQzVDLEtBQVAsQ0FBYTZDLEtBQUssQ0FBQ0osQ0FBRCxDQUFsQixFQUF1Qm5DLEtBQXZCLENBQWQsRUFBNkM7QUFDM0M7QUFDRDs7QUFDRGEsSUFBQUEsSUFBSSxDQUFDYSxPQUFMLENBQWEsVUFBQWdCLEdBQUcsRUFBSTtBQUNsQjtBQUNBLFVBQUlBLEdBQUcsQ0FBQ1AsQ0FBRCxDQUFILEtBQVcsSUFBZixFQUFxQjtBQUNuQk8sUUFBQUEsR0FBRyxDQUFDUCxDQUFELENBQUgsR0FBU0csTUFBTSxDQUFDMUMsS0FBUCxDQUFhOEMsR0FBRyxDQUFDUCxDQUFELENBQWhCLEVBQXFCbkMsS0FBckIsQ0FBVDs7QUFDQSxZQUFJcUMsV0FBVyxHQUFHLENBQUMsQ0FBZixJQUFvQkssR0FBRyxDQUFDTCxXQUFELENBQXZCLElBQXdDSyxHQUFHLENBQUNMLFdBQUQsQ0FBSCxDQUFpQk0sVUFBN0QsRUFBeUU7QUFDdkVELFVBQUFBLEdBQUcsQ0FBQ0wsV0FBRCxDQUFILENBQWlCTSxVQUFqQixDQUE0QjNDLEtBQUssQ0FBQ3lCLElBQWxDLElBQTBDaUIsR0FBRyxDQUFDUCxDQUFELENBQTdDO0FBQ0Q7QUFDRjtBQUNGLEtBUkQ7QUFTRDtBQUNGO0FBRUQ7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7QUF5Q08sU0FBU2hCLGlCQUFULENBQTJCeUIsSUFBM0IsRUFBaUNDLFVBQWpDLEVBQTZDO0FBQ2xEO0FBQ0EsTUFBTUMsUUFBUSxHQUFHQyx1QkFBU0MsY0FBVCxDQUNmSixJQURlLEVBRWYsQ0FBQztBQUFDSyxJQUFBQSxLQUFLLEVBQUUsdUJBQVI7QUFBaUNDLElBQUFBLFFBQVEsRUFBRTtBQUEzQyxHQUFELENBRmUsRUFHZjtBQUFDQyxJQUFBQSxnQkFBZ0IsRUFBRWpFO0FBQW5CLEdBSGUsQ0FBakI7O0FBRmtELDhCQVEzQmtFLHFCQUFxQixDQUFDUCxVQUFELENBUk07QUFBQSxNQVEzQ1EsWUFSMkMseUJBUTNDQSxZQVIyQzs7QUFVbEQsTUFBTTlDLE1BQU0sR0FBR3NDLFVBQVUsQ0FBQ1MsTUFBWCxDQUFrQixVQUFDQyxZQUFELEVBQWV2RCxLQUFmLEVBQXNCd0QsS0FBdEIsRUFBZ0M7QUFDL0QsUUFBTS9CLElBQUksR0FBRzRCLFlBQVksQ0FBQ0csS0FBRCxDQUF6QjtBQUVBLFFBQU1DLFNBQVMsR0FBR1gsUUFBUSxDQUFDTixJQUFULENBQWMsVUFBQWtCLENBQUM7QUFBQSxhQUFJQSxDQUFDLENBQUNDLEdBQUYsS0FBVTNELEtBQWQ7QUFBQSxLQUFmLENBQWxCOztBQUgrRCxnQkFJeEN5RCxTQUFTLElBQUksRUFKMkI7QUFBQSxRQUl4RG5FLElBSndELFNBSXhEQSxJQUp3RDtBQUFBLFFBSWxEVyxNQUprRCxTQUlsREEsTUFKa0Q7O0FBTS9Ec0QsSUFBQUEsWUFBWSxDQUFDQyxLQUFELENBQVosR0FBc0I7QUFDcEIvQixNQUFBQSxJQUFJLEVBQUpBLElBRG9CO0FBRXBCeEIsTUFBQUEsTUFBTSxFQUFOQSxNQUZvQjtBQUdwQjJELE1BQUFBLGVBQWUsRUFBRUosS0FBSyxHQUFHLENBSEw7QUFJcEJsRSxNQUFBQSxJQUFJLEVBQUV1RSx1QkFBdUIsQ0FBQ3ZFLElBQUQsQ0FKVDtBQUtwQndFLE1BQUFBLFlBQVksRUFBRXhFO0FBTE0sS0FBdEI7QUFPQSxXQUFPaUUsWUFBUDtBQUNELEdBZGMsRUFjWixFQWRZLENBQWY7QUFnQkEsU0FBT2hELE1BQVA7QUFDRDtBQUVEOzs7Ozs7Ozs7QUFPTyxTQUFTNkMscUJBQVQsQ0FBK0JQLFVBQS9CLEVBQTJDO0FBQ2hELFNBQU9BLFVBQVUsQ0FBQ1MsTUFBWCxDQUNMLFVBQUNTLElBQUQsRUFBTy9ELEtBQVAsRUFBY21DLENBQWQsRUFBb0I7QUFBQSxRQUNYNkIsUUFEVyxHQUNDRCxJQURELENBQ1hDLFFBRFc7QUFFbEIsUUFBSUMsU0FBUyxHQUFHakUsS0FBaEIsQ0FGa0IsQ0FJbEI7O0FBQ0EsUUFBSWdFLFFBQVEsQ0FBQ3pFLFFBQVQsQ0FBa0JTLEtBQWxCLENBQUosRUFBOEI7QUFDNUIsVUFBSWtFLE9BQU8sR0FBRyxDQUFkOztBQUNBLGFBQU9GLFFBQVEsQ0FBQ3pFLFFBQVQsV0FBcUJTLEtBQXJCLGNBQThCa0UsT0FBOUIsRUFBUCxFQUFpRDtBQUMvQ0EsUUFBQUEsT0FBTztBQUNSOztBQUNERCxNQUFBQSxTQUFTLGFBQU1qRSxLQUFOLGNBQWVrRSxPQUFmLENBQVQ7QUFDRDs7QUFFREgsSUFBQUEsSUFBSSxDQUFDVixZQUFMLENBQWtCbEIsQ0FBbEIsSUFBdUI4QixTQUF2QjtBQUNBRixJQUFBQSxJQUFJLENBQUNDLFFBQUwsQ0FBY0csSUFBZCxDQUFtQkYsU0FBbkI7QUFFQSxXQUFPRixJQUFQO0FBQ0QsR0FsQkksRUFtQkw7QUFBQ0MsSUFBQUEsUUFBUSxFQUFFLEVBQVg7QUFBZVgsSUFBQUEsWUFBWSxFQUFFO0FBQTdCLEdBbkJLLENBQVA7QUFxQkQ7QUFFRDs7Ozs7OztBQU1BOzs7QUFDTyxTQUFTUSx1QkFBVCxDQUFpQ08sS0FBakMsRUFBd0M7QUFBQSxNQUUzQ2pHLElBRjJDLEdBZ0J6Q0Qsd0JBaEJ5QyxDQUUzQ0MsSUFGMkM7QUFBQSxNQUczQ0MsSUFIMkMsR0FnQnpDRix3QkFoQnlDLENBRzNDRSxJQUgyQztBQUFBLE1BSTNDQyxRQUoyQyxHQWdCekNILHdCQWhCeUMsQ0FJM0NHLFFBSjJDO0FBQUEsTUFLM0NDLE1BTDJDLEdBZ0J6Q0osd0JBaEJ5QyxDQUszQ0ksTUFMMkM7QUFBQSxNQU0zQ0MsR0FOMkMsR0FnQnpDTCx3QkFoQnlDLENBTTNDSyxHQU4yQztBQUFBLE1BTzNDQyxLQVAyQyxHQWdCekNOLHdCQWhCeUMsQ0FPM0NNLEtBUDJDO0FBQUEsTUFRM0NDLE9BUjJDLEdBZ0J6Q1Asd0JBaEJ5QyxDQVEzQ08sT0FSMkM7QUFBQSxNQVMzQ0MsTUFUMkMsR0FnQnpDUix3QkFoQnlDLENBUzNDUSxNQVQyQztBQUFBLE1BVTNDQyxRQVYyQyxHQWdCekNULHdCQWhCeUMsQ0FVM0NTLFFBVjJDO0FBQUEsTUFXM0NDLG9CQVgyQyxHQWdCekNWLHdCQWhCeUMsQ0FXM0NVLG9CQVgyQztBQUFBLE1BWTNDQyx5QkFaMkMsR0FnQnpDWCx3QkFoQnlDLENBWTNDVyx5QkFaMkM7QUFBQSxNQWEzQ0MsT0FiMkMsR0FnQnpDWix3QkFoQnlDLENBYTNDWSxPQWIyQztBQUFBLE1BYzNDQyxLQWQyQyxHQWdCekNiLHdCQWhCeUMsQ0FjM0NhLEtBZDJDO0FBQUEsTUFlM0NDLE1BZjJDLEdBZ0J6Q2Qsd0JBaEJ5QyxDQWUzQ2MsTUFmMkMsRUFrQjdDO0FBQ0E7O0FBQ0EsVUFBUW9GLEtBQVI7QUFDRSxTQUFLakcsSUFBTDtBQUNFLGFBQU9zQixpQ0FBZ0I0RSxJQUF2Qjs7QUFDRixTQUFLakcsSUFBTDtBQUNBLFNBQUtDLFFBQUw7QUFDRSxhQUFPb0IsaUNBQWdCTSxTQUF2Qjs7QUFDRixTQUFLdkIsS0FBTDtBQUNFLGFBQU9pQixpQ0FBZ0JVLElBQXZCOztBQUNGLFNBQUs1QixHQUFMO0FBQ0UsYUFBT2tCLGlDQUFnQkksT0FBdkI7O0FBQ0YsU0FBS3BCLE9BQUw7QUFDRSxhQUFPZ0IsMkNBQVA7O0FBQ0YsU0FBS2QsUUFBTDtBQUNBLFNBQUtDLG9CQUFMO0FBQ0EsU0FBS0MseUJBQUw7QUFDQSxTQUFLRSxLQUFMO0FBQ0EsU0FBS0MsTUFBTDtBQUNFO0FBQ0EsYUFBT1MsaUNBQWdCNkUsT0FBdkI7O0FBQ0YsU0FBS2hHLE1BQUw7QUFDQSxTQUFLSSxNQUFMO0FBQ0EsU0FBS0ksT0FBTDtBQUNFLGFBQU9XLGlDQUFnQjhFLE1BQXZCOztBQUNGO0FBQ0VDLHNCQUFjQyxJQUFkLHNDQUFpREwsS0FBakQ7O0FBQ0EsYUFBTzNFLGlDQUFnQjhFLE1BQXZCO0FBekJKO0FBMkJEO0FBQ0Q7O0FBRUE7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7O0FBcUJPLFNBQVNHLGdCQUFULENBQTBCcEUsT0FBMUIsRUFBbUM7QUFDeEMsTUFBSSxDQUFDRSxLQUFLLENBQUNDLE9BQU4sQ0FBY0gsT0FBZCxDQUFELElBQTJCLENBQUNBLE9BQU8sQ0FBQ0ksTUFBeEMsRUFBZ0Q7QUFDOUMsV0FBTyxJQUFQO0FBQ0Q7O0FBRUQsTUFBTXRCLElBQUksR0FBR0QsTUFBTSxDQUFDQyxJQUFQLENBQVlrQixPQUFPLENBQUMsQ0FBRCxDQUFuQixDQUFiO0FBQ0EsTUFBTU8sSUFBSSxHQUFHUCxPQUFPLENBQUMyQixHQUFSLENBQVksVUFBQXRDLENBQUM7QUFBQSxXQUFJUCxJQUFJLENBQUM2QyxHQUFMLENBQVMsVUFBQTBCLEdBQUc7QUFBQSxhQUFJaEUsQ0FBQyxDQUFDZ0UsR0FBRCxDQUFMO0FBQUEsS0FBWixDQUFKO0FBQUEsR0FBYixDQUFiLENBTndDLENBUXhDOztBQUNBLE1BQU1nQixVQUFVLEdBQUcsOEJBQWNyRSxPQUFkLEVBQXVCLEdBQXZCLENBQW5CO0FBQ0EsTUFBTVcsTUFBTSxHQUFHRSxpQkFBaUIsQ0FBQ3dELFVBQUQsRUFBYXZGLElBQWIsQ0FBaEM7QUFDQSxNQUFNZ0MsVUFBVSxHQUFHQyxpQkFBaUIsQ0FBQ1IsSUFBRCxFQUFPSSxNQUFQLENBQXBDO0FBRUEsU0FBTztBQUNMQSxJQUFBQSxNQUFNLEVBQU5BLE1BREs7QUFFTEosSUFBQUEsSUFBSSxFQUFFTztBQUZELEdBQVA7QUFJRDtBQUVEOzs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7QUFxQ08sU0FBU3dELGNBQVQsQ0FBd0J0RSxPQUF4QixFQUFpQztBQUN0QyxNQUFNdUUsaUJBQWlCLEdBQUcsa0NBQVV2RSxPQUFWLENBQTFCOztBQUVBLE1BQUksQ0FBQ3VFLGlCQUFELElBQXNCLENBQUNyRSxLQUFLLENBQUNDLE9BQU4sQ0FBY29FLGlCQUFpQixDQUFDQyxRQUFoQyxDQUEzQixFQUFzRTtBQUNwRSxRQUFNQyxLQUFLLEdBQUcsSUFBSXBFLEtBQUosa0dBQzhFcUUsOEJBRDlFLE9BQWQ7QUFHQSxVQUFNRCxLQUFOLENBSm9FLENBS3BFO0FBQ0QsR0FUcUMsQ0FXdEM7OztBQUNBLE1BQU1FLFdBQVcsR0FBRyxFQUFwQjs7QUFDQSxPQUFLLElBQUk5QyxDQUFDLEdBQUcsQ0FBYixFQUFnQkEsQ0FBQyxHQUFHMEMsaUJBQWlCLENBQUNDLFFBQWxCLENBQTJCcEUsTUFBL0MsRUFBdUR5QixDQUFDLEVBQXhELEVBQTREO0FBQzFELFFBQU1YLENBQUMsR0FBR3FELGlCQUFpQixDQUFDQyxRQUFsQixDQUEyQjNDLENBQTNCLENBQVY7O0FBQ0EsUUFBSVgsQ0FBQyxDQUFDMEQsUUFBTixFQUFnQjtBQUNkRCxNQUFBQSxXQUFXLENBQUNkLElBQVo7QUFDRTtBQUNBZ0IsUUFBQUEsUUFBUSxFQUFFM0Q7QUFGWixTQUdNQSxDQUFDLENBQUNtQixVQUFGLElBQWdCLEVBSHRCO0FBS0Q7QUFDRixHQXRCcUMsQ0F1QnRDOzs7QUFDQSxNQUFNMUIsTUFBTSxHQUFHZ0UsV0FBVyxDQUFDM0IsTUFBWixDQUFtQixVQUFDOEIsSUFBRCxFQUFPQyxJQUFQLEVBQWdCO0FBQ2hEbEcsSUFBQUEsTUFBTSxDQUFDQyxJQUFQLENBQVlpRyxJQUFaLEVBQWtCM0QsT0FBbEIsQ0FBMEIsVUFBQWlDLEdBQUcsRUFBSTtBQUMvQixVQUFJLENBQUN5QixJQUFJLENBQUM3RixRQUFMLENBQWNvRSxHQUFkLENBQUwsRUFBeUI7QUFDdkJ5QixRQUFBQSxJQUFJLENBQUNqQixJQUFMLENBQVVSLEdBQVY7QUFDRDtBQUNGLEtBSkQ7QUFLQSxXQUFPeUIsSUFBUDtBQUNELEdBUGMsRUFPWixFQVBZLENBQWYsQ0F4QnNDLENBaUN0Qzs7QUFDQUgsRUFBQUEsV0FBVyxDQUFDdkQsT0FBWixDQUFvQixVQUFBL0IsQ0FBQyxFQUFJO0FBQ3ZCc0IsSUFBQUEsTUFBTSxDQUFDUyxPQUFQLENBQWUsVUFBQUYsQ0FBQyxFQUFJO0FBQ2xCLFVBQUksRUFBRUEsQ0FBQyxJQUFJN0IsQ0FBUCxDQUFKLEVBQWU7QUFDYkEsUUFBQUEsQ0FBQyxDQUFDNkIsQ0FBRCxDQUFELEdBQU8sSUFBUDtBQUNBN0IsUUFBQUEsQ0FBQyxDQUFDd0YsUUFBRixDQUFXeEMsVUFBWCxDQUFzQm5CLENBQXRCLElBQTJCLElBQTNCO0FBQ0Q7QUFDRixLQUxEO0FBTUQsR0FQRDtBQVNBLFNBQU9rRCxnQkFBZ0IsQ0FBQ08sV0FBRCxDQUF2QjtBQUNEO0FBRUQ7Ozs7Ozs7O0FBTU8sU0FBU0ssU0FBVCxDQUFtQjFDLElBQW5CLEVBQXlCM0IsTUFBekIsRUFBaUM7QUFDdEMsTUFBTXNFLE9BQU8sR0FBR3RFLE1BQU0sQ0FBQ2dCLEdBQVAsQ0FBVyxVQUFBVCxDQUFDO0FBQUEsV0FBSUEsQ0FBQyxDQUFDQyxJQUFOO0FBQUEsR0FBWixDQUFoQjtBQUNBLE1BQU0rRCxhQUFhLEdBQUcsQ0FBQ0QsT0FBRCxDQUF0QixDQUZzQyxDQUl0Qzs7QUFDQTNDLEVBQUFBLElBQUksQ0FBQ2xCLE9BQUwsQ0FBYSxVQUFBZ0IsR0FBRyxFQUFJO0FBQ2xCOEMsSUFBQUEsYUFBYSxDQUFDckIsSUFBZCxDQUFtQnpCLEdBQUcsQ0FBQ1QsR0FBSixDQUFRLFVBQUN0QyxDQUFELEVBQUl3QyxDQUFKO0FBQUEsYUFBVSxnQ0FBZ0J4QyxDQUFoQixFQUFtQnNCLE1BQU0sQ0FBQ2tCLENBQUQsQ0FBTixDQUFVN0MsSUFBN0IsQ0FBVjtBQUFBLEtBQVIsQ0FBbkI7QUFDRCxHQUZEO0FBSUEsU0FBTywwQkFBY2tHLGFBQWQsQ0FBUDtBQUNEO0FBRUQ7Ozs7Ozs7OztBQU9PLFNBQVNDLGlCQUFULENBQTJCN0MsSUFBM0IsRUFBaUM7QUFDdEMsTUFBSSxDQUFDLDBCQUFjQSxJQUFkLENBQUwsRUFBMEI7QUFDeEIsNEJBQU8saURBQVA7QUFDQSxXQUFPLElBQVA7QUFDRCxHQUhELE1BR08sSUFBSSxDQUFDcEMsS0FBSyxDQUFDQyxPQUFOLENBQWNtQyxJQUFJLENBQUMzQixNQUFuQixDQUFMLEVBQWlDO0FBQ3RDLDRCQUFPLCtEQUFQO0FBQ0EsV0FBTyxJQUFQO0FBQ0QsR0FITSxNQUdBLElBQUksQ0FBQ1QsS0FBSyxDQUFDQyxPQUFOLENBQWNtQyxJQUFJLENBQUMvQixJQUFuQixDQUFMLEVBQStCO0FBQ3BDLDRCQUFPLDZEQUFQO0FBQ0EsV0FBTyxJQUFQO0FBQ0Q7O0FBVnFDLE1BWS9CSSxNQVorQixHQVlmMkIsSUFaZSxDQVkvQjNCLE1BWitCO0FBQUEsTUFZdkJKLElBWnVCLEdBWWYrQixJQVplLENBWXZCL0IsSUFadUIsRUFjdEM7O0FBQ0EsTUFBTTZFLFFBQVEsR0FBR3pFLE1BQU0sQ0FBQzBFLEtBQVAsQ0FBYSxVQUFDbkUsQ0FBRCxFQUFJVyxDQUFKLEVBQVU7QUFDdEMsUUFBSSxDQUFDLDBCQUFjWCxDQUFkLENBQUwsRUFBdUI7QUFDckIsaUhBQWlFQSxDQUFqRTtBQUNBUCxNQUFBQSxNQUFNLENBQUNrQixDQUFELENBQU4sR0FBWSxFQUFaO0FBQ0Q7O0FBRUQsUUFBSSxDQUFDWCxDQUFDLENBQUNDLElBQVAsRUFBYTtBQUNYLDhFQUFnRG1FLElBQUksQ0FBQ0MsU0FBTCxDQUFlckUsQ0FBZixDQUFoRCxHQURXLENBRVg7O0FBQ0FQLE1BQUFBLE1BQU0sQ0FBQ2tCLENBQUQsQ0FBTixDQUFVVixJQUFWLG9CQUEyQlUsQ0FBM0I7QUFDRDs7QUFFRCxRQUFJLENBQUMxQyxpQ0FBZ0IrQixDQUFDLENBQUNsQyxJQUFsQixDQUFMLEVBQThCO0FBQzVCLDJEQUE2QmtDLENBQUMsQ0FBQ2xDLElBQS9CO0FBQ0EsYUFBTyxLQUFQO0FBQ0Q7O0FBRUQsUUFBSSxDQUFDMkIsTUFBTSxDQUFDMEUsS0FBUCxDQUFhLFVBQUEzRixLQUFLO0FBQUEsYUFBSUEsS0FBSyxDQUFDOEQsWUFBVjtBQUFBLEtBQWxCLENBQUwsRUFBZ0Q7QUFDOUMsOEJBQU8sNEJBQVA7QUFDQSxhQUFPLEtBQVA7QUFDRCxLQXBCcUMsQ0FzQnRDOzs7QUFDQSxRQUFJdEMsQ0FBQyxDQUFDbEMsSUFBRixLQUFXRyxpQ0FBZ0JNLFNBQS9CLEVBQTBDO0FBQ3hDLFVBQU1nQixNQUFNLEdBQUcrRSx1QkFBdUIsQ0FBQ2pGLElBQUQsRUFBT3NCLENBQVAsRUFBVSxFQUFWLENBQXZCLENBQXFDRixHQUFyQyxDQUF5QyxVQUFBUSxDQUFDO0FBQUEsZUFBSztBQUFDc0QsVUFBQUEsRUFBRSxFQUFFdEQsQ0FBQyxDQUFDTixDQUFEO0FBQU4sU0FBTDtBQUFBLE9BQTFDLENBQWY7O0FBQ0EsVUFBTTZELFlBQVksR0FBR2pELHVCQUFTQyxjQUFULENBQXdCakMsTUFBeEIsRUFBZ0MsQ0FBaEMsQ0FBckI7O0FBQ0EsYUFBT2lGLFlBQVksQ0FBQ0MsUUFBYixLQUEwQixNQUExQixJQUFvQ0QsWUFBWSxDQUFDL0YsTUFBYixLQUF3QnVCLENBQUMsQ0FBQ3ZCLE1BQXJFO0FBQ0Q7O0FBRUQsV0FBTyxJQUFQO0FBQ0QsR0E5QmdCLENBQWpCOztBQWdDQSxNQUFJeUYsUUFBSixFQUFjO0FBQ1osV0FBTztBQUFDN0UsTUFBQUEsSUFBSSxFQUFKQSxJQUFEO0FBQU9JLE1BQUFBLE1BQU0sRUFBTkE7QUFBUCxLQUFQO0FBQ0QsR0FqRHFDLENBbUR0QztBQUNBOzs7QUFDQSxNQUFNMEQsVUFBVSxHQUFHM0QsdUJBQXVCLENBQUM7QUFDekNDLElBQUFBLE1BQU0sRUFBRUEsTUFBTSxDQUFDZ0IsR0FBUCxDQUFXLFVBQUFULENBQUM7QUFBQSxhQUFJQSxDQUFDLENBQUNDLElBQU47QUFBQSxLQUFaLENBRGlDO0FBRXpDUCxJQUFBQSxPQUFPLEVBQUVMO0FBRmdDLEdBQUQsQ0FBMUM7QUFJQSxNQUFNZ0MsVUFBVSxHQUFHNUIsTUFBTSxDQUFDZ0IsR0FBUCxDQUFXLFVBQUFULENBQUM7QUFBQSxXQUFJQSxDQUFDLENBQUNDLElBQU47QUFBQSxHQUFaLENBQW5CO0FBQ0EsTUFBTXlFLElBQUksR0FBRy9FLGlCQUFpQixDQUFDd0QsVUFBRCxFQUFhOUIsVUFBYixDQUE5QjtBQUNBLE1BQU1zRCxhQUFhLEdBQUdsRixNQUFNLENBQUNnQixHQUFQLENBQVcsVUFBQ1QsQ0FBRCxFQUFJVyxDQUFKO0FBQUEsNkJBQzVCWCxDQUQ0QjtBQUUvQmxDLE1BQUFBLElBQUksRUFBRTRHLElBQUksQ0FBQy9ELENBQUQsQ0FBSixDQUFRN0MsSUFGaUI7QUFHL0JXLE1BQUFBLE1BQU0sRUFBRWlHLElBQUksQ0FBQy9ELENBQUQsQ0FBSixDQUFRbEMsTUFIZTtBQUkvQjZELE1BQUFBLFlBQVksRUFBRW9DLElBQUksQ0FBQy9ELENBQUQsQ0FBSixDQUFRMkI7QUFKUztBQUFBLEdBQVgsQ0FBdEI7QUFPQSxTQUFPO0FBQUM3QyxJQUFBQSxNQUFNLEVBQUVrRixhQUFUO0FBQXdCdEYsSUFBQUEsSUFBSSxFQUFKQTtBQUF4QixHQUFQO0FBQ0Q7O0FBRUQsU0FBU2lGLHVCQUFULENBQWlDakYsSUFBakMsRUFBdUNxQixRQUF2QyxFQUFpREosS0FBakQsRUFBd0Q7QUFDdEQsTUFBTWYsTUFBTSxHQUFHLEVBQWY7QUFDQSxNQUFJb0IsQ0FBQyxHQUFHLENBQVI7O0FBQ0EsU0FBT3BCLE1BQU0sQ0FBQ0wsTUFBUCxHQUFnQm9CLEtBQWhCLElBQXlCSyxDQUFDLEdBQUd0QixJQUFJLENBQUNILE1BQXpDLEVBQWlEO0FBQy9DLFFBQUksbUNBQW1CRyxJQUFJLENBQUNzQixDQUFELENBQUosQ0FBUUQsUUFBUixDQUFuQixDQUFKLEVBQTJDO0FBQ3pDbkIsTUFBQUEsTUFBTSxDQUFDb0QsSUFBUCxDQUFZdEQsSUFBSSxDQUFDc0IsQ0FBRCxDQUFoQjtBQUNEOztBQUNEQSxJQUFBQSxDQUFDO0FBQ0Y7O0FBQ0QsU0FBT3BCLE1BQVA7QUFDRDtBQUNEOzs7Ozs7Ozs7Ozs7Ozs7O0FBY08sU0FBU3FGLG1CQUFULENBQTZCOUYsT0FBN0IsRUFBc0M7QUFDM0MsU0FBT0EsT0FBTyxHQUFHK0Ysb0JBQWVDLElBQWYsQ0FBb0JoRyxPQUFPLENBQUNpRyxRQUE1QixFQUFzQ2pHLE9BQU8sQ0FBQ2tHLE1BQTlDLENBQUgsR0FBMkQsSUFBekU7QUFDRDtBQUVEOzs7Ozs7QUFJTyxTQUFTQyxzQkFBVCxDQUFnQ25HLE9BQWhDLEVBQXlDO0FBQzlDLE1BQUksQ0FBQ0EsT0FBTCxFQUFjO0FBQ1osV0FBTyxJQUFQO0FBQ0Q7O0FBRUQsTUFBTW9HLE9BQU8sR0FBR0wsb0JBQWVNLGNBQWYsQ0FBOEIsb0JBQVFyRyxPQUFSLENBQTlCLENBQWhCOztBQUNBLFNBQU9FLEtBQUssQ0FBQ0MsT0FBTixDQUFjSCxPQUFkLElBQXlCb0csT0FBekIsR0FBbUNBLE9BQU8sQ0FBQyxDQUFELENBQWpEO0FBQ0Q7O0FBRU0sSUFBTUUsZ0JBQWdCLGdGQUMxQkMsaUNBQWdCbkUsR0FEVSxFQUNKZ0MsZ0JBREksdURBRTFCbUMsaUNBQWdCdkMsT0FGVSxFQUVBTSxjQUZBLHVEQUcxQmlDLGlDQUFnQkMsR0FIVSxFQUdKekcsY0FISSx1REFJMUJ3RyxpQ0FBZ0JFLFFBSlUsRUFJQ04sc0JBSkQscUJBQXRCOztBQU9BLElBQU1PLFVBQVUsR0FBRztBQUN4QnBDLEVBQUFBLGNBQWMsRUFBZEEsY0FEd0I7QUFFeEJ2RSxFQUFBQSxjQUFjLEVBQWRBLGNBRndCO0FBR3hCcUUsRUFBQUEsZ0JBQWdCLEVBQWhCQSxnQkFId0I7QUFJeEIwQixFQUFBQSxtQkFBbUIsRUFBbkJBLG1CQUp3QjtBQUt4QkssRUFBQUEsc0JBQXNCLEVBQXRCQSxzQkFMd0I7QUFNeEI1QyxFQUFBQSx1QkFBdUIsRUFBdkJBLHVCQU53QjtBQU94QjFDLEVBQUFBLGlCQUFpQixFQUFqQkEsaUJBUHdCO0FBUXhCUSxFQUFBQSx1QkFBdUIsRUFBdkJBLHVCQVJ3QjtBQVN4QjJELEVBQUFBLFNBQVMsRUFBVEE7QUFUd0IsQ0FBbkIiLCJzb3VyY2VzQ29udGVudCI6WyIvLyBDb3B5cmlnaHQgKGMpIDIwMjAgVWJlciBUZWNobm9sb2dpZXMsIEluYy5cbi8vXG4vLyBQZXJtaXNzaW9uIGlzIGhlcmVieSBncmFudGVkLCBmcmVlIG9mIGNoYXJnZSwgdG8gYW55IHBlcnNvbiBvYnRhaW5pbmcgYSBjb3B5XG4vLyBvZiB0aGlzIHNvZnR3YXJlIGFuZCBhc3NvY2lhdGVkIGRvY3VtZW50YXRpb24gZmlsZXMgKHRoZSBcIlNvZnR3YXJlXCIpLCB0byBkZWFsXG4vLyBpbiB0aGUgU29mdHdhcmUgd2l0aG91dCByZXN0cmljdGlvbiwgaW5jbHVkaW5nIHdpdGhvdXQgbGltaXRhdGlvbiB0aGUgcmlnaHRzXG4vLyB0byB1c2UsIGNvcHksIG1vZGlmeSwgbWVyZ2UsIHB1Ymxpc2gsIGRpc3RyaWJ1dGUsIHN1YmxpY2Vuc2UsIGFuZC9vciBzZWxsXG4vLyBjb3BpZXMgb2YgdGhlIFNvZnR3YXJlLCBhbmQgdG8gcGVybWl0IHBlcnNvbnMgdG8gd2hvbSB0aGUgU29mdHdhcmUgaXNcbi8vIGZ1cm5pc2hlZCB0byBkbyBzbywgc3ViamVjdCB0byB0aGUgZm9sbG93aW5nIGNvbmRpdGlvbnM6XG4vL1xuLy8gVGhlIGFib3ZlIGNvcHlyaWdodCBub3RpY2UgYW5kIHRoaXMgcGVybWlzc2lvbiBub3RpY2Ugc2hhbGwgYmUgaW5jbHVkZWQgaW5cbi8vIGFsbCBjb3BpZXMgb3Igc3Vic3RhbnRpYWwgcG9ydGlvbnMgb2YgdGhlIFNvZnR3YXJlLlxuLy9cbi8vIFRIRSBTT0ZUV0FSRSBJUyBQUk9WSURFRCBcIkFTIElTXCIsIFdJVEhPVVQgV0FSUkFOVFkgT0YgQU5ZIEtJTkQsIEVYUFJFU1MgT1Jcbi8vIElNUExJRUQsIElOQ0xVRElORyBCVVQgTk9UIExJTUlURUQgVE8gVEhFIFdBUlJBTlRJRVMgT0YgTUVSQ0hBTlRBQklMSVRZLFxuLy8gRklUTkVTUyBGT1IgQSBQQVJUSUNVTEFSIFBVUlBPU0UgQU5EIE5PTklORlJJTkdFTUVOVC4gSU4gTk8gRVZFTlQgU0hBTEwgVEhFXG4vLyBBVVRIT1JTIE9SIENPUFlSSUdIVCBIT0xERVJTIEJFIExJQUJMRSBGT1IgQU5ZIENMQUlNLCBEQU1BR0VTIE9SIE9USEVSXG4vLyBMSUFCSUxJVFksIFdIRVRIRVIgSU4gQU4gQUNUSU9OIE9GIENPTlRSQUNULCBUT1JUIE9SIE9USEVSV0lTRSwgQVJJU0lORyBGUk9NLFxuLy8gT1VUIE9GIE9SIElOIENPTk5FQ1RJT04gV0lUSCBUSEUgU09GVFdBUkUgT1IgVEhFIFVTRSBPUiBPVEhFUiBERUFMSU5HUyBJTlxuLy8gVEhFIFNPRlRXQVJFLlxuXG5pbXBvcnQge2NzdlBhcnNlUm93cywgY3N2Rm9ybWF0Um93c30gZnJvbSAnZDMtZHN2JztcbmltcG9ydCB7cmFuZ2V9IGZyb20gJ2QzLWFycmF5JztcbmltcG9ydCB7Y29uc29sZSBhcyBnbG9iYWxDb25zb2xlfSBmcm9tICdnbG9iYWwvd2luZG93JztcbmltcG9ydCBhc3NlcnQgZnJvbSAnYXNzZXJ0JztcbmltcG9ydCB7QW5hbHl6ZXIsIERBVEFfVFlQRVMgYXMgQW5hbHl6ZXJEQVRBX1RZUEVTfSBmcm9tICd0eXBlLWFuYWx5emVyJztcbmltcG9ydCBub3JtYWxpemUgZnJvbSAnQG1hcGJveC9nZW9qc29uLW5vcm1hbGl6ZSc7XG5pbXBvcnQge0FMTF9GSUVMRF9UWVBFUywgREFUQVNFVF9GT1JNQVRTfSBmcm9tICdjb25zdGFudHMvZGVmYXVsdC1zZXR0aW5ncyc7XG5pbXBvcnQge25vdE51bGxvclVuZGVmaW5lZCwgcGFyc2VGaWVsZFZhbHVlLCBnZXRTYW1wbGVEYXRhfSBmcm9tICd1dGlscy9kYXRhLXV0aWxzJztcbmltcG9ydCBLZXBsZXJHbFNjaGVtYSBmcm9tICdzY2hlbWFzJztcbmltcG9ydCB7R1VJREVTX0ZJTEVfRk9STUFUfSBmcm9tICdjb25zdGFudHMvdXNlci1ndWlkZXMnO1xuaW1wb3J0IHtpc1BsYWluT2JqZWN0LCB0b0FycmF5fSBmcm9tICd1dGlscy91dGlscyc7XG5cbmV4cG9ydCBjb25zdCBBQ0NFUFRFRF9BTkFMWVpFUl9UWVBFUyA9IFtcbiAgQW5hbHl6ZXJEQVRBX1RZUEVTLkRBVEUsXG4gIEFuYWx5emVyREFUQV9UWVBFUy5USU1FLFxuICBBbmFseXplckRBVEFfVFlQRVMuREFURVRJTUUsXG4gIEFuYWx5emVyREFUQV9UWVBFUy5OVU1CRVIsXG4gIEFuYWx5emVyREFUQV9UWVBFUy5JTlQsXG4gIEFuYWx5emVyREFUQV9UWVBFUy5GTE9BVCxcbiAgQW5hbHl6ZXJEQVRBX1RZUEVTLkJPT0xFQU4sXG4gIEFuYWx5emVyREFUQV9UWVBFUy5TVFJJTkcsXG4gIEFuYWx5emVyREFUQV9UWVBFUy5HRU9NRVRSWSxcbiAgQW5hbHl6ZXJEQVRBX1RZUEVTLkdFT01FVFJZX0ZST01fU1RSSU5HLFxuICBBbmFseXplckRBVEFfVFlQRVMuUEFJUl9HRU9NRVRSWV9GUk9NX1NUUklORyxcbiAgQW5hbHl6ZXJEQVRBX1RZUEVTLlpJUENPREUsXG4gIEFuYWx5emVyREFUQV9UWVBFUy5BUlJBWSxcbiAgQW5hbHl6ZXJEQVRBX1RZUEVTLk9CSkVDVFxuXTtcblxuLy8gaWYgYW55IG9mIHRoZXNlIHZhbHVlIG9jY3VycyBpbiBjc3YsIHBhcnNlIGl0IHRvIG51bGw7XG5jb25zdCBDU1ZfTlVMTFMgPSBbJycsICdudWxsJywgJ05VTEwnLCAnTnVsbCcsICdOYU4nLCAnL04nXTtcblxuY29uc3QgSUdOT1JFX0RBVEFfVFlQRVMgPSBPYmplY3Qua2V5cyhBbmFseXplckRBVEFfVFlQRVMpLmZpbHRlcihcbiAgdHlwZSA9PiAhQUNDRVBURURfQU5BTFlaRVJfVFlQRVMuaW5jbHVkZXModHlwZSlcbik7XG5cbmV4cG9ydCBjb25zdCBQQVJTRV9GSUVMRF9WQUxVRV9GUk9NX1NUUklORyA9IHtcbiAgW0FMTF9GSUVMRF9UWVBFUy5ib29sZWFuXToge1xuICAgIHZhbGlkOiBkID0+IHR5cGVvZiBkID09PSAnYm9vbGVhbicsXG4gICAgcGFyc2U6IGQgPT4gZCA9PT0gJ3RydWUnIHx8IGQgPT09ICdUcnVlJyB8fCBkID09PSAnMSdcbiAgfSxcbiAgW0FMTF9GSUVMRF9UWVBFUy5pbnRlZ2VyXToge1xuICAgIHZhbGlkOiBkID0+IHBhcnNlSW50KGQsIDEwKSA9PT0gZCxcbiAgICBwYXJzZTogZCA9PiBwYXJzZUludChkLCAxMClcbiAgfSxcbiAgW0FMTF9GSUVMRF9UWVBFUy50aW1lc3RhbXBdOiB7XG4gICAgdmFsaWQ6IChkLCBmaWVsZCkgPT5cbiAgICAgIFsneCcsICdYJ10uaW5jbHVkZXMoZmllbGQuZm9ybWF0KSA/IHR5cGVvZiBkID09PSAnbnVtYmVyJyA6IHR5cGVvZiBkID09PSAnc3RyaW5nJyxcbiAgICBwYXJzZTogKGQsIGZpZWxkKSA9PiAoWyd4JywgJ1gnXS5pbmNsdWRlcyhmaWVsZC5mb3JtYXQpID8gTnVtYmVyKGQpIDogZClcbiAgfSxcbiAgW0FMTF9GSUVMRF9UWVBFUy5yZWFsXToge1xuICAgIHZhbGlkOiBkID0+IHBhcnNlRmxvYXQoZCkgPT09IGQsXG4gICAgcGFyc2U6IHBhcnNlRmxvYXRcbiAgfVxufTtcblxuLyoqXG4gKiBQcm9jZXNzIGNzdiBkYXRhLCBvdXRwdXQgYSBkYXRhIG9iamVjdCB3aXRoIGB7ZmllbGRzOiBbXSwgcm93czogW119YC5cbiAqIFRoZSBkYXRhIG9iamVjdCBjYW4gYmUgd3JhcHBlZCBpbiBhIGBkYXRhc2V0YCBhbmQgcGFzcyB0byBbYGFkZERhdGFUb01hcGBdKC4uL2FjdGlvbnMvYWN0aW9ucy5tZCNhZGRkYXRhdG9tYXApXG4gKiBAcGFyYW0ge3N0cmluZ30gcmF3RGF0YSByYXcgY3N2IHN0cmluZ1xuICogQHJldHVybnMge09iamVjdH0gZGF0YSBvYmplY3QgYHtmaWVsZHM6IFtdLCByb3dzOiBbXX1gXG4gKiBAcHVibGljXG4gKiBAZXhhbXBsZVxuICogaW1wb3J0IHtwcm9jZXNzQ3N2RGF0YX0gZnJvbSAna2VwbGVyLmdsL3Byb2Nlc3NvcnMnO1xuICpcbiAqIGNvbnN0IHRlc3REYXRhID0gYGdwc19kYXRhLnV0Y190aW1lc3RhbXAsZ3BzX2RhdGEubGF0LGdwc19kYXRhLmxuZyxncHNfZGF0YS50eXBlcyxlcG9jaCxoYXNfcmVzdWx0LGlkLHRpbWUsYmVnaW50cmlwX3RzX3V0YyxiZWdpbnRyaXBfdHNfbG9jY