UNPKG

kepler.gl.geoiq

Version:

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

653 lines 70 kB
"use strict";

var _interopRequireDefault = require("@babel/runtime/helpers/interopRequireDefault");

Object.defineProperty(exports, "__esModule", {
  value: true
});
exports.mergeAnimationConfig = mergeAnimationConfig;
exports.mergeFilters = mergeFilters;
exports.mergeInteractionTooltipConfig = mergeInteractionTooltipConfig;
exports.mergeInteractions = mergeInteractions;
exports.mergeLayerBlending = mergeLayerBlending;
exports.mergeLayers = mergeLayers;
exports.mergeSplitMaps = mergeSplitMaps;
exports.mergeWidgets = mergeWidgets;
exports.validateLayerWithData = validateLayerWithData;
exports.validateSavedLayerColumns = validateSavedLayerColumns;
exports.validateSavedTextLabel = validateSavedTextLabel;
exports.validateSavedVisualChannels = validateSavedVisualChannels;
exports.validateWidgetAndConfig = validateWidgetAndConfig;

var _slicedToArray2 = _interopRequireDefault(require("@babel/runtime/helpers/slicedToArray"));

var _objectWithoutProperties2 = _interopRequireDefault(require("@babel/runtime/helpers/objectWithoutProperties"));

var _defineProperty2 = _interopRequireDefault(require("@babel/runtime/helpers/defineProperty"));

var _toConsumableArray2 = _interopRequireDefault(require("@babel/runtime/helpers/toConsumableArray"));

var _lodash = _interopRequireDefault(require("lodash.uniq"));

var _lodash2 = _interopRequireDefault(require("lodash.pick"));

var _lodash3 = _interopRequireDefault(require("lodash.isequal"));

var _lodash4 = _interopRequireDefault(require("lodash.flattendeep"));

var _filterUtils = require("../utils/filter-utils");

var _splitMapUtils = require("../utils/split-map-utils");

var _defaultSettings = require("../constants/default-settings");

var _excluded = ["enabled"];

function ownKeys(e, r) { var t = Object.keys(e); if (Object.getOwnPropertySymbols) { var o = Object.getOwnPropertySymbols(e); r && (o = o.filter(function (r) { return Object.getOwnPropertyDescriptor(e, r).enumerable; })), t.push.apply(t, o); } return t; }

function _objectSpread(e) { for (var r = 1; r < arguments.length; r++) { var t = null != arguments[r] ? arguments[r] : {}; r % 2 ? ownKeys(Object(t), !0).forEach(function (r) { (0, _defineProperty2["default"])(e, r, t[r]); }) : Object.getOwnPropertyDescriptors ? Object.defineProperties(e, Object.getOwnPropertyDescriptors(t)) : ownKeys(Object(t)).forEach(function (r) { Object.defineProperty(e, r, Object.getOwnPropertyDescriptor(t, r)); }); } return e; }

/**
 * Merge loaded widgets with current state, if no widget are loaded
 * save it for later
 *
 * @param {*} state
 * @param {*} widgetsToMerge
 * @return {onject} updatedState
 */
function mergeWidgets(state, widgetsToMerge) {
  var mergedWidget = [];
  var unmerged = [];
  var datasets = state.datasets;

  if (!Array.isArray(widgetsToMerge) || !widgetsToMerge.length) {
    return state;
  } // console.log(state);


  widgetsToMerge.forEach(function (widget) {
    if (datasets[widget.config.dataId]) {
      // datasets are already loaded
      var validateWidget = validateWidgetAndConfig(datasets[widget.config.dataId], widget, state.widgetClasses, state);

      if (validateWidget) {
        mergedWidget.push(validateWidget);
      }
    } else {
      // datasets not yet loaded
      unmerged.push(widget);
    }
  }); // console.log(mergedWidget);

  var widgets = [].concat((0, _toConsumableArray2["default"])(state.widgets), mergedWidget);
  var newWidgetOrder = mergedWidget.map(function (_, i) {
    return state.widgets.length + i;
  }); // put new layers in front of current layers

  var widgetOrder = [].concat((0, _toConsumableArray2["default"])(newWidgetOrder), (0, _toConsumableArray2["default"])(state.widgetOrder)); // console.log('mergeWidgets', widgets);

  return _objectSpread(_objectSpread({}, state), {}, {
    widgets: widgets,
    widgetOrder: widgetOrder,
    widgetToBeMerged: unmerged
  });
}
/**
 * Merge loaded filters with current state, if no fields or data are loaded
 * save it for later
 *
 * @param {Object} state
 * @param {Array<Object>} filtersToMerge
 * @return {Object} updatedState
 */


function mergeFilters(state, filtersToMerge) {
  var merged = [];
  var unmerged = [];
  var datasets = state.datasets;

  if (!Array.isArray(filtersToMerge) || !filtersToMerge.length) {
    return state;
  } // merge filters


  filtersToMerge.forEach(function (filter) {
    // we can only look for datasets define in the filter dataId
    var datasetIds = Array.isArray(filter.dataId) ? filter.dataId : [filter.dataId]; // we can merge a filter only if all datasets supposed to be filtered are already loaded

    if (datasetIds.every(function (d) {
      return datasets[d];
    })) {
      // all datasetIds in filter must be present the state datasets
      var _datasetIds$reduce2 = datasetIds.reduce(function (acc, d) {
        var dataset = datasets[d];
        var layers = state.layers.filter(function (l) {
          return l.config.dataId === dataset.id;
        });
        var updatedFilter = (0, _filterUtils.validateFilterWithData)(dataset, filter, layers);

        if (updatedFilter) {
          return _objectSpread(_objectSpread({}, acc), {}, {
            filter: acc.filter ? _objectSpread(_objectSpread({}, acc.filter), (0, _filterUtils.mergeFilterProps)(acc, updatedFilter)) : updatedFilter,
            applytoDatasets: [].concat((0, _toConsumableArray2["default"])(acc.applytoDatasets), [d])
          });
        }

        return acc;
      }, {
        filter: null,
        applytoDatasets: []
      }),
          validatedFilter = _datasetIds$reduce2.filter,
          applytoDatasets = _datasetIds$reduce2.applytoDatasets;

      if (validatedFilter && (0, _lodash3["default"])(datasetIds, applytoDatasets)) {
        merged.push(validatedFilter);
      }
    } else {
      unmerged.push(filter);
    }
  }); // filter data

  var updatedFilters = [].concat((0, _toConsumableArray2["default"])(state.filters || []), merged); // flatten all filter dataIds

  var datasetsToFilter = (0, _lodash["default"])((0, _lodash4["default"])(merged.map(function (f) {
    return f.dataId;
  })));
  var updatedDatasets = (0, _filterUtils.applyFiltersToDatasets)(datasetsToFilter, datasets, updatedFilters, state.layers);
  var features = updatedFilters.reduce(function (acc, f) {
    return f.type === _filterUtils.FILTER_TYPES.polygon ? [].concat((0, _toConsumableArray2["default"])(acc), [f.value]) : acc;
  }, []);
  return _objectSpread(_objectSpread({}, state), {}, {
    filters: updatedFilters,
    datasets: updatedDatasets,
    filterToBeMerged: unmerged,
    editor: _objectSpread(_objectSpread({}, state.editor), {}, {
      features: [].concat((0, _toConsumableArray2["default"])((state.editor || {}).features), (0, _toConsumableArray2["default"])(features))
    })
  });
}
/**
 * Merge layers from de-serialized state, if no fields or data are loaded
 * save it for later
 *
 * @param {Object} state
 * @param {Array<Object>} layersToMerge
 * @return {Object} state
 */


function mergeLayers(state, layersToMerge) {
  var mergedLayer = [];
  var unmerged = [];
  var datasets = state.datasets;

  if (!Array.isArray(layersToMerge) || !layersToMerge.length) {
    return state;
  }

  layersToMerge.forEach(function (layer) {
    if (datasets[layer.config.dataId]) {
      // datasets are already loaded
      var validateLayer = validateLayerWithData(datasets[layer.config.dataId], layer, state.layerClasses);

      if (validateLayer) {
        mergedLayer.push(validateLayer);
      }
    } else {
      // datasets not yet loaded
      unmerged.push(layer);
    }
  });
  var layers = [].concat((0, _toConsumableArray2["default"])(state.layers), mergedLayer);
  var newLayerOrder = mergedLayer.map(function (_, i) {
    return state.layers.length + i;
  }); // put new layers in front of current layers

  var layerOrder = [].concat((0, _toConsumableArray2["default"])(newLayerOrder), (0, _toConsumableArray2["default"])(state.layerOrder));
  return _objectSpread(_objectSpread({}, state), {}, {
    layers: layers,
    layerOrder: layerOrder,
    layerToBeMerged: unmerged
  });
}
/**
 * Merge interactions with saved config
 *
 * @param {Object} state
 * @param {Object} interactionToBeMerged
 * @return {Object} mergedState
 */


function mergeInteractions(state, interactionToBeMerged) {
  var merged = {};
  var unmerged = {};

  if (interactionToBeMerged) {
    Object.keys(interactionToBeMerged).forEach(function (key) {
      if (!state.interactionConfig[key]) {
        return;
      }

      var _ref = interactionToBeMerged[key] || {},
          enabled = _ref.enabled,
          configSaved = (0, _objectWithoutProperties2["default"])(_ref, _excluded);

      var configToMerge = configSaved;

      if (key === 'tooltip') {
        var _mergeInteractionTool2 = mergeInteractionTooltipConfig(state, configSaved),
            mergedTooltip = _mergeInteractionTool2.mergedTooltip,
            unmergedTooltip = _mergeInteractionTool2.unmergedTooltip; // merge new dataset tooltips with original dataset tooltips


        configToMerge = {
          fieldsToShow: _objectSpread(_objectSpread({}, state.interactionConfig[key].config.fieldsToShow), mergedTooltip)
        };

        if (Object.keys(unmergedTooltip).length) {
          unmerged.tooltip = {
            fieldsToShow: unmergedTooltip,
            enabled: enabled
          };
        }
      }

      merged[key] = _objectSpread(_objectSpread({}, state.interactionConfig[key]), {}, {
        enabled: enabled,
        config: (0, _lodash2["default"])(_objectSpread(_objectSpread({}, state.interactionConfig[key].config), configToMerge), Object.keys(state.interactionConfig[key].config))
      });
    });
  }

  return _objectSpread(_objectSpread({}, state), {}, {
    interactionConfig: _objectSpread(_objectSpread({}, state.interactionConfig), merged),
    interactionToBeMerged: unmerged
  });
}
/**
 * Merge splitMaps config with current visStete.
 * 1. if current map is split, but splitMap DOESNOT contain maps
 *    : don't merge anything
 * 2. if current map is NOT split, but splitMaps contain maps
 *    : add to splitMaps, and add current layers to splitMaps
 */


function mergeSplitMaps(state) {
  var splitMaps = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : [];
  var merged = (0, _toConsumableArray2["default"])(state.splitMaps);
  var unmerged = [];
  splitMaps.forEach(function (sm, i) {
    Object.entries(sm.layers).forEach(function (_ref2) {
      var _ref3 = (0, _slicedToArray2["default"])(_ref2, 2),
          id = _ref3[0],
          value = _ref3[1];

      // check if layer exists
      var pushTo = state.layers.find(function (l) {
        return l.id === id;
      }) ? merged : unmerged; // create map panel if current map is not split

      pushTo[i] = pushTo[i] || {
        layers: pushTo === merged ? (0, _splitMapUtils.getInitialMapLayersForSplitMap)(state.layers) : []
      };
      pushTo[i].layers = _objectSpread(_objectSpread({}, pushTo[i].layers), {}, (0, _defineProperty2["default"])({}, id, value));
    });
  });
  return _objectSpread(_objectSpread({}, state), {}, {
    splitMaps: merged,
    splitMapsToBeMerged: unmerged
  });
}
/**
 * Merge interactionConfig.tooltip with saved config,
 * validate fieldsToShow
 *
 * @param {string} state
 * @param {Object} tooltipConfig
 * @return {Object} - {mergedTooltip: {}, unmergedTooltip: {}}
 */


function mergeInteractionTooltipConfig(state) {
  var tooltipConfig = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : {};
  var unmergedTooltip = {};
  var mergedTooltip = {};

  if (!tooltipConfig.fieldsToShow || !Object.keys(tooltipConfig.fieldsToShow).length) {
    return {
      mergedTooltip: mergedTooltip,
      unmergedTooltip: unmergedTooltip
    };
  }

  var _loop = function _loop() {
    if (!state.datasets[dataId]) {
      // is not yet loaded
      unmergedTooltip[dataId] = tooltipConfig.fieldsToShow[dataId];
    } else {
      // if dataset is loaded
      var allFields = state.datasets[dataId].fields.map(function (d) {
        return d.name;
      });
      var foundFieldsToShow = tooltipConfig.fieldsToShow[dataId].filter(function (name) {
        return allFields.includes(name);
      });
      mergedTooltip[dataId] = foundFieldsToShow;
    }
  };

  for (var dataId in tooltipConfig.fieldsToShow) {
    _loop();
  }

  return {
    mergedTooltip: mergedTooltip,
    unmergedTooltip: unmergedTooltip
  };
}
/**
 * Merge layerBlending with saved
 *
 * @param {object} state
 * @param {string} layerBlending
 * @return {object} merged state
 */


function mergeLayerBlending(state, layerBlending) {
  if (layerBlending && _defaultSettings.LAYER_BLENDINGS[layerBlending]) {
    return _objectSpread(_objectSpread({}, state), {}, {
      layerBlending: layerBlending
    });
  }

  return state;
}
/**
 * Merge animation config
 * @param {Object} state
 * @param {Object} animation
 */


function mergeAnimationConfig(state, animation) {
  if (animation && animation.currentTime) {
    return _objectSpread(_objectSpread({}, state), {}, {
      animationConfig: _objectSpread(_objectSpread(_objectSpread({}, state.animationConfig), animation), {}, {
        domain: null
      })
    });
  }

  return state;
}
/**
 * Validate saved layer columns with new data,
 * update fieldIdx based on new fields
 *
 * @param {Array<Object>} fields
 * @param {Object} savedCols
 * @param {Object} emptyCols
 * @return {null | Object} - validated columns or null
 */


function validateSavedLayerColumns(fields, savedCols, emptyCols) {
  var colFound = {}; // find actual column fieldIdx, in case it has changed

  var allColFound = Object.keys(emptyCols).every(function (key) {
    var saved = savedCols[key];
    colFound[key] = _objectSpread({}, emptyCols[key]); // TODO: replace with new approach

    var fieldIdx = fields.findIndex(function (_ref4) {
      var name = _ref4.name;
      return name === saved;
    });

    if (fieldIdx > -1) {
      // update found columns
      colFound[key].fieldIdx = fieldIdx;
      colFound[key].value = saved;
      return true;
    } // if col is optional, allow null value


    return emptyCols[key].optional || false;
  });
  return allColFound && colFound;
}
/**
 * Validate saved text label config with new data
 * refer to vis-state-schema.js TextLabelSchemaV1
 *
 * @param {Array<Object>} fields
 * @param {Object} savedTextLabel
 * @return {Object} - validated textlabel
 */


function validateSavedTextLabel(fields, _ref5, savedTextLabel) {
  var _ref6 = (0, _slicedToArray2["default"])(_ref5, 1),
      layerTextLabel = _ref6[0];

  var savedTextLabels = Array.isArray(savedTextLabel) ? savedTextLabel : [savedTextLabel]; // validate field

  return savedTextLabels.map(function (textLabel) {
    var field = textLabel.field ? fields.find(function (fd) {
      return Object.keys(textLabel.field).every(function (key) {
        return textLabel.field[key] === fd[key];
      });
    }) : null;
    return Object.keys(layerTextLabel).reduce(function (accu, key) {
      return _objectSpread(_objectSpread({}, accu), {}, (0, _defineProperty2["default"])({}, key, key === 'field' ? field : textLabel[key] || layerTextLabel[key]));
    }, {});
  });
}
/**
 * Validate saved visual channels config with new data,
 * refer to vis-state-schema.js VisualChannelSchemaV1
 *
 * @param {Array<Object>} fields
 * @param {Object} visualChannels
 * @param {Object} savedLayer
 * @return {Object} - validated visual channel in config or {}
 */


function validateSavedVisualChannels(fields, visualChannels, savedLayer) {
  return Object.values(visualChannels).reduce(function (found, _ref7) {
    var field = _ref7.field,
        scale = _ref7.scale;
    var foundField;

    if (savedLayer.config[field]) {
      foundField = fields.find(function (fd) {
        return Object.keys(savedLayer.config[field]).every(function (key) {
          return savedLayer.config[field][key] === fd[key];
        });
      });
    }

    return _objectSpread(_objectSpread(_objectSpread({}, found), foundField ? (0, _defineProperty2["default"])({}, field, foundField) : {}), savedLayer.config[scale] ? (0, _defineProperty2["default"])({}, scale, savedLayer.config[scale]) : {});
  }, {});
}
/**
 * Validate saved layer config with new data,
 * update fieldIdx based on new fields
 *
 * @param {Array<Object>} fields
 * @param {string} dataId
 * @param {Object} savedLayer
 * @param {Object} layerClasses
 * @return {null | Object} - validated layer or null
 */


function validateLayerWithData(_ref10, savedLayer, layerClasses) {
  var fields = _ref10.fields,
      dataId = _ref10.id,
      isLargeCategory = _ref10.isLargeCategory;
  var type = savedLayer.type; // layer doesnt have a valid type

  if (!layerClasses.hasOwnProperty(type) || !savedLayer.config) {
    return null;
  } // for layers which are not in large category


  if ((type === 'backendpoint' || type === 'backendgeojson') && !isLargeCategory) {
    return null;
  }

  if (['backendPoint', 'backendGeojson'].indexOf(type) === -1 && isLargeCategory) {
    return null;
  }

  var newLayer = new layerClasses[type]({
    id: savedLayer.id,
    dataId: dataId,
    label: savedLayer.config.label,
    color: savedLayer.config.color,
    isVisible: savedLayer.config.isVisible
  });
  var columns;

  if (['backendPoint', 'backendGeojson', 'dynamic', 'geoHash'].findIndex(function (t) {
    return t === type;
  }) === -1) {
    // find column fieldIdx
    columns = validateSavedLayerColumns(fields, savedLayer.config.columns, newLayer.getLayerColumns());

    if (!columns) {
      return null;
    }
  } // visual channel field is saved to be {name, type}
  // find visual channel field by matching both name and type
  // refer to vis-state-schema.js VisualChannelSchemaV1


  var foundVisualChannelConfigs = validateSavedVisualChannels(fields, newLayer.visualChannels, savedLayer);
  var textLabel = savedLayer.config.textLabel && newLayer.config.textLabel ? validateSavedTextLabel(fields, newLayer.config.textLabel, savedLayer.config.textLabel) : newLayer.config.textLabel; // copy visConfig over to emptyLayer to make sure it has all the props

  var visConfig = newLayer.copyLayerConfig(newLayer.config.visConfig, savedLayer.config.visConfig || {}, {
    shallowCopy: ['colorRange', 'strokeColorRange']
  });
  columns ? newLayer.updateLayerConfig(_objectSpread({
    columns: columns,
    visConfig: visConfig,
    textLabel: textLabel
  }, foundVisualChannelConfigs)) : newLayer.updateLayerConfig(_objectSpread({
    visConfig: visConfig,
    textLabel: textLabel
  }, foundVisualChannelConfigs)); // if (type === 'boundary' || type === 'pincode') {
  // const {boundaryAggregation} = savedLayer.config;
  // console.log(boundaryAggregation);

  newLayer.updateLayerConfig({
    // boundaryAggregation,
    apiCallRequest: true,
    apiCallLoader: true
  });

  if (type === 'boundary' || type === 'pincode') {
    var boundaryAggregation = savedLayer.config.boundaryAggregation; // console.log(boundaryAggregation);

    newLayer.updateLayerConfig({
      boundaryAggregation: boundaryAggregation,
      apiCallRequest: true,
      apiCallLoader: true
    });
  } // }


  return newLayer;
}
/**
 * Validate saved layer config with new data,
 * update fieldIdx based on new fields
 *
 * @param {Object[]} fields
 * @param {String} dataId
 * @param {Object} savedWidget
 * @param {Object} widgetClasses
 * @return {null | Object} - validated layer or null
 */


function validateWidgetAndConfig(_ref11, savedWidget, widgetClasses, state) {
  var fields = _ref11.fields,
      dataId = _ref11.id;
  // console.log('saved widget inside validate widget and confg', savedWidget);
  var type = savedWidget.type; // layer doesnt have a valid type

  if (!widgetClasses.hasOwnProperty(type) || !savedWidget.config) {
    return null;
  }

  var newWidget = new widgetClasses[type]({
    id: savedWidget.id,
    dataId: dataId,
    color: savedWidget.config.color,
    isVisible: savedWidget.config.isVisible
  });
  var config = newWidget.copyWidgetConfig(newWidget.config, savedWidget.config || {}); // console.log('config before updating config', config);

  newWidget.updateWidgetConfig(config); // console.log('new widget before aggregation data calculation ', newWidget);

  if (state.layerData.length) {
    calculateAggregationData(newWidget, state);
  } // console.log(newWidget);


  return newWidget;
} // /**
//  * Validate saved filter config with new data,
//  * calculate domain and fieldIdx based new fields and data
//  *
//  * @param {Array<Object>} dataset.fields
//  * @param {Array<Object>} dataset.allData
//  * @param {Object} filter - filter to be validate
//  * @return {Object | null} - validated filter
//  */
// export function validateFilterWithData({ fields, allData }, filter) {
//   // match filter.name to field.name
//   const fieldIdx = fields.findIndex(({ name }) => name === filter.name);
//   if (fieldIdx < 0) {
//     // if can't find field with same name, discharge filter
//     return null;
//   }
//   const field = fields[fieldIdx];
//   const value = filter.value;
//   // return filter type, default value, fieldType and fieldDomain from field
//   const filterPropsFromField = getFilterProps(allData, field);
//   let matchedFilter = {
//     ...getDefaultFilter(filter.dataId),
//     ...filter,
//     ...filterPropsFromField,
//     freeze: true,
//     fieldIdx
//   };
//   const { yAxis } = matchedFilter;
//   if (yAxis) {
//     const matcheAxis = fields.find(
//       ({ name, type }) => name === yAxis.name && type === yAxis.type
//     );
//     matchedFilter = matcheAxis
//       ? {
//           ...matchedFilter,
//           yAxis: matcheAxis,
//           ...getFilterPlot({ ...matchedFilter, yAxis: matcheAxis }, allData)
//         }
//       : matchedFilter;
//   }
//   matchedFilter.value = adjustValueToFilterDomain(value, matchedFilter);
//   if (matchedFilter.value === null) {
//     // cannt adjust saved value to filter
//     return null;
//   }
//   return matchedFilter;
// }
//# sourceMappingURL=data:application/json;charset=utf-8;base64,eyJ2ZXJzaW9uIjozLCJzb3VyY2VzIjpbIi4uLy4uL3NyYy9yZWR1Y2Vycy92aXMtc3RhdGUtbWVyZ2VyLmpzIl0sIm5hbWVzIjpbIm1lcmdlV2lkZ2V0cyIsInN0YXRlIiwid2lkZ2V0c1RvTWVyZ2UiLCJtZXJnZWRXaWRnZXQiLCJ1bm1lcmdlZCIsImRhdGFzZXRzIiwiQXJyYXkiLCJpc0FycmF5IiwibGVuZ3RoIiwiZm9yRWFjaCIsIndpZGdldCIsImNvbmZpZyIsImRhdGFJZCIsInZhbGlkYXRlV2lkZ2V0IiwidmFsaWRhdGVXaWRnZXRBbmRDb25maWciLCJ3aWRnZXRDbGFzc2VzIiwicHVzaCIsIndpZGdldHMiLCJuZXdXaWRnZXRPcmRlciIsIm1hcCIsIl8iLCJpIiwid2lkZ2V0T3JkZXIiLCJ3aWRnZXRUb0JlTWVyZ2VkIiwibWVyZ2VGaWx0ZXJzIiwiZmlsdGVyc1RvTWVyZ2UiLCJtZXJnZWQiLCJmaWx0ZXIiLCJkYXRhc2V0SWRzIiwiZXZlcnkiLCJkIiwicmVkdWNlIiwiYWNjIiwiZGF0YXNldCIsImxheWVycyIsImwiLCJpZCIsInVwZGF0ZWRGaWx0ZXIiLCJhcHBseXRvRGF0YXNldHMiLCJ2YWxpZGF0ZWRGaWx0ZXIiLCJ1cGRhdGVkRmlsdGVycyIsImZpbHRlcnMiLCJkYXRhc2V0c1RvRmlsdGVyIiwiZiIsInVwZGF0ZWREYXRhc2V0cyIsImZlYXR1cmVzIiwidHlwZSIsIkZJTFRFUl9UWVBFUyIsInBvbHlnb24iLCJ2YWx1ZSIsImZpbHRlclRvQmVNZXJnZWQiLCJlZGl0b3IiLCJtZXJnZUxheWVycyIsImxheWVyc1RvTWVyZ2UiLCJtZXJnZWRMYXllciIsImxheWVyIiwidmFsaWRhdGVMYXllciIsInZhbGlkYXRlTGF5ZXJXaXRoRGF0YSIsImxheWVyQ2xhc3NlcyIsIm5ld0xheWVyT3JkZXIiLCJsYXllck9yZGVyIiwibGF5ZXJUb0JlTWVyZ2VkIiwibWVyZ2VJbnRlcmFjdGlvbnMiLCJpbnRlcmFjdGlvblRvQmVNZXJnZWQiLCJPYmplY3QiLCJrZXlzIiwia2V5IiwiaW50ZXJhY3Rpb25Db25maWciLCJlbmFibGVkIiwiY29uZmlnU2F2ZWQiLCJjb25maWdUb01lcmdlIiwibWVyZ2VJbnRlcmFjdGlvblRvb2x0aXBDb25maWciLCJtZXJnZWRUb29sdGlwIiwidW5tZXJnZWRUb29sdGlwIiwiZmllbGRzVG9TaG93IiwidG9vbHRpcCIsIm1lcmdlU3BsaXRNYXBzIiwic3BsaXRNYXBzIiwic20iLCJlbnRyaWVzIiwicHVzaFRvIiwiZmluZCIsInNwbGl0TWFwc1RvQmVNZXJnZWQiLCJ0b29sdGlwQ29uZmlnIiwiYWxsRmllbGRzIiwiZmllbGRzIiwibmFtZSIsImZvdW5kRmllbGRzVG9TaG93IiwiaW5jbHVkZXMiLCJtZXJnZUxheWVyQmxlbmRpbmciLCJsYXllckJsZW5kaW5nIiwiTEFZRVJfQkxFTkRJTkdTIiwibWVyZ2VBbmltYXRpb25Db25maWciLCJhbmltYXRpb24iLCJjdXJyZW50VGltZSIsImFuaW1hdGlvbkNvbmZpZyIsImRvbWFpbiIsInZhbGlkYXRlU2F2ZWRMYXllckNvbHVtbnMiLCJzYXZlZENvbHMiLCJlbXB0eUNvbHMiLCJjb2xGb3VuZCIsImFsbENvbEZvdW5kIiwic2F2ZWQiLCJmaWVsZElkeCIsImZpbmRJbmRleCIsIm9wdGlvbmFsIiwidmFsaWRhdGVTYXZlZFRleHRMYWJlbCIsInNhdmVkVGV4dExhYmVsIiwibGF5ZXJUZXh0TGFiZWwiLCJzYXZlZFRleHRMYWJlbHMiLCJ0ZXh0TGFiZWwiLCJmaWVsZCIsImZkIiwiYWNjdSIsInZhbGlkYXRlU2F2ZWRWaXN1YWxDaGFubmVscyIsInZpc3VhbENoYW5uZWxzIiwic2F2ZWRMYXllciIsInZhbHVlcyIsImZvdW5kIiwic2NhbGUiLCJmb3VuZEZpZWxkIiwiaXNMYXJnZUNhdGVnb3J5IiwiaGFzT3duUHJvcGVydHkiLCJpbmRleE9mIiwibmV3TGF5ZXIiLCJsYWJlbCIsImNvbG9yIiwiaXNWaXNpYmxlIiwiY29sdW1ucyIsInQiLCJnZXRMYXllckNvbHVtbnMiLCJmb3VuZFZpc3VhbENoYW5uZWxDb25maWdzIiwidmlzQ29uZmlnIiwiY29weUxheWVyQ29uZmlnIiwic2hhbGxvd0NvcHkiLCJ1cGRhdGVMYXllckNvbmZpZyIsImFwaUNhbGxSZXF1ZXN0IiwiYXBpQ2FsbExvYWRlciIsImJvdW5kYXJ5QWdncmVnYXRpb24iLCJzYXZlZFdpZGdldCIsIm5ld1dpZGdldCIsImNvcHlXaWRnZXRDb25maWciLCJ1cGRhdGVXaWRnZXRDb25maWciLCJsYXllckRhdGEiLCJjYWxjdWxhdGVBZ2dyZWdhdGlvbkRhdGEiXSwibWFwcGluZ3MiOiI7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7O0FBb0JBOztBQUNBOztBQUNBOztBQUNBOztBQUVBOztBQUtBOztBQUVBOzs7Ozs7OztBQUdBOzs7Ozs7OztBQVNPLFNBQVNBLFlBQVQsQ0FBc0JDLEtBQXRCLEVBQTZCQyxjQUE3QixFQUE2QztBQUNsRCxNQUFNQyxZQUFZLEdBQUcsRUFBckI7QUFDQSxNQUFNQyxRQUFRLEdBQUcsRUFBakI7QUFFQSxNQUFPQyxRQUFQLEdBQW1CSixLQUFuQixDQUFPSSxRQUFQOztBQUVBLE1BQUksQ0FBQ0MsS0FBSyxDQUFDQyxPQUFOLENBQWNMLGNBQWQsQ0FBRCxJQUFrQyxDQUFDQSxjQUFjLENBQUNNLE1BQXRELEVBQThEO0FBQzVELFdBQU9QLEtBQVA7QUFDRCxHQVJpRCxDQVVsRDs7O0FBRUFDLEVBQUFBLGNBQWMsQ0FBQ08sT0FBZixDQUF1QixVQUFBQyxNQUFNLEVBQUk7QUFDL0IsUUFBSUwsUUFBUSxDQUFDSyxNQUFNLENBQUNDLE1BQVAsQ0FBY0MsTUFBZixDQUFaLEVBQW9DO0FBQ2xDO0FBQ0EsVUFBTUMsY0FBYyxHQUFHQyx1QkFBdUIsQ0FDNUNULFFBQVEsQ0FBQ0ssTUFBTSxDQUFDQyxNQUFQLENBQWNDLE1BQWYsQ0FEb0MsRUFFNUNGLE1BRjRDLEVBRzVDVCxLQUFLLENBQUNjLGFBSHNDLEVBSTVDZCxLQUo0QyxDQUE5Qzs7QUFPQSxVQUFJWSxjQUFKLEVBQW9CO0FBQ2xCVixRQUFBQSxZQUFZLENBQUNhLElBQWIsQ0FB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QUVZLFdBQVcsQ0FBQ2hJLE1BQVosQ0FBbUJvSDtBQUpVLEdBQXhCLENBQWxCO0FBTUEsTUFBTXBILE1BQU0sR0FBR2lJLFNBQVMsQ0FBQ0MsZ0JBQVYsQ0FDYkQsU0FBUyxDQUFDakksTUFERyxFQUViZ0ksV0FBVyxDQUFDaEksTUFBWixJQUFzQixFQUZULENBQWYsQ0FkQSxDQWtCQTs7QUFDQWlJLEVBQUFBLFNBQVMsQ0FBQ0Usa0JBQVYsQ0FBNkJuSSxNQUE3QixFQW5CQSxDQXFCQTs7QUFFQSxNQUFJVixLQUFLLENBQUM4SSxTQUFOLENBQWdCdkksTUFBcEIsRUFBNEI7QUFDMUJ3SSxJQUFBQSx3QkFBd0IsQ0FBQ0osU0FBRCxFQUFZM0ksS0FBWixDQUF4QjtBQUNELEdBekJELENBMkJBOzs7QUFDQSxTQUFPMkksU0FBUDtBQUNELEMsQ0FFRDtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUVBO0FBQ0E7QUFFQTtBQUNBO0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUVBO0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFFQTtBQUNBIiwic291cmNlc0NvbnRlbnQiOlsiLy8gQ29weXJpZ2h0IChjKSAyMDIzIFViZXIgVGVjaG5vbG9naWVzLCBJbmMuXG4vL1xuLy8gUGVybWlzc2lvbiBpcyBoZXJlYnkgZ3JhbnRlZCwgZnJlZSBvZiBjaGFyZ2UsIHRvIGFueSBwZXJzb24gb2J0YWluaW5nIGEgY29weVxuLy8gb2YgdGhpcyBzb2Z0d2FyZSBhbmQgYXNzb2NpYXRlZCBkb2N1bWVudGF0aW9uIGZpbGVzICh0aGUgXCJTb2Z0d2FyZVwiKSwgdG8gZGVhbFxuLy8gaW4gdGhlIFNvZnR3YXJlIHdpdGhvdXQgcmVzdHJpY3Rpb24sIGluY2x1ZGluZyB3aXRob3V0IGxpbWl0YXRpb24gdGhlIHJpZ2h0c1xuLy8gdG8gdXNlLCBjb3B5LCBtb2RpZnksIG1lcmdlLCBwdWJsaXNoLCBkaXN0cmlidXRlLCBzdWJsaWNlbnNlLCBhbmQvb3Igc2VsbFxuLy8gY29waWVzIG9mIHRoZSBTb2Z0d2FyZSwgYW5kIHRvIHBlcm1pdCBwZXJzb25zIHRvIHdob20gdGhlIFNvZnR3YXJlIGlzXG4vLyBmdXJuaXNoZWQgdG8gZG8gc28sIHN1YmplY3QgdG8gdGhlIGZvbGxvd2luZyBjb25kaXRpb25zOlxuLy9cbi8vIFRoZSBhYm92ZSBjb3B5cmlnaHQgbm90aWNlIGFuZCB0aGlzIHBlcm1pc3Npb24gbm90aWNlIHNoYWxsIGJlIGluY2x1ZGVkIGluXG4vLyBhbGwgY29waWVzIG9yIHN1YnN0YW50aWFsIHBvcnRpb25zIG9mIHRoZSBTb2Z0d2FyZS5cbi8vXG4vLyBUSEUgU09GVFdBUkUgSVMgUFJPVklERUQgXCJBUyBJU1wiLCBXSVRIT1VUIFdBUlJBTlRZIE9GIEFOWSBLSU5ELCBFWFBSRVNTIE9SXG4vLyBJTVBMSUVELCBJTkNMVURJTkcgQlVUIE5PVCBMSU1JVEVEIFRPIFRIRSBXQVJSQU5USUVTIE9GIE1FUkNIQU5UQUJJTElUWSxcbi8vIEZJVE5FU1MgRk9SIEEgUEFSVElDVUxBUiBQVVJQT1NFIEFORCBOT05JTkZSSU5HRU1FTlQuIElOIE5PIEVWRU5UIFNIQUxMIFRIRVxuLy8gQVVUSE9SUyBPUiBDT1BZUklHSFQgSE9MREVSUyBCRSBMSUFCTEUgRk9SIEFOWSBDTEFJTSwgREFNQUdFUyBPUiBPVEhFUlxuLy8gTElBQklMSVRZLCBXSEVUSEVSIElOIEFOIEFDVElPTiBPRiBDT05UUkFDVCwgVE9SVCBPUiBPVEhFUldJU0UsIEFSSVNJTkcgRlJPTSxcbi8vIE9VVCBPRiBPUiBJTiBDT05ORUNUSU9OIFdJVEggVEhFIFNPRlRXQVJFIE9SIFRIRSBVU0UgT1IgT1RIRVIgREVBTElOR1MgSU5cbi8vIFRIRSBTT0ZUV0FSRS5cblxuaW1wb3J0IHVuaXEgZnJvbSAnbG9kYXNoLnVuaXEnO1xuaW1wb3J0IHBpY2sgZnJvbSAnbG9kYXNoLnBpY2snO1xuaW1wb3J0IGlzRXF1YWwgZnJvbSAnbG9kYXNoLmlzZXF1YWwnO1xuaW1wb3J0IGZsYXR0ZW5EZWVwIGZyb20gJ2xvZGFzaC5mbGF0dGVuZGVlcCc7XG5cbmltcG9ydCB7XG4gIGFwcGx5RmlsdGVyc1RvRGF0YXNldHMsXG4gIHZhbGlkYXRlRmlsdGVyV2l0aERhdGFcbn0gZnJvbSAndXRpbHMvZmlsdGVyLXV0aWxzJztcblxuaW1wb3J0IHtnZXRJbml0aWFsTWFwTGF5ZXJzRm9yU3BsaXRNYXB9IGZyb20gJ3V0aWxzL3NwbGl0LW1hcC11dGlscyc7XG5cbmltcG9ydCB7TEFZRVJfQkxFTkRJTkdTfSBmcm9tICdjb25zdGFudHMvZGVmYXVsdC1zZXR0aW5ncyc7XG5pbXBvcnQge21lcmdlRmlsdGVyUHJvcHMsIEZJTFRFUl9UWVBFU30gZnJvbSAnLi4vdXRpbHMvZmlsdGVyLXV0aWxzJztcblxuLyoqXG4gKiBNZXJnZSBsb2FkZWQgd2lkZ2V0cyB3aXRoIGN1cnJlbnQgc3RhdGUsIGlmIG5vIHdpZGdldCBhcmUgbG9hZGVkXG4gKiBzYXZlIGl0IGZvciBsYXRlclxuICpcbiAqIEBwYXJhbSB7Kn0gc3RhdGVcbiAqIEBwYXJhbSB7Kn0gd2lkZ2V0c1RvTWVyZ2VcbiAqIEByZXR1cm4ge29uamVjdH0gdXBkYXRlZFN0YXRlXG4gKi9cblxuZXhwb3J0IGZ1bmN0aW9uIG1lcmdlV2lkZ2V0cyhzdGF0ZSwgd2lkZ2V0c1RvTWVyZ2UpIHtcbiAgY29uc3QgbWVyZ2VkV2lkZ2V0ID0gW107XG4gIGNvbnN0IHVubWVyZ2VkID0gW107XG5cbiAgY29uc3Qge2RhdGFzZXRzfSA9IHN0YXRlO1xuXG4gIGlmICghQXJyYXkuaXNBcnJheSh3aWRnZXRzVG9NZXJnZSkgfHwgIXdpZGdldHNUb01lcmdlLmxlbmd0aCkge1xuICAgIHJldHVybiBzdGF0ZTtcbiAgfVxuXG4gIC8vIGNvbnNvbGUubG9nKHN0YXRlKTtcblxuICB3aWRnZXRzVG9NZXJnZS5mb3JFYWNoKHdpZGdldCA9PiB7XG4gICAgaWYgKGRhdGFzZXRzW3dpZGdldC5jb25maWcuZGF0YUlkXSkge1xuICAgICAgLy8gZGF0YXNldHMgYXJlIGFscmVhZHkgbG9hZGVkXG4gICAgICBjb25zdCB2YWxpZGF0ZVdpZGdldCA9IHZhbGlkYXRlV2lkZ2V0QW5kQ29uZmlnKFxuICAgICAgICBkYXRhc2V0c1t3aWRnZXQuY29uZmlnLmRhdGFJZF0sXG4gICAgICAgIHdpZGdldCxcbiAgICAgICAgc3RhdGUud2lkZ2V0Q2xhc3NlcyxcbiAgICAgICAgc3RhdGVcbiAgICAgICk7XG5cbiAgICAgIGlmICh2YWxpZGF0ZVdpZGdldCkge1xuICAgICAgICBtZXJnZWRXaWRnZXQucHVzaCh2YWxpZGF0ZVdpZGdldCk7XG4gICAgICB9XG4gICAgfSBlbHNlIHtcbiAgICAgIC8vIGRhdGFzZXRzIG5vdCB5ZXQgbG9hZGVkXG4gICAgICB1bm1lcmdlZC5wdXNoKHdpZGdldCk7XG4gICAgfVxuICB9KTtcbiAgLy8gY29uc29sZS5sb2cobWVyZ2VkV2lkZ2V0KTtcbiAgY29uc3Qgd2lkZ2V0cyA9IFsuLi5zdGF0ZS53aWRnZXRzLCAuLi5tZXJnZWRXaWRnZXRdO1xuICBjb25zdCBuZXdXaWRnZXRPcmRlciA9IG1lcmdlZFdpZGdldC5tYXAoKF8sIGkpID0+IHN0YXRlLndpZGdldHMubGVuZ3RoICsgaSk7XG5cbiAgLy8gcHV0IG5ldyBsYXllcnMgaW4gZnJvbnQgb2YgY3VycmVudCBsYXllcnNcbiAgY29uc3Qgd2lkZ2V0T3JkZXIgPSBbLi4ubmV3V2lkZ2V0T3JkZXIsIC4uLnN0YXRlLndpZGdldE9yZGVyXTtcbiAgLy8gY29uc29sZS5sb2coJ21lcmdlV2lkZ2V0cycsIHdpZGdldHMpO1xuICByZXR1cm4ge1xuICAgIC4uLnN0YXRlLFxuICAgIHdpZGdldHMsXG4gICAgd2lkZ2V0T3JkZXIsXG4gICAgd2lkZ2V0VG9CZU1lcmdlZDogdW5tZXJnZWRcbiAgfTtcbn1cblxuLyoqXG4gKiBNZXJnZSBsb2FkZWQgZmlsdGVycyB3aXRoIGN1cnJlbnQgc3RhdGUsIGlmIG5vIGZpZWxkcyBvciBkYXRhIGFyZSBsb2FkZWRcbiAqIHNhdmUgaXQgZm9yIGxhdGVyXG4gKlxuICogQHBhcmFtIHtPYmplY3R9IHN0YXRlXG4gKiBAcGFyYW0ge0FycmF5PE9iamVjdD59IGZpbHRlcnNUb01lcmdlXG4gKiBAcmV0dXJuIHtPYmplY3R9IHVwZGF0ZWRTdGF0ZVxuICovXG5leHBvcnQgZnVuY3Rpb24gbWVyZ2VGaWx0ZXJzKHN0YXRlLCBmaWx0ZXJzVG9NZXJnZSkge1xuICBjb25zdCBtZXJnZWQgPSBbXTtcbiAgY29uc3QgdW5tZXJnZWQgPSBbXTtcbiAgY29uc3Qge2RhdGFzZXRzfSA9IHN0YXRlO1xuXG4gIGlmICghQXJyYXkuaXNBcnJheShmaWx0ZXJzVG9NZXJnZSkgfHwgIWZpbHRlcnNUb01lcmdlLmxlbmd0aCkge1xuICAgIHJldHVybiBzdGF0ZTtcbiAgfVxuXG4gIC8vIG1lcmdlIGZpbHRlcnNcbiAgZmlsdGVyc1RvTWVyZ2UuZm9yRWFjaChmaWx0ZXIgPT4ge1xuICAgIC8vIHdlIGNhbiBvbmx5IGxvb2sgZm9yIGRhdGFzZXRzIGRlZmluZSBpbiB0aGUgZmlsdGVyIGRhdGFJZFxuICAgIGNvbnN0IGRhdGFzZXRJZHMgPSBBcnJheS5pc0FycmF5KGZpbHRlci5kYXRhSWQpXG4gICAgICA/IGZpbHRlci5kYXRhSWRcbiAgICAgIDogW2ZpbHRlci5kYXRhSWRdO1xuXG4gICAgLy8gd2UgY2FuIG1lcmdlIGEgZmlsdGVyIG9ubHkgaWYgYWxsIGRhdGFzZXRzIHN1cHBvc2VkIHRvIGJlIGZpbHRlcmVkIGFyZSBhbHJlYWR5IGxvYWRlZFxuICAgIGlmIChkYXRhc2V0SWRzLmV2ZXJ5KGQgPT4gZGF0YXNldHNbZF0pKSB7XG4gICAgICAvLyBhbGwgZGF0YXNldElkcyBpbiBmaWx0ZXIgbXVzdCBiZSBwcmVzZW50IHRoZSBzdGF0ZSBkYXRhc2V0c1xuICAgICAgY29uc3Qge2ZpbHRlcjogdmFsaWRhdGVkRmlsdGVyLCBhcHBseXRvRGF0YXNldHN9ID0gZGF0YXNldElkcy5yZWR1Y2UoXG4gICAgICAgIChhY2MsIGQpID0+IHtcbiAgICAgICAgICBjb25zdCBkYXRhc2V0ID0gZGF0YXNldHNbZF07XG4gICAgICAgICAgY29uc3QgbGF5ZXJzID0gc3RhdGUubGF5ZXJzLmZpbHRlcihcbiAgICAgICAgICAgIGwgPT4gbC5jb25maWcuZGF0YUlkID09PSBkYXRhc2V0LmlkXG4gICAgICAgICAgKTtcbiAgICAgICAgICBjb25zdCB1cGRhdGVkRmlsdGVyID0gdmFsaWRhdGVGaWx0ZXJXaXRoRGF0YShkYXRhc2V0LCBmaWx0ZXIsIGxheWVycyk7XG4gICAgICAgICAgaWYgKHVwZGF0ZWRGaWx0ZXIpIHtcbiAgICAgICAgICAgIHJldHVybiB7XG4gICAgICAgICAgICAgIC4uLmFjYyxcbiAgICAgICAgICAgICAgZmlsdGVyOiBhY2MuZmlsdGVyXG4gICAgICAgICAgICAgICAgPyB7XG4gICAgICAgICAgICAgICAgICAgIC4uLmFjYy5maWx0ZXIsXG4gICAgICAgICAgICAgICAgICAgIC4uLm1lcmdlRmlsdGVyUHJvcHMoYWNjLCB1cGRhdGVkRmlsdGVyKVxuICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgIDogdXBkYXRlZEZpbHRlcixcbiAgICAgICAgICAgICAgYXBwbHl0b0RhdGFzZXRzOiBbLi4uYWNjLmFwcGx5dG9EYXRhc2V0cywgZF1cbiAgICAgICAgICAgIH07XG4gICAgICAgICAgfVxuXG4gICAgICAgICAgcmV0dXJuIGFjYztcbiAgICAgICAgfSxcbiAgICAgICAge1xuICAgICAgICAgIGZpbHRlcjogbnVsbCxcbiAgICAgICAgICBhcHBseXRvRGF0YXNldHM6IFtdXG4gICAgICAgIH1cbiAgICAgICk7XG5cbiAgICAgIGlmICh2YWxpZGF0ZWRGaWx0ZXIgJiYgaXNFcXVhbChkYXRhc2V0SWRzLCBhcHBseXRvRGF0YXNldHMpKSB7XG4gICAgICAgIG1lcmdlZC5wdXNoKHZhbGlkYXRlZEZpbHRlcik7XG4gICAgICB9XG4gICAgfSBlbHNlIHtcbiAgICAgIHVubWVyZ2VkLnB1c2goZmlsdGVyKTtcbiAgICB9XG4gIH0pO1xuXG4gIC8vIGZpbHRlciBkYXRhXG4gIGNvbnN0IHVwZGF0ZWRGaWx0ZXJzID0gWy4uLihzdGF0ZS5maWx0ZXJzIHx8IFtdKSwgLi4ubWVyZ2VkXTtcblxuICAvLyBmbGF0dGVuIGFsbCBmaWx0ZXIgZGF0YUlkc1xuICBjb25zdCBkYXRhc2V0c1RvRmlsdGVyID0gdW5pcShmbGF0dGVuRGVlcChtZXJnZWQubWFwKGYgPT4gZi5kYXRhSWQpKSk7XG5cbiAgY29uc3QgdXBkYXRlZERhdGFzZXRzID0gYXBwbHlGaWx0ZXJzVG9EYXRhc2V0cyhcbiAgICBkYXRhc2V0c1RvRmlsdGVyLFxuICAgIGRhdGFzZXRzLFxuICAgIHVwZGF0ZWRGaWx0ZXJzLFxuICAgIHN0YXRlLmxheWVyc1xuICApO1xuXG4gIGNvbnN0IGZlYXR1cmVzID0gdXBkYXRlZEZpbHRlcnMucmVkdWNlKChhY2MsIGYpID0+IHtcbiAgICByZXR1cm4gZi50eXBlID09PSBGSUxURVJfVFlQRVMucG9seWdvbiA/IFsuLi5hY2MsIGYudmFsdWVdIDogYWNjO1xuICB9LCBbXSk7XG5cbiAgcmV0dXJuIHtcbiAgICAuLi5zdGF0ZSxcbiAgICBmaWx0ZXJzOiB1cGRhdGVkRmlsdGVycyxcbiAgICBkYXRhc2V0czogdXBkYXRlZERhdGFzZXRzLFxuICAgIGZpbHRlclRvQmVNZXJnZWQ6IHVubWVyZ2VkLFxuICAgIGVkaXRvcjoge1xuICAgICAgLi4uc3RhdGUuZWRpdG9yLFxuICAgICAgZmVhdHVyZXM6IFsuLi4oc3RhdGUuZWRpdG9yIHx8IHt9KS5mZWF0dXJlcywgLi4uZmVhdHVyZXNdXG4gICAgfVxuICB9O1xufVxuXG4vKipcbiAqIE1lcmdlIGxheWVycyBmcm9tIGRlLXNlcmlhbGl6ZWQgc3RhdGUsIGlmIG5vIGZpZWxkcyBvciBkYXRhIGFyZSBsb2FkZWRcbiAqIHNhdmUgaXQgZm9yIGxhdGVyXG4gKlxuICogQHBhcmFtIHtPYmplY3R9IHN0YXRlXG4gKiBAcGFyYW0ge0FycmF5PE9iamVjdD59IGxheWVyc1RvTWVyZ2VcbiAqIEByZXR1cm4ge09iamVjdH0gc3RhdGVcbiAqL1xuZXhwb3J0IGZ1bmN0aW9uIG1lcmdlTGF5ZXJzKHN0YXRlLCBsYXllcnNUb01lcmdlKSB7XG4gIGNvbnN0IG1lcmdlZExheWVyID0gW107XG4gIGNvbnN0IHVubWVyZ2VkID0gW107XG5cbiAgY29uc3Qge2RhdGFzZXRzfSA9IHN0YXRlO1xuXG4gIGlmICghQXJyYXkuaXNBcnJheShsYXllcnNUb01lcmdlKSB8fCAhbGF5ZXJzVG9NZXJnZS5sZW5ndGgpIHtcbiAgICByZXR1cm4gc3RhdGU7XG4gIH1cblxuICBsYXllcnNUb01lcmdlLmZvckVhY2gobGF5ZXIgPT4ge1xuICAgIGlmIChkYXRhc2V0c1tsYXllci5jb25maWcuZGF0YUlkXSkge1xuICAgICAgLy8gZGF0YXNldHMgYXJlIGFscmVhZHkgbG9hZGVkXG4gICAgICBjb25zdCB2YWxpZGF0ZUxheWVyID0gdmFsaWRhdGVMYXllcldpdGhEYXRhKFxuICAgICAgICBkYXRhc2V0c1tsYXllci5jb25maWcuZGF0YUlkXSxcbiAgICAgICAgbGF5ZXIsXG4gICAgICAgIHN0YXRlLmxheWVyQ2xhc3Nlc1xuICAgICAgKTtcblxuICAgICAgaWYgKHZhbGlkYXRlTGF5ZXIpIHtcbiAgICAgICAgbWVyZ2VkTGF5ZXIucHVzaCh2YWxpZGF0ZUxheWVyKTtcbiAgICAgIH1cbiAgICB9IGVsc2Uge1xuICAgICAgLy8gZGF0YXNldHMgbm90IHlldCBsb2FkZWRcbiAgICAgIHVubWVyZ2VkLnB1c2gobGF5ZXIpO1xuICAgIH1cbiAgfSk7XG5cbiAgY29uc3QgbGF5ZXJzID0gWy4uLnN0YXRlLmxheWVycywgLi4ubWVyZ2VkTGF5ZXJdO1xuICBjb25zdCBuZXdMYXllck9yZGVyID0gbWVyZ2VkTGF5ZXIubWFwKChfLCBpKSA9PiBzdGF0ZS5sYXllcnMubGVuZ3RoICsgaSk7XG5cbiAgLy8gcHV0IG5ldyBsYXllcnMgaW4gZnJvbnQgb2YgY3VycmVudCBsYXllcnNcbiAgY29uc3QgbGF5ZXJPcmRlciA9IFsuLi5uZXdMYXllck9yZGVyLCAuLi5zdGF0ZS5sYXllck9yZGVyXTtcblxuICByZXR1cm4ge1xuICAgIC4uLnN0YXRlLFxuICAgIGxheWVycyxcbiAgICBsYXllck9yZGVyLFxuICAgIGxheWVyVG9CZU1lcmdlZDogdW5tZXJnZWRcbiAgfTtcbn1cblxuLyoqXG4gKiBNZXJnZSBpbnRlcmFjdGlvbnMgd2l0aCBzYXZlZCBjb25maWdcbiAqXG4gKiBAcGFyYW0ge09iamVjdH0gc3RhdGVcbiAqIEBwYXJhbSB7T2JqZWN0fSBpbnRlcmFjdGlvblRvQmVNZXJnZWRcbiAqIEByZXR1cm4ge09iamVjdH0gbWVyZ2VkU3RhdGVcbiAqL1xuZXhwb3J0IGZ1bmN0aW9uIG1lcmdlSW50ZXJhY3Rpb25zKHN0YXRlLCBpbnRlcmFjdGlvblRvQmVNZXJnZWQpIHtcbiAgY29uc3QgbWVyZ2VkID0ge307XG4gIGNvbnN0IHVubWVyZ2VkID0ge307XG5cbiAgaWYgKGludGVyYWN0aW9uVG9CZU1lcmdlZCkge1xuICAgIE9iamVjdC5rZXlzKGludGVyYWN0aW9uVG9CZU1lcmdlZCkuZm9yRWFjaChrZXkgPT4ge1xuICAgICAgaWYgKCFzdGF0ZS5pbnRlcmFjdGlvbkNvbmZpZ1trZXldKSB7XG4gICAgICAgIHJldHVybjtcbiAgICAgIH1cblxuICAgICAgY29uc3Qge2VuYWJsZWQsIC4uLmNvbmZpZ1NhdmVkfSA9IGludGVyYWN0aW9uVG9CZU1lcmdlZFtrZXldIHx8IHt9O1xuICAgICAgbGV0IGNvbmZpZ1RvTWVyZ2UgPSBjb25maWdTYXZlZDtcblxuICAgICAgaWYgKGtleSA9PT0gJ3Rvb2x0aXAnKSB7XG4gICAgICAgIGNvbnN0IHttZXJnZWRUb29sdGlwLCB1bm1lcmdlZFRvb2x0aXB9ID0gbWVyZ2VJbnRlcmFjdGlvblRvb2x0aXBDb25maWcoXG4gICAgICAgICAgc3RhdGUsXG4gICAgICAgICAgY29uZmlnU2F2ZWRcbiAgICAgICAgKTtcblxuICAgICAgICAvLyBtZXJnZSBuZXcgZGF0YXNldCB0b29sdGlwcyB3aXRoIG9yaWdpbmFsIGRhdGFzZXQgdG9vbHRpcHNcbiAgICAgICAgY29uZmlnVG9NZXJnZSA9IHtcbiAgICAgICAgICBmaWVsZHNUb1Nob3c6IHtcbiAgICAgICAgICAgIC4uLnN0YXRlLmludGVyYWN0aW9uQ29uZmlnW2tleV0uY29uZmlnLmZpZWxkc1RvU2hvdyxcbiAgICAgICAgICAgIC4uLm1lcmdlZFRvb2x0aXBcbiAgICAgICAgICB9XG4gICAgICAgIH07XG5cbiAgICAgICAgaWYgKE9iamVjdC5rZXlzKHVubWVyZ2VkVG9vbHRpcCkubGVuZ3RoKSB7XG4gICAgICAgICAgdW5tZXJnZWQudG9vbHRpcCA9IHtmaWVsZHNUb1Nob3c6IHVubWVyZ2VkVG9vbHRpcCwgZW5hYmxlZH07XG4gICAgICAgIH1cbiAgICAgIH1cblxuICAgICAgbWVyZ2VkW2tleV0gPSB7XG4gICAgICAgIC4uLnN0YXRlLmludGVyYWN0aW9uQ29uZmlnW2tleV0sXG4gICAgICAgIGVuYWJsZWQsXG4gICAgICAgIGNvbmZpZzogcGljayhcbiAgICAgICAgICB7XG4gICAgICAgICAgICAuLi5zdGF0ZS5pbnRlcmFjdGlvbkNvbmZpZ1trZXldLmNvbmZpZyxcbiAgICAgICAgICAgIC4uLmNvbmZpZ1RvTWVyZ2VcbiAgICAgICAgICB9LFxuICAgICAgICAgIE9iamVjdC5rZXlzKHN0YXRlLmludGVyYWN0aW9uQ29uZmlnW2tleV0uY29uZmlnKVxuICAgICAgICApXG4gICAgICB9O1xuICAgIH0pO1xuICB9XG5cbiAgcmV0dXJuIHtcbiAgICAuLi5zdGF0ZSxcbiAgICBpbnRlcmFjdGlvbkNvbmZpZzoge1xuICAgICAgLi4uc3RhdGUuaW50ZXJhY3Rpb25Db25maWcsXG4gICAgICAuLi5tZXJnZWRcbiAgICB9LFxuICAgIGludGVyYWN0aW9uVG9CZU1lcmdlZDogdW5tZXJnZWRcbiAgfTtcbn1cblxuLyoqXG4gKiBNZXJnZSBzcGxpdE1hcHMgY29uZmlnIHdpdGggY3VycmVudCB2aXNTdGV0ZS5cbiAqIDEuIGlmIGN1cnJlbnQgbWFwIGlzIHNwbGl0LCBidXQgc3BsaXRNYXAgRE9FU05PVCBjb250YWluIG1hcHNcbiAqICAgIDogZG9uJ3QgbWVyZ2UgYW55dGhpbmdcbiAqIDIuIGlmIGN1cnJlbnQgbWFwIGlzIE5PVCBzcGxpdCwgYnV0IHNwbGl0TWFwcyBjb250YWluIG1hcHNcbiAqICAgIDogYWRkIHRvIHNwbGl0TWFwcywgYW5kIGFkZCBjdXJyZW50IGxheWVycyB0byBzcGxpdE1hcHNcbiAqL1xuZXhwb3J0IGZ1bmN0aW9uIG1lcmdlU3BsaXRNYXBzKHN0YXRlLCBzcGxpdE1hcHMgPSBbXSkge1xuICBjb25zdCBtZXJnZWQgPSBbLi4uc3RhdGUuc3BsaXRNYXBzXTtcbiAgY29uc3QgdW5tZXJnZWQgPSBbXTtcbiAgc3BsaXRNYXBzLmZvckVhY2goKHNtLCBpKSA9PiB7XG4gICAgT2JqZWN0LmVudHJpZXMoc20ubGF5ZXJzKS5mb3JFYWNoKChbaWQsIHZhbHVlXSkgPT4ge1xuICAgICAgLy8gY2hlY2sgaWYgbGF5ZXIgZXhpc3RzXG4gICAgICBjb25zdCBwdXNoVG8gPSBzdGF0ZS5sYXllcnMuZmluZChsID0+IGwuaWQgPT09IGlkKSA/IG1lcmdlZCA6IHVubWVyZ2VkO1xuXG4gICAgICAvLyBjcmVhdGUgbWFwIHBhbmVsIGlmIGN1cnJlbnQgbWFwIGlzIG5vdCBzcGxpdFxuICAgICAgcHVzaFRvW2ldID0gcHVzaFRvW2ldIHx8IHtcbiAgICAgICAgbGF5ZXJzOlxuICAgICAgICAgIHB1c2hUbyA9PT0gbWVyZ2VkID8gZ2V0SW5pdGlhbE1hcExheWVyc0ZvclNwbGl0TWFwKHN0YXRlLmxheWVycykgOiBbXVxuICAgICAgfTtcbiAgICAgIHB1c2hUb1tpXS5sYXllcnMgPSB7XG4gICAgICAgIC4uLnB1c2hUb1tpXS5sYXllcnMsXG4gICAgICAgIFtpZF06IHZhbHVlXG4gICAgICB9O1xuICAgIH0pO1xuICB9KTtcblxuICByZXR1cm4ge1xuICAgIC4uLnN0YXRlLFxuICAgIHNwbGl0TWFwczogbWVyZ2VkLFxuICAgIHNwbGl0TWFwc1RvQmVNZXJnZWQ6IHVubWVyZ2VkXG4gIH07XG59XG5cbi8qKlxuICogTWVyZ2UgaW50ZXJhY3Rpb25Db25maWcudG9vbHRpcCB3aXRoIHNhdmVkIGNvbmZpZyxcbiAqIHZhbGlkYXRlIGZpZWxkc1RvU2hvd1xuICpcbiAqIEBwYXJhbSB7c3RyaW5nfSBzdGF0ZVxuICogQHBhcmFtIHtPYmplY3R9IHRvb2x0aXBDb25maWdcbiAqIEByZXR1cm4ge09iamVjdH0gLSB7bWVyZ2VkVG9vbHRpcDoge30sIHVubWVyZ2VkVG9vbHRpcDoge319XG4gKi9cbmV4cG9ydCBmdW5jdGlvbiBtZXJnZUludGVyYWN0aW9uVG9vbHRpcENvbmZpZyhzdGF0ZSwgdG9vbHRpcENvbmZpZyA9IHt9KSB7XG4gIGNvbnN0IHVubWVyZ2VkVG9vbHRpcCA9IHt9O1xuICBjb25zdCBtZXJnZWRUb29sdGlwID0ge307XG5cbiAgaWYgKFxuICAgICF0b29sdGlwQ29uZmlnLmZpZWxkc1RvU2hvdyB8fFxuICAgICFPYmplY3Qua2V5cyh0b29sdGlwQ29uZmlnLmZpZWxkc1RvU2hvdykubGVuZ3RoXG4gICkge1xuICAgIHJldHVybiB7bWVyZ2VkVG9vbHRpcCwgdW5tZXJnZWRUb29sdGlwfTtcbiAgfVxuXG4gIGZvciAoY29uc3QgZGF0YUlkIGluIHRvb2x0aXBDb25maWcuZmllbGRzVG9TaG93KSB7XG4gICAgaWYgKCFzdGF0ZS5kYXRhc2V0c1tkYXRhSWRdKSB7XG4gICAgICAvLyBpcyBub3QgeWV0IGxvYWRlZFxuICAgICAgdW5tZXJnZWRUb29sdGlwW2RhdGFJZF0gPSB0b29sdGlwQ29uZmlnLmZpZWxkc1RvU2hvd1tkYXRhSWRdO1xuICAgIH0gZWxzZSB7XG4gICAgICAvLyBpZiBkYXRhc2V0IGlzIGxvYWRlZFxuICAgICAgY29uc3QgYWxsRmllbGRzID0gc3RhdGUuZGF0YXNldHNbZGF0YUlkXS5maWVsZHMubWFwKGQgPT4gZC5uYW1lKTtcbiAgICAgIGNvbnN0IGZvdW5kRmllbGRzVG9TaG93ID0gdG9vbHRpcENvbmZpZy5maWVsZHNUb1Nob3dbXG4gICAgICAgIGRhdGFJZFxuICAgICAgXS5maWx0ZXIobmFtZSA9PiBhbGxGaWVsZHMuaW5jbHVkZXMobmFtZSkpO1xuXG4gICAgICBtZXJnZWRUb29sdGlwW2RhdGFJZF0gPSBmb3VuZEZpZWxkc1RvU2hvdztcbiAgICB9XG4gIH1cblxuICByZXR1cm4ge21lcmdlZFRvb2x0aXAsIHVubWVyZ2VkVG9vbHRpcH07XG59XG4vKipcbiAqIE1lcmdlIGxheWVyQmxlbmRpbmcgd2l0aCBzYXZlZFxuICpcbiAqIEBwYXJhbSB7b2JqZWN0fSBzdGF0ZVxuICogQHBhcmFtIHtzdHJpbmd9IGxheWVyQmxlbmRpbmdcbiAqIEByZXR1cm4ge29iamVjdH0gbWVyZ2VkIHN0YXRlXG4gKi9cbmV4cG9ydCBmdW5jdGlvbiBtZXJnZUxheWVyQmxlbmRpbmcoc3RhdGUsIGxheWVyQmxlbmRpbmcpIHtcbiAgaWYgKGxheWVyQmxlbmRpbmcgJiYgTEFZRVJfQkxFTkRJTkdTW2xheWVyQmxlbmRpbmddKSB7XG4gICAgcmV0dXJuIHtcbiAgICAgIC4uLnN0YXRlLFxuICAgICAgbGF5ZXJCbGVuZGluZ1xuICAgIH07XG4gIH1cblxuICByZXR1cm4gc3RhdGU7XG59XG5cbi8qKlxuICogTWVyZ2UgYW5pbWF0aW9uIGNvbmZpZ1xuICogQHBhcmFtIHtPYmplY3R9IHN0YXRlXG4gKiBAcGFyYW0ge09iamVjdH0gYW5pbWF0aW9uXG4gKi9cbmV4cG9ydCBmdW5jdGlvbiBtZXJnZUFuaW1hdGlvbkNvbmZpZyhzdGF0ZSwgYW5pbWF0aW9uKSB7XG4gIGlmIChhbmltYXRpb24gJiYgYW5pbWF0aW9uLmN1cnJlbnRUaW1lKSB7XG4gICAgcmV0dXJuIHtcbiAgICAgIC4uLnN0YXRlLFxuICAgICAgYW5pbWF0aW9uQ29uZmlnOiB7XG4gICAgICAgIC4uLnN0YXRlLmFuaW1hdGlvbkNvbmZpZyxcbiAgICAgICAgLi4uYW5pbWF0aW9uLFxuICAgICAgICBkb21haW46IG51bGxcbiAgICAgIH1cbiAgICB9O1xuICB9XG5cbiAgcmV0dXJuIHN0YXRlO1xufVxuXG4vKipcbiAqIFZhbGlkYXRlIHNhdmVkIGxheWVyIGNvbHVtbnMgd2l0aCBuZXcgZGF0YSxcbiAqIHVwZGF0ZSBmaWVsZElkeCBiYXNlZCBvbiBuZXcgZmllbGRzXG4gKlxuICogQHBhcmFtIHtBcnJheTxPYmplY3Q+fSBmaWVsZHNcbiAqIEBwYXJhbSB7T2JqZWN0fSBzYXZlZENvbHNcbiAqIEBwYXJhbSB7T2JqZWN0fSBlbXB0eUNvbHNcbiAqIEByZXR1cm4ge251bGwgfCBPYmplY3R9IC0gdmFsaWRhdGVkIGNvbHVtbnMgb3IgbnVsbFxuICovXG5cbmV4cG9ydCBmdW5jdGlvbiB2YWxpZGF0ZVNhdmVkTGF5ZXJDb2x1bW5zKGZpZWxkcywgc2F2ZWRDb2xzLCBlbXB0eUNvbHMpIHtcbiAgY29uc3QgY29sRm91bmQgPSB7fTtcbiAgLy8gZmluZCBhY3R1YWwgY29sdW1uIGZpZWxkSWR4LCBpbiBjYXNlIGl0IGhhcyBjaGFuZ2VkXG4gIGNvbnN0IGFsbENvbEZvdW5kID0gT2JqZWN0LmtleXMoZW1wdHlDb2xzKS5ldmVyeShrZXkgPT4ge1xuICAgIGNvbnN0IHNhdmVkID0gc2F2ZWRDb2xzW2tleV07XG4gICAgY29sRm91bmRba2V5XSA9IHsuLi5lbXB0eUNvbHNba2V5XX07XG5cbiAgICAvLyBUT0RPOiByZXBsYWNlIHdpdGggbmV3IGFwcHJvYWNoXG4gICAgY29uc3QgZmllbGRJZHggPSBmaWVsZHMuZmluZEluZGV4KCh7bmFtZX0pID0+IG5hbWUgPT09IHNhdmVkKTtcblxuICAgIGlmIChmaWVsZElkeCA+IC0xKSB7XG4gICAgICAvLyB1cGRhdGUgZm91bmQgY29sdW1uc1xuICAgICAgY29sRm91bmRba2V5XS5maWVsZElkeCA9IGZpZWxkSWR4O1xuICAgICAgY29sRm91bmRba2V5XS52YWx1ZSA9IHNhdmVkO1xuICAgICAgcmV0dXJuIHRydWU7XG4gICAgfVxuXG4gICAgLy8gaWYgY29sIGlzIG9wdGlvbmFsLCBhbGxvdyBudWxsIHZhbHVlXG4gICAgcmV0dXJuIGVtcHR5Q29sc1trZXldLm9wdGlvbmFsIHx8IGZhbHNlO1xuICB9KTtcblxuICByZXR1cm4gYWxsQ29sRm91bmQgJiYgY29sRm91bmQ7XG59XG5cbi8qKlxuICogVmFsaWRhdGUgc2F2ZWQgdGV4dCBsYWJlbCBjb25maWcgd2l0aCBuZXcgZGF0YVxuICogcmVmZXIgdG8gdmlzLXN0YXRlLXNjaGVtYS5qcyBUZXh0TGFiZWxTY2hlbWFWMVxuICpcbiAqIEBwYXJhbSB7QXJyYXk8T2JqZWN0Pn0gZmllbGRzXG4gKiBAcGFyYW0ge09iamVjdH0gc2F2ZWRUZXh0TGFiZWxcbiAqIEByZXR1cm4ge09iamVjdH0gLSB2YWxpZGF0ZWQgdGV4dGxhYmVsXG4gKi9cbmV4cG9ydCBmdW5jdGlvbiB2YWxpZGF0ZVNhdmVkVGV4dExhYmVsKFxuICBmaWVsZHMsXG4gIFtsYXllclRleHRMYWJlbF0sXG4gIHNhdmVkVGV4dExhYmVsXG4pIHtcbiAgY29uc3Qgc2F2ZWRUZXh0TGFiZWxzID0gQXJyYXkuaXNBcnJheShzYXZlZFRleHRMYWJlbClcbiAgICA/IHNhdmVkVGV4dExhYmVsXG4gICAgOiBbc2F2ZWRUZXh0TGFiZWxdO1xuXG4gIC8vIHZhbGlkYXRlIGZpZWxkXG4gIHJldHVybiBzYXZlZFRleHRMYWJlbHMubWFwKHRleHRMYWJlbCA9PiB7XG4gICAgY29uc3QgZmllbGQgPSB0ZXh0TGFiZWwuZmllbGRcbiAgICAgID8gZmllbGRzLmZpbmQoZmQgPT5cbiAgICAgICAgICBPYmplY3Qua2V5cyh0ZXh0TGFiZWwuZmllbGQpLmV2ZXJ5KFxuICAgICAgICAgICAga2V5ID0+IHRleHRMYWJlbC5maWVsZFtrZXldID09PSBmZFtrZXldXG4gICAgICAgICAgKVxuICAgICAgICApXG4gICAgICA6IG51bGw7XG5cbiAgICByZXR1cm4gT2JqZWN0LmtleXMobGF5ZXJUZXh0TGFiZWwpLnJlZHVjZShcbiAgICAgIChhY2N1LCBrZXkpID0+ICh7XG4gICAgICAgIC4uLmFjY3UsXG4gICAgICAgIFtrZXldOiBrZXkgPT09ICdmaWVsZCcgPyBmaWVsZCA6IHRleHRMYWJlbFtrZXldIHx8IGxheWVyVGV4dExhYmVsW2tleV1cbiAgICAgIH0pLFxuICAgICAge31cbiAgICApO1xuICB9KTtcbn1cblxuLyoqXG4gKiBWYWxpZGF0ZSBzYXZlZCB2aXN1YWwgY2hhbm5lbHMgY29uZmlnIHdpdGggbmV3IGRhdGEsXG4gKiByZWZlciB0byB2aXMtc3RhdGUtc2NoZW1hLmpzIFZpc3VhbENoYW5uZWxTY2hlbWFWMVxuICpcbiAqIEBwYXJhbSB7QXJyYXk8T2JqZWN0Pn0gZmllbGRzXG4gKiBAcGFyYW0ge09iamVjdH0gdmlzdWFsQ2hhbm5lbHNcbiAqIEBwYXJhbSB7T2JqZWN0fSBzYXZlZExheWVyXG4gKiBAcmV0dXJuIHtPYmplY3R9IC0gdmFsaWRhdGVkIHZpc3VhbCBjaGFubmVsIGluIGNvbmZpZyBvciB7fVxuICovXG5leHBvcnQgZnVuY3Rpb24gdmFsaWRhdGVTYXZlZFZpc3VhbENoYW5uZWxzKFxuICBmaWVsZHMsXG4gIHZpc3VhbENoYW5uZWxzLFxuICBzYXZlZExheWVyXG4pIHtcbiAgcmV0dXJuIE9iamVjdC52YWx1ZXModmlzdWFsQ2hhbm5lbHMpLnJlZHVjZSgoZm91bmQsIHtmaWVsZCwgc2NhbGV9KSA9PiB7XG4gICAgbGV0IGZvdW5kRmllbGQ7XG4gICAgaWYgKHNhdmVkTGF5ZXIuY29uZmlnW2ZpZWxkXSkge1xuICAgICAgZm91bmRGaWVsZCA9IGZpZWxkcy5maW5kKGZkID0+XG4gICAgICAgIE9iamVjdC5rZXlzKHNhdmVkTGF5ZXIuY29uZmlnW2ZpZWxkXSkuZXZlcnkoXG4gICAgICAgICAga2V5ID0+IHNhdmVkTGF5ZXIuY29uZmlnW2ZpZWxkXVtrZXldID09PSBmZFtrZXldXG4gICAgICAgIClcbiAgICAgICk7XG4gICAgfVxuXG4gICAgcmV0dXJuIHtcbiAgICAgIC4uLmZvdW5kLFxuICAgICAgLi4uKGZvdW5kRmllbGQgPyB7W2ZpZWxkXTogZm91bmRGaWVsZH0gOiB7fSksXG4gICAgICAuLi4oc2F2ZWRMYXllci5jb25maWdbc2NhbGVdID8ge1tzY2FsZV06IHNhdmVkTGF5ZXIuY29uZmlnW3NjYWxlXX0gOiB7fSlcbiAgICB9O1xuICB9LCB7fSk7XG59XG5cbi8qKlxuICogVmFsaWRhdGUgc2F2ZWQgbGF5ZXIgY29uZmlnIHdpdGggbmV3IGRhdGEsXG4gKiB1cGRhdGUgZmllbGRJZHggYmFzZWQgb24gbmV3IGZpZWxkc1xuICpcbiAqIEBwYXJhbSB7QXJyYXk8T2JqZWN0Pn0gZmllbGRzXG4gKiBAcGFyYW0ge3N0cmluZ30gZGF0YUlkXG4gKiBAcGFyYW0ge09iamVjdH0gc2F2ZWRMYXllclxuICogQHBhcmFtIHtPYmplY3R9IGxheWVyQ2xhc3Nlc1xuICogQHJldHVybiB7bnVsbCB8IE9iamVjdH0gLSB2YWxpZGF0ZWQgbGF5ZXIgb3IgbnVsbFxuICovXG5leHBvcnQgZnVuY3Rpb24gdmFsaWRhdGVMYXllcldpdGhEYXRhKFxuICB7ZmllbGRzLCBpZDogZGF0YUlkLCBpc0xhcmdlQ2F0ZWdvcnl9LFxuICBzYXZlZExheWVyLFxuICBsYXllckNsYXNzZXNcbikge1xuICBjb25zdCB7dHlwZX0gPSBzYXZlZExheWVyO1xuICAvLyBsYXllciBkb2VzbnQgaGF2ZSBhIHZhbGlkIHR5cGVcbiAgaWYgKCFsYXllckNsYXNzZXMuaGFzT3duUHJvcGVydHkodHlwZSkgfHwgIXNhdmVkTGF5ZXIuY29uZmlnKSB7XG4gICAgcmV0dXJuIG51bGw7XG4gIH1cblxuICAvLyBmb3IgbGF5ZXJzIHdoaWNoIGFyZSBub3QgaW4gbGFyZ2UgY2F0ZWdvcnlcbiAgaWYgKFxuICAgICh0eXBlID09PSAnYmFja2VuZHBvaW50JyB8fCB0eXBlID09PSAnYmFja2VuZGdlb2pzb24nKSAmJlxuICAgICFpc0xhcmdlQ2F0ZWdvcnlcbiAgKSB7XG4gICAgcmV0dXJuIG51bGw7XG4gIH1cblxuICBpZiAoXG4gICAgWydiYWNrZW5kUG9pbnQnLCAnYmFja2VuZEdlb2pzb24nXS5pbmRleE9mKHR5cGUpID09PSAtMSAmJlxuICAgIGlzTGFyZ2VDYXRlZ29yeVxuICApIHtcbiAgICByZXR1cm4gbnVsbDtcbiAgfVxuXG4gIGNvbnN0IG5ld0xheWVyID0gbmV3IGxheWVyQ2xhc3Nlc1t0eXBlXSh7XG4gICAgaWQ6IHNhdmVkTGF5ZXIuaWQsXG4gICAgZGF0YUlkLFxuICAgIGxhYmVsOiBzYXZlZExheWVyLmNvbmZpZy5sYWJlbCxcbiAgICBjb2xvcjogc2F2ZWRMYXllci5jb25maWcuY29sb3IsXG4gICAgaXNWaXNpYmxlOiBzYXZlZExheWVyLmNvbmZpZy5pc1Zpc2libGVcbiAgfSk7XG4gIGxldCBjb2x1bW5zO1xuICBpZiAoXG4gICAgWydiYWNrZW5kUG9pbnQnLCAnYmFja2VuZEdlb2pzb24nLCAnZHluYW1pYycsICdnZW9IYXNoJ10uZmluZEluZGV4KFxuICAgICAgdCA9PiB0ID09PSB0eXBlXG4gICAgKSA9PT0gLTFcbiAgKSB7XG4gICAgLy8gZmluZCBjb2x1bW4gZmllbGRJZHhcbiAgICBjb2x1bW5zID0gdmFsaWRhdGVTYXZlZExheWVyQ29sdW1ucyhcbiAgICAgIGZpZWxkcyxcbiAgICAgIHNhdmVkTGF5ZXIuY29uZmlnLmNvbHVtbnMsXG4gICAgICBuZXdMYXllci5nZXRMYXllckNvbHVtbnMoKVxuICAgICk7XG5cbiAgICBpZiAoIWNvbHVtbnMpIHtcbiAgICAgIHJldHVybiBudWxsO1xuICAgIH1cbiAgfVxuXG4gIC8vIHZpc3VhbCBjaGFubmVsIGZpZWxkIGlzIHNhdmVkIHRvIGJlIHtuYW1lLCB0eXBlfVxuICAvLyBmaW5kIHZpc3VhbCBjaGFubmVsIGZpZWxkIGJ5IG1hdGNoaW5nIGJvdGggbmFtZSBhbmQgdHlwZVxuICAvLyByZWZlciB0byB2aXMtc3RhdGUtc2NoZW1hLmpzIFZpc3VhbENoYW5uZWxTY2hlbWFWMVxuICBjb25zdCBmb3VuZFZpc3VhbENoYW5uZWxDb25maWdzID0gdmFsaWRhdGVTYXZlZFZpc3VhbENoYW5uZWxzKFxuICAgIGZpZWxkcyxcbiAgICBuZXdMYXllci52aXN1YWxDaGFubmVscyxcbiAgICBzYXZlZExheWVyXG4gICk7XG5cbiAgY29uc3QgdGV4dExhYmVsID1cbiAgICBzYXZlZExheWVyLmNvbmZpZy50ZXh0TGFiZWwgJiYgbmV3TGF5ZXIuY29uZmlnLnRleHRMYWJlbFxuICAgICAgPyB2YWxpZGF0ZVNhdmVkVGV4dExhYmVsKFxuICAgICAgICAgIGZpZWxkcyxcbiAgICAgICAgICBuZXdMYXllci5jb25maWcudGV4dExhYmVsLFxuICAgICAgICAgIHNhdmVkTGF5ZXIuY29uZmlnLnRleHRMYWJlbFxuICAgICAgICApXG4gICAgICA6IG5ld0xheWVyLmNvbmZpZy50ZXh0TGFiZWw7XG5cbiAgLy8gY29weSB2aXNDb25maWcgb3ZlciB0byBlbXB0eUxheWVyIHRvIG1ha2Ugc3VyZSBpdCBoYXMgYWxsIHRoZSBwcm9wc1xuICBjb25zdCB2aXNDb25maWcgPSBuZXdMYXllci5jb3B5TGF5ZXJDb25maWcoXG4gICAgbmV3TGF5ZXIuY29uZmlnLnZpc0NvbmZpZyxcbiAgICBzYXZlZExheWVyLmNvbmZpZy52aXNDb25maWcgfHwge30sXG4gICAge3NoYWxsb3dDb3B5OiBbJ2NvbG9yUmFuZ2UnLCAnc3Ryb2tlQ29sb3JSYW5nZSddfVxuICApO1xuICBjb2x1bW5zXG4gICAgPyBuZXdMYXllci51cGRhdGVMYXllckNvbmZpZyh7XG4gICAgICAgIGNvbHVtbnMsXG4gICAgICAgIHZpc0NvbmZpZyxcbiAgICAgICAgdGV4dExhYmVsLFxuICAgICAgICAuLi5mb3VuZFZpc3VhbENoYW5uZWxDb25maWdzXG4gICAgICB9KVxuICAgIDogbmV3TGF5ZXIudXBkYXRlTGF5ZXJDb25maWcoe1xuICAgICAgICB2aXNDb25maWcsXG4gICAgICAgIHRleHRMYWJlbCxcbiAgICAgICAgLi4uZm91bmRWaXN1YWxDaGFubmVsQ29uZmlnc1xuICAgICAgfSk7XG5cbiAgLy8gaWYgKHR5cGUgPT09ICdib3VuZGFyeScgfHwgdHlwZSA9PT0gJ3BpbmNvZGUnKSB7XG4gIC8vIGNvbnN0IHtib3VuZGFyeUFnZ3JlZ2F0aW9ufSA9IHNhdmVkTGF5ZXIuY29uZmlnO1xuICAvLyBjb25zb2xlLmxvZyhib3VuZGFyeUFnZ3JlZ2F0aW9uKTtcbiAgbmV3TGF5ZXIudXBkYXRlTGF5ZXJDb25maWcoe1xuICAgIC8vIGJvdW5kYXJ5QWdncmVnYXRpb24sXG4gICAgYXBpQ2FsbFJlcXVlc3Q6IHRydWUsXG4gICAgYXBpQ2FsbExvYWRlcjogdHJ1ZVxuICB9KTtcbiAgaWYgKHR5cGUgPT09ICdib3VuZGFyeScgfHwgdHlwZSA9PT0gJ3BpbmNvZGUnKSB7XG4gICAgY29uc3Qge2JvdW5kYXJ5QWdncmVnYXRpb259ID0gc2F2ZWRMYXllci5jb25maWc7XG4gICAgLy8gY29uc29sZS5sb2coYm91bmRhcnlBZ2dyZWdhdGlvbik7XG4gICAgbmV3TGF5ZXIudXBkYXRlTGF5ZXJDb25maWcoe1xuICAgICAgYm91bmRhcnlBZ2dyZWdhdGlvbixcbiAgICAgIGFwaUNhbGxSZXF1ZXN0OiB0cnVlLFxuICAgICAgYXBpQ2FsbExvYWRlcjogdHJ1ZVxuICAgIH0pO1xuICB9XG4gIC8vIH1cblxuICByZXR1cm4gbmV3TGF5ZXI7XG59XG5cbi8qKlxuICogVmFsaWRhdGUgc2F2ZWQgbGF5ZXIgY29uZmlnIHdpdGggbmV3IGRhdGEsXG4gKiB1cGRhdGUgZmllbGRJZHggYmFzZWQgb24gbmV3IGZpZWxkc1xuICpcbiAqIEBwYXJhbSB7T2JqZWN0W119IGZpZWxkc1xuICogQHBhcmFtIHtTdHJpbmd9IGRhdGFJZFxuICogQHBhcmFtIHtPYmplY3R9IHNhdmVkV2lkZ2V0XG4gKiBAcGFyYW0ge09iamVjdH0gd2lkZ2V0Q2xhc3Nlc1xuICogQHJldHVybiB7bnVsbCB8IE9iamVjdH0gLSB2YWxpZGF0ZWQgbGF5ZXIgb3IgbnVsbFxuICovXG5leHBvcnQgZnVuY3Rpb24gdmFsaWRhdGVXaWRnZXRBbmRDb25maWcoXG4gIHtmaWVsZHMsIGlkOiBkYXRhSWR9LFxuICBzYXZlZFdpZGdldCxcbiAgd2lkZ2V0Q2xhc3NlcyxcbiAgc3RhdGVcbikge1xuICAvLyBjb25zb2xlLmxvZygnc2F2ZWQgd2lkZ2V0IGluc2lkZSB2YWxpZGF0ZSB3aWRnZXQgYW5kIGNvbmZnJywgc2F2ZWRXaWRnZXQpO1xuICBjb25zdCB7dHlwZX0gPSBzYXZlZFdpZGdldDtcbiAgLy8gbGF5ZXIgZG9lc250IGhhdmUgYSB2YWxpZCB0eXBlXG4gIGlmICghd2lkZ2V0Q2xhc3Nlcy5oYXNPd25Qcm9wZXJ0eSh0eXBlKSB8fCAhc2F2ZWRXaWRnZXQuY29uZmlnKSB7XG4gICAgcmV0dXJuIG51bGw7XG4gIH1cblxuICBjb25zdCBuZXdXaWRnZXQgPSBuZXcgd2lkZ2V0Q2xhc3Nlc1t0eXBlXSh7XG4gICAgaWQ6IHNhdmVkV2lkZ2V0LmlkLFxuICAgIGRhdGFJZCxcbiAgICBjb2xvcjogc2F2ZWRXaWRnZXQuY29uZmlnLmNvbG9yLFxuICAgIGlzVmlzaWJsZTogc2F2ZWRXaWRnZXQuY29uZmlnLmlzVmlzaWJsZVxuICB9KTtcbiAgY29uc3QgY29uZmlnID0gbmV3V2lkZ2V0LmNvcHlXaWRnZXRDb25maWcoXG4gICAgbmV3V2lkZ2V0LmNvbmZpZyxcbiAgICBzYXZlZFdpZGdldC5jb25maWcgfHwge31cbiAgKTtcbiAgLy8gY29uc29sZS5sb2coJ2NvbmZpZyBiZWZvcmUgdXBkYXRpbmcgY29uZmlnJywgY29uZmlnKTtcbiAgbmV3V2lkZ2V0LnVwZGF0ZVdpZGdldENvbmZpZyhjb25maWcpO1xuXG4gIC8vIGNvbnNvbGUubG9nKCduZXcgd2lkZ2V0IGJlZm9yZSBhZ2dyZWdhdGlvbiBkYXRhIGNhbGN1bGF0aW9uICcsIG5ld1dpZGdldCk7XG5cbiAgaWYgKHN0YXRlLmxheWVyRGF0YS5sZW5ndGgpIHtcbiAgICBjYWxjdWxhdGVBZ2dyZWdhdGlvbkRhdGEobmV3V2lkZ2V0LCBzdGF0ZSk7XG4gIH1cblxuICAvLyBjb25zb2xlLmxvZyhuZXdXaWRnZXQpO1xuICByZXR1cm4gbmV3V2lkZ2V0O1xufVxuXG4vLyAvKipcbi8vICAqIFZhbGlkYXRlIHNhdmVkIGZpbHRlciBjb25maWcgd2l0aCBuZXcgZGF0YSxcbi8vICAqIGNhbGN1bGF0ZSBkb21haW4gYW5kIGZpZWxkSWR4IGJhc2VkIG5ldyBmaWVsZHMgYW5kIGRhdGFcbi8vICAqXG4vLyAgKiBAcGFyYW0ge0FycmF5PE9iamVjdD59IGRhdGFzZXQuZmllbGRzXG4vLyAgKiBAcGFyYW0ge0FycmF5PE9iamVjdD59IGRhdGFzZXQuYWxsRGF0YVxuLy8gICogQHBhcmFtIHtPYmplY3R9IGZpbHRlciAtIGZpbHRlciB0byBiZSB2YWxpZGF0ZVxuLy8gICogQHJldHVybiB7T2JqZWN0IHwgbnVsbH0gLSB2YWxpZGF0ZWQgZmlsdGVyXG4vLyAgKi9cbi8vIGV4cG9ydCBmdW5jdGlvbiB2YWxpZGF0ZUZpbHRlcldpdGhEYXRhKHsgZmllbGRzLCBhbGxEYXRhIH0sIGZpbHRlcikge1xuLy8gICAvLyBtYXRjaCBmaWx0ZXIubmFtZSB0byBmaWVsZC5uYW1lXG4vLyAgIGNvbnN0IGZpZWxkSWR4ID0gZmllbGRzLmZpbmRJbmRleCgoeyBuYW1lIH0pID0+IG5hbWUgPT09IGZpbHRlci5uYW1lKTtcblxuLy8gICBpZiAoZmllbGRJZHggPCAwKSB7XG4vLyAgICAgLy8gaWYgY2FuJ3QgZmluZCBmaWVsZCB3aXRoIHNhbWUgbmFtZSwgZGlzY2hhcmdlIGZpbHRlclxuLy8gICAgIHJldHVybiBudWxsO1xuLy8gICB9XG5cbi8vICAgY29uc3QgZmllbGQgPSBmaWVsZHNbZmllbGRJZHhdO1xuLy8gICBjb25zdCB2YWx1ZSA9IGZpbHRlci52YWx1ZTtcblxuLy8gICAvLyByZXR1cm4gZmlsdGVyIHR5cGUsIGRlZmF1bHQgdmFsdWUsIGZpZWxkVHlwZSBhbmQgZmllbGREb21haW4gZnJvbSBmaWVsZFxuLy8gICBjb25zdCBmaWx0ZXJQcm9wc0Zyb21GaWVsZCA9IGdldEZpbHRlclByb3BzKGFsbERhdGEsIGZpZWxkKTtcblxuLy8gICBsZXQgbWF0Y2hlZEZpbHRlciA9IHtcbi8vICAgICAuLi5nZXREZWZhdWx0RmlsdGVyKGZpbHRlci5kYXRhSWQpLFxuLy8gICAgIC4uLmZpbHRlcixcbi8vICAgICAuLi5maWx0ZXJQcm9wc0Zyb21GaWVsZCxcbi8vICAgICBmcmVlemU6IHRydWUsXG4vLyAgICAgZmllbGRJZHhcbi8vICAgfTtcblxuLy8gICBjb25zdCB7IHlBeGlzIH0gPSBtYXRjaGVkRmlsdGVyO1xuLy8gICBpZiAoeUF4aXMpIHtcbi8vICAgICBjb25zdCBtYXRjaGVBeGlzID0gZmllbGRzLmZpbmQoXG4vLyAgICAgICAoeyBuYW1lLCB0eXBlIH0pID0+IG5hbWUgPT09IHlBeGlzLm5hbWUgJiYgdHlwZSA9PT0geUF4aXMudHlwZVxuLy8gICAgICk7XG5cbi8vICAgICBtYXRjaGVkRmlsdGVyID0gbWF0Y2hlQXhpc1xuLy8gICAgICAgPyB7XG4vLyAgICAgICAgICAgLi4ubWF0Y2hlZEZpbHRlcixcbi8vICAgICAgICAgICB5QXhpczogbWF0Y2hlQXhpcyxcbi8vICAgICAgICAgICAuLi5nZXRGaWx0ZXJQbG90KHsgLi4ubWF0Y2hlZEZpbHRlciwgeUF4aXM6IG1hdGNoZUF4aXMgfSwgYWxsRGF0YSlcbi8vICAgICAgICAgfVxuLy8gICAgICAgOiBtYXRjaGVkRmlsdGVyO1xuLy8gICB9XG5cbi8vICAgbWF0Y2hlZEZpbHRlci52YWx1ZSA9IGFkanVzdFZhbHVlVG9GaWx0ZXJEb21haW4odmFsdWUsIG1hdGNoZWRGaWx0ZXIpO1xuXG4vLyAgIGlmIChtYXRjaGVkRmlsdGVyLnZhbHVlID09PSBudWxsKSB7XG4vLyAgICAgLy8gY2FubnQgYWRqdXN0IHNhdmVkIHZhbHVlIHRvIGZpbHRlclxuLy8gICAgIHJldHVybiBudWxsO1xuLy8gICB9XG5cbi8vICAgcmV0dXJuIG1hdGNoZWRGaWx0ZXI7XG4vLyB9XG4iXX0=