text: (function (global, factory) {
    typeof exports === 'object' && typeof module !== 'undefined' ? factory(exports) :
    typeof define === 'function' && define.amd ? define(['exports'], factory) :
    (factory((global[''] = global[''] || {}, global['']['/_30s'] = {})));
  }(this, (function (exports) { 'use strict';
  
    const fs = typeof require !== "undefined" && require('fs');
    const crypto = typeof require !== "undefined" && require('crypto');
  
    const all = (arr, fn = Boolean) => arr.every(fn);
    const allEqual = arr => arr.every(val => val === arr[0]);
    const any = (arr, fn = Boolean) => arr.some(fn);
    const approximatelyEqual = (v1, v2, epsilon = 0.001) => Math.abs(v1 - v2) < epsilon;
    const arrayToCSV = (arr, delimiter = ',') =>
      arr
        .map(v => v.map(x => (isNaN(x) ? `"${x.replace(/"/g, '""')}"` : x)).join(delimiter))
        .join('\n');
    const arrayToHtmlList = (arr, listID) =>
      (el => (
        (el = document.querySelector('#' + listID)),
        (el.innerHTML += arr.map(item => `<li>${item}</li>`).join(''))
      ))();
    const ary = (fn, n) => (...args) => fn(...args.slice(0, n));
    const atob = str => Buffer.from(str, 'base64').toString('binary');
    const attempt = (fn, ...args) => {
      try {
        return fn(...args);
      } catch (e) {
        return e instanceof Error ? e : new Error(e);
      }
    };
    const average = (...nums) => nums.reduce((acc, val) => acc + val, 0) / nums.length;
    const averageBy = (arr, fn) =>
      arr.map(typeof fn === 'function' ? fn : val => val[fn]).reduce((acc, val) => acc + val, 0) /
      arr.length;
    const bifurcate = (arr, filter) =>
      arr.reduce((acc, val, i) => (acc[filter[i] ? 0 : 1].push(val), acc), [[], []]);
    const bifurcateBy = (arr, fn) =>
      arr.reduce((acc, val, i) => (acc[fn(val, i) ? 0 : 1].push(val), acc), [[], []]);
    const bind = (fn, context, ...boundArgs) => (...args) => fn.apply(context, [...boundArgs, ...args]);
    const bindAll = (obj, ...fns) =>
      fns.forEach(
        fn => (
          (f = obj[fn]),
          (obj[fn] = function() {
            return f.apply(obj);
          })
        )
      );
    const bindKey = (context, fn, ...boundArgs) => (...args) =>
      context[fn].apply(context, [...boundArgs, ...args]);
    const binomialCoefficient = (n, k) => {
      if (Number.isNaN(n) || Number.isNaN(k)) return NaN;
      if (k < 0 || k > n) return 0;
      if (k === 0 || k === n) return 1;
      if (k === 1 || k === n - 1) return n;
      if (n - k < k) k = n - k;
      let res = n;
      for (let j = 2; j <= k; j++) res *= (n - j + 1) / j;
      return Math.round(res);
    };
    const bottomVisible = () =>
      document.documentElement.clientHeight + window.scrollY >=
      (document.documentElement.scrollHeight || document.documentElement.clientHeight);
    const btoa = str => Buffer.from(str, 'binary').toString('base64');
    const byteSize = str => new Blob([str]).size;
    const call = (key, ...args) => context => context[key](...args);
    const capitalize = ([first, ...rest], lowerRest = false) =>
      first.toUpperCase() + (lowerRest ? rest.join('').toLowerCase() : rest.join(''));
    const capitalizeEveryWord = str => str.replace(/\b[a-z]/g, char => char.toUpperCase());
    const castArray = val => (Array.isArray(val) ? val : [val]);
    const chainAsync = fns => {
      let curr = 0;
      const last = fns[fns.length - 1];
      const next = () => {
        const fn = fns[curr++];
        fn === last ? fn() : fn(next);
      };
      next();
    };
    const checkProp = (predicate, prop) => obj => !!predicate(obj[prop]);
    const chunk = (arr, size) =>
      Array.from({ length: Math.ceil(arr.length / size) }, (v, i) =>
        arr.slice(i * size, i * size + size)
      );
    const clampNumber = (num, a, b) => Math.max(Math.min(num, Math.max(a, b)), Math.min(a, b));
    const cloneRegExp = regExp => new RegExp(regExp.source, regExp.flags);
    const coalesce = (...args) => args.find(_ => ![undefined, null].includes(_));
    const coalesceFactory = valid => (...args) => args.find(valid);
    const collectInto = fn => (...args) => fn(args);
    const colorize = (...args) => ({
      black: `\x1b[30m${args.join(' ')}`,
      red: `\x1b[31m${args.join(' ')}`,
      green: `\x1b[32m${args.join(' ')}`,
      yellow: `\x1b[33m${args.join(' ')}`,
      blue: `\x1b[34m${args.join(' ')}`,
      magenta: `\x1b[35m${args.join(' ')}`,
      cyan: `\x1b[36m${args.join(' ')}`,
      white: `\x1b[37m${args.join(' ')}`,
      bgBlack: `\x1b[40m${args.join(' ')}\x1b[0m`,
      bgRed: `\x1b[41m${args.join(' ')}\x1b[0m`,
      bgGreen: `\x1b[42m${args.join(' ')}\x1b[0m`,
      bgYellow: `\x1b[43m${args.join(' ')}\x1b[0m`,
      bgBlue: `\x1b[44m${args.join(' ')}\x1b[0m`,
      bgMagenta: `\x1b[45m${args.join(' ')}\x1b[0m`,
      bgCyan: `\x1b[46m${args.join(' ')}\x1b[0m`,
      bgWhite: `\x1b[47m${args.join(' ')}\x1b[0m`
    });
    const compact = arr => arr.filter(Boolean);
    const compactWhitespace = str => str.replace(/\s{2,}/g, ' ');
    const compose = (...fns) => fns.reduce((f, g) => (...args) => f(g(...args)));
    const composeRight = (...fns) => fns.reduce((f, g) => (...args) => g(f(...args)));
    const converge = (converger, fns) => (...args) => converger(...fns.map(fn => fn.apply(null, args)));
    const copyToClipboard = str => {
      const el = document.createElement('textarea');
      el.value = str;
      el.setAttribute('readonly', '');
      el.style.position = 'absolute';
      el.style.left = '-9999px';
      document.body.appendChild(el);
      const selected =
        document.getSelection().rangeCount > 0 ? document.getSelection().getRangeAt(0) : false;
      el.select();
      document.execCommand('copy');
      document.body.removeChild(el);
      if (selected) {
        document.getSelection().removeAllRanges();
        document.getSelection().addRange(selected);
      }
    };
    const countBy = (arr, fn) =>
      arr.map(typeof fn === 'function' ? fn : val => val[fn]).reduce((acc, val) => {
        acc[val] = (acc[val] || 0) + 1;
        return acc;
      }, {});
    const counter = (selector, start, end, step = 1, duration = 2000) => {
      let current = start,
        _step = (end - start) * step < 0 ? -step : step,
        timer = setInterval(() => {
          current += _step;
          document.querySelector(selector).innerHTML = current;
          if (current >= end) document.querySelector(selector).innerHTML = end;
          if (current >= end) clearInterval(timer);
        }, Math.abs(Math.floor(duration / (end - start))));
      return timer;
    };
    const countOccurrences = (arr, val) => arr.reduce((a, v) => (v === val ? a + 1 : a), 0);
    const createDirIfNotExists = dir => (!fs.existsSync(dir) ? fs.mkdirSync(dir) : undefined);
    const createElement = str => {
      const el = document.createElement('div');
      el.innerHTML = str;
      return el.firstElementChild;
    };
    const createEventHub = () => ({
      hub: Object.create(null),
      emit(event, data) {
        (this.hub[event] || []).forEach(handler => handler(data));
      },
      on(event, handler) {
        if (!this.hub[event]) this.hub[event] = [];
        this.hub[event].push(handler);
      },
      off(event, handler) {
        const i = (this.hub[event] || []).findIndex(h => h === handler);
        if (i > -1) this.hub[event].splice(i, 1);
        if (this.hub[event].length === 0) delete this.hub[event];
      }
    });
    const CSVToArray = (data, delimiter = ',', omitFirstRow = false) =>
      data
        .slice(omitFirstRow ? data.indexOf('\n') + 1 : 0)
        .split('\n')
        .map(v => v.split(delimiter));
    const CSVToJSON = (data, delimiter = ',') => {
      const titles = data.slice(0, data.indexOf('\n')).split(delimiter);
      return data
        .slice(data.indexOf('\n') + 1)
        .split('\n')
        .map(v => {
          const values = v.split(delimiter);
          return titles.reduce((obj, title, index) => ((obj[title] = values[index]), obj), {});
        });
    };
    const currentURL = () => window.location.href;
    const curry = (fn, arity = fn.length, ...args) =>
      arity <= args.length ? fn(...args) : curry.bind(null, fn, arity, ...args);
    const dayOfYear = date =>
      Math.floor((date - new Date(date.getFullYear(), 0, 0)) / 1000 / 60 / 60 / 24);
    const debounce = (fn, ms = 0) => {
      let timeoutId;
      return function(...args) {
        clearTimeout(timeoutId);
        timeoutId = setTimeout(() => fn.apply(this, args), ms);
      };
    };
    const decapitalize = ([first, ...rest], upperRest = false) =>
      first.toLowerCase() + (upperRest ? rest.join('').toUpperCase() : rest.join(''));
    const deepClone = obj => {
      if (obj === null) return null;
      let clone = Object.assign({}, obj);
      Object.keys(clone).forEach(
        key => (clone[key] = typeof obj[key] === 'object' ? deepClone(obj[key]) : obj[key])
      );
      return Array.isArray(obj) && obj.length
        ? (clone.length = obj.length) && Array.from(clone)
        : Array.isArray(obj)
          ? Array.from(obj)
          : clone;
    };
    const deepFlatten = arr => [].concat(...arr.map(v => (Array.isArray(v) ? deepFlatten(v) : v)));
    const deepFreeze = obj =>
      Object.keys(obj).forEach(prop =>
        !(obj[prop] instanceof Object) || Object.isFrozen(obj[prop]) ? null : deepFreeze(obj[prop])
      ) || Object.freeze(obj);
    const deepGet = (obj, keys) => keys.reduce((xs, x) => (xs && xs[x] ? xs[x] : null), obj);
    const deepMapKeys = (obj, f) =>
      Array.isArray(obj)
        ? obj.map(val => deepMapKeys(val, f))
        : typeof obj === 'object'
          ? Object.keys(obj).reduce((acc, current) => {
            const val = obj[current];
            acc[f(current)] =
              val !== null && typeof val === 'object' ? deepMapKeys(val, f) : (acc[f(current)] = val);
            return acc;
          }, {})
          : obj;
    const defaults = (obj, ...defs) => Object.assign({}, obj, ...defs.reverse(), obj);
    const defer = (fn, ...args) => setTimeout(fn, 1, ...args);
    const degreesToRads = deg => (deg * Math.PI) / 180.0;
    const delay = (fn, wait, ...args) => setTimeout(fn, wait, ...args);
    const detectDeviceType = () =>
      /Android|webOS|iPhone|iPad|iPod|BlackBerry|IEMobile|Opera Mini/i.test(navigator.userAgent)
        ? 'Mobile'
        : 'Desktop';
    const difference = (a, b) => {
      const s = new Set(b);
      return a.filter(x => !s.has(x));
    };
    const differenceBy = (a, b, fn) => {
      const s = new Set(b.map(fn));
      return a.map(fn).filter(el => !s.has(el));
    };
    const differenceWith = (arr, val, comp) => arr.filter(a => val.findIndex(b => comp(a, b)) === -1);
    const dig = (obj, target) =>
      target in obj
        ? obj[target]
        : Object.values(obj).reduce((acc, val) => {
          if (acc !== undefined) return acc;
          if (typeof val === 'object') return dig(val, target);
        }, undefined);
    const digitize = n => [...`${n}`].map(i => parseInt(i));
    const distance = (x0, y0, x1, y1) => Math.hypot(x1 - x0, y1 - y0);
    const drop = (arr, n = 1) => arr.slice(n);
    const dropRight = (arr, n = 1) => arr.slice(0, -n);
    const dropRightWhile = (arr, func) => {
      let rightIndex = arr.length;
      while (rightIndex-- && !func(arr[rightIndex]));
      return arr.slice(0, rightIndex + 1);
    };
    const dropWhile = (arr, func) => {
      while (arr.length > 0 && !func(arr[0])) arr = arr.slice(1);
      return arr;
    };
    const elementContains = (parent, child) => parent !== child && parent.contains(child);
    const elementIsVisibleInViewport = (el, partiallyVisible = false) => {
      const { top, left, bottom, right } = el.getBoundingClientRect();
      const { innerHeight, innerWidth } = window;
      return partiallyVisible
        ? ((top > 0 && top < innerHeight) || (bottom > 0 && bottom < innerHeight)) &&
            ((left > 0 && left < innerWidth) || (right > 0 && right < innerWidth))
        : top >= 0 && left >= 0 && bottom <= innerHeight && right <= innerWidth;
    };
    const elo = ([...ratings], kFactor = 32, selfRating) => {
      const [a, b] = ratings;
      const expectedScore = (self, opponent) => 1 / (1 + 10 ** ((opponent - self) / 400));
      const newRating = (rating, i) =>
        (selfRating || rating) + kFactor * (i - expectedScore(i ? a : b, i ? b : a));
      if (ratings.length === 2) return [newRating(a, 1), newRating(b, 0)];
  
      for (let i = 0, len = ratings.length; i < len; i++) {
        let j = i;
        while (j < len - 1) {
          j++;
          [ratings[i], ratings[j]] = elo([ratings[i], ratings[j]], kFactor);
        }
      }
      return ratings;
    };
    const equals = (a, b) => {
      if (a === b) return true;
      if (a instanceof Date && b instanceof Date) return a.getTime() === b.getTime();
      if (!a || !b || (typeof a !== 'object' && typeof b !== 'object')) return a === b;
      if (a.prototype !== b.prototype) return false;
      let keys = Object.keys(a);
      if (keys.length !== Object.keys(b).length) return false;
      return keys.every(k => equals(a[k], b[k]));
    };
    const escapeHTML = str =>
      str.replace(
        /[&<>'"]/g,
        tag =>
          ({
            '&': '&amp;',
            '<': '&lt;',
            '>': '&gt;',
            "'": '&#39;',
            '"': '&quot;'
          }[tag] || tag)
      );
    const escapeRegExp = str => str.replace(/[.*+?^${}()|[\]\\]/g, '\\$&');
    const everyNth = (arr, nth) => arr.filter((e, i) => i % nth === nth - 1);
    const extendHex = shortHex =>
      '#' +
      shortHex
        .slice(shortHex.startsWith('#') ? 1 : 0)
        .split('')
        .map(x => x + x)
        .join('');
    const factorial = n =>
      n < 0
        ? (() => {
          throw new TypeError('Negative numbers are not allowed!');
        })()
        : n <= 1
          ? 1
          : n * factorial(n - 1);
    const fibonacci = n =>
      Array.from({ length: n }).reduce(
        (acc, val, i) => acc.concat(i > 1 ? acc[i - 1] + acc[i - 2] : i),
        []
      );
    const filterFalsy = arr => arr.filter(Boolean);
    const filterNonUnique = arr => arr.filter(i => arr.indexOf(i) === arr.lastIndexOf(i));
    const filterNonUniqueBy = (arr, fn) =>
      arr.filter((v, i) => arr.every((x, j) => (i === j) === fn(v, x, i, j)));
    const findKey = (obj, fn) => Object.keys(obj).find(key => fn(obj[key], key, obj));
    const findLast = (arr, fn) => arr.filter(fn).pop();
    const findLastIndex = (arr, fn) =>
      (arr
        .map((val, i) => [i, val])
        .filter(([i, val]) => fn(val, i, arr))
        .pop() || [-1])[0];
    const findLastKey = (obj, fn) =>
      Object.keys(obj)
        .reverse()
        .find(key => fn(obj[key], key, obj));
    const flatten = (arr, depth = 1) =>
      arr.reduce((a, v) => a.concat(depth > 1 && Array.isArray(v) ? flatten(v, depth - 1) : v), []);
    const flattenObject = (obj, prefix = '') =>
      Object.keys(obj).reduce((acc, k) => {
        const pre = prefix.length ? prefix + '.' : '';
        if (typeof obj[k] === 'object') Object.assign(acc, flattenObject(obj[k], pre + k));
        else acc[pre + k] = obj[k];
        return acc;
      }, {});
    const flip = fn => (first, ...rest) => fn(...rest, first);
    const forEachRight = (arr, callback) =>
      arr
        .slice(0)
        .reverse()
        .forEach(callback);
    const formatDuration = ms => {
      if (ms < 0) ms = -ms;
      const time = {
        day: Math.floor(ms / 86400000),
        hour: Math.floor(ms / 3600000) % 24,
        minute: Math.floor(ms / 60000) % 60,
        second: Math.floor(ms / 1000) % 60,
        millisecond: Math.floor(ms) % 1000
      };
      return Object.entries(time)
        .filter(val => val[1] !== 0)
        .map(([key, val]) => `${val} ${key}${val !== 1 ? 's' : ''}`)
        .join(', ');
    };
    const formToObject = form =>
      Array.from(new FormData(form)).reduce(
        (acc, [key, value]) => ({
          ...acc,
          [key]: value
        }),
        {}
      );
    const forOwn = (obj, fn) => Object.keys(obj).forEach(key => fn(obj[key], key, obj));
    const forOwnRight = (obj, fn) =>
      Object.keys(obj)
        .reverse()
        .forEach(key => fn(obj[key], key, obj));
    const frequencies = arr =>
      arr.reduce((a, v) => {
        a[v] = a[v] ? a[v] + 1 : 1;
        return a;
      }, {});
    const fromCamelCase = (str, separator = '_') =>
      str
        .replace(/([a-z\d])([A-Z])/g, '$1' + separator + '$2')
        .replace(/([A-Z]+)([A-Z][a-z\d]+)/g, '$1' + separator + '$2')
        .toLowerCase();
    const functionName = fn => (console.debug(fn.name), fn);
    const functions = (obj, inherited = false) =>
      (inherited
        ? [...Object.keys(obj), ...Object.keys(Object.getPrototypeOf(obj))]
        : Object.keys(obj)
      ).filter(key => typeof obj[key] === 'function');
    const gcd = (...arr) => {
      const _gcd = (x, y) => (!y ? x : gcd(y, x % y));
      return [...arr].reduce((a, b) => _gcd(a, b));
    };
    const geometricProgression = (end, start = 1, step = 2) =>
      Array.from({ length: Math.floor(Math.log(end / start) / Math.log(step)) + 1 }).map(
        (v, i) => start * step ** i
      );
    const get = (from, ...selectors) =>
      [...selectors].map(s =>
        s
          .replace(/\[([^\[\]]*)\]/g, '.$1.')
          .split('.')
          .filter(t => t !== '')
          .reduce((prev, cur) => prev && prev[cur], from)
      );
    const getColonTimeFromDate = date => date.toTimeString().slice(0, 8);
    const getDaysDiffBetweenDates = (dateInitial, dateFinal) =>
      (dateFinal - dateInitial) / (1000 * 3600 * 24);
    const getImages = (el, includeDuplicates = false) => {
      const images = [...el.getElementsByTagName('img')].map(img => img.getAttribute('src'));
      return includeDuplicates ? images : [...new Set(images)];
    };
    const getMeridiemSuffixOfInteger = num =>
      num === 0 || num === 24
        ? 12 + 'am'
        : num === 12
          ? 12 + 'pm'
          : num < 12
            ? (num % 12) + 'am'
            : (num % 12) + 'pm';
    const getScrollPosition = (el = window) => ({
      x: el.pageXOffset !== undefined ? el.pageXOffset : el.scrollLeft,
      y: el.pageYOffset !== undefined ? el.pageYOffset : el.scrollTop
    });
    const getStyle = (el, ruleName) => getComputedStyle(el)[ruleName];
    const getType = v =>
      v === undefined ? 'undefined' : v === null ? 'null' : v.constructor.name.toLowerCase();
    const getURLParameters = url =>
      (url.match(/([^?=&]+)(=([^&]*))/g) || []).reduce(
        (a, v) => ((a[v.slice(0, v.indexOf('='))] = v.slice(v.indexOf('=') + 1)), a),
        {}
      );
    const groupBy = (arr, fn) =>
      arr.map(typeof fn === 'function' ? fn : val => val[fn]).reduce((acc, val, i) => {
        acc[val] = (acc[val] || []).concat(arr[i]);
        return acc;
      }, {});
    const hammingDistance = (num1, num2) => ((num1 ^ num2).toString(2).match(/1/g) || '').length;
    const hasClass = (el, className) => el.classList.contains(className);
    const hasFlags = (...flags) =>
      flags.every(flag => process.argv.includes(/^-{1,2}/.test(flag) ? flag : '--' + flag));
    const hashBrowser = val =>
      crypto.subtle.digest('SHA-256', new TextEncoder('utf-8').encode(val)).then(h => {
        let hexes = [],
          view = new DataView(h);
        for (let i = 0; i < view.byteLength; i += 4)
          hexes.push(('00000000' + view.getUint32(i).toString(16)).slice(-8));
        return hexes.join('');
      });
    const hashNode = val =>
      new Promise(resolve =>
        setTimeout(
          () =>
            resolve(
              crypto
                .createHash('sha256')
                .update(val)
                .digest('hex')
            ),
          0
        )
      );
    const hasKey = (obj, keys) => {
      return (
        keys.length > 0 &&
        keys.every(key => {
          if (typeof obj !== 'object' || !obj.hasOwnProperty(key)) return false;
          obj = obj[key];
          return true;
        })
      );
    };
    const head = arr => (arr && arr.length ? arr[0] : undefined);
    const hexToRGB = hex => {
      let alpha = false,
        h = hex.slice(hex.startsWith('#') ? 1 : 0);
      if (h.length === 3) h = [...h].map(x => x + x).join('');
      else if (h.length === 8) alpha = true;
      h = parseInt(h, 16);
      return (
        'rgb' +
        (alpha ? 'a' : '') +
        '(' +
        (h >>> (alpha ? 24 : 16)) +
        ', ' +
        ((h & (alpha ? 0x00ff0000 : 0x00ff00)) >>> (alpha ? 16 : 8)) +
        ', ' +
        ((h & (alpha ? 0x0000ff00 : 0x0000ff)) >>> (alpha ? 8 : 0)) +
        (alpha ? `, ${h & 0x000000ff}` : '') +
        ')'
      );
    };
    const hide = (...el) => [...el].forEach(e => (e.style.display = 'none'));
    const httpGet = (url, callback, err = console.error) => {
      const request = new XMLHttpRequest();
      request.open('GET', url, true);
      request.onload = () => callback(request.responseText);
      request.onerror = () => err(request);
      request.send();
    };
    const httpPost = (url, data, callback, err = console.error) => {
      const request = new XMLHttpRequest();
      request.open('POST', url, true);
      request.setRequestHeader('Content-type', 'application/json; charset=utf-8');
      request.onload = () => callback(request.responseText);
      request.onerror = () => err(request);
      request.send(data);
    };
    const httpsRedirect = () => {
      if (location.protocol !== 'https:') location.replace('https://' + location.href.split('//')[1]);
    };
    const hz = (fn, iterations = 100) => {
      const before = performance.now();
      for (let i = 0; i < iterations; i++) fn();
      return (1000 * iterations) / (performance.now() - before);
    };
    const includesAll = (arr, values) => values.every(v => arr.includes(v));
    const includesAny = (arr, values) => values.some(v => arr.includes(v));
    const indentString = (str, count, indent = ' ') => str.replace(/^/gm, indent.repeat(count));
    const indexOfAll = (arr, val) => arr.reduce((acc, el, i) => (el === val ? [...acc, i] : acc), []);
    const initial = arr => arr.slice(0, -1);
    const initialize2DArray = (w, h, val = null) =>
      Array.from({ length: h }).map(() => Array.from({ length: w }).fill(val));
    const initializeArrayWithRange = (end, start = 0, step = 1) =>
      Array.from({ length: Math.ceil((end - start + 1) / step) }, (v, i) => i * step + start);
    const initializeArrayWithRangeRight = (end, start = 0, step = 1) =>
      Array.from({ length: Math.ceil((end + 1 - start) / step) }).map(
        (v, i, arr) => (arr.length - i - 1) * step + start
      );
    const initializeArrayWithValues = (n, val = 0) => Array(n).fill(val);
    const initializeNDArray = (val, ...args) =>
      args.length === 0
        ? val
        : Array.from({ length: args[0] }).map(() => initializeNDArray(val, ...args.slice(1)));
    const inRange = (n, start, end = null) => {
      if (end && start > end) [end, start] = [start, end];
      return end == null ? n >= 0 && n < start : n >= start && n < end;
    };
    const insertAfter = (el, htmlString) => el.insertAdjacentHTML('afterend', htmlString);
    const insertBefore = (el, htmlString) => el.insertAdjacentHTML('beforebegin', htmlString);
    const intersection = (a, b) => {
      const s = new Set(b);
      return a.filter(x => s.has(x));
    };
    const intersectionBy = (a, b, fn) => {
      const s = new Set(b.map(fn));
      return a.filter(x => s.has(fn(x)));
    };
    const intersectionWith = (a, b, comp) => a.filter(x => b.findIndex(y => comp(x, y)) !== -1);
    const invertKeyValues = (obj, fn) =>
      Object.keys(obj).reduce((acc, key) => {
        const val = fn ? fn(obj[key]) : obj[key];
        acc[val] = acc[val] || [];
        acc[val].push(key);
        return acc;
      }, {});
    const is = (type, val) => ![, null].includes(val) && val.constructor === type;
    const isAbsoluteURL = str => /^[a-z][a-z0-9+.-]*:/.test(str);
    const isAfterDate = (dateA, dateB) => dateA > dateB;
    const isAnagram = (str1, str2) => {
      const normalize = str =>
        str
          .toLowerCase()
          .replace(/[^a-z0-9]/gi, '')
          .split('')
          .sort()
          .join('');
      return normalize(str1) === normalize(str2);
    };
    const isArrayLike = obj => obj != null && typeof obj[Symbol.iterator] === 'function';
    const isBeforeDate = (dateA, dateB) => dateA < dateB;
    const isBoolean = val => typeof val === 'boolean';
    const isBrowser = () => ![typeof window, typeof document].includes('undefined');
    const isBrowserTabFocused = () => !document.hidden;
    const isDivisible = (dividend, divisor) => dividend % divisor === 0;
    const isDuplexStream = val =>
      val !== null &&
      typeof val === 'object' &&
      typeof val.pipe === 'function' &&
      typeof val._read === 'function' &&
      typeof val._readableState === 'object' &&
      typeof val._write === 'function' &&
      typeof val._writableState === 'object';
    const isEmpty = val => val == null || !(Object.keys(val) || val).length;
    const isEven = num => num % 2 === 0;
    const isFunction = val => typeof val === 'function';
    const isLowerCase = str => str === str.toLowerCase();
    const isNegativeZero = val => val === 0 && 1 / val === -Infinity;
    const isNil = val => val === undefined || val === null;
    const isNull = val => val === null;
    const isNumber = val => typeof val === 'number' && val === val;
    const isObject = obj => obj === Object(obj);
    const isObjectLike = val => val !== null && typeof val === 'object';
    const isOdd = num => num % 2 === 1;
    const isPlainObject = val => !!val && typeof val === 'object' && val.constructor === Object;
    const isPowerOfTwo = n => !!n && (n & (n - 1)) == 0;
    const isPrime = num => {
      const boundary = Math.floor(Math.sqrt(num));
      for (var i = 2; i <= boundary; i++) if (num % i === 0) return false;
      return num >= 2;
    };
    const isPrimitive = val => Object(val) !== val;
    const isPromiseLike = obj =>
      obj !== null &&
      (typeof obj === 'object' || typeof obj === 'function') &&
      typeof obj.then === 'function';
    const isReadableStream = val =>
      val !== null &&
      typeof val === 'object' &&
      typeof val.pipe === 'function' &&
      typeof val._read === 'function' &&
      typeof val._readableState === 'object';
    const isSameDate = (dateA, dateB) => dateA.toISOString() === dateB.toISOString();
    const isSorted = arr => {
      let direction = -(arr[0] - arr[1]);
      for (let [i, val] of arr.entries()) {
        direction = !direction ? -(arr[i - 1] - arr[i]) : direction;
        if (i === arr.length - 1) return !direction ? 0 : direction;
        else if ((val - arr[i + 1]) * direction > 0) return 0;
      }
    };
    const isStream = val => val !== null && typeof val === 'object' && typeof val.pipe === 'function';
    const isString = val => typeof val === 'string';
    const isSymbol = val => typeof val === 'symbol';
    const isTravisCI = () => 'TRAVIS' in process.env && 'CI' in process.env;
    const isUndefined = val => val === undefined;
    const isUpperCase = str => str === str.toUpperCase();
    const isValidJSON = str => {
      try {
        JSON.parse(str);
        return true;
      } catch (e) {
        return false;
      }
    };
    const isWeekday = (t = new Date()) => {
      return t.getDay() % 6 !== 0;
    };
    const isWeekend = (t = new Date()) => {
      return t.getDay() % 6 === 0;
    };
    const isWritableStream = val =>
      val !== null &&
      typeof val === 'object' &&
      typeof val.pipe === 'function' &&
      typeof val._write === 'function' &&
      typeof val._writableState === 'object';
    const join = (arr, separator = ',', end = separator) =>
      arr.reduce(
        (acc, val, i) =>
          i === arr.length - 2
            ? acc + val + end
            : i === arr.length - 1
              ? acc + val
              : acc + val + separator,
        ''
      );
    const JSONtoCSV = (arr, columns, delimiter = ',') =>
      [
        columns.join(delimiter),
        ...arr.map(obj =>
          columns.reduce(
            (acc, key) => `${acc}${!acc.length ? '' : delimiter}"${!obj[key] ? '' : obj[key]}"`,
            ''
          )
        )
      ].join('\n');
    const JSONToFile = (obj, filename) =>
      fs.writeFile(`${filename}.json`, JSON.stringify(obj, null, 2));
    const last = arr => (arr && arr.length ? arr[arr.length - 1] : undefined);
    const lcm = (...arr) => {
      const gcd = (x, y) => (!y ? x : gcd(y, x % y));
      const _lcm = (x, y) => (x * y) / gcd(x, y);
      return [...arr].reduce((a, b) => _lcm(a, b));
    };
    const longestItem = (...vals) => vals.reduce((a, x) => (x.length > a.length ? x : a));
    const lowercaseKeys = obj =>
      Object.keys(obj).reduce((acc, key) => {
        acc[key.toLowerCase()] = obj[key];
        return acc;
      }, {});
    const luhnCheck = num => {
      let arr = (num + '')
        .split('')
        .reverse()
        .map(x => parseInt(x));
      let lastDigit = arr.splice(0, 1)[0];
      let sum = arr.reduce((acc, val, i) => (i % 2 !== 0 ? acc + val : acc + ((val * 2) % 9) || 9), 0);
      sum += lastDigit;
      return sum % 10 === 0;
    };
    const mapKeys = (obj, fn) =>
      Object.keys(obj).reduce((acc, k) => {
        acc[fn(obj[k], k, obj)] = obj[k];
        return acc;
      }, {});
    const mapNumRange = (num, inMin, inMax, outMin, outMax) =>
      ((num - inMin) * (outMax - outMin)) / (inMax - inMin) + outMin;
    const mapObject = (arr, fn) =>
      (a => (
        (a = [arr, arr.map(fn)]), a[0].reduce((acc, val, ind) => ((acc[val] = a[1][ind]), acc), {})
      ))();
    const mapString = (str, fn) =>
      str
        .split('')
        .map((c, i) => fn(c, i, str))
        .join('');
    const mapValues = (obj, fn) =>
      Object.keys(obj).reduce((acc, k) => {
        acc[k] = fn(obj[k], k, obj);
        return acc;
      }, {});
    const mask = (cc, num = 4, mask = '*') => `${cc}`.slice(-num).padStart(`${cc}`.length, mask);
    const matches = (obj, source) =>
      Object.keys(source).every(key => obj.hasOwnProperty(key) && obj[key] === source[key]);
    const matchesWith = (obj, source, fn) =>
      Object.keys(source).every(key =>
        obj.hasOwnProperty(key) && fn
          ? fn(obj[key], source[key], key, obj, source)
          : obj[key] == source[key]
      );
    const maxBy = (arr, fn) => Math.max(...arr.map(typeof fn === 'function' ? fn : val => val[fn]));
    const maxDate = dates => new Date(Math.max(...dates));
    const maxN = (arr, n = 1) => [...arr].sort((a, b) => b - a).slice(0, n);
    const median = arr => {
      const mid = Math.floor(arr.length / 2),
        nums = [...arr].sort((a, b) => a - b);
      return arr.length % 2 !== 0 ? nums[mid] : (nums[mid - 1] + nums[mid]) / 2;
    };
    const memoize = fn => {
      const cache = new Map();
      const cached = function(val) {
        return cache.has(val) ? cache.get(val) : cache.set(val, fn.call(this, val)) && cache.get(val);
      };
      cached.cache = cache;
      return cached;
    };
    const merge = (...objs) =>
      [...objs].reduce(
        (acc, obj) =>
          Object.keys(obj).reduce((a, k) => {
            acc[k] = acc.hasOwnProperty(k) ? [].concat(acc[k]).concat(obj[k]) : obj[k];
            return acc;
          }, {}),
        {}
      );
    const midpoint = ([x1, y1], [x2, y2]) => [(x1 + x2) / 2, (y1 + y2) / 2];
    const minBy = (arr, fn) => Math.min(...arr.map(typeof fn === 'function' ? fn : val => val[fn]));
    const minDate = dates => new Date(Math.min(...dates));
    const minN = (arr, n = 1) => [...arr].sort((a, b) => a - b).slice(0, n);
    const mostFrequent = arr =>
      Object.entries(
        arr.reduce((a, v) => {
          a[v] = a[v] ? a[v] + 1 : 1;
          return a;
        }, {})
      ).reduce((a, v) => (v[1] >= a[1] ? v : a), [null, 0])[0];
    const mostPerformant = (fns, iterations = 10000) => {
      const times = fns.map(fn => {
        const before = performance.now();
        for (let i = 0; i < iterations; i++) fn();
        return performance.now() - before;
      });
      return times.indexOf(Math.min(...times));
    };
    const negate = func => (...args) => !func(...args);
    const nest = (items, id = null, link = 'parent_id') =>
      items
        .filter(item => item[link] === id)
        .map(item => ({ ...item, children: nest(items, item.id) }));
    const nodeListToArray = nodeList => [...nodeList];
    const none = (arr, fn = Boolean) => !arr.some(fn);
    const nthArg = n => (...args) => args.slice(n)[0];
    const nthElement = (arr, n = 0) => (n === -1 ? arr.slice(n) : arr.slice(n, n + 1))[0];
    const objectFromPairs = arr => arr.reduce((a, [key, val]) => ((a[key] = val), a), {});
    const objectToPairs = obj => Object.keys(obj).map(k => [k, obj[k]]);
    const objectToQueryString = queryParameters => {
      return queryParameters
        ? Object.entries(queryParameters).reduce((queryString, [key, val], index) => {
          const symbol = queryString.length === 0 ? '?' : '&';
          queryString += typeof val === 'string' ? `${symbol}${key}=${val}` : '';
          return queryString;
        }, '')
        : '';
    };
    const observeMutations = (element, callback, options) => {
      const observer = new MutationObserver(mutations => mutations.forEach(m => callback(m)));
      observer.observe(
        element,
        Object.assign(
          {
            childList: true,
            attributes: true,
            attributeOldValue: true,
            characterData: true,
            characterDataOldValue: true,
            subtree: true
          },
          options
        )
      );
      return observer;
    };
    const off = (el, evt, fn, opts = false) => el.removeEventListener(evt, fn, opts);
    const offset = (arr, offset) => [...arr.slice(offset), ...arr.slice(0, offset)];
    const omit = (obj, arr) =>
      Object.keys(obj)
        .filter(k => !arr.includes(k))
        .reduce((acc, key) => ((acc[key] = obj[key]), acc), {});
    const omitBy = (obj, fn) =>
      Object.keys(obj)
        .filter(k => !fn(obj[k], k))
        .reduce((acc, key) => ((acc[key] = obj[key]), acc), {});
    const on = (el, evt, fn, opts = {}) => {
      const delegatorFn = e => e.target.matches(opts.target) && fn.call(e.target, e);
      el.addEventListener(evt, opts.target ? delegatorFn : fn, opts.options || false);
      if (opts.target) return delegatorFn;
    };
    const once = fn => {
      let called = false;
      return function(...args) {
        if (called) return;
        called = true;
        return fn.apply(this, args);
      };
    };
    const onUserInputChange = callback => {
      let type = 'mouse',
        lastTime = 0;
      const mousemoveHandler = () => {
        const now = performance.now();
        if (now - lastTime < 20)
          (type = 'mouse'), callback(type), document.removeEventListener('mousemove', mousemoveHandler);
        lastTime = now;
      };
      document.addEventListener('touchstart', () => {
        if (type === 'touch') return;
        (type = 'touch'), callback(type), document.addEventListener('mousemove', mousemoveHandler);
      });
    };
    const orderBy = (arr, props, orders) =>
      [...arr].sort((a, b) =>
        props.reduce((acc, prop, i) => {
          if (acc === 0) {
            const [p1, p2] = orders && orders[i] === 'desc' ? [b[prop], a[prop]] : [a[prop], b[prop]];
            acc = p1 > p2 ? 1 : p1 < p2 ? -1 : 0;
          }
          return acc;
        }, 0)
      );
    const over = (...fns) => (...args) => fns.map(fn => fn.apply(null, args));
    const overArgs = (fn, transforms) => (...args) => fn(...args.map((val, i) => transforms[i](val)));
    const pad = (str, length, char = ' ') =>
      str.padStart((str.length + length) / 2, char).padEnd(length, char);
    const palindrome = str => {
      const s = str.toLowerCase().replace(/[\W_]/g, '');
      return s === [...s].reverse().join('');
    };
    const parseCookie = str =>
      str
        .split(';')
        .map(v => v.split('='))
        .reduce((acc, v) => {
          acc[decodeURIComponent(v[0].trim())] = decodeURIComponent(v[1].trim());
          return acc;
        }, {});
    const partial = (fn, ...partials) => (...args) => fn(...partials, ...args);
    const partialRight = (fn, ...partials) => (...args) => fn(...args, ...partials);
    const partition = (arr, fn) =>
      arr.reduce(
        (acc, val, i, arr) => {
          acc[fn(val, i, arr) ? 0 : 1].push(val);
          return acc;
        },
        [[], []]
      );
    const percentile = (arr, val) =>
      (100 * arr.reduce((acc, v) => acc + (v < val ? 1 : 0) + (v === val ? 0.5 : 0), 0)) / arr.length;
    const permutations = arr => {
      if (arr.length <= 2) return arr.length === 2 ? [arr, [arr[1], arr[0]]] : arr;
      return arr.reduce(
        (acc, item, i) =>
          acc.concat(
            permutations([...arr.slice(0, i), ...arr.slice(i + 1)]).map(val => [item, ...val])
          ),
        []
      );
    };
    const pick = (obj, arr) =>
      arr.reduce((acc, curr) => (curr in obj && (acc[curr] = obj[curr]), acc), {});
    const pickBy = (obj, fn) =>
      Object.keys(obj)
        .filter(k => fn(obj[k], k))
        .reduce((acc, key) => ((acc[key] = obj[key]), acc), {});
    const pipeAsyncFunctions = (...fns) => arg => fns.reduce((p, f) => p.then(f), Promise.resolve(arg));
    const pipeFunctions = (...fns) => fns.reduce((f, g) => (...args) => g(f(...args)));
    const pluralize = (val, word, plural = word + 's') => {
      const _pluralize = (num, word, plural = word + 's') =>
        [1, -1].includes(Number(num)) ? word : plural;
      if (typeof val === 'object') return (num, word) => _pluralize(num, word, val[word]);
      return _pluralize(val, word, plural);
    };
    const powerset = arr => arr.reduce((a, v) => a.concat(a.map(r => [v].concat(r))), [[]]);
    const prefix = prop => {
      const capitalizedProp = prop.charAt(0).toUpperCase() + prop.slice(1);
      const prefixes = ['', 'webkit', 'moz', 'ms', 'o'];
      const i = prefixes.findIndex(
        prefix => typeof document.body.style[prefix ? prefix + capitalizedProp : prop] !== 'undefined'
      );
      return i !== -1 ? (i === 0 ? prop : prefixes[i] + capitalizedProp) : null;
    };
    const prettyBytes = (num, precision = 3, addSpace = true) => {
      const UNITS = ['B', 'KB', 'MB', 'GB', 'TB', 'PB', 'EB', 'ZB', 'YB'];
      if (Math.abs(num) < 1) return num + (addSpace ? ' ' : '') + UNITS[0];
      const exponent = Math.min(Math.floor(Math.log10(num < 0 ? -num : num) / 3), UNITS.length - 1);
      const n = Number(((num < 0 ? -num : num) / 1000 ** exponent).toPrecision(precision));
      return (num < 0 ? '-' : '') + n + (addSpace ? ' ' : '') + UNITS[exponent];
    };
    const primes = num => {
      let arr = Array.from({ length: num - 1 }).map((x, i) => i + 2),
        sqroot = Math.floor(Math.sqrt(num)),
        numsTillSqroot = Array.from({ length: sqroot - 1 }).map((x, i) => i + 2);
      numsTillSqroot.forEach(x => (arr = arr.filter(y => y % x !== 0 || y === x)));
      return arr;
    };
    const promisify = func => (...args) =>
      new Promise((resolve, reject) =>
        func(...args, (err, result) => (err ? reject(err) : resolve(result)))
      );
    const pull = (arr, ...args) => {
      let argState = Array.isArray(args[0]) ? args[0] : args;
      let pulled = arr.filter(v => !argState.includes(v));
      arr.length = 0;
      pulled.forEach(v => arr.push(v));
    };
    const pullAtIndex = (arr, pullArr) => {
      let removed = [];
      let pulled = arr
        .map((v, i) => (pullArr.includes(i) ? removed.push(v) : v))
        .filter((v, i) => !pullArr.includes(i));
      arr.length = 0;
      pulled.forEach(v => arr.push(v));
      return removed;
    };
    const pullAtValue = (arr, pullArr) => {
      let removed = [],
        pushToRemove = arr.forEach((v, i) => (pullArr.includes(v) ? removed.push(v) : v)),
        mutateTo = arr.filter((v, i) => !pullArr.includes(v));
      arr.length = 0;
      mutateTo.forEach(v => arr.push(v));
      return removed;
    };
    const pullBy = (arr, ...args) => {
      const length = args.length;
      let fn = length > 1 ? args[length - 1] : undefined;
      fn = typeof fn == 'function' ? (args.pop(), fn) : undefined;
      let argState = (Array.isArray(args[0]) ? args[0] : args).map(val => fn(val));
      let pulled = arr.filter((v, i) => !argState.includes(fn(v)));
      arr.length = 0;
      pulled.forEach(v => arr.push(v));
    };
    const radsToDegrees = rad => (rad * 180.0) / Math.PI;
    const randomHexColorCode = () => {
      let n = (Math.random() * 0xfffff * 1000000).toString(16);
      return '#' + n.slice(0, 6);
    };
    const randomIntArrayInRange = (min, max, n = 1) =>
      Array.from({ length: n }, () => Math.floor(Math.random() * (max - min + 1)) + min);
    const randomIntegerInRange = (min, max) => Math.floor(Math.random() * (max - min + 1)) + min;
    const randomNumberInRange = (min, max) => Math.random() * (max - min) + min;
    const readFileLines = filename =>
      fs
        .readFileSync(filename)
        .toString('UTF8')
        .split('\n');
    const rearg = (fn, indexes) => (...args) => fn(...indexes.map(i => args[i]));
    const recordAnimationFrames = (callback, autoStart = true) => {
      let running = true,
        raf;
      const stop = () => {
        running = false;
        cancelAnimationFrame(raf);
      };
      const start = () => {
        running = true;
        run();
      };
      const run = () => {
        raf = requestAnimationFrame(() => {
          callback();
          if (running) run();
        });
      };
      if (autoStart) start();
      return { start, stop };
    };
    const redirect = (url, asLink = true) =>
      asLink ? (window.location.href = url) : window.location.replace(url);
    const reducedFilter = (data, keys, fn) =>
      data.filter(fn).map(el =>
        keys.reduce((acc, key) => {
          acc[key] = el[key];
          return acc;
        }, {})
      );
    const reduceSuccessive = (arr, fn, acc) =>
      arr.reduce((res, val, i, arr) => (res.push(fn(res.slice(-1)[0], val, i, arr)), res), [acc]);
    const reduceWhich = (arr, comparator = (a, b) => a - b) =>
      arr.reduce((a, b) => (comparator(a, b) >= 0 ? b : a));
    const reject = (pred, array) => array.filter((...args) => !pred(...args));
    const remove = (arr, func) =>
      Array.isArray(arr)
        ? arr.filter(func).reduce((acc, val) => {
            arr.splice(arr.indexOf(val), 1);
            return acc.concat(val);
          }, [])
        : [];
    const removeNonASCII = str => str.replace(/[^\x20-\x7E]/g, '');
    const renameKeys = (keysMap, obj) =>
      Object.keys(obj).reduce(
        (acc, key) => ({
          ...acc,
          ...{ [keysMap[key] || key]: obj[key] }
        }),
        {}
      );
    const reverseString = str => [...str].reverse().join('');
    const RGBToHex = (r, g, b) => ((r << 16) + (g << 8) + b).toString(16).padStart(6, '0');
    const round = (n, decimals = 0) => Number(`${Math.round(`${n}e${decimals}`)}e-${decimals}`);
    const runAsync = fn => {
      const worker = new Worker(
        URL.createObjectURL(new Blob([`postMessage((${fn})());`]), {
          type: 'application/javascript; charset=utf-8'
        })
      );
      return new Promise((res, rej) => {
        worker.onmessage = ({ data }) => {
          res(data), worker.terminate();
        };
        worker.onerror = err => {
          rej(err), worker.terminate();
        };
      });
    };
    const runPromisesInSeries = ps => ps.reduce((p, next) => p.then(next), Promise.resolve());
    const sample = arr => arr[Math.floor(Math.random() * arr.length)];
    const sampleSize = ([...arr], n = 1) => {
      let m = arr.length;
      while (m) {
        const i = Math.floor(Math.random() * m--);
        [arr[m], arr[i]] = [arr[i], arr[m]];
      }
      return arr.slice(0, n);
    };
    const scrollToTop = () => {
      const c = document.documentElement.scrollTop || document.body.scrollTop;
      if (c > 0) {
        window.requestAnimationFrame(scrollToTop);
        window.scrollTo(0, c - c / 8);
      }
    };
    const sdbm = str => {
      let arr = str.split('');
      return arr.reduce(
        (hashCode, currentVal) =>
          (hashCode = currentVal.charCodeAt(0) + (hashCode << 6) + (hashCode << 16) - hashCode),
        0
      );
    };
    const serializeCookie = (name, val) => `${encodeURIComponent(name)}=${encodeURIComponent(val)}`;
    const serializeForm = form =>
      Array.from(new FormData(form), field => field.map(encodeURIComponent).join('=')).join('&');
    const setStyle = (el, ruleName, val) => (el.style[ruleName] = val);
    const shallowClone = obj => Object.assign({}, obj);
    const shank = (arr, index = 0, delCount = 0, ...elements) =>
      arr
        .slice(0, index)
        .concat(elements)
        .concat(arr.slice(index + delCount));
    const show = (...el) => [...el].forEach(e => (e.style.display = ''));
    const shuffle = ([...arr]) => {
      let m = arr.length;
      while (m) {
        const i = Math.floor(Math.random() * m--);
        [arr[m], arr[i]] = [arr[i], arr[m]];
      }
      return arr;
    };
    const similarity = (arr, values) => arr.filter(v => values.includes(v));
    const size = val =>
      Array.isArray(val)
        ? val.length
        : val && typeof val === 'object'
          ? val.size || val.length || Object.keys(val).length
          : typeof val === 'string'
            ? new Blob([val]).size
            : 0;
    const sleep = ms => new Promise(resolve => setTimeout(resolve, ms));
    const smoothScroll = element =>
      document.querySelector(element).scrollIntoView({
        behavior: 'smooth'
      });
    const sortCharactersInString = str => [...str].sort((a, b) => a.localeCompare(b)).join('');
    const sortedIndex = (arr, n) => {
      const isDescending = arr[0] > arr[arr.length - 1];
      const index = arr.findIndex(el => (isDescending ? n >= el : n <= el));
      return index === -1 ? arr.length : index;
    };
    const sortedIndexBy = (arr, n, fn) => {
      const isDescending = fn(arr[0]) > fn(arr[arr.length - 1]);
      const val = fn(n);
      const index = arr.findIndex(el => (isDescending ? val >= fn(el) : val <= fn(el)));
      return index === -1 ? arr.length : index;
    };
    const sortedLastIndex = (arr, n) => {
      const isDescending = arr[0] > arr[arr.length - 1];
      const index = arr.reverse().findIndex(el => (isDescending ? n <= el : n >= el));
      return index === -1 ? 0 : arr.length - index;
    };
    const sortedLastIndexBy = (arr, n, fn) => {
      const isDescending = fn(arr[0]) > fn(arr[arr.length - 1]);
      const val = fn(n);
      const index = arr
        .map(fn)
        .reverse()
        .findIndex(el => (isDescending ? val <= el : val >= el));
      return index === -1 ? 0 : arr.length - index;
    };
    const splitLines = str => str.split(/\r?\n/);
    const spreadOver = fn => argsArr => fn(...argsArr);
    const stableSort = (arr, compare) =>
      arr
        .map((item, index) => ({ item, index }))
        .sort((a, b) => compare(a.item, b.item) || a.index - b.index)
        .map(({ item }) => item);
    const standardDeviation = (arr, usePopulation = false) => {
      const mean = arr.reduce((acc, val) => acc + val, 0) / arr.length;
      return Math.sqrt(
        arr.reduce((acc, val) => acc.concat((val - mean) ** 2), []).reduce((acc, val) => acc + val, 0) /
          (arr.length - (usePopulation ? 0 : 1))
      );
    };
    const stringPermutations = str => {
      if (str.length <= 2) return str.length === 2 ? [str, str[1] + str[0]] : [str];
      return str
        .split('')
        .reduce(
          (acc, letter, i) =>
            acc.concat(stringPermutations(str.slice(0, i) + str.slice(i + 1)).map(val => letter + val)),
          []
        );
    };
    const stripHTMLTags = str => str.replace(/<[^>]*>/g, '');
    const sum = (...arr) => [...arr].reduce((acc, val) => acc + val, 0);
    const sumBy = (arr, fn) =>
      arr.map(typeof fn === 'function' ? fn : val => val[fn]).reduce((acc, val) => acc + val, 0);
    const sumPower = (end, power = 2, start = 1) =>
      Array(end + 1 - start)
        .fill(0)
        .map((x, i) => (i + start) ** power)
        .reduce((a, b) => a + b, 0);
    const symmetricDifference = (a, b) => {
      const sA = new Set(a),
        sB = new Set(b);
      return [...a.filter(x => !sB.has(x)), ...b.filter(x => !sA.has(x))];
    };
    const symmetricDifferenceBy = (a, b, fn) => {
      const sA = new Set(a.map(v => fn(v))),
        sB = new Set(b.map(v => fn(v)));
      return [...a.filter(x => !sB.has(fn(x))), ...b.filter(x => !sA.has(fn(x)))];
    };
    const symmetricDifferenceWith = (arr, val, comp) => [
      ...arr.filter(a => val.findIndex(b => comp(a, b)) === -1),
      ...val.filter(a => arr.findIndex(b => comp(a, b)) === -1)
    ];
    const tail = arr => (arr.length > 1 ? arr.slice(1) : arr);
    const take = (arr, n = 1) => arr.slice(0, n);
    const takeRight = (arr, n = 1) => arr.slice(arr.length - n, arr.length);
    const takeRightWhile = (arr, func) =>
      arr.reduceRight((acc, el) => (func(el) ? acc : [el, ...acc]), []);
    const takeWhile = (arr, func) => {
      for (const [i, val] of arr.entries()) if (func(val)) return arr.slice(0, i);
      return arr;
    };
    const throttle = (fn, wait) => {
      let inThrottle, lastFn, lastTime;
      return function() {
        const context = this,
          args = arguments;
        if (!inThrottle) {
          fn.apply(context, args);
          lastTime = Date.now();
          inThrottle = true;
        } else {
          clearTimeout(lastFn);
          lastFn = setTimeout(function() {
            if (Date.now() - lastTime >= wait) {
              fn.apply(context, args);
              lastTime = Date.now();
            }
          }, Math.max(wait - (Date.now() - lastTime), 0));
        }
      };
    };
    const times = (n, fn, context = undefined) => {
      let i = 0;
      while (fn.call(context, i) !== false && ++i < n) {}
    };
    const timeTaken = callback => {
      console.time('timeTaken');
      const r = callback();
      console.timeEnd('timeTaken');
      return r;
    };
    const toCamelCase = str => {
      let s =
        str &&
        str
          .match(/[A-Z]{2,}(?=[A-Z][a-z]+[0-9]*|\b)|[A-Z]?[a-z]+[0-9]*|[A-Z]|[0-9]+/g)
          .map(x => x.slice(0, 1).toUpperCase() + x.slice(1).toLowerCase())
          .join('');
      return s.slice(0, 1).toLowerCase() + s.slice(1);
    };
    const toCurrency = (n, curr, LanguageFormat = undefined) =>
      Intl.NumberFormat(LanguageFormat, { style: 'currency', currency: curr }).format(n);
    const toDecimalMark = num => num.toLocaleString('en-US');
    const toggleClass = (el, className) => el.classList.toggle(className);
    const toHash = (object, key) =>
      Array.prototype.reduce.call(
        object,
        (acc, data, index) => ((acc[!key ? index : data[key]] = data), acc),
        {}
      );
    const toKebabCase = str =>
      str &&
      str
        .match(/[A-Z]{2,}(?=[A-Z][a-z]+[0-9]*|\b)|[A-Z]?[a-z]+[0-9]*|[A-Z]|[0-9]+/g)
        .map(x => x.toLowerCase())
        .join('-');
    const tomorrow = () => {
      let t = new Date();
      t.setDate(t.getDate() + 1);
      return t.toISOString().split('T')[0];
    };
    const toOrdinalSuffix = num => {
      const int = parseInt(num),
        digits = [int % 10, int % 100],
        ordinals = ['st', 'nd', 'rd', 'th'],
        oPattern = [1, 2, 3, 4],
        tPattern = [11, 12, 13, 14, 15, 16, 17, 18, 19];
      return oPattern.includes(digits[0]) && !tPattern.includes(digits[1])
        ? int + ordinals[digits[0] - 1]
        : int + ordinals[3];
    };
    const toSafeInteger = num =>
      Math.round(Math.max(Math.min(num, Number.MAX_SAFE_INTEGER), Number.MIN_SAFE_INTEGER));
    const toSnakeCase = str =>
      str &&
      str
        .match(/[A-Z]{2,}(?=[A-Z][a-z]+[0-9]*|\b)|[A-Z]?[a-z]+[0-9]*|[A-Z]|[0-9]+/g)
        .map(x => x.toLowerCase())
        .join('_');
    const toTitleCase = str =>
      str
        .match(/[A-Z]{2,}(?=[A-Z][a-z]+[0-9]*|\b)|[A-Z]?[a-z]+[0-9]*|[A-Z]|[0-9]+/g)
        .map(x => x.charAt(0).toUpperCase() + x.slice(1))
        .join(' ');
    const transform = (obj, fn, acc) => Object.keys(obj).reduce((a, k) => fn(a, obj[k], k, obj), acc);
    const triggerEvent = (el, eventType, detail) =>
      el.dispatchEvent(new CustomEvent(eventType, { detail }));
    const truncateString = (str, num) =>
      str.length > num ? str.slice(0, num > 3 ? num - 3 : num) + '...' : str;
    const truthCheckCollection = (collection, pre) => collection.every(obj => obj[pre]);
    const unary = fn => val => fn(val);
    const uncurry = (fn, n = 1) => (...args) => {
      const next = acc => args => args.reduce((x, y) => x(y), acc);
      if (n > args.length) throw new RangeError('Arguments too few!');
      return next(fn)(args.slice(0, n));
    };
    const unescapeHTML = str =>
      str.replace(
        /&amp;|&lt;|&gt;|&#39;|&quot;/g,
        tag =>
          ({
            '&amp;': '&',
            '&lt;': '<',
            '&gt;': '>',
            '&#39;': "'",
            '&quot;': '"'
          }[tag] || tag)
      );
    const unflattenObject = obj =>
      Object.keys(obj).reduce((acc, k) => {
        if (k.indexOf('.') !== -1) {
          const keys = k.split('.');
          Object.assign(
            acc,
            JSON.parse(
              '{' +
                keys.map((v, i) => (i !== keys.length - 1 ? `"${v}":{` : `"${v}":`)).join('') +
                obj[k] +
                '}'.repeat(keys.length)
            )
          );
        } else acc[k] = obj[k];
        return acc;
      }, {});
    const unfold = (fn, seed) => {
      let result = [],
        val = [null, seed];
      while ((val = fn(val[1]))) result.push(val[0]);
      return result;
    };
    const union = (a, b) => Array.from(new Set([...a, ...b]));
    const unionBy = (a, b, fn) => {
      const s = new Set(a.map(fn));
      return Array.from(new Set([...a, ...b.filter(x => !s.has(fn(x)))]));
    };
    const unionWith = (a, b, comp) =>
      Array.from(new Set([...a, ...b.filter(x => a.findIndex(y => comp(x, y)) === -1)]));
    const uniqueElements = arr => [...new Set(arr)];
    const uniqueElementsBy = (arr, fn) =>
      arr.reduce((acc, v) => {
        if (!acc.some(x => fn(v, x))) acc.push(v);
        return acc;
      }, []);
    const uniqueElementsByRight = (arr, fn) =>
      arr.reduceRight((acc, v) => {
        if (!acc.some(x => fn(v, x))) acc.push(v);
        return acc;
      }, []);
    const uniqueSymmetricDifference = (a, b) => [
      ...new Set([...a.filter(v => !b.includes(v)), ...b.filter(v => !a.includes(v))])
    ];
    const untildify = str => str.replace(/^~($|\/|\\)/, `${require('os').homedir()}$1`);
    const unzip = arr =>
      arr.reduce(
        (acc, val) => (val.forEach((v, i) => acc[i].push(v)), acc),
        Array.from({
          length: Math.max(...arr.map(x => x.length))
        }).map(x => [])
      );
    const unzipWith = (arr, fn) =>
      arr
        .reduce(
          (acc, val) => (val.forEach((v, i) => acc[i].push(v)), acc),
          Array.from({
            length: Math.max(...arr.map(x => x.length))
          }).map(x => [])
        )
        .map(val => fn(...val));
    const URLJoin = (...args) =>
      args
        .join('/')
        .replace(/[\/]+/g, '/')
        .replace(/^(.+):\//, '$1://')
        .replace(/^file:/, 'file:/')
        .replace(/\/(\?|&|#[^!])/g, '$1')
        .replace(/\?/g, '&')
        .replace('&', '?');
    const UUIDGeneratorBrowser = () =>
      ([1e7] + -1e3 + -4e3 + -8e3 + -1e11).replace(/[018]/g, c =>
        (c ^ (crypto.getRandomValues(new Uint8Array(1))[0] & (15 >> (c / 4)))).toString(16)
      );
    const UUIDGeneratorNode = () =>
      ([1e7] + -1e3 + -4e3 + -8e3 + -1e11).replace(/[018]/g, c =>
        (c ^ (crypto.randomBytes(1)[0] & (15 >> (c / 4)))).toString(16)
      );
    const validateNumber = n => !isNaN(parseFloat(n)) && isFinite(n) && Number(n) == n;
    const vectorDistance = (...coords) => {
      let pointLength = Math.trunc(coords.length / 2);
      let sum = coords
        .slice(0, pointLength)
        .reduce((acc, val, i) => acc + Math.pow(val - coords[pointLength + i], 2), 0);
      return Math.sqrt(sum);
    };
    const weightedSample = (arr, weights) => {
      let roll = Math.random();
      return arr[
        weights
          .reduce((acc, w, i) => (i === 0 ? [w] : [...acc, acc[acc.length - 1] + w]), [])
          .findIndex((v, i, s) => roll >= (i === 0 ? 0 : s[i - 1]) && roll < v)
      ];
    };
    const when = (pred, whenTrue) => x => (pred(x) ? whenTrue(x) : x);
    const without = (arr, ...args) => arr.filter(v => !args.includes(v));
    const words = (str, pattern = /[^a-zA-Z-]+/) => str.split(pattern).filter(Boolean);
    const xProd = (a, b) => a.reduce((acc, x) => acc.concat(b.map(y => [x, y])), []);
    const yesNo = (val, def = false) =>
      /^(y|yes)$/i.test(val) ? true : /^(n|no)$/i.test(val) ? false : def;
    const yesterday = () => {
      let t = new Date();
      t.setDate(t.getDate() - 1);
      return t.toISOString().split('T')[0];
    };
    const zip = (...arrays) => {
      const maxLength = Math.max(...arrays.map(x => x.length));
      return Array.from({ length: maxLength }).map((_, i) => {
        return Array.from({ length: arrays.length }, (_, k) => arrays[k][i]);
      });
    };
    const zipObject = (props, values) =>
      props.reduce((obj, prop, index) => ((obj[prop] = values[index]), obj), {});
    const zipWith = (...array) => {
      const fn = typeof array[array.length - 1] === 'function' ? array.pop() : undefined;
      return Array.from({ length: Math.max(...array.map(a => a.length)) }, (_, i) =>
        fn ? fn(...array.map(a => a[i])) : array.map(a => a[i])
      );
    };
    const binarySearch = (arr, val, start = 0, end = arr.length - 1) => {
      if (start > end) return -1;
      const mid = Math.floor((start + end) / 2);
      if (arr[mid] > val) return binarySearch(arr, val, start, mid - 1);
      if (arr[mid] < val) return binarySearch(arr, val, mid + 1, end);
      return mid;
    };
    const celsiusToFahrenheit = degrees => 1.8 * degrees + 32;
    const cleanObj = (obj, keysToKeep = [], childIndicator) => {
      Object.keys(obj).forEach(key => {
        if (key === childIndicator) {
          cleanObj(obj[key], keysToKeep, childIndicator);
        } else if (!keysToKeep.includes(key)) {
          delete obj[key];
        }
      });
      return obj;
    };
    const collatz = n => (n % 2 === 0 ? n / 2 : 3 * n + 1);
    const countVowels = str => (str.match(/[aeiou]/gi) || []).length;
    const factors = (num, primes = false) => {
      const isPrime = num => {
        const boundary = Math.floor(Math.sqrt(num));
        for (var i = 2; i <= boundary; i++) if (num % i === 0) return false;
        return num >= 2;
      };
      const isNeg = num < 0;
      num = isNeg ? -num : num;
      let array = Array.from({ length: num - 1 })
        .map((val, i) => (num % (i + 2) === 0 ? i + 2 : false))
        .filter(val => val);
      if (isNeg)
        array = array.reduce((acc, val) => {
          acc.push(val);
          acc.push(-val);
          return acc;
        }, []);
      return primes ? array.filter(isPrime) : array;
    };
    const fahrenheitToCelsius = degrees => (degrees - 32) * 5/9;
    const fibonacciCountUntilNum = num =>
      Math.ceil(Math.log(num * Math.sqrt(5) + 1 / 2) / Math.log((Math.sqrt(5) + 1) / 2));
    const fibonacciUntilNum = num => {
      let n = Math.ceil(Math.log(num * Math.sqrt(5) + 1 / 2) / Math.log((Math.sqrt(5) + 1) / 2));
      return Array.from({ length: n }).reduce(
        (acc, val, i) => acc.concat(i > 1 ? acc[i - 1] + acc[i - 2] : i),
        []
      );
    };
    const heronArea = (side_a, side_b, side_c) => {
        const p = (side_a + side_b + side_c) / 2;
        return Math.sqrt(p * (p-side_a) * (p-side_b) * (p-side_c))
      };
    const howManyTimes = (num, divisor) => {
      if (divisor === 1 || divisor === -1) return Infinity;
      if (divisor === 0) return 0;
      let i = 0;
      while (Number.isInteger(num / divisor)) {
        i++;
        num = num / divisor;
      }
      return i;
    };
    const httpDelete = (url, callback, err = console.error) => {
      const request = new XMLHttpRequest();
      request.open('DELETE', url, true);
      request.onload = () => callback(request);
      request.onerror = () => err(request);
      request.send();
    };
    const httpPut = (url, data, callback, err = console.error) => {
      const request = new XMLHttpRequest();
      request.open("PUT", url, true);
      request.setRequestHeader('Content-type','application/json; charset=utf-8');
      request.onload = () => callback(request);
      request.onerror = () => err(request);
      request.send(data);
    };
    const isArmstrongNumber = digits =>
      (arr => arr.reduce((a, d) => a + parseInt(d) ** arr.length, 0) == digits)(
        (digits + '').split('')
      );
    const isSimilar = (pattern, str) =>
      [...str].reduce(
          (matchIndex, char) =>
              char.toLowerCase() === (pattern[matchIndex] || '').toLowerCase()
                  ? matchIndex + 1
                  : matchIndex,
          0
      ) === pattern.length;
    const JSONToDate = arr => {
      const dt = new Date(parseInt(arr.toString().substr(6)));
      return `${dt.getDate()}/${dt.getMonth() + 1}/${dt.getFullYear()}`;
    };
    const kmphToMph = (kmph) => 0.621371192 * kmph;
    const levenshteinDistance = (string1, string2) => {
      if (string1.length === 0) return string2.length;
      if (string2.length === 0) return string1.length;
      let matrix = Array(string2.length + 1)
        .fill(0)
        .map((x, i) => [i]);
      matrix[0] = Array(string1.length + 1)
        .fill(0)
        .map((x, i) => i);
      for (let i = 1; i <= string2.length; i++) {
        for (let j = 1; j <= string1.length; j++) {
          if (string2[i - 1] === string1[j - 1]) {
            matrix[i][j] = matrix[i - 1][j - 1];
          } else {
            matrix[i][j] = Math.min(
              matrix[i - 1][j - 1] + 1,
              matrix[i][j - 1] + 1,
              matrix[i - 1][j] + 1
            );
          }
        }
      }
      return matrix[string2.length][string1.length];
    };
    const mphToKmph = (mph) => 1.6093440006146922 * mph;
    const pipeLog = data => console.log(data) || data;
    const quickSort = ([n, ...nums], desc) =>
      isNaN(n)
        ? []
        : [
            ...quickSort(nums.filter(v => (desc ? v > n : v <= n)), desc),
            n,
            ...quickSort(nums.filter(v => (!desc ? v > n : v <= n)), desc)
          ];
    const removeVowels = (str, repl = '') => str.replace(/[aeiou]/gi, repl);
    const solveRPN = rpn => {
      const OPERATORS = {
        '*': (a, b) => a * b,
        '+': (a, b) => a + b,
        '-': (a, b) => a - b,
        '/': (a, b) => a / b,
        '**': (a, b) => a ** b
      };
      const [stack, solve] = [
        [],
        rpn
          .replace(/\^/g, '**')
          .split(/\s+/g)
          .filter(el => !/\s+/.test(el) && el !== '')
      ];
      solve.forEach(symbol => {
        if (!isNaN(parseFloat(symbol)) && isFinite(symbol)) {
          stack.push(symbol);
        } else if (Object.keys(OPERATORS).includes(symbol)) {
          const [a, b] = [stack.pop(), stack.pop()];
          stack.push(OPERATORS[symbol](parseFloat(b), parseFloat(a)));
        } else {
          throw `${symbol} is not a recognized symbol`;
        }
      });
      if (stack.length === 1) return stack.pop();
      else throw `${rpn} is not a proper RPN. Please check it and try again`;
    };
    const speechSynthesis = message => {
      const msg = new SpeechSynthesisUtterance(message);
      msg.voice = window.speechSynthesis.getVoices()[0];
      window.speechSynthesis.speak(msg);
    };
    const squareSum = (...args) => args.reduce((squareSum, number) => squareSum + Math.pow(number, 2), 0);
  
    exports.all = all;
    exports.allEqual = allEqual;
    exports.any = any;
    exports.approximatelyEqual = approximatelyEqual;
    exports.arrayToCSV = arrayToCSV;
    exports.arrayToHtmlList = arrayToHtmlList;
    exports.ary = ary;
    exports.atob = atob;
    exports.attempt = attempt;
    exports.average = average;
    exports.averageBy = averageBy;
    exports.bifurcate = bifurcate;
    exports.bifurcateBy = bifurcateBy;
    exports.bind = bind;
    exports.bindAll = bindAll;
    exports.bindKey = bindKey;
    exports.binomialCoefficient = binomialCoefficient;
    exports.bottomVisible = bottomVisible;
    exports.btoa = btoa;
    exports.byteSize = byteSize;
    exports.call = call;
    exports.capitalize = capitalize;
    exports.capitalizeEveryWord = capitalizeEveryWord;
    exports.castArray = castArray;
    exports.chainAsync = chainAsync;
    exports.checkProp = checkProp;
    exports.chunk = chunk;
    exports.clampNumber = clampNumber;
    exports.cloneRegExp = cloneRegExp;
    exports.coalesce = coalesce;
    exports.coalesceFactory = coalesceFactory;
    exports.collectInto = collectInto;
    exports.colorize = colorize;
    exports.compact = compact;
    exports.compactWhitespace = compactWhitespace;
    exports.compose = compose;
    exports.composeRight = composeRight;
    exports.converge = converge;
    exports.copyToClipboard = copyToClipboard;
    exports.countBy = countBy;
    exports.counter = counter;
    exports.countOccurrences = countOccurrences;
    exports.createDirIfNotExists = createDirIfNotExists;
    exports.createElement = createElement;
    exports.createEventHub = createEventHub;
    exports.CSVToArray = CSVToArray;
    exports.CSVToJSON = CSVToJSON;
    exports.currentURL = currentURL;
    exports.curry = curry;
    exports.dayOfYear = dayOfYear;
    exports.debounce = debounce;
    exports.decapitalize = decapitalize;
    exports.deepClone = deepClone;
    exports.deepFlatten = deepFlatten;
    exports.deepFreeze = deepFreeze;
    exports.deepGet = deepGet;
    exports.deepMapKeys = deepMapKeys;
    exports.defaults = defaults;
    exports.defer = defer;
    exports.degreesToRads = degreesToRads;
    exports.delay = delay;
    exports.detectDeviceType = detectDeviceType;
    exports.difference = difference;
    exports.differenceBy = differenceBy;
    exports.differenceWith = differenceWith;
    exports.dig = dig;
    exports.digitize = digitize;
    exports.distance = distance;
    exports.drop = drop;
    exports.dropRight = dropRight;
    exports.dropRightWhile = dropRightWhile;
    exports.dropWhile = dropWhile;
    exports.elementContains = elementContains;
    exports.elementIsVisibleInViewport = elementIsVisibleInViewport;
    exports.elo = elo;
    exports.equals = equals;
    exports.escapeHTML = escapeHTML;
    exports.escapeRegExp = escapeRegExp;
    exports.everyNth = everyNth;
    exports.extendHex = extendHex;
    exports.factorial = factorial;
    exports.fibonacci = fibonacci;
    exports.filterFalsy = filterFalsy;
    exports.filterNonUnique = filterNonUnique;
    exports.filterNonUniqueBy = filterNonUniqueBy;
    exports.findKey = findKey;
    exports.findLast = findLast;
    exports.findLastIndex = findLastIndex;
    exports.findLastKey = findLastKey;
    exports.flatten = flatten;
    exports.flattenObject = flattenObject;
    exports.flip = flip;
    exports.forEachRight = forEachRight;
    exports.formatDuration = formatDuration;
    exports.formToObject = formToObject;
    exports.forOwn = forOwn;
    exports.forOwnRight = forOwnRight;
    exports.frequencies = frequencies;
    exports.fromCamelCase = fromCamelCase;
    exports.functionName = functionName;
    exports.functions = functions;
    exports.gcd = gcd;
    exports.geometricProgression = geometricProgression;
    exports.get = get;
    exports.getColonTimeFromDate = getColonTimeFromDate;
    exports.getDaysDiffBetweenDates = getDaysDiffBetweenDates;
    exports.getImages = getImages;
    exports.getMeridiemSuffixOfInteger = getMeridiemSuffixOfInteger;
    exports.getScrollPosition = getScrollPosition;
    exports.getStyle = getStyle;
    exports.getType = getType;
    exports.getURLParameters = getURLParameters;
    exports.groupBy = groupBy;
    exports.hammingDistance = hammingDistance;
    exports.hasClass = hasClass;
    exports.hasFlags = hasFlags;
    exports.hashBrowser = hashBrowser;
    exports.hashNode = hashNode;
    exports.hasKey = hasKey;
    exports.head = head;
    exports.hexToRGB = hexToRGB;
    exports.hide = hide;
    exports.httpGet = httpGet;
    exports.httpPost = httpPost;
    exports.httpsRedirect = httpsRedirect;
    exports.hz = hz;
    exports.includesAll = includesAll;
    exports.includesAny = includesAny;
    exports.indentString = indentString;
    exports.indexOfAll = indexOfAll;
    exports.initial = initial;
    exports.initialize2DArray = initialize2DArray;
    exports.initializeArrayWithRange = initializeArrayWithRange;
    exports.initializeArrayWithRangeRight = initializeArrayWithRangeRight;
    exports.initializeArrayWithValues = initializeArrayWithValues;
    exports.initializeNDArray = initializeNDArray;
    exports.inRange = inRange;
    exports.insertAfter = insertAfter;
    exports.insertBefore = insertBefore;
    exports.intersection = intersection;
    exports.intersectionBy = intersectionBy;
    exports.intersectionWith = intersectionWith;
    exports.invertKeyValues = invertKeyValues;
    exports.is = is;
    exports.isAbsoluteURL = isAbsoluteURL;
    exports.isAfterDate = isAfterDate;
    exports.isAnagram = isAnagram;
    exports.isArrayLike = isArrayLike;
    exports.isBeforeDate = isBeforeDate;
    exports.isBoolean = isBoolean;
    exports.isBrowser = isBrowser;
    exports.isBrowserTabFocused = isBrowserTabFocused;
    exports.isDivisible = isDivisible;
    exports.isDuplexStream = isDuplexStream;
    exports.isEmpty = isEmpty;
    exports.isEven = isEven;
    exports.isFunction = isFunction;
    exports.isLowerCase = isLowerCase;
    exports.isNegativeZero = isNegativeZero;
    exports.isNil = isNil;
    exports.isNull = isNull;
    exports.isNumber = isNumber;
    exports.isObject = isObject;
    exports.isObjectLike = isObjectLike;
    exports.isOdd = isOdd;
    exports.isPlainObject = isPlainObject;
    exports.isPowerOfTwo = isPowerOfTwo;
    exports.isPrime = isPrime;
    exports.isPrimitive = isPrimitive;
    exports.isPromiseLike = isPromiseLike;
    exports.isReadableStream = isReadableStream;
    exports.isSameDate = isSameDate;
    exports.isSorted = isSorted;
    exports.isStream = isStream;
    exports.isString = isString;
    exports.isSymbol = isSymbol;
    exports.isTravisCI = isTravisCI;
    exports.isUndefined = isUndefined;
    exports.isUpperCase = isUpperCase;
    exports.isValidJSON = isValidJSON;
    exports.isWeekday = isWeekday;
    exports.isWeekend = isWeekend;
    exports.isWritableStream = isWritableStream;
    exports.join = join;
    exports.JSONtoCSV = JSONtoCSV;
    exports.JSONToFile = JSONToFile;
    exports.last = last;
    exports.lcm = lcm;
    exports.longestItem = longestItem;
    exports.lowercaseKeys = lowercaseKeys;
    exports.luhnCheck = luhnCheck;
    exports.mapKeys = mapKeys;
    exports.mapNumRange = mapNumRange;
    exports.mapObject = mapObject;
    exports.mapString = mapString;
    exports.mapValues = mapValues;
    exports.mask = mask;
    exports.matches = matches;
    exports.matchesWith = matchesWith;
    exports.maxBy = maxBy;
    exports.maxDate = maxDate;
    exports.maxN = maxN;
    exports.median = median;
    exports.memoize = memoize;
    exports.merge = merge;
    exports.midpoint = midpoint;
    exports.minBy = minBy;
    exports.minDate = minDate;
    exports.minN = minN;
    exports.mostFrequent = mostFrequent;
    exports.mostPerformant = mostPerformant;
    exports.negate = negate;
    exports.nest = nest;
    exports.nodeListToArray = nodeListToArray;
    exports.none = none;
    exports.nthArg = nthArg;
    exports.nthElement = nthElement;
    exports.objectFromPairs = objectFromPairs;
    exports.objectToPairs = objectToPairs;
    exports.objectToQueryString = objectToQueryString;
    exports.observeMutations = observeMutations;
    exports.off = off;
    exports.offset = offset;
    exports.omit = omit;
    exports.omitBy = omitBy;
    exports.on = on;
    exports.once = once;
    exports.onUserInputChange = onUserInputChange;
    exports.orderBy = orderBy;
    exports.over = over;
    exports.overArgs = overArgs;
    exports.pad = pad;
    exports.palindrome = palindrome;
    exports.parseCookie = parseCookie;
    exports.partial = partial;
    exports.partialRight = partialRight;
    exports.partition = partition;
    exports.percentile = percentile;
    exports.permutations = permutations;
    exports.pick = pick;
    exports.pickBy = pickBy;
    exports.pipeAsyncFunctions = pipeAsyncFunctions;
    exports.pipeFunctions = pipeFunctions;
    exports.pluralize = pluralize;
    exports.powerset = powerset;
    exports.prefix = prefix;
    exports.prettyBytes = prettyBytes;
    exports.primes = primes;
    exports.promisify = promisify;
    exports.pull = pull;
    exports.pullAtIndex = pullAtIndex;
    exports.pullAtValue = pullAtValue;
    exports.pullBy = pullBy;
    exports.radsToDegrees = radsToDegrees;
    exports.randomHexColorCode = randomHexColorCode;
    exports.randomIntArrayInRange = randomIntArrayInRange;
    exports.randomIntegerInRange = randomIntegerInRange;
    exports.randomNumberInRange = randomNumberInRange;
    exports.readFileLines = readFileLines;
    exports.rearg = rearg;
    exports.recordAnimationFrames = recordAnimationFrames;
    exports.redirect = redirect;
    exports.reducedFilter = reducedFilter;
    exports.reduceSuccessive = reduceSuccessive;
    exports.reduceWhich = reduceWhich;
    exports.reject = reject;
    exports.remove = remove;
    exports.removeNonASCII = removeNonASCII;
    exports.renameKeys = renameKeys;
    exports.reverseString = reverseString;
    exports.RGBToHex = RGBToHex;
    exports.round = round;
    exports.runAsync = runAsync;
    exports.runPromisesInSeries = runPromisesInSeries;
    exports.sample = sample;
    exports.sampleSize = sampleSize;
    exports.scrollToTop = scrollToTop;
    exports.sdbm = sdbm;
    exports.serializeCookie = serializeCookie;
    exports.serializeForm = serializeForm;
    exports.setStyle = setStyle;
    exports.shallowClone = shallowClone;
    exports.shank = shank;
    exports.show = show;
    exports.shuffle = shuffle;
    exports.similarity = similarity;
    exports.size = size;
    exports.sleep = sleep;
    exports.smoothScroll = smoothScroll;
    exports.sortCharactersInString = sortCharactersInString;
    exports.sortedIndex = sortedIndex;
    exports.sortedIndexBy = sortedIndexBy;
    exports.sortedLastIndex = sortedLastIndex;
    exports.sortedLastIndexBy = sortedLastIndexBy;
    exports.splitLines = splitLines;
    exports.spreadOver = spreadOver;
    exports.stableSort = stableSort;
    exports.standardDeviation = standardDeviation;
    exports.stringPermutations = stringPermutations;
    exports.stripHTMLTags = stripHTMLTags;
    exports.sum = sum;
    exports.sumBy = sumBy;
    exports.sumPower = sumPower;
    exports.symmetricDifference = symmetricDifference;
    exports.symmetricDifferenceBy = symmetricDifferenceBy;
    exports.symmetricDifferenceWith = symmetricDifferenceWith;
    exports.tail = tail;
    exports.take = take;
    exports.takeRight = takeRight;
    exports.takeRightWhile = takeRightWhile;
    exports.takeWhile = takeWhile;
    exports.throttle = throttle;
    exports.times = times;
    exports.timeTaken = timeTaken;
    exports.toCamelCase = toCamelCase;
    exports.toCurrency = toCurrency;
    exports.toDecimalMark = toDecimalMark;
    exports.toggleClass = toggleClass;
    exports.toHash = toHash;
    exports.toKebabCase = toKebabCase;
    exports.tomorrow = tomorrow;
    exports.toOrdinalSuffix = toOrdinalSuffix;
    exports.toSafeInteger = toSafeInteger;
    exports.toSnakeCase = toSnakeCase;
    exports.toTitleCase = toTitleCase;
    exports.transform = transform;
    exports.triggerEvent = triggerEvent;
    exports.truncateString = truncateString;
    exports.truthCheckCollection = truthCheckCollection;
    exports.unary = unary;
    exports.uncurry = uncurry;
    exports.unescapeHTML = unescapeHTML;
    exports.unflattenObject = unflattenObject;
    exports.unfold = unfold;
    exports.union = union;
    exports.unionBy = unionBy;
    exports.unionWith = unionWith;
    exports.uniqueElements = uniqueElements;
    exports.uniqueElementsBy = uniqueElementsBy;
    exports.uniqueElementsByRight = uniqueElementsByRight;
    exports.uniqueSymmetricDifference = uniqueSymmetricDifference;
    exports.untildify = untildify;
    exports.unzip = unzip;
    exports.unzipWith = unzipWith;
    exports.URLJoin = URLJoin;
    exports.UUIDGeneratorBrowser = UUIDGeneratorBrowser;
    exports.UUIDGeneratorNode = UUIDGeneratorNode;
    exports.validateNumber = validateNumber;
    exports.vectorDistance = vectorDistance;
    exports.weightedSample = weightedSample;
    exports.when = when;
    exports.without = without;
    exports.words = words;
    exports.xProd = xProd;
    exports.yesNo = yesNo;
    exports.yesterday = yesterday;
    exports.zip = zip;
    exports.zipObject = zipObject;
    exports.zipWith = zipWith;
    exports.binarySearch = binarySearch;
    exports.celsiusToFahrenheit = celsiusToFahrenheit;
    exports.cleanObj = cleanObj;
    exports.collatz = collatz;
    exports.countVowels = countVowels;
    exports.factors = factors;
    exports.fahrenheitToCelsius = fahrenheitToCelsius;
    exports.fibonacciCountUntilNum = fibonacciCountUntilNum;
    exports.fibonacciUntilNum = fibonacciUntilNum;
    exports.heronArea = heronArea;
    exports.howManyTimes = howManyTimes;
    exports.httpDelete = httpDelete;
    exports.httpPut = httpPut;
    exports.isArmstrongNumber = isArmstrongNumber;
    exports.isSimilar = isSimilar;
    exports.JSONToDate = JSONToDate;
    exports.kmphToMph = kmphToMph;
    exports.levenshteinDistance = levenshteinDistance;
    exports.mphToKmph = mphToKmph;
    exports.pipeLog = pipeLog;
    exports.quickSort = quickSort;
    exports.removeVowels = removeVowels;
    exports.solveRPN = solveRPN;
    exports.speechSynthesis = speechSynthesis;
    exports.squareSum = squareSum;
  
    Object.defineProperty(exports, '__esModule', { value: true });
  
  })));
  