diff --git a/.config/spicetify/CustomApps/stats/cache.js b/.config/spicetify/CustomApps/stats/cache.js
new file mode 100644
index 00000000..11abb7d3
--- /dev/null
+++ b/.config/spicetify/CustomApps/stats/cache.js
@@ -0,0 +1,55 @@
+(async function() {
+ while (!Spicetify.React || !Spicetify.ReactDOM) {
+ await new Promise(resolve => setTimeout(resolve, 10));
+ }
+ "use strict";
+var stats = (() => {
+ var __defProp = Object.defineProperty;
+ var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
+ var __getOwnPropNames = Object.getOwnPropertyNames;
+ var __hasOwnProp = Object.prototype.hasOwnProperty;
+ var __export = (target, all) => {
+ for (var name in all)
+ __defProp(target, name, { get: all[name], enumerable: true });
+ };
+ var __copyProps = (to, from, except, desc) => {
+ if (from && typeof from === "object" || typeof from === "function") {
+ for (let key of __getOwnPropNames(from))
+ if (!__hasOwnProp.call(to, key) && key !== except)
+ __defProp(to, key, { get: () => from[key], enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable });
+ }
+ return to;
+ };
+ var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod);
+
+ // src/extensions/cache.ts
+ var cache_exports = {};
+ __export(cache_exports, {
+ cacher: () => cacher,
+ invalidator: () => invalidator
+ });
+ var cache = {};
+ var set = (key, value) => {
+ cache[key] = value;
+ };
+ var invalidate = (key) => {
+ delete cache[key];
+ };
+ var cacher = (cb) => {
+ return async ({ queryKey }) => {
+ const key = queryKey.join("-");
+ if (cache[key])
+ return cache[key];
+ const result = await cb();
+ set(key, result);
+ return result;
+ };
+ };
+ var invalidator = (queryKey, refetch) => {
+ invalidate(queryKey.join("-"));
+ refetch();
+ };
+ return __toCommonJS(cache_exports);
+})();
+
+ })();
\ No newline at end of file
diff --git a/.config/spicetify/CustomApps/stats/extension.js b/.config/spicetify/CustomApps/stats/extension.js
index ef6499cd..bdc3489a 100644
--- a/.config/spicetify/CustomApps/stats/extension.js
+++ b/.config/spicetify/CustomApps/stats/extension.js
@@ -38,6 +38,5444 @@ var stats = (() => {
}
});
+ // ../node_modules/lodash/lodash.js
+ var require_lodash = __commonJS({
+ "../node_modules/lodash/lodash.js"(exports, module) {
+ (function() {
+ var undefined2;
+ var VERSION = "4.17.21";
+ var LARGE_ARRAY_SIZE = 200;
+ var CORE_ERROR_TEXT = "Unsupported core-js use. Try https://npms.io/search?q=ponyfill.", FUNC_ERROR_TEXT = "Expected a function", INVALID_TEMPL_VAR_ERROR_TEXT = "Invalid `variable` option passed into `_.template`";
+ var HASH_UNDEFINED = "__lodash_hash_undefined__";
+ var MAX_MEMOIZE_SIZE = 500;
+ var PLACEHOLDER = "__lodash_placeholder__";
+ var CLONE_DEEP_FLAG = 1, CLONE_FLAT_FLAG = 2, CLONE_SYMBOLS_FLAG = 4;
+ var COMPARE_PARTIAL_FLAG = 1, COMPARE_UNORDERED_FLAG = 2;
+ var WRAP_BIND_FLAG = 1, WRAP_BIND_KEY_FLAG = 2, WRAP_CURRY_BOUND_FLAG = 4, WRAP_CURRY_FLAG = 8, WRAP_CURRY_RIGHT_FLAG = 16, WRAP_PARTIAL_FLAG = 32, WRAP_PARTIAL_RIGHT_FLAG = 64, WRAP_ARY_FLAG = 128, WRAP_REARG_FLAG = 256, WRAP_FLIP_FLAG = 512;
+ var DEFAULT_TRUNC_LENGTH = 30, DEFAULT_TRUNC_OMISSION = "...";
+ var HOT_COUNT = 800, HOT_SPAN = 16;
+ var LAZY_FILTER_FLAG = 1, LAZY_MAP_FLAG = 2, LAZY_WHILE_FLAG = 3;
+ var INFINITY = 1 / 0, MAX_SAFE_INTEGER = 9007199254740991, MAX_INTEGER = 17976931348623157e292, NAN = 0 / 0;
+ var MAX_ARRAY_LENGTH = 4294967295, MAX_ARRAY_INDEX = MAX_ARRAY_LENGTH - 1, HALF_MAX_ARRAY_LENGTH = MAX_ARRAY_LENGTH >>> 1;
+ var wrapFlags = [
+ ["ary", WRAP_ARY_FLAG],
+ ["bind", WRAP_BIND_FLAG],
+ ["bindKey", WRAP_BIND_KEY_FLAG],
+ ["curry", WRAP_CURRY_FLAG],
+ ["curryRight", WRAP_CURRY_RIGHT_FLAG],
+ ["flip", WRAP_FLIP_FLAG],
+ ["partial", WRAP_PARTIAL_FLAG],
+ ["partialRight", WRAP_PARTIAL_RIGHT_FLAG],
+ ["rearg", WRAP_REARG_FLAG]
+ ];
+ var argsTag = "[object Arguments]", arrayTag = "[object Array]", asyncTag = "[object AsyncFunction]", boolTag = "[object Boolean]", dateTag = "[object Date]", domExcTag = "[object DOMException]", errorTag = "[object Error]", funcTag = "[object Function]", genTag = "[object GeneratorFunction]", mapTag = "[object Map]", numberTag = "[object Number]", nullTag = "[object Null]", objectTag = "[object Object]", promiseTag = "[object Promise]", proxyTag = "[object Proxy]", regexpTag = "[object RegExp]", setTag = "[object Set]", stringTag = "[object String]", symbolTag = "[object Symbol]", undefinedTag = "[object Undefined]", weakMapTag = "[object WeakMap]", weakSetTag = "[object WeakSet]";
+ var arrayBufferTag = "[object ArrayBuffer]", dataViewTag = "[object DataView]", float32Tag = "[object Float32Array]", float64Tag = "[object Float64Array]", int8Tag = "[object Int8Array]", int16Tag = "[object Int16Array]", int32Tag = "[object Int32Array]", uint8Tag = "[object Uint8Array]", uint8ClampedTag = "[object Uint8ClampedArray]", uint16Tag = "[object Uint16Array]", uint32Tag = "[object Uint32Array]";
+ var reEmptyStringLeading = /\b__p \+= '';/g, reEmptyStringMiddle = /\b(__p \+=) '' \+/g, reEmptyStringTrailing = /(__e\(.*?\)|\b__t\)) \+\n'';/g;
+ var reEscapedHtml = /&(?:amp|lt|gt|quot|#39);/g, reUnescapedHtml = /[&<>"']/g, reHasEscapedHtml = RegExp(reEscapedHtml.source), reHasUnescapedHtml = RegExp(reUnescapedHtml.source);
+ var reEscape = /<%-([\s\S]+?)%>/g, reEvaluate = /<%([\s\S]+?)%>/g, reInterpolate = /<%=([\s\S]+?)%>/g;
+ var reIsDeepProp = /\.|\[(?:[^[\]]*|(["'])(?:(?!\1)[^\\]|\\.)*?\1)\]/, reIsPlainProp = /^\w*$/, rePropName = /[^.[\]]+|\[(?:(-?\d+(?:\.\d+)?)|(["'])((?:(?!\2)[^\\]|\\.)*?)\2)\]|(?=(?:\.|\[\])(?:\.|\[\]|$))/g;
+ var reRegExpChar = /[\\^$.*+?()[\]{}|]/g, reHasRegExpChar = RegExp(reRegExpChar.source);
+ var reTrimStart = /^\s+/;
+ var reWhitespace = /\s/;
+ var reWrapComment = /\{(?:\n\/\* \[wrapped with .+\] \*\/)?\n?/, reWrapDetails = /\{\n\/\* \[wrapped with (.+)\] \*/, reSplitDetails = /,? & /;
+ var reAsciiWord = /[^\x00-\x2f\x3a-\x40\x5b-\x60\x7b-\x7f]+/g;
+ var reForbiddenIdentifierChars = /[()=,{}\[\]\/\s]/;
+ var reEscapeChar = /\\(\\)?/g;
+ var reEsTemplate = /\$\{([^\\}]*(?:\\.[^\\}]*)*)\}/g;
+ var reFlags = /\w*$/;
+ var reIsBadHex = /^[-+]0x[0-9a-f]+$/i;
+ var reIsBinary = /^0b[01]+$/i;
+ var reIsHostCtor = /^\[object .+?Constructor\]$/;
+ var reIsOctal = /^0o[0-7]+$/i;
+ var reIsUint = /^(?:0|[1-9]\d*)$/;
+ var reLatin = /[\xc0-\xd6\xd8-\xf6\xf8-\xff\u0100-\u017f]/g;
+ var reNoMatch = /($^)/;
+ var reUnescapedString = /['\n\r\u2028\u2029\\]/g;
+ var rsAstralRange = "\\ud800-\\udfff", rsComboMarksRange = "\\u0300-\\u036f", reComboHalfMarksRange = "\\ufe20-\\ufe2f", rsComboSymbolsRange = "\\u20d0-\\u20ff", rsComboRange = rsComboMarksRange + reComboHalfMarksRange + rsComboSymbolsRange, rsDingbatRange = "\\u2700-\\u27bf", rsLowerRange = "a-z\\xdf-\\xf6\\xf8-\\xff", rsMathOpRange = "\\xac\\xb1\\xd7\\xf7", rsNonCharRange = "\\x00-\\x2f\\x3a-\\x40\\x5b-\\x60\\x7b-\\xbf", rsPunctuationRange = "\\u2000-\\u206f", rsSpaceRange = " \\t\\x0b\\f\\xa0\\ufeff\\n\\r\\u2028\\u2029\\u1680\\u180e\\u2000\\u2001\\u2002\\u2003\\u2004\\u2005\\u2006\\u2007\\u2008\\u2009\\u200a\\u202f\\u205f\\u3000", rsUpperRange = "A-Z\\xc0-\\xd6\\xd8-\\xde", rsVarRange = "\\ufe0e\\ufe0f", rsBreakRange = rsMathOpRange + rsNonCharRange + rsPunctuationRange + rsSpaceRange;
+ var rsApos = "['\u2019]", rsAstral = "[" + rsAstralRange + "]", rsBreak = "[" + rsBreakRange + "]", rsCombo = "[" + rsComboRange + "]", rsDigits = "\\d+", rsDingbat = "[" + rsDingbatRange + "]", rsLower = "[" + rsLowerRange + "]", rsMisc = "[^" + rsAstralRange + rsBreakRange + rsDigits + rsDingbatRange + rsLowerRange + rsUpperRange + "]", rsFitz = "\\ud83c[\\udffb-\\udfff]", rsModifier = "(?:" + rsCombo + "|" + rsFitz + ")", rsNonAstral = "[^" + rsAstralRange + "]", rsRegional = "(?:\\ud83c[\\udde6-\\uddff]){2}", rsSurrPair = "[\\ud800-\\udbff][\\udc00-\\udfff]", rsUpper = "[" + rsUpperRange + "]", rsZWJ = "\\u200d";
+ var rsMiscLower = "(?:" + rsLower + "|" + rsMisc + ")", rsMiscUpper = "(?:" + rsUpper + "|" + rsMisc + ")", rsOptContrLower = "(?:" + rsApos + "(?:d|ll|m|re|s|t|ve))?", rsOptContrUpper = "(?:" + rsApos + "(?:D|LL|M|RE|S|T|VE))?", reOptMod = rsModifier + "?", rsOptVar = "[" + rsVarRange + "]?", rsOptJoin = "(?:" + rsZWJ + "(?:" + [rsNonAstral, rsRegional, rsSurrPair].join("|") + ")" + rsOptVar + reOptMod + ")*", rsOrdLower = "\\d*(?:1st|2nd|3rd|(?![123])\\dth)(?=\\b|[A-Z_])", rsOrdUpper = "\\d*(?:1ST|2ND|3RD|(?![123])\\dTH)(?=\\b|[a-z_])", rsSeq = rsOptVar + reOptMod + rsOptJoin, rsEmoji = "(?:" + [rsDingbat, rsRegional, rsSurrPair].join("|") + ")" + rsSeq, rsSymbol = "(?:" + [rsNonAstral + rsCombo + "?", rsCombo, rsRegional, rsSurrPair, rsAstral].join("|") + ")";
+ var reApos = RegExp(rsApos, "g");
+ var reComboMark = RegExp(rsCombo, "g");
+ var reUnicode = RegExp(rsFitz + "(?=" + rsFitz + ")|" + rsSymbol + rsSeq, "g");
+ var reUnicodeWord = RegExp([
+ rsUpper + "?" + rsLower + "+" + rsOptContrLower + "(?=" + [rsBreak, rsUpper, "$"].join("|") + ")",
+ rsMiscUpper + "+" + rsOptContrUpper + "(?=" + [rsBreak, rsUpper + rsMiscLower, "$"].join("|") + ")",
+ rsUpper + "?" + rsMiscLower + "+" + rsOptContrLower,
+ rsUpper + "+" + rsOptContrUpper,
+ rsOrdUpper,
+ rsOrdLower,
+ rsDigits,
+ rsEmoji
+ ].join("|"), "g");
+ var reHasUnicode = RegExp("[" + rsZWJ + rsAstralRange + rsComboRange + rsVarRange + "]");
+ var reHasUnicodeWord = /[a-z][A-Z]|[A-Z]{2}[a-z]|[0-9][a-zA-Z]|[a-zA-Z][0-9]|[^a-zA-Z0-9 ]/;
+ var contextProps = [
+ "Array",
+ "Buffer",
+ "DataView",
+ "Date",
+ "Error",
+ "Float32Array",
+ "Float64Array",
+ "Function",
+ "Int8Array",
+ "Int16Array",
+ "Int32Array",
+ "Map",
+ "Math",
+ "Object",
+ "Promise",
+ "RegExp",
+ "Set",
+ "String",
+ "Symbol",
+ "TypeError",
+ "Uint8Array",
+ "Uint8ClampedArray",
+ "Uint16Array",
+ "Uint32Array",
+ "WeakMap",
+ "_",
+ "clearTimeout",
+ "isFinite",
+ "parseInt",
+ "setTimeout"
+ ];
+ var templateCounter = -1;
+ var typedArrayTags = {};
+ typedArrayTags[float32Tag] = typedArrayTags[float64Tag] = typedArrayTags[int8Tag] = typedArrayTags[int16Tag] = typedArrayTags[int32Tag] = typedArrayTags[uint8Tag] = typedArrayTags[uint8ClampedTag] = typedArrayTags[uint16Tag] = typedArrayTags[uint32Tag] = true;
+ typedArrayTags[argsTag] = typedArrayTags[arrayTag] = typedArrayTags[arrayBufferTag] = typedArrayTags[boolTag] = typedArrayTags[dataViewTag] = typedArrayTags[dateTag] = typedArrayTags[errorTag] = typedArrayTags[funcTag] = typedArrayTags[mapTag] = typedArrayTags[numberTag] = typedArrayTags[objectTag] = typedArrayTags[regexpTag] = typedArrayTags[setTag] = typedArrayTags[stringTag] = typedArrayTags[weakMapTag] = false;
+ var cloneableTags = {};
+ cloneableTags[argsTag] = cloneableTags[arrayTag] = cloneableTags[arrayBufferTag] = cloneableTags[dataViewTag] = cloneableTags[boolTag] = cloneableTags[dateTag] = cloneableTags[float32Tag] = cloneableTags[float64Tag] = cloneableTags[int8Tag] = cloneableTags[int16Tag] = cloneableTags[int32Tag] = cloneableTags[mapTag] = cloneableTags[numberTag] = cloneableTags[objectTag] = cloneableTags[regexpTag] = cloneableTags[setTag] = cloneableTags[stringTag] = cloneableTags[symbolTag] = cloneableTags[uint8Tag] = cloneableTags[uint8ClampedTag] = cloneableTags[uint16Tag] = cloneableTags[uint32Tag] = true;
+ cloneableTags[errorTag] = cloneableTags[funcTag] = cloneableTags[weakMapTag] = false;
+ var deburredLetters = {
+ "\xC0": "A",
+ "\xC1": "A",
+ "\xC2": "A",
+ "\xC3": "A",
+ "\xC4": "A",
+ "\xC5": "A",
+ "\xE0": "a",
+ "\xE1": "a",
+ "\xE2": "a",
+ "\xE3": "a",
+ "\xE4": "a",
+ "\xE5": "a",
+ "\xC7": "C",
+ "\xE7": "c",
+ "\xD0": "D",
+ "\xF0": "d",
+ "\xC8": "E",
+ "\xC9": "E",
+ "\xCA": "E",
+ "\xCB": "E",
+ "\xE8": "e",
+ "\xE9": "e",
+ "\xEA": "e",
+ "\xEB": "e",
+ "\xCC": "I",
+ "\xCD": "I",
+ "\xCE": "I",
+ "\xCF": "I",
+ "\xEC": "i",
+ "\xED": "i",
+ "\xEE": "i",
+ "\xEF": "i",
+ "\xD1": "N",
+ "\xF1": "n",
+ "\xD2": "O",
+ "\xD3": "O",
+ "\xD4": "O",
+ "\xD5": "O",
+ "\xD6": "O",
+ "\xD8": "O",
+ "\xF2": "o",
+ "\xF3": "o",
+ "\xF4": "o",
+ "\xF5": "o",
+ "\xF6": "o",
+ "\xF8": "o",
+ "\xD9": "U",
+ "\xDA": "U",
+ "\xDB": "U",
+ "\xDC": "U",
+ "\xF9": "u",
+ "\xFA": "u",
+ "\xFB": "u",
+ "\xFC": "u",
+ "\xDD": "Y",
+ "\xFD": "y",
+ "\xFF": "y",
+ "\xC6": "Ae",
+ "\xE6": "ae",
+ "\xDE": "Th",
+ "\xFE": "th",
+ "\xDF": "ss",
+ "\u0100": "A",
+ "\u0102": "A",
+ "\u0104": "A",
+ "\u0101": "a",
+ "\u0103": "a",
+ "\u0105": "a",
+ "\u0106": "C",
+ "\u0108": "C",
+ "\u010A": "C",
+ "\u010C": "C",
+ "\u0107": "c",
+ "\u0109": "c",
+ "\u010B": "c",
+ "\u010D": "c",
+ "\u010E": "D",
+ "\u0110": "D",
+ "\u010F": "d",
+ "\u0111": "d",
+ "\u0112": "E",
+ "\u0114": "E",
+ "\u0116": "E",
+ "\u0118": "E",
+ "\u011A": "E",
+ "\u0113": "e",
+ "\u0115": "e",
+ "\u0117": "e",
+ "\u0119": "e",
+ "\u011B": "e",
+ "\u011C": "G",
+ "\u011E": "G",
+ "\u0120": "G",
+ "\u0122": "G",
+ "\u011D": "g",
+ "\u011F": "g",
+ "\u0121": "g",
+ "\u0123": "g",
+ "\u0124": "H",
+ "\u0126": "H",
+ "\u0125": "h",
+ "\u0127": "h",
+ "\u0128": "I",
+ "\u012A": "I",
+ "\u012C": "I",
+ "\u012E": "I",
+ "\u0130": "I",
+ "\u0129": "i",
+ "\u012B": "i",
+ "\u012D": "i",
+ "\u012F": "i",
+ "\u0131": "i",
+ "\u0134": "J",
+ "\u0135": "j",
+ "\u0136": "K",
+ "\u0137": "k",
+ "\u0138": "k",
+ "\u0139": "L",
+ "\u013B": "L",
+ "\u013D": "L",
+ "\u013F": "L",
+ "\u0141": "L",
+ "\u013A": "l",
+ "\u013C": "l",
+ "\u013E": "l",
+ "\u0140": "l",
+ "\u0142": "l",
+ "\u0143": "N",
+ "\u0145": "N",
+ "\u0147": "N",
+ "\u014A": "N",
+ "\u0144": "n",
+ "\u0146": "n",
+ "\u0148": "n",
+ "\u014B": "n",
+ "\u014C": "O",
+ "\u014E": "O",
+ "\u0150": "O",
+ "\u014D": "o",
+ "\u014F": "o",
+ "\u0151": "o",
+ "\u0154": "R",
+ "\u0156": "R",
+ "\u0158": "R",
+ "\u0155": "r",
+ "\u0157": "r",
+ "\u0159": "r",
+ "\u015A": "S",
+ "\u015C": "S",
+ "\u015E": "S",
+ "\u0160": "S",
+ "\u015B": "s",
+ "\u015D": "s",
+ "\u015F": "s",
+ "\u0161": "s",
+ "\u0162": "T",
+ "\u0164": "T",
+ "\u0166": "T",
+ "\u0163": "t",
+ "\u0165": "t",
+ "\u0167": "t",
+ "\u0168": "U",
+ "\u016A": "U",
+ "\u016C": "U",
+ "\u016E": "U",
+ "\u0170": "U",
+ "\u0172": "U",
+ "\u0169": "u",
+ "\u016B": "u",
+ "\u016D": "u",
+ "\u016F": "u",
+ "\u0171": "u",
+ "\u0173": "u",
+ "\u0174": "W",
+ "\u0175": "w",
+ "\u0176": "Y",
+ "\u0177": "y",
+ "\u0178": "Y",
+ "\u0179": "Z",
+ "\u017B": "Z",
+ "\u017D": "Z",
+ "\u017A": "z",
+ "\u017C": "z",
+ "\u017E": "z",
+ "\u0132": "IJ",
+ "\u0133": "ij",
+ "\u0152": "Oe",
+ "\u0153": "oe",
+ "\u0149": "'n",
+ "\u017F": "s"
+ };
+ var htmlEscapes = {
+ "&": "&",
+ "<": "<",
+ ">": ">",
+ '"': """,
+ "'": "'"
+ };
+ var htmlUnescapes = {
+ "&": "&",
+ "<": "<",
+ ">": ">",
+ """: '"',
+ "'": "'"
+ };
+ var stringEscapes = {
+ "\\": "\\",
+ "'": "'",
+ "\n": "n",
+ "\r": "r",
+ "\u2028": "u2028",
+ "\u2029": "u2029"
+ };
+ var freeParseFloat = parseFloat, freeParseInt = parseInt;
+ var freeGlobal = typeof global == "object" && global && global.Object === Object && global;
+ var freeSelf = typeof self == "object" && self && self.Object === Object && self;
+ var root = freeGlobal || freeSelf || Function("return this")();
+ var freeExports = typeof exports == "object" && exports && !exports.nodeType && exports;
+ var freeModule = freeExports && typeof module == "object" && module && !module.nodeType && module;
+ var moduleExports = freeModule && freeModule.exports === freeExports;
+ var freeProcess = moduleExports && freeGlobal.process;
+ var nodeUtil = function() {
+ try {
+ var types = freeModule && freeModule.require && freeModule.require("util").types;
+ if (types) {
+ return types;
+ }
+ return freeProcess && freeProcess.binding && freeProcess.binding("util");
+ } catch (e) {
+ }
+ }();
+ var nodeIsArrayBuffer = nodeUtil && nodeUtil.isArrayBuffer, nodeIsDate = nodeUtil && nodeUtil.isDate, nodeIsMap = nodeUtil && nodeUtil.isMap, nodeIsRegExp = nodeUtil && nodeUtil.isRegExp, nodeIsSet = nodeUtil && nodeUtil.isSet, nodeIsTypedArray = nodeUtil && nodeUtil.isTypedArray;
+ function apply(func, thisArg, args) {
+ switch (args.length) {
+ case 0:
+ return func.call(thisArg);
+ case 1:
+ return func.call(thisArg, args[0]);
+ case 2:
+ return func.call(thisArg, args[0], args[1]);
+ case 3:
+ return func.call(thisArg, args[0], args[1], args[2]);
+ }
+ return func.apply(thisArg, args);
+ }
+ function arrayAggregator(array, setter, iteratee, accumulator) {
+ var index = -1, length = array == null ? 0 : array.length;
+ while (++index < length) {
+ var value = array[index];
+ setter(accumulator, value, iteratee(value), array);
+ }
+ return accumulator;
+ }
+ function arrayEach(array, iteratee) {
+ var index = -1, length = array == null ? 0 : array.length;
+ while (++index < length) {
+ if (iteratee(array[index], index, array) === false) {
+ break;
+ }
+ }
+ return array;
+ }
+ function arrayEachRight(array, iteratee) {
+ var length = array == null ? 0 : array.length;
+ while (length--) {
+ if (iteratee(array[length], length, array) === false) {
+ break;
+ }
+ }
+ return array;
+ }
+ function arrayEvery(array, predicate) {
+ var index = -1, length = array == null ? 0 : array.length;
+ while (++index < length) {
+ if (!predicate(array[index], index, array)) {
+ return false;
+ }
+ }
+ return true;
+ }
+ function arrayFilter(array, predicate) {
+ var index = -1, length = array == null ? 0 : array.length, resIndex = 0, result = [];
+ while (++index < length) {
+ var value = array[index];
+ if (predicate(value, index, array)) {
+ result[resIndex++] = value;
+ }
+ }
+ return result;
+ }
+ function arrayIncludes(array, value) {
+ var length = array == null ? 0 : array.length;
+ return !!length && baseIndexOf(array, value, 0) > -1;
+ }
+ function arrayIncludesWith(array, value, comparator) {
+ var index = -1, length = array == null ? 0 : array.length;
+ while (++index < length) {
+ if (comparator(value, array[index])) {
+ return true;
+ }
+ }
+ return false;
+ }
+ function arrayMap(array, iteratee) {
+ var index = -1, length = array == null ? 0 : array.length, result = Array(length);
+ while (++index < length) {
+ result[index] = iteratee(array[index], index, array);
+ }
+ return result;
+ }
+ function arrayPush(array, values) {
+ var index = -1, length = values.length, offset = array.length;
+ while (++index < length) {
+ array[offset + index] = values[index];
+ }
+ return array;
+ }
+ function arrayReduce(array, iteratee, accumulator, initAccum) {
+ var index = -1, length = array == null ? 0 : array.length;
+ if (initAccum && length) {
+ accumulator = array[++index];
+ }
+ while (++index < length) {
+ accumulator = iteratee(accumulator, array[index], index, array);
+ }
+ return accumulator;
+ }
+ function arrayReduceRight(array, iteratee, accumulator, initAccum) {
+ var length = array == null ? 0 : array.length;
+ if (initAccum && length) {
+ accumulator = array[--length];
+ }
+ while (length--) {
+ accumulator = iteratee(accumulator, array[length], length, array);
+ }
+ return accumulator;
+ }
+ function arraySome(array, predicate) {
+ var index = -1, length = array == null ? 0 : array.length;
+ while (++index < length) {
+ if (predicate(array[index], index, array)) {
+ return true;
+ }
+ }
+ return false;
+ }
+ var asciiSize = baseProperty("length");
+ function asciiToArray(string) {
+ return string.split("");
+ }
+ function asciiWords(string) {
+ return string.match(reAsciiWord) || [];
+ }
+ function baseFindKey(collection, predicate, eachFunc) {
+ var result;
+ eachFunc(collection, function(value, key, collection2) {
+ if (predicate(value, key, collection2)) {
+ result = key;
+ return false;
+ }
+ });
+ return result;
+ }
+ function baseFindIndex(array, predicate, fromIndex, fromRight) {
+ var length = array.length, index = fromIndex + (fromRight ? 1 : -1);
+ while (fromRight ? index-- : ++index < length) {
+ if (predicate(array[index], index, array)) {
+ return index;
+ }
+ }
+ return -1;
+ }
+ function baseIndexOf(array, value, fromIndex) {
+ return value === value ? strictIndexOf(array, value, fromIndex) : baseFindIndex(array, baseIsNaN, fromIndex);
+ }
+ function baseIndexOfWith(array, value, fromIndex, comparator) {
+ var index = fromIndex - 1, length = array.length;
+ while (++index < length) {
+ if (comparator(array[index], value)) {
+ return index;
+ }
+ }
+ return -1;
+ }
+ function baseIsNaN(value) {
+ return value !== value;
+ }
+ function baseMean(array, iteratee) {
+ var length = array == null ? 0 : array.length;
+ return length ? baseSum(array, iteratee) / length : NAN;
+ }
+ function baseProperty(key) {
+ return function(object) {
+ return object == null ? undefined2 : object[key];
+ };
+ }
+ function basePropertyOf(object) {
+ return function(key) {
+ return object == null ? undefined2 : object[key];
+ };
+ }
+ function baseReduce(collection, iteratee, accumulator, initAccum, eachFunc) {
+ eachFunc(collection, function(value, index, collection2) {
+ accumulator = initAccum ? (initAccum = false, value) : iteratee(accumulator, value, index, collection2);
+ });
+ return accumulator;
+ }
+ function baseSortBy(array, comparer) {
+ var length = array.length;
+ array.sort(comparer);
+ while (length--) {
+ array[length] = array[length].value;
+ }
+ return array;
+ }
+ function baseSum(array, iteratee) {
+ var result, index = -1, length = array.length;
+ while (++index < length) {
+ var current = iteratee(array[index]);
+ if (current !== undefined2) {
+ result = result === undefined2 ? current : result + current;
+ }
+ }
+ return result;
+ }
+ function baseTimes(n, iteratee) {
+ var index = -1, result = Array(n);
+ while (++index < n) {
+ result[index] = iteratee(index);
+ }
+ return result;
+ }
+ function baseToPairs(object, props) {
+ return arrayMap(props, function(key) {
+ return [key, object[key]];
+ });
+ }
+ function baseTrim(string) {
+ return string ? string.slice(0, trimmedEndIndex(string) + 1).replace(reTrimStart, "") : string;
+ }
+ function baseUnary(func) {
+ return function(value) {
+ return func(value);
+ };
+ }
+ function baseValues(object, props) {
+ return arrayMap(props, function(key) {
+ return object[key];
+ });
+ }
+ function cacheHas(cache, key) {
+ return cache.has(key);
+ }
+ function charsStartIndex(strSymbols, chrSymbols) {
+ var index = -1, length = strSymbols.length;
+ while (++index < length && baseIndexOf(chrSymbols, strSymbols[index], 0) > -1) {
+ }
+ return index;
+ }
+ function charsEndIndex(strSymbols, chrSymbols) {
+ var index = strSymbols.length;
+ while (index-- && baseIndexOf(chrSymbols, strSymbols[index], 0) > -1) {
+ }
+ return index;
+ }
+ function countHolders(array, placeholder) {
+ var length = array.length, result = 0;
+ while (length--) {
+ if (array[length] === placeholder) {
+ ++result;
+ }
+ }
+ return result;
+ }
+ var deburrLetter = basePropertyOf(deburredLetters);
+ var escapeHtmlChar = basePropertyOf(htmlEscapes);
+ function escapeStringChar(chr) {
+ return "\\" + stringEscapes[chr];
+ }
+ function getValue(object, key) {
+ return object == null ? undefined2 : object[key];
+ }
+ function hasUnicode(string) {
+ return reHasUnicode.test(string);
+ }
+ function hasUnicodeWord(string) {
+ return reHasUnicodeWord.test(string);
+ }
+ function iteratorToArray(iterator) {
+ var data, result = [];
+ while (!(data = iterator.next()).done) {
+ result.push(data.value);
+ }
+ return result;
+ }
+ function mapToArray(map) {
+ var index = -1, result = Array(map.size);
+ map.forEach(function(value, key) {
+ result[++index] = [key, value];
+ });
+ return result;
+ }
+ function overArg(func, transform) {
+ return function(arg) {
+ return func(transform(arg));
+ };
+ }
+ function replaceHolders(array, placeholder) {
+ var index = -1, length = array.length, resIndex = 0, result = [];
+ while (++index < length) {
+ var value = array[index];
+ if (value === placeholder || value === PLACEHOLDER) {
+ array[index] = PLACEHOLDER;
+ result[resIndex++] = index;
+ }
+ }
+ return result;
+ }
+ function setToArray(set) {
+ var index = -1, result = Array(set.size);
+ set.forEach(function(value) {
+ result[++index] = value;
+ });
+ return result;
+ }
+ function setToPairs(set) {
+ var index = -1, result = Array(set.size);
+ set.forEach(function(value) {
+ result[++index] = [value, value];
+ });
+ return result;
+ }
+ function strictIndexOf(array, value, fromIndex) {
+ var index = fromIndex - 1, length = array.length;
+ while (++index < length) {
+ if (array[index] === value) {
+ return index;
+ }
+ }
+ return -1;
+ }
+ function strictLastIndexOf(array, value, fromIndex) {
+ var index = fromIndex + 1;
+ while (index--) {
+ if (array[index] === value) {
+ return index;
+ }
+ }
+ return index;
+ }
+ function stringSize(string) {
+ return hasUnicode(string) ? unicodeSize(string) : asciiSize(string);
+ }
+ function stringToArray(string) {
+ return hasUnicode(string) ? unicodeToArray(string) : asciiToArray(string);
+ }
+ function trimmedEndIndex(string) {
+ var index = string.length;
+ while (index-- && reWhitespace.test(string.charAt(index))) {
+ }
+ return index;
+ }
+ var unescapeHtmlChar = basePropertyOf(htmlUnescapes);
+ function unicodeSize(string) {
+ var result = reUnicode.lastIndex = 0;
+ while (reUnicode.test(string)) {
+ ++result;
+ }
+ return result;
+ }
+ function unicodeToArray(string) {
+ return string.match(reUnicode) || [];
+ }
+ function unicodeWords(string) {
+ return string.match(reUnicodeWord) || [];
+ }
+ var runInContext = function runInContext2(context) {
+ context = context == null ? root : _2.defaults(root.Object(), context, _2.pick(root, contextProps));
+ var Array2 = context.Array, Date = context.Date, Error2 = context.Error, Function2 = context.Function, Math2 = context.Math, Object2 = context.Object, RegExp2 = context.RegExp, String2 = context.String, TypeError2 = context.TypeError;
+ var arrayProto = Array2.prototype, funcProto = Function2.prototype, objectProto = Object2.prototype;
+ var coreJsData = context["__core-js_shared__"];
+ var funcToString = funcProto.toString;
+ var hasOwnProperty = objectProto.hasOwnProperty;
+ var idCounter = 0;
+ var maskSrcKey = function() {
+ var uid = /[^.]+$/.exec(coreJsData && coreJsData.keys && coreJsData.keys.IE_PROTO || "");
+ return uid ? "Symbol(src)_1." + uid : "";
+ }();
+ var nativeObjectToString = objectProto.toString;
+ var objectCtorString = funcToString.call(Object2);
+ var oldDash = root._;
+ var reIsNative = RegExp2(
+ "^" + funcToString.call(hasOwnProperty).replace(reRegExpChar, "\\$&").replace(/hasOwnProperty|(function).*?(?=\\\()| for .+?(?=\\\])/g, "$1.*?") + "$"
+ );
+ var Buffer2 = moduleExports ? context.Buffer : undefined2, Symbol = context.Symbol, Uint8Array2 = context.Uint8Array, allocUnsafe = Buffer2 ? Buffer2.allocUnsafe : undefined2, getPrototype = overArg(Object2.getPrototypeOf, Object2), objectCreate = Object2.create, propertyIsEnumerable = objectProto.propertyIsEnumerable, splice = arrayProto.splice, spreadableSymbol = Symbol ? Symbol.isConcatSpreadable : undefined2, symIterator = Symbol ? Symbol.iterator : undefined2, symToStringTag = Symbol ? Symbol.toStringTag : undefined2;
+ var defineProperty = function() {
+ try {
+ var func = getNative(Object2, "defineProperty");
+ func({}, "", {});
+ return func;
+ } catch (e) {
+ }
+ }();
+ var ctxClearTimeout = context.clearTimeout !== root.clearTimeout && context.clearTimeout, ctxNow = Date && Date.now !== root.Date.now && Date.now, ctxSetTimeout = context.setTimeout !== root.setTimeout && context.setTimeout;
+ var nativeCeil = Math2.ceil, nativeFloor = Math2.floor, nativeGetSymbols = Object2.getOwnPropertySymbols, nativeIsBuffer = Buffer2 ? Buffer2.isBuffer : undefined2, nativeIsFinite = context.isFinite, nativeJoin = arrayProto.join, nativeKeys = overArg(Object2.keys, Object2), nativeMax = Math2.max, nativeMin = Math2.min, nativeNow = Date.now, nativeParseInt = context.parseInt, nativeRandom = Math2.random, nativeReverse = arrayProto.reverse;
+ var DataView = getNative(context, "DataView"), Map2 = getNative(context, "Map"), Promise2 = getNative(context, "Promise"), Set = getNative(context, "Set"), WeakMap = getNative(context, "WeakMap"), nativeCreate = getNative(Object2, "create");
+ var metaMap = WeakMap && new WeakMap();
+ var realNames = {};
+ var dataViewCtorString = toSource(DataView), mapCtorString = toSource(Map2), promiseCtorString = toSource(Promise2), setCtorString = toSource(Set), weakMapCtorString = toSource(WeakMap);
+ var symbolProto = Symbol ? Symbol.prototype : undefined2, symbolValueOf = symbolProto ? symbolProto.valueOf : undefined2, symbolToString = symbolProto ? symbolProto.toString : undefined2;
+ function lodash(value) {
+ if (isObjectLike(value) && !isArray(value) && !(value instanceof LazyWrapper)) {
+ if (value instanceof LodashWrapper) {
+ return value;
+ }
+ if (hasOwnProperty.call(value, "__wrapped__")) {
+ return wrapperClone(value);
+ }
+ }
+ return new LodashWrapper(value);
+ }
+ var baseCreate = function() {
+ function object() {
+ }
+ return function(proto) {
+ if (!isObject(proto)) {
+ return {};
+ }
+ if (objectCreate) {
+ return objectCreate(proto);
+ }
+ object.prototype = proto;
+ var result2 = new object();
+ object.prototype = undefined2;
+ return result2;
+ };
+ }();
+ function baseLodash() {
+ }
+ function LodashWrapper(value, chainAll) {
+ this.__wrapped__ = value;
+ this.__actions__ = [];
+ this.__chain__ = !!chainAll;
+ this.__index__ = 0;
+ this.__values__ = undefined2;
+ }
+ lodash.templateSettings = {
+ "escape": reEscape,
+ "evaluate": reEvaluate,
+ "interpolate": reInterpolate,
+ "variable": "",
+ "imports": {
+ "_": lodash
+ }
+ };
+ lodash.prototype = baseLodash.prototype;
+ lodash.prototype.constructor = lodash;
+ LodashWrapper.prototype = baseCreate(baseLodash.prototype);
+ LodashWrapper.prototype.constructor = LodashWrapper;
+ function LazyWrapper(value) {
+ this.__wrapped__ = value;
+ this.__actions__ = [];
+ this.__dir__ = 1;
+ this.__filtered__ = false;
+ this.__iteratees__ = [];
+ this.__takeCount__ = MAX_ARRAY_LENGTH;
+ this.__views__ = [];
+ }
+ function lazyClone() {
+ var result2 = new LazyWrapper(this.__wrapped__);
+ result2.__actions__ = copyArray(this.__actions__);
+ result2.__dir__ = this.__dir__;
+ result2.__filtered__ = this.__filtered__;
+ result2.__iteratees__ = copyArray(this.__iteratees__);
+ result2.__takeCount__ = this.__takeCount__;
+ result2.__views__ = copyArray(this.__views__);
+ return result2;
+ }
+ function lazyReverse() {
+ if (this.__filtered__) {
+ var result2 = new LazyWrapper(this);
+ result2.__dir__ = -1;
+ result2.__filtered__ = true;
+ } else {
+ result2 = this.clone();
+ result2.__dir__ *= -1;
+ }
+ return result2;
+ }
+ function lazyValue() {
+ var array = this.__wrapped__.value(), dir = this.__dir__, isArr = isArray(array), isRight = dir < 0, arrLength = isArr ? array.length : 0, view = getView(0, arrLength, this.__views__), start = view.start, end = view.end, length = end - start, index = isRight ? end : start - 1, iteratees = this.__iteratees__, iterLength = iteratees.length, resIndex = 0, takeCount = nativeMin(length, this.__takeCount__);
+ if (!isArr || !isRight && arrLength == length && takeCount == length) {
+ return baseWrapperValue(array, this.__actions__);
+ }
+ var result2 = [];
+ outer:
+ while (length-- && resIndex < takeCount) {
+ index += dir;
+ var iterIndex = -1, value = array[index];
+ while (++iterIndex < iterLength) {
+ var data = iteratees[iterIndex], iteratee2 = data.iteratee, type = data.type, computed = iteratee2(value);
+ if (type == LAZY_MAP_FLAG) {
+ value = computed;
+ } else if (!computed) {
+ if (type == LAZY_FILTER_FLAG) {
+ continue outer;
+ } else {
+ break outer;
+ }
+ }
+ }
+ result2[resIndex++] = value;
+ }
+ return result2;
+ }
+ LazyWrapper.prototype = baseCreate(baseLodash.prototype);
+ LazyWrapper.prototype.constructor = LazyWrapper;
+ function Hash(entries) {
+ var index = -1, length = entries == null ? 0 : entries.length;
+ this.clear();
+ while (++index < length) {
+ var entry = entries[index];
+ this.set(entry[0], entry[1]);
+ }
+ }
+ function hashClear() {
+ this.__data__ = nativeCreate ? nativeCreate(null) : {};
+ this.size = 0;
+ }
+ function hashDelete(key) {
+ var result2 = this.has(key) && delete this.__data__[key];
+ this.size -= result2 ? 1 : 0;
+ return result2;
+ }
+ function hashGet(key) {
+ var data = this.__data__;
+ if (nativeCreate) {
+ var result2 = data[key];
+ return result2 === HASH_UNDEFINED ? undefined2 : result2;
+ }
+ return hasOwnProperty.call(data, key) ? data[key] : undefined2;
+ }
+ function hashHas(key) {
+ var data = this.__data__;
+ return nativeCreate ? data[key] !== undefined2 : hasOwnProperty.call(data, key);
+ }
+ function hashSet(key, value) {
+ var data = this.__data__;
+ this.size += this.has(key) ? 0 : 1;
+ data[key] = nativeCreate && value === undefined2 ? HASH_UNDEFINED : value;
+ return this;
+ }
+ Hash.prototype.clear = hashClear;
+ Hash.prototype["delete"] = hashDelete;
+ Hash.prototype.get = hashGet;
+ Hash.prototype.has = hashHas;
+ Hash.prototype.set = hashSet;
+ function ListCache(entries) {
+ var index = -1, length = entries == null ? 0 : entries.length;
+ this.clear();
+ while (++index < length) {
+ var entry = entries[index];
+ this.set(entry[0], entry[1]);
+ }
+ }
+ function listCacheClear() {
+ this.__data__ = [];
+ this.size = 0;
+ }
+ function listCacheDelete(key) {
+ var data = this.__data__, index = assocIndexOf(data, key);
+ if (index < 0) {
+ return false;
+ }
+ var lastIndex = data.length - 1;
+ if (index == lastIndex) {
+ data.pop();
+ } else {
+ splice.call(data, index, 1);
+ }
+ --this.size;
+ return true;
+ }
+ function listCacheGet(key) {
+ var data = this.__data__, index = assocIndexOf(data, key);
+ return index < 0 ? undefined2 : data[index][1];
+ }
+ function listCacheHas(key) {
+ return assocIndexOf(this.__data__, key) > -1;
+ }
+ function listCacheSet(key, value) {
+ var data = this.__data__, index = assocIndexOf(data, key);
+ if (index < 0) {
+ ++this.size;
+ data.push([key, value]);
+ } else {
+ data[index][1] = value;
+ }
+ return this;
+ }
+ ListCache.prototype.clear = listCacheClear;
+ ListCache.prototype["delete"] = listCacheDelete;
+ ListCache.prototype.get = listCacheGet;
+ ListCache.prototype.has = listCacheHas;
+ ListCache.prototype.set = listCacheSet;
+ function MapCache(entries) {
+ var index = -1, length = entries == null ? 0 : entries.length;
+ this.clear();
+ while (++index < length) {
+ var entry = entries[index];
+ this.set(entry[0], entry[1]);
+ }
+ }
+ function mapCacheClear() {
+ this.size = 0;
+ this.__data__ = {
+ "hash": new Hash(),
+ "map": new (Map2 || ListCache)(),
+ "string": new Hash()
+ };
+ }
+ function mapCacheDelete(key) {
+ var result2 = getMapData(this, key)["delete"](key);
+ this.size -= result2 ? 1 : 0;
+ return result2;
+ }
+ function mapCacheGet(key) {
+ return getMapData(this, key).get(key);
+ }
+ function mapCacheHas(key) {
+ return getMapData(this, key).has(key);
+ }
+ function mapCacheSet(key, value) {
+ var data = getMapData(this, key), size2 = data.size;
+ data.set(key, value);
+ this.size += data.size == size2 ? 0 : 1;
+ return this;
+ }
+ MapCache.prototype.clear = mapCacheClear;
+ MapCache.prototype["delete"] = mapCacheDelete;
+ MapCache.prototype.get = mapCacheGet;
+ MapCache.prototype.has = mapCacheHas;
+ MapCache.prototype.set = mapCacheSet;
+ function SetCache(values2) {
+ var index = -1, length = values2 == null ? 0 : values2.length;
+ this.__data__ = new MapCache();
+ while (++index < length) {
+ this.add(values2[index]);
+ }
+ }
+ function setCacheAdd(value) {
+ this.__data__.set(value, HASH_UNDEFINED);
+ return this;
+ }
+ function setCacheHas(value) {
+ return this.__data__.has(value);
+ }
+ SetCache.prototype.add = SetCache.prototype.push = setCacheAdd;
+ SetCache.prototype.has = setCacheHas;
+ function Stack(entries) {
+ var data = this.__data__ = new ListCache(entries);
+ this.size = data.size;
+ }
+ function stackClear() {
+ this.__data__ = new ListCache();
+ this.size = 0;
+ }
+ function stackDelete(key) {
+ var data = this.__data__, result2 = data["delete"](key);
+ this.size = data.size;
+ return result2;
+ }
+ function stackGet(key) {
+ return this.__data__.get(key);
+ }
+ function stackHas(key) {
+ return this.__data__.has(key);
+ }
+ function stackSet(key, value) {
+ var data = this.__data__;
+ if (data instanceof ListCache) {
+ var pairs = data.__data__;
+ if (!Map2 || pairs.length < LARGE_ARRAY_SIZE - 1) {
+ pairs.push([key, value]);
+ this.size = ++data.size;
+ return this;
+ }
+ data = this.__data__ = new MapCache(pairs);
+ }
+ data.set(key, value);
+ this.size = data.size;
+ return this;
+ }
+ Stack.prototype.clear = stackClear;
+ Stack.prototype["delete"] = stackDelete;
+ Stack.prototype.get = stackGet;
+ Stack.prototype.has = stackHas;
+ Stack.prototype.set = stackSet;
+ function arrayLikeKeys(value, inherited) {
+ var isArr = isArray(value), isArg = !isArr && isArguments(value), isBuff = !isArr && !isArg && isBuffer(value), isType = !isArr && !isArg && !isBuff && isTypedArray(value), skipIndexes = isArr || isArg || isBuff || isType, result2 = skipIndexes ? baseTimes(value.length, String2) : [], length = result2.length;
+ for (var key in value) {
+ if ((inherited || hasOwnProperty.call(value, key)) && !(skipIndexes && (key == "length" || isBuff && (key == "offset" || key == "parent") || isType && (key == "buffer" || key == "byteLength" || key == "byteOffset") || isIndex(key, length)))) {
+ result2.push(key);
+ }
+ }
+ return result2;
+ }
+ function arraySample(array) {
+ var length = array.length;
+ return length ? array[baseRandom(0, length - 1)] : undefined2;
+ }
+ function arraySampleSize(array, n) {
+ return shuffleSelf(copyArray(array), baseClamp(n, 0, array.length));
+ }
+ function arrayShuffle(array) {
+ return shuffleSelf(copyArray(array));
+ }
+ function assignMergeValue(object, key, value) {
+ if (value !== undefined2 && !eq(object[key], value) || value === undefined2 && !(key in object)) {
+ baseAssignValue(object, key, value);
+ }
+ }
+ function assignValue(object, key, value) {
+ var objValue = object[key];
+ if (!(hasOwnProperty.call(object, key) && eq(objValue, value)) || value === undefined2 && !(key in object)) {
+ baseAssignValue(object, key, value);
+ }
+ }
+ function assocIndexOf(array, key) {
+ var length = array.length;
+ while (length--) {
+ if (eq(array[length][0], key)) {
+ return length;
+ }
+ }
+ return -1;
+ }
+ function baseAggregator(collection, setter, iteratee2, accumulator) {
+ baseEach(collection, function(value, key, collection2) {
+ setter(accumulator, value, iteratee2(value), collection2);
+ });
+ return accumulator;
+ }
+ function baseAssign(object, source) {
+ return object && copyObject(source, keys(source), object);
+ }
+ function baseAssignIn(object, source) {
+ return object && copyObject(source, keysIn(source), object);
+ }
+ function baseAssignValue(object, key, value) {
+ if (key == "__proto__" && defineProperty) {
+ defineProperty(object, key, {
+ "configurable": true,
+ "enumerable": true,
+ "value": value,
+ "writable": true
+ });
+ } else {
+ object[key] = value;
+ }
+ }
+ function baseAt(object, paths) {
+ var index = -1, length = paths.length, result2 = Array2(length), skip = object == null;
+ while (++index < length) {
+ result2[index] = skip ? undefined2 : get(object, paths[index]);
+ }
+ return result2;
+ }
+ function baseClamp(number, lower, upper) {
+ if (number === number) {
+ if (upper !== undefined2) {
+ number = number <= upper ? number : upper;
+ }
+ if (lower !== undefined2) {
+ number = number >= lower ? number : lower;
+ }
+ }
+ return number;
+ }
+ function baseClone(value, bitmask, customizer, key, object, stack) {
+ var result2, isDeep = bitmask & CLONE_DEEP_FLAG, isFlat = bitmask & CLONE_FLAT_FLAG, isFull = bitmask & CLONE_SYMBOLS_FLAG;
+ if (customizer) {
+ result2 = object ? customizer(value, key, object, stack) : customizer(value);
+ }
+ if (result2 !== undefined2) {
+ return result2;
+ }
+ if (!isObject(value)) {
+ return value;
+ }
+ var isArr = isArray(value);
+ if (isArr) {
+ result2 = initCloneArray(value);
+ if (!isDeep) {
+ return copyArray(value, result2);
+ }
+ } else {
+ var tag = getTag(value), isFunc = tag == funcTag || tag == genTag;
+ if (isBuffer(value)) {
+ return cloneBuffer(value, isDeep);
+ }
+ if (tag == objectTag || tag == argsTag || isFunc && !object) {
+ result2 = isFlat || isFunc ? {} : initCloneObject(value);
+ if (!isDeep) {
+ return isFlat ? copySymbolsIn(value, baseAssignIn(result2, value)) : copySymbols(value, baseAssign(result2, value));
+ }
+ } else {
+ if (!cloneableTags[tag]) {
+ return object ? value : {};
+ }
+ result2 = initCloneByTag(value, tag, isDeep);
+ }
+ }
+ stack || (stack = new Stack());
+ var stacked = stack.get(value);
+ if (stacked) {
+ return stacked;
+ }
+ stack.set(value, result2);
+ if (isSet(value)) {
+ value.forEach(function(subValue) {
+ result2.add(baseClone(subValue, bitmask, customizer, subValue, value, stack));
+ });
+ } else if (isMap(value)) {
+ value.forEach(function(subValue, key2) {
+ result2.set(key2, baseClone(subValue, bitmask, customizer, key2, value, stack));
+ });
+ }
+ var keysFunc = isFull ? isFlat ? getAllKeysIn : getAllKeys : isFlat ? keysIn : keys;
+ var props = isArr ? undefined2 : keysFunc(value);
+ arrayEach(props || value, function(subValue, key2) {
+ if (props) {
+ key2 = subValue;
+ subValue = value[key2];
+ }
+ assignValue(result2, key2, baseClone(subValue, bitmask, customizer, key2, value, stack));
+ });
+ return result2;
+ }
+ function baseConforms(source) {
+ var props = keys(source);
+ return function(object) {
+ return baseConformsTo(object, source, props);
+ };
+ }
+ function baseConformsTo(object, source, props) {
+ var length = props.length;
+ if (object == null) {
+ return !length;
+ }
+ object = Object2(object);
+ while (length--) {
+ var key = props[length], predicate = source[key], value = object[key];
+ if (value === undefined2 && !(key in object) || !predicate(value)) {
+ return false;
+ }
+ }
+ return true;
+ }
+ function baseDelay(func, wait, args) {
+ if (typeof func != "function") {
+ throw new TypeError2(FUNC_ERROR_TEXT);
+ }
+ return setTimeout2(function() {
+ func.apply(undefined2, args);
+ }, wait);
+ }
+ function baseDifference(array, values2, iteratee2, comparator) {
+ var index = -1, includes2 = arrayIncludes, isCommon = true, length = array.length, result2 = [], valuesLength = values2.length;
+ if (!length) {
+ return result2;
+ }
+ if (iteratee2) {
+ values2 = arrayMap(values2, baseUnary(iteratee2));
+ }
+ if (comparator) {
+ includes2 = arrayIncludesWith;
+ isCommon = false;
+ } else if (values2.length >= LARGE_ARRAY_SIZE) {
+ includes2 = cacheHas;
+ isCommon = false;
+ values2 = new SetCache(values2);
+ }
+ outer:
+ while (++index < length) {
+ var value = array[index], computed = iteratee2 == null ? value : iteratee2(value);
+ value = comparator || value !== 0 ? value : 0;
+ if (isCommon && computed === computed) {
+ var valuesIndex = valuesLength;
+ while (valuesIndex--) {
+ if (values2[valuesIndex] === computed) {
+ continue outer;
+ }
+ }
+ result2.push(value);
+ } else if (!includes2(values2, computed, comparator)) {
+ result2.push(value);
+ }
+ }
+ return result2;
+ }
+ var baseEach = createBaseEach(baseForOwn);
+ var baseEachRight = createBaseEach(baseForOwnRight, true);
+ function baseEvery(collection, predicate) {
+ var result2 = true;
+ baseEach(collection, function(value, index, collection2) {
+ result2 = !!predicate(value, index, collection2);
+ return result2;
+ });
+ return result2;
+ }
+ function baseExtremum(array, iteratee2, comparator) {
+ var index = -1, length = array.length;
+ while (++index < length) {
+ var value = array[index], current = iteratee2(value);
+ if (current != null && (computed === undefined2 ? current === current && !isSymbol(current) : comparator(current, computed))) {
+ var computed = current, result2 = value;
+ }
+ }
+ return result2;
+ }
+ function baseFill(array, value, start, end) {
+ var length = array.length;
+ start = toInteger(start);
+ if (start < 0) {
+ start = -start > length ? 0 : length + start;
+ }
+ end = end === undefined2 || end > length ? length : toInteger(end);
+ if (end < 0) {
+ end += length;
+ }
+ end = start > end ? 0 : toLength(end);
+ while (start < end) {
+ array[start++] = value;
+ }
+ return array;
+ }
+ function baseFilter(collection, predicate) {
+ var result2 = [];
+ baseEach(collection, function(value, index, collection2) {
+ if (predicate(value, index, collection2)) {
+ result2.push(value);
+ }
+ });
+ return result2;
+ }
+ function baseFlatten(array, depth, predicate, isStrict, result2) {
+ var index = -1, length = array.length;
+ predicate || (predicate = isFlattenable);
+ result2 || (result2 = []);
+ while (++index < length) {
+ var value = array[index];
+ if (depth > 0 && predicate(value)) {
+ if (depth > 1) {
+ baseFlatten(value, depth - 1, predicate, isStrict, result2);
+ } else {
+ arrayPush(result2, value);
+ }
+ } else if (!isStrict) {
+ result2[result2.length] = value;
+ }
+ }
+ return result2;
+ }
+ var baseFor = createBaseFor();
+ var baseForRight = createBaseFor(true);
+ function baseForOwn(object, iteratee2) {
+ return object && baseFor(object, iteratee2, keys);
+ }
+ function baseForOwnRight(object, iteratee2) {
+ return object && baseForRight(object, iteratee2, keys);
+ }
+ function baseFunctions(object, props) {
+ return arrayFilter(props, function(key) {
+ return isFunction(object[key]);
+ });
+ }
+ function baseGet(object, path) {
+ path = castPath(path, object);
+ var index = 0, length = path.length;
+ while (object != null && index < length) {
+ object = object[toKey(path[index++])];
+ }
+ return index && index == length ? object : undefined2;
+ }
+ function baseGetAllKeys(object, keysFunc, symbolsFunc) {
+ var result2 = keysFunc(object);
+ return isArray(object) ? result2 : arrayPush(result2, symbolsFunc(object));
+ }
+ function baseGetTag(value) {
+ if (value == null) {
+ return value === undefined2 ? undefinedTag : nullTag;
+ }
+ return symToStringTag && symToStringTag in Object2(value) ? getRawTag(value) : objectToString(value);
+ }
+ function baseGt(value, other) {
+ return value > other;
+ }
+ function baseHas(object, key) {
+ return object != null && hasOwnProperty.call(object, key);
+ }
+ function baseHasIn(object, key) {
+ return object != null && key in Object2(object);
+ }
+ function baseInRange(number, start, end) {
+ return number >= nativeMin(start, end) && number < nativeMax(start, end);
+ }
+ function baseIntersection(arrays, iteratee2, comparator) {
+ var includes2 = comparator ? arrayIncludesWith : arrayIncludes, length = arrays[0].length, othLength = arrays.length, othIndex = othLength, caches = Array2(othLength), maxLength = Infinity, result2 = [];
+ while (othIndex--) {
+ var array = arrays[othIndex];
+ if (othIndex && iteratee2) {
+ array = arrayMap(array, baseUnary(iteratee2));
+ }
+ maxLength = nativeMin(array.length, maxLength);
+ caches[othIndex] = !comparator && (iteratee2 || length >= 120 && array.length >= 120) ? new SetCache(othIndex && array) : undefined2;
+ }
+ array = arrays[0];
+ var index = -1, seen = caches[0];
+ outer:
+ while (++index < length && result2.length < maxLength) {
+ var value = array[index], computed = iteratee2 ? iteratee2(value) : value;
+ value = comparator || value !== 0 ? value : 0;
+ if (!(seen ? cacheHas(seen, computed) : includes2(result2, computed, comparator))) {
+ othIndex = othLength;
+ while (--othIndex) {
+ var cache = caches[othIndex];
+ if (!(cache ? cacheHas(cache, computed) : includes2(arrays[othIndex], computed, comparator))) {
+ continue outer;
+ }
+ }
+ if (seen) {
+ seen.push(computed);
+ }
+ result2.push(value);
+ }
+ }
+ return result2;
+ }
+ function baseInverter(object, setter, iteratee2, accumulator) {
+ baseForOwn(object, function(value, key, object2) {
+ setter(accumulator, iteratee2(value), key, object2);
+ });
+ return accumulator;
+ }
+ function baseInvoke(object, path, args) {
+ path = castPath(path, object);
+ object = parent(object, path);
+ var func = object == null ? object : object[toKey(last(path))];
+ return func == null ? undefined2 : apply(func, object, args);
+ }
+ function baseIsArguments(value) {
+ return isObjectLike(value) && baseGetTag(value) == argsTag;
+ }
+ function baseIsArrayBuffer(value) {
+ return isObjectLike(value) && baseGetTag(value) == arrayBufferTag;
+ }
+ function baseIsDate(value) {
+ return isObjectLike(value) && baseGetTag(value) == dateTag;
+ }
+ function baseIsEqual(value, other, bitmask, customizer, stack) {
+ if (value === other) {
+ return true;
+ }
+ if (value == null || other == null || !isObjectLike(value) && !isObjectLike(other)) {
+ return value !== value && other !== other;
+ }
+ return baseIsEqualDeep(value, other, bitmask, customizer, baseIsEqual, stack);
+ }
+ function baseIsEqualDeep(object, other, bitmask, customizer, equalFunc, stack) {
+ var objIsArr = isArray(object), othIsArr = isArray(other), objTag = objIsArr ? arrayTag : getTag(object), othTag = othIsArr ? arrayTag : getTag(other);
+ objTag = objTag == argsTag ? objectTag : objTag;
+ othTag = othTag == argsTag ? objectTag : othTag;
+ var objIsObj = objTag == objectTag, othIsObj = othTag == objectTag, isSameTag = objTag == othTag;
+ if (isSameTag && isBuffer(object)) {
+ if (!isBuffer(other)) {
+ return false;
+ }
+ objIsArr = true;
+ objIsObj = false;
+ }
+ if (isSameTag && !objIsObj) {
+ stack || (stack = new Stack());
+ return objIsArr || isTypedArray(object) ? equalArrays(object, other, bitmask, customizer, equalFunc, stack) : equalByTag(object, other, objTag, bitmask, customizer, equalFunc, stack);
+ }
+ if (!(bitmask & COMPARE_PARTIAL_FLAG)) {
+ var objIsWrapped = objIsObj && hasOwnProperty.call(object, "__wrapped__"), othIsWrapped = othIsObj && hasOwnProperty.call(other, "__wrapped__");
+ if (objIsWrapped || othIsWrapped) {
+ var objUnwrapped = objIsWrapped ? object.value() : object, othUnwrapped = othIsWrapped ? other.value() : other;
+ stack || (stack = new Stack());
+ return equalFunc(objUnwrapped, othUnwrapped, bitmask, customizer, stack);
+ }
+ }
+ if (!isSameTag) {
+ return false;
+ }
+ stack || (stack = new Stack());
+ return equalObjects(object, other, bitmask, customizer, equalFunc, stack);
+ }
+ function baseIsMap(value) {
+ return isObjectLike(value) && getTag(value) == mapTag;
+ }
+ function baseIsMatch(object, source, matchData, customizer) {
+ var index = matchData.length, length = index, noCustomizer = !customizer;
+ if (object == null) {
+ return !length;
+ }
+ object = Object2(object);
+ while (index--) {
+ var data = matchData[index];
+ if (noCustomizer && data[2] ? data[1] !== object[data[0]] : !(data[0] in object)) {
+ return false;
+ }
+ }
+ while (++index < length) {
+ data = matchData[index];
+ var key = data[0], objValue = object[key], srcValue = data[1];
+ if (noCustomizer && data[2]) {
+ if (objValue === undefined2 && !(key in object)) {
+ return false;
+ }
+ } else {
+ var stack = new Stack();
+ if (customizer) {
+ var result2 = customizer(objValue, srcValue, key, object, source, stack);
+ }
+ if (!(result2 === undefined2 ? baseIsEqual(srcValue, objValue, COMPARE_PARTIAL_FLAG | COMPARE_UNORDERED_FLAG, customizer, stack) : result2)) {
+ return false;
+ }
+ }
+ }
+ return true;
+ }
+ function baseIsNative(value) {
+ if (!isObject(value) || isMasked(value)) {
+ return false;
+ }
+ var pattern = isFunction(value) ? reIsNative : reIsHostCtor;
+ return pattern.test(toSource(value));
+ }
+ function baseIsRegExp(value) {
+ return isObjectLike(value) && baseGetTag(value) == regexpTag;
+ }
+ function baseIsSet(value) {
+ return isObjectLike(value) && getTag(value) == setTag;
+ }
+ function baseIsTypedArray(value) {
+ return isObjectLike(value) && isLength(value.length) && !!typedArrayTags[baseGetTag(value)];
+ }
+ function baseIteratee(value) {
+ if (typeof value == "function") {
+ return value;
+ }
+ if (value == null) {
+ return identity;
+ }
+ if (typeof value == "object") {
+ return isArray(value) ? baseMatchesProperty(value[0], value[1]) : baseMatches(value);
+ }
+ return property(value);
+ }
+ function baseKeys(object) {
+ if (!isPrototype(object)) {
+ return nativeKeys(object);
+ }
+ var result2 = [];
+ for (var key in Object2(object)) {
+ if (hasOwnProperty.call(object, key) && key != "constructor") {
+ result2.push(key);
+ }
+ }
+ return result2;
+ }
+ function baseKeysIn(object) {
+ if (!isObject(object)) {
+ return nativeKeysIn(object);
+ }
+ var isProto = isPrototype(object), result2 = [];
+ for (var key in object) {
+ if (!(key == "constructor" && (isProto || !hasOwnProperty.call(object, key)))) {
+ result2.push(key);
+ }
+ }
+ return result2;
+ }
+ function baseLt(value, other) {
+ return value < other;
+ }
+ function baseMap(collection, iteratee2) {
+ var index = -1, result2 = isArrayLike(collection) ? Array2(collection.length) : [];
+ baseEach(collection, function(value, key, collection2) {
+ result2[++index] = iteratee2(value, key, collection2);
+ });
+ return result2;
+ }
+ function baseMatches(source) {
+ var matchData = getMatchData(source);
+ if (matchData.length == 1 && matchData[0][2]) {
+ return matchesStrictComparable(matchData[0][0], matchData[0][1]);
+ }
+ return function(object) {
+ return object === source || baseIsMatch(object, source, matchData);
+ };
+ }
+ function baseMatchesProperty(path, srcValue) {
+ if (isKey(path) && isStrictComparable(srcValue)) {
+ return matchesStrictComparable(toKey(path), srcValue);
+ }
+ return function(object) {
+ var objValue = get(object, path);
+ return objValue === undefined2 && objValue === srcValue ? hasIn(object, path) : baseIsEqual(srcValue, objValue, COMPARE_PARTIAL_FLAG | COMPARE_UNORDERED_FLAG);
+ };
+ }
+ function baseMerge(object, source, srcIndex, customizer, stack) {
+ if (object === source) {
+ return;
+ }
+ baseFor(source, function(srcValue, key) {
+ stack || (stack = new Stack());
+ if (isObject(srcValue)) {
+ baseMergeDeep(object, source, key, srcIndex, baseMerge, customizer, stack);
+ } else {
+ var newValue = customizer ? customizer(safeGet(object, key), srcValue, key + "", object, source, stack) : undefined2;
+ if (newValue === undefined2) {
+ newValue = srcValue;
+ }
+ assignMergeValue(object, key, newValue);
+ }
+ }, keysIn);
+ }
+ function baseMergeDeep(object, source, key, srcIndex, mergeFunc, customizer, stack) {
+ var objValue = safeGet(object, key), srcValue = safeGet(source, key), stacked = stack.get(srcValue);
+ if (stacked) {
+ assignMergeValue(object, key, stacked);
+ return;
+ }
+ var newValue = customizer ? customizer(objValue, srcValue, key + "", object, source, stack) : undefined2;
+ var isCommon = newValue === undefined2;
+ if (isCommon) {
+ var isArr = isArray(srcValue), isBuff = !isArr && isBuffer(srcValue), isTyped = !isArr && !isBuff && isTypedArray(srcValue);
+ newValue = srcValue;
+ if (isArr || isBuff || isTyped) {
+ if (isArray(objValue)) {
+ newValue = objValue;
+ } else if (isArrayLikeObject(objValue)) {
+ newValue = copyArray(objValue);
+ } else if (isBuff) {
+ isCommon = false;
+ newValue = cloneBuffer(srcValue, true);
+ } else if (isTyped) {
+ isCommon = false;
+ newValue = cloneTypedArray(srcValue, true);
+ } else {
+ newValue = [];
+ }
+ } else if (isPlainObject(srcValue) || isArguments(srcValue)) {
+ newValue = objValue;
+ if (isArguments(objValue)) {
+ newValue = toPlainObject(objValue);
+ } else if (!isObject(objValue) || isFunction(objValue)) {
+ newValue = initCloneObject(srcValue);
+ }
+ } else {
+ isCommon = false;
+ }
+ }
+ if (isCommon) {
+ stack.set(srcValue, newValue);
+ mergeFunc(newValue, srcValue, srcIndex, customizer, stack);
+ stack["delete"](srcValue);
+ }
+ assignMergeValue(object, key, newValue);
+ }
+ function baseNth(array, n) {
+ var length = array.length;
+ if (!length) {
+ return;
+ }
+ n += n < 0 ? length : 0;
+ return isIndex(n, length) ? array[n] : undefined2;
+ }
+ function baseOrderBy(collection, iteratees, orders) {
+ if (iteratees.length) {
+ iteratees = arrayMap(iteratees, function(iteratee2) {
+ if (isArray(iteratee2)) {
+ return function(value) {
+ return baseGet(value, iteratee2.length === 1 ? iteratee2[0] : iteratee2);
+ };
+ }
+ return iteratee2;
+ });
+ } else {
+ iteratees = [identity];
+ }
+ var index = -1;
+ iteratees = arrayMap(iteratees, baseUnary(getIteratee()));
+ var result2 = baseMap(collection, function(value, key, collection2) {
+ var criteria = arrayMap(iteratees, function(iteratee2) {
+ return iteratee2(value);
+ });
+ return { "criteria": criteria, "index": ++index, "value": value };
+ });
+ return baseSortBy(result2, function(object, other) {
+ return compareMultiple(object, other, orders);
+ });
+ }
+ function basePick(object, paths) {
+ return basePickBy(object, paths, function(value, path) {
+ return hasIn(object, path);
+ });
+ }
+ function basePickBy(object, paths, predicate) {
+ var index = -1, length = paths.length, result2 = {};
+ while (++index < length) {
+ var path = paths[index], value = baseGet(object, path);
+ if (predicate(value, path)) {
+ baseSet(result2, castPath(path, object), value);
+ }
+ }
+ return result2;
+ }
+ function basePropertyDeep(path) {
+ return function(object) {
+ return baseGet(object, path);
+ };
+ }
+ function basePullAll(array, values2, iteratee2, comparator) {
+ var indexOf2 = comparator ? baseIndexOfWith : baseIndexOf, index = -1, length = values2.length, seen = array;
+ if (array === values2) {
+ values2 = copyArray(values2);
+ }
+ if (iteratee2) {
+ seen = arrayMap(array, baseUnary(iteratee2));
+ }
+ while (++index < length) {
+ var fromIndex = 0, value = values2[index], computed = iteratee2 ? iteratee2(value) : value;
+ while ((fromIndex = indexOf2(seen, computed, fromIndex, comparator)) > -1) {
+ if (seen !== array) {
+ splice.call(seen, fromIndex, 1);
+ }
+ splice.call(array, fromIndex, 1);
+ }
+ }
+ return array;
+ }
+ function basePullAt(array, indexes) {
+ var length = array ? indexes.length : 0, lastIndex = length - 1;
+ while (length--) {
+ var index = indexes[length];
+ if (length == lastIndex || index !== previous) {
+ var previous = index;
+ if (isIndex(index)) {
+ splice.call(array, index, 1);
+ } else {
+ baseUnset(array, index);
+ }
+ }
+ }
+ return array;
+ }
+ function baseRandom(lower, upper) {
+ return lower + nativeFloor(nativeRandom() * (upper - lower + 1));
+ }
+ function baseRange(start, end, step, fromRight) {
+ var index = -1, length = nativeMax(nativeCeil((end - start) / (step || 1)), 0), result2 = Array2(length);
+ while (length--) {
+ result2[fromRight ? length : ++index] = start;
+ start += step;
+ }
+ return result2;
+ }
+ function baseRepeat(string, n) {
+ var result2 = "";
+ if (!string || n < 1 || n > MAX_SAFE_INTEGER) {
+ return result2;
+ }
+ do {
+ if (n % 2) {
+ result2 += string;
+ }
+ n = nativeFloor(n / 2);
+ if (n) {
+ string += string;
+ }
+ } while (n);
+ return result2;
+ }
+ function baseRest(func, start) {
+ return setToString(overRest(func, start, identity), func + "");
+ }
+ function baseSample(collection) {
+ return arraySample(values(collection));
+ }
+ function baseSampleSize(collection, n) {
+ var array = values(collection);
+ return shuffleSelf(array, baseClamp(n, 0, array.length));
+ }
+ function baseSet(object, path, value, customizer) {
+ if (!isObject(object)) {
+ return object;
+ }
+ path = castPath(path, object);
+ var index = -1, length = path.length, lastIndex = length - 1, nested = object;
+ while (nested != null && ++index < length) {
+ var key = toKey(path[index]), newValue = value;
+ if (key === "__proto__" || key === "constructor" || key === "prototype") {
+ return object;
+ }
+ if (index != lastIndex) {
+ var objValue = nested[key];
+ newValue = customizer ? customizer(objValue, key, nested) : undefined2;
+ if (newValue === undefined2) {
+ newValue = isObject(objValue) ? objValue : isIndex(path[index + 1]) ? [] : {};
+ }
+ }
+ assignValue(nested, key, newValue);
+ nested = nested[key];
+ }
+ return object;
+ }
+ var baseSetData = !metaMap ? identity : function(func, data) {
+ metaMap.set(func, data);
+ return func;
+ };
+ var baseSetToString = !defineProperty ? identity : function(func, string) {
+ return defineProperty(func, "toString", {
+ "configurable": true,
+ "enumerable": false,
+ "value": constant(string),
+ "writable": true
+ });
+ };
+ function baseShuffle(collection) {
+ return shuffleSelf(values(collection));
+ }
+ function baseSlice(array, start, end) {
+ var index = -1, length = array.length;
+ if (start < 0) {
+ start = -start > length ? 0 : length + start;
+ }
+ end = end > length ? length : end;
+ if (end < 0) {
+ end += length;
+ }
+ length = start > end ? 0 : end - start >>> 0;
+ start >>>= 0;
+ var result2 = Array2(length);
+ while (++index < length) {
+ result2[index] = array[index + start];
+ }
+ return result2;
+ }
+ function baseSome(collection, predicate) {
+ var result2;
+ baseEach(collection, function(value, index, collection2) {
+ result2 = predicate(value, index, collection2);
+ return !result2;
+ });
+ return !!result2;
+ }
+ function baseSortedIndex(array, value, retHighest) {
+ var low = 0, high = array == null ? low : array.length;
+ if (typeof value == "number" && value === value && high <= HALF_MAX_ARRAY_LENGTH) {
+ while (low < high) {
+ var mid = low + high >>> 1, computed = array[mid];
+ if (computed !== null && !isSymbol(computed) && (retHighest ? computed <= value : computed < value)) {
+ low = mid + 1;
+ } else {
+ high = mid;
+ }
+ }
+ return high;
+ }
+ return baseSortedIndexBy(array, value, identity, retHighest);
+ }
+ function baseSortedIndexBy(array, value, iteratee2, retHighest) {
+ var low = 0, high = array == null ? 0 : array.length;
+ if (high === 0) {
+ return 0;
+ }
+ value = iteratee2(value);
+ var valIsNaN = value !== value, valIsNull = value === null, valIsSymbol = isSymbol(value), valIsUndefined = value === undefined2;
+ while (low < high) {
+ var mid = nativeFloor((low + high) / 2), computed = iteratee2(array[mid]), othIsDefined = computed !== undefined2, othIsNull = computed === null, othIsReflexive = computed === computed, othIsSymbol = isSymbol(computed);
+ if (valIsNaN) {
+ var setLow = retHighest || othIsReflexive;
+ } else if (valIsUndefined) {
+ setLow = othIsReflexive && (retHighest || othIsDefined);
+ } else if (valIsNull) {
+ setLow = othIsReflexive && othIsDefined && (retHighest || !othIsNull);
+ } else if (valIsSymbol) {
+ setLow = othIsReflexive && othIsDefined && !othIsNull && (retHighest || !othIsSymbol);
+ } else if (othIsNull || othIsSymbol) {
+ setLow = false;
+ } else {
+ setLow = retHighest ? computed <= value : computed < value;
+ }
+ if (setLow) {
+ low = mid + 1;
+ } else {
+ high = mid;
+ }
+ }
+ return nativeMin(high, MAX_ARRAY_INDEX);
+ }
+ function baseSortedUniq(array, iteratee2) {
+ var index = -1, length = array.length, resIndex = 0, result2 = [];
+ while (++index < length) {
+ var value = array[index], computed = iteratee2 ? iteratee2(value) : value;
+ if (!index || !eq(computed, seen)) {
+ var seen = computed;
+ result2[resIndex++] = value === 0 ? 0 : value;
+ }
+ }
+ return result2;
+ }
+ function baseToNumber(value) {
+ if (typeof value == "number") {
+ return value;
+ }
+ if (isSymbol(value)) {
+ return NAN;
+ }
+ return +value;
+ }
+ function baseToString(value) {
+ if (typeof value == "string") {
+ return value;
+ }
+ if (isArray(value)) {
+ return arrayMap(value, baseToString) + "";
+ }
+ if (isSymbol(value)) {
+ return symbolToString ? symbolToString.call(value) : "";
+ }
+ var result2 = value + "";
+ return result2 == "0" && 1 / value == -INFINITY ? "-0" : result2;
+ }
+ function baseUniq(array, iteratee2, comparator) {
+ var index = -1, includes2 = arrayIncludes, length = array.length, isCommon = true, result2 = [], seen = result2;
+ if (comparator) {
+ isCommon = false;
+ includes2 = arrayIncludesWith;
+ } else if (length >= LARGE_ARRAY_SIZE) {
+ var set2 = iteratee2 ? null : createSet(array);
+ if (set2) {
+ return setToArray(set2);
+ }
+ isCommon = false;
+ includes2 = cacheHas;
+ seen = new SetCache();
+ } else {
+ seen = iteratee2 ? [] : result2;
+ }
+ outer:
+ while (++index < length) {
+ var value = array[index], computed = iteratee2 ? iteratee2(value) : value;
+ value = comparator || value !== 0 ? value : 0;
+ if (isCommon && computed === computed) {
+ var seenIndex = seen.length;
+ while (seenIndex--) {
+ if (seen[seenIndex] === computed) {
+ continue outer;
+ }
+ }
+ if (iteratee2) {
+ seen.push(computed);
+ }
+ result2.push(value);
+ } else if (!includes2(seen, computed, comparator)) {
+ if (seen !== result2) {
+ seen.push(computed);
+ }
+ result2.push(value);
+ }
+ }
+ return result2;
+ }
+ function baseUnset(object, path) {
+ path = castPath(path, object);
+ object = parent(object, path);
+ return object == null || delete object[toKey(last(path))];
+ }
+ function baseUpdate(object, path, updater, customizer) {
+ return baseSet(object, path, updater(baseGet(object, path)), customizer);
+ }
+ function baseWhile(array, predicate, isDrop, fromRight) {
+ var length = array.length, index = fromRight ? length : -1;
+ while ((fromRight ? index-- : ++index < length) && predicate(array[index], index, array)) {
+ }
+ return isDrop ? baseSlice(array, fromRight ? 0 : index, fromRight ? index + 1 : length) : baseSlice(array, fromRight ? index + 1 : 0, fromRight ? length : index);
+ }
+ function baseWrapperValue(value, actions) {
+ var result2 = value;
+ if (result2 instanceof LazyWrapper) {
+ result2 = result2.value();
+ }
+ return arrayReduce(actions, function(result3, action) {
+ return action.func.apply(action.thisArg, arrayPush([result3], action.args));
+ }, result2);
+ }
+ function baseXor(arrays, iteratee2, comparator) {
+ var length = arrays.length;
+ if (length < 2) {
+ return length ? baseUniq(arrays[0]) : [];
+ }
+ var index = -1, result2 = Array2(length);
+ while (++index < length) {
+ var array = arrays[index], othIndex = -1;
+ while (++othIndex < length) {
+ if (othIndex != index) {
+ result2[index] = baseDifference(result2[index] || array, arrays[othIndex], iteratee2, comparator);
+ }
+ }
+ }
+ return baseUniq(baseFlatten(result2, 1), iteratee2, comparator);
+ }
+ function baseZipObject(props, values2, assignFunc) {
+ var index = -1, length = props.length, valsLength = values2.length, result2 = {};
+ while (++index < length) {
+ var value = index < valsLength ? values2[index] : undefined2;
+ assignFunc(result2, props[index], value);
+ }
+ return result2;
+ }
+ function castArrayLikeObject(value) {
+ return isArrayLikeObject(value) ? value : [];
+ }
+ function castFunction(value) {
+ return typeof value == "function" ? value : identity;
+ }
+ function castPath(value, object) {
+ if (isArray(value)) {
+ return value;
+ }
+ return isKey(value, object) ? [value] : stringToPath(toString(value));
+ }
+ var castRest = baseRest;
+ function castSlice(array, start, end) {
+ var length = array.length;
+ end = end === undefined2 ? length : end;
+ return !start && end >= length ? array : baseSlice(array, start, end);
+ }
+ var clearTimeout2 = ctxClearTimeout || function(id) {
+ return root.clearTimeout(id);
+ };
+ function cloneBuffer(buffer, isDeep) {
+ if (isDeep) {
+ return buffer.slice();
+ }
+ var length = buffer.length, result2 = allocUnsafe ? allocUnsafe(length) : new buffer.constructor(length);
+ buffer.copy(result2);
+ return result2;
+ }
+ function cloneArrayBuffer(arrayBuffer) {
+ var result2 = new arrayBuffer.constructor(arrayBuffer.byteLength);
+ new Uint8Array2(result2).set(new Uint8Array2(arrayBuffer));
+ return result2;
+ }
+ function cloneDataView(dataView, isDeep) {
+ var buffer = isDeep ? cloneArrayBuffer(dataView.buffer) : dataView.buffer;
+ return new dataView.constructor(buffer, dataView.byteOffset, dataView.byteLength);
+ }
+ function cloneRegExp(regexp) {
+ var result2 = new regexp.constructor(regexp.source, reFlags.exec(regexp));
+ result2.lastIndex = regexp.lastIndex;
+ return result2;
+ }
+ function cloneSymbol(symbol) {
+ return symbolValueOf ? Object2(symbolValueOf.call(symbol)) : {};
+ }
+ function cloneTypedArray(typedArray, isDeep) {
+ var buffer = isDeep ? cloneArrayBuffer(typedArray.buffer) : typedArray.buffer;
+ return new typedArray.constructor(buffer, typedArray.byteOffset, typedArray.length);
+ }
+ function compareAscending(value, other) {
+ if (value !== other) {
+ var valIsDefined = value !== undefined2, valIsNull = value === null, valIsReflexive = value === value, valIsSymbol = isSymbol(value);
+ var othIsDefined = other !== undefined2, othIsNull = other === null, othIsReflexive = other === other, othIsSymbol = isSymbol(other);
+ if (!othIsNull && !othIsSymbol && !valIsSymbol && value > other || valIsSymbol && othIsDefined && othIsReflexive && !othIsNull && !othIsSymbol || valIsNull && othIsDefined && othIsReflexive || !valIsDefined && othIsReflexive || !valIsReflexive) {
+ return 1;
+ }
+ if (!valIsNull && !valIsSymbol && !othIsSymbol && value < other || othIsSymbol && valIsDefined && valIsReflexive && !valIsNull && !valIsSymbol || othIsNull && valIsDefined && valIsReflexive || !othIsDefined && valIsReflexive || !othIsReflexive) {
+ return -1;
+ }
+ }
+ return 0;
+ }
+ function compareMultiple(object, other, orders) {
+ var index = -1, objCriteria = object.criteria, othCriteria = other.criteria, length = objCriteria.length, ordersLength = orders.length;
+ while (++index < length) {
+ var result2 = compareAscending(objCriteria[index], othCriteria[index]);
+ if (result2) {
+ if (index >= ordersLength) {
+ return result2;
+ }
+ var order = orders[index];
+ return result2 * (order == "desc" ? -1 : 1);
+ }
+ }
+ return object.index - other.index;
+ }
+ function composeArgs(args, partials, holders, isCurried) {
+ var argsIndex = -1, argsLength = args.length, holdersLength = holders.length, leftIndex = -1, leftLength = partials.length, rangeLength = nativeMax(argsLength - holdersLength, 0), result2 = Array2(leftLength + rangeLength), isUncurried = !isCurried;
+ while (++leftIndex < leftLength) {
+ result2[leftIndex] = partials[leftIndex];
+ }
+ while (++argsIndex < holdersLength) {
+ if (isUncurried || argsIndex < argsLength) {
+ result2[holders[argsIndex]] = args[argsIndex];
+ }
+ }
+ while (rangeLength--) {
+ result2[leftIndex++] = args[argsIndex++];
+ }
+ return result2;
+ }
+ function composeArgsRight(args, partials, holders, isCurried) {
+ var argsIndex = -1, argsLength = args.length, holdersIndex = -1, holdersLength = holders.length, rightIndex = -1, rightLength = partials.length, rangeLength = nativeMax(argsLength - holdersLength, 0), result2 = Array2(rangeLength + rightLength), isUncurried = !isCurried;
+ while (++argsIndex < rangeLength) {
+ result2[argsIndex] = args[argsIndex];
+ }
+ var offset = argsIndex;
+ while (++rightIndex < rightLength) {
+ result2[offset + rightIndex] = partials[rightIndex];
+ }
+ while (++holdersIndex < holdersLength) {
+ if (isUncurried || argsIndex < argsLength) {
+ result2[offset + holders[holdersIndex]] = args[argsIndex++];
+ }
+ }
+ return result2;
+ }
+ function copyArray(source, array) {
+ var index = -1, length = source.length;
+ array || (array = Array2(length));
+ while (++index < length) {
+ array[index] = source[index];
+ }
+ return array;
+ }
+ function copyObject(source, props, object, customizer) {
+ var isNew = !object;
+ object || (object = {});
+ var index = -1, length = props.length;
+ while (++index < length) {
+ var key = props[index];
+ var newValue = customizer ? customizer(object[key], source[key], key, object, source) : undefined2;
+ if (newValue === undefined2) {
+ newValue = source[key];
+ }
+ if (isNew) {
+ baseAssignValue(object, key, newValue);
+ } else {
+ assignValue(object, key, newValue);
+ }
+ }
+ return object;
+ }
+ function copySymbols(source, object) {
+ return copyObject(source, getSymbols(source), object);
+ }
+ function copySymbolsIn(source, object) {
+ return copyObject(source, getSymbolsIn(source), object);
+ }
+ function createAggregator(setter, initializer) {
+ return function(collection, iteratee2) {
+ var func = isArray(collection) ? arrayAggregator : baseAggregator, accumulator = initializer ? initializer() : {};
+ return func(collection, setter, getIteratee(iteratee2, 2), accumulator);
+ };
+ }
+ function createAssigner(assigner) {
+ return baseRest(function(object, sources) {
+ var index = -1, length = sources.length, customizer = length > 1 ? sources[length - 1] : undefined2, guard = length > 2 ? sources[2] : undefined2;
+ customizer = assigner.length > 3 && typeof customizer == "function" ? (length--, customizer) : undefined2;
+ if (guard && isIterateeCall(sources[0], sources[1], guard)) {
+ customizer = length < 3 ? undefined2 : customizer;
+ length = 1;
+ }
+ object = Object2(object);
+ while (++index < length) {
+ var source = sources[index];
+ if (source) {
+ assigner(object, source, index, customizer);
+ }
+ }
+ return object;
+ });
+ }
+ function createBaseEach(eachFunc, fromRight) {
+ return function(collection, iteratee2) {
+ if (collection == null) {
+ return collection;
+ }
+ if (!isArrayLike(collection)) {
+ return eachFunc(collection, iteratee2);
+ }
+ var length = collection.length, index = fromRight ? length : -1, iterable = Object2(collection);
+ while (fromRight ? index-- : ++index < length) {
+ if (iteratee2(iterable[index], index, iterable) === false) {
+ break;
+ }
+ }
+ return collection;
+ };
+ }
+ function createBaseFor(fromRight) {
+ return function(object, iteratee2, keysFunc) {
+ var index = -1, iterable = Object2(object), props = keysFunc(object), length = props.length;
+ while (length--) {
+ var key = props[fromRight ? length : ++index];
+ if (iteratee2(iterable[key], key, iterable) === false) {
+ break;
+ }
+ }
+ return object;
+ };
+ }
+ function createBind(func, bitmask, thisArg) {
+ var isBind = bitmask & WRAP_BIND_FLAG, Ctor = createCtor(func);
+ function wrapper() {
+ var fn = this && this !== root && this instanceof wrapper ? Ctor : func;
+ return fn.apply(isBind ? thisArg : this, arguments);
+ }
+ return wrapper;
+ }
+ function createCaseFirst(methodName) {
+ return function(string) {
+ string = toString(string);
+ var strSymbols = hasUnicode(string) ? stringToArray(string) : undefined2;
+ var chr = strSymbols ? strSymbols[0] : string.charAt(0);
+ var trailing = strSymbols ? castSlice(strSymbols, 1).join("") : string.slice(1);
+ return chr[methodName]() + trailing;
+ };
+ }
+ function createCompounder(callback) {
+ return function(string) {
+ return arrayReduce(words(deburr(string).replace(reApos, "")), callback, "");
+ };
+ }
+ function createCtor(Ctor) {
+ return function() {
+ var args = arguments;
+ switch (args.length) {
+ case 0:
+ return new Ctor();
+ case 1:
+ return new Ctor(args[0]);
+ case 2:
+ return new Ctor(args[0], args[1]);
+ case 3:
+ return new Ctor(args[0], args[1], args[2]);
+ case 4:
+ return new Ctor(args[0], args[1], args[2], args[3]);
+ case 5:
+ return new Ctor(args[0], args[1], args[2], args[3], args[4]);
+ case 6:
+ return new Ctor(args[0], args[1], args[2], args[3], args[4], args[5]);
+ case 7:
+ return new Ctor(args[0], args[1], args[2], args[3], args[4], args[5], args[6]);
+ }
+ var thisBinding = baseCreate(Ctor.prototype), result2 = Ctor.apply(thisBinding, args);
+ return isObject(result2) ? result2 : thisBinding;
+ };
+ }
+ function createCurry(func, bitmask, arity) {
+ var Ctor = createCtor(func);
+ function wrapper() {
+ var length = arguments.length, args = Array2(length), index = length, placeholder = getHolder(wrapper);
+ while (index--) {
+ args[index] = arguments[index];
+ }
+ var holders = length < 3 && args[0] !== placeholder && args[length - 1] !== placeholder ? [] : replaceHolders(args, placeholder);
+ length -= holders.length;
+ if (length < arity) {
+ return createRecurry(
+ func,
+ bitmask,
+ createHybrid,
+ wrapper.placeholder,
+ undefined2,
+ args,
+ holders,
+ undefined2,
+ undefined2,
+ arity - length
+ );
+ }
+ var fn = this && this !== root && this instanceof wrapper ? Ctor : func;
+ return apply(fn, this, args);
+ }
+ return wrapper;
+ }
+ function createFind(findIndexFunc) {
+ return function(collection, predicate, fromIndex) {
+ var iterable = Object2(collection);
+ if (!isArrayLike(collection)) {
+ var iteratee2 = getIteratee(predicate, 3);
+ collection = keys(collection);
+ predicate = function(key) {
+ return iteratee2(iterable[key], key, iterable);
+ };
+ }
+ var index = findIndexFunc(collection, predicate, fromIndex);
+ return index > -1 ? iterable[iteratee2 ? collection[index] : index] : undefined2;
+ };
+ }
+ function createFlow(fromRight) {
+ return flatRest(function(funcs) {
+ var length = funcs.length, index = length, prereq = LodashWrapper.prototype.thru;
+ if (fromRight) {
+ funcs.reverse();
+ }
+ while (index--) {
+ var func = funcs[index];
+ if (typeof func != "function") {
+ throw new TypeError2(FUNC_ERROR_TEXT);
+ }
+ if (prereq && !wrapper && getFuncName(func) == "wrapper") {
+ var wrapper = new LodashWrapper([], true);
+ }
+ }
+ index = wrapper ? index : length;
+ while (++index < length) {
+ func = funcs[index];
+ var funcName = getFuncName(func), data = funcName == "wrapper" ? getData(func) : undefined2;
+ if (data && isLaziable(data[0]) && data[1] == (WRAP_ARY_FLAG | WRAP_CURRY_FLAG | WRAP_PARTIAL_FLAG | WRAP_REARG_FLAG) && !data[4].length && data[9] == 1) {
+ wrapper = wrapper[getFuncName(data[0])].apply(wrapper, data[3]);
+ } else {
+ wrapper = func.length == 1 && isLaziable(func) ? wrapper[funcName]() : wrapper.thru(func);
+ }
+ }
+ return function() {
+ var args = arguments, value = args[0];
+ if (wrapper && args.length == 1 && isArray(value)) {
+ return wrapper.plant(value).value();
+ }
+ var index2 = 0, result2 = length ? funcs[index2].apply(this, args) : value;
+ while (++index2 < length) {
+ result2 = funcs[index2].call(this, result2);
+ }
+ return result2;
+ };
+ });
+ }
+ function createHybrid(func, bitmask, thisArg, partials, holders, partialsRight, holdersRight, argPos, ary2, arity) {
+ var isAry = bitmask & WRAP_ARY_FLAG, isBind = bitmask & WRAP_BIND_FLAG, isBindKey = bitmask & WRAP_BIND_KEY_FLAG, isCurried = bitmask & (WRAP_CURRY_FLAG | WRAP_CURRY_RIGHT_FLAG), isFlip = bitmask & WRAP_FLIP_FLAG, Ctor = isBindKey ? undefined2 : createCtor(func);
+ function wrapper() {
+ var length = arguments.length, args = Array2(length), index = length;
+ while (index--) {
+ args[index] = arguments[index];
+ }
+ if (isCurried) {
+ var placeholder = getHolder(wrapper), holdersCount = countHolders(args, placeholder);
+ }
+ if (partials) {
+ args = composeArgs(args, partials, holders, isCurried);
+ }
+ if (partialsRight) {
+ args = composeArgsRight(args, partialsRight, holdersRight, isCurried);
+ }
+ length -= holdersCount;
+ if (isCurried && length < arity) {
+ var newHolders = replaceHolders(args, placeholder);
+ return createRecurry(
+ func,
+ bitmask,
+ createHybrid,
+ wrapper.placeholder,
+ thisArg,
+ args,
+ newHolders,
+ argPos,
+ ary2,
+ arity - length
+ );
+ }
+ var thisBinding = isBind ? thisArg : this, fn = isBindKey ? thisBinding[func] : func;
+ length = args.length;
+ if (argPos) {
+ args = reorder(args, argPos);
+ } else if (isFlip && length > 1) {
+ args.reverse();
+ }
+ if (isAry && ary2 < length) {
+ args.length = ary2;
+ }
+ if (this && this !== root && this instanceof wrapper) {
+ fn = Ctor || createCtor(fn);
+ }
+ return fn.apply(thisBinding, args);
+ }
+ return wrapper;
+ }
+ function createInverter(setter, toIteratee) {
+ return function(object, iteratee2) {
+ return baseInverter(object, setter, toIteratee(iteratee2), {});
+ };
+ }
+ function createMathOperation(operator, defaultValue) {
+ return function(value, other) {
+ var result2;
+ if (value === undefined2 && other === undefined2) {
+ return defaultValue;
+ }
+ if (value !== undefined2) {
+ result2 = value;
+ }
+ if (other !== undefined2) {
+ if (result2 === undefined2) {
+ return other;
+ }
+ if (typeof value == "string" || typeof other == "string") {
+ value = baseToString(value);
+ other = baseToString(other);
+ } else {
+ value = baseToNumber(value);
+ other = baseToNumber(other);
+ }
+ result2 = operator(value, other);
+ }
+ return result2;
+ };
+ }
+ function createOver(arrayFunc) {
+ return flatRest(function(iteratees) {
+ iteratees = arrayMap(iteratees, baseUnary(getIteratee()));
+ return baseRest(function(args) {
+ var thisArg = this;
+ return arrayFunc(iteratees, function(iteratee2) {
+ return apply(iteratee2, thisArg, args);
+ });
+ });
+ });
+ }
+ function createPadding(length, chars) {
+ chars = chars === undefined2 ? " " : baseToString(chars);
+ var charsLength = chars.length;
+ if (charsLength < 2) {
+ return charsLength ? baseRepeat(chars, length) : chars;
+ }
+ var result2 = baseRepeat(chars, nativeCeil(length / stringSize(chars)));
+ return hasUnicode(chars) ? castSlice(stringToArray(result2), 0, length).join("") : result2.slice(0, length);
+ }
+ function createPartial(func, bitmask, thisArg, partials) {
+ var isBind = bitmask & WRAP_BIND_FLAG, Ctor = createCtor(func);
+ function wrapper() {
+ var argsIndex = -1, argsLength = arguments.length, leftIndex = -1, leftLength = partials.length, args = Array2(leftLength + argsLength), fn = this && this !== root && this instanceof wrapper ? Ctor : func;
+ while (++leftIndex < leftLength) {
+ args[leftIndex] = partials[leftIndex];
+ }
+ while (argsLength--) {
+ args[leftIndex++] = arguments[++argsIndex];
+ }
+ return apply(fn, isBind ? thisArg : this, args);
+ }
+ return wrapper;
+ }
+ function createRange(fromRight) {
+ return function(start, end, step) {
+ if (step && typeof step != "number" && isIterateeCall(start, end, step)) {
+ end = step = undefined2;
+ }
+ start = toFinite(start);
+ if (end === undefined2) {
+ end = start;
+ start = 0;
+ } else {
+ end = toFinite(end);
+ }
+ step = step === undefined2 ? start < end ? 1 : -1 : toFinite(step);
+ return baseRange(start, end, step, fromRight);
+ };
+ }
+ function createRelationalOperation(operator) {
+ return function(value, other) {
+ if (!(typeof value == "string" && typeof other == "string")) {
+ value = toNumber(value);
+ other = toNumber(other);
+ }
+ return operator(value, other);
+ };
+ }
+ function createRecurry(func, bitmask, wrapFunc, placeholder, thisArg, partials, holders, argPos, ary2, arity) {
+ var isCurry = bitmask & WRAP_CURRY_FLAG, newHolders = isCurry ? holders : undefined2, newHoldersRight = isCurry ? undefined2 : holders, newPartials = isCurry ? partials : undefined2, newPartialsRight = isCurry ? undefined2 : partials;
+ bitmask |= isCurry ? WRAP_PARTIAL_FLAG : WRAP_PARTIAL_RIGHT_FLAG;
+ bitmask &= ~(isCurry ? WRAP_PARTIAL_RIGHT_FLAG : WRAP_PARTIAL_FLAG);
+ if (!(bitmask & WRAP_CURRY_BOUND_FLAG)) {
+ bitmask &= ~(WRAP_BIND_FLAG | WRAP_BIND_KEY_FLAG);
+ }
+ var newData = [
+ func,
+ bitmask,
+ thisArg,
+ newPartials,
+ newHolders,
+ newPartialsRight,
+ newHoldersRight,
+ argPos,
+ ary2,
+ arity
+ ];
+ var result2 = wrapFunc.apply(undefined2, newData);
+ if (isLaziable(func)) {
+ setData(result2, newData);
+ }
+ result2.placeholder = placeholder;
+ return setWrapToString(result2, func, bitmask);
+ }
+ function createRound(methodName) {
+ var func = Math2[methodName];
+ return function(number, precision) {
+ number = toNumber(number);
+ precision = precision == null ? 0 : nativeMin(toInteger(precision), 292);
+ if (precision && nativeIsFinite(number)) {
+ var pair = (toString(number) + "e").split("e"), value = func(pair[0] + "e" + (+pair[1] + precision));
+ pair = (toString(value) + "e").split("e");
+ return +(pair[0] + "e" + (+pair[1] - precision));
+ }
+ return func(number);
+ };
+ }
+ var createSet = !(Set && 1 / setToArray(new Set([, -0]))[1] == INFINITY) ? noop : function(values2) {
+ return new Set(values2);
+ };
+ function createToPairs(keysFunc) {
+ return function(object) {
+ var tag = getTag(object);
+ if (tag == mapTag) {
+ return mapToArray(object);
+ }
+ if (tag == setTag) {
+ return setToPairs(object);
+ }
+ return baseToPairs(object, keysFunc(object));
+ };
+ }
+ function createWrap(func, bitmask, thisArg, partials, holders, argPos, ary2, arity) {
+ var isBindKey = bitmask & WRAP_BIND_KEY_FLAG;
+ if (!isBindKey && typeof func != "function") {
+ throw new TypeError2(FUNC_ERROR_TEXT);
+ }
+ var length = partials ? partials.length : 0;
+ if (!length) {
+ bitmask &= ~(WRAP_PARTIAL_FLAG | WRAP_PARTIAL_RIGHT_FLAG);
+ partials = holders = undefined2;
+ }
+ ary2 = ary2 === undefined2 ? ary2 : nativeMax(toInteger(ary2), 0);
+ arity = arity === undefined2 ? arity : toInteger(arity);
+ length -= holders ? holders.length : 0;
+ if (bitmask & WRAP_PARTIAL_RIGHT_FLAG) {
+ var partialsRight = partials, holdersRight = holders;
+ partials = holders = undefined2;
+ }
+ var data = isBindKey ? undefined2 : getData(func);
+ var newData = [
+ func,
+ bitmask,
+ thisArg,
+ partials,
+ holders,
+ partialsRight,
+ holdersRight,
+ argPos,
+ ary2,
+ arity
+ ];
+ if (data) {
+ mergeData(newData, data);
+ }
+ func = newData[0];
+ bitmask = newData[1];
+ thisArg = newData[2];
+ partials = newData[3];
+ holders = newData[4];
+ arity = newData[9] = newData[9] === undefined2 ? isBindKey ? 0 : func.length : nativeMax(newData[9] - length, 0);
+ if (!arity && bitmask & (WRAP_CURRY_FLAG | WRAP_CURRY_RIGHT_FLAG)) {
+ bitmask &= ~(WRAP_CURRY_FLAG | WRAP_CURRY_RIGHT_FLAG);
+ }
+ if (!bitmask || bitmask == WRAP_BIND_FLAG) {
+ var result2 = createBind(func, bitmask, thisArg);
+ } else if (bitmask == WRAP_CURRY_FLAG || bitmask == WRAP_CURRY_RIGHT_FLAG) {
+ result2 = createCurry(func, bitmask, arity);
+ } else if ((bitmask == WRAP_PARTIAL_FLAG || bitmask == (WRAP_BIND_FLAG | WRAP_PARTIAL_FLAG)) && !holders.length) {
+ result2 = createPartial(func, bitmask, thisArg, partials);
+ } else {
+ result2 = createHybrid.apply(undefined2, newData);
+ }
+ var setter = data ? baseSetData : setData;
+ return setWrapToString(setter(result2, newData), func, bitmask);
+ }
+ function customDefaultsAssignIn(objValue, srcValue, key, object) {
+ if (objValue === undefined2 || eq(objValue, objectProto[key]) && !hasOwnProperty.call(object, key)) {
+ return srcValue;
+ }
+ return objValue;
+ }
+ function customDefaultsMerge(objValue, srcValue, key, object, source, stack) {
+ if (isObject(objValue) && isObject(srcValue)) {
+ stack.set(srcValue, objValue);
+ baseMerge(objValue, srcValue, undefined2, customDefaultsMerge, stack);
+ stack["delete"](srcValue);
+ }
+ return objValue;
+ }
+ function customOmitClone(value) {
+ return isPlainObject(value) ? undefined2 : value;
+ }
+ function equalArrays(array, other, bitmask, customizer, equalFunc, stack) {
+ var isPartial = bitmask & COMPARE_PARTIAL_FLAG, arrLength = array.length, othLength = other.length;
+ if (arrLength != othLength && !(isPartial && othLength > arrLength)) {
+ return false;
+ }
+ var arrStacked = stack.get(array);
+ var othStacked = stack.get(other);
+ if (arrStacked && othStacked) {
+ return arrStacked == other && othStacked == array;
+ }
+ var index = -1, result2 = true, seen = bitmask & COMPARE_UNORDERED_FLAG ? new SetCache() : undefined2;
+ stack.set(array, other);
+ stack.set(other, array);
+ while (++index < arrLength) {
+ var arrValue = array[index], othValue = other[index];
+ if (customizer) {
+ var compared = isPartial ? customizer(othValue, arrValue, index, other, array, stack) : customizer(arrValue, othValue, index, array, other, stack);
+ }
+ if (compared !== undefined2) {
+ if (compared) {
+ continue;
+ }
+ result2 = false;
+ break;
+ }
+ if (seen) {
+ if (!arraySome(other, function(othValue2, othIndex) {
+ if (!cacheHas(seen, othIndex) && (arrValue === othValue2 || equalFunc(arrValue, othValue2, bitmask, customizer, stack))) {
+ return seen.push(othIndex);
+ }
+ })) {
+ result2 = false;
+ break;
+ }
+ } else if (!(arrValue === othValue || equalFunc(arrValue, othValue, bitmask, customizer, stack))) {
+ result2 = false;
+ break;
+ }
+ }
+ stack["delete"](array);
+ stack["delete"](other);
+ return result2;
+ }
+ function equalByTag(object, other, tag, bitmask, customizer, equalFunc, stack) {
+ switch (tag) {
+ case dataViewTag:
+ if (object.byteLength != other.byteLength || object.byteOffset != other.byteOffset) {
+ return false;
+ }
+ object = object.buffer;
+ other = other.buffer;
+ case arrayBufferTag:
+ if (object.byteLength != other.byteLength || !equalFunc(new Uint8Array2(object), new Uint8Array2(other))) {
+ return false;
+ }
+ return true;
+ case boolTag:
+ case dateTag:
+ case numberTag:
+ return eq(+object, +other);
+ case errorTag:
+ return object.name == other.name && object.message == other.message;
+ case regexpTag:
+ case stringTag:
+ return object == other + "";
+ case mapTag:
+ var convert = mapToArray;
+ case setTag:
+ var isPartial = bitmask & COMPARE_PARTIAL_FLAG;
+ convert || (convert = setToArray);
+ if (object.size != other.size && !isPartial) {
+ return false;
+ }
+ var stacked = stack.get(object);
+ if (stacked) {
+ return stacked == other;
+ }
+ bitmask |= COMPARE_UNORDERED_FLAG;
+ stack.set(object, other);
+ var result2 = equalArrays(convert(object), convert(other), bitmask, customizer, equalFunc, stack);
+ stack["delete"](object);
+ return result2;
+ case symbolTag:
+ if (symbolValueOf) {
+ return symbolValueOf.call(object) == symbolValueOf.call(other);
+ }
+ }
+ return false;
+ }
+ function equalObjects(object, other, bitmask, customizer, equalFunc, stack) {
+ var isPartial = bitmask & COMPARE_PARTIAL_FLAG, objProps = getAllKeys(object), objLength = objProps.length, othProps = getAllKeys(other), othLength = othProps.length;
+ if (objLength != othLength && !isPartial) {
+ return false;
+ }
+ var index = objLength;
+ while (index--) {
+ var key = objProps[index];
+ if (!(isPartial ? key in other : hasOwnProperty.call(other, key))) {
+ return false;
+ }
+ }
+ var objStacked = stack.get(object);
+ var othStacked = stack.get(other);
+ if (objStacked && othStacked) {
+ return objStacked == other && othStacked == object;
+ }
+ var result2 = true;
+ stack.set(object, other);
+ stack.set(other, object);
+ var skipCtor = isPartial;
+ while (++index < objLength) {
+ key = objProps[index];
+ var objValue = object[key], othValue = other[key];
+ if (customizer) {
+ var compared = isPartial ? customizer(othValue, objValue, key, other, object, stack) : customizer(objValue, othValue, key, object, other, stack);
+ }
+ if (!(compared === undefined2 ? objValue === othValue || equalFunc(objValue, othValue, bitmask, customizer, stack) : compared)) {
+ result2 = false;
+ break;
+ }
+ skipCtor || (skipCtor = key == "constructor");
+ }
+ if (result2 && !skipCtor) {
+ var objCtor = object.constructor, othCtor = other.constructor;
+ if (objCtor != othCtor && ("constructor" in object && "constructor" in other) && !(typeof objCtor == "function" && objCtor instanceof objCtor && typeof othCtor == "function" && othCtor instanceof othCtor)) {
+ result2 = false;
+ }
+ }
+ stack["delete"](object);
+ stack["delete"](other);
+ return result2;
+ }
+ function flatRest(func) {
+ return setToString(overRest(func, undefined2, flatten), func + "");
+ }
+ function getAllKeys(object) {
+ return baseGetAllKeys(object, keys, getSymbols);
+ }
+ function getAllKeysIn(object) {
+ return baseGetAllKeys(object, keysIn, getSymbolsIn);
+ }
+ var getData = !metaMap ? noop : function(func) {
+ return metaMap.get(func);
+ };
+ function getFuncName(func) {
+ var result2 = func.name + "", array = realNames[result2], length = hasOwnProperty.call(realNames, result2) ? array.length : 0;
+ while (length--) {
+ var data = array[length], otherFunc = data.func;
+ if (otherFunc == null || otherFunc == func) {
+ return data.name;
+ }
+ }
+ return result2;
+ }
+ function getHolder(func) {
+ var object = hasOwnProperty.call(lodash, "placeholder") ? lodash : func;
+ return object.placeholder;
+ }
+ function getIteratee() {
+ var result2 = lodash.iteratee || iteratee;
+ result2 = result2 === iteratee ? baseIteratee : result2;
+ return arguments.length ? result2(arguments[0], arguments[1]) : result2;
+ }
+ function getMapData(map2, key) {
+ var data = map2.__data__;
+ return isKeyable(key) ? data[typeof key == "string" ? "string" : "hash"] : data.map;
+ }
+ function getMatchData(object) {
+ var result2 = keys(object), length = result2.length;
+ while (length--) {
+ var key = result2[length], value = object[key];
+ result2[length] = [key, value, isStrictComparable(value)];
+ }
+ return result2;
+ }
+ function getNative(object, key) {
+ var value = getValue(object, key);
+ return baseIsNative(value) ? value : undefined2;
+ }
+ function getRawTag(value) {
+ var isOwn = hasOwnProperty.call(value, symToStringTag), tag = value[symToStringTag];
+ try {
+ value[symToStringTag] = undefined2;
+ var unmasked = true;
+ } catch (e) {
+ }
+ var result2 = nativeObjectToString.call(value);
+ if (unmasked) {
+ if (isOwn) {
+ value[symToStringTag] = tag;
+ } else {
+ delete value[symToStringTag];
+ }
+ }
+ return result2;
+ }
+ var getSymbols = !nativeGetSymbols ? stubArray : function(object) {
+ if (object == null) {
+ return [];
+ }
+ object = Object2(object);
+ return arrayFilter(nativeGetSymbols(object), function(symbol) {
+ return propertyIsEnumerable.call(object, symbol);
+ });
+ };
+ var getSymbolsIn = !nativeGetSymbols ? stubArray : function(object) {
+ var result2 = [];
+ while (object) {
+ arrayPush(result2, getSymbols(object));
+ object = getPrototype(object);
+ }
+ return result2;
+ };
+ var getTag = baseGetTag;
+ if (DataView && getTag(new DataView(new ArrayBuffer(1))) != dataViewTag || Map2 && getTag(new Map2()) != mapTag || Promise2 && getTag(Promise2.resolve()) != promiseTag || Set && getTag(new Set()) != setTag || WeakMap && getTag(new WeakMap()) != weakMapTag) {
+ getTag = function(value) {
+ var result2 = baseGetTag(value), Ctor = result2 == objectTag ? value.constructor : undefined2, ctorString = Ctor ? toSource(Ctor) : "";
+ if (ctorString) {
+ switch (ctorString) {
+ case dataViewCtorString:
+ return dataViewTag;
+ case mapCtorString:
+ return mapTag;
+ case promiseCtorString:
+ return promiseTag;
+ case setCtorString:
+ return setTag;
+ case weakMapCtorString:
+ return weakMapTag;
+ }
+ }
+ return result2;
+ };
+ }
+ function getView(start, end, transforms) {
+ var index = -1, length = transforms.length;
+ while (++index < length) {
+ var data = transforms[index], size2 = data.size;
+ switch (data.type) {
+ case "drop":
+ start += size2;
+ break;
+ case "dropRight":
+ end -= size2;
+ break;
+ case "take":
+ end = nativeMin(end, start + size2);
+ break;
+ case "takeRight":
+ start = nativeMax(start, end - size2);
+ break;
+ }
+ }
+ return { "start": start, "end": end };
+ }
+ function getWrapDetails(source) {
+ var match = source.match(reWrapDetails);
+ return match ? match[1].split(reSplitDetails) : [];
+ }
+ function hasPath(object, path, hasFunc) {
+ path = castPath(path, object);
+ var index = -1, length = path.length, result2 = false;
+ while (++index < length) {
+ var key = toKey(path[index]);
+ if (!(result2 = object != null && hasFunc(object, key))) {
+ break;
+ }
+ object = object[key];
+ }
+ if (result2 || ++index != length) {
+ return result2;
+ }
+ length = object == null ? 0 : object.length;
+ return !!length && isLength(length) && isIndex(key, length) && (isArray(object) || isArguments(object));
+ }
+ function initCloneArray(array) {
+ var length = array.length, result2 = new array.constructor(length);
+ if (length && typeof array[0] == "string" && hasOwnProperty.call(array, "index")) {
+ result2.index = array.index;
+ result2.input = array.input;
+ }
+ return result2;
+ }
+ function initCloneObject(object) {
+ return typeof object.constructor == "function" && !isPrototype(object) ? baseCreate(getPrototype(object)) : {};
+ }
+ function initCloneByTag(object, tag, isDeep) {
+ var Ctor = object.constructor;
+ switch (tag) {
+ case arrayBufferTag:
+ return cloneArrayBuffer(object);
+ case boolTag:
+ case dateTag:
+ return new Ctor(+object);
+ case dataViewTag:
+ return cloneDataView(object, isDeep);
+ case float32Tag:
+ case float64Tag:
+ case int8Tag:
+ case int16Tag:
+ case int32Tag:
+ case uint8Tag:
+ case uint8ClampedTag:
+ case uint16Tag:
+ case uint32Tag:
+ return cloneTypedArray(object, isDeep);
+ case mapTag:
+ return new Ctor();
+ case numberTag:
+ case stringTag:
+ return new Ctor(object);
+ case regexpTag:
+ return cloneRegExp(object);
+ case setTag:
+ return new Ctor();
+ case symbolTag:
+ return cloneSymbol(object);
+ }
+ }
+ function insertWrapDetails(source, details) {
+ var length = details.length;
+ if (!length) {
+ return source;
+ }
+ var lastIndex = length - 1;
+ details[lastIndex] = (length > 1 ? "& " : "") + details[lastIndex];
+ details = details.join(length > 2 ? ", " : " ");
+ return source.replace(reWrapComment, "{\n/* [wrapped with " + details + "] */\n");
+ }
+ function isFlattenable(value) {
+ return isArray(value) || isArguments(value) || !!(spreadableSymbol && value && value[spreadableSymbol]);
+ }
+ function isIndex(value, length) {
+ var type = typeof value;
+ length = length == null ? MAX_SAFE_INTEGER : length;
+ return !!length && (type == "number" || type != "symbol" && reIsUint.test(value)) && (value > -1 && value % 1 == 0 && value < length);
+ }
+ function isIterateeCall(value, index, object) {
+ if (!isObject(object)) {
+ return false;
+ }
+ var type = typeof index;
+ if (type == "number" ? isArrayLike(object) && isIndex(index, object.length) : type == "string" && index in object) {
+ return eq(object[index], value);
+ }
+ return false;
+ }
+ function isKey(value, object) {
+ if (isArray(value)) {
+ return false;
+ }
+ var type = typeof value;
+ if (type == "number" || type == "symbol" || type == "boolean" || value == null || isSymbol(value)) {
+ return true;
+ }
+ return reIsPlainProp.test(value) || !reIsDeepProp.test(value) || object != null && value in Object2(object);
+ }
+ function isKeyable(value) {
+ var type = typeof value;
+ return type == "string" || type == "number" || type == "symbol" || type == "boolean" ? value !== "__proto__" : value === null;
+ }
+ function isLaziable(func) {
+ var funcName = getFuncName(func), other = lodash[funcName];
+ if (typeof other != "function" || !(funcName in LazyWrapper.prototype)) {
+ return false;
+ }
+ if (func === other) {
+ return true;
+ }
+ var data = getData(other);
+ return !!data && func === data[0];
+ }
+ function isMasked(func) {
+ return !!maskSrcKey && maskSrcKey in func;
+ }
+ var isMaskable = coreJsData ? isFunction : stubFalse;
+ function isPrototype(value) {
+ var Ctor = value && value.constructor, proto = typeof Ctor == "function" && Ctor.prototype || objectProto;
+ return value === proto;
+ }
+ function isStrictComparable(value) {
+ return value === value && !isObject(value);
+ }
+ function matchesStrictComparable(key, srcValue) {
+ return function(object) {
+ if (object == null) {
+ return false;
+ }
+ return object[key] === srcValue && (srcValue !== undefined2 || key in Object2(object));
+ };
+ }
+ function memoizeCapped(func) {
+ var result2 = memoize(func, function(key) {
+ if (cache.size === MAX_MEMOIZE_SIZE) {
+ cache.clear();
+ }
+ return key;
+ });
+ var cache = result2.cache;
+ return result2;
+ }
+ function mergeData(data, source) {
+ var bitmask = data[1], srcBitmask = source[1], newBitmask = bitmask | srcBitmask, isCommon = newBitmask < (WRAP_BIND_FLAG | WRAP_BIND_KEY_FLAG | WRAP_ARY_FLAG);
+ var isCombo = srcBitmask == WRAP_ARY_FLAG && bitmask == WRAP_CURRY_FLAG || srcBitmask == WRAP_ARY_FLAG && bitmask == WRAP_REARG_FLAG && data[7].length <= source[8] || srcBitmask == (WRAP_ARY_FLAG | WRAP_REARG_FLAG) && source[7].length <= source[8] && bitmask == WRAP_CURRY_FLAG;
+ if (!(isCommon || isCombo)) {
+ return data;
+ }
+ if (srcBitmask & WRAP_BIND_FLAG) {
+ data[2] = source[2];
+ newBitmask |= bitmask & WRAP_BIND_FLAG ? 0 : WRAP_CURRY_BOUND_FLAG;
+ }
+ var value = source[3];
+ if (value) {
+ var partials = data[3];
+ data[3] = partials ? composeArgs(partials, value, source[4]) : value;
+ data[4] = partials ? replaceHolders(data[3], PLACEHOLDER) : source[4];
+ }
+ value = source[5];
+ if (value) {
+ partials = data[5];
+ data[5] = partials ? composeArgsRight(partials, value, source[6]) : value;
+ data[6] = partials ? replaceHolders(data[5], PLACEHOLDER) : source[6];
+ }
+ value = source[7];
+ if (value) {
+ data[7] = value;
+ }
+ if (srcBitmask & WRAP_ARY_FLAG) {
+ data[8] = data[8] == null ? source[8] : nativeMin(data[8], source[8]);
+ }
+ if (data[9] == null) {
+ data[9] = source[9];
+ }
+ data[0] = source[0];
+ data[1] = newBitmask;
+ return data;
+ }
+ function nativeKeysIn(object) {
+ var result2 = [];
+ if (object != null) {
+ for (var key in Object2(object)) {
+ result2.push(key);
+ }
+ }
+ return result2;
+ }
+ function objectToString(value) {
+ return nativeObjectToString.call(value);
+ }
+ function overRest(func, start, transform2) {
+ start = nativeMax(start === undefined2 ? func.length - 1 : start, 0);
+ return function() {
+ var args = arguments, index = -1, length = nativeMax(args.length - start, 0), array = Array2(length);
+ while (++index < length) {
+ array[index] = args[start + index];
+ }
+ index = -1;
+ var otherArgs = Array2(start + 1);
+ while (++index < start) {
+ otherArgs[index] = args[index];
+ }
+ otherArgs[start] = transform2(array);
+ return apply(func, this, otherArgs);
+ };
+ }
+ function parent(object, path) {
+ return path.length < 2 ? object : baseGet(object, baseSlice(path, 0, -1));
+ }
+ function reorder(array, indexes) {
+ var arrLength = array.length, length = nativeMin(indexes.length, arrLength), oldArray = copyArray(array);
+ while (length--) {
+ var index = indexes[length];
+ array[length] = isIndex(index, arrLength) ? oldArray[index] : undefined2;
+ }
+ return array;
+ }
+ function safeGet(object, key) {
+ if (key === "constructor" && typeof object[key] === "function") {
+ return;
+ }
+ if (key == "__proto__") {
+ return;
+ }
+ return object[key];
+ }
+ var setData = shortOut(baseSetData);
+ var setTimeout2 = ctxSetTimeout || function(func, wait) {
+ return root.setTimeout(func, wait);
+ };
+ var setToString = shortOut(baseSetToString);
+ function setWrapToString(wrapper, reference, bitmask) {
+ var source = reference + "";
+ return setToString(wrapper, insertWrapDetails(source, updateWrapDetails(getWrapDetails(source), bitmask)));
+ }
+ function shortOut(func) {
+ var count = 0, lastCalled = 0;
+ return function() {
+ var stamp = nativeNow(), remaining = HOT_SPAN - (stamp - lastCalled);
+ lastCalled = stamp;
+ if (remaining > 0) {
+ if (++count >= HOT_COUNT) {
+ return arguments[0];
+ }
+ } else {
+ count = 0;
+ }
+ return func.apply(undefined2, arguments);
+ };
+ }
+ function shuffleSelf(array, size2) {
+ var index = -1, length = array.length, lastIndex = length - 1;
+ size2 = size2 === undefined2 ? length : size2;
+ while (++index < size2) {
+ var rand = baseRandom(index, lastIndex), value = array[rand];
+ array[rand] = array[index];
+ array[index] = value;
+ }
+ array.length = size2;
+ return array;
+ }
+ var stringToPath = memoizeCapped(function(string) {
+ var result2 = [];
+ if (string.charCodeAt(0) === 46) {
+ result2.push("");
+ }
+ string.replace(rePropName, function(match, number, quote, subString) {
+ result2.push(quote ? subString.replace(reEscapeChar, "$1") : number || match);
+ });
+ return result2;
+ });
+ function toKey(value) {
+ if (typeof value == "string" || isSymbol(value)) {
+ return value;
+ }
+ var result2 = value + "";
+ return result2 == "0" && 1 / value == -INFINITY ? "-0" : result2;
+ }
+ function toSource(func) {
+ if (func != null) {
+ try {
+ return funcToString.call(func);
+ } catch (e) {
+ }
+ try {
+ return func + "";
+ } catch (e) {
+ }
+ }
+ return "";
+ }
+ function updateWrapDetails(details, bitmask) {
+ arrayEach(wrapFlags, function(pair) {
+ var value = "_." + pair[0];
+ if (bitmask & pair[1] && !arrayIncludes(details, value)) {
+ details.push(value);
+ }
+ });
+ return details.sort();
+ }
+ function wrapperClone(wrapper) {
+ if (wrapper instanceof LazyWrapper) {
+ return wrapper.clone();
+ }
+ var result2 = new LodashWrapper(wrapper.__wrapped__, wrapper.__chain__);
+ result2.__actions__ = copyArray(wrapper.__actions__);
+ result2.__index__ = wrapper.__index__;
+ result2.__values__ = wrapper.__values__;
+ return result2;
+ }
+ function chunk(array, size2, guard) {
+ if (guard ? isIterateeCall(array, size2, guard) : size2 === undefined2) {
+ size2 = 1;
+ } else {
+ size2 = nativeMax(toInteger(size2), 0);
+ }
+ var length = array == null ? 0 : array.length;
+ if (!length || size2 < 1) {
+ return [];
+ }
+ var index = 0, resIndex = 0, result2 = Array2(nativeCeil(length / size2));
+ while (index < length) {
+ result2[resIndex++] = baseSlice(array, index, index += size2);
+ }
+ return result2;
+ }
+ function compact(array) {
+ var index = -1, length = array == null ? 0 : array.length, resIndex = 0, result2 = [];
+ while (++index < length) {
+ var value = array[index];
+ if (value) {
+ result2[resIndex++] = value;
+ }
+ }
+ return result2;
+ }
+ function concat() {
+ var length = arguments.length;
+ if (!length) {
+ return [];
+ }
+ var args = Array2(length - 1), array = arguments[0], index = length;
+ while (index--) {
+ args[index - 1] = arguments[index];
+ }
+ return arrayPush(isArray(array) ? copyArray(array) : [array], baseFlatten(args, 1));
+ }
+ var difference = baseRest(function(array, values2) {
+ return isArrayLikeObject(array) ? baseDifference(array, baseFlatten(values2, 1, isArrayLikeObject, true)) : [];
+ });
+ var differenceBy = baseRest(function(array, values2) {
+ var iteratee2 = last(values2);
+ if (isArrayLikeObject(iteratee2)) {
+ iteratee2 = undefined2;
+ }
+ return isArrayLikeObject(array) ? baseDifference(array, baseFlatten(values2, 1, isArrayLikeObject, true), getIteratee(iteratee2, 2)) : [];
+ });
+ var differenceWith = baseRest(function(array, values2) {
+ var comparator = last(values2);
+ if (isArrayLikeObject(comparator)) {
+ comparator = undefined2;
+ }
+ return isArrayLikeObject(array) ? baseDifference(array, baseFlatten(values2, 1, isArrayLikeObject, true), undefined2, comparator) : [];
+ });
+ function drop(array, n, guard) {
+ var length = array == null ? 0 : array.length;
+ if (!length) {
+ return [];
+ }
+ n = guard || n === undefined2 ? 1 : toInteger(n);
+ return baseSlice(array, n < 0 ? 0 : n, length);
+ }
+ function dropRight(array, n, guard) {
+ var length = array == null ? 0 : array.length;
+ if (!length) {
+ return [];
+ }
+ n = guard || n === undefined2 ? 1 : toInteger(n);
+ n = length - n;
+ return baseSlice(array, 0, n < 0 ? 0 : n);
+ }
+ function dropRightWhile(array, predicate) {
+ return array && array.length ? baseWhile(array, getIteratee(predicate, 3), true, true) : [];
+ }
+ function dropWhile(array, predicate) {
+ return array && array.length ? baseWhile(array, getIteratee(predicate, 3), true) : [];
+ }
+ function fill(array, value, start, end) {
+ var length = array == null ? 0 : array.length;
+ if (!length) {
+ return [];
+ }
+ if (start && typeof start != "number" && isIterateeCall(array, value, start)) {
+ start = 0;
+ end = length;
+ }
+ return baseFill(array, value, start, end);
+ }
+ function findIndex(array, predicate, fromIndex) {
+ var length = array == null ? 0 : array.length;
+ if (!length) {
+ return -1;
+ }
+ var index = fromIndex == null ? 0 : toInteger(fromIndex);
+ if (index < 0) {
+ index = nativeMax(length + index, 0);
+ }
+ return baseFindIndex(array, getIteratee(predicate, 3), index);
+ }
+ function findLastIndex(array, predicate, fromIndex) {
+ var length = array == null ? 0 : array.length;
+ if (!length) {
+ return -1;
+ }
+ var index = length - 1;
+ if (fromIndex !== undefined2) {
+ index = toInteger(fromIndex);
+ index = fromIndex < 0 ? nativeMax(length + index, 0) : nativeMin(index, length - 1);
+ }
+ return baseFindIndex(array, getIteratee(predicate, 3), index, true);
+ }
+ function flatten(array) {
+ var length = array == null ? 0 : array.length;
+ return length ? baseFlatten(array, 1) : [];
+ }
+ function flattenDeep(array) {
+ var length = array == null ? 0 : array.length;
+ return length ? baseFlatten(array, INFINITY) : [];
+ }
+ function flattenDepth(array, depth) {
+ var length = array == null ? 0 : array.length;
+ if (!length) {
+ return [];
+ }
+ depth = depth === undefined2 ? 1 : toInteger(depth);
+ return baseFlatten(array, depth);
+ }
+ function fromPairs(pairs) {
+ var index = -1, length = pairs == null ? 0 : pairs.length, result2 = {};
+ while (++index < length) {
+ var pair = pairs[index];
+ result2[pair[0]] = pair[1];
+ }
+ return result2;
+ }
+ function head(array) {
+ return array && array.length ? array[0] : undefined2;
+ }
+ function indexOf(array, value, fromIndex) {
+ var length = array == null ? 0 : array.length;
+ if (!length) {
+ return -1;
+ }
+ var index = fromIndex == null ? 0 : toInteger(fromIndex);
+ if (index < 0) {
+ index = nativeMax(length + index, 0);
+ }
+ return baseIndexOf(array, value, index);
+ }
+ function initial(array) {
+ var length = array == null ? 0 : array.length;
+ return length ? baseSlice(array, 0, -1) : [];
+ }
+ var intersection = baseRest(function(arrays) {
+ var mapped = arrayMap(arrays, castArrayLikeObject);
+ return mapped.length && mapped[0] === arrays[0] ? baseIntersection(mapped) : [];
+ });
+ var intersectionBy = baseRest(function(arrays) {
+ var iteratee2 = last(arrays), mapped = arrayMap(arrays, castArrayLikeObject);
+ if (iteratee2 === last(mapped)) {
+ iteratee2 = undefined2;
+ } else {
+ mapped.pop();
+ }
+ return mapped.length && mapped[0] === arrays[0] ? baseIntersection(mapped, getIteratee(iteratee2, 2)) : [];
+ });
+ var intersectionWith = baseRest(function(arrays) {
+ var comparator = last(arrays), mapped = arrayMap(arrays, castArrayLikeObject);
+ comparator = typeof comparator == "function" ? comparator : undefined2;
+ if (comparator) {
+ mapped.pop();
+ }
+ return mapped.length && mapped[0] === arrays[0] ? baseIntersection(mapped, undefined2, comparator) : [];
+ });
+ function join(array, separator) {
+ return array == null ? "" : nativeJoin.call(array, separator);
+ }
+ function last(array) {
+ var length = array == null ? 0 : array.length;
+ return length ? array[length - 1] : undefined2;
+ }
+ function lastIndexOf(array, value, fromIndex) {
+ var length = array == null ? 0 : array.length;
+ if (!length) {
+ return -1;
+ }
+ var index = length;
+ if (fromIndex !== undefined2) {
+ index = toInteger(fromIndex);
+ index = index < 0 ? nativeMax(length + index, 0) : nativeMin(index, length - 1);
+ }
+ return value === value ? strictLastIndexOf(array, value, index) : baseFindIndex(array, baseIsNaN, index, true);
+ }
+ function nth(array, n) {
+ return array && array.length ? baseNth(array, toInteger(n)) : undefined2;
+ }
+ var pull = baseRest(pullAll);
+ function pullAll(array, values2) {
+ return array && array.length && values2 && values2.length ? basePullAll(array, values2) : array;
+ }
+ function pullAllBy(array, values2, iteratee2) {
+ return array && array.length && values2 && values2.length ? basePullAll(array, values2, getIteratee(iteratee2, 2)) : array;
+ }
+ function pullAllWith(array, values2, comparator) {
+ return array && array.length && values2 && values2.length ? basePullAll(array, values2, undefined2, comparator) : array;
+ }
+ var pullAt = flatRest(function(array, indexes) {
+ var length = array == null ? 0 : array.length, result2 = baseAt(array, indexes);
+ basePullAt(array, arrayMap(indexes, function(index) {
+ return isIndex(index, length) ? +index : index;
+ }).sort(compareAscending));
+ return result2;
+ });
+ function remove(array, predicate) {
+ var result2 = [];
+ if (!(array && array.length)) {
+ return result2;
+ }
+ var index = -1, indexes = [], length = array.length;
+ predicate = getIteratee(predicate, 3);
+ while (++index < length) {
+ var value = array[index];
+ if (predicate(value, index, array)) {
+ result2.push(value);
+ indexes.push(index);
+ }
+ }
+ basePullAt(array, indexes);
+ return result2;
+ }
+ function reverse(array) {
+ return array == null ? array : nativeReverse.call(array);
+ }
+ function slice(array, start, end) {
+ var length = array == null ? 0 : array.length;
+ if (!length) {
+ return [];
+ }
+ if (end && typeof end != "number" && isIterateeCall(array, start, end)) {
+ start = 0;
+ end = length;
+ } else {
+ start = start == null ? 0 : toInteger(start);
+ end = end === undefined2 ? length : toInteger(end);
+ }
+ return baseSlice(array, start, end);
+ }
+ function sortedIndex(array, value) {
+ return baseSortedIndex(array, value);
+ }
+ function sortedIndexBy(array, value, iteratee2) {
+ return baseSortedIndexBy(array, value, getIteratee(iteratee2, 2));
+ }
+ function sortedIndexOf(array, value) {
+ var length = array == null ? 0 : array.length;
+ if (length) {
+ var index = baseSortedIndex(array, value);
+ if (index < length && eq(array[index], value)) {
+ return index;
+ }
+ }
+ return -1;
+ }
+ function sortedLastIndex(array, value) {
+ return baseSortedIndex(array, value, true);
+ }
+ function sortedLastIndexBy(array, value, iteratee2) {
+ return baseSortedIndexBy(array, value, getIteratee(iteratee2, 2), true);
+ }
+ function sortedLastIndexOf(array, value) {
+ var length = array == null ? 0 : array.length;
+ if (length) {
+ var index = baseSortedIndex(array, value, true) - 1;
+ if (eq(array[index], value)) {
+ return index;
+ }
+ }
+ return -1;
+ }
+ function sortedUniq(array) {
+ return array && array.length ? baseSortedUniq(array) : [];
+ }
+ function sortedUniqBy(array, iteratee2) {
+ return array && array.length ? baseSortedUniq(array, getIteratee(iteratee2, 2)) : [];
+ }
+ function tail(array) {
+ var length = array == null ? 0 : array.length;
+ return length ? baseSlice(array, 1, length) : [];
+ }
+ function take(array, n, guard) {
+ if (!(array && array.length)) {
+ return [];
+ }
+ n = guard || n === undefined2 ? 1 : toInteger(n);
+ return baseSlice(array, 0, n < 0 ? 0 : n);
+ }
+ function takeRight(array, n, guard) {
+ var length = array == null ? 0 : array.length;
+ if (!length) {
+ return [];
+ }
+ n = guard || n === undefined2 ? 1 : toInteger(n);
+ n = length - n;
+ return baseSlice(array, n < 0 ? 0 : n, length);
+ }
+ function takeRightWhile(array, predicate) {
+ return array && array.length ? baseWhile(array, getIteratee(predicate, 3), false, true) : [];
+ }
+ function takeWhile(array, predicate) {
+ return array && array.length ? baseWhile(array, getIteratee(predicate, 3)) : [];
+ }
+ var union = baseRest(function(arrays) {
+ return baseUniq(baseFlatten(arrays, 1, isArrayLikeObject, true));
+ });
+ var unionBy = baseRest(function(arrays) {
+ var iteratee2 = last(arrays);
+ if (isArrayLikeObject(iteratee2)) {
+ iteratee2 = undefined2;
+ }
+ return baseUniq(baseFlatten(arrays, 1, isArrayLikeObject, true), getIteratee(iteratee2, 2));
+ });
+ var unionWith = baseRest(function(arrays) {
+ var comparator = last(arrays);
+ comparator = typeof comparator == "function" ? comparator : undefined2;
+ return baseUniq(baseFlatten(arrays, 1, isArrayLikeObject, true), undefined2, comparator);
+ });
+ function uniq(array) {
+ return array && array.length ? baseUniq(array) : [];
+ }
+ function uniqBy(array, iteratee2) {
+ return array && array.length ? baseUniq(array, getIteratee(iteratee2, 2)) : [];
+ }
+ function uniqWith(array, comparator) {
+ comparator = typeof comparator == "function" ? comparator : undefined2;
+ return array && array.length ? baseUniq(array, undefined2, comparator) : [];
+ }
+ function unzip(array) {
+ if (!(array && array.length)) {
+ return [];
+ }
+ var length = 0;
+ array = arrayFilter(array, function(group) {
+ if (isArrayLikeObject(group)) {
+ length = nativeMax(group.length, length);
+ return true;
+ }
+ });
+ return baseTimes(length, function(index) {
+ return arrayMap(array, baseProperty(index));
+ });
+ }
+ function unzipWith(array, iteratee2) {
+ if (!(array && array.length)) {
+ return [];
+ }
+ var result2 = unzip(array);
+ if (iteratee2 == null) {
+ return result2;
+ }
+ return arrayMap(result2, function(group) {
+ return apply(iteratee2, undefined2, group);
+ });
+ }
+ var without = baseRest(function(array, values2) {
+ return isArrayLikeObject(array) ? baseDifference(array, values2) : [];
+ });
+ var xor = baseRest(function(arrays) {
+ return baseXor(arrayFilter(arrays, isArrayLikeObject));
+ });
+ var xorBy = baseRest(function(arrays) {
+ var iteratee2 = last(arrays);
+ if (isArrayLikeObject(iteratee2)) {
+ iteratee2 = undefined2;
+ }
+ return baseXor(arrayFilter(arrays, isArrayLikeObject), getIteratee(iteratee2, 2));
+ });
+ var xorWith = baseRest(function(arrays) {
+ var comparator = last(arrays);
+ comparator = typeof comparator == "function" ? comparator : undefined2;
+ return baseXor(arrayFilter(arrays, isArrayLikeObject), undefined2, comparator);
+ });
+ var zip = baseRest(unzip);
+ function zipObject(props, values2) {
+ return baseZipObject(props || [], values2 || [], assignValue);
+ }
+ function zipObjectDeep(props, values2) {
+ return baseZipObject(props || [], values2 || [], baseSet);
+ }
+ var zipWith = baseRest(function(arrays) {
+ var length = arrays.length, iteratee2 = length > 1 ? arrays[length - 1] : undefined2;
+ iteratee2 = typeof iteratee2 == "function" ? (arrays.pop(), iteratee2) : undefined2;
+ return unzipWith(arrays, iteratee2);
+ });
+ function chain(value) {
+ var result2 = lodash(value);
+ result2.__chain__ = true;
+ return result2;
+ }
+ function tap(value, interceptor) {
+ interceptor(value);
+ return value;
+ }
+ function thru(value, interceptor) {
+ return interceptor(value);
+ }
+ var wrapperAt = flatRest(function(paths) {
+ var length = paths.length, start = length ? paths[0] : 0, value = this.__wrapped__, interceptor = function(object) {
+ return baseAt(object, paths);
+ };
+ if (length > 1 || this.__actions__.length || !(value instanceof LazyWrapper) || !isIndex(start)) {
+ return this.thru(interceptor);
+ }
+ value = value.slice(start, +start + (length ? 1 : 0));
+ value.__actions__.push({
+ "func": thru,
+ "args": [interceptor],
+ "thisArg": undefined2
+ });
+ return new LodashWrapper(value, this.__chain__).thru(function(array) {
+ if (length && !array.length) {
+ array.push(undefined2);
+ }
+ return array;
+ });
+ });
+ function wrapperChain() {
+ return chain(this);
+ }
+ function wrapperCommit() {
+ return new LodashWrapper(this.value(), this.__chain__);
+ }
+ function wrapperNext() {
+ if (this.__values__ === undefined2) {
+ this.__values__ = toArray(this.value());
+ }
+ var done = this.__index__ >= this.__values__.length, value = done ? undefined2 : this.__values__[this.__index__++];
+ return { "done": done, "value": value };
+ }
+ function wrapperToIterator() {
+ return this;
+ }
+ function wrapperPlant(value) {
+ var result2, parent2 = this;
+ while (parent2 instanceof baseLodash) {
+ var clone2 = wrapperClone(parent2);
+ clone2.__index__ = 0;
+ clone2.__values__ = undefined2;
+ if (result2) {
+ previous.__wrapped__ = clone2;
+ } else {
+ result2 = clone2;
+ }
+ var previous = clone2;
+ parent2 = parent2.__wrapped__;
+ }
+ previous.__wrapped__ = value;
+ return result2;
+ }
+ function wrapperReverse() {
+ var value = this.__wrapped__;
+ if (value instanceof LazyWrapper) {
+ var wrapped = value;
+ if (this.__actions__.length) {
+ wrapped = new LazyWrapper(this);
+ }
+ wrapped = wrapped.reverse();
+ wrapped.__actions__.push({
+ "func": thru,
+ "args": [reverse],
+ "thisArg": undefined2
+ });
+ return new LodashWrapper(wrapped, this.__chain__);
+ }
+ return this.thru(reverse);
+ }
+ function wrapperValue() {
+ return baseWrapperValue(this.__wrapped__, this.__actions__);
+ }
+ var countBy = createAggregator(function(result2, value, key) {
+ if (hasOwnProperty.call(result2, key)) {
+ ++result2[key];
+ } else {
+ baseAssignValue(result2, key, 1);
+ }
+ });
+ function every(collection, predicate, guard) {
+ var func = isArray(collection) ? arrayEvery : baseEvery;
+ if (guard && isIterateeCall(collection, predicate, guard)) {
+ predicate = undefined2;
+ }
+ return func(collection, getIteratee(predicate, 3));
+ }
+ function filter(collection, predicate) {
+ var func = isArray(collection) ? arrayFilter : baseFilter;
+ return func(collection, getIteratee(predicate, 3));
+ }
+ var find = createFind(findIndex);
+ var findLast = createFind(findLastIndex);
+ function flatMap(collection, iteratee2) {
+ return baseFlatten(map(collection, iteratee2), 1);
+ }
+ function flatMapDeep(collection, iteratee2) {
+ return baseFlatten(map(collection, iteratee2), INFINITY);
+ }
+ function flatMapDepth(collection, iteratee2, depth) {
+ depth = depth === undefined2 ? 1 : toInteger(depth);
+ return baseFlatten(map(collection, iteratee2), depth);
+ }
+ function forEach(collection, iteratee2) {
+ var func = isArray(collection) ? arrayEach : baseEach;
+ return func(collection, getIteratee(iteratee2, 3));
+ }
+ function forEachRight(collection, iteratee2) {
+ var func = isArray(collection) ? arrayEachRight : baseEachRight;
+ return func(collection, getIteratee(iteratee2, 3));
+ }
+ var groupBy = createAggregator(function(result2, value, key) {
+ if (hasOwnProperty.call(result2, key)) {
+ result2[key].push(value);
+ } else {
+ baseAssignValue(result2, key, [value]);
+ }
+ });
+ function includes(collection, value, fromIndex, guard) {
+ collection = isArrayLike(collection) ? collection : values(collection);
+ fromIndex = fromIndex && !guard ? toInteger(fromIndex) : 0;
+ var length = collection.length;
+ if (fromIndex < 0) {
+ fromIndex = nativeMax(length + fromIndex, 0);
+ }
+ return isString(collection) ? fromIndex <= length && collection.indexOf(value, fromIndex) > -1 : !!length && baseIndexOf(collection, value, fromIndex) > -1;
+ }
+ var invokeMap = baseRest(function(collection, path, args) {
+ var index = -1, isFunc = typeof path == "function", result2 = isArrayLike(collection) ? Array2(collection.length) : [];
+ baseEach(collection, function(value) {
+ result2[++index] = isFunc ? apply(path, value, args) : baseInvoke(value, path, args);
+ });
+ return result2;
+ });
+ var keyBy = createAggregator(function(result2, value, key) {
+ baseAssignValue(result2, key, value);
+ });
+ function map(collection, iteratee2) {
+ var func = isArray(collection) ? arrayMap : baseMap;
+ return func(collection, getIteratee(iteratee2, 3));
+ }
+ function orderBy(collection, iteratees, orders, guard) {
+ if (collection == null) {
+ return [];
+ }
+ if (!isArray(iteratees)) {
+ iteratees = iteratees == null ? [] : [iteratees];
+ }
+ orders = guard ? undefined2 : orders;
+ if (!isArray(orders)) {
+ orders = orders == null ? [] : [orders];
+ }
+ return baseOrderBy(collection, iteratees, orders);
+ }
+ var partition = createAggregator(function(result2, value, key) {
+ result2[key ? 0 : 1].push(value);
+ }, function() {
+ return [[], []];
+ });
+ function reduce(collection, iteratee2, accumulator) {
+ var func = isArray(collection) ? arrayReduce : baseReduce, initAccum = arguments.length < 3;
+ return func(collection, getIteratee(iteratee2, 4), accumulator, initAccum, baseEach);
+ }
+ function reduceRight(collection, iteratee2, accumulator) {
+ var func = isArray(collection) ? arrayReduceRight : baseReduce, initAccum = arguments.length < 3;
+ return func(collection, getIteratee(iteratee2, 4), accumulator, initAccum, baseEachRight);
+ }
+ function reject(collection, predicate) {
+ var func = isArray(collection) ? arrayFilter : baseFilter;
+ return func(collection, negate(getIteratee(predicate, 3)));
+ }
+ function sample(collection) {
+ var func = isArray(collection) ? arraySample : baseSample;
+ return func(collection);
+ }
+ function sampleSize(collection, n, guard) {
+ if (guard ? isIterateeCall(collection, n, guard) : n === undefined2) {
+ n = 1;
+ } else {
+ n = toInteger(n);
+ }
+ var func = isArray(collection) ? arraySampleSize : baseSampleSize;
+ return func(collection, n);
+ }
+ function shuffle(collection) {
+ var func = isArray(collection) ? arrayShuffle : baseShuffle;
+ return func(collection);
+ }
+ function size(collection) {
+ if (collection == null) {
+ return 0;
+ }
+ if (isArrayLike(collection)) {
+ return isString(collection) ? stringSize(collection) : collection.length;
+ }
+ var tag = getTag(collection);
+ if (tag == mapTag || tag == setTag) {
+ return collection.size;
+ }
+ return baseKeys(collection).length;
+ }
+ function some(collection, predicate, guard) {
+ var func = isArray(collection) ? arraySome : baseSome;
+ if (guard && isIterateeCall(collection, predicate, guard)) {
+ predicate = undefined2;
+ }
+ return func(collection, getIteratee(predicate, 3));
+ }
+ var sortBy = baseRest(function(collection, iteratees) {
+ if (collection == null) {
+ return [];
+ }
+ var length = iteratees.length;
+ if (length > 1 && isIterateeCall(collection, iteratees[0], iteratees[1])) {
+ iteratees = [];
+ } else if (length > 2 && isIterateeCall(iteratees[0], iteratees[1], iteratees[2])) {
+ iteratees = [iteratees[0]];
+ }
+ return baseOrderBy(collection, baseFlatten(iteratees, 1), []);
+ });
+ var now = ctxNow || function() {
+ return root.Date.now();
+ };
+ function after(n, func) {
+ if (typeof func != "function") {
+ throw new TypeError2(FUNC_ERROR_TEXT);
+ }
+ n = toInteger(n);
+ return function() {
+ if (--n < 1) {
+ return func.apply(this, arguments);
+ }
+ };
+ }
+ function ary(func, n, guard) {
+ n = guard ? undefined2 : n;
+ n = func && n == null ? func.length : n;
+ return createWrap(func, WRAP_ARY_FLAG, undefined2, undefined2, undefined2, undefined2, n);
+ }
+ function before(n, func) {
+ var result2;
+ if (typeof func != "function") {
+ throw new TypeError2(FUNC_ERROR_TEXT);
+ }
+ n = toInteger(n);
+ return function() {
+ if (--n > 0) {
+ result2 = func.apply(this, arguments);
+ }
+ if (n <= 1) {
+ func = undefined2;
+ }
+ return result2;
+ };
+ }
+ var bind = baseRest(function(func, thisArg, partials) {
+ var bitmask = WRAP_BIND_FLAG;
+ if (partials.length) {
+ var holders = replaceHolders(partials, getHolder(bind));
+ bitmask |= WRAP_PARTIAL_FLAG;
+ }
+ return createWrap(func, bitmask, thisArg, partials, holders);
+ });
+ var bindKey = baseRest(function(object, key, partials) {
+ var bitmask = WRAP_BIND_FLAG | WRAP_BIND_KEY_FLAG;
+ if (partials.length) {
+ var holders = replaceHolders(partials, getHolder(bindKey));
+ bitmask |= WRAP_PARTIAL_FLAG;
+ }
+ return createWrap(key, bitmask, object, partials, holders);
+ });
+ function curry(func, arity, guard) {
+ arity = guard ? undefined2 : arity;
+ var result2 = createWrap(func, WRAP_CURRY_FLAG, undefined2, undefined2, undefined2, undefined2, undefined2, arity);
+ result2.placeholder = curry.placeholder;
+ return result2;
+ }
+ function curryRight(func, arity, guard) {
+ arity = guard ? undefined2 : arity;
+ var result2 = createWrap(func, WRAP_CURRY_RIGHT_FLAG, undefined2, undefined2, undefined2, undefined2, undefined2, arity);
+ result2.placeholder = curryRight.placeholder;
+ return result2;
+ }
+ function debounce(func, wait, options) {
+ var lastArgs, lastThis, maxWait, result2, timerId, lastCallTime, lastInvokeTime = 0, leading = false, maxing = false, trailing = true;
+ if (typeof func != "function") {
+ throw new TypeError2(FUNC_ERROR_TEXT);
+ }
+ wait = toNumber(wait) || 0;
+ if (isObject(options)) {
+ leading = !!options.leading;
+ maxing = "maxWait" in options;
+ maxWait = maxing ? nativeMax(toNumber(options.maxWait) || 0, wait) : maxWait;
+ trailing = "trailing" in options ? !!options.trailing : trailing;
+ }
+ function invokeFunc(time) {
+ var args = lastArgs, thisArg = lastThis;
+ lastArgs = lastThis = undefined2;
+ lastInvokeTime = time;
+ result2 = func.apply(thisArg, args);
+ return result2;
+ }
+ function leadingEdge(time) {
+ lastInvokeTime = time;
+ timerId = setTimeout2(timerExpired, wait);
+ return leading ? invokeFunc(time) : result2;
+ }
+ function remainingWait(time) {
+ var timeSinceLastCall = time - lastCallTime, timeSinceLastInvoke = time - lastInvokeTime, timeWaiting = wait - timeSinceLastCall;
+ return maxing ? nativeMin(timeWaiting, maxWait - timeSinceLastInvoke) : timeWaiting;
+ }
+ function shouldInvoke(time) {
+ var timeSinceLastCall = time - lastCallTime, timeSinceLastInvoke = time - lastInvokeTime;
+ return lastCallTime === undefined2 || timeSinceLastCall >= wait || timeSinceLastCall < 0 || maxing && timeSinceLastInvoke >= maxWait;
+ }
+ function timerExpired() {
+ var time = now();
+ if (shouldInvoke(time)) {
+ return trailingEdge(time);
+ }
+ timerId = setTimeout2(timerExpired, remainingWait(time));
+ }
+ function trailingEdge(time) {
+ timerId = undefined2;
+ if (trailing && lastArgs) {
+ return invokeFunc(time);
+ }
+ lastArgs = lastThis = undefined2;
+ return result2;
+ }
+ function cancel() {
+ if (timerId !== undefined2) {
+ clearTimeout2(timerId);
+ }
+ lastInvokeTime = 0;
+ lastArgs = lastCallTime = lastThis = timerId = undefined2;
+ }
+ function flush() {
+ return timerId === undefined2 ? result2 : trailingEdge(now());
+ }
+ function debounced() {
+ var time = now(), isInvoking = shouldInvoke(time);
+ lastArgs = arguments;
+ lastThis = this;
+ lastCallTime = time;
+ if (isInvoking) {
+ if (timerId === undefined2) {
+ return leadingEdge(lastCallTime);
+ }
+ if (maxing) {
+ clearTimeout2(timerId);
+ timerId = setTimeout2(timerExpired, wait);
+ return invokeFunc(lastCallTime);
+ }
+ }
+ if (timerId === undefined2) {
+ timerId = setTimeout2(timerExpired, wait);
+ }
+ return result2;
+ }
+ debounced.cancel = cancel;
+ debounced.flush = flush;
+ return debounced;
+ }
+ var defer = baseRest(function(func, args) {
+ return baseDelay(func, 1, args);
+ });
+ var delay = baseRest(function(func, wait, args) {
+ return baseDelay(func, toNumber(wait) || 0, args);
+ });
+ function flip(func) {
+ return createWrap(func, WRAP_FLIP_FLAG);
+ }
+ function memoize(func, resolver) {
+ if (typeof func != "function" || resolver != null && typeof resolver != "function") {
+ throw new TypeError2(FUNC_ERROR_TEXT);
+ }
+ var memoized = function() {
+ var args = arguments, key = resolver ? resolver.apply(this, args) : args[0], cache = memoized.cache;
+ if (cache.has(key)) {
+ return cache.get(key);
+ }
+ var result2 = func.apply(this, args);
+ memoized.cache = cache.set(key, result2) || cache;
+ return result2;
+ };
+ memoized.cache = new (memoize.Cache || MapCache)();
+ return memoized;
+ }
+ memoize.Cache = MapCache;
+ function negate(predicate) {
+ if (typeof predicate != "function") {
+ throw new TypeError2(FUNC_ERROR_TEXT);
+ }
+ return function() {
+ var args = arguments;
+ switch (args.length) {
+ case 0:
+ return !predicate.call(this);
+ case 1:
+ return !predicate.call(this, args[0]);
+ case 2:
+ return !predicate.call(this, args[0], args[1]);
+ case 3:
+ return !predicate.call(this, args[0], args[1], args[2]);
+ }
+ return !predicate.apply(this, args);
+ };
+ }
+ function once(func) {
+ return before(2, func);
+ }
+ var overArgs = castRest(function(func, transforms) {
+ transforms = transforms.length == 1 && isArray(transforms[0]) ? arrayMap(transforms[0], baseUnary(getIteratee())) : arrayMap(baseFlatten(transforms, 1), baseUnary(getIteratee()));
+ var funcsLength = transforms.length;
+ return baseRest(function(args) {
+ var index = -1, length = nativeMin(args.length, funcsLength);
+ while (++index < length) {
+ args[index] = transforms[index].call(this, args[index]);
+ }
+ return apply(func, this, args);
+ });
+ });
+ var partial = baseRest(function(func, partials) {
+ var holders = replaceHolders(partials, getHolder(partial));
+ return createWrap(func, WRAP_PARTIAL_FLAG, undefined2, partials, holders);
+ });
+ var partialRight = baseRest(function(func, partials) {
+ var holders = replaceHolders(partials, getHolder(partialRight));
+ return createWrap(func, WRAP_PARTIAL_RIGHT_FLAG, undefined2, partials, holders);
+ });
+ var rearg = flatRest(function(func, indexes) {
+ return createWrap(func, WRAP_REARG_FLAG, undefined2, undefined2, undefined2, indexes);
+ });
+ function rest(func, start) {
+ if (typeof func != "function") {
+ throw new TypeError2(FUNC_ERROR_TEXT);
+ }
+ start = start === undefined2 ? start : toInteger(start);
+ return baseRest(func, start);
+ }
+ function spread(func, start) {
+ if (typeof func != "function") {
+ throw new TypeError2(FUNC_ERROR_TEXT);
+ }
+ start = start == null ? 0 : nativeMax(toInteger(start), 0);
+ return baseRest(function(args) {
+ var array = args[start], otherArgs = castSlice(args, 0, start);
+ if (array) {
+ arrayPush(otherArgs, array);
+ }
+ return apply(func, this, otherArgs);
+ });
+ }
+ function throttle(func, wait, options) {
+ var leading = true, trailing = true;
+ if (typeof func != "function") {
+ throw new TypeError2(FUNC_ERROR_TEXT);
+ }
+ if (isObject(options)) {
+ leading = "leading" in options ? !!options.leading : leading;
+ trailing = "trailing" in options ? !!options.trailing : trailing;
+ }
+ return debounce(func, wait, {
+ "leading": leading,
+ "maxWait": wait,
+ "trailing": trailing
+ });
+ }
+ function unary(func) {
+ return ary(func, 1);
+ }
+ function wrap(value, wrapper) {
+ return partial(castFunction(wrapper), value);
+ }
+ function castArray() {
+ if (!arguments.length) {
+ return [];
+ }
+ var value = arguments[0];
+ return isArray(value) ? value : [value];
+ }
+ function clone(value) {
+ return baseClone(value, CLONE_SYMBOLS_FLAG);
+ }
+ function cloneWith(value, customizer) {
+ customizer = typeof customizer == "function" ? customizer : undefined2;
+ return baseClone(value, CLONE_SYMBOLS_FLAG, customizer);
+ }
+ function cloneDeep(value) {
+ return baseClone(value, CLONE_DEEP_FLAG | CLONE_SYMBOLS_FLAG);
+ }
+ function cloneDeepWith(value, customizer) {
+ customizer = typeof customizer == "function" ? customizer : undefined2;
+ return baseClone(value, CLONE_DEEP_FLAG | CLONE_SYMBOLS_FLAG, customizer);
+ }
+ function conformsTo(object, source) {
+ return source == null || baseConformsTo(object, source, keys(source));
+ }
+ function eq(value, other) {
+ return value === other || value !== value && other !== other;
+ }
+ var gt = createRelationalOperation(baseGt);
+ var gte = createRelationalOperation(function(value, other) {
+ return value >= other;
+ });
+ var isArguments = baseIsArguments(function() {
+ return arguments;
+ }()) ? baseIsArguments : function(value) {
+ return isObjectLike(value) && hasOwnProperty.call(value, "callee") && !propertyIsEnumerable.call(value, "callee");
+ };
+ var isArray = Array2.isArray;
+ var isArrayBuffer = nodeIsArrayBuffer ? baseUnary(nodeIsArrayBuffer) : baseIsArrayBuffer;
+ function isArrayLike(value) {
+ return value != null && isLength(value.length) && !isFunction(value);
+ }
+ function isArrayLikeObject(value) {
+ return isObjectLike(value) && isArrayLike(value);
+ }
+ function isBoolean(value) {
+ return value === true || value === false || isObjectLike(value) && baseGetTag(value) == boolTag;
+ }
+ var isBuffer = nativeIsBuffer || stubFalse;
+ var isDate = nodeIsDate ? baseUnary(nodeIsDate) : baseIsDate;
+ function isElement(value) {
+ return isObjectLike(value) && value.nodeType === 1 && !isPlainObject(value);
+ }
+ function isEmpty(value) {
+ if (value == null) {
+ return true;
+ }
+ if (isArrayLike(value) && (isArray(value) || typeof value == "string" || typeof value.splice == "function" || isBuffer(value) || isTypedArray(value) || isArguments(value))) {
+ return !value.length;
+ }
+ var tag = getTag(value);
+ if (tag == mapTag || tag == setTag) {
+ return !value.size;
+ }
+ if (isPrototype(value)) {
+ return !baseKeys(value).length;
+ }
+ for (var key in value) {
+ if (hasOwnProperty.call(value, key)) {
+ return false;
+ }
+ }
+ return true;
+ }
+ function isEqual(value, other) {
+ return baseIsEqual(value, other);
+ }
+ function isEqualWith(value, other, customizer) {
+ customizer = typeof customizer == "function" ? customizer : undefined2;
+ var result2 = customizer ? customizer(value, other) : undefined2;
+ return result2 === undefined2 ? baseIsEqual(value, other, undefined2, customizer) : !!result2;
+ }
+ function isError(value) {
+ if (!isObjectLike(value)) {
+ return false;
+ }
+ var tag = baseGetTag(value);
+ return tag == errorTag || tag == domExcTag || typeof value.message == "string" && typeof value.name == "string" && !isPlainObject(value);
+ }
+ function isFinite(value) {
+ return typeof value == "number" && nativeIsFinite(value);
+ }
+ function isFunction(value) {
+ if (!isObject(value)) {
+ return false;
+ }
+ var tag = baseGetTag(value);
+ return tag == funcTag || tag == genTag || tag == asyncTag || tag == proxyTag;
+ }
+ function isInteger(value) {
+ return typeof value == "number" && value == toInteger(value);
+ }
+ function isLength(value) {
+ return typeof value == "number" && value > -1 && value % 1 == 0 && value <= MAX_SAFE_INTEGER;
+ }
+ function isObject(value) {
+ var type = typeof value;
+ return value != null && (type == "object" || type == "function");
+ }
+ function isObjectLike(value) {
+ return value != null && typeof value == "object";
+ }
+ var isMap = nodeIsMap ? baseUnary(nodeIsMap) : baseIsMap;
+ function isMatch(object, source) {
+ return object === source || baseIsMatch(object, source, getMatchData(source));
+ }
+ function isMatchWith(object, source, customizer) {
+ customizer = typeof customizer == "function" ? customizer : undefined2;
+ return baseIsMatch(object, source, getMatchData(source), customizer);
+ }
+ function isNaN(value) {
+ return isNumber(value) && value != +value;
+ }
+ function isNative(value) {
+ if (isMaskable(value)) {
+ throw new Error2(CORE_ERROR_TEXT);
+ }
+ return baseIsNative(value);
+ }
+ function isNull(value) {
+ return value === null;
+ }
+ function isNil(value) {
+ return value == null;
+ }
+ function isNumber(value) {
+ return typeof value == "number" || isObjectLike(value) && baseGetTag(value) == numberTag;
+ }
+ function isPlainObject(value) {
+ if (!isObjectLike(value) || baseGetTag(value) != objectTag) {
+ return false;
+ }
+ var proto = getPrototype(value);
+ if (proto === null) {
+ return true;
+ }
+ var Ctor = hasOwnProperty.call(proto, "constructor") && proto.constructor;
+ return typeof Ctor == "function" && Ctor instanceof Ctor && funcToString.call(Ctor) == objectCtorString;
+ }
+ var isRegExp = nodeIsRegExp ? baseUnary(nodeIsRegExp) : baseIsRegExp;
+ function isSafeInteger(value) {
+ return isInteger(value) && value >= -MAX_SAFE_INTEGER && value <= MAX_SAFE_INTEGER;
+ }
+ var isSet = nodeIsSet ? baseUnary(nodeIsSet) : baseIsSet;
+ function isString(value) {
+ return typeof value == "string" || !isArray(value) && isObjectLike(value) && baseGetTag(value) == stringTag;
+ }
+ function isSymbol(value) {
+ return typeof value == "symbol" || isObjectLike(value) && baseGetTag(value) == symbolTag;
+ }
+ var isTypedArray = nodeIsTypedArray ? baseUnary(nodeIsTypedArray) : baseIsTypedArray;
+ function isUndefined(value) {
+ return value === undefined2;
+ }
+ function isWeakMap(value) {
+ return isObjectLike(value) && getTag(value) == weakMapTag;
+ }
+ function isWeakSet(value) {
+ return isObjectLike(value) && baseGetTag(value) == weakSetTag;
+ }
+ var lt = createRelationalOperation(baseLt);
+ var lte = createRelationalOperation(function(value, other) {
+ return value <= other;
+ });
+ function toArray(value) {
+ if (!value) {
+ return [];
+ }
+ if (isArrayLike(value)) {
+ return isString(value) ? stringToArray(value) : copyArray(value);
+ }
+ if (symIterator && value[symIterator]) {
+ return iteratorToArray(value[symIterator]());
+ }
+ var tag = getTag(value), func = tag == mapTag ? mapToArray : tag == setTag ? setToArray : values;
+ return func(value);
+ }
+ function toFinite(value) {
+ if (!value) {
+ return value === 0 ? value : 0;
+ }
+ value = toNumber(value);
+ if (value === INFINITY || value === -INFINITY) {
+ var sign = value < 0 ? -1 : 1;
+ return sign * MAX_INTEGER;
+ }
+ return value === value ? value : 0;
+ }
+ function toInteger(value) {
+ var result2 = toFinite(value), remainder = result2 % 1;
+ return result2 === result2 ? remainder ? result2 - remainder : result2 : 0;
+ }
+ function toLength(value) {
+ return value ? baseClamp(toInteger(value), 0, MAX_ARRAY_LENGTH) : 0;
+ }
+ function toNumber(value) {
+ if (typeof value == "number") {
+ return value;
+ }
+ if (isSymbol(value)) {
+ return NAN;
+ }
+ if (isObject(value)) {
+ var other = typeof value.valueOf == "function" ? value.valueOf() : value;
+ value = isObject(other) ? other + "" : other;
+ }
+ if (typeof value != "string") {
+ return value === 0 ? value : +value;
+ }
+ value = baseTrim(value);
+ var isBinary = reIsBinary.test(value);
+ return isBinary || reIsOctal.test(value) ? freeParseInt(value.slice(2), isBinary ? 2 : 8) : reIsBadHex.test(value) ? NAN : +value;
+ }
+ function toPlainObject(value) {
+ return copyObject(value, keysIn(value));
+ }
+ function toSafeInteger(value) {
+ return value ? baseClamp(toInteger(value), -MAX_SAFE_INTEGER, MAX_SAFE_INTEGER) : value === 0 ? value : 0;
+ }
+ function toString(value) {
+ return value == null ? "" : baseToString(value);
+ }
+ var assign = createAssigner(function(object, source) {
+ if (isPrototype(source) || isArrayLike(source)) {
+ copyObject(source, keys(source), object);
+ return;
+ }
+ for (var key in source) {
+ if (hasOwnProperty.call(source, key)) {
+ assignValue(object, key, source[key]);
+ }
+ }
+ });
+ var assignIn = createAssigner(function(object, source) {
+ copyObject(source, keysIn(source), object);
+ });
+ var assignInWith = createAssigner(function(object, source, srcIndex, customizer) {
+ copyObject(source, keysIn(source), object, customizer);
+ });
+ var assignWith = createAssigner(function(object, source, srcIndex, customizer) {
+ copyObject(source, keys(source), object, customizer);
+ });
+ var at = flatRest(baseAt);
+ function create(prototype, properties) {
+ var result2 = baseCreate(prototype);
+ return properties == null ? result2 : baseAssign(result2, properties);
+ }
+ var defaults = baseRest(function(object, sources) {
+ object = Object2(object);
+ var index = -1;
+ var length = sources.length;
+ var guard = length > 2 ? sources[2] : undefined2;
+ if (guard && isIterateeCall(sources[0], sources[1], guard)) {
+ length = 1;
+ }
+ while (++index < length) {
+ var source = sources[index];
+ var props = keysIn(source);
+ var propsIndex = -1;
+ var propsLength = props.length;
+ while (++propsIndex < propsLength) {
+ var key = props[propsIndex];
+ var value = object[key];
+ if (value === undefined2 || eq(value, objectProto[key]) && !hasOwnProperty.call(object, key)) {
+ object[key] = source[key];
+ }
+ }
+ }
+ return object;
+ });
+ var defaultsDeep = baseRest(function(args) {
+ args.push(undefined2, customDefaultsMerge);
+ return apply(mergeWith, undefined2, args);
+ });
+ function findKey(object, predicate) {
+ return baseFindKey(object, getIteratee(predicate, 3), baseForOwn);
+ }
+ function findLastKey(object, predicate) {
+ return baseFindKey(object, getIteratee(predicate, 3), baseForOwnRight);
+ }
+ function forIn(object, iteratee2) {
+ return object == null ? object : baseFor(object, getIteratee(iteratee2, 3), keysIn);
+ }
+ function forInRight(object, iteratee2) {
+ return object == null ? object : baseForRight(object, getIteratee(iteratee2, 3), keysIn);
+ }
+ function forOwn(object, iteratee2) {
+ return object && baseForOwn(object, getIteratee(iteratee2, 3));
+ }
+ function forOwnRight(object, iteratee2) {
+ return object && baseForOwnRight(object, getIteratee(iteratee2, 3));
+ }
+ function functions(object) {
+ return object == null ? [] : baseFunctions(object, keys(object));
+ }
+ function functionsIn(object) {
+ return object == null ? [] : baseFunctions(object, keysIn(object));
+ }
+ function get(object, path, defaultValue) {
+ var result2 = object == null ? undefined2 : baseGet(object, path);
+ return result2 === undefined2 ? defaultValue : result2;
+ }
+ function has(object, path) {
+ return object != null && hasPath(object, path, baseHas);
+ }
+ function hasIn(object, path) {
+ return object != null && hasPath(object, path, baseHasIn);
+ }
+ var invert = createInverter(function(result2, value, key) {
+ if (value != null && typeof value.toString != "function") {
+ value = nativeObjectToString.call(value);
+ }
+ result2[value] = key;
+ }, constant(identity));
+ var invertBy = createInverter(function(result2, value, key) {
+ if (value != null && typeof value.toString != "function") {
+ value = nativeObjectToString.call(value);
+ }
+ if (hasOwnProperty.call(result2, value)) {
+ result2[value].push(key);
+ } else {
+ result2[value] = [key];
+ }
+ }, getIteratee);
+ var invoke = baseRest(baseInvoke);
+ function keys(object) {
+ return isArrayLike(object) ? arrayLikeKeys(object) : baseKeys(object);
+ }
+ function keysIn(object) {
+ return isArrayLike(object) ? arrayLikeKeys(object, true) : baseKeysIn(object);
+ }
+ function mapKeys(object, iteratee2) {
+ var result2 = {};
+ iteratee2 = getIteratee(iteratee2, 3);
+ baseForOwn(object, function(value, key, object2) {
+ baseAssignValue(result2, iteratee2(value, key, object2), value);
+ });
+ return result2;
+ }
+ function mapValues(object, iteratee2) {
+ var result2 = {};
+ iteratee2 = getIteratee(iteratee2, 3);
+ baseForOwn(object, function(value, key, object2) {
+ baseAssignValue(result2, key, iteratee2(value, key, object2));
+ });
+ return result2;
+ }
+ var merge = createAssigner(function(object, source, srcIndex) {
+ baseMerge(object, source, srcIndex);
+ });
+ var mergeWith = createAssigner(function(object, source, srcIndex, customizer) {
+ baseMerge(object, source, srcIndex, customizer);
+ });
+ var omit = flatRest(function(object, paths) {
+ var result2 = {};
+ if (object == null) {
+ return result2;
+ }
+ var isDeep = false;
+ paths = arrayMap(paths, function(path) {
+ path = castPath(path, object);
+ isDeep || (isDeep = path.length > 1);
+ return path;
+ });
+ copyObject(object, getAllKeysIn(object), result2);
+ if (isDeep) {
+ result2 = baseClone(result2, CLONE_DEEP_FLAG | CLONE_FLAT_FLAG | CLONE_SYMBOLS_FLAG, customOmitClone);
+ }
+ var length = paths.length;
+ while (length--) {
+ baseUnset(result2, paths[length]);
+ }
+ return result2;
+ });
+ function omitBy(object, predicate) {
+ return pickBy(object, negate(getIteratee(predicate)));
+ }
+ var pick = flatRest(function(object, paths) {
+ return object == null ? {} : basePick(object, paths);
+ });
+ function pickBy(object, predicate) {
+ if (object == null) {
+ return {};
+ }
+ var props = arrayMap(getAllKeysIn(object), function(prop) {
+ return [prop];
+ });
+ predicate = getIteratee(predicate);
+ return basePickBy(object, props, function(value, path) {
+ return predicate(value, path[0]);
+ });
+ }
+ function result(object, path, defaultValue) {
+ path = castPath(path, object);
+ var index = -1, length = path.length;
+ if (!length) {
+ length = 1;
+ object = undefined2;
+ }
+ while (++index < length) {
+ var value = object == null ? undefined2 : object[toKey(path[index])];
+ if (value === undefined2) {
+ index = length;
+ value = defaultValue;
+ }
+ object = isFunction(value) ? value.call(object) : value;
+ }
+ return object;
+ }
+ function set(object, path, value) {
+ return object == null ? object : baseSet(object, path, value);
+ }
+ function setWith(object, path, value, customizer) {
+ customizer = typeof customizer == "function" ? customizer : undefined2;
+ return object == null ? object : baseSet(object, path, value, customizer);
+ }
+ var toPairs = createToPairs(keys);
+ var toPairsIn = createToPairs(keysIn);
+ function transform(object, iteratee2, accumulator) {
+ var isArr = isArray(object), isArrLike = isArr || isBuffer(object) || isTypedArray(object);
+ iteratee2 = getIteratee(iteratee2, 4);
+ if (accumulator == null) {
+ var Ctor = object && object.constructor;
+ if (isArrLike) {
+ accumulator = isArr ? new Ctor() : [];
+ } else if (isObject(object)) {
+ accumulator = isFunction(Ctor) ? baseCreate(getPrototype(object)) : {};
+ } else {
+ accumulator = {};
+ }
+ }
+ (isArrLike ? arrayEach : baseForOwn)(object, function(value, index, object2) {
+ return iteratee2(accumulator, value, index, object2);
+ });
+ return accumulator;
+ }
+ function unset(object, path) {
+ return object == null ? true : baseUnset(object, path);
+ }
+ function update(object, path, updater) {
+ return object == null ? object : baseUpdate(object, path, castFunction(updater));
+ }
+ function updateWith(object, path, updater, customizer) {
+ customizer = typeof customizer == "function" ? customizer : undefined2;
+ return object == null ? object : baseUpdate(object, path, castFunction(updater), customizer);
+ }
+ function values(object) {
+ return object == null ? [] : baseValues(object, keys(object));
+ }
+ function valuesIn(object) {
+ return object == null ? [] : baseValues(object, keysIn(object));
+ }
+ function clamp(number, lower, upper) {
+ if (upper === undefined2) {
+ upper = lower;
+ lower = undefined2;
+ }
+ if (upper !== undefined2) {
+ upper = toNumber(upper);
+ upper = upper === upper ? upper : 0;
+ }
+ if (lower !== undefined2) {
+ lower = toNumber(lower);
+ lower = lower === lower ? lower : 0;
+ }
+ return baseClamp(toNumber(number), lower, upper);
+ }
+ function inRange(number, start, end) {
+ start = toFinite(start);
+ if (end === undefined2) {
+ end = start;
+ start = 0;
+ } else {
+ end = toFinite(end);
+ }
+ number = toNumber(number);
+ return baseInRange(number, start, end);
+ }
+ function random(lower, upper, floating) {
+ if (floating && typeof floating != "boolean" && isIterateeCall(lower, upper, floating)) {
+ upper = floating = undefined2;
+ }
+ if (floating === undefined2) {
+ if (typeof upper == "boolean") {
+ floating = upper;
+ upper = undefined2;
+ } else if (typeof lower == "boolean") {
+ floating = lower;
+ lower = undefined2;
+ }
+ }
+ if (lower === undefined2 && upper === undefined2) {
+ lower = 0;
+ upper = 1;
+ } else {
+ lower = toFinite(lower);
+ if (upper === undefined2) {
+ upper = lower;
+ lower = 0;
+ } else {
+ upper = toFinite(upper);
+ }
+ }
+ if (lower > upper) {
+ var temp = lower;
+ lower = upper;
+ upper = temp;
+ }
+ if (floating || lower % 1 || upper % 1) {
+ var rand = nativeRandom();
+ return nativeMin(lower + rand * (upper - lower + freeParseFloat("1e-" + ((rand + "").length - 1))), upper);
+ }
+ return baseRandom(lower, upper);
+ }
+ var camelCase = createCompounder(function(result2, word, index) {
+ word = word.toLowerCase();
+ return result2 + (index ? capitalize(word) : word);
+ });
+ function capitalize(string) {
+ return upperFirst(toString(string).toLowerCase());
+ }
+ function deburr(string) {
+ string = toString(string);
+ return string && string.replace(reLatin, deburrLetter).replace(reComboMark, "");
+ }
+ function endsWith(string, target, position) {
+ string = toString(string);
+ target = baseToString(target);
+ var length = string.length;
+ position = position === undefined2 ? length : baseClamp(toInteger(position), 0, length);
+ var end = position;
+ position -= target.length;
+ return position >= 0 && string.slice(position, end) == target;
+ }
+ function escape(string) {
+ string = toString(string);
+ return string && reHasUnescapedHtml.test(string) ? string.replace(reUnescapedHtml, escapeHtmlChar) : string;
+ }
+ function escapeRegExp(string) {
+ string = toString(string);
+ return string && reHasRegExpChar.test(string) ? string.replace(reRegExpChar, "\\$&") : string;
+ }
+ var kebabCase = createCompounder(function(result2, word, index) {
+ return result2 + (index ? "-" : "") + word.toLowerCase();
+ });
+ var lowerCase = createCompounder(function(result2, word, index) {
+ return result2 + (index ? " " : "") + word.toLowerCase();
+ });
+ var lowerFirst = createCaseFirst("toLowerCase");
+ function pad(string, length, chars) {
+ string = toString(string);
+ length = toInteger(length);
+ var strLength = length ? stringSize(string) : 0;
+ if (!length || strLength >= length) {
+ return string;
+ }
+ var mid = (length - strLength) / 2;
+ return createPadding(nativeFloor(mid), chars) + string + createPadding(nativeCeil(mid), chars);
+ }
+ function padEnd(string, length, chars) {
+ string = toString(string);
+ length = toInteger(length);
+ var strLength = length ? stringSize(string) : 0;
+ return length && strLength < length ? string + createPadding(length - strLength, chars) : string;
+ }
+ function padStart(string, length, chars) {
+ string = toString(string);
+ length = toInteger(length);
+ var strLength = length ? stringSize(string) : 0;
+ return length && strLength < length ? createPadding(length - strLength, chars) + string : string;
+ }
+ function parseInt2(string, radix, guard) {
+ if (guard || radix == null) {
+ radix = 0;
+ } else if (radix) {
+ radix = +radix;
+ }
+ return nativeParseInt(toString(string).replace(reTrimStart, ""), radix || 0);
+ }
+ function repeat(string, n, guard) {
+ if (guard ? isIterateeCall(string, n, guard) : n === undefined2) {
+ n = 1;
+ } else {
+ n = toInteger(n);
+ }
+ return baseRepeat(toString(string), n);
+ }
+ function replace() {
+ var args = arguments, string = toString(args[0]);
+ return args.length < 3 ? string : string.replace(args[1], args[2]);
+ }
+ var snakeCase = createCompounder(function(result2, word, index) {
+ return result2 + (index ? "_" : "") + word.toLowerCase();
+ });
+ function split(string, separator, limit) {
+ if (limit && typeof limit != "number" && isIterateeCall(string, separator, limit)) {
+ separator = limit = undefined2;
+ }
+ limit = limit === undefined2 ? MAX_ARRAY_LENGTH : limit >>> 0;
+ if (!limit) {
+ return [];
+ }
+ string = toString(string);
+ if (string && (typeof separator == "string" || separator != null && !isRegExp(separator))) {
+ separator = baseToString(separator);
+ if (!separator && hasUnicode(string)) {
+ return castSlice(stringToArray(string), 0, limit);
+ }
+ }
+ return string.split(separator, limit);
+ }
+ var startCase = createCompounder(function(result2, word, index) {
+ return result2 + (index ? " " : "") + upperFirst(word);
+ });
+ function startsWith(string, target, position) {
+ string = toString(string);
+ position = position == null ? 0 : baseClamp(toInteger(position), 0, string.length);
+ target = baseToString(target);
+ return string.slice(position, position + target.length) == target;
+ }
+ function template(string, options, guard) {
+ var settings = lodash.templateSettings;
+ if (guard && isIterateeCall(string, options, guard)) {
+ options = undefined2;
+ }
+ string = toString(string);
+ options = assignInWith({}, options, settings, customDefaultsAssignIn);
+ var imports = assignInWith({}, options.imports, settings.imports, customDefaultsAssignIn), importsKeys = keys(imports), importsValues = baseValues(imports, importsKeys);
+ var isEscaping, isEvaluating, index = 0, interpolate = options.interpolate || reNoMatch, source = "__p += '";
+ var reDelimiters = RegExp2(
+ (options.escape || reNoMatch).source + "|" + interpolate.source + "|" + (interpolate === reInterpolate ? reEsTemplate : reNoMatch).source + "|" + (options.evaluate || reNoMatch).source + "|$",
+ "g"
+ );
+ var sourceURL = "//# sourceURL=" + (hasOwnProperty.call(options, "sourceURL") ? (options.sourceURL + "").replace(/\s/g, " ") : "lodash.templateSources[" + ++templateCounter + "]") + "\n";
+ string.replace(reDelimiters, function(match, escapeValue, interpolateValue, esTemplateValue, evaluateValue, offset) {
+ interpolateValue || (interpolateValue = esTemplateValue);
+ source += string.slice(index, offset).replace(reUnescapedString, escapeStringChar);
+ if (escapeValue) {
+ isEscaping = true;
+ source += "' +\n__e(" + escapeValue + ") +\n'";
+ }
+ if (evaluateValue) {
+ isEvaluating = true;
+ source += "';\n" + evaluateValue + ";\n__p += '";
+ }
+ if (interpolateValue) {
+ source += "' +\n((__t = (" + interpolateValue + ")) == null ? '' : __t) +\n'";
+ }
+ index = offset + match.length;
+ return match;
+ });
+ source += "';\n";
+ var variable = hasOwnProperty.call(options, "variable") && options.variable;
+ if (!variable) {
+ source = "with (obj) {\n" + source + "\n}\n";
+ } else if (reForbiddenIdentifierChars.test(variable)) {
+ throw new Error2(INVALID_TEMPL_VAR_ERROR_TEXT);
+ }
+ source = (isEvaluating ? source.replace(reEmptyStringLeading, "") : source).replace(reEmptyStringMiddle, "$1").replace(reEmptyStringTrailing, "$1;");
+ source = "function(" + (variable || "obj") + ") {\n" + (variable ? "" : "obj || (obj = {});\n") + "var __t, __p = ''" + (isEscaping ? ", __e = _.escape" : "") + (isEvaluating ? ", __j = Array.prototype.join;\nfunction print() { __p += __j.call(arguments, '') }\n" : ";\n") + source + "return __p\n}";
+ var result2 = attempt(function() {
+ return Function2(importsKeys, sourceURL + "return " + source).apply(undefined2, importsValues);
+ });
+ result2.source = source;
+ if (isError(result2)) {
+ throw result2;
+ }
+ return result2;
+ }
+ function toLower(value) {
+ return toString(value).toLowerCase();
+ }
+ function toUpper(value) {
+ return toString(value).toUpperCase();
+ }
+ function trim(string, chars, guard) {
+ string = toString(string);
+ if (string && (guard || chars === undefined2)) {
+ return baseTrim(string);
+ }
+ if (!string || !(chars = baseToString(chars))) {
+ return string;
+ }
+ var strSymbols = stringToArray(string), chrSymbols = stringToArray(chars), start = charsStartIndex(strSymbols, chrSymbols), end = charsEndIndex(strSymbols, chrSymbols) + 1;
+ return castSlice(strSymbols, start, end).join("");
+ }
+ function trimEnd(string, chars, guard) {
+ string = toString(string);
+ if (string && (guard || chars === undefined2)) {
+ return string.slice(0, trimmedEndIndex(string) + 1);
+ }
+ if (!string || !(chars = baseToString(chars))) {
+ return string;
+ }
+ var strSymbols = stringToArray(string), end = charsEndIndex(strSymbols, stringToArray(chars)) + 1;
+ return castSlice(strSymbols, 0, end).join("");
+ }
+ function trimStart(string, chars, guard) {
+ string = toString(string);
+ if (string && (guard || chars === undefined2)) {
+ return string.replace(reTrimStart, "");
+ }
+ if (!string || !(chars = baseToString(chars))) {
+ return string;
+ }
+ var strSymbols = stringToArray(string), start = charsStartIndex(strSymbols, stringToArray(chars));
+ return castSlice(strSymbols, start).join("");
+ }
+ function truncate(string, options) {
+ var length = DEFAULT_TRUNC_LENGTH, omission = DEFAULT_TRUNC_OMISSION;
+ if (isObject(options)) {
+ var separator = "separator" in options ? options.separator : separator;
+ length = "length" in options ? toInteger(options.length) : length;
+ omission = "omission" in options ? baseToString(options.omission) : omission;
+ }
+ string = toString(string);
+ var strLength = string.length;
+ if (hasUnicode(string)) {
+ var strSymbols = stringToArray(string);
+ strLength = strSymbols.length;
+ }
+ if (length >= strLength) {
+ return string;
+ }
+ var end = length - stringSize(omission);
+ if (end < 1) {
+ return omission;
+ }
+ var result2 = strSymbols ? castSlice(strSymbols, 0, end).join("") : string.slice(0, end);
+ if (separator === undefined2) {
+ return result2 + omission;
+ }
+ if (strSymbols) {
+ end += result2.length - end;
+ }
+ if (isRegExp(separator)) {
+ if (string.slice(end).search(separator)) {
+ var match, substring = result2;
+ if (!separator.global) {
+ separator = RegExp2(separator.source, toString(reFlags.exec(separator)) + "g");
+ }
+ separator.lastIndex = 0;
+ while (match = separator.exec(substring)) {
+ var newEnd = match.index;
+ }
+ result2 = result2.slice(0, newEnd === undefined2 ? end : newEnd);
+ }
+ } else if (string.indexOf(baseToString(separator), end) != end) {
+ var index = result2.lastIndexOf(separator);
+ if (index > -1) {
+ result2 = result2.slice(0, index);
+ }
+ }
+ return result2 + omission;
+ }
+ function unescape(string) {
+ string = toString(string);
+ return string && reHasEscapedHtml.test(string) ? string.replace(reEscapedHtml, unescapeHtmlChar) : string;
+ }
+ var upperCase = createCompounder(function(result2, word, index) {
+ return result2 + (index ? " " : "") + word.toUpperCase();
+ });
+ var upperFirst = createCaseFirst("toUpperCase");
+ function words(string, pattern, guard) {
+ string = toString(string);
+ pattern = guard ? undefined2 : pattern;
+ if (pattern === undefined2) {
+ return hasUnicodeWord(string) ? unicodeWords(string) : asciiWords(string);
+ }
+ return string.match(pattern) || [];
+ }
+ var attempt = baseRest(function(func, args) {
+ try {
+ return apply(func, undefined2, args);
+ } catch (e) {
+ return isError(e) ? e : new Error2(e);
+ }
+ });
+ var bindAll = flatRest(function(object, methodNames) {
+ arrayEach(methodNames, function(key) {
+ key = toKey(key);
+ baseAssignValue(object, key, bind(object[key], object));
+ });
+ return object;
+ });
+ function cond(pairs) {
+ var length = pairs == null ? 0 : pairs.length, toIteratee = getIteratee();
+ pairs = !length ? [] : arrayMap(pairs, function(pair) {
+ if (typeof pair[1] != "function") {
+ throw new TypeError2(FUNC_ERROR_TEXT);
+ }
+ return [toIteratee(pair[0]), pair[1]];
+ });
+ return baseRest(function(args) {
+ var index = -1;
+ while (++index < length) {
+ var pair = pairs[index];
+ if (apply(pair[0], this, args)) {
+ return apply(pair[1], this, args);
+ }
+ }
+ });
+ }
+ function conforms(source) {
+ return baseConforms(baseClone(source, CLONE_DEEP_FLAG));
+ }
+ function constant(value) {
+ return function() {
+ return value;
+ };
+ }
+ function defaultTo(value, defaultValue) {
+ return value == null || value !== value ? defaultValue : value;
+ }
+ var flow = createFlow();
+ var flowRight = createFlow(true);
+ function identity(value) {
+ return value;
+ }
+ function iteratee(func) {
+ return baseIteratee(typeof func == "function" ? func : baseClone(func, CLONE_DEEP_FLAG));
+ }
+ function matches(source) {
+ return baseMatches(baseClone(source, CLONE_DEEP_FLAG));
+ }
+ function matchesProperty(path, srcValue) {
+ return baseMatchesProperty(path, baseClone(srcValue, CLONE_DEEP_FLAG));
+ }
+ var method = baseRest(function(path, args) {
+ return function(object) {
+ return baseInvoke(object, path, args);
+ };
+ });
+ var methodOf = baseRest(function(object, args) {
+ return function(path) {
+ return baseInvoke(object, path, args);
+ };
+ });
+ function mixin(object, source, options) {
+ var props = keys(source), methodNames = baseFunctions(source, props);
+ if (options == null && !(isObject(source) && (methodNames.length || !props.length))) {
+ options = source;
+ source = object;
+ object = this;
+ methodNames = baseFunctions(source, keys(source));
+ }
+ var chain2 = !(isObject(options) && "chain" in options) || !!options.chain, isFunc = isFunction(object);
+ arrayEach(methodNames, function(methodName) {
+ var func = source[methodName];
+ object[methodName] = func;
+ if (isFunc) {
+ object.prototype[methodName] = function() {
+ var chainAll = this.__chain__;
+ if (chain2 || chainAll) {
+ var result2 = object(this.__wrapped__), actions = result2.__actions__ = copyArray(this.__actions__);
+ actions.push({ "func": func, "args": arguments, "thisArg": object });
+ result2.__chain__ = chainAll;
+ return result2;
+ }
+ return func.apply(object, arrayPush([this.value()], arguments));
+ };
+ }
+ });
+ return object;
+ }
+ function noConflict() {
+ if (root._ === this) {
+ root._ = oldDash;
+ }
+ return this;
+ }
+ function noop() {
+ }
+ function nthArg(n) {
+ n = toInteger(n);
+ return baseRest(function(args) {
+ return baseNth(args, n);
+ });
+ }
+ var over = createOver(arrayMap);
+ var overEvery = createOver(arrayEvery);
+ var overSome = createOver(arraySome);
+ function property(path) {
+ return isKey(path) ? baseProperty(toKey(path)) : basePropertyDeep(path);
+ }
+ function propertyOf(object) {
+ return function(path) {
+ return object == null ? undefined2 : baseGet(object, path);
+ };
+ }
+ var range = createRange();
+ var rangeRight = createRange(true);
+ function stubArray() {
+ return [];
+ }
+ function stubFalse() {
+ return false;
+ }
+ function stubObject() {
+ return {};
+ }
+ function stubString() {
+ return "";
+ }
+ function stubTrue() {
+ return true;
+ }
+ function times(n, iteratee2) {
+ n = toInteger(n);
+ if (n < 1 || n > MAX_SAFE_INTEGER) {
+ return [];
+ }
+ var index = MAX_ARRAY_LENGTH, length = nativeMin(n, MAX_ARRAY_LENGTH);
+ iteratee2 = getIteratee(iteratee2);
+ n -= MAX_ARRAY_LENGTH;
+ var result2 = baseTimes(length, iteratee2);
+ while (++index < n) {
+ iteratee2(index);
+ }
+ return result2;
+ }
+ function toPath(value) {
+ if (isArray(value)) {
+ return arrayMap(value, toKey);
+ }
+ return isSymbol(value) ? [value] : copyArray(stringToPath(toString(value)));
+ }
+ function uniqueId(prefix) {
+ var id = ++idCounter;
+ return toString(prefix) + id;
+ }
+ var add = createMathOperation(function(augend, addend) {
+ return augend + addend;
+ }, 0);
+ var ceil = createRound("ceil");
+ var divide = createMathOperation(function(dividend, divisor) {
+ return dividend / divisor;
+ }, 1);
+ var floor = createRound("floor");
+ function max(array) {
+ return array && array.length ? baseExtremum(array, identity, baseGt) : undefined2;
+ }
+ function maxBy(array, iteratee2) {
+ return array && array.length ? baseExtremum(array, getIteratee(iteratee2, 2), baseGt) : undefined2;
+ }
+ function mean(array) {
+ return baseMean(array, identity);
+ }
+ function meanBy(array, iteratee2) {
+ return baseMean(array, getIteratee(iteratee2, 2));
+ }
+ function min(array) {
+ return array && array.length ? baseExtremum(array, identity, baseLt) : undefined2;
+ }
+ function minBy(array, iteratee2) {
+ return array && array.length ? baseExtremum(array, getIteratee(iteratee2, 2), baseLt) : undefined2;
+ }
+ var multiply = createMathOperation(function(multiplier, multiplicand) {
+ return multiplier * multiplicand;
+ }, 1);
+ var round = createRound("round");
+ var subtract = createMathOperation(function(minuend, subtrahend) {
+ return minuend - subtrahend;
+ }, 0);
+ function sum(array) {
+ return array && array.length ? baseSum(array, identity) : 0;
+ }
+ function sumBy(array, iteratee2) {
+ return array && array.length ? baseSum(array, getIteratee(iteratee2, 2)) : 0;
+ }
+ lodash.after = after;
+ lodash.ary = ary;
+ lodash.assign = assign;
+ lodash.assignIn = assignIn;
+ lodash.assignInWith = assignInWith;
+ lodash.assignWith = assignWith;
+ lodash.at = at;
+ lodash.before = before;
+ lodash.bind = bind;
+ lodash.bindAll = bindAll;
+ lodash.bindKey = bindKey;
+ lodash.castArray = castArray;
+ lodash.chain = chain;
+ lodash.chunk = chunk;
+ lodash.compact = compact;
+ lodash.concat = concat;
+ lodash.cond = cond;
+ lodash.conforms = conforms;
+ lodash.constant = constant;
+ lodash.countBy = countBy;
+ lodash.create = create;
+ lodash.curry = curry;
+ lodash.curryRight = curryRight;
+ lodash.debounce = debounce;
+ lodash.defaults = defaults;
+ lodash.defaultsDeep = defaultsDeep;
+ lodash.defer = defer;
+ lodash.delay = delay;
+ lodash.difference = difference;
+ lodash.differenceBy = differenceBy;
+ lodash.differenceWith = differenceWith;
+ lodash.drop = drop;
+ lodash.dropRight = dropRight;
+ lodash.dropRightWhile = dropRightWhile;
+ lodash.dropWhile = dropWhile;
+ lodash.fill = fill;
+ lodash.filter = filter;
+ lodash.flatMap = flatMap;
+ lodash.flatMapDeep = flatMapDeep;
+ lodash.flatMapDepth = flatMapDepth;
+ lodash.flatten = flatten;
+ lodash.flattenDeep = flattenDeep;
+ lodash.flattenDepth = flattenDepth;
+ lodash.flip = flip;
+ lodash.flow = flow;
+ lodash.flowRight = flowRight;
+ lodash.fromPairs = fromPairs;
+ lodash.functions = functions;
+ lodash.functionsIn = functionsIn;
+ lodash.groupBy = groupBy;
+ lodash.initial = initial;
+ lodash.intersection = intersection;
+ lodash.intersectionBy = intersectionBy;
+ lodash.intersectionWith = intersectionWith;
+ lodash.invert = invert;
+ lodash.invertBy = invertBy;
+ lodash.invokeMap = invokeMap;
+ lodash.iteratee = iteratee;
+ lodash.keyBy = keyBy;
+ lodash.keys = keys;
+ lodash.keysIn = keysIn;
+ lodash.map = map;
+ lodash.mapKeys = mapKeys;
+ lodash.mapValues = mapValues;
+ lodash.matches = matches;
+ lodash.matchesProperty = matchesProperty;
+ lodash.memoize = memoize;
+ lodash.merge = merge;
+ lodash.mergeWith = mergeWith;
+ lodash.method = method;
+ lodash.methodOf = methodOf;
+ lodash.mixin = mixin;
+ lodash.negate = negate;
+ lodash.nthArg = nthArg;
+ lodash.omit = omit;
+ lodash.omitBy = omitBy;
+ lodash.once = once;
+ lodash.orderBy = orderBy;
+ lodash.over = over;
+ lodash.overArgs = overArgs;
+ lodash.overEvery = overEvery;
+ lodash.overSome = overSome;
+ lodash.partial = partial;
+ lodash.partialRight = partialRight;
+ lodash.partition = partition;
+ lodash.pick = pick;
+ lodash.pickBy = pickBy;
+ lodash.property = property;
+ lodash.propertyOf = propertyOf;
+ lodash.pull = pull;
+ lodash.pullAll = pullAll;
+ lodash.pullAllBy = pullAllBy;
+ lodash.pullAllWith = pullAllWith;
+ lodash.pullAt = pullAt;
+ lodash.range = range;
+ lodash.rangeRight = rangeRight;
+ lodash.rearg = rearg;
+ lodash.reject = reject;
+ lodash.remove = remove;
+ lodash.rest = rest;
+ lodash.reverse = reverse;
+ lodash.sampleSize = sampleSize;
+ lodash.set = set;
+ lodash.setWith = setWith;
+ lodash.shuffle = shuffle;
+ lodash.slice = slice;
+ lodash.sortBy = sortBy;
+ lodash.sortedUniq = sortedUniq;
+ lodash.sortedUniqBy = sortedUniqBy;
+ lodash.split = split;
+ lodash.spread = spread;
+ lodash.tail = tail;
+ lodash.take = take;
+ lodash.takeRight = takeRight;
+ lodash.takeRightWhile = takeRightWhile;
+ lodash.takeWhile = takeWhile;
+ lodash.tap = tap;
+ lodash.throttle = throttle;
+ lodash.thru = thru;
+ lodash.toArray = toArray;
+ lodash.toPairs = toPairs;
+ lodash.toPairsIn = toPairsIn;
+ lodash.toPath = toPath;
+ lodash.toPlainObject = toPlainObject;
+ lodash.transform = transform;
+ lodash.unary = unary;
+ lodash.union = union;
+ lodash.unionBy = unionBy;
+ lodash.unionWith = unionWith;
+ lodash.uniq = uniq;
+ lodash.uniqBy = uniqBy;
+ lodash.uniqWith = uniqWith;
+ lodash.unset = unset;
+ lodash.unzip = unzip;
+ lodash.unzipWith = unzipWith;
+ lodash.update = update;
+ lodash.updateWith = updateWith;
+ lodash.values = values;
+ lodash.valuesIn = valuesIn;
+ lodash.without = without;
+ lodash.words = words;
+ lodash.wrap = wrap;
+ lodash.xor = xor;
+ lodash.xorBy = xorBy;
+ lodash.xorWith = xorWith;
+ lodash.zip = zip;
+ lodash.zipObject = zipObject;
+ lodash.zipObjectDeep = zipObjectDeep;
+ lodash.zipWith = zipWith;
+ lodash.entries = toPairs;
+ lodash.entriesIn = toPairsIn;
+ lodash.extend = assignIn;
+ lodash.extendWith = assignInWith;
+ mixin(lodash, lodash);
+ lodash.add = add;
+ lodash.attempt = attempt;
+ lodash.camelCase = camelCase;
+ lodash.capitalize = capitalize;
+ lodash.ceil = ceil;
+ lodash.clamp = clamp;
+ lodash.clone = clone;
+ lodash.cloneDeep = cloneDeep;
+ lodash.cloneDeepWith = cloneDeepWith;
+ lodash.cloneWith = cloneWith;
+ lodash.conformsTo = conformsTo;
+ lodash.deburr = deburr;
+ lodash.defaultTo = defaultTo;
+ lodash.divide = divide;
+ lodash.endsWith = endsWith;
+ lodash.eq = eq;
+ lodash.escape = escape;
+ lodash.escapeRegExp = escapeRegExp;
+ lodash.every = every;
+ lodash.find = find;
+ lodash.findIndex = findIndex;
+ lodash.findKey = findKey;
+ lodash.findLast = findLast;
+ lodash.findLastIndex = findLastIndex;
+ lodash.findLastKey = findLastKey;
+ lodash.floor = floor;
+ lodash.forEach = forEach;
+ lodash.forEachRight = forEachRight;
+ lodash.forIn = forIn;
+ lodash.forInRight = forInRight;
+ lodash.forOwn = forOwn;
+ lodash.forOwnRight = forOwnRight;
+ lodash.get = get;
+ lodash.gt = gt;
+ lodash.gte = gte;
+ lodash.has = has;
+ lodash.hasIn = hasIn;
+ lodash.head = head;
+ lodash.identity = identity;
+ lodash.includes = includes;
+ lodash.indexOf = indexOf;
+ lodash.inRange = inRange;
+ lodash.invoke = invoke;
+ lodash.isArguments = isArguments;
+ lodash.isArray = isArray;
+ lodash.isArrayBuffer = isArrayBuffer;
+ lodash.isArrayLike = isArrayLike;
+ lodash.isArrayLikeObject = isArrayLikeObject;
+ lodash.isBoolean = isBoolean;
+ lodash.isBuffer = isBuffer;
+ lodash.isDate = isDate;
+ lodash.isElement = isElement;
+ lodash.isEmpty = isEmpty;
+ lodash.isEqual = isEqual;
+ lodash.isEqualWith = isEqualWith;
+ lodash.isError = isError;
+ lodash.isFinite = isFinite;
+ lodash.isFunction = isFunction;
+ lodash.isInteger = isInteger;
+ lodash.isLength = isLength;
+ lodash.isMap = isMap;
+ lodash.isMatch = isMatch;
+ lodash.isMatchWith = isMatchWith;
+ lodash.isNaN = isNaN;
+ lodash.isNative = isNative;
+ lodash.isNil = isNil;
+ lodash.isNull = isNull;
+ lodash.isNumber = isNumber;
+ lodash.isObject = isObject;
+ lodash.isObjectLike = isObjectLike;
+ lodash.isPlainObject = isPlainObject;
+ lodash.isRegExp = isRegExp;
+ lodash.isSafeInteger = isSafeInteger;
+ lodash.isSet = isSet;
+ lodash.isString = isString;
+ lodash.isSymbol = isSymbol;
+ lodash.isTypedArray = isTypedArray;
+ lodash.isUndefined = isUndefined;
+ lodash.isWeakMap = isWeakMap;
+ lodash.isWeakSet = isWeakSet;
+ lodash.join = join;
+ lodash.kebabCase = kebabCase;
+ lodash.last = last;
+ lodash.lastIndexOf = lastIndexOf;
+ lodash.lowerCase = lowerCase;
+ lodash.lowerFirst = lowerFirst;
+ lodash.lt = lt;
+ lodash.lte = lte;
+ lodash.max = max;
+ lodash.maxBy = maxBy;
+ lodash.mean = mean;
+ lodash.meanBy = meanBy;
+ lodash.min = min;
+ lodash.minBy = minBy;
+ lodash.stubArray = stubArray;
+ lodash.stubFalse = stubFalse;
+ lodash.stubObject = stubObject;
+ lodash.stubString = stubString;
+ lodash.stubTrue = stubTrue;
+ lodash.multiply = multiply;
+ lodash.nth = nth;
+ lodash.noConflict = noConflict;
+ lodash.noop = noop;
+ lodash.now = now;
+ lodash.pad = pad;
+ lodash.padEnd = padEnd;
+ lodash.padStart = padStart;
+ lodash.parseInt = parseInt2;
+ lodash.random = random;
+ lodash.reduce = reduce;
+ lodash.reduceRight = reduceRight;
+ lodash.repeat = repeat;
+ lodash.replace = replace;
+ lodash.result = result;
+ lodash.round = round;
+ lodash.runInContext = runInContext2;
+ lodash.sample = sample;
+ lodash.size = size;
+ lodash.snakeCase = snakeCase;
+ lodash.some = some;
+ lodash.sortedIndex = sortedIndex;
+ lodash.sortedIndexBy = sortedIndexBy;
+ lodash.sortedIndexOf = sortedIndexOf;
+ lodash.sortedLastIndex = sortedLastIndex;
+ lodash.sortedLastIndexBy = sortedLastIndexBy;
+ lodash.sortedLastIndexOf = sortedLastIndexOf;
+ lodash.startCase = startCase;
+ lodash.startsWith = startsWith;
+ lodash.subtract = subtract;
+ lodash.sum = sum;
+ lodash.sumBy = sumBy;
+ lodash.template = template;
+ lodash.times = times;
+ lodash.toFinite = toFinite;
+ lodash.toInteger = toInteger;
+ lodash.toLength = toLength;
+ lodash.toLower = toLower;
+ lodash.toNumber = toNumber;
+ lodash.toSafeInteger = toSafeInteger;
+ lodash.toString = toString;
+ lodash.toUpper = toUpper;
+ lodash.trim = trim;
+ lodash.trimEnd = trimEnd;
+ lodash.trimStart = trimStart;
+ lodash.truncate = truncate;
+ lodash.unescape = unescape;
+ lodash.uniqueId = uniqueId;
+ lodash.upperCase = upperCase;
+ lodash.upperFirst = upperFirst;
+ lodash.each = forEach;
+ lodash.eachRight = forEachRight;
+ lodash.first = head;
+ mixin(lodash, function() {
+ var source = {};
+ baseForOwn(lodash, function(func, methodName) {
+ if (!hasOwnProperty.call(lodash.prototype, methodName)) {
+ source[methodName] = func;
+ }
+ });
+ return source;
+ }(), { "chain": false });
+ lodash.VERSION = VERSION;
+ arrayEach(["bind", "bindKey", "curry", "curryRight", "partial", "partialRight"], function(methodName) {
+ lodash[methodName].placeholder = lodash;
+ });
+ arrayEach(["drop", "take"], function(methodName, index) {
+ LazyWrapper.prototype[methodName] = function(n) {
+ n = n === undefined2 ? 1 : nativeMax(toInteger(n), 0);
+ var result2 = this.__filtered__ && !index ? new LazyWrapper(this) : this.clone();
+ if (result2.__filtered__) {
+ result2.__takeCount__ = nativeMin(n, result2.__takeCount__);
+ } else {
+ result2.__views__.push({
+ "size": nativeMin(n, MAX_ARRAY_LENGTH),
+ "type": methodName + (result2.__dir__ < 0 ? "Right" : "")
+ });
+ }
+ return result2;
+ };
+ LazyWrapper.prototype[methodName + "Right"] = function(n) {
+ return this.reverse()[methodName](n).reverse();
+ };
+ });
+ arrayEach(["filter", "map", "takeWhile"], function(methodName, index) {
+ var type = index + 1, isFilter = type == LAZY_FILTER_FLAG || type == LAZY_WHILE_FLAG;
+ LazyWrapper.prototype[methodName] = function(iteratee2) {
+ var result2 = this.clone();
+ result2.__iteratees__.push({
+ "iteratee": getIteratee(iteratee2, 3),
+ "type": type
+ });
+ result2.__filtered__ = result2.__filtered__ || isFilter;
+ return result2;
+ };
+ });
+ arrayEach(["head", "last"], function(methodName, index) {
+ var takeName = "take" + (index ? "Right" : "");
+ LazyWrapper.prototype[methodName] = function() {
+ return this[takeName](1).value()[0];
+ };
+ });
+ arrayEach(["initial", "tail"], function(methodName, index) {
+ var dropName = "drop" + (index ? "" : "Right");
+ LazyWrapper.prototype[methodName] = function() {
+ return this.__filtered__ ? new LazyWrapper(this) : this[dropName](1);
+ };
+ });
+ LazyWrapper.prototype.compact = function() {
+ return this.filter(identity);
+ };
+ LazyWrapper.prototype.find = function(predicate) {
+ return this.filter(predicate).head();
+ };
+ LazyWrapper.prototype.findLast = function(predicate) {
+ return this.reverse().find(predicate);
+ };
+ LazyWrapper.prototype.invokeMap = baseRest(function(path, args) {
+ if (typeof path == "function") {
+ return new LazyWrapper(this);
+ }
+ return this.map(function(value) {
+ return baseInvoke(value, path, args);
+ });
+ });
+ LazyWrapper.prototype.reject = function(predicate) {
+ return this.filter(negate(getIteratee(predicate)));
+ };
+ LazyWrapper.prototype.slice = function(start, end) {
+ start = toInteger(start);
+ var result2 = this;
+ if (result2.__filtered__ && (start > 0 || end < 0)) {
+ return new LazyWrapper(result2);
+ }
+ if (start < 0) {
+ result2 = result2.takeRight(-start);
+ } else if (start) {
+ result2 = result2.drop(start);
+ }
+ if (end !== undefined2) {
+ end = toInteger(end);
+ result2 = end < 0 ? result2.dropRight(-end) : result2.take(end - start);
+ }
+ return result2;
+ };
+ LazyWrapper.prototype.takeRightWhile = function(predicate) {
+ return this.reverse().takeWhile(predicate).reverse();
+ };
+ LazyWrapper.prototype.toArray = function() {
+ return this.take(MAX_ARRAY_LENGTH);
+ };
+ baseForOwn(LazyWrapper.prototype, function(func, methodName) {
+ var checkIteratee = /^(?:filter|find|map|reject)|While$/.test(methodName), isTaker = /^(?:head|last)$/.test(methodName), lodashFunc = lodash[isTaker ? "take" + (methodName == "last" ? "Right" : "") : methodName], retUnwrapped = isTaker || /^find/.test(methodName);
+ if (!lodashFunc) {
+ return;
+ }
+ lodash.prototype[methodName] = function() {
+ var value = this.__wrapped__, args = isTaker ? [1] : arguments, isLazy = value instanceof LazyWrapper, iteratee2 = args[0], useLazy = isLazy || isArray(value);
+ var interceptor = function(value2) {
+ var result3 = lodashFunc.apply(lodash, arrayPush([value2], args));
+ return isTaker && chainAll ? result3[0] : result3;
+ };
+ if (useLazy && checkIteratee && typeof iteratee2 == "function" && iteratee2.length != 1) {
+ isLazy = useLazy = false;
+ }
+ var chainAll = this.__chain__, isHybrid = !!this.__actions__.length, isUnwrapped = retUnwrapped && !chainAll, onlyLazy = isLazy && !isHybrid;
+ if (!retUnwrapped && useLazy) {
+ value = onlyLazy ? value : new LazyWrapper(this);
+ var result2 = func.apply(value, args);
+ result2.__actions__.push({ "func": thru, "args": [interceptor], "thisArg": undefined2 });
+ return new LodashWrapper(result2, chainAll);
+ }
+ if (isUnwrapped && onlyLazy) {
+ return func.apply(this, args);
+ }
+ result2 = this.thru(interceptor);
+ return isUnwrapped ? isTaker ? result2.value()[0] : result2.value() : result2;
+ };
+ });
+ arrayEach(["pop", "push", "shift", "sort", "splice", "unshift"], function(methodName) {
+ var func = arrayProto[methodName], chainName = /^(?:push|sort|unshift)$/.test(methodName) ? "tap" : "thru", retUnwrapped = /^(?:pop|shift)$/.test(methodName);
+ lodash.prototype[methodName] = function() {
+ var args = arguments;
+ if (retUnwrapped && !this.__chain__) {
+ var value = this.value();
+ return func.apply(isArray(value) ? value : [], args);
+ }
+ return this[chainName](function(value2) {
+ return func.apply(isArray(value2) ? value2 : [], args);
+ });
+ };
+ });
+ baseForOwn(LazyWrapper.prototype, function(func, methodName) {
+ var lodashFunc = lodash[methodName];
+ if (lodashFunc) {
+ var key = lodashFunc.name + "";
+ if (!hasOwnProperty.call(realNames, key)) {
+ realNames[key] = [];
+ }
+ realNames[key].push({ "name": methodName, "func": lodashFunc });
+ }
+ });
+ realNames[createHybrid(undefined2, WRAP_BIND_KEY_FLAG).name] = [{
+ "name": "wrapper",
+ "func": undefined2
+ }];
+ LazyWrapper.prototype.clone = lazyClone;
+ LazyWrapper.prototype.reverse = lazyReverse;
+ LazyWrapper.prototype.value = lazyValue;
+ lodash.prototype.at = wrapperAt;
+ lodash.prototype.chain = wrapperChain;
+ lodash.prototype.commit = wrapperCommit;
+ lodash.prototype.next = wrapperNext;
+ lodash.prototype.plant = wrapperPlant;
+ lodash.prototype.reverse = wrapperReverse;
+ lodash.prototype.toJSON = lodash.prototype.valueOf = lodash.prototype.value = wrapperValue;
+ lodash.prototype.first = lodash.prototype.head;
+ if (symIterator) {
+ lodash.prototype[symIterator] = wrapperToIterator;
+ }
+ return lodash;
+ };
+ var _2 = runInContext();
+ if (typeof define == "function" && typeof define.amd == "object" && define.amd) {
+ root._ = _2;
+ define(function() {
+ return _2;
+ });
+ } else if (freeModule) {
+ (freeModule.exports = _2)._ = _2;
+ freeExports._ = _2;
+ } else {
+ root._ = _2;
+ }
+ }).call(exports);
+ }
+ });
+
// src/extensions/extension.tsx
var import_react15 = __toESM(require_react());
@@ -46,41 +5484,26 @@ var stats = (() => {
// src/components/cards/stat_card.tsx
var import_react = __toESM(require_react());
- function formatValue(name, value) {
- switch (name) {
- case "tempo":
- return `${Math.round(value)} bpm`;
- case "popularity":
- return `${Math.round(value)} %`;
- default:
- return `${Math.round(value * 100)} %`;
- }
- }
- function normalizeString(inputString) {
- return inputString.charAt(0).toUpperCase() + inputString.slice(1).toLowerCase();
- }
- function StatCard(props) {
+ var import_lodash = __toESM(require_lodash());
+ function StatCard({ label, value }) {
const { TextComponent } = Spicetify.ReactComponent;
- const { label, value } = props;
return /* @__PURE__ */ import_react.default.createElement("div", {
className: "main-card-card"
}, /* @__PURE__ */ import_react.default.createElement(TextComponent, {
as: "div",
semanticColor: "textBase",
- variant: "alto",
- children: typeof value === "number" ? formatValue(label, value) : value
- }), /* @__PURE__ */ import_react.default.createElement(TextComponent, {
+ variant: "alto"
+ }, value), /* @__PURE__ */ import_react.default.createElement(TextComponent, {
as: "div",
semanticColor: "textBase",
- variant: "balladBold",
- children: normalizeString(label)
- }));
+ variant: "balladBold"
+ }, import_lodash.default.startCase(label)));
}
var stat_card_default = StatCard;
- // src/components/cards/genres_card.tsx
+ // src/components/cards/chart_card.tsx
var import_react2 = __toESM(require_react());
- var genreLine = (name, value, limit, total) => {
+ var ChartLine = (name, value, limit, total) => {
return /* @__PURE__ */ import_react2.default.createElement("div", {
className: "stats-genreRow"
}, /* @__PURE__ */ import_react2.default.createElement("div", {
@@ -92,20 +5515,23 @@ var stats = (() => {
className: "stats-genreText"
}, name)), /* @__PURE__ */ import_react2.default.createElement("span", {
className: "stats-genreValue"
- }, Math.round(value / total * 100) + "%"));
+ }, `${Math.round(value / total * 100)}%`));
};
- var genreLines = (genres, total) => {
- return genres.map(([genre, value]) => {
- return genreLine(genre, value, genres[0][1], total);
- });
- };
- var genresCard = ({ genres, total }) => {
- const genresArray = genres.sort(([, a], [, b]) => b - a).slice(0, 10);
+ var ChartCard = ({ data }) => {
+ const [extended, setExtended] = import_react2.default.useState(false);
+ const keys = Object.keys(data).sort((a, b) => data[b] - data[a]).slice(0, extended ? 50 : 10);
+ const total = Object.values(data).reduce((acc, curr) => acc + curr, 0);
return /* @__PURE__ */ import_react2.default.createElement("div", {
- className: `main-card-card stats-genreCard`
- }, genreLines(genresArray, total));
+ className: "main-card-card stats-genreCard"
+ }, keys.map((key) => ChartLine(key, data[key], data[keys[0]], total)), /* @__PURE__ */ import_react2.default.createElement("button", {
+ type: "button",
+ className: "extend-button",
+ onClick: () => {
+ setExtended(!extended);
+ }
+ }, extended ? "See Less" : "See More"));
};
- var genres_card_default = genresCard;
+ var chart_card_default = ChartCard;
// ../library/src/components/collection_menu.tsx
var import_react5 = __toESM(require_react());
@@ -276,8 +5702,7 @@ var stats = (() => {
const { Cards, TextComponent, ArtistMenu, AlbumMenu, PodcastShowMenu, PlaylistMenu, ContextMenu } = Spicetify.ReactComponent;
const { FeatureCard: Card, CardImage } = Cards;
const { createHref, push } = Spicetify.Platform.History;
- const { type, header, uri, imageUrl, subheader, artistUri } = props;
- const backupImageUrl = type === "folder" || type === "collection" ? "https://raw.githubusercontent.com/harbassan/spicetify-apps/main/shared/placeholders/folder_placeholder.png" : "https://raw.githubusercontent.com/harbassan/spicetify-apps/main/shared/placeholders/def_placeholder.png";
+ const { type, header, uri, imageUrl, subheader, artistUri, badge, provider } = props;
const Menu = () => {
switch (type) {
case "artist":
@@ -310,7 +5735,11 @@ var stats = (() => {
return /* @__PURE__ */ import_react8.default.createElement(import_react8.default.Fragment, null);
}
};
- const lastfmProps = type === "lastfm" ? { onClick: () => window.open(uri, "_blank"), isPlayable: false, delegateNavigation: true } : {};
+ const lastfmProps = provider === "lastfm" ? {
+ onClick: () => window.open(uri, "_blank"),
+ isPlayable: false,
+ delegateNavigation: true
+ } : {};
const folderProps = type === "folder" ? {
delegateNavigation: true,
onClick: () => {
@@ -328,6 +5757,8 @@ var stats = (() => {
return /* @__PURE__ */ import_react8.default.createElement(ContextMenu, {
menu: Menu(),
trigger: "right-click"
+ }, /* @__PURE__ */ import_react8.default.createElement("div", {
+ style: { position: "relative" }
}, /* @__PURE__ */ import_react8.default.createElement(Card, {
featureIdentifier: type,
headerText: header,
@@ -340,7 +5771,7 @@ var stats = (() => {
}
],
isCircular: type === "artist",
- FallbackComponent: folder_fallback_default
+ FallbackComponent: type === "folder" || type === "collection" ? folder_fallback_default : void 0
}),
renderSubHeaderContent: () => /* @__PURE__ */ import_react8.default.createElement(TextComponent, {
as: "div",
@@ -352,27 +5783,54 @@ var stats = (() => {
...lastfmProps,
...folderProps,
...collectionProps
- }));
+ }), badge && /* @__PURE__ */ import_react8.default.createElement("div", {
+ className: "badge"
+ }, badge)));
}
var spotify_card_default = SpotifyCard;
- // ../shared/components/status.tsx
+ // src/components/shelf.tsx
var import_react9 = __toESM(require_react());
+ function Shelf(props) {
+ const { TextComponent } = Spicetify.ReactComponent;
+ const { title, children } = props;
+ return /* @__PURE__ */ import_react9.default.createElement("section", {
+ className: "main-shelf-shelf Shelf"
+ }, /* @__PURE__ */ import_react9.default.createElement("div", {
+ className: "main-shelf-header"
+ }, /* @__PURE__ */ import_react9.default.createElement("div", {
+ className: "main-shelf-topRow"
+ }, /* @__PURE__ */ import_react9.default.createElement("div", {
+ className: "main-shelf-titleWrapper"
+ }, /* @__PURE__ */ import_react9.default.createElement(TextComponent, {
+ children: title,
+ as: "h2",
+ variant: "canon",
+ semanticColor: "textBase"
+ })))), /* @__PURE__ */ import_react9.default.createElement("section", null, children));
+ }
+ var shelf_default = import_react9.default.memo(Shelf);
+
+ // ../shared/status/useStatus.tsx
+ var import_react11 = __toESM(require_react());
+
+ // ../shared/status/status.tsx
+ var import_react10 = __toESM(require_react());
var ErrorIcon = () => {
- return /* @__PURE__ */ import_react9.default.createElement("svg", {
+ return /* @__PURE__ */ import_react10.default.createElement("svg", {
"data-encore-id": "icon",
role: "img",
"aria-hidden": "true",
viewBox: "0 0 24 24",
className: "status-icon"
- }, /* @__PURE__ */ import_react9.default.createElement("path", {
+ }, /* @__PURE__ */ import_react10.default.createElement("path", {
d: "M11 18v-2h2v2h-2zm0-4V6h2v8h-2z"
- }), /* @__PURE__ */ import_react9.default.createElement("path", {
+ }), /* @__PURE__ */ import_react10.default.createElement("path", {
d: "M12 3a9 9 0 1 0 0 18 9 9 0 0 0 0-18zM1 12C1 5.925 5.925 1 12 1s11 4.925 11 11-4.925 11-11 11S1 18.075 1 12z"
}));
};
var LibraryIcon = () => {
- return /* @__PURE__ */ import_react9.default.createElement("svg", {
+ return /* @__PURE__ */ import_react10.default.createElement("svg", {
role: "img",
height: "46",
width: "46",
@@ -380,336 +5838,260 @@ var stats = (() => {
viewBox: "0 0 24 24",
"data-encore-id": "icon",
className: "status-icon"
- }, /* @__PURE__ */ import_react9.default.createElement("path", {
+ }, /* @__PURE__ */ import_react10.default.createElement("path", {
d: "M14.5 2.134a1 1 0 0 1 1 0l6 3.464a1 1 0 0 1 .5.866V21a1 1 0 0 1-1 1h-6a1 1 0 0 1-1-1V3a1 1 0 0 1 .5-.866zM16 4.732V20h4V7.041l-4-2.309zM3 22a1 1 0 0 1-1-1V3a1 1 0 0 1 2 0v18a1 1 0 0 1-1 1zm6 0a1 1 0 0 1-1-1V3a1 1 0 0 1 2 0v18a1 1 0 0 1-1 1z"
}));
};
var Status = (props) => {
- const [isVisible, setIsVisible] = import_react9.default.useState(false);
- import_react9.default.useEffect(() => {
+ const [isVisible, setIsVisible] = import_react10.default.useState(false);
+ import_react10.default.useEffect(() => {
const to = setTimeout(() => {
setIsVisible(true);
}, 500);
return () => clearTimeout(to);
}, []);
- return isVisible ? /* @__PURE__ */ import_react9.default.createElement(import_react9.default.Fragment, null, /* @__PURE__ */ import_react9.default.createElement("div", {
+ return isVisible ? /* @__PURE__ */ import_react10.default.createElement(import_react10.default.Fragment, null, /* @__PURE__ */ import_react10.default.createElement("div", {
className: "loadingWrapper"
- }, props.icon === "error" ? /* @__PURE__ */ import_react9.default.createElement(ErrorIcon, null) : /* @__PURE__ */ import_react9.default.createElement(LibraryIcon, null), /* @__PURE__ */ import_react9.default.createElement("h1", null, props.heading), /* @__PURE__ */ import_react9.default.createElement("h3", null, props.subheading))) : /* @__PURE__ */ import_react9.default.createElement(import_react9.default.Fragment, null);
+ }, props.icon === "error" ? /* @__PURE__ */ import_react10.default.createElement(ErrorIcon, null) : /* @__PURE__ */ import_react10.default.createElement(LibraryIcon, null), /* @__PURE__ */ import_react10.default.createElement("h1", null, props.heading), /* @__PURE__ */ import_react10.default.createElement("h3", null, props.subheading))) : /* @__PURE__ */ import_react10.default.createElement(import_react10.default.Fragment, null);
};
var status_default = Status;
- // src/components/inline_grid.tsx
- var import_react10 = __toESM(require_react());
- function scrollGrid(event) {
- const { target } = event;
- if (!(target instanceof HTMLElement))
- return;
- const grid = target.parentNode?.querySelector("div");
- if (!grid)
- return;
- grid.scrollLeft += grid.clientWidth;
- if (grid.scrollWidth - grid.clientWidth - grid.scrollLeft <= grid.clientWidth) {
- grid.setAttribute("data-scroll", "end");
- } else {
- grid.setAttribute("data-scroll", "both");
+ // ../shared/status/useStatus.tsx
+ var useStatus = (status, error) => {
+ if (status === "pending") {
+ return /* @__PURE__ */ import_react11.default.createElement(status_default, {
+ icon: "library",
+ heading: "Loading",
+ subheading: "Please wait, this may take a moment"
+ });
}
- }
- function scrollGridLeft(event) {
- const { target } = event;
- if (!(target instanceof HTMLElement))
- return;
- const grid = target.parentNode?.querySelector("div");
- if (!grid)
- return;
- grid.scrollLeft -= grid.clientWidth;
- if (grid.scrollLeft <= grid.clientWidth) {
- grid.setAttribute("data-scroll", "start");
- } else {
- grid.setAttribute("data-scroll", "both");
+ if (status === "error") {
+ return /* @__PURE__ */ import_react11.default.createElement(status_default, {
+ icon: "error",
+ heading: "Error",
+ subheading: error?.message || "An unknown error occurred"
+ });
}
- }
- function InlineGrid(props) {
- const { children, special } = props;
- return /* @__PURE__ */ import_react10.default.createElement("section", {
- className: "stats-gridInlineSection"
- }, /* @__PURE__ */ import_react10.default.createElement("button", {
- className: "stats-scrollButton",
- onClick: scrollGridLeft
- }, "<"), /* @__PURE__ */ import_react10.default.createElement("button", {
- className: "stats-scrollButton",
- onClick: scrollGrid
- }, ">"), /* @__PURE__ */ import_react10.default.createElement("div", {
- className: `main-gridContainer-gridContainer stats-gridInline${special ? " stats-specialGrid" : ""}`,
- "data-scroll": "start"
- }, children));
- }
- var inline_grid_default = import_react10.default.memo(InlineGrid);
-
- // src/components/shelf.tsx
- var import_react11 = __toESM(require_react());
- function Shelf(props) {
- const { TextComponent } = Spicetify.ReactComponent;
- const { title, children } = props;
- return /* @__PURE__ */ import_react11.default.createElement("section", {
- className: "main-shelf-shelf Shelf"
- }, /* @__PURE__ */ import_react11.default.createElement("div", {
- className: "main-shelf-header"
- }, /* @__PURE__ */ import_react11.default.createElement("div", {
- className: "main-shelf-topRow"
- }, /* @__PURE__ */ import_react11.default.createElement("div", {
- className: "main-shelf-titleWrapper"
- }, /* @__PURE__ */ import_react11.default.createElement(TextComponent, {
- children: title,
- as: "h2",
- variant: "canon",
- semanticColor: "textBase"
- })))), /* @__PURE__ */ import_react11.default.createElement("section", null, children));
- }
- var shelf_default = import_react11.default.memo(Shelf);
-
- // src/endpoints.ts
- var SPOTIFY = {
- toptracks: (range) => `https://api.spotify.com/v1/me/top/tracks?limit=50&offset=0&time_range=${range}`,
- topartists: (range) => `https://api.spotify.com/v1/me/top/artists?limit=50&offset=0&time_range=${range}`,
- artists: (artists) => `https://api.spotify.com/v1/artists?ids=${filter(artists)}`,
- rootlist: "sp://core-playlist/v1/rootlist",
- playlist: (uri) => `sp://core-playlist/v1/playlist/${uri}`,
- search: (track, artist) => `https://api.spotify.com/v1/search?q=track:${filter(track)}+artist:${filter(artist)}&type=track`,
- searchartist: (artist) => `https://api.spotify.com/v1/search?q=artist:${filter(artist)}&type=artist`,
- searchalbum: (album, artist) => `https://api.spotify.com/v1/search?q=${filter(album)}+artist:${filter(artist)}&type=album`,
- audiofeatures: (ids) => `https://api.spotify.com/v1/audio-features?ids=${ids}`,
- queryliked: (ids) => `https://api.spotify.com/v1/me/tracks/contains?ids=${ids}`
+ return null;
};
- var PLACEHOLDER = "https://raw.githubusercontent.com/harbassan/spicetify-apps/main/stats/src/styles/placeholder.png";
+ var useStatus_default = useStatus;
- // src/funcs.ts
- function filter(str) {
- const normalizedStr = str.normalize("NFD").replace(/[\u0300-\u036f]/g, "");
- return normalizedStr.replace(/[^a-zA-Z0-9\-._~:/?#[\]@!$&()*+,;= ]/g, "").replace(/ /g, "+");
- }
- var apiRequest = async (name, url, timeout = 5, log = true) => {
+ // src/api/spotify.ts
+ var apiFetch = async (name, url, log = true) => {
try {
const timeStart = window.performance.now();
const response = await Spicetify.CosmosAsync.get(url);
if (log)
console.log("stats -", name, "fetch time:", window.performance.now() - timeStart);
return response;
- } catch (e) {
- if (timeout === 0) {
- console.log("stats -", name, "all requests failed:", e);
- console.log("stats -", name, "giving up");
- return null;
- } else {
- if (timeout === 5) {
- console.log("stats -", name, "request failed:", e);
- console.log("stats -", name, "retrying...");
- }
- await new Promise((resolve) => setTimeout(resolve, 5e3));
- return apiRequest(name, url, timeout - 1);
+ } catch (error) {
+ console.log("stats -", name, "request failed:", error);
+ throw error;
+ }
+ };
+ var getArtistMetas = (ids) => {
+ return apiFetch("artistMetas", `https://api.spotify.com/v1/artists?ids=${ids}`).then(
+ (res) => res.artists
+ );
+ };
+ var getAlbumMetas = (ids) => {
+ return apiFetch("albumMetas", `https://api.spotify.com/v1/albums?ids=${ids}`).then(
+ (res) => res.albums
+ );
+ };
+ var getAudioFeatures = (ids) => {
+ return apiFetch(
+ "audioFeatures",
+ `https://api.spotify.com/v1/audio-features?ids=${ids}`
+ ).then((res) => res.audio_features);
+ };
+
+ // src/utils/converter.ts
+ var minifyArtist = (artist) => ({
+ id: artist.id,
+ name: artist.name,
+ image: artist.images.at(-1)?.url,
+ uri: artist.uri,
+ genres: artist.genres,
+ type: "spotify"
+ });
+ var minifyAlbum = (album) => ({
+ id: album.id,
+ uri: album.uri,
+ name: album.name,
+ image: album.images[0]?.url,
+ type: "spotify"
+ });
+
+ // src/utils/track_helper.ts
+ var batchRequest = (size, request) => {
+ return (ids) => {
+ const chunks = [];
+ for (let i = 0; i < ids.length; i += size) {
+ chunks.push(ids.slice(i, i + size));
+ }
+ return Promise.all(chunks.map(request)).then((res) => res.flat());
+ };
+ };
+ var getMeanAudioFeatures = async (ids) => {
+ const audioFeaturesSum = {
+ danceability: 0,
+ energy: 0,
+ speechiness: 0,
+ acousticness: 0,
+ instrumentalness: 0,
+ liveness: 0,
+ valence: 0,
+ tempo: 0
+ };
+ const audioFeaturesList = await batchRequest(100, getAudioFeatures)(ids);
+ for (const audioFeatures of audioFeaturesList) {
+ if (!audioFeatures)
+ continue;
+ for (const f of Object.keys(audioFeaturesSum)) {
+ audioFeaturesSum[f] += audioFeatures[f];
}
}
- };
- var fetchAudioFeatures = async (ids) => {
- const batchSize = 100;
- const batches = [];
- ids = ids.filter((id) => id.match(/^[a-zA-Z0-9]{22}$/));
- for (let i = 0; i < ids.length; i += batchSize) {
- const batch = ids.slice(i, i + batchSize);
- batches.push(batch);
+ for (const f of Object.keys(audioFeaturesSum)) {
+ audioFeaturesSum[f] /= audioFeaturesList.length;
}
- const promises = batches.map((batch, index) => {
- return apiRequest(`audioFeaturesBatch${index}`, SPOTIFY.audiofeatures(batch.join(",")), 5, false);
- });
- const responses = await Promise.all(promises);
- const data = responses.reduce((acc, response) => {
- if (!response?.audio_features)
- return acc;
- return acc.concat(response.audio_features);
- }, []);
- return data;
+ return audioFeaturesSum;
};
- var fetchTopAlbums = async (albums, cachedAlbums) => {
- let album_keys = Object.keys(albums).filter((id) => id.match(/^[a-zA-Z0-9]{22}$/)).sort((a, b) => albums[b] - albums[a]).slice(0, 100);
- let release_years = {};
- let total_album_tracks = 0;
- const cachedAlbumsSet = new Set(cachedAlbums?.map((album) => album.uri));
- let top_albums = await Promise.all(
- album_keys.map(async (albumID) => {
- let albumMeta;
- if (cachedAlbums && cachedAlbumsSet.has(`spotify:album:${albumID}`)) {
- albumMeta = cachedAlbums.find((album) => album.uri === `spotify:album:${albumID}`);
- }
- if (!albumMeta) {
- try {
- albumMeta = await Spicetify.GraphQL.Request(Spicetify.GraphQL.Definitions.getAlbum, {
- uri: `spotify:album:${albumID}`,
- locale: "en",
- offset: 0,
- limit: 50
- });
- if (!albumMeta?.data?.albumUnion?.name)
- throw new Error("Invalid URI");
- } catch (e) {
- console.error("stats - album metadata request failed:", e);
- return;
- }
- }
- const releaseYear = albumMeta?.release_year || albumMeta.data.albumUnion.date.isoString.slice(0, 4);
- release_years[releaseYear] = (release_years[releaseYear] || 0) + albums[albumID];
- total_album_tracks += albums[albumID];
- return {
- name: albumMeta.name || albumMeta.data.albumUnion.name,
- uri: albumMeta.uri || albumMeta.data.albumUnion.uri,
- image: albumMeta.image || albumMeta.data.albumUnion.coverArt.sources[0]?.url || PLACEHOLDER,
- release_year: releaseYear,
- freq: albums[albumID]
- };
- })
- );
- top_albums = top_albums.filter((el) => el != null).slice(0, 10);
- return [top_albums, Object.entries(release_years), total_album_tracks];
- };
- var fetchTopArtists = async (artists) => {
- if (Object.keys(artists).length === 0)
- return [[], [], 0];
- let artist_keys = Object.keys(artists).filter((id) => id.match(/^[a-zA-Z0-9]{22}$/)).sort((a, b) => artists[b] - artists[a]).slice(0, 50);
- let genres = {};
- let total_genre_tracks = 0;
- const artistsMeta = await apiRequest("artistsMetadata", SPOTIFY.artists(artist_keys.join(",")));
- let top_artists = artistsMeta?.artists?.map((artist) => {
- if (!artist)
- return null;
- artist.genres.forEach((genre) => {
- genres[genre] = (genres[genre] || 0) + artists[artist.id];
- });
- total_genre_tracks += artists[artist.id];
- return {
- name: artist.name,
- uri: artist.uri,
- image: artist.images[2]?.url || PLACEHOLDER,
- freq: artists[artist.id]
- };
+ var parseAlbums = async (albumsRaw) => {
+ const frequencyMap = {};
+ const albumIDs = albumsRaw.map((album) => album.uri.split(":")[2]);
+ for (const id of albumIDs) {
+ frequencyMap[id] = (frequencyMap[id] || 0) + 1;
+ }
+ const ids = Object.keys(frequencyMap).sort((a, b) => frequencyMap[b] - frequencyMap[a]).slice(0, 100);
+ const albums = await batchRequest(20, getAlbumMetas)(ids);
+ const releaseYears = {};
+ const uniqueAlbums = albums.map((album) => {
+ const year = album.release_date.slice(0, 4);
+ releaseYears[year] = (releaseYears[year] || 0) + 1;
+ return { ...minifyAlbum(album), frequency: frequencyMap[album.id] };
});
- top_artists = top_artists.filter((el) => el != null).slice(0, 10);
- const top_genres = Object.entries(genres).sort((a, b) => b[1] - a[1]).slice(0, 10);
- return [top_artists, top_genres, total_genre_tracks];
+ return { releaseYears, albums: { contents: uniqueAlbums, length: Object.keys(frequencyMap).length } };
+ };
+ var parseArtists = async (artistsRaw) => {
+ const frequencyMap = {};
+ const artistIDs = artistsRaw.map((artist) => artist.uri.split(":")[2]);
+ for (const id of artistIDs) {
+ frequencyMap[id] = (frequencyMap[id] || 0) + 1;
+ }
+ const ids = Object.keys(frequencyMap).sort((a, b) => frequencyMap[b] - frequencyMap[a]).slice(0, 250);
+ const artists = await batchRequest(50, getArtistMetas)(ids);
+ const genres = {};
+ const uniqueArtists = artists.map((artist) => {
+ for (const genre of artist.genres) {
+ genres[genre] = (genres[genre] || 0) + 1;
+ }
+ return { ...minifyArtist(artist), frequency: frequencyMap[artist.id] };
+ });
+ return { genres, artists: { contents: uniqueArtists, length: Object.keys(frequencyMap).length } };
+ };
+ var parseTracks = async (tracks) => {
+ const trackIDs = [];
+ const albumsRaw = [];
+ const artistsRaw = [];
+ let explicit = 0;
+ let duration = 0;
+ for (const track of tracks) {
+ if (track?.type !== "track" || track.isLocal)
+ continue;
+ duration += track.duration.milliseconds;
+ explicit += track.isExplicit ? 1 : 0;
+ trackIDs.push(track.uri.split(":")[2]);
+ albumsRaw.push(track.album);
+ artistsRaw.push(...track.artists);
+ }
+ explicit = explicit / trackIDs.length;
+ const audioFeatures = await getMeanAudioFeatures(trackIDs);
+ const analysis = { ...audioFeatures, explicit };
+ const { genres, artists } = await parseArtists(artistsRaw);
+ const { releaseYears, albums } = await parseAlbums(albumsRaw);
+ return {
+ analysis,
+ genres,
+ artists,
+ albums,
+ releaseYears,
+ duration,
+ length: trackIDs.length
+ };
+ };
+ var parseStat = (name) => {
+ switch (name) {
+ case "tempo":
+ return (v) => `${Math.round(v)} bpm`;
+ case "popularity":
+ return (v) => `${Math.round(v)}%`;
+ default:
+ return (v) => `${Math.round(v * 100)}%`;
+ }
+ };
+
+ // src/api/platform.ts
+ var getFullPlaylist = async (uri) => {
+ const playlist = await Spicetify.Platform.PlaylistAPI.getPlaylist(uri);
+ const tracks = playlist.contents.items;
+ return tracks;
};
// src/pages/playlist.tsx
- var PlaylistPage = ({ uri }) => {
- const { ReactComponent, ReactQuery, Platform, _platform } = Spicetify;
- const { History, ReduxStore } = Platform;
- const { QueryClientProvider, QueryClient } = ReactQuery;
- const { Router, Route, Routes, PlatformProvider, StoreProvider } = ReactComponent;
- const [library, setLibrary] = import_react12.default.useState(100);
- const fetchData = async () => {
- const start = window.performance.now();
- const playlistMeta = await apiRequest("playlistMeta", SPOTIFY.playlist(uri));
- if (!playlistMeta) {
- setLibrary(200);
- return;
- }
- let duration = playlistMeta.playlist.duration;
- let trackCount = playlistMeta.playlist.length;
- let explicitCount = 0;
- let trackIDs = [];
- let popularity = 0;
- let albums = {};
- let artists = {};
- playlistMeta.items.forEach((track) => {
- popularity += track.popularity;
- trackIDs.push(track.link.split(":")[2]);
- if (track.isExplicit)
- explicitCount++;
- const albumID = track.album.link.split(":")[2];
- albums[albumID] = albums[albumID] ? albums[albumID] + 1 : 1;
- track.artists.forEach((artist) => {
- const artistID = artist.link.split(":")[2];
- artists[artistID] = artists[artistID] ? artists[artistID] + 1 : 1;
- });
- });
- const [topAlbums, releaseYears, releaseYearsTotal] = await fetchTopAlbums(albums);
- const [topArtists, topGenres, topGenresTotal] = await fetchTopArtists(artists);
- const fetchedFeatures = await fetchAudioFeatures(trackIDs);
- let audioFeatures = {
- danceability: 0,
- energy: 0,
- valence: 0,
- speechiness: 0,
- acousticness: 0,
- instrumentalness: 0,
- liveness: 0,
- tempo: 0
- };
- for (let i = 0; i < fetchedFeatures.length; i++) {
- if (!fetchedFeatures[i])
- continue;
- const track = fetchedFeatures[i];
- Object.keys(audioFeatures).forEach((feature) => {
- audioFeatures[feature] += track[feature];
- });
- }
- audioFeatures = {
- popularity,
- explicitness: explicitCount,
- ...audioFeatures
- };
- for (let key in audioFeatures) {
- audioFeatures[key] /= fetchedFeatures.length;
- }
- const stats2 = {
- audioFeatures,
- trackCount,
- totalDuration: duration,
- artistCount: Object.keys(artists).length,
- artists: topArtists,
- genres: topGenres,
- genresDenominator: topGenresTotal,
- albums: topAlbums,
- years: releaseYears,
- yearsDenominator: releaseYearsTotal
- };
- setLibrary(stats2);
- console.log("total playlist stats fetch time:", window.performance.now() - start);
- };
+ var getPlaylist = async (uri) => {
+ const contents = await getFullPlaylist(uri);
+ return parseTracks(contents);
+ };
+ var useQueryShitty = (callback) => {
+ const [error, setError] = import_react12.default.useState(null);
+ const [data, setData] = import_react12.default.useState(null);
+ const [status, setStatus] = import_react12.default.useState("pending");
import_react12.default.useEffect(() => {
+ const fetchData = async () => {
+ try {
+ const data2 = await callback();
+ setData(data2);
+ setStatus("success");
+ } catch (e) {
+ setError(e);
+ setStatus("error");
+ }
+ };
fetchData();
- }, []);
- switch (library) {
- case 200:
- return /* @__PURE__ */ import_react12.default.createElement(status_default, {
- icon: "error",
- heading: "Failed to Fetch Stats",
- subheading: "Make an issue on Github"
- });
- case 100:
- return /* @__PURE__ */ import_react12.default.createElement(status_default, {
- icon: "library",
- heading: "Analysing the Playlist",
- subheading: "This may take a while"
- });
- }
- const statCards = Object.entries(library.audioFeatures).map(([key, value]) => {
+ }, [callback]);
+ return { status, error, data };
+ };
+ var PlaylistPage = ({ uri }) => {
+ const query = (0, import_react12.useCallback)(() => getPlaylist(uri), [uri]);
+ const { status, error, data } = useQueryShitty(query);
+ const Status2 = useStatus_default(status, error);
+ if (Status2)
+ return Status2;
+ const analysis = data;
+ const statCards = Object.entries(analysis.analysis).map(([key, value]) => {
return /* @__PURE__ */ import_react12.default.createElement(stat_card_default, {
label: key,
- value
+ value: parseStat(key)(value)
});
});
- const artistCards = library.artists.map((artist) => {
+ const artistCards = analysis.artists.contents.slice(0, 10).map((artist) => {
return /* @__PURE__ */ import_react12.default.createElement(spotify_card_default, {
type: "artist",
+ provider: artist.type,
uri: artist.uri,
header: artist.name,
- subheader: `Appears in ${artist.freq} tracks`,
+ subheader: `Appears in ${artist.frequency} tracks`,
imageUrl: artist.image
});
});
- const albumCards = library.albums.map((album) => {
+ const albumCards = analysis.albums.contents.slice(0, 10).map((album) => {
return /* @__PURE__ */ import_react12.default.createElement(spotify_card_default, {
type: "album",
+ provider: album.type,
uri: album.uri,
header: album.name,
- subheader: `Appears in ${album.freq} tracks`,
+ subheader: `Appears in ${album.frequency} tracks`,
imageUrl: album.image
});
});
@@ -720,28 +6102,29 @@ var stats = (() => {
className: "stats-libraryOverview"
}, /* @__PURE__ */ import_react12.default.createElement(stat_card_default, {
label: "Total Tracks",
- value: library.trackCount.toString()
+ value: analysis.length
}), /* @__PURE__ */ import_react12.default.createElement(stat_card_default, {
label: "Total Artists",
- value: library.artistCount.toString()
+ value: analysis.artists.length
+ }), /* @__PURE__ */ import_react12.default.createElement(stat_card_default, {
+ label: "Total Albums",
+ value: analysis.albums.length
}), /* @__PURE__ */ import_react12.default.createElement(stat_card_default, {
label: "Total Minutes",
- value: Math.floor(library.totalDuration / 60).toString()
+ value: Math.floor(analysis.duration / 6e4)
}), /* @__PURE__ */ import_react12.default.createElement(stat_card_default, {
label: "Total Hours",
- value: (library.totalDuration / (60 * 60)).toFixed(1)
+ value: (analysis.duration / 36e5).toFixed(1)
})), /* @__PURE__ */ import_react12.default.createElement(shelf_default, {
title: "Most Frequent Genres"
- }, /* @__PURE__ */ import_react12.default.createElement(genres_card_default, {
- genres: library.genres,
- total: library.genresDenominator
- }), /* @__PURE__ */ import_react12.default.createElement(inline_grid_default, {
- special: true
+ }, /* @__PURE__ */ import_react12.default.createElement(chart_card_default, {
+ data: analysis.genres
+ }), /* @__PURE__ */ import_react12.default.createElement("div", {
+ className: "main-gridContainer-gridContainer grid"
}, statCards)), /* @__PURE__ */ import_react12.default.createElement(shelf_default, {
title: "Release Year Distribution"
- }, /* @__PURE__ */ import_react12.default.createElement(genres_card_default, {
- genres: library.years,
- total: library.yearsDenominator
+ }, /* @__PURE__ */ import_react12.default.createElement(chart_card_default, {
+ data: analysis.releaseYears
})));
};
var playlist_default = import_react12.default.memo(PlaylistPage);
@@ -987,7 +6370,7 @@ var stats = (() => {
key: "use-lastfm",
type: "toggle",
def: false,
- desc: `Last.fm charts your stats purely based on the streaming count, whereas Spotify factors in other variables`
+ desc: "Last.fm charts your stats purely based on the streaming count, whereas Spotify factors in other variables"
},
{
name: "Artists Page",
@@ -1002,7 +6385,7 @@ var stats = (() => {
key: "show-albums",
type: "toggle",
def: false,
- desc: `Requires Last.fm API key and username`
+ desc: "Requires Last.fm API key and username"
},
{ name: "Genres Page", key: "show-genres", type: "toggle", def: true },
{ name: "Library Page", key: "show-library", type: "toggle", def: true },
@@ -1011,7 +6394,7 @@ var stats = (() => {
key: "show-charts",
type: "toggle",
def: true,
- desc: `Requires Last.fm API key`
+ desc: "Requires Last.fm API key"
}
],
"stats"
@@ -1039,7 +6422,6 @@ var stats = (() => {
}
localStorage.setItem("stats:version", version);
}
- LocalStorage.set("stats:cache-info", JSON.stringify([0, 0, 0, 0, 0, 0]));
const styleLink = document.createElement("link");
styleLink.rel = "stylesheet";
styleLink.href = "/spicetify-routes-stats.css";
@@ -1062,5 +6444,13 @@ var stats = (() => {
});
})();
})();
+/**
+ * @license
+ * Lodash
+ * Copyright OpenJS Foundation and other contributors
+ * Released under MIT license
+ * Based on Underscore.js 1.8.3
+ * Copyright Jeremy Ashkenas, DocumentCloud and Investigative Reporters & Editors
+ */
})();
\ No newline at end of file
diff --git a/.config/spicetify/CustomApps/stats/index.js b/.config/spicetify/CustomApps/stats/index.js
index 56fcfc30..9e2a0d4f 100644
--- a/.config/spicetify/CustomApps/stats/index.js
+++ b/.config/spicetify/CustomApps/stats/index.js
@@ -40,6 +40,5444 @@ var stats = (() => {
}
});
+ // ../node_modules/lodash/lodash.js
+ var require_lodash = __commonJS({
+ "../node_modules/lodash/lodash.js"(exports, module) {
+ (function() {
+ var undefined2;
+ var VERSION = "4.17.21";
+ var LARGE_ARRAY_SIZE = 200;
+ var CORE_ERROR_TEXT = "Unsupported core-js use. Try https://npms.io/search?q=ponyfill.", FUNC_ERROR_TEXT = "Expected a function", INVALID_TEMPL_VAR_ERROR_TEXT = "Invalid `variable` option passed into `_.template`";
+ var HASH_UNDEFINED = "__lodash_hash_undefined__";
+ var MAX_MEMOIZE_SIZE = 500;
+ var PLACEHOLDER = "__lodash_placeholder__";
+ var CLONE_DEEP_FLAG = 1, CLONE_FLAT_FLAG = 2, CLONE_SYMBOLS_FLAG = 4;
+ var COMPARE_PARTIAL_FLAG = 1, COMPARE_UNORDERED_FLAG = 2;
+ var WRAP_BIND_FLAG = 1, WRAP_BIND_KEY_FLAG = 2, WRAP_CURRY_BOUND_FLAG = 4, WRAP_CURRY_FLAG = 8, WRAP_CURRY_RIGHT_FLAG = 16, WRAP_PARTIAL_FLAG = 32, WRAP_PARTIAL_RIGHT_FLAG = 64, WRAP_ARY_FLAG = 128, WRAP_REARG_FLAG = 256, WRAP_FLIP_FLAG = 512;
+ var DEFAULT_TRUNC_LENGTH = 30, DEFAULT_TRUNC_OMISSION = "...";
+ var HOT_COUNT = 800, HOT_SPAN = 16;
+ var LAZY_FILTER_FLAG = 1, LAZY_MAP_FLAG = 2, LAZY_WHILE_FLAG = 3;
+ var INFINITY = 1 / 0, MAX_SAFE_INTEGER = 9007199254740991, MAX_INTEGER = 17976931348623157e292, NAN = 0 / 0;
+ var MAX_ARRAY_LENGTH = 4294967295, MAX_ARRAY_INDEX = MAX_ARRAY_LENGTH - 1, HALF_MAX_ARRAY_LENGTH = MAX_ARRAY_LENGTH >>> 1;
+ var wrapFlags = [
+ ["ary", WRAP_ARY_FLAG],
+ ["bind", WRAP_BIND_FLAG],
+ ["bindKey", WRAP_BIND_KEY_FLAG],
+ ["curry", WRAP_CURRY_FLAG],
+ ["curryRight", WRAP_CURRY_RIGHT_FLAG],
+ ["flip", WRAP_FLIP_FLAG],
+ ["partial", WRAP_PARTIAL_FLAG],
+ ["partialRight", WRAP_PARTIAL_RIGHT_FLAG],
+ ["rearg", WRAP_REARG_FLAG]
+ ];
+ var argsTag = "[object Arguments]", arrayTag = "[object Array]", asyncTag = "[object AsyncFunction]", boolTag = "[object Boolean]", dateTag = "[object Date]", domExcTag = "[object DOMException]", errorTag = "[object Error]", funcTag = "[object Function]", genTag = "[object GeneratorFunction]", mapTag = "[object Map]", numberTag = "[object Number]", nullTag = "[object Null]", objectTag = "[object Object]", promiseTag = "[object Promise]", proxyTag = "[object Proxy]", regexpTag = "[object RegExp]", setTag = "[object Set]", stringTag = "[object String]", symbolTag = "[object Symbol]", undefinedTag = "[object Undefined]", weakMapTag = "[object WeakMap]", weakSetTag = "[object WeakSet]";
+ var arrayBufferTag = "[object ArrayBuffer]", dataViewTag = "[object DataView]", float32Tag = "[object Float32Array]", float64Tag = "[object Float64Array]", int8Tag = "[object Int8Array]", int16Tag = "[object Int16Array]", int32Tag = "[object Int32Array]", uint8Tag = "[object Uint8Array]", uint8ClampedTag = "[object Uint8ClampedArray]", uint16Tag = "[object Uint16Array]", uint32Tag = "[object Uint32Array]";
+ var reEmptyStringLeading = /\b__p \+= '';/g, reEmptyStringMiddle = /\b(__p \+=) '' \+/g, reEmptyStringTrailing = /(__e\(.*?\)|\b__t\)) \+\n'';/g;
+ var reEscapedHtml = /&(?:amp|lt|gt|quot|#39);/g, reUnescapedHtml = /[&<>"']/g, reHasEscapedHtml = RegExp(reEscapedHtml.source), reHasUnescapedHtml = RegExp(reUnescapedHtml.source);
+ var reEscape = /<%-([\s\S]+?)%>/g, reEvaluate = /<%([\s\S]+?)%>/g, reInterpolate = /<%=([\s\S]+?)%>/g;
+ var reIsDeepProp = /\.|\[(?:[^[\]]*|(["'])(?:(?!\1)[^\\]|\\.)*?\1)\]/, reIsPlainProp = /^\w*$/, rePropName = /[^.[\]]+|\[(?:(-?\d+(?:\.\d+)?)|(["'])((?:(?!\2)[^\\]|\\.)*?)\2)\]|(?=(?:\.|\[\])(?:\.|\[\]|$))/g;
+ var reRegExpChar = /[\\^$.*+?()[\]{}|]/g, reHasRegExpChar = RegExp(reRegExpChar.source);
+ var reTrimStart = /^\s+/;
+ var reWhitespace = /\s/;
+ var reWrapComment = /\{(?:\n\/\* \[wrapped with .+\] \*\/)?\n?/, reWrapDetails = /\{\n\/\* \[wrapped with (.+)\] \*/, reSplitDetails = /,? & /;
+ var reAsciiWord = /[^\x00-\x2f\x3a-\x40\x5b-\x60\x7b-\x7f]+/g;
+ var reForbiddenIdentifierChars = /[()=,{}\[\]\/\s]/;
+ var reEscapeChar = /\\(\\)?/g;
+ var reEsTemplate = /\$\{([^\\}]*(?:\\.[^\\}]*)*)\}/g;
+ var reFlags = /\w*$/;
+ var reIsBadHex = /^[-+]0x[0-9a-f]+$/i;
+ var reIsBinary = /^0b[01]+$/i;
+ var reIsHostCtor = /^\[object .+?Constructor\]$/;
+ var reIsOctal = /^0o[0-7]+$/i;
+ var reIsUint = /^(?:0|[1-9]\d*)$/;
+ var reLatin = /[\xc0-\xd6\xd8-\xf6\xf8-\xff\u0100-\u017f]/g;
+ var reNoMatch = /($^)/;
+ var reUnescapedString = /['\n\r\u2028\u2029\\]/g;
+ var rsAstralRange = "\\ud800-\\udfff", rsComboMarksRange = "\\u0300-\\u036f", reComboHalfMarksRange = "\\ufe20-\\ufe2f", rsComboSymbolsRange = "\\u20d0-\\u20ff", rsComboRange = rsComboMarksRange + reComboHalfMarksRange + rsComboSymbolsRange, rsDingbatRange = "\\u2700-\\u27bf", rsLowerRange = "a-z\\xdf-\\xf6\\xf8-\\xff", rsMathOpRange = "\\xac\\xb1\\xd7\\xf7", rsNonCharRange = "\\x00-\\x2f\\x3a-\\x40\\x5b-\\x60\\x7b-\\xbf", rsPunctuationRange = "\\u2000-\\u206f", rsSpaceRange = " \\t\\x0b\\f\\xa0\\ufeff\\n\\r\\u2028\\u2029\\u1680\\u180e\\u2000\\u2001\\u2002\\u2003\\u2004\\u2005\\u2006\\u2007\\u2008\\u2009\\u200a\\u202f\\u205f\\u3000", rsUpperRange = "A-Z\\xc0-\\xd6\\xd8-\\xde", rsVarRange = "\\ufe0e\\ufe0f", rsBreakRange = rsMathOpRange + rsNonCharRange + rsPunctuationRange + rsSpaceRange;
+ var rsApos = "['\u2019]", rsAstral = "[" + rsAstralRange + "]", rsBreak = "[" + rsBreakRange + "]", rsCombo = "[" + rsComboRange + "]", rsDigits = "\\d+", rsDingbat = "[" + rsDingbatRange + "]", rsLower = "[" + rsLowerRange + "]", rsMisc = "[^" + rsAstralRange + rsBreakRange + rsDigits + rsDingbatRange + rsLowerRange + rsUpperRange + "]", rsFitz = "\\ud83c[\\udffb-\\udfff]", rsModifier = "(?:" + rsCombo + "|" + rsFitz + ")", rsNonAstral = "[^" + rsAstralRange + "]", rsRegional = "(?:\\ud83c[\\udde6-\\uddff]){2}", rsSurrPair = "[\\ud800-\\udbff][\\udc00-\\udfff]", rsUpper = "[" + rsUpperRange + "]", rsZWJ = "\\u200d";
+ var rsMiscLower = "(?:" + rsLower + "|" + rsMisc + ")", rsMiscUpper = "(?:" + rsUpper + "|" + rsMisc + ")", rsOptContrLower = "(?:" + rsApos + "(?:d|ll|m|re|s|t|ve))?", rsOptContrUpper = "(?:" + rsApos + "(?:D|LL|M|RE|S|T|VE))?", reOptMod = rsModifier + "?", rsOptVar = "[" + rsVarRange + "]?", rsOptJoin = "(?:" + rsZWJ + "(?:" + [rsNonAstral, rsRegional, rsSurrPair].join("|") + ")" + rsOptVar + reOptMod + ")*", rsOrdLower = "\\d*(?:1st|2nd|3rd|(?![123])\\dth)(?=\\b|[A-Z_])", rsOrdUpper = "\\d*(?:1ST|2ND|3RD|(?![123])\\dTH)(?=\\b|[a-z_])", rsSeq = rsOptVar + reOptMod + rsOptJoin, rsEmoji = "(?:" + [rsDingbat, rsRegional, rsSurrPair].join("|") + ")" + rsSeq, rsSymbol = "(?:" + [rsNonAstral + rsCombo + "?", rsCombo, rsRegional, rsSurrPair, rsAstral].join("|") + ")";
+ var reApos = RegExp(rsApos, "g");
+ var reComboMark = RegExp(rsCombo, "g");
+ var reUnicode = RegExp(rsFitz + "(?=" + rsFitz + ")|" + rsSymbol + rsSeq, "g");
+ var reUnicodeWord = RegExp([
+ rsUpper + "?" + rsLower + "+" + rsOptContrLower + "(?=" + [rsBreak, rsUpper, "$"].join("|") + ")",
+ rsMiscUpper + "+" + rsOptContrUpper + "(?=" + [rsBreak, rsUpper + rsMiscLower, "$"].join("|") + ")",
+ rsUpper + "?" + rsMiscLower + "+" + rsOptContrLower,
+ rsUpper + "+" + rsOptContrUpper,
+ rsOrdUpper,
+ rsOrdLower,
+ rsDigits,
+ rsEmoji
+ ].join("|"), "g");
+ var reHasUnicode = RegExp("[" + rsZWJ + rsAstralRange + rsComboRange + rsVarRange + "]");
+ var reHasUnicodeWord = /[a-z][A-Z]|[A-Z]{2}[a-z]|[0-9][a-zA-Z]|[a-zA-Z][0-9]|[^a-zA-Z0-9 ]/;
+ var contextProps = [
+ "Array",
+ "Buffer",
+ "DataView",
+ "Date",
+ "Error",
+ "Float32Array",
+ "Float64Array",
+ "Function",
+ "Int8Array",
+ "Int16Array",
+ "Int32Array",
+ "Map",
+ "Math",
+ "Object",
+ "Promise",
+ "RegExp",
+ "Set",
+ "String",
+ "Symbol",
+ "TypeError",
+ "Uint8Array",
+ "Uint8ClampedArray",
+ "Uint16Array",
+ "Uint32Array",
+ "WeakMap",
+ "_",
+ "clearTimeout",
+ "isFinite",
+ "parseInt",
+ "setTimeout"
+ ];
+ var templateCounter = -1;
+ var typedArrayTags = {};
+ typedArrayTags[float32Tag] = typedArrayTags[float64Tag] = typedArrayTags[int8Tag] = typedArrayTags[int16Tag] = typedArrayTags[int32Tag] = typedArrayTags[uint8Tag] = typedArrayTags[uint8ClampedTag] = typedArrayTags[uint16Tag] = typedArrayTags[uint32Tag] = true;
+ typedArrayTags[argsTag] = typedArrayTags[arrayTag] = typedArrayTags[arrayBufferTag] = typedArrayTags[boolTag] = typedArrayTags[dataViewTag] = typedArrayTags[dateTag] = typedArrayTags[errorTag] = typedArrayTags[funcTag] = typedArrayTags[mapTag] = typedArrayTags[numberTag] = typedArrayTags[objectTag] = typedArrayTags[regexpTag] = typedArrayTags[setTag] = typedArrayTags[stringTag] = typedArrayTags[weakMapTag] = false;
+ var cloneableTags = {};
+ cloneableTags[argsTag] = cloneableTags[arrayTag] = cloneableTags[arrayBufferTag] = cloneableTags[dataViewTag] = cloneableTags[boolTag] = cloneableTags[dateTag] = cloneableTags[float32Tag] = cloneableTags[float64Tag] = cloneableTags[int8Tag] = cloneableTags[int16Tag] = cloneableTags[int32Tag] = cloneableTags[mapTag] = cloneableTags[numberTag] = cloneableTags[objectTag] = cloneableTags[regexpTag] = cloneableTags[setTag] = cloneableTags[stringTag] = cloneableTags[symbolTag] = cloneableTags[uint8Tag] = cloneableTags[uint8ClampedTag] = cloneableTags[uint16Tag] = cloneableTags[uint32Tag] = true;
+ cloneableTags[errorTag] = cloneableTags[funcTag] = cloneableTags[weakMapTag] = false;
+ var deburredLetters = {
+ "\xC0": "A",
+ "\xC1": "A",
+ "\xC2": "A",
+ "\xC3": "A",
+ "\xC4": "A",
+ "\xC5": "A",
+ "\xE0": "a",
+ "\xE1": "a",
+ "\xE2": "a",
+ "\xE3": "a",
+ "\xE4": "a",
+ "\xE5": "a",
+ "\xC7": "C",
+ "\xE7": "c",
+ "\xD0": "D",
+ "\xF0": "d",
+ "\xC8": "E",
+ "\xC9": "E",
+ "\xCA": "E",
+ "\xCB": "E",
+ "\xE8": "e",
+ "\xE9": "e",
+ "\xEA": "e",
+ "\xEB": "e",
+ "\xCC": "I",
+ "\xCD": "I",
+ "\xCE": "I",
+ "\xCF": "I",
+ "\xEC": "i",
+ "\xED": "i",
+ "\xEE": "i",
+ "\xEF": "i",
+ "\xD1": "N",
+ "\xF1": "n",
+ "\xD2": "O",
+ "\xD3": "O",
+ "\xD4": "O",
+ "\xD5": "O",
+ "\xD6": "O",
+ "\xD8": "O",
+ "\xF2": "o",
+ "\xF3": "o",
+ "\xF4": "o",
+ "\xF5": "o",
+ "\xF6": "o",
+ "\xF8": "o",
+ "\xD9": "U",
+ "\xDA": "U",
+ "\xDB": "U",
+ "\xDC": "U",
+ "\xF9": "u",
+ "\xFA": "u",
+ "\xFB": "u",
+ "\xFC": "u",
+ "\xDD": "Y",
+ "\xFD": "y",
+ "\xFF": "y",
+ "\xC6": "Ae",
+ "\xE6": "ae",
+ "\xDE": "Th",
+ "\xFE": "th",
+ "\xDF": "ss",
+ "\u0100": "A",
+ "\u0102": "A",
+ "\u0104": "A",
+ "\u0101": "a",
+ "\u0103": "a",
+ "\u0105": "a",
+ "\u0106": "C",
+ "\u0108": "C",
+ "\u010A": "C",
+ "\u010C": "C",
+ "\u0107": "c",
+ "\u0109": "c",
+ "\u010B": "c",
+ "\u010D": "c",
+ "\u010E": "D",
+ "\u0110": "D",
+ "\u010F": "d",
+ "\u0111": "d",
+ "\u0112": "E",
+ "\u0114": "E",
+ "\u0116": "E",
+ "\u0118": "E",
+ "\u011A": "E",
+ "\u0113": "e",
+ "\u0115": "e",
+ "\u0117": "e",
+ "\u0119": "e",
+ "\u011B": "e",
+ "\u011C": "G",
+ "\u011E": "G",
+ "\u0120": "G",
+ "\u0122": "G",
+ "\u011D": "g",
+ "\u011F": "g",
+ "\u0121": "g",
+ "\u0123": "g",
+ "\u0124": "H",
+ "\u0126": "H",
+ "\u0125": "h",
+ "\u0127": "h",
+ "\u0128": "I",
+ "\u012A": "I",
+ "\u012C": "I",
+ "\u012E": "I",
+ "\u0130": "I",
+ "\u0129": "i",
+ "\u012B": "i",
+ "\u012D": "i",
+ "\u012F": "i",
+ "\u0131": "i",
+ "\u0134": "J",
+ "\u0135": "j",
+ "\u0136": "K",
+ "\u0137": "k",
+ "\u0138": "k",
+ "\u0139": "L",
+ "\u013B": "L",
+ "\u013D": "L",
+ "\u013F": "L",
+ "\u0141": "L",
+ "\u013A": "l",
+ "\u013C": "l",
+ "\u013E": "l",
+ "\u0140": "l",
+ "\u0142": "l",
+ "\u0143": "N",
+ "\u0145": "N",
+ "\u0147": "N",
+ "\u014A": "N",
+ "\u0144": "n",
+ "\u0146": "n",
+ "\u0148": "n",
+ "\u014B": "n",
+ "\u014C": "O",
+ "\u014E": "O",
+ "\u0150": "O",
+ "\u014D": "o",
+ "\u014F": "o",
+ "\u0151": "o",
+ "\u0154": "R",
+ "\u0156": "R",
+ "\u0158": "R",
+ "\u0155": "r",
+ "\u0157": "r",
+ "\u0159": "r",
+ "\u015A": "S",
+ "\u015C": "S",
+ "\u015E": "S",
+ "\u0160": "S",
+ "\u015B": "s",
+ "\u015D": "s",
+ "\u015F": "s",
+ "\u0161": "s",
+ "\u0162": "T",
+ "\u0164": "T",
+ "\u0166": "T",
+ "\u0163": "t",
+ "\u0165": "t",
+ "\u0167": "t",
+ "\u0168": "U",
+ "\u016A": "U",
+ "\u016C": "U",
+ "\u016E": "U",
+ "\u0170": "U",
+ "\u0172": "U",
+ "\u0169": "u",
+ "\u016B": "u",
+ "\u016D": "u",
+ "\u016F": "u",
+ "\u0171": "u",
+ "\u0173": "u",
+ "\u0174": "W",
+ "\u0175": "w",
+ "\u0176": "Y",
+ "\u0177": "y",
+ "\u0178": "Y",
+ "\u0179": "Z",
+ "\u017B": "Z",
+ "\u017D": "Z",
+ "\u017A": "z",
+ "\u017C": "z",
+ "\u017E": "z",
+ "\u0132": "IJ",
+ "\u0133": "ij",
+ "\u0152": "Oe",
+ "\u0153": "oe",
+ "\u0149": "'n",
+ "\u017F": "s"
+ };
+ var htmlEscapes = {
+ "&": "&",
+ "<": "<",
+ ">": ">",
+ '"': """,
+ "'": "'"
+ };
+ var htmlUnescapes = {
+ "&": "&",
+ "<": "<",
+ ">": ">",
+ """: '"',
+ "'": "'"
+ };
+ var stringEscapes = {
+ "\\": "\\",
+ "'": "'",
+ "\n": "n",
+ "\r": "r",
+ "\u2028": "u2028",
+ "\u2029": "u2029"
+ };
+ var freeParseFloat = parseFloat, freeParseInt = parseInt;
+ var freeGlobal = typeof global == "object" && global && global.Object === Object && global;
+ var freeSelf = typeof self == "object" && self && self.Object === Object && self;
+ var root = freeGlobal || freeSelf || Function("return this")();
+ var freeExports = typeof exports == "object" && exports && !exports.nodeType && exports;
+ var freeModule = freeExports && typeof module == "object" && module && !module.nodeType && module;
+ var moduleExports = freeModule && freeModule.exports === freeExports;
+ var freeProcess = moduleExports && freeGlobal.process;
+ var nodeUtil = function() {
+ try {
+ var types = freeModule && freeModule.require && freeModule.require("util").types;
+ if (types) {
+ return types;
+ }
+ return freeProcess && freeProcess.binding && freeProcess.binding("util");
+ } catch (e) {
+ }
+ }();
+ var nodeIsArrayBuffer = nodeUtil && nodeUtil.isArrayBuffer, nodeIsDate = nodeUtil && nodeUtil.isDate, nodeIsMap = nodeUtil && nodeUtil.isMap, nodeIsRegExp = nodeUtil && nodeUtil.isRegExp, nodeIsSet = nodeUtil && nodeUtil.isSet, nodeIsTypedArray = nodeUtil && nodeUtil.isTypedArray;
+ function apply(func, thisArg, args) {
+ switch (args.length) {
+ case 0:
+ return func.call(thisArg);
+ case 1:
+ return func.call(thisArg, args[0]);
+ case 2:
+ return func.call(thisArg, args[0], args[1]);
+ case 3:
+ return func.call(thisArg, args[0], args[1], args[2]);
+ }
+ return func.apply(thisArg, args);
+ }
+ function arrayAggregator(array, setter, iteratee, accumulator) {
+ var index = -1, length = array == null ? 0 : array.length;
+ while (++index < length) {
+ var value = array[index];
+ setter(accumulator, value, iteratee(value), array);
+ }
+ return accumulator;
+ }
+ function arrayEach(array, iteratee) {
+ var index = -1, length = array == null ? 0 : array.length;
+ while (++index < length) {
+ if (iteratee(array[index], index, array) === false) {
+ break;
+ }
+ }
+ return array;
+ }
+ function arrayEachRight(array, iteratee) {
+ var length = array == null ? 0 : array.length;
+ while (length--) {
+ if (iteratee(array[length], length, array) === false) {
+ break;
+ }
+ }
+ return array;
+ }
+ function arrayEvery(array, predicate) {
+ var index = -1, length = array == null ? 0 : array.length;
+ while (++index < length) {
+ if (!predicate(array[index], index, array)) {
+ return false;
+ }
+ }
+ return true;
+ }
+ function arrayFilter(array, predicate) {
+ var index = -1, length = array == null ? 0 : array.length, resIndex = 0, result = [];
+ while (++index < length) {
+ var value = array[index];
+ if (predicate(value, index, array)) {
+ result[resIndex++] = value;
+ }
+ }
+ return result;
+ }
+ function arrayIncludes(array, value) {
+ var length = array == null ? 0 : array.length;
+ return !!length && baseIndexOf(array, value, 0) > -1;
+ }
+ function arrayIncludesWith(array, value, comparator) {
+ var index = -1, length = array == null ? 0 : array.length;
+ while (++index < length) {
+ if (comparator(value, array[index])) {
+ return true;
+ }
+ }
+ return false;
+ }
+ function arrayMap(array, iteratee) {
+ var index = -1, length = array == null ? 0 : array.length, result = Array(length);
+ while (++index < length) {
+ result[index] = iteratee(array[index], index, array);
+ }
+ return result;
+ }
+ function arrayPush(array, values) {
+ var index = -1, length = values.length, offset = array.length;
+ while (++index < length) {
+ array[offset + index] = values[index];
+ }
+ return array;
+ }
+ function arrayReduce(array, iteratee, accumulator, initAccum) {
+ var index = -1, length = array == null ? 0 : array.length;
+ if (initAccum && length) {
+ accumulator = array[++index];
+ }
+ while (++index < length) {
+ accumulator = iteratee(accumulator, array[index], index, array);
+ }
+ return accumulator;
+ }
+ function arrayReduceRight(array, iteratee, accumulator, initAccum) {
+ var length = array == null ? 0 : array.length;
+ if (initAccum && length) {
+ accumulator = array[--length];
+ }
+ while (length--) {
+ accumulator = iteratee(accumulator, array[length], length, array);
+ }
+ return accumulator;
+ }
+ function arraySome(array, predicate) {
+ var index = -1, length = array == null ? 0 : array.length;
+ while (++index < length) {
+ if (predicate(array[index], index, array)) {
+ return true;
+ }
+ }
+ return false;
+ }
+ var asciiSize = baseProperty("length");
+ function asciiToArray(string) {
+ return string.split("");
+ }
+ function asciiWords(string) {
+ return string.match(reAsciiWord) || [];
+ }
+ function baseFindKey(collection, predicate, eachFunc) {
+ var result;
+ eachFunc(collection, function(value, key, collection2) {
+ if (predicate(value, key, collection2)) {
+ result = key;
+ return false;
+ }
+ });
+ return result;
+ }
+ function baseFindIndex(array, predicate, fromIndex, fromRight) {
+ var length = array.length, index = fromIndex + (fromRight ? 1 : -1);
+ while (fromRight ? index-- : ++index < length) {
+ if (predicate(array[index], index, array)) {
+ return index;
+ }
+ }
+ return -1;
+ }
+ function baseIndexOf(array, value, fromIndex) {
+ return value === value ? strictIndexOf(array, value, fromIndex) : baseFindIndex(array, baseIsNaN, fromIndex);
+ }
+ function baseIndexOfWith(array, value, fromIndex, comparator) {
+ var index = fromIndex - 1, length = array.length;
+ while (++index < length) {
+ if (comparator(array[index], value)) {
+ return index;
+ }
+ }
+ return -1;
+ }
+ function baseIsNaN(value) {
+ return value !== value;
+ }
+ function baseMean(array, iteratee) {
+ var length = array == null ? 0 : array.length;
+ return length ? baseSum(array, iteratee) / length : NAN;
+ }
+ function baseProperty(key) {
+ return function(object) {
+ return object == null ? undefined2 : object[key];
+ };
+ }
+ function basePropertyOf(object) {
+ return function(key) {
+ return object == null ? undefined2 : object[key];
+ };
+ }
+ function baseReduce(collection, iteratee, accumulator, initAccum, eachFunc) {
+ eachFunc(collection, function(value, index, collection2) {
+ accumulator = initAccum ? (initAccum = false, value) : iteratee(accumulator, value, index, collection2);
+ });
+ return accumulator;
+ }
+ function baseSortBy(array, comparer) {
+ var length = array.length;
+ array.sort(comparer);
+ while (length--) {
+ array[length] = array[length].value;
+ }
+ return array;
+ }
+ function baseSum(array, iteratee) {
+ var result, index = -1, length = array.length;
+ while (++index < length) {
+ var current = iteratee(array[index]);
+ if (current !== undefined2) {
+ result = result === undefined2 ? current : result + current;
+ }
+ }
+ return result;
+ }
+ function baseTimes(n, iteratee) {
+ var index = -1, result = Array(n);
+ while (++index < n) {
+ result[index] = iteratee(index);
+ }
+ return result;
+ }
+ function baseToPairs(object, props) {
+ return arrayMap(props, function(key) {
+ return [key, object[key]];
+ });
+ }
+ function baseTrim(string) {
+ return string ? string.slice(0, trimmedEndIndex(string) + 1).replace(reTrimStart, "") : string;
+ }
+ function baseUnary(func) {
+ return function(value) {
+ return func(value);
+ };
+ }
+ function baseValues(object, props) {
+ return arrayMap(props, function(key) {
+ return object[key];
+ });
+ }
+ function cacheHas(cache2, key) {
+ return cache2.has(key);
+ }
+ function charsStartIndex(strSymbols, chrSymbols) {
+ var index = -1, length = strSymbols.length;
+ while (++index < length && baseIndexOf(chrSymbols, strSymbols[index], 0) > -1) {
+ }
+ return index;
+ }
+ function charsEndIndex(strSymbols, chrSymbols) {
+ var index = strSymbols.length;
+ while (index-- && baseIndexOf(chrSymbols, strSymbols[index], 0) > -1) {
+ }
+ return index;
+ }
+ function countHolders(array, placeholder) {
+ var length = array.length, result = 0;
+ while (length--) {
+ if (array[length] === placeholder) {
+ ++result;
+ }
+ }
+ return result;
+ }
+ var deburrLetter = basePropertyOf(deburredLetters);
+ var escapeHtmlChar = basePropertyOf(htmlEscapes);
+ function escapeStringChar(chr) {
+ return "\\" + stringEscapes[chr];
+ }
+ function getValue(object, key) {
+ return object == null ? undefined2 : object[key];
+ }
+ function hasUnicode(string) {
+ return reHasUnicode.test(string);
+ }
+ function hasUnicodeWord(string) {
+ return reHasUnicodeWord.test(string);
+ }
+ function iteratorToArray(iterator) {
+ var data, result = [];
+ while (!(data = iterator.next()).done) {
+ result.push(data.value);
+ }
+ return result;
+ }
+ function mapToArray(map) {
+ var index = -1, result = Array(map.size);
+ map.forEach(function(value, key) {
+ result[++index] = [key, value];
+ });
+ return result;
+ }
+ function overArg(func, transform) {
+ return function(arg) {
+ return func(transform(arg));
+ };
+ }
+ function replaceHolders(array, placeholder) {
+ var index = -1, length = array.length, resIndex = 0, result = [];
+ while (++index < length) {
+ var value = array[index];
+ if (value === placeholder || value === PLACEHOLDER) {
+ array[index] = PLACEHOLDER;
+ result[resIndex++] = index;
+ }
+ }
+ return result;
+ }
+ function setToArray(set2) {
+ var index = -1, result = Array(set2.size);
+ set2.forEach(function(value) {
+ result[++index] = value;
+ });
+ return result;
+ }
+ function setToPairs(set2) {
+ var index = -1, result = Array(set2.size);
+ set2.forEach(function(value) {
+ result[++index] = [value, value];
+ });
+ return result;
+ }
+ function strictIndexOf(array, value, fromIndex) {
+ var index = fromIndex - 1, length = array.length;
+ while (++index < length) {
+ if (array[index] === value) {
+ return index;
+ }
+ }
+ return -1;
+ }
+ function strictLastIndexOf(array, value, fromIndex) {
+ var index = fromIndex + 1;
+ while (index--) {
+ if (array[index] === value) {
+ return index;
+ }
+ }
+ return index;
+ }
+ function stringSize(string) {
+ return hasUnicode(string) ? unicodeSize(string) : asciiSize(string);
+ }
+ function stringToArray(string) {
+ return hasUnicode(string) ? unicodeToArray(string) : asciiToArray(string);
+ }
+ function trimmedEndIndex(string) {
+ var index = string.length;
+ while (index-- && reWhitespace.test(string.charAt(index))) {
+ }
+ return index;
+ }
+ var unescapeHtmlChar = basePropertyOf(htmlUnescapes);
+ function unicodeSize(string) {
+ var result = reUnicode.lastIndex = 0;
+ while (reUnicode.test(string)) {
+ ++result;
+ }
+ return result;
+ }
+ function unicodeToArray(string) {
+ return string.match(reUnicode) || [];
+ }
+ function unicodeWords(string) {
+ return string.match(reUnicodeWord) || [];
+ }
+ var runInContext = function runInContext2(context) {
+ context = context == null ? root : _3.defaults(root.Object(), context, _3.pick(root, contextProps));
+ var Array2 = context.Array, Date2 = context.Date, Error2 = context.Error, Function2 = context.Function, Math2 = context.Math, Object2 = context.Object, RegExp2 = context.RegExp, String = context.String, TypeError2 = context.TypeError;
+ var arrayProto = Array2.prototype, funcProto = Function2.prototype, objectProto = Object2.prototype;
+ var coreJsData = context["__core-js_shared__"];
+ var funcToString = funcProto.toString;
+ var hasOwnProperty = objectProto.hasOwnProperty;
+ var idCounter = 0;
+ var maskSrcKey = function() {
+ var uid = /[^.]+$/.exec(coreJsData && coreJsData.keys && coreJsData.keys.IE_PROTO || "");
+ return uid ? "Symbol(src)_1." + uid : "";
+ }();
+ var nativeObjectToString = objectProto.toString;
+ var objectCtorString = funcToString.call(Object2);
+ var oldDash = root._;
+ var reIsNative = RegExp2(
+ "^" + funcToString.call(hasOwnProperty).replace(reRegExpChar, "\\$&").replace(/hasOwnProperty|(function).*?(?=\\\()| for .+?(?=\\\])/g, "$1.*?") + "$"
+ );
+ var Buffer2 = moduleExports ? context.Buffer : undefined2, Symbol = context.Symbol, Uint8Array2 = context.Uint8Array, allocUnsafe = Buffer2 ? Buffer2.allocUnsafe : undefined2, getPrototype = overArg(Object2.getPrototypeOf, Object2), objectCreate = Object2.create, propertyIsEnumerable = objectProto.propertyIsEnumerable, splice = arrayProto.splice, spreadableSymbol = Symbol ? Symbol.isConcatSpreadable : undefined2, symIterator = Symbol ? Symbol.iterator : undefined2, symToStringTag = Symbol ? Symbol.toStringTag : undefined2;
+ var defineProperty = function() {
+ try {
+ var func = getNative(Object2, "defineProperty");
+ func({}, "", {});
+ return func;
+ } catch (e) {
+ }
+ }();
+ var ctxClearTimeout = context.clearTimeout !== root.clearTimeout && context.clearTimeout, ctxNow = Date2 && Date2.now !== root.Date.now && Date2.now, ctxSetTimeout = context.setTimeout !== root.setTimeout && context.setTimeout;
+ var nativeCeil = Math2.ceil, nativeFloor = Math2.floor, nativeGetSymbols = Object2.getOwnPropertySymbols, nativeIsBuffer = Buffer2 ? Buffer2.isBuffer : undefined2, nativeIsFinite = context.isFinite, nativeJoin = arrayProto.join, nativeKeys = overArg(Object2.keys, Object2), nativeMax = Math2.max, nativeMin = Math2.min, nativeNow = Date2.now, nativeParseInt = context.parseInt, nativeRandom = Math2.random, nativeReverse = arrayProto.reverse;
+ var DataView = getNative(context, "DataView"), Map2 = getNative(context, "Map"), Promise2 = getNative(context, "Promise"), Set = getNative(context, "Set"), WeakMap = getNative(context, "WeakMap"), nativeCreate = getNative(Object2, "create");
+ var metaMap = WeakMap && new WeakMap();
+ var realNames = {};
+ var dataViewCtorString = toSource(DataView), mapCtorString = toSource(Map2), promiseCtorString = toSource(Promise2), setCtorString = toSource(Set), weakMapCtorString = toSource(WeakMap);
+ var symbolProto = Symbol ? Symbol.prototype : undefined2, symbolValueOf = symbolProto ? symbolProto.valueOf : undefined2, symbolToString = symbolProto ? symbolProto.toString : undefined2;
+ function lodash(value) {
+ if (isObjectLike(value) && !isArray(value) && !(value instanceof LazyWrapper)) {
+ if (value instanceof LodashWrapper) {
+ return value;
+ }
+ if (hasOwnProperty.call(value, "__wrapped__")) {
+ return wrapperClone(value);
+ }
+ }
+ return new LodashWrapper(value);
+ }
+ var baseCreate = function() {
+ function object() {
+ }
+ return function(proto) {
+ if (!isObject(proto)) {
+ return {};
+ }
+ if (objectCreate) {
+ return objectCreate(proto);
+ }
+ object.prototype = proto;
+ var result2 = new object();
+ object.prototype = undefined2;
+ return result2;
+ };
+ }();
+ function baseLodash() {
+ }
+ function LodashWrapper(value, chainAll) {
+ this.__wrapped__ = value;
+ this.__actions__ = [];
+ this.__chain__ = !!chainAll;
+ this.__index__ = 0;
+ this.__values__ = undefined2;
+ }
+ lodash.templateSettings = {
+ "escape": reEscape,
+ "evaluate": reEvaluate,
+ "interpolate": reInterpolate,
+ "variable": "",
+ "imports": {
+ "_": lodash
+ }
+ };
+ lodash.prototype = baseLodash.prototype;
+ lodash.prototype.constructor = lodash;
+ LodashWrapper.prototype = baseCreate(baseLodash.prototype);
+ LodashWrapper.prototype.constructor = LodashWrapper;
+ function LazyWrapper(value) {
+ this.__wrapped__ = value;
+ this.__actions__ = [];
+ this.__dir__ = 1;
+ this.__filtered__ = false;
+ this.__iteratees__ = [];
+ this.__takeCount__ = MAX_ARRAY_LENGTH;
+ this.__views__ = [];
+ }
+ function lazyClone() {
+ var result2 = new LazyWrapper(this.__wrapped__);
+ result2.__actions__ = copyArray(this.__actions__);
+ result2.__dir__ = this.__dir__;
+ result2.__filtered__ = this.__filtered__;
+ result2.__iteratees__ = copyArray(this.__iteratees__);
+ result2.__takeCount__ = this.__takeCount__;
+ result2.__views__ = copyArray(this.__views__);
+ return result2;
+ }
+ function lazyReverse() {
+ if (this.__filtered__) {
+ var result2 = new LazyWrapper(this);
+ result2.__dir__ = -1;
+ result2.__filtered__ = true;
+ } else {
+ result2 = this.clone();
+ result2.__dir__ *= -1;
+ }
+ return result2;
+ }
+ function lazyValue() {
+ var array = this.__wrapped__.value(), dir = this.__dir__, isArr = isArray(array), isRight = dir < 0, arrLength = isArr ? array.length : 0, view = getView(0, arrLength, this.__views__), start = view.start, end = view.end, length = end - start, index = isRight ? end : start - 1, iteratees = this.__iteratees__, iterLength = iteratees.length, resIndex = 0, takeCount = nativeMin(length, this.__takeCount__);
+ if (!isArr || !isRight && arrLength == length && takeCount == length) {
+ return baseWrapperValue(array, this.__actions__);
+ }
+ var result2 = [];
+ outer:
+ while (length-- && resIndex < takeCount) {
+ index += dir;
+ var iterIndex = -1, value = array[index];
+ while (++iterIndex < iterLength) {
+ var data = iteratees[iterIndex], iteratee2 = data.iteratee, type = data.type, computed = iteratee2(value);
+ if (type == LAZY_MAP_FLAG) {
+ value = computed;
+ } else if (!computed) {
+ if (type == LAZY_FILTER_FLAG) {
+ continue outer;
+ } else {
+ break outer;
+ }
+ }
+ }
+ result2[resIndex++] = value;
+ }
+ return result2;
+ }
+ LazyWrapper.prototype = baseCreate(baseLodash.prototype);
+ LazyWrapper.prototype.constructor = LazyWrapper;
+ function Hash(entries) {
+ var index = -1, length = entries == null ? 0 : entries.length;
+ this.clear();
+ while (++index < length) {
+ var entry = entries[index];
+ this.set(entry[0], entry[1]);
+ }
+ }
+ function hashClear() {
+ this.__data__ = nativeCreate ? nativeCreate(null) : {};
+ this.size = 0;
+ }
+ function hashDelete(key) {
+ var result2 = this.has(key) && delete this.__data__[key];
+ this.size -= result2 ? 1 : 0;
+ return result2;
+ }
+ function hashGet(key) {
+ var data = this.__data__;
+ if (nativeCreate) {
+ var result2 = data[key];
+ return result2 === HASH_UNDEFINED ? undefined2 : result2;
+ }
+ return hasOwnProperty.call(data, key) ? data[key] : undefined2;
+ }
+ function hashHas(key) {
+ var data = this.__data__;
+ return nativeCreate ? data[key] !== undefined2 : hasOwnProperty.call(data, key);
+ }
+ function hashSet(key, value) {
+ var data = this.__data__;
+ this.size += this.has(key) ? 0 : 1;
+ data[key] = nativeCreate && value === undefined2 ? HASH_UNDEFINED : value;
+ return this;
+ }
+ Hash.prototype.clear = hashClear;
+ Hash.prototype["delete"] = hashDelete;
+ Hash.prototype.get = hashGet;
+ Hash.prototype.has = hashHas;
+ Hash.prototype.set = hashSet;
+ function ListCache(entries) {
+ var index = -1, length = entries == null ? 0 : entries.length;
+ this.clear();
+ while (++index < length) {
+ var entry = entries[index];
+ this.set(entry[0], entry[1]);
+ }
+ }
+ function listCacheClear() {
+ this.__data__ = [];
+ this.size = 0;
+ }
+ function listCacheDelete(key) {
+ var data = this.__data__, index = assocIndexOf(data, key);
+ if (index < 0) {
+ return false;
+ }
+ var lastIndex = data.length - 1;
+ if (index == lastIndex) {
+ data.pop();
+ } else {
+ splice.call(data, index, 1);
+ }
+ --this.size;
+ return true;
+ }
+ function listCacheGet(key) {
+ var data = this.__data__, index = assocIndexOf(data, key);
+ return index < 0 ? undefined2 : data[index][1];
+ }
+ function listCacheHas(key) {
+ return assocIndexOf(this.__data__, key) > -1;
+ }
+ function listCacheSet(key, value) {
+ var data = this.__data__, index = assocIndexOf(data, key);
+ if (index < 0) {
+ ++this.size;
+ data.push([key, value]);
+ } else {
+ data[index][1] = value;
+ }
+ return this;
+ }
+ ListCache.prototype.clear = listCacheClear;
+ ListCache.prototype["delete"] = listCacheDelete;
+ ListCache.prototype.get = listCacheGet;
+ ListCache.prototype.has = listCacheHas;
+ ListCache.prototype.set = listCacheSet;
+ function MapCache(entries) {
+ var index = -1, length = entries == null ? 0 : entries.length;
+ this.clear();
+ while (++index < length) {
+ var entry = entries[index];
+ this.set(entry[0], entry[1]);
+ }
+ }
+ function mapCacheClear() {
+ this.size = 0;
+ this.__data__ = {
+ "hash": new Hash(),
+ "map": new (Map2 || ListCache)(),
+ "string": new Hash()
+ };
+ }
+ function mapCacheDelete(key) {
+ var result2 = getMapData(this, key)["delete"](key);
+ this.size -= result2 ? 1 : 0;
+ return result2;
+ }
+ function mapCacheGet(key) {
+ return getMapData(this, key).get(key);
+ }
+ function mapCacheHas(key) {
+ return getMapData(this, key).has(key);
+ }
+ function mapCacheSet(key, value) {
+ var data = getMapData(this, key), size2 = data.size;
+ data.set(key, value);
+ this.size += data.size == size2 ? 0 : 1;
+ return this;
+ }
+ MapCache.prototype.clear = mapCacheClear;
+ MapCache.prototype["delete"] = mapCacheDelete;
+ MapCache.prototype.get = mapCacheGet;
+ MapCache.prototype.has = mapCacheHas;
+ MapCache.prototype.set = mapCacheSet;
+ function SetCache(values2) {
+ var index = -1, length = values2 == null ? 0 : values2.length;
+ this.__data__ = new MapCache();
+ while (++index < length) {
+ this.add(values2[index]);
+ }
+ }
+ function setCacheAdd(value) {
+ this.__data__.set(value, HASH_UNDEFINED);
+ return this;
+ }
+ function setCacheHas(value) {
+ return this.__data__.has(value);
+ }
+ SetCache.prototype.add = SetCache.prototype.push = setCacheAdd;
+ SetCache.prototype.has = setCacheHas;
+ function Stack(entries) {
+ var data = this.__data__ = new ListCache(entries);
+ this.size = data.size;
+ }
+ function stackClear() {
+ this.__data__ = new ListCache();
+ this.size = 0;
+ }
+ function stackDelete(key) {
+ var data = this.__data__, result2 = data["delete"](key);
+ this.size = data.size;
+ return result2;
+ }
+ function stackGet(key) {
+ return this.__data__.get(key);
+ }
+ function stackHas(key) {
+ return this.__data__.has(key);
+ }
+ function stackSet(key, value) {
+ var data = this.__data__;
+ if (data instanceof ListCache) {
+ var pairs = data.__data__;
+ if (!Map2 || pairs.length < LARGE_ARRAY_SIZE - 1) {
+ pairs.push([key, value]);
+ this.size = ++data.size;
+ return this;
+ }
+ data = this.__data__ = new MapCache(pairs);
+ }
+ data.set(key, value);
+ this.size = data.size;
+ return this;
+ }
+ Stack.prototype.clear = stackClear;
+ Stack.prototype["delete"] = stackDelete;
+ Stack.prototype.get = stackGet;
+ Stack.prototype.has = stackHas;
+ Stack.prototype.set = stackSet;
+ function arrayLikeKeys(value, inherited) {
+ var isArr = isArray(value), isArg = !isArr && isArguments(value), isBuff = !isArr && !isArg && isBuffer(value), isType = !isArr && !isArg && !isBuff && isTypedArray(value), skipIndexes = isArr || isArg || isBuff || isType, result2 = skipIndexes ? baseTimes(value.length, String) : [], length = result2.length;
+ for (var key in value) {
+ if ((inherited || hasOwnProperty.call(value, key)) && !(skipIndexes && (key == "length" || isBuff && (key == "offset" || key == "parent") || isType && (key == "buffer" || key == "byteLength" || key == "byteOffset") || isIndex(key, length)))) {
+ result2.push(key);
+ }
+ }
+ return result2;
+ }
+ function arraySample(array) {
+ var length = array.length;
+ return length ? array[baseRandom(0, length - 1)] : undefined2;
+ }
+ function arraySampleSize(array, n) {
+ return shuffleSelf(copyArray(array), baseClamp(n, 0, array.length));
+ }
+ function arrayShuffle(array) {
+ return shuffleSelf(copyArray(array));
+ }
+ function assignMergeValue(object, key, value) {
+ if (value !== undefined2 && !eq(object[key], value) || value === undefined2 && !(key in object)) {
+ baseAssignValue(object, key, value);
+ }
+ }
+ function assignValue(object, key, value) {
+ var objValue = object[key];
+ if (!(hasOwnProperty.call(object, key) && eq(objValue, value)) || value === undefined2 && !(key in object)) {
+ baseAssignValue(object, key, value);
+ }
+ }
+ function assocIndexOf(array, key) {
+ var length = array.length;
+ while (length--) {
+ if (eq(array[length][0], key)) {
+ return length;
+ }
+ }
+ return -1;
+ }
+ function baseAggregator(collection, setter, iteratee2, accumulator) {
+ baseEach(collection, function(value, key, collection2) {
+ setter(accumulator, value, iteratee2(value), collection2);
+ });
+ return accumulator;
+ }
+ function baseAssign(object, source) {
+ return object && copyObject(source, keys(source), object);
+ }
+ function baseAssignIn(object, source) {
+ return object && copyObject(source, keysIn(source), object);
+ }
+ function baseAssignValue(object, key, value) {
+ if (key == "__proto__" && defineProperty) {
+ defineProperty(object, key, {
+ "configurable": true,
+ "enumerable": true,
+ "value": value,
+ "writable": true
+ });
+ } else {
+ object[key] = value;
+ }
+ }
+ function baseAt(object, paths) {
+ var index = -1, length = paths.length, result2 = Array2(length), skip = object == null;
+ while (++index < length) {
+ result2[index] = skip ? undefined2 : get(object, paths[index]);
+ }
+ return result2;
+ }
+ function baseClamp(number, lower, upper) {
+ if (number === number) {
+ if (upper !== undefined2) {
+ number = number <= upper ? number : upper;
+ }
+ if (lower !== undefined2) {
+ number = number >= lower ? number : lower;
+ }
+ }
+ return number;
+ }
+ function baseClone(value, bitmask, customizer, key, object, stack) {
+ var result2, isDeep = bitmask & CLONE_DEEP_FLAG, isFlat = bitmask & CLONE_FLAT_FLAG, isFull = bitmask & CLONE_SYMBOLS_FLAG;
+ if (customizer) {
+ result2 = object ? customizer(value, key, object, stack) : customizer(value);
+ }
+ if (result2 !== undefined2) {
+ return result2;
+ }
+ if (!isObject(value)) {
+ return value;
+ }
+ var isArr = isArray(value);
+ if (isArr) {
+ result2 = initCloneArray(value);
+ if (!isDeep) {
+ return copyArray(value, result2);
+ }
+ } else {
+ var tag = getTag(value), isFunc = tag == funcTag || tag == genTag;
+ if (isBuffer(value)) {
+ return cloneBuffer(value, isDeep);
+ }
+ if (tag == objectTag || tag == argsTag || isFunc && !object) {
+ result2 = isFlat || isFunc ? {} : initCloneObject(value);
+ if (!isDeep) {
+ return isFlat ? copySymbolsIn(value, baseAssignIn(result2, value)) : copySymbols(value, baseAssign(result2, value));
+ }
+ } else {
+ if (!cloneableTags[tag]) {
+ return object ? value : {};
+ }
+ result2 = initCloneByTag(value, tag, isDeep);
+ }
+ }
+ stack || (stack = new Stack());
+ var stacked = stack.get(value);
+ if (stacked) {
+ return stacked;
+ }
+ stack.set(value, result2);
+ if (isSet(value)) {
+ value.forEach(function(subValue) {
+ result2.add(baseClone(subValue, bitmask, customizer, subValue, value, stack));
+ });
+ } else if (isMap(value)) {
+ value.forEach(function(subValue, key2) {
+ result2.set(key2, baseClone(subValue, bitmask, customizer, key2, value, stack));
+ });
+ }
+ var keysFunc = isFull ? isFlat ? getAllKeysIn : getAllKeys : isFlat ? keysIn : keys;
+ var props = isArr ? undefined2 : keysFunc(value);
+ arrayEach(props || value, function(subValue, key2) {
+ if (props) {
+ key2 = subValue;
+ subValue = value[key2];
+ }
+ assignValue(result2, key2, baseClone(subValue, bitmask, customizer, key2, value, stack));
+ });
+ return result2;
+ }
+ function baseConforms(source) {
+ var props = keys(source);
+ return function(object) {
+ return baseConformsTo(object, source, props);
+ };
+ }
+ function baseConformsTo(object, source, props) {
+ var length = props.length;
+ if (object == null) {
+ return !length;
+ }
+ object = Object2(object);
+ while (length--) {
+ var key = props[length], predicate = source[key], value = object[key];
+ if (value === undefined2 && !(key in object) || !predicate(value)) {
+ return false;
+ }
+ }
+ return true;
+ }
+ function baseDelay(func, wait, args) {
+ if (typeof func != "function") {
+ throw new TypeError2(FUNC_ERROR_TEXT);
+ }
+ return setTimeout2(function() {
+ func.apply(undefined2, args);
+ }, wait);
+ }
+ function baseDifference(array, values2, iteratee2, comparator) {
+ var index = -1, includes2 = arrayIncludes, isCommon = true, length = array.length, result2 = [], valuesLength = values2.length;
+ if (!length) {
+ return result2;
+ }
+ if (iteratee2) {
+ values2 = arrayMap(values2, baseUnary(iteratee2));
+ }
+ if (comparator) {
+ includes2 = arrayIncludesWith;
+ isCommon = false;
+ } else if (values2.length >= LARGE_ARRAY_SIZE) {
+ includes2 = cacheHas;
+ isCommon = false;
+ values2 = new SetCache(values2);
+ }
+ outer:
+ while (++index < length) {
+ var value = array[index], computed = iteratee2 == null ? value : iteratee2(value);
+ value = comparator || value !== 0 ? value : 0;
+ if (isCommon && computed === computed) {
+ var valuesIndex = valuesLength;
+ while (valuesIndex--) {
+ if (values2[valuesIndex] === computed) {
+ continue outer;
+ }
+ }
+ result2.push(value);
+ } else if (!includes2(values2, computed, comparator)) {
+ result2.push(value);
+ }
+ }
+ return result2;
+ }
+ var baseEach = createBaseEach(baseForOwn);
+ var baseEachRight = createBaseEach(baseForOwnRight, true);
+ function baseEvery(collection, predicate) {
+ var result2 = true;
+ baseEach(collection, function(value, index, collection2) {
+ result2 = !!predicate(value, index, collection2);
+ return result2;
+ });
+ return result2;
+ }
+ function baseExtremum(array, iteratee2, comparator) {
+ var index = -1, length = array.length;
+ while (++index < length) {
+ var value = array[index], current = iteratee2(value);
+ if (current != null && (computed === undefined2 ? current === current && !isSymbol(current) : comparator(current, computed))) {
+ var computed = current, result2 = value;
+ }
+ }
+ return result2;
+ }
+ function baseFill(array, value, start, end) {
+ var length = array.length;
+ start = toInteger(start);
+ if (start < 0) {
+ start = -start > length ? 0 : length + start;
+ }
+ end = end === undefined2 || end > length ? length : toInteger(end);
+ if (end < 0) {
+ end += length;
+ }
+ end = start > end ? 0 : toLength(end);
+ while (start < end) {
+ array[start++] = value;
+ }
+ return array;
+ }
+ function baseFilter(collection, predicate) {
+ var result2 = [];
+ baseEach(collection, function(value, index, collection2) {
+ if (predicate(value, index, collection2)) {
+ result2.push(value);
+ }
+ });
+ return result2;
+ }
+ function baseFlatten(array, depth, predicate, isStrict, result2) {
+ var index = -1, length = array.length;
+ predicate || (predicate = isFlattenable);
+ result2 || (result2 = []);
+ while (++index < length) {
+ var value = array[index];
+ if (depth > 0 && predicate(value)) {
+ if (depth > 1) {
+ baseFlatten(value, depth - 1, predicate, isStrict, result2);
+ } else {
+ arrayPush(result2, value);
+ }
+ } else if (!isStrict) {
+ result2[result2.length] = value;
+ }
+ }
+ return result2;
+ }
+ var baseFor = createBaseFor();
+ var baseForRight = createBaseFor(true);
+ function baseForOwn(object, iteratee2) {
+ return object && baseFor(object, iteratee2, keys);
+ }
+ function baseForOwnRight(object, iteratee2) {
+ return object && baseForRight(object, iteratee2, keys);
+ }
+ function baseFunctions(object, props) {
+ return arrayFilter(props, function(key) {
+ return isFunction(object[key]);
+ });
+ }
+ function baseGet(object, path) {
+ path = castPath(path, object);
+ var index = 0, length = path.length;
+ while (object != null && index < length) {
+ object = object[toKey(path[index++])];
+ }
+ return index && index == length ? object : undefined2;
+ }
+ function baseGetAllKeys(object, keysFunc, symbolsFunc) {
+ var result2 = keysFunc(object);
+ return isArray(object) ? result2 : arrayPush(result2, symbolsFunc(object));
+ }
+ function baseGetTag(value) {
+ if (value == null) {
+ return value === undefined2 ? undefinedTag : nullTag;
+ }
+ return symToStringTag && symToStringTag in Object2(value) ? getRawTag(value) : objectToString(value);
+ }
+ function baseGt(value, other) {
+ return value > other;
+ }
+ function baseHas(object, key) {
+ return object != null && hasOwnProperty.call(object, key);
+ }
+ function baseHasIn(object, key) {
+ return object != null && key in Object2(object);
+ }
+ function baseInRange(number, start, end) {
+ return number >= nativeMin(start, end) && number < nativeMax(start, end);
+ }
+ function baseIntersection(arrays, iteratee2, comparator) {
+ var includes2 = comparator ? arrayIncludesWith : arrayIncludes, length = arrays[0].length, othLength = arrays.length, othIndex = othLength, caches = Array2(othLength), maxLength = Infinity, result2 = [];
+ while (othIndex--) {
+ var array = arrays[othIndex];
+ if (othIndex && iteratee2) {
+ array = arrayMap(array, baseUnary(iteratee2));
+ }
+ maxLength = nativeMin(array.length, maxLength);
+ caches[othIndex] = !comparator && (iteratee2 || length >= 120 && array.length >= 120) ? new SetCache(othIndex && array) : undefined2;
+ }
+ array = arrays[0];
+ var index = -1, seen = caches[0];
+ outer:
+ while (++index < length && result2.length < maxLength) {
+ var value = array[index], computed = iteratee2 ? iteratee2(value) : value;
+ value = comparator || value !== 0 ? value : 0;
+ if (!(seen ? cacheHas(seen, computed) : includes2(result2, computed, comparator))) {
+ othIndex = othLength;
+ while (--othIndex) {
+ var cache2 = caches[othIndex];
+ if (!(cache2 ? cacheHas(cache2, computed) : includes2(arrays[othIndex], computed, comparator))) {
+ continue outer;
+ }
+ }
+ if (seen) {
+ seen.push(computed);
+ }
+ result2.push(value);
+ }
+ }
+ return result2;
+ }
+ function baseInverter(object, setter, iteratee2, accumulator) {
+ baseForOwn(object, function(value, key, object2) {
+ setter(accumulator, iteratee2(value), key, object2);
+ });
+ return accumulator;
+ }
+ function baseInvoke(object, path, args) {
+ path = castPath(path, object);
+ object = parent(object, path);
+ var func = object == null ? object : object[toKey(last(path))];
+ return func == null ? undefined2 : apply(func, object, args);
+ }
+ function baseIsArguments(value) {
+ return isObjectLike(value) && baseGetTag(value) == argsTag;
+ }
+ function baseIsArrayBuffer(value) {
+ return isObjectLike(value) && baseGetTag(value) == arrayBufferTag;
+ }
+ function baseIsDate(value) {
+ return isObjectLike(value) && baseGetTag(value) == dateTag;
+ }
+ function baseIsEqual(value, other, bitmask, customizer, stack) {
+ if (value === other) {
+ return true;
+ }
+ if (value == null || other == null || !isObjectLike(value) && !isObjectLike(other)) {
+ return value !== value && other !== other;
+ }
+ return baseIsEqualDeep(value, other, bitmask, customizer, baseIsEqual, stack);
+ }
+ function baseIsEqualDeep(object, other, bitmask, customizer, equalFunc, stack) {
+ var objIsArr = isArray(object), othIsArr = isArray(other), objTag = objIsArr ? arrayTag : getTag(object), othTag = othIsArr ? arrayTag : getTag(other);
+ objTag = objTag == argsTag ? objectTag : objTag;
+ othTag = othTag == argsTag ? objectTag : othTag;
+ var objIsObj = objTag == objectTag, othIsObj = othTag == objectTag, isSameTag = objTag == othTag;
+ if (isSameTag && isBuffer(object)) {
+ if (!isBuffer(other)) {
+ return false;
+ }
+ objIsArr = true;
+ objIsObj = false;
+ }
+ if (isSameTag && !objIsObj) {
+ stack || (stack = new Stack());
+ return objIsArr || isTypedArray(object) ? equalArrays(object, other, bitmask, customizer, equalFunc, stack) : equalByTag(object, other, objTag, bitmask, customizer, equalFunc, stack);
+ }
+ if (!(bitmask & COMPARE_PARTIAL_FLAG)) {
+ var objIsWrapped = objIsObj && hasOwnProperty.call(object, "__wrapped__"), othIsWrapped = othIsObj && hasOwnProperty.call(other, "__wrapped__");
+ if (objIsWrapped || othIsWrapped) {
+ var objUnwrapped = objIsWrapped ? object.value() : object, othUnwrapped = othIsWrapped ? other.value() : other;
+ stack || (stack = new Stack());
+ return equalFunc(objUnwrapped, othUnwrapped, bitmask, customizer, stack);
+ }
+ }
+ if (!isSameTag) {
+ return false;
+ }
+ stack || (stack = new Stack());
+ return equalObjects(object, other, bitmask, customizer, equalFunc, stack);
+ }
+ function baseIsMap(value) {
+ return isObjectLike(value) && getTag(value) == mapTag;
+ }
+ function baseIsMatch(object, source, matchData, customizer) {
+ var index = matchData.length, length = index, noCustomizer = !customizer;
+ if (object == null) {
+ return !length;
+ }
+ object = Object2(object);
+ while (index--) {
+ var data = matchData[index];
+ if (noCustomizer && data[2] ? data[1] !== object[data[0]] : !(data[0] in object)) {
+ return false;
+ }
+ }
+ while (++index < length) {
+ data = matchData[index];
+ var key = data[0], objValue = object[key], srcValue = data[1];
+ if (noCustomizer && data[2]) {
+ if (objValue === undefined2 && !(key in object)) {
+ return false;
+ }
+ } else {
+ var stack = new Stack();
+ if (customizer) {
+ var result2 = customizer(objValue, srcValue, key, object, source, stack);
+ }
+ if (!(result2 === undefined2 ? baseIsEqual(srcValue, objValue, COMPARE_PARTIAL_FLAG | COMPARE_UNORDERED_FLAG, customizer, stack) : result2)) {
+ return false;
+ }
+ }
+ }
+ return true;
+ }
+ function baseIsNative(value) {
+ if (!isObject(value) || isMasked(value)) {
+ return false;
+ }
+ var pattern = isFunction(value) ? reIsNative : reIsHostCtor;
+ return pattern.test(toSource(value));
+ }
+ function baseIsRegExp(value) {
+ return isObjectLike(value) && baseGetTag(value) == regexpTag;
+ }
+ function baseIsSet(value) {
+ return isObjectLike(value) && getTag(value) == setTag;
+ }
+ function baseIsTypedArray(value) {
+ return isObjectLike(value) && isLength(value.length) && !!typedArrayTags[baseGetTag(value)];
+ }
+ function baseIteratee(value) {
+ if (typeof value == "function") {
+ return value;
+ }
+ if (value == null) {
+ return identity;
+ }
+ if (typeof value == "object") {
+ return isArray(value) ? baseMatchesProperty(value[0], value[1]) : baseMatches(value);
+ }
+ return property(value);
+ }
+ function baseKeys(object) {
+ if (!isPrototype(object)) {
+ return nativeKeys(object);
+ }
+ var result2 = [];
+ for (var key in Object2(object)) {
+ if (hasOwnProperty.call(object, key) && key != "constructor") {
+ result2.push(key);
+ }
+ }
+ return result2;
+ }
+ function baseKeysIn(object) {
+ if (!isObject(object)) {
+ return nativeKeysIn(object);
+ }
+ var isProto = isPrototype(object), result2 = [];
+ for (var key in object) {
+ if (!(key == "constructor" && (isProto || !hasOwnProperty.call(object, key)))) {
+ result2.push(key);
+ }
+ }
+ return result2;
+ }
+ function baseLt(value, other) {
+ return value < other;
+ }
+ function baseMap(collection, iteratee2) {
+ var index = -1, result2 = isArrayLike(collection) ? Array2(collection.length) : [];
+ baseEach(collection, function(value, key, collection2) {
+ result2[++index] = iteratee2(value, key, collection2);
+ });
+ return result2;
+ }
+ function baseMatches(source) {
+ var matchData = getMatchData(source);
+ if (matchData.length == 1 && matchData[0][2]) {
+ return matchesStrictComparable(matchData[0][0], matchData[0][1]);
+ }
+ return function(object) {
+ return object === source || baseIsMatch(object, source, matchData);
+ };
+ }
+ function baseMatchesProperty(path, srcValue) {
+ if (isKey(path) && isStrictComparable(srcValue)) {
+ return matchesStrictComparable(toKey(path), srcValue);
+ }
+ return function(object) {
+ var objValue = get(object, path);
+ return objValue === undefined2 && objValue === srcValue ? hasIn(object, path) : baseIsEqual(srcValue, objValue, COMPARE_PARTIAL_FLAG | COMPARE_UNORDERED_FLAG);
+ };
+ }
+ function baseMerge(object, source, srcIndex, customizer, stack) {
+ if (object === source) {
+ return;
+ }
+ baseFor(source, function(srcValue, key) {
+ stack || (stack = new Stack());
+ if (isObject(srcValue)) {
+ baseMergeDeep(object, source, key, srcIndex, baseMerge, customizer, stack);
+ } else {
+ var newValue = customizer ? customizer(safeGet(object, key), srcValue, key + "", object, source, stack) : undefined2;
+ if (newValue === undefined2) {
+ newValue = srcValue;
+ }
+ assignMergeValue(object, key, newValue);
+ }
+ }, keysIn);
+ }
+ function baseMergeDeep(object, source, key, srcIndex, mergeFunc, customizer, stack) {
+ var objValue = safeGet(object, key), srcValue = safeGet(source, key), stacked = stack.get(srcValue);
+ if (stacked) {
+ assignMergeValue(object, key, stacked);
+ return;
+ }
+ var newValue = customizer ? customizer(objValue, srcValue, key + "", object, source, stack) : undefined2;
+ var isCommon = newValue === undefined2;
+ if (isCommon) {
+ var isArr = isArray(srcValue), isBuff = !isArr && isBuffer(srcValue), isTyped = !isArr && !isBuff && isTypedArray(srcValue);
+ newValue = srcValue;
+ if (isArr || isBuff || isTyped) {
+ if (isArray(objValue)) {
+ newValue = objValue;
+ } else if (isArrayLikeObject(objValue)) {
+ newValue = copyArray(objValue);
+ } else if (isBuff) {
+ isCommon = false;
+ newValue = cloneBuffer(srcValue, true);
+ } else if (isTyped) {
+ isCommon = false;
+ newValue = cloneTypedArray(srcValue, true);
+ } else {
+ newValue = [];
+ }
+ } else if (isPlainObject(srcValue) || isArguments(srcValue)) {
+ newValue = objValue;
+ if (isArguments(objValue)) {
+ newValue = toPlainObject(objValue);
+ } else if (!isObject(objValue) || isFunction(objValue)) {
+ newValue = initCloneObject(srcValue);
+ }
+ } else {
+ isCommon = false;
+ }
+ }
+ if (isCommon) {
+ stack.set(srcValue, newValue);
+ mergeFunc(newValue, srcValue, srcIndex, customizer, stack);
+ stack["delete"](srcValue);
+ }
+ assignMergeValue(object, key, newValue);
+ }
+ function baseNth(array, n) {
+ var length = array.length;
+ if (!length) {
+ return;
+ }
+ n += n < 0 ? length : 0;
+ return isIndex(n, length) ? array[n] : undefined2;
+ }
+ function baseOrderBy(collection, iteratees, orders) {
+ if (iteratees.length) {
+ iteratees = arrayMap(iteratees, function(iteratee2) {
+ if (isArray(iteratee2)) {
+ return function(value) {
+ return baseGet(value, iteratee2.length === 1 ? iteratee2[0] : iteratee2);
+ };
+ }
+ return iteratee2;
+ });
+ } else {
+ iteratees = [identity];
+ }
+ var index = -1;
+ iteratees = arrayMap(iteratees, baseUnary(getIteratee()));
+ var result2 = baseMap(collection, function(value, key, collection2) {
+ var criteria = arrayMap(iteratees, function(iteratee2) {
+ return iteratee2(value);
+ });
+ return { "criteria": criteria, "index": ++index, "value": value };
+ });
+ return baseSortBy(result2, function(object, other) {
+ return compareMultiple(object, other, orders);
+ });
+ }
+ function basePick(object, paths) {
+ return basePickBy(object, paths, function(value, path) {
+ return hasIn(object, path);
+ });
+ }
+ function basePickBy(object, paths, predicate) {
+ var index = -1, length = paths.length, result2 = {};
+ while (++index < length) {
+ var path = paths[index], value = baseGet(object, path);
+ if (predicate(value, path)) {
+ baseSet(result2, castPath(path, object), value);
+ }
+ }
+ return result2;
+ }
+ function basePropertyDeep(path) {
+ return function(object) {
+ return baseGet(object, path);
+ };
+ }
+ function basePullAll(array, values2, iteratee2, comparator) {
+ var indexOf2 = comparator ? baseIndexOfWith : baseIndexOf, index = -1, length = values2.length, seen = array;
+ if (array === values2) {
+ values2 = copyArray(values2);
+ }
+ if (iteratee2) {
+ seen = arrayMap(array, baseUnary(iteratee2));
+ }
+ while (++index < length) {
+ var fromIndex = 0, value = values2[index], computed = iteratee2 ? iteratee2(value) : value;
+ while ((fromIndex = indexOf2(seen, computed, fromIndex, comparator)) > -1) {
+ if (seen !== array) {
+ splice.call(seen, fromIndex, 1);
+ }
+ splice.call(array, fromIndex, 1);
+ }
+ }
+ return array;
+ }
+ function basePullAt(array, indexes) {
+ var length = array ? indexes.length : 0, lastIndex = length - 1;
+ while (length--) {
+ var index = indexes[length];
+ if (length == lastIndex || index !== previous) {
+ var previous = index;
+ if (isIndex(index)) {
+ splice.call(array, index, 1);
+ } else {
+ baseUnset(array, index);
+ }
+ }
+ }
+ return array;
+ }
+ function baseRandom(lower, upper) {
+ return lower + nativeFloor(nativeRandom() * (upper - lower + 1));
+ }
+ function baseRange(start, end, step, fromRight) {
+ var index = -1, length = nativeMax(nativeCeil((end - start) / (step || 1)), 0), result2 = Array2(length);
+ while (length--) {
+ result2[fromRight ? length : ++index] = start;
+ start += step;
+ }
+ return result2;
+ }
+ function baseRepeat(string, n) {
+ var result2 = "";
+ if (!string || n < 1 || n > MAX_SAFE_INTEGER) {
+ return result2;
+ }
+ do {
+ if (n % 2) {
+ result2 += string;
+ }
+ n = nativeFloor(n / 2);
+ if (n) {
+ string += string;
+ }
+ } while (n);
+ return result2;
+ }
+ function baseRest(func, start) {
+ return setToString(overRest(func, start, identity), func + "");
+ }
+ function baseSample(collection) {
+ return arraySample(values(collection));
+ }
+ function baseSampleSize(collection, n) {
+ var array = values(collection);
+ return shuffleSelf(array, baseClamp(n, 0, array.length));
+ }
+ function baseSet(object, path, value, customizer) {
+ if (!isObject(object)) {
+ return object;
+ }
+ path = castPath(path, object);
+ var index = -1, length = path.length, lastIndex = length - 1, nested = object;
+ while (nested != null && ++index < length) {
+ var key = toKey(path[index]), newValue = value;
+ if (key === "__proto__" || key === "constructor" || key === "prototype") {
+ return object;
+ }
+ if (index != lastIndex) {
+ var objValue = nested[key];
+ newValue = customizer ? customizer(objValue, key, nested) : undefined2;
+ if (newValue === undefined2) {
+ newValue = isObject(objValue) ? objValue : isIndex(path[index + 1]) ? [] : {};
+ }
+ }
+ assignValue(nested, key, newValue);
+ nested = nested[key];
+ }
+ return object;
+ }
+ var baseSetData = !metaMap ? identity : function(func, data) {
+ metaMap.set(func, data);
+ return func;
+ };
+ var baseSetToString = !defineProperty ? identity : function(func, string) {
+ return defineProperty(func, "toString", {
+ "configurable": true,
+ "enumerable": false,
+ "value": constant(string),
+ "writable": true
+ });
+ };
+ function baseShuffle(collection) {
+ return shuffleSelf(values(collection));
+ }
+ function baseSlice(array, start, end) {
+ var index = -1, length = array.length;
+ if (start < 0) {
+ start = -start > length ? 0 : length + start;
+ }
+ end = end > length ? length : end;
+ if (end < 0) {
+ end += length;
+ }
+ length = start > end ? 0 : end - start >>> 0;
+ start >>>= 0;
+ var result2 = Array2(length);
+ while (++index < length) {
+ result2[index] = array[index + start];
+ }
+ return result2;
+ }
+ function baseSome(collection, predicate) {
+ var result2;
+ baseEach(collection, function(value, index, collection2) {
+ result2 = predicate(value, index, collection2);
+ return !result2;
+ });
+ return !!result2;
+ }
+ function baseSortedIndex(array, value, retHighest) {
+ var low = 0, high = array == null ? low : array.length;
+ if (typeof value == "number" && value === value && high <= HALF_MAX_ARRAY_LENGTH) {
+ while (low < high) {
+ var mid = low + high >>> 1, computed = array[mid];
+ if (computed !== null && !isSymbol(computed) && (retHighest ? computed <= value : computed < value)) {
+ low = mid + 1;
+ } else {
+ high = mid;
+ }
+ }
+ return high;
+ }
+ return baseSortedIndexBy(array, value, identity, retHighest);
+ }
+ function baseSortedIndexBy(array, value, iteratee2, retHighest) {
+ var low = 0, high = array == null ? 0 : array.length;
+ if (high === 0) {
+ return 0;
+ }
+ value = iteratee2(value);
+ var valIsNaN = value !== value, valIsNull = value === null, valIsSymbol = isSymbol(value), valIsUndefined = value === undefined2;
+ while (low < high) {
+ var mid = nativeFloor((low + high) / 2), computed = iteratee2(array[mid]), othIsDefined = computed !== undefined2, othIsNull = computed === null, othIsReflexive = computed === computed, othIsSymbol = isSymbol(computed);
+ if (valIsNaN) {
+ var setLow = retHighest || othIsReflexive;
+ } else if (valIsUndefined) {
+ setLow = othIsReflexive && (retHighest || othIsDefined);
+ } else if (valIsNull) {
+ setLow = othIsReflexive && othIsDefined && (retHighest || !othIsNull);
+ } else if (valIsSymbol) {
+ setLow = othIsReflexive && othIsDefined && !othIsNull && (retHighest || !othIsSymbol);
+ } else if (othIsNull || othIsSymbol) {
+ setLow = false;
+ } else {
+ setLow = retHighest ? computed <= value : computed < value;
+ }
+ if (setLow) {
+ low = mid + 1;
+ } else {
+ high = mid;
+ }
+ }
+ return nativeMin(high, MAX_ARRAY_INDEX);
+ }
+ function baseSortedUniq(array, iteratee2) {
+ var index = -1, length = array.length, resIndex = 0, result2 = [];
+ while (++index < length) {
+ var value = array[index], computed = iteratee2 ? iteratee2(value) : value;
+ if (!index || !eq(computed, seen)) {
+ var seen = computed;
+ result2[resIndex++] = value === 0 ? 0 : value;
+ }
+ }
+ return result2;
+ }
+ function baseToNumber(value) {
+ if (typeof value == "number") {
+ return value;
+ }
+ if (isSymbol(value)) {
+ return NAN;
+ }
+ return +value;
+ }
+ function baseToString(value) {
+ if (typeof value == "string") {
+ return value;
+ }
+ if (isArray(value)) {
+ return arrayMap(value, baseToString) + "";
+ }
+ if (isSymbol(value)) {
+ return symbolToString ? symbolToString.call(value) : "";
+ }
+ var result2 = value + "";
+ return result2 == "0" && 1 / value == -INFINITY ? "-0" : result2;
+ }
+ function baseUniq(array, iteratee2, comparator) {
+ var index = -1, includes2 = arrayIncludes, length = array.length, isCommon = true, result2 = [], seen = result2;
+ if (comparator) {
+ isCommon = false;
+ includes2 = arrayIncludesWith;
+ } else if (length >= LARGE_ARRAY_SIZE) {
+ var set3 = iteratee2 ? null : createSet(array);
+ if (set3) {
+ return setToArray(set3);
+ }
+ isCommon = false;
+ includes2 = cacheHas;
+ seen = new SetCache();
+ } else {
+ seen = iteratee2 ? [] : result2;
+ }
+ outer:
+ while (++index < length) {
+ var value = array[index], computed = iteratee2 ? iteratee2(value) : value;
+ value = comparator || value !== 0 ? value : 0;
+ if (isCommon && computed === computed) {
+ var seenIndex = seen.length;
+ while (seenIndex--) {
+ if (seen[seenIndex] === computed) {
+ continue outer;
+ }
+ }
+ if (iteratee2) {
+ seen.push(computed);
+ }
+ result2.push(value);
+ } else if (!includes2(seen, computed, comparator)) {
+ if (seen !== result2) {
+ seen.push(computed);
+ }
+ result2.push(value);
+ }
+ }
+ return result2;
+ }
+ function baseUnset(object, path) {
+ path = castPath(path, object);
+ object = parent(object, path);
+ return object == null || delete object[toKey(last(path))];
+ }
+ function baseUpdate(object, path, updater, customizer) {
+ return baseSet(object, path, updater(baseGet(object, path)), customizer);
+ }
+ function baseWhile(array, predicate, isDrop, fromRight) {
+ var length = array.length, index = fromRight ? length : -1;
+ while ((fromRight ? index-- : ++index < length) && predicate(array[index], index, array)) {
+ }
+ return isDrop ? baseSlice(array, fromRight ? 0 : index, fromRight ? index + 1 : length) : baseSlice(array, fromRight ? index + 1 : 0, fromRight ? length : index);
+ }
+ function baseWrapperValue(value, actions) {
+ var result2 = value;
+ if (result2 instanceof LazyWrapper) {
+ result2 = result2.value();
+ }
+ return arrayReduce(actions, function(result3, action) {
+ return action.func.apply(action.thisArg, arrayPush([result3], action.args));
+ }, result2);
+ }
+ function baseXor(arrays, iteratee2, comparator) {
+ var length = arrays.length;
+ if (length < 2) {
+ return length ? baseUniq(arrays[0]) : [];
+ }
+ var index = -1, result2 = Array2(length);
+ while (++index < length) {
+ var array = arrays[index], othIndex = -1;
+ while (++othIndex < length) {
+ if (othIndex != index) {
+ result2[index] = baseDifference(result2[index] || array, arrays[othIndex], iteratee2, comparator);
+ }
+ }
+ }
+ return baseUniq(baseFlatten(result2, 1), iteratee2, comparator);
+ }
+ function baseZipObject(props, values2, assignFunc) {
+ var index = -1, length = props.length, valsLength = values2.length, result2 = {};
+ while (++index < length) {
+ var value = index < valsLength ? values2[index] : undefined2;
+ assignFunc(result2, props[index], value);
+ }
+ return result2;
+ }
+ function castArrayLikeObject(value) {
+ return isArrayLikeObject(value) ? value : [];
+ }
+ function castFunction(value) {
+ return typeof value == "function" ? value : identity;
+ }
+ function castPath(value, object) {
+ if (isArray(value)) {
+ return value;
+ }
+ return isKey(value, object) ? [value] : stringToPath(toString(value));
+ }
+ var castRest = baseRest;
+ function castSlice(array, start, end) {
+ var length = array.length;
+ end = end === undefined2 ? length : end;
+ return !start && end >= length ? array : baseSlice(array, start, end);
+ }
+ var clearTimeout2 = ctxClearTimeout || function(id) {
+ return root.clearTimeout(id);
+ };
+ function cloneBuffer(buffer, isDeep) {
+ if (isDeep) {
+ return buffer.slice();
+ }
+ var length = buffer.length, result2 = allocUnsafe ? allocUnsafe(length) : new buffer.constructor(length);
+ buffer.copy(result2);
+ return result2;
+ }
+ function cloneArrayBuffer(arrayBuffer) {
+ var result2 = new arrayBuffer.constructor(arrayBuffer.byteLength);
+ new Uint8Array2(result2).set(new Uint8Array2(arrayBuffer));
+ return result2;
+ }
+ function cloneDataView(dataView, isDeep) {
+ var buffer = isDeep ? cloneArrayBuffer(dataView.buffer) : dataView.buffer;
+ return new dataView.constructor(buffer, dataView.byteOffset, dataView.byteLength);
+ }
+ function cloneRegExp(regexp) {
+ var result2 = new regexp.constructor(regexp.source, reFlags.exec(regexp));
+ result2.lastIndex = regexp.lastIndex;
+ return result2;
+ }
+ function cloneSymbol(symbol) {
+ return symbolValueOf ? Object2(symbolValueOf.call(symbol)) : {};
+ }
+ function cloneTypedArray(typedArray, isDeep) {
+ var buffer = isDeep ? cloneArrayBuffer(typedArray.buffer) : typedArray.buffer;
+ return new typedArray.constructor(buffer, typedArray.byteOffset, typedArray.length);
+ }
+ function compareAscending(value, other) {
+ if (value !== other) {
+ var valIsDefined = value !== undefined2, valIsNull = value === null, valIsReflexive = value === value, valIsSymbol = isSymbol(value);
+ var othIsDefined = other !== undefined2, othIsNull = other === null, othIsReflexive = other === other, othIsSymbol = isSymbol(other);
+ if (!othIsNull && !othIsSymbol && !valIsSymbol && value > other || valIsSymbol && othIsDefined && othIsReflexive && !othIsNull && !othIsSymbol || valIsNull && othIsDefined && othIsReflexive || !valIsDefined && othIsReflexive || !valIsReflexive) {
+ return 1;
+ }
+ if (!valIsNull && !valIsSymbol && !othIsSymbol && value < other || othIsSymbol && valIsDefined && valIsReflexive && !valIsNull && !valIsSymbol || othIsNull && valIsDefined && valIsReflexive || !othIsDefined && valIsReflexive || !othIsReflexive) {
+ return -1;
+ }
+ }
+ return 0;
+ }
+ function compareMultiple(object, other, orders) {
+ var index = -1, objCriteria = object.criteria, othCriteria = other.criteria, length = objCriteria.length, ordersLength = orders.length;
+ while (++index < length) {
+ var result2 = compareAscending(objCriteria[index], othCriteria[index]);
+ if (result2) {
+ if (index >= ordersLength) {
+ return result2;
+ }
+ var order = orders[index];
+ return result2 * (order == "desc" ? -1 : 1);
+ }
+ }
+ return object.index - other.index;
+ }
+ function composeArgs(args, partials, holders, isCurried) {
+ var argsIndex = -1, argsLength = args.length, holdersLength = holders.length, leftIndex = -1, leftLength = partials.length, rangeLength = nativeMax(argsLength - holdersLength, 0), result2 = Array2(leftLength + rangeLength), isUncurried = !isCurried;
+ while (++leftIndex < leftLength) {
+ result2[leftIndex] = partials[leftIndex];
+ }
+ while (++argsIndex < holdersLength) {
+ if (isUncurried || argsIndex < argsLength) {
+ result2[holders[argsIndex]] = args[argsIndex];
+ }
+ }
+ while (rangeLength--) {
+ result2[leftIndex++] = args[argsIndex++];
+ }
+ return result2;
+ }
+ function composeArgsRight(args, partials, holders, isCurried) {
+ var argsIndex = -1, argsLength = args.length, holdersIndex = -1, holdersLength = holders.length, rightIndex = -1, rightLength = partials.length, rangeLength = nativeMax(argsLength - holdersLength, 0), result2 = Array2(rangeLength + rightLength), isUncurried = !isCurried;
+ while (++argsIndex < rangeLength) {
+ result2[argsIndex] = args[argsIndex];
+ }
+ var offset = argsIndex;
+ while (++rightIndex < rightLength) {
+ result2[offset + rightIndex] = partials[rightIndex];
+ }
+ while (++holdersIndex < holdersLength) {
+ if (isUncurried || argsIndex < argsLength) {
+ result2[offset + holders[holdersIndex]] = args[argsIndex++];
+ }
+ }
+ return result2;
+ }
+ function copyArray(source, array) {
+ var index = -1, length = source.length;
+ array || (array = Array2(length));
+ while (++index < length) {
+ array[index] = source[index];
+ }
+ return array;
+ }
+ function copyObject(source, props, object, customizer) {
+ var isNew = !object;
+ object || (object = {});
+ var index = -1, length = props.length;
+ while (++index < length) {
+ var key = props[index];
+ var newValue = customizer ? customizer(object[key], source[key], key, object, source) : undefined2;
+ if (newValue === undefined2) {
+ newValue = source[key];
+ }
+ if (isNew) {
+ baseAssignValue(object, key, newValue);
+ } else {
+ assignValue(object, key, newValue);
+ }
+ }
+ return object;
+ }
+ function copySymbols(source, object) {
+ return copyObject(source, getSymbols(source), object);
+ }
+ function copySymbolsIn(source, object) {
+ return copyObject(source, getSymbolsIn(source), object);
+ }
+ function createAggregator(setter, initializer) {
+ return function(collection, iteratee2) {
+ var func = isArray(collection) ? arrayAggregator : baseAggregator, accumulator = initializer ? initializer() : {};
+ return func(collection, setter, getIteratee(iteratee2, 2), accumulator);
+ };
+ }
+ function createAssigner(assigner) {
+ return baseRest(function(object, sources) {
+ var index = -1, length = sources.length, customizer = length > 1 ? sources[length - 1] : undefined2, guard = length > 2 ? sources[2] : undefined2;
+ customizer = assigner.length > 3 && typeof customizer == "function" ? (length--, customizer) : undefined2;
+ if (guard && isIterateeCall(sources[0], sources[1], guard)) {
+ customizer = length < 3 ? undefined2 : customizer;
+ length = 1;
+ }
+ object = Object2(object);
+ while (++index < length) {
+ var source = sources[index];
+ if (source) {
+ assigner(object, source, index, customizer);
+ }
+ }
+ return object;
+ });
+ }
+ function createBaseEach(eachFunc, fromRight) {
+ return function(collection, iteratee2) {
+ if (collection == null) {
+ return collection;
+ }
+ if (!isArrayLike(collection)) {
+ return eachFunc(collection, iteratee2);
+ }
+ var length = collection.length, index = fromRight ? length : -1, iterable = Object2(collection);
+ while (fromRight ? index-- : ++index < length) {
+ if (iteratee2(iterable[index], index, iterable) === false) {
+ break;
+ }
+ }
+ return collection;
+ };
+ }
+ function createBaseFor(fromRight) {
+ return function(object, iteratee2, keysFunc) {
+ var index = -1, iterable = Object2(object), props = keysFunc(object), length = props.length;
+ while (length--) {
+ var key = props[fromRight ? length : ++index];
+ if (iteratee2(iterable[key], key, iterable) === false) {
+ break;
+ }
+ }
+ return object;
+ };
+ }
+ function createBind(func, bitmask, thisArg) {
+ var isBind = bitmask & WRAP_BIND_FLAG, Ctor = createCtor(func);
+ function wrapper() {
+ var fn = this && this !== root && this instanceof wrapper ? Ctor : func;
+ return fn.apply(isBind ? thisArg : this, arguments);
+ }
+ return wrapper;
+ }
+ function createCaseFirst(methodName) {
+ return function(string) {
+ string = toString(string);
+ var strSymbols = hasUnicode(string) ? stringToArray(string) : undefined2;
+ var chr = strSymbols ? strSymbols[0] : string.charAt(0);
+ var trailing = strSymbols ? castSlice(strSymbols, 1).join("") : string.slice(1);
+ return chr[methodName]() + trailing;
+ };
+ }
+ function createCompounder(callback) {
+ return function(string) {
+ return arrayReduce(words(deburr(string).replace(reApos, "")), callback, "");
+ };
+ }
+ function createCtor(Ctor) {
+ return function() {
+ var args = arguments;
+ switch (args.length) {
+ case 0:
+ return new Ctor();
+ case 1:
+ return new Ctor(args[0]);
+ case 2:
+ return new Ctor(args[0], args[1]);
+ case 3:
+ return new Ctor(args[0], args[1], args[2]);
+ case 4:
+ return new Ctor(args[0], args[1], args[2], args[3]);
+ case 5:
+ return new Ctor(args[0], args[1], args[2], args[3], args[4]);
+ case 6:
+ return new Ctor(args[0], args[1], args[2], args[3], args[4], args[5]);
+ case 7:
+ return new Ctor(args[0], args[1], args[2], args[3], args[4], args[5], args[6]);
+ }
+ var thisBinding = baseCreate(Ctor.prototype), result2 = Ctor.apply(thisBinding, args);
+ return isObject(result2) ? result2 : thisBinding;
+ };
+ }
+ function createCurry(func, bitmask, arity) {
+ var Ctor = createCtor(func);
+ function wrapper() {
+ var length = arguments.length, args = Array2(length), index = length, placeholder = getHolder(wrapper);
+ while (index--) {
+ args[index] = arguments[index];
+ }
+ var holders = length < 3 && args[0] !== placeholder && args[length - 1] !== placeholder ? [] : replaceHolders(args, placeholder);
+ length -= holders.length;
+ if (length < arity) {
+ return createRecurry(
+ func,
+ bitmask,
+ createHybrid,
+ wrapper.placeholder,
+ undefined2,
+ args,
+ holders,
+ undefined2,
+ undefined2,
+ arity - length
+ );
+ }
+ var fn = this && this !== root && this instanceof wrapper ? Ctor : func;
+ return apply(fn, this, args);
+ }
+ return wrapper;
+ }
+ function createFind(findIndexFunc) {
+ return function(collection, predicate, fromIndex) {
+ var iterable = Object2(collection);
+ if (!isArrayLike(collection)) {
+ var iteratee2 = getIteratee(predicate, 3);
+ collection = keys(collection);
+ predicate = function(key) {
+ return iteratee2(iterable[key], key, iterable);
+ };
+ }
+ var index = findIndexFunc(collection, predicate, fromIndex);
+ return index > -1 ? iterable[iteratee2 ? collection[index] : index] : undefined2;
+ };
+ }
+ function createFlow(fromRight) {
+ return flatRest(function(funcs) {
+ var length = funcs.length, index = length, prereq = LodashWrapper.prototype.thru;
+ if (fromRight) {
+ funcs.reverse();
+ }
+ while (index--) {
+ var func = funcs[index];
+ if (typeof func != "function") {
+ throw new TypeError2(FUNC_ERROR_TEXT);
+ }
+ if (prereq && !wrapper && getFuncName(func) == "wrapper") {
+ var wrapper = new LodashWrapper([], true);
+ }
+ }
+ index = wrapper ? index : length;
+ while (++index < length) {
+ func = funcs[index];
+ var funcName = getFuncName(func), data = funcName == "wrapper" ? getData(func) : undefined2;
+ if (data && isLaziable(data[0]) && data[1] == (WRAP_ARY_FLAG | WRAP_CURRY_FLAG | WRAP_PARTIAL_FLAG | WRAP_REARG_FLAG) && !data[4].length && data[9] == 1) {
+ wrapper = wrapper[getFuncName(data[0])].apply(wrapper, data[3]);
+ } else {
+ wrapper = func.length == 1 && isLaziable(func) ? wrapper[funcName]() : wrapper.thru(func);
+ }
+ }
+ return function() {
+ var args = arguments, value = args[0];
+ if (wrapper && args.length == 1 && isArray(value)) {
+ return wrapper.plant(value).value();
+ }
+ var index2 = 0, result2 = length ? funcs[index2].apply(this, args) : value;
+ while (++index2 < length) {
+ result2 = funcs[index2].call(this, result2);
+ }
+ return result2;
+ };
+ });
+ }
+ function createHybrid(func, bitmask, thisArg, partials, holders, partialsRight, holdersRight, argPos, ary2, arity) {
+ var isAry = bitmask & WRAP_ARY_FLAG, isBind = bitmask & WRAP_BIND_FLAG, isBindKey = bitmask & WRAP_BIND_KEY_FLAG, isCurried = bitmask & (WRAP_CURRY_FLAG | WRAP_CURRY_RIGHT_FLAG), isFlip = bitmask & WRAP_FLIP_FLAG, Ctor = isBindKey ? undefined2 : createCtor(func);
+ function wrapper() {
+ var length = arguments.length, args = Array2(length), index = length;
+ while (index--) {
+ args[index] = arguments[index];
+ }
+ if (isCurried) {
+ var placeholder = getHolder(wrapper), holdersCount = countHolders(args, placeholder);
+ }
+ if (partials) {
+ args = composeArgs(args, partials, holders, isCurried);
+ }
+ if (partialsRight) {
+ args = composeArgsRight(args, partialsRight, holdersRight, isCurried);
+ }
+ length -= holdersCount;
+ if (isCurried && length < arity) {
+ var newHolders = replaceHolders(args, placeholder);
+ return createRecurry(
+ func,
+ bitmask,
+ createHybrid,
+ wrapper.placeholder,
+ thisArg,
+ args,
+ newHolders,
+ argPos,
+ ary2,
+ arity - length
+ );
+ }
+ var thisBinding = isBind ? thisArg : this, fn = isBindKey ? thisBinding[func] : func;
+ length = args.length;
+ if (argPos) {
+ args = reorder(args, argPos);
+ } else if (isFlip && length > 1) {
+ args.reverse();
+ }
+ if (isAry && ary2 < length) {
+ args.length = ary2;
+ }
+ if (this && this !== root && this instanceof wrapper) {
+ fn = Ctor || createCtor(fn);
+ }
+ return fn.apply(thisBinding, args);
+ }
+ return wrapper;
+ }
+ function createInverter(setter, toIteratee) {
+ return function(object, iteratee2) {
+ return baseInverter(object, setter, toIteratee(iteratee2), {});
+ };
+ }
+ function createMathOperation(operator, defaultValue) {
+ return function(value, other) {
+ var result2;
+ if (value === undefined2 && other === undefined2) {
+ return defaultValue;
+ }
+ if (value !== undefined2) {
+ result2 = value;
+ }
+ if (other !== undefined2) {
+ if (result2 === undefined2) {
+ return other;
+ }
+ if (typeof value == "string" || typeof other == "string") {
+ value = baseToString(value);
+ other = baseToString(other);
+ } else {
+ value = baseToNumber(value);
+ other = baseToNumber(other);
+ }
+ result2 = operator(value, other);
+ }
+ return result2;
+ };
+ }
+ function createOver(arrayFunc) {
+ return flatRest(function(iteratees) {
+ iteratees = arrayMap(iteratees, baseUnary(getIteratee()));
+ return baseRest(function(args) {
+ var thisArg = this;
+ return arrayFunc(iteratees, function(iteratee2) {
+ return apply(iteratee2, thisArg, args);
+ });
+ });
+ });
+ }
+ function createPadding(length, chars) {
+ chars = chars === undefined2 ? " " : baseToString(chars);
+ var charsLength = chars.length;
+ if (charsLength < 2) {
+ return charsLength ? baseRepeat(chars, length) : chars;
+ }
+ var result2 = baseRepeat(chars, nativeCeil(length / stringSize(chars)));
+ return hasUnicode(chars) ? castSlice(stringToArray(result2), 0, length).join("") : result2.slice(0, length);
+ }
+ function createPartial(func, bitmask, thisArg, partials) {
+ var isBind = bitmask & WRAP_BIND_FLAG, Ctor = createCtor(func);
+ function wrapper() {
+ var argsIndex = -1, argsLength = arguments.length, leftIndex = -1, leftLength = partials.length, args = Array2(leftLength + argsLength), fn = this && this !== root && this instanceof wrapper ? Ctor : func;
+ while (++leftIndex < leftLength) {
+ args[leftIndex] = partials[leftIndex];
+ }
+ while (argsLength--) {
+ args[leftIndex++] = arguments[++argsIndex];
+ }
+ return apply(fn, isBind ? thisArg : this, args);
+ }
+ return wrapper;
+ }
+ function createRange(fromRight) {
+ return function(start, end, step) {
+ if (step && typeof step != "number" && isIterateeCall(start, end, step)) {
+ end = step = undefined2;
+ }
+ start = toFinite(start);
+ if (end === undefined2) {
+ end = start;
+ start = 0;
+ } else {
+ end = toFinite(end);
+ }
+ step = step === undefined2 ? start < end ? 1 : -1 : toFinite(step);
+ return baseRange(start, end, step, fromRight);
+ };
+ }
+ function createRelationalOperation(operator) {
+ return function(value, other) {
+ if (!(typeof value == "string" && typeof other == "string")) {
+ value = toNumber(value);
+ other = toNumber(other);
+ }
+ return operator(value, other);
+ };
+ }
+ function createRecurry(func, bitmask, wrapFunc, placeholder, thisArg, partials, holders, argPos, ary2, arity) {
+ var isCurry = bitmask & WRAP_CURRY_FLAG, newHolders = isCurry ? holders : undefined2, newHoldersRight = isCurry ? undefined2 : holders, newPartials = isCurry ? partials : undefined2, newPartialsRight = isCurry ? undefined2 : partials;
+ bitmask |= isCurry ? WRAP_PARTIAL_FLAG : WRAP_PARTIAL_RIGHT_FLAG;
+ bitmask &= ~(isCurry ? WRAP_PARTIAL_RIGHT_FLAG : WRAP_PARTIAL_FLAG);
+ if (!(bitmask & WRAP_CURRY_BOUND_FLAG)) {
+ bitmask &= ~(WRAP_BIND_FLAG | WRAP_BIND_KEY_FLAG);
+ }
+ var newData = [
+ func,
+ bitmask,
+ thisArg,
+ newPartials,
+ newHolders,
+ newPartialsRight,
+ newHoldersRight,
+ argPos,
+ ary2,
+ arity
+ ];
+ var result2 = wrapFunc.apply(undefined2, newData);
+ if (isLaziable(func)) {
+ setData(result2, newData);
+ }
+ result2.placeholder = placeholder;
+ return setWrapToString(result2, func, bitmask);
+ }
+ function createRound(methodName) {
+ var func = Math2[methodName];
+ return function(number, precision) {
+ number = toNumber(number);
+ precision = precision == null ? 0 : nativeMin(toInteger(precision), 292);
+ if (precision && nativeIsFinite(number)) {
+ var pair = (toString(number) + "e").split("e"), value = func(pair[0] + "e" + (+pair[1] + precision));
+ pair = (toString(value) + "e").split("e");
+ return +(pair[0] + "e" + (+pair[1] - precision));
+ }
+ return func(number);
+ };
+ }
+ var createSet = !(Set && 1 / setToArray(new Set([, -0]))[1] == INFINITY) ? noop : function(values2) {
+ return new Set(values2);
+ };
+ function createToPairs(keysFunc) {
+ return function(object) {
+ var tag = getTag(object);
+ if (tag == mapTag) {
+ return mapToArray(object);
+ }
+ if (tag == setTag) {
+ return setToPairs(object);
+ }
+ return baseToPairs(object, keysFunc(object));
+ };
+ }
+ function createWrap(func, bitmask, thisArg, partials, holders, argPos, ary2, arity) {
+ var isBindKey = bitmask & WRAP_BIND_KEY_FLAG;
+ if (!isBindKey && typeof func != "function") {
+ throw new TypeError2(FUNC_ERROR_TEXT);
+ }
+ var length = partials ? partials.length : 0;
+ if (!length) {
+ bitmask &= ~(WRAP_PARTIAL_FLAG | WRAP_PARTIAL_RIGHT_FLAG);
+ partials = holders = undefined2;
+ }
+ ary2 = ary2 === undefined2 ? ary2 : nativeMax(toInteger(ary2), 0);
+ arity = arity === undefined2 ? arity : toInteger(arity);
+ length -= holders ? holders.length : 0;
+ if (bitmask & WRAP_PARTIAL_RIGHT_FLAG) {
+ var partialsRight = partials, holdersRight = holders;
+ partials = holders = undefined2;
+ }
+ var data = isBindKey ? undefined2 : getData(func);
+ var newData = [
+ func,
+ bitmask,
+ thisArg,
+ partials,
+ holders,
+ partialsRight,
+ holdersRight,
+ argPos,
+ ary2,
+ arity
+ ];
+ if (data) {
+ mergeData(newData, data);
+ }
+ func = newData[0];
+ bitmask = newData[1];
+ thisArg = newData[2];
+ partials = newData[3];
+ holders = newData[4];
+ arity = newData[9] = newData[9] === undefined2 ? isBindKey ? 0 : func.length : nativeMax(newData[9] - length, 0);
+ if (!arity && bitmask & (WRAP_CURRY_FLAG | WRAP_CURRY_RIGHT_FLAG)) {
+ bitmask &= ~(WRAP_CURRY_FLAG | WRAP_CURRY_RIGHT_FLAG);
+ }
+ if (!bitmask || bitmask == WRAP_BIND_FLAG) {
+ var result2 = createBind(func, bitmask, thisArg);
+ } else if (bitmask == WRAP_CURRY_FLAG || bitmask == WRAP_CURRY_RIGHT_FLAG) {
+ result2 = createCurry(func, bitmask, arity);
+ } else if ((bitmask == WRAP_PARTIAL_FLAG || bitmask == (WRAP_BIND_FLAG | WRAP_PARTIAL_FLAG)) && !holders.length) {
+ result2 = createPartial(func, bitmask, thisArg, partials);
+ } else {
+ result2 = createHybrid.apply(undefined2, newData);
+ }
+ var setter = data ? baseSetData : setData;
+ return setWrapToString(setter(result2, newData), func, bitmask);
+ }
+ function customDefaultsAssignIn(objValue, srcValue, key, object) {
+ if (objValue === undefined2 || eq(objValue, objectProto[key]) && !hasOwnProperty.call(object, key)) {
+ return srcValue;
+ }
+ return objValue;
+ }
+ function customDefaultsMerge(objValue, srcValue, key, object, source, stack) {
+ if (isObject(objValue) && isObject(srcValue)) {
+ stack.set(srcValue, objValue);
+ baseMerge(objValue, srcValue, undefined2, customDefaultsMerge, stack);
+ stack["delete"](srcValue);
+ }
+ return objValue;
+ }
+ function customOmitClone(value) {
+ return isPlainObject(value) ? undefined2 : value;
+ }
+ function equalArrays(array, other, bitmask, customizer, equalFunc, stack) {
+ var isPartial = bitmask & COMPARE_PARTIAL_FLAG, arrLength = array.length, othLength = other.length;
+ if (arrLength != othLength && !(isPartial && othLength > arrLength)) {
+ return false;
+ }
+ var arrStacked = stack.get(array);
+ var othStacked = stack.get(other);
+ if (arrStacked && othStacked) {
+ return arrStacked == other && othStacked == array;
+ }
+ var index = -1, result2 = true, seen = bitmask & COMPARE_UNORDERED_FLAG ? new SetCache() : undefined2;
+ stack.set(array, other);
+ stack.set(other, array);
+ while (++index < arrLength) {
+ var arrValue = array[index], othValue = other[index];
+ if (customizer) {
+ var compared = isPartial ? customizer(othValue, arrValue, index, other, array, stack) : customizer(arrValue, othValue, index, array, other, stack);
+ }
+ if (compared !== undefined2) {
+ if (compared) {
+ continue;
+ }
+ result2 = false;
+ break;
+ }
+ if (seen) {
+ if (!arraySome(other, function(othValue2, othIndex) {
+ if (!cacheHas(seen, othIndex) && (arrValue === othValue2 || equalFunc(arrValue, othValue2, bitmask, customizer, stack))) {
+ return seen.push(othIndex);
+ }
+ })) {
+ result2 = false;
+ break;
+ }
+ } else if (!(arrValue === othValue || equalFunc(arrValue, othValue, bitmask, customizer, stack))) {
+ result2 = false;
+ break;
+ }
+ }
+ stack["delete"](array);
+ stack["delete"](other);
+ return result2;
+ }
+ function equalByTag(object, other, tag, bitmask, customizer, equalFunc, stack) {
+ switch (tag) {
+ case dataViewTag:
+ if (object.byteLength != other.byteLength || object.byteOffset != other.byteOffset) {
+ return false;
+ }
+ object = object.buffer;
+ other = other.buffer;
+ case arrayBufferTag:
+ if (object.byteLength != other.byteLength || !equalFunc(new Uint8Array2(object), new Uint8Array2(other))) {
+ return false;
+ }
+ return true;
+ case boolTag:
+ case dateTag:
+ case numberTag:
+ return eq(+object, +other);
+ case errorTag:
+ return object.name == other.name && object.message == other.message;
+ case regexpTag:
+ case stringTag:
+ return object == other + "";
+ case mapTag:
+ var convert = mapToArray;
+ case setTag:
+ var isPartial = bitmask & COMPARE_PARTIAL_FLAG;
+ convert || (convert = setToArray);
+ if (object.size != other.size && !isPartial) {
+ return false;
+ }
+ var stacked = stack.get(object);
+ if (stacked) {
+ return stacked == other;
+ }
+ bitmask |= COMPARE_UNORDERED_FLAG;
+ stack.set(object, other);
+ var result2 = equalArrays(convert(object), convert(other), bitmask, customizer, equalFunc, stack);
+ stack["delete"](object);
+ return result2;
+ case symbolTag:
+ if (symbolValueOf) {
+ return symbolValueOf.call(object) == symbolValueOf.call(other);
+ }
+ }
+ return false;
+ }
+ function equalObjects(object, other, bitmask, customizer, equalFunc, stack) {
+ var isPartial = bitmask & COMPARE_PARTIAL_FLAG, objProps = getAllKeys(object), objLength = objProps.length, othProps = getAllKeys(other), othLength = othProps.length;
+ if (objLength != othLength && !isPartial) {
+ return false;
+ }
+ var index = objLength;
+ while (index--) {
+ var key = objProps[index];
+ if (!(isPartial ? key in other : hasOwnProperty.call(other, key))) {
+ return false;
+ }
+ }
+ var objStacked = stack.get(object);
+ var othStacked = stack.get(other);
+ if (objStacked && othStacked) {
+ return objStacked == other && othStacked == object;
+ }
+ var result2 = true;
+ stack.set(object, other);
+ stack.set(other, object);
+ var skipCtor = isPartial;
+ while (++index < objLength) {
+ key = objProps[index];
+ var objValue = object[key], othValue = other[key];
+ if (customizer) {
+ var compared = isPartial ? customizer(othValue, objValue, key, other, object, stack) : customizer(objValue, othValue, key, object, other, stack);
+ }
+ if (!(compared === undefined2 ? objValue === othValue || equalFunc(objValue, othValue, bitmask, customizer, stack) : compared)) {
+ result2 = false;
+ break;
+ }
+ skipCtor || (skipCtor = key == "constructor");
+ }
+ if (result2 && !skipCtor) {
+ var objCtor = object.constructor, othCtor = other.constructor;
+ if (objCtor != othCtor && ("constructor" in object && "constructor" in other) && !(typeof objCtor == "function" && objCtor instanceof objCtor && typeof othCtor == "function" && othCtor instanceof othCtor)) {
+ result2 = false;
+ }
+ }
+ stack["delete"](object);
+ stack["delete"](other);
+ return result2;
+ }
+ function flatRest(func) {
+ return setToString(overRest(func, undefined2, flatten), func + "");
+ }
+ function getAllKeys(object) {
+ return baseGetAllKeys(object, keys, getSymbols);
+ }
+ function getAllKeysIn(object) {
+ return baseGetAllKeys(object, keysIn, getSymbolsIn);
+ }
+ var getData = !metaMap ? noop : function(func) {
+ return metaMap.get(func);
+ };
+ function getFuncName(func) {
+ var result2 = func.name + "", array = realNames[result2], length = hasOwnProperty.call(realNames, result2) ? array.length : 0;
+ while (length--) {
+ var data = array[length], otherFunc = data.func;
+ if (otherFunc == null || otherFunc == func) {
+ return data.name;
+ }
+ }
+ return result2;
+ }
+ function getHolder(func) {
+ var object = hasOwnProperty.call(lodash, "placeholder") ? lodash : func;
+ return object.placeholder;
+ }
+ function getIteratee() {
+ var result2 = lodash.iteratee || iteratee;
+ result2 = result2 === iteratee ? baseIteratee : result2;
+ return arguments.length ? result2(arguments[0], arguments[1]) : result2;
+ }
+ function getMapData(map2, key) {
+ var data = map2.__data__;
+ return isKeyable(key) ? data[typeof key == "string" ? "string" : "hash"] : data.map;
+ }
+ function getMatchData(object) {
+ var result2 = keys(object), length = result2.length;
+ while (length--) {
+ var key = result2[length], value = object[key];
+ result2[length] = [key, value, isStrictComparable(value)];
+ }
+ return result2;
+ }
+ function getNative(object, key) {
+ var value = getValue(object, key);
+ return baseIsNative(value) ? value : undefined2;
+ }
+ function getRawTag(value) {
+ var isOwn = hasOwnProperty.call(value, symToStringTag), tag = value[symToStringTag];
+ try {
+ value[symToStringTag] = undefined2;
+ var unmasked = true;
+ } catch (e) {
+ }
+ var result2 = nativeObjectToString.call(value);
+ if (unmasked) {
+ if (isOwn) {
+ value[symToStringTag] = tag;
+ } else {
+ delete value[symToStringTag];
+ }
+ }
+ return result2;
+ }
+ var getSymbols = !nativeGetSymbols ? stubArray : function(object) {
+ if (object == null) {
+ return [];
+ }
+ object = Object2(object);
+ return arrayFilter(nativeGetSymbols(object), function(symbol) {
+ return propertyIsEnumerable.call(object, symbol);
+ });
+ };
+ var getSymbolsIn = !nativeGetSymbols ? stubArray : function(object) {
+ var result2 = [];
+ while (object) {
+ arrayPush(result2, getSymbols(object));
+ object = getPrototype(object);
+ }
+ return result2;
+ };
+ var getTag = baseGetTag;
+ if (DataView && getTag(new DataView(new ArrayBuffer(1))) != dataViewTag || Map2 && getTag(new Map2()) != mapTag || Promise2 && getTag(Promise2.resolve()) != promiseTag || Set && getTag(new Set()) != setTag || WeakMap && getTag(new WeakMap()) != weakMapTag) {
+ getTag = function(value) {
+ var result2 = baseGetTag(value), Ctor = result2 == objectTag ? value.constructor : undefined2, ctorString = Ctor ? toSource(Ctor) : "";
+ if (ctorString) {
+ switch (ctorString) {
+ case dataViewCtorString:
+ return dataViewTag;
+ case mapCtorString:
+ return mapTag;
+ case promiseCtorString:
+ return promiseTag;
+ case setCtorString:
+ return setTag;
+ case weakMapCtorString:
+ return weakMapTag;
+ }
+ }
+ return result2;
+ };
+ }
+ function getView(start, end, transforms) {
+ var index = -1, length = transforms.length;
+ while (++index < length) {
+ var data = transforms[index], size2 = data.size;
+ switch (data.type) {
+ case "drop":
+ start += size2;
+ break;
+ case "dropRight":
+ end -= size2;
+ break;
+ case "take":
+ end = nativeMin(end, start + size2);
+ break;
+ case "takeRight":
+ start = nativeMax(start, end - size2);
+ break;
+ }
+ }
+ return { "start": start, "end": end };
+ }
+ function getWrapDetails(source) {
+ var match = source.match(reWrapDetails);
+ return match ? match[1].split(reSplitDetails) : [];
+ }
+ function hasPath(object, path, hasFunc) {
+ path = castPath(path, object);
+ var index = -1, length = path.length, result2 = false;
+ while (++index < length) {
+ var key = toKey(path[index]);
+ if (!(result2 = object != null && hasFunc(object, key))) {
+ break;
+ }
+ object = object[key];
+ }
+ if (result2 || ++index != length) {
+ return result2;
+ }
+ length = object == null ? 0 : object.length;
+ return !!length && isLength(length) && isIndex(key, length) && (isArray(object) || isArguments(object));
+ }
+ function initCloneArray(array) {
+ var length = array.length, result2 = new array.constructor(length);
+ if (length && typeof array[0] == "string" && hasOwnProperty.call(array, "index")) {
+ result2.index = array.index;
+ result2.input = array.input;
+ }
+ return result2;
+ }
+ function initCloneObject(object) {
+ return typeof object.constructor == "function" && !isPrototype(object) ? baseCreate(getPrototype(object)) : {};
+ }
+ function initCloneByTag(object, tag, isDeep) {
+ var Ctor = object.constructor;
+ switch (tag) {
+ case arrayBufferTag:
+ return cloneArrayBuffer(object);
+ case boolTag:
+ case dateTag:
+ return new Ctor(+object);
+ case dataViewTag:
+ return cloneDataView(object, isDeep);
+ case float32Tag:
+ case float64Tag:
+ case int8Tag:
+ case int16Tag:
+ case int32Tag:
+ case uint8Tag:
+ case uint8ClampedTag:
+ case uint16Tag:
+ case uint32Tag:
+ return cloneTypedArray(object, isDeep);
+ case mapTag:
+ return new Ctor();
+ case numberTag:
+ case stringTag:
+ return new Ctor(object);
+ case regexpTag:
+ return cloneRegExp(object);
+ case setTag:
+ return new Ctor();
+ case symbolTag:
+ return cloneSymbol(object);
+ }
+ }
+ function insertWrapDetails(source, details) {
+ var length = details.length;
+ if (!length) {
+ return source;
+ }
+ var lastIndex = length - 1;
+ details[lastIndex] = (length > 1 ? "& " : "") + details[lastIndex];
+ details = details.join(length > 2 ? ", " : " ");
+ return source.replace(reWrapComment, "{\n/* [wrapped with " + details + "] */\n");
+ }
+ function isFlattenable(value) {
+ return isArray(value) || isArguments(value) || !!(spreadableSymbol && value && value[spreadableSymbol]);
+ }
+ function isIndex(value, length) {
+ var type = typeof value;
+ length = length == null ? MAX_SAFE_INTEGER : length;
+ return !!length && (type == "number" || type != "symbol" && reIsUint.test(value)) && (value > -1 && value % 1 == 0 && value < length);
+ }
+ function isIterateeCall(value, index, object) {
+ if (!isObject(object)) {
+ return false;
+ }
+ var type = typeof index;
+ if (type == "number" ? isArrayLike(object) && isIndex(index, object.length) : type == "string" && index in object) {
+ return eq(object[index], value);
+ }
+ return false;
+ }
+ function isKey(value, object) {
+ if (isArray(value)) {
+ return false;
+ }
+ var type = typeof value;
+ if (type == "number" || type == "symbol" || type == "boolean" || value == null || isSymbol(value)) {
+ return true;
+ }
+ return reIsPlainProp.test(value) || !reIsDeepProp.test(value) || object != null && value in Object2(object);
+ }
+ function isKeyable(value) {
+ var type = typeof value;
+ return type == "string" || type == "number" || type == "symbol" || type == "boolean" ? value !== "__proto__" : value === null;
+ }
+ function isLaziable(func) {
+ var funcName = getFuncName(func), other = lodash[funcName];
+ if (typeof other != "function" || !(funcName in LazyWrapper.prototype)) {
+ return false;
+ }
+ if (func === other) {
+ return true;
+ }
+ var data = getData(other);
+ return !!data && func === data[0];
+ }
+ function isMasked(func) {
+ return !!maskSrcKey && maskSrcKey in func;
+ }
+ var isMaskable = coreJsData ? isFunction : stubFalse;
+ function isPrototype(value) {
+ var Ctor = value && value.constructor, proto = typeof Ctor == "function" && Ctor.prototype || objectProto;
+ return value === proto;
+ }
+ function isStrictComparable(value) {
+ return value === value && !isObject(value);
+ }
+ function matchesStrictComparable(key, srcValue) {
+ return function(object) {
+ if (object == null) {
+ return false;
+ }
+ return object[key] === srcValue && (srcValue !== undefined2 || key in Object2(object));
+ };
+ }
+ function memoizeCapped(func) {
+ var result2 = memoize(func, function(key) {
+ if (cache2.size === MAX_MEMOIZE_SIZE) {
+ cache2.clear();
+ }
+ return key;
+ });
+ var cache2 = result2.cache;
+ return result2;
+ }
+ function mergeData(data, source) {
+ var bitmask = data[1], srcBitmask = source[1], newBitmask = bitmask | srcBitmask, isCommon = newBitmask < (WRAP_BIND_FLAG | WRAP_BIND_KEY_FLAG | WRAP_ARY_FLAG);
+ var isCombo = srcBitmask == WRAP_ARY_FLAG && bitmask == WRAP_CURRY_FLAG || srcBitmask == WRAP_ARY_FLAG && bitmask == WRAP_REARG_FLAG && data[7].length <= source[8] || srcBitmask == (WRAP_ARY_FLAG | WRAP_REARG_FLAG) && source[7].length <= source[8] && bitmask == WRAP_CURRY_FLAG;
+ if (!(isCommon || isCombo)) {
+ return data;
+ }
+ if (srcBitmask & WRAP_BIND_FLAG) {
+ data[2] = source[2];
+ newBitmask |= bitmask & WRAP_BIND_FLAG ? 0 : WRAP_CURRY_BOUND_FLAG;
+ }
+ var value = source[3];
+ if (value) {
+ var partials = data[3];
+ data[3] = partials ? composeArgs(partials, value, source[4]) : value;
+ data[4] = partials ? replaceHolders(data[3], PLACEHOLDER) : source[4];
+ }
+ value = source[5];
+ if (value) {
+ partials = data[5];
+ data[5] = partials ? composeArgsRight(partials, value, source[6]) : value;
+ data[6] = partials ? replaceHolders(data[5], PLACEHOLDER) : source[6];
+ }
+ value = source[7];
+ if (value) {
+ data[7] = value;
+ }
+ if (srcBitmask & WRAP_ARY_FLAG) {
+ data[8] = data[8] == null ? source[8] : nativeMin(data[8], source[8]);
+ }
+ if (data[9] == null) {
+ data[9] = source[9];
+ }
+ data[0] = source[0];
+ data[1] = newBitmask;
+ return data;
+ }
+ function nativeKeysIn(object) {
+ var result2 = [];
+ if (object != null) {
+ for (var key in Object2(object)) {
+ result2.push(key);
+ }
+ }
+ return result2;
+ }
+ function objectToString(value) {
+ return nativeObjectToString.call(value);
+ }
+ function overRest(func, start, transform2) {
+ start = nativeMax(start === undefined2 ? func.length - 1 : start, 0);
+ return function() {
+ var args = arguments, index = -1, length = nativeMax(args.length - start, 0), array = Array2(length);
+ while (++index < length) {
+ array[index] = args[start + index];
+ }
+ index = -1;
+ var otherArgs = Array2(start + 1);
+ while (++index < start) {
+ otherArgs[index] = args[index];
+ }
+ otherArgs[start] = transform2(array);
+ return apply(func, this, otherArgs);
+ };
+ }
+ function parent(object, path) {
+ return path.length < 2 ? object : baseGet(object, baseSlice(path, 0, -1));
+ }
+ function reorder(array, indexes) {
+ var arrLength = array.length, length = nativeMin(indexes.length, arrLength), oldArray = copyArray(array);
+ while (length--) {
+ var index = indexes[length];
+ array[length] = isIndex(index, arrLength) ? oldArray[index] : undefined2;
+ }
+ return array;
+ }
+ function safeGet(object, key) {
+ if (key === "constructor" && typeof object[key] === "function") {
+ return;
+ }
+ if (key == "__proto__") {
+ return;
+ }
+ return object[key];
+ }
+ var setData = shortOut(baseSetData);
+ var setTimeout2 = ctxSetTimeout || function(func, wait) {
+ return root.setTimeout(func, wait);
+ };
+ var setToString = shortOut(baseSetToString);
+ function setWrapToString(wrapper, reference, bitmask) {
+ var source = reference + "";
+ return setToString(wrapper, insertWrapDetails(source, updateWrapDetails(getWrapDetails(source), bitmask)));
+ }
+ function shortOut(func) {
+ var count = 0, lastCalled = 0;
+ return function() {
+ var stamp = nativeNow(), remaining = HOT_SPAN - (stamp - lastCalled);
+ lastCalled = stamp;
+ if (remaining > 0) {
+ if (++count >= HOT_COUNT) {
+ return arguments[0];
+ }
+ } else {
+ count = 0;
+ }
+ return func.apply(undefined2, arguments);
+ };
+ }
+ function shuffleSelf(array, size2) {
+ var index = -1, length = array.length, lastIndex = length - 1;
+ size2 = size2 === undefined2 ? length : size2;
+ while (++index < size2) {
+ var rand = baseRandom(index, lastIndex), value = array[rand];
+ array[rand] = array[index];
+ array[index] = value;
+ }
+ array.length = size2;
+ return array;
+ }
+ var stringToPath = memoizeCapped(function(string) {
+ var result2 = [];
+ if (string.charCodeAt(0) === 46) {
+ result2.push("");
+ }
+ string.replace(rePropName, function(match, number, quote, subString) {
+ result2.push(quote ? subString.replace(reEscapeChar, "$1") : number || match);
+ });
+ return result2;
+ });
+ function toKey(value) {
+ if (typeof value == "string" || isSymbol(value)) {
+ return value;
+ }
+ var result2 = value + "";
+ return result2 == "0" && 1 / value == -INFINITY ? "-0" : result2;
+ }
+ function toSource(func) {
+ if (func != null) {
+ try {
+ return funcToString.call(func);
+ } catch (e) {
+ }
+ try {
+ return func + "";
+ } catch (e) {
+ }
+ }
+ return "";
+ }
+ function updateWrapDetails(details, bitmask) {
+ arrayEach(wrapFlags, function(pair) {
+ var value = "_." + pair[0];
+ if (bitmask & pair[1] && !arrayIncludes(details, value)) {
+ details.push(value);
+ }
+ });
+ return details.sort();
+ }
+ function wrapperClone(wrapper) {
+ if (wrapper instanceof LazyWrapper) {
+ return wrapper.clone();
+ }
+ var result2 = new LodashWrapper(wrapper.__wrapped__, wrapper.__chain__);
+ result2.__actions__ = copyArray(wrapper.__actions__);
+ result2.__index__ = wrapper.__index__;
+ result2.__values__ = wrapper.__values__;
+ return result2;
+ }
+ function chunk(array, size2, guard) {
+ if (guard ? isIterateeCall(array, size2, guard) : size2 === undefined2) {
+ size2 = 1;
+ } else {
+ size2 = nativeMax(toInteger(size2), 0);
+ }
+ var length = array == null ? 0 : array.length;
+ if (!length || size2 < 1) {
+ return [];
+ }
+ var index = 0, resIndex = 0, result2 = Array2(nativeCeil(length / size2));
+ while (index < length) {
+ result2[resIndex++] = baseSlice(array, index, index += size2);
+ }
+ return result2;
+ }
+ function compact(array) {
+ var index = -1, length = array == null ? 0 : array.length, resIndex = 0, result2 = [];
+ while (++index < length) {
+ var value = array[index];
+ if (value) {
+ result2[resIndex++] = value;
+ }
+ }
+ return result2;
+ }
+ function concat() {
+ var length = arguments.length;
+ if (!length) {
+ return [];
+ }
+ var args = Array2(length - 1), array = arguments[0], index = length;
+ while (index--) {
+ args[index - 1] = arguments[index];
+ }
+ return arrayPush(isArray(array) ? copyArray(array) : [array], baseFlatten(args, 1));
+ }
+ var difference = baseRest(function(array, values2) {
+ return isArrayLikeObject(array) ? baseDifference(array, baseFlatten(values2, 1, isArrayLikeObject, true)) : [];
+ });
+ var differenceBy = baseRest(function(array, values2) {
+ var iteratee2 = last(values2);
+ if (isArrayLikeObject(iteratee2)) {
+ iteratee2 = undefined2;
+ }
+ return isArrayLikeObject(array) ? baseDifference(array, baseFlatten(values2, 1, isArrayLikeObject, true), getIteratee(iteratee2, 2)) : [];
+ });
+ var differenceWith = baseRest(function(array, values2) {
+ var comparator = last(values2);
+ if (isArrayLikeObject(comparator)) {
+ comparator = undefined2;
+ }
+ return isArrayLikeObject(array) ? baseDifference(array, baseFlatten(values2, 1, isArrayLikeObject, true), undefined2, comparator) : [];
+ });
+ function drop(array, n, guard) {
+ var length = array == null ? 0 : array.length;
+ if (!length) {
+ return [];
+ }
+ n = guard || n === undefined2 ? 1 : toInteger(n);
+ return baseSlice(array, n < 0 ? 0 : n, length);
+ }
+ function dropRight(array, n, guard) {
+ var length = array == null ? 0 : array.length;
+ if (!length) {
+ return [];
+ }
+ n = guard || n === undefined2 ? 1 : toInteger(n);
+ n = length - n;
+ return baseSlice(array, 0, n < 0 ? 0 : n);
+ }
+ function dropRightWhile(array, predicate) {
+ return array && array.length ? baseWhile(array, getIteratee(predicate, 3), true, true) : [];
+ }
+ function dropWhile(array, predicate) {
+ return array && array.length ? baseWhile(array, getIteratee(predicate, 3), true) : [];
+ }
+ function fill(array, value, start, end) {
+ var length = array == null ? 0 : array.length;
+ if (!length) {
+ return [];
+ }
+ if (start && typeof start != "number" && isIterateeCall(array, value, start)) {
+ start = 0;
+ end = length;
+ }
+ return baseFill(array, value, start, end);
+ }
+ function findIndex(array, predicate, fromIndex) {
+ var length = array == null ? 0 : array.length;
+ if (!length) {
+ return -1;
+ }
+ var index = fromIndex == null ? 0 : toInteger(fromIndex);
+ if (index < 0) {
+ index = nativeMax(length + index, 0);
+ }
+ return baseFindIndex(array, getIteratee(predicate, 3), index);
+ }
+ function findLastIndex(array, predicate, fromIndex) {
+ var length = array == null ? 0 : array.length;
+ if (!length) {
+ return -1;
+ }
+ var index = length - 1;
+ if (fromIndex !== undefined2) {
+ index = toInteger(fromIndex);
+ index = fromIndex < 0 ? nativeMax(length + index, 0) : nativeMin(index, length - 1);
+ }
+ return baseFindIndex(array, getIteratee(predicate, 3), index, true);
+ }
+ function flatten(array) {
+ var length = array == null ? 0 : array.length;
+ return length ? baseFlatten(array, 1) : [];
+ }
+ function flattenDeep(array) {
+ var length = array == null ? 0 : array.length;
+ return length ? baseFlatten(array, INFINITY) : [];
+ }
+ function flattenDepth(array, depth) {
+ var length = array == null ? 0 : array.length;
+ if (!length) {
+ return [];
+ }
+ depth = depth === undefined2 ? 1 : toInteger(depth);
+ return baseFlatten(array, depth);
+ }
+ function fromPairs(pairs) {
+ var index = -1, length = pairs == null ? 0 : pairs.length, result2 = {};
+ while (++index < length) {
+ var pair = pairs[index];
+ result2[pair[0]] = pair[1];
+ }
+ return result2;
+ }
+ function head(array) {
+ return array && array.length ? array[0] : undefined2;
+ }
+ function indexOf(array, value, fromIndex) {
+ var length = array == null ? 0 : array.length;
+ if (!length) {
+ return -1;
+ }
+ var index = fromIndex == null ? 0 : toInteger(fromIndex);
+ if (index < 0) {
+ index = nativeMax(length + index, 0);
+ }
+ return baseIndexOf(array, value, index);
+ }
+ function initial(array) {
+ var length = array == null ? 0 : array.length;
+ return length ? baseSlice(array, 0, -1) : [];
+ }
+ var intersection = baseRest(function(arrays) {
+ var mapped = arrayMap(arrays, castArrayLikeObject);
+ return mapped.length && mapped[0] === arrays[0] ? baseIntersection(mapped) : [];
+ });
+ var intersectionBy = baseRest(function(arrays) {
+ var iteratee2 = last(arrays), mapped = arrayMap(arrays, castArrayLikeObject);
+ if (iteratee2 === last(mapped)) {
+ iteratee2 = undefined2;
+ } else {
+ mapped.pop();
+ }
+ return mapped.length && mapped[0] === arrays[0] ? baseIntersection(mapped, getIteratee(iteratee2, 2)) : [];
+ });
+ var intersectionWith = baseRest(function(arrays) {
+ var comparator = last(arrays), mapped = arrayMap(arrays, castArrayLikeObject);
+ comparator = typeof comparator == "function" ? comparator : undefined2;
+ if (comparator) {
+ mapped.pop();
+ }
+ return mapped.length && mapped[0] === arrays[0] ? baseIntersection(mapped, undefined2, comparator) : [];
+ });
+ function join(array, separator) {
+ return array == null ? "" : nativeJoin.call(array, separator);
+ }
+ function last(array) {
+ var length = array == null ? 0 : array.length;
+ return length ? array[length - 1] : undefined2;
+ }
+ function lastIndexOf(array, value, fromIndex) {
+ var length = array == null ? 0 : array.length;
+ if (!length) {
+ return -1;
+ }
+ var index = length;
+ if (fromIndex !== undefined2) {
+ index = toInteger(fromIndex);
+ index = index < 0 ? nativeMax(length + index, 0) : nativeMin(index, length - 1);
+ }
+ return value === value ? strictLastIndexOf(array, value, index) : baseFindIndex(array, baseIsNaN, index, true);
+ }
+ function nth(array, n) {
+ return array && array.length ? baseNth(array, toInteger(n)) : undefined2;
+ }
+ var pull = baseRest(pullAll);
+ function pullAll(array, values2) {
+ return array && array.length && values2 && values2.length ? basePullAll(array, values2) : array;
+ }
+ function pullAllBy(array, values2, iteratee2) {
+ return array && array.length && values2 && values2.length ? basePullAll(array, values2, getIteratee(iteratee2, 2)) : array;
+ }
+ function pullAllWith(array, values2, comparator) {
+ return array && array.length && values2 && values2.length ? basePullAll(array, values2, undefined2, comparator) : array;
+ }
+ var pullAt = flatRest(function(array, indexes) {
+ var length = array == null ? 0 : array.length, result2 = baseAt(array, indexes);
+ basePullAt(array, arrayMap(indexes, function(index) {
+ return isIndex(index, length) ? +index : index;
+ }).sort(compareAscending));
+ return result2;
+ });
+ function remove(array, predicate) {
+ var result2 = [];
+ if (!(array && array.length)) {
+ return result2;
+ }
+ var index = -1, indexes = [], length = array.length;
+ predicate = getIteratee(predicate, 3);
+ while (++index < length) {
+ var value = array[index];
+ if (predicate(value, index, array)) {
+ result2.push(value);
+ indexes.push(index);
+ }
+ }
+ basePullAt(array, indexes);
+ return result2;
+ }
+ function reverse(array) {
+ return array == null ? array : nativeReverse.call(array);
+ }
+ function slice(array, start, end) {
+ var length = array == null ? 0 : array.length;
+ if (!length) {
+ return [];
+ }
+ if (end && typeof end != "number" && isIterateeCall(array, start, end)) {
+ start = 0;
+ end = length;
+ } else {
+ start = start == null ? 0 : toInteger(start);
+ end = end === undefined2 ? length : toInteger(end);
+ }
+ return baseSlice(array, start, end);
+ }
+ function sortedIndex(array, value) {
+ return baseSortedIndex(array, value);
+ }
+ function sortedIndexBy(array, value, iteratee2) {
+ return baseSortedIndexBy(array, value, getIteratee(iteratee2, 2));
+ }
+ function sortedIndexOf(array, value) {
+ var length = array == null ? 0 : array.length;
+ if (length) {
+ var index = baseSortedIndex(array, value);
+ if (index < length && eq(array[index], value)) {
+ return index;
+ }
+ }
+ return -1;
+ }
+ function sortedLastIndex(array, value) {
+ return baseSortedIndex(array, value, true);
+ }
+ function sortedLastIndexBy(array, value, iteratee2) {
+ return baseSortedIndexBy(array, value, getIteratee(iteratee2, 2), true);
+ }
+ function sortedLastIndexOf(array, value) {
+ var length = array == null ? 0 : array.length;
+ if (length) {
+ var index = baseSortedIndex(array, value, true) - 1;
+ if (eq(array[index], value)) {
+ return index;
+ }
+ }
+ return -1;
+ }
+ function sortedUniq(array) {
+ return array && array.length ? baseSortedUniq(array) : [];
+ }
+ function sortedUniqBy(array, iteratee2) {
+ return array && array.length ? baseSortedUniq(array, getIteratee(iteratee2, 2)) : [];
+ }
+ function tail(array) {
+ var length = array == null ? 0 : array.length;
+ return length ? baseSlice(array, 1, length) : [];
+ }
+ function take(array, n, guard) {
+ if (!(array && array.length)) {
+ return [];
+ }
+ n = guard || n === undefined2 ? 1 : toInteger(n);
+ return baseSlice(array, 0, n < 0 ? 0 : n);
+ }
+ function takeRight(array, n, guard) {
+ var length = array == null ? 0 : array.length;
+ if (!length) {
+ return [];
+ }
+ n = guard || n === undefined2 ? 1 : toInteger(n);
+ n = length - n;
+ return baseSlice(array, n < 0 ? 0 : n, length);
+ }
+ function takeRightWhile(array, predicate) {
+ return array && array.length ? baseWhile(array, getIteratee(predicate, 3), false, true) : [];
+ }
+ function takeWhile(array, predicate) {
+ return array && array.length ? baseWhile(array, getIteratee(predicate, 3)) : [];
+ }
+ var union = baseRest(function(arrays) {
+ return baseUniq(baseFlatten(arrays, 1, isArrayLikeObject, true));
+ });
+ var unionBy = baseRest(function(arrays) {
+ var iteratee2 = last(arrays);
+ if (isArrayLikeObject(iteratee2)) {
+ iteratee2 = undefined2;
+ }
+ return baseUniq(baseFlatten(arrays, 1, isArrayLikeObject, true), getIteratee(iteratee2, 2));
+ });
+ var unionWith = baseRest(function(arrays) {
+ var comparator = last(arrays);
+ comparator = typeof comparator == "function" ? comparator : undefined2;
+ return baseUniq(baseFlatten(arrays, 1, isArrayLikeObject, true), undefined2, comparator);
+ });
+ function uniq(array) {
+ return array && array.length ? baseUniq(array) : [];
+ }
+ function uniqBy(array, iteratee2) {
+ return array && array.length ? baseUniq(array, getIteratee(iteratee2, 2)) : [];
+ }
+ function uniqWith(array, comparator) {
+ comparator = typeof comparator == "function" ? comparator : undefined2;
+ return array && array.length ? baseUniq(array, undefined2, comparator) : [];
+ }
+ function unzip(array) {
+ if (!(array && array.length)) {
+ return [];
+ }
+ var length = 0;
+ array = arrayFilter(array, function(group) {
+ if (isArrayLikeObject(group)) {
+ length = nativeMax(group.length, length);
+ return true;
+ }
+ });
+ return baseTimes(length, function(index) {
+ return arrayMap(array, baseProperty(index));
+ });
+ }
+ function unzipWith(array, iteratee2) {
+ if (!(array && array.length)) {
+ return [];
+ }
+ var result2 = unzip(array);
+ if (iteratee2 == null) {
+ return result2;
+ }
+ return arrayMap(result2, function(group) {
+ return apply(iteratee2, undefined2, group);
+ });
+ }
+ var without = baseRest(function(array, values2) {
+ return isArrayLikeObject(array) ? baseDifference(array, values2) : [];
+ });
+ var xor = baseRest(function(arrays) {
+ return baseXor(arrayFilter(arrays, isArrayLikeObject));
+ });
+ var xorBy = baseRest(function(arrays) {
+ var iteratee2 = last(arrays);
+ if (isArrayLikeObject(iteratee2)) {
+ iteratee2 = undefined2;
+ }
+ return baseXor(arrayFilter(arrays, isArrayLikeObject), getIteratee(iteratee2, 2));
+ });
+ var xorWith = baseRest(function(arrays) {
+ var comparator = last(arrays);
+ comparator = typeof comparator == "function" ? comparator : undefined2;
+ return baseXor(arrayFilter(arrays, isArrayLikeObject), undefined2, comparator);
+ });
+ var zip = baseRest(unzip);
+ function zipObject(props, values2) {
+ return baseZipObject(props || [], values2 || [], assignValue);
+ }
+ function zipObjectDeep(props, values2) {
+ return baseZipObject(props || [], values2 || [], baseSet);
+ }
+ var zipWith = baseRest(function(arrays) {
+ var length = arrays.length, iteratee2 = length > 1 ? arrays[length - 1] : undefined2;
+ iteratee2 = typeof iteratee2 == "function" ? (arrays.pop(), iteratee2) : undefined2;
+ return unzipWith(arrays, iteratee2);
+ });
+ function chain(value) {
+ var result2 = lodash(value);
+ result2.__chain__ = true;
+ return result2;
+ }
+ function tap(value, interceptor) {
+ interceptor(value);
+ return value;
+ }
+ function thru(value, interceptor) {
+ return interceptor(value);
+ }
+ var wrapperAt = flatRest(function(paths) {
+ var length = paths.length, start = length ? paths[0] : 0, value = this.__wrapped__, interceptor = function(object) {
+ return baseAt(object, paths);
+ };
+ if (length > 1 || this.__actions__.length || !(value instanceof LazyWrapper) || !isIndex(start)) {
+ return this.thru(interceptor);
+ }
+ value = value.slice(start, +start + (length ? 1 : 0));
+ value.__actions__.push({
+ "func": thru,
+ "args": [interceptor],
+ "thisArg": undefined2
+ });
+ return new LodashWrapper(value, this.__chain__).thru(function(array) {
+ if (length && !array.length) {
+ array.push(undefined2);
+ }
+ return array;
+ });
+ });
+ function wrapperChain() {
+ return chain(this);
+ }
+ function wrapperCommit() {
+ return new LodashWrapper(this.value(), this.__chain__);
+ }
+ function wrapperNext() {
+ if (this.__values__ === undefined2) {
+ this.__values__ = toArray(this.value());
+ }
+ var done = this.__index__ >= this.__values__.length, value = done ? undefined2 : this.__values__[this.__index__++];
+ return { "done": done, "value": value };
+ }
+ function wrapperToIterator() {
+ return this;
+ }
+ function wrapperPlant(value) {
+ var result2, parent2 = this;
+ while (parent2 instanceof baseLodash) {
+ var clone2 = wrapperClone(parent2);
+ clone2.__index__ = 0;
+ clone2.__values__ = undefined2;
+ if (result2) {
+ previous.__wrapped__ = clone2;
+ } else {
+ result2 = clone2;
+ }
+ var previous = clone2;
+ parent2 = parent2.__wrapped__;
+ }
+ previous.__wrapped__ = value;
+ return result2;
+ }
+ function wrapperReverse() {
+ var value = this.__wrapped__;
+ if (value instanceof LazyWrapper) {
+ var wrapped = value;
+ if (this.__actions__.length) {
+ wrapped = new LazyWrapper(this);
+ }
+ wrapped = wrapped.reverse();
+ wrapped.__actions__.push({
+ "func": thru,
+ "args": [reverse],
+ "thisArg": undefined2
+ });
+ return new LodashWrapper(wrapped, this.__chain__);
+ }
+ return this.thru(reverse);
+ }
+ function wrapperValue() {
+ return baseWrapperValue(this.__wrapped__, this.__actions__);
+ }
+ var countBy = createAggregator(function(result2, value, key) {
+ if (hasOwnProperty.call(result2, key)) {
+ ++result2[key];
+ } else {
+ baseAssignValue(result2, key, 1);
+ }
+ });
+ function every(collection, predicate, guard) {
+ var func = isArray(collection) ? arrayEvery : baseEvery;
+ if (guard && isIterateeCall(collection, predicate, guard)) {
+ predicate = undefined2;
+ }
+ return func(collection, getIteratee(predicate, 3));
+ }
+ function filter(collection, predicate) {
+ var func = isArray(collection) ? arrayFilter : baseFilter;
+ return func(collection, getIteratee(predicate, 3));
+ }
+ var find = createFind(findIndex);
+ var findLast = createFind(findLastIndex);
+ function flatMap(collection, iteratee2) {
+ return baseFlatten(map(collection, iteratee2), 1);
+ }
+ function flatMapDeep(collection, iteratee2) {
+ return baseFlatten(map(collection, iteratee2), INFINITY);
+ }
+ function flatMapDepth(collection, iteratee2, depth) {
+ depth = depth === undefined2 ? 1 : toInteger(depth);
+ return baseFlatten(map(collection, iteratee2), depth);
+ }
+ function forEach(collection, iteratee2) {
+ var func = isArray(collection) ? arrayEach : baseEach;
+ return func(collection, getIteratee(iteratee2, 3));
+ }
+ function forEachRight(collection, iteratee2) {
+ var func = isArray(collection) ? arrayEachRight : baseEachRight;
+ return func(collection, getIteratee(iteratee2, 3));
+ }
+ var groupBy = createAggregator(function(result2, value, key) {
+ if (hasOwnProperty.call(result2, key)) {
+ result2[key].push(value);
+ } else {
+ baseAssignValue(result2, key, [value]);
+ }
+ });
+ function includes(collection, value, fromIndex, guard) {
+ collection = isArrayLike(collection) ? collection : values(collection);
+ fromIndex = fromIndex && !guard ? toInteger(fromIndex) : 0;
+ var length = collection.length;
+ if (fromIndex < 0) {
+ fromIndex = nativeMax(length + fromIndex, 0);
+ }
+ return isString(collection) ? fromIndex <= length && collection.indexOf(value, fromIndex) > -1 : !!length && baseIndexOf(collection, value, fromIndex) > -1;
+ }
+ var invokeMap = baseRest(function(collection, path, args) {
+ var index = -1, isFunc = typeof path == "function", result2 = isArrayLike(collection) ? Array2(collection.length) : [];
+ baseEach(collection, function(value) {
+ result2[++index] = isFunc ? apply(path, value, args) : baseInvoke(value, path, args);
+ });
+ return result2;
+ });
+ var keyBy = createAggregator(function(result2, value, key) {
+ baseAssignValue(result2, key, value);
+ });
+ function map(collection, iteratee2) {
+ var func = isArray(collection) ? arrayMap : baseMap;
+ return func(collection, getIteratee(iteratee2, 3));
+ }
+ function orderBy(collection, iteratees, orders, guard) {
+ if (collection == null) {
+ return [];
+ }
+ if (!isArray(iteratees)) {
+ iteratees = iteratees == null ? [] : [iteratees];
+ }
+ orders = guard ? undefined2 : orders;
+ if (!isArray(orders)) {
+ orders = orders == null ? [] : [orders];
+ }
+ return baseOrderBy(collection, iteratees, orders);
+ }
+ var partition = createAggregator(function(result2, value, key) {
+ result2[key ? 0 : 1].push(value);
+ }, function() {
+ return [[], []];
+ });
+ function reduce(collection, iteratee2, accumulator) {
+ var func = isArray(collection) ? arrayReduce : baseReduce, initAccum = arguments.length < 3;
+ return func(collection, getIteratee(iteratee2, 4), accumulator, initAccum, baseEach);
+ }
+ function reduceRight(collection, iteratee2, accumulator) {
+ var func = isArray(collection) ? arrayReduceRight : baseReduce, initAccum = arguments.length < 3;
+ return func(collection, getIteratee(iteratee2, 4), accumulator, initAccum, baseEachRight);
+ }
+ function reject(collection, predicate) {
+ var func = isArray(collection) ? arrayFilter : baseFilter;
+ return func(collection, negate(getIteratee(predicate, 3)));
+ }
+ function sample(collection) {
+ var func = isArray(collection) ? arraySample : baseSample;
+ return func(collection);
+ }
+ function sampleSize(collection, n, guard) {
+ if (guard ? isIterateeCall(collection, n, guard) : n === undefined2) {
+ n = 1;
+ } else {
+ n = toInteger(n);
+ }
+ var func = isArray(collection) ? arraySampleSize : baseSampleSize;
+ return func(collection, n);
+ }
+ function shuffle(collection) {
+ var func = isArray(collection) ? arrayShuffle : baseShuffle;
+ return func(collection);
+ }
+ function size(collection) {
+ if (collection == null) {
+ return 0;
+ }
+ if (isArrayLike(collection)) {
+ return isString(collection) ? stringSize(collection) : collection.length;
+ }
+ var tag = getTag(collection);
+ if (tag == mapTag || tag == setTag) {
+ return collection.size;
+ }
+ return baseKeys(collection).length;
+ }
+ function some(collection, predicate, guard) {
+ var func = isArray(collection) ? arraySome : baseSome;
+ if (guard && isIterateeCall(collection, predicate, guard)) {
+ predicate = undefined2;
+ }
+ return func(collection, getIteratee(predicate, 3));
+ }
+ var sortBy = baseRest(function(collection, iteratees) {
+ if (collection == null) {
+ return [];
+ }
+ var length = iteratees.length;
+ if (length > 1 && isIterateeCall(collection, iteratees[0], iteratees[1])) {
+ iteratees = [];
+ } else if (length > 2 && isIterateeCall(iteratees[0], iteratees[1], iteratees[2])) {
+ iteratees = [iteratees[0]];
+ }
+ return baseOrderBy(collection, baseFlatten(iteratees, 1), []);
+ });
+ var now = ctxNow || function() {
+ return root.Date.now();
+ };
+ function after(n, func) {
+ if (typeof func != "function") {
+ throw new TypeError2(FUNC_ERROR_TEXT);
+ }
+ n = toInteger(n);
+ return function() {
+ if (--n < 1) {
+ return func.apply(this, arguments);
+ }
+ };
+ }
+ function ary(func, n, guard) {
+ n = guard ? undefined2 : n;
+ n = func && n == null ? func.length : n;
+ return createWrap(func, WRAP_ARY_FLAG, undefined2, undefined2, undefined2, undefined2, n);
+ }
+ function before(n, func) {
+ var result2;
+ if (typeof func != "function") {
+ throw new TypeError2(FUNC_ERROR_TEXT);
+ }
+ n = toInteger(n);
+ return function() {
+ if (--n > 0) {
+ result2 = func.apply(this, arguments);
+ }
+ if (n <= 1) {
+ func = undefined2;
+ }
+ return result2;
+ };
+ }
+ var bind = baseRest(function(func, thisArg, partials) {
+ var bitmask = WRAP_BIND_FLAG;
+ if (partials.length) {
+ var holders = replaceHolders(partials, getHolder(bind));
+ bitmask |= WRAP_PARTIAL_FLAG;
+ }
+ return createWrap(func, bitmask, thisArg, partials, holders);
+ });
+ var bindKey = baseRest(function(object, key, partials) {
+ var bitmask = WRAP_BIND_FLAG | WRAP_BIND_KEY_FLAG;
+ if (partials.length) {
+ var holders = replaceHolders(partials, getHolder(bindKey));
+ bitmask |= WRAP_PARTIAL_FLAG;
+ }
+ return createWrap(key, bitmask, object, partials, holders);
+ });
+ function curry(func, arity, guard) {
+ arity = guard ? undefined2 : arity;
+ var result2 = createWrap(func, WRAP_CURRY_FLAG, undefined2, undefined2, undefined2, undefined2, undefined2, arity);
+ result2.placeholder = curry.placeholder;
+ return result2;
+ }
+ function curryRight(func, arity, guard) {
+ arity = guard ? undefined2 : arity;
+ var result2 = createWrap(func, WRAP_CURRY_RIGHT_FLAG, undefined2, undefined2, undefined2, undefined2, undefined2, arity);
+ result2.placeholder = curryRight.placeholder;
+ return result2;
+ }
+ function debounce(func, wait, options) {
+ var lastArgs, lastThis, maxWait, result2, timerId, lastCallTime, lastInvokeTime = 0, leading = false, maxing = false, trailing = true;
+ if (typeof func != "function") {
+ throw new TypeError2(FUNC_ERROR_TEXT);
+ }
+ wait = toNumber(wait) || 0;
+ if (isObject(options)) {
+ leading = !!options.leading;
+ maxing = "maxWait" in options;
+ maxWait = maxing ? nativeMax(toNumber(options.maxWait) || 0, wait) : maxWait;
+ trailing = "trailing" in options ? !!options.trailing : trailing;
+ }
+ function invokeFunc(time) {
+ var args = lastArgs, thisArg = lastThis;
+ lastArgs = lastThis = undefined2;
+ lastInvokeTime = time;
+ result2 = func.apply(thisArg, args);
+ return result2;
+ }
+ function leadingEdge(time) {
+ lastInvokeTime = time;
+ timerId = setTimeout2(timerExpired, wait);
+ return leading ? invokeFunc(time) : result2;
+ }
+ function remainingWait(time) {
+ var timeSinceLastCall = time - lastCallTime, timeSinceLastInvoke = time - lastInvokeTime, timeWaiting = wait - timeSinceLastCall;
+ return maxing ? nativeMin(timeWaiting, maxWait - timeSinceLastInvoke) : timeWaiting;
+ }
+ function shouldInvoke(time) {
+ var timeSinceLastCall = time - lastCallTime, timeSinceLastInvoke = time - lastInvokeTime;
+ return lastCallTime === undefined2 || timeSinceLastCall >= wait || timeSinceLastCall < 0 || maxing && timeSinceLastInvoke >= maxWait;
+ }
+ function timerExpired() {
+ var time = now();
+ if (shouldInvoke(time)) {
+ return trailingEdge(time);
+ }
+ timerId = setTimeout2(timerExpired, remainingWait(time));
+ }
+ function trailingEdge(time) {
+ timerId = undefined2;
+ if (trailing && lastArgs) {
+ return invokeFunc(time);
+ }
+ lastArgs = lastThis = undefined2;
+ return result2;
+ }
+ function cancel() {
+ if (timerId !== undefined2) {
+ clearTimeout2(timerId);
+ }
+ lastInvokeTime = 0;
+ lastArgs = lastCallTime = lastThis = timerId = undefined2;
+ }
+ function flush() {
+ return timerId === undefined2 ? result2 : trailingEdge(now());
+ }
+ function debounced() {
+ var time = now(), isInvoking = shouldInvoke(time);
+ lastArgs = arguments;
+ lastThis = this;
+ lastCallTime = time;
+ if (isInvoking) {
+ if (timerId === undefined2) {
+ return leadingEdge(lastCallTime);
+ }
+ if (maxing) {
+ clearTimeout2(timerId);
+ timerId = setTimeout2(timerExpired, wait);
+ return invokeFunc(lastCallTime);
+ }
+ }
+ if (timerId === undefined2) {
+ timerId = setTimeout2(timerExpired, wait);
+ }
+ return result2;
+ }
+ debounced.cancel = cancel;
+ debounced.flush = flush;
+ return debounced;
+ }
+ var defer = baseRest(function(func, args) {
+ return baseDelay(func, 1, args);
+ });
+ var delay = baseRest(function(func, wait, args) {
+ return baseDelay(func, toNumber(wait) || 0, args);
+ });
+ function flip(func) {
+ return createWrap(func, WRAP_FLIP_FLAG);
+ }
+ function memoize(func, resolver) {
+ if (typeof func != "function" || resolver != null && typeof resolver != "function") {
+ throw new TypeError2(FUNC_ERROR_TEXT);
+ }
+ var memoized = function() {
+ var args = arguments, key = resolver ? resolver.apply(this, args) : args[0], cache2 = memoized.cache;
+ if (cache2.has(key)) {
+ return cache2.get(key);
+ }
+ var result2 = func.apply(this, args);
+ memoized.cache = cache2.set(key, result2) || cache2;
+ return result2;
+ };
+ memoized.cache = new (memoize.Cache || MapCache)();
+ return memoized;
+ }
+ memoize.Cache = MapCache;
+ function negate(predicate) {
+ if (typeof predicate != "function") {
+ throw new TypeError2(FUNC_ERROR_TEXT);
+ }
+ return function() {
+ var args = arguments;
+ switch (args.length) {
+ case 0:
+ return !predicate.call(this);
+ case 1:
+ return !predicate.call(this, args[0]);
+ case 2:
+ return !predicate.call(this, args[0], args[1]);
+ case 3:
+ return !predicate.call(this, args[0], args[1], args[2]);
+ }
+ return !predicate.apply(this, args);
+ };
+ }
+ function once(func) {
+ return before(2, func);
+ }
+ var overArgs = castRest(function(func, transforms) {
+ transforms = transforms.length == 1 && isArray(transforms[0]) ? arrayMap(transforms[0], baseUnary(getIteratee())) : arrayMap(baseFlatten(transforms, 1), baseUnary(getIteratee()));
+ var funcsLength = transforms.length;
+ return baseRest(function(args) {
+ var index = -1, length = nativeMin(args.length, funcsLength);
+ while (++index < length) {
+ args[index] = transforms[index].call(this, args[index]);
+ }
+ return apply(func, this, args);
+ });
+ });
+ var partial = baseRest(function(func, partials) {
+ var holders = replaceHolders(partials, getHolder(partial));
+ return createWrap(func, WRAP_PARTIAL_FLAG, undefined2, partials, holders);
+ });
+ var partialRight = baseRest(function(func, partials) {
+ var holders = replaceHolders(partials, getHolder(partialRight));
+ return createWrap(func, WRAP_PARTIAL_RIGHT_FLAG, undefined2, partials, holders);
+ });
+ var rearg = flatRest(function(func, indexes) {
+ return createWrap(func, WRAP_REARG_FLAG, undefined2, undefined2, undefined2, indexes);
+ });
+ function rest(func, start) {
+ if (typeof func != "function") {
+ throw new TypeError2(FUNC_ERROR_TEXT);
+ }
+ start = start === undefined2 ? start : toInteger(start);
+ return baseRest(func, start);
+ }
+ function spread(func, start) {
+ if (typeof func != "function") {
+ throw new TypeError2(FUNC_ERROR_TEXT);
+ }
+ start = start == null ? 0 : nativeMax(toInteger(start), 0);
+ return baseRest(function(args) {
+ var array = args[start], otherArgs = castSlice(args, 0, start);
+ if (array) {
+ arrayPush(otherArgs, array);
+ }
+ return apply(func, this, otherArgs);
+ });
+ }
+ function throttle(func, wait, options) {
+ var leading = true, trailing = true;
+ if (typeof func != "function") {
+ throw new TypeError2(FUNC_ERROR_TEXT);
+ }
+ if (isObject(options)) {
+ leading = "leading" in options ? !!options.leading : leading;
+ trailing = "trailing" in options ? !!options.trailing : trailing;
+ }
+ return debounce(func, wait, {
+ "leading": leading,
+ "maxWait": wait,
+ "trailing": trailing
+ });
+ }
+ function unary(func) {
+ return ary(func, 1);
+ }
+ function wrap(value, wrapper) {
+ return partial(castFunction(wrapper), value);
+ }
+ function castArray() {
+ if (!arguments.length) {
+ return [];
+ }
+ var value = arguments[0];
+ return isArray(value) ? value : [value];
+ }
+ function clone(value) {
+ return baseClone(value, CLONE_SYMBOLS_FLAG);
+ }
+ function cloneWith(value, customizer) {
+ customizer = typeof customizer == "function" ? customizer : undefined2;
+ return baseClone(value, CLONE_SYMBOLS_FLAG, customizer);
+ }
+ function cloneDeep(value) {
+ return baseClone(value, CLONE_DEEP_FLAG | CLONE_SYMBOLS_FLAG);
+ }
+ function cloneDeepWith(value, customizer) {
+ customizer = typeof customizer == "function" ? customizer : undefined2;
+ return baseClone(value, CLONE_DEEP_FLAG | CLONE_SYMBOLS_FLAG, customizer);
+ }
+ function conformsTo(object, source) {
+ return source == null || baseConformsTo(object, source, keys(source));
+ }
+ function eq(value, other) {
+ return value === other || value !== value && other !== other;
+ }
+ var gt = createRelationalOperation(baseGt);
+ var gte = createRelationalOperation(function(value, other) {
+ return value >= other;
+ });
+ var isArguments = baseIsArguments(function() {
+ return arguments;
+ }()) ? baseIsArguments : function(value) {
+ return isObjectLike(value) && hasOwnProperty.call(value, "callee") && !propertyIsEnumerable.call(value, "callee");
+ };
+ var isArray = Array2.isArray;
+ var isArrayBuffer = nodeIsArrayBuffer ? baseUnary(nodeIsArrayBuffer) : baseIsArrayBuffer;
+ function isArrayLike(value) {
+ return value != null && isLength(value.length) && !isFunction(value);
+ }
+ function isArrayLikeObject(value) {
+ return isObjectLike(value) && isArrayLike(value);
+ }
+ function isBoolean(value) {
+ return value === true || value === false || isObjectLike(value) && baseGetTag(value) == boolTag;
+ }
+ var isBuffer = nativeIsBuffer || stubFalse;
+ var isDate = nodeIsDate ? baseUnary(nodeIsDate) : baseIsDate;
+ function isElement(value) {
+ return isObjectLike(value) && value.nodeType === 1 && !isPlainObject(value);
+ }
+ function isEmpty(value) {
+ if (value == null) {
+ return true;
+ }
+ if (isArrayLike(value) && (isArray(value) || typeof value == "string" || typeof value.splice == "function" || isBuffer(value) || isTypedArray(value) || isArguments(value))) {
+ return !value.length;
+ }
+ var tag = getTag(value);
+ if (tag == mapTag || tag == setTag) {
+ return !value.size;
+ }
+ if (isPrototype(value)) {
+ return !baseKeys(value).length;
+ }
+ for (var key in value) {
+ if (hasOwnProperty.call(value, key)) {
+ return false;
+ }
+ }
+ return true;
+ }
+ function isEqual(value, other) {
+ return baseIsEqual(value, other);
+ }
+ function isEqualWith(value, other, customizer) {
+ customizer = typeof customizer == "function" ? customizer : undefined2;
+ var result2 = customizer ? customizer(value, other) : undefined2;
+ return result2 === undefined2 ? baseIsEqual(value, other, undefined2, customizer) : !!result2;
+ }
+ function isError(value) {
+ if (!isObjectLike(value)) {
+ return false;
+ }
+ var tag = baseGetTag(value);
+ return tag == errorTag || tag == domExcTag || typeof value.message == "string" && typeof value.name == "string" && !isPlainObject(value);
+ }
+ function isFinite(value) {
+ return typeof value == "number" && nativeIsFinite(value);
+ }
+ function isFunction(value) {
+ if (!isObject(value)) {
+ return false;
+ }
+ var tag = baseGetTag(value);
+ return tag == funcTag || tag == genTag || tag == asyncTag || tag == proxyTag;
+ }
+ function isInteger(value) {
+ return typeof value == "number" && value == toInteger(value);
+ }
+ function isLength(value) {
+ return typeof value == "number" && value > -1 && value % 1 == 0 && value <= MAX_SAFE_INTEGER;
+ }
+ function isObject(value) {
+ var type = typeof value;
+ return value != null && (type == "object" || type == "function");
+ }
+ function isObjectLike(value) {
+ return value != null && typeof value == "object";
+ }
+ var isMap = nodeIsMap ? baseUnary(nodeIsMap) : baseIsMap;
+ function isMatch(object, source) {
+ return object === source || baseIsMatch(object, source, getMatchData(source));
+ }
+ function isMatchWith(object, source, customizer) {
+ customizer = typeof customizer == "function" ? customizer : undefined2;
+ return baseIsMatch(object, source, getMatchData(source), customizer);
+ }
+ function isNaN(value) {
+ return isNumber(value) && value != +value;
+ }
+ function isNative(value) {
+ if (isMaskable(value)) {
+ throw new Error2(CORE_ERROR_TEXT);
+ }
+ return baseIsNative(value);
+ }
+ function isNull(value) {
+ return value === null;
+ }
+ function isNil(value) {
+ return value == null;
+ }
+ function isNumber(value) {
+ return typeof value == "number" || isObjectLike(value) && baseGetTag(value) == numberTag;
+ }
+ function isPlainObject(value) {
+ if (!isObjectLike(value) || baseGetTag(value) != objectTag) {
+ return false;
+ }
+ var proto = getPrototype(value);
+ if (proto === null) {
+ return true;
+ }
+ var Ctor = hasOwnProperty.call(proto, "constructor") && proto.constructor;
+ return typeof Ctor == "function" && Ctor instanceof Ctor && funcToString.call(Ctor) == objectCtorString;
+ }
+ var isRegExp = nodeIsRegExp ? baseUnary(nodeIsRegExp) : baseIsRegExp;
+ function isSafeInteger(value) {
+ return isInteger(value) && value >= -MAX_SAFE_INTEGER && value <= MAX_SAFE_INTEGER;
+ }
+ var isSet = nodeIsSet ? baseUnary(nodeIsSet) : baseIsSet;
+ function isString(value) {
+ return typeof value == "string" || !isArray(value) && isObjectLike(value) && baseGetTag(value) == stringTag;
+ }
+ function isSymbol(value) {
+ return typeof value == "symbol" || isObjectLike(value) && baseGetTag(value) == symbolTag;
+ }
+ var isTypedArray = nodeIsTypedArray ? baseUnary(nodeIsTypedArray) : baseIsTypedArray;
+ function isUndefined(value) {
+ return value === undefined2;
+ }
+ function isWeakMap(value) {
+ return isObjectLike(value) && getTag(value) == weakMapTag;
+ }
+ function isWeakSet(value) {
+ return isObjectLike(value) && baseGetTag(value) == weakSetTag;
+ }
+ var lt = createRelationalOperation(baseLt);
+ var lte = createRelationalOperation(function(value, other) {
+ return value <= other;
+ });
+ function toArray(value) {
+ if (!value) {
+ return [];
+ }
+ if (isArrayLike(value)) {
+ return isString(value) ? stringToArray(value) : copyArray(value);
+ }
+ if (symIterator && value[symIterator]) {
+ return iteratorToArray(value[symIterator]());
+ }
+ var tag = getTag(value), func = tag == mapTag ? mapToArray : tag == setTag ? setToArray : values;
+ return func(value);
+ }
+ function toFinite(value) {
+ if (!value) {
+ return value === 0 ? value : 0;
+ }
+ value = toNumber(value);
+ if (value === INFINITY || value === -INFINITY) {
+ var sign = value < 0 ? -1 : 1;
+ return sign * MAX_INTEGER;
+ }
+ return value === value ? value : 0;
+ }
+ function toInteger(value) {
+ var result2 = toFinite(value), remainder = result2 % 1;
+ return result2 === result2 ? remainder ? result2 - remainder : result2 : 0;
+ }
+ function toLength(value) {
+ return value ? baseClamp(toInteger(value), 0, MAX_ARRAY_LENGTH) : 0;
+ }
+ function toNumber(value) {
+ if (typeof value == "number") {
+ return value;
+ }
+ if (isSymbol(value)) {
+ return NAN;
+ }
+ if (isObject(value)) {
+ var other = typeof value.valueOf == "function" ? value.valueOf() : value;
+ value = isObject(other) ? other + "" : other;
+ }
+ if (typeof value != "string") {
+ return value === 0 ? value : +value;
+ }
+ value = baseTrim(value);
+ var isBinary = reIsBinary.test(value);
+ return isBinary || reIsOctal.test(value) ? freeParseInt(value.slice(2), isBinary ? 2 : 8) : reIsBadHex.test(value) ? NAN : +value;
+ }
+ function toPlainObject(value) {
+ return copyObject(value, keysIn(value));
+ }
+ function toSafeInteger(value) {
+ return value ? baseClamp(toInteger(value), -MAX_SAFE_INTEGER, MAX_SAFE_INTEGER) : value === 0 ? value : 0;
+ }
+ function toString(value) {
+ return value == null ? "" : baseToString(value);
+ }
+ var assign = createAssigner(function(object, source) {
+ if (isPrototype(source) || isArrayLike(source)) {
+ copyObject(source, keys(source), object);
+ return;
+ }
+ for (var key in source) {
+ if (hasOwnProperty.call(source, key)) {
+ assignValue(object, key, source[key]);
+ }
+ }
+ });
+ var assignIn = createAssigner(function(object, source) {
+ copyObject(source, keysIn(source), object);
+ });
+ var assignInWith = createAssigner(function(object, source, srcIndex, customizer) {
+ copyObject(source, keysIn(source), object, customizer);
+ });
+ var assignWith = createAssigner(function(object, source, srcIndex, customizer) {
+ copyObject(source, keys(source), object, customizer);
+ });
+ var at = flatRest(baseAt);
+ function create(prototype, properties) {
+ var result2 = baseCreate(prototype);
+ return properties == null ? result2 : baseAssign(result2, properties);
+ }
+ var defaults = baseRest(function(object, sources) {
+ object = Object2(object);
+ var index = -1;
+ var length = sources.length;
+ var guard = length > 2 ? sources[2] : undefined2;
+ if (guard && isIterateeCall(sources[0], sources[1], guard)) {
+ length = 1;
+ }
+ while (++index < length) {
+ var source = sources[index];
+ var props = keysIn(source);
+ var propsIndex = -1;
+ var propsLength = props.length;
+ while (++propsIndex < propsLength) {
+ var key = props[propsIndex];
+ var value = object[key];
+ if (value === undefined2 || eq(value, objectProto[key]) && !hasOwnProperty.call(object, key)) {
+ object[key] = source[key];
+ }
+ }
+ }
+ return object;
+ });
+ var defaultsDeep = baseRest(function(args) {
+ args.push(undefined2, customDefaultsMerge);
+ return apply(mergeWith, undefined2, args);
+ });
+ function findKey(object, predicate) {
+ return baseFindKey(object, getIteratee(predicate, 3), baseForOwn);
+ }
+ function findLastKey(object, predicate) {
+ return baseFindKey(object, getIteratee(predicate, 3), baseForOwnRight);
+ }
+ function forIn(object, iteratee2) {
+ return object == null ? object : baseFor(object, getIteratee(iteratee2, 3), keysIn);
+ }
+ function forInRight(object, iteratee2) {
+ return object == null ? object : baseForRight(object, getIteratee(iteratee2, 3), keysIn);
+ }
+ function forOwn(object, iteratee2) {
+ return object && baseForOwn(object, getIteratee(iteratee2, 3));
+ }
+ function forOwnRight(object, iteratee2) {
+ return object && baseForOwnRight(object, getIteratee(iteratee2, 3));
+ }
+ function functions(object) {
+ return object == null ? [] : baseFunctions(object, keys(object));
+ }
+ function functionsIn(object) {
+ return object == null ? [] : baseFunctions(object, keysIn(object));
+ }
+ function get(object, path, defaultValue) {
+ var result2 = object == null ? undefined2 : baseGet(object, path);
+ return result2 === undefined2 ? defaultValue : result2;
+ }
+ function has(object, path) {
+ return object != null && hasPath(object, path, baseHas);
+ }
+ function hasIn(object, path) {
+ return object != null && hasPath(object, path, baseHasIn);
+ }
+ var invert = createInverter(function(result2, value, key) {
+ if (value != null && typeof value.toString != "function") {
+ value = nativeObjectToString.call(value);
+ }
+ result2[value] = key;
+ }, constant(identity));
+ var invertBy = createInverter(function(result2, value, key) {
+ if (value != null && typeof value.toString != "function") {
+ value = nativeObjectToString.call(value);
+ }
+ if (hasOwnProperty.call(result2, value)) {
+ result2[value].push(key);
+ } else {
+ result2[value] = [key];
+ }
+ }, getIteratee);
+ var invoke = baseRest(baseInvoke);
+ function keys(object) {
+ return isArrayLike(object) ? arrayLikeKeys(object) : baseKeys(object);
+ }
+ function keysIn(object) {
+ return isArrayLike(object) ? arrayLikeKeys(object, true) : baseKeysIn(object);
+ }
+ function mapKeys(object, iteratee2) {
+ var result2 = {};
+ iteratee2 = getIteratee(iteratee2, 3);
+ baseForOwn(object, function(value, key, object2) {
+ baseAssignValue(result2, iteratee2(value, key, object2), value);
+ });
+ return result2;
+ }
+ function mapValues(object, iteratee2) {
+ var result2 = {};
+ iteratee2 = getIteratee(iteratee2, 3);
+ baseForOwn(object, function(value, key, object2) {
+ baseAssignValue(result2, key, iteratee2(value, key, object2));
+ });
+ return result2;
+ }
+ var merge = createAssigner(function(object, source, srcIndex) {
+ baseMerge(object, source, srcIndex);
+ });
+ var mergeWith = createAssigner(function(object, source, srcIndex, customizer) {
+ baseMerge(object, source, srcIndex, customizer);
+ });
+ var omit = flatRest(function(object, paths) {
+ var result2 = {};
+ if (object == null) {
+ return result2;
+ }
+ var isDeep = false;
+ paths = arrayMap(paths, function(path) {
+ path = castPath(path, object);
+ isDeep || (isDeep = path.length > 1);
+ return path;
+ });
+ copyObject(object, getAllKeysIn(object), result2);
+ if (isDeep) {
+ result2 = baseClone(result2, CLONE_DEEP_FLAG | CLONE_FLAT_FLAG | CLONE_SYMBOLS_FLAG, customOmitClone);
+ }
+ var length = paths.length;
+ while (length--) {
+ baseUnset(result2, paths[length]);
+ }
+ return result2;
+ });
+ function omitBy(object, predicate) {
+ return pickBy(object, negate(getIteratee(predicate)));
+ }
+ var pick = flatRest(function(object, paths) {
+ return object == null ? {} : basePick(object, paths);
+ });
+ function pickBy(object, predicate) {
+ if (object == null) {
+ return {};
+ }
+ var props = arrayMap(getAllKeysIn(object), function(prop) {
+ return [prop];
+ });
+ predicate = getIteratee(predicate);
+ return basePickBy(object, props, function(value, path) {
+ return predicate(value, path[0]);
+ });
+ }
+ function result(object, path, defaultValue) {
+ path = castPath(path, object);
+ var index = -1, length = path.length;
+ if (!length) {
+ length = 1;
+ object = undefined2;
+ }
+ while (++index < length) {
+ var value = object == null ? undefined2 : object[toKey(path[index])];
+ if (value === undefined2) {
+ index = length;
+ value = defaultValue;
+ }
+ object = isFunction(value) ? value.call(object) : value;
+ }
+ return object;
+ }
+ function set2(object, path, value) {
+ return object == null ? object : baseSet(object, path, value);
+ }
+ function setWith(object, path, value, customizer) {
+ customizer = typeof customizer == "function" ? customizer : undefined2;
+ return object == null ? object : baseSet(object, path, value, customizer);
+ }
+ var toPairs = createToPairs(keys);
+ var toPairsIn = createToPairs(keysIn);
+ function transform(object, iteratee2, accumulator) {
+ var isArr = isArray(object), isArrLike = isArr || isBuffer(object) || isTypedArray(object);
+ iteratee2 = getIteratee(iteratee2, 4);
+ if (accumulator == null) {
+ var Ctor = object && object.constructor;
+ if (isArrLike) {
+ accumulator = isArr ? new Ctor() : [];
+ } else if (isObject(object)) {
+ accumulator = isFunction(Ctor) ? baseCreate(getPrototype(object)) : {};
+ } else {
+ accumulator = {};
+ }
+ }
+ (isArrLike ? arrayEach : baseForOwn)(object, function(value, index, object2) {
+ return iteratee2(accumulator, value, index, object2);
+ });
+ return accumulator;
+ }
+ function unset(object, path) {
+ return object == null ? true : baseUnset(object, path);
+ }
+ function update(object, path, updater) {
+ return object == null ? object : baseUpdate(object, path, castFunction(updater));
+ }
+ function updateWith(object, path, updater, customizer) {
+ customizer = typeof customizer == "function" ? customizer : undefined2;
+ return object == null ? object : baseUpdate(object, path, castFunction(updater), customizer);
+ }
+ function values(object) {
+ return object == null ? [] : baseValues(object, keys(object));
+ }
+ function valuesIn(object) {
+ return object == null ? [] : baseValues(object, keysIn(object));
+ }
+ function clamp(number, lower, upper) {
+ if (upper === undefined2) {
+ upper = lower;
+ lower = undefined2;
+ }
+ if (upper !== undefined2) {
+ upper = toNumber(upper);
+ upper = upper === upper ? upper : 0;
+ }
+ if (lower !== undefined2) {
+ lower = toNumber(lower);
+ lower = lower === lower ? lower : 0;
+ }
+ return baseClamp(toNumber(number), lower, upper);
+ }
+ function inRange(number, start, end) {
+ start = toFinite(start);
+ if (end === undefined2) {
+ end = start;
+ start = 0;
+ } else {
+ end = toFinite(end);
+ }
+ number = toNumber(number);
+ return baseInRange(number, start, end);
+ }
+ function random(lower, upper, floating) {
+ if (floating && typeof floating != "boolean" && isIterateeCall(lower, upper, floating)) {
+ upper = floating = undefined2;
+ }
+ if (floating === undefined2) {
+ if (typeof upper == "boolean") {
+ floating = upper;
+ upper = undefined2;
+ } else if (typeof lower == "boolean") {
+ floating = lower;
+ lower = undefined2;
+ }
+ }
+ if (lower === undefined2 && upper === undefined2) {
+ lower = 0;
+ upper = 1;
+ } else {
+ lower = toFinite(lower);
+ if (upper === undefined2) {
+ upper = lower;
+ lower = 0;
+ } else {
+ upper = toFinite(upper);
+ }
+ }
+ if (lower > upper) {
+ var temp = lower;
+ lower = upper;
+ upper = temp;
+ }
+ if (floating || lower % 1 || upper % 1) {
+ var rand = nativeRandom();
+ return nativeMin(lower + rand * (upper - lower + freeParseFloat("1e-" + ((rand + "").length - 1))), upper);
+ }
+ return baseRandom(lower, upper);
+ }
+ var camelCase = createCompounder(function(result2, word, index) {
+ word = word.toLowerCase();
+ return result2 + (index ? capitalize(word) : word);
+ });
+ function capitalize(string) {
+ return upperFirst(toString(string).toLowerCase());
+ }
+ function deburr(string) {
+ string = toString(string);
+ return string && string.replace(reLatin, deburrLetter).replace(reComboMark, "");
+ }
+ function endsWith(string, target, position) {
+ string = toString(string);
+ target = baseToString(target);
+ var length = string.length;
+ position = position === undefined2 ? length : baseClamp(toInteger(position), 0, length);
+ var end = position;
+ position -= target.length;
+ return position >= 0 && string.slice(position, end) == target;
+ }
+ function escape(string) {
+ string = toString(string);
+ return string && reHasUnescapedHtml.test(string) ? string.replace(reUnescapedHtml, escapeHtmlChar) : string;
+ }
+ function escapeRegExp(string) {
+ string = toString(string);
+ return string && reHasRegExpChar.test(string) ? string.replace(reRegExpChar, "\\$&") : string;
+ }
+ var kebabCase = createCompounder(function(result2, word, index) {
+ return result2 + (index ? "-" : "") + word.toLowerCase();
+ });
+ var lowerCase = createCompounder(function(result2, word, index) {
+ return result2 + (index ? " " : "") + word.toLowerCase();
+ });
+ var lowerFirst = createCaseFirst("toLowerCase");
+ function pad(string, length, chars) {
+ string = toString(string);
+ length = toInteger(length);
+ var strLength = length ? stringSize(string) : 0;
+ if (!length || strLength >= length) {
+ return string;
+ }
+ var mid = (length - strLength) / 2;
+ return createPadding(nativeFloor(mid), chars) + string + createPadding(nativeCeil(mid), chars);
+ }
+ function padEnd(string, length, chars) {
+ string = toString(string);
+ length = toInteger(length);
+ var strLength = length ? stringSize(string) : 0;
+ return length && strLength < length ? string + createPadding(length - strLength, chars) : string;
+ }
+ function padStart(string, length, chars) {
+ string = toString(string);
+ length = toInteger(length);
+ var strLength = length ? stringSize(string) : 0;
+ return length && strLength < length ? createPadding(length - strLength, chars) + string : string;
+ }
+ function parseInt2(string, radix, guard) {
+ if (guard || radix == null) {
+ radix = 0;
+ } else if (radix) {
+ radix = +radix;
+ }
+ return nativeParseInt(toString(string).replace(reTrimStart, ""), radix || 0);
+ }
+ function repeat(string, n, guard) {
+ if (guard ? isIterateeCall(string, n, guard) : n === undefined2) {
+ n = 1;
+ } else {
+ n = toInteger(n);
+ }
+ return baseRepeat(toString(string), n);
+ }
+ function replace() {
+ var args = arguments, string = toString(args[0]);
+ return args.length < 3 ? string : string.replace(args[1], args[2]);
+ }
+ var snakeCase = createCompounder(function(result2, word, index) {
+ return result2 + (index ? "_" : "") + word.toLowerCase();
+ });
+ function split(string, separator, limit) {
+ if (limit && typeof limit != "number" && isIterateeCall(string, separator, limit)) {
+ separator = limit = undefined2;
+ }
+ limit = limit === undefined2 ? MAX_ARRAY_LENGTH : limit >>> 0;
+ if (!limit) {
+ return [];
+ }
+ string = toString(string);
+ if (string && (typeof separator == "string" || separator != null && !isRegExp(separator))) {
+ separator = baseToString(separator);
+ if (!separator && hasUnicode(string)) {
+ return castSlice(stringToArray(string), 0, limit);
+ }
+ }
+ return string.split(separator, limit);
+ }
+ var startCase = createCompounder(function(result2, word, index) {
+ return result2 + (index ? " " : "") + upperFirst(word);
+ });
+ function startsWith(string, target, position) {
+ string = toString(string);
+ position = position == null ? 0 : baseClamp(toInteger(position), 0, string.length);
+ target = baseToString(target);
+ return string.slice(position, position + target.length) == target;
+ }
+ function template(string, options, guard) {
+ var settings = lodash.templateSettings;
+ if (guard && isIterateeCall(string, options, guard)) {
+ options = undefined2;
+ }
+ string = toString(string);
+ options = assignInWith({}, options, settings, customDefaultsAssignIn);
+ var imports = assignInWith({}, options.imports, settings.imports, customDefaultsAssignIn), importsKeys = keys(imports), importsValues = baseValues(imports, importsKeys);
+ var isEscaping, isEvaluating, index = 0, interpolate = options.interpolate || reNoMatch, source = "__p += '";
+ var reDelimiters = RegExp2(
+ (options.escape || reNoMatch).source + "|" + interpolate.source + "|" + (interpolate === reInterpolate ? reEsTemplate : reNoMatch).source + "|" + (options.evaluate || reNoMatch).source + "|$",
+ "g"
+ );
+ var sourceURL = "//# sourceURL=" + (hasOwnProperty.call(options, "sourceURL") ? (options.sourceURL + "").replace(/\s/g, " ") : "lodash.templateSources[" + ++templateCounter + "]") + "\n";
+ string.replace(reDelimiters, function(match, escapeValue, interpolateValue, esTemplateValue, evaluateValue, offset) {
+ interpolateValue || (interpolateValue = esTemplateValue);
+ source += string.slice(index, offset).replace(reUnescapedString, escapeStringChar);
+ if (escapeValue) {
+ isEscaping = true;
+ source += "' +\n__e(" + escapeValue + ") +\n'";
+ }
+ if (evaluateValue) {
+ isEvaluating = true;
+ source += "';\n" + evaluateValue + ";\n__p += '";
+ }
+ if (interpolateValue) {
+ source += "' +\n((__t = (" + interpolateValue + ")) == null ? '' : __t) +\n'";
+ }
+ index = offset + match.length;
+ return match;
+ });
+ source += "';\n";
+ var variable = hasOwnProperty.call(options, "variable") && options.variable;
+ if (!variable) {
+ source = "with (obj) {\n" + source + "\n}\n";
+ } else if (reForbiddenIdentifierChars.test(variable)) {
+ throw new Error2(INVALID_TEMPL_VAR_ERROR_TEXT);
+ }
+ source = (isEvaluating ? source.replace(reEmptyStringLeading, "") : source).replace(reEmptyStringMiddle, "$1").replace(reEmptyStringTrailing, "$1;");
+ source = "function(" + (variable || "obj") + ") {\n" + (variable ? "" : "obj || (obj = {});\n") + "var __t, __p = ''" + (isEscaping ? ", __e = _.escape" : "") + (isEvaluating ? ", __j = Array.prototype.join;\nfunction print() { __p += __j.call(arguments, '') }\n" : ";\n") + source + "return __p\n}";
+ var result2 = attempt(function() {
+ return Function2(importsKeys, sourceURL + "return " + source).apply(undefined2, importsValues);
+ });
+ result2.source = source;
+ if (isError(result2)) {
+ throw result2;
+ }
+ return result2;
+ }
+ function toLower(value) {
+ return toString(value).toLowerCase();
+ }
+ function toUpper(value) {
+ return toString(value).toUpperCase();
+ }
+ function trim(string, chars, guard) {
+ string = toString(string);
+ if (string && (guard || chars === undefined2)) {
+ return baseTrim(string);
+ }
+ if (!string || !(chars = baseToString(chars))) {
+ return string;
+ }
+ var strSymbols = stringToArray(string), chrSymbols = stringToArray(chars), start = charsStartIndex(strSymbols, chrSymbols), end = charsEndIndex(strSymbols, chrSymbols) + 1;
+ return castSlice(strSymbols, start, end).join("");
+ }
+ function trimEnd(string, chars, guard) {
+ string = toString(string);
+ if (string && (guard || chars === undefined2)) {
+ return string.slice(0, trimmedEndIndex(string) + 1);
+ }
+ if (!string || !(chars = baseToString(chars))) {
+ return string;
+ }
+ var strSymbols = stringToArray(string), end = charsEndIndex(strSymbols, stringToArray(chars)) + 1;
+ return castSlice(strSymbols, 0, end).join("");
+ }
+ function trimStart(string, chars, guard) {
+ string = toString(string);
+ if (string && (guard || chars === undefined2)) {
+ return string.replace(reTrimStart, "");
+ }
+ if (!string || !(chars = baseToString(chars))) {
+ return string;
+ }
+ var strSymbols = stringToArray(string), start = charsStartIndex(strSymbols, stringToArray(chars));
+ return castSlice(strSymbols, start).join("");
+ }
+ function truncate(string, options) {
+ var length = DEFAULT_TRUNC_LENGTH, omission = DEFAULT_TRUNC_OMISSION;
+ if (isObject(options)) {
+ var separator = "separator" in options ? options.separator : separator;
+ length = "length" in options ? toInteger(options.length) : length;
+ omission = "omission" in options ? baseToString(options.omission) : omission;
+ }
+ string = toString(string);
+ var strLength = string.length;
+ if (hasUnicode(string)) {
+ var strSymbols = stringToArray(string);
+ strLength = strSymbols.length;
+ }
+ if (length >= strLength) {
+ return string;
+ }
+ var end = length - stringSize(omission);
+ if (end < 1) {
+ return omission;
+ }
+ var result2 = strSymbols ? castSlice(strSymbols, 0, end).join("") : string.slice(0, end);
+ if (separator === undefined2) {
+ return result2 + omission;
+ }
+ if (strSymbols) {
+ end += result2.length - end;
+ }
+ if (isRegExp(separator)) {
+ if (string.slice(end).search(separator)) {
+ var match, substring = result2;
+ if (!separator.global) {
+ separator = RegExp2(separator.source, toString(reFlags.exec(separator)) + "g");
+ }
+ separator.lastIndex = 0;
+ while (match = separator.exec(substring)) {
+ var newEnd = match.index;
+ }
+ result2 = result2.slice(0, newEnd === undefined2 ? end : newEnd);
+ }
+ } else if (string.indexOf(baseToString(separator), end) != end) {
+ var index = result2.lastIndexOf(separator);
+ if (index > -1) {
+ result2 = result2.slice(0, index);
+ }
+ }
+ return result2 + omission;
+ }
+ function unescape(string) {
+ string = toString(string);
+ return string && reHasEscapedHtml.test(string) ? string.replace(reEscapedHtml, unescapeHtmlChar) : string;
+ }
+ var upperCase = createCompounder(function(result2, word, index) {
+ return result2 + (index ? " " : "") + word.toUpperCase();
+ });
+ var upperFirst = createCaseFirst("toUpperCase");
+ function words(string, pattern, guard) {
+ string = toString(string);
+ pattern = guard ? undefined2 : pattern;
+ if (pattern === undefined2) {
+ return hasUnicodeWord(string) ? unicodeWords(string) : asciiWords(string);
+ }
+ return string.match(pattern) || [];
+ }
+ var attempt = baseRest(function(func, args) {
+ try {
+ return apply(func, undefined2, args);
+ } catch (e) {
+ return isError(e) ? e : new Error2(e);
+ }
+ });
+ var bindAll = flatRest(function(object, methodNames) {
+ arrayEach(methodNames, function(key) {
+ key = toKey(key);
+ baseAssignValue(object, key, bind(object[key], object));
+ });
+ return object;
+ });
+ function cond(pairs) {
+ var length = pairs == null ? 0 : pairs.length, toIteratee = getIteratee();
+ pairs = !length ? [] : arrayMap(pairs, function(pair) {
+ if (typeof pair[1] != "function") {
+ throw new TypeError2(FUNC_ERROR_TEXT);
+ }
+ return [toIteratee(pair[0]), pair[1]];
+ });
+ return baseRest(function(args) {
+ var index = -1;
+ while (++index < length) {
+ var pair = pairs[index];
+ if (apply(pair[0], this, args)) {
+ return apply(pair[1], this, args);
+ }
+ }
+ });
+ }
+ function conforms(source) {
+ return baseConforms(baseClone(source, CLONE_DEEP_FLAG));
+ }
+ function constant(value) {
+ return function() {
+ return value;
+ };
+ }
+ function defaultTo(value, defaultValue) {
+ return value == null || value !== value ? defaultValue : value;
+ }
+ var flow = createFlow();
+ var flowRight = createFlow(true);
+ function identity(value) {
+ return value;
+ }
+ function iteratee(func) {
+ return baseIteratee(typeof func == "function" ? func : baseClone(func, CLONE_DEEP_FLAG));
+ }
+ function matches(source) {
+ return baseMatches(baseClone(source, CLONE_DEEP_FLAG));
+ }
+ function matchesProperty(path, srcValue) {
+ return baseMatchesProperty(path, baseClone(srcValue, CLONE_DEEP_FLAG));
+ }
+ var method = baseRest(function(path, args) {
+ return function(object) {
+ return baseInvoke(object, path, args);
+ };
+ });
+ var methodOf = baseRest(function(object, args) {
+ return function(path) {
+ return baseInvoke(object, path, args);
+ };
+ });
+ function mixin(object, source, options) {
+ var props = keys(source), methodNames = baseFunctions(source, props);
+ if (options == null && !(isObject(source) && (methodNames.length || !props.length))) {
+ options = source;
+ source = object;
+ object = this;
+ methodNames = baseFunctions(source, keys(source));
+ }
+ var chain2 = !(isObject(options) && "chain" in options) || !!options.chain, isFunc = isFunction(object);
+ arrayEach(methodNames, function(methodName) {
+ var func = source[methodName];
+ object[methodName] = func;
+ if (isFunc) {
+ object.prototype[methodName] = function() {
+ var chainAll = this.__chain__;
+ if (chain2 || chainAll) {
+ var result2 = object(this.__wrapped__), actions = result2.__actions__ = copyArray(this.__actions__);
+ actions.push({ "func": func, "args": arguments, "thisArg": object });
+ result2.__chain__ = chainAll;
+ return result2;
+ }
+ return func.apply(object, arrayPush([this.value()], arguments));
+ };
+ }
+ });
+ return object;
+ }
+ function noConflict() {
+ if (root._ === this) {
+ root._ = oldDash;
+ }
+ return this;
+ }
+ function noop() {
+ }
+ function nthArg(n) {
+ n = toInteger(n);
+ return baseRest(function(args) {
+ return baseNth(args, n);
+ });
+ }
+ var over = createOver(arrayMap);
+ var overEvery = createOver(arrayEvery);
+ var overSome = createOver(arraySome);
+ function property(path) {
+ return isKey(path) ? baseProperty(toKey(path)) : basePropertyDeep(path);
+ }
+ function propertyOf(object) {
+ return function(path) {
+ return object == null ? undefined2 : baseGet(object, path);
+ };
+ }
+ var range = createRange();
+ var rangeRight = createRange(true);
+ function stubArray() {
+ return [];
+ }
+ function stubFalse() {
+ return false;
+ }
+ function stubObject() {
+ return {};
+ }
+ function stubString() {
+ return "";
+ }
+ function stubTrue() {
+ return true;
+ }
+ function times(n, iteratee2) {
+ n = toInteger(n);
+ if (n < 1 || n > MAX_SAFE_INTEGER) {
+ return [];
+ }
+ var index = MAX_ARRAY_LENGTH, length = nativeMin(n, MAX_ARRAY_LENGTH);
+ iteratee2 = getIteratee(iteratee2);
+ n -= MAX_ARRAY_LENGTH;
+ var result2 = baseTimes(length, iteratee2);
+ while (++index < n) {
+ iteratee2(index);
+ }
+ return result2;
+ }
+ function toPath(value) {
+ if (isArray(value)) {
+ return arrayMap(value, toKey);
+ }
+ return isSymbol(value) ? [value] : copyArray(stringToPath(toString(value)));
+ }
+ function uniqueId(prefix) {
+ var id = ++idCounter;
+ return toString(prefix) + id;
+ }
+ var add = createMathOperation(function(augend, addend) {
+ return augend + addend;
+ }, 0);
+ var ceil = createRound("ceil");
+ var divide = createMathOperation(function(dividend, divisor) {
+ return dividend / divisor;
+ }, 1);
+ var floor = createRound("floor");
+ function max(array) {
+ return array && array.length ? baseExtremum(array, identity, baseGt) : undefined2;
+ }
+ function maxBy(array, iteratee2) {
+ return array && array.length ? baseExtremum(array, getIteratee(iteratee2, 2), baseGt) : undefined2;
+ }
+ function mean(array) {
+ return baseMean(array, identity);
+ }
+ function meanBy(array, iteratee2) {
+ return baseMean(array, getIteratee(iteratee2, 2));
+ }
+ function min(array) {
+ return array && array.length ? baseExtremum(array, identity, baseLt) : undefined2;
+ }
+ function minBy(array, iteratee2) {
+ return array && array.length ? baseExtremum(array, getIteratee(iteratee2, 2), baseLt) : undefined2;
+ }
+ var multiply = createMathOperation(function(multiplier, multiplicand) {
+ return multiplier * multiplicand;
+ }, 1);
+ var round = createRound("round");
+ var subtract = createMathOperation(function(minuend, subtrahend) {
+ return minuend - subtrahend;
+ }, 0);
+ function sum(array) {
+ return array && array.length ? baseSum(array, identity) : 0;
+ }
+ function sumBy(array, iteratee2) {
+ return array && array.length ? baseSum(array, getIteratee(iteratee2, 2)) : 0;
+ }
+ lodash.after = after;
+ lodash.ary = ary;
+ lodash.assign = assign;
+ lodash.assignIn = assignIn;
+ lodash.assignInWith = assignInWith;
+ lodash.assignWith = assignWith;
+ lodash.at = at;
+ lodash.before = before;
+ lodash.bind = bind;
+ lodash.bindAll = bindAll;
+ lodash.bindKey = bindKey;
+ lodash.castArray = castArray;
+ lodash.chain = chain;
+ lodash.chunk = chunk;
+ lodash.compact = compact;
+ lodash.concat = concat;
+ lodash.cond = cond;
+ lodash.conforms = conforms;
+ lodash.constant = constant;
+ lodash.countBy = countBy;
+ lodash.create = create;
+ lodash.curry = curry;
+ lodash.curryRight = curryRight;
+ lodash.debounce = debounce;
+ lodash.defaults = defaults;
+ lodash.defaultsDeep = defaultsDeep;
+ lodash.defer = defer;
+ lodash.delay = delay;
+ lodash.difference = difference;
+ lodash.differenceBy = differenceBy;
+ lodash.differenceWith = differenceWith;
+ lodash.drop = drop;
+ lodash.dropRight = dropRight;
+ lodash.dropRightWhile = dropRightWhile;
+ lodash.dropWhile = dropWhile;
+ lodash.fill = fill;
+ lodash.filter = filter;
+ lodash.flatMap = flatMap;
+ lodash.flatMapDeep = flatMapDeep;
+ lodash.flatMapDepth = flatMapDepth;
+ lodash.flatten = flatten;
+ lodash.flattenDeep = flattenDeep;
+ lodash.flattenDepth = flattenDepth;
+ lodash.flip = flip;
+ lodash.flow = flow;
+ lodash.flowRight = flowRight;
+ lodash.fromPairs = fromPairs;
+ lodash.functions = functions;
+ lodash.functionsIn = functionsIn;
+ lodash.groupBy = groupBy;
+ lodash.initial = initial;
+ lodash.intersection = intersection;
+ lodash.intersectionBy = intersectionBy;
+ lodash.intersectionWith = intersectionWith;
+ lodash.invert = invert;
+ lodash.invertBy = invertBy;
+ lodash.invokeMap = invokeMap;
+ lodash.iteratee = iteratee;
+ lodash.keyBy = keyBy;
+ lodash.keys = keys;
+ lodash.keysIn = keysIn;
+ lodash.map = map;
+ lodash.mapKeys = mapKeys;
+ lodash.mapValues = mapValues;
+ lodash.matches = matches;
+ lodash.matchesProperty = matchesProperty;
+ lodash.memoize = memoize;
+ lodash.merge = merge;
+ lodash.mergeWith = mergeWith;
+ lodash.method = method;
+ lodash.methodOf = methodOf;
+ lodash.mixin = mixin;
+ lodash.negate = negate;
+ lodash.nthArg = nthArg;
+ lodash.omit = omit;
+ lodash.omitBy = omitBy;
+ lodash.once = once;
+ lodash.orderBy = orderBy;
+ lodash.over = over;
+ lodash.overArgs = overArgs;
+ lodash.overEvery = overEvery;
+ lodash.overSome = overSome;
+ lodash.partial = partial;
+ lodash.partialRight = partialRight;
+ lodash.partition = partition;
+ lodash.pick = pick;
+ lodash.pickBy = pickBy;
+ lodash.property = property;
+ lodash.propertyOf = propertyOf;
+ lodash.pull = pull;
+ lodash.pullAll = pullAll;
+ lodash.pullAllBy = pullAllBy;
+ lodash.pullAllWith = pullAllWith;
+ lodash.pullAt = pullAt;
+ lodash.range = range;
+ lodash.rangeRight = rangeRight;
+ lodash.rearg = rearg;
+ lodash.reject = reject;
+ lodash.remove = remove;
+ lodash.rest = rest;
+ lodash.reverse = reverse;
+ lodash.sampleSize = sampleSize;
+ lodash.set = set2;
+ lodash.setWith = setWith;
+ lodash.shuffle = shuffle;
+ lodash.slice = slice;
+ lodash.sortBy = sortBy;
+ lodash.sortedUniq = sortedUniq;
+ lodash.sortedUniqBy = sortedUniqBy;
+ lodash.split = split;
+ lodash.spread = spread;
+ lodash.tail = tail;
+ lodash.take = take;
+ lodash.takeRight = takeRight;
+ lodash.takeRightWhile = takeRightWhile;
+ lodash.takeWhile = takeWhile;
+ lodash.tap = tap;
+ lodash.throttle = throttle;
+ lodash.thru = thru;
+ lodash.toArray = toArray;
+ lodash.toPairs = toPairs;
+ lodash.toPairsIn = toPairsIn;
+ lodash.toPath = toPath;
+ lodash.toPlainObject = toPlainObject;
+ lodash.transform = transform;
+ lodash.unary = unary;
+ lodash.union = union;
+ lodash.unionBy = unionBy;
+ lodash.unionWith = unionWith;
+ lodash.uniq = uniq;
+ lodash.uniqBy = uniqBy;
+ lodash.uniqWith = uniqWith;
+ lodash.unset = unset;
+ lodash.unzip = unzip;
+ lodash.unzipWith = unzipWith;
+ lodash.update = update;
+ lodash.updateWith = updateWith;
+ lodash.values = values;
+ lodash.valuesIn = valuesIn;
+ lodash.without = without;
+ lodash.words = words;
+ lodash.wrap = wrap;
+ lodash.xor = xor;
+ lodash.xorBy = xorBy;
+ lodash.xorWith = xorWith;
+ lodash.zip = zip;
+ lodash.zipObject = zipObject;
+ lodash.zipObjectDeep = zipObjectDeep;
+ lodash.zipWith = zipWith;
+ lodash.entries = toPairs;
+ lodash.entriesIn = toPairsIn;
+ lodash.extend = assignIn;
+ lodash.extendWith = assignInWith;
+ mixin(lodash, lodash);
+ lodash.add = add;
+ lodash.attempt = attempt;
+ lodash.camelCase = camelCase;
+ lodash.capitalize = capitalize;
+ lodash.ceil = ceil;
+ lodash.clamp = clamp;
+ lodash.clone = clone;
+ lodash.cloneDeep = cloneDeep;
+ lodash.cloneDeepWith = cloneDeepWith;
+ lodash.cloneWith = cloneWith;
+ lodash.conformsTo = conformsTo;
+ lodash.deburr = deburr;
+ lodash.defaultTo = defaultTo;
+ lodash.divide = divide;
+ lodash.endsWith = endsWith;
+ lodash.eq = eq;
+ lodash.escape = escape;
+ lodash.escapeRegExp = escapeRegExp;
+ lodash.every = every;
+ lodash.find = find;
+ lodash.findIndex = findIndex;
+ lodash.findKey = findKey;
+ lodash.findLast = findLast;
+ lodash.findLastIndex = findLastIndex;
+ lodash.findLastKey = findLastKey;
+ lodash.floor = floor;
+ lodash.forEach = forEach;
+ lodash.forEachRight = forEachRight;
+ lodash.forIn = forIn;
+ lodash.forInRight = forInRight;
+ lodash.forOwn = forOwn;
+ lodash.forOwnRight = forOwnRight;
+ lodash.get = get;
+ lodash.gt = gt;
+ lodash.gte = gte;
+ lodash.has = has;
+ lodash.hasIn = hasIn;
+ lodash.head = head;
+ lodash.identity = identity;
+ lodash.includes = includes;
+ lodash.indexOf = indexOf;
+ lodash.inRange = inRange;
+ lodash.invoke = invoke;
+ lodash.isArguments = isArguments;
+ lodash.isArray = isArray;
+ lodash.isArrayBuffer = isArrayBuffer;
+ lodash.isArrayLike = isArrayLike;
+ lodash.isArrayLikeObject = isArrayLikeObject;
+ lodash.isBoolean = isBoolean;
+ lodash.isBuffer = isBuffer;
+ lodash.isDate = isDate;
+ lodash.isElement = isElement;
+ lodash.isEmpty = isEmpty;
+ lodash.isEqual = isEqual;
+ lodash.isEqualWith = isEqualWith;
+ lodash.isError = isError;
+ lodash.isFinite = isFinite;
+ lodash.isFunction = isFunction;
+ lodash.isInteger = isInteger;
+ lodash.isLength = isLength;
+ lodash.isMap = isMap;
+ lodash.isMatch = isMatch;
+ lodash.isMatchWith = isMatchWith;
+ lodash.isNaN = isNaN;
+ lodash.isNative = isNative;
+ lodash.isNil = isNil;
+ lodash.isNull = isNull;
+ lodash.isNumber = isNumber;
+ lodash.isObject = isObject;
+ lodash.isObjectLike = isObjectLike;
+ lodash.isPlainObject = isPlainObject;
+ lodash.isRegExp = isRegExp;
+ lodash.isSafeInteger = isSafeInteger;
+ lodash.isSet = isSet;
+ lodash.isString = isString;
+ lodash.isSymbol = isSymbol;
+ lodash.isTypedArray = isTypedArray;
+ lodash.isUndefined = isUndefined;
+ lodash.isWeakMap = isWeakMap;
+ lodash.isWeakSet = isWeakSet;
+ lodash.join = join;
+ lodash.kebabCase = kebabCase;
+ lodash.last = last;
+ lodash.lastIndexOf = lastIndexOf;
+ lodash.lowerCase = lowerCase;
+ lodash.lowerFirst = lowerFirst;
+ lodash.lt = lt;
+ lodash.lte = lte;
+ lodash.max = max;
+ lodash.maxBy = maxBy;
+ lodash.mean = mean;
+ lodash.meanBy = meanBy;
+ lodash.min = min;
+ lodash.minBy = minBy;
+ lodash.stubArray = stubArray;
+ lodash.stubFalse = stubFalse;
+ lodash.stubObject = stubObject;
+ lodash.stubString = stubString;
+ lodash.stubTrue = stubTrue;
+ lodash.multiply = multiply;
+ lodash.nth = nth;
+ lodash.noConflict = noConflict;
+ lodash.noop = noop;
+ lodash.now = now;
+ lodash.pad = pad;
+ lodash.padEnd = padEnd;
+ lodash.padStart = padStart;
+ lodash.parseInt = parseInt2;
+ lodash.random = random;
+ lodash.reduce = reduce;
+ lodash.reduceRight = reduceRight;
+ lodash.repeat = repeat;
+ lodash.replace = replace;
+ lodash.result = result;
+ lodash.round = round;
+ lodash.runInContext = runInContext2;
+ lodash.sample = sample;
+ lodash.size = size;
+ lodash.snakeCase = snakeCase;
+ lodash.some = some;
+ lodash.sortedIndex = sortedIndex;
+ lodash.sortedIndexBy = sortedIndexBy;
+ lodash.sortedIndexOf = sortedIndexOf;
+ lodash.sortedLastIndex = sortedLastIndex;
+ lodash.sortedLastIndexBy = sortedLastIndexBy;
+ lodash.sortedLastIndexOf = sortedLastIndexOf;
+ lodash.startCase = startCase;
+ lodash.startsWith = startsWith;
+ lodash.subtract = subtract;
+ lodash.sum = sum;
+ lodash.sumBy = sumBy;
+ lodash.template = template;
+ lodash.times = times;
+ lodash.toFinite = toFinite;
+ lodash.toInteger = toInteger;
+ lodash.toLength = toLength;
+ lodash.toLower = toLower;
+ lodash.toNumber = toNumber;
+ lodash.toSafeInteger = toSafeInteger;
+ lodash.toString = toString;
+ lodash.toUpper = toUpper;
+ lodash.trim = trim;
+ lodash.trimEnd = trimEnd;
+ lodash.trimStart = trimStart;
+ lodash.truncate = truncate;
+ lodash.unescape = unescape;
+ lodash.uniqueId = uniqueId;
+ lodash.upperCase = upperCase;
+ lodash.upperFirst = upperFirst;
+ lodash.each = forEach;
+ lodash.eachRight = forEachRight;
+ lodash.first = head;
+ mixin(lodash, function() {
+ var source = {};
+ baseForOwn(lodash, function(func, methodName) {
+ if (!hasOwnProperty.call(lodash.prototype, methodName)) {
+ source[methodName] = func;
+ }
+ });
+ return source;
+ }(), { "chain": false });
+ lodash.VERSION = VERSION;
+ arrayEach(["bind", "bindKey", "curry", "curryRight", "partial", "partialRight"], function(methodName) {
+ lodash[methodName].placeholder = lodash;
+ });
+ arrayEach(["drop", "take"], function(methodName, index) {
+ LazyWrapper.prototype[methodName] = function(n) {
+ n = n === undefined2 ? 1 : nativeMax(toInteger(n), 0);
+ var result2 = this.__filtered__ && !index ? new LazyWrapper(this) : this.clone();
+ if (result2.__filtered__) {
+ result2.__takeCount__ = nativeMin(n, result2.__takeCount__);
+ } else {
+ result2.__views__.push({
+ "size": nativeMin(n, MAX_ARRAY_LENGTH),
+ "type": methodName + (result2.__dir__ < 0 ? "Right" : "")
+ });
+ }
+ return result2;
+ };
+ LazyWrapper.prototype[methodName + "Right"] = function(n) {
+ return this.reverse()[methodName](n).reverse();
+ };
+ });
+ arrayEach(["filter", "map", "takeWhile"], function(methodName, index) {
+ var type = index + 1, isFilter = type == LAZY_FILTER_FLAG || type == LAZY_WHILE_FLAG;
+ LazyWrapper.prototype[methodName] = function(iteratee2) {
+ var result2 = this.clone();
+ result2.__iteratees__.push({
+ "iteratee": getIteratee(iteratee2, 3),
+ "type": type
+ });
+ result2.__filtered__ = result2.__filtered__ || isFilter;
+ return result2;
+ };
+ });
+ arrayEach(["head", "last"], function(methodName, index) {
+ var takeName = "take" + (index ? "Right" : "");
+ LazyWrapper.prototype[methodName] = function() {
+ return this[takeName](1).value()[0];
+ };
+ });
+ arrayEach(["initial", "tail"], function(methodName, index) {
+ var dropName = "drop" + (index ? "" : "Right");
+ LazyWrapper.prototype[methodName] = function() {
+ return this.__filtered__ ? new LazyWrapper(this) : this[dropName](1);
+ };
+ });
+ LazyWrapper.prototype.compact = function() {
+ return this.filter(identity);
+ };
+ LazyWrapper.prototype.find = function(predicate) {
+ return this.filter(predicate).head();
+ };
+ LazyWrapper.prototype.findLast = function(predicate) {
+ return this.reverse().find(predicate);
+ };
+ LazyWrapper.prototype.invokeMap = baseRest(function(path, args) {
+ if (typeof path == "function") {
+ return new LazyWrapper(this);
+ }
+ return this.map(function(value) {
+ return baseInvoke(value, path, args);
+ });
+ });
+ LazyWrapper.prototype.reject = function(predicate) {
+ return this.filter(negate(getIteratee(predicate)));
+ };
+ LazyWrapper.prototype.slice = function(start, end) {
+ start = toInteger(start);
+ var result2 = this;
+ if (result2.__filtered__ && (start > 0 || end < 0)) {
+ return new LazyWrapper(result2);
+ }
+ if (start < 0) {
+ result2 = result2.takeRight(-start);
+ } else if (start) {
+ result2 = result2.drop(start);
+ }
+ if (end !== undefined2) {
+ end = toInteger(end);
+ result2 = end < 0 ? result2.dropRight(-end) : result2.take(end - start);
+ }
+ return result2;
+ };
+ LazyWrapper.prototype.takeRightWhile = function(predicate) {
+ return this.reverse().takeWhile(predicate).reverse();
+ };
+ LazyWrapper.prototype.toArray = function() {
+ return this.take(MAX_ARRAY_LENGTH);
+ };
+ baseForOwn(LazyWrapper.prototype, function(func, methodName) {
+ var checkIteratee = /^(?:filter|find|map|reject)|While$/.test(methodName), isTaker = /^(?:head|last)$/.test(methodName), lodashFunc = lodash[isTaker ? "take" + (methodName == "last" ? "Right" : "") : methodName], retUnwrapped = isTaker || /^find/.test(methodName);
+ if (!lodashFunc) {
+ return;
+ }
+ lodash.prototype[methodName] = function() {
+ var value = this.__wrapped__, args = isTaker ? [1] : arguments, isLazy = value instanceof LazyWrapper, iteratee2 = args[0], useLazy = isLazy || isArray(value);
+ var interceptor = function(value2) {
+ var result3 = lodashFunc.apply(lodash, arrayPush([value2], args));
+ return isTaker && chainAll ? result3[0] : result3;
+ };
+ if (useLazy && checkIteratee && typeof iteratee2 == "function" && iteratee2.length != 1) {
+ isLazy = useLazy = false;
+ }
+ var chainAll = this.__chain__, isHybrid = !!this.__actions__.length, isUnwrapped = retUnwrapped && !chainAll, onlyLazy = isLazy && !isHybrid;
+ if (!retUnwrapped && useLazy) {
+ value = onlyLazy ? value : new LazyWrapper(this);
+ var result2 = func.apply(value, args);
+ result2.__actions__.push({ "func": thru, "args": [interceptor], "thisArg": undefined2 });
+ return new LodashWrapper(result2, chainAll);
+ }
+ if (isUnwrapped && onlyLazy) {
+ return func.apply(this, args);
+ }
+ result2 = this.thru(interceptor);
+ return isUnwrapped ? isTaker ? result2.value()[0] : result2.value() : result2;
+ };
+ });
+ arrayEach(["pop", "push", "shift", "sort", "splice", "unshift"], function(methodName) {
+ var func = arrayProto[methodName], chainName = /^(?:push|sort|unshift)$/.test(methodName) ? "tap" : "thru", retUnwrapped = /^(?:pop|shift)$/.test(methodName);
+ lodash.prototype[methodName] = function() {
+ var args = arguments;
+ if (retUnwrapped && !this.__chain__) {
+ var value = this.value();
+ return func.apply(isArray(value) ? value : [], args);
+ }
+ return this[chainName](function(value2) {
+ return func.apply(isArray(value2) ? value2 : [], args);
+ });
+ };
+ });
+ baseForOwn(LazyWrapper.prototype, function(func, methodName) {
+ var lodashFunc = lodash[methodName];
+ if (lodashFunc) {
+ var key = lodashFunc.name + "";
+ if (!hasOwnProperty.call(realNames, key)) {
+ realNames[key] = [];
+ }
+ realNames[key].push({ "name": methodName, "func": lodashFunc });
+ }
+ });
+ realNames[createHybrid(undefined2, WRAP_BIND_KEY_FLAG).name] = [{
+ "name": "wrapper",
+ "func": undefined2
+ }];
+ LazyWrapper.prototype.clone = lazyClone;
+ LazyWrapper.prototype.reverse = lazyReverse;
+ LazyWrapper.prototype.value = lazyValue;
+ lodash.prototype.at = wrapperAt;
+ lodash.prototype.chain = wrapperChain;
+ lodash.prototype.commit = wrapperCommit;
+ lodash.prototype.next = wrapperNext;
+ lodash.prototype.plant = wrapperPlant;
+ lodash.prototype.reverse = wrapperReverse;
+ lodash.prototype.toJSON = lodash.prototype.valueOf = lodash.prototype.value = wrapperValue;
+ lodash.prototype.first = lodash.prototype.head;
+ if (symIterator) {
+ lodash.prototype[symIterator] = wrapperToIterator;
+ }
+ return lodash;
+ };
+ var _3 = runInContext();
+ if (typeof define == "function" && typeof define.amd == "object" && define.amd) {
+ root._ = _3;
+ define(function() {
+ return _3;
+ });
+ } else if (freeModule) {
+ (freeModule.exports = _3)._ = _3;
+ freeExports._ = _3;
+ } else {
+ root._ = _3;
+ }
+ }).call(exports);
+ }
+ });
+
// ../../../AppData/Local/Temp/spicetify-creator/index.jsx
var spicetify_creator_exports = {};
__export(spicetify_creator_exports, {
@@ -47,7 +5485,7 @@ var stats = (() => {
});
// src/app.tsx
- var import_react29 = __toESM(require_react());
+ var import_react30 = __toESM(require_react());
// ../node_modules/spcr-navigation-bar/useNavigationBar.tsx
var import_react3 = __toESM(require_react());
@@ -105,7 +5543,7 @@ var stats = (() => {
});
var optionsMenu_default = OptionsMenu;
- // postcss-module:C:\Users\user\AppData\Local\Temp\tmp-17120-n3iWRzissBjg\18f3cbbb4bc3\navBar.module.css
+ // postcss-module:C:\Users\user\AppData\Local\Temp\tmp-8216-VCWpAfv0Bkqy\1909217e9563\navBar.module.css
var navBar_module_default = { "topBarHeaderItem": "navBar-module__topBarHeaderItem___piw4C_stats", "topBarHeaderItemLink": "navBar-module__topBarHeaderItemLink___xA4uv_stats", "topBarActive": "navBar-module__topBarActive___XhWpm_stats", "topBarNav": "navBar-module__topBarNav___qWGeZ_stats", "optionsMenuDropBox": "navBar-module__optionsMenuDropBox___pzfNI_stats" };
// ../node_modules/spcr-navigation-bar/navBar.tsx
@@ -208,7 +5646,7 @@ var stats = (() => {
}, /* @__PURE__ */ import_react2.default.createElement("ul", {
className: navBar_module_default.topBarHeader,
ref: navBarListRef
- }, items.filter((_, id) => !outOfRangeItemIndexes.includes(id)).map(
+ }, items.filter((_3, id) => !outOfRangeItemIndexes.includes(id)).map(
(item) => /* @__PURE__ */ import_react2.default.createElement(NavbarItemComponent, {
item,
switchTo: props.switchCallback
@@ -233,7 +5671,7 @@ var stats = (() => {
var useNavigationBar_default = useNavigationBar;
// src/pages/top_artists.tsx
- var import_react17 = __toESM(require_react());
+ var import_react18 = __toESM(require_react());
// ../shared/dropdown/useDropdownMenu.tsx
var import_react5 = __toESM(require_react());
@@ -491,8 +5929,7 @@ var stats = (() => {
const { Cards, TextComponent, ArtistMenu, AlbumMenu, PodcastShowMenu, PlaylistMenu, ContextMenu } = Spicetify.ReactComponent;
const { FeatureCard: Card, CardImage } = Cards;
const { createHref, push } = Spicetify.Platform.History;
- const { type, header, uri, imageUrl, subheader, artistUri } = props;
- const backupImageUrl = type === "folder" || type === "collection" ? "https://raw.githubusercontent.com/harbassan/spicetify-apps/main/shared/placeholders/folder_placeholder.png" : "https://raw.githubusercontent.com/harbassan/spicetify-apps/main/shared/placeholders/def_placeholder.png";
+ const { type, header, uri, imageUrl, subheader, artistUri, badge, provider } = props;
const Menu = () => {
switch (type) {
case "artist":
@@ -525,7 +5962,11 @@ var stats = (() => {
return /* @__PURE__ */ import_react11.default.createElement(import_react11.default.Fragment, null);
}
};
- const lastfmProps = type === "lastfm" ? { onClick: () => window.open(uri, "_blank"), isPlayable: false, delegateNavigation: true } : {};
+ const lastfmProps = provider === "lastfm" ? {
+ onClick: () => window.open(uri, "_blank"),
+ isPlayable: false,
+ delegateNavigation: true
+ } : {};
const folderProps = type === "folder" ? {
delegateNavigation: true,
onClick: () => {
@@ -543,6 +5984,8 @@ var stats = (() => {
return /* @__PURE__ */ import_react11.default.createElement(ContextMenu, {
menu: Menu(),
trigger: "right-click"
+ }, /* @__PURE__ */ import_react11.default.createElement("div", {
+ style: { position: "relative" }
}, /* @__PURE__ */ import_react11.default.createElement(Card, {
featureIdentifier: type,
headerText: header,
@@ -555,7 +5998,7 @@ var stats = (() => {
}
],
isCircular: type === "artist",
- FallbackComponent: folder_fallback_default
+ FallbackComponent: type === "folder" || type === "collection" ? folder_fallback_default : void 0
}),
renderSubHeaderContent: () => /* @__PURE__ */ import_react11.default.createElement(TextComponent, {
as: "div",
@@ -567,350 +6010,17 @@ var stats = (() => {
...lastfmProps,
...folderProps,
...collectionProps
- }));
+ }), badge && /* @__PURE__ */ import_react11.default.createElement("div", {
+ className: "badge"
+ }, badge)));
}
var spotify_card_default = SpotifyCard;
- // src/endpoints.ts
- var lfmperiods = {
- short_term: "1month",
- medium_term: "6month",
- long_term: "overall"
- };
- var LASTFM = {
- toptracks: (user, key, range) => `http://ws.audioscrobbler.com/2.0/?method=user.gettoptracks&user=${user}&api_key=${key}&format=json&period=${lfmperiods[range]}`,
- topalbums: (user, key, range) => `https://ws.audioscrobbler.com/2.0/?method=user.gettopalbums&user=${user}&api_key=${key}&format=json&period=${lfmperiods[range]}`,
- topartists: (user, key, range) => `https://ws.audioscrobbler.com/2.0/?method=user.gettopartists&user=${user}&api_key=${key}&format=json&period=${lfmperiods[range]}`,
- charts: (key, type) => `http://ws.audioscrobbler.com/2.0/?method=chart.gettop${type}&api_key=${key}&format=json`
- };
- var SPOTIFY = {
- toptracks: (range) => `https://api.spotify.com/v1/me/top/tracks?limit=50&offset=0&time_range=${range}`,
- topartists: (range) => `https://api.spotify.com/v1/me/top/artists?limit=50&offset=0&time_range=${range}`,
- artists: (artists) => `https://api.spotify.com/v1/artists?ids=${filter(artists)}`,
- rootlist: "sp://core-playlist/v1/rootlist",
- playlist: (uri) => `sp://core-playlist/v1/playlist/${uri}`,
- search: (track, artist) => `https://api.spotify.com/v1/search?q=track:${filter(track)}+artist:${filter(artist)}&type=track`,
- searchartist: (artist) => `https://api.spotify.com/v1/search?q=artist:${filter(artist)}&type=artist`,
- searchalbum: (album, artist) => `https://api.spotify.com/v1/search?q=${filter(album)}+artist:${filter(artist)}&type=album`,
- audiofeatures: (ids) => `https://api.spotify.com/v1/audio-features?ids=${ids}`,
- queryliked: (ids) => `https://api.spotify.com/v1/me/tracks/contains?ids=${ids}`
- };
- var PLACEHOLDER = "https://raw.githubusercontent.com/harbassan/spicetify-apps/main/stats/src/styles/placeholder.png";
-
- // src/funcs.ts
- function filter(str) {
- const normalizedStr = str.normalize("NFD").replace(/[\u0300-\u036f]/g, "");
- return normalizedStr.replace(/[^a-zA-Z0-9\-._~:/?#[\]@!$&()*+,;= ]/g, "").replace(/ /g, "+");
- }
- var updatePageCache = (i, callback, activeOption, lib = false) => {
- let cacheInfo = Spicetify.LocalStorage.get("stats:cache-info");
- if (!cacheInfo)
- return;
- let cacheInfoArray = JSON.parse(cacheInfo);
- if (!cacheInfoArray[i]) {
- if (!lib) {
- ["short_term", "medium_term", "long_term"].filter((option) => option !== activeOption).forEach((option) => callback(option, true, false));
- }
- if (lib === "charts") {
- ["artists", "tracks"].filter((option) => option !== activeOption).forEach((option) => callback(option, true, false));
- }
- callback(activeOption, true);
- cacheInfoArray[i] = true;
- Spicetify.LocalStorage.set("stats:cache-info", JSON.stringify(cacheInfoArray));
- }
- };
- var apiRequest = async (name, url, timeout = 5, log = true) => {
- try {
- const timeStart = window.performance.now();
- const response = await Spicetify.CosmosAsync.get(url);
- if (log)
- console.log("stats -", name, "fetch time:", window.performance.now() - timeStart);
- return response;
- } catch (e) {
- if (timeout === 0) {
- console.log("stats -", name, "all requests failed:", e);
- console.log("stats -", name, "giving up");
- return null;
- } else {
- if (timeout === 5) {
- console.log("stats -", name, "request failed:", e);
- console.log("stats -", name, "retrying...");
- }
- await new Promise((resolve) => setTimeout(resolve, 5e3));
- return apiRequest(name, url, timeout - 1);
- }
- }
- };
- var fetchAudioFeatures = async (ids) => {
- const batchSize = 100;
- const batches = [];
- ids = ids.filter((id) => id.match(/^[a-zA-Z0-9]{22}$/));
- for (let i = 0; i < ids.length; i += batchSize) {
- const batch = ids.slice(i, i + batchSize);
- batches.push(batch);
- }
- const promises = batches.map((batch, index) => {
- return apiRequest(`audioFeaturesBatch${index}`, SPOTIFY.audiofeatures(batch.join(",")), 5, false);
- });
- const responses = await Promise.all(promises);
- const data = responses.reduce((acc, response) => {
- if (!response?.audio_features)
- return acc;
- return acc.concat(response.audio_features);
- }, []);
- return data;
- };
- var fetchTopAlbums = async (albums, cachedAlbums) => {
- let album_keys = Object.keys(albums).filter((id) => id.match(/^[a-zA-Z0-9]{22}$/)).sort((a, b) => albums[b] - albums[a]).slice(0, 100);
- let release_years = {};
- let total_album_tracks = 0;
- const cachedAlbumsSet = new Set(cachedAlbums?.map((album) => album.uri));
- let top_albums = await Promise.all(
- album_keys.map(async (albumID) => {
- let albumMeta;
- if (cachedAlbums && cachedAlbumsSet.has(`spotify:album:${albumID}`)) {
- albumMeta = cachedAlbums.find((album) => album.uri === `spotify:album:${albumID}`);
- }
- if (!albumMeta) {
- try {
- albumMeta = await Spicetify.GraphQL.Request(Spicetify.GraphQL.Definitions.getAlbum, {
- uri: `spotify:album:${albumID}`,
- locale: "en",
- offset: 0,
- limit: 50
- });
- if (!albumMeta?.data?.albumUnion?.name)
- throw new Error("Invalid URI");
- } catch (e) {
- console.error("stats - album metadata request failed:", e);
- return;
- }
- }
- const releaseYear = albumMeta?.release_year || albumMeta.data.albumUnion.date.isoString.slice(0, 4);
- release_years[releaseYear] = (release_years[releaseYear] || 0) + albums[albumID];
- total_album_tracks += albums[albumID];
- return {
- name: albumMeta.name || albumMeta.data.albumUnion.name,
- uri: albumMeta.uri || albumMeta.data.albumUnion.uri,
- image: albumMeta.image || albumMeta.data.albumUnion.coverArt.sources[0]?.url || PLACEHOLDER,
- release_year: releaseYear,
- freq: albums[albumID]
- };
- })
- );
- top_albums = top_albums.filter((el) => el != null).slice(0, 10);
- return [top_albums, Object.entries(release_years), total_album_tracks];
- };
- var fetchTopArtists = async (artists) => {
- if (Object.keys(artists).length === 0)
- return [[], [], 0];
- let artist_keys = Object.keys(artists).filter((id) => id.match(/^[a-zA-Z0-9]{22}$/)).sort((a, b) => artists[b] - artists[a]).slice(0, 50);
- let genres = {};
- let total_genre_tracks = 0;
- const artistsMeta = await apiRequest("artistsMetadata", SPOTIFY.artists(artist_keys.join(",")));
- let top_artists = artistsMeta?.artists?.map((artist) => {
- if (!artist)
- return null;
- artist.genres.forEach((genre) => {
- genres[genre] = (genres[genre] || 0) + artists[artist.id];
- });
- total_genre_tracks += artists[artist.id];
- return {
- name: artist.name,
- uri: artist.uri,
- image: artist.images[2]?.url || PLACEHOLDER,
- freq: artists[artist.id]
- };
- });
- top_artists = top_artists.filter((el) => el != null).slice(0, 10);
- const top_genres = Object.entries(genres).sort((a, b) => b[1] - a[1]).slice(0, 10);
- return [top_artists, top_genres, total_genre_tracks];
- };
- var convertTrackData = async (data) => {
- return await Promise.all(
- data.map(async (item) => {
- const spotifyItem = await Spicetify.CosmosAsync.get(SPOTIFY.search(item.name, item.artist.name)).then(
- (res) => res.tracks?.items[0]
- );
- if (!spotifyItem) {
- console.log(`couldn't find track: ${item.name} by ${item.artist.name}`);
- return {
- name: item.name,
- image: PLACEHOLDER,
- uri: item.url,
- artists: [{ name: item.artist.name, uri: item.artist.url }],
- duration: 0,
- album: "N/A",
- popularity: 0,
- explicit: false,
- album_uri: item.url
- };
- }
- return {
- name: item.name,
- image: spotifyItem.album.images[0].url,
- uri: spotifyItem.uri,
- id: spotifyItem.id,
- artists: spotifyItem.artists.map((artist) => ({ name: artist.name, uri: artist.uri })),
- duration: spotifyItem.duration_ms,
- album: spotifyItem.album.name,
- popularity: spotifyItem.popularity,
- explicit: spotifyItem.explicit,
- album_uri: spotifyItem.album.uri,
- release_year: spotifyItem.album.release_date.slice(0, 4)
- };
- })
- );
- };
- var convertAlbumData = async (data) => {
- return await Promise.all(
- data.map(async (item) => {
- const spotifyItem = await Spicetify.CosmosAsync.get(SPOTIFY.searchalbum(item.name, item.artist.name)).then(
- (res) => res.albums?.items[0]
- );
- if (!spotifyItem) {
- console.log(`couldn't find album: ${item.name} by ${item.artist.name}`);
- return {
- name: item.name,
- image: PLACEHOLDER,
- uri: item.url,
- id: item.mbid
- };
- }
- return {
- name: item.name,
- image: spotifyItem.images[0].url,
- uri: spotifyItem.uri,
- id: spotifyItem.id
- };
- })
- );
- };
- var convertArtistData = async (data) => {
- return await Promise.all(
- data.map(async (item) => {
- const spotifyItem = await Spicetify.CosmosAsync.get(SPOTIFY.searchartist(item.name)).then(
- (res) => res.artists?.items[0]
- );
- if (!spotifyItem) {
- console.log(`couldn't find artist: ${item.name}`);
- return {
- name: item.name,
- image: PLACEHOLDER,
- uri: item.url,
- id: item.mbid
- };
- }
- return {
- name: item.name,
- image: spotifyItem.images[0].url,
- uri: spotifyItem.uri,
- id: spotifyItem.id,
- genres: spotifyItem.genres
- };
- })
- );
- };
- var checkLiked = async (tracks) => {
- const nullIndexes = [];
- tracks.forEach((track, index) => {
- if (track === null) {
- nullIndexes.push(index);
- }
- });
- const apiResponse = await apiRequest("checkLiked", SPOTIFY.queryliked(tracks.filter((e) => e).join(",")));
- if (!apiResponse)
- return;
- const response = [];
- let nullIndexesIndex = 0;
- for (let i = 0; i < tracks.length; i++) {
- if (nullIndexes.includes(i)) {
- response.push(false);
- } else {
- response.push(apiResponse[nullIndexesIndex]);
- nullIndexesIndex++;
- }
- }
- return response;
- };
- async function queue(list, context = null) {
- list.push("spotify:delimiter");
- const { _queue, _client } = Spicetify.Platform.PlayerAPI._queue;
- const { prevTracks, queueRevision } = _queue;
- const nextTracks = list.map((uri) => ({
- contextTrack: {
- uri,
- uid: "",
- metadata: {
- is_queued: "false"
- }
- },
- removed: [],
- blocked: [],
- provider: "context"
- }));
- _client.setQueue({
- nextTracks,
- prevTracks,
- queueRevision
- });
- if (context) {
- const { sessionId } = Spicetify.Platform.PlayerAPI.getState();
- Spicetify.Platform.PlayerAPI.updateContext(sessionId, {
- uri: `spotify:user:${Spicetify.Platform.LibraryAPI._currentUsername}:top:tracks`,
- url: ""
- });
- }
- Spicetify.Player.next();
- }
-
- // ../shared/components/status.tsx
- var import_react12 = __toESM(require_react());
- var ErrorIcon = () => {
- return /* @__PURE__ */ import_react12.default.createElement("svg", {
- "data-encore-id": "icon",
- role: "img",
- "aria-hidden": "true",
- viewBox: "0 0 24 24",
- className: "status-icon"
- }, /* @__PURE__ */ import_react12.default.createElement("path", {
- d: "M11 18v-2h2v2h-2zm0-4V6h2v8h-2z"
- }), /* @__PURE__ */ import_react12.default.createElement("path", {
- d: "M12 3a9 9 0 1 0 0 18 9 9 0 0 0 0-18zM1 12C1 5.925 5.925 1 12 1s11 4.925 11 11-4.925 11-11 11S1 18.075 1 12z"
- }));
- };
- var LibraryIcon = () => {
- return /* @__PURE__ */ import_react12.default.createElement("svg", {
- role: "img",
- height: "46",
- width: "46",
- "aria-hidden": "true",
- viewBox: "0 0 24 24",
- "data-encore-id": "icon",
- className: "status-icon"
- }, /* @__PURE__ */ import_react12.default.createElement("path", {
- d: "M14.5 2.134a1 1 0 0 1 1 0l6 3.464a1 1 0 0 1 .5.866V21a1 1 0 0 1-1 1h-6a1 1 0 0 1-1-1V3a1 1 0 0 1 .5-.866zM16 4.732V20h4V7.041l-4-2.309zM3 22a1 1 0 0 1-1-1V3a1 1 0 0 1 2 0v18a1 1 0 0 1-1 1zm6 0a1 1 0 0 1-1-1V3a1 1 0 0 1 2 0v18a1 1 0 0 1-1 1z"
- }));
- };
- var Status = (props) => {
- const [isVisible, setIsVisible] = import_react12.default.useState(false);
- import_react12.default.useEffect(() => {
- const to = setTimeout(() => {
- setIsVisible(true);
- }, 500);
- return () => clearTimeout(to);
- }, []);
- return isVisible ? /* @__PURE__ */ import_react12.default.createElement(import_react12.default.Fragment, null, /* @__PURE__ */ import_react12.default.createElement("div", {
- className: "loadingWrapper"
- }, props.icon === "error" ? /* @__PURE__ */ import_react12.default.createElement(ErrorIcon, null) : /* @__PURE__ */ import_react12.default.createElement(LibraryIcon, null), /* @__PURE__ */ import_react12.default.createElement("h1", null, props.heading), /* @__PURE__ */ import_react12.default.createElement("h3", null, props.subheading))) : /* @__PURE__ */ import_react12.default.createElement(import_react12.default.Fragment, null);
- };
- var status_default = Status;
-
// ../shared/components/page_container.tsx
- var import_react14 = __toESM(require_react());
+ var import_react13 = __toESM(require_react());
// src/components/buttons/create_playlist_button.tsx
- var import_react13 = __toESM(require_react());
+ var import_react12 = __toESM(require_react());
async function createPlaylistAsync(infoToCreatePlaylist) {
const { Platform, showNotification } = Spicetify;
const { RootlistAPI, PlaylistAPI } = Platform;
@@ -926,11 +6036,11 @@ var stats = (() => {
function CreatePlaylistButton(props) {
const { TooltipWrapper, ButtonSecondary } = Spicetify.ReactComponent;
const { infoToCreatePlaylist } = props;
- return /* @__PURE__ */ import_react13.default.createElement(TooltipWrapper, {
+ return /* @__PURE__ */ import_react12.default.createElement(TooltipWrapper, {
label: "Turn Into Playlist",
renderInline: true,
placement: "top"
- }, /* @__PURE__ */ import_react13.default.createElement(ButtonSecondary, {
+ }, /* @__PURE__ */ import_react12.default.createElement(ButtonSecondary, {
"aria-label": "Turn Into Playlist",
children: "Turn Into Playlist",
semanticColor: "textBase",
@@ -945,31 +6055,31 @@ var stats = (() => {
var PageContainer = (props) => {
const { title, infoToCreatePlaylist, headerEls, children } = props;
const { TextComponent } = Spicetify.ReactComponent;
- return /* @__PURE__ */ import_react14.default.createElement("section", {
+ return /* @__PURE__ */ import_react13.default.createElement("section", {
className: "contentSpacing"
- }, /* @__PURE__ */ import_react14.default.createElement("div", {
+ }, /* @__PURE__ */ import_react13.default.createElement("div", {
className: "page-header"
- }, /* @__PURE__ */ import_react14.default.createElement("div", {
+ }, /* @__PURE__ */ import_react13.default.createElement("div", {
className: "header-left"
- }, /* @__PURE__ */ import_react14.default.createElement(TextComponent, {
+ }, /* @__PURE__ */ import_react13.default.createElement(TextComponent, {
children: title,
as: "h1",
variant: "canon",
semanticColor: "textBase"
- }), infoToCreatePlaylist ? /* @__PURE__ */ import_react14.default.createElement(create_playlist_button_default, {
+ }), infoToCreatePlaylist ? /* @__PURE__ */ import_react13.default.createElement(create_playlist_button_default, {
infoToCreatePlaylist
- }) : null), /* @__PURE__ */ import_react14.default.createElement("div", {
+ }) : null), /* @__PURE__ */ import_react13.default.createElement("div", {
className: "header-right"
- }, headerEls)), /* @__PURE__ */ import_react14.default.createElement("div", {
+ }, headerEls)), /* @__PURE__ */ import_react13.default.createElement("div", {
className: "page-content"
}, children));
};
var page_container_default = PageContainer;
// ../shared/components/settings_button.tsx
- var import_react15 = __toESM(require_react());
+ var import_react14 = __toESM(require_react());
function SettingsIcon() {
- return /* @__PURE__ */ import_react15.default.createElement(Spicetify.ReactComponent.IconComponent, {
+ return /* @__PURE__ */ import_react14.default.createElement(Spicetify.ReactComponent.IconComponent, {
semanticColor: "textSubdued",
dangerouslySetInnerHTML: {
__html: ''
@@ -980,11 +6090,11 @@ var stats = (() => {
function SettingsButton(props) {
const { TooltipWrapper, ButtonTertiary } = Spicetify.ReactComponent;
const { configWrapper } = props;
- return /* @__PURE__ */ import_react15.default.createElement(TooltipWrapper, {
+ return /* @__PURE__ */ import_react14.default.createElement(TooltipWrapper, {
label: "Settings",
renderInline: true,
placement: "top"
- }, /* @__PURE__ */ import_react15.default.createElement(ButtonTertiary, {
+ }, /* @__PURE__ */ import_react14.default.createElement(ButtonTertiary, {
buttonSize: "sm",
onClick: configWrapper.launchModal,
"aria-label": "Settings",
@@ -994,9 +6104,9 @@ var stats = (() => {
var settings_button_default = SettingsButton;
// src/components/buttons/refresh_button.tsx
- var import_react16 = __toESM(require_react());
+ var import_react15 = __toESM(require_react());
function RefreshIcon() {
- return /* @__PURE__ */ import_react16.default.createElement(Spicetify.ReactComponent.IconComponent, {
+ return /* @__PURE__ */ import_react15.default.createElement(Spicetify.ReactComponent.IconComponent, {
semanticColor: "textSubdued",
iconSize: 16,
dangerouslySetInnerHTML: {
@@ -1007,11 +6117,11 @@ var stats = (() => {
function RefreshButton(props) {
const { ButtonTertiary, TooltipWrapper } = Spicetify.ReactComponent;
const { callback } = props;
- return /* @__PURE__ */ import_react16.default.createElement(TooltipWrapper, {
+ return /* @__PURE__ */ import_react15.default.createElement(TooltipWrapper, {
label: "Refresh",
renderInline: true,
placement: "top"
- }, /* @__PURE__ */ import_react16.default.createElement(ButtonTertiary, {
+ }, /* @__PURE__ */ import_react15.default.createElement(ButtonTertiary, {
buttonSize: "sm",
onClick: callback,
"aria-label": "Refresh",
@@ -1020,330 +6130,369 @@ var stats = (() => {
}
var refresh_button_default = RefreshButton;
- // src/pages/top_artists.tsx
- var topArtistsReq = async (time_range, configWrapper) => {
- const { config } = configWrapper;
- if (config["use-lastfm"] === true) {
- if (!config["api-key"] || !config["lastfm-user"])
- return 300;
- const { ["lastfm-user"]: user, ["api-key"]: key } = config;
- const response = await apiRequest("lastfm", LASTFM.topartists(user, key, time_range));
- if (!response)
- return 200;
- return await convertArtistData(response.topartists.artist);
- } else {
- const response = await apiRequest("topArtists", SPOTIFY.topartists(time_range));
- if (!response)
- return 200;
- return response.items.map((artist) => {
- const image = artist.images[2]?.url || artist.images[1]?.url || PLACEHOLDER;
- return {
- id: artist.id,
- name: artist.name,
- image,
- uri: artist.uri,
- genres: artist.genres
- };
- });
+ // src/api/spotify.ts
+ var apiFetch = async (name, url, log = true) => {
+ try {
+ const timeStart = window.performance.now();
+ const response = await Spicetify.CosmosAsync.get(url);
+ if (log)
+ console.log("stats -", name, "fetch time:", window.performance.now() - timeStart);
+ return response;
+ } catch (error) {
+ console.log("stats -", name, "request failed:", error);
+ throw error;
}
};
- var DropdownOptions = [
- { id: "short_term", name: "Past Month" },
- { id: "medium_term", name: "Past 6 Months" },
- { id: "long_term", name: "All Time" }
- ];
- var ArtistsPage = ({ configWrapper }) => {
- const [topArtists, setTopArtists] = import_react17.default.useState(100);
- const [dropdown, activeOption, setActiveOption] = useDropdownMenu_default(DropdownOptions, "stats:top-artists");
- const fetchTopArtists2 = async (time_range, force, set = true) => {
- if (!force) {
- let storedData = Spicetify.LocalStorage.get(`stats:top-artists:${time_range}`);
- if (storedData)
- return setTopArtists(JSON.parse(storedData));
- }
- const start = window.performance.now();
- const topArtists2 = await topArtistsReq(time_range, configWrapper);
- if (set)
- setTopArtists(topArtists2);
- Spicetify.LocalStorage.set(`stats:top-artists:${time_range}`, JSON.stringify(topArtists2));
- console.log("total artists fetch time:", window.performance.now() - start);
+ var f = (param) => {
+ return encodeURIComponent(param.replace(/'/g, ""));
+ };
+ var getTopTracks = (range) => {
+ return apiFetch(
+ "topTracks",
+ `https://api.spotify.com/v1/me/top/tracks?limit=50&offset=0&time_range=${range}`
+ ).then((res) => res.items);
+ };
+ var getTopArtists = (range) => {
+ return apiFetch(
+ "topArtists",
+ `https://api.spotify.com/v1/me/top/artists?limit=50&offset=0&time_range=${range}`
+ ).then((res) => res.items);
+ };
+ var getArtistMetas = (ids) => {
+ return apiFetch("artistMetas", `https://api.spotify.com/v1/artists?ids=${ids}`).then(
+ (res) => res.artists
+ );
+ };
+ var getAlbumMetas = (ids) => {
+ return apiFetch("albumMetas", `https://api.spotify.com/v1/albums?ids=${ids}`).then(
+ (res) => res.albums
+ );
+ };
+ var getAudioFeatures = (ids) => {
+ return apiFetch(
+ "audioFeatures",
+ `https://api.spotify.com/v1/audio-features?ids=${ids}`
+ ).then((res) => res.audio_features);
+ };
+ var searchForTrack = (track, artist) => {
+ return apiFetch(
+ "searchForTrack",
+ `https://api.spotify.com/v1/search?q=track:${f(track)}+artist:${f(artist)}&type=track&limit=50`
+ ).then((res) => res.tracks.items);
+ };
+ var searchForArtist = (artist) => {
+ return apiFetch(
+ "searchForArtist",
+ `https://api.spotify.com/v1/search?q=artist:${f(artist)}&type=artist&limit=50`
+ ).then((res) => res.artists.items);
+ };
+ var searchForAlbum = (album, artist) => {
+ return apiFetch(
+ "searchForAlbum",
+ `https://api.spotify.com/v1/search?q=album:${f(album)}+artist:${f(artist)}&type=album&limit=50`
+ ).then((res) => res.albums.items);
+ };
+ var queryLiked = (ids) => {
+ return apiFetch("queryLiked", `https://api.spotify.com/v1/me/tracks/contains?ids=${ids}`);
+ };
+ var getUserPlaylists = () => {
+ return apiFetch("userPlaylists", "https://api.spotify.com/v1/me/playlists").then(
+ (res) => res.items
+ );
+ };
+
+ // src/api/lastfm.ts
+ var lfmperiods = {
+ extra_short_term: "7day",
+ short_term: "1month",
+ medium_term: "6month",
+ long_term: "overall"
+ };
+ var getTopTracks2 = (key, user, range) => {
+ const url = `http://ws.audioscrobbler.com/2.0/?method=user.gettoptracks&user=${user}&api_key=${key}&limit=100&format=json&period=${lfmperiods[range]}`;
+ return apiFetch("lfmTopTracks", url).then((res) => res.toptracks.track);
+ };
+ var getTopArtists2 = (key, user, range) => {
+ const url = `http://ws.audioscrobbler.com/2.0/?method=user.gettopartists&user=${user}&api_key=${key}&limit=100&format=json&period=${lfmperiods[range]}`;
+ return apiFetch("lfmTopArtists", url).then((res) => res.topartists.artist);
+ };
+ var getTopAlbums = (key, user, range) => {
+ const url = `http://ws.audioscrobbler.com/2.0/?method=user.gettopalbums&user=${user}&api_key=${key}&limit=100&format=json&period=${lfmperiods[range]}`;
+ return apiFetch("lfmTopAlbums", url).then((res) => res.topalbums.album);
+ };
+ var getArtistChart = (key) => {
+ const url = `http://ws.audioscrobbler.com/2.0/?method=chart.gettopartists&api_key=${key}&format=json`;
+ return apiFetch("lfmArtistChart", url).then((res) => res.artists.artist);
+ };
+ var getTrackChart = (key) => {
+ const url = `http://ws.audioscrobbler.com/2.0/?method=chart.gettoptracks&api_key=${key}&format=json`;
+ return apiFetch("lfmTrackChart", url).then((res) => res.tracks.track);
+ };
+
+ // src/extensions/cache.ts
+ var cache = {};
+ var set = (key, value) => {
+ cache[key] = value;
+ };
+ var invalidate = (key) => {
+ delete cache[key];
+ };
+ var cacher = (cb) => {
+ return async ({ queryKey }) => {
+ const key = queryKey.join("-");
+ if (cache[key])
+ return cache[key];
+ const result = await cb();
+ set(key, result);
+ return result;
};
- import_react17.default.useEffect(() => {
- updatePageCache(0, fetchTopArtists2, activeOption.id);
+ };
+ var invalidator = (queryKey, refetch) => {
+ invalidate(queryKey.join("-"));
+ refetch();
+ };
+
+ // src/utils/converter.ts
+ var minifyArtist = (artist) => ({
+ id: artist.id,
+ name: artist.name,
+ image: artist.images.at(-1)?.url,
+ uri: artist.uri,
+ genres: artist.genres,
+ type: "spotify"
+ });
+ var minifyAlbum = (album) => ({
+ id: album.id,
+ uri: album.uri,
+ name: album.name,
+ image: album.images[0]?.url,
+ type: "spotify"
+ });
+ var minifyTrack = (track) => ({
+ id: track.id,
+ uri: track.uri,
+ name: track.name,
+ duration_ms: track.duration_ms,
+ popularity: track.popularity,
+ explicit: track.explicit,
+ image: track.album.images.at(-1)?.url,
+ artists: track.artists.map((artist) => ({
+ name: artist.name,
+ uri: artist.uri
+ })),
+ album: {
+ name: track.album.name,
+ uri: track.album.uri,
+ release_date: track.album.release_date
+ },
+ type: "spotify"
+ });
+ var convertArtist = async (artist) => {
+ const searchRes = await cacher(() => searchForArtist(artist.name))({ queryKey: ["searchForArtist", artist.name] });
+ const spotifyArtist = searchRes.find(
+ (a) => a.name.localeCompare(artist.name, void 0, { sensitivity: "base" }) === 0
+ );
+ if (!spotifyArtist)
+ return {
+ name: artist.name,
+ playcount: Number(artist.playcount),
+ uri: artist.url,
+ type: "lastfm"
+ };
+ return {
+ ...minifyArtist(spotifyArtist),
+ playcount: Number(artist.playcount),
+ name: artist.name
+ };
+ };
+ var convertAlbum = async (album) => {
+ const searchRes = await cacher(() => searchForAlbum(album.name, album.artist.name))({
+ queryKey: ["searchForAlbum", album.name, album.artist.name]
+ });
+ const spotifyAlbum = searchRes.find(
+ (a) => a.name.localeCompare(album.name, void 0, { sensitivity: "base" }) === 0
+ );
+ if (!spotifyAlbum)
+ return {
+ uri: album.url,
+ name: album.name,
+ playcount: Number(album.playcount),
+ type: "lastfm"
+ };
+ return { ...minifyAlbum(spotifyAlbum), playcount: Number(album.playcount), name: album.name };
+ };
+ var convertTrack = async (track) => {
+ const searchRes = await cacher(() => searchForTrack(track.name, track.artist.name))({
+ queryKey: ["searchForTrack", track.name, track.artist.name]
+ });
+ const spotifyTrack = searchRes.find(
+ (t) => t.name.localeCompare(track.name, void 0, { sensitivity: "base" }) === 0
+ );
+ if (!spotifyTrack)
+ return {
+ uri: track.url,
+ name: track.name,
+ playcount: Number(track.playcount),
+ duration_ms: Number(track.duration) * 1e3,
+ artists: [
+ {
+ name: track.artist.name,
+ uri: track.artist.url
+ }
+ ],
+ type: "lastfm"
+ };
+ return { ...minifyTrack(spotifyTrack), playcount: Number(track.playcount), name: track.name };
+ };
+
+ // ../shared/status/useStatus.tsx
+ var import_react17 = __toESM(require_react());
+
+ // ../shared/status/status.tsx
+ var import_react16 = __toESM(require_react());
+ var ErrorIcon = () => {
+ return /* @__PURE__ */ import_react16.default.createElement("svg", {
+ "data-encore-id": "icon",
+ role: "img",
+ "aria-hidden": "true",
+ viewBox: "0 0 24 24",
+ className: "status-icon"
+ }, /* @__PURE__ */ import_react16.default.createElement("path", {
+ d: "M11 18v-2h2v2h-2zm0-4V6h2v8h-2z"
+ }), /* @__PURE__ */ import_react16.default.createElement("path", {
+ d: "M12 3a9 9 0 1 0 0 18 9 9 0 0 0 0-18zM1 12C1 5.925 5.925 1 12 1s11 4.925 11 11-4.925 11-11 11S1 18.075 1 12z"
+ }));
+ };
+ var LibraryIcon = () => {
+ return /* @__PURE__ */ import_react16.default.createElement("svg", {
+ role: "img",
+ height: "46",
+ width: "46",
+ "aria-hidden": "true",
+ viewBox: "0 0 24 24",
+ "data-encore-id": "icon",
+ className: "status-icon"
+ }, /* @__PURE__ */ import_react16.default.createElement("path", {
+ d: "M14.5 2.134a1 1 0 0 1 1 0l6 3.464a1 1 0 0 1 .5.866V21a1 1 0 0 1-1 1h-6a1 1 0 0 1-1-1V3a1 1 0 0 1 .5-.866zM16 4.732V20h4V7.041l-4-2.309zM3 22a1 1 0 0 1-1-1V3a1 1 0 0 1 2 0v18a1 1 0 0 1-1 1zm6 0a1 1 0 0 1-1-1V3a1 1 0 0 1 2 0v18a1 1 0 0 1-1 1z"
+ }));
+ };
+ var Status = (props) => {
+ const [isVisible, setIsVisible] = import_react16.default.useState(false);
+ import_react16.default.useEffect(() => {
+ const to = setTimeout(() => {
+ setIsVisible(true);
+ }, 500);
+ return () => clearTimeout(to);
}, []);
- import_react17.default.useEffect(() => {
- fetchTopArtists2(activeOption.id);
- }, [activeOption]);
- const refresh = () => {
- fetchTopArtists2(activeOption.id, true);
- };
+ return isVisible ? /* @__PURE__ */ import_react16.default.createElement(import_react16.default.Fragment, null, /* @__PURE__ */ import_react16.default.createElement("div", {
+ className: "loadingWrapper"
+ }, props.icon === "error" ? /* @__PURE__ */ import_react16.default.createElement(ErrorIcon, null) : /* @__PURE__ */ import_react16.default.createElement(LibraryIcon, null), /* @__PURE__ */ import_react16.default.createElement("h1", null, props.heading), /* @__PURE__ */ import_react16.default.createElement("h3", null, props.subheading))) : /* @__PURE__ */ import_react16.default.createElement(import_react16.default.Fragment, null);
+ };
+ var status_default = Status;
+
+ // ../shared/status/useStatus.tsx
+ var useStatus = (status, error) => {
+ if (status === "pending") {
+ return /* @__PURE__ */ import_react17.default.createElement(status_default, {
+ icon: "library",
+ heading: "Loading",
+ subheading: "Please wait, this may take a moment"
+ });
+ }
+ if (status === "error") {
+ return /* @__PURE__ */ import_react17.default.createElement(status_default, {
+ icon: "error",
+ heading: "Error",
+ subheading: error?.message || "An unknown error occurred"
+ });
+ }
+ return null;
+ };
+ var useStatus_default = useStatus;
+
+ // src/utils/react_query.ts
+ var ReactQuery = Spicetify.ReactQuery;
+ var useQuery = ReactQuery.useQuery;
+ var QueryClient = ReactQuery.QueryClient;
+ var QueryClientProvider = ReactQuery.QueryClientProvider;
+
+ // src/pages/top_artists.tsx
+ var getTopArtists3 = async (timeRange, config) => {
+ if (config["use-lastfm"]) {
+ const { "lastfm-user": user, "api-key": key } = config;
+ if (!user || !key)
+ throw new Error("Missing LastFM API Key or Username");
+ const response2 = await getTopArtists2(key, user, timeRange);
+ return Promise.all(response2.map(convertArtist));
+ }
+ const response = await getTopArtists(timeRange);
+ return response.map(minifyArtist);
+ };
+ var DropdownOptions = ({ config: { "use-lastfm": useLastFM } }) => [
+ useLastFM && { id: "extra_short_term", name: "Past Week" },
+ { id: "short_term" /* Short */, name: "Past Month" },
+ { id: "medium_term" /* Medium */, name: "Past 6 Months" },
+ { id: "long_term" /* Long */, name: "All Time" }
+ ].filter(Boolean);
+ var ArtistsPage = ({ configWrapper }) => {
+ const [dropdown, activeOption] = useDropdownMenu_default(DropdownOptions(configWrapper), "stats:top-artists");
+ const { status, error, data, refetch } = useQuery({
+ queryKey: ["top-artists", activeOption.id],
+ queryFn: cacher(() => getTopArtists3(activeOption.id, configWrapper.config))
+ });
+ const Status2 = useStatus_default(status, error);
const props = {
title: "Top Artists",
- headerEls: [dropdown, /* @__PURE__ */ import_react17.default.createElement(refresh_button_default, {
- callback: refresh
- }), /* @__PURE__ */ import_react17.default.createElement(settings_button_default, {
- configWrapper
- })]
+ headerEls: [
+ dropdown,
+ /* @__PURE__ */ import_react18.default.createElement(refresh_button_default, {
+ callback: () => invalidator(["top-artists", activeOption.id], refetch)
+ }),
+ /* @__PURE__ */ import_react18.default.createElement(settings_button_default, {
+ configWrapper
+ })
+ ]
};
- switch (topArtists) {
- case 300:
- return /* @__PURE__ */ import_react17.default.createElement(page_container_default, {
- ...props
- }, /* @__PURE__ */ import_react17.default.createElement(status_default, {
- icon: "error",
- heading: "No API Key or Username",
- subheading: "Please enter these in the settings menu"
- }));
- case 200:
- return /* @__PURE__ */ import_react17.default.createElement(page_container_default, {
- ...props
- }, /* @__PURE__ */ import_react17.default.createElement(status_default, {
- icon: "error",
- heading: "Failed to Fetch Top Artists",
- subheading: "An error occurred while fetching the data"
- }));
- case 100:
- return /* @__PURE__ */ import_react17.default.createElement(page_container_default, {
- ...props
- }, /* @__PURE__ */ import_react17.default.createElement(status_default, {
- icon: "library",
- heading: "Loading",
- subheading: "Fetching data..."
- }));
- }
- const artistCards = topArtists.map((artist, index) => /* @__PURE__ */ import_react17.default.createElement(spotify_card_default, {
- type: artist.uri.includes("last") ? "lastfm" : "artist",
+ if (Status2)
+ return /* @__PURE__ */ import_react18.default.createElement(page_container_default, {
+ ...props
+ }, Status2);
+ const topArtists = data;
+ const artistCards = topArtists.map((artist, index) => /* @__PURE__ */ import_react18.default.createElement(spotify_card_default, {
+ type: "artist",
+ provider: artist.type,
uri: artist.uri,
header: artist.name,
- subheader: `#${index + 1} Artist`,
- imageUrl: artist.image
+ subheader: artist.playcount ? `\u29BE ${artist.playcount} Scrobbles` : "Artist",
+ imageUrl: artist.image,
+ badge: `${index + 1}`
}));
- return /* @__PURE__ */ import_react17.default.createElement(import_react17.default.Fragment, null, /* @__PURE__ */ import_react17.default.createElement(page_container_default, {
+ return /* @__PURE__ */ import_react18.default.createElement(import_react18.default.Fragment, null, /* @__PURE__ */ import_react18.default.createElement(page_container_default, {
...props
- }, /* @__PURE__ */ import_react17.default.createElement("div", {
- className: `main-gridContainer-gridContainer grid`
+ }, /* @__PURE__ */ import_react18.default.createElement("div", {
+ className: "main-gridContainer-gridContainer grid"
}, artistCards)));
};
- var top_artists_default = import_react17.default.memo(ArtistsPage);
+ var top_artists_default = import_react18.default.memo(ArtistsPage);
// src/pages/top_tracks.tsx
- var import_react20 = __toESM(require_react());
+ var import_react22 = __toESM(require_react());
// src/components/track_row.tsx
- var import_react18 = __toESM(require_react());
- var ArtistLink = ({ name, uri, index, length }) => {
- return /* @__PURE__ */ import_react18.default.createElement(import_react18.default.Fragment, null, /* @__PURE__ */ import_react18.default.createElement("a", {
- draggable: "true",
- dir: "auto",
- href: uri,
- tabIndex: -1
- }, name), index === length ? null : ", ");
- };
- var ExplicitBadge = import_react18.default.memo(() => {
- return /* @__PURE__ */ import_react18.default.createElement(import_react18.default.Fragment, null, /* @__PURE__ */ import_react18.default.createElement("span", {
- className: "TypeElement-ballad-textSubdued-type main-trackList-rowBadges",
- "data-encore-id": "type"
- }, /* @__PURE__ */ import_react18.default.createElement("span", {
- "aria-label": "Explicit",
- className: "main-tag-container",
- title: "Explicit"
- }, "E")));
- });
- var LikedIcon = ({ active, uri }) => {
- const [liked, setLiked] = import_react18.default.useState(active);
- const toggleLike = () => {
- if (liked) {
- Spicetify.Platform.LibraryAPI.remove(uri);
- } else {
- Spicetify.Platform.LibraryAPI.add(uri);
- }
- setLiked(!liked);
- };
- import_react18.default.useEffect(() => {
- setLiked(active);
- }, [active]);
- return /* @__PURE__ */ import_react18.default.createElement(Spicetify.ReactComponent.TooltipWrapper, {
- label: liked ? `Remove from Your Library` : "Save to Your Library",
- placement: "top"
- }, /* @__PURE__ */ import_react18.default.createElement("button", {
- type: "button",
- role: "switch",
- "aria-checked": liked,
- "aria-label": "Remove from Your Library",
- onClick: toggleLike,
- className: liked ? "main-addButton-button main-trackList-rowHeartButton main-addButton-active" : "main-addButton-button main-trackList-rowHeartButton",
- tabIndex: -1
- }, /* @__PURE__ */ import_react18.default.createElement("svg", {
- role: "img",
- height: "16",
- width: "16",
- "aria-hidden": "true",
- viewBox: "0 0 16 16",
- "data-encore-id": "icon",
- className: "Svg-img-16 Svg-img-16-icon Svg-img-icon Svg-img-icon-small"
- }, /* @__PURE__ */ import_react18.default.createElement("path", {
- d: liked ? "M15.724 4.22A4.313 4.313 0 0 0 12.192.814a4.269 4.269 0 0 0-3.622 1.13.837.837 0 0 1-1.14 0 4.272 4.272 0 0 0-6.21 5.855l5.916 7.05a1.128 1.128 0 0 0 1.727 0l5.916-7.05a4.228 4.228 0 0 0 .945-3.577z" : "M1.69 2A4.582 4.582 0 0 1 8 2.023 4.583 4.583 0 0 1 11.88.817h.002a4.618 4.618 0 0 1 3.782 3.65v.003a4.543 4.543 0 0 1-1.011 3.84L9.35 14.629a1.765 1.765 0 0 1-2.093.464 1.762 1.762 0 0 1-.605-.463L1.348 8.309A4.582 4.582 0 0 1 1.689 2zm3.158.252A3.082 3.082 0 0 0 2.49 7.337l.005.005L7.8 13.664a.264.264 0 0 0 .311.069.262.262 0 0 0 .09-.069l5.312-6.33a3.043 3.043 0 0 0 .68-2.573 3.118 3.118 0 0 0-2.551-2.463 3.079 3.079 0 0 0-2.612.816l-.007.007a1.501 1.501 0 0 1-2.045 0l-.009-.008a3.082 3.082 0 0 0-2.121-.861z"
- }))));
- };
- var DraggableComponent = ({
- uri,
- title,
- ...props
- }) => {
- const dragHandler = Spicetify.ReactHook.DragHandler?.([uri], title);
- return /* @__PURE__ */ import_react18.default.createElement("div", {
- onDragStart: dragHandler,
- draggable: "true",
- ...props
- }, props.children);
- };
- function playAndQueue(uri, uris) {
- uris = uris.filter((u) => !u.includes("last"));
- uris = uris.concat(uris.splice(0, uris.indexOf(uri)));
- queue(uris);
- }
- var MenuWrapper = import_react18.default.memo((props) => /* @__PURE__ */ import_react18.default.createElement(Spicetify.ReactComponent.AlbumMenu, {
- ...props
- }));
- var TrackRow = (props) => {
- const ArtistLinks = props.artists.map((artist, index) => {
- return /* @__PURE__ */ import_react18.default.createElement(ArtistLink, {
- index,
- length: props.artists.length - 1,
- name: artist.name,
- uri: artist.uri
- });
- });
- return /* @__PURE__ */ import_react18.default.createElement(import_react18.default.Fragment, null, /* @__PURE__ */ import_react18.default.createElement(Spicetify.ReactComponent.ContextMenu, {
- menu: /* @__PURE__ */ import_react18.default.createElement(MenuWrapper, {
- uri: props.uri
- }),
- trigger: "right-click"
- }, /* @__PURE__ */ import_react18.default.createElement("div", {
- role: "row",
- "aria-rowindex": 2,
- "aria-selected": "false"
- }, /* @__PURE__ */ import_react18.default.createElement(DraggableComponent, {
- uri: props.uri,
- title: `${props.name} \u2022 ${props.artists.map((artist) => artist.name).join(", ")}`,
- className: "main-trackList-trackListRow main-trackList-trackListRowGrid",
- role: "presentation",
- onClick: (event) => event.detail === 2 && playAndQueue(props.uri, props.uris),
- style: { height: 56 }
- }, /* @__PURE__ */ import_react18.default.createElement("div", {
- className: "main-trackList-rowSectionIndex",
- role: "gridcell",
- "aria-colindex": 1,
- tabIndex: -1
- }, /* @__PURE__ */ import_react18.default.createElement("div", {
- uri: props.uri,
- className: "main-trackList-rowMarker"
- }, /* @__PURE__ */ import_react18.default.createElement("span", {
- className: "TypeElement-ballad-type main-trackList-number",
- "data-encore-id": "type"
- }, props.index), /* @__PURE__ */ import_react18.default.createElement(Spicetify.ReactComponent.TooltipWrapper, {
- label: `Play ${props.name} by ${props.artists.map((artist) => artist.name).join(", ")}`,
- placement: "top"
- }, /* @__PURE__ */ import_react18.default.createElement("button", {
- className: "main-trackList-rowImagePlayButton",
- "aria-label": `Play ${props.name}`,
- tabIndex: -1,
- onClick: () => playAndQueue(props.uri, props.uris)
- }, /* @__PURE__ */ import_react18.default.createElement("svg", {
- role: "img",
- height: "24",
- width: "24",
- "aria-hidden": "true",
- className: "Svg-img-24 Svg-img-24-icon main-trackList-rowPlayPauseIcon",
- viewBox: "0 0 24 24",
- "data-encore-id": "icon"
- }, /* @__PURE__ */ import_react18.default.createElement("path", {
- d: "m7.05 3.606 13.49 7.788a.7.7 0 0 1 0 1.212L7.05 20.394A.7.7 0 0 1 6 19.788V4.212a.7.7 0 0 1 1.05-.606z"
- })))))), /* @__PURE__ */ import_react18.default.createElement("div", {
- className: "main-trackList-rowSectionStart",
- role: "gridcell",
- "aria-colindex": 2,
- tabIndex: -1
- }, /* @__PURE__ */ import_react18.default.createElement("img", {
- "aria-hidden": "false",
- draggable: "false",
- loading: "eager",
- src: props.image,
- alt: "",
- className: "main-image-image main-trackList-rowImage main-image-loaded",
- width: "40",
- height: "40"
- }), /* @__PURE__ */ import_react18.default.createElement("div", {
- className: "main-trackList-rowMainContent"
- }, /* @__PURE__ */ import_react18.default.createElement("div", {
- dir: "auto",
- className: "TypeElement-ballad-textBase TypeElement-ballad-textBase-type main-trackList-rowTitle standalone-ellipsis-one-line",
- "data-encore-id": "type"
- }, props.name), props.explicit && /* @__PURE__ */ import_react18.default.createElement(ExplicitBadge, null), /* @__PURE__ */ import_react18.default.createElement("span", {
- className: "TypeElement-mesto-textSubdued TypeElement-mesto-textSubdued-type main-trackList-rowSubTitle standalone-ellipsis-one-line",
- "data-encore-id": "type"
- }, ArtistLinks))), /* @__PURE__ */ import_react18.default.createElement("div", {
- className: "main-trackList-rowSectionVariable",
- role: "gridcell",
- "aria-colindex": 3,
- tabIndex: -1
- }, /* @__PURE__ */ import_react18.default.createElement("span", {
- "data-encore-id": "type",
- className: "TypeElement-mesto TypeElement-mesto-type"
- }, /* @__PURE__ */ import_react18.default.createElement("a", {
- draggable: "true",
- className: "standalone-ellipsis-one-line",
- dir: "auto",
- href: props.album_uri,
- tabIndex: -1
- }, props.album))), /* @__PURE__ */ import_react18.default.createElement("div", {
- className: "main-trackList-rowSectionEnd",
- role: "gridcell",
- "aria-colindex": 5,
- tabIndex: -1
- }, /* @__PURE__ */ import_react18.default.createElement(LikedIcon, {
- active: props.liked || false,
- uri: props.uri
- }), /* @__PURE__ */ import_react18.default.createElement("div", {
- className: "TypeElement-mesto-textSubdued TypeElement-mesto-textSubdued-type main-trackList-rowDuration",
- "data-encore-id": "type"
- }, Spicetify.Player.formatTime(props.duration)), /* @__PURE__ */ import_react18.default.createElement(Spicetify.ReactComponent.ContextMenu, {
- menu: /* @__PURE__ */ import_react18.default.createElement(MenuWrapper, {
- uri: props.uri
- }),
- trigger: "click"
- }, /* @__PURE__ */ import_react18.default.createElement("button", {
- type: "button",
- "aria-haspopup": "menu",
- "aria-label": `More options for ${props.name}`,
- className: "main-moreButton-button Button-sm-16-buttonTertiary-iconOnly-condensed-useBrowserDefaultFocusStyle Button-small-small-buttonTertiary-iconOnly-condensed-useBrowserDefaultFocusStyle main-trackList-rowMoreButton",
- tabIndex: -1
- }, /* @__PURE__ */ import_react18.default.createElement(Spicetify.ReactComponent.TooltipWrapper, {
- label: `More options for ${props.name} by ${props.artists.map((artist) => artist.name).join(", ")}`,
- placement: "top"
- }, /* @__PURE__ */ import_react18.default.createElement("span", null, /* @__PURE__ */ import_react18.default.createElement("svg", {
- role: "img",
- height: "16",
- width: "16",
- "aria-hidden": "true",
- viewBox: "0 0 16 16",
- "data-encore-id": "icon",
- className: "Svg-img-16 Svg-img-16-icon Svg-img-icon Svg-img-icon-small"
- }, /* @__PURE__ */ import_react18.default.createElement("path", {
- d: "M3 8a1.5 1.5 0 1 1-3 0 1.5 1.5 0 0 1 3 0zm6.5 0a1.5 1.5 0 1 1-3 0 1.5 1.5 0 0 1 3 0zM16 8a1.5 1.5 0 1 1-3 0 1.5 1.5 0 0 1 3 0z"
- })))))))))));
- };
- var track_row_default = import_react18.default.memo(TrackRow);
+ var import_react21 = __toESM(require_react());
+
+ // src/pages/charts.tsx
+ var import_react20 = __toESM(require_react());
// src/components/tracklist.tsx
var import_react19 = __toESM(require_react());
- var Tracklist = ({ minified = false, children }) => {
+ var Tracklist = ({ playcount = false, minified = false, children }) => {
+ const height = children.length;
return /* @__PURE__ */ import_react19.default.createElement("div", {
role: "grid",
- "aria-rowcount": minified ? 5 : 50,
- "aria-colcount": 4,
- className: "main-trackList-trackList main-trackList-indexable",
- tabIndex: 0
+ "aria-rowcount": height,
+ "aria-colcount": 5,
+ className: "main-trackList-trackList main-trackList-indexable"
}, !minified && /* @__PURE__ */ import_react19.default.createElement("div", {
className: "main-trackList-trackListHeader",
role: "presentation"
@@ -1364,18 +6513,33 @@ var stats = (() => {
"aria-sort": "none",
tabIndex: -1
}, /* @__PURE__ */ import_react19.default.createElement("button", {
+ type: "button",
className: "main-trackList-column main-trackList-sortable",
tabIndex: -1
}, /* @__PURE__ */ import_react19.default.createElement("span", {
className: "TypeElement-mesto-type standalone-ellipsis-one-line",
"data-encore-id": "type"
- }, "Title"))), /* @__PURE__ */ import_react19.default.createElement("div", {
+ }, "Title"))), playcount && /* @__PURE__ */ import_react19.default.createElement("div", {
className: "main-trackList-rowSectionVariable",
role: "columnheader",
"aria-colindex": 3,
"aria-sort": "none",
tabIndex: -1
}, /* @__PURE__ */ import_react19.default.createElement("button", {
+ type: "button",
+ className: "main-trackList-column main-trackList-sortable",
+ tabIndex: -1
+ }, /* @__PURE__ */ import_react19.default.createElement("span", {
+ className: "TypeElement-mesto-type standalone-ellipsis-one-line",
+ "data-encore-id": "type"
+ }, "\u29BE Scrobbles"))), /* @__PURE__ */ import_react19.default.createElement("div", {
+ className: "main-trackList-rowSectionVariable",
+ role: "columnheader",
+ "aria-colindex": 4,
+ "aria-sort": "none",
+ tabIndex: -1
+ }, /* @__PURE__ */ import_react19.default.createElement("button", {
+ type: "button",
className: "main-trackList-column main-trackList-sortable",
tabIndex: -1
}, /* @__PURE__ */ import_react19.default.createElement("span", {
@@ -1391,6 +6555,7 @@ var stats = (() => {
label: "Duration",
placement: "top"
}, /* @__PURE__ */ import_react19.default.createElement("button", {
+ type: "button",
"aria-label": "Duration",
className: "main-trackList-column main-trackList-durationHeader main-trackList-sortable",
tabIndex: -1
@@ -1409,209 +6574,666 @@ var stats = (() => {
}))))))), /* @__PURE__ */ import_react19.default.createElement("div", {
className: "main-rootlist-wrapper",
role: "presentation",
- style: { height: (minified ? 5 : 50) * 56 }
+ style: { height: height * 56 }
}, /* @__PURE__ */ import_react19.default.createElement("div", {
role: "presentation"
}, children)));
};
var tracklist_default = Tracklist;
- // src/pages/top_tracks.tsx
- var topTracksReq = async (time_range, configWrapper) => {
- const { config } = configWrapper;
- if (config["use-lastfm"] === true) {
- if (!config["api-key"] || !config["lastfm-user"])
- return 300;
- const { ["lastfm-user"]: user, ["api-key"]: key } = config;
- const lastfmData = await apiRequest("lastfm", LASTFM.toptracks(user, key, time_range));
- if (!lastfmData)
- return 200;
- const spotifyData = await convertTrackData(lastfmData.toptracks.track);
- const likedArray2 = await checkLiked(spotifyData.map((track) => track.id));
- if (!likedArray2)
- return 200;
- spotifyData.forEach((track, index) => {
- track.liked = likedArray2[index];
- });
- return spotifyData;
+ // src/pages/charts.tsx
+ var import_lodash = __toESM(require_lodash());
+
+ // src/utils/track_helper.ts
+ var batchRequest = (size, request) => {
+ return (ids) => {
+ const chunks = [];
+ for (let i = 0; i < ids.length; i += size) {
+ chunks.push(ids.slice(i, i + size));
+ }
+ return Promise.all(chunks.map(request)).then((res) => res.flat());
+ };
+ };
+ var getMeanAudioFeatures = async (ids) => {
+ const audioFeaturesSum = {
+ danceability: 0,
+ energy: 0,
+ speechiness: 0,
+ acousticness: 0,
+ instrumentalness: 0,
+ liveness: 0,
+ valence: 0,
+ tempo: 0
+ };
+ const audioFeaturesList = await batchRequest(100, getAudioFeatures)(ids);
+ for (const audioFeatures of audioFeaturesList) {
+ if (!audioFeatures)
+ continue;
+ for (const f2 of Object.keys(audioFeaturesSum)) {
+ audioFeaturesSum[f2] += audioFeatures[f2];
+ }
}
- const response = await apiRequest("topTracks", SPOTIFY.toptracks(time_range));
- if (!response)
- return 200;
- const likedArray = await checkLiked(response.items.map((track) => track.id));
- if (!likedArray)
- return 200;
- return response.items.map((track, index) => {
- const images = track.album.images;
- const image = images[2]?.url || images[1]?.url || PLACEHOLDER;
- return {
- liked: likedArray[index],
- name: track.name,
- image,
- uri: track.uri,
- id: track.id,
- artists: track.artists.map((artist) => ({
- name: artist.name,
- uri: artist.uri
- })),
- duration: track.duration_ms,
- album: track.album.name,
- album_uri: track.album.uri,
- popularity: track.popularity,
- explicit: track.explicit,
- release_year: track.album.release_date.slice(0, 4)
- };
+ for (const f2 of Object.keys(audioFeaturesSum)) {
+ audioFeaturesSum[f2] /= audioFeaturesList.length;
+ }
+ return audioFeaturesSum;
+ };
+ var parseAlbums = async (albumsRaw) => {
+ const frequencyMap = {};
+ const albumIDs = albumsRaw.map((album) => album.uri.split(":")[2]);
+ for (const id of albumIDs) {
+ frequencyMap[id] = (frequencyMap[id] || 0) + 1;
+ }
+ const ids = Object.keys(frequencyMap).sort((a, b) => frequencyMap[b] - frequencyMap[a]).slice(0, 100);
+ const albums = await batchRequest(20, getAlbumMetas)(ids);
+ const releaseYears = {};
+ const uniqueAlbums = albums.map((album) => {
+ const year = album.release_date.slice(0, 4);
+ releaseYears[year] = (releaseYears[year] || 0) + 1;
+ return { ...minifyAlbum(album), frequency: frequencyMap[album.id] };
});
+ return { releaseYears, albums: { contents: uniqueAlbums, length: Object.keys(frequencyMap).length } };
+ };
+ var parseArtists = async (artistsRaw) => {
+ const frequencyMap = {};
+ const artistIDs = artistsRaw.map((artist) => artist.uri.split(":")[2]);
+ for (const id of artistIDs) {
+ frequencyMap[id] = (frequencyMap[id] || 0) + 1;
+ }
+ const ids = Object.keys(frequencyMap).sort((a, b) => frequencyMap[b] - frequencyMap[a]).slice(0, 250);
+ const artists = await batchRequest(50, getArtistMetas)(ids);
+ const genres = {};
+ const uniqueArtists = artists.map((artist) => {
+ for (const genre of artist.genres) {
+ genres[genre] = (genres[genre] || 0) + 1;
+ }
+ return { ...minifyArtist(artist), frequency: frequencyMap[artist.id] };
+ });
+ return { genres, artists: { contents: uniqueArtists, length: Object.keys(frequencyMap).length } };
+ };
+ var parseTracks = async (tracks) => {
+ const trackIDs = [];
+ const albumsRaw = [];
+ const artistsRaw = [];
+ let explicit = 0;
+ let duration = 0;
+ for (const track of tracks) {
+ if (track?.type !== "track" || track.isLocal)
+ continue;
+ duration += track.duration.milliseconds;
+ explicit += track.isExplicit ? 1 : 0;
+ trackIDs.push(track.uri.split(":")[2]);
+ albumsRaw.push(track.album);
+ artistsRaw.push(...track.artists);
+ }
+ explicit = explicit / trackIDs.length;
+ const audioFeatures = await getMeanAudioFeatures(trackIDs);
+ const analysis = { ...audioFeatures, explicit };
+ const { genres, artists } = await parseArtists(artistsRaw);
+ const { releaseYears, albums } = await parseAlbums(albumsRaw);
+ return {
+ analysis,
+ genres,
+ artists,
+ albums,
+ releaseYears,
+ duration,
+ length: trackIDs.length
+ };
+ };
+ var parseStat = (name) => {
+ switch (name) {
+ case "tempo":
+ return (v) => `${Math.round(v)} bpm`;
+ case "popularity":
+ return (v) => `${Math.round(v)}%`;
+ default:
+ return (v) => `${Math.round(v * 100)}%`;
+ }
+ };
+ var parseLiked = async (tracks) => {
+ const trackIDs = tracks.filter((t) => t.type === "spotify").map((t) => t.id);
+ const liked = await batchRequest(50, queryLiked)(trackIDs);
+ const likedMap = new Map(trackIDs.map((id, i) => [id, liked[i]]));
+ return tracks.map((t) => ({ ...t, liked: t.type === "spotify" ? likedMap.get(t.id) : false }));
+ };
+
+ // src/pages/charts.tsx
+ var formatNumber = (num) => {
+ if (num >= 1e9)
+ return `${(num / 1e9).toFixed(2)}B`;
+ if (num >= 1e6)
+ return `${(num / 1e6).toFixed(2)}M`;
+ if (num >= 1e3)
+ return `${(num / 1e3).toFixed(2)}K`;
+ return num.toString();
};
var DropdownOptions2 = [
- { id: "short_term", name: "Past Month" },
- { id: "medium_term", name: "Past 6 Months" },
- { id: "long_term", name: "All Time" }
+ { id: "artists", name: "Top Artists" },
+ { id: "tracks", name: "Top Tracks" }
];
- var TracksPage = ({ configWrapper }) => {
- const { LocalStorage } = Spicetify;
- const [topTracks, setTopTracks] = import_react20.default.useState(100);
- const [dropdown, activeOption] = useDropdownMenu_default(DropdownOptions2, "stats:top-tracks");
- const fetchTopTracks = async (time_range, force, set = true) => {
- if (!force) {
- const storedData = LocalStorage.get(`stats:top-tracks:${time_range}`);
- if (storedData)
- return setTopTracks(JSON.parse(storedData));
+ var getChart = async (type, config) => {
+ const { "api-key": key } = config;
+ if (!key)
+ throw new Error("Missing LastFM API Key or Username");
+ if (type === "artists") {
+ const response2 = await getArtistChart(key);
+ return Promise.all(response2.map(convertArtist));
+ }
+ const response = await getTrackChart(key);
+ return parseLiked(await Promise.all(response.map(convertTrack)));
+ };
+ var ArtistChart = ({ artists }) => {
+ return /* @__PURE__ */ import_react20.default.createElement("div", {
+ className: "main-gridContainer-gridContainer grid"
+ }, artists.map((artist, index) => {
+ return /* @__PURE__ */ import_react20.default.createElement(spotify_card_default, {
+ type: "artist",
+ provider: artist.type,
+ uri: artist.uri,
+ header: artist.name,
+ subheader: artist.playcount ? `\u29BE ${formatNumber(artist.playcount)} Scrobbles` : "Artist",
+ imageUrl: artist.image,
+ badge: `${index + 1}`
+ });
+ }));
+ };
+ var TrackChart = ({ tracks }) => {
+ return /* @__PURE__ */ import_react20.default.createElement(tracklist_default, {
+ playcount: true
+ }, tracks.map((track, index) => /* @__PURE__ */ import_react20.default.createElement(track_row_default, {
+ index: index + 1,
+ ...track,
+ uris: tracks.map((track2) => track2.uri)
+ })));
+ };
+ var getDate = () => {
+ return new Date().toLocaleDateString("en-US", {
+ year: "numeric",
+ month: "2-digit",
+ day: "2-digit"
+ });
+ };
+ var ChartsPage = ({ configWrapper }) => {
+ const [dropdown, activeOption] = useDropdownMenu_default(DropdownOptions2, "stats:charts");
+ const { status, error, data, refetch } = useQuery({
+ queryKey: ["top-charts", activeOption.id],
+ queryFn: cacher(() => getChart(activeOption.id, configWrapper.config))
+ });
+ const Status2 = useStatus_default(status, error);
+ const props = {
+ title: `Top Charts - ${import_lodash.default.startCase(activeOption.id)}`,
+ headerEls: [
+ dropdown,
+ /* @__PURE__ */ import_react20.default.createElement(refresh_button_default, {
+ callback: () => invalidator(["top-charts", activeOption.id], refetch)
+ }),
+ /* @__PURE__ */ import_react20.default.createElement(settings_button_default, {
+ configWrapper
+ })
+ ]
+ };
+ if (Status2)
+ return /* @__PURE__ */ import_react20.default.createElement(page_container_default, {
+ ...props
+ }, Status2);
+ const items = data;
+ const infoToCreatePlaylist = {
+ playlistName: `Top Track Chart - ${getDate()}`,
+ itemsUris: items.map((track) => track.uri)
+ };
+ if (activeOption.id === "tracks") {
+ props.infoToCreatePlaylist = infoToCreatePlaylist;
+ }
+ const chartToRender = activeOption.id === "artists" ? /* @__PURE__ */ import_react20.default.createElement(ArtistChart, {
+ artists: items
+ }) : /* @__PURE__ */ import_react20.default.createElement(TrackChart, {
+ tracks: items
+ });
+ return /* @__PURE__ */ import_react20.default.createElement(page_container_default, {
+ ...props
+ }, chartToRender);
+ };
+ var charts_default = import_react20.default.memo(ChartsPage);
+
+ // src/components/track_row.tsx
+ var ArtistLink = ({ name, uri, index, length }) => {
+ return /* @__PURE__ */ import_react21.default.createElement(import_react21.default.Fragment, null, /* @__PURE__ */ import_react21.default.createElement("a", {
+ draggable: "true",
+ dir: "auto",
+ href: uri,
+ tabIndex: -1
+ }, name), index === length ? null : ", ");
+ };
+ var ExplicitBadge = import_react21.default.memo(() => {
+ return /* @__PURE__ */ import_react21.default.createElement(import_react21.default.Fragment, null, /* @__PURE__ */ import_react21.default.createElement("span", {
+ className: "TypeElement-ballad-textSubdued-type main-trackList-rowBadges",
+ "data-encore-id": "type"
+ }, /* @__PURE__ */ import_react21.default.createElement("span", {
+ "aria-label": "Explicit",
+ className: "main-tag-container",
+ title: "Explicit"
+ }, "E")));
+ });
+ var LikedIcon = ({ active, uri }) => {
+ const [liked, setLiked] = import_react21.default.useState(active);
+ const toggleLike = () => {
+ if (liked) {
+ Spicetify.Platform.LibraryAPI.remove(uri);
+ } else {
+ Spicetify.Platform.LibraryAPI.add(uri);
}
- const start = window.performance.now();
- const topTracks2 = await topTracksReq(time_range, configWrapper);
- if (set)
- setTopTracks(topTracks2);
- LocalStorage.set(`stats:top-tracks:${time_range}`, JSON.stringify(topTracks2));
- console.log("total tracks fetch time:", window.performance.now() - start);
- };
- import_react20.default.useEffect(() => {
- updatePageCache(1, fetchTopTracks, activeOption.id);
- }, []);
- import_react20.default.useEffect(() => {
- fetchTopTracks(activeOption.id);
- }, [activeOption]);
- const refresh = () => {
- fetchTopTracks(activeOption.id, true);
+ setLiked(!liked);
};
+ import_react21.default.useEffect(() => {
+ setLiked(active);
+ }, [active]);
+ return /* @__PURE__ */ import_react21.default.createElement(Spicetify.ReactComponent.TooltipWrapper, {
+ label: liked ? "Remove from Your Library" : "Save to Your Library",
+ placement: "top"
+ }, /* @__PURE__ */ import_react21.default.createElement("button", {
+ type: "button",
+ role: "switch",
+ "aria-checked": liked,
+ "aria-label": "Remove from Your Library",
+ onClick: toggleLike,
+ className: liked ? "main-addButton-button main-trackList-rowHeartButton main-addButton-active" : "main-addButton-button main-trackList-rowHeartButton",
+ tabIndex: -1
+ }, /* @__PURE__ */ import_react21.default.createElement("svg", {
+ role: "img",
+ height: "16",
+ width: "16",
+ "aria-hidden": "true",
+ viewBox: "0 0 16 16",
+ "data-encore-id": "icon",
+ className: "Svg-img-16 Svg-img-16-icon Svg-img-icon Svg-img-icon-small"
+ }, /* @__PURE__ */ import_react21.default.createElement("path", {
+ d: liked ? "M15.724 4.22A4.313 4.313 0 0 0 12.192.814a4.269 4.269 0 0 0-3.622 1.13.837.837 0 0 1-1.14 0 4.272 4.272 0 0 0-6.21 5.855l5.916 7.05a1.128 1.128 0 0 0 1.727 0l5.916-7.05a4.228 4.228 0 0 0 .945-3.577z" : "M1.69 2A4.582 4.582 0 0 1 8 2.023 4.583 4.583 0 0 1 11.88.817h.002a4.618 4.618 0 0 1 3.782 3.65v.003a4.543 4.543 0 0 1-1.011 3.84L9.35 14.629a1.765 1.765 0 0 1-2.093.464 1.762 1.762 0 0 1-.605-.463L1.348 8.309A4.582 4.582 0 0 1 1.689 2zm3.158.252A3.082 3.082 0 0 0 2.49 7.337l.005.005L7.8 13.664a.264.264 0 0 0 .311.069.262.262 0 0 0 .09-.069l5.312-6.33a3.043 3.043 0 0 0 .68-2.573 3.118 3.118 0 0 0-2.551-2.463 3.079 3.079 0 0 0-2.612.816l-.007.007a1.501 1.501 0 0 1-2.045 0l-.009-.008a3.082 3.082 0 0 0-2.121-.861z"
+ }))));
+ };
+ var DraggableComponent = ({
+ uri,
+ title,
+ ...props
+ }) => {
+ const dragHandler = Spicetify.ReactHook.DragHandler?.([uri], title);
+ return /* @__PURE__ */ import_react21.default.createElement("div", {
+ onDragStart: dragHandler,
+ draggable: "true",
+ ...props
+ }, props.children);
+ };
+ function playAndQueue(uri, uris) {
+ }
+ var MenuWrapper = import_react21.default.memo((props) => /* @__PURE__ */ import_react21.default.createElement(Spicetify.ReactComponent.AlbumMenu, {
+ ...props
+ }));
+ var TrackRow = (props) => {
+ const ArtistLinks = props.artists.map((artist, index) => {
+ return /* @__PURE__ */ import_react21.default.createElement(ArtistLink, {
+ index,
+ length: props.artists.length - 1,
+ name: artist.name,
+ uri: artist.uri
+ });
+ });
+ return /* @__PURE__ */ import_react21.default.createElement(import_react21.default.Fragment, null, /* @__PURE__ */ import_react21.default.createElement(Spicetify.ReactComponent.ContextMenu, {
+ menu: /* @__PURE__ */ import_react21.default.createElement(MenuWrapper, {
+ uri: props.uri
+ }),
+ trigger: "right-click"
+ }, /* @__PURE__ */ import_react21.default.createElement("div", {
+ role: "row",
+ "aria-rowindex": 2,
+ "aria-selected": "false"
+ }, /* @__PURE__ */ import_react21.default.createElement(DraggableComponent, {
+ uri: props.uri,
+ title: `${props.name} \u2022 ${props.artists.map((artist) => artist.name).join(", ")}`,
+ className: "main-trackList-trackListRow main-trackList-trackListRowGrid",
+ role: "presentation",
+ onClick: (event) => event.detail === 2 && playAndQueue(props.uri, props.uris),
+ style: { height: 56 }
+ }, /* @__PURE__ */ import_react21.default.createElement("div", {
+ className: "main-trackList-rowSectionIndex",
+ role: "gridcell",
+ "aria-colindex": 1,
+ tabIndex: -1
+ }, /* @__PURE__ */ import_react21.default.createElement("div", {
+ uri: props.uri,
+ className: "main-trackList-rowMarker"
+ }, /* @__PURE__ */ import_react21.default.createElement("span", {
+ className: "TypeElement-ballad-type main-trackList-number",
+ "data-encore-id": "type"
+ }, props.index), /* @__PURE__ */ import_react21.default.createElement(Spicetify.ReactComponent.TooltipWrapper, {
+ label: `Play ${props.name} by ${props.artists.map((artist) => artist.name).join(", ")}`,
+ placement: "top"
+ }, /* @__PURE__ */ import_react21.default.createElement("button", {
+ type: "button",
+ className: "main-trackList-rowImagePlayButton",
+ "aria-label": `Play ${props.name}`,
+ tabIndex: -1,
+ onClick: () => playAndQueue(props.uri, props.uris)
+ }, /* @__PURE__ */ import_react21.default.createElement("svg", {
+ role: "img",
+ height: "24",
+ width: "24",
+ "aria-hidden": "true",
+ className: "Svg-img-24 Svg-img-24-icon main-trackList-rowPlayPauseIcon",
+ viewBox: "0 0 24 24",
+ "data-encore-id": "icon"
+ }, /* @__PURE__ */ import_react21.default.createElement("path", {
+ d: "m7.05 3.606 13.49 7.788a.7.7 0 0 1 0 1.212L7.05 20.394A.7.7 0 0 1 6 19.788V4.212a.7.7 0 0 1 1.05-.606z"
+ })))))), /* @__PURE__ */ import_react21.default.createElement("div", {
+ className: "main-trackList-rowSectionStart",
+ role: "gridcell",
+ "aria-colindex": 2,
+ tabIndex: -1
+ }, /* @__PURE__ */ import_react21.default.createElement("img", {
+ "aria-hidden": "false",
+ draggable: "false",
+ loading: "eager",
+ src: props.image || "https://raw.githubusercontent.com/harbassan/spicetify-apps/main/stats/src/styles/placeholder.png",
+ alt: "",
+ className: "main-image-image main-trackList-rowImage main-image-loaded",
+ width: "40",
+ height: "40"
+ }), /* @__PURE__ */ import_react21.default.createElement("div", {
+ className: "main-trackList-rowMainContent"
+ }, /* @__PURE__ */ import_react21.default.createElement("div", {
+ dir: "auto",
+ className: "TypeElement-ballad-textBase TypeElement-ballad-textBase-type main-trackList-rowTitle standalone-ellipsis-one-line",
+ "data-encore-id": "type"
+ }, props.name), props.explicit && /* @__PURE__ */ import_react21.default.createElement(ExplicitBadge, null), /* @__PURE__ */ import_react21.default.createElement("span", {
+ className: "TypeElement-mesto-textSubdued TypeElement-mesto-textSubdued-type main-trackList-rowSubTitle standalone-ellipsis-one-line",
+ "data-encore-id": "type"
+ }, ArtistLinks))), props.playcount && /* @__PURE__ */ import_react21.default.createElement("div", {
+ className: "main-trackList-rowSectionVariable",
+ role: "gridcell",
+ "aria-colindex": 3,
+ tabIndex: -1
+ }, /* @__PURE__ */ import_react21.default.createElement("span", {
+ "data-encore-id": "type",
+ className: "TypeElement-mesto TypeElement-mesto-type"
+ }, formatNumber(props.playcount))), /* @__PURE__ */ import_react21.default.createElement("div", {
+ className: "main-trackList-rowSectionVariable",
+ role: "gridcell",
+ "aria-colindex": 4,
+ tabIndex: -1
+ }, /* @__PURE__ */ import_react21.default.createElement("span", {
+ "data-encore-id": "type",
+ className: "TypeElement-mesto TypeElement-mesto-type"
+ }, /* @__PURE__ */ import_react21.default.createElement("a", {
+ draggable: "true",
+ className: "standalone-ellipsis-one-line",
+ dir: "auto",
+ href: props.album?.uri,
+ tabIndex: -1
+ }, props.album?.name || "Unknown"))), /* @__PURE__ */ import_react21.default.createElement("div", {
+ className: "main-trackList-rowSectionEnd",
+ role: "gridcell",
+ "aria-colindex": 5,
+ tabIndex: -1
+ }, /* @__PURE__ */ import_react21.default.createElement(LikedIcon, {
+ active: props.liked || false,
+ uri: props.uri
+ }), /* @__PURE__ */ import_react21.default.createElement("div", {
+ className: "TypeElement-mesto-textSubdued TypeElement-mesto-textSubdued-type main-trackList-rowDuration",
+ "data-encore-id": "type"
+ }, Spicetify.Player.formatTime(props.duration_ms)), /* @__PURE__ */ import_react21.default.createElement(Spicetify.ReactComponent.ContextMenu, {
+ menu: /* @__PURE__ */ import_react21.default.createElement(MenuWrapper, {
+ uri: props.uri
+ }),
+ trigger: "click"
+ }, /* @__PURE__ */ import_react21.default.createElement("button", {
+ type: "button",
+ "aria-haspopup": "menu",
+ "aria-label": `More options for ${props.name}`,
+ className: "main-moreButton-button Button-sm-16-buttonTertiary-iconOnly-condensed-useBrowserDefaultFocusStyle Button-small-small-buttonTertiary-iconOnly-condensed-useBrowserDefaultFocusStyle main-trackList-rowMoreButton",
+ tabIndex: -1
+ }, /* @__PURE__ */ import_react21.default.createElement(Spicetify.ReactComponent.TooltipWrapper, {
+ label: `More options for ${props.name} by ${props.artists.map((artist) => artist.name).join(", ")}`,
+ placement: "top"
+ }, /* @__PURE__ */ import_react21.default.createElement("span", null, /* @__PURE__ */ import_react21.default.createElement("svg", {
+ role: "img",
+ height: "16",
+ width: "16",
+ "aria-hidden": "true",
+ viewBox: "0 0 16 16",
+ "data-encore-id": "icon",
+ className: "Svg-img-16 Svg-img-16-icon Svg-img-icon Svg-img-icon-small"
+ }, /* @__PURE__ */ import_react21.default.createElement("path", {
+ d: "M3 8a1.5 1.5 0 1 1-3 0 1.5 1.5 0 0 1 3 0zm6.5 0a1.5 1.5 0 1 1-3 0 1.5 1.5 0 0 1 3 0zM16 8a1.5 1.5 0 1 1-3 0 1.5 1.5 0 0 1 3 0z"
+ })))))))))));
+ };
+ var track_row_default = import_react21.default.memo(TrackRow);
+
+ // src/pages/top_tracks.tsx
+ var getTopTracks3 = async (timeRange, config) => {
+ if (config["use-lastfm"]) {
+ const { "lastfm-user": user, "api-key": key } = config;
+ if (!user || !key)
+ throw new Error("Missing LastFM API Key or Username");
+ const response2 = await getTopTracks2(key, user, timeRange);
+ return parseLiked(await Promise.all(response2.map(convertTrack)));
+ }
+ const response = await getTopTracks(timeRange);
+ return parseLiked(response.map(minifyTrack));
+ };
+ var TracksPage = ({ configWrapper }) => {
+ const [dropdown, activeOption] = useDropdownMenu_default(DropdownOptions(configWrapper), "stats:top-tracks");
+ const { status, error, data, refetch } = useQuery({
+ queryKey: ["top-tracks", activeOption.id],
+ queryFn: cacher(() => getTopTracks3(activeOption.id, configWrapper.config))
+ });
+ const Status2 = useStatus_default(status, error);
const props = {
title: "Top Tracks",
- headerEls: [dropdown, /* @__PURE__ */ import_react20.default.createElement(refresh_button_default, {
- callback: refresh
- }), /* @__PURE__ */ import_react20.default.createElement(settings_button_default, {
- configWrapper
- })]
+ headerEls: [
+ dropdown,
+ /* @__PURE__ */ import_react22.default.createElement(refresh_button_default, {
+ callback: () => invalidator(["top-tracks", activeOption.id], refetch)
+ }),
+ /* @__PURE__ */ import_react22.default.createElement(settings_button_default, {
+ configWrapper
+ })
+ ]
};
- switch (topTracks) {
- case 300:
- return /* @__PURE__ */ import_react20.default.createElement(page_container_default, {
- ...props
- }, /* @__PURE__ */ import_react20.default.createElement(status_default, {
- icon: "error",
- heading: "No API Key or Username",
- subheading: "Please enter these in the settings menu"
- }));
- case 200:
- return /* @__PURE__ */ import_react20.default.createElement(page_container_default, {
- ...props
- }, /* @__PURE__ */ import_react20.default.createElement(status_default, {
- icon: "error",
- heading: "Failed to Fetch Top Tracks",
- subheading: "An error occurred while fetching the data"
- }));
- case 100:
- return /* @__PURE__ */ import_react20.default.createElement(page_container_default, {
- ...props
- }, /* @__PURE__ */ import_react20.default.createElement(status_default, {
- icon: "library",
- heading: "Loading",
- subheading: "Fetching data..."
- }));
- }
+ if (Status2)
+ return /* @__PURE__ */ import_react22.default.createElement(page_container_default, {
+ ...props
+ }, Status2);
+ const topTracks = data;
const infoToCreatePlaylist = {
- playlistName: `Top Songs - ${activeOption}`,
+ playlistName: `Top Songs - ${activeOption.name}`,
itemsUris: topTracks.map((track) => track.uri)
};
- const trackRows = topTracks.map((track, index) => /* @__PURE__ */ import_react20.default.createElement(track_row_default, {
+ const trackRows = topTracks.map((track, index) => /* @__PURE__ */ import_react22.default.createElement(track_row_default, {
index: index + 1,
...track,
uris: topTracks.map((track2) => track2.uri)
}));
- return /* @__PURE__ */ import_react20.default.createElement(page_container_default, {
+ return /* @__PURE__ */ import_react22.default.createElement(page_container_default, {
...props,
infoToCreatePlaylist
- }, /* @__PURE__ */ import_react20.default.createElement(tracklist_default, null, trackRows));
+ }, /* @__PURE__ */ import_react22.default.createElement(tracklist_default, {
+ playcount: Boolean(topTracks[0].playcount)
+ }, trackRows));
};
- var top_tracks_default = import_react20.default.memo(TracksPage);
+ var top_tracks_default = import_react22.default.memo(TracksPage);
// src/pages/top_genres.tsx
- var import_react25 = __toESM(require_react());
+ var import_react26 = __toESM(require_react());
// src/components/cards/stat_card.tsx
- var import_react21 = __toESM(require_react());
- function formatValue(name, value) {
- switch (name) {
- case "tempo":
- return `${Math.round(value)} bpm`;
- case "popularity":
- return `${Math.round(value)} %`;
- default:
- return `${Math.round(value * 100)} %`;
- }
- }
- function normalizeString(inputString) {
- return inputString.charAt(0).toUpperCase() + inputString.slice(1).toLowerCase();
- }
- function StatCard(props) {
+ var import_react23 = __toESM(require_react());
+ var import_lodash2 = __toESM(require_lodash());
+ function StatCard({ label, value }) {
const { TextComponent } = Spicetify.ReactComponent;
- const { label, value } = props;
- return /* @__PURE__ */ import_react21.default.createElement("div", {
+ return /* @__PURE__ */ import_react23.default.createElement("div", {
className: "main-card-card"
- }, /* @__PURE__ */ import_react21.default.createElement(TextComponent, {
+ }, /* @__PURE__ */ import_react23.default.createElement(TextComponent, {
as: "div",
semanticColor: "textBase",
- variant: "alto",
- children: typeof value === "number" ? formatValue(label, value) : value
- }), /* @__PURE__ */ import_react21.default.createElement(TextComponent, {
+ variant: "alto"
+ }, value), /* @__PURE__ */ import_react23.default.createElement(TextComponent, {
as: "div",
semanticColor: "textBase",
- variant: "balladBold",
- children: normalizeString(label)
- }));
+ variant: "balladBold"
+ }, import_lodash2.default.startCase(label)));
}
var stat_card_default = StatCard;
- // src/components/cards/genres_card.tsx
- var import_react22 = __toESM(require_react());
- var genreLine = (name, value, limit, total) => {
- return /* @__PURE__ */ import_react22.default.createElement("div", {
+ // src/components/cards/chart_card.tsx
+ var import_react24 = __toESM(require_react());
+ var ChartLine = (name, value, limit, total) => {
+ return /* @__PURE__ */ import_react24.default.createElement("div", {
className: "stats-genreRow"
- }, /* @__PURE__ */ import_react22.default.createElement("div", {
+ }, /* @__PURE__ */ import_react24.default.createElement("div", {
className: "stats-genreRowFill",
style: {
width: `calc(${value / limit * 100}% + ${(limit - value) / (limit - 1) * 100}px)`
}
- }, /* @__PURE__ */ import_react22.default.createElement("span", {
+ }, /* @__PURE__ */ import_react24.default.createElement("span", {
className: "stats-genreText"
- }, name)), /* @__PURE__ */ import_react22.default.createElement("span", {
+ }, name)), /* @__PURE__ */ import_react24.default.createElement("span", {
className: "stats-genreValue"
- }, Math.round(value / total * 100) + "%"));
+ }, `${Math.round(value / total * 100)}%`));
};
- var genreLines = (genres, total) => {
- return genres.map(([genre, value]) => {
- return genreLine(genre, value, genres[0][1], total);
+ var ChartCard = ({ data }) => {
+ const [extended, setExtended] = import_react24.default.useState(false);
+ const keys = Object.keys(data).sort((a, b) => data[b] - data[a]).slice(0, extended ? 50 : 10);
+ const total = Object.values(data).reduce((acc, curr) => acc + curr, 0);
+ return /* @__PURE__ */ import_react24.default.createElement("div", {
+ className: "main-card-card stats-genreCard"
+ }, keys.map((key) => ChartLine(key, data[key], data[keys[0]], total)), /* @__PURE__ */ import_react24.default.createElement("button", {
+ type: "button",
+ className: "extend-button",
+ onClick: () => {
+ setExtended(!extended);
+ }
+ }, extended ? "See Less" : "See More"));
+ };
+ var chart_card_default = ChartCard;
+
+ // src/components/shelf.tsx
+ var import_react25 = __toESM(require_react());
+ function Shelf(props) {
+ const { TextComponent } = Spicetify.ReactComponent;
+ const { title, children } = props;
+ return /* @__PURE__ */ import_react25.default.createElement("section", {
+ className: "main-shelf-shelf Shelf"
+ }, /* @__PURE__ */ import_react25.default.createElement("div", {
+ className: "main-shelf-header"
+ }, /* @__PURE__ */ import_react25.default.createElement("div", {
+ className: "main-shelf-topRow"
+ }, /* @__PURE__ */ import_react25.default.createElement("div", {
+ className: "main-shelf-titleWrapper"
+ }, /* @__PURE__ */ import_react25.default.createElement(TextComponent, {
+ children: title,
+ as: "h2",
+ variant: "canon",
+ semanticColor: "textBase"
+ })))), /* @__PURE__ */ import_react25.default.createElement("section", null, children));
+ }
+ var shelf_default = import_react25.default.memo(Shelf);
+
+ // src/pages/top_genres.tsx
+ var parseArtists2 = async (artistsRaw) => {
+ const artists = await batchRequest(50, getArtistMetas)(artistsRaw.map((artist) => artist.uri.split(":")[2]));
+ const genres = {};
+ for (const artist of artists) {
+ for (const genre of artist.genres) {
+ genres[genre] = (genres[genre] || 0) + 1;
+ }
+ }
+ return genres;
+ };
+ var parseAlbums2 = (albums) => {
+ const releaseYears = {};
+ for (const album of albums) {
+ const year = album.release_date.slice(0, 4);
+ releaseYears[year] = (releaseYears[year] || 0) + 1;
+ }
+ return releaseYears;
+ };
+ var parseTracks2 = async (tracks) => {
+ const trackIDs = [];
+ const albumsRaw = [];
+ const artistsRaw = [];
+ let explicit = 0;
+ let popularity = 0;
+ for (const track of tracks) {
+ if (track.type !== "spotify")
+ continue;
+ popularity += track.popularity;
+ explicit += track.explicit ? 1 : 0;
+ trackIDs.push(track.id);
+ albumsRaw.push(track.album);
+ artistsRaw.push(...track.artists);
+ }
+ explicit = explicit / trackIDs.length;
+ popularity = popularity / trackIDs.length;
+ const audioFeatures = await getMeanAudioFeatures(trackIDs);
+ const analysis = { ...audioFeatures, popularity, explicit };
+ const genres = await parseArtists2(artistsRaw);
+ const releaseYears = parseAlbums2(albumsRaw);
+ return { analysis, genres, releaseYears };
+ };
+ var getGenres = async (time_range, config) => {
+ const topTracks = await cacher(() => getTopTracks3(time_range, config))({ queryKey: ["top-tracks", time_range] });
+ return parseTracks2(topTracks);
+ };
+ var GenresPage = ({ configWrapper }) => {
+ const [dropdown, activeOption] = useDropdownMenu_default(DropdownOptions(configWrapper), "stats:top-genres");
+ const { status, error, data, refetch } = useQuery({
+ queryKey: ["top-genres", activeOption.id],
+ queryFn: cacher(() => getGenres(activeOption.id, configWrapper.config))
});
+ const Status2 = useStatus_default(status, error);
+ const props = {
+ title: "Top Genres",
+ headerEls: [
+ dropdown,
+ /* @__PURE__ */ import_react26.default.createElement(refresh_button_default, {
+ callback: () => invalidator(["top-genres", activeOption.id], refetch)
+ }),
+ /* @__PURE__ */ import_react26.default.createElement(settings_button_default, {
+ configWrapper
+ })
+ ]
+ };
+ if (Status2)
+ return /* @__PURE__ */ import_react26.default.createElement(page_container_default, {
+ ...props
+ }, Status2);
+ const analysis = data;
+ const statCards = Object.entries(analysis.analysis).map(([key, value]) => {
+ return /* @__PURE__ */ import_react26.default.createElement(stat_card_default, {
+ label: key,
+ value: parseStat(key)(value)
+ });
+ });
+ return /* @__PURE__ */ import_react26.default.createElement(page_container_default, {
+ ...props
+ }, /* @__PURE__ */ import_react26.default.createElement("section", {
+ className: "main-shelf-shelf Shelf"
+ }, /* @__PURE__ */ import_react26.default.createElement(chart_card_default, {
+ data: analysis.genres
+ }), /* @__PURE__ */ import_react26.default.createElement("div", {
+ className: "main-gridContainer-gridContainer grid"
+ }, statCards)), /* @__PURE__ */ import_react26.default.createElement(shelf_default, {
+ title: "Release Year Distribution"
+ }, /* @__PURE__ */ import_react26.default.createElement(chart_card_default, {
+ data: analysis.releaseYears
+ })));
};
- var genresCard = ({ genres, total }) => {
- const genresArray = genres.sort(([, a], [, b]) => b - a).slice(0, 10);
- return /* @__PURE__ */ import_react22.default.createElement("div", {
- className: `main-card-card stats-genreCard`
- }, genreLines(genresArray, total));
- };
- var genres_card_default = genresCard;
+ var top_genres_default = import_react26.default.memo(GenresPage);
+
+ // src/pages/library.tsx
+ var import_react28 = __toESM(require_react());
// src/components/inline_grid.tsx
- var import_react23 = __toESM(require_react());
+ var import_react27 = __toESM(require_react());
function scrollGrid(event) {
const { target } = event;
if (!(target instanceof HTMLElement))
@@ -1642,766 +7264,184 @@ var stats = (() => {
}
function InlineGrid(props) {
const { children, special } = props;
- return /* @__PURE__ */ import_react23.default.createElement("section", {
+ return /* @__PURE__ */ import_react27.default.createElement("section", {
className: "stats-gridInlineSection"
- }, /* @__PURE__ */ import_react23.default.createElement("button", {
+ }, /* @__PURE__ */ import_react27.default.createElement("button", {
className: "stats-scrollButton",
onClick: scrollGridLeft
- }, "<"), /* @__PURE__ */ import_react23.default.createElement("button", {
+ }, "<"), /* @__PURE__ */ import_react27.default.createElement("button", {
className: "stats-scrollButton",
onClick: scrollGrid
- }, ">"), /* @__PURE__ */ import_react23.default.createElement("div", {
+ }, ">"), /* @__PURE__ */ import_react27.default.createElement("div", {
className: `main-gridContainer-gridContainer stats-gridInline${special ? " stats-specialGrid" : ""}`,
"data-scroll": "start"
}, children));
}
- var inline_grid_default = import_react23.default.memo(InlineGrid);
+ var inline_grid_default = import_react27.default.memo(InlineGrid);
- // src/components/shelf.tsx
- var import_react24 = __toESM(require_react());
- function Shelf(props) {
- const { TextComponent } = Spicetify.ReactComponent;
- const { title, children } = props;
- return /* @__PURE__ */ import_react24.default.createElement("section", {
- className: "main-shelf-shelf Shelf"
- }, /* @__PURE__ */ import_react24.default.createElement("div", {
- className: "main-shelf-header"
- }, /* @__PURE__ */ import_react24.default.createElement("div", {
- className: "main-shelf-topRow"
- }, /* @__PURE__ */ import_react24.default.createElement("div", {
- className: "main-shelf-titleWrapper"
- }, /* @__PURE__ */ import_react24.default.createElement(TextComponent, {
- children: title,
- as: "h2",
- variant: "canon",
- semanticColor: "textBase"
- })))), /* @__PURE__ */ import_react24.default.createElement("section", null, children));
- }
- var shelf_default = import_react24.default.memo(Shelf);
-
- // src/pages/top_genres.tsx
- var DropdownOptions3 = [
- { id: "short_term", name: "Past Month" },
- { id: "medium_term", name: "Past 6 Months" },
- { id: "long_term", name: "All Time" }
- ];
- var GenresPage = ({ configWrapper }) => {
- const { LocalStorage } = Spicetify;
- const [topGenres, setTopGenres] = import_react25.default.useState(100);
- const [dropdown, activeOption] = useDropdownMenu_default(DropdownOptions3, "stats:top-genres");
- const fetchTopGenres = async (time_range, force, set = true, force_refetch) => {
- if (!force) {
- let storedData = LocalStorage.get(`stats:top-genres:${time_range}`);
- if (storedData)
- return setTopGenres(JSON.parse(storedData));
- }
- const start = window.performance.now();
- const cacheInfo = JSON.parse(LocalStorage.get("stats:cache-info"));
- const fetchedItems = await Promise.all(
- ["artists", "tracks"].map(async (type, index) => {
- if (cacheInfo[index] === true && !force_refetch) {
- return await JSON.parse(LocalStorage.get(`stats:top-${type}:${time_range}`));
- }
- const fetchedItems2 = await (type === "artists" ? topArtistsReq(time_range, configWrapper) : topTracksReq(time_range, configWrapper));
- cacheInfo[index] = true;
- cacheInfo[2] = true;
- LocalStorage.set(`stats:top-${type}:${time_range}`, JSON.stringify(fetchedItems2));
- LocalStorage.set("stats:cache-info", JSON.stringify(cacheInfo));
- return fetchedItems2;
- })
- );
- for (let i = 0; i < 2; i++) {
- if (fetchedItems[i] === 200 || fetchedItems[i] === 300)
- return setTopGenres(fetchedItems[i]);
- }
- const fetchedArtists = fetchedItems[0].filter((artist) => artist?.genres);
- const fetchedTracks = fetchedItems[1].filter((track) => track?.id);
- const genres = fetchedArtists.reduce((acc, artist) => {
- artist.genres.forEach((genre) => {
- const index = acc.findIndex(([g]) => g === genre);
- if (index !== -1) {
- acc[index][1] += 1 * Math.abs(fetchedArtists.indexOf(artist) - 50);
- } else {
- acc.push([genre, 1 * Math.abs(fetchedArtists.indexOf(artist) - 50)]);
- }
- });
- return acc;
- }, []);
- let trackPopularity = 0;
- let explicitness = 0;
- let releaseData = [];
- const topTracks = fetchedTracks.map((track) => {
- trackPopularity += track.popularity;
- if (track.explicit)
- explicitness++;
- if (track.release_year) {
- const year = track.release_year;
- const index = releaseData.findIndex(([y]) => y === year);
- if (index !== -1) {
- releaseData[index][1] += 1;
- } else {
- releaseData.push([year, 1]);
- }
- }
- return track.id;
- });
- async function testDupe(track) {
- const spotifyItem = await apiRequest(
- "track",
- SPOTIFY.search(track.name, track.artists[0].name),
- 1,
- false
- ).then((res) => res.tracks?.items);
- if (!spotifyItem)
- return false;
- return spotifyItem.some((item) => {
- return item.name === track.name && item.popularity > track.popularity;
- });
- }
- let obscureTracks2 = [];
- for (let i = 0; i < fetchedTracks.length; i++) {
- let track = fetchedTracks[i];
- if (!track?.popularity)
- continue;
- if (obscureTracks2.length < 5) {
- const dupe = await testDupe(track);
- if (dupe)
- continue;
- obscureTracks2.push(track);
- obscureTracks2.sort((a, b) => b.popularity - a.popularity);
- continue;
- }
- for (let j = 0; j < 5; j++) {
- if (track.popularity < obscureTracks2[j].popularity) {
- const dupe = await testDupe(track);
- if (dupe)
- break;
- obscureTracks2.splice(j, 0, track);
- obscureTracks2 = obscureTracks2.slice(0, 5);
- break;
- }
- }
- }
- const fetchedFeatures = await fetchAudioFeatures(topTracks);
- let audioFeatures = {
- danceability: 0,
- energy: 0,
- valence: 0,
- speechiness: 0,
- acousticness: 0,
- instrumentalness: 0,
- liveness: 0,
- tempo: 0
- };
- for (let i = 0; i < fetchedFeatures.length; i++) {
- if (!fetchedFeatures[i])
- continue;
- const track = fetchedFeatures[i];
- Object.keys(audioFeatures).forEach((feature) => {
- audioFeatures[feature] += track[feature];
- });
- }
- audioFeatures = {
- popularity: trackPopularity,
- explicitness,
- ...audioFeatures
- };
- for (let key in audioFeatures) {
- audioFeatures[key] = audioFeatures[key] / 50;
- }
- console.log("total genres fetch time:", window.performance.now() - start);
- if (set)
- setTopGenres({
- genres,
- features: audioFeatures,
- years: releaseData,
- obscureTracks: obscureTracks2
- });
- LocalStorage.set(
- `stats:top-genres:${time_range}`,
- JSON.stringify({
- genres,
- features: audioFeatures,
- years: releaseData,
- obscureTracks: obscureTracks2
- })
- );
- };
- import_react25.default.useEffect(() => {
- updatePageCache(2, fetchTopGenres, activeOption.id);
- }, []);
- import_react25.default.useEffect(() => {
- fetchTopGenres(activeOption.id);
- }, [activeOption]);
- const refresh = () => {
- fetchTopGenres(activeOption.id, true);
- };
- const props = {
- title: "Top Genres",
- headerEls: [dropdown, /* @__PURE__ */ import_react25.default.createElement(refresh_button_default, {
- callback: refresh
- }), /* @__PURE__ */ import_react25.default.createElement(settings_button_default, {
- configWrapper
- })]
- };
- switch (topGenres) {
- case 300:
- return /* @__PURE__ */ import_react25.default.createElement(page_container_default, {
- ...props
- }, /* @__PURE__ */ import_react25.default.createElement(status_default, {
- icon: "error",
- heading: "No API Key or Username",
- subheading: "Please enter these in the settings menu"
- }));
- case 200:
- return /* @__PURE__ */ import_react25.default.createElement(page_container_default, {
- ...props
- }, /* @__PURE__ */ import_react25.default.createElement(status_default, {
- icon: "error",
- heading: "Failed to Fetch Top Genres",
- subheading: "An error occurred while fetching the data"
- }));
- case 100:
- return /* @__PURE__ */ import_react25.default.createElement(page_container_default, {
- ...props
- }, /* @__PURE__ */ import_react25.default.createElement(status_default, {
- icon: "library",
- heading: "Loading",
- subheading: "Fetching data..."
- }));
- }
- const statCards = Object.entries(topGenres.features).map(([key, value]) => {
- return /* @__PURE__ */ import_react25.default.createElement(stat_card_default, {
- label: key,
- value
- });
- });
- const obscureTracks = topGenres.obscureTracks.map((track, index) => /* @__PURE__ */ import_react25.default.createElement(track_row_default, {
- index: index + 1,
- ...track,
- uris: topGenres.obscureTracks.map((track2) => track2.uri)
- }));
- return /* @__PURE__ */ import_react25.default.createElement(page_container_default, {
- ...props
- }, /* @__PURE__ */ import_react25.default.createElement("section", {
- className: "main-shelf-shelf Shelf"
- }, /* @__PURE__ */ import_react25.default.createElement(genres_card_default, {
- genres: topGenres.genres,
- total: 1275
- }), /* @__PURE__ */ import_react25.default.createElement(inline_grid_default, {
- special: true
- }, statCards)), /* @__PURE__ */ import_react25.default.createElement(shelf_default, {
- title: "Release Year Distribution"
- }, /* @__PURE__ */ import_react25.default.createElement(genres_card_default, {
- genres: topGenres.years,
- total: 50
- })), /* @__PURE__ */ import_react25.default.createElement(shelf_default, {
- title: "Most Obscure Tracks"
- }, /* @__PURE__ */ import_react25.default.createElement(tracklist_default, {
- minified: true
- }, obscureTracks)));
+ // src/api/platform.ts
+ var getFullPlaylist = async (uri) => {
+ const playlist = await Spicetify.Platform.PlaylistAPI.getPlaylist(uri);
+ const tracks = playlist.contents.items;
+ return tracks;
};
- var top_genres_default = import_react25.default.memo(GenresPage);
// src/pages/library.tsx
- var import_react26 = __toESM(require_react());
- var DropdownOptions4 = [
+ var DropdownOptions3 = [
{ id: "owned", name: "My Playlists" },
{ id: "all", name: "All Playlists" }
];
+ var getLibrary = async (type) => {
+ let playlists = await getUserPlaylists();
+ if (type === "owned")
+ playlists = playlists.filter((p) => p.owner.id === Spicetify.Platform.username);
+ if (playlists.length === 0)
+ throw new Error("You have no playlists saved");
+ const contents = await Promise.all(playlists.map((p) => getFullPlaylist(p.uri)));
+ const analysis = await parseTracks(contents.flat());
+ return { ...analysis, playlists: playlists.length };
+ };
var LibraryPage = ({ configWrapper }) => {
- const [library, setLibrary] = import_react26.default.useState(100);
- const [dropdown, activeOption, setActiveOption] = useDropdownMenu_default(DropdownOptions4, "stats:library");
- const fetchData = async (option, force, set = true) => {
- try {
- if (!force) {
- let storedData = Spicetify.LocalStorage.get(`stats:library:${option}`);
- if (storedData)
- return setLibrary(JSON.parse(storedData));
- }
- const start = window.performance.now();
- const rootlistItems = await apiRequest("rootlist", SPOTIFY.rootlist);
- const flattenPlaylists = (items) => {
- const playlists2 = [];
- items.forEach((row) => {
- if (row.type === "playlist") {
- playlists2.push(row);
- } else if (row.type === "folder") {
- if (!row.rows)
- return;
- const folderPlaylists = flattenPlaylists(row.rows);
- playlists2.push(...folderPlaylists);
- }
- });
- return playlists2;
- };
- let playlists = flattenPlaylists(rootlistItems?.rows);
- playlists = playlists.sort((a, b) => a.ownedBySelf === b.ownedBySelf ? 0 : a.ownedBySelf ? -1 : 1);
- let indexOfFirstNotOwned = -1;
- let playlistUris = [];
- let trackCount = 0;
- let ownedTrackCount = 0;
- playlists.forEach((playlist) => {
- if (playlist.totalLength === 0)
- return;
- if (!playlist.ownedBySelf && indexOfFirstNotOwned === -1)
- indexOfFirstNotOwned = playlistUris.length;
- playlistUris.push(playlist.link);
- trackCount += playlist.totalLength;
- if (playlist.ownedBySelf)
- ownedTrackCount += playlist.totalLength;
- }, 0);
- const playlistsMeta = await Promise.all(
- playlistUris.map((uri) => {
- return apiRequest("playlistsMetadata", SPOTIFY.playlist(uri), 5, false);
- })
- );
- let duration = 0;
- let trackIDs = [];
- let popularity = 0;
- let albums = {};
- let artists = {};
- let explicitCount = 0;
- let ownedDuration = 0;
- let ownedArtists = {};
- let ownedPopularity = 0;
- let ownedAlbums = {};
- let ownedExplicitCount = 0;
- for (let i = 0; i < playlistsMeta.length; i++) {
- const playlist = playlistsMeta[i];
- if (!playlist)
- continue;
- if (i === indexOfFirstNotOwned) {
- ownedDuration = duration;
- ownedArtists = Object.assign({}, artists);
- ownedPopularity = popularity;
- ownedExplicitCount = explicitCount;
- ownedAlbums = Object.assign({}, albums);
- }
- duration += playlist.playlist.duration;
- playlist.items.forEach((track) => {
- if (!track?.album)
- return;
- if (track.link.includes("local"))
- return;
- trackIDs.push(track.link.split(":")[2]);
- if (track.isExplicit)
- explicitCount++;
- popularity += track.popularity;
- const albumID = track.album.link.split(":")[2];
- albums[albumID] = albums[albumID] ? albums[albumID] + 1 : 1;
- track.artists.forEach((artist) => {
- const artistID = artist.link.split(":")[2];
- artists[artistID] = artists[artistID] ? artists[artistID] + 1 : 1;
- });
- });
- }
- const [topArtists, topGenres, topGenresTotal] = await fetchTopArtists(artists);
- const [ownedTopArtists, ownedTopGenres, ownedTopGenresTotal] = await fetchTopArtists(ownedArtists);
- const [topAlbums, releaseYears, releaseYearsTotal] = await fetchTopAlbums(albums);
- const [ownedTopAlbums, ownedReleaseYears, ownedReleaseYearsTotal] = await fetchTopAlbums(
- ownedAlbums,
- topAlbums
- );
- const fetchedFeatures = await fetchAudioFeatures(trackIDs);
- const audioFeatures = {
- danceability: 0,
- energy: 0,
- valence: 0,
- speechiness: 0,
- acousticness: 0,
- instrumentalness: 0,
- liveness: 0,
- tempo: 0
- };
- let ownedAudioFeatures = {};
- for (let i = 0; i < fetchedFeatures.length; i++) {
- if (i === ownedTrackCount) {
- ownedAudioFeatures = {
- popularity: ownedPopularity,
- explicitness: ownedExplicitCount,
- ...audioFeatures
- };
- }
- if (!fetchedFeatures[i])
- continue;
- const track = fetchedFeatures[i];
- Object.keys(audioFeatures).forEach((feature) => {
- audioFeatures[feature] += track[feature];
- });
- }
- const allAudioFeatures = {
- popularity,
- explicitness: explicitCount,
- ...audioFeatures
- };
- for (let key in allAudioFeatures) {
- allAudioFeatures[key] /= fetchedFeatures.length;
- }
- for (let key in ownedAudioFeatures) {
- ownedAudioFeatures[key] /= ownedTrackCount;
- }
- const ownedStats = {
- audioFeatures: ownedAudioFeatures,
- trackCount: ownedTrackCount,
- totalDuration: ownedDuration,
- artists: ownedTopArtists,
- artistCount: Object.keys(ownedArtists).length,
- genres: ownedTopGenres,
- genresDenominator: ownedTopGenresTotal,
- playlistCount: indexOfFirstNotOwned > 0 ? indexOfFirstNotOwned : 0,
- albums: ownedTopAlbums,
- years: ownedReleaseYears,
- yearsDenominator: ownedReleaseYearsTotal
- };
- const allStats = {
- playlistCount: playlists.length,
- audioFeatures: allAudioFeatures,
- trackCount,
- totalDuration: duration,
- artistCount: Object.keys(artists).length,
- artists: topArtists,
- genres: topGenres,
- genresDenominator: topGenresTotal,
- albums: topAlbums,
- years: releaseYears,
- yearsDenominator: releaseYearsTotal
- };
- if (set) {
- if (option === "all" && allStats.playlistCount)
- setLibrary(allStats);
- else if (option === "owned" && ownedStats.playlistCount)
- setLibrary(ownedStats);
- else
- return setLibrary(300);
- }
- Spicetify.LocalStorage.set(`stats:library:all`, JSON.stringify(allStats));
- Spicetify.LocalStorage.set(`stats:library:owned`, JSON.stringify(ownedStats));
- console.log("total library fetch time:", window.performance.now() - start);
- } catch (e) {
- console.error(e);
- setLibrary(200);
- }
- };
- import_react26.default.useEffect(() => {
- updatePageCache(3, fetchData, activeOption.id, true);
- }, []);
- import_react26.default.useEffect(() => {
- fetchData(activeOption.id);
- }, [activeOption]);
- const refresh = () => {
- fetchData(activeOption.id, true);
- };
+ const [dropdown, activeOption] = useDropdownMenu_default(DropdownOptions3, "stats:library");
+ const { status, error, data, refetch } = useQuery({
+ queryKey: ["library", activeOption.id],
+ queryFn: cacher(() => getLibrary(activeOption.id))
+ });
const props = {
title: "Library Analysis",
- headerEls: [dropdown, /* @__PURE__ */ import_react26.default.createElement(refresh_button_default, {
- callback: refresh
- }), /* @__PURE__ */ import_react26.default.createElement(settings_button_default, {
- configWrapper
- })]
+ headerEls: [
+ dropdown,
+ /* @__PURE__ */ import_react28.default.createElement(refresh_button_default, {
+ callback: () => invalidator(["library", activeOption.id], refetch)
+ }),
+ /* @__PURE__ */ import_react28.default.createElement(settings_button_default, {
+ configWrapper
+ })
+ ]
};
- switch (library) {
- case 300:
- return /* @__PURE__ */ import_react26.default.createElement(page_container_default, {
- ...props
- }, /* @__PURE__ */ import_react26.default.createElement(status_default, {
- icon: "error",
- heading: "No Playlists In Your Library",
- subheading: "Try adding some playlists first"
- }));
- case 200:
- return /* @__PURE__ */ import_react26.default.createElement(page_container_default, {
- ...props
- }, /* @__PURE__ */ import_react26.default.createElement(status_default, {
- icon: "error",
- heading: "Failed to Fetch Stats",
- subheading: "Make an issue on Github"
- }));
- case 100:
- return /* @__PURE__ */ import_react26.default.createElement(page_container_default, {
- ...props
- }, /* @__PURE__ */ import_react26.default.createElement(status_default, {
- icon: "library",
- heading: "Analysing your Library",
- subheading: "This may take a while"
- }));
- }
- const statCards = Object.entries(library.audioFeatures).map(([key, value]) => {
- return /* @__PURE__ */ import_react26.default.createElement(stat_card_default, {
+ const Status2 = useStatus_default(status, error);
+ if (Status2)
+ return /* @__PURE__ */ import_react28.default.createElement(page_container_default, {
+ ...props
+ }, Status2);
+ const analysis = data;
+ const statCards = Object.entries(analysis.analysis).map(([key, value]) => {
+ return /* @__PURE__ */ import_react28.default.createElement(stat_card_default, {
label: key,
- value
+ value: parseStat(key)(value)
});
});
- const artistCards = library.artists.slice(0, 10).map((artist) => {
- return /* @__PURE__ */ import_react26.default.createElement(spotify_card_default, {
+ const artistCards = analysis.artists.contents.slice(0, 10).map((artist) => {
+ return /* @__PURE__ */ import_react28.default.createElement(spotify_card_default, {
type: "artist",
+ provider: artist.type,
uri: artist.uri,
header: artist.name,
- subheader: `Appears in ${artist.freq} tracks`,
+ subheader: `Appears in ${artist.frequency} tracks`,
imageUrl: artist.image
});
});
- const albumCards = library.albums.map((album) => {
- return /* @__PURE__ */ import_react26.default.createElement(spotify_card_default, {
- type: "album",
- uri: album.uri,
- header: album.name,
- subheader: `Appears in ${album.freq} tracks`,
- imageUrl: album.image
- });
- });
- return /* @__PURE__ */ import_react26.default.createElement(page_container_default, {
- ...props
- }, /* @__PURE__ */ import_react26.default.createElement("section", {
- className: "stats-libraryOverview"
- }, /* @__PURE__ */ import_react26.default.createElement(stat_card_default, {
- label: "Total Playlists",
- value: library.playlistCount.toString()
- }), /* @__PURE__ */ import_react26.default.createElement(stat_card_default, {
- label: "Total Tracks",
- value: library.trackCount.toString()
- }), /* @__PURE__ */ import_react26.default.createElement(stat_card_default, {
- label: "Total Artists",
- value: library.artistCount.toString()
- }), /* @__PURE__ */ import_react26.default.createElement(stat_card_default, {
- label: "Total Minutes",
- value: Math.floor(library.totalDuration / 60).toString()
- }), /* @__PURE__ */ import_react26.default.createElement(stat_card_default, {
- label: "Total Hours",
- value: (library.totalDuration / (60 * 60)).toFixed(1)
- })), /* @__PURE__ */ import_react26.default.createElement(shelf_default, {
- title: "Most Frequent Genres"
- }, /* @__PURE__ */ import_react26.default.createElement(genres_card_default, {
- genres: library.genres,
- total: library.genresDenominator
- }), /* @__PURE__ */ import_react26.default.createElement(inline_grid_default, {
- special: true
- }, statCards)), /* @__PURE__ */ import_react26.default.createElement(shelf_default, {
- title: "Most Frequent Artists"
- }, /* @__PURE__ */ import_react26.default.createElement(inline_grid_default, null, artistCards)), /* @__PURE__ */ import_react26.default.createElement(shelf_default, {
- title: "Most Frequent Albums"
- }, /* @__PURE__ */ import_react26.default.createElement(inline_grid_default, null, albumCards)), /* @__PURE__ */ import_react26.default.createElement(shelf_default, {
- title: "Release Year Distribution"
- }, /* @__PURE__ */ import_react26.default.createElement(genres_card_default, {
- genres: library.years,
- total: library.yearsDenominator
- })));
- };
- var library_default = import_react26.default.memo(LibraryPage);
-
- // src/pages/charts.tsx
- var import_react27 = __toESM(require_react());
- var DropdownOptions5 = [
- { id: "artists", name: "Top Artists" },
- { id: "tracks", name: "Top Tracks" }
- ];
- var ChartsPage = ({ configWrapper }) => {
- const [chartData, setChartData] = import_react27.default.useState(100);
- const [dropdown, activeOption, setActiveOption] = useDropdownMenu_default(DropdownOptions5, "stats:charts");
- async function fetchChartData(type, force, set = true) {
- if (!force) {
- let storedData = Spicetify.LocalStorage.get(`stats:charts:${type}`);
- if (storedData)
- return setChartData(JSON.parse(storedData));
- }
- const api_key = configWrapper.config["api-key"];
- if (!api_key)
- return setChartData(200);
- const response = await apiRequest("charts", LASTFM.charts(api_key, type));
- if (!response)
- return setChartData(500);
- const data = response[type].track || response[type].artist;
- const cardData = await (type == "artists" ? convertArtistData(data) : convertTrackData(data));
- if (type === "tracks") {
- const likedArray = await checkLiked(cardData.map((track) => track.id));
- if (!likedArray)
- return setChartData(200);
- cardData.forEach((track, index) => {
- track.liked = likedArray[index];
- });
- }
- if (set)
- setChartData(cardData);
- Spicetify.LocalStorage.set(`stats:charts:${type}`, JSON.stringify(cardData));
- }
- import_react27.default.useEffect(() => {
- updatePageCache(4, fetchChartData, activeOption.id, "charts");
- }, []);
- import_react27.default.useEffect(() => {
- fetchChartData(activeOption.id);
- }, [activeOption]);
- const refresh = () => {
- fetchChartData(activeOption.id, true);
- };
- const props = {
- title: "Top Albums",
- headerEls: [dropdown, /* @__PURE__ */ import_react27.default.createElement(refresh_button_default, {
- callback: refresh
- }), /* @__PURE__ */ import_react27.default.createElement(settings_button_default, {
- configWrapper
- })]
- };
- switch (chartData) {
- case 200:
- return /* @__PURE__ */ import_react27.default.createElement(page_container_default, {
- ...props
- }, /* @__PURE__ */ import_react27.default.createElement(status_default, {
- icon: "error",
- heading: "No API Key",
- subheading: "Please enter your Last.fm API key in the settings menu."
- }));
- case 500:
- return /* @__PURE__ */ import_react27.default.createElement(page_container_default, {
- ...props
- }, /* @__PURE__ */ import_react27.default.createElement(status_default, {
- icon: "error",
- heading: "Error",
- subheading: "An error occurred while fetching the data."
- }));
- case 100:
- return /* @__PURE__ */ import_react27.default.createElement(page_container_default, {
- ...props
- }, /* @__PURE__ */ import_react27.default.createElement(status_default, {
- icon: "library",
- heading: "Loading",
- subheading: "Fetching data from Last.fm..."
- }));
- }
- if (!chartData[0]?.album) {
- const artistCards = chartData.map((artist, index) => {
- const type = artist.uri.startsWith("https") ? "lastfm" : "artist";
- return /* @__PURE__ */ import_react27.default.createElement(spotify_card_default, {
- type,
- uri: artist.uri,
- header: artist.name,
- subheader: `#${index + 1} Artist`,
- imageUrl: artist.image
- });
- });
- props.title = `Charts - Top Artists`;
- return /* @__PURE__ */ import_react27.default.createElement(page_container_default, {
- ...props
- }, /* @__PURE__ */ import_react27.default.createElement("div", {
- className: `main-gridContainer-gridContainer grid`
- }, artistCards));
- } else {
- const date = new Date().toLocaleDateString("en-US", {
- year: "numeric",
- month: "2-digit",
- day: "2-digit"
- });
- const infoToCreatePlaylist = {
- playlistName: `Charts - Top Tracks - ${date}`,
- itemsUris: chartData.map((track) => track.uri)
- };
- const trackRows = chartData.map((track, index) => /* @__PURE__ */ import_react27.default.createElement(track_row_default, {
- index: index + 1,
- ...track,
- uris: chartData.map((track2) => track2.uri)
- }));
- props.title = `Charts - Top Tracks`;
- return /* @__PURE__ */ import_react27.default.createElement(page_container_default, {
- ...props,
- infoToCreatePlaylist
- }, /* @__PURE__ */ import_react27.default.createElement(tracklist_default, null, trackRows));
- }
- };
- var charts_default = import_react27.default.memo(ChartsPage);
-
- // src/pages/top_albums.tsx
- var import_react28 = __toESM(require_react());
- var topAlbumsReq = async (time_range, configWrapper) => {
- const { config } = configWrapper;
- if (!config["api-key"] || !config["lastfm-user"])
- return 300;
- const { ["lastfm-user"]: user, ["api-key"]: key } = config;
- const response = await apiRequest("lastfm", LASTFM.topalbums(user, key, time_range));
- if (!response)
- return 200;
- return await convertAlbumData(response.topalbums.album);
- };
- var DropdownOptions6 = [
- { id: "short_term", name: "Past Month" },
- { id: "medium_term", name: "Past 6 Months" },
- { id: "long_term", name: "All Time" }
- ];
- var AlbumsPage = ({ configWrapper }) => {
- const { LocalStorage } = Spicetify;
- const [topAlbums, setTopAlbums] = import_react28.default.useState(100);
- const [dropdown, activeOption] = useDropdownMenu_default(DropdownOptions6, "stats:top-albums");
- const fetchTopAlbums2 = async (time_range, force, set = true) => {
- if (!force) {
- let storedData = LocalStorage.get(`stats:top-albums:${time_range}`);
- if (storedData)
- return setTopAlbums(JSON.parse(storedData));
- }
- const start = window.performance.now();
- const topAlbums2 = await topAlbumsReq(time_range, configWrapper);
- if (set)
- setTopAlbums(topAlbums2);
- LocalStorage.set(`stats:top-albums:${time_range}`, JSON.stringify(topAlbums2));
- console.log("total albums fetch time:", window.performance.now() - start);
- };
- import_react28.default.useEffect(() => {
- updatePageCache(5, fetchTopAlbums2, activeOption.id);
- }, []);
- import_react28.default.useEffect(() => {
- fetchTopAlbums2(activeOption.id);
- }, [activeOption]);
- const refresh = () => {
- fetchTopAlbums2(activeOption.id, true);
- };
- const props = {
- title: "Top Albums",
- headerEls: [dropdown, /* @__PURE__ */ import_react28.default.createElement(refresh_button_default, {
- callback: refresh
- }), /* @__PURE__ */ import_react28.default.createElement(settings_button_default, {
- configWrapper
- })]
- };
- switch (topAlbums) {
- case 300:
- return /* @__PURE__ */ import_react28.default.createElement(page_container_default, {
- ...props
- }, /* @__PURE__ */ import_react28.default.createElement(status_default, {
- icon: "error",
- heading: "No API Key or Username",
- subheading: "Please enter these in the settings menu"
- }));
- case 200:
- return /* @__PURE__ */ import_react28.default.createElement(page_container_default, {
- ...props
- }, /* @__PURE__ */ import_react28.default.createElement(status_default, {
- icon: "error",
- heading: "Failed to Fetch Top Artists",
- subheading: "An error occurred while fetching the data"
- }));
- case 100:
- return /* @__PURE__ */ import_react28.default.createElement(page_container_default, {
- ...props
- }, /* @__PURE__ */ import_react28.default.createElement(status_default, {
- icon: "library",
- heading: "Loading",
- subheading: "Fetching data..."
- }));
- }
- const albumCards = topAlbums.map((album, index) => {
- const type = album.uri.startsWith("https") ? "lastfm" : "album";
+ const albumCards = analysis.albums.contents.slice(0, 10).map((album) => {
return /* @__PURE__ */ import_react28.default.createElement(spotify_card_default, {
- type,
+ type: "album",
+ provider: album.type,
uri: album.uri,
header: album.name,
- subheader: `#${index + 1} Album`,
+ subheader: `Appears in ${album.frequency} tracks`,
imageUrl: album.image
});
});
return /* @__PURE__ */ import_react28.default.createElement(page_container_default, {
...props
- }, /* @__PURE__ */ import_react28.default.createElement("div", {
- className: `main-gridContainer-gridContainer grid`
+ }, /* @__PURE__ */ import_react28.default.createElement("section", {
+ className: "stats-libraryOverview"
+ }, /* @__PURE__ */ import_react28.default.createElement(stat_card_default, {
+ label: "Total Playlists",
+ value: analysis.playlists
+ }), /* @__PURE__ */ import_react28.default.createElement(stat_card_default, {
+ label: "Total Tracks",
+ value: analysis.length
+ }), /* @__PURE__ */ import_react28.default.createElement(stat_card_default, {
+ label: "Total Artists",
+ value: analysis.artists.length
+ }), /* @__PURE__ */ import_react28.default.createElement(stat_card_default, {
+ label: "Total Albums",
+ value: analysis.albums.length
+ }), /* @__PURE__ */ import_react28.default.createElement(stat_card_default, {
+ label: "Total Minutes",
+ value: Math.floor(analysis.duration / 6e4)
+ }), /* @__PURE__ */ import_react28.default.createElement(stat_card_default, {
+ label: "Total Hours",
+ value: (analysis.duration / 36e5).toFixed(1)
+ })), /* @__PURE__ */ import_react28.default.createElement(shelf_default, {
+ title: "Most Frequent Genres"
+ }, /* @__PURE__ */ import_react28.default.createElement(chart_card_default, {
+ data: analysis.genres
+ }), /* @__PURE__ */ import_react28.default.createElement("div", {
+ className: "main-gridContainer-gridContainer grid"
+ }, statCards)), /* @__PURE__ */ import_react28.default.createElement(shelf_default, {
+ title: "Most Frequent Artists"
+ }, /* @__PURE__ */ import_react28.default.createElement(inline_grid_default, null, artistCards)), /* @__PURE__ */ import_react28.default.createElement(shelf_default, {
+ title: "Most Frequent Albums"
+ }, /* @__PURE__ */ import_react28.default.createElement(inline_grid_default, null, albumCards)), /* @__PURE__ */ import_react28.default.createElement(shelf_default, {
+ title: "Release Year Distribution"
+ }, /* @__PURE__ */ import_react28.default.createElement(chart_card_default, {
+ data: analysis.releaseYears
+ })));
+ };
+ var library_default = import_react28.default.memo(LibraryPage);
+
+ // src/pages/top_albums.tsx
+ var import_react29 = __toESM(require_react());
+ var getTopAlbums2 = async (timeRange, config) => {
+ const { "lastfm-user": user, "api-key": key } = config;
+ if (!user || !key)
+ throw new Error("Missing LastFM API Key or Username");
+ const response = await getTopAlbums(key, user, timeRange);
+ return Promise.all(response.map(convertAlbum));
+ };
+ var AlbumsPage = ({ configWrapper }) => {
+ const [dropdown, activeOption] = useDropdownMenu_default(DropdownOptions(configWrapper), "stats:top-albums");
+ const { status, error, data, refetch } = useQuery({
+ queryKey: ["top-albums", activeOption.id],
+ queryFn: cacher(() => getTopAlbums2(activeOption.id, configWrapper.config))
+ });
+ const Status2 = useStatus_default(status, error);
+ const props = {
+ title: "Top Albums",
+ headerEls: [
+ dropdown,
+ /* @__PURE__ */ import_react29.default.createElement(refresh_button_default, {
+ callback: () => invalidator(["top-albums", activeOption.id], refetch)
+ }),
+ /* @__PURE__ */ import_react29.default.createElement(settings_button_default, {
+ configWrapper
+ })
+ ]
+ };
+ if (Status2)
+ return /* @__PURE__ */ import_react29.default.createElement(page_container_default, {
+ ...props
+ }, Status2);
+ const topAlbums = data;
+ const albumCards = topAlbums.map((album, index) => {
+ return /* @__PURE__ */ import_react29.default.createElement(spotify_card_default, {
+ type: "album",
+ provider: album.type,
+ uri: album.uri,
+ header: album.name,
+ subheader: album.playcount ? `\u29BE ${album.playcount} Scrobbles` : "Album",
+ imageUrl: album.image,
+ badge: `${index + 1}`
+ });
+ });
+ return /* @__PURE__ */ import_react29.default.createElement(page_container_default, {
+ ...props
+ }, /* @__PURE__ */ import_react29.default.createElement("div", {
+ className: "main-gridContainer-gridContainer grid"
}, albumCards));
};
- var top_albums_default = import_react28.default.memo(AlbumsPage);
+ var top_albums_default = import_react29.default.memo(AlbumsPage);
// package.json
var version = "0.3.3";
@@ -2419,7 +7459,9 @@ var stats = (() => {
);
};
var App = () => {
- const [config, setConfig] = import_react29.default.useState({ ...SpicetifyStats.ConfigWrapper.Config });
+ const [config, setConfig] = import_react30.default.useState({
+ ...SpicetifyStats.ConfigWrapper.Config
+ });
const launchModal = () => {
SpicetifyStats.ConfigWrapper.launchModal(setConfig);
};
@@ -2428,22 +7470,22 @@ var stats = (() => {
launchModal
};
const pages = {
- ["Artists"]: /* @__PURE__ */ import_react29.default.createElement(top_artists_default, {
+ ["Artists"]: /* @__PURE__ */ import_react30.default.createElement(top_artists_default, {
configWrapper
}),
- ["Tracks"]: /* @__PURE__ */ import_react29.default.createElement(top_tracks_default, {
+ ["Tracks"]: /* @__PURE__ */ import_react30.default.createElement(top_tracks_default, {
configWrapper
}),
- ["Albums"]: /* @__PURE__ */ import_react29.default.createElement(top_albums_default, {
+ ["Albums"]: /* @__PURE__ */ import_react30.default.createElement(top_albums_default, {
configWrapper
}),
- ["Genres"]: /* @__PURE__ */ import_react29.default.createElement(top_genres_default, {
+ ["Genres"]: /* @__PURE__ */ import_react30.default.createElement(top_genres_default, {
configWrapper
}),
- ["Library"]: /* @__PURE__ */ import_react29.default.createElement(library_default, {
+ ["Library"]: /* @__PURE__ */ import_react30.default.createElement(library_default, {
configWrapper
}),
- ["Charts"]: /* @__PURE__ */ import_react29.default.createElement(charts_default, {
+ ["Charts"]: /* @__PURE__ */ import_react30.default.createElement(charts_default, {
configWrapper
})
};
@@ -2451,34 +7493,42 @@ var stats = (() => {
(page) => configWrapper.config[`show-${page.toLowerCase()}`]
);
const [navBar, activeLink, setActiveLink] = useNavigationBar_default(tabPages);
- const [hasPageSwitched, setHasPageSwitched] = import_react29.default.useState(false);
- const [newUpdate, setNewUpdate] = import_react29.default.useState(false);
- import_react29.default.useEffect(() => {
+ const [hasPageSwitched, setHasPageSwitched] = import_react30.default.useState(false);
+ const [newUpdate, setNewUpdate] = import_react30.default.useState(false);
+ import_react30.default.useEffect(() => {
setActiveLink(Spicetify.LocalStorage.get("stats:active-link") || "Artists");
checkForUpdates(setNewUpdate);
setHasPageSwitched(true);
}, []);
- import_react29.default.useEffect(() => {
+ import_react30.default.useEffect(() => {
Spicetify.LocalStorage.set("stats:active-link", activeLink);
}, [activeLink]);
if (!hasPageSwitched) {
- return /* @__PURE__ */ import_react29.default.createElement(import_react29.default.Fragment, null);
+ return /* @__PURE__ */ import_react30.default.createElement(import_react30.default.Fragment, null);
}
- return /* @__PURE__ */ import_react29.default.createElement("div", {
+ return /* @__PURE__ */ import_react30.default.createElement("div", {
id: "stats-app"
- }, navBar, newUpdate && /* @__PURE__ */ import_react29.default.createElement("div", {
+ }, navBar, newUpdate && /* @__PURE__ */ import_react30.default.createElement("div", {
className: "new-update"
- }, "New app update available! Visit", " ", /* @__PURE__ */ import_react29.default.createElement("a", {
+ }, "New app update available! Visit", " ", /* @__PURE__ */ import_react30.default.createElement("a", {
href: "https://github.com/harbassan/spicetify-apps/releases"
}, "harbassan/spicetify-apps"), " to install."), pages[activeLink]);
};
var app_default = App;
// ../../../AppData/Local/Temp/spicetify-creator/index.jsx
- var import_react30 = __toESM(require_react());
+ var import_react31 = __toESM(require_react());
function render() {
- return /* @__PURE__ */ import_react30.default.createElement(app_default, null);
+ return /* @__PURE__ */ import_react31.default.createElement(app_default, null);
}
return __toCommonJS(spicetify_creator_exports);
})();
+/**
+ * @license
+ * Lodash
+ * Copyright OpenJS Foundation and other contributors
+ * Released under MIT license
+ * Based on Underscore.js 1.8.3
+ * Copyright Jeremy Ashkenas, DocumentCloud and Investigative Reporters & Editors
+ */
const render=()=>stats.default();
diff --git a/.config/spicetify/CustomApps/stats/manifest.json b/.config/spicetify/CustomApps/stats/manifest.json
index 2a652239..08e506cf 100644
--- a/.config/spicetify/CustomApps/stats/manifest.json
+++ b/.config/spicetify/CustomApps/stats/manifest.json
@@ -4,6 +4,7 @@
"active-icon": "\r\n",
"subfiles": [],
"subfiles_extension": [
+ "cache.js",
"extension.js"
]
}
\ No newline at end of file
diff --git a/.config/spicetify/CustomApps/stats/style.css b/.config/spicetify/CustomApps/stats/style.css
index ba798f30..3c7cbddf 100644
--- a/.config/spicetify/CustomApps/stats/style.css
+++ b/.config/spicetify/CustomApps/stats/style.css
@@ -1,4 +1,4 @@
-/* ../../../AppData/Local/Temp/tmp-17120-n3iWRzissBjg/18f3cbbb4bc3/navBar.module.css */
+/* ../../../AppData/Local/Temp/tmp-8216-VCWpAfv0Bkqy/1909217e9563/navBar.module.css */
.navBar-module__topBarHeaderItem___piw4C_stats {
-webkit-app-region: no-drag;
display: inline-block;
@@ -46,7 +46,7 @@ div.navBar-module__topBarHeaderItemLink___xA4uv_stats {
padding: 0;
}
-/* ../../../AppData/Local/Temp/tmp-17120-n3iWRzissBjg/18f3cbbb33e0/app.css */
+/* ../../../AppData/Local/Temp/tmp-8216-VCWpAfv0Bkqy/1909217e7ff0/app.css */
#stats-app .stats-gridInline {
--grid-gap: 24px;
grid-template-columns: repeat(10, 180px) !important;
@@ -54,6 +54,9 @@ div.navBar-module__topBarHeaderItemLink___xA4uv_stats {
scroll-behavior: smooth;
margin-top: 5px;
}
+#stats-app .grid:nth-child(2) {
+ margin-top: 24px;
+}
#stats-app [data-scroll=both] {
-webkit-mask-image: linear-gradient(to right, transparent, black 10%, black 90%, transparent);
mask-image: linear-gradient(to right, transparent, black 10%, black 90%, transparent);
@@ -125,6 +128,9 @@ div.navBar-module__topBarHeaderItemLink___xA4uv_stats {
font-size: 0.875rem;
margin-left: 7px;
font-weight: bold;
+ white-space: nowrap;
+ overflow: hidden;
+ text-overflow: ellipsis;
}
#stats-app .stats-genreValue {
color: var(--spice-text);
@@ -138,6 +144,35 @@ div.navBar-module__topBarHeaderItemLink___xA4uv_stats {
background-color: transparent;
border: none;
}
+#stats-app .main-trackList-rowPlayPauseIcon {
+ fill: currentColor;
+}
+#stats-app .badge {
+ position: absolute;
+ top: 3%;
+ left: 3%;
+ height: 30px;
+ width: 30px;
+ border-radius: 50%;
+ background-color: rgb(65, 110, 170);
+ color: white;
+ display: flex;
+ align-items: center;
+ justify-content: center;
+ font-size: 12px;
+}
+#stats-app .extend-button {
+ background-color: transparent;
+ border: none;
+ position: absolute;
+ right: 20px;
+ bottom: 20px;
+ font-size: 14px;
+ color: var(--spice-subtext);
+}
+#stats-app .extend-button:hover {
+ color: var(--spice-text);
+}
.GenericModal[aria-label="Playlist Stats"] .main-embedWidgetGenerator-container {
width: 80vw;
height: 80vh;
@@ -147,7 +182,7 @@ div.navBar-module__topBarHeaderItemLink___xA4uv_stats {
color: var(--spice-text);
}
-/* ../../../AppData/Local/Temp/tmp-17120-n3iWRzissBjg/18f3cbbb48b1/config_modal.css */
+/* ../../../AppData/Local/Temp/tmp-8216-VCWpAfv0Bkqy/1909217e92e1/config_modal.css */
.config-container {
gap: 10px;
display: flex;
@@ -224,7 +259,7 @@ div.navBar-module__topBarHeaderItemLink___xA4uv_stats {
width: 200px;
}
-/* ../../../AppData/Local/Temp/tmp-17120-n3iWRzissBjg/18f3cbbb49f2/shared.css */
+/* ../../../AppData/Local/Temp/tmp-8216-VCWpAfv0Bkqy/1909217e93c2/shared.css */
.grid {
--grid-gap: 24px;
grid-template-columns: repeat(auto-fill, minmax(180px, 1fr)) !important;